Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/jkirsher/next...
authorDavid S. Miller <davem@davemloft.net>
Sat, 27 Aug 2011 16:14:34 +0000 (12:14 -0400)
committerDavid S. Miller <davem@davemloft.net>
Sat, 27 Aug 2011 16:14:34 +0000 (12:14 -0400)
185 files changed:
MAINTAINERS
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/arcnet/Kconfig
drivers/net/arcnet/Makefile
drivers/net/arcnet/com20020_cs.c [new file with mode: 0644]
drivers/net/bsd_comp.c [deleted file]
drivers/net/defxx.c [deleted file]
drivers/net/defxx.h [deleted file]
drivers/net/ethernet/3com/Kconfig
drivers/net/ethernet/8390/Kconfig
drivers/net/ethernet/adaptec/Kconfig
drivers/net/ethernet/alteon/Kconfig
drivers/net/ethernet/amd/Kconfig
drivers/net/ethernet/apple/Kconfig
drivers/net/ethernet/atheros/Kconfig
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/brocade/Kconfig
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/cirrus/Kconfig
drivers/net/ethernet/cisco/Kconfig
drivers/net/ethernet/dec/Kconfig
drivers/net/ethernet/dlink/Kconfig
drivers/net/ethernet/emulex/Kconfig
drivers/net/ethernet/faraday/Kconfig
drivers/net/ethernet/freescale/Kconfig
drivers/net/ethernet/fujitsu/Kconfig
drivers/net/ethernet/hp/Kconfig
drivers/net/ethernet/i825xx/Kconfig
drivers/net/ethernet/ibm/Kconfig
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/marvell/Kconfig
drivers/net/ethernet/mellanox/Kconfig
drivers/net/ethernet/micrel/Kconfig
drivers/net/ethernet/microchip/Kconfig
drivers/net/ethernet/myricom/Kconfig
drivers/net/ethernet/natsemi/Kconfig
drivers/net/ethernet/neterion/Kconfig
drivers/net/ethernet/nuvoton/Kconfig
drivers/net/ethernet/nvidia/Kconfig
drivers/net/ethernet/oki-semi/Kconfig
drivers/net/ethernet/pasemi/Kconfig
drivers/net/ethernet/qlogic/Kconfig
drivers/net/ethernet/racal/Kconfig
drivers/net/ethernet/rdc/Kconfig
drivers/net/ethernet/realtek/Kconfig
drivers/net/ethernet/seeq/Kconfig
drivers/net/ethernet/sgi/Kconfig
drivers/net/ethernet/sis/Kconfig
drivers/net/ethernet/smsc/Kconfig
drivers/net/ethernet/stmicro/Kconfig
drivers/net/ethernet/sun/Kconfig
drivers/net/ethernet/tehuti/Kconfig
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/toshiba/Kconfig
drivers/net/ethernet/tundra/Kconfig
drivers/net/ethernet/via/Kconfig
drivers/net/ethernet/xilinx/Kconfig
drivers/net/ethernet/xircom/Kconfig
drivers/net/ethernet/xscale/Kconfig
drivers/net/fddi/Kconfig [new file with mode: 0644]
drivers/net/fddi/Makefile [new file with mode: 0644]
drivers/net/fddi/defxx.c [new file with mode: 0644]
drivers/net/fddi/defxx.h [new file with mode: 0644]
drivers/net/fddi/skfp/Makefile [new file with mode: 0644]
drivers/net/fddi/skfp/cfm.c [new file with mode: 0644]
drivers/net/fddi/skfp/drvfbi.c [new file with mode: 0644]
drivers/net/fddi/skfp/ecm.c [new file with mode: 0644]
drivers/net/fddi/skfp/ess.c [new file with mode: 0644]
drivers/net/fddi/skfp/fplustm.c [new file with mode: 0644]
drivers/net/fddi/skfp/h/cmtdef.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/fddi.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/fddimib.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/fplustm.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/hwmtm.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/mbuf.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/osdef1st.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/sba.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/sba_def.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/skfbi.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/skfbiinc.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/smc.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/smt.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/smt_p.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/smtstate.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/supern_2.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/targethw.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/targetos.h [new file with mode: 0644]
drivers/net/fddi/skfp/h/types.h [new file with mode: 0644]
drivers/net/fddi/skfp/hwmtm.c [new file with mode: 0644]
drivers/net/fddi/skfp/hwt.c [new file with mode: 0644]
drivers/net/fddi/skfp/pcmplc.c [new file with mode: 0644]
drivers/net/fddi/skfp/pmf.c [new file with mode: 0644]
drivers/net/fddi/skfp/queue.c [new file with mode: 0644]
drivers/net/fddi/skfp/rmt.c [new file with mode: 0644]
drivers/net/fddi/skfp/skfddi.c [new file with mode: 0644]
drivers/net/fddi/skfp/smt.c [new file with mode: 0644]
drivers/net/fddi/skfp/smtdef.c [new file with mode: 0644]
drivers/net/fddi/skfp/smtinit.c [new file with mode: 0644]
drivers/net/fddi/skfp/smttimer.c [new file with mode: 0644]
drivers/net/fddi/skfp/srf.c [new file with mode: 0644]
drivers/net/hippi/Kconfig [new file with mode: 0644]
drivers/net/hippi/Makefile [new file with mode: 0644]
drivers/net/hippi/rrunner.c [new file with mode: 0644]
drivers/net/hippi/rrunner.h [new file with mode: 0644]
drivers/net/pcmcia/Kconfig [deleted file]
drivers/net/pcmcia/Makefile [deleted file]
drivers/net/pcmcia/com20020_cs.c [deleted file]
drivers/net/pcmcia/ibmtr_cs.c [deleted file]
drivers/net/phy/Kconfig
drivers/net/plip.c [deleted file]
drivers/net/plip/Kconfig [new file with mode: 0644]
drivers/net/plip/Makefile [new file with mode: 0644]
drivers/net/plip/plip.c [new file with mode: 0644]
drivers/net/ppp/Kconfig [new file with mode: 0644]
drivers/net/ppp/Makefile [new file with mode: 0644]
drivers/net/ppp/bsd_comp.c [new file with mode: 0644]
drivers/net/ppp/ppp_async.c [new file with mode: 0644]
drivers/net/ppp/ppp_deflate.c [new file with mode: 0644]
drivers/net/ppp/ppp_generic.c [new file with mode: 0644]
drivers/net/ppp/ppp_mppe.c [new file with mode: 0644]
drivers/net/ppp/ppp_mppe.h [new file with mode: 0644]
drivers/net/ppp/ppp_synctty.c [new file with mode: 0644]
drivers/net/ppp/pppoe.c [new file with mode: 0644]
drivers/net/ppp/pppox.c [new file with mode: 0644]
drivers/net/ppp/pptp.c [new file with mode: 0644]
drivers/net/ppp_async.c [deleted file]
drivers/net/ppp_deflate.c [deleted file]
drivers/net/ppp_generic.c [deleted file]
drivers/net/ppp_mppe.c [deleted file]
drivers/net/ppp_mppe.h [deleted file]
drivers/net/ppp_synctty.c [deleted file]
drivers/net/pppoe.c [deleted file]
drivers/net/pppox.c [deleted file]
drivers/net/pptp.c [deleted file]
drivers/net/rrunner.c [deleted file]
drivers/net/rrunner.h [deleted file]
drivers/net/skfp/Makefile [deleted file]
drivers/net/skfp/cfm.c [deleted file]
drivers/net/skfp/drvfbi.c [deleted file]
drivers/net/skfp/ecm.c [deleted file]
drivers/net/skfp/ess.c [deleted file]
drivers/net/skfp/fplustm.c [deleted file]
drivers/net/skfp/h/cmtdef.h [deleted file]
drivers/net/skfp/h/fddi.h [deleted file]
drivers/net/skfp/h/fddimib.h [deleted file]
drivers/net/skfp/h/fplustm.h [deleted file]
drivers/net/skfp/h/hwmtm.h [deleted file]
drivers/net/skfp/h/mbuf.h [deleted file]
drivers/net/skfp/h/osdef1st.h [deleted file]
drivers/net/skfp/h/sba.h [deleted file]
drivers/net/skfp/h/sba_def.h [deleted file]
drivers/net/skfp/h/skfbi.h [deleted file]
drivers/net/skfp/h/skfbiinc.h [deleted file]
drivers/net/skfp/h/smc.h [deleted file]
drivers/net/skfp/h/smt.h [deleted file]
drivers/net/skfp/h/smt_p.h [deleted file]
drivers/net/skfp/h/smtstate.h [deleted file]
drivers/net/skfp/h/supern_2.h [deleted file]
drivers/net/skfp/h/targethw.h [deleted file]
drivers/net/skfp/h/targetos.h [deleted file]
drivers/net/skfp/h/types.h [deleted file]
drivers/net/skfp/hwmtm.c [deleted file]
drivers/net/skfp/hwt.c [deleted file]
drivers/net/skfp/pcmplc.c [deleted file]
drivers/net/skfp/pmf.c [deleted file]
drivers/net/skfp/queue.c [deleted file]
drivers/net/skfp/rmt.c [deleted file]
drivers/net/skfp/skfddi.c [deleted file]
drivers/net/skfp/smt.c [deleted file]
drivers/net/skfp/smtdef.c [deleted file]
drivers/net/skfp/smtinit.c [deleted file]
drivers/net/skfp/smttimer.c [deleted file]
drivers/net/skfp/srf.c [deleted file]
drivers/net/slhc.c [deleted file]
drivers/net/slip.c [deleted file]
drivers/net/slip.h [deleted file]
drivers/net/slip/Kconfig [new file with mode: 0644]
drivers/net/slip/Makefile [new file with mode: 0644]
drivers/net/slip/slhc.c [new file with mode: 0644]
drivers/net/slip/slip.c [new file with mode: 0644]
drivers/net/slip/slip.h [new file with mode: 0644]
drivers/net/tokenring/Kconfig
drivers/net/tokenring/Makefile
drivers/net/tokenring/ibmtr_cs.c [new file with mode: 0644]

index d32e1ca5ba732d1ff12f9092ed4c466ccf8c87a4..194095ac07ec3e6f78cfc8f94261e88f675a99c7 100644 (file)
@@ -2113,7 +2113,7 @@ F:        net/decnet/
 DEFXX FDDI NETWORK DRIVER
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
-F:     drivers/net/defxx.*
+F:     drivers/net/fddi/defxx.*
 
 DELL LAPTOP DRIVER
 M:     Matthew Garrett <mjg59@srcf.ucam.org>
@@ -3049,6 +3049,7 @@ S:        Maintained
 F:     include/linux/hippidevice.h
 F:     include/linux/if_hippi.h
 F:     net/802/hippi.c
+F:     drivers/net/hippi/
 
 HOST AP DRIVER
 M:     Jouni Malinen <j@w1.fi>
@@ -5066,7 +5067,7 @@ PPP PROTOCOL DRIVERS AND COMPRESSORS
 M:     Paul Mackerras <paulus@samba.org>
 L:     linux-ppp@vger.kernel.org
 S:     Maintained
-F:     drivers/net/ppp_*
+F:     drivers/net/ppp/ppp_*
 
 PPP OVER ATM (RFC 2364)
 M:     Mitchell Blank Jr <mitch@sfgoth.com>
@@ -5077,8 +5078,8 @@ F:        include/linux/atmppp.h
 PPP OVER ETHERNET
 M:     Michal Ostrowski <mostrows@earthlink.net>
 S:     Maintained
-F:     drivers/net/pppoe.c
-F:     drivers/net/pppox.c
+F:     drivers/net/ppp/pppoe.c
+F:     drivers/net/ppp/pppox.c
 
 PPP OVER L2TP
 M:     James Chapman <jchapman@katalix.com>
@@ -5099,7 +5100,7 @@ PPTP DRIVER
 M:     Dmitry Kozlov <xeb@mail.ru>
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     drivers/net/pptp.c
+F:     drivers/net/ppp/pptp.c
 W:     http://sourceforge.net/projects/accel-pptp
 
 PREEMPTIBLE KERNEL
index ef6b6bee11da9d0cd33d8c7e855a0ee76c5077f0..583f66cd5bbd63dc199468b87b96baf32582bcb1 100644 (file)
@@ -25,18 +25,32 @@ menuconfig NETDEVICES
 # that for each of the symbols.
 if NETDEVICES
 
-config IFB
-       tristate "Intermediate Functional Block support"
-       depends on NET_CLS_ACT
+config NET_CORE
+       default y
+       bool "Network core driver support"
        ---help---
-         This is an intermediate driver that allows sharing of
-         resources.
+         You can say N here if you do not intend to use any of the
+         networking core drivers (i.e. VLAN, bridging, bonding, etc.)
+
+if NET_CORE
+
+config BONDING
+       tristate "Bonding driver support"
+       depends on INET
+       depends on IPV6 || IPV6=n
+       ---help---
+         Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
+         Channels together. This is called 'Etherchannel' by Cisco,
+         'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
+
+         The driver supports multiple bonding modes to allow for both high
+         performance and high availability operation.
+
+         Refer to <file:Documentation/networking/bonding.txt> for more
+         information.
+
          To compile this driver as a module, choose M here: the module
-         will be called ifb.  If you want to use more than one ifb
-         device at a time, you need to compile this driver as a module.
-         Instead of 'ifb', the devices will then be called 'ifb0',
-         'ifb1' etc.
-         Look at the iproute2 documentation directory for usage etc
+         will be called bonding.
 
 config DUMMY
        tristate "Dummy net driver support"
@@ -57,23 +71,59 @@ config DUMMY
          Instead of 'dummy', the devices will then be called 'dummy0',
          'dummy1' etc.
 
-config BONDING
-       tristate "Bonding driver support"
-       depends on INET
-       depends on IPV6 || IPV6=n
+config EQUALIZER
+       tristate "EQL (serial line load balancing) support"
        ---help---
-         Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
-         Channels together. This is called 'Etherchannel' by Cisco,
-         'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
+         If you have two serial connections to some other computer (this
+         usually requires two modems and two telephone lines) and you use
+         SLIP (the protocol for sending Internet traffic over telephone
+         lines) or PPP (a better SLIP) on them, you can make them behave like
+         one double speed connection using this driver.  Naturally, this has
+         to be supported at the other end as well, either with a similar EQL
+         Linux driver or with a Livingston Portmaster 2e.
 
-         The driver supports multiple bonding modes to allow for both high
-         performance and high availability operation.
+         Say Y if you want this and read
+         <file:Documentation/networking/eql.txt>.  You may also want to read
+         section 6.2 of the NET-3-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
 
-         Refer to <file:Documentation/networking/bonding.txt> for more
-         information.
+         To compile this driver as a module, choose M here: the module
+         will be called eql.  If unsure, say N.
+
+config NET_FC
+       bool "Fibre Channel driver support"
+       depends on SCSI && PCI
+       help
+         Fibre Channel is a high speed serial protocol mainly used to connect
+         large storage devices to the computer; it is compatible with and
+         intended to replace SCSI.
+
+         If you intend to use Fibre Channel, you need to have a Fibre channel
+         adaptor card in your computer; say Y here and to the driver for your
+         adaptor below. You also should have said Y to "SCSI support" and
+         "SCSI generic support".
+
+config MII
+       tristate "Generic Media Independent Interface device support"
+       help
+         Most ethernet controllers have MII transceiver either as an external
+         or internal device.  It is safe to say Y or M here even if your
+         ethernet card lacks MII.
+
+source "drivers/ieee802154/Kconfig"
 
+config IFB
+       tristate "Intermediate Functional Block support"
+       depends on NET_CLS_ACT
+       ---help---
+         This is an intermediate driver that allows sharing of
+         resources.
          To compile this driver as a module, choose M here: the module
-         will be called bonding.
+         will be called ifb.  If you want to use more than one ifb
+         device at a time, you need to compile this driver as a module.
+         Instead of 'ifb', the devices will then be called 'ifb0',
+         'ifb1' etc.
+         Look at the iproute2 documentation directory for usage etc
 
 config MACVLAN
        tristate "MAC-VLAN support (EXPERIMENTAL)"
@@ -102,24 +152,46 @@ config MACVTAP
          To compile this driver as a module, choose M here: the module
          will be called macvtap.
 
-config EQUALIZER
-       tristate "EQL (serial line load balancing) support"
+config NETCONSOLE
+       tristate "Network console logging support"
        ---help---
-         If you have two serial connections to some other computer (this
-         usually requires two modems and two telephone lines) and you use
-         SLIP (the protocol for sending Internet traffic over telephone
-         lines) or PPP (a better SLIP) on them, you can make them behave like
-         one double speed connection using this driver.  Naturally, this has
-         to be supported at the other end as well, either with a similar EQL
-         Linux driver or with a Livingston Portmaster 2e.
+       If you want to log kernel messages over the network, enable this.
+       See <file:Documentation/networking/netconsole.txt> for details.
 
-         Say Y if you want this and read
-         <file:Documentation/networking/eql.txt>.  You may also want to read
-         section 6.2 of the NET-3-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
+config NETCONSOLE_DYNAMIC
+       bool "Dynamic reconfiguration of logging targets"
+       depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
+                       !(NETCONSOLE=y && CONFIGFS_FS=m)
+       help
+         This option enables the ability to dynamically reconfigure target
+         parameters (interface, IP addresses, port numbers, MAC addresses)
+         at runtime through a userspace interface exported using configfs.
+         See <file:Documentation/networking/netconsole.txt> for details.
 
-         To compile this driver as a module, choose M here: the module
-         will be called eql.  If unsure, say N.
+config NETPOLL
+       def_bool NETCONSOLE
+
+config NETPOLL_TRAP
+       bool "Netpoll traffic trapping"
+       default n
+       depends on NETPOLL
+
+config NET_POLL_CONTROLLER
+       def_bool NETPOLL
+
+config RIONET
+       tristate "RapidIO Ethernet over messaging driver support"
+       depends on RAPIDIO
+
+config RIONET_TX_SIZE
+       int "Number of outbound queue entries"
+       depends on RIONET
+       default "128"
+
+config RIONET_RX_SIZE
+       int "Number of inbound queue entries"
+       depends on RIONET
+       default "128"
 
 config TUN
        tristate "Universal TUN/TAP device driver support"
@@ -151,6 +223,28 @@ config VETH
          When one end receives the packet it appears on its pair and vice
          versa.
 
+config VIRTIO_NET
+       tristate "Virtio network driver (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && VIRTIO
+       ---help---
+         This is the virtual network driver for virtio.  It can be used with
+         lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
+
+endif # NET_CORE
+
+config SUNGEM_PHY
+       tristate
+
+source "drivers/net/arcnet/Kconfig"
+
+source "drivers/atm/Kconfig"
+
+source "drivers/net/caif/Kconfig"
+
+source "drivers/net/ethernet/Kconfig"
+
+source "drivers/net/fddi/Kconfig"
+
 config NET_SB1000
        tristate "General Instruments Surfboard 1000"
        depends on PNP
@@ -175,46 +269,26 @@ config NET_SB1000
 
          If you don't have this card, of course say N.
 
-source "drivers/net/arcnet/Kconfig"
-
-config MII
-       tristate "Generic Media Independent Interface device support"
-       help
-         Most ethernet controllers have MII transceiver either as an external
-         or internal device.  It is safe to say Y or M here even if your
-         ethernet card lacks MII.
-
 source "drivers/net/phy/Kconfig"
 
-config SUNGEM_PHY
-       tristate
+source "drivers/net/plip/Kconfig"
 
-#
-#      Ethernet
-#
+source "drivers/net/ppp/Kconfig"
 
-source "drivers/net/ethernet/Kconfig"
+source "drivers/net/slip/Kconfig"
+
+source "drivers/s390/net/Kconfig"
 
 source "drivers/net/tokenring/Kconfig"
 
+source "drivers/net/usb/Kconfig"
+
 source "drivers/net/wireless/Kconfig"
 
 source "drivers/net/wimax/Kconfig"
 
-source "drivers/net/usb/Kconfig"
-
-source "drivers/net/pcmcia/Kconfig"
-
 source "drivers/net/wan/Kconfig"
 
-source "drivers/atm/Kconfig"
-
-source "drivers/ieee802154/Kconfig"
-
-source "drivers/s390/net/Kconfig"
-
-source "drivers/net/caif/Kconfig"
-
 config XEN_NETDEV_FRONTEND
        tristate "Xen network device frontend driver"
        depends on XEN
@@ -254,444 +328,6 @@ config XEN_NETDEV_BACKEND
          compile this driver as a module, chose M here: the module
          will be called xen-netback.
 
-config RIONET
-       tristate "RapidIO Ethernet over messaging driver support"
-       depends on RAPIDIO
-
-config RIONET_TX_SIZE
-       int "Number of outbound queue entries"
-       depends on RIONET
-       default "128"
-
-config RIONET_RX_SIZE
-       int "Number of inbound queue entries"
-       depends on RIONET
-       default "128"
-
-config FDDI
-       tristate "FDDI driver support"
-       depends on (PCI || EISA || TC)
-       help
-         Fiber Distributed Data Interface is a high speed local area network
-         design; essentially a replacement for high speed Ethernet. FDDI can
-         run over copper or fiber. If you are connected to such a network and
-         want a driver for the FDDI card in your computer, say Y here (and
-         then also Y to the driver for your FDDI card, below). Most people
-         will say N.
-
-config DEFXX
-       tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
-       depends on FDDI && (PCI || EISA || TC)
-       ---help---
-         This is support for the DIGITAL series of TURBOchannel (DEFTA),
-         EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
-         to a local FDDI network.
-
-         To compile this driver as a module, choose M here: the module
-         will be called defxx.  If unsure, say N.
-
-config DEFXX_MMIO
-       bool
-       prompt "Use MMIO instead of PIO" if PCI || EISA
-       depends on DEFXX
-       default n if PCI || EISA
-       default y
-       ---help---
-         This instructs the driver to use EISA or PCI memory-mapped I/O
-         (MMIO) as appropriate instead of programmed I/O ports (PIO).
-         Enabling this gives an improvement in processing time in parts
-         of the driver, but it may cause problems with EISA (DEFEA)
-         adapters.  TURBOchannel does not have the concept of I/O ports,
-         so MMIO is always used for these (DEFTA) adapters.
-
-         If unsure, say N.
-
-config SKFP
-       tristate "SysKonnect FDDI PCI support"
-       depends on FDDI && PCI
-       select BITREVERSE
-       ---help---
-         Say Y here if you have a SysKonnect FDDI PCI adapter.
-         The following adapters are supported by this driver:
-         - SK-5521 (SK-NET FDDI-UP)
-         - SK-5522 (SK-NET FDDI-UP DAS)
-         - SK-5541 (SK-NET FDDI-FP)
-         - SK-5543 (SK-NET FDDI-LP)
-         - SK-5544 (SK-NET FDDI-LP DAS)
-         - SK-5821 (SK-NET FDDI-UP64)
-         - SK-5822 (SK-NET FDDI-UP64 DAS)
-         - SK-5841 (SK-NET FDDI-FP64)
-         - SK-5843 (SK-NET FDDI-LP64)
-         - SK-5844 (SK-NET FDDI-LP64 DAS)
-         - Netelligent 100 FDDI DAS Fibre SC
-         - Netelligent 100 FDDI SAS Fibre SC
-         - Netelligent 100 FDDI DAS UTP
-         - Netelligent 100 FDDI SAS UTP
-         - Netelligent 100 FDDI SAS Fibre MIC
-
-         Read <file:Documentation/networking/skfp.txt> for information about
-         the driver.
-
-         Questions concerning this driver can be addressed to:
-         <linux@syskonnect.de>
-
-         To compile this driver as a module, choose M here: the module
-         will be called skfp.  This is recommended.
-
-config HIPPI
-       bool "HIPPI driver support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && INET && PCI
-       help
-         HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
-         1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
-         can run over copper (25m) or fiber (300m on multi-mode or 10km on
-         single-mode). HIPPI networks are commonly used for clusters and to
-         connect to super computers. If you are connected to a HIPPI network
-         and have a HIPPI network card in your computer that you want to use
-         under Linux, say Y here (you must also remember to enable the driver
-         for your HIPPI card below). Most people will say N here.
-
-config ROADRUNNER
-       tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
-       depends on HIPPI && PCI
-       help
-         Say Y here if this is your PCI HIPPI network card.
-
-         To compile this driver as a module, choose M here: the module
-         will be called rrunner.  If unsure, say N.
-
-config ROADRUNNER_LARGE_RINGS
-       bool "Use large TX/RX rings (EXPERIMENTAL)"
-       depends on ROADRUNNER
-       help
-         If you say Y here, the RoadRunner driver will preallocate up to 2 MB
-         of additional memory to allow for fastest operation, both for
-         transmitting and receiving. This memory cannot be used by any other
-         kernel code or by user space programs. Say Y here only if you have
-         the memory.
-
-config PLIP
-       tristate "PLIP (parallel port) support"
-       depends on PARPORT
-       ---help---
-         PLIP (Parallel Line Internet Protocol) is used to create a
-         reasonably fast mini network consisting of two (or, rarely, more)
-         local machines.  A PLIP link from a Linux box is a popular means to
-         install a Linux distribution on a machine which doesn't have a
-         CD-ROM drive (a minimal system has to be transferred with floppies
-         first). The kernels on both machines need to have this PLIP option
-         enabled for this to work.
-
-         The PLIP driver has two modes, mode 0 and mode 1.  The parallel
-         ports (the connectors at the computers with 25 holes) are connected
-         with "null printer" or "Turbo Laplink" cables which can transmit 4
-         bits at a time (mode 0) or with special PLIP cables, to be used on
-         bidirectional parallel ports only, which can transmit 8 bits at a
-         time (mode 1); you can find the wiring of these cables in
-         <file:Documentation/networking/PLIP.txt>.  The cables can be up to
-         15m long.  Mode 0 works also if one of the machines runs DOS/Windows
-         and has some PLIP software installed, e.g. the Crynwr PLIP packet
-         driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
-         and winsock or NCSA's telnet.
-
-         If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
-         as the NET-3-HOWTO, both available from
-         <http://www.tldp.org/docs.html#howto>.  Note that the PLIP
-         protocol has been changed and this PLIP driver won't work together
-         with the PLIP support in Linux versions 1.0.x.  This option enlarges
-         your kernel by about 8 KB.
-
-         To compile this driver as a module, choose M here. The module
-         will be called plip. If unsure, say Y or M, in case you buy
-         a laptop later.
-
-config PPP
-       tristate "PPP (point-to-point protocol) support"
-       select SLHC
-       ---help---
-         PPP (Point to Point Protocol) is a newer and better SLIP.  It serves
-         the same purpose: sending Internet traffic over telephone (and other
-         serial) lines.  Ask your access provider if they support it, because
-         otherwise you can't use it; most Internet access providers these
-         days support PPP rather than SLIP.
-
-         To use PPP, you need an additional program called pppd as described
-         in the PPP-HOWTO, available at
-         <http://www.tldp.org/docs.html#howto>.  Make sure that you have
-         the version of pppd recommended in <file:Documentation/Changes>.
-         The PPP option enlarges your kernel by about 16 KB.
-
-         There are actually two versions of PPP: the traditional PPP for
-         asynchronous lines, such as regular analog phone lines, and
-         synchronous PPP which can be used over digital ISDN lines for
-         example.  If you want to use PPP over phone lines or other
-         asynchronous serial lines, you need to say Y (or M) here and also to
-         the next option, "PPP support for async serial ports".  For PPP over
-         synchronous lines, you should say Y (or M) here and to "Support
-         synchronous PPP", below.
-
-         If you said Y to "Version information on all symbols" above, then
-         you cannot compile the PPP driver into the kernel; you can then only
-         compile it as a module. To compile this driver as a module, choose M
-         here. The module will be called ppp_generic.
-
-config PPP_MULTILINK
-       bool "PPP multilink support (EXPERIMENTAL)"
-       depends on PPP && EXPERIMENTAL
-       help
-         PPP multilink is a protocol (defined in RFC 1990) which allows you
-         to combine several (logical or physical) lines into one logical PPP
-         connection, so that you can utilize your full bandwidth.
-
-         This has to be supported at the other end as well and you need a
-         version of the pppd daemon which understands the multilink protocol.
-
-         If unsure, say N.
-
-config PPP_FILTER
-       bool "PPP filtering"
-       depends on PPP
-       help
-         Say Y here if you want to be able to filter the packets passing over
-         PPP interfaces.  This allows you to control which packets count as
-         activity (i.e. which packets will reset the idle timer or bring up
-         a demand-dialed link) and which packets are to be dropped entirely.
-         You need to say Y here if you wish to use the pass-filter and
-         active-filter options to pppd.
-
-         If unsure, say N.
-
-config PPP_ASYNC
-       tristate "PPP support for async serial ports"
-       depends on PPP
-       select CRC_CCITT
-       ---help---
-         Say Y (or M) here if you want to be able to use PPP over standard
-         asynchronous serial ports, such as COM1 or COM2 on a PC.  If you use
-         a modem (not a synchronous or ISDN modem) to contact your ISP, you
-         need this option.
-
-         To compile this driver as a module, choose M here.
-
-         If unsure, say Y.
-
-config PPP_SYNC_TTY
-       tristate "PPP support for sync tty ports"
-       depends on PPP
-       help
-         Say Y (or M) here if you want to be able to use PPP over synchronous
-         (HDLC) tty devices, such as the SyncLink adapter. These devices
-         are often used for high-speed leased lines like T1/E1.
-
-         To compile this driver as a module, choose M here.
-
-config PPP_DEFLATE
-       tristate "PPP Deflate compression"
-       depends on PPP
-       select ZLIB_INFLATE
-       select ZLIB_DEFLATE
-       ---help---
-         Support for the Deflate compression method for PPP, which uses the
-         Deflate algorithm (the same algorithm that gzip uses) to compress
-         each PPP packet before it is sent over the wire.  The machine at the
-         other end of the PPP link (usually your ISP) has to support the
-         Deflate compression method as well for this to be useful.  Even if
-         they don't support it, it is safe to say Y here.
-
-         To compile this driver as a module, choose M here.
-
-config PPP_BSDCOMP
-       tristate "PPP BSD-Compress compression"
-       depends on PPP
-       ---help---
-         Support for the BSD-Compress compression method for PPP, which uses
-         the LZW compression method to compress each PPP packet before it is
-         sent over the wire. The machine at the other end of the PPP link
-         (usually your ISP) has to support the BSD-Compress compression
-         method as well for this to be useful. Even if they don't support it,
-         it is safe to say Y here.
-
-         The PPP Deflate compression method ("PPP Deflate compression",
-         above) is preferable to BSD-Compress, because it compresses better
-         and is patent-free.
-
-         Note that the BSD compression code will always be compiled as a
-         module; it is called bsd_comp and will show up in the directory
-         modules once you have said "make modules". If unsure, say N.
-
-config PPP_MPPE
-       tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
-       depends on PPP && EXPERIMENTAL
-       select CRYPTO
-       select CRYPTO_SHA1
-       select CRYPTO_ARC4
-       select CRYPTO_ECB
-       ---help---
-         Support for the MPPE Encryption protocol, as employed by the
-         Microsoft Point-to-Point Tunneling Protocol.
-
-         See http://pptpclient.sourceforge.net/ for information on
-         configuring PPTP clients and servers to utilize this method.
-
-config PPPOE
-       tristate "PPP over Ethernet (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PPP
-       help
-         Support for PPP over Ethernet.
-
-         This driver requires the latest version of pppd from the CVS
-         repository at cvs.samba.org.  Alternatively, see the 
-         RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
-         which contains instruction on how to use this driver (under 
-         the heading "Kernel mode PPPoE").
-
-config PPTP
-       tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
-       help
-         Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
-
-         This driver requires pppd plugin to work in client mode or
-         modified pptpd (poptop) to work in server mode.
-         See http://accel-pptp.sourceforge.net/ for information how to
-         utilize this module.
-
-config PPPOATM
-       tristate "PPP over ATM"
-       depends on ATM && PPP
-       help
-         Support PPP (Point to Point Protocol) encapsulated in ATM frames.
-         This implementation does not yet comply with section 8 of RFC2364,
-         which can lead to bad results if the ATM peer loses state and
-         changes its encapsulation unilaterally.
-
-config PPPOL2TP
-       tristate "PPP over L2TP (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && L2TP && PPP
-       help
-         Support for PPP-over-L2TP socket family. L2TP is a protocol
-         used by ISPs and enterprises to tunnel PPP traffic over UDP
-         tunnels. L2TP is replacing PPTP for VPN uses.
-
-config SLIP
-       tristate "SLIP (serial line) support"
-       ---help---
-         Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
-         connect to your Internet service provider or to connect to some
-         other local Unix box or if you want to configure your Linux box as a
-         Slip/CSlip server for other people to dial in. SLIP (Serial Line
-         Internet Protocol) is a protocol used to send Internet traffic over
-         serial connections such as telephone lines or null modem cables;
-         nowadays, the protocol PPP is more commonly used for this same
-         purpose.
-
-         Normally, your access provider has to support SLIP in order for you
-         to be able to use it, but there is now a SLIP emulator called SLiRP
-         around (available from
-         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
-         allows you to use SLIP over a regular dial up shell connection. If
-         you plan to use SLiRP, make sure to say Y to CSLIP, below. The
-         NET-3-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, explains how to
-         configure SLIP. Note that you don't need this option if you just
-         want to run term (term is a program which gives you almost full
-         Internet connectivity if you have a regular dial up shell account on
-         some Internet connected Unix computer. Read
-         <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
-         support will enlarge your kernel by about 4 KB. If unsure, say N.
-
-         To compile this driver as a module, choose M here. The module
-         will be called slip.
-
-config SLIP_COMPRESSED
-       bool "CSLIP compressed headers"
-       depends on SLIP
-       select SLHC
-       ---help---
-         This protocol is faster than SLIP because it uses compression on the
-         TCP/IP headers (not on the data itself), but it has to be supported
-         on both ends. Ask your access provider if you are not sure and
-         answer Y, just in case. You will still be able to use plain SLIP. If
-         you plan to use SLiRP, the SLIP emulator (available from
-         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
-         allows you to use SLIP over a regular dial up shell connection, you
-         definitely want to say Y here. The NET-3-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>, explains how to configure
-         CSLIP. This won't enlarge your kernel.
-
-config SLHC
-       tristate
-       help
-         This option enables Van Jacobsen serial line header compression
-         routines.
-
-config SLIP_SMART
-       bool "Keepalive and linefill"
-       depends on SLIP
-       help
-         Adds additional capabilities to the SLIP driver to support the
-         RELCOM line fill and keepalive monitoring. Ideal on poor quality
-         analogue lines.
-
-config SLIP_MODE_SLIP6
-       bool "Six bit SLIP encapsulation"
-       depends on SLIP
-       help
-         Just occasionally you may need to run IP over hostile serial
-         networks that don't pass all control characters or are only seven
-         bit. Saying Y here adds an extra mode you can use with SLIP:
-         "slip6". In this mode, SLIP will only send normal ASCII symbols over
-         the serial device. Naturally, this has to be supported at the other
-         end of the link as well. It's good enough, for example, to run IP
-         over the async ports of a Camtec JNT Pad. If unsure, say N.
-
-config NET_FC
-       bool "Fibre Channel driver support"
-       depends on SCSI && PCI
-       help
-         Fibre Channel is a high speed serial protocol mainly used to connect
-         large storage devices to the computer; it is compatible with and
-         intended to replace SCSI.
-
-         If you intend to use Fibre Channel, you need to have a Fibre channel
-         adaptor card in your computer; say Y here and to the driver for your
-         adaptor below. You also should have said Y to "SCSI support" and
-         "SCSI generic support".
-
-config NETCONSOLE
-       tristate "Network console logging support"
-       ---help---
-       If you want to log kernel messages over the network, enable this.
-       See <file:Documentation/networking/netconsole.txt> for details.
-
-config NETCONSOLE_DYNAMIC
-       bool "Dynamic reconfiguration of logging targets"
-       depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
-                       !(NETCONSOLE=y && CONFIGFS_FS=m)
-       help
-         This option enables the ability to dynamically reconfigure target
-         parameters (interface, IP addresses, port numbers, MAC addresses)
-         at runtime through a userspace interface exported using configfs.
-         See <file:Documentation/networking/netconsole.txt> for details.
-
-config NETPOLL
-       def_bool NETCONSOLE
-
-config NETPOLL_TRAP
-       bool "Netpoll traffic trapping"
-       default n
-       depends on NETPOLL
-
-config NET_POLL_CONTROLLER
-       def_bool NETPOLL
-
-config VIRTIO_NET
-       tristate "Virtio network driver (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && VIRTIO
-       ---help---
-         This is the virtual network driver for virtio.  It can be used with
-         lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
-
 config VMXNET3
        tristate "VMware VMXNET3 ethernet driver"
        depends on PCI && INET
index c33009b49608c8b88436521b2f24bef4cbb843df..1f52e73547b00cae603f63fd2450cbeb5d08c966 100644 (file)
@@ -2,57 +2,61 @@
 # Makefile for the Linux network device drivers.
 #
 
-obj-$(CONFIG_MII) += mii.o
-obj-$(CONFIG_MDIO) += mdio.o
-obj-$(CONFIG_PHYLIB) += phy/
-obj-$(CONFIG_CAN) += can/
-obj-$(CONFIG_BONDING) += bonding/
-obj-$(CONFIG_VMXNET3) += vmxnet3/
-
 #
-# link order important here
+# Networking Core Drivers
 #
-obj-$(CONFIG_PLIP) += plip.o
-obj-$(CONFIG_ROADRUNNER) += rrunner.o
-obj-$(CONFIG_SKFP) += skfp/
-obj-$(CONFIG_RIONET) += rionet.o
-
-#
-# end link order section
-#
-
-obj-$(CONFIG_NET) += Space.o loopback.o
-obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_PPP) += ppp_generic.o
-obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
-obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
-obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
-obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
-obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
-obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
-obj-$(CONFIG_PPPOL2TP) += pppox.o
-obj-$(CONFIG_PPTP) += pppox.o pptp.o
-obj-$(CONFIG_SLIP) += slip.o
-obj-$(CONFIG_SLHC) += slhc.o
-
-obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
-obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
-
+obj-$(CONFIG_BONDING) += bonding/
 obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_IFB) += ifb.o
 obj-$(CONFIG_MACVLAN) += macvlan.o
 obj-$(CONFIG_MACVTAP) += macvtap.o
-obj-$(CONFIG_DEFXX) += defxx.o
-obj-$(CONFIG_EQUALIZER) += eql.o
+obj-$(CONFIG_MII) += mii.o
+obj-$(CONFIG_MDIO) += mdio.o
+obj-$(CONFIG_NET) += Space.o loopback.o
+obj-$(CONFIG_NETCONSOLE) += netconsole.o
+obj-$(CONFIG_PHYLIB) += phy/
+obj-$(CONFIG_RIONET) += rionet.o
 obj-$(CONFIG_TUN) += tun.o
 obj-$(CONFIG_VETH) += veth.o
+obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
 
+#
+# Networking Drivers
+#
+obj-$(CONFIG_ARCNET) += arcnet/
 obj-$(CONFIG_DEV_APPLETALK) += appletalk/
+obj-$(CONFIG_CAIF) += caif/
+obj-$(CONFIG_CAN) += can/
+obj-$(CONFIG_ETRAX_ETHERNET) += cris/
 obj-$(CONFIG_ETHERNET) += ethernet/
+obj-$(CONFIG_FDDI) += fddi/
+obj-$(CONFIG_HIPPI) += hippi/
+obj-$(CONFIG_HAMRADIO) += hamradio/
+obj-$(CONFIG_IRDA) += irda/
+obj-$(CONFIG_PLIP) += plip/
+onj-$(CONFIG_PPP) += ppp/
+obj-$(CONFIG_PPP_ASYNC) += ppp/
+obj-$(CONFIG_PPP_BSDCOMP) += ppp/
+obj-$(CONFIG_PPP_DEFLATE) += ppp/
+obj-$(CONFIG_PPP_MPPE) += ppp/
+obj-$(CONFIG_PPP_SYNC_TTY) += ppp/
+obj-$(CONFIG_PPPOE) += ppp/
+obj-$(CONFIG_PPPOL2TP) += ppp/
+obj-$(CONFIG_PPTP) += ppp/
+onj-$(CONFIG_SLIP) += slip/
+obj-$(CONFIG_SLHC) += slip/
+obj-$(CONFIG_NET_SB1000) += sb1000.o
+onj-$(CONFIG_SLIP) += slip/
+obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
 obj-$(CONFIG_TR) += tokenring/
 obj-$(CONFIG_WAN) += wan/
-obj-$(CONFIG_ARCNET) += arcnet/
-obj-$(CONFIG_NET_PCMCIA) += pcmcia/
+obj-$(CONFIG_WLAN) += wireless/
+obj-$(CONFIG_WIMAX) += wimax/
+
+obj-$(CONFIG_VMXNET3) += vmxnet3/
+obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
 
 obj-$(CONFIG_USB_CATC)          += usb/
 obj-$(CONFIG_USB_KAWETH)        += usb/
@@ -63,17 +67,3 @@ obj-$(CONFIG_USB_USBNET)        += usb/
 obj-$(CONFIG_USB_ZD1201)        += usb/
 obj-$(CONFIG_USB_IPHETH)        += usb/
 obj-$(CONFIG_USB_CDC_PHONET)   += usb/
-
-obj-$(CONFIG_WLAN) += wireless/
-obj-$(CONFIG_HAMRADIO) += hamradio/
-obj-$(CONFIG_IRDA) += irda/
-obj-$(CONFIG_ETRAX_ETHERNET) += cris/
-
-obj-$(CONFIG_NETCONSOLE) += netconsole.o
-
-obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
-
-obj-$(CONFIG_WIMAX) += wimax/
-obj-$(CONFIG_CAIF) += caif/
-
-obj-$(CONFIG_SUNGEM_PHY) += sungem_phy.o
index 3b2f7f11546489aaf48bb016d0469020b511b724..a73d9dc80ff674d7b90de88226511470b9c8c873 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 menuconfig ARCNET
-       depends on NETDEVICES && (ISA || PCI)
-       tristate "ARCnet support"
+       depends on NETDEVICES && (ISA || PCI || PCMCIA)
+       bool "ARCnet support"
        ---help---
          If you have a network card of this type, say Y and check out the
          (arguably) beautiful poetry in
@@ -123,4 +123,14 @@ config ARCNET_COM20020_PCI
        tristate "Support for COM20020 on PCI"
        depends on ARCNET_COM20020 && PCI
 
+config ARCNET_COM20020_CS
+       tristate "COM20020 ARCnet PCMCIA support"
+       depends on ARCNET_COM20020 && PCMCIA
+       help
+         Say Y here if you intend to attach this type of ARCnet PCMCIA card
+         to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called com20020_cs.  If unsure, say N.
+
 endif # ARCNET
index 5861af543d4222aa4e424833422550eabdb31043..5ce8ee63e43594c17159a28db6b1e49686274752 100644 (file)
@@ -12,3 +12,4 @@ obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o
 obj-$(CONFIG_ARCNET_COM20020) += com20020.o
 obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
 obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
+obj-$(CONFIG_ARCNET_COM20020_CS) += com20020_cs.o
diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c
new file mode 100644 (file)
index 0000000..980e65c
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Linux ARCnet driver - COM20020 PCMCIA support
+ * 
+ * Written 1994-1999 by Avery Pennarun,
+ *    based on an ISA version by David Woodhouse.
+ * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
+ *    which was derived from pcnet_cs.c by David Hinds.
+ * Some additional portions derived from skeleton.c by Donald Becker.
+ *
+ * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
+ *  for sponsoring the further development of this driver.
+ *
+ * **********************
+ *
+ * The original copyright of skeleton.c was as follows:
+ *
+ * skeleton.c Written 1993 by Donald Becker.
+ * Copyright 1993 United States Government as represented by the
+ * Director, National Security Agency.  This software may only be used
+ * and distributed according to the terms of the GNU General Public License as
+ * modified by SRC, incorporated herein by reference.
+ * 
+ * **********************
+ * Changes:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
+ * - reorganize kmallocs in com20020_attach, checking all for failure
+ *   and releasing the previous allocations if one fails
+ * **********************
+ * 
+ * For more details, see drivers/net/arcnet.c
+ *
+ * **********************
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/arcdevice.h>
+#include <linux/com20020.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
+
+
+static void regdump(struct net_device *dev)
+{
+#ifdef DEBUG
+    int ioaddr = dev->base_addr;
+    int count;
+    
+    netdev_dbg(dev, "register dump:\n");
+    for (count = ioaddr; count < ioaddr + 16; count++)
+    {
+       if (!(count % 16))
+           pr_cont("%04X:", count);
+       pr_cont(" %02X", inb(count));
+    }
+    pr_cont("\n");
+    
+    netdev_dbg(dev, "buffer0 dump:\n");
+       /* set up the address register */
+        count = 0;
+       outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
+       outb(count & 0xff, _ADDR_LO);
+    
+    for (count = 0; count < 256+32; count++)
+    {
+       if (!(count % 16))
+           pr_cont("%04X:", count);
+       
+       /* copy the data */
+       pr_cont(" %02X", inb(_MEMDATA));
+    }
+    pr_cont("\n");
+#endif
+}
+
+
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+static int node;
+static int timeout = 3;
+static int backplane;
+static int clockp;
+static int clockm;
+
+module_param(node, int, 0);
+module_param(timeout, int, 0);
+module_param(backplane, int, 0);
+module_param(clockp, int, 0);
+module_param(clockm, int, 0);
+
+MODULE_LICENSE("GPL");
+
+/*====================================================================*/
+
+static int com20020_config(struct pcmcia_device *link);
+static void com20020_release(struct pcmcia_device *link);
+
+static void com20020_detach(struct pcmcia_device *p_dev);
+
+/*====================================================================*/
+
+typedef struct com20020_dev_t {
+    struct net_device       *dev;
+} com20020_dev_t;
+
+static int com20020_probe(struct pcmcia_device *p_dev)
+{
+    com20020_dev_t *info;
+    struct net_device *dev;
+    struct arcnet_local *lp;
+
+    dev_dbg(&p_dev->dev, "com20020_attach()\n");
+
+    /* Create new network device */
+    info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
+    if (!info)
+       goto fail_alloc_info;
+
+    dev = alloc_arcdev("");
+    if (!dev)
+       goto fail_alloc_dev;
+
+    lp = netdev_priv(dev);
+    lp->timeout = timeout;
+    lp->backplane = backplane;
+    lp->clockp = clockp;
+    lp->clockm = clockm & 3;
+    lp->hw.owner = THIS_MODULE;
+
+    /* fill in our module parameters as defaults */
+    dev->dev_addr[0] = node;
+
+    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    p_dev->resource[0]->end = 16;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
+
+    info->dev = dev;
+    p_dev->priv = info;
+
+    return com20020_config(p_dev);
+
+fail_alloc_dev:
+    kfree(info);
+fail_alloc_info:
+    return -ENOMEM;
+} /* com20020_attach */
+
+static void com20020_detach(struct pcmcia_device *link)
+{
+    struct com20020_dev_t *info = link->priv;
+    struct net_device *dev = info->dev;
+
+    dev_dbg(&link->dev, "detach...\n");
+
+    dev_dbg(&link->dev, "com20020_detach\n");
+
+    dev_dbg(&link->dev, "unregister...\n");
+
+    unregister_netdev(dev);
+
+    /*
+     * this is necessary because we register our IRQ separately
+     * from card services.
+     */
+    if (dev->irq)
+           free_irq(dev->irq, dev);
+
+    com20020_release(link);
+
+    /* Unlink device structure, free bits */
+    dev_dbg(&link->dev, "unlinking...\n");
+    if (link->priv)
+    {
+       dev = info->dev;
+       if (dev)
+       {
+           dev_dbg(&link->dev, "kfree...\n");
+           free_netdev(dev);
+       }
+       dev_dbg(&link->dev, "kfree2...\n");
+       kfree(info);
+    }
+
+} /* com20020_detach */
+
+static int com20020_config(struct pcmcia_device *link)
+{
+    struct arcnet_local *lp;
+    com20020_dev_t *info;
+    struct net_device *dev;
+    int i, ret;
+    int ioaddr;
+
+    info = link->priv;
+    dev = info->dev;
+
+    dev_dbg(&link->dev, "config...\n");
+
+    dev_dbg(&link->dev, "com20020_config\n");
+
+    dev_dbg(&link->dev, "baseport1 is %Xh\n",
+           (unsigned int) link->resource[0]->start);
+
+    i = -ENODEV;
+    link->io_lines = 16;
+
+    if (!link->resource[0]->start)
+    {
+       for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
+       {
+           link->resource[0]->start = ioaddr;
+           i = pcmcia_request_io(link);
+           if (i == 0)
+               break;
+       }
+    }
+    else
+       i = pcmcia_request_io(link);
+    
+    if (i != 0)
+    {
+       dev_dbg(&link->dev, "requestIO failed totally!\n");
+       goto failed;
+    }
+       
+    ioaddr = dev->base_addr = link->resource[0]->start;
+    dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
+
+    dev_dbg(&link->dev, "request IRQ %d\n",
+           link->irq);
+    if (!link->irq)
+    {
+       dev_dbg(&link->dev, "requestIRQ failed totally!\n");
+       goto failed;
+    }
+
+    dev->irq = link->irq;
+
+    ret = pcmcia_enable_device(link);
+    if (ret)
+           goto failed;
+
+    if (com20020_check(dev))
+    {
+       regdump(dev);
+       goto failed;
+    }
+    
+    lp = netdev_priv(dev);
+    lp->card_name = "PCMCIA COM20020";
+    lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
+
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    i = com20020_found(dev, 0);        /* calls register_netdev */
+    
+    if (i != 0) {
+       dev_notice(&link->dev,
+                  "com20020_found() failed\n");
+       goto failed;
+    }
+
+    netdev_dbg(dev, "port %#3lx, irq %d\n",
+              dev->base_addr, dev->irq);
+    return 0;
+
+failed:
+    dev_dbg(&link->dev, "com20020_config failed...\n");
+    com20020_release(link);
+    return -ENODEV;
+} /* com20020_config */
+
+static void com20020_release(struct pcmcia_device *link)
+{
+       dev_dbg(&link->dev, "com20020_release\n");
+       pcmcia_disable_device(link);
+}
+
+static int com20020_suspend(struct pcmcia_device *link)
+{
+       com20020_dev_t *info = link->priv;
+       struct net_device *dev = info->dev;
+
+       if (link->open)
+               netif_device_detach(dev);
+
+       return 0;
+}
+
+static int com20020_resume(struct pcmcia_device *link)
+{
+       com20020_dev_t *info = link->priv;
+       struct net_device *dev = info->dev;
+
+       if (link->open) {
+               int ioaddr = dev->base_addr;
+               struct arcnet_local *lp = netdev_priv(dev);
+               ARCRESET;
+       }
+
+       return 0;
+}
+
+static const struct pcmcia_device_id com20020_ids[] = {
+       PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
+                       "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
+       PCMCIA_DEVICE_PROD_ID12("SoHard AG",
+                       "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
+       PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
+
+static struct pcmcia_driver com20020_cs_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "com20020_cs",
+       .probe          = com20020_probe,
+       .remove         = com20020_detach,
+       .id_table       = com20020_ids,
+       .suspend        = com20020_suspend,
+       .resume         = com20020_resume,
+};
+
+static int __init init_com20020_cs(void)
+{
+       return pcmcia_register_driver(&com20020_cs_driver);
+}
+
+static void __exit exit_com20020_cs(void)
+{
+       pcmcia_unregister_driver(&com20020_cs_driver);
+}
+
+module_init(init_com20020_cs);
+module_exit(exit_com20020_cs);
diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c
deleted file mode 100644 (file)
index a9b759a..0000000
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * Update: The Berkeley copyright was changed, and the change
- * is retroactive to all "true" BSD software (ie everything
- * from UCB as opposed to other peoples code that just carried
- * the same license). The new copyright doesn't clash with the
- * GPL, so the module-only restriction has been removed..
- */
-
-/* Because this code is derived from the 4.3BSD compress source:
- *
- * Copyright (c) 1985, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * James A. Woods, derived from original work by Spencer Thomas
- * and Joseph Orost.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * This version is for use with contiguous buffers on Linux-derived systems.
- *
- *  ==FILEVERSION 20000226==
- *
- *  NOTE TO MAINTAINERS:
- *     If you modify this file at all, please set the number above to the
- *     date of the modification as YYMMDD (year month day).
- *     bsd_comp.c is shipped with a PPP distribution as well as with
- *     the kernel; if everyone increases the FILEVERSION number above,
- *     then scripts can do the right thing when deciding whether to
- *     install a new bsd_comp.c file. Don't change the format of that
- *     line otherwise, so the installation script can recognize it.
- *
- * From: bsd_comp.c,v 1.3 1994/12/08 01:59:58 paulus Exp
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/string.h>
-
-#include <linux/ppp_defs.h>
-
-#undef   PACKETPTR
-#define  PACKETPTR 1
-#include <linux/ppp-comp.h>
-#undef   PACKETPTR
-
-#include <asm/byteorder.h>
-
-/*
- * PPP "BSD compress" compression
- *  The differences between this compression and the classic BSD LZW
- *  source are obvious from the requirement that the classic code worked
- *  with files while this handles arbitrarily long streams that
- *  are broken into packets.  They are:
- *
- *     When the code size expands, a block of junk is not emitted by
- *         the compressor and not expected by the decompressor.
- *
- *     New codes are not necessarily assigned every time an old
- *         code is output by the compressor.  This is because a packet
- *         end forces a code to be emitted, but does not imply that a
- *         new sequence has been seen.
- *
- *     The compression ratio is checked at the first end of a packet
- *         after the appropriate gap.  Besides simplifying and speeding
- *         things up, this makes it more likely that the transmitter
- *         and receiver will agree when the dictionary is cleared when
- *         compression is not going well.
- */
-
-/*
- * Macros to extract protocol version and number of bits
- * from the third byte of the BSD Compress CCP configuration option.
- */
-
-#define BSD_VERSION(x) ((x) >> 5)
-#define BSD_NBITS(x)   ((x) & 0x1F)
-
-#define BSD_CURRENT_VERSION    1
-
-/*
- * A dictionary for doing BSD compress.
- */
-
-struct bsd_dict {
-    union {                            /* hash value */
-       unsigned long   fcode;
-       struct {
-#if defined(__LITTLE_ENDIAN)           /* Little endian order */
-           unsigned short      prefix; /* preceding code */
-           unsigned char       suffix; /* last character of new code */
-           unsigned char       pad;
-#elif defined(__BIG_ENDIAN)            /* Big endian order */
-           unsigned char       pad;
-           unsigned char       suffix; /* last character of new code */
-           unsigned short      prefix; /* preceding code */
-#else
-#error Endianness not defined...
-#endif
-       } hs;
-    } f;
-    unsigned short codem1;             /* output of hash table -1 */
-    unsigned short cptr;               /* map code to hash table entry */
-};
-
-struct bsd_db {
-    int            totlen;                     /* length of this structure */
-    unsigned int   hsize;              /* size of the hash table */
-    unsigned char  hshift;             /* used in hash function */
-    unsigned char  n_bits;             /* current bits/code */
-    unsigned char  maxbits;            /* maximum bits/code */
-    unsigned char  debug;              /* non-zero if debug desired */
-    unsigned char  unit;               /* ppp unit number */
-    unsigned short seqno;              /* sequence # of next packet */
-    unsigned int   mru;                        /* size of receive (decompress) bufr */
-    unsigned int   maxmaxcode;         /* largest valid code */
-    unsigned int   max_ent;            /* largest code in use */
-    unsigned int   in_count;           /* uncompressed bytes, aged */
-    unsigned int   bytes_out;          /* compressed bytes, aged */
-    unsigned int   ratio;              /* recent compression ratio */
-    unsigned int   checkpoint;         /* when to next check the ratio */
-    unsigned int   clear_count;                /* times dictionary cleared */
-    unsigned int   incomp_count;       /* incompressible packets */
-    unsigned int   incomp_bytes;       /* incompressible bytes */
-    unsigned int   uncomp_count;       /* uncompressed packets */
-    unsigned int   uncomp_bytes;       /* uncompressed bytes */
-    unsigned int   comp_count;         /* compressed packets */
-    unsigned int   comp_bytes;         /* compressed bytes */
-    unsigned short  *lens;             /* array of lengths of codes */
-    struct bsd_dict *dict;             /* dictionary */
-};
-
-#define BSD_OVHD       2               /* BSD compress overhead/packet */
-#define MIN_BSD_BITS   9
-#define BSD_INIT_BITS  MIN_BSD_BITS
-#define MAX_BSD_BITS   15
-
-static void    bsd_free (void *state);
-static void    *bsd_alloc(unsigned char *options, int opt_len, int decomp);
-static void    *bsd_comp_alloc (unsigned char *options, int opt_len);
-static void    *bsd_decomp_alloc (unsigned char *options, int opt_len);
-
-static int     bsd_init        (void *db, unsigned char *options,
-                                int opt_len, int unit, int debug, int decomp);
-static int     bsd_comp_init   (void *state, unsigned char *options,
-                                int opt_len, int unit, int opthdr, int debug);
-static int     bsd_decomp_init (void *state, unsigned char *options,
-                                int opt_len, int unit, int opthdr, int mru,
-                                int debug);
-
-static void    bsd_reset (void *state);
-static void    bsd_comp_stats (void *state, struct compstat *stats);
-
-static int     bsd_compress (void *state, unsigned char *rptr,
-                             unsigned char *obuf, int isize, int osize);
-static void    bsd_incomp (void *state, unsigned char *ibuf, int icnt);
-
-static int     bsd_decompress (void *state, unsigned char *ibuf, int isize,
-                               unsigned char *obuf, int osize);
-
-/* These are in ppp_generic.c */
-extern int  ppp_register_compressor   (struct compressor *cp);
-extern void ppp_unregister_compressor (struct compressor *cp);
-
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define CLEAR  256                     /* table clear output code */
-#define FIRST  257                     /* first free entry */
-#define LAST   255
-
-#define MAXCODE(b)     ((1 << (b)) - 1)
-#define BADCODEM1      MAXCODE(MAX_BSD_BITS)
-
-#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
-                                        ^ (unsigned long)(prefix))
-#define BSD_KEY(prefix,suffix)         ((((unsigned long)(suffix)) << 16) \
-                                        + (unsigned long)(prefix))
-
-#define CHECK_GAP      10000           /* Ratio check interval */
-
-#define RATIO_SCALE_LOG        8
-#define RATIO_SCALE    (1<<RATIO_SCALE_LOG)
-#define RATIO_MAX      (0x7fffffff>>RATIO_SCALE_LOG)
-
-/*
- * clear the dictionary
- */
-
-static void
-bsd_clear(struct bsd_db *db)
-{
-    db->clear_count++;
-    db->max_ent      = FIRST-1;
-    db->n_bits       = BSD_INIT_BITS;
-    db->bytes_out    = 0;
-    db->in_count     = 0;
-    db->ratio       = 0;
-    db->checkpoint   = CHECK_GAP;
-}
-
-/*
- * If the dictionary is full, then see if it is time to reset it.
- *
- * Compute the compression ratio using fixed-point arithmetic
- * with 8 fractional bits.
- *
- * Since we have an infinite stream instead of a single file,
- * watch only the local compression ratio.
- *
- * Since both peers must reset the dictionary at the same time even in
- * the absence of CLEAR codes (while packets are incompressible), they
- * must compute the same ratio.
- */
-
-static int bsd_check (struct bsd_db *db)       /* 1=output CLEAR */
-  {
-    unsigned int new_ratio;
-
-    if (db->in_count >= db->checkpoint)
-      {
-       /* age the ratio by limiting the size of the counts */
-       if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
-         {
-           db->in_count  -= (db->in_count  >> 2);
-           db->bytes_out -= (db->bytes_out >> 2);
-         }
-
-       db->checkpoint = db->in_count + CHECK_GAP;
-
-       if (db->max_ent >= db->maxmaxcode)
-         {
-           /* Reset the dictionary only if the ratio is worse,
-            * or if it looks as if it has been poisoned
-            * by incompressible data.
-            *
-            * This does not overflow, because
-            *  db->in_count <= RATIO_MAX.
-            */
-
-           new_ratio = db->in_count << RATIO_SCALE_LOG;
-           if (db->bytes_out != 0)
-             {
-               new_ratio /= db->bytes_out;
-             }
-
-           if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
-             {
-               bsd_clear (db);
-               return 1;
-             }
-           db->ratio = new_ratio;
-         }
-      }
-    return 0;
-  }
-
-/*
- * Return statistics.
- */
-
-static void bsd_comp_stats (void *state, struct compstat *stats)
-  {
-    struct bsd_db *db = (struct bsd_db *) state;
-
-    stats->unc_bytes    = db->uncomp_bytes;
-    stats->unc_packets  = db->uncomp_count;
-    stats->comp_bytes   = db->comp_bytes;
-    stats->comp_packets = db->comp_count;
-    stats->inc_bytes    = db->incomp_bytes;
-    stats->inc_packets  = db->incomp_count;
-    stats->in_count     = db->in_count;
-    stats->bytes_out    = db->bytes_out;
-  }
-
-/*
- * Reset state, as on a CCP ResetReq.
- */
-
-static void bsd_reset (void *state)
-  {
-    struct bsd_db *db = (struct bsd_db *) state;
-
-    bsd_clear(db);
-
-    db->seqno       = 0;
-    db->clear_count = 0;
-  }
-
-/*
- * Release the compression structure
- */
-
-static void bsd_free (void *state)
-{
-       struct bsd_db *db = state;
-
-       if (!db)
-               return;
-
-/*
- * Release the dictionary
- */
-       vfree(db->dict);
-       db->dict = NULL;
-/*
- * Release the string buffer
- */
-       vfree(db->lens);
-       db->lens = NULL;
-/*
- * Finally release the structure itself.
- */
-       kfree(db);
-}
-
-/*
- * Allocate space for a (de) compressor.
- */
-
-static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
-  {
-    int bits;
-    unsigned int hsize, hshift, maxmaxcode;
-    struct bsd_db *db;
-
-    if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
-       || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
-      {
-       return NULL;
-      }
-
-    bits = BSD_NBITS(options[2]);
-
-    switch (bits)
-      {
-    case 9:                    /* needs 82152 for both directions */
-    case 10:                   /* needs 84144 */
-    case 11:                   /* needs 88240 */
-    case 12:                   /* needs 96432 */
-       hsize = 5003;
-       hshift = 4;
-       break;
-    case 13:                   /* needs 176784 */
-       hsize = 9001;
-       hshift = 5;
-       break;
-    case 14:                   /* needs 353744 */
-       hsize = 18013;
-       hshift = 6;
-       break;
-    case 15:                   /* needs 691440 */
-       hsize = 35023;
-       hshift = 7;
-       break;
-    case 16:                   /* needs 1366160--far too much, */
-       /* hsize = 69001; */    /* and 69001 is too big for cptr */
-       /* hshift = 8; */       /* in struct bsd_db */
-       /* break; */
-    default:
-       return NULL;
-      }
-/*
- * Allocate the main control structure for this instance.
- */
-    maxmaxcode = MAXCODE(bits);
-    db         = kzalloc(sizeof (struct bsd_db),
-                                           GFP_KERNEL);
-    if (!db)
-      {
-       return NULL;
-      }
-
-/*
- * Allocate space for the dictionary. This may be more than one page in
- * length.
- */
-    db->dict = vmalloc(hsize * sizeof(struct bsd_dict));
-    if (!db->dict)
-      {
-       bsd_free (db);
-       return NULL;
-      }
-
-/*
- * If this is the compression buffer then there is no length data.
- */
-    if (!decomp)
-      {
-       db->lens = NULL;
-      }
-/*
- * For decompression, the length information is needed as well.
- */
-    else
-      {
-        db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0]));
-       if (!db->lens)
-         {
-           bsd_free (db);
-           return NULL;
-         }
-      }
-/*
- * Initialize the data information for the compression code
- */
-    db->totlen     = sizeof (struct bsd_db)   +
-                   (sizeof (struct bsd_dict) * hsize);
-
-    db->hsize      = hsize;
-    db->hshift     = hshift;
-    db->maxmaxcode = maxmaxcode;
-    db->maxbits    = bits;
-
-    return (void *) db;
-  }
-
-static void *bsd_comp_alloc (unsigned char *options, int opt_len)
-  {
-    return bsd_alloc (options, opt_len, 0);
-  }
-
-static void *bsd_decomp_alloc (unsigned char *options, int opt_len)
-  {
-    return bsd_alloc (options, opt_len, 1);
-  }
-
-/*
- * Initialize the database.
- */
-
-static int bsd_init (void *state, unsigned char *options,
-                    int opt_len, int unit, int debug, int decomp)
-  {
-    struct bsd_db *db = state;
-    int indx;
-
-    if ((opt_len != 3) || (options[0] != CI_BSD_COMPRESS) || (options[1] != 3)
-       || (BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
-       || (BSD_NBITS(options[2]) != db->maxbits)
-       || (decomp && db->lens == NULL))
-      {
-       return 0;
-      }
-
-    if (decomp)
-      {
-       indx = LAST;
-       do
-         {
-           db->lens[indx] = 1;
-         }
-       while (indx-- > 0);
-      }
-
-    indx = db->hsize;
-    while (indx-- != 0)
-      {
-       db->dict[indx].codem1 = BADCODEM1;
-       db->dict[indx].cptr   = 0;
-      }
-
-    db->unit = unit;
-    db->mru  = 0;
-#ifndef DEBUG
-    if (debug)
-#endif
-      db->debug = 1;
-
-    bsd_reset(db);
-
-    return 1;
-  }
-
-static int bsd_comp_init (void *state, unsigned char *options,
-                         int opt_len, int unit, int opthdr, int debug)
-  {
-    return bsd_init (state, options, opt_len, unit, debug, 0);
-  }
-
-static int bsd_decomp_init (void *state, unsigned char *options,
-                           int opt_len, int unit, int opthdr, int mru,
-                           int debug)
-  {
-    return bsd_init (state, options, opt_len, unit, debug, 1);
-  }
-
-/*
- * Obtain pointers to the various structures in the compression tables
- */
-
-#define dict_ptrx(p,idx) &(p->dict[idx])
-#define lens_ptrx(p,idx) &(p->lens[idx])
-
-#ifdef DEBUG
-static unsigned short *lens_ptr(struct bsd_db *db, int idx)
-  {
-    if ((unsigned int) idx > (unsigned int) db->maxmaxcode)
-      {
-       printk ("<9>ppp: lens_ptr(%d) > max\n", idx);
-       idx = 0;
-      }
-    return lens_ptrx (db, idx);
-  }
-
-static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
-  {
-    if ((unsigned int) idx >= (unsigned int) db->hsize)
-      {
-       printk ("<9>ppp: dict_ptr(%d) > max\n", idx);
-       idx = 0;
-      }
-    return dict_ptrx (db, idx);
-  }
-
-#else
-#define lens_ptr(db,idx) lens_ptrx(db,idx)
-#define dict_ptr(db,idx) dict_ptrx(db,idx)
-#endif
-
-/*
- * compress a packet
- *
- *     The result of this function is the size of the compressed
- *     packet. A zero is returned if the packet was not compressed
- *     for some reason, such as the size being larger than uncompressed.
- *
- *     One change from the BSD compress command is that when the
- *     code size expands, we do not output a bunch of padding.
- */
-
-static int bsd_compress (void *state, unsigned char *rptr, unsigned char *obuf,
-                        int isize, int osize)
-  {
-    struct bsd_db *db;
-    int hshift;
-    unsigned int max_ent;
-    unsigned int n_bits;
-    unsigned int bitno;
-    unsigned long accm;
-    int ent;
-    unsigned long fcode;
-    struct bsd_dict *dictp;
-    unsigned char c;
-    int hval;
-    int disp;
-    int ilen;
-    int mxcode;
-    unsigned char *wptr;
-    int olen;
-
-#define PUTBYTE(v)                     \
-  {                                    \
-    ++olen;                            \
-    if (wptr)                          \
-      {                                        \
-       *wptr++ = (unsigned char) (v);  \
-       if (olen >= osize)              \
-         {                             \
-           wptr = NULL;                \
-         }                             \
-      }                                        \
-  }
-
-#define OUTPUT(ent)                    \
-  {                                    \
-    bitno -= n_bits;                   \
-    accm |= ((ent) << bitno);          \
-    do                                 \
-      {                                        \
-       PUTBYTE(accm >> 24);            \
-       accm <<= 8;                     \
-       bitno += 8;                     \
-      }                                        \
-    while (bitno <= 24);               \
-  }
-
-  /*
-   * If the protocol is not in the range we're interested in,
-   * just return without compressing the packet.  If it is,
-   * the protocol becomes the first byte to compress.
-   */
-
-    ent = PPP_PROTOCOL(rptr);
-    if (ent < 0x21 || ent > 0xf9)
-      {
-       return 0;
-      }
-
-    db      = (struct bsd_db *) state;
-    hshift  = db->hshift;
-    max_ent = db->max_ent;
-    n_bits  = db->n_bits;
-    bitno   = 32;
-    accm    = 0;
-    mxcode  = MAXCODE (n_bits);
-
-    /* Initialize the output pointers */
-    wptr  = obuf;
-    olen  = PPP_HDRLEN + BSD_OVHD;
-
-    if (osize > isize)
-      {
-       osize = isize;
-      }
-
-    /* This is the PPP header information */
-    if (wptr)
-      {
-       *wptr++ = PPP_ADDRESS(rptr);
-       *wptr++ = PPP_CONTROL(rptr);
-       *wptr++ = 0;
-       *wptr++ = PPP_COMP;
-       *wptr++ = db->seqno >> 8;
-       *wptr++ = db->seqno;
-      }
-
-    /* Skip the input header */
-    rptr  += PPP_HDRLEN;
-    isize -= PPP_HDRLEN;
-    ilen   = ++isize;  /* Low byte of protocol is counted as input */
-
-    while (--ilen > 0)
-      {
-       c     = *rptr++;
-       fcode = BSD_KEY  (ent, c);
-       hval  = BSD_HASH (ent, c, hshift);
-       dictp = dict_ptr (db, hval);
-
-       /* Validate and then check the entry. */
-       if (dictp->codem1 >= max_ent)
-         {
-           goto nomatch;
-         }
-
-       if (dictp->f.fcode == fcode)
-         {
-           ent = dictp->codem1 + 1;
-           continue;   /* found (prefix,suffix) */
-         }
-
-       /* continue probing until a match or invalid entry */
-       disp = (hval == 0) ? 1 : hval;
-
-       do
-         {
-           hval += disp;
-           if (hval >= db->hsize)
-             {
-               hval -= db->hsize;
-             }
-           dictp = dict_ptr (db, hval);
-           if (dictp->codem1 >= max_ent)
-             {
-               goto nomatch;
-             }
-         }
-       while (dictp->f.fcode != fcode);
-
-       ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
-       continue;
-
-nomatch:
-       OUTPUT(ent);            /* output the prefix */
-
-       /* code -> hashtable */
-       if (max_ent < db->maxmaxcode)
-         {
-           struct bsd_dict *dictp2;
-           struct bsd_dict *dictp3;
-           int    indx;
-
-           /* expand code size if needed */
-           if (max_ent >= mxcode)
-             {
-               db->n_bits = ++n_bits;
-               mxcode     = MAXCODE (n_bits);
-             }
-
-           /* Invalidate old hash table entry using
-            * this code, and then take it over.
-            */
-
-           dictp2 = dict_ptr (db, max_ent + 1);
-           indx   = dictp2->cptr;
-           dictp3 = dict_ptr (db, indx);
-
-           if (dictp3->codem1 == max_ent)
-             {
-               dictp3->codem1 = BADCODEM1;
-             }
-
-           dictp2->cptr   = hval;
-           dictp->codem1  = max_ent;
-           dictp->f.fcode = fcode;
-           db->max_ent    = ++max_ent;
-
-           if (db->lens)
-             {
-               unsigned short *len1 = lens_ptr (db, max_ent);
-               unsigned short *len2 = lens_ptr (db, ent);
-               *len1 = *len2 + 1;
-             }
-         }
-       ent = c;
-      }
-
-    OUTPUT(ent);               /* output the last code */
-
-    db->bytes_out    += olen - PPP_HDRLEN - BSD_OVHD;
-    db->uncomp_bytes += isize;
-    db->in_count     += isize;
-    ++db->uncomp_count;
-    ++db->seqno;
-
-    if (bitno < 32)
-      {
-       ++db->bytes_out; /* must be set before calling bsd_check */
-      }
-
-    /*
-     * Generate the clear command if needed
-     */
-
-    if (bsd_check(db))
-      {
-       OUTPUT (CLEAR);
-      }
-
-    /*
-     * Pad dribble bits of last code with ones.
-     * Do not emit a completely useless byte of ones.
-     */
-
-    if (bitno != 32)
-      {
-       PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
-      }
-
-    /*
-     * Increase code size if we would have without the packet
-     * boundary because the decompressor will do so.
-     */
-
-    if (max_ent >= mxcode && max_ent < db->maxmaxcode)
-      {
-       db->n_bits++;
-      }
-
-    /* If output length is too large then this is an incomplete frame. */
-    if (wptr == NULL)
-      {
-       ++db->incomp_count;
-       db->incomp_bytes += isize;
-       olen              = 0;
-      }
-    else /* Count the number of compressed frames */
-      {
-       ++db->comp_count;
-       db->comp_bytes += olen;
-      }
-
-    /* Return the resulting output length */
-    return olen;
-#undef OUTPUT
-#undef PUTBYTE
-  }
-
-/*
- * Update the "BSD Compress" dictionary on the receiver for
- * incompressible data by pretending to compress the incoming data.
- */
-
-static void bsd_incomp (void *state, unsigned char *ibuf, int icnt)
-  {
-    (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0);
-  }
-
-/*
- * Decompress "BSD Compress".
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression.  For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-
-static int bsd_decompress (void *state, unsigned char *ibuf, int isize,
-                          unsigned char *obuf, int osize)
-  {
-    struct bsd_db *db;
-    unsigned int max_ent;
-    unsigned long accm;
-    unsigned int bitno;                /* 1st valid bit in accm */
-    unsigned int n_bits;
-    unsigned int tgtbitno;     /* bitno when we have a code */
-    struct bsd_dict *dictp;
-    int explen;
-    int seq;
-    unsigned int incode;
-    unsigned int oldcode;
-    unsigned int finchar;
-    unsigned char *p;
-    unsigned char *wptr;
-    int adrs;
-    int ctrl;
-    int ilen;
-    int codelen;
-    int extra;
-
-    db       = (struct bsd_db *) state;
-    max_ent  = db->max_ent;
-    accm     = 0;
-    bitno    = 32;             /* 1st valid bit in accm */
-    n_bits   = db->n_bits;
-    tgtbitno = 32 - n_bits;    /* bitno when we have a code */
-
-    /*
-     * Save the address/control from the PPP header
-     * and then get the sequence number.
-     */
-
-    adrs  = PPP_ADDRESS (ibuf);
-    ctrl  = PPP_CONTROL (ibuf);
-
-    seq   = (ibuf[4] << 8) + ibuf[5];
-
-    ibuf += (PPP_HDRLEN + 2);
-    ilen  = isize - (PPP_HDRLEN + 2);
-
-    /*
-     * Check the sequence number and give up if it differs from
-     * the value we're expecting.
-     */
-
-    if (seq != db->seqno)
-      {
-       if (db->debug)
-         {
-           printk("bsd_decomp%d: bad sequence # %d, expected %d\n",
-                  db->unit, seq, db->seqno - 1);
-         }
-       return DECOMP_ERROR;
-      }
-
-    ++db->seqno;
-    db->bytes_out += ilen;
-
-    /*
-     * Fill in the ppp header, but not the last byte of the protocol
-     * (that comes from the decompressed data).
-     */
-
-    wptr    = obuf;
-    *wptr++ = adrs;
-    *wptr++ = ctrl;
-    *wptr++ = 0;
-
-    oldcode = CLEAR;
-    explen  = 3;
-
-    /*
-     * Keep the checkpoint correctly so that incompressible packets
-     * clear the dictionary at the proper times.
-     */
-
-    for (;;)
-      {
-       if (ilen-- <= 0)
-         {
-           db->in_count += (explen - 3); /* don't count the header */
-           break;
-         }
-
-       /*
-        * Accumulate bytes until we have a complete code.
-        * Then get the next code, relying on the 32-bit,
-        * unsigned accm to mask the result.
-        */
-
-       bitno -= 8;
-       accm  |= *ibuf++ << bitno;
-       if (tgtbitno < bitno)
-         {
-           continue;
-         }
-
-       incode = accm >> tgtbitno;
-       accm <<= n_bits;
-       bitno += n_bits;
-
-       /*
-        * The dictionary must only be cleared at the end of a packet.
-        */
-
-       if (incode == CLEAR)
-         {
-           if (ilen > 0)
-             {
-               if (db->debug)
-                 {
-                   printk("bsd_decomp%d: bad CLEAR\n", db->unit);
-                 }
-               return DECOMP_FATALERROR;       /* probably a bug */
-             }
-
-           bsd_clear(db);
-           break;
-         }
-
-       if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
-           || (incode > max_ent && oldcode == CLEAR))
-         {
-           if (db->debug)
-             {
-               printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
-                      db->unit, incode, oldcode);
-               printk("max_ent=0x%x explen=%d seqno=%d\n",
-                      max_ent, explen, db->seqno);
-             }
-           return DECOMP_FATALERROR;   /* probably a bug */
-         }
-
-       /* Special case for KwKwK string. */
-       if (incode > max_ent)
-         {
-           finchar = oldcode;
-           extra   = 1;
-         }
-       else
-         {
-           finchar = incode;
-           extra   = 0;
-         }
-
-       codelen = *(lens_ptr (db, finchar));
-       explen += codelen + extra;
-       if (explen > osize)
-         {
-           if (db->debug)
-             {
-               printk("bsd_decomp%d: ran out of mru\n", db->unit);
-#ifdef DEBUG
-               printk("  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
-                      ilen, finchar, codelen, explen);
-#endif
-             }
-           return DECOMP_FATALERROR;
-         }
-
-       /*
-        * Decode this code and install it in the decompressed buffer.
-        */
-
-       wptr += codelen;
-       p     = wptr;
-       while (finchar > LAST)
-         {
-           struct bsd_dict *dictp2 = dict_ptr (db, finchar);
-
-           dictp = dict_ptr (db, dictp2->cptr);
-#ifdef DEBUG
-           if (--codelen <= 0 || dictp->codem1 != finchar-1)
-             {
-               if (codelen <= 0)
-                 {
-                   printk("bsd_decomp%d: fell off end of chain ", db->unit);
-                   printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
-                          incode, finchar, dictp2->cptr, max_ent);
-                 }
-               else
-                 {
-                   if (dictp->codem1 != finchar-1)
-                     {
-                       printk("bsd_decomp%d: bad code chain 0x%x "
-                              "finchar=0x%x ",
-                              db->unit, incode, finchar);
-
-                       printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n",
-                              oldcode, dictp2->cptr, dictp->codem1);
-                     }
-                 }
-               return DECOMP_FATALERROR;
-             }
-#endif
-           *--p    = dictp->f.hs.suffix;
-           finchar = dictp->f.hs.prefix;
-         }
-       *--p = finchar;
-
-#ifdef DEBUG
-       if (--codelen != 0)
-         {
-           printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
-                  db->unit, codelen, incode, max_ent);
-         }
-#endif
-
-       if (extra)              /* the KwKwK case again */
-         {
-           *wptr++ = finchar;
-         }
-
-       /*
-        * If not first code in a packet, and
-        * if not out of code space, then allocate a new code.
-        *
-        * Keep the hash table correct so it can be used
-        * with uncompressed packets.
-        */
-
-       if (oldcode != CLEAR && max_ent < db->maxmaxcode)
-         {
-           struct bsd_dict *dictp2, *dictp3;
-           unsigned short  *lens1,  *lens2;
-           unsigned long fcode;
-           int hval, disp, indx;
-
-           fcode = BSD_KEY(oldcode,finchar);
-           hval  = BSD_HASH(oldcode,finchar,db->hshift);
-           dictp = dict_ptr (db, hval);
-
-           /* look for a free hash table entry */
-           if (dictp->codem1 < max_ent)
-             {
-               disp = (hval == 0) ? 1 : hval;
-               do
-                 {
-                   hval += disp;
-                   if (hval >= db->hsize)
-                     {
-                       hval -= db->hsize;
-                     }
-                   dictp = dict_ptr (db, hval);
-                 }
-               while (dictp->codem1 < max_ent);
-             }
-
-           /*
-            * Invalidate previous hash table entry
-            * assigned this code, and then take it over
-            */
-
-           dictp2 = dict_ptr (db, max_ent + 1);
-           indx   = dictp2->cptr;
-           dictp3 = dict_ptr (db, indx);
-
-           if (dictp3->codem1 == max_ent)
-             {
-               dictp3->codem1 = BADCODEM1;
-             }
-
-           dictp2->cptr   = hval;
-           dictp->codem1  = max_ent;
-           dictp->f.fcode = fcode;
-           db->max_ent    = ++max_ent;
-
-           /* Update the length of this string. */
-           lens1  = lens_ptr (db, max_ent);
-           lens2  = lens_ptr (db, oldcode);
-           *lens1 = *lens2 + 1;
-
-           /* Expand code size if needed. */
-           if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
-             {
-               db->n_bits = ++n_bits;
-               tgtbitno   = 32-n_bits;
-             }
-         }
-       oldcode = incode;
-      }
-
-    ++db->comp_count;
-    ++db->uncomp_count;
-    db->comp_bytes   += isize - BSD_OVHD - PPP_HDRLEN;
-    db->uncomp_bytes += explen;
-
-    if (bsd_check(db))
-      {
-       if (db->debug)
-         {
-           printk("bsd_decomp%d: peer should have cleared dictionary on %d\n",
-                  db->unit, db->seqno - 1);
-         }
-      }
-    return explen;
-  }
-
-/*************************************************************
- * Table of addresses for the BSD compression module
- *************************************************************/
-
-static struct compressor ppp_bsd_compress = {
-       .compress_proto =       CI_BSD_COMPRESS,
-       .comp_alloc =           bsd_comp_alloc,
-       .comp_free =            bsd_free,
-       .comp_init =            bsd_comp_init,
-       .comp_reset =           bsd_reset,
-       .compress =             bsd_compress,
-       .comp_stat =            bsd_comp_stats,
-       .decomp_alloc =         bsd_decomp_alloc,
-       .decomp_free =          bsd_free,
-       .decomp_init =          bsd_decomp_init,
-       .decomp_reset =         bsd_reset,
-       .decompress =           bsd_decompress,
-       .incomp =               bsd_incomp,
-       .decomp_stat =          bsd_comp_stats,
-       .owner =                THIS_MODULE
-};
-
-/*************************************************************
- * Module support routines
- *************************************************************/
-
-static int __init bsdcomp_init(void)
-{
-       int answer = ppp_register_compressor(&ppp_bsd_compress);
-       if (answer == 0)
-               printk(KERN_INFO "PPP BSD Compression module registered\n");
-       return answer;
-}
-
-static void __exit bsdcomp_cleanup(void)
-{
-       ppp_unregister_compressor(&ppp_bsd_compress);
-}
-
-module_init(bsdcomp_init);
-module_exit(bsdcomp_cleanup);
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("ppp-compress-" __stringify(CI_BSD_COMPRESS));
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
deleted file mode 100644 (file)
index 4ad80f7..0000000
+++ /dev/null
@@ -1,3739 +0,0 @@
-/*
- * File Name:
- *   defxx.c
- *
- * Copyright Information:
- *   Copyright Digital Equipment Corporation 1996.
- *
- *   This software may be used and distributed according to the terms of
- *   the GNU General Public License, incorporated herein by reference.
- *
- * Abstract:
- *   A Linux device driver supporting the Digital Equipment Corporation
- *   FDDI TURBOchannel, EISA and PCI controller families.  Supported
- *   adapters include:
- *
- *             DEC FDDIcontroller/TURBOchannel (DEFTA)
- *             DEC FDDIcontroller/EISA         (DEFEA)
- *             DEC FDDIcontroller/PCI          (DEFPA)
- *
- * The original author:
- *   LVS       Lawrence V. Stefani <lstefani@yahoo.com>
- *
- * Maintainers:
- *   macro     Maciej W. Rozycki <macro@linux-mips.org>
- *
- * Credits:
- *   I'd like to thank Patricia Cross for helping me get started with
- *   Linux, David Davies for a lot of help upgrading and configuring
- *   my development system and for answering many OS and driver
- *   development questions, and Alan Cox for recommendations and
- *   integration help on getting FDDI support into Linux.  LVS
- *
- * Driver Architecture:
- *   The driver architecture is largely based on previous driver work
- *   for other operating systems.  The upper edge interface and
- *   functions were largely taken from existing Linux device drivers
- *   such as David Davies' DE4X5.C driver and Donald Becker's TULIP.C
- *   driver.
- *
- *   Adapter Probe -
- *             The driver scans for supported EISA adapters by reading the
- *             SLOT ID register for each EISA slot and making a match
- *             against the expected value.
- *
- *   Bus-Specific Initialization -
- *             This driver currently supports both EISA and PCI controller
- *             families.  While the custom DMA chip and FDDI logic is similar
- *             or identical, the bus logic is very different.  After
- *             initialization, the     only bus-specific differences is in how the
- *             driver enables and disables interrupts.  Other than that, the
- *             run-time critical code behaves the same on both families.
- *             It's important to note that both adapter families are configured
- *             to I/O map, rather than memory map, the adapter registers.
- *
- *   Driver Open/Close -
- *             In the driver open routine, the driver ISR (interrupt service
- *             routine) is registered and the adapter is brought to an
- *             operational state.  In the driver close routine, the opposite
- *             occurs; the driver ISR is deregistered and the adapter is
- *             brought to a safe, but closed state.  Users may use consecutive
- *             commands to bring the adapter up and down as in the following
- *             example:
- *                                     ifconfig fddi0 up
- *                                     ifconfig fddi0 down
- *                                     ifconfig fddi0 up
- *
- *   Driver Shutdown -
- *             Apparently, there is no shutdown or halt routine support under
- *             Linux.  This routine would be called during "reboot" or
- *             "shutdown" to allow the driver to place the adapter in a safe
- *             state before a warm reboot occurs.  To be really safe, the user
- *             should close the adapter before shutdown (eg. ifconfig fddi0 down)
- *             to ensure that the adapter DMA engine is taken off-line.  However,
- *             the current driver code anticipates this problem and always issues
- *             a soft reset of the adapter     at the beginning of driver initialization.
- *             A future driver enhancement in this area may occur in 2.1.X where
- *             Alan indicated that a shutdown handler may be implemented.
- *
- *   Interrupt Service Routine -
- *             The driver supports shared interrupts, so the ISR is registered for
- *             each board with the appropriate flag and the pointer to that board's
- *             device structure.  This provides the context during interrupt
- *             processing to support shared interrupts and multiple boards.
- *
- *             Interrupt enabling/disabling can occur at many levels.  At the host
- *             end, you can disable system interrupts, or disable interrupts at the
- *             PIC (on Intel systems).  Across the bus, both EISA and PCI adapters
- *             have a bus-logic chip interrupt enable/disable as well as a DMA
- *             controller interrupt enable/disable.
- *
- *             The driver currently enables and disables adapter interrupts at the
- *             bus-logic chip and assumes that Linux will take care of clearing or
- *             acknowledging any host-based interrupt chips.
- *
- *   Control Functions -
- *             Control functions are those used to support functions such as adding
- *             or deleting multicast addresses, enabling or disabling packet
- *             reception filters, or other custom/proprietary commands.  Presently,
- *             the driver supports the "get statistics", "set multicast list", and
- *             "set mac address" functions defined by Linux.  A list of possible
- *             enhancements include:
- *
- *                             - Custom ioctl interface for executing port interface commands
- *                             - Custom ioctl interface for adding unicast addresses to
- *                               adapter CAM (to support bridge functions).
- *                             - Custom ioctl interface for supporting firmware upgrades.
- *
- *   Hardware (port interface) Support Routines -
- *             The driver function names that start with "dfx_hw_" represent
- *             low-level port interface routines that are called frequently.  They
- *             include issuing a DMA or port control command to the adapter,
- *             resetting the adapter, or reading the adapter state.  Since the
- *             driver initialization and run-time code must make calls into the
- *             port interface, these routines were written to be as generic and
- *             usable as possible.
- *
- *   Receive Path -
- *             The adapter DMA engine supports a 256 entry receive descriptor block
- *             of which up to 255 entries can be used at any given time.  The
- *             architecture is a standard producer, consumer, completion model in
- *             which the driver "produces" receive buffers to the adapter, the
- *             adapter "consumes" the receive buffers by DMAing incoming packet data,
- *             and the driver "completes" the receive buffers by servicing the
- *             incoming packet, then "produces" a new buffer and starts the cycle
- *             again.  Receive buffers can be fragmented in up to 16 fragments
- *             (descriptor     entries).  For simplicity, this driver posts
- *             single-fragment receive buffers of 4608 bytes, then allocates a
- *             sk_buff, copies the data, then reposts the buffer.  To reduce CPU
- *             utilization, a better approach would be to pass up the receive
- *             buffer (no extra copy) then allocate and post a replacement buffer.
- *             This is a performance enhancement that should be looked into at
- *             some point.
- *
- *   Transmit Path -
- *             Like the receive path, the adapter DMA engine supports a 256 entry
- *             transmit descriptor block of which up to 255 entries can be used at
- *             any     given time.  Transmit buffers can be fragmented in up to 255
- *             fragments (descriptor entries).  This driver always posts one
- *             fragment per transmit packet request.
- *
- *             The fragment contains the entire packet from FC to end of data.
- *             Before posting the buffer to the adapter, the driver sets a three-byte
- *             packet request header (PRH) which is required by the Motorola MAC chip
- *             used on the adapters.  The PRH tells the MAC the type of token to
- *             receive/send, whether or not to generate and append the CRC, whether
- *             synchronous or asynchronous framing is used, etc.  Since the PRH
- *             definition is not necessarily consistent across all FDDI chipsets,
- *             the driver, rather than the common FDDI packet handler routines,
- *             sets these bytes.
- *
- *             To reduce the amount of descriptor fetches needed per transmit request,
- *             the driver takes advantage of the fact that there are at least three
- *             bytes available before the skb->data field on the outgoing transmit
- *             request.  This is guaranteed by having fddi_setup() in net_init.c set
- *             dev->hard_header_len to 24 bytes.  21 bytes accounts for the largest
- *             header in an 802.2 SNAP frame.  The other 3 bytes are the extra "pad"
- *             bytes which we'll use to store the PRH.
- *
- *             There's a subtle advantage to adding these pad bytes to the
- *             hard_header_len, it ensures that the data portion of the packet for
- *             an 802.2 SNAP frame is longword aligned.  Other FDDI driver
- *             implementations may not need the extra padding and can start copying
- *             or DMAing directly from the FC byte which starts at skb->data.  Should
- *             another driver implementation need ADDITIONAL padding, the net_init.c
- *             module should be updated and dev->hard_header_len should be increased.
- *             NOTE: To maintain the alignment on the data portion of the packet,
- *             dev->hard_header_len should always be evenly divisible by 4 and at
- *             least 24 bytes in size.
- *
- * Modification History:
- *             Date            Name    Description
- *             16-Aug-96       LVS             Created.
- *             20-Aug-96       LVS             Updated dfx_probe so that version information
- *                                                     string is only displayed if 1 or more cards are
- *                                                     found.  Changed dfx_rcv_queue_process to copy
- *                                                     3 NULL bytes before FC to ensure that data is
- *                                                     longword aligned in receive buffer.
- *             09-Sep-96       LVS             Updated dfx_ctl_set_multicast_list to enable
- *                                                     LLC group promiscuous mode if multicast list
- *                                                     is too large.  LLC individual/group promiscuous
- *                                                     mode is now disabled if IFF_PROMISC flag not set.
- *                                                     dfx_xmt_queue_pkt no longer checks for NULL skb
- *                                                     on Alan Cox recommendation.  Added node address
- *                                                     override support.
- *             12-Sep-96       LVS             Reset current address to factory address during
- *                                                     device open.  Updated transmit path to post a
- *                                                     single fragment which includes PRH->end of data.
- *             Mar 2000        AC              Did various cleanups for 2.3.x
- *             Jun 2000        jgarzik         PCI and resource alloc cleanups
- *             Jul 2000        tjeerd          Much cleanup and some bug fixes
- *             Sep 2000        tjeerd          Fix leak on unload, cosmetic code cleanup
- *             Feb 2001                        Skb allocation fixes
- *             Feb 2001        davej           PCI enable cleanups.
- *             04 Aug 2003     macro           Converted to the DMA API.
- *             14 Aug 2004     macro           Fix device names reported.
- *             14 Jun 2005     macro           Use irqreturn_t.
- *             23 Oct 2006     macro           Big-endian host support.
- *             14 Dec 2006     macro           TURBOchannel support.
- */
-
-/* Include files */
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/eisa.h>
-#include <linux/errno.h>
-#include <linux/fddidevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/pci.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/tc.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "defxx.h"
-
-/* Version information string should be updated prior to each new release!  */
-#define DRV_NAME "defxx"
-#define DRV_VERSION "v1.10"
-#define DRV_RELDATE "2006/12/14"
-
-static char version[] __devinitdata =
-       DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
-       "  Lawrence V. Stefani and others\n";
-
-#define DYNAMIC_BUFFERS 1
-
-#define SKBUFF_RX_COPYBREAK 200
-/*
- * NEW_SKB_SIZE = PI_RCV_DATA_K_SIZE_MAX+128 to allow 128 byte
- * alignment for compatibility with old EISA boards.
- */
-#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)
-
-#ifdef CONFIG_PCI
-#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type)
-#else
-#define DFX_BUS_PCI(dev) 0
-#endif
-
-#ifdef CONFIG_EISA
-#define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type)
-#else
-#define DFX_BUS_EISA(dev) 0
-#endif
-
-#ifdef CONFIG_TC
-#define DFX_BUS_TC(dev) (dev->bus == &tc_bus_type)
-#else
-#define DFX_BUS_TC(dev) 0
-#endif
-
-#ifdef CONFIG_DEFXX_MMIO
-#define DFX_MMIO 1
-#else
-#define DFX_MMIO 0
-#endif
-
-/* Define module-wide (static) routines */
-
-static void            dfx_bus_init(struct net_device *dev);
-static void            dfx_bus_uninit(struct net_device *dev);
-static void            dfx_bus_config_check(DFX_board_t *bp);
-
-static int             dfx_driver_init(struct net_device *dev,
-                                       const char *print_name,
-                                       resource_size_t bar_start);
-static int             dfx_adap_init(DFX_board_t *bp, int get_buffers);
-
-static int             dfx_open(struct net_device *dev);
-static int             dfx_close(struct net_device *dev);
-
-static void            dfx_int_pr_halt_id(DFX_board_t *bp);
-static void            dfx_int_type_0_process(DFX_board_t *bp);
-static void            dfx_int_common(struct net_device *dev);
-static irqreturn_t     dfx_interrupt(int irq, void *dev_id);
-
-static struct          net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
-static void            dfx_ctl_set_multicast_list(struct net_device *dev);
-static int             dfx_ctl_set_mac_address(struct net_device *dev, void *addr);
-static int             dfx_ctl_update_cam(DFX_board_t *bp);
-static int             dfx_ctl_update_filters(DFX_board_t *bp);
-
-static int             dfx_hw_dma_cmd_req(DFX_board_t *bp);
-static int             dfx_hw_port_ctrl_req(DFX_board_t *bp, PI_UINT32 command, PI_UINT32 data_a, PI_UINT32 data_b, PI_UINT32 *host_data);
-static void            dfx_hw_adap_reset(DFX_board_t *bp, PI_UINT32 type);
-static int             dfx_hw_adap_state_rd(DFX_board_t *bp);
-static int             dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type);
-
-static int             dfx_rcv_init(DFX_board_t *bp, int get_buffers);
-static void            dfx_rcv_queue_process(DFX_board_t *bp);
-static void            dfx_rcv_flush(DFX_board_t *bp);
-
-static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
-                                    struct net_device *dev);
-static int             dfx_xmt_done(DFX_board_t *bp);
-static void            dfx_xmt_flush(DFX_board_t *bp);
-
-/* Define module-wide (static) variables */
-
-static struct pci_driver dfx_pci_driver;
-static struct eisa_driver dfx_eisa_driver;
-static struct tc_driver dfx_tc_driver;
-
-
-/*
- * =======================
- * = dfx_port_write_long =
- * = dfx_port_read_long  =
- * =======================
- *
- * Overview:
- *   Routines for reading and writing values from/to adapter
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp                - pointer to board information
- *   offset    - register offset from base I/O address
- *   data      - for dfx_port_write_long, this is a value to write;
- *               for dfx_port_read_long, this is a pointer to store
- *               the read value
- *
- * Functional Description:
- *   These routines perform the correct operation to read or write
- *   the adapter register.
- *
- *   EISA port block base addresses are based on the slot number in which the
- *   controller is installed.  For example, if the EISA controller is installed
- *   in slot 4, the port block base address is 0x4000.  If the controller is
- *   installed in slot 2, the port block base address is 0x2000, and so on.
- *   This port block can be used to access PDQ, ESIC, and DEFEA on-board
- *   registers using the register offsets defined in DEFXX.H.
- *
- *   PCI port block base addresses are assigned by the PCI BIOS or system
- *   firmware.  There is one 128 byte port block which can be accessed.  It
- *   allows for I/O mapping of both PDQ and PFI registers using the register
- *   offsets defined in DEFXX.H.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   bp->base is a valid base I/O address for this adapter.
- *   offset is a valid register offset for this adapter.
- *
- * Side Effects:
- *   Rather than produce macros for these functions, these routines
- *   are defined using "inline" to ensure that the compiler will
- *   generate inline code and not waste a procedure call and return.
- *   This provides all the benefits of macros, but with the
- *   advantage of strict data type checking.
- */
-
-static inline void dfx_writel(DFX_board_t *bp, int offset, u32 data)
-{
-       writel(data, bp->base.mem + offset);
-       mb();
-}
-
-static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data)
-{
-       outl(data, bp->base.port + offset);
-}
-
-static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data)
-{
-       struct device __maybe_unused *bdev = bp->bus_dev;
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-
-       if (dfx_use_mmio)
-               dfx_writel(bp, offset, data);
-       else
-               dfx_outl(bp, offset, data);
-}
-
-
-static inline void dfx_readl(DFX_board_t *bp, int offset, u32 *data)
-{
-       mb();
-       *data = readl(bp->base.mem + offset);
-}
-
-static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data)
-{
-       *data = inl(bp->base.port + offset);
-}
-
-static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
-{
-       struct device __maybe_unused *bdev = bp->bus_dev;
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-
-       if (dfx_use_mmio)
-               dfx_readl(bp, offset, data);
-       else
-               dfx_inl(bp, offset, data);
-}
-
-
-/*
- * ================
- * = dfx_get_bars =
- * ================
- *
- * Overview:
- *   Retrieves the address range used to access control and status
- *   registers.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bdev      - pointer to device information
- *   bar_start - pointer to store the start address
- *   bar_len   - pointer to store the length of the area
- *
- * Assumptions:
- *   I am sure there are some.
- *
- * Side Effects:
- *   None
- */
-static void dfx_get_bars(struct device *bdev,
-                        resource_size_t *bar_start, resource_size_t *bar_len)
-{
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-
-       if (dfx_bus_pci) {
-               int num = dfx_use_mmio ? 0 : 1;
-
-               *bar_start = pci_resource_start(to_pci_dev(bdev), num);
-               *bar_len = pci_resource_len(to_pci_dev(bdev), num);
-       }
-       if (dfx_bus_eisa) {
-               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-               resource_size_t bar;
-
-               if (dfx_use_mmio) {
-                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
-                       bar <<= 16;
-                       *bar_start = bar;
-                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
-                       bar <<= 8;
-                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
-                       bar <<= 16;
-                       *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
-               } else {
-                       *bar_start = base_addr;
-                       *bar_len = PI_ESIC_K_CSR_IO_LEN;
-               }
-       }
-       if (dfx_bus_tc) {
-               *bar_start = to_tc_dev(bdev)->resource.start +
-                            PI_TC_K_CSR_OFFSET;
-               *bar_len = PI_TC_K_CSR_LEN;
-       }
-}
-
-static const struct net_device_ops dfx_netdev_ops = {
-       .ndo_open               = dfx_open,
-       .ndo_stop               = dfx_close,
-       .ndo_start_xmit         = dfx_xmt_queue_pkt,
-       .ndo_get_stats          = dfx_ctl_get_stats,
-       .ndo_set_rx_mode        = dfx_ctl_set_multicast_list,
-       .ndo_set_mac_address    = dfx_ctl_set_mac_address,
-};
-
-/*
- * ================
- * = dfx_register =
- * ================
- *
- * Overview:
- *   Initializes a supported FDDI controller
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bdev - pointer to device information
- *
- * Functional Description:
- *
- * Return Codes:
- *   0          - This device (fddi0, fddi1, etc) configured successfully
- *   -EBUSY      - Failed to get resources, or dfx_driver_init failed.
- *
- * Assumptions:
- *   It compiles so it should work :-( (PCI cards do :-)
- *
- * Side Effects:
- *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
- *   initialized and the board resources are read and stored in
- *   the device structure.
- */
-static int __devinit dfx_register(struct device *bdev)
-{
-       static int version_disp;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-       const char *print_name = dev_name(bdev);
-       struct net_device *dev;
-       DFX_board_t       *bp;                  /* board pointer */
-       resource_size_t bar_start = 0;          /* pointer to port */
-       resource_size_t bar_len = 0;            /* resource length */
-       int alloc_size;                         /* total buffer size used */
-       struct resource *region;
-       int err = 0;
-
-       if (!version_disp) {    /* display version info if adapter is found */
-               version_disp = 1;       /* set display flag to TRUE so that */
-               printk(version);        /* we only display this string ONCE */
-       }
-
-       dev = alloc_fddidev(sizeof(*bp));
-       if (!dev) {
-               printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n",
-                      print_name);
-               return -ENOMEM;
-       }
-
-       /* Enable PCI device. */
-       if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
-               printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
-                      print_name);
-               goto err_out;
-       }
-
-       SET_NETDEV_DEV(dev, bdev);
-
-       bp = netdev_priv(dev);
-       bp->bus_dev = bdev;
-       dev_set_drvdata(bdev, dev);
-
-       dfx_get_bars(bdev, &bar_start, &bar_len);
-
-       if (dfx_use_mmio)
-               region = request_mem_region(bar_start, bar_len, print_name);
-       else
-               region = request_region(bar_start, bar_len, print_name);
-       if (!region) {
-               printk(KERN_ERR "%s: Cannot reserve I/O resource "
-                      "0x%lx @ 0x%lx, aborting\n",
-                      print_name, (long)bar_len, (long)bar_start);
-               err = -EBUSY;
-               goto err_out_disable;
-       }
-
-       /* Set up I/O base address. */
-       if (dfx_use_mmio) {
-               bp->base.mem = ioremap_nocache(bar_start, bar_len);
-               if (!bp->base.mem) {
-                       printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
-                       err = -ENOMEM;
-                       goto err_out_region;
-               }
-       } else {
-               bp->base.port = bar_start;
-               dev->base_addr = bar_start;
-       }
-
-       /* Initialize new device structure */
-       dev->netdev_ops                 = &dfx_netdev_ops;
-
-       if (dfx_bus_pci)
-               pci_set_master(to_pci_dev(bdev));
-
-       if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
-               err = -ENODEV;
-               goto err_out_unmap;
-       }
-
-       err = register_netdev(dev);
-       if (err)
-               goto err_out_kfree;
-
-       printk("%s: registered as %s\n", print_name, dev->name);
-       return 0;
-
-err_out_kfree:
-       alloc_size = sizeof(PI_DESCR_BLOCK) +
-                    PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
-#ifndef DYNAMIC_BUFFERS
-                    (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
-#endif
-                    sizeof(PI_CONSUMER_BLOCK) +
-                    (PI_ALIGN_K_DESC_BLK - 1);
-       if (bp->kmalloced)
-               dma_free_coherent(bdev, alloc_size,
-                                 bp->kmalloced, bp->kmalloced_dma);
-
-err_out_unmap:
-       if (dfx_use_mmio)
-               iounmap(bp->base.mem);
-
-err_out_region:
-       if (dfx_use_mmio)
-               release_mem_region(bar_start, bar_len);
-       else
-               release_region(bar_start, bar_len);
-
-err_out_disable:
-       if (dfx_bus_pci)
-               pci_disable_device(to_pci_dev(bdev));
-
-err_out:
-       free_netdev(dev);
-       return err;
-}
-
-
-/*
- * ================
- * = dfx_bus_init =
- * ================
- *
- * Overview:
- *   Initializes the bus-specific controller logic.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Determine and save adapter IRQ in device table,
- *   then perform bus-specific logic initialization.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   bp->base has already been set with the proper
- *      base I/O address for this device.
- *
- * Side Effects:
- *   Interrupts are enabled at the adapter bus-specific logic.
- *   Note:  Interrupts at the DMA engine (PDQ chip) are not
- *   enabled yet.
- */
-
-static void __devinit dfx_bus_init(struct net_device *dev)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-       struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-       u8 val;
-
-       DBG_printk("In dfx_bus_init...\n");
-
-       /* Initialize a pointer back to the net_device struct */
-       bp->dev = dev;
-
-       /* Initialize adapter based on bus type */
-
-       if (dfx_bus_tc)
-               dev->irq = to_tc_dev(bdev)->interrupt;
-       if (dfx_bus_eisa) {
-               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-
-               /* Get the interrupt level from the ESIC chip.  */
-               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-               val &= PI_CONFIG_STAT_0_M_IRQ;
-               val >>= PI_CONFIG_STAT_0_V_IRQ;
-
-               switch (val) {
-               case PI_CONFIG_STAT_0_IRQ_K_9:
-                       dev->irq = 9;
-                       break;
-
-               case PI_CONFIG_STAT_0_IRQ_K_10:
-                       dev->irq = 10;
-                       break;
-
-               case PI_CONFIG_STAT_0_IRQ_K_11:
-                       dev->irq = 11;
-                       break;
-
-               case PI_CONFIG_STAT_0_IRQ_K_15:
-                       dev->irq = 15;
-                       break;
-               }
-
-               /*
-                * Enable memory decoding (MEMCS0) and/or port decoding
-                * (IOCS1/IOCS0) as appropriate in Function Control
-                * Register.  One of the port chip selects seems to be
-                * used for the Burst Holdoff register, but this bit of
-                * documentation is missing and as yet it has not been
-                * determined which of the two.  This is also the reason
-                * the size of the decoded port range is twice as large
-                * as one required by the PDQ.
-                */
-
-               /* Set the decode range of the board.  */
-               val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT);
-               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val);
-               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0);
-               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val);
-               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0);
-               val = PI_ESIC_K_CSR_IO_LEN - 1;
-               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff);
-               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff);
-               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff);
-               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff);
-
-               /* Enable the decoders.  */
-               val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
-               if (dfx_use_mmio)
-                       val |= PI_FUNCTION_CNTRL_M_MEMCS0;
-               outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val);
-
-               /*
-                * Enable access to the rest of the module
-                * (including PDQ and packet memory).
-                */
-               val = PI_SLOT_CNTRL_M_ENB;
-               outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val);
-
-               /*
-                * Map PDQ registers into memory or port space.  This is
-                * done with a bit in the Burst Holdoff register.
-                */
-               val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF);
-               if (dfx_use_mmio)
-                       val |= PI_BURST_HOLDOFF_V_MEM_MAP;
-               else
-                       val &= ~PI_BURST_HOLDOFF_V_MEM_MAP;
-               outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val);
-
-               /* Enable interrupts at EISA bus interface chip (ESIC) */
-               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-               val |= PI_CONFIG_STAT_0_M_INT_ENB;
-               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
-       }
-       if (dfx_bus_pci) {
-               struct pci_dev *pdev = to_pci_dev(bdev);
-
-               /* Get the interrupt level from the PCI Configuration Table */
-
-               dev->irq = pdev->irq;
-
-               /* Check Latency Timer and set if less than minimal */
-
-               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
-               if (val < PFI_K_LAT_TIMER_MIN) {
-                       val = PFI_K_LAT_TIMER_DEF;
-                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
-               }
-
-               /* Enable interrupts at PCI bus interface chip (PFI) */
-               val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB;
-               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val);
-       }
-}
-
-/*
- * ==================
- * = dfx_bus_uninit =
- * ==================
- *
- * Overview:
- *   Uninitializes the bus-specific controller logic.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Perform bus-specific logic uninitialization.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   bp->base has already been set with the proper
- *      base I/O address for this device.
- *
- * Side Effects:
- *   Interrupts are disabled at the adapter bus-specific logic.
- */
-
-static void __devexit dfx_bus_uninit(struct net_device *dev)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-       struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-       u8 val;
-
-       DBG_printk("In dfx_bus_uninit...\n");
-
-       /* Uninitialize adapter based on bus type */
-
-       if (dfx_bus_eisa) {
-               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-
-               /* Disable interrupts at EISA bus interface chip (ESIC) */
-               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-               val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
-       }
-       if (dfx_bus_pci) {
-               /* Disable interrupts at PCI bus interface chip (PFI) */
-               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0);
-       }
-}
-
-
-/*
- * ========================
- * = dfx_bus_config_check =
- * ========================
- *
- * Overview:
- *   Checks the configuration (burst size, full-duplex, etc.)  If any parameters
- *   are illegal, then this routine will set new defaults.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   For Revision 1 FDDI EISA, Revision 2 or later FDDI EISA with rev E or later
- *   PDQ, and all FDDI PCI controllers, all values are legal.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   dfx_adap_init has NOT been called yet so burst size and other items have
- *   not been set.
- *
- * Side Effects:
- *   None
- */
-
-static void __devinit dfx_bus_config_check(DFX_board_t *bp)
-{
-       struct device __maybe_unused *bdev = bp->bus_dev;
-       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-       int     status;                         /* return code from adapter port control call */
-       u32     host_data;                      /* LW data returned from port control call */
-
-       DBG_printk("In dfx_bus_config_check...\n");
-
-       /* Configuration check only valid for EISA adapter */
-
-       if (dfx_bus_eisa) {
-               /*
-                * First check if revision 2 EISA controller.  Rev. 1 cards used
-                * PDQ revision B, so no workaround needed in this case.  Rev. 3
-                * cards used PDQ revision E, so no workaround needed in this
-                * case, either.  Only Rev. 2 cards used either Rev. D or E
-                * chips, so we must verify the chip revision on Rev. 2 cards.
-                */
-               if (to_eisa_device(bdev)->id.driver_data == DEFEA_PROD_ID_2) {
-                       /*
-                        * Revision 2 FDDI EISA controller found,
-                        * so let's check PDQ revision of adapter.
-                        */
-                       status = dfx_hw_port_ctrl_req(bp,
-                                                                                       PI_PCTRL_M_SUB_CMD,
-                                                                                       PI_SUB_CMD_K_PDQ_REV_GET,
-                                                                                       0,
-                                                                                       &host_data);
-                       if ((status != DFX_K_SUCCESS) || (host_data == 2))
-                               {
-                               /*
-                                * Either we couldn't determine the PDQ revision, or
-                                * we determined that it is at revision D.  In either case,
-                                * we need to implement the workaround.
-                                */
-
-                               /* Ensure that the burst size is set to 8 longwords or less */
-
-                               switch (bp->burst_size)
-                                       {
-                                       case PI_PDATA_B_DMA_BURST_SIZE_32:
-                                       case PI_PDATA_B_DMA_BURST_SIZE_16:
-                                               bp->burst_size = PI_PDATA_B_DMA_BURST_SIZE_8;
-                                               break;
-
-                                       default:
-                                               break;
-                                       }
-
-                               /* Ensure that full-duplex mode is not enabled */
-
-                               bp->full_duplex_enb = PI_SNMP_K_FALSE;
-                               }
-                       }
-               }
-       }
-
-
-/*
- * ===================
- * = dfx_driver_init =
- * ===================
- *
- * Overview:
- *   Initializes remaining adapter board structure information
- *   and makes sure adapter is in a safe state prior to dfx_open().
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   dev - pointer to device information
- *   print_name - printable device name
- *
- * Functional Description:
- *   This function allocates additional resources such as the host memory
- *   blocks needed by the adapter (eg. descriptor and consumer blocks).
- *      Remaining bus initialization steps are also completed.  The adapter
- *   is also reset so that it is in the DMA_UNAVAILABLE state.  The OS
- *   must call dfx_open() to open the adapter and bring it on-line.
- *
- * Return Codes:
- *   DFX_K_SUCCESS     - initialization succeeded
- *   DFX_K_FAILURE     - initialization failed - could not allocate memory
- *                                             or read adapter MAC address
- *
- * Assumptions:
- *   Memory allocated from pci_alloc_consistent() call is physically
- *   contiguous, locked memory.
- *
- * Side Effects:
- *   Adapter is reset and should be in DMA_UNAVAILABLE state before
- *   returning from this routine.
- */
-
-static int __devinit dfx_driver_init(struct net_device *dev,
-                                    const char *print_name,
-                                    resource_size_t bar_start)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-       struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-       int alloc_size;                 /* total buffer size needed */
-       char *top_v, *curr_v;           /* virtual addrs into memory block */
-       dma_addr_t top_p, curr_p;       /* physical addrs into memory block */
-       u32 data;                       /* host data register value */
-       __le32 le32;
-       char *board_name = NULL;
-
-       DBG_printk("In dfx_driver_init...\n");
-
-       /* Initialize bus-specific hardware registers */
-
-       dfx_bus_init(dev);
-
-       /*
-        * Initialize default values for configurable parameters
-        *
-        * Note: All of these parameters are ones that a user may
-        *       want to customize.  It'd be nice to break these
-        *               out into Space.c or someplace else that's more
-        *               accessible/understandable than this file.
-        */
-
-       bp->full_duplex_enb             = PI_SNMP_K_FALSE;
-       bp->req_ttrt                    = 8 * 12500;            /* 8ms in 80 nanosec units */
-       bp->burst_size                  = PI_PDATA_B_DMA_BURST_SIZE_DEF;
-       bp->rcv_bufs_to_post    = RCV_BUFS_DEF;
-
-       /*
-        * Ensure that HW configuration is OK
-        *
-        * Note: Depending on the hardware revision, we may need to modify
-        *       some of the configurable parameters to workaround hardware
-        *       limitations.  We'll perform this configuration check AFTER
-        *       setting the parameters to their default values.
-        */
-
-       dfx_bus_config_check(bp);
-
-       /* Disable PDQ interrupts first */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-
-       /* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
-
-       (void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
-
-       /*  Read the factory MAC address from the adapter then save it */
-
-       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0,
-                                &data) != DFX_K_SUCCESS) {
-               printk("%s: Could not read adapter factory MAC address!\n",
-                      print_name);
-               return DFX_K_FAILURE;
-       }
-       le32 = cpu_to_le32(data);
-       memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
-
-       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
-                                &data) != DFX_K_SUCCESS) {
-               printk("%s: Could not read adapter factory MAC address!\n",
-                      print_name);
-               return DFX_K_FAILURE;
-       }
-       le32 = cpu_to_le32(data);
-       memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
-
-       /*
-        * Set current address to factory address
-        *
-        * Note: Node address override support is handled through
-        *       dfx_ctl_set_mac_address.
-        */
-
-       memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
-       if (dfx_bus_tc)
-               board_name = "DEFTA";
-       if (dfx_bus_eisa)
-               board_name = "DEFEA";
-       if (dfx_bus_pci)
-               board_name = "DEFPA";
-       pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
-               print_name, board_name, dfx_use_mmio ? "" : "I/O ",
-               (long long)bar_start, dev->irq, dev->dev_addr);
-
-       /*
-        * Get memory for descriptor block, consumer block, and other buffers
-        * that need to be DMA read or written to by the adapter.
-        */
-
-       alloc_size = sizeof(PI_DESCR_BLOCK) +
-                                       PI_CMD_REQ_K_SIZE_MAX +
-                                       PI_CMD_RSP_K_SIZE_MAX +
-#ifndef DYNAMIC_BUFFERS
-                                       (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
-#endif
-                                       sizeof(PI_CONSUMER_BLOCK) +
-                                       (PI_ALIGN_K_DESC_BLK - 1);
-       bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
-                                                  &bp->kmalloced_dma,
-                                                  GFP_ATOMIC);
-       if (top_v == NULL) {
-               printk("%s: Could not allocate memory for host buffers "
-                      "and structures!\n", print_name);
-               return DFX_K_FAILURE;
-       }
-       memset(top_v, 0, alloc_size);   /* zero out memory before continuing */
-       top_p = bp->kmalloced_dma;      /* get physical address of buffer */
-
-       /*
-        *  To guarantee the 8K alignment required for the descriptor block, 8K - 1
-        *  plus the amount of memory needed was allocated.  The physical address
-        *      is now 8K aligned.  By carving up the memory in a specific order,
-        *  we'll guarantee the alignment requirements for all other structures.
-        *
-        *  Note: If the assumptions change regarding the non-paged, non-cached,
-        *                physically contiguous nature of the memory block or the address
-        *                alignments, then we'll need to implement a different algorithm
-        *                for allocating the needed memory.
-        */
-
-       curr_p = ALIGN(top_p, PI_ALIGN_K_DESC_BLK);
-       curr_v = top_v + (curr_p - top_p);
-
-       /* Reserve space for descriptor block */
-
-       bp->descr_block_virt = (PI_DESCR_BLOCK *) curr_v;
-       bp->descr_block_phys = curr_p;
-       curr_v += sizeof(PI_DESCR_BLOCK);
-       curr_p += sizeof(PI_DESCR_BLOCK);
-
-       /* Reserve space for command request buffer */
-
-       bp->cmd_req_virt = (PI_DMA_CMD_REQ *) curr_v;
-       bp->cmd_req_phys = curr_p;
-       curr_v += PI_CMD_REQ_K_SIZE_MAX;
-       curr_p += PI_CMD_REQ_K_SIZE_MAX;
-
-       /* Reserve space for command response buffer */
-
-       bp->cmd_rsp_virt = (PI_DMA_CMD_RSP *) curr_v;
-       bp->cmd_rsp_phys = curr_p;
-       curr_v += PI_CMD_RSP_K_SIZE_MAX;
-       curr_p += PI_CMD_RSP_K_SIZE_MAX;
-
-       /* Reserve space for the LLC host receive queue buffers */
-
-       bp->rcv_block_virt = curr_v;
-       bp->rcv_block_phys = curr_p;
-
-#ifndef DYNAMIC_BUFFERS
-       curr_v += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
-       curr_p += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
-#endif
-
-       /* Reserve space for the consumer block */
-
-       bp->cons_block_virt = (PI_CONSUMER_BLOCK *) curr_v;
-       bp->cons_block_phys = curr_p;
-
-       /* Display virtual and physical addresses if debug driver */
-
-       DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
-                  print_name,
-                  (long)bp->descr_block_virt, bp->descr_block_phys);
-       DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
-                  print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
-       DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
-                  print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
-       DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
-                  print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
-       DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
-                  print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
-
-       return DFX_K_SUCCESS;
-}
-
-
-/*
- * =================
- * = dfx_adap_init =
- * =================
- *
- * Overview:
- *   Brings the adapter to the link avail/link unavailable state.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *   get_buffers - non-zero if buffers to be allocated
- *
- * Functional Description:
- *   Issues the low-level firmware/hardware calls necessary to bring
- *   the adapter up, or to properly reset and restore adapter during
- *   run-time.
- *
- * Return Codes:
- *   DFX_K_SUCCESS - Adapter brought up successfully
- *   DFX_K_FAILURE - Adapter initialization failed
- *
- * Assumptions:
- *   bp->reset_type should be set to a valid reset type value before
- *   calling this routine.
- *
- * Side Effects:
- *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
- *   upon a successful return of this routine.
- */
-
-static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
-       {
-       DBG_printk("In dfx_adap_init...\n");
-
-       /* Disable PDQ interrupts first */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-
-       /* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
-
-       if (dfx_hw_dma_uninit(bp, bp->reset_type) != DFX_K_SUCCESS)
-               {
-               printk("%s: Could not uninitialize/reset adapter!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /*
-        * When the PDQ is reset, some false Type 0 interrupts may be pending,
-        * so we'll acknowledge all Type 0 interrupts now before continuing.
-        */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, PI_HOST_INT_K_ACK_ALL_TYPE_0);
-
-       /*
-        * Clear Type 1 and Type 2 registers before going to DMA_AVAILABLE state
-        *
-        * Note: We only need to clear host copies of these registers.  The PDQ reset
-        *       takes care of the on-board register values.
-        */
-
-       bp->cmd_req_reg.lword   = 0;
-       bp->cmd_rsp_reg.lword   = 0;
-       bp->rcv_xmt_reg.lword   = 0;
-
-       /* Clear consumer block before going to DMA_AVAILABLE state */
-
-       memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
-
-       /* Initialize the DMA Burst Size */
-
-       if (dfx_hw_port_ctrl_req(bp,
-                                                       PI_PCTRL_M_SUB_CMD,
-                                                       PI_SUB_CMD_K_BURST_SIZE_SET,
-                                                       bp->burst_size,
-                                                       NULL) != DFX_K_SUCCESS)
-               {
-               printk("%s: Could not set adapter burst size!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /*
-        * Set base address of Consumer Block
-        *
-        * Assumption: 32-bit physical address of consumer block is 64 byte
-        *                         aligned.  That is, bits 0-5 of the address must be zero.
-        */
-
-       if (dfx_hw_port_ctrl_req(bp,
-                                                       PI_PCTRL_M_CONS_BLOCK,
-                                                       bp->cons_block_phys,
-                                                       0,
-                                                       NULL) != DFX_K_SUCCESS)
-               {
-               printk("%s: Could not set consumer block address!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /*
-        * Set the base address of Descriptor Block and bring adapter
-        * to DMA_AVAILABLE state.
-        *
-        * Note: We also set the literal and data swapping requirements
-        *       in this command.
-        *
-        * Assumption: 32-bit physical address of descriptor block
-        *       is 8Kbyte aligned.
-        */
-       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_INIT,
-                                (u32)(bp->descr_block_phys |
-                                      PI_PDATA_A_INIT_M_BSWAP_INIT),
-                                0, NULL) != DFX_K_SUCCESS) {
-               printk("%s: Could not set descriptor block address!\n",
-                      bp->dev->name);
-               return DFX_K_FAILURE;
-       }
-
-       /* Set transmit flush timeout value */
-
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_CHARS_SET;
-       bp->cmd_req_virt->char_set.item[0].item_code    = PI_ITEM_K_FLUSH_TIME;
-       bp->cmd_req_virt->char_set.item[0].value                = 3;    /* 3 seconds */
-       bp->cmd_req_virt->char_set.item[0].item_index   = 0;
-       bp->cmd_req_virt->char_set.item[1].item_code    = PI_ITEM_K_EOL;
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               {
-               printk("%s: DMA command request failed!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /* Set the initial values for eFDXEnable and MACTReq MIB objects */
-
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_SNMP_SET;
-       bp->cmd_req_virt->snmp_set.item[0].item_code    = PI_ITEM_K_FDX_ENB_DIS;
-       bp->cmd_req_virt->snmp_set.item[0].value                = bp->full_duplex_enb;
-       bp->cmd_req_virt->snmp_set.item[0].item_index   = 0;
-       bp->cmd_req_virt->snmp_set.item[1].item_code    = PI_ITEM_K_MAC_T_REQ;
-       bp->cmd_req_virt->snmp_set.item[1].value                = bp->req_ttrt;
-       bp->cmd_req_virt->snmp_set.item[1].item_index   = 0;
-       bp->cmd_req_virt->snmp_set.item[2].item_code    = PI_ITEM_K_EOL;
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               {
-               printk("%s: DMA command request failed!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /* Initialize adapter CAM */
-
-       if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
-               {
-               printk("%s: Adapter CAM update failed!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /* Initialize adapter filters */
-
-       if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
-               {
-               printk("%s: Adapter filters update failed!\n", bp->dev->name);
-               return DFX_K_FAILURE;
-               }
-
-       /*
-        * Remove any existing dynamic buffers (i.e. if the adapter is being
-        * reinitialized)
-        */
-
-       if (get_buffers)
-               dfx_rcv_flush(bp);
-
-       /* Initialize receive descriptor block and produce buffers */
-
-       if (dfx_rcv_init(bp, get_buffers))
-               {
-               printk("%s: Receive buffer allocation failed\n", bp->dev->name);
-               if (get_buffers)
-                       dfx_rcv_flush(bp);
-               return DFX_K_FAILURE;
-               }
-
-       /* Issue START command and bring adapter to LINK_(UN)AVAILABLE state */
-
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_START;
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               {
-               printk("%s: Start command failed\n", bp->dev->name);
-               if (get_buffers)
-                       dfx_rcv_flush(bp);
-               return DFX_K_FAILURE;
-               }
-
-       /* Initialization succeeded, reenable PDQ interrupts */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_ENABLE_DEF_INTS);
-       return DFX_K_SUCCESS;
-       }
-
-
-/*
- * ============
- * = dfx_open =
- * ============
- *
- * Overview:
- *   Opens the adapter
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This function brings the adapter to an operational state.
- *
- * Return Codes:
- *   0          - Adapter was successfully opened
- *   -EAGAIN - Could not register IRQ or adapter initialization failed
- *
- * Assumptions:
- *   This routine should only be called for a device that was
- *   initialized successfully.
- *
- * Side Effects:
- *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
- *   if the open is successful.
- */
-
-static int dfx_open(struct net_device *dev)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-       int ret;
-
-       DBG_printk("In dfx_open...\n");
-
-       /* Register IRQ - support shared interrupts by passing device ptr */
-
-       ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name,
-                         dev);
-       if (ret) {
-               printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
-               return ret;
-       }
-
-       /*
-        * Set current address to factory MAC address
-        *
-        * Note: We've already done this step in dfx_driver_init.
-        *       However, it's possible that a user has set a node
-        *               address override, then closed and reopened the
-        *               adapter.  Unless we reset the device address field
-        *               now, we'll continue to use the existing modified
-        *               address.
-        */
-
-       memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
-
-       /* Clear local unicast/multicast address tables and counts */
-
-       memset(bp->uc_table, 0, sizeof(bp->uc_table));
-       memset(bp->mc_table, 0, sizeof(bp->mc_table));
-       bp->uc_count = 0;
-       bp->mc_count = 0;
-
-       /* Disable promiscuous filter settings */
-
-       bp->ind_group_prom      = PI_FSTATE_K_BLOCK;
-       bp->group_prom          = PI_FSTATE_K_BLOCK;
-
-       spin_lock_init(&bp->lock);
-
-       /* Reset and initialize adapter */
-
-       bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST;    /* skip self-test */
-       if (dfx_adap_init(bp, 1) != DFX_K_SUCCESS)
-       {
-               printk(KERN_ERR "%s: Adapter open failed!\n", dev->name);
-               free_irq(dev->irq, dev);
-               return -EAGAIN;
-       }
-
-       /* Set device structure info */
-       netif_start_queue(dev);
-       return 0;
-}
-
-
-/*
- * =============
- * = dfx_close =
- * =============
- *
- * Overview:
- *   Closes the device/module.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This routine closes the adapter and brings it to a safe state.
- *   The interrupt service routine is deregistered with the OS.
- *   The adapter can be opened again with another call to dfx_open().
- *
- * Return Codes:
- *   Always return 0.
- *
- * Assumptions:
- *   No further requests for this adapter are made after this routine is
- *   called.  dfx_open() can be called to reset and reinitialize the
- *   adapter.
- *
- * Side Effects:
- *   Adapter should be in DMA_UNAVAILABLE state upon completion of this
- *   routine.
- */
-
-static int dfx_close(struct net_device *dev)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-
-       DBG_printk("In dfx_close...\n");
-
-       /* Disable PDQ interrupts first */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-
-       /* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
-
-       (void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
-
-       /*
-        * Flush any pending transmit buffers
-        *
-        * Note: It's important that we flush the transmit buffers
-        *               BEFORE we clear our copy of the Type 2 register.
-        *               Otherwise, we'll have no idea how many buffers
-        *               we need to free.
-        */
-
-       dfx_xmt_flush(bp);
-
-       /*
-        * Clear Type 1 and Type 2 registers after adapter reset
-        *
-        * Note: Even though we're closing the adapter, it's
-        *       possible that an interrupt will occur after
-        *               dfx_close is called.  Without some assurance to
-        *               the contrary we want to make sure that we don't
-        *               process receive and transmit LLC frames and update
-        *               the Type 2 register with bad information.
-        */
-
-       bp->cmd_req_reg.lword   = 0;
-       bp->cmd_rsp_reg.lword   = 0;
-       bp->rcv_xmt_reg.lword   = 0;
-
-       /* Clear consumer block for the same reason given above */
-
-       memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
-
-       /* Release all dynamically allocate skb in the receive ring. */
-
-       dfx_rcv_flush(bp);
-
-       /* Clear device structure flags */
-
-       netif_stop_queue(dev);
-
-       /* Deregister (free) IRQ */
-
-       free_irq(dev->irq, dev);
-
-       return 0;
-}
-
-
-/*
- * ======================
- * = dfx_int_pr_halt_id =
- * ======================
- *
- * Overview:
- *   Displays halt id's in string form.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Determine current halt id and display appropriate string.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static void dfx_int_pr_halt_id(DFX_board_t     *bp)
-       {
-       PI_UINT32       port_status;                    /* PDQ port status register value */
-       PI_UINT32       halt_id;                                /* PDQ port status halt ID */
-
-       /* Read the latest port status */
-
-       dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-
-       /* Display halt state transition information */
-
-       halt_id = (port_status & PI_PSTATUS_M_HALT_ID) >> PI_PSTATUS_V_HALT_ID;
-       switch (halt_id)
-               {
-               case PI_HALT_ID_K_SELFTEST_TIMEOUT:
-                       printk("%s: Halt ID: Selftest Timeout\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_PARITY_ERROR:
-                       printk("%s: Halt ID: Host Bus Parity Error\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_HOST_DIR_HALT:
-                       printk("%s: Halt ID: Host-Directed Halt\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_SW_FAULT:
-                       printk("%s: Halt ID: Adapter Software Fault\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_HW_FAULT:
-                       printk("%s: Halt ID: Adapter Hardware Fault\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_PC_TRACE:
-                       printk("%s: Halt ID: FDDI Network PC Trace Path Test\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_DMA_ERROR:
-                       printk("%s: Halt ID: Adapter DMA Error\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_IMAGE_CRC_ERROR:
-                       printk("%s: Halt ID: Firmware Image CRC Error\n", bp->dev->name);
-                       break;
-
-               case PI_HALT_ID_K_BUS_EXCEPTION:
-                       printk("%s: Halt ID: 68000 Bus Exception\n", bp->dev->name);
-                       break;
-
-               default:
-                       printk("%s: Halt ID: Unknown (code = %X)\n", bp->dev->name, halt_id);
-                       break;
-               }
-       }
-
-
-/*
- * ==========================
- * = dfx_int_type_0_process =
- * ==========================
- *
- * Overview:
- *   Processes Type 0 interrupts.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Processes all enabled Type 0 interrupts.  If the reason for the interrupt
- *   is a serious fault on the adapter, then an error message is displayed
- *   and the adapter is reset.
- *
- *   One tricky potential timing window is the rapid succession of "link avail"
- *   "link unavail" state change interrupts.  The acknowledgement of the Type 0
- *   interrupt must be done before reading the state from the Port Status
- *   register.  This is true because a state change could occur after reading
- *   the data, but before acknowledging the interrupt.  If this state change
- *   does happen, it would be lost because the driver is using the old state,
- *   and it will never know about the new state because it subsequently
- *   acknowledges the state change interrupt.
- *
- *          INCORRECT                                      CORRECT
- *      read type 0 int reasons                   read type 0 int reasons
- *      read adapter state                        ack type 0 interrupts
- *      ack type 0 interrupts                     read adapter state
- *      ... process interrupt ...                 ... process interrupt ...
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   An adapter reset may occur if the adapter has any Type 0 error interrupts
- *   or if the port status indicates that the adapter is halted.  The driver
- *   is responsible for reinitializing the adapter with the current CAM
- *   contents and adapter filter settings.
- */
-
-static void dfx_int_type_0_process(DFX_board_t *bp)
-
-       {
-       PI_UINT32       type_0_status;          /* Host Interrupt Type 0 register */
-       PI_UINT32       state;                          /* current adap state (from port status) */
-
-       /*
-        * Read host interrupt Type 0 register to determine which Type 0
-        * interrupts are pending.  Immediately write it back out to clear
-        * those interrupts.
-        */
-
-       dfx_port_read_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, &type_0_status);
-       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, type_0_status);
-
-       /* Check for Type 0 error interrupts */
-
-       if (type_0_status & (PI_TYPE_0_STAT_M_NXM |
-                                                       PI_TYPE_0_STAT_M_PM_PAR_ERR |
-                                                       PI_TYPE_0_STAT_M_BUS_PAR_ERR))
-               {
-               /* Check for Non-Existent Memory error */
-
-               if (type_0_status & PI_TYPE_0_STAT_M_NXM)
-                       printk("%s: Non-Existent Memory Access Error\n", bp->dev->name);
-
-               /* Check for Packet Memory Parity error */
-
-               if (type_0_status & PI_TYPE_0_STAT_M_PM_PAR_ERR)
-                       printk("%s: Packet Memory Parity Error\n", bp->dev->name);
-
-               /* Check for Host Bus Parity error */
-
-               if (type_0_status & PI_TYPE_0_STAT_M_BUS_PAR_ERR)
-                       printk("%s: Host Bus Parity Error\n", bp->dev->name);
-
-               /* Reset adapter and bring it back on-line */
-
-               bp->link_available = PI_K_FALSE;        /* link is no longer available */
-               bp->reset_type = 0;                                     /* rerun on-board diagnostics */
-               printk("%s: Resetting adapter...\n", bp->dev->name);
-               if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
-                       {
-                       printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
-                       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-                       return;
-                       }
-               printk("%s: Adapter reset successful!\n", bp->dev->name);
-               return;
-               }
-
-       /* Check for transmit flush interrupt */
-
-       if (type_0_status & PI_TYPE_0_STAT_M_XMT_FLUSH)
-               {
-               /* Flush any pending xmt's and acknowledge the flush interrupt */
-
-               bp->link_available = PI_K_FALSE;                /* link is no longer available */
-               dfx_xmt_flush(bp);                                              /* flush any outstanding packets */
-               (void) dfx_hw_port_ctrl_req(bp,
-                                                                       PI_PCTRL_M_XMT_DATA_FLUSH_DONE,
-                                                                       0,
-                                                                       0,
-                                                                       NULL);
-               }
-
-       /* Check for adapter state change */
-
-       if (type_0_status & PI_TYPE_0_STAT_M_STATE_CHANGE)
-               {
-               /* Get latest adapter state */
-
-               state = dfx_hw_adap_state_rd(bp);       /* get adapter state */
-               if (state == PI_STATE_K_HALTED)
-                       {
-                       /*
-                        * Adapter has transitioned to HALTED state, try to reset
-                        * adapter to bring it back on-line.  If reset fails,
-                        * leave the adapter in the broken state.
-                        */
-
-                       printk("%s: Controller has transitioned to HALTED state!\n", bp->dev->name);
-                       dfx_int_pr_halt_id(bp);                 /* display halt id as string */
-
-                       /* Reset adapter and bring it back on-line */
-
-                       bp->link_available = PI_K_FALSE;        /* link is no longer available */
-                       bp->reset_type = 0;                                     /* rerun on-board diagnostics */
-                       printk("%s: Resetting adapter...\n", bp->dev->name);
-                       if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
-                               {
-                               printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
-                               dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
-                               return;
-                               }
-                       printk("%s: Adapter reset successful!\n", bp->dev->name);
-                       }
-               else if (state == PI_STATE_K_LINK_AVAIL)
-                       {
-                       bp->link_available = PI_K_TRUE;         /* set link available flag */
-                       }
-               }
-       }
-
-
-/*
- * ==================
- * = dfx_int_common =
- * ==================
- *
- * Overview:
- *   Interrupt service routine (ISR)
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   This is the ISR which processes incoming adapter interrupts.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   This routine assumes PDQ interrupts have not been disabled.
- *   When interrupts are disabled at the PDQ, the Port Status register
- *   is automatically cleared.  This routine uses the Port Status
- *   register value to determine whether a Type 0 interrupt occurred,
- *   so it's important that adapter interrupts are not normally
- *   enabled/disabled at the PDQ.
- *
- *   It's vital that this routine is NOT reentered for the
- *   same board and that the OS is not in another section of
- *   code (eg. dfx_xmt_queue_pkt) for the same board on a
- *   different thread.
- *
- * Side Effects:
- *   Pending interrupts are serviced.  Depending on the type of
- *   interrupt, acknowledging and clearing the interrupt at the
- *   PDQ involves writing a register to clear the interrupt bit
- *   or updating completion indices.
- */
-
-static void dfx_int_common(struct net_device *dev)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-       PI_UINT32       port_status;            /* Port Status register */
-
-       /* Process xmt interrupts - frequent case, so always call this routine */
-
-       if(dfx_xmt_done(bp))                            /* free consumed xmt packets */
-               netif_wake_queue(dev);
-
-       /* Process rcv interrupts - frequent case, so always call this routine */
-
-       dfx_rcv_queue_process(bp);              /* service received LLC frames */
-
-       /*
-        * Transmit and receive producer and completion indices are updated on the
-        * adapter by writing to the Type 2 Producer register.  Since the frequent
-        * case is that we'll be processing either LLC transmit or receive buffers,
-        * we'll optimize I/O writes by doing a single register write here.
-        */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
-
-       /* Read PDQ Port Status register to find out which interrupts need processing */
-
-       dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-
-       /* Process Type 0 interrupts (if any) - infrequent, so only call when needed */
-
-       if (port_status & PI_PSTATUS_M_TYPE_0_PENDING)
-               dfx_int_type_0_process(bp);     /* process Type 0 interrupts */
-       }
-
-
-/*
- * =================
- * = dfx_interrupt =
- * =================
- *
- * Overview:
- *   Interrupt processing routine
- *
- * Returns:
- *   Whether a valid interrupt was seen.
- *
- * Arguments:
- *   irq       - interrupt vector
- *   dev_id    - pointer to device information
- *
- * Functional Description:
- *   This routine calls the interrupt processing routine for this adapter.  It
- *   disables and reenables adapter interrupts, as appropriate.  We can support
- *   shared interrupts since the incoming dev_id pointer provides our device
- *   structure context.
- *
- * Return Codes:
- *   IRQ_HANDLED - an IRQ was handled.
- *   IRQ_NONE    - no IRQ was handled.
- *
- * Assumptions:
- *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
- *   on Intel-based systems) is done by the operating system outside this
- *   routine.
- *
- *      System interrupts are enabled through this call.
- *
- * Side Effects:
- *   Interrupts are disabled, then reenabled at the adapter.
- */
-
-static irqreturn_t dfx_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       DFX_board_t *bp = netdev_priv(dev);
-       struct device *bdev = bp->bus_dev;
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-
-       /* Service adapter interrupts */
-
-       if (dfx_bus_pci) {
-               u32 status;
-
-               dfx_port_read_long(bp, PFI_K_REG_STATUS, &status);
-               if (!(status & PFI_STATUS_M_PDQ_INT))
-                       return IRQ_NONE;
-
-               spin_lock(&bp->lock);
-
-               /* Disable PDQ-PFI interrupts at PFI */
-               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
-                                   PFI_MODE_M_DMA_ENB);
-
-               /* Call interrupt service routine for this adapter */
-               dfx_int_common(dev);
-
-               /* Clear PDQ interrupt status bit and reenable interrupts */
-               dfx_port_write_long(bp, PFI_K_REG_STATUS,
-                                   PFI_STATUS_M_PDQ_INT);
-               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
-                                   (PFI_MODE_M_PDQ_INT_ENB |
-                                    PFI_MODE_M_DMA_ENB));
-
-               spin_unlock(&bp->lock);
-       }
-       if (dfx_bus_eisa) {
-               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
-               u8 status;
-
-               status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-               if (!(status & PI_CONFIG_STAT_0_M_PEND))
-                       return IRQ_NONE;
-
-               spin_lock(&bp->lock);
-
-               /* Disable interrupts at the ESIC */
-               status &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
-
-               /* Call interrupt service routine for this adapter */
-               dfx_int_common(dev);
-
-               /* Reenable interrupts at the ESIC */
-               status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
-               status |= PI_CONFIG_STAT_0_M_INT_ENB;
-               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
-
-               spin_unlock(&bp->lock);
-       }
-       if (dfx_bus_tc) {
-               u32 status;
-
-               dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &status);
-               if (!(status & (PI_PSTATUS_M_RCV_DATA_PENDING |
-                               PI_PSTATUS_M_XMT_DATA_PENDING |
-                               PI_PSTATUS_M_SMT_HOST_PENDING |
-                               PI_PSTATUS_M_UNSOL_PENDING |
-                               PI_PSTATUS_M_CMD_RSP_PENDING |
-                               PI_PSTATUS_M_CMD_REQ_PENDING |
-                               PI_PSTATUS_M_TYPE_0_PENDING)))
-                       return IRQ_NONE;
-
-               spin_lock(&bp->lock);
-
-               /* Call interrupt service routine for this adapter */
-               dfx_int_common(dev);
-
-               spin_unlock(&bp->lock);
-       }
-
-       return IRQ_HANDLED;
-}
-
-
-/*
- * =====================
- * = dfx_ctl_get_stats =
- * =====================
- *
- * Overview:
- *   Get statistics for FDDI adapter
- *
- * Returns:
- *   Pointer to FDDI statistics structure
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Gets current MIB objects from adapter, then
- *   returns FDDI statistics structure as defined
- *   in if_fddi.h.
- *
- *   Note: Since the FDDI statistics structure is
- *   still new and the device structure doesn't
- *   have an FDDI-specific get statistics handler,
- *   we'll return the FDDI statistics structure as
- *   a pointer to an Ethernet statistics structure.
- *   That way, at least the first part of the statistics
- *   structure can be decoded properly, and it allows
- *   "smart" applications to perform a second cast to
- *   decode the FDDI-specific statistics.
- *
- *   We'll have to pay attention to this routine as the
- *   device structure becomes more mature and LAN media
- *   independent.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
-       {
-       DFX_board_t *bp = netdev_priv(dev);
-
-       /* Fill the bp->stats structure with driver-maintained counters */
-
-       bp->stats.gen.rx_packets = bp->rcv_total_frames;
-       bp->stats.gen.tx_packets = bp->xmt_total_frames;
-       bp->stats.gen.rx_bytes   = bp->rcv_total_bytes;
-       bp->stats.gen.tx_bytes   = bp->xmt_total_bytes;
-       bp->stats.gen.rx_errors  = bp->rcv_crc_errors +
-                                  bp->rcv_frame_status_errors +
-                                  bp->rcv_length_errors;
-       bp->stats.gen.tx_errors  = bp->xmt_length_errors;
-       bp->stats.gen.rx_dropped = bp->rcv_discards;
-       bp->stats.gen.tx_dropped = bp->xmt_discards;
-       bp->stats.gen.multicast  = bp->rcv_multicast_frames;
-       bp->stats.gen.collisions = 0;           /* always zero (0) for FDDI */
-
-       /* Get FDDI SMT MIB objects */
-
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET;
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               return (struct net_device_stats *)&bp->stats;
-
-       /* Fill the bp->stats structure with the SMT MIB object values */
-
-       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));
-       bp->stats.smt_op_version_id                                     = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
-       bp->stats.smt_hi_version_id                                     = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
-       bp->stats.smt_lo_version_id                                     = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
-       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));
-       bp->stats.smt_mib_version_id                            = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
-       bp->stats.smt_mac_cts                                           = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
-       bp->stats.smt_non_master_cts                            = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
-       bp->stats.smt_master_cts                                        = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
-       bp->stats.smt_available_paths                           = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
-       bp->stats.smt_config_capabilities                       = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
-       bp->stats.smt_config_policy                                     = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
-       bp->stats.smt_connection_policy                         = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
-       bp->stats.smt_t_notify                                          = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
-       bp->stats.smt_stat_rpt_policy                           = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
-       bp->stats.smt_trace_max_expiration                      = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
-       bp->stats.smt_bypass_present                            = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
-       bp->stats.smt_ecm_state                                         = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
-       bp->stats.smt_cf_state                                          = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
-       bp->stats.smt_remote_disconnect_flag            = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
-       bp->stats.smt_station_status                            = bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
-       bp->stats.smt_peer_wrap_flag                            = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
-       bp->stats.smt_time_stamp                                        = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
-       bp->stats.smt_transition_time_stamp                     = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
-       bp->stats.mac_frame_status_functions            = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
-       bp->stats.mac_t_max_capability                          = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
-       bp->stats.mac_tvx_capability                            = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
-       bp->stats.mac_available_paths                           = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
-       bp->stats.mac_current_path                                      = bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
-       memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
-       memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
-       memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
-       memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
-       bp->stats.mac_dup_address_test                          = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
-       bp->stats.mac_requested_paths                           = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
-       bp->stats.mac_downstream_port_type                      = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
-       memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
-       bp->stats.mac_t_req                                                     = bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
-       bp->stats.mac_t_neg                                                     = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
-       bp->stats.mac_t_max                                                     = bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
-       bp->stats.mac_tvx_value                                         = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
-       bp->stats.mac_frame_error_threshold                     = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
-       bp->stats.mac_frame_error_ratio                         = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
-       bp->stats.mac_rmt_state                                         = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
-       bp->stats.mac_da_flag                                           = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
-       bp->stats.mac_una_da_flag                                       = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
-       bp->stats.mac_frame_error_flag                          = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
-       bp->stats.mac_ma_unitdata_available                     = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
-       bp->stats.mac_hardware_present                          = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
-       bp->stats.mac_ma_unitdata_enable                        = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
-       bp->stats.path_tvx_lower_bound                          = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
-       bp->stats.path_t_max_lower_bound                        = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
-       bp->stats.path_max_t_req                                        = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
-       memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
-       bp->stats.port_my_type[0]                                       = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
-       bp->stats.port_my_type[1]                                       = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
-       bp->stats.port_neighbor_type[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
-       bp->stats.port_neighbor_type[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
-       bp->stats.port_connection_policies[0]           = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
-       bp->stats.port_connection_policies[1]           = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
-       bp->stats.port_mac_indicated[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
-       bp->stats.port_mac_indicated[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
-       bp->stats.port_current_path[0]                          = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
-       bp->stats.port_current_path[1]                          = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
-       memcpy(&bp->stats.port_requested_paths[0*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
-       memcpy(&bp->stats.port_requested_paths[1*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
-       bp->stats.port_mac_placement[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
-       bp->stats.port_mac_placement[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
-       bp->stats.port_available_paths[0]                       = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
-       bp->stats.port_available_paths[1]                       = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
-       bp->stats.port_pmd_class[0]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
-       bp->stats.port_pmd_class[1]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
-       bp->stats.port_connection_capabilities[0]       = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
-       bp->stats.port_connection_capabilities[1]       = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
-       bp->stats.port_bs_flag[0]                                       = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
-       bp->stats.port_bs_flag[1]                                       = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
-       bp->stats.port_ler_estimate[0]                          = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
-       bp->stats.port_ler_estimate[1]                          = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
-       bp->stats.port_ler_cutoff[0]                            = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
-       bp->stats.port_ler_cutoff[1]                            = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
-       bp->stats.port_ler_alarm[0]                                     = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
-       bp->stats.port_ler_alarm[1]                                     = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
-       bp->stats.port_connect_state[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
-       bp->stats.port_connect_state[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
-       bp->stats.port_pcm_state[0]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
-       bp->stats.port_pcm_state[1]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
-       bp->stats.port_pc_withhold[0]                           = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
-       bp->stats.port_pc_withhold[1]                           = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
-       bp->stats.port_ler_flag[0]                                      = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
-       bp->stats.port_ler_flag[1]                                      = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
-       bp->stats.port_hardware_present[0]                      = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
-       bp->stats.port_hardware_present[1]                      = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
-
-       /* Get FDDI counters */
-
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_CNTRS_GET;
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               return (struct net_device_stats *)&bp->stats;
-
-       /* Fill the bp->stats structure with the FDDI counter values */
-
-       bp->stats.mac_frame_cts                         = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
-       bp->stats.mac_copied_cts                        = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
-       bp->stats.mac_transmit_cts                      = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
-       bp->stats.mac_error_cts                         = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
-       bp->stats.mac_lost_cts                          = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
-       bp->stats.port_lct_fail_cts[0]          = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
-       bp->stats.port_lct_fail_cts[1]          = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
-       bp->stats.port_lem_reject_cts[0]        = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
-       bp->stats.port_lem_reject_cts[1]        = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
-       bp->stats.port_lem_cts[0]                       = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
-       bp->stats.port_lem_cts[1]                       = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
-
-       return (struct net_device_stats *)&bp->stats;
-       }
-
-
-/*
- * ==============================
- * = dfx_ctl_set_multicast_list =
- * ==============================
- *
- * Overview:
- *   Enable/Disable LLC frame promiscuous mode reception
- *   on the adapter and/or update multicast address table.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This routine follows a fairly simple algorithm for setting the
- *   adapter filters and CAM:
- *
- *             if IFF_PROMISC flag is set
- *                     enable LLC individual/group promiscuous mode
- *             else
- *                     disable LLC individual/group promiscuous mode
- *                     if number of incoming multicast addresses >
- *                                     (CAM max size - number of unicast addresses in CAM)
- *                             enable LLC group promiscuous mode
- *                             set driver-maintained multicast address count to zero
- *                     else
- *                             disable LLC group promiscuous mode
- *                             set driver-maintained multicast address count to incoming count
- *                     update adapter CAM
- *             update adapter filters
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   Multicast addresses are presented in canonical (LSB) format.
- *
- * Side Effects:
- *   On-board adapter CAM and filters are updated.
- */
-
-static void dfx_ctl_set_multicast_list(struct net_device *dev)
-{
-       DFX_board_t *bp = netdev_priv(dev);
-       int                                     i;                      /* used as index in for loop */
-       struct netdev_hw_addr *ha;
-
-       /* Enable LLC frame promiscuous mode, if necessary */
-
-       if (dev->flags & IFF_PROMISC)
-               bp->ind_group_prom = PI_FSTATE_K_PASS;          /* Enable LLC ind/group prom mode */
-
-       /* Else, update multicast address table */
-
-       else
-               {
-               bp->ind_group_prom = PI_FSTATE_K_BLOCK;         /* Disable LLC ind/group prom mode */
-               /*
-                * Check whether incoming multicast address count exceeds table size
-                *
-                * Note: The adapters utilize an on-board 64 entry CAM for
-                *       supporting perfect filtering of multicast packets
-                *               and bridge functions when adding unicast addresses.
-                *               There is no hash function available.  To support
-                *               additional multicast addresses, the all multicast
-                *               filter (LLC group promiscuous mode) must be enabled.
-                *
-                *               The firmware reserves two CAM entries for SMT-related
-                *               multicast addresses, which leaves 62 entries available.
-                *               The following code ensures that we're not being asked
-                *               to add more than 62 addresses to the CAM.  If we are,
-                *               the driver will enable the all multicast filter.
-                *               Should the number of multicast addresses drop below
-                *               the high water mark, the filter will be disabled and
-                *               perfect filtering will be used.
-                */
-
-               if (netdev_mc_count(dev) > (PI_CMD_ADDR_FILTER_K_SIZE - bp->uc_count))
-                       {
-                       bp->group_prom  = PI_FSTATE_K_PASS;             /* Enable LLC group prom mode */
-                       bp->mc_count    = 0;                                    /* Don't add mc addrs to CAM */
-                       }
-               else
-                       {
-                       bp->group_prom  = PI_FSTATE_K_BLOCK;    /* Disable LLC group prom mode */
-                       bp->mc_count    = netdev_mc_count(dev);         /* Add mc addrs to CAM */
-                       }
-
-               /* Copy addresses to multicast address table, then update adapter CAM */
-
-               i = 0;
-               netdev_for_each_mc_addr(ha, dev)
-                       memcpy(&bp->mc_table[i++ * FDDI_K_ALEN],
-                              ha->addr, FDDI_K_ALEN);
-
-               if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
-                       {
-                       DBG_printk("%s: Could not update multicast address table!\n", dev->name);
-                       }
-               else
-                       {
-                       DBG_printk("%s: Multicast address table updated!  Added %d addresses.\n", dev->name, bp->mc_count);
-                       }
-               }
-
-       /* Update adapter filters */
-
-       if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
-               {
-               DBG_printk("%s: Could not update adapter filters!\n", dev->name);
-               }
-       else
-               {
-               DBG_printk("%s: Adapter filters updated!\n", dev->name);
-               }
-       }
-
-
-/*
- * ===========================
- * = dfx_ctl_set_mac_address =
- * ===========================
- *
- * Overview:
- *   Add node address override (unicast address) to adapter
- *   CAM and update dev_addr field in device table.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   dev  - pointer to device information
- *   addr - pointer to sockaddr structure containing unicast address to add
- *
- * Functional Description:
- *   The adapter supports node address overrides by adding one or more
- *   unicast addresses to the adapter CAM.  This is similar to adding
- *   multicast addresses.  In this routine we'll update the driver and
- *   device structures with the new address, then update the adapter CAM
- *   to ensure that the adapter will copy and strip frames destined and
- *   sourced by that address.
- *
- * Return Codes:
- *   Always returns zero.
- *
- * Assumptions:
- *   The address pointed to by addr->sa_data is a valid unicast
- *   address and is presented in canonical (LSB) format.
- *
- * Side Effects:
- *   On-board adapter CAM is updated.  On-board adapter filters
- *   may be updated.
- */
-
-static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
-       {
-       struct sockaddr *p_sockaddr = (struct sockaddr *)addr;
-       DFX_board_t *bp = netdev_priv(dev);
-
-       /* Copy unicast address to driver-maintained structs and update count */
-
-       memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);        /* update device struct */
-       memcpy(&bp->uc_table[0], p_sockaddr->sa_data, FDDI_K_ALEN);     /* update driver struct */
-       bp->uc_count = 1;
-
-       /*
-        * Verify we're not exceeding the CAM size by adding unicast address
-        *
-        * Note: It's possible that before entering this routine we've
-        *       already filled the CAM with 62 multicast addresses.
-        *               Since we need to place the node address override into
-        *               the CAM, we have to check to see that we're not
-        *               exceeding the CAM size.  If we are, we have to enable
-        *               the LLC group (multicast) promiscuous mode filter as
-        *               in dfx_ctl_set_multicast_list.
-        */
-
-       if ((bp->uc_count + bp->mc_count) > PI_CMD_ADDR_FILTER_K_SIZE)
-               {
-               bp->group_prom  = PI_FSTATE_K_PASS;             /* Enable LLC group prom mode */
-               bp->mc_count    = 0;                                    /* Don't add mc addrs to CAM */
-
-               /* Update adapter filters */
-
-               if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
-                       {
-                       DBG_printk("%s: Could not update adapter filters!\n", dev->name);
-                       }
-               else
-                       {
-                       DBG_printk("%s: Adapter filters updated!\n", dev->name);
-                       }
-               }
-
-       /* Update adapter CAM with new unicast address */
-
-       if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
-               {
-               DBG_printk("%s: Could not set new MAC address!\n", dev->name);
-               }
-       else
-               {
-               DBG_printk("%s: Adapter CAM updated with new MAC address\n", dev->name);
-               }
-       return 0;                       /* always return zero */
-       }
-
-
-/*
- * ======================
- * = dfx_ctl_update_cam =
- * ======================
- *
- * Overview:
- *   Procedure to update adapter CAM (Content Addressable Memory)
- *   with desired unicast and multicast address entries.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Updates adapter CAM with current contents of board structure
- *   unicast and multicast address tables.  Since there are only 62
- *   free entries in CAM, this routine ensures that the command
- *   request buffer is not overrun.
- *
- * Return Codes:
- *   DFX_K_SUCCESS - Request succeeded
- *   DFX_K_FAILURE - Request failed
- *
- * Assumptions:
- *   All addresses being added (unicast and multicast) are in canonical
- *   order.
- *
- * Side Effects:
- *   On-board adapter CAM is updated.
- */
-
-static int dfx_ctl_update_cam(DFX_board_t *bp)
-       {
-       int                     i;                              /* used as index */
-       PI_LAN_ADDR     *p_addr;                /* pointer to CAM entry */
-
-       /*
-        * Fill in command request information
-        *
-        * Note: Even though both the unicast and multicast address
-        *       table entries are stored as contiguous 6 byte entries,
-        *               the firmware address filter set command expects each
-        *               entry to be two longwords (8 bytes total).  We must be
-        *               careful to only copy the six bytes of each unicast and
-        *               multicast table entry into each command entry.  This
-        *               is also why we must first clear the entire command
-        *               request buffer.
-        */
-
-       memset(bp->cmd_req_virt, 0, PI_CMD_REQ_K_SIZE_MAX);     /* first clear buffer */
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_ADDR_FILTER_SET;
-       p_addr = &bp->cmd_req_virt->addr_filter_set.entry[0];
-
-       /* Now add unicast addresses to command request buffer, if any */
-
-       for (i=0; i < (int)bp->uc_count; i++)
-               {
-               if (i < PI_CMD_ADDR_FILTER_K_SIZE)
-                       {
-                       memcpy(p_addr, &bp->uc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
-                       p_addr++;                       /* point to next command entry */
-                       }
-               }
-
-       /* Now add multicast addresses to command request buffer, if any */
-
-       for (i=0; i < (int)bp->mc_count; i++)
-               {
-               if ((i + bp->uc_count) < PI_CMD_ADDR_FILTER_K_SIZE)
-                       {
-                       memcpy(p_addr, &bp->mc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
-                       p_addr++;                       /* point to next command entry */
-                       }
-               }
-
-       /* Issue command to update adapter CAM, then return */
-
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               return DFX_K_FAILURE;
-       return DFX_K_SUCCESS;
-       }
-
-
-/*
- * ==========================
- * = dfx_ctl_update_filters =
- * ==========================
- *
- * Overview:
- *   Procedure to update adapter filters with desired
- *   filter settings.
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Enables or disables filter using current filter settings.
- *
- * Return Codes:
- *   DFX_K_SUCCESS - Request succeeded.
- *   DFX_K_FAILURE - Request failed.
- *
- * Assumptions:
- *   We must always pass up packets destined to the broadcast
- *   address (FF-FF-FF-FF-FF-FF), so we'll always keep the
- *   broadcast filter enabled.
- *
- * Side Effects:
- *   On-board adapter filters are updated.
- */
-
-static int dfx_ctl_update_filters(DFX_board_t *bp)
-       {
-       int     i = 0;                                  /* used as index */
-
-       /* Fill in command request information */
-
-       bp->cmd_req_virt->cmd_type = PI_CMD_K_FILTERS_SET;
-
-       /* Initialize Broadcast filter - * ALWAYS ENABLED * */
-
-       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_BROADCAST;
-       bp->cmd_req_virt->filter_set.item[i++].value    = PI_FSTATE_K_PASS;
-
-       /* Initialize LLC Individual/Group Promiscuous filter */
-
-       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_IND_GROUP_PROM;
-       bp->cmd_req_virt->filter_set.item[i++].value    = bp->ind_group_prom;
-
-       /* Initialize LLC Group Promiscuous filter */
-
-       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_GROUP_PROM;
-       bp->cmd_req_virt->filter_set.item[i++].value    = bp->group_prom;
-
-       /* Terminate the item code list */
-
-       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_EOL;
-
-       /* Issue command to update adapter filters, then return */
-
-       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
-               return DFX_K_FAILURE;
-       return DFX_K_SUCCESS;
-       }
-
-
-/*
- * ======================
- * = dfx_hw_dma_cmd_req =
- * ======================
- *
- * Overview:
- *   Sends PDQ DMA command to adapter firmware
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   The command request and response buffers are posted to the adapter in the manner
- *   described in the PDQ Port Specification:
- *
- *             1. Command Response Buffer is posted to adapter.
- *             2. Command Request Buffer is posted to adapter.
- *             3. Command Request consumer index is polled until it indicates that request
- *         buffer has been DMA'd to adapter.
- *             4. Command Response consumer index is polled until it indicates that response
- *         buffer has been DMA'd from adapter.
- *
- *   This ordering ensures that a response buffer is already available for the firmware
- *   to use once it's done processing the request buffer.
- *
- * Return Codes:
- *   DFX_K_SUCCESS       - DMA command succeeded
- *      DFX_K_OUTSTATE   - Adapter is NOT in proper state
- *   DFX_K_HW_TIMEOUT - DMA command timed out
- *
- * Assumptions:
- *   Command request buffer has already been filled with desired DMA command.
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
-       {
-       int status;                     /* adapter status */
-       int timeout_cnt;        /* used in for loops */
-
-       /* Make sure the adapter is in a state that we can issue the DMA command in */
-
-       status = dfx_hw_adap_state_rd(bp);
-       if ((status == PI_STATE_K_RESET)                ||
-               (status == PI_STATE_K_HALTED)           ||
-               (status == PI_STATE_K_DMA_UNAVAIL)      ||
-               (status == PI_STATE_K_UPGRADE))
-               return DFX_K_OUTSTATE;
-
-       /* Put response buffer on the command response queue */
-
-       bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-                       ((PI_CMD_RSP_K_SIZE_MAX / PI_ALIGN_K_CMD_RSP_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
-       bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_1 = bp->cmd_rsp_phys;
-
-       /* Bump (and wrap) the producer index and write out to register */
-
-       bp->cmd_rsp_reg.index.prod += 1;
-       bp->cmd_rsp_reg.index.prod &= PI_CMD_RSP_K_NUM_ENTRIES-1;
-       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
-
-       /* Put request buffer on the command request queue */
-
-       bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_0 = (u32) (PI_XMT_DESCR_M_SOP |
-                       PI_XMT_DESCR_M_EOP | (PI_CMD_REQ_K_SIZE_MAX << PI_XMT_DESCR_V_SEG_LEN));
-       bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_1 = bp->cmd_req_phys;
-
-       /* Bump (and wrap) the producer index and write out to register */
-
-       bp->cmd_req_reg.index.prod += 1;
-       bp->cmd_req_reg.index.prod &= PI_CMD_REQ_K_NUM_ENTRIES-1;
-       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
-
-       /*
-        * Here we wait for the command request consumer index to be equal
-        * to the producer, indicating that the adapter has DMAed the request.
-        */
-
-       for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
-               {
-               if (bp->cmd_req_reg.index.prod == (u8)(bp->cons_block_virt->cmd_req))
-                       break;
-               udelay(100);                    /* wait for 100 microseconds */
-               }
-       if (timeout_cnt == 0)
-               return DFX_K_HW_TIMEOUT;
-
-       /* Bump (and wrap) the completion index and write out to register */
-
-       bp->cmd_req_reg.index.comp += 1;
-       bp->cmd_req_reg.index.comp &= PI_CMD_REQ_K_NUM_ENTRIES-1;
-       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
-
-       /*
-        * Here we wait for the command response consumer index to be equal
-        * to the producer, indicating that the adapter has DMAed the response.
-        */
-
-       for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
-               {
-               if (bp->cmd_rsp_reg.index.prod == (u8)(bp->cons_block_virt->cmd_rsp))
-                       break;
-               udelay(100);                    /* wait for 100 microseconds */
-               }
-       if (timeout_cnt == 0)
-               return DFX_K_HW_TIMEOUT;
-
-       /* Bump (and wrap) the completion index and write out to register */
-
-       bp->cmd_rsp_reg.index.comp += 1;
-       bp->cmd_rsp_reg.index.comp &= PI_CMD_RSP_K_NUM_ENTRIES-1;
-       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
-       return DFX_K_SUCCESS;
-       }
-
-
-/*
- * ========================
- * = dfx_hw_port_ctrl_req =
- * ========================
- *
- * Overview:
- *   Sends PDQ port control command to adapter firmware
- *
- * Returns:
- *   Host data register value in host_data if ptr is not NULL
- *
- * Arguments:
- *   bp                        - pointer to board information
- *      command        - port control command
- *      data_a         - port data A register value
- *      data_b         - port data B register value
- *      host_data      - ptr to host data register value
- *
- * Functional Description:
- *   Send generic port control command to adapter by writing
- *   to various PDQ port registers, then polling for completion.
- *
- * Return Codes:
- *   DFX_K_SUCCESS       - port control command succeeded
- *   DFX_K_HW_TIMEOUT - port control command timed out
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_hw_port_ctrl_req(
-       DFX_board_t     *bp,
-       PI_UINT32       command,
-       PI_UINT32       data_a,
-       PI_UINT32       data_b,
-       PI_UINT32       *host_data
-       )
-
-       {
-       PI_UINT32       port_cmd;               /* Port Control command register value */
-       int                     timeout_cnt;    /* used in for loops */
-
-       /* Set Command Error bit in command longword */
-
-       port_cmd = (PI_UINT32) (command | PI_PCTRL_M_CMD_ERROR);
-
-       /* Issue port command to the adapter */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, data_a);
-       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_B, data_b);
-       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_CTRL, port_cmd);
-
-       /* Now wait for command to complete */
-
-       if (command == PI_PCTRL_M_BLAST_FLASH)
-               timeout_cnt = 600000;   /* set command timeout count to 60 seconds */
-       else
-               timeout_cnt = 20000;    /* set command timeout count to 2 seconds */
-
-       for (; timeout_cnt > 0; timeout_cnt--)
-               {
-               dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_CTRL, &port_cmd);
-               if (!(port_cmd & PI_PCTRL_M_CMD_ERROR))
-                       break;
-               udelay(100);                    /* wait for 100 microseconds */
-               }
-       if (timeout_cnt == 0)
-               return DFX_K_HW_TIMEOUT;
-
-       /*
-        * If the address of host_data is non-zero, assume caller has supplied a
-        * non NULL pointer, and return the contents of the HOST_DATA register in
-        * it.
-        */
-
-       if (host_data != NULL)
-               dfx_port_read_long(bp, PI_PDQ_K_REG_HOST_DATA, host_data);
-       return DFX_K_SUCCESS;
-       }
-
-
-/*
- * =====================
- * = dfx_hw_adap_reset =
- * =====================
- *
- * Overview:
- *   Resets adapter
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp   - pointer to board information
- *   type - type of reset to perform
- *
- * Functional Description:
- *   Issue soft reset to adapter by writing to PDQ Port Reset
- *   register.  Use incoming reset type to tell adapter what
- *   kind of reset operation to perform.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   This routine merely issues a soft reset to the adapter.
- *   It is expected that after this routine returns, the caller
- *   will appropriately poll the Port Status register for the
- *   adapter to enter the proper state.
- *
- * Side Effects:
- *   Internal adapter registers are cleared.
- */
-
-static void dfx_hw_adap_reset(
-       DFX_board_t     *bp,
-       PI_UINT32       type
-       )
-
-       {
-       /* Set Reset type and assert reset */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, type);        /* tell adapter type of reset */
-       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, PI_RESET_M_ASSERT_RESET);
-
-       /* Wait for at least 1 Microsecond according to the spec. We wait 20 just to be safe */
-
-       udelay(20);
-
-       /* Deassert reset */
-
-       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, 0);
-       }
-
-
-/*
- * ========================
- * = dfx_hw_adap_state_rd =
- * ========================
- *
- * Overview:
- *   Returns current adapter state
- *
- * Returns:
- *   Adapter state per PDQ Port Specification
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Reads PDQ Port Status register and returns adapter state.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_hw_adap_state_rd(DFX_board_t *bp)
-       {
-       PI_UINT32 port_status;          /* Port Status register value */
-
-       dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
-       return (port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE;
-       }
-
-
-/*
- * =====================
- * = dfx_hw_dma_uninit =
- * =====================
- *
- * Overview:
- *   Brings adapter to DMA_UNAVAILABLE state
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bp   - pointer to board information
- *   type - type of reset to perform
- *
- * Functional Description:
- *   Bring adapter to DMA_UNAVAILABLE state by performing the following:
- *             1. Set reset type bit in Port Data A Register then reset adapter.
- *             2. Check that adapter is in DMA_UNAVAILABLE state.
- *
- * Return Codes:
- *   DFX_K_SUCCESS       - adapter is in DMA_UNAVAILABLE state
- *   DFX_K_HW_TIMEOUT - adapter did not reset properly
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   Internal adapter registers are cleared.
- */
-
-static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type)
-       {
-       int timeout_cnt;        /* used in for loops */
-
-       /* Set reset type bit and reset adapter */
-
-       dfx_hw_adap_reset(bp, type);
-
-       /* Now wait for adapter to enter DMA_UNAVAILABLE state */
-
-       for (timeout_cnt = 100000; timeout_cnt > 0; timeout_cnt--)
-               {
-               if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_DMA_UNAVAIL)
-                       break;
-               udelay(100);                                    /* wait for 100 microseconds */
-               }
-       if (timeout_cnt == 0)
-               return DFX_K_HW_TIMEOUT;
-       return DFX_K_SUCCESS;
-       }
-
-/*
- *     Align an sk_buff to a boundary power of 2
- *
- */
-
-static void my_skb_align(struct sk_buff *skb, int n)
-{
-       unsigned long x = (unsigned long)skb->data;
-       unsigned long v;
-
-       v = ALIGN(x, n);        /* Where we want to be */
-
-       skb_reserve(skb, v - x);
-}
-
-
-/*
- * ================
- * = dfx_rcv_init =
- * ================
- *
- * Overview:
- *   Produces buffers to adapter LLC Host receive descriptor block
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *   get_buffers - non-zero if buffers to be allocated
- *
- * Functional Description:
- *   This routine can be called during dfx_adap_init() or during an adapter
- *      reset.  It initializes the descriptor block and produces all allocated
- *   LLC Host queue receive buffers.
- *
- * Return Codes:
- *   Return 0 on success or -ENOMEM if buffer allocation failed (when using
- *   dynamic buffer allocation). If the buffer allocation failed, the
- *   already allocated buffers will not be released and the caller should do
- *   this.
- *
- * Assumptions:
- *   The PDQ has been reset and the adapter and driver maintained Type 2
- *   register indices are cleared.
- *
- * Side Effects:
- *   Receive buffers are posted to the adapter LLC queue and the adapter
- *   is notified.
- */
-
-static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
-       {
-       int     i, j;                                   /* used in for loop */
-
-       /*
-        *  Since each receive buffer is a single fragment of same length, initialize
-        *  first longword in each receive descriptor for entire LLC Host descriptor
-        *  block.  Also initialize second longword in each receive descriptor with
-        *  physical address of receive buffer.  We'll always allocate receive
-        *  buffers in powers of 2 so that we can easily fill the 256 entry descriptor
-        *  block and produce new receive buffers by simply updating the receive
-        *  producer index.
-        *
-        *      Assumptions:
-        *              To support all shipping versions of PDQ, the receive buffer size
-        *              must be mod 128 in length and the physical address must be 128 byte
-        *              aligned.  In other words, bits 0-6 of the length and address must
-        *              be zero for the following descriptor field entries to be correct on
-        *              all PDQ-based boards.  We guaranteed both requirements during
-        *              driver initialization when we allocated memory for the receive buffers.
-        */
-
-       if (get_buffers) {
-#ifdef DYNAMIC_BUFFERS
-       for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
-               for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
-               {
-                       struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO);
-                       if (!newskb)
-                               return -ENOMEM;
-                       bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-                               ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
-                       /*
-                        * align to 128 bytes for compatibility with
-                        * the old EISA boards.
-                        */
-
-                       my_skb_align(newskb, 128);
-                       bp->descr_block_virt->rcv_data[i + j].long_1 =
-                               (u32)dma_map_single(bp->bus_dev, newskb->data,
-                                                   NEW_SKB_SIZE,
-                                                   DMA_FROM_DEVICE);
-                       /*
-                        * p_rcv_buff_va is only used inside the
-                        * kernel so we put the skb pointer here.
-                        */
-                       bp->p_rcv_buff_va[i+j] = (char *) newskb;
-               }
-#else
-       for (i=0; i < (int)(bp->rcv_bufs_to_post); i++)
-               for (j=0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
-                       {
-                       bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
-                               ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
-                       bp->descr_block_virt->rcv_data[i+j].long_1 = (u32) (bp->rcv_block_phys + (i * PI_RCV_DATA_K_SIZE_MAX));
-                       bp->p_rcv_buff_va[i+j] = (char *) (bp->rcv_block_virt + (i * PI_RCV_DATA_K_SIZE_MAX));
-                       }
-#endif
-       }
-
-       /* Update receive producer and Type 2 register */
-
-       bp->rcv_xmt_reg.index.rcv_prod = bp->rcv_bufs_to_post;
-       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
-       return 0;
-       }
-
-
-/*
- * =========================
- * = dfx_rcv_queue_process =
- * =========================
- *
- * Overview:
- *   Process received LLC frames.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Received LLC frames are processed until there are no more consumed frames.
- *   Once all frames are processed, the receive buffers are returned to the
- *   adapter.  Note that this algorithm fixes the length of time that can be spent
- *   in this routine, because there are a fixed number of receive buffers to
- *   process and buffers are not produced until this routine exits and returns
- *   to the ISR.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   None
- *
- * Side Effects:
- *   None
- */
-
-static void dfx_rcv_queue_process(
-       DFX_board_t *bp
-       )
-
-       {
-       PI_TYPE_2_CONSUMER      *p_type_2_cons;         /* ptr to rcv/xmt consumer block register */
-       char                            *p_buff;                        /* ptr to start of packet receive buffer (FMC descriptor) */
-       u32                                     descr, pkt_len;         /* FMC descriptor field and packet length */
-       struct sk_buff          *skb;                           /* pointer to a sk_buff to hold incoming packet data */
-
-       /* Service all consumed LLC receive frames */
-
-       p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
-       while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons)
-               {
-               /* Process any errors */
-
-               int entry;
-
-               entry = bp->rcv_xmt_reg.index.rcv_comp;
-#ifdef DYNAMIC_BUFFERS
-               p_buff = (char *) (((struct sk_buff *)bp->p_rcv_buff_va[entry])->data);
-#else
-               p_buff = (char *) bp->p_rcv_buff_va[entry];
-#endif
-               memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));
-
-               if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
-                       {
-                       if (descr & PI_FMC_DESCR_M_RCC_CRC)
-                               bp->rcv_crc_errors++;
-                       else
-                               bp->rcv_frame_status_errors++;
-                       }
-               else
-               {
-                       int rx_in_place = 0;
-
-                       /* The frame was received without errors - verify packet length */
-
-                       pkt_len = (u32)((descr & PI_FMC_DESCR_M_LEN) >> PI_FMC_DESCR_V_LEN);
-                       pkt_len -= 4;                           /* subtract 4 byte CRC */
-                       if (!IN_RANGE(pkt_len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
-                               bp->rcv_length_errors++;
-                       else{
-#ifdef DYNAMIC_BUFFERS
-                               if (pkt_len > SKBUFF_RX_COPYBREAK) {
-                                       struct sk_buff *newskb;
-
-                                       newskb = dev_alloc_skb(NEW_SKB_SIZE);
-                                       if (newskb){
-                                               rx_in_place = 1;
-
-                                               my_skb_align(newskb, 128);
-                                               skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
-                                               dma_unmap_single(bp->bus_dev,
-                                                       bp->descr_block_virt->rcv_data[entry].long_1,
-                                                       NEW_SKB_SIZE,
-                                                       DMA_FROM_DEVICE);
-                                               skb_reserve(skb, RCV_BUFF_K_PADDING);
-                                               bp->p_rcv_buff_va[entry] = (char *)newskb;
-                                               bp->descr_block_virt->rcv_data[entry].long_1 =
-                                                       (u32)dma_map_single(bp->bus_dev,
-                                                               newskb->data,
-                                                               NEW_SKB_SIZE,
-                                                               DMA_FROM_DEVICE);
-                                       } else
-                                               skb = NULL;
-                               } else
-#endif
-                                       skb = dev_alloc_skb(pkt_len+3); /* alloc new buffer to pass up, add room for PRH */
-                               if (skb == NULL)
-                                       {
-                                       printk("%s: Could not allocate receive buffer.  Dropping packet.\n", bp->dev->name);
-                                       bp->rcv_discards++;
-                                       break;
-                                       }
-                               else {
-#ifndef DYNAMIC_BUFFERS
-                                       if (! rx_in_place)
-#endif
-                                       {
-                                               /* Receive buffer allocated, pass receive packet up */
-
-                                               skb_copy_to_linear_data(skb,
-                                                              p_buff + RCV_BUFF_K_PADDING,
-                                                              pkt_len + 3);
-                                       }
-
-                                       skb_reserve(skb,3);             /* adjust data field so that it points to FC byte */
-                                       skb_put(skb, pkt_len);          /* pass up packet length, NOT including CRC */
-                                       skb->protocol = fddi_type_trans(skb, bp->dev);
-                                       bp->rcv_total_bytes += skb->len;
-                                       netif_rx(skb);
-
-                                       /* Update the rcv counters */
-                                       bp->rcv_total_frames++;
-                                       if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
-                                               bp->rcv_multicast_frames++;
-                               }
-                       }
-                       }
-
-               /*
-                * Advance the producer (for recycling) and advance the completion
-                * (for servicing received frames).  Note that it is okay to
-                * advance the producer without checking that it passes the
-                * completion index because they are both advanced at the same
-                * rate.
-                */
-
-               bp->rcv_xmt_reg.index.rcv_prod += 1;
-               bp->rcv_xmt_reg.index.rcv_comp += 1;
-               }
-       }
-
-
-/*
- * =====================
- * = dfx_xmt_queue_pkt =
- * =====================
- *
- * Overview:
- *   Queues packets for transmission
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   skb - pointer to sk_buff to queue for transmission
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Here we assume that an incoming skb transmit request
- *   is contained in a single physically contiguous buffer
- *   in which the virtual address of the start of packet
- *   (skb->data) can be converted to a physical address
- *   by using pci_map_single().
- *
- *   Since the adapter architecture requires a three byte
- *   packet request header to prepend the start of packet,
- *   we'll write the three byte field immediately prior to
- *   the FC byte.  This assumption is valid because we've
- *   ensured that dev->hard_header_len includes three pad
- *   bytes.  By posting a single fragment to the adapter,
- *   we'll reduce the number of descriptor fetches and
- *   bus traffic needed to send the request.
- *
- *   Also, we can't free the skb until after it's been DMA'd
- *   out by the adapter, so we'll queue it in the driver and
- *   return it in dfx_xmt_done.
- *
- * Return Codes:
- *   0 - driver queued packet, link is unavailable, or skbuff was bad
- *      1 - caller should requeue the sk_buff for later transmission
- *
- * Assumptions:
- *      First and foremost, we assume the incoming skb pointer
- *   is NOT NULL and is pointing to a valid sk_buff structure.
- *
- *   The outgoing packet is complete, starting with the
- *   frame control byte including the last byte of data,
- *   but NOT including the 4 byte CRC.  We'll let the
- *   adapter hardware generate and append the CRC.
- *
- *   The entire packet is stored in one physically
- *   contiguous buffer which is not cached and whose
- *   32-bit physical address can be determined.
- *
- *   It's vital that this routine is NOT reentered for the
- *   same board and that the OS is not in another section of
- *   code (eg. dfx_int_common) for the same board on a
- *   different thread.
- *
- * Side Effects:
- *   None
- */
-
-static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
-                                    struct net_device *dev)
-       {
-       DFX_board_t             *bp = netdev_priv(dev);
-       u8                      prod;                           /* local transmit producer index */
-       PI_XMT_DESCR            *p_xmt_descr;           /* ptr to transmit descriptor block entry */
-       XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
-       unsigned long           flags;
-
-       netif_stop_queue(dev);
-
-       /*
-        * Verify that incoming transmit request is OK
-        *
-        * Note: The packet size check is consistent with other
-        *               Linux device drivers, although the correct packet
-        *               size should be verified before calling the
-        *               transmit routine.
-        */
-
-       if (!IN_RANGE(skb->len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
-       {
-               printk("%s: Invalid packet length - %u bytes\n",
-                       dev->name, skb->len);
-               bp->xmt_length_errors++;                /* bump error counter */
-               netif_wake_queue(dev);
-               dev_kfree_skb(skb);
-               return NETDEV_TX_OK;                    /* return "success" */
-       }
-       /*
-        * See if adapter link is available, if not, free buffer
-        *
-        * Note: If the link isn't available, free buffer and return 0
-        *               rather than tell the upper layer to requeue the packet.
-        *               The methodology here is that by the time the link
-        *               becomes available, the packet to be sent will be
-        *               fairly stale.  By simply dropping the packet, the
-        *               higher layer protocols will eventually time out
-        *               waiting for response packets which it won't receive.
-        */
-
-       if (bp->link_available == PI_K_FALSE)
-               {
-               if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_LINK_AVAIL)  /* is link really available? */
-                       bp->link_available = PI_K_TRUE;         /* if so, set flag and continue */
-               else
-                       {
-                       bp->xmt_discards++;                                     /* bump error counter */
-                       dev_kfree_skb(skb);             /* free sk_buff now */
-                       netif_wake_queue(dev);
-                       return NETDEV_TX_OK;            /* return "success" */
-                       }
-               }
-
-       spin_lock_irqsave(&bp->lock, flags);
-
-       /* Get the current producer and the next free xmt data descriptor */
-
-       prod            = bp->rcv_xmt_reg.index.xmt_prod;
-       p_xmt_descr = &(bp->descr_block_virt->xmt_data[prod]);
-
-       /*
-        * Get pointer to auxiliary queue entry to contain information
-        * for this packet.
-        *
-        * Note: The current xmt producer index will become the
-        *       current xmt completion index when we complete this
-        *       packet later on.  So, we'll get the pointer to the
-        *       next auxiliary queue entry now before we bump the
-        *       producer index.
-        */
-
-       p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]);     /* also bump producer index */
-
-       /* Write the three PRH bytes immediately before the FC byte */
-
-       skb_push(skb,3);
-       skb->data[0] = DFX_PRH0_BYTE;   /* these byte values are defined */
-       skb->data[1] = DFX_PRH1_BYTE;   /* in the Motorola FDDI MAC chip */
-       skb->data[2] = DFX_PRH2_BYTE;   /* specification */
-
-       /*
-        * Write the descriptor with buffer info and bump producer
-        *
-        * Note: Since we need to start DMA from the packet request
-        *               header, we'll add 3 bytes to the DMA buffer length,
-        *               and we'll determine the physical address of the
-        *               buffer from the PRH, not skb->data.
-        *
-        * Assumptions:
-        *               1. Packet starts with the frame control (FC) byte
-        *                  at skb->data.
-        *               2. The 4-byte CRC is not appended to the buffer or
-        *                      included in the length.
-        *               3. Packet length (skb->len) is from FC to end of
-        *                      data, inclusive.
-        *               4. The packet length does not exceed the maximum
-        *                      FDDI LLC frame length of 4491 bytes.
-        *               5. The entire packet is contained in a physically
-        *                      contiguous, non-cached, locked memory space
-        *                      comprised of a single buffer pointed to by
-        *                      skb->data.
-        *               6. The physical address of the start of packet
-        *                      can be determined from the virtual address
-        *                      by using pci_map_single() and is only 32-bits
-        *                      wide.
-        */
-
-       p_xmt_descr->long_0     = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
-       p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
-                                                 skb->len, DMA_TO_DEVICE);
-
-       /*
-        * Verify that descriptor is actually available
-        *
-        * Note: If descriptor isn't available, return 1 which tells
-        *       the upper layer to requeue the packet for later
-        *       transmission.
-        *
-        *       We need to ensure that the producer never reaches the
-        *       completion, except to indicate that the queue is empty.
-        */
-
-       if (prod == bp->rcv_xmt_reg.index.xmt_comp)
-       {
-               skb_pull(skb,3);
-               spin_unlock_irqrestore(&bp->lock, flags);
-               return NETDEV_TX_BUSY;  /* requeue packet for later */
-       }
-
-       /*
-        * Save info for this packet for xmt done indication routine
-        *
-        * Normally, we'd save the producer index in the p_xmt_drv_descr
-        * structure so that we'd have it handy when we complete this
-        * packet later (in dfx_xmt_done).  However, since the current
-        * transmit architecture guarantees a single fragment for the
-        * entire packet, we can simply bump the completion index by
-        * one (1) for each completed packet.
-        *
-        * Note: If this assumption changes and we're presented with
-        *       an inconsistent number of transmit fragments for packet
-        *       data, we'll need to modify this code to save the current
-        *       transmit producer index.
-        */
-
-       p_xmt_drv_descr->p_skb = skb;
-
-       /* Update Type 2 register */
-
-       bp->rcv_xmt_reg.index.xmt_prod = prod;
-       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
-       spin_unlock_irqrestore(&bp->lock, flags);
-       netif_wake_queue(dev);
-       return NETDEV_TX_OK;    /* packet queued to adapter */
-       }
-
-
-/*
- * ================
- * = dfx_xmt_done =
- * ================
- *
- * Overview:
- *   Processes all frames that have been transmitted.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   For all consumed transmit descriptors that have not
- *   yet been completed, we'll free the skb we were holding
- *   onto using dev_kfree_skb and bump the appropriate
- *   counters.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   The Type 2 register is not updated in this routine.  It is
- *   assumed that it will be updated in the ISR when dfx_xmt_done
- *   returns.
- *
- * Side Effects:
- *   None
- */
-
-static int dfx_xmt_done(DFX_board_t *bp)
-       {
-       XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
-       PI_TYPE_2_CONSUMER      *p_type_2_cons;         /* ptr to rcv/xmt consumer block register */
-       u8                      comp;                   /* local transmit completion index */
-       int                     freed = 0;              /* buffers freed */
-
-       /* Service all consumed transmit frames */
-
-       p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
-       while (bp->rcv_xmt_reg.index.xmt_comp != p_type_2_cons->index.xmt_cons)
-               {
-               /* Get pointer to the transmit driver descriptor block information */
-
-               p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
-
-               /* Increment transmit counters */
-
-               bp->xmt_total_frames++;
-               bp->xmt_total_bytes += p_xmt_drv_descr->p_skb->len;
-
-               /* Return skb to operating system */
-               comp = bp->rcv_xmt_reg.index.xmt_comp;
-               dma_unmap_single(bp->bus_dev,
-                                bp->descr_block_virt->xmt_data[comp].long_1,
-                                p_xmt_drv_descr->p_skb->len,
-                                DMA_TO_DEVICE);
-               dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
-
-               /*
-                * Move to start of next packet by updating completion index
-                *
-                * Here we assume that a transmit packet request is always
-                * serviced by posting one fragment.  We can therefore
-                * simplify the completion code by incrementing the
-                * completion index by one.  This code will need to be
-                * modified if this assumption changes.  See comments
-                * in dfx_xmt_queue_pkt for more details.
-                */
-
-               bp->rcv_xmt_reg.index.xmt_comp += 1;
-               freed++;
-               }
-       return freed;
-       }
-
-
-/*
- * =================
- * = dfx_rcv_flush =
- * =================
- *
- * Overview:
- *   Remove all skb's in the receive ring.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   Free's all the dynamically allocated skb's that are
- *   currently attached to the device receive ring. This
- *   function is typically only used when the device is
- *   initialized or reinitialized.
- *
- * Return Codes:
- *   None
- *
- * Side Effects:
- *   None
- */
-#ifdef DYNAMIC_BUFFERS
-static void dfx_rcv_flush( DFX_board_t *bp )
-       {
-       int i, j;
-
-       for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
-               for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
-               {
-                       struct sk_buff *skb;
-                       skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j];
-                       if (skb)
-                               dev_kfree_skb(skb);
-                       bp->p_rcv_buff_va[i+j] = NULL;
-               }
-
-       }
-#else
-static inline void dfx_rcv_flush( DFX_board_t *bp )
-{
-}
-#endif /* DYNAMIC_BUFFERS */
-
-/*
- * =================
- * = dfx_xmt_flush =
- * =================
- *
- * Overview:
- *   Processes all frames whether they've been transmitted
- *   or not.
- *
- * Returns:
- *   None
- *
- * Arguments:
- *   bp - pointer to board information
- *
- * Functional Description:
- *   For all produced transmit descriptors that have not
- *   yet been completed, we'll free the skb we were holding
- *   onto using dev_kfree_skb and bump the appropriate
- *   counters.  Of course, it's possible that some of
- *   these transmit requests actually did go out, but we
- *   won't make that distinction here.  Finally, we'll
- *   update the consumer index to match the producer.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   This routine does NOT update the Type 2 register.  It
- *   is assumed that this routine is being called during a
- *   transmit flush interrupt, or a shutdown or close routine.
- *
- * Side Effects:
- *   None
- */
-
-static void dfx_xmt_flush( DFX_board_t *bp )
-       {
-       u32                     prod_cons;              /* rcv/xmt consumer block longword */
-       XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
-       u8                      comp;                   /* local transmit completion index */
-
-       /* Flush all outstanding transmit frames */
-
-       while (bp->rcv_xmt_reg.index.xmt_comp != bp->rcv_xmt_reg.index.xmt_prod)
-               {
-               /* Get pointer to the transmit driver descriptor block information */
-
-               p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
-
-               /* Return skb to operating system */
-               comp = bp->rcv_xmt_reg.index.xmt_comp;
-               dma_unmap_single(bp->bus_dev,
-                                bp->descr_block_virt->xmt_data[comp].long_1,
-                                p_xmt_drv_descr->p_skb->len,
-                                DMA_TO_DEVICE);
-               dev_kfree_skb(p_xmt_drv_descr->p_skb);
-
-               /* Increment transmit error counter */
-
-               bp->xmt_discards++;
-
-               /*
-                * Move to start of next packet by updating completion index
-                *
-                * Here we assume that a transmit packet request is always
-                * serviced by posting one fragment.  We can therefore
-                * simplify the completion code by incrementing the
-                * completion index by one.  This code will need to be
-                * modified if this assumption changes.  See comments
-                * in dfx_xmt_queue_pkt for more details.
-                */
-
-               bp->rcv_xmt_reg.index.xmt_comp += 1;
-               }
-
-       /* Update the transmit consumer index in the consumer block */
-
-       prod_cons = (u32)(bp->cons_block_virt->xmt_rcv_data & ~PI_CONS_M_XMT_INDEX);
-       prod_cons |= (u32)(bp->rcv_xmt_reg.index.xmt_prod << PI_CONS_V_XMT_INDEX);
-       bp->cons_block_virt->xmt_rcv_data = prod_cons;
-       }
-
-/*
- * ==================
- * = dfx_unregister =
- * ==================
- *
- * Overview:
- *   Shuts down an FDDI controller
- *
- * Returns:
- *   Condition code
- *
- * Arguments:
- *   bdev - pointer to device information
- *
- * Functional Description:
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   It compiles so it should work :-( (PCI cards do :-)
- *
- * Side Effects:
- *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
- *   freed.
- */
-static void __devexit dfx_unregister(struct device *bdev)
-{
-       struct net_device *dev = dev_get_drvdata(bdev);
-       DFX_board_t *bp = netdev_priv(dev);
-       int dfx_bus_pci = DFX_BUS_PCI(bdev);
-       int dfx_bus_tc = DFX_BUS_TC(bdev);
-       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
-       resource_size_t bar_start = 0;          /* pointer to port */
-       resource_size_t bar_len = 0;            /* resource length */
-       int             alloc_size;             /* total buffer size used */
-
-       unregister_netdev(dev);
-
-       alloc_size = sizeof(PI_DESCR_BLOCK) +
-                    PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
-#ifndef DYNAMIC_BUFFERS
-                    (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
-#endif
-                    sizeof(PI_CONSUMER_BLOCK) +
-                    (PI_ALIGN_K_DESC_BLK - 1);
-       if (bp->kmalloced)
-               dma_free_coherent(bdev, alloc_size,
-                                 bp->kmalloced, bp->kmalloced_dma);
-
-       dfx_bus_uninit(dev);
-
-       dfx_get_bars(bdev, &bar_start, &bar_len);
-       if (dfx_use_mmio) {
-               iounmap(bp->base.mem);
-               release_mem_region(bar_start, bar_len);
-       } else
-               release_region(bar_start, bar_len);
-
-       if (dfx_bus_pci)
-               pci_disable_device(to_pci_dev(bdev));
-
-       free_netdev(dev);
-}
-
-
-static int __devinit __maybe_unused dfx_dev_register(struct device *);
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
-
-#ifdef CONFIG_PCI
-static int __devinit dfx_pci_register(struct pci_dev *,
-                                     const struct pci_device_id *);
-static void __devexit dfx_pci_unregister(struct pci_dev *);
-
-static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
-       { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
-       { }
-};
-MODULE_DEVICE_TABLE(pci, dfx_pci_table);
-
-static struct pci_driver dfx_pci_driver = {
-       .name           = "defxx",
-       .id_table       = dfx_pci_table,
-       .probe          = dfx_pci_register,
-       .remove         = __devexit_p(dfx_pci_unregister),
-};
-
-static __devinit int dfx_pci_register(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
-{
-       return dfx_register(&pdev->dev);
-}
-
-static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
-{
-       dfx_unregister(&pdev->dev);
-}
-#endif /* CONFIG_PCI */
-
-#ifdef CONFIG_EISA
-static struct eisa_device_id dfx_eisa_table[] = {
-        { "DEC3001", DEFEA_PROD_ID_1 },
-        { "DEC3002", DEFEA_PROD_ID_2 },
-        { "DEC3003", DEFEA_PROD_ID_3 },
-        { "DEC3004", DEFEA_PROD_ID_4 },
-        { }
-};
-MODULE_DEVICE_TABLE(eisa, dfx_eisa_table);
-
-static struct eisa_driver dfx_eisa_driver = {
-       .id_table       = dfx_eisa_table,
-       .driver         = {
-               .name   = "defxx",
-               .bus    = &eisa_bus_type,
-               .probe  = dfx_dev_register,
-               .remove = __devexit_p(dfx_dev_unregister),
-       },
-};
-#endif /* CONFIG_EISA */
-
-#ifdef CONFIG_TC
-static struct tc_device_id const dfx_tc_table[] = {
-       { "DEC     ", "PMAF-FA " },
-       { "DEC     ", "PMAF-FD " },
-       { "DEC     ", "PMAF-FS " },
-       { "DEC     ", "PMAF-FU " },
-       { }
-};
-MODULE_DEVICE_TABLE(tc, dfx_tc_table);
-
-static struct tc_driver dfx_tc_driver = {
-       .id_table       = dfx_tc_table,
-       .driver         = {
-               .name   = "defxx",
-               .bus    = &tc_bus_type,
-               .probe  = dfx_dev_register,
-               .remove = __devexit_p(dfx_dev_unregister),
-       },
-};
-#endif /* CONFIG_TC */
-
-static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
-{
-       int status;
-
-       status = dfx_register(dev);
-       if (!status)
-               get_device(dev);
-       return status;
-}
-
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
-{
-       put_device(dev);
-       dfx_unregister(dev);
-       return 0;
-}
-
-
-static int __devinit dfx_init(void)
-{
-       int status;
-
-       status = pci_register_driver(&dfx_pci_driver);
-       if (!status)
-               status = eisa_driver_register(&dfx_eisa_driver);
-       if (!status)
-               status = tc_register_driver(&dfx_tc_driver);
-       return status;
-}
-
-static void __devexit dfx_cleanup(void)
-{
-       tc_unregister_driver(&dfx_tc_driver);
-       eisa_driver_unregister(&dfx_eisa_driver);
-       pci_unregister_driver(&dfx_pci_driver);
-}
-
-module_init(dfx_init);
-module_exit(dfx_cleanup);
-MODULE_AUTHOR("Lawrence V. Stefani");
-MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver "
-                  DRV_VERSION " " DRV_RELDATE);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h
deleted file mode 100644 (file)
index 19a6f64..0000000
+++ /dev/null
@@ -1,1801 +0,0 @@
-/*
- * File Name:
- *   defxx.h
- *
- * Copyright Information:
- *   Copyright Digital Equipment Corporation 1996.
- *
- *   This software may be used and distributed according to the terms of
- *   the GNU General Public License, incorporated herein by reference.
- *
- * Abstract:
- *   Contains all definitions specified by port specification and required
- *   by the defxx.c driver.
- *
- * The original author:
- *   LVS       Lawrence V. Stefani <lstefani@yahoo.com>
- *
- * Maintainers:
- *   macro     Maciej W. Rozycki <macro@linux-mips.org>
- *
- * Modification History:
- *             Date            Name    Description
- *             16-Aug-96       LVS             Created.
- *             09-Sep-96       LVS             Added group_prom field.  Moved read/write I/O
- *                                                     macros to DEFXX.C.
- *             12-Sep-96       LVS             Removed packet request header pointers.
- *             04 Aug 2003     macro           Converted to the DMA API.
- *             23 Oct 2006     macro           Big-endian host support.
- *             14 Dec 2006     macro           TURBOchannel support.
- */
-
-#ifndef _DEFXX_H_
-#define _DEFXX_H_
-
-/* Define basic types for unsigned chars, shorts, longs */
-
-typedef u8     PI_UINT8;
-typedef u16    PI_UINT16;
-typedef u32    PI_UINT32;
-
-/* Define general structures */
-
-typedef struct                                                 /* 64-bit counter */
-       {
-       PI_UINT32  ms;
-       PI_UINT32  ls;
-       } PI_CNTR;
-
-typedef struct                                                 /* LAN address */
-       {
-       PI_UINT32  lwrd_0;
-       PI_UINT32  lwrd_1;
-       } PI_LAN_ADDR;
-
-typedef struct                                                 /* Station ID address */
-       {
-       PI_UINT32  octet_7_4;
-       PI_UINT32  octet_3_0;
-       } PI_STATION_ID;
-
-
-/* Define general constants */
-
-#define PI_ALIGN_K_DESC_BLK                            8192    /* Descriptor block boundary            */
-#define PI_ALIGN_K_CONS_BLK                            64              /* Consumer block boundary                      */
-#define PI_ALIGN_K_CMD_REQ_BUFF                128             /* Xmt Command que buffer alignment */
-#define PI_ALIGN_K_CMD_RSP_BUFF                        128             /* Rcv Command que buffer alignment */
-#define PI_ALIGN_K_UNSOL_BUFF                  128             /* Unsol que buffer alignment           */
-#define PI_ALIGN_K_XMT_DATA_BUFF               0               /* Xmt data que buffer alignment        */
-#define PI_ALIGN_K_RCV_DATA_BUFF               128             /* Rcv que buffer alignment                     */
-
-/* Define PHY index values */
-
-#define PI_PHY_K_S                                             0               /* Index to S phy */
-#define PI_PHY_K_A                                             0               /* Index to A phy */
-#define PI_PHY_K_B                                             1               /* Index to B phy */
-#define PI_PHY_K_MAX                                   2               /* Max number of phys */
-
-/* Define FMC descriptor fields */
-
-#define PI_FMC_DESCR_V_SOP                             31
-#define PI_FMC_DESCR_V_EOP                             30
-#define PI_FMC_DESCR_V_FSC                             27
-#define PI_FMC_DESCR_V_FSB_ERROR               26
-#define PI_FMC_DESCR_V_FSB_ADDR_RECOG  25
-#define PI_FMC_DESCR_V_FSB_ADDR_COPIED 24
-#define PI_FMC_DESCR_V_FSB                             22
-#define PI_FMC_DESCR_V_RCC_FLUSH               21
-#define PI_FMC_DESCR_V_RCC_CRC                 20
-#define PI_FMC_DESCR_V_RCC_RRR                 17
-#define PI_FMC_DESCR_V_RCC_DD                  15
-#define PI_FMC_DESCR_V_RCC_SS                  13
-#define PI_FMC_DESCR_V_RCC                             13
-#define PI_FMC_DESCR_V_LEN                             0
-
-#define PI_FMC_DESCR_M_SOP                             0x80000000
-#define PI_FMC_DESCR_M_EOP                             0x40000000
-#define PI_FMC_DESCR_M_FSC                             0x38000000
-#define PI_FMC_DESCR_M_FSB_ERROR               0x04000000
-#define PI_FMC_DESCR_M_FSB_ADDR_RECOG  0x02000000
-#define PI_FMC_DESCR_M_FSB_ADDR_COPIED 0x01000000
-#define PI_FMC_DESCR_M_FSB                             0x07C00000
-#define PI_FMC_DESCR_M_RCC_FLUSH               0x00200000
-#define PI_FMC_DESCR_M_RCC_CRC                 0x00100000
-#define PI_FMC_DESCR_M_RCC_RRR                 0x000E0000
-#define PI_FMC_DESCR_M_RCC_DD                  0x00018000
-#define PI_FMC_DESCR_M_RCC_SS                  0x00006000
-#define PI_FMC_DESCR_M_RCC                             0x003FE000
-#define PI_FMC_DESCR_M_LEN                             0x00001FFF
-
-#define PI_FMC_DESCR_K_RCC_FMC_INT_ERR 0x01AA
-
-#define PI_FMC_DESCR_K_RRR_SUCCESS             0x00
-#define PI_FMC_DESCR_K_RRR_SA_MATCH            0x01
-#define PI_FMC_DESCR_K_RRR_DA_MATCH            0x02
-#define PI_FMC_DESCR_K_RRR_FMC_ABORT   0x03
-#define PI_FMC_DESCR_K_RRR_LENGTH_BAD  0x04
-#define PI_FMC_DESCR_K_RRR_FRAGMENT            0x05
-#define PI_FMC_DESCR_K_RRR_FORMAT_ERR  0x06
-#define PI_FMC_DESCR_K_RRR_MAC_RESET   0x07
-
-#define PI_FMC_DESCR_K_DD_NO_MATCH             0x0
-#define PI_FMC_DESCR_K_DD_PROMISCUOUS  0x1
-#define PI_FMC_DESCR_K_DD_CAM_MATCH            0x2
-#define PI_FMC_DESCR_K_DD_LOCAL_MATCH  0x3
-
-#define PI_FMC_DESCR_K_SS_NO_MATCH             0x0
-#define PI_FMC_DESCR_K_SS_BRIDGE_MATCH 0x1
-#define PI_FMC_DESCR_K_SS_NOT_POSSIBLE 0x2
-#define PI_FMC_DESCR_K_SS_LOCAL_MATCH  0x3
-
-/* Define some max buffer sizes */
-
-#define PI_CMD_REQ_K_SIZE_MAX                  512
-#define PI_CMD_RSP_K_SIZE_MAX                  512
-#define PI_UNSOL_K_SIZE_MAX                            512
-#define PI_SMT_HOST_K_SIZE_MAX                 4608            /* 4 1/2 K */
-#define PI_RCV_DATA_K_SIZE_MAX                 4608            /* 4 1/2 K */
-#define PI_XMT_DATA_K_SIZE_MAX                 4608            /* 4 1/2 K */
-
-/* Define adapter states */
-
-#define PI_STATE_K_RESET                               0
-#define PI_STATE_K_UPGRADE                             1
-#define PI_STATE_K_DMA_UNAVAIL                 2
-#define PI_STATE_K_DMA_AVAIL                   3
-#define PI_STATE_K_LINK_AVAIL                  4
-#define PI_STATE_K_LINK_UNAVAIL                        5
-#define PI_STATE_K_HALTED                              6
-#define PI_STATE_K_RING_MEMBER                 7
-#define PI_STATE_K_NUMBER                              8
-
-/* Define codes for command type */
-
-#define PI_CMD_K_START                                 0x00
-#define PI_CMD_K_FILTERS_SET                   0x01
-#define PI_CMD_K_FILTERS_GET                   0x02
-#define PI_CMD_K_CHARS_SET                             0x03
-#define PI_CMD_K_STATUS_CHARS_GET              0x04
-#define PI_CMD_K_CNTRS_GET                             0x05
-#define PI_CMD_K_CNTRS_SET                             0x06
-#define PI_CMD_K_ADDR_FILTER_SET               0x07
-#define PI_CMD_K_ADDR_FILTER_GET               0x08
-#define PI_CMD_K_ERROR_LOG_CLEAR               0x09
-#define PI_CMD_K_ERROR_LOG_GET                 0x0A
-#define PI_CMD_K_FDDI_MIB_GET                  0x0B
-#define PI_CMD_K_DEC_EXT_MIB_GET               0x0C
-#define PI_CMD_K_DEVICE_SPECIFIC_GET   0x0D
-#define PI_CMD_K_SNMP_SET                              0x0E
-#define PI_CMD_K_UNSOL_TEST                            0x0F
-#define PI_CMD_K_SMT_MIB_GET                   0x10
-#define PI_CMD_K_SMT_MIB_SET                   0x11
-#define PI_CMD_K_MAX                                   0x11    /* Must match last */
-
-/* Define item codes for Chars_Set and Filters_Set commands */
-
-#define PI_ITEM_K_EOL                                  0x00    /* End-of-Item list               */
-#define PI_ITEM_K_T_REQ                                        0x01    /* DECnet T_REQ                           */
-#define PI_ITEM_K_TVX                                  0x02    /* DECnet TVX                             */
-#define PI_ITEM_K_RESTRICTED_TOKEN             0x03    /* DECnet Restricted Token        */
-#define PI_ITEM_K_LEM_THRESHOLD                        0x04    /* DECnet LEM Threshold           */
-#define PI_ITEM_K_RING_PURGER                  0x05    /* DECnet Ring Purger Enable  */
-#define PI_ITEM_K_CNTR_INTERVAL                        0x06    /* Chars_Set                              */
-#define PI_ITEM_K_IND_GROUP_PROM               0x07    /* Filters_Set                            */
-#define PI_ITEM_K_GROUP_PROM                   0x08    /* Filters_Set                            */
-#define PI_ITEM_K_BROADCAST                            0x09    /* Filters_Set                            */
-#define PI_ITEM_K_SMT_PROM                             0x0A    /* Filters_Set                            */
-#define PI_ITEM_K_SMT_USER                             0x0B    /* Filters_Set                            */
-#define PI_ITEM_K_RESERVED                             0x0C    /* Filters_Set                            */
-#define PI_ITEM_K_IMPLEMENTOR                  0x0D    /* Filters_Set                            */
-#define PI_ITEM_K_LOOPBACK_MODE                        0x0E    /* Chars_Set                              */
-#define PI_ITEM_K_CONFIG_POLICY                        0x10    /* SMTConfigPolicy                        */
-#define PI_ITEM_K_CON_POLICY                   0x11    /* SMTConnectionPolicy            */
-#define PI_ITEM_K_T_NOTIFY                             0x12    /* SMTTNotify                             */
-#define PI_ITEM_K_STATION_ACTION               0x13    /* SMTStationAction                       */
-#define PI_ITEM_K_MAC_PATHS_REQ                        0x15    /* MACPathsRequested              */
-#define PI_ITEM_K_MAC_ACTION                   0x17    /* MACAction                              */
-#define PI_ITEM_K_CON_POLICIES                 0x18    /* PORTConnectionPolicies         */
-#define PI_ITEM_K_PORT_PATHS_REQ               0x19    /* PORTPathsRequested             */
-#define PI_ITEM_K_MAC_LOOP_TIME                        0x1A    /* PORTMACLoopTime                        */
-#define PI_ITEM_K_TB_MAX                               0x1B    /* PORTTBMax                              */
-#define PI_ITEM_K_LER_CUTOFF                   0x1C    /* PORTLerCutoff                          */
-#define PI_ITEM_K_LER_ALARM                            0x1D    /* PORTLerAlarm                           */
-#define PI_ITEM_K_PORT_ACTION                  0x1E    /* PORTAction                             */
-#define PI_ITEM_K_FLUSH_TIME                   0x20    /* Chars_Set                              */
-#define PI_ITEM_K_MAC_T_REQ                            0x29    /* MACTReq                                        */
-#define PI_ITEM_K_EMAC_RING_PURGER             0x2A    /* eMACRingPurgerEnable           */
-#define PI_ITEM_K_EMAC_RTOKEN_TIMEOUT  0x2B    /* eMACRestrictedTokenTimeout */
-#define PI_ITEM_K_FDX_ENB_DIS                  0x2C    /* eFDXEnable                             */
-#define PI_ITEM_K_MAX                                  0x2C    /* Must equal high item           */
-
-/* Values for some of the items */
-
-#define PI_K_FALSE                                             0          /* Generic false */
-#define PI_K_TRUE                                              1          /* Generic true  */
-
-#define PI_SNMP_K_TRUE                                 1          /* SNMP true/false values */
-#define PI_SNMP_K_FALSE                                        2
-
-#define PI_FSTATE_K_BLOCK                              0          /* Filter State */
-#define PI_FSTATE_K_PASS                               1
-
-/* Define command return codes */
-
-#define PI_RSP_K_SUCCESS                               0x00
-#define PI_RSP_K_FAILURE                               0x01
-#define PI_RSP_K_WARNING                               0x02
-#define PI_RSP_K_LOOP_MODE_BAD                 0x03
-#define PI_RSP_K_ITEM_CODE_BAD                 0x04
-#define PI_RSP_K_TVX_BAD                               0x05
-#define PI_RSP_K_TREQ_BAD                              0x06
-#define PI_RSP_K_TOKEN_BAD                             0x07
-#define PI_RSP_K_NO_EOL                                        0x0C
-#define PI_RSP_K_FILTER_STATE_BAD              0x0D
-#define PI_RSP_K_CMD_TYPE_BAD                  0x0E
-#define PI_RSP_K_ADAPTER_STATE_BAD             0x0F
-#define PI_RSP_K_RING_PURGER_BAD               0x10
-#define PI_RSP_K_LEM_THRESHOLD_BAD             0x11
-#define PI_RSP_K_LOOP_NOT_SUPPORTED            0x12
-#define PI_RSP_K_FLUSH_TIME_BAD                        0x13
-#define PI_RSP_K_NOT_IMPLEMENTED               0x14
-#define PI_RSP_K_CONFIG_POLICY_BAD             0x15
-#define PI_RSP_K_STATION_ACTION_BAD            0x16
-#define PI_RSP_K_MAC_ACTION_BAD                        0x17
-#define PI_RSP_K_CON_POLICIES_BAD              0x18
-#define PI_RSP_K_MAC_LOOP_TIME_BAD             0x19
-#define PI_RSP_K_TB_MAX_BAD                            0x1A
-#define PI_RSP_K_LER_CUTOFF_BAD                        0x1B
-#define PI_RSP_K_LER_ALARM_BAD                 0x1C
-#define PI_RSP_K_MAC_PATHS_REQ_BAD             0x1D
-#define PI_RSP_K_MAC_T_REQ_BAD                 0x1E
-#define PI_RSP_K_EMAC_RING_PURGER_BAD  0x1F
-#define PI_RSP_K_EMAC_RTOKEN_TIME_BAD  0x20
-#define PI_RSP_K_NO_SUCH_ENTRY                 0x21
-#define PI_RSP_K_T_NOTIFY_BAD                  0x22
-#define PI_RSP_K_TR_MAX_EXP_BAD                        0x23
-#define PI_RSP_K_MAC_FRM_ERR_THR_BAD   0x24
-#define PI_RSP_K_MAX_T_REQ_BAD                 0x25
-#define PI_RSP_K_FDX_ENB_DIS_BAD               0x26
-#define PI_RSP_K_ITEM_INDEX_BAD                        0x27
-#define PI_RSP_K_PORT_ACTION_BAD               0x28
-
-/* Commonly used structures */
-
-typedef struct                                                                 /* Item list */
-       {
-       PI_UINT32  item_code;
-       PI_UINT32  value;
-       } PI_ITEM_LIST;
-
-typedef struct                                                                 /* Response header */
-       {
-       PI_UINT32  reserved;
-       PI_UINT32  cmd_type;
-       PI_UINT32  status;
-       } PI_RSP_HEADER;
-
-
-/* Start Command */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_START_REQ;
-
-/* Start Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_START_RSP;
-
-/* Filters_Set Request */
-
-#define PI_CMD_FILTERS_SET_K_ITEMS_MAX  63             /* Fits in a 512 byte buffer */
-
-typedef struct
-       {
-       PI_UINT32               cmd_type;
-       PI_ITEM_LIST    item[PI_CMD_FILTERS_SET_K_ITEMS_MAX];
-       } PI_CMD_FILTERS_SET_REQ;
-
-/* Filters_Set Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_FILTERS_SET_RSP;
-
-/* Filters_Get Request */
-
-typedef struct
-       {
-       PI_UINT32               cmd_type;
-       } PI_CMD_FILTERS_GET_REQ;
-
-/* Filters_Get Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       PI_UINT32               ind_group_prom;
-       PI_UINT32               group_prom;
-       PI_UINT32               broadcast_all;
-       PI_UINT32               smt_all;
-       PI_UINT32               smt_user;
-       PI_UINT32               reserved_all;
-       PI_UINT32               implementor_all;
-       } PI_CMD_FILTERS_GET_RSP;
-
-
-/* Chars_Set Request */
-
-#define PI_CMD_CHARS_SET_K_ITEMS_MAX 42                /* Fits in a 512 byte buffer */
-
-typedef struct
-       {
-       PI_UINT32               cmd_type;
-       struct                                                                  /* Item list */
-               {
-               PI_UINT32       item_code;
-               PI_UINT32       value;
-               PI_UINT32       item_index;
-               } item[PI_CMD_CHARS_SET_K_ITEMS_MAX];
-       } PI_CMD_CHARS_SET_REQ;
-
-/* Chars_Set Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_CHARS_SET_RSP;
-
-
-/* SNMP_Set Request */
-
-#define PI_CMD_SNMP_SET_K_ITEMS_MAX 42         /* Fits in a 512 byte buffer */
-
-typedef struct
-       {
-       PI_UINT32               cmd_type;
-       struct                                                                  /* Item list */
-               {
-               PI_UINT32       item_code;
-               PI_UINT32       value;
-               PI_UINT32       item_index;
-               } item[PI_CMD_SNMP_SET_K_ITEMS_MAX];
-       } PI_CMD_SNMP_SET_REQ;
-
-/* SNMP_Set Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_SNMP_SET_RSP;
-
-
-/* SMT_MIB_Set Request */
-
-#define PI_CMD_SMT_MIB_SET_K_ITEMS_MAX 42      /* Max number of items */
-
-typedef struct
-       {
-       PI_UINT32       cmd_type;
-       struct
-               {
-               PI_UINT32       item_code;
-               PI_UINT32       value;
-               PI_UINT32       item_index;
-               } item[PI_CMD_SMT_MIB_SET_K_ITEMS_MAX];
-       } PI_CMD_SMT_MIB_SET_REQ;
-
-/* SMT_MIB_Set Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_SMT_MIB_SET_RSP;
-
-/* SMT_MIB_Get Request */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_SMT_MIB_GET_REQ;
-
-/* SMT_MIB_Get Response */
-
-typedef struct                                           /* Refer to ANSI FDDI SMT Rev. 7.3 */
-       {
-       PI_RSP_HEADER  header;
-
-       /* SMT GROUP */
-
-       PI_STATION_ID   smt_station_id;
-       PI_UINT32               smt_op_version_id;
-       PI_UINT32               smt_hi_version_id;
-       PI_UINT32               smt_lo_version_id;
-       PI_UINT32               smt_user_data[8];
-       PI_UINT32               smt_mib_version_id;
-       PI_UINT32               smt_mac_ct;
-       PI_UINT32               smt_non_master_ct;
-       PI_UINT32               smt_master_ct;
-       PI_UINT32               smt_available_paths;
-       PI_UINT32               smt_config_capabilities;
-       PI_UINT32               smt_config_policy;
-       PI_UINT32               smt_connection_policy;
-       PI_UINT32               smt_t_notify;
-       PI_UINT32               smt_stat_rpt_policy;
-       PI_UINT32               smt_trace_max_expiration;
-       PI_UINT32               smt_bypass_present;
-       PI_UINT32               smt_ecm_state;
-       PI_UINT32               smt_cf_state;
-       PI_UINT32               smt_remote_disconnect_flag;
-       PI_UINT32               smt_station_status;
-       PI_UINT32               smt_peer_wrap_flag;
-       PI_CNTR                 smt_msg_time_stamp;
-       PI_CNTR                 smt_transition_time_stamp;
-
-       /* MAC GROUP */
-
-       PI_UINT32               mac_frame_status_functions;
-       PI_UINT32               mac_t_max_capability;
-       PI_UINT32               mac_tvx_capability;
-       PI_UINT32               mac_available_paths;
-       PI_UINT32               mac_current_path;
-       PI_LAN_ADDR             mac_upstream_nbr;
-       PI_LAN_ADDR             mac_downstream_nbr;
-       PI_LAN_ADDR             mac_old_upstream_nbr;
-       PI_LAN_ADDR             mac_old_downstream_nbr;
-       PI_UINT32               mac_dup_address_test;
-       PI_UINT32               mac_requested_paths;
-       PI_UINT32               mac_downstream_port_type;
-       PI_LAN_ADDR             mac_smt_address;
-       PI_UINT32               mac_t_req;
-       PI_UINT32               mac_t_neg;
-       PI_UINT32               mac_t_max;
-       PI_UINT32               mac_tvx_value;
-       PI_UINT32               mac_frame_error_threshold;
-       PI_UINT32               mac_frame_error_ratio;
-       PI_UINT32               mac_rmt_state;
-       PI_UINT32               mac_da_flag;
-       PI_UINT32               mac_unda_flag;
-       PI_UINT32               mac_frame_error_flag;
-       PI_UINT32               mac_ma_unitdata_available;
-       PI_UINT32               mac_hardware_present;
-       PI_UINT32               mac_ma_unitdata_enable;
-
-       /* PATH GROUP */
-
-       PI_UINT32               path_configuration[8];
-       PI_UINT32               path_tvx_lower_bound;
-       PI_UINT32               path_t_max_lower_bound;
-       PI_UINT32               path_max_t_req;
-
-       /* PORT GROUP */
-
-       PI_UINT32               port_my_type[PI_PHY_K_MAX];
-       PI_UINT32               port_neighbor_type[PI_PHY_K_MAX];
-       PI_UINT32               port_connection_policies[PI_PHY_K_MAX];
-       PI_UINT32               port_mac_indicated[PI_PHY_K_MAX];
-       PI_UINT32               port_current_path[PI_PHY_K_MAX];
-       PI_UINT32               port_requested_paths[PI_PHY_K_MAX];
-       PI_UINT32               port_mac_placement[PI_PHY_K_MAX];
-       PI_UINT32               port_available_paths[PI_PHY_K_MAX];
-       PI_UINT32               port_pmd_class[PI_PHY_K_MAX];
-       PI_UINT32               port_connection_capabilities[PI_PHY_K_MAX];
-       PI_UINT32               port_bs_flag[PI_PHY_K_MAX];
-       PI_UINT32               port_ler_estimate[PI_PHY_K_MAX];
-       PI_UINT32               port_ler_cutoff[PI_PHY_K_MAX];
-       PI_UINT32               port_ler_alarm[PI_PHY_K_MAX];
-       PI_UINT32               port_connect_state[PI_PHY_K_MAX];
-       PI_UINT32               port_pcm_state[PI_PHY_K_MAX];
-       PI_UINT32               port_pc_withhold[PI_PHY_K_MAX];
-       PI_UINT32               port_ler_flag[PI_PHY_K_MAX];
-       PI_UINT32               port_hardware_present[PI_PHY_K_MAX];
-
-       /* GROUP for things that were added later, so must be at the end. */
-
-       PI_CNTR                 path_ring_latency;
-
-       } PI_CMD_SMT_MIB_GET_RSP;
-
-
-/*
- *  Item and group code definitions for SMT 7.3 mandatory objects.  These
- *  definitions are to be used as appropriate in SMT_MIB_SET commands and
- *  certain host-sent SMT frames such as PMF Get and Set requests.  The
- *  codes have been taken from the MIB summary section of ANSI SMT 7.3.
- */
-
-#define PI_GRP_K_SMT_STATION_ID                        0x100A
-#define PI_ITEM_K_SMT_STATION_ID               0x100B
-#define PI_ITEM_K_SMT_OP_VERS_ID               0x100D
-#define PI_ITEM_K_SMT_HI_VERS_ID               0x100E
-#define PI_ITEM_K_SMT_LO_VERS_ID               0x100F
-#define PI_ITEM_K_SMT_USER_DATA                        0x1011
-#define PI_ITEM_K_SMT_MIB_VERS_ID              0x1012
-
-#define PI_GRP_K_SMT_STATION_CONFIG            0x1014
-#define PI_ITEM_K_SMT_MAC_CT                   0x1015
-#define PI_ITEM_K_SMT_NON_MASTER_CT            0x1016
-#define PI_ITEM_K_SMT_MASTER_CT                        0x1017
-#define PI_ITEM_K_SMT_AVAIL_PATHS              0x1018
-#define PI_ITEM_K_SMT_CONFIG_CAPS              0x1019
-#define PI_ITEM_K_SMT_CONFIG_POL               0x101A
-#define PI_ITEM_K_SMT_CONN_POL                 0x101B
-#define PI_ITEM_K_SMT_T_NOTIFY                 0x101D
-#define PI_ITEM_K_SMT_STAT_POL                 0x101E
-#define PI_ITEM_K_SMT_TR_MAX_EXP               0x101F
-#define PI_ITEM_K_SMT_PORT_INDEXES             0x1020
-#define PI_ITEM_K_SMT_MAC_INDEXES              0x1021
-#define PI_ITEM_K_SMT_BYPASS_PRESENT   0x1022
-
-#define PI_GRP_K_SMT_STATUS                            0x1028
-#define PI_ITEM_K_SMT_ECM_STATE                        0x1029
-#define PI_ITEM_K_SMT_CF_STATE                 0x102A
-#define PI_ITEM_K_SMT_REM_DISC_FLAG            0x102C
-#define PI_ITEM_K_SMT_STATION_STATUS   0x102D
-#define PI_ITEM_K_SMT_PEER_WRAP_FLAG   0x102E
-
-#define PI_GRP_K_SMT_MIB_OPERATION             0x1032
-#define PI_ITEM_K_SMT_MSG_TIME_STAMP   0x1033
-#define PI_ITEM_K_SMT_TRN_TIME_STAMP   0x1034
-
-#define PI_ITEM_K_SMT_STATION_ACT              0x103C
-
-#define PI_GRP_K_MAC_CAPABILITIES              0x200A
-#define PI_ITEM_K_MAC_FRM_STAT_FUNC            0x200B
-#define PI_ITEM_K_MAC_T_MAX_CAP                        0x200D
-#define PI_ITEM_K_MAC_TVX_CAP                  0x200E
-
-#define PI_GRP_K_MAC_CONFIG                            0x2014
-#define PI_ITEM_K_MAC_AVAIL_PATHS              0x2016
-#define PI_ITEM_K_MAC_CURRENT_PATH             0x2017
-#define PI_ITEM_K_MAC_UP_NBR                   0x2018
-#define PI_ITEM_K_MAC_DOWN_NBR                 0x2019
-#define PI_ITEM_K_MAC_OLD_UP_NBR               0x201A
-#define PI_ITEM_K_MAC_OLD_DOWN_NBR             0x201B
-#define PI_ITEM_K_MAC_DUP_ADDR_TEST            0x201D
-#define PI_ITEM_K_MAC_REQ_PATHS                        0x2020
-#define PI_ITEM_K_MAC_DOWN_PORT_TYPE           0x2021
-#define PI_ITEM_K_MAC_INDEX                            0x2022
-
-#define PI_GRP_K_MAC_ADDRESS                   0x2028
-#define PI_ITEM_K_MAC_SMT_ADDRESS              0x2029
-
-#define PI_GRP_K_MAC_OPERATION                 0x2032
-#define PI_ITEM_K_MAC_TREQ                             0x2033
-#define PI_ITEM_K_MAC_TNEG                             0x2034
-#define PI_ITEM_K_MAC_TMAX                             0x2035
-#define PI_ITEM_K_MAC_TVX_VALUE                        0x2036
-
-#define PI_GRP_K_MAC_COUNTERS                  0x2046
-#define PI_ITEM_K_MAC_FRAME_CT                 0x2047
-#define PI_ITEM_K_MAC_COPIED_CT                        0x2048
-#define PI_ITEM_K_MAC_TRANSMIT_CT              0x2049
-#define PI_ITEM_K_MAC_ERROR_CT                 0x2051
-#define PI_ITEM_K_MAC_LOST_CT                  0x2052
-
-#define PI_GRP_K_MAC_FRM_ERR_COND              0x205A
-#define PI_ITEM_K_MAC_FRM_ERR_THR              0x205F
-#define PI_ITEM_K_MAC_FRM_ERR_RAT              0x2060
-
-#define PI_GRP_K_MAC_STATUS                            0x206E
-#define PI_ITEM_K_MAC_RMT_STATE                        0x206F
-#define PI_ITEM_K_MAC_DA_FLAG                  0x2070
-#define PI_ITEM_K_MAC_UNDA_FLAG                        0x2071
-#define PI_ITEM_K_MAC_FRM_ERR_FLAG             0x2072
-#define PI_ITEM_K_MAC_MA_UNIT_AVAIL            0x2074
-#define PI_ITEM_K_MAC_HW_PRESENT               0x2075
-#define PI_ITEM_K_MAC_MA_UNIT_ENAB             0x2076
-
-#define PI_GRP_K_PATH_CONFIG                   0x320A
-#define PI_ITEM_K_PATH_INDEX                   0x320B
-#define PI_ITEM_K_PATH_CONFIGURATION   0x3212
-#define PI_ITEM_K_PATH_TVX_LB                  0x3215
-#define PI_ITEM_K_PATH_T_MAX_LB                        0x3216
-#define PI_ITEM_K_PATH_MAX_T_REQ               0x3217
-
-#define PI_GRP_K_PORT_CONFIG                   0x400A
-#define PI_ITEM_K_PORT_MY_TYPE                 0x400C
-#define PI_ITEM_K_PORT_NBR_TYPE                        0x400D
-#define PI_ITEM_K_PORT_CONN_POLS               0x400E
-#define PI_ITEM_K_PORT_MAC_INDICATED   0x400F
-#define PI_ITEM_K_PORT_CURRENT_PATH            0x4010
-#define PI_ITEM_K_PORT_REQ_PATHS               0x4011
-#define PI_ITEM_K_PORT_MAC_PLACEMENT   0x4012
-#define PI_ITEM_K_PORT_AVAIL_PATHS             0x4013
-#define PI_ITEM_K_PORT_PMD_CLASS               0x4016
-#define PI_ITEM_K_PORT_CONN_CAPS               0x4017
-#define PI_ITEM_K_PORT_INDEX                   0x401D
-
-#define PI_GRP_K_PORT_OPERATION                        0x401E
-#define PI_ITEM_K_PORT_BS_FLAG                 0x4021
-
-#define PI_GRP_K_PORT_ERR_CNTRS                        0x4028
-#define PI_ITEM_K_PORT_LCT_FAIL_CT             0x402A
-
-#define PI_GRP_K_PORT_LER                              0x4032
-#define PI_ITEM_K_PORT_LER_ESTIMATE            0x4033
-#define PI_ITEM_K_PORT_LEM_REJ_CT              0x4034
-#define PI_ITEM_K_PORT_LEM_CT                  0x4035
-#define PI_ITEM_K_PORT_LER_CUTOFF              0x403A
-#define PI_ITEM_K_PORT_LER_ALARM               0x403B
-
-#define PI_GRP_K_PORT_STATUS                   0x403C
-#define PI_ITEM_K_PORT_CONNECT_STATE   0x403D
-#define PI_ITEM_K_PORT_PCM_STATE               0x403E
-#define PI_ITEM_K_PORT_PC_WITHHOLD             0x403F
-#define PI_ITEM_K_PORT_LER_FLAG                        0x4040
-#define PI_ITEM_K_PORT_HW_PRESENT              0x4041
-
-#define PI_ITEM_K_PORT_ACT                             0x4046
-
-/* Addr_Filter_Set Request */
-
-#define PI_CMD_ADDR_FILTER_K_SIZE   62
-
-typedef struct
-       {
-       PI_UINT32       cmd_type;
-       PI_LAN_ADDR     entry[PI_CMD_ADDR_FILTER_K_SIZE];
-       } PI_CMD_ADDR_FILTER_SET_REQ;
-
-/* Addr_Filter_Set Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_ADDR_FILTER_SET_RSP;
-
-/* Addr_Filter_Get Request */
-
-typedef struct
-       {
-       PI_UINT32       cmd_type;
-       } PI_CMD_ADDR_FILTER_GET_REQ;
-
-/* Addr_Filter_Get Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       PI_LAN_ADDR             entry[PI_CMD_ADDR_FILTER_K_SIZE];
-       } PI_CMD_ADDR_FILTER_GET_RSP;
-
-/* Status_Chars_Get Request */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_STATUS_CHARS_GET_REQ;
-
-/* Status_Chars_Get Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       PI_STATION_ID   station_id;                                             /* Station */
-       PI_UINT32               station_type;
-       PI_UINT32               smt_ver_id;
-       PI_UINT32               smt_ver_id_max;
-       PI_UINT32               smt_ver_id_min;
-       PI_UINT32               station_state;
-       PI_LAN_ADDR             link_addr;                                              /* Link */
-       PI_UINT32               t_req;
-       PI_UINT32               tvx;
-       PI_UINT32               token_timeout;
-       PI_UINT32               purger_enb;
-       PI_UINT32               link_state;
-       PI_UINT32               tneg;
-       PI_UINT32               dup_addr_flag;
-       PI_LAN_ADDR             una;
-       PI_LAN_ADDR             una_old;
-       PI_UINT32               un_dup_addr_flag;
-       PI_LAN_ADDR             dna;
-       PI_LAN_ADDR             dna_old;
-       PI_UINT32               purger_state;
-       PI_UINT32               fci_mode;
-       PI_UINT32               error_reason;
-       PI_UINT32               loopback;
-       PI_UINT32               ring_latency;
-       PI_LAN_ADDR             last_dir_beacon_sa;
-       PI_LAN_ADDR             last_dir_beacon_una;
-       PI_UINT32               phy_type[PI_PHY_K_MAX];                 /* Phy */
-       PI_UINT32               pmd_type[PI_PHY_K_MAX];
-       PI_UINT32               lem_threshold[PI_PHY_K_MAX];
-       PI_UINT32               phy_state[PI_PHY_K_MAX];
-       PI_UINT32               nbor_phy_type[PI_PHY_K_MAX];
-       PI_UINT32               link_error_est[PI_PHY_K_MAX];
-       PI_UINT32               broken_reason[PI_PHY_K_MAX];
-       PI_UINT32               reject_reason[PI_PHY_K_MAX];
-       PI_UINT32               cntr_interval;                                  /* Miscellaneous */
-       PI_UINT32               module_rev;
-       PI_UINT32               firmware_rev;
-       PI_UINT32               mop_device_type;
-       PI_UINT32               phy_led[PI_PHY_K_MAX];
-       PI_UINT32               flush_time;
-       } PI_CMD_STATUS_CHARS_GET_RSP;
-
-/* FDDI_MIB_Get Request */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_FDDI_MIB_GET_REQ;
-
-/* FDDI_MIB_Get Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-
-       /* SMT GROUP */
-
-       PI_STATION_ID   smt_station_id;
-       PI_UINT32               smt_op_version_id;
-       PI_UINT32               smt_hi_version_id;
-       PI_UINT32               smt_lo_version_id;
-       PI_UINT32               smt_mac_ct;
-       PI_UINT32               smt_non_master_ct;
-       PI_UINT32               smt_master_ct;
-       PI_UINT32               smt_paths_available;
-       PI_UINT32               smt_config_capabilities;
-       PI_UINT32               smt_config_policy;
-       PI_UINT32               smt_connection_policy;
-       PI_UINT32               smt_t_notify;
-       PI_UINT32               smt_status_reporting;
-       PI_UINT32               smt_ecm_state;
-       PI_UINT32               smt_cf_state;
-       PI_UINT32               smt_hold_state;
-       PI_UINT32               smt_remote_disconnect_flag;
-       PI_UINT32               smt_station_action;
-
-       /* MAC GROUP */
-
-       PI_UINT32               mac_frame_status_capabilities;
-       PI_UINT32               mac_t_max_greatest_lower_bound;
-       PI_UINT32               mac_tvx_greatest_lower_bound;
-       PI_UINT32               mac_paths_available;
-       PI_UINT32               mac_current_path;
-       PI_LAN_ADDR             mac_upstream_nbr;
-       PI_LAN_ADDR             mac_old_upstream_nbr;
-       PI_UINT32               mac_dup_addr_test;
-       PI_UINT32               mac_paths_requested;
-       PI_UINT32               mac_downstream_port_type;
-       PI_LAN_ADDR             mac_smt_address;
-       PI_UINT32               mac_t_req;
-       PI_UINT32               mac_t_neg;
-       PI_UINT32               mac_t_max;
-       PI_UINT32               mac_tvx_value;
-       PI_UINT32               mac_t_min;
-       PI_UINT32               mac_current_frame_status;
-       /*                              mac_frame_cts                   */
-       /*                              mac_error_cts                   */
-       /*                              mac_lost_cts                    */
-       PI_UINT32               mac_frame_error_threshold;
-       PI_UINT32               mac_frame_error_ratio;
-       PI_UINT32               mac_rmt_state;
-       PI_UINT32               mac_da_flag;
-       PI_UINT32               mac_una_da_flag;
-       PI_UINT32               mac_frame_condition;
-       PI_UINT32               mac_chip_set;
-       PI_UINT32               mac_action;
-
-       /* PATH GROUP => Does not need to be implemented */
-
-       /* PORT GROUP */
-
-       PI_UINT32               port_pc_type[PI_PHY_K_MAX];
-       PI_UINT32               port_pc_neighbor[PI_PHY_K_MAX];
-       PI_UINT32               port_connection_policies[PI_PHY_K_MAX];
-       PI_UINT32               port_remote_mac_indicated[PI_PHY_K_MAX];
-       PI_UINT32               port_ce_state[PI_PHY_K_MAX];
-       PI_UINT32               port_paths_requested[PI_PHY_K_MAX];
-       PI_UINT32               port_mac_placement[PI_PHY_K_MAX];
-       PI_UINT32               port_available_paths[PI_PHY_K_MAX];
-       PI_UINT32               port_mac_loop_time[PI_PHY_K_MAX];
-       PI_UINT32               port_tb_max[PI_PHY_K_MAX];
-       PI_UINT32               port_bs_flag[PI_PHY_K_MAX];
-       /*                              port_lct_fail_cts[PI_PHY_K_MAX];        */
-       PI_UINT32               port_ler_estimate[PI_PHY_K_MAX];
-       /*                              port_lem_reject_cts[PI_PHY_K_MAX];      */
-       /*                              port_lem_cts[PI_PHY_K_MAX];             */
-       PI_UINT32               port_ler_cutoff[PI_PHY_K_MAX];
-       PI_UINT32               port_ler_alarm[PI_PHY_K_MAX];
-       PI_UINT32               port_connect_state[PI_PHY_K_MAX];
-       PI_UINT32               port_pcm_state[PI_PHY_K_MAX];
-       PI_UINT32               port_pc_withhold[PI_PHY_K_MAX];
-       PI_UINT32               port_ler_condition[PI_PHY_K_MAX];
-       PI_UINT32               port_chip_set[PI_PHY_K_MAX];
-       PI_UINT32               port_action[PI_PHY_K_MAX];
-
-       /* ATTACHMENT GROUP */
-
-       PI_UINT32               attachment_class;
-       PI_UINT32               attachment_ob_present;
-       PI_UINT32               attachment_imax_expiration;
-       PI_UINT32               attachment_inserted_status;
-       PI_UINT32               attachment_insert_policy;
-
-       /* CHIP SET GROUP => Does not need to be implemented */
-
-       } PI_CMD_FDDI_MIB_GET_RSP;
-
-/* DEC_Ext_MIB_Get Request */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_DEC_EXT_MIB_GET_REQ;
-
-/* DEC_Ext_MIB_Get (efddi and efdx groups only) Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-
-       /* SMT GROUP */
-
-       PI_UINT32               esmt_station_type;
-
-       /* MAC GROUP */
-
-       PI_UINT32               emac_link_state;
-       PI_UINT32               emac_ring_purger_state;
-       PI_UINT32               emac_ring_purger_enable;
-       PI_UINT32               emac_frame_strip_mode;
-       PI_UINT32               emac_ring_error_reason;
-       PI_UINT32               emac_up_nbr_dup_addr_flag;
-       PI_UINT32               emac_restricted_token_timeout;
-
-       /* PORT GROUP */
-
-       PI_UINT32               eport_pmd_type[PI_PHY_K_MAX];
-       PI_UINT32               eport_phy_state[PI_PHY_K_MAX];
-       PI_UINT32               eport_reject_reason[PI_PHY_K_MAX];
-
-       /* FDX (Full-Duplex) GROUP */
-
-       PI_UINT32               efdx_enable;                            /* Valid only in SMT 7.3 */
-       PI_UINT32               efdx_op;                                        /* Valid only in SMT 7.3 */
-       PI_UINT32               efdx_state;                                     /* Valid only in SMT 7.3 */
-
-       } PI_CMD_DEC_EXT_MIB_GET_RSP;
-
-typedef struct
-       {
-       PI_CNTR         traces_rcvd;                                    /* Station */
-       PI_CNTR         frame_cnt;                                              /* Link */
-       PI_CNTR         error_cnt;
-       PI_CNTR         lost_cnt;
-       PI_CNTR         octets_rcvd;
-       PI_CNTR         octets_sent;
-       PI_CNTR         pdus_rcvd;
-       PI_CNTR         pdus_sent;
-       PI_CNTR         mcast_octets_rcvd;
-       PI_CNTR         mcast_octets_sent;
-       PI_CNTR         mcast_pdus_rcvd;
-       PI_CNTR         mcast_pdus_sent;
-       PI_CNTR         xmt_underruns;
-       PI_CNTR         xmt_failures;
-       PI_CNTR         block_check_errors;
-       PI_CNTR         frame_status_errors;
-       PI_CNTR         pdu_length_errors;
-       PI_CNTR         rcv_overruns;
-       PI_CNTR         user_buff_unavailable;
-       PI_CNTR         inits_initiated;
-       PI_CNTR         inits_rcvd;
-       PI_CNTR         beacons_initiated;
-       PI_CNTR         dup_addrs;
-       PI_CNTR         dup_tokens;
-       PI_CNTR         purge_errors;
-       PI_CNTR         fci_strip_errors;
-       PI_CNTR         traces_initiated;
-       PI_CNTR         directed_beacons_rcvd;
-       PI_CNTR         emac_frame_alignment_errors;
-       PI_CNTR         ebuff_errors[PI_PHY_K_MAX];             /* Phy */
-       PI_CNTR         lct_rejects[PI_PHY_K_MAX];
-       PI_CNTR         lem_rejects[PI_PHY_K_MAX];
-       PI_CNTR         link_errors[PI_PHY_K_MAX];
-       PI_CNTR         connections[PI_PHY_K_MAX];
-       PI_CNTR         copied_cnt;                                             /* Valid only if using SMT 7.3 */
-       PI_CNTR         transmit_cnt;                                   /* Valid only if using SMT 7.3 */
-       PI_CNTR         tokens;
-       } PI_CNTR_BLK;
-
-/* Counters_Get Request */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_CNTRS_GET_REQ;
-
-/* Counters_Get Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       PI_CNTR         time_since_reset;
-       PI_CNTR_BLK             cntrs;
-       } PI_CMD_CNTRS_GET_RSP;
-
-/* Counters_Set Request */
-
-typedef struct
-       {
-       PI_UINT32       cmd_type;
-       PI_CNTR_BLK     cntrs;
-       } PI_CMD_CNTRS_SET_REQ;
-
-/* Counters_Set Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_CNTRS_SET_RSP;
-
-/* Error_Log_Clear Request */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       } PI_CMD_ERROR_LOG_CLEAR_REQ;
-
-/* Error_Log_Clear Response */
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       } PI_CMD_ERROR_LOG_CLEAR_RSP;
-
-/* Error_Log_Get Request */
-
-#define PI_LOG_ENTRY_K_INDEX_MIN       0               /* Minimum index for entry */
-
-typedef struct
-       {
-       PI_UINT32  cmd_type;
-       PI_UINT32  entry_index;
-       } PI_CMD_ERROR_LOG_GET_REQ;
-
-/* Error_Log_Get Response */
-
-#define PI_K_LOG_FW_SIZE                       111             /* Max number of fw longwords */
-#define PI_K_LOG_DIAG_SIZE                     6               /* Max number of diag longwords */
-
-typedef struct
-       {
-       struct
-               {
-               PI_UINT32       fru_imp_mask;
-               PI_UINT32       test_id;
-               PI_UINT32       reserved[PI_K_LOG_DIAG_SIZE];
-               } diag;
-       PI_UINT32               fw[PI_K_LOG_FW_SIZE];
-       } PI_LOG_ENTRY;
-
-typedef struct
-       {
-       PI_RSP_HEADER   header;
-       PI_UINT32               event_status;
-       PI_UINT32               caller_id;
-       PI_UINT32               timestamp_l;
-       PI_UINT32               timestamp_h;
-       PI_UINT32               write_count;
-       PI_LOG_ENTRY    entry_info;
-       } PI_CMD_ERROR_LOG_GET_RSP;
-
-/* Define error log related constants and types.                                       */
-/*   Not all of the caller id's can occur.  The only ones currently */
-/*   implemented are: none, selftest, mfg, fw, console                         */
-
-#define PI_LOG_EVENT_STATUS_K_VALID            0       /* Valid Event Status           */
-#define PI_LOG_EVENT_STATUS_K_INVALID  1       /* Invalid Event Status         */
-#define PI_LOG_CALLER_ID_K_NONE                        0       /* No caller                            */
-#define PI_LOG_CALLER_ID_K_SELFTEST            1       /* Normal power-up selftest */
-#define PI_LOG_CALLER_ID_K_MFG                 2       /* Mfg power-up selftest        */
-#define PI_LOG_CALLER_ID_K_ONLINE              3       /* On-line diagnostics          */
-#define PI_LOG_CALLER_ID_K_HW                  4       /* Hardware                             */
-#define PI_LOG_CALLER_ID_K_FW                  5       /* Firmware                             */
-#define PI_LOG_CALLER_ID_K_CNS_HW              6       /* CNS firmware                         */
-#define PI_LOG_CALLER_ID_K_CNS_FW              7       /* CNS hardware                         */
-#define PI_LOG_CALLER_ID_K_CONSOLE             8   /* Console Caller Id                */
-
-/*
- *  Place all DMA commands in the following request and response structures
- *  to simplify code.
- */
-
-typedef union
-       {
-       PI_UINT32                                       cmd_type;
-       PI_CMD_START_REQ                        start;
-       PI_CMD_FILTERS_SET_REQ          filter_set;
-       PI_CMD_FILTERS_GET_REQ          filter_get;
-       PI_CMD_CHARS_SET_REQ            char_set;
-       PI_CMD_ADDR_FILTER_SET_REQ      addr_filter_set;
-       PI_CMD_ADDR_FILTER_GET_REQ      addr_filter_get;
-       PI_CMD_STATUS_CHARS_GET_REQ     stat_char_get;
-       PI_CMD_CNTRS_GET_REQ            cntrs_get;
-       PI_CMD_CNTRS_SET_REQ            cntrs_set;
-       PI_CMD_ERROR_LOG_CLEAR_REQ      error_log_clear;
-       PI_CMD_ERROR_LOG_GET_REQ        error_log_read;
-       PI_CMD_SNMP_SET_REQ                     snmp_set;
-       PI_CMD_FDDI_MIB_GET_REQ         fddi_mib_get;
-       PI_CMD_DEC_EXT_MIB_GET_REQ      dec_mib_get;
-       PI_CMD_SMT_MIB_SET_REQ          smt_mib_set;
-       PI_CMD_SMT_MIB_GET_REQ          smt_mib_get;
-       char                                            pad[PI_CMD_REQ_K_SIZE_MAX];
-       } PI_DMA_CMD_REQ;
-
-typedef union
-       {
-       PI_RSP_HEADER                           header;
-       PI_CMD_START_RSP                        start;
-       PI_CMD_FILTERS_SET_RSP          filter_set;
-       PI_CMD_FILTERS_GET_RSP          filter_get;
-       PI_CMD_CHARS_SET_RSP            char_set;
-       PI_CMD_ADDR_FILTER_SET_RSP      addr_filter_set;
-       PI_CMD_ADDR_FILTER_GET_RSP      addr_filter_get;
-       PI_CMD_STATUS_CHARS_GET_RSP     stat_char_get;
-       PI_CMD_CNTRS_GET_RSP            cntrs_get;
-       PI_CMD_CNTRS_SET_RSP            cntrs_set;
-       PI_CMD_ERROR_LOG_CLEAR_RSP      error_log_clear;
-       PI_CMD_ERROR_LOG_GET_RSP        error_log_get;
-       PI_CMD_SNMP_SET_RSP                     snmp_set;
-       PI_CMD_FDDI_MIB_GET_RSP         fddi_mib_get;
-       PI_CMD_DEC_EXT_MIB_GET_RSP      dec_mib_get;
-       PI_CMD_SMT_MIB_SET_RSP          smt_mib_set;
-       PI_CMD_SMT_MIB_GET_RSP          smt_mib_get;
-       char                                            pad[PI_CMD_RSP_K_SIZE_MAX];
-       } PI_DMA_CMD_RSP;
-
-typedef union
-       {
-       PI_DMA_CMD_REQ  request;
-       PI_DMA_CMD_RSP  response;
-       } PI_DMA_CMD_BUFFER;
-
-
-/* Define format of Consumer Block (resident in host memory) */
-
-typedef struct
-       {
-       volatile PI_UINT32      xmt_rcv_data;
-       volatile PI_UINT32      reserved_1;
-       volatile PI_UINT32      smt_host;
-       volatile PI_UINT32      reserved_2;
-       volatile PI_UINT32      unsol;
-       volatile PI_UINT32      reserved_3;
-       volatile PI_UINT32      cmd_rsp;
-       volatile PI_UINT32      reserved_4;
-       volatile PI_UINT32      cmd_req;
-       volatile PI_UINT32      reserved_5;
-       } PI_CONSUMER_BLOCK;
-
-#define PI_CONS_M_RCV_INDEX                    0x000000FF
-#define PI_CONS_M_XMT_INDEX                    0x00FF0000
-#define PI_CONS_V_RCV_INDEX                    0
-#define PI_CONS_V_XMT_INDEX                    16
-
-/* Offsets into consumer block */
-
-#define PI_CONS_BLK_K_XMT_RCV          0x00
-#define PI_CONS_BLK_K_SMT_HOST         0x08
-#define PI_CONS_BLK_K_UNSOL                    0x10
-#define PI_CONS_BLK_K_CMD_RSP          0x18
-#define PI_CONS_BLK_K_CMD_REQ          0x20
-
-/* Offsets into descriptor block */
-
-#define PI_DESCR_BLK_K_RCV_DATA                0x0000
-#define PI_DESCR_BLK_K_XMT_DATA                0x0800
-#define PI_DESCR_BLK_K_SMT_HOST        0x1000
-#define PI_DESCR_BLK_K_UNSOL           0x1200
-#define PI_DESCR_BLK_K_CMD_RSP         0x1280
-#define PI_DESCR_BLK_K_CMD_REQ         0x1300
-
-/* Define format of a rcv descr (Rcv Data, Cmd Rsp, Unsolicited, SMT Host)   */
-/*   Note a field has been added for later versions of the PDQ to allow for  */
-/*   finer granularity of the rcv buffer alignment.  For backwards                      */
-/*   compatibility, the two bits (which allow the rcv buffer to be longword  */
-/*   aligned) have been added at the MBZ bits.  To support previous drivers, */
-/*   the MBZ definition is left intact.                                                                                 */
-
-typedef struct
-       {
-       PI_UINT32       long_0;
-       PI_UINT32       long_1;
-       } PI_RCV_DESCR;
-
-#define        PI_RCV_DESCR_M_SOP                      0x80000000
-#define PI_RCV_DESCR_M_SEG_LEN_LO      0x60000000
-#define PI_RCV_DESCR_M_MBZ                     0x60000000
-#define PI_RCV_DESCR_M_SEG_LEN         0x1F800000
-#define PI_RCV_DESCR_M_SEG_LEN_HI      0x1FF00000
-#define PI_RCV_DESCR_M_SEG_CNT         0x000F0000
-#define PI_RCV_DESCR_M_BUFF_HI         0x0000FFFF
-
-#define        PI_RCV_DESCR_V_SOP                      31
-#define PI_RCV_DESCR_V_SEG_LEN_LO      29
-#define PI_RCV_DESCR_V_MBZ                     29
-#define PI_RCV_DESCR_V_SEG_LEN         23
-#define PI_RCV_DESCR_V_SEG_LEN_HI      20
-#define PI_RCV_DESCR_V_SEG_CNT         16
-#define PI_RCV_DESCR_V_BUFF_HI         0
-
-/* Define the format of a transmit descriptor (Xmt Data, Cmd Req) */
-
-typedef struct
-       {
-       PI_UINT32       long_0;
-       PI_UINT32       long_1;
-       } PI_XMT_DESCR;
-
-#define        PI_XMT_DESCR_M_SOP                      0x80000000
-#define PI_XMT_DESCR_M_EOP                     0x40000000
-#define PI_XMT_DESCR_M_MBZ                     0x20000000
-#define PI_XMT_DESCR_M_SEG_LEN         0x1FFF0000
-#define PI_XMT_DESCR_M_BUFF_HI         0x0000FFFF
-
-#define        PI_XMT_DESCR_V_SOP                      31
-#define        PI_XMT_DESCR_V_EOP                      30
-#define PI_XMT_DESCR_V_MBZ                     29
-#define PI_XMT_DESCR_V_SEG_LEN         16
-#define PI_XMT_DESCR_V_BUFF_HI         0
-
-/* Define format of the Descriptor Block (resident in host memory) */
-
-#define PI_RCV_DATA_K_NUM_ENTRIES                      256
-#define PI_XMT_DATA_K_NUM_ENTRIES                      256
-#define PI_SMT_HOST_K_NUM_ENTRIES                      64
-#define PI_UNSOL_K_NUM_ENTRIES                         16
-#define PI_CMD_RSP_K_NUM_ENTRIES                       16
-#define PI_CMD_REQ_K_NUM_ENTRIES                       16
-
-typedef struct
-       {
-       PI_RCV_DESCR  rcv_data[PI_RCV_DATA_K_NUM_ENTRIES];
-       PI_XMT_DESCR  xmt_data[PI_XMT_DATA_K_NUM_ENTRIES];
-       PI_RCV_DESCR  smt_host[PI_SMT_HOST_K_NUM_ENTRIES];
-       PI_RCV_DESCR  unsol[PI_UNSOL_K_NUM_ENTRIES];
-       PI_RCV_DESCR  cmd_rsp[PI_CMD_RSP_K_NUM_ENTRIES];
-       PI_XMT_DESCR  cmd_req[PI_CMD_REQ_K_NUM_ENTRIES];
-       } PI_DESCR_BLOCK;
-
-/* Define Port Registers - offsets from PDQ Base address */
-
-#define PI_PDQ_K_REG_PORT_RESET                        0x00000000
-#define PI_PDQ_K_REG_HOST_DATA                 0x00000004
-#define PI_PDQ_K_REG_PORT_CTRL                 0x00000008
-#define PI_PDQ_K_REG_PORT_DATA_A               0x0000000C
-#define PI_PDQ_K_REG_PORT_DATA_B               0x00000010
-#define PI_PDQ_K_REG_PORT_STATUS               0x00000014
-#define PI_PDQ_K_REG_TYPE_0_STATUS             0x00000018
-#define PI_PDQ_K_REG_HOST_INT_ENB              0x0000001C
-#define PI_PDQ_K_REG_TYPE_2_PROD_NOINT         0x00000020
-#define PI_PDQ_K_REG_TYPE_2_PROD               0x00000024
-#define PI_PDQ_K_REG_CMD_RSP_PROD              0x00000028
-#define PI_PDQ_K_REG_CMD_REQ_PROD              0x0000002C
-#define PI_PDQ_K_REG_SMT_HOST_PROD     0x00000030
-#define PI_PDQ_K_REG_UNSOL_PROD                        0x00000034
-
-/* Port Control Register - Command codes for primary commands */
-
-#define PI_PCTRL_M_CMD_ERROR                   0x8000
-#define PI_PCTRL_M_BLAST_FLASH                 0x4000
-#define PI_PCTRL_M_HALT                                        0x2000
-#define PI_PCTRL_M_COPY_DATA                   0x1000
-#define PI_PCTRL_M_ERROR_LOG_START             0x0800
-#define PI_PCTRL_M_ERROR_LOG_READ              0x0400
-#define PI_PCTRL_M_XMT_DATA_FLUSH_DONE 0x0200
-#define PI_PCTRL_M_INIT                                        0x0100
-#define PI_PCTRL_M_INIT_START              0x0080
-#define PI_PCTRL_M_CONS_BLOCK                  0x0040
-#define PI_PCTRL_M_UNINIT                              0x0020
-#define PI_PCTRL_M_RING_MEMBER                 0x0010
-#define PI_PCTRL_M_MLA                                 0x0008
-#define PI_PCTRL_M_FW_REV_READ                 0x0004
-#define PI_PCTRL_M_DEV_SPECIFIC                        0x0002
-#define PI_PCTRL_M_SUB_CMD                             0x0001
-
-/* Define sub-commands accessed via the PI_PCTRL_M_SUB_CMD command */
-
-#define PI_SUB_CMD_K_LINK_UNINIT               0x0001
-#define PI_SUB_CMD_K_BURST_SIZE_SET            0x0002
-#define PI_SUB_CMD_K_PDQ_REV_GET               0x0004
-#define PI_SUB_CMD_K_HW_REV_GET                        0x0008
-
-/* Define some Port Data B values */
-
-#define PI_PDATA_B_DMA_BURST_SIZE_4            0               /* valid values for command */
-#define PI_PDATA_B_DMA_BURST_SIZE_8            1
-#define PI_PDATA_B_DMA_BURST_SIZE_16   2
-#define PI_PDATA_B_DMA_BURST_SIZE_32   3               /* not supported on PCI */
-#define PI_PDATA_B_DMA_BURST_SIZE_DEF  PI_PDATA_B_DMA_BURST_SIZE_16
-
-/* Port Data A Reset state */
-
-#define PI_PDATA_A_RESET_M_UPGRADE             0x00000001
-#define PI_PDATA_A_RESET_M_SOFT_RESET  0x00000002
-#define PI_PDATA_A_RESET_M_SKIP_ST             0x00000004
-
-/* Read adapter MLA address port control command constants */
-
-#define PI_PDATA_A_MLA_K_LO                            0
-#define PI_PDATA_A_MLA_K_HI                            1
-
-/* Byte Swap values for init command */
-
-#define PI_PDATA_A_INIT_M_DESC_BLK_ADDR                        0x0FFFFE000
-#define PI_PDATA_A_INIT_M_RESERVED                             0x000001FFC
-#define PI_PDATA_A_INIT_M_BSWAP_DATA                   0x000000002
-#define PI_PDATA_A_INIT_M_BSWAP_LITERAL                        0x000000001
-
-#define PI_PDATA_A_INIT_V_DESC_BLK_ADDR                        13
-#define PI_PDATA_A_INIT_V_RESERVED                             3
-#define PI_PDATA_A_INIT_V_BSWAP_DATA                   1
-#define PI_PDATA_A_INIT_V_BSWAP_LITERAL                        0
-
-/* Port Reset Register */
-
-#define PI_RESET_M_ASSERT_RESET                        1
-
-/* Port Status register */
-
-#define PI_PSTATUS_V_RCV_DATA_PENDING  31
-#define PI_PSTATUS_V_XMT_DATA_PENDING  30
-#define PI_PSTATUS_V_SMT_HOST_PENDING  29
-#define PI_PSTATUS_V_UNSOL_PENDING             28
-#define PI_PSTATUS_V_CMD_RSP_PENDING   27
-#define PI_PSTATUS_V_CMD_REQ_PENDING   26
-#define PI_PSTATUS_V_TYPE_0_PENDING            25
-#define PI_PSTATUS_V_RESERVED_1                        16
-#define PI_PSTATUS_V_RESERVED_2                        11
-#define PI_PSTATUS_V_STATE                             8
-#define PI_PSTATUS_V_HALT_ID                   0
-
-#define PI_PSTATUS_M_RCV_DATA_PENDING  0x80000000
-#define PI_PSTATUS_M_XMT_DATA_PENDING  0x40000000
-#define PI_PSTATUS_M_SMT_HOST_PENDING  0x20000000
-#define PI_PSTATUS_M_UNSOL_PENDING             0x10000000
-#define PI_PSTATUS_M_CMD_RSP_PENDING   0x08000000
-#define PI_PSTATUS_M_CMD_REQ_PENDING   0x04000000
-#define PI_PSTATUS_M_TYPE_0_PENDING            0x02000000
-#define PI_PSTATUS_M_RESERVED_1                        0x01FF0000
-#define PI_PSTATUS_M_RESERVED_2                        0x0000F800
-#define PI_PSTATUS_M_STATE                             0x00000700
-#define PI_PSTATUS_M_HALT_ID                   0x000000FF
-
-/* Define Halt Id's                                                            */
-/*   Do not insert into this list, only append. */
-
-#define PI_HALT_ID_K_SELFTEST_TIMEOUT  0
-#define PI_HALT_ID_K_PARITY_ERROR              1
-#define PI_HALT_ID_K_HOST_DIR_HALT             2
-#define PI_HALT_ID_K_SW_FAULT                  3
-#define PI_HALT_ID_K_HW_FAULT                  4
-#define PI_HALT_ID_K_PC_TRACE                  5
-#define PI_HALT_ID_K_DMA_ERROR                 6                       /* Host Data has error reg */
-#define PI_HALT_ID_K_IMAGE_CRC_ERROR   7               /* Image is bad, update it */
-#define PI_HALT_ID_K_BUS_EXCEPTION             8               /* 68K bus exception       */
-
-/* Host Interrupt Enable Register as seen by host */
-
-#define PI_HOST_INT_M_XMT_DATA_ENB             0x80000000      /* Type 2 Enables */
-#define PI_HOST_INT_M_RCV_DATA_ENB             0x40000000
-#define PI_HOST_INT_M_SMT_HOST_ENB             0x10000000      /* Type 1 Enables */
-#define PI_HOST_INT_M_UNSOL_ENB                        0x20000000
-#define PI_HOST_INT_M_CMD_RSP_ENB              0x08000000
-#define PI_HOST_INT_M_CMD_REQ_ENB              0x04000000
-#define        PI_HOST_INT_M_TYPE_1_RESERVED   0x00FF0000
-#define        PI_HOST_INT_M_TYPE_0_RESERVED   0x0000FF00      /* Type 0 Enables */
-#define PI_HOST_INT_M_1MS                              0x00000080
-#define PI_HOST_INT_M_20MS                             0x00000040
-#define PI_HOST_INT_M_CSR_CMD_DONE             0x00000020
-#define PI_HOST_INT_M_STATE_CHANGE             0x00000010
-#define PI_HOST_INT_M_XMT_FLUSH                        0x00000008
-#define PI_HOST_INT_M_NXM                              0x00000004
-#define PI_HOST_INT_M_PM_PAR_ERR               0x00000002
-#define PI_HOST_INT_M_BUS_PAR_ERR              0x00000001
-
-#define PI_HOST_INT_V_XMT_DATA_ENB             31                      /* Type 2 Enables */
-#define PI_HOST_INT_V_RCV_DATA_ENB             30
-#define PI_HOST_INT_V_SMT_HOST_ENB             29                      /* Type 1 Enables */
-#define PI_HOST_INT_V_UNSOL_ENB                        28
-#define PI_HOST_INT_V_CMD_RSP_ENB              27
-#define PI_HOST_INT_V_CMD_REQ_ENB              26
-#define        PI_HOST_INT_V_TYPE_1_RESERVED   16
-#define        PI_HOST_INT_V_TYPE_0_RESERVED   8                       /* Type 0 Enables */
-#define PI_HOST_INT_V_1MS_ENB                  7
-#define PI_HOST_INT_V_20MS_ENB                 6
-#define PI_HOST_INT_V_CSR_CMD_DONE_ENB 5
-#define PI_HOST_INT_V_STATE_CHANGE_ENB 4
-#define PI_HOST_INT_V_XMT_FLUSH_ENB    3
-#define PI_HOST_INT_V_NXM_ENB                  2
-#define PI_HOST_INT_V_PM_PAR_ERR_ENB   1
-#define PI_HOST_INT_V_BUS_PAR_ERR_ENB  0
-
-#define PI_HOST_INT_K_ACK_ALL_TYPE_0   0x000000FF
-#define PI_HOST_INT_K_DISABLE_ALL_INTS 0x00000000
-#define PI_HOST_INT_K_ENABLE_ALL_INTS  0xFFFFFFFF
-#define PI_HOST_INT_K_ENABLE_DEF_INTS  0xC000001F
-
-/* Type 0 Interrupt Status Register */
-
-#define PI_TYPE_0_STAT_M_1MS                   0x00000080
-#define PI_TYPE_0_STAT_M_20MS                  0x00000040
-#define PI_TYPE_0_STAT_M_CSR_CMD_DONE  0x00000020
-#define PI_TYPE_0_STAT_M_STATE_CHANGE  0x00000010
-#define PI_TYPE_0_STAT_M_XMT_FLUSH             0x00000008
-#define PI_TYPE_0_STAT_M_NXM                   0x00000004
-#define PI_TYPE_0_STAT_M_PM_PAR_ERR            0x00000002
-#define PI_TYPE_0_STAT_M_BUS_PAR_ERR   0x00000001
-
-#define PI_TYPE_0_STAT_V_1MS                   7
-#define PI_TYPE_0_STAT_V_20MS                  6
-#define PI_TYPE_0_STAT_V_CSR_CMD_DONE  5
-#define PI_TYPE_0_STAT_V_STATE_CHANGE  4
-#define PI_TYPE_0_STAT_V_XMT_FLUSH             3
-#define PI_TYPE_0_STAT_V_NXM                   2
-#define PI_TYPE_0_STAT_V_PM_PAR_ERR            1
-#define PI_TYPE_0_STAT_V_BUS_PAR_ERR   0
-
-/* Register definition structures are defined for both big and little endian systems */
-
-#ifndef __BIG_ENDIAN
-
-/* Little endian format of Type 1 Producer register */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        prod;
-               PI_UINT8        comp;
-               PI_UINT8        mbz_1;
-               PI_UINT8        mbz_2;
-               } index;
-       } PI_TYPE_1_PROD_REG;
-
-/* Little endian format of Type 2 Producer register */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        rcv_prod;
-               PI_UINT8        xmt_prod;
-               PI_UINT8        rcv_comp;
-               PI_UINT8        xmt_comp;
-               } index;
-       } PI_TYPE_2_PROD_REG;
-
-/* Little endian format of Type 1 Consumer Block longword */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        cons;
-               PI_UINT8        res0;
-               PI_UINT8        res1;
-               PI_UINT8        res2;
-               } index;
-       } PI_TYPE_1_CONSUMER;
-
-/* Little endian format of Type 2 Consumer Block longword */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        rcv_cons;
-               PI_UINT8        res0;
-               PI_UINT8        xmt_cons;
-               PI_UINT8        res1;
-               } index;
-       } PI_TYPE_2_CONSUMER;
-
-/* Define swapping required by DMA transfers.  */
-#define PI_PDATA_A_INIT_M_BSWAP_INIT   \
-       (PI_PDATA_A_INIT_M_BSWAP_DATA)
-
-#else /* __BIG_ENDIAN */
-
-/* Big endian format of Type 1 Producer register */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        mbz_2;
-               PI_UINT8        mbz_1;
-               PI_UINT8        comp;
-               PI_UINT8        prod;
-               } index;
-       } PI_TYPE_1_PROD_REG;
-
-/* Big endian format of Type 2 Producer register */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        xmt_comp;
-               PI_UINT8        rcv_comp;
-               PI_UINT8        xmt_prod;
-               PI_UINT8        rcv_prod;
-               } index;
-       } PI_TYPE_2_PROD_REG;
-
-/* Big endian format of Type 1 Consumer Block longword */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        res2;
-               PI_UINT8        res1;
-               PI_UINT8        res0;
-               PI_UINT8        cons;
-               } index;
-       } PI_TYPE_1_CONSUMER;
-
-/* Big endian format of Type 2 Consumer Block longword */
-
-typedef union
-       {
-       PI_UINT32       lword;
-       struct
-               {
-               PI_UINT8        res1;
-               PI_UINT8        xmt_cons;
-               PI_UINT8        res0;
-               PI_UINT8        rcv_cons;
-               } index;
-       } PI_TYPE_2_CONSUMER;
-
-/* Define swapping required by DMA transfers.  */
-#define PI_PDATA_A_INIT_M_BSWAP_INIT   \
-       (PI_PDATA_A_INIT_M_BSWAP_DATA | PI_PDATA_A_INIT_M_BSWAP_LITERAL)
-
-#endif /* __BIG_ENDIAN */
-
-/* Define TC PDQ CSR offset and length */
-
-#define PI_TC_K_CSR_OFFSET             0x100000
-#define PI_TC_K_CSR_LEN                        0x40            /* 64 bytes */
-
-/* Define EISA controller register offsets */
-
-#define PI_ESIC_K_CSR_IO_LEN           0x80            /* 128 bytes */
-
-#define PI_DEFEA_K_BURST_HOLDOFF       0x040
-
-#define PI_ESIC_K_SLOT_ID              0xC80
-#define PI_ESIC_K_SLOT_CNTRL           0xC84
-#define PI_ESIC_K_MEM_ADD_CMP_0        0xC85
-#define PI_ESIC_K_MEM_ADD_CMP_1        0xC86
-#define PI_ESIC_K_MEM_ADD_CMP_2        0xC87
-#define PI_ESIC_K_MEM_ADD_HI_CMP_0     0xC88
-#define PI_ESIC_K_MEM_ADD_HI_CMP_1     0xC89
-#define PI_ESIC_K_MEM_ADD_HI_CMP_2     0xC8A
-#define PI_ESIC_K_MEM_ADD_MASK_0       0xC8B
-#define PI_ESIC_K_MEM_ADD_MASK_1       0xC8C
-#define PI_ESIC_K_MEM_ADD_MASK_2       0xC8D
-#define PI_ESIC_K_MEM_ADD_LO_CMP_0     0xC8E
-#define PI_ESIC_K_MEM_ADD_LO_CMP_1     0xC8F
-#define PI_ESIC_K_MEM_ADD_LO_CMP_2     0xC90
-#define PI_ESIC_K_IO_ADD_CMP_0_0       0xC91
-#define PI_ESIC_K_IO_ADD_CMP_0_1       0xC92
-#define PI_ESIC_K_IO_ADD_CMP_1_0       0xC93
-#define PI_ESIC_K_IO_ADD_CMP_1_1       0xC94
-#define PI_ESIC_K_IO_ADD_CMP_2_0       0xC95
-#define PI_ESIC_K_IO_ADD_CMP_2_1       0xC96
-#define PI_ESIC_K_IO_ADD_CMP_3_0       0xC97
-#define PI_ESIC_K_IO_ADD_CMP_3_1       0xC98
-#define PI_ESIC_K_IO_ADD_MASK_0_0      0xC99
-#define PI_ESIC_K_IO_ADD_MASK_0_1      0xC9A
-#define PI_ESIC_K_IO_ADD_MASK_1_0      0xC9B
-#define PI_ESIC_K_IO_ADD_MASK_1_1      0xC9C
-#define PI_ESIC_K_IO_ADD_MASK_2_0      0xC9D
-#define PI_ESIC_K_IO_ADD_MASK_2_1      0xC9E
-#define PI_ESIC_K_IO_ADD_MASK_3_0      0xC9F
-#define PI_ESIC_K_IO_ADD_MASK_3_1      0xCA0
-#define PI_ESIC_K_MOD_CONFIG_1         0xCA1
-#define PI_ESIC_K_MOD_CONFIG_2         0xCA2
-#define PI_ESIC_K_MOD_CONFIG_3         0xCA3
-#define PI_ESIC_K_MOD_CONFIG_4         0xCA4
-#define PI_ESIC_K_MOD_CONFIG_5         0xCA5
-#define PI_ESIC_K_MOD_CONFIG_6         0xCA6
-#define PI_ESIC_K_MOD_CONFIG_7         0xCA7
-#define PI_ESIC_K_DIP_SWITCH           0xCA8
-#define PI_ESIC_K_IO_CONFIG_STAT_0     0xCA9
-#define PI_ESIC_K_IO_CONFIG_STAT_1     0xCAA
-#define PI_ESIC_K_DMA_CONFIG           0xCAB
-#define PI_ESIC_K_INPUT_PORT           0xCAC
-#define PI_ESIC_K_OUTPUT_PORT          0xCAD
-#define PI_ESIC_K_FUNCTION_CNTRL       0xCAE
-
-/* Define the bits in the function control register. */
-
-#define PI_FUNCTION_CNTRL_M_IOCS0      0x01
-#define PI_FUNCTION_CNTRL_M_IOCS1      0x02
-#define PI_FUNCTION_CNTRL_M_IOCS2      0x04
-#define PI_FUNCTION_CNTRL_M_IOCS3      0x08
-#define PI_FUNCTION_CNTRL_M_MEMCS0     0x10
-#define PI_FUNCTION_CNTRL_M_MEMCS1     0x20
-#define PI_FUNCTION_CNTRL_M_DMA                0x80
-
-/* Define the bits in the slot control register. */
-
-#define PI_SLOT_CNTRL_M_RESET          0x04    /* Don't use.       */
-#define PI_SLOT_CNTRL_M_ERROR          0x02    /* Not implemented. */
-#define PI_SLOT_CNTRL_M_ENB            0x01    /* Must be set.     */
-
-/* Define the bits in the burst holdoff register. */
-
-#define PI_BURST_HOLDOFF_M_HOLDOFF     0xFC
-#define PI_BURST_HOLDOFF_M_RESERVED    0x02
-#define PI_BURST_HOLDOFF_M_MEM_MAP     0x01
-
-#define PI_BURST_HOLDOFF_V_HOLDOFF     2
-#define PI_BURST_HOLDOFF_V_RESERVED    1
-#define PI_BURST_HOLDOFF_V_MEM_MAP     0
-
-/* Define the implicit mask of the Memory Address Mask Register.  */
-
-#define PI_MEM_ADD_MASK_M              0x3ff
-
-/*
- * Define the fields in the IO Compare registers.
- * The driver must initialize the slot field with the slot ID shifted by the
- * amount shown below.
- */
-
-#define PI_IO_CMP_V_SLOT               4
-
-/* Define the fields in the Interrupt Channel Configuration and Status reg */
-
-#define PI_CONFIG_STAT_0_M_PEND                        0x80
-#define PI_CONFIG_STAT_0_M_RES_1               0x40
-#define PI_CONFIG_STAT_0_M_IREQ_OUT            0x20
-#define PI_CONFIG_STAT_0_M_IREQ_IN             0x10
-#define PI_CONFIG_STAT_0_M_INT_ENB             0x08
-#define PI_CONFIG_STAT_0_M_RES_0               0x04
-#define PI_CONFIG_STAT_0_M_IRQ                 0x03
-
-#define PI_CONFIG_STAT_0_V_PEND                        7
-#define PI_CONFIG_STAT_0_V_RES_1               6
-#define PI_CONFIG_STAT_0_V_IREQ_OUT            5
-#define PI_CONFIG_STAT_0_V_IREQ_IN             4
-#define PI_CONFIG_STAT_0_V_INT_ENB             3
-#define PI_CONFIG_STAT_0_V_RES_0               2
-#define PI_CONFIG_STAT_0_V_IRQ                 0
-
-#define PI_CONFIG_STAT_0_IRQ_K_9               0
-#define PI_CONFIG_STAT_0_IRQ_K_10              1
-#define PI_CONFIG_STAT_0_IRQ_K_11              2
-#define PI_CONFIG_STAT_0_IRQ_K_15              3
-
-/* Define DEC FDDIcontroller/EISA (DEFEA) EISA hardware ID's */
-
-#define DEFEA_PRODUCT_ID       0x0030A310              /* DEC product 300 (no rev)     */
-#define DEFEA_PROD_ID_1                0x0130A310              /* DEC product 300, rev 1       */
-#define DEFEA_PROD_ID_2                0x0230A310              /* DEC product 300, rev 2       */
-#define DEFEA_PROD_ID_3                0x0330A310              /* DEC product 300, rev 3       */
-#define DEFEA_PROD_ID_4                0x0430A310              /* DEC product 300, rev 4       */
-
-/**********************************************/
-/* Digital PFI Specification v1.0 Definitions */
-/**********************************************/
-
-/* PCI Configuration Space Constants */
-
-#define PFI_K_LAT_TIMER_DEF                    0x88    /* def max master latency timer */
-#define PFI_K_LAT_TIMER_MIN                    0x20    /* min max master latency timer */
-#define PFI_K_CSR_MEM_LEN                      0x80    /* 128 bytes */
-#define PFI_K_CSR_IO_LEN                       0x80    /* 128 bytes */
-#define PFI_K_PKT_MEM_LEN                      0x10000 /* 64K bytes */
-
-/* PFI Register Offsets (starting at PDQ Register Base Address) */
-
-#define PFI_K_REG_RESERVED_0            0X00000038
-#define PFI_K_REG_RESERVED_1            0X0000003C
-#define PFI_K_REG_MODE_CTRL             0X00000040
-#define PFI_K_REG_STATUS                0X00000044
-#define PFI_K_REG_FIFO_WRITE            0X00000048
-#define PFI_K_REG_FIFO_READ             0X0000004C
-
-/* PFI Mode Control Register Constants */
-
-#define PFI_MODE_M_RESERVED             0XFFFFFFF0
-#define PFI_MODE_M_TGT_ABORT_ENB        0X00000008
-#define PFI_MODE_M_PDQ_INT_ENB          0X00000004
-#define PFI_MODE_M_PFI_INT_ENB          0X00000002
-#define PFI_MODE_M_DMA_ENB              0X00000001
-
-#define PFI_MODE_V_RESERVED             4
-#define PFI_MODE_V_TGT_ABORT_ENB        3
-#define PFI_MODE_V_PDQ_INT_ENB          2
-#define PFI_MODE_V_PFI_INT_ENB          1
-#define PFI_MODE_V_DMA_ENB              0
-
-#define PFI_MODE_K_ALL_DISABLE          0X00000000
-
-/* PFI Status Register Constants */
-
-#define PFI_STATUS_M_RESERVED           0XFFFFFFC0
-#define PFI_STATUS_M_PFI_ERROR          0X00000020             /* only valid in rev 1 or later PFI */
-#define PFI_STATUS_M_PDQ_INT            0X00000010
-#define PFI_STATUS_M_PDQ_DMA_ABORT      0X00000008
-#define PFI_STATUS_M_FIFO_FULL          0X00000004
-#define PFI_STATUS_M_FIFO_EMPTY                 0X00000002
-#define PFI_STATUS_M_DMA_IN_PROGRESS    0X00000001
-
-#define PFI_STATUS_V_RESERVED           6
-#define PFI_STATUS_V_PFI_ERROR          5                      /* only valid in rev 1 or later PFI */
-#define PFI_STATUS_V_PDQ_INT            4
-#define PFI_STATUS_V_PDQ_DMA_ABORT      3
-#define PFI_STATUS_V_FIFO_FULL          2
-#define PFI_STATUS_V_FIFO_EMPTY                 1
-#define PFI_STATUS_V_DMA_IN_PROGRESS 0
-
-#define DFX_FC_PRH2_PRH1_PRH0          0x54003820      /* Packet Request Header bytes + FC */
-#define DFX_PRH0_BYTE                  0x20            /* Packet Request Header byte 0 */
-#define DFX_PRH1_BYTE                  0x38            /* Packet Request Header byte 1 */
-#define DFX_PRH2_BYTE                  0x00            /* Packet Request Header byte 2 */
-
-/* Driver routine status (return) codes */
-
-#define DFX_K_SUCCESS                  0                       /* routine succeeded */
-#define DFX_K_FAILURE                  1                       /* routine failed */
-#define DFX_K_OUTSTATE                 2                       /* bad state for command */
-#define DFX_K_HW_TIMEOUT               3                       /* command timed out */
-
-/* Define LLC host receive buffer min/max/default values */
-
-#define RCV_BUFS_MIN   2                                       /* minimum pre-allocated receive buffers */
-#define RCV_BUFS_MAX   32                                      /* maximum pre-allocated receive buffers */
-#define RCV_BUFS_DEF   8                                       /* default pre-allocated receive buffers */
-
-/* Define offsets into FDDI LLC or SMT receive frame buffers - used when indicating frames */
-
-#define RCV_BUFF_K_DESCR       0                               /* four byte FMC descriptor */
-#define RCV_BUFF_K_PADDING     4                               /* three null bytes */
-#define RCV_BUFF_K_FC          7                               /* one byte frame control */
-#define RCV_BUFF_K_DA          8                               /* six byte destination address */
-#define RCV_BUFF_K_SA          14                              /* six byte source address */
-#define RCV_BUFF_K_DATA                20                              /* offset to start of packet data */
-
-/* Define offsets into FDDI LLC transmit frame buffers - used when sending frames */
-
-#define XMT_BUFF_K_FC          0                               /* one byte frame control */
-#define XMT_BUFF_K_DA          1                               /* six byte destination address */
-#define XMT_BUFF_K_SA          7                               /* six byte source address */
-#define XMT_BUFF_K_DATA                13                              /* offset to start of packet data */
-
-/* Macro for checking a "value" is within a specific range */
-
-#define IN_RANGE(value,low,high) ((value >= low) && (value <= high))
-
-/* Only execute special print call when debug driver was built */
-
-#ifdef DEFXX_DEBUG
-#define DBG_printk(args...) printk(## args)
-#else
-#define DBG_printk(args...)
-#endif
-
-/* Define constants for masking/unmasking interrupts */
-
-#define DFX_MASK_INTERRUPTS            1
-#define DFX_UNMASK_INTERRUPTS          0
-
-/* Define structure for driver transmit descriptor block */
-
-typedef struct
-       {
-       struct sk_buff  *p_skb;                                 /* ptr to skb */
-       } XMT_DRIVER_DESCR;
-
-typedef struct DFX_board_tag
-       {
-       /* Keep virtual and physical pointers to locked, physically contiguous memory */
-
-       char                            *kmalloced;                                     /* pci_free_consistent this on unload */
-       dma_addr_t                      kmalloced_dma;
-       /* DMA handle for the above */
-       PI_DESCR_BLOCK                  *descr_block_virt;                              /* PDQ descriptor block virt address */
-       dma_addr_t                      descr_block_phys;                               /* PDQ descriptor block phys address */
-       PI_DMA_CMD_REQ                  *cmd_req_virt;                                  /* Command request buffer virt address */
-       dma_addr_t                      cmd_req_phys;                                   /* Command request buffer phys address */
-       PI_DMA_CMD_RSP                  *cmd_rsp_virt;                                  /* Command response buffer virt address */
-       dma_addr_t                      cmd_rsp_phys;                                   /* Command response buffer phys address */
-       char                            *rcv_block_virt;                                /* LLC host receive queue buf blk virt */
-       dma_addr_t                      rcv_block_phys;                                 /* LLC host receive queue buf blk phys */
-       PI_CONSUMER_BLOCK               *cons_block_virt;                               /* PDQ consumer block virt address */
-       dma_addr_t                      cons_block_phys;                                /* PDQ consumer block phys address */
-
-       /* Keep local copies of Type 1 and Type 2 register data */
-
-       PI_TYPE_1_PROD_REG              cmd_req_reg;                                    /* Command Request register */
-       PI_TYPE_1_PROD_REG              cmd_rsp_reg;                                    /* Command Response register */
-       PI_TYPE_2_PROD_REG              rcv_xmt_reg;                                    /* Type 2 (RCV/XMT) register */
-
-       /* Storage for unicast and multicast address entries in adapter CAM */
-
-       u8                              uc_table[1*FDDI_K_ALEN];
-       u32                             uc_count;                                               /* number of unicast addresses */
-       u8                              mc_table[PI_CMD_ADDR_FILTER_K_SIZE*FDDI_K_ALEN];
-       u32                             mc_count;                                               /* number of multicast addresses */
-
-       /* Current packet filter settings */
-
-       u32                             ind_group_prom;                                 /* LLC individual & group frame prom mode */
-       u32                             group_prom;                                     /* LLC group (multicast) frame prom mode */
-
-       /* Link available flag needed to determine whether to drop outgoing packet requests */
-
-       u32                             link_available;                                 /* is link available? */
-
-       /* Resources to indicate reset type when resetting adapter */
-
-       u32                             reset_type;                                     /* skip or rerun diagnostics */
-
-       /* Store pointers to receive buffers for queue processing code */
-
-       char                            *p_rcv_buff_va[PI_RCV_DATA_K_NUM_ENTRIES];
-
-       /* Store pointers to transmit buffers for transmit completion code */
-
-       XMT_DRIVER_DESCR                xmt_drv_descr_blk[PI_XMT_DATA_K_NUM_ENTRIES];
-
-       /* Transmit spinlocks */
-
-       spinlock_t                      lock;
-
-       /* Store device, bus-specific, and parameter information for this adapter */
-
-       struct net_device               *dev;                                           /* pointer to device structure */
-       union {
-               void __iomem *mem;
-               int port;
-       } base;                                                                         /* base address */
-       struct device                   *bus_dev;
-       u32                             full_duplex_enb;                                /* FDDI Full Duplex enable (1 == on, 2 == off) */
-       u32                             req_ttrt;                                       /* requested TTRT value (in 80ns units) */
-       u32                             burst_size;                                     /* adapter burst size (enumerated) */
-       u32                             rcv_bufs_to_post;                               /* receive buffers to post for LLC host queue */
-       u8                              factory_mac_addr[FDDI_K_ALEN];                  /* factory (on-board) MAC address */
-
-       /* Common FDDI statistics structure and private counters */
-
-       struct fddi_statistics  stats;
-
-       u32                             rcv_discards;
-       u32                             rcv_crc_errors;
-       u32                             rcv_frame_status_errors;
-       u32                             rcv_length_errors;
-       u32                             rcv_total_frames;
-       u32                             rcv_multicast_frames;
-       u32                             rcv_total_bytes;
-
-       u32                             xmt_discards;
-       u32                             xmt_length_errors;
-       u32                             xmt_total_frames;
-       u32                             xmt_total_bytes;
-       } DFX_board_t;
-
-#endif /* #ifndef _DEFXX_H_ */
index 65cc129da1146229fd4a76d2ef8d7704c5f5d656..a439cbdda3b9bc3db0361358283e2c3ac5cdcb53 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_3COM
        bool "3Com devices"
+       default y
        depends on ISA || EISA || MCA || PCI || PCMCIA
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 5d2169809b19e03c4f69bb98640caa01e8bddb9b..e04ade444247491c1f882c183d8e2001af8a0af4 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_8390
        bool "National Semi-conductor 8390 devices"
+       default y
        depends on NET_VENDOR_NATSEMI && (AMIGA_PCMCIA || PCI || SUPERH || \
                   ISA || MCA || EISA || MAC || M32R || MACH_TX49XX || \
                   MCA_LEGACY || H8300 || ARM || MIPS || ZORRO || PCMCIA || \
index 5e9dbe9817fdfaa106d5d9ef7866c1084ca2c3fe..5c804bbe3dabdeebc6dc16870e5f0b3177ed8246 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_ADAPTEC
        bool "Adaptec devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 68862e4d145c006260280885b4df23b216d3d440..799a8528207043b4fa454aec3621f0450b753666 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_ALTEON
        bool "Alteon devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 05139403ea8d04461e742fdbab01224889d15525..8af1c934dbd58b375cbef687dbd494e335f1da75 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_AMD
        bool "AMD devices"
+       default y
        depends on DIO || MACH_DECSTATION || MVME147 || ATARI || SUN3 || \
                   SUN3X || SBUS || PCI || ZORRO || (ISA && ISA_DMA_API) || \
                   (ARM && ARCH_EBSA110) || ISA || EISA || MCA || PCMCIA
index fc796bc353d08e2dd2c1c0550532c91124819587..59d5c2630acb850ef6c126e408114385f622a139 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_APPLE
        bool "Apple devices"
+       default y
        depends on (PPC_PMAC && PPC32) || MAC || ISA || EISA || MACH_IXDP2351 \
                   || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
        ---help---
index 966c6c7ea09c22842f6dd8d81dc6ab49123d4d82..26ab8cae28b5c02f5b4db9517b292126a7b8ecc0 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_ATHEROS
        bool "Atheros devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 8986e57d7f9c25c6fb45cabcfae3f1fcf41bfa0a..d82ad221ebd45366d9e08dfef9a464cfe9e63bf6 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_BROADCOM
        bool "Broadcom devices"
+       default y
        depends on (SSB_POSSIBLE && HAS_DMA) || PCI || BCM63XX || \
                   SIBYTE_SB1xxx_SOC
        ---help---
index 03f0b17b87c396ef6a3e70098c87619719bcc6e6..2641557788575e6fec7ed26a2161e35a5eedf9ab 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_BROCADE
        bool "Brocade devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 7b54574107ce4945317aed05913030f4c57b4e6f..2de50f95798f266213b9c9a150145929f509fc16 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_CHELSIO
        bool "Chelsio devices"
+       default y
        depends on PCI || INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 53ebe78991747907028c48278576ca570036a7de..e0cacf662914f552de27059a8ddb8f1bb436a6c9 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_CIRRUS
        bool "Cirrus devices"
+       default y
        depends on ARM && ARCH_EP93XX
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index bbd5348806709a435c7e861542d066f98af68cbf..94606f7ee13ae2e969c9c91fccce118d908f6b02 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_CISCO
        bool "Cisco devices"
+       default y
        depends on PCI && INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 40e8df9fde8d5d2f7094f49066c091dd00e800d5..37940279ded82e7ace413b06c62068de8ea7dd48 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_DEC
        bool "Digital Equipment devices"
+       default y
        depends on PCI || EISA || CARDBUS
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 9fdb66b66f15dd8360b56424494f56b950f1fa8f..84a28a6681627648337e968c531fd3e476cb1151 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_DLINK
        bool "D-Link devices"
+       default y
        depends on PCI || PARPORT
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 018ac94fb8244c67989429fde7549e2cd6bc4ccf..7a28a643394414a40eb3d3493eb7ffcea188f7cc 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_EMULEX
        bool "Emulex devices"
+       default y
        depends on PCI && INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index b0d76f01d47b7f6aafb86b32c238a2e07040f4b2..5918c68916946acc9cf14202b0e28d823a7515c3 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_FARADAY
        bool "Faraday devices"
+       default y
        depends on ARM
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 2fd2c614c08ba48c65a7d0f6ffc6ce74582f43d4..4dbe41f1cbc6b1fa13eb12fa9357a748c5610edb 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_FREESCALE
        bool "Freescale devices"
+       default y
        depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
                   M523x || M527x || M5272 || M528x || M520x || M532x || \
                   IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC || \
index 2cd968edb7330a1f07275364cd17bdd3e5b89505..dffee9d44fd55ee13f2ba226c016f8b592eaac12 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_FUJITSU
        bool "Fujitsu devices"
+       default y
        depends on ISA || PCMCIA || ((ISA || MCA_LEGACY) && EXPERIMENTAL)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 07b42e96314340825f021a4a668f7b902198d5f7..a0b8ece1e3bcbfcd2755d2f0b3fb91f2e791a6d7 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_HP
        bool "HP devices"
+       default y
        depends on ISA || EISA || PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 5c30a5b3cba9887cf7bf83b7e03387d3fd213298..2be46986cbe21399398e8130854e868f02f7f55f 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_I825XX
        bool "Intel (82586/82593/82596) devices"
+       default y
        depends on NET_VENDOR_INTEL && (ISA || ISA_DMA_API || ARM || \
                   ARCH_ACORN || MCA || MCA_LEGACY || SNI_RM || SUN3 || \
                   GSC || BVME6000 || MVME16x || EXPERIMENTAL)
index 4c7ef980f1c69eb783d31f7def960cb1affd2f03..9e16f3fa97b2c7ec918347de09887f4d04ad18d3 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_IBM
        bool "IBM devices"
+       default y
        depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
                   (IBMEBUS && INET && SPARSEMEM)
        ---help---
index 5fe185ba07bc38349812bc51ebcc747371cc47a1..4a98e83812b75c83c6150c20181af9dc9cfe1381 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_INTEL
        bool "Intel devices"
+       default y
        depends on PCI || PCI_MSI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index e525408367b6363db12863d4983b49439738c451..0029934748bc26c9e820ca2bd707b56b5c82672a 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_MARVELL
        bool "Marvell devices"
+       default y
        depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index e06949127b1f077e24190600661385f456c044e0..d8099a7903d3d7bd2fbb5fd627bf822016cc09f4 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_MELLANOX
        bool "Mellanox devices"
+       default y
        depends on PCI && INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 4227de6d11f263d718ade45c898afd408c3ccf56..bd090dbe3ad6fc6d86aa76e720764f5ee782a51c 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_MICREL
        bool "Micrel devices"
+       default y
        depends on (HAS_IOMEM && DMA_ENGINE) || SPI || PCI || HAS_IOMEM || \
                   (ARM && ARCH_KS8695)
        ---help---
index 53b0b04935a38ea5569b2c55fe6ac7760d86e1ad..8163fd0f453f3aa03e9ff1c8b368cc2d366f6ef2 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_MICROCHIP
        bool "Microchip devices"
+       default y
        depends on SPI && EXPERIMENTAL
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 1816ae12ce07e5a3a90980dbf9714b9172013dde..540f0c6fc160d5d1dc4074e2142c1ea8417f7a4e 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_MYRI
        bool "Myricom devices"
+       default y
        depends on PCI && INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say
index 1e5c1e1ec79ace989c7e9a3e5934e85269e0e94e..4a6b9fd073b6330f5d2b693c322c0c5ea2bd5c29 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_NATSEMI
        bool "National Semi-conductor devices"
+       default y
        depends on MCA || MAC || MACH_JAZZ || PCI || XTENSA_PLATFORM_XT2000
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 3d98e62c24126a871110df69cf3beaadc8c5b008..ff26b54bd3fbb79f2220ebd8799f5819f73baba1 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_EXAR
        bool "Exar devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say
index 3b91c3be62709fd219749dccdaf26ba381e4ff0b..01182b559473cc4812909bccdcbf78cb81de08ce 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_NUVOTON
        bool "Nuvoton devices"
+       default y
        depends on ARM && ARCH_W90X900
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 0a18e731419560802ec3c3a1010e1cc2df55d41c..ace19e7f6d132354e74bca86b8ea8d9d2315ec9a 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_NVIDIA
        bool "NVIDIA devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 97f5e72f0ec76a886c74dc58dad3cfa223d2bfb5..ecd45f9ea9d9507826eae8ad9b4c34e5330e6360 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_OKI
        bool "OKI Semiconductor devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index ccb79b8069adf790bde9e16366d4659370dc0e1c..01e6c329d78cd657b29f91d0dc8b72cbe9558cf1 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_PASEMI
        bool "PA Semi devices"
+       default y
        depends on PPC_PASEMI && PCI && INET
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index a7c4424011ec10ec7894b6e2f1a100dc22e80530..a8669adecc9708b633d1347b9b22798175a7a261 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_QLOGIC
        bool "QLogic devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 45d493036cece768b7355d79aabf2424378a58dc..01969e0a9c68d92f1f3a2a9dc57e8b7fb086e9a2 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_RACAL
        bool "Racal-Interlan (Micom) NI devices"
+       default y
        depends on ISA
        ---help---
          If you have a network (Ethernet) card belonging to this class, such
index b15ebac75f518871e1506dc02f33df077fb6884b..2055f7eb2ba94f6855a37bf8a613dd77e75a757e 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_RDC
        bool "RDC devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index a5f67a091c4dbacb25e5ed0f7c14a75c04d69758..d8df67ac51b9d8bf3eb99f64f96c39e12d3952d8 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_REALTEK
        bool "Realtek devices"
+       default y
        depends on PCI || (PARPORT && X86)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 02667915b34a853ea662aae596c4849802be4078..49b6d5b1dfd2812745b55cc212717836cc783fbc 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_SEEQ
        bool "SEEQ devices"
+       default y
        depends on (ARM && ARCH_ACORN) || SGI_HAS_SEEQ || EXPERIMENTAL
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 3098594ab2742409eea6b7f350808aaddf381e69..e832f46660c9edab927d7d335cd6be6a6ff7d989 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_SGI
        bool "SGI devices"
+       default y
        depends on (PCI && SGI_IP27) || SGI_IP32
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 01d43e870eeb805733489dcfac06de3f9d5df9ba..68d052b09af1e1ee9950f3b2e0944aca7a8e86c3 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_SIS
        bool "Silicon Integrated Systems (SiS) devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 702efe686c482c181bf9f9244104f7b49727a862..f9619285b5ef20a88d54431da5434b3edf2fc893 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_SMSC
        bool "SMC (SMSC)/Western Digital devices"
+       default y
        depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \
                BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA
        ---help---
index e40df64338601edb485e5f108576b53f32b106fc..f4a80da0065009e81b745d701715769fbaa32752 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_STMICRO
        bool "STMicroelectronics devices"
+       default y
        depends on HAS_IOMEM
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 5132fa69047a3d29327fca2975054bdea8aaf9ee..57bfd859967940daca36b7ebd80d517ddd3a51e1 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_SUN
        bool "Sun devices"
+       default y
        depends on SUN3 || SBUS || PCI || SUN_LDOMS
        ---help---
          If you have a network (Ethernet) card belonging to this class, say
index 914ad4059eae46db6c9974077b6e9fb135cffef2..1fc027eda33ea3b521abc150534fad0a6d00a12a 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_TEHUTI
        bool "Tehuti devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 1284319ba7e05a31376fc4fb3355145489c1f039..de76c70ec8fb55ba960e9e87fb6fc70d99cacb5f 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_TI
        bool "Texas Instruments (TI) devices"
+       default y
        depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 6ef2ce2c0ea7e3d9bde6685244d7cf07450f560d..0517647045594c087b54070f2afaffc1f8e4be97 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_TOSHIBA
        bool "Toshiba devices"
+       default y
        depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) || PPC_PS3
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 03925d1aecb26ab33404f228d62927d432d6e2f5..cf7d69b62c42cc6bac1b40765c2ea88e8840eb50 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_TUNDRA
        bool "Tundra devices"
+       default y
        depends on TSI108_BRIDGE
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 7199194fa89824363c93967ef4a1ccb8073d0d7e..e5d82a53ea57af5ac68e1ac42a67cf54e02eec72 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_VIA
        bool "VIA devices"
+       default y
        depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 4e3aad401cd8ddad80afba3a5599b3434bfaa15c..d5a826063a82613dc3f96ca7e989d7727f36228b 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_XILINX
        bool "Xilinx devices"
+       default y
        depends on PPC || PPC32 || MICROBLAZE
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 3d64e58e3f8bdfd71a20c6cd55cae979f7971f05..69f56a6de821626137b59141661d25212ee53280 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_XIRCOM
        bool "Xircom devices"
+       default y
        depends on PCMCIA
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
index 6bbcc54d6ce7241bba1277c85c97ce0db54ec1e2..cf67352cea14cfe2392de7b7cfa3139537a5c0a2 100644 (file)
@@ -4,6 +4,7 @@
 
 config NET_VENDOR_XSCALE
        bool "Intel XScale IXP devices"
+       default y
        depends on NET_VENDOR_INTEL && ((ARM && ARCH_IXP4XX && \
                   IXP4XX_NPE && IXP4XX_QMGR) || ARCH_ENP2611)
        ---help---
diff --git a/drivers/net/fddi/Kconfig b/drivers/net/fddi/Kconfig
new file mode 100644 (file)
index 0000000..3a424c8
--- /dev/null
@@ -0,0 +1,77 @@
+#
+# FDDI network device configuration
+#
+
+config FDDI
+       tristate "FDDI driver support"
+       depends on PCI || EISA || TC
+       ---help---
+         Fiber Distributed Data Interface is a high speed local area network
+         design; essentially a replacement for high speed Ethernet. FDDI can
+         run over copper or fiber. If you are connected to such a network and
+         want a driver for the FDDI card in your computer, say Y here (and
+         then also Y to the driver for your FDDI card, below). Most people
+         will say N.
+
+if FDDI
+
+config DEFXX
+       tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
+       depends on FDDI && (PCI || EISA || TC)
+       ---help---
+         This is support for the DIGITAL series of TURBOchannel (DEFTA),
+         EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
+         to a local FDDI network.
+
+         To compile this driver as a module, choose M here: the module
+         will be called defxx.  If unsure, say N.
+
+config DEFXX_MMIO
+       bool
+       prompt "Use MMIO instead of PIO" if PCI || EISA
+       depends on DEFXX
+       default n if PCI || EISA
+       default y
+       ---help---
+         This instructs the driver to use EISA or PCI memory-mapped I/O
+         (MMIO) as appropriate instead of programmed I/O ports (PIO).
+         Enabling this gives an improvement in processing time in parts
+         of the driver, but it may cause problems with EISA (DEFEA)
+         adapters.  TURBOchannel does not have the concept of I/O ports,
+         so MMIO is always used for these (DEFTA) adapters.
+
+         If unsure, say N.
+
+config SKFP
+       tristate "SysKonnect FDDI PCI support"
+       depends on FDDI && PCI
+       select BITREVERSE
+       ---help---
+         Say Y here if you have a SysKonnect FDDI PCI adapter.
+         The following adapters are supported by this driver:
+         - SK-5521 (SK-NET FDDI-UP)
+         - SK-5522 (SK-NET FDDI-UP DAS)
+         - SK-5541 (SK-NET FDDI-FP)
+         - SK-5543 (SK-NET FDDI-LP)
+         - SK-5544 (SK-NET FDDI-LP DAS)
+         - SK-5821 (SK-NET FDDI-UP64)
+         - SK-5822 (SK-NET FDDI-UP64 DAS)
+         - SK-5841 (SK-NET FDDI-FP64)
+         - SK-5843 (SK-NET FDDI-LP64)
+         - SK-5844 (SK-NET FDDI-LP64 DAS)
+         - Netelligent 100 FDDI DAS Fibre SC
+         - Netelligent 100 FDDI SAS Fibre SC
+         - Netelligent 100 FDDI DAS UTP
+         - Netelligent 100 FDDI SAS UTP
+         - Netelligent 100 FDDI SAS Fibre MIC
+
+         Read <file:Documentation/networking/skfp.txt> for information about
+         the driver.
+
+         Questions concerning this driver can be addressed to:
+         <linux@syskonnect.de>
+
+         To compile this driver as a module, choose M here: the module
+         will be called skfp.  This is recommended.
+
+endif # FDDI
diff --git a/drivers/net/fddi/Makefile b/drivers/net/fddi/Makefile
new file mode 100644 (file)
index 0000000..36da19c
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the Linux FDDI network device drivers.
+#
+
+obj-$(CONFIG_DEFXX) += defxx.o
+obj-$(CONFIG_SKFP) += skfp/
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
new file mode 100644 (file)
index 0000000..4ad80f7
--- /dev/null
@@ -0,0 +1,3739 @@
+/*
+ * File Name:
+ *   defxx.c
+ *
+ * Copyright Information:
+ *   Copyright Digital Equipment Corporation 1996.
+ *
+ *   This software may be used and distributed according to the terms of
+ *   the GNU General Public License, incorporated herein by reference.
+ *
+ * Abstract:
+ *   A Linux device driver supporting the Digital Equipment Corporation
+ *   FDDI TURBOchannel, EISA and PCI controller families.  Supported
+ *   adapters include:
+ *
+ *             DEC FDDIcontroller/TURBOchannel (DEFTA)
+ *             DEC FDDIcontroller/EISA         (DEFEA)
+ *             DEC FDDIcontroller/PCI          (DEFPA)
+ *
+ * The original author:
+ *   LVS       Lawrence V. Stefani <lstefani@yahoo.com>
+ *
+ * Maintainers:
+ *   macro     Maciej W. Rozycki <macro@linux-mips.org>
+ *
+ * Credits:
+ *   I'd like to thank Patricia Cross for helping me get started with
+ *   Linux, David Davies for a lot of help upgrading and configuring
+ *   my development system and for answering many OS and driver
+ *   development questions, and Alan Cox for recommendations and
+ *   integration help on getting FDDI support into Linux.  LVS
+ *
+ * Driver Architecture:
+ *   The driver architecture is largely based on previous driver work
+ *   for other operating systems.  The upper edge interface and
+ *   functions were largely taken from existing Linux device drivers
+ *   such as David Davies' DE4X5.C driver and Donald Becker's TULIP.C
+ *   driver.
+ *
+ *   Adapter Probe -
+ *             The driver scans for supported EISA adapters by reading the
+ *             SLOT ID register for each EISA slot and making a match
+ *             against the expected value.
+ *
+ *   Bus-Specific Initialization -
+ *             This driver currently supports both EISA and PCI controller
+ *             families.  While the custom DMA chip and FDDI logic is similar
+ *             or identical, the bus logic is very different.  After
+ *             initialization, the     only bus-specific differences is in how the
+ *             driver enables and disables interrupts.  Other than that, the
+ *             run-time critical code behaves the same on both families.
+ *             It's important to note that both adapter families are configured
+ *             to I/O map, rather than memory map, the adapter registers.
+ *
+ *   Driver Open/Close -
+ *             In the driver open routine, the driver ISR (interrupt service
+ *             routine) is registered and the adapter is brought to an
+ *             operational state.  In the driver close routine, the opposite
+ *             occurs; the driver ISR is deregistered and the adapter is
+ *             brought to a safe, but closed state.  Users may use consecutive
+ *             commands to bring the adapter up and down as in the following
+ *             example:
+ *                                     ifconfig fddi0 up
+ *                                     ifconfig fddi0 down
+ *                                     ifconfig fddi0 up
+ *
+ *   Driver Shutdown -
+ *             Apparently, there is no shutdown or halt routine support under
+ *             Linux.  This routine would be called during "reboot" or
+ *             "shutdown" to allow the driver to place the adapter in a safe
+ *             state before a warm reboot occurs.  To be really safe, the user
+ *             should close the adapter before shutdown (eg. ifconfig fddi0 down)
+ *             to ensure that the adapter DMA engine is taken off-line.  However,
+ *             the current driver code anticipates this problem and always issues
+ *             a soft reset of the adapter     at the beginning of driver initialization.
+ *             A future driver enhancement in this area may occur in 2.1.X where
+ *             Alan indicated that a shutdown handler may be implemented.
+ *
+ *   Interrupt Service Routine -
+ *             The driver supports shared interrupts, so the ISR is registered for
+ *             each board with the appropriate flag and the pointer to that board's
+ *             device structure.  This provides the context during interrupt
+ *             processing to support shared interrupts and multiple boards.
+ *
+ *             Interrupt enabling/disabling can occur at many levels.  At the host
+ *             end, you can disable system interrupts, or disable interrupts at the
+ *             PIC (on Intel systems).  Across the bus, both EISA and PCI adapters
+ *             have a bus-logic chip interrupt enable/disable as well as a DMA
+ *             controller interrupt enable/disable.
+ *
+ *             The driver currently enables and disables adapter interrupts at the
+ *             bus-logic chip and assumes that Linux will take care of clearing or
+ *             acknowledging any host-based interrupt chips.
+ *
+ *   Control Functions -
+ *             Control functions are those used to support functions such as adding
+ *             or deleting multicast addresses, enabling or disabling packet
+ *             reception filters, or other custom/proprietary commands.  Presently,
+ *             the driver supports the "get statistics", "set multicast list", and
+ *             "set mac address" functions defined by Linux.  A list of possible
+ *             enhancements include:
+ *
+ *                             - Custom ioctl interface for executing port interface commands
+ *                             - Custom ioctl interface for adding unicast addresses to
+ *                               adapter CAM (to support bridge functions).
+ *                             - Custom ioctl interface for supporting firmware upgrades.
+ *
+ *   Hardware (port interface) Support Routines -
+ *             The driver function names that start with "dfx_hw_" represent
+ *             low-level port interface routines that are called frequently.  They
+ *             include issuing a DMA or port control command to the adapter,
+ *             resetting the adapter, or reading the adapter state.  Since the
+ *             driver initialization and run-time code must make calls into the
+ *             port interface, these routines were written to be as generic and
+ *             usable as possible.
+ *
+ *   Receive Path -
+ *             The adapter DMA engine supports a 256 entry receive descriptor block
+ *             of which up to 255 entries can be used at any given time.  The
+ *             architecture is a standard producer, consumer, completion model in
+ *             which the driver "produces" receive buffers to the adapter, the
+ *             adapter "consumes" the receive buffers by DMAing incoming packet data,
+ *             and the driver "completes" the receive buffers by servicing the
+ *             incoming packet, then "produces" a new buffer and starts the cycle
+ *             again.  Receive buffers can be fragmented in up to 16 fragments
+ *             (descriptor     entries).  For simplicity, this driver posts
+ *             single-fragment receive buffers of 4608 bytes, then allocates a
+ *             sk_buff, copies the data, then reposts the buffer.  To reduce CPU
+ *             utilization, a better approach would be to pass up the receive
+ *             buffer (no extra copy) then allocate and post a replacement buffer.
+ *             This is a performance enhancement that should be looked into at
+ *             some point.
+ *
+ *   Transmit Path -
+ *             Like the receive path, the adapter DMA engine supports a 256 entry
+ *             transmit descriptor block of which up to 255 entries can be used at
+ *             any     given time.  Transmit buffers can be fragmented in up to 255
+ *             fragments (descriptor entries).  This driver always posts one
+ *             fragment per transmit packet request.
+ *
+ *             The fragment contains the entire packet from FC to end of data.
+ *             Before posting the buffer to the adapter, the driver sets a three-byte
+ *             packet request header (PRH) which is required by the Motorola MAC chip
+ *             used on the adapters.  The PRH tells the MAC the type of token to
+ *             receive/send, whether or not to generate and append the CRC, whether
+ *             synchronous or asynchronous framing is used, etc.  Since the PRH
+ *             definition is not necessarily consistent across all FDDI chipsets,
+ *             the driver, rather than the common FDDI packet handler routines,
+ *             sets these bytes.
+ *
+ *             To reduce the amount of descriptor fetches needed per transmit request,
+ *             the driver takes advantage of the fact that there are at least three
+ *             bytes available before the skb->data field on the outgoing transmit
+ *             request.  This is guaranteed by having fddi_setup() in net_init.c set
+ *             dev->hard_header_len to 24 bytes.  21 bytes accounts for the largest
+ *             header in an 802.2 SNAP frame.  The other 3 bytes are the extra "pad"
+ *             bytes which we'll use to store the PRH.
+ *
+ *             There's a subtle advantage to adding these pad bytes to the
+ *             hard_header_len, it ensures that the data portion of the packet for
+ *             an 802.2 SNAP frame is longword aligned.  Other FDDI driver
+ *             implementations may not need the extra padding and can start copying
+ *             or DMAing directly from the FC byte which starts at skb->data.  Should
+ *             another driver implementation need ADDITIONAL padding, the net_init.c
+ *             module should be updated and dev->hard_header_len should be increased.
+ *             NOTE: To maintain the alignment on the data portion of the packet,
+ *             dev->hard_header_len should always be evenly divisible by 4 and at
+ *             least 24 bytes in size.
+ *
+ * Modification History:
+ *             Date            Name    Description
+ *             16-Aug-96       LVS             Created.
+ *             20-Aug-96       LVS             Updated dfx_probe so that version information
+ *                                                     string is only displayed if 1 or more cards are
+ *                                                     found.  Changed dfx_rcv_queue_process to copy
+ *                                                     3 NULL bytes before FC to ensure that data is
+ *                                                     longword aligned in receive buffer.
+ *             09-Sep-96       LVS             Updated dfx_ctl_set_multicast_list to enable
+ *                                                     LLC group promiscuous mode if multicast list
+ *                                                     is too large.  LLC individual/group promiscuous
+ *                                                     mode is now disabled if IFF_PROMISC flag not set.
+ *                                                     dfx_xmt_queue_pkt no longer checks for NULL skb
+ *                                                     on Alan Cox recommendation.  Added node address
+ *                                                     override support.
+ *             12-Sep-96       LVS             Reset current address to factory address during
+ *                                                     device open.  Updated transmit path to post a
+ *                                                     single fragment which includes PRH->end of data.
+ *             Mar 2000        AC              Did various cleanups for 2.3.x
+ *             Jun 2000        jgarzik         PCI and resource alloc cleanups
+ *             Jul 2000        tjeerd          Much cleanup and some bug fixes
+ *             Sep 2000        tjeerd          Fix leak on unload, cosmetic code cleanup
+ *             Feb 2001                        Skb allocation fixes
+ *             Feb 2001        davej           PCI enable cleanups.
+ *             04 Aug 2003     macro           Converted to the DMA API.
+ *             14 Aug 2004     macro           Fix device names reported.
+ *             14 Jun 2005     macro           Use irqreturn_t.
+ *             23 Oct 2006     macro           Big-endian host support.
+ *             14 Dec 2006     macro           TURBOchannel support.
+ */
+
+/* Include files */
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/eisa.h>
+#include <linux/errno.h>
+#include <linux/fddidevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tc.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include "defxx.h"
+
+/* Version information string should be updated prior to each new release!  */
+#define DRV_NAME "defxx"
+#define DRV_VERSION "v1.10"
+#define DRV_RELDATE "2006/12/14"
+
+static char version[] __devinitdata =
+       DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
+       "  Lawrence V. Stefani and others\n";
+
+#define DYNAMIC_BUFFERS 1
+
+#define SKBUFF_RX_COPYBREAK 200
+/*
+ * NEW_SKB_SIZE = PI_RCV_DATA_K_SIZE_MAX+128 to allow 128 byte
+ * alignment for compatibility with old EISA boards.
+ */
+#define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)
+
+#ifdef CONFIG_PCI
+#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type)
+#else
+#define DFX_BUS_PCI(dev) 0
+#endif
+
+#ifdef CONFIG_EISA
+#define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type)
+#else
+#define DFX_BUS_EISA(dev) 0
+#endif
+
+#ifdef CONFIG_TC
+#define DFX_BUS_TC(dev) (dev->bus == &tc_bus_type)
+#else
+#define DFX_BUS_TC(dev) 0
+#endif
+
+#ifdef CONFIG_DEFXX_MMIO
+#define DFX_MMIO 1
+#else
+#define DFX_MMIO 0
+#endif
+
+/* Define module-wide (static) routines */
+
+static void            dfx_bus_init(struct net_device *dev);
+static void            dfx_bus_uninit(struct net_device *dev);
+static void            dfx_bus_config_check(DFX_board_t *bp);
+
+static int             dfx_driver_init(struct net_device *dev,
+                                       const char *print_name,
+                                       resource_size_t bar_start);
+static int             dfx_adap_init(DFX_board_t *bp, int get_buffers);
+
+static int             dfx_open(struct net_device *dev);
+static int             dfx_close(struct net_device *dev);
+
+static void            dfx_int_pr_halt_id(DFX_board_t *bp);
+static void            dfx_int_type_0_process(DFX_board_t *bp);
+static void            dfx_int_common(struct net_device *dev);
+static irqreturn_t     dfx_interrupt(int irq, void *dev_id);
+
+static struct          net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
+static void            dfx_ctl_set_multicast_list(struct net_device *dev);
+static int             dfx_ctl_set_mac_address(struct net_device *dev, void *addr);
+static int             dfx_ctl_update_cam(DFX_board_t *bp);
+static int             dfx_ctl_update_filters(DFX_board_t *bp);
+
+static int             dfx_hw_dma_cmd_req(DFX_board_t *bp);
+static int             dfx_hw_port_ctrl_req(DFX_board_t *bp, PI_UINT32 command, PI_UINT32 data_a, PI_UINT32 data_b, PI_UINT32 *host_data);
+static void            dfx_hw_adap_reset(DFX_board_t *bp, PI_UINT32 type);
+static int             dfx_hw_adap_state_rd(DFX_board_t *bp);
+static int             dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type);
+
+static int             dfx_rcv_init(DFX_board_t *bp, int get_buffers);
+static void            dfx_rcv_queue_process(DFX_board_t *bp);
+static void            dfx_rcv_flush(DFX_board_t *bp);
+
+static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
+                                    struct net_device *dev);
+static int             dfx_xmt_done(DFX_board_t *bp);
+static void            dfx_xmt_flush(DFX_board_t *bp);
+
+/* Define module-wide (static) variables */
+
+static struct pci_driver dfx_pci_driver;
+static struct eisa_driver dfx_eisa_driver;
+static struct tc_driver dfx_tc_driver;
+
+
+/*
+ * =======================
+ * = dfx_port_write_long =
+ * = dfx_port_read_long  =
+ * =======================
+ *
+ * Overview:
+ *   Routines for reading and writing values from/to adapter
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp                - pointer to board information
+ *   offset    - register offset from base I/O address
+ *   data      - for dfx_port_write_long, this is a value to write;
+ *               for dfx_port_read_long, this is a pointer to store
+ *               the read value
+ *
+ * Functional Description:
+ *   These routines perform the correct operation to read or write
+ *   the adapter register.
+ *
+ *   EISA port block base addresses are based on the slot number in which the
+ *   controller is installed.  For example, if the EISA controller is installed
+ *   in slot 4, the port block base address is 0x4000.  If the controller is
+ *   installed in slot 2, the port block base address is 0x2000, and so on.
+ *   This port block can be used to access PDQ, ESIC, and DEFEA on-board
+ *   registers using the register offsets defined in DEFXX.H.
+ *
+ *   PCI port block base addresses are assigned by the PCI BIOS or system
+ *   firmware.  There is one 128 byte port block which can be accessed.  It
+ *   allows for I/O mapping of both PDQ and PFI registers using the register
+ *   offsets defined in DEFXX.H.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   bp->base is a valid base I/O address for this adapter.
+ *   offset is a valid register offset for this adapter.
+ *
+ * Side Effects:
+ *   Rather than produce macros for these functions, these routines
+ *   are defined using "inline" to ensure that the compiler will
+ *   generate inline code and not waste a procedure call and return.
+ *   This provides all the benefits of macros, but with the
+ *   advantage of strict data type checking.
+ */
+
+static inline void dfx_writel(DFX_board_t *bp, int offset, u32 data)
+{
+       writel(data, bp->base.mem + offset);
+       mb();
+}
+
+static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data)
+{
+       outl(data, bp->base.port + offset);
+}
+
+static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data)
+{
+       struct device __maybe_unused *bdev = bp->bus_dev;
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+
+       if (dfx_use_mmio)
+               dfx_writel(bp, offset, data);
+       else
+               dfx_outl(bp, offset, data);
+}
+
+
+static inline void dfx_readl(DFX_board_t *bp, int offset, u32 *data)
+{
+       mb();
+       *data = readl(bp->base.mem + offset);
+}
+
+static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data)
+{
+       *data = inl(bp->base.port + offset);
+}
+
+static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
+{
+       struct device __maybe_unused *bdev = bp->bus_dev;
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+
+       if (dfx_use_mmio)
+               dfx_readl(bp, offset, data);
+       else
+               dfx_inl(bp, offset, data);
+}
+
+
+/*
+ * ================
+ * = dfx_get_bars =
+ * ================
+ *
+ * Overview:
+ *   Retrieves the address range used to access control and status
+ *   registers.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bdev      - pointer to device information
+ *   bar_start - pointer to store the start address
+ *   bar_len   - pointer to store the length of the area
+ *
+ * Assumptions:
+ *   I am sure there are some.
+ *
+ * Side Effects:
+ *   None
+ */
+static void dfx_get_bars(struct device *bdev,
+                        resource_size_t *bar_start, resource_size_t *bar_len)
+{
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+
+       if (dfx_bus_pci) {
+               int num = dfx_use_mmio ? 0 : 1;
+
+               *bar_start = pci_resource_start(to_pci_dev(bdev), num);
+               *bar_len = pci_resource_len(to_pci_dev(bdev), num);
+       }
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+               resource_size_t bar;
+
+               if (dfx_use_mmio) {
+                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
+                       bar <<= 16;
+                       *bar_start = bar;
+                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
+                       bar <<= 16;
+                       *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
+               } else {
+                       *bar_start = base_addr;
+                       *bar_len = PI_ESIC_K_CSR_IO_LEN;
+               }
+       }
+       if (dfx_bus_tc) {
+               *bar_start = to_tc_dev(bdev)->resource.start +
+                            PI_TC_K_CSR_OFFSET;
+               *bar_len = PI_TC_K_CSR_LEN;
+       }
+}
+
+static const struct net_device_ops dfx_netdev_ops = {
+       .ndo_open               = dfx_open,
+       .ndo_stop               = dfx_close,
+       .ndo_start_xmit         = dfx_xmt_queue_pkt,
+       .ndo_get_stats          = dfx_ctl_get_stats,
+       .ndo_set_rx_mode        = dfx_ctl_set_multicast_list,
+       .ndo_set_mac_address    = dfx_ctl_set_mac_address,
+};
+
+/*
+ * ================
+ * = dfx_register =
+ * ================
+ *
+ * Overview:
+ *   Initializes a supported FDDI controller
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bdev - pointer to device information
+ *
+ * Functional Description:
+ *
+ * Return Codes:
+ *   0          - This device (fddi0, fddi1, etc) configured successfully
+ *   -EBUSY      - Failed to get resources, or dfx_driver_init failed.
+ *
+ * Assumptions:
+ *   It compiles so it should work :-( (PCI cards do :-)
+ *
+ * Side Effects:
+ *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ *   initialized and the board resources are read and stored in
+ *   the device structure.
+ */
+static int __devinit dfx_register(struct device *bdev)
+{
+       static int version_disp;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       const char *print_name = dev_name(bdev);
+       struct net_device *dev;
+       DFX_board_t       *bp;                  /* board pointer */
+       resource_size_t bar_start = 0;          /* pointer to port */
+       resource_size_t bar_len = 0;            /* resource length */
+       int alloc_size;                         /* total buffer size used */
+       struct resource *region;
+       int err = 0;
+
+       if (!version_disp) {    /* display version info if adapter is found */
+               version_disp = 1;       /* set display flag to TRUE so that */
+               printk(version);        /* we only display this string ONCE */
+       }
+
+       dev = alloc_fddidev(sizeof(*bp));
+       if (!dev) {
+               printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n",
+                      print_name);
+               return -ENOMEM;
+       }
+
+       /* Enable PCI device. */
+       if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
+               printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
+                      print_name);
+               goto err_out;
+       }
+
+       SET_NETDEV_DEV(dev, bdev);
+
+       bp = netdev_priv(dev);
+       bp->bus_dev = bdev;
+       dev_set_drvdata(bdev, dev);
+
+       dfx_get_bars(bdev, &bar_start, &bar_len);
+
+       if (dfx_use_mmio)
+               region = request_mem_region(bar_start, bar_len, print_name);
+       else
+               region = request_region(bar_start, bar_len, print_name);
+       if (!region) {
+               printk(KERN_ERR "%s: Cannot reserve I/O resource "
+                      "0x%lx @ 0x%lx, aborting\n",
+                      print_name, (long)bar_len, (long)bar_start);
+               err = -EBUSY;
+               goto err_out_disable;
+       }
+
+       /* Set up I/O base address. */
+       if (dfx_use_mmio) {
+               bp->base.mem = ioremap_nocache(bar_start, bar_len);
+               if (!bp->base.mem) {
+                       printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
+                       err = -ENOMEM;
+                       goto err_out_region;
+               }
+       } else {
+               bp->base.port = bar_start;
+               dev->base_addr = bar_start;
+       }
+
+       /* Initialize new device structure */
+       dev->netdev_ops                 = &dfx_netdev_ops;
+
+       if (dfx_bus_pci)
+               pci_set_master(to_pci_dev(bdev));
+
+       if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
+               err = -ENODEV;
+               goto err_out_unmap;
+       }
+
+       err = register_netdev(dev);
+       if (err)
+               goto err_out_kfree;
+
+       printk("%s: registered as %s\n", print_name, dev->name);
+       return 0;
+
+err_out_kfree:
+       alloc_size = sizeof(PI_DESCR_BLOCK) +
+                    PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
+#ifndef DYNAMIC_BUFFERS
+                    (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
+#endif
+                    sizeof(PI_CONSUMER_BLOCK) +
+                    (PI_ALIGN_K_DESC_BLK - 1);
+       if (bp->kmalloced)
+               dma_free_coherent(bdev, alloc_size,
+                                 bp->kmalloced, bp->kmalloced_dma);
+
+err_out_unmap:
+       if (dfx_use_mmio)
+               iounmap(bp->base.mem);
+
+err_out_region:
+       if (dfx_use_mmio)
+               release_mem_region(bar_start, bar_len);
+       else
+               release_region(bar_start, bar_len);
+
+err_out_disable:
+       if (dfx_bus_pci)
+               pci_disable_device(to_pci_dev(bdev));
+
+err_out:
+       free_netdev(dev);
+       return err;
+}
+
+
+/*
+ * ================
+ * = dfx_bus_init =
+ * ================
+ *
+ * Overview:
+ *   Initializes the bus-specific controller logic.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Determine and save adapter IRQ in device table,
+ *   then perform bus-specific logic initialization.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   bp->base has already been set with the proper
+ *      base I/O address for this device.
+ *
+ * Side Effects:
+ *   Interrupts are enabled at the adapter bus-specific logic.
+ *   Note:  Interrupts at the DMA engine (PDQ chip) are not
+ *   enabled yet.
+ */
+
+static void __devinit dfx_bus_init(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       u8 val;
+
+       DBG_printk("In dfx_bus_init...\n");
+
+       /* Initialize a pointer back to the net_device struct */
+       bp->dev = dev;
+
+       /* Initialize adapter based on bus type */
+
+       if (dfx_bus_tc)
+               dev->irq = to_tc_dev(bdev)->interrupt;
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+
+               /* Get the interrupt level from the ESIC chip.  */
+               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               val &= PI_CONFIG_STAT_0_M_IRQ;
+               val >>= PI_CONFIG_STAT_0_V_IRQ;
+
+               switch (val) {
+               case PI_CONFIG_STAT_0_IRQ_K_9:
+                       dev->irq = 9;
+                       break;
+
+               case PI_CONFIG_STAT_0_IRQ_K_10:
+                       dev->irq = 10;
+                       break;
+
+               case PI_CONFIG_STAT_0_IRQ_K_11:
+                       dev->irq = 11;
+                       break;
+
+               case PI_CONFIG_STAT_0_IRQ_K_15:
+                       dev->irq = 15;
+                       break;
+               }
+
+               /*
+                * Enable memory decoding (MEMCS0) and/or port decoding
+                * (IOCS1/IOCS0) as appropriate in Function Control
+                * Register.  One of the port chip selects seems to be
+                * used for the Burst Holdoff register, but this bit of
+                * documentation is missing and as yet it has not been
+                * determined which of the two.  This is also the reason
+                * the size of the decoded port range is twice as large
+                * as one required by the PDQ.
+                */
+
+               /* Set the decode range of the board.  */
+               val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0);
+               val = PI_ESIC_K_CSR_IO_LEN - 1;
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff);
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff);
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff);
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff);
+
+               /* Enable the decoders.  */
+               val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
+               if (dfx_use_mmio)
+                       val |= PI_FUNCTION_CNTRL_M_MEMCS0;
+               outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val);
+
+               /*
+                * Enable access to the rest of the module
+                * (including PDQ and packet memory).
+                */
+               val = PI_SLOT_CNTRL_M_ENB;
+               outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val);
+
+               /*
+                * Map PDQ registers into memory or port space.  This is
+                * done with a bit in the Burst Holdoff register.
+                */
+               val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF);
+               if (dfx_use_mmio)
+                       val |= PI_BURST_HOLDOFF_V_MEM_MAP;
+               else
+                       val &= ~PI_BURST_HOLDOFF_V_MEM_MAP;
+               outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val);
+
+               /* Enable interrupts at EISA bus interface chip (ESIC) */
+               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               val |= PI_CONFIG_STAT_0_M_INT_ENB;
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
+       }
+       if (dfx_bus_pci) {
+               struct pci_dev *pdev = to_pci_dev(bdev);
+
+               /* Get the interrupt level from the PCI Configuration Table */
+
+               dev->irq = pdev->irq;
+
+               /* Check Latency Timer and set if less than minimal */
+
+               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
+               if (val < PFI_K_LAT_TIMER_MIN) {
+                       val = PFI_K_LAT_TIMER_DEF;
+                       pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
+               }
+
+               /* Enable interrupts at PCI bus interface chip (PFI) */
+               val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB;
+               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val);
+       }
+}
+
+/*
+ * ==================
+ * = dfx_bus_uninit =
+ * ==================
+ *
+ * Overview:
+ *   Uninitializes the bus-specific controller logic.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Perform bus-specific logic uninitialization.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   bp->base has already been set with the proper
+ *      base I/O address for this device.
+ *
+ * Side Effects:
+ *   Interrupts are disabled at the adapter bus-specific logic.
+ */
+
+static void __devexit dfx_bus_uninit(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       u8 val;
+
+       DBG_printk("In dfx_bus_uninit...\n");
+
+       /* Uninitialize adapter based on bus type */
+
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+
+               /* Disable interrupts at EISA bus interface chip (ESIC) */
+               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
+       }
+       if (dfx_bus_pci) {
+               /* Disable interrupts at PCI bus interface chip (PFI) */
+               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0);
+       }
+}
+
+
+/*
+ * ========================
+ * = dfx_bus_config_check =
+ * ========================
+ *
+ * Overview:
+ *   Checks the configuration (burst size, full-duplex, etc.)  If any parameters
+ *   are illegal, then this routine will set new defaults.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   For Revision 1 FDDI EISA, Revision 2 or later FDDI EISA with rev E or later
+ *   PDQ, and all FDDI PCI controllers, all values are legal.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   dfx_adap_init has NOT been called yet so burst size and other items have
+ *   not been set.
+ *
+ * Side Effects:
+ *   None
+ */
+
+static void __devinit dfx_bus_config_check(DFX_board_t *bp)
+{
+       struct device __maybe_unused *bdev = bp->bus_dev;
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int     status;                         /* return code from adapter port control call */
+       u32     host_data;                      /* LW data returned from port control call */
+
+       DBG_printk("In dfx_bus_config_check...\n");
+
+       /* Configuration check only valid for EISA adapter */
+
+       if (dfx_bus_eisa) {
+               /*
+                * First check if revision 2 EISA controller.  Rev. 1 cards used
+                * PDQ revision B, so no workaround needed in this case.  Rev. 3
+                * cards used PDQ revision E, so no workaround needed in this
+                * case, either.  Only Rev. 2 cards used either Rev. D or E
+                * chips, so we must verify the chip revision on Rev. 2 cards.
+                */
+               if (to_eisa_device(bdev)->id.driver_data == DEFEA_PROD_ID_2) {
+                       /*
+                        * Revision 2 FDDI EISA controller found,
+                        * so let's check PDQ revision of adapter.
+                        */
+                       status = dfx_hw_port_ctrl_req(bp,
+                                                                                       PI_PCTRL_M_SUB_CMD,
+                                                                                       PI_SUB_CMD_K_PDQ_REV_GET,
+                                                                                       0,
+                                                                                       &host_data);
+                       if ((status != DFX_K_SUCCESS) || (host_data == 2))
+                               {
+                               /*
+                                * Either we couldn't determine the PDQ revision, or
+                                * we determined that it is at revision D.  In either case,
+                                * we need to implement the workaround.
+                                */
+
+                               /* Ensure that the burst size is set to 8 longwords or less */
+
+                               switch (bp->burst_size)
+                                       {
+                                       case PI_PDATA_B_DMA_BURST_SIZE_32:
+                                       case PI_PDATA_B_DMA_BURST_SIZE_16:
+                                               bp->burst_size = PI_PDATA_B_DMA_BURST_SIZE_8;
+                                               break;
+
+                                       default:
+                                               break;
+                                       }
+
+                               /* Ensure that full-duplex mode is not enabled */
+
+                               bp->full_duplex_enb = PI_SNMP_K_FALSE;
+                               }
+                       }
+               }
+       }
+
+
+/*
+ * ===================
+ * = dfx_driver_init =
+ * ===================
+ *
+ * Overview:
+ *   Initializes remaining adapter board structure information
+ *   and makes sure adapter is in a safe state prior to dfx_open().
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *   print_name - printable device name
+ *
+ * Functional Description:
+ *   This function allocates additional resources such as the host memory
+ *   blocks needed by the adapter (eg. descriptor and consumer blocks).
+ *      Remaining bus initialization steps are also completed.  The adapter
+ *   is also reset so that it is in the DMA_UNAVAILABLE state.  The OS
+ *   must call dfx_open() to open the adapter and bring it on-line.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS     - initialization succeeded
+ *   DFX_K_FAILURE     - initialization failed - could not allocate memory
+ *                                             or read adapter MAC address
+ *
+ * Assumptions:
+ *   Memory allocated from pci_alloc_consistent() call is physically
+ *   contiguous, locked memory.
+ *
+ * Side Effects:
+ *   Adapter is reset and should be in DMA_UNAVAILABLE state before
+ *   returning from this routine.
+ */
+
+static int __devinit dfx_driver_init(struct net_device *dev,
+                                    const char *print_name,
+                                    resource_size_t bar_start)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       int alloc_size;                 /* total buffer size needed */
+       char *top_v, *curr_v;           /* virtual addrs into memory block */
+       dma_addr_t top_p, curr_p;       /* physical addrs into memory block */
+       u32 data;                       /* host data register value */
+       __le32 le32;
+       char *board_name = NULL;
+
+       DBG_printk("In dfx_driver_init...\n");
+
+       /* Initialize bus-specific hardware registers */
+
+       dfx_bus_init(dev);
+
+       /*
+        * Initialize default values for configurable parameters
+        *
+        * Note: All of these parameters are ones that a user may
+        *       want to customize.  It'd be nice to break these
+        *               out into Space.c or someplace else that's more
+        *               accessible/understandable than this file.
+        */
+
+       bp->full_duplex_enb             = PI_SNMP_K_FALSE;
+       bp->req_ttrt                    = 8 * 12500;            /* 8ms in 80 nanosec units */
+       bp->burst_size                  = PI_PDATA_B_DMA_BURST_SIZE_DEF;
+       bp->rcv_bufs_to_post    = RCV_BUFS_DEF;
+
+       /*
+        * Ensure that HW configuration is OK
+        *
+        * Note: Depending on the hardware revision, we may need to modify
+        *       some of the configurable parameters to workaround hardware
+        *       limitations.  We'll perform this configuration check AFTER
+        *       setting the parameters to their default values.
+        */
+
+       dfx_bus_config_check(bp);
+
+       /* Disable PDQ interrupts first */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+
+       /* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
+
+       (void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
+
+       /*  Read the factory MAC address from the adapter then save it */
+
+       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0,
+                                &data) != DFX_K_SUCCESS) {
+               printk("%s: Could not read adapter factory MAC address!\n",
+                      print_name);
+               return DFX_K_FAILURE;
+       }
+       le32 = cpu_to_le32(data);
+       memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
+
+       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
+                                &data) != DFX_K_SUCCESS) {
+               printk("%s: Could not read adapter factory MAC address!\n",
+                      print_name);
+               return DFX_K_FAILURE;
+       }
+       le32 = cpu_to_le32(data);
+       memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
+
+       /*
+        * Set current address to factory address
+        *
+        * Note: Node address override support is handled through
+        *       dfx_ctl_set_mac_address.
+        */
+
+       memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
+       if (dfx_bus_tc)
+               board_name = "DEFTA";
+       if (dfx_bus_eisa)
+               board_name = "DEFEA";
+       if (dfx_bus_pci)
+               board_name = "DEFPA";
+       pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
+               print_name, board_name, dfx_use_mmio ? "" : "I/O ",
+               (long long)bar_start, dev->irq, dev->dev_addr);
+
+       /*
+        * Get memory for descriptor block, consumer block, and other buffers
+        * that need to be DMA read or written to by the adapter.
+        */
+
+       alloc_size = sizeof(PI_DESCR_BLOCK) +
+                                       PI_CMD_REQ_K_SIZE_MAX +
+                                       PI_CMD_RSP_K_SIZE_MAX +
+#ifndef DYNAMIC_BUFFERS
+                                       (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
+#endif
+                                       sizeof(PI_CONSUMER_BLOCK) +
+                                       (PI_ALIGN_K_DESC_BLK - 1);
+       bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
+                                                  &bp->kmalloced_dma,
+                                                  GFP_ATOMIC);
+       if (top_v == NULL) {
+               printk("%s: Could not allocate memory for host buffers "
+                      "and structures!\n", print_name);
+               return DFX_K_FAILURE;
+       }
+       memset(top_v, 0, alloc_size);   /* zero out memory before continuing */
+       top_p = bp->kmalloced_dma;      /* get physical address of buffer */
+
+       /*
+        *  To guarantee the 8K alignment required for the descriptor block, 8K - 1
+        *  plus the amount of memory needed was allocated.  The physical address
+        *      is now 8K aligned.  By carving up the memory in a specific order,
+        *  we'll guarantee the alignment requirements for all other structures.
+        *
+        *  Note: If the assumptions change regarding the non-paged, non-cached,
+        *                physically contiguous nature of the memory block or the address
+        *                alignments, then we'll need to implement a different algorithm
+        *                for allocating the needed memory.
+        */
+
+       curr_p = ALIGN(top_p, PI_ALIGN_K_DESC_BLK);
+       curr_v = top_v + (curr_p - top_p);
+
+       /* Reserve space for descriptor block */
+
+       bp->descr_block_virt = (PI_DESCR_BLOCK *) curr_v;
+       bp->descr_block_phys = curr_p;
+       curr_v += sizeof(PI_DESCR_BLOCK);
+       curr_p += sizeof(PI_DESCR_BLOCK);
+
+       /* Reserve space for command request buffer */
+
+       bp->cmd_req_virt = (PI_DMA_CMD_REQ *) curr_v;
+       bp->cmd_req_phys = curr_p;
+       curr_v += PI_CMD_REQ_K_SIZE_MAX;
+       curr_p += PI_CMD_REQ_K_SIZE_MAX;
+
+       /* Reserve space for command response buffer */
+
+       bp->cmd_rsp_virt = (PI_DMA_CMD_RSP *) curr_v;
+       bp->cmd_rsp_phys = curr_p;
+       curr_v += PI_CMD_RSP_K_SIZE_MAX;
+       curr_p += PI_CMD_RSP_K_SIZE_MAX;
+
+       /* Reserve space for the LLC host receive queue buffers */
+
+       bp->rcv_block_virt = curr_v;
+       bp->rcv_block_phys = curr_p;
+
+#ifndef DYNAMIC_BUFFERS
+       curr_v += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
+       curr_p += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
+#endif
+
+       /* Reserve space for the consumer block */
+
+       bp->cons_block_virt = (PI_CONSUMER_BLOCK *) curr_v;
+       bp->cons_block_phys = curr_p;
+
+       /* Display virtual and physical addresses if debug driver */
+
+       DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
+                  print_name,
+                  (long)bp->descr_block_virt, bp->descr_block_phys);
+       DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
+                  print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
+       DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
+                  print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
+       DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
+                  print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
+       DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
+                  print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
+
+       return DFX_K_SUCCESS;
+}
+
+
+/*
+ * =================
+ * = dfx_adap_init =
+ * =================
+ *
+ * Overview:
+ *   Brings the adapter to the link avail/link unavailable state.
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *   get_buffers - non-zero if buffers to be allocated
+ *
+ * Functional Description:
+ *   Issues the low-level firmware/hardware calls necessary to bring
+ *   the adapter up, or to properly reset and restore adapter during
+ *   run-time.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS - Adapter brought up successfully
+ *   DFX_K_FAILURE - Adapter initialization failed
+ *
+ * Assumptions:
+ *   bp->reset_type should be set to a valid reset type value before
+ *   calling this routine.
+ *
+ * Side Effects:
+ *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
+ *   upon a successful return of this routine.
+ */
+
+static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
+       {
+       DBG_printk("In dfx_adap_init...\n");
+
+       /* Disable PDQ interrupts first */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+
+       /* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
+
+       if (dfx_hw_dma_uninit(bp, bp->reset_type) != DFX_K_SUCCESS)
+               {
+               printk("%s: Could not uninitialize/reset adapter!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /*
+        * When the PDQ is reset, some false Type 0 interrupts may be pending,
+        * so we'll acknowledge all Type 0 interrupts now before continuing.
+        */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, PI_HOST_INT_K_ACK_ALL_TYPE_0);
+
+       /*
+        * Clear Type 1 and Type 2 registers before going to DMA_AVAILABLE state
+        *
+        * Note: We only need to clear host copies of these registers.  The PDQ reset
+        *       takes care of the on-board register values.
+        */
+
+       bp->cmd_req_reg.lword   = 0;
+       bp->cmd_rsp_reg.lword   = 0;
+       bp->rcv_xmt_reg.lword   = 0;
+
+       /* Clear consumer block before going to DMA_AVAILABLE state */
+
+       memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
+
+       /* Initialize the DMA Burst Size */
+
+       if (dfx_hw_port_ctrl_req(bp,
+                                                       PI_PCTRL_M_SUB_CMD,
+                                                       PI_SUB_CMD_K_BURST_SIZE_SET,
+                                                       bp->burst_size,
+                                                       NULL) != DFX_K_SUCCESS)
+               {
+               printk("%s: Could not set adapter burst size!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /*
+        * Set base address of Consumer Block
+        *
+        * Assumption: 32-bit physical address of consumer block is 64 byte
+        *                         aligned.  That is, bits 0-5 of the address must be zero.
+        */
+
+       if (dfx_hw_port_ctrl_req(bp,
+                                                       PI_PCTRL_M_CONS_BLOCK,
+                                                       bp->cons_block_phys,
+                                                       0,
+                                                       NULL) != DFX_K_SUCCESS)
+               {
+               printk("%s: Could not set consumer block address!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /*
+        * Set the base address of Descriptor Block and bring adapter
+        * to DMA_AVAILABLE state.
+        *
+        * Note: We also set the literal and data swapping requirements
+        *       in this command.
+        *
+        * Assumption: 32-bit physical address of descriptor block
+        *       is 8Kbyte aligned.
+        */
+       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_INIT,
+                                (u32)(bp->descr_block_phys |
+                                      PI_PDATA_A_INIT_M_BSWAP_INIT),
+                                0, NULL) != DFX_K_SUCCESS) {
+               printk("%s: Could not set descriptor block address!\n",
+                      bp->dev->name);
+               return DFX_K_FAILURE;
+       }
+
+       /* Set transmit flush timeout value */
+
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_CHARS_SET;
+       bp->cmd_req_virt->char_set.item[0].item_code    = PI_ITEM_K_FLUSH_TIME;
+       bp->cmd_req_virt->char_set.item[0].value                = 3;    /* 3 seconds */
+       bp->cmd_req_virt->char_set.item[0].item_index   = 0;
+       bp->cmd_req_virt->char_set.item[1].item_code    = PI_ITEM_K_EOL;
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               {
+               printk("%s: DMA command request failed!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /* Set the initial values for eFDXEnable and MACTReq MIB objects */
+
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_SNMP_SET;
+       bp->cmd_req_virt->snmp_set.item[0].item_code    = PI_ITEM_K_FDX_ENB_DIS;
+       bp->cmd_req_virt->snmp_set.item[0].value                = bp->full_duplex_enb;
+       bp->cmd_req_virt->snmp_set.item[0].item_index   = 0;
+       bp->cmd_req_virt->snmp_set.item[1].item_code    = PI_ITEM_K_MAC_T_REQ;
+       bp->cmd_req_virt->snmp_set.item[1].value                = bp->req_ttrt;
+       bp->cmd_req_virt->snmp_set.item[1].item_index   = 0;
+       bp->cmd_req_virt->snmp_set.item[2].item_code    = PI_ITEM_K_EOL;
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               {
+               printk("%s: DMA command request failed!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /* Initialize adapter CAM */
+
+       if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
+               {
+               printk("%s: Adapter CAM update failed!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /* Initialize adapter filters */
+
+       if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
+               {
+               printk("%s: Adapter filters update failed!\n", bp->dev->name);
+               return DFX_K_FAILURE;
+               }
+
+       /*
+        * Remove any existing dynamic buffers (i.e. if the adapter is being
+        * reinitialized)
+        */
+
+       if (get_buffers)
+               dfx_rcv_flush(bp);
+
+       /* Initialize receive descriptor block and produce buffers */
+
+       if (dfx_rcv_init(bp, get_buffers))
+               {
+               printk("%s: Receive buffer allocation failed\n", bp->dev->name);
+               if (get_buffers)
+                       dfx_rcv_flush(bp);
+               return DFX_K_FAILURE;
+               }
+
+       /* Issue START command and bring adapter to LINK_(UN)AVAILABLE state */
+
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_START;
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               {
+               printk("%s: Start command failed\n", bp->dev->name);
+               if (get_buffers)
+                       dfx_rcv_flush(bp);
+               return DFX_K_FAILURE;
+               }
+
+       /* Initialization succeeded, reenable PDQ interrupts */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_ENABLE_DEF_INTS);
+       return DFX_K_SUCCESS;
+       }
+
+
+/*
+ * ============
+ * = dfx_open =
+ * ============
+ *
+ * Overview:
+ *   Opens the adapter
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This function brings the adapter to an operational state.
+ *
+ * Return Codes:
+ *   0          - Adapter was successfully opened
+ *   -EAGAIN - Could not register IRQ or adapter initialization failed
+ *
+ * Assumptions:
+ *   This routine should only be called for a device that was
+ *   initialized successfully.
+ *
+ * Side Effects:
+ *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
+ *   if the open is successful.
+ */
+
+static int dfx_open(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       int ret;
+
+       DBG_printk("In dfx_open...\n");
+
+       /* Register IRQ - support shared interrupts by passing device ptr */
+
+       ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name,
+                         dev);
+       if (ret) {
+               printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
+               return ret;
+       }
+
+       /*
+        * Set current address to factory MAC address
+        *
+        * Note: We've already done this step in dfx_driver_init.
+        *       However, it's possible that a user has set a node
+        *               address override, then closed and reopened the
+        *               adapter.  Unless we reset the device address field
+        *               now, we'll continue to use the existing modified
+        *               address.
+        */
+
+       memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
+
+       /* Clear local unicast/multicast address tables and counts */
+
+       memset(bp->uc_table, 0, sizeof(bp->uc_table));
+       memset(bp->mc_table, 0, sizeof(bp->mc_table));
+       bp->uc_count = 0;
+       bp->mc_count = 0;
+
+       /* Disable promiscuous filter settings */
+
+       bp->ind_group_prom      = PI_FSTATE_K_BLOCK;
+       bp->group_prom          = PI_FSTATE_K_BLOCK;
+
+       spin_lock_init(&bp->lock);
+
+       /* Reset and initialize adapter */
+
+       bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST;    /* skip self-test */
+       if (dfx_adap_init(bp, 1) != DFX_K_SUCCESS)
+       {
+               printk(KERN_ERR "%s: Adapter open failed!\n", dev->name);
+               free_irq(dev->irq, dev);
+               return -EAGAIN;
+       }
+
+       /* Set device structure info */
+       netif_start_queue(dev);
+       return 0;
+}
+
+
+/*
+ * =============
+ * = dfx_close =
+ * =============
+ *
+ * Overview:
+ *   Closes the device/module.
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This routine closes the adapter and brings it to a safe state.
+ *   The interrupt service routine is deregistered with the OS.
+ *   The adapter can be opened again with another call to dfx_open().
+ *
+ * Return Codes:
+ *   Always return 0.
+ *
+ * Assumptions:
+ *   No further requests for this adapter are made after this routine is
+ *   called.  dfx_open() can be called to reset and reinitialize the
+ *   adapter.
+ *
+ * Side Effects:
+ *   Adapter should be in DMA_UNAVAILABLE state upon completion of this
+ *   routine.
+ */
+
+static int dfx_close(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+
+       DBG_printk("In dfx_close...\n");
+
+       /* Disable PDQ interrupts first */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+
+       /* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
+
+       (void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
+
+       /*
+        * Flush any pending transmit buffers
+        *
+        * Note: It's important that we flush the transmit buffers
+        *               BEFORE we clear our copy of the Type 2 register.
+        *               Otherwise, we'll have no idea how many buffers
+        *               we need to free.
+        */
+
+       dfx_xmt_flush(bp);
+
+       /*
+        * Clear Type 1 and Type 2 registers after adapter reset
+        *
+        * Note: Even though we're closing the adapter, it's
+        *       possible that an interrupt will occur after
+        *               dfx_close is called.  Without some assurance to
+        *               the contrary we want to make sure that we don't
+        *               process receive and transmit LLC frames and update
+        *               the Type 2 register with bad information.
+        */
+
+       bp->cmd_req_reg.lword   = 0;
+       bp->cmd_rsp_reg.lword   = 0;
+       bp->rcv_xmt_reg.lword   = 0;
+
+       /* Clear consumer block for the same reason given above */
+
+       memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
+
+       /* Release all dynamically allocate skb in the receive ring. */
+
+       dfx_rcv_flush(bp);
+
+       /* Clear device structure flags */
+
+       netif_stop_queue(dev);
+
+       /* Deregister (free) IRQ */
+
+       free_irq(dev->irq, dev);
+
+       return 0;
+}
+
+
+/*
+ * ======================
+ * = dfx_int_pr_halt_id =
+ * ======================
+ *
+ * Overview:
+ *   Displays halt id's in string form.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Determine current halt id and display appropriate string.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+static void dfx_int_pr_halt_id(DFX_board_t     *bp)
+       {
+       PI_UINT32       port_status;                    /* PDQ port status register value */
+       PI_UINT32       halt_id;                                /* PDQ port status halt ID */
+
+       /* Read the latest port status */
+
+       dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
+
+       /* Display halt state transition information */
+
+       halt_id = (port_status & PI_PSTATUS_M_HALT_ID) >> PI_PSTATUS_V_HALT_ID;
+       switch (halt_id)
+               {
+               case PI_HALT_ID_K_SELFTEST_TIMEOUT:
+                       printk("%s: Halt ID: Selftest Timeout\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_PARITY_ERROR:
+                       printk("%s: Halt ID: Host Bus Parity Error\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_HOST_DIR_HALT:
+                       printk("%s: Halt ID: Host-Directed Halt\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_SW_FAULT:
+                       printk("%s: Halt ID: Adapter Software Fault\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_HW_FAULT:
+                       printk("%s: Halt ID: Adapter Hardware Fault\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_PC_TRACE:
+                       printk("%s: Halt ID: FDDI Network PC Trace Path Test\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_DMA_ERROR:
+                       printk("%s: Halt ID: Adapter DMA Error\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_IMAGE_CRC_ERROR:
+                       printk("%s: Halt ID: Firmware Image CRC Error\n", bp->dev->name);
+                       break;
+
+               case PI_HALT_ID_K_BUS_EXCEPTION:
+                       printk("%s: Halt ID: 68000 Bus Exception\n", bp->dev->name);
+                       break;
+
+               default:
+                       printk("%s: Halt ID: Unknown (code = %X)\n", bp->dev->name, halt_id);
+                       break;
+               }
+       }
+
+
+/*
+ * ==========================
+ * = dfx_int_type_0_process =
+ * ==========================
+ *
+ * Overview:
+ *   Processes Type 0 interrupts.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Processes all enabled Type 0 interrupts.  If the reason for the interrupt
+ *   is a serious fault on the adapter, then an error message is displayed
+ *   and the adapter is reset.
+ *
+ *   One tricky potential timing window is the rapid succession of "link avail"
+ *   "link unavail" state change interrupts.  The acknowledgement of the Type 0
+ *   interrupt must be done before reading the state from the Port Status
+ *   register.  This is true because a state change could occur after reading
+ *   the data, but before acknowledging the interrupt.  If this state change
+ *   does happen, it would be lost because the driver is using the old state,
+ *   and it will never know about the new state because it subsequently
+ *   acknowledges the state change interrupt.
+ *
+ *          INCORRECT                                      CORRECT
+ *      read type 0 int reasons                   read type 0 int reasons
+ *      read adapter state                        ack type 0 interrupts
+ *      ack type 0 interrupts                     read adapter state
+ *      ... process interrupt ...                 ... process interrupt ...
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   An adapter reset may occur if the adapter has any Type 0 error interrupts
+ *   or if the port status indicates that the adapter is halted.  The driver
+ *   is responsible for reinitializing the adapter with the current CAM
+ *   contents and adapter filter settings.
+ */
+
+static void dfx_int_type_0_process(DFX_board_t *bp)
+
+       {
+       PI_UINT32       type_0_status;          /* Host Interrupt Type 0 register */
+       PI_UINT32       state;                          /* current adap state (from port status) */
+
+       /*
+        * Read host interrupt Type 0 register to determine which Type 0
+        * interrupts are pending.  Immediately write it back out to clear
+        * those interrupts.
+        */
+
+       dfx_port_read_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, &type_0_status);
+       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, type_0_status);
+
+       /* Check for Type 0 error interrupts */
+
+       if (type_0_status & (PI_TYPE_0_STAT_M_NXM |
+                                                       PI_TYPE_0_STAT_M_PM_PAR_ERR |
+                                                       PI_TYPE_0_STAT_M_BUS_PAR_ERR))
+               {
+               /* Check for Non-Existent Memory error */
+
+               if (type_0_status & PI_TYPE_0_STAT_M_NXM)
+                       printk("%s: Non-Existent Memory Access Error\n", bp->dev->name);
+
+               /* Check for Packet Memory Parity error */
+
+               if (type_0_status & PI_TYPE_0_STAT_M_PM_PAR_ERR)
+                       printk("%s: Packet Memory Parity Error\n", bp->dev->name);
+
+               /* Check for Host Bus Parity error */
+
+               if (type_0_status & PI_TYPE_0_STAT_M_BUS_PAR_ERR)
+                       printk("%s: Host Bus Parity Error\n", bp->dev->name);
+
+               /* Reset adapter and bring it back on-line */
+
+               bp->link_available = PI_K_FALSE;        /* link is no longer available */
+               bp->reset_type = 0;                                     /* rerun on-board diagnostics */
+               printk("%s: Resetting adapter...\n", bp->dev->name);
+               if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
+                       {
+                       printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
+                       dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+                       return;
+                       }
+               printk("%s: Adapter reset successful!\n", bp->dev->name);
+               return;
+               }
+
+       /* Check for transmit flush interrupt */
+
+       if (type_0_status & PI_TYPE_0_STAT_M_XMT_FLUSH)
+               {
+               /* Flush any pending xmt's and acknowledge the flush interrupt */
+
+               bp->link_available = PI_K_FALSE;                /* link is no longer available */
+               dfx_xmt_flush(bp);                                              /* flush any outstanding packets */
+               (void) dfx_hw_port_ctrl_req(bp,
+                                                                       PI_PCTRL_M_XMT_DATA_FLUSH_DONE,
+                                                                       0,
+                                                                       0,
+                                                                       NULL);
+               }
+
+       /* Check for adapter state change */
+
+       if (type_0_status & PI_TYPE_0_STAT_M_STATE_CHANGE)
+               {
+               /* Get latest adapter state */
+
+               state = dfx_hw_adap_state_rd(bp);       /* get adapter state */
+               if (state == PI_STATE_K_HALTED)
+                       {
+                       /*
+                        * Adapter has transitioned to HALTED state, try to reset
+                        * adapter to bring it back on-line.  If reset fails,
+                        * leave the adapter in the broken state.
+                        */
+
+                       printk("%s: Controller has transitioned to HALTED state!\n", bp->dev->name);
+                       dfx_int_pr_halt_id(bp);                 /* display halt id as string */
+
+                       /* Reset adapter and bring it back on-line */
+
+                       bp->link_available = PI_K_FALSE;        /* link is no longer available */
+                       bp->reset_type = 0;                                     /* rerun on-board diagnostics */
+                       printk("%s: Resetting adapter...\n", bp->dev->name);
+                       if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
+                               {
+                               printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
+                               dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+                               return;
+                               }
+                       printk("%s: Adapter reset successful!\n", bp->dev->name);
+                       }
+               else if (state == PI_STATE_K_LINK_AVAIL)
+                       {
+                       bp->link_available = PI_K_TRUE;         /* set link available flag */
+                       }
+               }
+       }
+
+
+/*
+ * ==================
+ * = dfx_int_common =
+ * ==================
+ *
+ * Overview:
+ *   Interrupt service routine (ISR)
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   This is the ISR which processes incoming adapter interrupts.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   This routine assumes PDQ interrupts have not been disabled.
+ *   When interrupts are disabled at the PDQ, the Port Status register
+ *   is automatically cleared.  This routine uses the Port Status
+ *   register value to determine whether a Type 0 interrupt occurred,
+ *   so it's important that adapter interrupts are not normally
+ *   enabled/disabled at the PDQ.
+ *
+ *   It's vital that this routine is NOT reentered for the
+ *   same board and that the OS is not in another section of
+ *   code (eg. dfx_xmt_queue_pkt) for the same board on a
+ *   different thread.
+ *
+ * Side Effects:
+ *   Pending interrupts are serviced.  Depending on the type of
+ *   interrupt, acknowledging and clearing the interrupt at the
+ *   PDQ involves writing a register to clear the interrupt bit
+ *   or updating completion indices.
+ */
+
+static void dfx_int_common(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       PI_UINT32       port_status;            /* Port Status register */
+
+       /* Process xmt interrupts - frequent case, so always call this routine */
+
+       if(dfx_xmt_done(bp))                            /* free consumed xmt packets */
+               netif_wake_queue(dev);
+
+       /* Process rcv interrupts - frequent case, so always call this routine */
+
+       dfx_rcv_queue_process(bp);              /* service received LLC frames */
+
+       /*
+        * Transmit and receive producer and completion indices are updated on the
+        * adapter by writing to the Type 2 Producer register.  Since the frequent
+        * case is that we'll be processing either LLC transmit or receive buffers,
+        * we'll optimize I/O writes by doing a single register write here.
+        */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+
+       /* Read PDQ Port Status register to find out which interrupts need processing */
+
+       dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
+
+       /* Process Type 0 interrupts (if any) - infrequent, so only call when needed */
+
+       if (port_status & PI_PSTATUS_M_TYPE_0_PENDING)
+               dfx_int_type_0_process(bp);     /* process Type 0 interrupts */
+       }
+
+
+/*
+ * =================
+ * = dfx_interrupt =
+ * =================
+ *
+ * Overview:
+ *   Interrupt processing routine
+ *
+ * Returns:
+ *   Whether a valid interrupt was seen.
+ *
+ * Arguments:
+ *   irq       - interrupt vector
+ *   dev_id    - pointer to device information
+ *
+ * Functional Description:
+ *   This routine calls the interrupt processing routine for this adapter.  It
+ *   disables and reenables adapter interrupts, as appropriate.  We can support
+ *   shared interrupts since the incoming dev_id pointer provides our device
+ *   structure context.
+ *
+ * Return Codes:
+ *   IRQ_HANDLED - an IRQ was handled.
+ *   IRQ_NONE    - no IRQ was handled.
+ *
+ * Assumptions:
+ *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
+ *   on Intel-based systems) is done by the operating system outside this
+ *   routine.
+ *
+ *      System interrupts are enabled through this call.
+ *
+ * Side Effects:
+ *   Interrupts are disabled, then reenabled at the adapter.
+ */
+
+static irqreturn_t dfx_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+
+       /* Service adapter interrupts */
+
+       if (dfx_bus_pci) {
+               u32 status;
+
+               dfx_port_read_long(bp, PFI_K_REG_STATUS, &status);
+               if (!(status & PFI_STATUS_M_PDQ_INT))
+                       return IRQ_NONE;
+
+               spin_lock(&bp->lock);
+
+               /* Disable PDQ-PFI interrupts at PFI */
+               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
+                                   PFI_MODE_M_DMA_ENB);
+
+               /* Call interrupt service routine for this adapter */
+               dfx_int_common(dev);
+
+               /* Clear PDQ interrupt status bit and reenable interrupts */
+               dfx_port_write_long(bp, PFI_K_REG_STATUS,
+                                   PFI_STATUS_M_PDQ_INT);
+               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
+                                   (PFI_MODE_M_PDQ_INT_ENB |
+                                    PFI_MODE_M_DMA_ENB));
+
+               spin_unlock(&bp->lock);
+       }
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+               u8 status;
+
+               status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               if (!(status & PI_CONFIG_STAT_0_M_PEND))
+                       return IRQ_NONE;
+
+               spin_lock(&bp->lock);
+
+               /* Disable interrupts at the ESIC */
+               status &= ~PI_CONFIG_STAT_0_M_INT_ENB;
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
+
+               /* Call interrupt service routine for this adapter */
+               dfx_int_common(dev);
+
+               /* Reenable interrupts at the ESIC */
+               status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               status |= PI_CONFIG_STAT_0_M_INT_ENB;
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
+
+               spin_unlock(&bp->lock);
+       }
+       if (dfx_bus_tc) {
+               u32 status;
+
+               dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &status);
+               if (!(status & (PI_PSTATUS_M_RCV_DATA_PENDING |
+                               PI_PSTATUS_M_XMT_DATA_PENDING |
+                               PI_PSTATUS_M_SMT_HOST_PENDING |
+                               PI_PSTATUS_M_UNSOL_PENDING |
+                               PI_PSTATUS_M_CMD_RSP_PENDING |
+                               PI_PSTATUS_M_CMD_REQ_PENDING |
+                               PI_PSTATUS_M_TYPE_0_PENDING)))
+                       return IRQ_NONE;
+
+               spin_lock(&bp->lock);
+
+               /* Call interrupt service routine for this adapter */
+               dfx_int_common(dev);
+
+               spin_unlock(&bp->lock);
+       }
+
+       return IRQ_HANDLED;
+}
+
+
+/*
+ * =====================
+ * = dfx_ctl_get_stats =
+ * =====================
+ *
+ * Overview:
+ *   Get statistics for FDDI adapter
+ *
+ * Returns:
+ *   Pointer to FDDI statistics structure
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Gets current MIB objects from adapter, then
+ *   returns FDDI statistics structure as defined
+ *   in if_fddi.h.
+ *
+ *   Note: Since the FDDI statistics structure is
+ *   still new and the device structure doesn't
+ *   have an FDDI-specific get statistics handler,
+ *   we'll return the FDDI statistics structure as
+ *   a pointer to an Ethernet statistics structure.
+ *   That way, at least the first part of the statistics
+ *   structure can be decoded properly, and it allows
+ *   "smart" applications to perform a second cast to
+ *   decode the FDDI-specific statistics.
+ *
+ *   We'll have to pay attention to this routine as the
+ *   device structure becomes more mature and LAN media
+ *   independent.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
+       {
+       DFX_board_t *bp = netdev_priv(dev);
+
+       /* Fill the bp->stats structure with driver-maintained counters */
+
+       bp->stats.gen.rx_packets = bp->rcv_total_frames;
+       bp->stats.gen.tx_packets = bp->xmt_total_frames;
+       bp->stats.gen.rx_bytes   = bp->rcv_total_bytes;
+       bp->stats.gen.tx_bytes   = bp->xmt_total_bytes;
+       bp->stats.gen.rx_errors  = bp->rcv_crc_errors +
+                                  bp->rcv_frame_status_errors +
+                                  bp->rcv_length_errors;
+       bp->stats.gen.tx_errors  = bp->xmt_length_errors;
+       bp->stats.gen.rx_dropped = bp->rcv_discards;
+       bp->stats.gen.tx_dropped = bp->xmt_discards;
+       bp->stats.gen.multicast  = bp->rcv_multicast_frames;
+       bp->stats.gen.collisions = 0;           /* always zero (0) for FDDI */
+
+       /* Get FDDI SMT MIB objects */
+
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET;
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               return (struct net_device_stats *)&bp->stats;
+
+       /* Fill the bp->stats structure with the SMT MIB object values */
+
+       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));
+       bp->stats.smt_op_version_id                                     = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
+       bp->stats.smt_hi_version_id                                     = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
+       bp->stats.smt_lo_version_id                                     = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
+       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));
+       bp->stats.smt_mib_version_id                            = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
+       bp->stats.smt_mac_cts                                           = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
+       bp->stats.smt_non_master_cts                            = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
+       bp->stats.smt_master_cts                                        = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
+       bp->stats.smt_available_paths                           = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
+       bp->stats.smt_config_capabilities                       = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
+       bp->stats.smt_config_policy                                     = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
+       bp->stats.smt_connection_policy                         = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
+       bp->stats.smt_t_notify                                          = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
+       bp->stats.smt_stat_rpt_policy                           = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
+       bp->stats.smt_trace_max_expiration                      = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
+       bp->stats.smt_bypass_present                            = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
+       bp->stats.smt_ecm_state                                         = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
+       bp->stats.smt_cf_state                                          = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
+       bp->stats.smt_remote_disconnect_flag            = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
+       bp->stats.smt_station_status                            = bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
+       bp->stats.smt_peer_wrap_flag                            = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
+       bp->stats.smt_time_stamp                                        = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
+       bp->stats.smt_transition_time_stamp                     = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
+       bp->stats.mac_frame_status_functions            = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
+       bp->stats.mac_t_max_capability                          = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
+       bp->stats.mac_tvx_capability                            = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
+       bp->stats.mac_available_paths                           = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
+       bp->stats.mac_current_path                                      = bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
+       memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
+       memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
+       memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
+       memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
+       bp->stats.mac_dup_address_test                          = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
+       bp->stats.mac_requested_paths                           = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
+       bp->stats.mac_downstream_port_type                      = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
+       memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
+       bp->stats.mac_t_req                                                     = bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
+       bp->stats.mac_t_neg                                                     = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
+       bp->stats.mac_t_max                                                     = bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
+       bp->stats.mac_tvx_value                                         = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
+       bp->stats.mac_frame_error_threshold                     = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
+       bp->stats.mac_frame_error_ratio                         = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
+       bp->stats.mac_rmt_state                                         = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
+       bp->stats.mac_da_flag                                           = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
+       bp->stats.mac_una_da_flag                                       = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
+       bp->stats.mac_frame_error_flag                          = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
+       bp->stats.mac_ma_unitdata_available                     = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
+       bp->stats.mac_hardware_present                          = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
+       bp->stats.mac_ma_unitdata_enable                        = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
+       bp->stats.path_tvx_lower_bound                          = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
+       bp->stats.path_t_max_lower_bound                        = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
+       bp->stats.path_max_t_req                                        = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
+       memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
+       bp->stats.port_my_type[0]                                       = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
+       bp->stats.port_my_type[1]                                       = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
+       bp->stats.port_neighbor_type[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
+       bp->stats.port_neighbor_type[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
+       bp->stats.port_connection_policies[0]           = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
+       bp->stats.port_connection_policies[1]           = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
+       bp->stats.port_mac_indicated[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
+       bp->stats.port_mac_indicated[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
+       bp->stats.port_current_path[0]                          = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
+       bp->stats.port_current_path[1]                          = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
+       memcpy(&bp->stats.port_requested_paths[0*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
+       memcpy(&bp->stats.port_requested_paths[1*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
+       bp->stats.port_mac_placement[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
+       bp->stats.port_mac_placement[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
+       bp->stats.port_available_paths[0]                       = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
+       bp->stats.port_available_paths[1]                       = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
+       bp->stats.port_pmd_class[0]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
+       bp->stats.port_pmd_class[1]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
+       bp->stats.port_connection_capabilities[0]       = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
+       bp->stats.port_connection_capabilities[1]       = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
+       bp->stats.port_bs_flag[0]                                       = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
+       bp->stats.port_bs_flag[1]                                       = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
+       bp->stats.port_ler_estimate[0]                          = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
+       bp->stats.port_ler_estimate[1]                          = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
+       bp->stats.port_ler_cutoff[0]                            = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
+       bp->stats.port_ler_cutoff[1]                            = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
+       bp->stats.port_ler_alarm[0]                                     = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
+       bp->stats.port_ler_alarm[1]                                     = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
+       bp->stats.port_connect_state[0]                         = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
+       bp->stats.port_connect_state[1]                         = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
+       bp->stats.port_pcm_state[0]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
+       bp->stats.port_pcm_state[1]                                     = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
+       bp->stats.port_pc_withhold[0]                           = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
+       bp->stats.port_pc_withhold[1]                           = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
+       bp->stats.port_ler_flag[0]                                      = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
+       bp->stats.port_ler_flag[1]                                      = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
+       bp->stats.port_hardware_present[0]                      = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
+       bp->stats.port_hardware_present[1]                      = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
+
+       /* Get FDDI counters */
+
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_CNTRS_GET;
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               return (struct net_device_stats *)&bp->stats;
+
+       /* Fill the bp->stats structure with the FDDI counter values */
+
+       bp->stats.mac_frame_cts                         = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
+       bp->stats.mac_copied_cts                        = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
+       bp->stats.mac_transmit_cts                      = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
+       bp->stats.mac_error_cts                         = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
+       bp->stats.mac_lost_cts                          = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
+       bp->stats.port_lct_fail_cts[0]          = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
+       bp->stats.port_lct_fail_cts[1]          = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
+       bp->stats.port_lem_reject_cts[0]        = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
+       bp->stats.port_lem_reject_cts[1]        = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
+       bp->stats.port_lem_cts[0]                       = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
+       bp->stats.port_lem_cts[1]                       = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
+
+       return (struct net_device_stats *)&bp->stats;
+       }
+
+
+/*
+ * ==============================
+ * = dfx_ctl_set_multicast_list =
+ * ==============================
+ *
+ * Overview:
+ *   Enable/Disable LLC frame promiscuous mode reception
+ *   on the adapter and/or update multicast address table.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This routine follows a fairly simple algorithm for setting the
+ *   adapter filters and CAM:
+ *
+ *             if IFF_PROMISC flag is set
+ *                     enable LLC individual/group promiscuous mode
+ *             else
+ *                     disable LLC individual/group promiscuous mode
+ *                     if number of incoming multicast addresses >
+ *                                     (CAM max size - number of unicast addresses in CAM)
+ *                             enable LLC group promiscuous mode
+ *                             set driver-maintained multicast address count to zero
+ *                     else
+ *                             disable LLC group promiscuous mode
+ *                             set driver-maintained multicast address count to incoming count
+ *                     update adapter CAM
+ *             update adapter filters
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   Multicast addresses are presented in canonical (LSB) format.
+ *
+ * Side Effects:
+ *   On-board adapter CAM and filters are updated.
+ */
+
+static void dfx_ctl_set_multicast_list(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       int                                     i;                      /* used as index in for loop */
+       struct netdev_hw_addr *ha;
+
+       /* Enable LLC frame promiscuous mode, if necessary */
+
+       if (dev->flags & IFF_PROMISC)
+               bp->ind_group_prom = PI_FSTATE_K_PASS;          /* Enable LLC ind/group prom mode */
+
+       /* Else, update multicast address table */
+
+       else
+               {
+               bp->ind_group_prom = PI_FSTATE_K_BLOCK;         /* Disable LLC ind/group prom mode */
+               /*
+                * Check whether incoming multicast address count exceeds table size
+                *
+                * Note: The adapters utilize an on-board 64 entry CAM for
+                *       supporting perfect filtering of multicast packets
+                *               and bridge functions when adding unicast addresses.
+                *               There is no hash function available.  To support
+                *               additional multicast addresses, the all multicast
+                *               filter (LLC group promiscuous mode) must be enabled.
+                *
+                *               The firmware reserves two CAM entries for SMT-related
+                *               multicast addresses, which leaves 62 entries available.
+                *               The following code ensures that we're not being asked
+                *               to add more than 62 addresses to the CAM.  If we are,
+                *               the driver will enable the all multicast filter.
+                *               Should the number of multicast addresses drop below
+                *               the high water mark, the filter will be disabled and
+                *               perfect filtering will be used.
+                */
+
+               if (netdev_mc_count(dev) > (PI_CMD_ADDR_FILTER_K_SIZE - bp->uc_count))
+                       {
+                       bp->group_prom  = PI_FSTATE_K_PASS;             /* Enable LLC group prom mode */
+                       bp->mc_count    = 0;                                    /* Don't add mc addrs to CAM */
+                       }
+               else
+                       {
+                       bp->group_prom  = PI_FSTATE_K_BLOCK;    /* Disable LLC group prom mode */
+                       bp->mc_count    = netdev_mc_count(dev);         /* Add mc addrs to CAM */
+                       }
+
+               /* Copy addresses to multicast address table, then update adapter CAM */
+
+               i = 0;
+               netdev_for_each_mc_addr(ha, dev)
+                       memcpy(&bp->mc_table[i++ * FDDI_K_ALEN],
+                              ha->addr, FDDI_K_ALEN);
+
+               if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
+                       {
+                       DBG_printk("%s: Could not update multicast address table!\n", dev->name);
+                       }
+               else
+                       {
+                       DBG_printk("%s: Multicast address table updated!  Added %d addresses.\n", dev->name, bp->mc_count);
+                       }
+               }
+
+       /* Update adapter filters */
+
+       if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
+               {
+               DBG_printk("%s: Could not update adapter filters!\n", dev->name);
+               }
+       else
+               {
+               DBG_printk("%s: Adapter filters updated!\n", dev->name);
+               }
+       }
+
+
+/*
+ * ===========================
+ * = dfx_ctl_set_mac_address =
+ * ===========================
+ *
+ * Overview:
+ *   Add node address override (unicast address) to adapter
+ *   CAM and update dev_addr field in device table.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   dev  - pointer to device information
+ *   addr - pointer to sockaddr structure containing unicast address to add
+ *
+ * Functional Description:
+ *   The adapter supports node address overrides by adding one or more
+ *   unicast addresses to the adapter CAM.  This is similar to adding
+ *   multicast addresses.  In this routine we'll update the driver and
+ *   device structures with the new address, then update the adapter CAM
+ *   to ensure that the adapter will copy and strip frames destined and
+ *   sourced by that address.
+ *
+ * Return Codes:
+ *   Always returns zero.
+ *
+ * Assumptions:
+ *   The address pointed to by addr->sa_data is a valid unicast
+ *   address and is presented in canonical (LSB) format.
+ *
+ * Side Effects:
+ *   On-board adapter CAM is updated.  On-board adapter filters
+ *   may be updated.
+ */
+
+static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
+       {
+       struct sockaddr *p_sockaddr = (struct sockaddr *)addr;
+       DFX_board_t *bp = netdev_priv(dev);
+
+       /* Copy unicast address to driver-maintained structs and update count */
+
+       memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);        /* update device struct */
+       memcpy(&bp->uc_table[0], p_sockaddr->sa_data, FDDI_K_ALEN);     /* update driver struct */
+       bp->uc_count = 1;
+
+       /*
+        * Verify we're not exceeding the CAM size by adding unicast address
+        *
+        * Note: It's possible that before entering this routine we've
+        *       already filled the CAM with 62 multicast addresses.
+        *               Since we need to place the node address override into
+        *               the CAM, we have to check to see that we're not
+        *               exceeding the CAM size.  If we are, we have to enable
+        *               the LLC group (multicast) promiscuous mode filter as
+        *               in dfx_ctl_set_multicast_list.
+        */
+
+       if ((bp->uc_count + bp->mc_count) > PI_CMD_ADDR_FILTER_K_SIZE)
+               {
+               bp->group_prom  = PI_FSTATE_K_PASS;             /* Enable LLC group prom mode */
+               bp->mc_count    = 0;                                    /* Don't add mc addrs to CAM */
+
+               /* Update adapter filters */
+
+               if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
+                       {
+                       DBG_printk("%s: Could not update adapter filters!\n", dev->name);
+                       }
+               else
+                       {
+                       DBG_printk("%s: Adapter filters updated!\n", dev->name);
+                       }
+               }
+
+       /* Update adapter CAM with new unicast address */
+
+       if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
+               {
+               DBG_printk("%s: Could not set new MAC address!\n", dev->name);
+               }
+       else
+               {
+               DBG_printk("%s: Adapter CAM updated with new MAC address\n", dev->name);
+               }
+       return 0;                       /* always return zero */
+       }
+
+
+/*
+ * ======================
+ * = dfx_ctl_update_cam =
+ * ======================
+ *
+ * Overview:
+ *   Procedure to update adapter CAM (Content Addressable Memory)
+ *   with desired unicast and multicast address entries.
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Updates adapter CAM with current contents of board structure
+ *   unicast and multicast address tables.  Since there are only 62
+ *   free entries in CAM, this routine ensures that the command
+ *   request buffer is not overrun.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS - Request succeeded
+ *   DFX_K_FAILURE - Request failed
+ *
+ * Assumptions:
+ *   All addresses being added (unicast and multicast) are in canonical
+ *   order.
+ *
+ * Side Effects:
+ *   On-board adapter CAM is updated.
+ */
+
+static int dfx_ctl_update_cam(DFX_board_t *bp)
+       {
+       int                     i;                              /* used as index */
+       PI_LAN_ADDR     *p_addr;                /* pointer to CAM entry */
+
+       /*
+        * Fill in command request information
+        *
+        * Note: Even though both the unicast and multicast address
+        *       table entries are stored as contiguous 6 byte entries,
+        *               the firmware address filter set command expects each
+        *               entry to be two longwords (8 bytes total).  We must be
+        *               careful to only copy the six bytes of each unicast and
+        *               multicast table entry into each command entry.  This
+        *               is also why we must first clear the entire command
+        *               request buffer.
+        */
+
+       memset(bp->cmd_req_virt, 0, PI_CMD_REQ_K_SIZE_MAX);     /* first clear buffer */
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_ADDR_FILTER_SET;
+       p_addr = &bp->cmd_req_virt->addr_filter_set.entry[0];
+
+       /* Now add unicast addresses to command request buffer, if any */
+
+       for (i=0; i < (int)bp->uc_count; i++)
+               {
+               if (i < PI_CMD_ADDR_FILTER_K_SIZE)
+                       {
+                       memcpy(p_addr, &bp->uc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
+                       p_addr++;                       /* point to next command entry */
+                       }
+               }
+
+       /* Now add multicast addresses to command request buffer, if any */
+
+       for (i=0; i < (int)bp->mc_count; i++)
+               {
+               if ((i + bp->uc_count) < PI_CMD_ADDR_FILTER_K_SIZE)
+                       {
+                       memcpy(p_addr, &bp->mc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
+                       p_addr++;                       /* point to next command entry */
+                       }
+               }
+
+       /* Issue command to update adapter CAM, then return */
+
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               return DFX_K_FAILURE;
+       return DFX_K_SUCCESS;
+       }
+
+
+/*
+ * ==========================
+ * = dfx_ctl_update_filters =
+ * ==========================
+ *
+ * Overview:
+ *   Procedure to update adapter filters with desired
+ *   filter settings.
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Enables or disables filter using current filter settings.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS - Request succeeded.
+ *   DFX_K_FAILURE - Request failed.
+ *
+ * Assumptions:
+ *   We must always pass up packets destined to the broadcast
+ *   address (FF-FF-FF-FF-FF-FF), so we'll always keep the
+ *   broadcast filter enabled.
+ *
+ * Side Effects:
+ *   On-board adapter filters are updated.
+ */
+
+static int dfx_ctl_update_filters(DFX_board_t *bp)
+       {
+       int     i = 0;                                  /* used as index */
+
+       /* Fill in command request information */
+
+       bp->cmd_req_virt->cmd_type = PI_CMD_K_FILTERS_SET;
+
+       /* Initialize Broadcast filter - * ALWAYS ENABLED * */
+
+       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_BROADCAST;
+       bp->cmd_req_virt->filter_set.item[i++].value    = PI_FSTATE_K_PASS;
+
+       /* Initialize LLC Individual/Group Promiscuous filter */
+
+       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_IND_GROUP_PROM;
+       bp->cmd_req_virt->filter_set.item[i++].value    = bp->ind_group_prom;
+
+       /* Initialize LLC Group Promiscuous filter */
+
+       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_GROUP_PROM;
+       bp->cmd_req_virt->filter_set.item[i++].value    = bp->group_prom;
+
+       /* Terminate the item code list */
+
+       bp->cmd_req_virt->filter_set.item[i].item_code  = PI_ITEM_K_EOL;
+
+       /* Issue command to update adapter filters, then return */
+
+       if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+               return DFX_K_FAILURE;
+       return DFX_K_SUCCESS;
+       }
+
+
+/*
+ * ======================
+ * = dfx_hw_dma_cmd_req =
+ * ======================
+ *
+ * Overview:
+ *   Sends PDQ DMA command to adapter firmware
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   The command request and response buffers are posted to the adapter in the manner
+ *   described in the PDQ Port Specification:
+ *
+ *             1. Command Response Buffer is posted to adapter.
+ *             2. Command Request Buffer is posted to adapter.
+ *             3. Command Request consumer index is polled until it indicates that request
+ *         buffer has been DMA'd to adapter.
+ *             4. Command Response consumer index is polled until it indicates that response
+ *         buffer has been DMA'd from adapter.
+ *
+ *   This ordering ensures that a response buffer is already available for the firmware
+ *   to use once it's done processing the request buffer.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS       - DMA command succeeded
+ *      DFX_K_OUTSTATE   - Adapter is NOT in proper state
+ *   DFX_K_HW_TIMEOUT - DMA command timed out
+ *
+ * Assumptions:
+ *   Command request buffer has already been filled with desired DMA command.
+ *
+ * Side Effects:
+ *   None
+ */
+
+static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
+       {
+       int status;                     /* adapter status */
+       int timeout_cnt;        /* used in for loops */
+
+       /* Make sure the adapter is in a state that we can issue the DMA command in */
+
+       status = dfx_hw_adap_state_rd(bp);
+       if ((status == PI_STATE_K_RESET)                ||
+               (status == PI_STATE_K_HALTED)           ||
+               (status == PI_STATE_K_DMA_UNAVAIL)      ||
+               (status == PI_STATE_K_UPGRADE))
+               return DFX_K_OUTSTATE;
+
+       /* Put response buffer on the command response queue */
+
+       bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
+                       ((PI_CMD_RSP_K_SIZE_MAX / PI_ALIGN_K_CMD_RSP_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
+       bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_1 = bp->cmd_rsp_phys;
+
+       /* Bump (and wrap) the producer index and write out to register */
+
+       bp->cmd_rsp_reg.index.prod += 1;
+       bp->cmd_rsp_reg.index.prod &= PI_CMD_RSP_K_NUM_ENTRIES-1;
+       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
+
+       /* Put request buffer on the command request queue */
+
+       bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_0 = (u32) (PI_XMT_DESCR_M_SOP |
+                       PI_XMT_DESCR_M_EOP | (PI_CMD_REQ_K_SIZE_MAX << PI_XMT_DESCR_V_SEG_LEN));
+       bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_1 = bp->cmd_req_phys;
+
+       /* Bump (and wrap) the producer index and write out to register */
+
+       bp->cmd_req_reg.index.prod += 1;
+       bp->cmd_req_reg.index.prod &= PI_CMD_REQ_K_NUM_ENTRIES-1;
+       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
+
+       /*
+        * Here we wait for the command request consumer index to be equal
+        * to the producer, indicating that the adapter has DMAed the request.
+        */
+
+       for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
+               {
+               if (bp->cmd_req_reg.index.prod == (u8)(bp->cons_block_virt->cmd_req))
+                       break;
+               udelay(100);                    /* wait for 100 microseconds */
+               }
+       if (timeout_cnt == 0)
+               return DFX_K_HW_TIMEOUT;
+
+       /* Bump (and wrap) the completion index and write out to register */
+
+       bp->cmd_req_reg.index.comp += 1;
+       bp->cmd_req_reg.index.comp &= PI_CMD_REQ_K_NUM_ENTRIES-1;
+       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
+
+       /*
+        * Here we wait for the command response consumer index to be equal
+        * to the producer, indicating that the adapter has DMAed the response.
+        */
+
+       for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
+               {
+               if (bp->cmd_rsp_reg.index.prod == (u8)(bp->cons_block_virt->cmd_rsp))
+                       break;
+               udelay(100);                    /* wait for 100 microseconds */
+               }
+       if (timeout_cnt == 0)
+               return DFX_K_HW_TIMEOUT;
+
+       /* Bump (and wrap) the completion index and write out to register */
+
+       bp->cmd_rsp_reg.index.comp += 1;
+       bp->cmd_rsp_reg.index.comp &= PI_CMD_RSP_K_NUM_ENTRIES-1;
+       dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
+       return DFX_K_SUCCESS;
+       }
+
+
+/*
+ * ========================
+ * = dfx_hw_port_ctrl_req =
+ * ========================
+ *
+ * Overview:
+ *   Sends PDQ port control command to adapter firmware
+ *
+ * Returns:
+ *   Host data register value in host_data if ptr is not NULL
+ *
+ * Arguments:
+ *   bp                        - pointer to board information
+ *      command        - port control command
+ *      data_a         - port data A register value
+ *      data_b         - port data B register value
+ *      host_data      - ptr to host data register value
+ *
+ * Functional Description:
+ *   Send generic port control command to adapter by writing
+ *   to various PDQ port registers, then polling for completion.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS       - port control command succeeded
+ *   DFX_K_HW_TIMEOUT - port control command timed out
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+static int dfx_hw_port_ctrl_req(
+       DFX_board_t     *bp,
+       PI_UINT32       command,
+       PI_UINT32       data_a,
+       PI_UINT32       data_b,
+       PI_UINT32       *host_data
+       )
+
+       {
+       PI_UINT32       port_cmd;               /* Port Control command register value */
+       int                     timeout_cnt;    /* used in for loops */
+
+       /* Set Command Error bit in command longword */
+
+       port_cmd = (PI_UINT32) (command | PI_PCTRL_M_CMD_ERROR);
+
+       /* Issue port command to the adapter */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, data_a);
+       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_B, data_b);
+       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_CTRL, port_cmd);
+
+       /* Now wait for command to complete */
+
+       if (command == PI_PCTRL_M_BLAST_FLASH)
+               timeout_cnt = 600000;   /* set command timeout count to 60 seconds */
+       else
+               timeout_cnt = 20000;    /* set command timeout count to 2 seconds */
+
+       for (; timeout_cnt > 0; timeout_cnt--)
+               {
+               dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_CTRL, &port_cmd);
+               if (!(port_cmd & PI_PCTRL_M_CMD_ERROR))
+                       break;
+               udelay(100);                    /* wait for 100 microseconds */
+               }
+       if (timeout_cnt == 0)
+               return DFX_K_HW_TIMEOUT;
+
+       /*
+        * If the address of host_data is non-zero, assume caller has supplied a
+        * non NULL pointer, and return the contents of the HOST_DATA register in
+        * it.
+        */
+
+       if (host_data != NULL)
+               dfx_port_read_long(bp, PI_PDQ_K_REG_HOST_DATA, host_data);
+       return DFX_K_SUCCESS;
+       }
+
+
+/*
+ * =====================
+ * = dfx_hw_adap_reset =
+ * =====================
+ *
+ * Overview:
+ *   Resets adapter
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp   - pointer to board information
+ *   type - type of reset to perform
+ *
+ * Functional Description:
+ *   Issue soft reset to adapter by writing to PDQ Port Reset
+ *   register.  Use incoming reset type to tell adapter what
+ *   kind of reset operation to perform.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   This routine merely issues a soft reset to the adapter.
+ *   It is expected that after this routine returns, the caller
+ *   will appropriately poll the Port Status register for the
+ *   adapter to enter the proper state.
+ *
+ * Side Effects:
+ *   Internal adapter registers are cleared.
+ */
+
+static void dfx_hw_adap_reset(
+       DFX_board_t     *bp,
+       PI_UINT32       type
+       )
+
+       {
+       /* Set Reset type and assert reset */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, type);        /* tell adapter type of reset */
+       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, PI_RESET_M_ASSERT_RESET);
+
+       /* Wait for at least 1 Microsecond according to the spec. We wait 20 just to be safe */
+
+       udelay(20);
+
+       /* Deassert reset */
+
+       dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, 0);
+       }
+
+
+/*
+ * ========================
+ * = dfx_hw_adap_state_rd =
+ * ========================
+ *
+ * Overview:
+ *   Returns current adapter state
+ *
+ * Returns:
+ *   Adapter state per PDQ Port Specification
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Reads PDQ Port Status register and returns adapter state.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+static int dfx_hw_adap_state_rd(DFX_board_t *bp)
+       {
+       PI_UINT32 port_status;          /* Port Status register value */
+
+       dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
+       return (port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE;
+       }
+
+
+/*
+ * =====================
+ * = dfx_hw_dma_uninit =
+ * =====================
+ *
+ * Overview:
+ *   Brings adapter to DMA_UNAVAILABLE state
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bp   - pointer to board information
+ *   type - type of reset to perform
+ *
+ * Functional Description:
+ *   Bring adapter to DMA_UNAVAILABLE state by performing the following:
+ *             1. Set reset type bit in Port Data A Register then reset adapter.
+ *             2. Check that adapter is in DMA_UNAVAILABLE state.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS       - adapter is in DMA_UNAVAILABLE state
+ *   DFX_K_HW_TIMEOUT - adapter did not reset properly
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   Internal adapter registers are cleared.
+ */
+
+static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type)
+       {
+       int timeout_cnt;        /* used in for loops */
+
+       /* Set reset type bit and reset adapter */
+
+       dfx_hw_adap_reset(bp, type);
+
+       /* Now wait for adapter to enter DMA_UNAVAILABLE state */
+
+       for (timeout_cnt = 100000; timeout_cnt > 0; timeout_cnt--)
+               {
+               if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_DMA_UNAVAIL)
+                       break;
+               udelay(100);                                    /* wait for 100 microseconds */
+               }
+       if (timeout_cnt == 0)
+               return DFX_K_HW_TIMEOUT;
+       return DFX_K_SUCCESS;
+       }
+
+/*
+ *     Align an sk_buff to a boundary power of 2
+ *
+ */
+
+static void my_skb_align(struct sk_buff *skb, int n)
+{
+       unsigned long x = (unsigned long)skb->data;
+       unsigned long v;
+
+       v = ALIGN(x, n);        /* Where we want to be */
+
+       skb_reserve(skb, v - x);
+}
+
+
+/*
+ * ================
+ * = dfx_rcv_init =
+ * ================
+ *
+ * Overview:
+ *   Produces buffers to adapter LLC Host receive descriptor block
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *   get_buffers - non-zero if buffers to be allocated
+ *
+ * Functional Description:
+ *   This routine can be called during dfx_adap_init() or during an adapter
+ *      reset.  It initializes the descriptor block and produces all allocated
+ *   LLC Host queue receive buffers.
+ *
+ * Return Codes:
+ *   Return 0 on success or -ENOMEM if buffer allocation failed (when using
+ *   dynamic buffer allocation). If the buffer allocation failed, the
+ *   already allocated buffers will not be released and the caller should do
+ *   this.
+ *
+ * Assumptions:
+ *   The PDQ has been reset and the adapter and driver maintained Type 2
+ *   register indices are cleared.
+ *
+ * Side Effects:
+ *   Receive buffers are posted to the adapter LLC queue and the adapter
+ *   is notified.
+ */
+
+static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
+       {
+       int     i, j;                                   /* used in for loop */
+
+       /*
+        *  Since each receive buffer is a single fragment of same length, initialize
+        *  first longword in each receive descriptor for entire LLC Host descriptor
+        *  block.  Also initialize second longword in each receive descriptor with
+        *  physical address of receive buffer.  We'll always allocate receive
+        *  buffers in powers of 2 so that we can easily fill the 256 entry descriptor
+        *  block and produce new receive buffers by simply updating the receive
+        *  producer index.
+        *
+        *      Assumptions:
+        *              To support all shipping versions of PDQ, the receive buffer size
+        *              must be mod 128 in length and the physical address must be 128 byte
+        *              aligned.  In other words, bits 0-6 of the length and address must
+        *              be zero for the following descriptor field entries to be correct on
+        *              all PDQ-based boards.  We guaranteed both requirements during
+        *              driver initialization when we allocated memory for the receive buffers.
+        */
+
+       if (get_buffers) {
+#ifdef DYNAMIC_BUFFERS
+       for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
+               for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
+               {
+                       struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO);
+                       if (!newskb)
+                               return -ENOMEM;
+                       bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
+                               ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
+                       /*
+                        * align to 128 bytes for compatibility with
+                        * the old EISA boards.
+                        */
+
+                       my_skb_align(newskb, 128);
+                       bp->descr_block_virt->rcv_data[i + j].long_1 =
+                               (u32)dma_map_single(bp->bus_dev, newskb->data,
+                                                   NEW_SKB_SIZE,
+                                                   DMA_FROM_DEVICE);
+                       /*
+                        * p_rcv_buff_va is only used inside the
+                        * kernel so we put the skb pointer here.
+                        */
+                       bp->p_rcv_buff_va[i+j] = (char *) newskb;
+               }
+#else
+       for (i=0; i < (int)(bp->rcv_bufs_to_post); i++)
+               for (j=0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
+                       {
+                       bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
+                               ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
+                       bp->descr_block_virt->rcv_data[i+j].long_1 = (u32) (bp->rcv_block_phys + (i * PI_RCV_DATA_K_SIZE_MAX));
+                       bp->p_rcv_buff_va[i+j] = (char *) (bp->rcv_block_virt + (i * PI_RCV_DATA_K_SIZE_MAX));
+                       }
+#endif
+       }
+
+       /* Update receive producer and Type 2 register */
+
+       bp->rcv_xmt_reg.index.rcv_prod = bp->rcv_bufs_to_post;
+       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+       return 0;
+       }
+
+
+/*
+ * =========================
+ * = dfx_rcv_queue_process =
+ * =========================
+ *
+ * Overview:
+ *   Process received LLC frames.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Received LLC frames are processed until there are no more consumed frames.
+ *   Once all frames are processed, the receive buffers are returned to the
+ *   adapter.  Note that this algorithm fixes the length of time that can be spent
+ *   in this routine, because there are a fixed number of receive buffers to
+ *   process and buffers are not produced until this routine exits and returns
+ *   to the ISR.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+static void dfx_rcv_queue_process(
+       DFX_board_t *bp
+       )
+
+       {
+       PI_TYPE_2_CONSUMER      *p_type_2_cons;         /* ptr to rcv/xmt consumer block register */
+       char                            *p_buff;                        /* ptr to start of packet receive buffer (FMC descriptor) */
+       u32                                     descr, pkt_len;         /* FMC descriptor field and packet length */
+       struct sk_buff          *skb;                           /* pointer to a sk_buff to hold incoming packet data */
+
+       /* Service all consumed LLC receive frames */
+
+       p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
+       while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons)
+               {
+               /* Process any errors */
+
+               int entry;
+
+               entry = bp->rcv_xmt_reg.index.rcv_comp;
+#ifdef DYNAMIC_BUFFERS
+               p_buff = (char *) (((struct sk_buff *)bp->p_rcv_buff_va[entry])->data);
+#else
+               p_buff = (char *) bp->p_rcv_buff_va[entry];
+#endif
+               memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));
+
+               if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
+                       {
+                       if (descr & PI_FMC_DESCR_M_RCC_CRC)
+                               bp->rcv_crc_errors++;
+                       else
+                               bp->rcv_frame_status_errors++;
+                       }
+               else
+               {
+                       int rx_in_place = 0;
+
+                       /* The frame was received without errors - verify packet length */
+
+                       pkt_len = (u32)((descr & PI_FMC_DESCR_M_LEN) >> PI_FMC_DESCR_V_LEN);
+                       pkt_len -= 4;                           /* subtract 4 byte CRC */
+                       if (!IN_RANGE(pkt_len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
+                               bp->rcv_length_errors++;
+                       else{
+#ifdef DYNAMIC_BUFFERS
+                               if (pkt_len > SKBUFF_RX_COPYBREAK) {
+                                       struct sk_buff *newskb;
+
+                                       newskb = dev_alloc_skb(NEW_SKB_SIZE);
+                                       if (newskb){
+                                               rx_in_place = 1;
+
+                                               my_skb_align(newskb, 128);
+                                               skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
+                                               dma_unmap_single(bp->bus_dev,
+                                                       bp->descr_block_virt->rcv_data[entry].long_1,
+                                                       NEW_SKB_SIZE,
+                                                       DMA_FROM_DEVICE);
+                                               skb_reserve(skb, RCV_BUFF_K_PADDING);
+                                               bp->p_rcv_buff_va[entry] = (char *)newskb;
+                                               bp->descr_block_virt->rcv_data[entry].long_1 =
+                                                       (u32)dma_map_single(bp->bus_dev,
+                                                               newskb->data,
+                                                               NEW_SKB_SIZE,
+                                                               DMA_FROM_DEVICE);
+                                       } else
+                                               skb = NULL;
+                               } else
+#endif
+                                       skb = dev_alloc_skb(pkt_len+3); /* alloc new buffer to pass up, add room for PRH */
+                               if (skb == NULL)
+                                       {
+                                       printk("%s: Could not allocate receive buffer.  Dropping packet.\n", bp->dev->name);
+                                       bp->rcv_discards++;
+                                       break;
+                                       }
+                               else {
+#ifndef DYNAMIC_BUFFERS
+                                       if (! rx_in_place)
+#endif
+                                       {
+                                               /* Receive buffer allocated, pass receive packet up */
+
+                                               skb_copy_to_linear_data(skb,
+                                                              p_buff + RCV_BUFF_K_PADDING,
+                                                              pkt_len + 3);
+                                       }
+
+                                       skb_reserve(skb,3);             /* adjust data field so that it points to FC byte */
+                                       skb_put(skb, pkt_len);          /* pass up packet length, NOT including CRC */
+                                       skb->protocol = fddi_type_trans(skb, bp->dev);
+                                       bp->rcv_total_bytes += skb->len;
+                                       netif_rx(skb);
+
+                                       /* Update the rcv counters */
+                                       bp->rcv_total_frames++;
+                                       if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
+                                               bp->rcv_multicast_frames++;
+                               }
+                       }
+                       }
+
+               /*
+                * Advance the producer (for recycling) and advance the completion
+                * (for servicing received frames).  Note that it is okay to
+                * advance the producer without checking that it passes the
+                * completion index because they are both advanced at the same
+                * rate.
+                */
+
+               bp->rcv_xmt_reg.index.rcv_prod += 1;
+               bp->rcv_xmt_reg.index.rcv_comp += 1;
+               }
+       }
+
+
+/*
+ * =====================
+ * = dfx_xmt_queue_pkt =
+ * =====================
+ *
+ * Overview:
+ *   Queues packets for transmission
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   skb - pointer to sk_buff to queue for transmission
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Here we assume that an incoming skb transmit request
+ *   is contained in a single physically contiguous buffer
+ *   in which the virtual address of the start of packet
+ *   (skb->data) can be converted to a physical address
+ *   by using pci_map_single().
+ *
+ *   Since the adapter architecture requires a three byte
+ *   packet request header to prepend the start of packet,
+ *   we'll write the three byte field immediately prior to
+ *   the FC byte.  This assumption is valid because we've
+ *   ensured that dev->hard_header_len includes three pad
+ *   bytes.  By posting a single fragment to the adapter,
+ *   we'll reduce the number of descriptor fetches and
+ *   bus traffic needed to send the request.
+ *
+ *   Also, we can't free the skb until after it's been DMA'd
+ *   out by the adapter, so we'll queue it in the driver and
+ *   return it in dfx_xmt_done.
+ *
+ * Return Codes:
+ *   0 - driver queued packet, link is unavailable, or skbuff was bad
+ *      1 - caller should requeue the sk_buff for later transmission
+ *
+ * Assumptions:
+ *      First and foremost, we assume the incoming skb pointer
+ *   is NOT NULL and is pointing to a valid sk_buff structure.
+ *
+ *   The outgoing packet is complete, starting with the
+ *   frame control byte including the last byte of data,
+ *   but NOT including the 4 byte CRC.  We'll let the
+ *   adapter hardware generate and append the CRC.
+ *
+ *   The entire packet is stored in one physically
+ *   contiguous buffer which is not cached and whose
+ *   32-bit physical address can be determined.
+ *
+ *   It's vital that this routine is NOT reentered for the
+ *   same board and that the OS is not in another section of
+ *   code (eg. dfx_int_common) for the same board on a
+ *   different thread.
+ *
+ * Side Effects:
+ *   None
+ */
+
+static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
+                                    struct net_device *dev)
+       {
+       DFX_board_t             *bp = netdev_priv(dev);
+       u8                      prod;                           /* local transmit producer index */
+       PI_XMT_DESCR            *p_xmt_descr;           /* ptr to transmit descriptor block entry */
+       XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
+       unsigned long           flags;
+
+       netif_stop_queue(dev);
+
+       /*
+        * Verify that incoming transmit request is OK
+        *
+        * Note: The packet size check is consistent with other
+        *               Linux device drivers, although the correct packet
+        *               size should be verified before calling the
+        *               transmit routine.
+        */
+
+       if (!IN_RANGE(skb->len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
+       {
+               printk("%s: Invalid packet length - %u bytes\n",
+                       dev->name, skb->len);
+               bp->xmt_length_errors++;                /* bump error counter */
+               netif_wake_queue(dev);
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;                    /* return "success" */
+       }
+       /*
+        * See if adapter link is available, if not, free buffer
+        *
+        * Note: If the link isn't available, free buffer and return 0
+        *               rather than tell the upper layer to requeue the packet.
+        *               The methodology here is that by the time the link
+        *               becomes available, the packet to be sent will be
+        *               fairly stale.  By simply dropping the packet, the
+        *               higher layer protocols will eventually time out
+        *               waiting for response packets which it won't receive.
+        */
+
+       if (bp->link_available == PI_K_FALSE)
+               {
+               if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_LINK_AVAIL)  /* is link really available? */
+                       bp->link_available = PI_K_TRUE;         /* if so, set flag and continue */
+               else
+                       {
+                       bp->xmt_discards++;                                     /* bump error counter */
+                       dev_kfree_skb(skb);             /* free sk_buff now */
+                       netif_wake_queue(dev);
+                       return NETDEV_TX_OK;            /* return "success" */
+                       }
+               }
+
+       spin_lock_irqsave(&bp->lock, flags);
+
+       /* Get the current producer and the next free xmt data descriptor */
+
+       prod            = bp->rcv_xmt_reg.index.xmt_prod;
+       p_xmt_descr = &(bp->descr_block_virt->xmt_data[prod]);
+
+       /*
+        * Get pointer to auxiliary queue entry to contain information
+        * for this packet.
+        *
+        * Note: The current xmt producer index will become the
+        *       current xmt completion index when we complete this
+        *       packet later on.  So, we'll get the pointer to the
+        *       next auxiliary queue entry now before we bump the
+        *       producer index.
+        */
+
+       p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]);     /* also bump producer index */
+
+       /* Write the three PRH bytes immediately before the FC byte */
+
+       skb_push(skb,3);
+       skb->data[0] = DFX_PRH0_BYTE;   /* these byte values are defined */
+       skb->data[1] = DFX_PRH1_BYTE;   /* in the Motorola FDDI MAC chip */
+       skb->data[2] = DFX_PRH2_BYTE;   /* specification */
+
+       /*
+        * Write the descriptor with buffer info and bump producer
+        *
+        * Note: Since we need to start DMA from the packet request
+        *               header, we'll add 3 bytes to the DMA buffer length,
+        *               and we'll determine the physical address of the
+        *               buffer from the PRH, not skb->data.
+        *
+        * Assumptions:
+        *               1. Packet starts with the frame control (FC) byte
+        *                  at skb->data.
+        *               2. The 4-byte CRC is not appended to the buffer or
+        *                      included in the length.
+        *               3. Packet length (skb->len) is from FC to end of
+        *                      data, inclusive.
+        *               4. The packet length does not exceed the maximum
+        *                      FDDI LLC frame length of 4491 bytes.
+        *               5. The entire packet is contained in a physically
+        *                      contiguous, non-cached, locked memory space
+        *                      comprised of a single buffer pointed to by
+        *                      skb->data.
+        *               6. The physical address of the start of packet
+        *                      can be determined from the virtual address
+        *                      by using pci_map_single() and is only 32-bits
+        *                      wide.
+        */
+
+       p_xmt_descr->long_0     = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
+       p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
+                                                 skb->len, DMA_TO_DEVICE);
+
+       /*
+        * Verify that descriptor is actually available
+        *
+        * Note: If descriptor isn't available, return 1 which tells
+        *       the upper layer to requeue the packet for later
+        *       transmission.
+        *
+        *       We need to ensure that the producer never reaches the
+        *       completion, except to indicate that the queue is empty.
+        */
+
+       if (prod == bp->rcv_xmt_reg.index.xmt_comp)
+       {
+               skb_pull(skb,3);
+               spin_unlock_irqrestore(&bp->lock, flags);
+               return NETDEV_TX_BUSY;  /* requeue packet for later */
+       }
+
+       /*
+        * Save info for this packet for xmt done indication routine
+        *
+        * Normally, we'd save the producer index in the p_xmt_drv_descr
+        * structure so that we'd have it handy when we complete this
+        * packet later (in dfx_xmt_done).  However, since the current
+        * transmit architecture guarantees a single fragment for the
+        * entire packet, we can simply bump the completion index by
+        * one (1) for each completed packet.
+        *
+        * Note: If this assumption changes and we're presented with
+        *       an inconsistent number of transmit fragments for packet
+        *       data, we'll need to modify this code to save the current
+        *       transmit producer index.
+        */
+
+       p_xmt_drv_descr->p_skb = skb;
+
+       /* Update Type 2 register */
+
+       bp->rcv_xmt_reg.index.xmt_prod = prod;
+       dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+       spin_unlock_irqrestore(&bp->lock, flags);
+       netif_wake_queue(dev);
+       return NETDEV_TX_OK;    /* packet queued to adapter */
+       }
+
+
+/*
+ * ================
+ * = dfx_xmt_done =
+ * ================
+ *
+ * Overview:
+ *   Processes all frames that have been transmitted.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   For all consumed transmit descriptors that have not
+ *   yet been completed, we'll free the skb we were holding
+ *   onto using dev_kfree_skb and bump the appropriate
+ *   counters.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   The Type 2 register is not updated in this routine.  It is
+ *   assumed that it will be updated in the ISR when dfx_xmt_done
+ *   returns.
+ *
+ * Side Effects:
+ *   None
+ */
+
+static int dfx_xmt_done(DFX_board_t *bp)
+       {
+       XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
+       PI_TYPE_2_CONSUMER      *p_type_2_cons;         /* ptr to rcv/xmt consumer block register */
+       u8                      comp;                   /* local transmit completion index */
+       int                     freed = 0;              /* buffers freed */
+
+       /* Service all consumed transmit frames */
+
+       p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
+       while (bp->rcv_xmt_reg.index.xmt_comp != p_type_2_cons->index.xmt_cons)
+               {
+               /* Get pointer to the transmit driver descriptor block information */
+
+               p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
+
+               /* Increment transmit counters */
+
+               bp->xmt_total_frames++;
+               bp->xmt_total_bytes += p_xmt_drv_descr->p_skb->len;
+
+               /* Return skb to operating system */
+               comp = bp->rcv_xmt_reg.index.xmt_comp;
+               dma_unmap_single(bp->bus_dev,
+                                bp->descr_block_virt->xmt_data[comp].long_1,
+                                p_xmt_drv_descr->p_skb->len,
+                                DMA_TO_DEVICE);
+               dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
+
+               /*
+                * Move to start of next packet by updating completion index
+                *
+                * Here we assume that a transmit packet request is always
+                * serviced by posting one fragment.  We can therefore
+                * simplify the completion code by incrementing the
+                * completion index by one.  This code will need to be
+                * modified if this assumption changes.  See comments
+                * in dfx_xmt_queue_pkt for more details.
+                */
+
+               bp->rcv_xmt_reg.index.xmt_comp += 1;
+               freed++;
+               }
+       return freed;
+       }
+
+
+/*
+ * =================
+ * = dfx_rcv_flush =
+ * =================
+ *
+ * Overview:
+ *   Remove all skb's in the receive ring.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Free's all the dynamically allocated skb's that are
+ *   currently attached to the device receive ring. This
+ *   function is typically only used when the device is
+ *   initialized or reinitialized.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+#ifdef DYNAMIC_BUFFERS
+static void dfx_rcv_flush( DFX_board_t *bp )
+       {
+       int i, j;
+
+       for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
+               for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
+               {
+                       struct sk_buff *skb;
+                       skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j];
+                       if (skb)
+                               dev_kfree_skb(skb);
+                       bp->p_rcv_buff_va[i+j] = NULL;
+               }
+
+       }
+#else
+static inline void dfx_rcv_flush( DFX_board_t *bp )
+{
+}
+#endif /* DYNAMIC_BUFFERS */
+
+/*
+ * =================
+ * = dfx_xmt_flush =
+ * =================
+ *
+ * Overview:
+ *   Processes all frames whether they've been transmitted
+ *   or not.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   For all produced transmit descriptors that have not
+ *   yet been completed, we'll free the skb we were holding
+ *   onto using dev_kfree_skb and bump the appropriate
+ *   counters.  Of course, it's possible that some of
+ *   these transmit requests actually did go out, but we
+ *   won't make that distinction here.  Finally, we'll
+ *   update the consumer index to match the producer.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   This routine does NOT update the Type 2 register.  It
+ *   is assumed that this routine is being called during a
+ *   transmit flush interrupt, or a shutdown or close routine.
+ *
+ * Side Effects:
+ *   None
+ */
+
+static void dfx_xmt_flush( DFX_board_t *bp )
+       {
+       u32                     prod_cons;              /* rcv/xmt consumer block longword */
+       XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
+       u8                      comp;                   /* local transmit completion index */
+
+       /* Flush all outstanding transmit frames */
+
+       while (bp->rcv_xmt_reg.index.xmt_comp != bp->rcv_xmt_reg.index.xmt_prod)
+               {
+               /* Get pointer to the transmit driver descriptor block information */
+
+               p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
+
+               /* Return skb to operating system */
+               comp = bp->rcv_xmt_reg.index.xmt_comp;
+               dma_unmap_single(bp->bus_dev,
+                                bp->descr_block_virt->xmt_data[comp].long_1,
+                                p_xmt_drv_descr->p_skb->len,
+                                DMA_TO_DEVICE);
+               dev_kfree_skb(p_xmt_drv_descr->p_skb);
+
+               /* Increment transmit error counter */
+
+               bp->xmt_discards++;
+
+               /*
+                * Move to start of next packet by updating completion index
+                *
+                * Here we assume that a transmit packet request is always
+                * serviced by posting one fragment.  We can therefore
+                * simplify the completion code by incrementing the
+                * completion index by one.  This code will need to be
+                * modified if this assumption changes.  See comments
+                * in dfx_xmt_queue_pkt for more details.
+                */
+
+               bp->rcv_xmt_reg.index.xmt_comp += 1;
+               }
+
+       /* Update the transmit consumer index in the consumer block */
+
+       prod_cons = (u32)(bp->cons_block_virt->xmt_rcv_data & ~PI_CONS_M_XMT_INDEX);
+       prod_cons |= (u32)(bp->rcv_xmt_reg.index.xmt_prod << PI_CONS_V_XMT_INDEX);
+       bp->cons_block_virt->xmt_rcv_data = prod_cons;
+       }
+
+/*
+ * ==================
+ * = dfx_unregister =
+ * ==================
+ *
+ * Overview:
+ *   Shuts down an FDDI controller
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bdev - pointer to device information
+ *
+ * Functional Description:
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   It compiles so it should work :-( (PCI cards do :-)
+ *
+ * Side Effects:
+ *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ *   freed.
+ */
+static void __devexit dfx_unregister(struct device *bdev)
+{
+       struct net_device *dev = dev_get_drvdata(bdev);
+       DFX_board_t *bp = netdev_priv(dev);
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       resource_size_t bar_start = 0;          /* pointer to port */
+       resource_size_t bar_len = 0;            /* resource length */
+       int             alloc_size;             /* total buffer size used */
+
+       unregister_netdev(dev);
+
+       alloc_size = sizeof(PI_DESCR_BLOCK) +
+                    PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
+#ifndef DYNAMIC_BUFFERS
+                    (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
+#endif
+                    sizeof(PI_CONSUMER_BLOCK) +
+                    (PI_ALIGN_K_DESC_BLK - 1);
+       if (bp->kmalloced)
+               dma_free_coherent(bdev, alloc_size,
+                                 bp->kmalloced, bp->kmalloced_dma);
+
+       dfx_bus_uninit(dev);
+
+       dfx_get_bars(bdev, &bar_start, &bar_len);
+       if (dfx_use_mmio) {
+               iounmap(bp->base.mem);
+               release_mem_region(bar_start, bar_len);
+       } else
+               release_region(bar_start, bar_len);
+
+       if (dfx_bus_pci)
+               pci_disable_device(to_pci_dev(bdev));
+
+       free_netdev(dev);
+}
+
+
+static int __devinit __maybe_unused dfx_dev_register(struct device *);
+static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
+
+#ifdef CONFIG_PCI
+static int __devinit dfx_pci_register(struct pci_dev *,
+                                     const struct pci_device_id *);
+static void __devexit dfx_pci_unregister(struct pci_dev *);
+
+static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, dfx_pci_table);
+
+static struct pci_driver dfx_pci_driver = {
+       .name           = "defxx",
+       .id_table       = dfx_pci_table,
+       .probe          = dfx_pci_register,
+       .remove         = __devexit_p(dfx_pci_unregister),
+};
+
+static __devinit int dfx_pci_register(struct pci_dev *pdev,
+                                     const struct pci_device_id *ent)
+{
+       return dfx_register(&pdev->dev);
+}
+
+static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
+{
+       dfx_unregister(&pdev->dev);
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id dfx_eisa_table[] = {
+        { "DEC3001", DEFEA_PROD_ID_1 },
+        { "DEC3002", DEFEA_PROD_ID_2 },
+        { "DEC3003", DEFEA_PROD_ID_3 },
+        { "DEC3004", DEFEA_PROD_ID_4 },
+        { }
+};
+MODULE_DEVICE_TABLE(eisa, dfx_eisa_table);
+
+static struct eisa_driver dfx_eisa_driver = {
+       .id_table       = dfx_eisa_table,
+       .driver         = {
+               .name   = "defxx",
+               .bus    = &eisa_bus_type,
+               .probe  = dfx_dev_register,
+               .remove = __devexit_p(dfx_dev_unregister),
+       },
+};
+#endif /* CONFIG_EISA */
+
+#ifdef CONFIG_TC
+static struct tc_device_id const dfx_tc_table[] = {
+       { "DEC     ", "PMAF-FA " },
+       { "DEC     ", "PMAF-FD " },
+       { "DEC     ", "PMAF-FS " },
+       { "DEC     ", "PMAF-FU " },
+       { }
+};
+MODULE_DEVICE_TABLE(tc, dfx_tc_table);
+
+static struct tc_driver dfx_tc_driver = {
+       .id_table       = dfx_tc_table,
+       .driver         = {
+               .name   = "defxx",
+               .bus    = &tc_bus_type,
+               .probe  = dfx_dev_register,
+               .remove = __devexit_p(dfx_dev_unregister),
+       },
+};
+#endif /* CONFIG_TC */
+
+static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
+{
+       int status;
+
+       status = dfx_register(dev);
+       if (!status)
+               get_device(dev);
+       return status;
+}
+
+static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
+{
+       put_device(dev);
+       dfx_unregister(dev);
+       return 0;
+}
+
+
+static int __devinit dfx_init(void)
+{
+       int status;
+
+       status = pci_register_driver(&dfx_pci_driver);
+       if (!status)
+               status = eisa_driver_register(&dfx_eisa_driver);
+       if (!status)
+               status = tc_register_driver(&dfx_tc_driver);
+       return status;
+}
+
+static void __devexit dfx_cleanup(void)
+{
+       tc_unregister_driver(&dfx_tc_driver);
+       eisa_driver_unregister(&dfx_eisa_driver);
+       pci_unregister_driver(&dfx_pci_driver);
+}
+
+module_init(dfx_init);
+module_exit(dfx_cleanup);
+MODULE_AUTHOR("Lawrence V. Stefani");
+MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver "
+                  DRV_VERSION " " DRV_RELDATE);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/fddi/defxx.h b/drivers/net/fddi/defxx.h
new file mode 100644 (file)
index 0000000..19a6f64
--- /dev/null
@@ -0,0 +1,1801 @@
+/*
+ * File Name:
+ *   defxx.h
+ *
+ * Copyright Information:
+ *   Copyright Digital Equipment Corporation 1996.
+ *
+ *   This software may be used and distributed according to the terms of
+ *   the GNU General Public License, incorporated herein by reference.
+ *
+ * Abstract:
+ *   Contains all definitions specified by port specification and required
+ *   by the defxx.c driver.
+ *
+ * The original author:
+ *   LVS       Lawrence V. Stefani <lstefani@yahoo.com>
+ *
+ * Maintainers:
+ *   macro     Maciej W. Rozycki <macro@linux-mips.org>
+ *
+ * Modification History:
+ *             Date            Name    Description
+ *             16-Aug-96       LVS             Created.
+ *             09-Sep-96       LVS             Added group_prom field.  Moved read/write I/O
+ *                                                     macros to DEFXX.C.
+ *             12-Sep-96       LVS             Removed packet request header pointers.
+ *             04 Aug 2003     macro           Converted to the DMA API.
+ *             23 Oct 2006     macro           Big-endian host support.
+ *             14 Dec 2006     macro           TURBOchannel support.
+ */
+
+#ifndef _DEFXX_H_
+#define _DEFXX_H_
+
+/* Define basic types for unsigned chars, shorts, longs */
+
+typedef u8     PI_UINT8;
+typedef u16    PI_UINT16;
+typedef u32    PI_UINT32;
+
+/* Define general structures */
+
+typedef struct                                                 /* 64-bit counter */
+       {
+       PI_UINT32  ms;
+       PI_UINT32  ls;
+       } PI_CNTR;
+
+typedef struct                                                 /* LAN address */
+       {
+       PI_UINT32  lwrd_0;
+       PI_UINT32  lwrd_1;
+       } PI_LAN_ADDR;
+
+typedef struct                                                 /* Station ID address */
+       {
+       PI_UINT32  octet_7_4;
+       PI_UINT32  octet_3_0;
+       } PI_STATION_ID;
+
+
+/* Define general constants */
+
+#define PI_ALIGN_K_DESC_BLK                            8192    /* Descriptor block boundary            */
+#define PI_ALIGN_K_CONS_BLK                            64              /* Consumer block boundary                      */
+#define PI_ALIGN_K_CMD_REQ_BUFF                128             /* Xmt Command que buffer alignment */
+#define PI_ALIGN_K_CMD_RSP_BUFF                        128             /* Rcv Command que buffer alignment */
+#define PI_ALIGN_K_UNSOL_BUFF                  128             /* Unsol que buffer alignment           */
+#define PI_ALIGN_K_XMT_DATA_BUFF               0               /* Xmt data que buffer alignment        */
+#define PI_ALIGN_K_RCV_DATA_BUFF               128             /* Rcv que buffer alignment                     */
+
+/* Define PHY index values */
+
+#define PI_PHY_K_S                                             0               /* Index to S phy */
+#define PI_PHY_K_A                                             0               /* Index to A phy */
+#define PI_PHY_K_B                                             1               /* Index to B phy */
+#define PI_PHY_K_MAX                                   2               /* Max number of phys */
+
+/* Define FMC descriptor fields */
+
+#define PI_FMC_DESCR_V_SOP                             31
+#define PI_FMC_DESCR_V_EOP                             30
+#define PI_FMC_DESCR_V_FSC                             27
+#define PI_FMC_DESCR_V_FSB_ERROR               26
+#define PI_FMC_DESCR_V_FSB_ADDR_RECOG  25
+#define PI_FMC_DESCR_V_FSB_ADDR_COPIED 24
+#define PI_FMC_DESCR_V_FSB                             22
+#define PI_FMC_DESCR_V_RCC_FLUSH               21
+#define PI_FMC_DESCR_V_RCC_CRC                 20
+#define PI_FMC_DESCR_V_RCC_RRR                 17
+#define PI_FMC_DESCR_V_RCC_DD                  15
+#define PI_FMC_DESCR_V_RCC_SS                  13
+#define PI_FMC_DESCR_V_RCC                             13
+#define PI_FMC_DESCR_V_LEN                             0
+
+#define PI_FMC_DESCR_M_SOP                             0x80000000
+#define PI_FMC_DESCR_M_EOP                             0x40000000
+#define PI_FMC_DESCR_M_FSC                             0x38000000
+#define PI_FMC_DESCR_M_FSB_ERROR               0x04000000
+#define PI_FMC_DESCR_M_FSB_ADDR_RECOG  0x02000000
+#define PI_FMC_DESCR_M_FSB_ADDR_COPIED 0x01000000
+#define PI_FMC_DESCR_M_FSB                             0x07C00000
+#define PI_FMC_DESCR_M_RCC_FLUSH               0x00200000
+#define PI_FMC_DESCR_M_RCC_CRC                 0x00100000
+#define PI_FMC_DESCR_M_RCC_RRR                 0x000E0000
+#define PI_FMC_DESCR_M_RCC_DD                  0x00018000
+#define PI_FMC_DESCR_M_RCC_SS                  0x00006000
+#define PI_FMC_DESCR_M_RCC                             0x003FE000
+#define PI_FMC_DESCR_M_LEN                             0x00001FFF
+
+#define PI_FMC_DESCR_K_RCC_FMC_INT_ERR 0x01AA
+
+#define PI_FMC_DESCR_K_RRR_SUCCESS             0x00
+#define PI_FMC_DESCR_K_RRR_SA_MATCH            0x01
+#define PI_FMC_DESCR_K_RRR_DA_MATCH            0x02
+#define PI_FMC_DESCR_K_RRR_FMC_ABORT   0x03
+#define PI_FMC_DESCR_K_RRR_LENGTH_BAD  0x04
+#define PI_FMC_DESCR_K_RRR_FRAGMENT            0x05
+#define PI_FMC_DESCR_K_RRR_FORMAT_ERR  0x06
+#define PI_FMC_DESCR_K_RRR_MAC_RESET   0x07
+
+#define PI_FMC_DESCR_K_DD_NO_MATCH             0x0
+#define PI_FMC_DESCR_K_DD_PROMISCUOUS  0x1
+#define PI_FMC_DESCR_K_DD_CAM_MATCH            0x2
+#define PI_FMC_DESCR_K_DD_LOCAL_MATCH  0x3
+
+#define PI_FMC_DESCR_K_SS_NO_MATCH             0x0
+#define PI_FMC_DESCR_K_SS_BRIDGE_MATCH 0x1
+#define PI_FMC_DESCR_K_SS_NOT_POSSIBLE 0x2
+#define PI_FMC_DESCR_K_SS_LOCAL_MATCH  0x3
+
+/* Define some max buffer sizes */
+
+#define PI_CMD_REQ_K_SIZE_MAX                  512
+#define PI_CMD_RSP_K_SIZE_MAX                  512
+#define PI_UNSOL_K_SIZE_MAX                            512
+#define PI_SMT_HOST_K_SIZE_MAX                 4608            /* 4 1/2 K */
+#define PI_RCV_DATA_K_SIZE_MAX                 4608            /* 4 1/2 K */
+#define PI_XMT_DATA_K_SIZE_MAX                 4608            /* 4 1/2 K */
+
+/* Define adapter states */
+
+#define PI_STATE_K_RESET                               0
+#define PI_STATE_K_UPGRADE                             1
+#define PI_STATE_K_DMA_UNAVAIL                 2
+#define PI_STATE_K_DMA_AVAIL                   3
+#define PI_STATE_K_LINK_AVAIL                  4
+#define PI_STATE_K_LINK_UNAVAIL                        5
+#define PI_STATE_K_HALTED                              6
+#define PI_STATE_K_RING_MEMBER                 7
+#define PI_STATE_K_NUMBER                              8
+
+/* Define codes for command type */
+
+#define PI_CMD_K_START                                 0x00
+#define PI_CMD_K_FILTERS_SET                   0x01
+#define PI_CMD_K_FILTERS_GET                   0x02
+#define PI_CMD_K_CHARS_SET                             0x03
+#define PI_CMD_K_STATUS_CHARS_GET              0x04
+#define PI_CMD_K_CNTRS_GET                             0x05
+#define PI_CMD_K_CNTRS_SET                             0x06
+#define PI_CMD_K_ADDR_FILTER_SET               0x07
+#define PI_CMD_K_ADDR_FILTER_GET               0x08
+#define PI_CMD_K_ERROR_LOG_CLEAR               0x09
+#define PI_CMD_K_ERROR_LOG_GET                 0x0A
+#define PI_CMD_K_FDDI_MIB_GET                  0x0B
+#define PI_CMD_K_DEC_EXT_MIB_GET               0x0C
+#define PI_CMD_K_DEVICE_SPECIFIC_GET   0x0D
+#define PI_CMD_K_SNMP_SET                              0x0E
+#define PI_CMD_K_UNSOL_TEST                            0x0F
+#define PI_CMD_K_SMT_MIB_GET                   0x10
+#define PI_CMD_K_SMT_MIB_SET                   0x11
+#define PI_CMD_K_MAX                                   0x11    /* Must match last */
+
+/* Define item codes for Chars_Set and Filters_Set commands */
+
+#define PI_ITEM_K_EOL                                  0x00    /* End-of-Item list               */
+#define PI_ITEM_K_T_REQ                                        0x01    /* DECnet T_REQ                           */
+#define PI_ITEM_K_TVX                                  0x02    /* DECnet TVX                             */
+#define PI_ITEM_K_RESTRICTED_TOKEN             0x03    /* DECnet Restricted Token        */
+#define PI_ITEM_K_LEM_THRESHOLD                        0x04    /* DECnet LEM Threshold           */
+#define PI_ITEM_K_RING_PURGER                  0x05    /* DECnet Ring Purger Enable  */
+#define PI_ITEM_K_CNTR_INTERVAL                        0x06    /* Chars_Set                              */
+#define PI_ITEM_K_IND_GROUP_PROM               0x07    /* Filters_Set                            */
+#define PI_ITEM_K_GROUP_PROM                   0x08    /* Filters_Set                            */
+#define PI_ITEM_K_BROADCAST                            0x09    /* Filters_Set                            */
+#define PI_ITEM_K_SMT_PROM                             0x0A    /* Filters_Set                            */
+#define PI_ITEM_K_SMT_USER                             0x0B    /* Filters_Set                            */
+#define PI_ITEM_K_RESERVED                             0x0C    /* Filters_Set                            */
+#define PI_ITEM_K_IMPLEMENTOR                  0x0D    /* Filters_Set                            */
+#define PI_ITEM_K_LOOPBACK_MODE                        0x0E    /* Chars_Set                              */
+#define PI_ITEM_K_CONFIG_POLICY                        0x10    /* SMTConfigPolicy                        */
+#define PI_ITEM_K_CON_POLICY                   0x11    /* SMTConnectionPolicy            */
+#define PI_ITEM_K_T_NOTIFY                             0x12    /* SMTTNotify                             */
+#define PI_ITEM_K_STATION_ACTION               0x13    /* SMTStationAction                       */
+#define PI_ITEM_K_MAC_PATHS_REQ                        0x15    /* MACPathsRequested              */
+#define PI_ITEM_K_MAC_ACTION                   0x17    /* MACAction                              */
+#define PI_ITEM_K_CON_POLICIES                 0x18    /* PORTConnectionPolicies         */
+#define PI_ITEM_K_PORT_PATHS_REQ               0x19    /* PORTPathsRequested             */
+#define PI_ITEM_K_MAC_LOOP_TIME                        0x1A    /* PORTMACLoopTime                        */
+#define PI_ITEM_K_TB_MAX                               0x1B    /* PORTTBMax                              */
+#define PI_ITEM_K_LER_CUTOFF                   0x1C    /* PORTLerCutoff                          */
+#define PI_ITEM_K_LER_ALARM                            0x1D    /* PORTLerAlarm                           */
+#define PI_ITEM_K_PORT_ACTION                  0x1E    /* PORTAction                             */
+#define PI_ITEM_K_FLUSH_TIME                   0x20    /* Chars_Set                              */
+#define PI_ITEM_K_MAC_T_REQ                            0x29    /* MACTReq                                        */
+#define PI_ITEM_K_EMAC_RING_PURGER             0x2A    /* eMACRingPurgerEnable           */
+#define PI_ITEM_K_EMAC_RTOKEN_TIMEOUT  0x2B    /* eMACRestrictedTokenTimeout */
+#define PI_ITEM_K_FDX_ENB_DIS                  0x2C    /* eFDXEnable                             */
+#define PI_ITEM_K_MAX                                  0x2C    /* Must equal high item           */
+
+/* Values for some of the items */
+
+#define PI_K_FALSE                                             0          /* Generic false */
+#define PI_K_TRUE                                              1          /* Generic true  */
+
+#define PI_SNMP_K_TRUE                                 1          /* SNMP true/false values */
+#define PI_SNMP_K_FALSE                                        2
+
+#define PI_FSTATE_K_BLOCK                              0          /* Filter State */
+#define PI_FSTATE_K_PASS                               1
+
+/* Define command return codes */
+
+#define PI_RSP_K_SUCCESS                               0x00
+#define PI_RSP_K_FAILURE                               0x01
+#define PI_RSP_K_WARNING                               0x02
+#define PI_RSP_K_LOOP_MODE_BAD                 0x03
+#define PI_RSP_K_ITEM_CODE_BAD                 0x04
+#define PI_RSP_K_TVX_BAD                               0x05
+#define PI_RSP_K_TREQ_BAD                              0x06
+#define PI_RSP_K_TOKEN_BAD                             0x07
+#define PI_RSP_K_NO_EOL                                        0x0C
+#define PI_RSP_K_FILTER_STATE_BAD              0x0D
+#define PI_RSP_K_CMD_TYPE_BAD                  0x0E
+#define PI_RSP_K_ADAPTER_STATE_BAD             0x0F
+#define PI_RSP_K_RING_PURGER_BAD               0x10
+#define PI_RSP_K_LEM_THRESHOLD_BAD             0x11
+#define PI_RSP_K_LOOP_NOT_SUPPORTED            0x12
+#define PI_RSP_K_FLUSH_TIME_BAD                        0x13
+#define PI_RSP_K_NOT_IMPLEMENTED               0x14
+#define PI_RSP_K_CONFIG_POLICY_BAD             0x15
+#define PI_RSP_K_STATION_ACTION_BAD            0x16
+#define PI_RSP_K_MAC_ACTION_BAD                        0x17
+#define PI_RSP_K_CON_POLICIES_BAD              0x18
+#define PI_RSP_K_MAC_LOOP_TIME_BAD             0x19
+#define PI_RSP_K_TB_MAX_BAD                            0x1A
+#define PI_RSP_K_LER_CUTOFF_BAD                        0x1B
+#define PI_RSP_K_LER_ALARM_BAD                 0x1C
+#define PI_RSP_K_MAC_PATHS_REQ_BAD             0x1D
+#define PI_RSP_K_MAC_T_REQ_BAD                 0x1E
+#define PI_RSP_K_EMAC_RING_PURGER_BAD  0x1F
+#define PI_RSP_K_EMAC_RTOKEN_TIME_BAD  0x20
+#define PI_RSP_K_NO_SUCH_ENTRY                 0x21
+#define PI_RSP_K_T_NOTIFY_BAD                  0x22
+#define PI_RSP_K_TR_MAX_EXP_BAD                        0x23
+#define PI_RSP_K_MAC_FRM_ERR_THR_BAD   0x24
+#define PI_RSP_K_MAX_T_REQ_BAD                 0x25
+#define PI_RSP_K_FDX_ENB_DIS_BAD               0x26
+#define PI_RSP_K_ITEM_INDEX_BAD                        0x27
+#define PI_RSP_K_PORT_ACTION_BAD               0x28
+
+/* Commonly used structures */
+
+typedef struct                                                                 /* Item list */
+       {
+       PI_UINT32  item_code;
+       PI_UINT32  value;
+       } PI_ITEM_LIST;
+
+typedef struct                                                                 /* Response header */
+       {
+       PI_UINT32  reserved;
+       PI_UINT32  cmd_type;
+       PI_UINT32  status;
+       } PI_RSP_HEADER;
+
+
+/* Start Command */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_START_REQ;
+
+/* Start Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_START_RSP;
+
+/* Filters_Set Request */
+
+#define PI_CMD_FILTERS_SET_K_ITEMS_MAX  63             /* Fits in a 512 byte buffer */
+
+typedef struct
+       {
+       PI_UINT32               cmd_type;
+       PI_ITEM_LIST    item[PI_CMD_FILTERS_SET_K_ITEMS_MAX];
+       } PI_CMD_FILTERS_SET_REQ;
+
+/* Filters_Set Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_FILTERS_SET_RSP;
+
+/* Filters_Get Request */
+
+typedef struct
+       {
+       PI_UINT32               cmd_type;
+       } PI_CMD_FILTERS_GET_REQ;
+
+/* Filters_Get Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       PI_UINT32               ind_group_prom;
+       PI_UINT32               group_prom;
+       PI_UINT32               broadcast_all;
+       PI_UINT32               smt_all;
+       PI_UINT32               smt_user;
+       PI_UINT32               reserved_all;
+       PI_UINT32               implementor_all;
+       } PI_CMD_FILTERS_GET_RSP;
+
+
+/* Chars_Set Request */
+
+#define PI_CMD_CHARS_SET_K_ITEMS_MAX 42                /* Fits in a 512 byte buffer */
+
+typedef struct
+       {
+       PI_UINT32               cmd_type;
+       struct                                                                  /* Item list */
+               {
+               PI_UINT32       item_code;
+               PI_UINT32       value;
+               PI_UINT32       item_index;
+               } item[PI_CMD_CHARS_SET_K_ITEMS_MAX];
+       } PI_CMD_CHARS_SET_REQ;
+
+/* Chars_Set Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_CHARS_SET_RSP;
+
+
+/* SNMP_Set Request */
+
+#define PI_CMD_SNMP_SET_K_ITEMS_MAX 42         /* Fits in a 512 byte buffer */
+
+typedef struct
+       {
+       PI_UINT32               cmd_type;
+       struct                                                                  /* Item list */
+               {
+               PI_UINT32       item_code;
+               PI_UINT32       value;
+               PI_UINT32       item_index;
+               } item[PI_CMD_SNMP_SET_K_ITEMS_MAX];
+       } PI_CMD_SNMP_SET_REQ;
+
+/* SNMP_Set Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_SNMP_SET_RSP;
+
+
+/* SMT_MIB_Set Request */
+
+#define PI_CMD_SMT_MIB_SET_K_ITEMS_MAX 42      /* Max number of items */
+
+typedef struct
+       {
+       PI_UINT32       cmd_type;
+       struct
+               {
+               PI_UINT32       item_code;
+               PI_UINT32       value;
+               PI_UINT32       item_index;
+               } item[PI_CMD_SMT_MIB_SET_K_ITEMS_MAX];
+       } PI_CMD_SMT_MIB_SET_REQ;
+
+/* SMT_MIB_Set Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_SMT_MIB_SET_RSP;
+
+/* SMT_MIB_Get Request */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_SMT_MIB_GET_REQ;
+
+/* SMT_MIB_Get Response */
+
+typedef struct                                           /* Refer to ANSI FDDI SMT Rev. 7.3 */
+       {
+       PI_RSP_HEADER  header;
+
+       /* SMT GROUP */
+
+       PI_STATION_ID   smt_station_id;
+       PI_UINT32               smt_op_version_id;
+       PI_UINT32               smt_hi_version_id;
+       PI_UINT32               smt_lo_version_id;
+       PI_UINT32               smt_user_data[8];
+       PI_UINT32               smt_mib_version_id;
+       PI_UINT32               smt_mac_ct;
+       PI_UINT32               smt_non_master_ct;
+       PI_UINT32               smt_master_ct;
+       PI_UINT32               smt_available_paths;
+       PI_UINT32               smt_config_capabilities;
+       PI_UINT32               smt_config_policy;
+       PI_UINT32               smt_connection_policy;
+       PI_UINT32               smt_t_notify;
+       PI_UINT32               smt_stat_rpt_policy;
+       PI_UINT32               smt_trace_max_expiration;
+       PI_UINT32               smt_bypass_present;
+       PI_UINT32               smt_ecm_state;
+       PI_UINT32               smt_cf_state;
+       PI_UINT32               smt_remote_disconnect_flag;
+       PI_UINT32               smt_station_status;
+       PI_UINT32               smt_peer_wrap_flag;
+       PI_CNTR                 smt_msg_time_stamp;
+       PI_CNTR                 smt_transition_time_stamp;
+
+       /* MAC GROUP */
+
+       PI_UINT32               mac_frame_status_functions;
+       PI_UINT32               mac_t_max_capability;
+       PI_UINT32               mac_tvx_capability;
+       PI_UINT32               mac_available_paths;
+       PI_UINT32               mac_current_path;
+       PI_LAN_ADDR             mac_upstream_nbr;
+       PI_LAN_ADDR             mac_downstream_nbr;
+       PI_LAN_ADDR             mac_old_upstream_nbr;
+       PI_LAN_ADDR             mac_old_downstream_nbr;
+       PI_UINT32               mac_dup_address_test;
+       PI_UINT32               mac_requested_paths;
+       PI_UINT32               mac_downstream_port_type;
+       PI_LAN_ADDR             mac_smt_address;
+       PI_UINT32               mac_t_req;
+       PI_UINT32               mac_t_neg;
+       PI_UINT32               mac_t_max;
+       PI_UINT32               mac_tvx_value;
+       PI_UINT32               mac_frame_error_threshold;
+       PI_UINT32               mac_frame_error_ratio;
+       PI_UINT32               mac_rmt_state;
+       PI_UINT32               mac_da_flag;
+       PI_UINT32               mac_unda_flag;
+       PI_UINT32               mac_frame_error_flag;
+       PI_UINT32               mac_ma_unitdata_available;
+       PI_UINT32               mac_hardware_present;
+       PI_UINT32               mac_ma_unitdata_enable;
+
+       /* PATH GROUP */
+
+       PI_UINT32               path_configuration[8];
+       PI_UINT32               path_tvx_lower_bound;
+       PI_UINT32               path_t_max_lower_bound;
+       PI_UINT32               path_max_t_req;
+
+       /* PORT GROUP */
+
+       PI_UINT32               port_my_type[PI_PHY_K_MAX];
+       PI_UINT32               port_neighbor_type[PI_PHY_K_MAX];
+       PI_UINT32               port_connection_policies[PI_PHY_K_MAX];
+       PI_UINT32               port_mac_indicated[PI_PHY_K_MAX];
+       PI_UINT32               port_current_path[PI_PHY_K_MAX];
+       PI_UINT32               port_requested_paths[PI_PHY_K_MAX];
+       PI_UINT32               port_mac_placement[PI_PHY_K_MAX];
+       PI_UINT32               port_available_paths[PI_PHY_K_MAX];
+       PI_UINT32               port_pmd_class[PI_PHY_K_MAX];
+       PI_UINT32               port_connection_capabilities[PI_PHY_K_MAX];
+       PI_UINT32               port_bs_flag[PI_PHY_K_MAX];
+       PI_UINT32               port_ler_estimate[PI_PHY_K_MAX];
+       PI_UINT32               port_ler_cutoff[PI_PHY_K_MAX];
+       PI_UINT32               port_ler_alarm[PI_PHY_K_MAX];
+       PI_UINT32               port_connect_state[PI_PHY_K_MAX];
+       PI_UINT32               port_pcm_state[PI_PHY_K_MAX];
+       PI_UINT32               port_pc_withhold[PI_PHY_K_MAX];
+       PI_UINT32               port_ler_flag[PI_PHY_K_MAX];
+       PI_UINT32               port_hardware_present[PI_PHY_K_MAX];
+
+       /* GROUP for things that were added later, so must be at the end. */
+
+       PI_CNTR                 path_ring_latency;
+
+       } PI_CMD_SMT_MIB_GET_RSP;
+
+
+/*
+ *  Item and group code definitions for SMT 7.3 mandatory objects.  These
+ *  definitions are to be used as appropriate in SMT_MIB_SET commands and
+ *  certain host-sent SMT frames such as PMF Get and Set requests.  The
+ *  codes have been taken from the MIB summary section of ANSI SMT 7.3.
+ */
+
+#define PI_GRP_K_SMT_STATION_ID                        0x100A
+#define PI_ITEM_K_SMT_STATION_ID               0x100B
+#define PI_ITEM_K_SMT_OP_VERS_ID               0x100D
+#define PI_ITEM_K_SMT_HI_VERS_ID               0x100E
+#define PI_ITEM_K_SMT_LO_VERS_ID               0x100F
+#define PI_ITEM_K_SMT_USER_DATA                        0x1011
+#define PI_ITEM_K_SMT_MIB_VERS_ID              0x1012
+
+#define PI_GRP_K_SMT_STATION_CONFIG            0x1014
+#define PI_ITEM_K_SMT_MAC_CT                   0x1015
+#define PI_ITEM_K_SMT_NON_MASTER_CT            0x1016
+#define PI_ITEM_K_SMT_MASTER_CT                        0x1017
+#define PI_ITEM_K_SMT_AVAIL_PATHS              0x1018
+#define PI_ITEM_K_SMT_CONFIG_CAPS              0x1019
+#define PI_ITEM_K_SMT_CONFIG_POL               0x101A
+#define PI_ITEM_K_SMT_CONN_POL                 0x101B
+#define PI_ITEM_K_SMT_T_NOTIFY                 0x101D
+#define PI_ITEM_K_SMT_STAT_POL                 0x101E
+#define PI_ITEM_K_SMT_TR_MAX_EXP               0x101F
+#define PI_ITEM_K_SMT_PORT_INDEXES             0x1020
+#define PI_ITEM_K_SMT_MAC_INDEXES              0x1021
+#define PI_ITEM_K_SMT_BYPASS_PRESENT   0x1022
+
+#define PI_GRP_K_SMT_STATUS                            0x1028
+#define PI_ITEM_K_SMT_ECM_STATE                        0x1029
+#define PI_ITEM_K_SMT_CF_STATE                 0x102A
+#define PI_ITEM_K_SMT_REM_DISC_FLAG            0x102C
+#define PI_ITEM_K_SMT_STATION_STATUS   0x102D
+#define PI_ITEM_K_SMT_PEER_WRAP_FLAG   0x102E
+
+#define PI_GRP_K_SMT_MIB_OPERATION             0x1032
+#define PI_ITEM_K_SMT_MSG_TIME_STAMP   0x1033
+#define PI_ITEM_K_SMT_TRN_TIME_STAMP   0x1034
+
+#define PI_ITEM_K_SMT_STATION_ACT              0x103C
+
+#define PI_GRP_K_MAC_CAPABILITIES              0x200A
+#define PI_ITEM_K_MAC_FRM_STAT_FUNC            0x200B
+#define PI_ITEM_K_MAC_T_MAX_CAP                        0x200D
+#define PI_ITEM_K_MAC_TVX_CAP                  0x200E
+
+#define PI_GRP_K_MAC_CONFIG                            0x2014
+#define PI_ITEM_K_MAC_AVAIL_PATHS              0x2016
+#define PI_ITEM_K_MAC_CURRENT_PATH             0x2017
+#define PI_ITEM_K_MAC_UP_NBR                   0x2018
+#define PI_ITEM_K_MAC_DOWN_NBR                 0x2019
+#define PI_ITEM_K_MAC_OLD_UP_NBR               0x201A
+#define PI_ITEM_K_MAC_OLD_DOWN_NBR             0x201B
+#define PI_ITEM_K_MAC_DUP_ADDR_TEST            0x201D
+#define PI_ITEM_K_MAC_REQ_PATHS                        0x2020
+#define PI_ITEM_K_MAC_DOWN_PORT_TYPE           0x2021
+#define PI_ITEM_K_MAC_INDEX                            0x2022
+
+#define PI_GRP_K_MAC_ADDRESS                   0x2028
+#define PI_ITEM_K_MAC_SMT_ADDRESS              0x2029
+
+#define PI_GRP_K_MAC_OPERATION                 0x2032
+#define PI_ITEM_K_MAC_TREQ                             0x2033
+#define PI_ITEM_K_MAC_TNEG                             0x2034
+#define PI_ITEM_K_MAC_TMAX                             0x2035
+#define PI_ITEM_K_MAC_TVX_VALUE                        0x2036
+
+#define PI_GRP_K_MAC_COUNTERS                  0x2046
+#define PI_ITEM_K_MAC_FRAME_CT                 0x2047
+#define PI_ITEM_K_MAC_COPIED_CT                        0x2048
+#define PI_ITEM_K_MAC_TRANSMIT_CT              0x2049
+#define PI_ITEM_K_MAC_ERROR_CT                 0x2051
+#define PI_ITEM_K_MAC_LOST_CT                  0x2052
+
+#define PI_GRP_K_MAC_FRM_ERR_COND              0x205A
+#define PI_ITEM_K_MAC_FRM_ERR_THR              0x205F
+#define PI_ITEM_K_MAC_FRM_ERR_RAT              0x2060
+
+#define PI_GRP_K_MAC_STATUS                            0x206E
+#define PI_ITEM_K_MAC_RMT_STATE                        0x206F
+#define PI_ITEM_K_MAC_DA_FLAG                  0x2070
+#define PI_ITEM_K_MAC_UNDA_FLAG                        0x2071
+#define PI_ITEM_K_MAC_FRM_ERR_FLAG             0x2072
+#define PI_ITEM_K_MAC_MA_UNIT_AVAIL            0x2074
+#define PI_ITEM_K_MAC_HW_PRESENT               0x2075
+#define PI_ITEM_K_MAC_MA_UNIT_ENAB             0x2076
+
+#define PI_GRP_K_PATH_CONFIG                   0x320A
+#define PI_ITEM_K_PATH_INDEX                   0x320B
+#define PI_ITEM_K_PATH_CONFIGURATION   0x3212
+#define PI_ITEM_K_PATH_TVX_LB                  0x3215
+#define PI_ITEM_K_PATH_T_MAX_LB                        0x3216
+#define PI_ITEM_K_PATH_MAX_T_REQ               0x3217
+
+#define PI_GRP_K_PORT_CONFIG                   0x400A
+#define PI_ITEM_K_PORT_MY_TYPE                 0x400C
+#define PI_ITEM_K_PORT_NBR_TYPE                        0x400D
+#define PI_ITEM_K_PORT_CONN_POLS               0x400E
+#define PI_ITEM_K_PORT_MAC_INDICATED   0x400F
+#define PI_ITEM_K_PORT_CURRENT_PATH            0x4010
+#define PI_ITEM_K_PORT_REQ_PATHS               0x4011
+#define PI_ITEM_K_PORT_MAC_PLACEMENT   0x4012
+#define PI_ITEM_K_PORT_AVAIL_PATHS             0x4013
+#define PI_ITEM_K_PORT_PMD_CLASS               0x4016
+#define PI_ITEM_K_PORT_CONN_CAPS               0x4017
+#define PI_ITEM_K_PORT_INDEX                   0x401D
+
+#define PI_GRP_K_PORT_OPERATION                        0x401E
+#define PI_ITEM_K_PORT_BS_FLAG                 0x4021
+
+#define PI_GRP_K_PORT_ERR_CNTRS                        0x4028
+#define PI_ITEM_K_PORT_LCT_FAIL_CT             0x402A
+
+#define PI_GRP_K_PORT_LER                              0x4032
+#define PI_ITEM_K_PORT_LER_ESTIMATE            0x4033
+#define PI_ITEM_K_PORT_LEM_REJ_CT              0x4034
+#define PI_ITEM_K_PORT_LEM_CT                  0x4035
+#define PI_ITEM_K_PORT_LER_CUTOFF              0x403A
+#define PI_ITEM_K_PORT_LER_ALARM               0x403B
+
+#define PI_GRP_K_PORT_STATUS                   0x403C
+#define PI_ITEM_K_PORT_CONNECT_STATE   0x403D
+#define PI_ITEM_K_PORT_PCM_STATE               0x403E
+#define PI_ITEM_K_PORT_PC_WITHHOLD             0x403F
+#define PI_ITEM_K_PORT_LER_FLAG                        0x4040
+#define PI_ITEM_K_PORT_HW_PRESENT              0x4041
+
+#define PI_ITEM_K_PORT_ACT                             0x4046
+
+/* Addr_Filter_Set Request */
+
+#define PI_CMD_ADDR_FILTER_K_SIZE   62
+
+typedef struct
+       {
+       PI_UINT32       cmd_type;
+       PI_LAN_ADDR     entry[PI_CMD_ADDR_FILTER_K_SIZE];
+       } PI_CMD_ADDR_FILTER_SET_REQ;
+
+/* Addr_Filter_Set Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_ADDR_FILTER_SET_RSP;
+
+/* Addr_Filter_Get Request */
+
+typedef struct
+       {
+       PI_UINT32       cmd_type;
+       } PI_CMD_ADDR_FILTER_GET_REQ;
+
+/* Addr_Filter_Get Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       PI_LAN_ADDR             entry[PI_CMD_ADDR_FILTER_K_SIZE];
+       } PI_CMD_ADDR_FILTER_GET_RSP;
+
+/* Status_Chars_Get Request */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_STATUS_CHARS_GET_REQ;
+
+/* Status_Chars_Get Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       PI_STATION_ID   station_id;                                             /* Station */
+       PI_UINT32               station_type;
+       PI_UINT32               smt_ver_id;
+       PI_UINT32               smt_ver_id_max;
+       PI_UINT32               smt_ver_id_min;
+       PI_UINT32               station_state;
+       PI_LAN_ADDR             link_addr;                                              /* Link */
+       PI_UINT32               t_req;
+       PI_UINT32               tvx;
+       PI_UINT32               token_timeout;
+       PI_UINT32               purger_enb;
+       PI_UINT32               link_state;
+       PI_UINT32               tneg;
+       PI_UINT32               dup_addr_flag;
+       PI_LAN_ADDR             una;
+       PI_LAN_ADDR             una_old;
+       PI_UINT32               un_dup_addr_flag;
+       PI_LAN_ADDR             dna;
+       PI_LAN_ADDR             dna_old;
+       PI_UINT32               purger_state;
+       PI_UINT32               fci_mode;
+       PI_UINT32               error_reason;
+       PI_UINT32               loopback;
+       PI_UINT32               ring_latency;
+       PI_LAN_ADDR             last_dir_beacon_sa;
+       PI_LAN_ADDR             last_dir_beacon_una;
+       PI_UINT32               phy_type[PI_PHY_K_MAX];                 /* Phy */
+       PI_UINT32               pmd_type[PI_PHY_K_MAX];
+       PI_UINT32               lem_threshold[PI_PHY_K_MAX];
+       PI_UINT32               phy_state[PI_PHY_K_MAX];
+       PI_UINT32               nbor_phy_type[PI_PHY_K_MAX];
+       PI_UINT32               link_error_est[PI_PHY_K_MAX];
+       PI_UINT32               broken_reason[PI_PHY_K_MAX];
+       PI_UINT32               reject_reason[PI_PHY_K_MAX];
+       PI_UINT32               cntr_interval;                                  /* Miscellaneous */
+       PI_UINT32               module_rev;
+       PI_UINT32               firmware_rev;
+       PI_UINT32               mop_device_type;
+       PI_UINT32               phy_led[PI_PHY_K_MAX];
+       PI_UINT32               flush_time;
+       } PI_CMD_STATUS_CHARS_GET_RSP;
+
+/* FDDI_MIB_Get Request */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_FDDI_MIB_GET_REQ;
+
+/* FDDI_MIB_Get Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+
+       /* SMT GROUP */
+
+       PI_STATION_ID   smt_station_id;
+       PI_UINT32               smt_op_version_id;
+       PI_UINT32               smt_hi_version_id;
+       PI_UINT32               smt_lo_version_id;
+       PI_UINT32               smt_mac_ct;
+       PI_UINT32               smt_non_master_ct;
+       PI_UINT32               smt_master_ct;
+       PI_UINT32               smt_paths_available;
+       PI_UINT32               smt_config_capabilities;
+       PI_UINT32               smt_config_policy;
+       PI_UINT32               smt_connection_policy;
+       PI_UINT32               smt_t_notify;
+       PI_UINT32               smt_status_reporting;
+       PI_UINT32               smt_ecm_state;
+       PI_UINT32               smt_cf_state;
+       PI_UINT32               smt_hold_state;
+       PI_UINT32               smt_remote_disconnect_flag;
+       PI_UINT32               smt_station_action;
+
+       /* MAC GROUP */
+
+       PI_UINT32               mac_frame_status_capabilities;
+       PI_UINT32               mac_t_max_greatest_lower_bound;
+       PI_UINT32               mac_tvx_greatest_lower_bound;
+       PI_UINT32               mac_paths_available;
+       PI_UINT32               mac_current_path;
+       PI_LAN_ADDR             mac_upstream_nbr;
+       PI_LAN_ADDR             mac_old_upstream_nbr;
+       PI_UINT32               mac_dup_addr_test;
+       PI_UINT32               mac_paths_requested;
+       PI_UINT32               mac_downstream_port_type;
+       PI_LAN_ADDR             mac_smt_address;
+       PI_UINT32               mac_t_req;
+       PI_UINT32               mac_t_neg;
+       PI_UINT32               mac_t_max;
+       PI_UINT32               mac_tvx_value;
+       PI_UINT32               mac_t_min;
+       PI_UINT32               mac_current_frame_status;
+       /*                              mac_frame_cts                   */
+       /*                              mac_error_cts                   */
+       /*                              mac_lost_cts                    */
+       PI_UINT32               mac_frame_error_threshold;
+       PI_UINT32               mac_frame_error_ratio;
+       PI_UINT32               mac_rmt_state;
+       PI_UINT32               mac_da_flag;
+       PI_UINT32               mac_una_da_flag;
+       PI_UINT32               mac_frame_condition;
+       PI_UINT32               mac_chip_set;
+       PI_UINT32               mac_action;
+
+       /* PATH GROUP => Does not need to be implemented */
+
+       /* PORT GROUP */
+
+       PI_UINT32               port_pc_type[PI_PHY_K_MAX];
+       PI_UINT32               port_pc_neighbor[PI_PHY_K_MAX];
+       PI_UINT32               port_connection_policies[PI_PHY_K_MAX];
+       PI_UINT32               port_remote_mac_indicated[PI_PHY_K_MAX];
+       PI_UINT32               port_ce_state[PI_PHY_K_MAX];
+       PI_UINT32               port_paths_requested[PI_PHY_K_MAX];
+       PI_UINT32               port_mac_placement[PI_PHY_K_MAX];
+       PI_UINT32               port_available_paths[PI_PHY_K_MAX];
+       PI_UINT32               port_mac_loop_time[PI_PHY_K_MAX];
+       PI_UINT32               port_tb_max[PI_PHY_K_MAX];
+       PI_UINT32               port_bs_flag[PI_PHY_K_MAX];
+       /*                              port_lct_fail_cts[PI_PHY_K_MAX];        */
+       PI_UINT32               port_ler_estimate[PI_PHY_K_MAX];
+       /*                              port_lem_reject_cts[PI_PHY_K_MAX];      */
+       /*                              port_lem_cts[PI_PHY_K_MAX];             */
+       PI_UINT32               port_ler_cutoff[PI_PHY_K_MAX];
+       PI_UINT32               port_ler_alarm[PI_PHY_K_MAX];
+       PI_UINT32               port_connect_state[PI_PHY_K_MAX];
+       PI_UINT32               port_pcm_state[PI_PHY_K_MAX];
+       PI_UINT32               port_pc_withhold[PI_PHY_K_MAX];
+       PI_UINT32               port_ler_condition[PI_PHY_K_MAX];
+       PI_UINT32               port_chip_set[PI_PHY_K_MAX];
+       PI_UINT32               port_action[PI_PHY_K_MAX];
+
+       /* ATTACHMENT GROUP */
+
+       PI_UINT32               attachment_class;
+       PI_UINT32               attachment_ob_present;
+       PI_UINT32               attachment_imax_expiration;
+       PI_UINT32               attachment_inserted_status;
+       PI_UINT32               attachment_insert_policy;
+
+       /* CHIP SET GROUP => Does not need to be implemented */
+
+       } PI_CMD_FDDI_MIB_GET_RSP;
+
+/* DEC_Ext_MIB_Get Request */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_DEC_EXT_MIB_GET_REQ;
+
+/* DEC_Ext_MIB_Get (efddi and efdx groups only) Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+
+       /* SMT GROUP */
+
+       PI_UINT32               esmt_station_type;
+
+       /* MAC GROUP */
+
+       PI_UINT32               emac_link_state;
+       PI_UINT32               emac_ring_purger_state;
+       PI_UINT32               emac_ring_purger_enable;
+       PI_UINT32               emac_frame_strip_mode;
+       PI_UINT32               emac_ring_error_reason;
+       PI_UINT32               emac_up_nbr_dup_addr_flag;
+       PI_UINT32               emac_restricted_token_timeout;
+
+       /* PORT GROUP */
+
+       PI_UINT32               eport_pmd_type[PI_PHY_K_MAX];
+       PI_UINT32               eport_phy_state[PI_PHY_K_MAX];
+       PI_UINT32               eport_reject_reason[PI_PHY_K_MAX];
+
+       /* FDX (Full-Duplex) GROUP */
+
+       PI_UINT32               efdx_enable;                            /* Valid only in SMT 7.3 */
+       PI_UINT32               efdx_op;                                        /* Valid only in SMT 7.3 */
+       PI_UINT32               efdx_state;                                     /* Valid only in SMT 7.3 */
+
+       } PI_CMD_DEC_EXT_MIB_GET_RSP;
+
+typedef struct
+       {
+       PI_CNTR         traces_rcvd;                                    /* Station */
+       PI_CNTR         frame_cnt;                                              /* Link */
+       PI_CNTR         error_cnt;
+       PI_CNTR         lost_cnt;
+       PI_CNTR         octets_rcvd;
+       PI_CNTR         octets_sent;
+       PI_CNTR         pdus_rcvd;
+       PI_CNTR         pdus_sent;
+       PI_CNTR         mcast_octets_rcvd;
+       PI_CNTR         mcast_octets_sent;
+       PI_CNTR         mcast_pdus_rcvd;
+       PI_CNTR         mcast_pdus_sent;
+       PI_CNTR         xmt_underruns;
+       PI_CNTR         xmt_failures;
+       PI_CNTR         block_check_errors;
+       PI_CNTR         frame_status_errors;
+       PI_CNTR         pdu_length_errors;
+       PI_CNTR         rcv_overruns;
+       PI_CNTR         user_buff_unavailable;
+       PI_CNTR         inits_initiated;
+       PI_CNTR         inits_rcvd;
+       PI_CNTR         beacons_initiated;
+       PI_CNTR         dup_addrs;
+       PI_CNTR         dup_tokens;
+       PI_CNTR         purge_errors;
+       PI_CNTR         fci_strip_errors;
+       PI_CNTR         traces_initiated;
+       PI_CNTR         directed_beacons_rcvd;
+       PI_CNTR         emac_frame_alignment_errors;
+       PI_CNTR         ebuff_errors[PI_PHY_K_MAX];             /* Phy */
+       PI_CNTR         lct_rejects[PI_PHY_K_MAX];
+       PI_CNTR         lem_rejects[PI_PHY_K_MAX];
+       PI_CNTR         link_errors[PI_PHY_K_MAX];
+       PI_CNTR         connections[PI_PHY_K_MAX];
+       PI_CNTR         copied_cnt;                                             /* Valid only if using SMT 7.3 */
+       PI_CNTR         transmit_cnt;                                   /* Valid only if using SMT 7.3 */
+       PI_CNTR         tokens;
+       } PI_CNTR_BLK;
+
+/* Counters_Get Request */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_CNTRS_GET_REQ;
+
+/* Counters_Get Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       PI_CNTR         time_since_reset;
+       PI_CNTR_BLK             cntrs;
+       } PI_CMD_CNTRS_GET_RSP;
+
+/* Counters_Set Request */
+
+typedef struct
+       {
+       PI_UINT32       cmd_type;
+       PI_CNTR_BLK     cntrs;
+       } PI_CMD_CNTRS_SET_REQ;
+
+/* Counters_Set Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_CNTRS_SET_RSP;
+
+/* Error_Log_Clear Request */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       } PI_CMD_ERROR_LOG_CLEAR_REQ;
+
+/* Error_Log_Clear Response */
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       } PI_CMD_ERROR_LOG_CLEAR_RSP;
+
+/* Error_Log_Get Request */
+
+#define PI_LOG_ENTRY_K_INDEX_MIN       0               /* Minimum index for entry */
+
+typedef struct
+       {
+       PI_UINT32  cmd_type;
+       PI_UINT32  entry_index;
+       } PI_CMD_ERROR_LOG_GET_REQ;
+
+/* Error_Log_Get Response */
+
+#define PI_K_LOG_FW_SIZE                       111             /* Max number of fw longwords */
+#define PI_K_LOG_DIAG_SIZE                     6               /* Max number of diag longwords */
+
+typedef struct
+       {
+       struct
+               {
+               PI_UINT32       fru_imp_mask;
+               PI_UINT32       test_id;
+               PI_UINT32       reserved[PI_K_LOG_DIAG_SIZE];
+               } diag;
+       PI_UINT32               fw[PI_K_LOG_FW_SIZE];
+       } PI_LOG_ENTRY;
+
+typedef struct
+       {
+       PI_RSP_HEADER   header;
+       PI_UINT32               event_status;
+       PI_UINT32               caller_id;
+       PI_UINT32               timestamp_l;
+       PI_UINT32               timestamp_h;
+       PI_UINT32               write_count;
+       PI_LOG_ENTRY    entry_info;
+       } PI_CMD_ERROR_LOG_GET_RSP;
+
+/* Define error log related constants and types.                                       */
+/*   Not all of the caller id's can occur.  The only ones currently */
+/*   implemented are: none, selftest, mfg, fw, console                         */
+
+#define PI_LOG_EVENT_STATUS_K_VALID            0       /* Valid Event Status           */
+#define PI_LOG_EVENT_STATUS_K_INVALID  1       /* Invalid Event Status         */
+#define PI_LOG_CALLER_ID_K_NONE                        0       /* No caller                            */
+#define PI_LOG_CALLER_ID_K_SELFTEST            1       /* Normal power-up selftest */
+#define PI_LOG_CALLER_ID_K_MFG                 2       /* Mfg power-up selftest        */
+#define PI_LOG_CALLER_ID_K_ONLINE              3       /* On-line diagnostics          */
+#define PI_LOG_CALLER_ID_K_HW                  4       /* Hardware                             */
+#define PI_LOG_CALLER_ID_K_FW                  5       /* Firmware                             */
+#define PI_LOG_CALLER_ID_K_CNS_HW              6       /* CNS firmware                         */
+#define PI_LOG_CALLER_ID_K_CNS_FW              7       /* CNS hardware                         */
+#define PI_LOG_CALLER_ID_K_CONSOLE             8   /* Console Caller Id                */
+
+/*
+ *  Place all DMA commands in the following request and response structures
+ *  to simplify code.
+ */
+
+typedef union
+       {
+       PI_UINT32                                       cmd_type;
+       PI_CMD_START_REQ                        start;
+       PI_CMD_FILTERS_SET_REQ          filter_set;
+       PI_CMD_FILTERS_GET_REQ          filter_get;
+       PI_CMD_CHARS_SET_REQ            char_set;
+       PI_CMD_ADDR_FILTER_SET_REQ      addr_filter_set;
+       PI_CMD_ADDR_FILTER_GET_REQ      addr_filter_get;
+       PI_CMD_STATUS_CHARS_GET_REQ     stat_char_get;
+       PI_CMD_CNTRS_GET_REQ            cntrs_get;
+       PI_CMD_CNTRS_SET_REQ            cntrs_set;
+       PI_CMD_ERROR_LOG_CLEAR_REQ      error_log_clear;
+       PI_CMD_ERROR_LOG_GET_REQ        error_log_read;
+       PI_CMD_SNMP_SET_REQ                     snmp_set;
+       PI_CMD_FDDI_MIB_GET_REQ         fddi_mib_get;
+       PI_CMD_DEC_EXT_MIB_GET_REQ      dec_mib_get;
+       PI_CMD_SMT_MIB_SET_REQ          smt_mib_set;
+       PI_CMD_SMT_MIB_GET_REQ          smt_mib_get;
+       char                                            pad[PI_CMD_REQ_K_SIZE_MAX];
+       } PI_DMA_CMD_REQ;
+
+typedef union
+       {
+       PI_RSP_HEADER                           header;
+       PI_CMD_START_RSP                        start;
+       PI_CMD_FILTERS_SET_RSP          filter_set;
+       PI_CMD_FILTERS_GET_RSP          filter_get;
+       PI_CMD_CHARS_SET_RSP            char_set;
+       PI_CMD_ADDR_FILTER_SET_RSP      addr_filter_set;
+       PI_CMD_ADDR_FILTER_GET_RSP      addr_filter_get;
+       PI_CMD_STATUS_CHARS_GET_RSP     stat_char_get;
+       PI_CMD_CNTRS_GET_RSP            cntrs_get;
+       PI_CMD_CNTRS_SET_RSP            cntrs_set;
+       PI_CMD_ERROR_LOG_CLEAR_RSP      error_log_clear;
+       PI_CMD_ERROR_LOG_GET_RSP        error_log_get;
+       PI_CMD_SNMP_SET_RSP                     snmp_set;
+       PI_CMD_FDDI_MIB_GET_RSP         fddi_mib_get;
+       PI_CMD_DEC_EXT_MIB_GET_RSP      dec_mib_get;
+       PI_CMD_SMT_MIB_SET_RSP          smt_mib_set;
+       PI_CMD_SMT_MIB_GET_RSP          smt_mib_get;
+       char                                            pad[PI_CMD_RSP_K_SIZE_MAX];
+       } PI_DMA_CMD_RSP;
+
+typedef union
+       {
+       PI_DMA_CMD_REQ  request;
+       PI_DMA_CMD_RSP  response;
+       } PI_DMA_CMD_BUFFER;
+
+
+/* Define format of Consumer Block (resident in host memory) */
+
+typedef struct
+       {
+       volatile PI_UINT32      xmt_rcv_data;
+       volatile PI_UINT32      reserved_1;
+       volatile PI_UINT32      smt_host;
+       volatile PI_UINT32      reserved_2;
+       volatile PI_UINT32      unsol;
+       volatile PI_UINT32      reserved_3;
+       volatile PI_UINT32      cmd_rsp;
+       volatile PI_UINT32      reserved_4;
+       volatile PI_UINT32      cmd_req;
+       volatile PI_UINT32      reserved_5;
+       } PI_CONSUMER_BLOCK;
+
+#define PI_CONS_M_RCV_INDEX                    0x000000FF
+#define PI_CONS_M_XMT_INDEX                    0x00FF0000
+#define PI_CONS_V_RCV_INDEX                    0
+#define PI_CONS_V_XMT_INDEX                    16
+
+/* Offsets into consumer block */
+
+#define PI_CONS_BLK_K_XMT_RCV          0x00
+#define PI_CONS_BLK_K_SMT_HOST         0x08
+#define PI_CONS_BLK_K_UNSOL                    0x10
+#define PI_CONS_BLK_K_CMD_RSP          0x18
+#define PI_CONS_BLK_K_CMD_REQ          0x20
+
+/* Offsets into descriptor block */
+
+#define PI_DESCR_BLK_K_RCV_DATA                0x0000
+#define PI_DESCR_BLK_K_XMT_DATA                0x0800
+#define PI_DESCR_BLK_K_SMT_HOST        0x1000
+#define PI_DESCR_BLK_K_UNSOL           0x1200
+#define PI_DESCR_BLK_K_CMD_RSP         0x1280
+#define PI_DESCR_BLK_K_CMD_REQ         0x1300
+
+/* Define format of a rcv descr (Rcv Data, Cmd Rsp, Unsolicited, SMT Host)   */
+/*   Note a field has been added for later versions of the PDQ to allow for  */
+/*   finer granularity of the rcv buffer alignment.  For backwards                      */
+/*   compatibility, the two bits (which allow the rcv buffer to be longword  */
+/*   aligned) have been added at the MBZ bits.  To support previous drivers, */
+/*   the MBZ definition is left intact.                                                                                 */
+
+typedef struct
+       {
+       PI_UINT32       long_0;
+       PI_UINT32       long_1;
+       } PI_RCV_DESCR;
+
+#define        PI_RCV_DESCR_M_SOP                      0x80000000
+#define PI_RCV_DESCR_M_SEG_LEN_LO      0x60000000
+#define PI_RCV_DESCR_M_MBZ                     0x60000000
+#define PI_RCV_DESCR_M_SEG_LEN         0x1F800000
+#define PI_RCV_DESCR_M_SEG_LEN_HI      0x1FF00000
+#define PI_RCV_DESCR_M_SEG_CNT         0x000F0000
+#define PI_RCV_DESCR_M_BUFF_HI         0x0000FFFF
+
+#define        PI_RCV_DESCR_V_SOP                      31
+#define PI_RCV_DESCR_V_SEG_LEN_LO      29
+#define PI_RCV_DESCR_V_MBZ                     29
+#define PI_RCV_DESCR_V_SEG_LEN         23
+#define PI_RCV_DESCR_V_SEG_LEN_HI      20
+#define PI_RCV_DESCR_V_SEG_CNT         16
+#define PI_RCV_DESCR_V_BUFF_HI         0
+
+/* Define the format of a transmit descriptor (Xmt Data, Cmd Req) */
+
+typedef struct
+       {
+       PI_UINT32       long_0;
+       PI_UINT32       long_1;
+       } PI_XMT_DESCR;
+
+#define        PI_XMT_DESCR_M_SOP                      0x80000000
+#define PI_XMT_DESCR_M_EOP                     0x40000000
+#define PI_XMT_DESCR_M_MBZ                     0x20000000
+#define PI_XMT_DESCR_M_SEG_LEN         0x1FFF0000
+#define PI_XMT_DESCR_M_BUFF_HI         0x0000FFFF
+
+#define        PI_XMT_DESCR_V_SOP                      31
+#define        PI_XMT_DESCR_V_EOP                      30
+#define PI_XMT_DESCR_V_MBZ                     29
+#define PI_XMT_DESCR_V_SEG_LEN         16
+#define PI_XMT_DESCR_V_BUFF_HI         0
+
+/* Define format of the Descriptor Block (resident in host memory) */
+
+#define PI_RCV_DATA_K_NUM_ENTRIES                      256
+#define PI_XMT_DATA_K_NUM_ENTRIES                      256
+#define PI_SMT_HOST_K_NUM_ENTRIES                      64
+#define PI_UNSOL_K_NUM_ENTRIES                         16
+#define PI_CMD_RSP_K_NUM_ENTRIES                       16
+#define PI_CMD_REQ_K_NUM_ENTRIES                       16
+
+typedef struct
+       {
+       PI_RCV_DESCR  rcv_data[PI_RCV_DATA_K_NUM_ENTRIES];
+       PI_XMT_DESCR  xmt_data[PI_XMT_DATA_K_NUM_ENTRIES];
+       PI_RCV_DESCR  smt_host[PI_SMT_HOST_K_NUM_ENTRIES];
+       PI_RCV_DESCR  unsol[PI_UNSOL_K_NUM_ENTRIES];
+       PI_RCV_DESCR  cmd_rsp[PI_CMD_RSP_K_NUM_ENTRIES];
+       PI_XMT_DESCR  cmd_req[PI_CMD_REQ_K_NUM_ENTRIES];
+       } PI_DESCR_BLOCK;
+
+/* Define Port Registers - offsets from PDQ Base address */
+
+#define PI_PDQ_K_REG_PORT_RESET                        0x00000000
+#define PI_PDQ_K_REG_HOST_DATA                 0x00000004
+#define PI_PDQ_K_REG_PORT_CTRL                 0x00000008
+#define PI_PDQ_K_REG_PORT_DATA_A               0x0000000C
+#define PI_PDQ_K_REG_PORT_DATA_B               0x00000010
+#define PI_PDQ_K_REG_PORT_STATUS               0x00000014
+#define PI_PDQ_K_REG_TYPE_0_STATUS             0x00000018
+#define PI_PDQ_K_REG_HOST_INT_ENB              0x0000001C
+#define PI_PDQ_K_REG_TYPE_2_PROD_NOINT         0x00000020
+#define PI_PDQ_K_REG_TYPE_2_PROD               0x00000024
+#define PI_PDQ_K_REG_CMD_RSP_PROD              0x00000028
+#define PI_PDQ_K_REG_CMD_REQ_PROD              0x0000002C
+#define PI_PDQ_K_REG_SMT_HOST_PROD     0x00000030
+#define PI_PDQ_K_REG_UNSOL_PROD                        0x00000034
+
+/* Port Control Register - Command codes for primary commands */
+
+#define PI_PCTRL_M_CMD_ERROR                   0x8000
+#define PI_PCTRL_M_BLAST_FLASH                 0x4000
+#define PI_PCTRL_M_HALT                                        0x2000
+#define PI_PCTRL_M_COPY_DATA                   0x1000
+#define PI_PCTRL_M_ERROR_LOG_START             0x0800
+#define PI_PCTRL_M_ERROR_LOG_READ              0x0400
+#define PI_PCTRL_M_XMT_DATA_FLUSH_DONE 0x0200
+#define PI_PCTRL_M_INIT                                        0x0100
+#define PI_PCTRL_M_INIT_START              0x0080
+#define PI_PCTRL_M_CONS_BLOCK                  0x0040
+#define PI_PCTRL_M_UNINIT                              0x0020
+#define PI_PCTRL_M_RING_MEMBER                 0x0010
+#define PI_PCTRL_M_MLA                                 0x0008
+#define PI_PCTRL_M_FW_REV_READ                 0x0004
+#define PI_PCTRL_M_DEV_SPECIFIC                        0x0002
+#define PI_PCTRL_M_SUB_CMD                             0x0001
+
+/* Define sub-commands accessed via the PI_PCTRL_M_SUB_CMD command */
+
+#define PI_SUB_CMD_K_LINK_UNINIT               0x0001
+#define PI_SUB_CMD_K_BURST_SIZE_SET            0x0002
+#define PI_SUB_CMD_K_PDQ_REV_GET               0x0004
+#define PI_SUB_CMD_K_HW_REV_GET                        0x0008
+
+/* Define some Port Data B values */
+
+#define PI_PDATA_B_DMA_BURST_SIZE_4            0               /* valid values for command */
+#define PI_PDATA_B_DMA_BURST_SIZE_8            1
+#define PI_PDATA_B_DMA_BURST_SIZE_16   2
+#define PI_PDATA_B_DMA_BURST_SIZE_32   3               /* not supported on PCI */
+#define PI_PDATA_B_DMA_BURST_SIZE_DEF  PI_PDATA_B_DMA_BURST_SIZE_16
+
+/* Port Data A Reset state */
+
+#define PI_PDATA_A_RESET_M_UPGRADE             0x00000001
+#define PI_PDATA_A_RESET_M_SOFT_RESET  0x00000002
+#define PI_PDATA_A_RESET_M_SKIP_ST             0x00000004
+
+/* Read adapter MLA address port control command constants */
+
+#define PI_PDATA_A_MLA_K_LO                            0
+#define PI_PDATA_A_MLA_K_HI                            1
+
+/* Byte Swap values for init command */
+
+#define PI_PDATA_A_INIT_M_DESC_BLK_ADDR                        0x0FFFFE000
+#define PI_PDATA_A_INIT_M_RESERVED                             0x000001FFC
+#define PI_PDATA_A_INIT_M_BSWAP_DATA                   0x000000002
+#define PI_PDATA_A_INIT_M_BSWAP_LITERAL                        0x000000001
+
+#define PI_PDATA_A_INIT_V_DESC_BLK_ADDR                        13
+#define PI_PDATA_A_INIT_V_RESERVED                             3
+#define PI_PDATA_A_INIT_V_BSWAP_DATA                   1
+#define PI_PDATA_A_INIT_V_BSWAP_LITERAL                        0
+
+/* Port Reset Register */
+
+#define PI_RESET_M_ASSERT_RESET                        1
+
+/* Port Status register */
+
+#define PI_PSTATUS_V_RCV_DATA_PENDING  31
+#define PI_PSTATUS_V_XMT_DATA_PENDING  30
+#define PI_PSTATUS_V_SMT_HOST_PENDING  29
+#define PI_PSTATUS_V_UNSOL_PENDING             28
+#define PI_PSTATUS_V_CMD_RSP_PENDING   27
+#define PI_PSTATUS_V_CMD_REQ_PENDING   26
+#define PI_PSTATUS_V_TYPE_0_PENDING            25
+#define PI_PSTATUS_V_RESERVED_1                        16
+#define PI_PSTATUS_V_RESERVED_2                        11
+#define PI_PSTATUS_V_STATE                             8
+#define PI_PSTATUS_V_HALT_ID                   0
+
+#define PI_PSTATUS_M_RCV_DATA_PENDING  0x80000000
+#define PI_PSTATUS_M_XMT_DATA_PENDING  0x40000000
+#define PI_PSTATUS_M_SMT_HOST_PENDING  0x20000000
+#define PI_PSTATUS_M_UNSOL_PENDING             0x10000000
+#define PI_PSTATUS_M_CMD_RSP_PENDING   0x08000000
+#define PI_PSTATUS_M_CMD_REQ_PENDING   0x04000000
+#define PI_PSTATUS_M_TYPE_0_PENDING            0x02000000
+#define PI_PSTATUS_M_RESERVED_1                        0x01FF0000
+#define PI_PSTATUS_M_RESERVED_2                        0x0000F800
+#define PI_PSTATUS_M_STATE                             0x00000700
+#define PI_PSTATUS_M_HALT_ID                   0x000000FF
+
+/* Define Halt Id's                                                            */
+/*   Do not insert into this list, only append. */
+
+#define PI_HALT_ID_K_SELFTEST_TIMEOUT  0
+#define PI_HALT_ID_K_PARITY_ERROR              1
+#define PI_HALT_ID_K_HOST_DIR_HALT             2
+#define PI_HALT_ID_K_SW_FAULT                  3
+#define PI_HALT_ID_K_HW_FAULT                  4
+#define PI_HALT_ID_K_PC_TRACE                  5
+#define PI_HALT_ID_K_DMA_ERROR                 6                       /* Host Data has error reg */
+#define PI_HALT_ID_K_IMAGE_CRC_ERROR   7               /* Image is bad, update it */
+#define PI_HALT_ID_K_BUS_EXCEPTION             8               /* 68K bus exception       */
+
+/* Host Interrupt Enable Register as seen by host */
+
+#define PI_HOST_INT_M_XMT_DATA_ENB             0x80000000      /* Type 2 Enables */
+#define PI_HOST_INT_M_RCV_DATA_ENB             0x40000000
+#define PI_HOST_INT_M_SMT_HOST_ENB             0x10000000      /* Type 1 Enables */
+#define PI_HOST_INT_M_UNSOL_ENB                        0x20000000
+#define PI_HOST_INT_M_CMD_RSP_ENB              0x08000000
+#define PI_HOST_INT_M_CMD_REQ_ENB              0x04000000
+#define        PI_HOST_INT_M_TYPE_1_RESERVED   0x00FF0000
+#define        PI_HOST_INT_M_TYPE_0_RESERVED   0x0000FF00      /* Type 0 Enables */
+#define PI_HOST_INT_M_1MS                              0x00000080
+#define PI_HOST_INT_M_20MS                             0x00000040
+#define PI_HOST_INT_M_CSR_CMD_DONE             0x00000020
+#define PI_HOST_INT_M_STATE_CHANGE             0x00000010
+#define PI_HOST_INT_M_XMT_FLUSH                        0x00000008
+#define PI_HOST_INT_M_NXM                              0x00000004
+#define PI_HOST_INT_M_PM_PAR_ERR               0x00000002
+#define PI_HOST_INT_M_BUS_PAR_ERR              0x00000001
+
+#define PI_HOST_INT_V_XMT_DATA_ENB             31                      /* Type 2 Enables */
+#define PI_HOST_INT_V_RCV_DATA_ENB             30
+#define PI_HOST_INT_V_SMT_HOST_ENB             29                      /* Type 1 Enables */
+#define PI_HOST_INT_V_UNSOL_ENB                        28
+#define PI_HOST_INT_V_CMD_RSP_ENB              27
+#define PI_HOST_INT_V_CMD_REQ_ENB              26
+#define        PI_HOST_INT_V_TYPE_1_RESERVED   16
+#define        PI_HOST_INT_V_TYPE_0_RESERVED   8                       /* Type 0 Enables */
+#define PI_HOST_INT_V_1MS_ENB                  7
+#define PI_HOST_INT_V_20MS_ENB                 6
+#define PI_HOST_INT_V_CSR_CMD_DONE_ENB 5
+#define PI_HOST_INT_V_STATE_CHANGE_ENB 4
+#define PI_HOST_INT_V_XMT_FLUSH_ENB    3
+#define PI_HOST_INT_V_NXM_ENB                  2
+#define PI_HOST_INT_V_PM_PAR_ERR_ENB   1
+#define PI_HOST_INT_V_BUS_PAR_ERR_ENB  0
+
+#define PI_HOST_INT_K_ACK_ALL_TYPE_0   0x000000FF
+#define PI_HOST_INT_K_DISABLE_ALL_INTS 0x00000000
+#define PI_HOST_INT_K_ENABLE_ALL_INTS  0xFFFFFFFF
+#define PI_HOST_INT_K_ENABLE_DEF_INTS  0xC000001F
+
+/* Type 0 Interrupt Status Register */
+
+#define PI_TYPE_0_STAT_M_1MS                   0x00000080
+#define PI_TYPE_0_STAT_M_20MS                  0x00000040
+#define PI_TYPE_0_STAT_M_CSR_CMD_DONE  0x00000020
+#define PI_TYPE_0_STAT_M_STATE_CHANGE  0x00000010
+#define PI_TYPE_0_STAT_M_XMT_FLUSH             0x00000008
+#define PI_TYPE_0_STAT_M_NXM                   0x00000004
+#define PI_TYPE_0_STAT_M_PM_PAR_ERR            0x00000002
+#define PI_TYPE_0_STAT_M_BUS_PAR_ERR   0x00000001
+
+#define PI_TYPE_0_STAT_V_1MS                   7
+#define PI_TYPE_0_STAT_V_20MS                  6
+#define PI_TYPE_0_STAT_V_CSR_CMD_DONE  5
+#define PI_TYPE_0_STAT_V_STATE_CHANGE  4
+#define PI_TYPE_0_STAT_V_XMT_FLUSH             3
+#define PI_TYPE_0_STAT_V_NXM                   2
+#define PI_TYPE_0_STAT_V_PM_PAR_ERR            1
+#define PI_TYPE_0_STAT_V_BUS_PAR_ERR   0
+
+/* Register definition structures are defined for both big and little endian systems */
+
+#ifndef __BIG_ENDIAN
+
+/* Little endian format of Type 1 Producer register */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        prod;
+               PI_UINT8        comp;
+               PI_UINT8        mbz_1;
+               PI_UINT8        mbz_2;
+               } index;
+       } PI_TYPE_1_PROD_REG;
+
+/* Little endian format of Type 2 Producer register */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        rcv_prod;
+               PI_UINT8        xmt_prod;
+               PI_UINT8        rcv_comp;
+               PI_UINT8        xmt_comp;
+               } index;
+       } PI_TYPE_2_PROD_REG;
+
+/* Little endian format of Type 1 Consumer Block longword */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        cons;
+               PI_UINT8        res0;
+               PI_UINT8        res1;
+               PI_UINT8        res2;
+               } index;
+       } PI_TYPE_1_CONSUMER;
+
+/* Little endian format of Type 2 Consumer Block longword */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        rcv_cons;
+               PI_UINT8        res0;
+               PI_UINT8        xmt_cons;
+               PI_UINT8        res1;
+               } index;
+       } PI_TYPE_2_CONSUMER;
+
+/* Define swapping required by DMA transfers.  */
+#define PI_PDATA_A_INIT_M_BSWAP_INIT   \
+       (PI_PDATA_A_INIT_M_BSWAP_DATA)
+
+#else /* __BIG_ENDIAN */
+
+/* Big endian format of Type 1 Producer register */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        mbz_2;
+               PI_UINT8        mbz_1;
+               PI_UINT8        comp;
+               PI_UINT8        prod;
+               } index;
+       } PI_TYPE_1_PROD_REG;
+
+/* Big endian format of Type 2 Producer register */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        xmt_comp;
+               PI_UINT8        rcv_comp;
+               PI_UINT8        xmt_prod;
+               PI_UINT8        rcv_prod;
+               } index;
+       } PI_TYPE_2_PROD_REG;
+
+/* Big endian format of Type 1 Consumer Block longword */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        res2;
+               PI_UINT8        res1;
+               PI_UINT8        res0;
+               PI_UINT8        cons;
+               } index;
+       } PI_TYPE_1_CONSUMER;
+
+/* Big endian format of Type 2 Consumer Block longword */
+
+typedef union
+       {
+       PI_UINT32       lword;
+       struct
+               {
+               PI_UINT8        res1;
+               PI_UINT8        xmt_cons;
+               PI_UINT8        res0;
+               PI_UINT8        rcv_cons;
+               } index;
+       } PI_TYPE_2_CONSUMER;
+
+/* Define swapping required by DMA transfers.  */
+#define PI_PDATA_A_INIT_M_BSWAP_INIT   \
+       (PI_PDATA_A_INIT_M_BSWAP_DATA | PI_PDATA_A_INIT_M_BSWAP_LITERAL)
+
+#endif /* __BIG_ENDIAN */
+
+/* Define TC PDQ CSR offset and length */
+
+#define PI_TC_K_CSR_OFFSET             0x100000
+#define PI_TC_K_CSR_LEN                        0x40            /* 64 bytes */
+
+/* Define EISA controller register offsets */
+
+#define PI_ESIC_K_CSR_IO_LEN           0x80            /* 128 bytes */
+
+#define PI_DEFEA_K_BURST_HOLDOFF       0x040
+
+#define PI_ESIC_K_SLOT_ID              0xC80
+#define PI_ESIC_K_SLOT_CNTRL           0xC84
+#define PI_ESIC_K_MEM_ADD_CMP_0        0xC85
+#define PI_ESIC_K_MEM_ADD_CMP_1        0xC86
+#define PI_ESIC_K_MEM_ADD_CMP_2        0xC87
+#define PI_ESIC_K_MEM_ADD_HI_CMP_0     0xC88
+#define PI_ESIC_K_MEM_ADD_HI_CMP_1     0xC89
+#define PI_ESIC_K_MEM_ADD_HI_CMP_2     0xC8A
+#define PI_ESIC_K_MEM_ADD_MASK_0       0xC8B
+#define PI_ESIC_K_MEM_ADD_MASK_1       0xC8C
+#define PI_ESIC_K_MEM_ADD_MASK_2       0xC8D
+#define PI_ESIC_K_MEM_ADD_LO_CMP_0     0xC8E
+#define PI_ESIC_K_MEM_ADD_LO_CMP_1     0xC8F
+#define PI_ESIC_K_MEM_ADD_LO_CMP_2     0xC90
+#define PI_ESIC_K_IO_ADD_CMP_0_0       0xC91
+#define PI_ESIC_K_IO_ADD_CMP_0_1       0xC92
+#define PI_ESIC_K_IO_ADD_CMP_1_0       0xC93
+#define PI_ESIC_K_IO_ADD_CMP_1_1       0xC94
+#define PI_ESIC_K_IO_ADD_CMP_2_0       0xC95
+#define PI_ESIC_K_IO_ADD_CMP_2_1       0xC96
+#define PI_ESIC_K_IO_ADD_CMP_3_0       0xC97
+#define PI_ESIC_K_IO_ADD_CMP_3_1       0xC98
+#define PI_ESIC_K_IO_ADD_MASK_0_0      0xC99
+#define PI_ESIC_K_IO_ADD_MASK_0_1      0xC9A
+#define PI_ESIC_K_IO_ADD_MASK_1_0      0xC9B
+#define PI_ESIC_K_IO_ADD_MASK_1_1      0xC9C
+#define PI_ESIC_K_IO_ADD_MASK_2_0      0xC9D
+#define PI_ESIC_K_IO_ADD_MASK_2_1      0xC9E
+#define PI_ESIC_K_IO_ADD_MASK_3_0      0xC9F
+#define PI_ESIC_K_IO_ADD_MASK_3_1      0xCA0
+#define PI_ESIC_K_MOD_CONFIG_1         0xCA1
+#define PI_ESIC_K_MOD_CONFIG_2         0xCA2
+#define PI_ESIC_K_MOD_CONFIG_3         0xCA3
+#define PI_ESIC_K_MOD_CONFIG_4         0xCA4
+#define PI_ESIC_K_MOD_CONFIG_5         0xCA5
+#define PI_ESIC_K_MOD_CONFIG_6         0xCA6
+#define PI_ESIC_K_MOD_CONFIG_7         0xCA7
+#define PI_ESIC_K_DIP_SWITCH           0xCA8
+#define PI_ESIC_K_IO_CONFIG_STAT_0     0xCA9
+#define PI_ESIC_K_IO_CONFIG_STAT_1     0xCAA
+#define PI_ESIC_K_DMA_CONFIG           0xCAB
+#define PI_ESIC_K_INPUT_PORT           0xCAC
+#define PI_ESIC_K_OUTPUT_PORT          0xCAD
+#define PI_ESIC_K_FUNCTION_CNTRL       0xCAE
+
+/* Define the bits in the function control register. */
+
+#define PI_FUNCTION_CNTRL_M_IOCS0      0x01
+#define PI_FUNCTION_CNTRL_M_IOCS1      0x02
+#define PI_FUNCTION_CNTRL_M_IOCS2      0x04
+#define PI_FUNCTION_CNTRL_M_IOCS3      0x08
+#define PI_FUNCTION_CNTRL_M_MEMCS0     0x10
+#define PI_FUNCTION_CNTRL_M_MEMCS1     0x20
+#define PI_FUNCTION_CNTRL_M_DMA                0x80
+
+/* Define the bits in the slot control register. */
+
+#define PI_SLOT_CNTRL_M_RESET          0x04    /* Don't use.       */
+#define PI_SLOT_CNTRL_M_ERROR          0x02    /* Not implemented. */
+#define PI_SLOT_CNTRL_M_ENB            0x01    /* Must be set.     */
+
+/* Define the bits in the burst holdoff register. */
+
+#define PI_BURST_HOLDOFF_M_HOLDOFF     0xFC
+#define PI_BURST_HOLDOFF_M_RESERVED    0x02
+#define PI_BURST_HOLDOFF_M_MEM_MAP     0x01
+
+#define PI_BURST_HOLDOFF_V_HOLDOFF     2
+#define PI_BURST_HOLDOFF_V_RESERVED    1
+#define PI_BURST_HOLDOFF_V_MEM_MAP     0
+
+/* Define the implicit mask of the Memory Address Mask Register.  */
+
+#define PI_MEM_ADD_MASK_M              0x3ff
+
+/*
+ * Define the fields in the IO Compare registers.
+ * The driver must initialize the slot field with the slot ID shifted by the
+ * amount shown below.
+ */
+
+#define PI_IO_CMP_V_SLOT               4
+
+/* Define the fields in the Interrupt Channel Configuration and Status reg */
+
+#define PI_CONFIG_STAT_0_M_PEND                        0x80
+#define PI_CONFIG_STAT_0_M_RES_1               0x40
+#define PI_CONFIG_STAT_0_M_IREQ_OUT            0x20
+#define PI_CONFIG_STAT_0_M_IREQ_IN             0x10
+#define PI_CONFIG_STAT_0_M_INT_ENB             0x08
+#define PI_CONFIG_STAT_0_M_RES_0               0x04
+#define PI_CONFIG_STAT_0_M_IRQ                 0x03
+
+#define PI_CONFIG_STAT_0_V_PEND                        7
+#define PI_CONFIG_STAT_0_V_RES_1               6
+#define PI_CONFIG_STAT_0_V_IREQ_OUT            5
+#define PI_CONFIG_STAT_0_V_IREQ_IN             4
+#define PI_CONFIG_STAT_0_V_INT_ENB             3
+#define PI_CONFIG_STAT_0_V_RES_0               2
+#define PI_CONFIG_STAT_0_V_IRQ                 0
+
+#define PI_CONFIG_STAT_0_IRQ_K_9               0
+#define PI_CONFIG_STAT_0_IRQ_K_10              1
+#define PI_CONFIG_STAT_0_IRQ_K_11              2
+#define PI_CONFIG_STAT_0_IRQ_K_15              3
+
+/* Define DEC FDDIcontroller/EISA (DEFEA) EISA hardware ID's */
+
+#define DEFEA_PRODUCT_ID       0x0030A310              /* DEC product 300 (no rev)     */
+#define DEFEA_PROD_ID_1                0x0130A310              /* DEC product 300, rev 1       */
+#define DEFEA_PROD_ID_2                0x0230A310              /* DEC product 300, rev 2       */
+#define DEFEA_PROD_ID_3                0x0330A310              /* DEC product 300, rev 3       */
+#define DEFEA_PROD_ID_4                0x0430A310              /* DEC product 300, rev 4       */
+
+/**********************************************/
+/* Digital PFI Specification v1.0 Definitions */
+/**********************************************/
+
+/* PCI Configuration Space Constants */
+
+#define PFI_K_LAT_TIMER_DEF                    0x88    /* def max master latency timer */
+#define PFI_K_LAT_TIMER_MIN                    0x20    /* min max master latency timer */
+#define PFI_K_CSR_MEM_LEN                      0x80    /* 128 bytes */
+#define PFI_K_CSR_IO_LEN                       0x80    /* 128 bytes */
+#define PFI_K_PKT_MEM_LEN                      0x10000 /* 64K bytes */
+
+/* PFI Register Offsets (starting at PDQ Register Base Address) */
+
+#define PFI_K_REG_RESERVED_0            0X00000038
+#define PFI_K_REG_RESERVED_1            0X0000003C
+#define PFI_K_REG_MODE_CTRL             0X00000040
+#define PFI_K_REG_STATUS                0X00000044
+#define PFI_K_REG_FIFO_WRITE            0X00000048
+#define PFI_K_REG_FIFO_READ             0X0000004C
+
+/* PFI Mode Control Register Constants */
+
+#define PFI_MODE_M_RESERVED             0XFFFFFFF0
+#define PFI_MODE_M_TGT_ABORT_ENB        0X00000008
+#define PFI_MODE_M_PDQ_INT_ENB          0X00000004
+#define PFI_MODE_M_PFI_INT_ENB          0X00000002
+#define PFI_MODE_M_DMA_ENB              0X00000001
+
+#define PFI_MODE_V_RESERVED             4
+#define PFI_MODE_V_TGT_ABORT_ENB        3
+#define PFI_MODE_V_PDQ_INT_ENB          2
+#define PFI_MODE_V_PFI_INT_ENB          1
+#define PFI_MODE_V_DMA_ENB              0
+
+#define PFI_MODE_K_ALL_DISABLE          0X00000000
+
+/* PFI Status Register Constants */
+
+#define PFI_STATUS_M_RESERVED           0XFFFFFFC0
+#define PFI_STATUS_M_PFI_ERROR          0X00000020             /* only valid in rev 1 or later PFI */
+#define PFI_STATUS_M_PDQ_INT            0X00000010
+#define PFI_STATUS_M_PDQ_DMA_ABORT      0X00000008
+#define PFI_STATUS_M_FIFO_FULL          0X00000004
+#define PFI_STATUS_M_FIFO_EMPTY                 0X00000002
+#define PFI_STATUS_M_DMA_IN_PROGRESS    0X00000001
+
+#define PFI_STATUS_V_RESERVED           6
+#define PFI_STATUS_V_PFI_ERROR          5                      /* only valid in rev 1 or later PFI */
+#define PFI_STATUS_V_PDQ_INT            4
+#define PFI_STATUS_V_PDQ_DMA_ABORT      3
+#define PFI_STATUS_V_FIFO_FULL          2
+#define PFI_STATUS_V_FIFO_EMPTY                 1
+#define PFI_STATUS_V_DMA_IN_PROGRESS 0
+
+#define DFX_FC_PRH2_PRH1_PRH0          0x54003820      /* Packet Request Header bytes + FC */
+#define DFX_PRH0_BYTE                  0x20            /* Packet Request Header byte 0 */
+#define DFX_PRH1_BYTE                  0x38            /* Packet Request Header byte 1 */
+#define DFX_PRH2_BYTE                  0x00            /* Packet Request Header byte 2 */
+
+/* Driver routine status (return) codes */
+
+#define DFX_K_SUCCESS                  0                       /* routine succeeded */
+#define DFX_K_FAILURE                  1                       /* routine failed */
+#define DFX_K_OUTSTATE                 2                       /* bad state for command */
+#define DFX_K_HW_TIMEOUT               3                       /* command timed out */
+
+/* Define LLC host receive buffer min/max/default values */
+
+#define RCV_BUFS_MIN   2                                       /* minimum pre-allocated receive buffers */
+#define RCV_BUFS_MAX   32                                      /* maximum pre-allocated receive buffers */
+#define RCV_BUFS_DEF   8                                       /* default pre-allocated receive buffers */
+
+/* Define offsets into FDDI LLC or SMT receive frame buffers - used when indicating frames */
+
+#define RCV_BUFF_K_DESCR       0                               /* four byte FMC descriptor */
+#define RCV_BUFF_K_PADDING     4                               /* three null bytes */
+#define RCV_BUFF_K_FC          7                               /* one byte frame control */
+#define RCV_BUFF_K_DA          8                               /* six byte destination address */
+#define RCV_BUFF_K_SA          14                              /* six byte source address */
+#define RCV_BUFF_K_DATA                20                              /* offset to start of packet data */
+
+/* Define offsets into FDDI LLC transmit frame buffers - used when sending frames */
+
+#define XMT_BUFF_K_FC          0                               /* one byte frame control */
+#define XMT_BUFF_K_DA          1                               /* six byte destination address */
+#define XMT_BUFF_K_SA          7                               /* six byte source address */
+#define XMT_BUFF_K_DATA                13                              /* offset to start of packet data */
+
+/* Macro for checking a "value" is within a specific range */
+
+#define IN_RANGE(value,low,high) ((value >= low) && (value <= high))
+
+/* Only execute special print call when debug driver was built */
+
+#ifdef DEFXX_DEBUG
+#define DBG_printk(args...) printk(## args)
+#else
+#define DBG_printk(args...)
+#endif
+
+/* Define constants for masking/unmasking interrupts */
+
+#define DFX_MASK_INTERRUPTS            1
+#define DFX_UNMASK_INTERRUPTS          0
+
+/* Define structure for driver transmit descriptor block */
+
+typedef struct
+       {
+       struct sk_buff  *p_skb;                                 /* ptr to skb */
+       } XMT_DRIVER_DESCR;
+
+typedef struct DFX_board_tag
+       {
+       /* Keep virtual and physical pointers to locked, physically contiguous memory */
+
+       char                            *kmalloced;                                     /* pci_free_consistent this on unload */
+       dma_addr_t                      kmalloced_dma;
+       /* DMA handle for the above */
+       PI_DESCR_BLOCK                  *descr_block_virt;                              /* PDQ descriptor block virt address */
+       dma_addr_t                      descr_block_phys;                               /* PDQ descriptor block phys address */
+       PI_DMA_CMD_REQ                  *cmd_req_virt;                                  /* Command request buffer virt address */
+       dma_addr_t                      cmd_req_phys;                                   /* Command request buffer phys address */
+       PI_DMA_CMD_RSP                  *cmd_rsp_virt;                                  /* Command response buffer virt address */
+       dma_addr_t                      cmd_rsp_phys;                                   /* Command response buffer phys address */
+       char                            *rcv_block_virt;                                /* LLC host receive queue buf blk virt */
+       dma_addr_t                      rcv_block_phys;                                 /* LLC host receive queue buf blk phys */
+       PI_CONSUMER_BLOCK               *cons_block_virt;                               /* PDQ consumer block virt address */
+       dma_addr_t                      cons_block_phys;                                /* PDQ consumer block phys address */
+
+       /* Keep local copies of Type 1 and Type 2 register data */
+
+       PI_TYPE_1_PROD_REG              cmd_req_reg;                                    /* Command Request register */
+       PI_TYPE_1_PROD_REG              cmd_rsp_reg;                                    /* Command Response register */
+       PI_TYPE_2_PROD_REG              rcv_xmt_reg;                                    /* Type 2 (RCV/XMT) register */
+
+       /* Storage for unicast and multicast address entries in adapter CAM */
+
+       u8                              uc_table[1*FDDI_K_ALEN];
+       u32                             uc_count;                                               /* number of unicast addresses */
+       u8                              mc_table[PI_CMD_ADDR_FILTER_K_SIZE*FDDI_K_ALEN];
+       u32                             mc_count;                                               /* number of multicast addresses */
+
+       /* Current packet filter settings */
+
+       u32                             ind_group_prom;                                 /* LLC individual & group frame prom mode */
+       u32                             group_prom;                                     /* LLC group (multicast) frame prom mode */
+
+       /* Link available flag needed to determine whether to drop outgoing packet requests */
+
+       u32                             link_available;                                 /* is link available? */
+
+       /* Resources to indicate reset type when resetting adapter */
+
+       u32                             reset_type;                                     /* skip or rerun diagnostics */
+
+       /* Store pointers to receive buffers for queue processing code */
+
+       char                            *p_rcv_buff_va[PI_RCV_DATA_K_NUM_ENTRIES];
+
+       /* Store pointers to transmit buffers for transmit completion code */
+
+       XMT_DRIVER_DESCR                xmt_drv_descr_blk[PI_XMT_DATA_K_NUM_ENTRIES];
+
+       /* Transmit spinlocks */
+
+       spinlock_t                      lock;
+
+       /* Store device, bus-specific, and parameter information for this adapter */
+
+       struct net_device               *dev;                                           /* pointer to device structure */
+       union {
+               void __iomem *mem;
+               int port;
+       } base;                                                                         /* base address */
+       struct device                   *bus_dev;
+       u32                             full_duplex_enb;                                /* FDDI Full Duplex enable (1 == on, 2 == off) */
+       u32                             req_ttrt;                                       /* requested TTRT value (in 80ns units) */
+       u32                             burst_size;                                     /* adapter burst size (enumerated) */
+       u32                             rcv_bufs_to_post;                               /* receive buffers to post for LLC host queue */
+       u8                              factory_mac_addr[FDDI_K_ALEN];                  /* factory (on-board) MAC address */
+
+       /* Common FDDI statistics structure and private counters */
+
+       struct fddi_statistics  stats;
+
+       u32                             rcv_discards;
+       u32                             rcv_crc_errors;
+       u32                             rcv_frame_status_errors;
+       u32                             rcv_length_errors;
+       u32                             rcv_total_frames;
+       u32                             rcv_multicast_frames;
+       u32                             rcv_total_bytes;
+
+       u32                             xmt_discards;
+       u32                             xmt_length_errors;
+       u32                             xmt_total_frames;
+       u32                             xmt_total_bytes;
+       } DFX_board_t;
+
+#endif /* #ifndef _DEFXX_H_ */
diff --git a/drivers/net/fddi/skfp/Makefile b/drivers/net/fddi/skfp/Makefile
new file mode 100644 (file)
index 0000000..b0be023
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the SysKonnect FDDI PCI adapter driver
+#
+
+obj-$(CONFIG_SKFP) += skfp.o
+
+skfp-objs :=  skfddi.o    hwmtm.o    fplustm.o  smt.o      cfm.o     \
+              ecm.o       pcmplc.o   pmf.o      queue.o    rmt.o     \
+             smtdef.o    smtinit.o  smttimer.o srf.o      hwt.o     \
+             drvfbi.o   ess.o
+
+# NOTE:
+#   Compiling this driver produces some warnings (and some more are 
+#   switched off below), but I did not fix this, because the Hardware
+#   Module source (see skfddi.c for details) is used for different
+#   drivers, and fixing it for Linux might bring problems on other
+#   projects. To keep the source common for all those drivers (and
+#   thus simplify fixes to it), please do not clean it up!
+
+ccflags-y := -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes
diff --git a/drivers/net/fddi/skfp/cfm.c b/drivers/net/fddi/skfp/cfm.c
new file mode 100644 (file)
index 0000000..e395ace
--- /dev/null
@@ -0,0 +1,627 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT CFM
+       Configuration Management
+       DAS with single MAC
+*/
+
+/*
+ *     Hardware independent state machine implemantation
+ *     The following external SMT functions are referenced :
+ *
+ *             queue_event()
+ *
+ *     The following external HW dependent functions are referenced :
+ *             config_mux()
+ *
+ *     The following HW dependent events are required :
+ *             NONE 
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)cfm.c       2.18 98/10/06 (C) SK " ;
+#endif
+
+/*
+ * FSM Macros
+ */
+#define AFLAG  0x10
+#define GO_STATE(x)    (smc->mib.fddiSMTCF_State = (x)|AFLAG)
+#define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG)
+#define ACTIONS(x)     (x|AFLAG)
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const cfm_states[] = {
+       "SC0_ISOLATED","CF1","CF2","CF3","CF4",
+       "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S",
+       "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const cfm_events[] = {
+       "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B"
+} ;
+#endif
+
+/*
+ * map from state to downstream port type
+ */
+static const unsigned char cf_to_ptype[] = {
+       TNONE,TNONE,TNONE,TNONE,TNONE,
+       TNONE,TB,TB,TS,
+       TA,TB,TS,TB
+} ;
+
+/*
+ * CEM port states
+ */
+#define        CEM_PST_DOWN    0
+#define        CEM_PST_UP      1
+#define        CEM_PST_HOLD    2
+/* define portstate array only for A and B port */
+/* Do this within the smc structure (use in multiple cards) */
+
+/*
+ * all Globals  are defined in smc.h
+ * struct s_cfm
+ */
+
+/*
+ * function declarations
+ */
+static void cfm_fsm(struct s_smc *smc, int cmd);
+
+/*
+       init CFM state machine
+       clear all CFM vars and flags
+*/
+void cfm_init(struct s_smc *smc)
+{
+       smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
+       smc->r.rm_join = 0 ;
+       smc->r.rm_loop = 0 ;
+       smc->y[PA].scrub = 0 ;
+       smc->y[PB].scrub = 0 ;
+       smc->y[PA].cem_pst = CEM_PST_DOWN ;
+       smc->y[PB].cem_pst = CEM_PST_DOWN ;
+}
+
+/* Some terms conditions used by the selection criteria */
+#define THRU_ENABLED(smc)      (smc->y[PA].pc_mode != PM_TREE && \
+                                smc->y[PB].pc_mode != PM_TREE)
+/* Selection criteria for the ports */
+static void selection_criteria (struct s_smc *smc, struct s_phy *phy)
+{
+
+       switch (phy->mib->fddiPORTMy_Type) {
+       case TA:
+               if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) {
+                       phy->wc_flag = TRUE ;
+               } else {
+                       phy->wc_flag = FALSE ;
+               }
+
+               break;
+       case TB:
+               /* take precedence over PA */
+               phy->wc_flag = FALSE ;
+               break;
+       case TS:
+               phy->wc_flag = FALSE ;
+               break;
+       case TM:
+               phy->wc_flag = FALSE ;
+               break;
+       }
+
+}
+
+void all_selection_criteria(struct s_smc *smc)
+{
+       struct s_phy    *phy ;
+       int             p ;
+
+       for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) {
+               /* Do the selection criteria */
+               selection_criteria (smc,phy);
+       }
+}
+
+static void cem_priv_state(struct s_smc *smc, int event)
+/* State machine for private PORT states: used to optimize dual homing */
+{
+       int     np;     /* Number of the port */
+       int     i;
+
+       /* Do this only in a DAS */
+       if (smc->s.sas != SMT_DAS )
+               return ;
+
+       np = event - CF_JOIN;
+
+       if (np != PA && np != PB) {
+               return ;
+       }
+       /* Change the port state according to the event (portnumber) */
+       if (smc->y[np].cf_join) {
+               smc->y[np].cem_pst = CEM_PST_UP ;
+       } else if (!smc->y[np].wc_flag) {
+               /* set the port to done only if it is not withheld */
+               smc->y[np].cem_pst = CEM_PST_DOWN ;
+       }
+
+       /* Don't set an hold port to down */
+
+       /* Check all ports of restart conditions */
+       for (i = 0 ; i < 2 ; i ++ ) {
+               /* Check all port for PORT is on hold and no withhold is done */
+               if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) {
+                       smc->y[i].cem_pst = CEM_PST_DOWN;
+                       queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
+               }
+               if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) {
+                       smc->y[i].cem_pst = CEM_PST_HOLD;
+                       queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
+               }
+               if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) {
+                       /*
+                        * The port must be restarted when the wc_flag
+                        * will be reset. So set the port on hold.
+                        */
+                       smc->y[i].cem_pst = CEM_PST_HOLD;
+               }
+       }
+       return ;
+}
+
+/*
+       CFM state machine
+       called by dispatcher
+
+       do
+               display state change
+               process event
+       until SM is stable
+*/
+void cfm(struct s_smc *smc, int event)
+{
+       int     state ;         /* remember last state */
+       int     cond ;
+       int     oldstate ;
+
+       /* We will do the following: */
+       /*  - compute the variable WC_Flag for every port (This is where */
+       /*    we can extend the requested path checking !!) */
+       /*  - do the old (SMT 6.2 like) state machine */
+       /*  - do the resulting station states */
+
+       all_selection_criteria (smc);
+
+       /* We will check now whether a state transition is allowed or not */
+       /*  - change the portstates */
+       cem_priv_state (smc, event);
+
+       oldstate = smc->mib.fddiSMTCF_State ;
+       do {
+               DB_CFM("CFM : state %s%s",
+                       (smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "",
+                       cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ;
+               DB_CFM(" event %s\n",cfm_events[event],0) ;
+               state = smc->mib.fddiSMTCF_State ;
+               cfm_fsm(smc,event) ;
+               event = 0 ;
+       } while (state != smc->mib.fddiSMTCF_State) ;
+
+#ifndef        SLIM_SMT
+       /*
+        * check peer wrap condition
+        */
+       cond = FALSE ;
+       if (    (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
+               smc->y[PA].pc_mode == PM_PEER)  ||
+               (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
+               smc->y[PB].pc_mode == PM_PEER)  ||
+               (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
+               smc->y[PS].pc_mode == PM_PEER &&
+               smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
+                       cond = TRUE ;
+       }
+       if (cond != smc->mib.fddiSMTPeerWrapFlag)
+               smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ;
+
+#if    0
+       /*
+        * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired
+        * to the primary path.
+        */
+       /*
+        * path change
+        */
+       if (smc->mib.fddiSMTCF_State != oldstate) {
+               smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ;
+       }
+#endif
+#endif /* no SLIM_SMT */
+
+       /*
+        * set MAC port type
+        */
+       smc->mib.m[MAC0].fddiMACDownstreamPORTType =
+               cf_to_ptype[smc->mib.fddiSMTCF_State] ;
+       cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
+}
+
+/*
+       process CFM event
+*/
+/*ARGSUSED1*/
+static void cfm_fsm(struct s_smc *smc, int cmd)
+{
+       switch(smc->mib.fddiSMTCF_State) {
+       case ACTIONS(SC0_ISOLATED) :
+               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+               smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
+               smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
+               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
+               config_mux(smc,MUX_ISOLATE) ;   /* configure PHY Mux */
+               smc->r.rm_loop = FALSE ;
+               smc->r.rm_join = FALSE ;
+               queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+               /* Don't do the WC-Flag changing here */
+               ACTIONS_DONE() ;
+               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+               break;
+       case SC0_ISOLATED :
+               /*SC07*/
+               /*SAS port can be PA or PB ! */
+               if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
+                               smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
+                       GO_STATE(SC11_C_WRAP_S) ;
+                       break ;
+               }
+               /*SC01*/
+               if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
+                    !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
+                       GO_STATE(SC9_C_WRAP_A) ;
+                       break ;
+               }
+               /*SC02*/
+               if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
+                    !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
+                       GO_STATE(SC10_C_WRAP_B) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(SC9_C_WRAP_A) :
+               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
+               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+               smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
+               smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
+               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
+               config_mux(smc,MUX_WRAPA) ;             /* configure PHY mux */
+               if (smc->y[PA].cf_loop) {
+                       smc->r.rm_join = FALSE ;
+                       smc->r.rm_loop = TRUE ;
+                       queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
+               }
+               if (smc->y[PA].cf_join) {
+                       smc->r.rm_loop = FALSE ;
+                       smc->r.rm_join = TRUE ;
+                       queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+               }
+               ACTIONS_DONE() ;
+               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+               break ;
+       case SC9_C_WRAP_A :
+               /*SC10*/
+               if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
+                     !smc->y[PA].cf_loop ) {
+                       GO_STATE(SC0_ISOLATED) ;
+                       break ;
+               }
+               /*SC12*/
+               else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
+                          smc->y[PA].cem_pst == CEM_PST_UP) ||
+                         ((smc->y[PB].cf_loop ||
+                          (smc->y[PB].cf_join &&
+                           smc->y[PB].cem_pst == CEM_PST_UP)) &&
+                           (smc->y[PA].pc_mode == PM_TREE ||
+                            smc->y[PB].pc_mode == PM_TREE))) {
+                       smc->y[PA].scrub = TRUE ;
+                       GO_STATE(SC10_C_WRAP_B) ;
+                       break ;
+               }
+               /*SC14*/
+               else if (!smc->s.attach_s &&
+                         smc->y[PA].cf_join &&
+                         smc->y[PA].cem_pst == CEM_PST_UP &&
+                         smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
+                         smc->y[PB].cem_pst == CEM_PST_UP &&
+                         smc->y[PB].pc_mode == PM_PEER) {
+                       smc->y[PA].scrub = TRUE ;
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC4_THRU_A) ;
+                       break ;
+               }
+               /*SC15*/
+               else if ( smc->s.attach_s &&
+                         smc->y[PA].cf_join &&
+                         smc->y[PA].cem_pst == CEM_PST_UP &&
+                         smc->y[PA].pc_mode == PM_PEER &&
+                         smc->y[PB].cf_join &&
+                         smc->y[PB].cem_pst == CEM_PST_UP &&
+                         smc->y[PB].pc_mode == PM_PEER) {
+                       smc->y[PA].scrub = TRUE ;
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC5_THRU_B) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(SC10_C_WRAP_B) :
+               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
+               smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
+               smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
+               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
+               config_mux(smc,MUX_WRAPB) ;             /* configure PHY mux */
+               if (smc->y[PB].cf_loop) {
+                       smc->r.rm_join = FALSE ;
+                       smc->r.rm_loop = TRUE ;
+                       queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
+               }
+               if (smc->y[PB].cf_join) {
+                       smc->r.rm_loop = FALSE ;
+                       smc->r.rm_join = TRUE ;
+                       queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+               }
+               ACTIONS_DONE() ;
+               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+               break ;
+       case SC10_C_WRAP_B :
+               /*SC20*/
+               if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
+                       GO_STATE(SC0_ISOLATED) ;
+                       break ;
+               }
+               /*SC21*/
+               else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
+                         smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC9_C_WRAP_A) ;
+                       break ;
+               }
+               /*SC24*/
+               else if (!smc->s.attach_s &&
+                        smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
+                        smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
+                       smc->y[PA].scrub = TRUE ;
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC4_THRU_A) ;
+                       break ;
+               }
+               /*SC25*/
+               else if ( smc->s.attach_s &&
+                        smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
+                        smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
+                       smc->y[PA].scrub = TRUE ;
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC5_THRU_B) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(SC4_THRU_A) :
+               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
+               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
+               smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
+               smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
+               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
+               config_mux(smc,MUX_THRUA) ;             /* configure PHY mux */
+               smc->r.rm_loop = FALSE ;
+               smc->r.rm_join = TRUE ;
+               queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+               ACTIONS_DONE() ;
+               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+               break ;
+       case SC4_THRU_A :
+               /*SC41*/
+               if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
+                       smc->y[PA].scrub = TRUE ;
+                       GO_STATE(SC9_C_WRAP_A) ;
+                       break ;
+               }
+               /*SC42*/
+               else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC10_C_WRAP_B) ;
+                       break ;
+               }
+               /*SC45*/
+               else if (smc->s.attach_s) {
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC5_THRU_B) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(SC5_THRU_B) :
+               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
+               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
+               smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
+               smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
+               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
+               config_mux(smc,MUX_THRUB) ;             /* configure PHY mux */
+               smc->r.rm_loop = FALSE ;
+               smc->r.rm_join = TRUE ;
+               queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+               ACTIONS_DONE() ;
+               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+               break ;
+       case SC5_THRU_B :
+               /*SC51*/
+               if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
+                       smc->y[PA].scrub = TRUE ;
+                       GO_STATE(SC9_C_WRAP_A) ;
+                       break ;
+               }
+               /*SC52*/
+               else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
+                       smc->y[PB].scrub = TRUE ;
+                       GO_STATE(SC10_C_WRAP_B) ;
+                       break ;
+               }
+               /*SC54*/
+               else if (!smc->s.attach_s) {
+                       smc->y[PA].scrub = TRUE ;
+                       GO_STATE(SC4_THRU_A) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(SC11_C_WRAP_S) :
+               smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
+               smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
+               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
+               config_mux(smc,MUX_WRAPS) ;             /* configure PHY mux */
+               if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
+                       smc->r.rm_join = FALSE ;
+                       smc->r.rm_loop = TRUE ;
+                       queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
+               }
+               if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
+                       smc->r.rm_loop = FALSE ;
+                       smc->r.rm_join = TRUE ;
+                       queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
+               }
+               ACTIONS_DONE() ;
+               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
+               break ;
+       case SC11_C_WRAP_S :
+               /*SC70*/
+               if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
+                    !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
+                       GO_STATE(SC0_ISOLATED) ;
+                       break ;
+               }
+               break ;
+       default:
+               SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ;
+               break;
+       }
+}
+
+/*
+ * get MAC's input Port
+ *     return :
+ *             PA or PB
+ */
+int cfm_get_mac_input(struct s_smc *smc)
+{
+       return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+               smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
+}
+
+/*
+ * get MAC's output Port
+ *     return :
+ *             PA or PB
+ */
+int cfm_get_mac_output(struct s_smc *smc)
+{
+       return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
+               smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
+}
+
+static char path_iso[] = {
+       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_ISO,
+       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_ISO,
+       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_ISO
+} ;
+
+static char path_wrap_a[] = {
+       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_PRIM,
+       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
+       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_ISO
+} ;
+
+static char path_wrap_b[] = {
+       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_PRIM,
+       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
+       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_ISO
+} ;
+
+static char path_thru[] = {
+       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_PRIM,
+       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
+       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_PRIM
+} ;
+
+static char path_wrap_s[] = {
+       0,0,    0,RES_PORT,     0,PS + INDEX_PORT,      0,PATH_PRIM,
+       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
+} ;
+
+static char path_iso_s[] = {
+       0,0,    0,RES_PORT,     0,PS + INDEX_PORT,      0,PATH_ISO,
+       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_ISO,
+} ;
+
+int cem_build_path(struct s_smc *smc, char *to, int path_index)
+{
+       char    *path ;
+       int     len ;
+
+       switch (smc->mib.fddiSMTCF_State) {
+       default :
+       case SC0_ISOLATED :
+               path = smc->s.sas ? path_iso_s : path_iso ;
+               len = smc->s.sas ? sizeof(path_iso_s) :  sizeof(path_iso) ;
+               break ;
+       case SC9_C_WRAP_A :
+               path = path_wrap_a ;
+               len = sizeof(path_wrap_a) ;
+               break ;
+       case SC10_C_WRAP_B :
+               path = path_wrap_b ;
+               len = sizeof(path_wrap_b) ;
+               break ;
+       case SC4_THRU_A :
+               path = path_thru ;
+               len = sizeof(path_thru) ;
+               break ;
+       case SC11_C_WRAP_S :
+               path = path_wrap_s ;
+               len = sizeof(path_wrap_s) ;
+               break ;
+       }
+       memcpy(to,path,len) ;
+
+       LINT_USE(path_index);
+
+       return len;
+}
diff --git a/drivers/net/fddi/skfp/drvfbi.c b/drivers/net/fddi/skfp/drvfbi.c
new file mode 100644 (file)
index 0000000..07da97c
--- /dev/null
@@ -0,0 +1,584 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * FBI board dependent Driver for SMT and LLC
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#include "h/skfbiinc.h"
+#include <linux/bitrev.h>
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)drvfbi.c    1.63 99/02/11 (C) SK " ;
+#endif
+
+/*
+ * PCM active state
+ */
+#define PC8_ACTIVE     8
+
+#define        LED_Y_ON        0x11    /* Used for ring up/down indication */
+#define        LED_Y_OFF       0x10
+
+
+#define MS2BCLK(x)     ((x)*12500L)
+
+/*
+ * valid configuration values are:
+ */
+
+/*
+ *     xPOS_ID:xxxx
+ *     |       \  /
+ *     |        \/
+ *     |         --------------------- the patched POS_ID of the Adapter
+ *     |                               xxxx = (Vendor ID low byte,
+ *     |                                       Vendor ID high byte,
+ *     |                                       Device ID low byte,
+ *     |                                       Device ID high byte)
+ *     +------------------------------ the patched oem_id must be
+ *                                     'S' for SK or 'I' for IBM
+ *                                     this is a short id for the driver.
+ */
+#ifndef MULT_OEM
+#ifndef        OEM_CONCEPT
+const u_char oem_id[] = "xPOS_ID:xxxx" ;
+#else  /* OEM_CONCEPT */
+const u_char oem_id[] = OEM_ID ;
+#endif /* OEM_CONCEPT */
+#define        ID_BYTE0        8
+#define        OEMID(smc,i)    oem_id[ID_BYTE0 + i]
+#else  /* MULT_OEM */
+const struct s_oem_ids oem_ids[] = {
+#include "oemids.h"
+{0}
+};
+#define        OEMID(smc,i)    smc->hw.oem_id->oi_id[i]
+#endif /* MULT_OEM */
+
+/* Prototypes of external functions */
+#ifdef AIX
+extern int AIX_vpdReadByte() ;
+#endif
+
+
+/* Prototype of a local function. */
+static void smt_stop_watchdog(struct s_smc *smc);
+
+/*
+ * FDDI card reset
+ */
+static void card_start(struct s_smc *smc)
+{
+       int i ;
+#ifdef PCI
+       u_char  rev_id ;
+       u_short word;
+#endif
+
+       smt_stop_watchdog(smc) ;
+
+#ifdef PCI
+       /*
+        * make sure no transfer activity is pending
+        */
+       outpw(FM_A(FM_MDREG1),FM_MINIT) ;
+       outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
+       hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
+       /*
+        * now reset everything
+        */
+       outp(ADDR(B0_CTRL),CTRL_RST_SET) ;      /* reset for all chips */
+       i = (int) inp(ADDR(B0_CTRL)) ;          /* do dummy read */
+       SK_UNUSED(i) ;                          /* Make LINT happy. */
+       outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
+
+       /*
+        * Reset all bits in the PCI STATUS register
+        */
+       outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ;     /* enable for writes */
+       word = inpw(PCI_C(PCI_STATUS)) ;
+       outpw(PCI_C(PCI_STATUS), word | PCI_ERRBITS) ;
+       outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ;    /* disable writes */
+
+       /*
+        * Release the reset of all the State machines
+        * Release Master_Reset
+        * Release HPI_SM_Reset
+        */
+       outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
+
+       /*
+        * determine the adapter type
+        * Note: Do it here, because some drivers may call card_start() once
+        *       at very first before any other initialization functions is
+        *       executed.
+        */
+       rev_id = inp(PCI_C(PCI_REV_ID)) ;
+       if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
+               smc->hw.hw_is_64bit = TRUE ;
+       } else {
+               smc->hw.hw_is_64bit = FALSE ;
+       }
+
+       /*
+        * Watermark initialization
+        */
+       if (!smc->hw.hw_is_64bit) {
+               outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
+               outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
+               outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
+       }
+
+       outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;      /* clear the reset chips */
+       outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
+
+       /* init the timer value for the watch dog 2,5 minutes */
+       outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
+
+       /* initialize the ISR mask */
+       smc->hw.is_imask = ISR_MASK ;
+       smc->hw.hw_state = STOPPED ;
+#endif
+       GET_PAGE(0) ;           /* necessary for BOOT */
+}
+
+void card_stop(struct s_smc *smc)
+{
+       smt_stop_watchdog(smc) ;
+       smc->hw.mac_ring_is_up = 0 ;            /* ring down */
+
+#ifdef PCI
+       /*
+        * make sure no transfer activity is pending
+        */
+       outpw(FM_A(FM_MDREG1),FM_MINIT) ;
+       outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
+       hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
+       /*
+        * now reset everything
+        */
+       outp(ADDR(B0_CTRL),CTRL_RST_SET) ;      /* reset for all chips */
+       outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;      /* reset for all chips */
+       outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
+       smc->hw.hw_state = STOPPED ;
+#endif
+}
+/*--------------------------- ISR handling ----------------------------------*/
+
+void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
+{
+       int     restart_tx = 0 ;
+again:
+
+       /*
+        * parity error: note encoding error is not possible in tag mode
+        */
+       if (stl & (FM_SPCEPDS  |        /* parity err. syn.q.*/
+                  FM_SPCEPDA0 |        /* parity err. a.q.0 */
+                  FM_SPCEPDA1)) {      /* parity err. a.q.1 */
+               SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
+       }
+       /*
+        * buffer underrun: can only occur if a tx threshold is specified
+        */
+       if (stl & (FM_STBURS  |         /* tx buffer underrun syn.q.*/
+                  FM_STBURA0 |         /* tx buffer underrun a.q.0 */
+                  FM_STBURA1)) {       /* tx buffer underrun a.q.2 */
+               SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
+       }
+
+       if ( (stu & (FM_SXMTABT |               /* transmit abort */
+                    FM_STXABRS |               /* syn. tx abort */
+                    FM_STXABRA0)) ||           /* asyn. tx abort */
+            (stl & (FM_SQLCKS |                /* lock for syn. q. */
+                    FM_SQLCKA0)) ) {           /* lock for asyn. q. */
+               formac_tx_restart(smc) ;        /* init tx */
+               restart_tx = 1 ;
+               stu = inpw(FM_A(FM_ST1U)) ;
+               stl = inpw(FM_A(FM_ST1L)) ;
+               stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
+               if (stu || stl)
+                       goto again ;
+       }
+
+       if (stu & (FM_STEFRMA0 |        /* end of asyn tx */
+                   FM_STEFRMS)) {      /* end of sync tx */
+               restart_tx = 1 ;
+       }
+
+       if (restart_tx)
+               llc_restart_tx(smc) ;
+}
+
+/*
+ * interrupt source= plc1
+ * this function is called in nwfbisr.asm
+ */
+void plc1_irq(struct s_smc *smc)
+{
+       u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
+
+       plc_irq(smc,PB,st) ;
+}
+
+/*
+ * interrupt source= plc2
+ * this function is called in nwfbisr.asm
+ */
+void plc2_irq(struct s_smc *smc)
+{
+       u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
+
+       plc_irq(smc,PA,st) ;
+}
+
+
+/*
+ * interrupt source= timer
+ */
+void timer_irq(struct s_smc *smc)
+{
+       hwt_restart(smc);
+       smc->hw.t_stop = smc->hw.t_start;
+       smt_timer_done(smc) ;
+}
+
+/*
+ * return S-port (PA or PB)
+ */
+int pcm_get_s_port(struct s_smc *smc)
+{
+       SK_UNUSED(smc) ;
+       return PS;
+}
+
+/*
+ * Station Label = "FDDI-XYZ" where
+ *
+ *     X = connector type
+ *     Y = PMD type
+ *     Z = port type
+ */
+#define STATION_LABEL_CONNECTOR_OFFSET 5
+#define STATION_LABEL_PMD_OFFSET       6
+#define STATION_LABEL_PORT_OFFSET      7
+
+void read_address(struct s_smc *smc, u_char *mac_addr)
+{
+       char ConnectorType ;
+       char PmdType ;
+       int     i ;
+
+#ifdef PCI
+       for (i = 0; i < 6; i++) {       /* read mac address from board */
+               smc->hw.fddi_phys_addr.a[i] =
+                       bitrev8(inp(ADDR(B2_MAC_0+i)));
+       }
+#endif
+
+       ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
+       PmdType = inp(ADDR(B2_PMD_TYP)) ;
+
+       smc->y[PA].pmd_type[PMD_SK_CONN] =
+       smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
+       smc->y[PA].pmd_type[PMD_SK_PMD ] =
+       smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
+
+       if (mac_addr) {
+               for (i = 0; i < 6 ;i++) {
+                       smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
+                       smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]);
+               }
+               return ;
+       }
+       smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
+
+       for (i = 0; i < 6 ;i++) {
+               smc->hw.fddi_canon_addr.a[i] =
+                       bitrev8(smc->hw.fddi_phys_addr.a[i]);
+       }
+}
+
+/*
+ * FDDI card soft reset
+ */
+void init_board(struct s_smc *smc, u_char *mac_addr)
+{
+       card_start(smc) ;
+       read_address(smc,mac_addr) ;
+
+       if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
+               smc->s.sas = SMT_SAS ;  /* Single att. station */
+       else
+               smc->s.sas = SMT_DAS ;  /* Dual att. station */
+
+       if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
+               smc->mib.fddiSMTBypassPresent = 0 ;
+               /* without opt. bypass */
+       else
+               smc->mib.fddiSMTBypassPresent = 1 ;
+               /* with opt. bypass */
+}
+
+/*
+ * insert or deinsert optical bypass (called by ECM)
+ */
+void sm_pm_bypass_req(struct s_smc *smc, int mode)
+{
+       DB_ECMN(1,"ECM : sm_pm_bypass_req(%s)\n",(mode == BP_INSERT) ?
+                                       "BP_INSERT" : "BP_DEINSERT",0) ;
+
+       if (smc->s.sas != SMT_DAS)
+               return ;
+
+#ifdef PCI
+       switch(mode) {
+       case BP_INSERT :
+               outp(ADDR(B0_DAS),DAS_BYP_INS) ;        /* insert station */
+               break ;
+       case BP_DEINSERT :
+               outp(ADDR(B0_DAS),DAS_BYP_RMV) ;        /* bypass station */
+               break ;
+       }
+#endif
+}
+
+/*
+ * check if bypass connected
+ */
+int sm_pm_bypass_present(struct s_smc *smc)
+{
+       return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
+}
+
+void plc_clear_irq(struct s_smc *smc, int p)
+{
+       SK_UNUSED(p) ;
+
+       SK_UNUSED(smc) ;
+}
+
+
+/*
+ * led_indication called by rmt_indication() and
+ * pcm_state_change()
+ *
+ * Input:
+ *     smc:    SMT context
+ *     led_event:
+ *     0       Only switch green LEDs according to their respective PCM state
+ *     LED_Y_OFF       just switch yellow LED off
+ *     LED_Y_ON        just switch yello LED on
+ */
+static void led_indication(struct s_smc *smc, int led_event)
+{
+       /* use smc->hw.mac_ring_is_up == TRUE 
+        * as indication for Ring Operational
+        */
+       u_short                 led_state ;
+       struct s_phy            *phy ;
+       struct fddi_mib_p       *mib_a ;
+       struct fddi_mib_p       *mib_b ;
+
+       phy = &smc->y[PA] ;
+       mib_a = phy->mib ;
+       phy = &smc->y[PB] ;
+       mib_b = phy->mib ;
+
+#ifdef PCI
+        led_state = 0 ;
+       
+       /* Ring up = yellow led OFF*/
+       if (led_event == LED_Y_ON) {
+               led_state |= LED_MY_ON ;
+       }
+       else if (led_event == LED_Y_OFF) {
+               led_state |= LED_MY_OFF ;
+       }
+       else {  /* PCM state changed */
+               /* Link at Port A/S = green led A ON */
+               if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {    
+                       led_state |= LED_GA_ON ;
+               }
+               else {
+                       led_state |= LED_GA_OFF ;
+               }
+               
+               /* Link at Port B = green led B ON */
+               if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
+                       led_state |= LED_GB_ON ;
+               }
+               else {
+                       led_state |= LED_GB_OFF ;
+               }
+       }
+
+        outp(ADDR(B0_LED), led_state) ;
+#endif /* PCI */
+
+}
+
+
+void pcm_state_change(struct s_smc *smc, int plc, int p_state)
+{
+       /*
+        * the current implementation of pcm_state_change() in the driver
+        * parts must be renamed to drv_pcm_state_change() which will be called
+        * now after led_indication.
+        */
+       DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
+       
+       led_indication(smc,0) ;
+}
+
+
+void rmt_indication(struct s_smc *smc, int i)
+{
+       /* Call a driver special function if defined */
+       DRV_RMT_INDICATION(smc,i) ;
+
+        led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
+}
+
+
+/*
+ * llc_recover_tx called by init_tx (fplus.c)
+ */
+void llc_recover_tx(struct s_smc *smc)
+{
+#ifdef LOAD_GEN
+       extern  int load_gen_flag ;
+
+       load_gen_flag = 0 ;
+#endif
+#ifndef        SYNC
+       smc->hw.n_a_send= 0 ;
+#else
+       SK_UNUSED(smc) ;
+#endif
+}
+
+#ifdef MULT_OEM
+static int is_equal_num(char comp1[], char comp2[], int num)
+{
+       int i ;
+
+       for (i = 0 ; i < num ; i++) {
+               if (comp1[i] != comp2[i])
+                       return 0;
+       }
+               return 1;
+}      /* is_equal_num */
+
+
+/*
+ * set the OEM ID defaults, and test the contents of the OEM data base
+ * The default OEM is the first ACTIVE entry in the OEM data base 
+ *
+ * returns:    0       success
+ *             1       error in data base
+ *             2       data base empty
+ *             3       no active entry 
+ */
+int set_oi_id_def(struct s_smc *smc)
+{
+       int sel_id ;
+       int i ;
+       int act_entries ;
+
+       i = 0 ;
+       sel_id = -1 ;
+       act_entries = FALSE ;
+       smc->hw.oem_id = 0 ;
+       smc->hw.oem_min_status = OI_STAT_ACTIVE ;
+       
+       /* check OEM data base */
+       while (oem_ids[i].oi_status) {
+               switch (oem_ids[i].oi_status) {
+               case OI_STAT_ACTIVE:
+                       act_entries = TRUE ;    /* we have active IDs */
+                       if (sel_id == -1)
+                               sel_id = i ;    /* save the first active ID */
+               case OI_STAT_VALID:
+               case OI_STAT_PRESENT:
+                       i++ ;
+                       break ;                 /* entry ok */
+               default:
+                       return 1;               /* invalid oi_status */
+               }
+       }
+
+       if (i == 0)
+               return 2;
+       if (!act_entries)
+               return 3;
+
+       /* ok, we have a valid OEM data base with an active entry */
+       smc->hw.oem_id = (struct s_oem_ids *)  &oem_ids[sel_id] ;
+       return 0;
+}
+#endif /* MULT_OEM */
+
+void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
+{
+       int i ;
+
+       for (i = 0 ; i < 6 ; i++)
+               bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]);
+}
+
+void smt_start_watchdog(struct s_smc *smc)
+{
+       SK_UNUSED(smc) ;        /* Make LINT happy. */
+
+#ifndef        DEBUG
+
+#ifdef PCI
+       if (smc->hw.wdog_used) {
+               outpw(ADDR(B2_WDOG_CRTL),TIM_START) ;   /* Start timer. */
+       }
+#endif
+
+#endif /* DEBUG */
+}
+
+static void smt_stop_watchdog(struct s_smc *smc)
+{
+       SK_UNUSED(smc) ;        /* Make LINT happy. */
+#ifndef        DEBUG
+
+#ifdef PCI
+       if (smc->hw.wdog_used) {
+               outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ;    /* Stop timer. */
+       }
+#endif
+
+#endif /* DEBUG */
+}
+
+#ifdef PCI
+
+void mac_do_pci_fix(struct s_smc *smc)
+{
+       SK_UNUSED(smc) ;
+}
+#endif /* PCI */
+
diff --git a/drivers/net/fddi/skfp/ecm.c b/drivers/net/fddi/skfp/ecm.c
new file mode 100644 (file)
index 0000000..47d922c
--- /dev/null
@@ -0,0 +1,536 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT ECM
+       Entity Coordination Management
+       Hardware independent state machine
+*/
+
+/*
+ * Hardware independent state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ *             queue_event()
+ *             smt_timer_start()
+ *             smt_timer_stop()
+ *
+ *     The following external HW dependent functions are referenced :
+ *             sm_pm_bypass_req()
+ *             sm_pm_ls_latch()
+ *             sm_pm_get_ls()
+ * 
+ *     The following HW dependent events are required :
+ *             NONE
+ *
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)ecm.c       2.7 99/08/05 (C) SK " ;
+#endif
+
+/*
+ * FSM Macros
+ */
+#define AFLAG  0x10
+#define GO_STATE(x)    (smc->mib.fddiSMTECMState = (x)|AFLAG)
+#define ACTIONS_DONE() (smc->mib.fddiSMTECMState &= ~AFLAG)
+#define ACTIONS(x)     (x|AFLAG)
+
+#define EC0_OUT                0                       /* not inserted */
+#define EC1_IN         1                       /* inserted */
+#define EC2_TRACE      2                       /* tracing */
+#define EC3_LEAVE      3                       /* leaving the ring */
+#define EC4_PATH_TEST  4                       /* performing path test */
+#define EC5_INSERT     5                       /* bypass being turned on */
+#define EC6_CHECK      6                       /* checking bypass */
+#define EC7_DEINSERT   7                       /* bypass being turnde off */
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const ecm_states[] = {
+       "EC0_OUT","EC1_IN","EC2_TRACE","EC3_LEAVE","EC4_PATH_TEST",
+       "EC5_INSERT","EC6_CHECK","EC7_DEINSERT"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const ecm_events[] = {
+       "NONE","EC_CONNECT","EC_DISCONNECT","EC_TRACE_PROP","EC_PATH_TEST",
+       "EC_TIMEOUT_TD","EC_TIMEOUT_TMAX",
+       "EC_TIMEOUT_IMAX","EC_TIMEOUT_INMAX","EC_TEST_DONE"
+} ;
+#endif
+
+/*
+ * all Globals  are defined in smc.h
+ * struct s_ecm
+ */
+
+/*
+ * function declarations
+ */
+
+static void ecm_fsm(struct s_smc *smc, int cmd);
+static void start_ecm_timer(struct s_smc *smc, u_long value, int event);
+static void stop_ecm_timer(struct s_smc *smc);
+static void prop_actions(struct s_smc *smc);
+
+/*
+       init ECM state machine
+       clear all ECM vars and flags
+*/
+void ecm_init(struct s_smc *smc)
+{
+       smc->e.path_test = PT_PASSED ;
+       smc->e.trace_prop = 0 ;
+       smc->e.sb_flag = 0 ;
+       smc->mib.fddiSMTECMState = ACTIONS(EC0_OUT) ;
+       smc->e.ecm_line_state = FALSE ;
+}
+
+/*
+       ECM state machine
+       called by dispatcher
+
+       do
+               display state change
+               process event
+       until SM is stable
+*/
+void ecm(struct s_smc *smc, int event)
+{
+       int     state ;
+
+       do {
+               DB_ECM("ECM : state %s%s",
+                       (smc->mib.fddiSMTECMState & AFLAG) ? "ACTIONS " : "",
+                       ecm_states[smc->mib.fddiSMTECMState & ~AFLAG]) ;
+               DB_ECM(" event %s\n",ecm_events[event],0) ;
+               state = smc->mib.fddiSMTECMState ;
+               ecm_fsm(smc,event) ;
+               event = 0 ;
+       } while (state != smc->mib.fddiSMTECMState) ;
+       ecm_state_change(smc,(int)smc->mib.fddiSMTECMState) ;
+}
+
+/*
+       process ECM event
+*/
+static void ecm_fsm(struct s_smc *smc, int cmd)
+{
+       int ls_a ;                      /* current line state PHY A */
+       int ls_b ;                      /* current line state PHY B */
+       int     p ;                     /* ports */
+
+
+       smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
+       if (cmd == EC_CONNECT)
+               smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
+
+       /* For AIX event notification: */
+       /* Is a disconnect  command remotely issued ? */
+       if (cmd == EC_DISCONNECT &&
+               smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
+               AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
+                       FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
+                       smt_get_error_word(smc) );
+
+       /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
+       if (cmd == EC_CONNECT) {
+               smc->e.DisconnectFlag = FALSE ;
+       }
+       else if (cmd == EC_DISCONNECT) {
+               smc->e.DisconnectFlag = TRUE ;
+       }
+       
+       switch(smc->mib.fddiSMTECMState) {
+       case ACTIONS(EC0_OUT) :
+               /*
+                * We do not perform a path test
+                */
+               smc->e.path_test = PT_PASSED ;
+               smc->e.ecm_line_state = FALSE ;
+               stop_ecm_timer(smc) ;
+               ACTIONS_DONE() ;
+               break ;
+       case EC0_OUT:
+               /*EC01*/
+               if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
+                       && smc->e.path_test==PT_PASSED) {
+                       GO_STATE(EC1_IN) ;
+                       break ;
+               }
+               /*EC05*/
+               else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
+                       smc->mib.fddiSMTBypassPresent &&
+                       (smc->s.sas == SMT_DAS)) {
+                       GO_STATE(EC5_INSERT) ;
+                       break ;
+               }
+               break;
+       case ACTIONS(EC1_IN) :
+               stop_ecm_timer(smc) ;
+               smc->e.trace_prop = 0 ;
+               sm_ma_control(smc,MA_TREQ) ;
+               for (p = 0 ; p < NUMPHYS ; p++)
+                       if (smc->mib.p[p].fddiPORTHardwarePresent)
+                               queue_event(smc,EVENT_PCMA+p,PC_START) ;
+               ACTIONS_DONE() ;
+               break ;
+       case EC1_IN:
+               /*EC12*/
+               if (cmd == EC_TRACE_PROP) {
+                       prop_actions(smc) ;
+                       GO_STATE(EC2_TRACE) ;
+                       break ;
+               }
+               /*EC13*/
+               else if (cmd == EC_DISCONNECT) {
+                       GO_STATE(EC3_LEAVE) ;
+                       break ;
+               }
+               break;
+       case ACTIONS(EC2_TRACE) :
+               start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
+                       EC_TIMEOUT_TMAX) ;
+               ACTIONS_DONE() ;
+               break ;
+       case EC2_TRACE :
+               /*EC22*/
+               if (cmd == EC_TRACE_PROP) {
+                       prop_actions(smc) ;
+                       GO_STATE(EC2_TRACE) ;
+                       break ;
+               }
+               /*EC23a*/
+               else if (cmd == EC_DISCONNECT) {
+                       smc->e.path_test = PT_EXITING ;
+                       GO_STATE(EC3_LEAVE) ;
+                       break ;
+               }
+               /*EC23b*/
+               else if (smc->e.path_test == PT_PENDING) {
+                       GO_STATE(EC3_LEAVE) ;
+                       break ;
+               }
+               /*EC23c*/
+               else if (cmd == EC_TIMEOUT_TMAX) {
+                       /* Trace_Max is expired */
+                       /* -> send AIX_EVENT */
+                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
+                               (u_long) FDDI_SMT_ERROR, (u_long)
+                               FDDI_TRACE_MAX, smt_get_error_word(smc));
+                       smc->e.path_test = PT_PENDING ;
+                       GO_STATE(EC3_LEAVE) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(EC3_LEAVE) :
+               start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
+               for (p = 0 ; p < NUMPHYS ; p++)
+                       queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
+               ACTIONS_DONE() ;
+               break ;
+       case EC3_LEAVE:
+               /*EC30*/
+               if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
+                       (smc->e.path_test != PT_PENDING)) {
+                       GO_STATE(EC0_OUT) ;
+                       break ;
+               }
+               /*EC34*/
+               else if (cmd == EC_TIMEOUT_TD &&
+                       (smc->e.path_test == PT_PENDING)) {
+                       GO_STATE(EC4_PATH_TEST) ;
+                       break ;
+               }
+               /*EC31*/
+               else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
+                       GO_STATE(EC1_IN) ;
+                       break ;
+               }
+               /*EC33*/
+               else if (cmd == EC_DISCONNECT &&
+                       smc->e.path_test == PT_PENDING) {
+                       smc->e.path_test = PT_EXITING ;
+                       /*
+                        * stay in state - state will be left via timeout
+                        */
+               }
+               /*EC37*/
+               else if (cmd == EC_TIMEOUT_TD &&
+                       smc->mib.fddiSMTBypassPresent &&
+                       smc->e.path_test != PT_PENDING) {
+                       GO_STATE(EC7_DEINSERT) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(EC4_PATH_TEST) :
+               stop_ecm_timer(smc) ;
+               smc->e.path_test = PT_TESTING ;
+               start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
+               /* now perform path test ... just a simulation */
+               ACTIONS_DONE() ;
+               break ;
+       case EC4_PATH_TEST :
+               /* path test done delay */
+               if (cmd == EC_TEST_DONE)
+                       smc->e.path_test = PT_PASSED ;
+
+               if (smc->e.path_test == PT_FAILED)
+                       RS_SET(smc,RS_PATHTEST) ;
+
+               /*EC40a*/
+               if (smc->e.path_test == PT_FAILED &&
+                       !smc->mib.fddiSMTBypassPresent) {
+                       GO_STATE(EC0_OUT) ;
+                       break ;
+               }
+               /*EC40b*/
+               else if (cmd == EC_DISCONNECT &&
+                       !smc->mib.fddiSMTBypassPresent) {
+                       GO_STATE(EC0_OUT) ;
+                       break ;
+               }
+               /*EC41*/
+               else if (smc->e.path_test == PT_PASSED) {
+                       GO_STATE(EC1_IN) ;
+                       break ;
+               }
+               /*EC47a*/
+               else if (smc->e.path_test == PT_FAILED &&
+                       smc->mib.fddiSMTBypassPresent) {
+                       GO_STATE(EC7_DEINSERT) ;
+                       break ;
+               }
+               /*EC47b*/
+               else if (cmd == EC_DISCONNECT &&
+                       smc->mib.fddiSMTBypassPresent) {
+                       GO_STATE(EC7_DEINSERT) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(EC5_INSERT) :
+               sm_pm_bypass_req(smc,BP_INSERT);
+               start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
+               ACTIONS_DONE() ;
+               break ;
+       case EC5_INSERT :
+               /*EC56*/
+               if (cmd == EC_TIMEOUT_INMAX) {
+                       GO_STATE(EC6_CHECK) ;
+                       break ;
+               }
+               /*EC57*/
+               else if (cmd == EC_DISCONNECT) {
+                       GO_STATE(EC7_DEINSERT) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(EC6_CHECK) :
+               /*
+                * in EC6_CHECK, we *POLL* the line state !
+                * check whether both bypass switches have switched.
+                */
+               start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
+               smc->e.ecm_line_state = TRUE ;  /* flag to pcm: report Q/HLS */
+               (void) sm_pm_ls_latch(smc,PA,1) ; /* enable line state latch */
+               (void) sm_pm_ls_latch(smc,PB,1) ; /* enable line state latch */
+               ACTIONS_DONE() ;
+               break ;
+       case EC6_CHECK :
+               ls_a = sm_pm_get_ls(smc,PA) ;
+               ls_b = sm_pm_get_ls(smc,PB) ;
+
+               /*EC61*/
+               if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
+                   ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
+                       smc->e.sb_flag = FALSE ;
+                       smc->e.ecm_line_state = FALSE ;
+                       GO_STATE(EC1_IN) ;
+                       break ;
+               }
+               /*EC66*/
+               else if (!smc->e.sb_flag &&
+                        (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
+                         ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
+                       smc->e.sb_flag = TRUE ;
+                       DB_ECMN(1,"ECM : EC6_CHECK - stuck bypass\n",0,0) ;
+                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                               FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
+                               smt_get_error_word(smc));
+               }
+               /*EC67*/
+               else if (cmd == EC_DISCONNECT) {
+                       smc->e.ecm_line_state = FALSE ;
+                       GO_STATE(EC7_DEINSERT) ;
+                       break ;
+               }
+               else {
+                       /*
+                        * restart poll
+                        */
+                       start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
+               }
+               break ;
+       case ACTIONS(EC7_DEINSERT) :
+               sm_pm_bypass_req(smc,BP_DEINSERT);
+               start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
+               ACTIONS_DONE() ;
+               break ;
+       case EC7_DEINSERT:
+               /*EC70*/
+               if (cmd == EC_TIMEOUT_IMAX) {
+                       GO_STATE(EC0_OUT) ;
+                       break ;
+               }
+               /*EC75*/
+               else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
+                       GO_STATE(EC5_INSERT) ;
+                       break ;
+               }
+               break;
+       default:
+               SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
+               break;
+       }
+}
+
+#ifndef        CONCENTRATOR
+/*
+ * trace propagation actions for SAS & DAS
+ */
+static void prop_actions(struct s_smc *smc)
+{
+       int     port_in = 0 ;
+       int     port_out = 0 ;
+
+       RS_SET(smc,RS_EVENT) ;
+       switch (smc->s.sas) {
+       case SMT_SAS :
+               port_in = port_out = pcm_get_s_port(smc) ;
+               break ;
+       case SMT_DAS :
+               port_in = cfm_get_mac_input(smc) ;      /* PA or PB */
+               port_out = cfm_get_mac_output(smc) ;    /* PA or PB */
+               break ;
+       case SMT_NAC :
+               SMT_PANIC(smc,SMT_E0108, SMT_E0108_MSG) ;
+               return ;
+       }
+
+       DB_ECM("ECM : prop_actions - trace_prop %d\n", smc->e.trace_prop,0) ;
+       DB_ECM("ECM : prop_actions - in %d out %d\n", port_in,port_out) ;
+
+       if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
+               /* trace initiatior */
+               DB_ECM("ECM : initiate TRACE on PHY %c\n",'A'+port_in-PA,0) ;
+               queue_event(smc,EVENT_PCM+port_in,PC_TRACE) ;
+       }
+       else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PA))) &&
+               port_out != PA) {
+               /* trace propagate upstream */
+               DB_ECM("ECM : propagate TRACE on PHY B\n",0,0) ;
+               queue_event(smc,EVENT_PCMB,PC_TRACE) ;
+       }
+       else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PB))) &&
+               port_out != PB) {
+               /* trace propagate upstream */
+               DB_ECM("ECM : propagate TRACE on PHY A\n",0,0) ;
+               queue_event(smc,EVENT_PCMA,PC_TRACE) ;
+       }
+       else {
+               /* signal trace termination */
+               DB_ECM("ECM : TRACE terminated\n",0,0) ;
+               smc->e.path_test = PT_PENDING ;
+       }
+       smc->e.trace_prop = 0 ;
+}
+#else
+/*
+ * trace propagation actions for Concentrator
+ */
+static void prop_actions(struct s_smc *smc)
+{
+       int     initiator ;
+       int     upstream ;
+       int     p ;
+
+       RS_SET(smc,RS_EVENT) ;
+       while (smc->e.trace_prop) {
+               DB_ECM("ECM : prop_actions - trace_prop %d\n",
+                       smc->e.trace_prop,0) ;
+
+               if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
+                       initiator = ENTITY_MAC ;
+                       smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_MAC) ;
+                       DB_ECM("ECM: MAC initiates trace\n",0,0) ;
+               }
+               else {
+                       for (p = NUMPHYS-1 ; p >= 0 ; p--) {
+                               if (smc->e.trace_prop &
+                                       ENTITY_BIT(ENTITY_PHY(p)))
+                                       break ;
+                       }
+                       initiator = ENTITY_PHY(p) ;
+                       smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_PHY(p)) ;
+               }
+               upstream = cem_get_upstream(smc,initiator) ;
+
+               if (upstream == ENTITY_MAC) {
+                       /* signal trace termination */
+                       DB_ECM("ECM : TRACE terminated\n",0,0) ;
+                       smc->e.path_test = PT_PENDING ;
+               }
+               else {
+                       /* trace propagate upstream */
+                       DB_ECM("ECM : propagate TRACE on PHY %d\n",upstream,0) ;
+                       queue_event(smc,EVENT_PCM+upstream,PC_TRACE) ;
+               }
+       }
+}
+#endif
+
+
+/*
+ * SMT timer interface
+ *     start ECM timer
+ */
+static void start_ecm_timer(struct s_smc *smc, u_long value, int event)
+{
+       smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event));
+}
+
+/*
+ * SMT timer interface
+ *     stop ECM timer
+ */
+static void stop_ecm_timer(struct s_smc *smc)
+{
+       if (smc->e.ecm_timer.tm_active)
+               smt_timer_stop(smc,&smc->e.ecm_timer) ;
+}
diff --git a/drivers/net/fddi/skfp/ess.c b/drivers/net/fddi/skfp/ess.c
new file mode 100644 (file)
index 0000000..2fc5987
--- /dev/null
@@ -0,0 +1,720 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * *******************************************************************
+ * This SBA code implements the Synchronous Bandwidth Allocation
+ * functions described in the "FDDI Synchronous Forum Implementer's
+ * Agreement" dated December 1th, 1993.
+ * *******************************************************************
+ *
+ *     PURPOSE: The purpose of this function is to control
+ *              synchronous allocations on a single FDDI segment.
+ *              Allocations are limited to the primary FDDI ring.
+ *              The SBM provides recovery mechanisms to recover
+ *              unused bandwidth also resolves T_Neg and
+ *              reconfiguration changes. Many of the SBM state
+ *              machine inputs are sourced by the underlying
+ *              FDDI sub-system supporting the SBA application.
+ *
+ * *******************************************************************
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+
+#ifndef        SLIM_SMT
+
+#ifdef ESS
+
+#ifndef lint
+static const char ID_sccs[] = "@(#)ess.c       1.10 96/02/23 (C) SK" ;
+#define LINT_USE(x)
+#else
+#define LINT_USE(x)    (x)=(x)
+#endif
+#define MS2BCLK(x)     ((x)*12500L)
+
+/*
+       -------------------------------------------------------------
+       LOCAL VARIABLES:
+       -------------------------------------------------------------
+*/
+
+static const u_short plist_raf_alc_res[] = { SMT_P0012, SMT_P320B, SMT_P320F,
+                                       SMT_P3210, SMT_P0019, SMT_P001A,
+                                       SMT_P001D, 0 } ;
+
+static const u_short plist_raf_chg_req[] = { SMT_P320B, SMT_P320F, SMT_P3210,
+                                       SMT_P001A, 0 } ;
+
+static const struct fddi_addr smt_sba_da = {{0x80,0x01,0x43,0x00,0x80,0x0C}} ;
+static const struct fddi_addr null_addr = {{0,0,0,0,0,0}} ;
+
+/*
+       -------------------------------------------------------------
+       GLOBAL VARIABLES:
+       -------------------------------------------------------------
+*/
+
+
+/*
+       -------------------------------------------------------------
+       LOCAL FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
+                             int sba_cmd);
+static void ess_config_fifo(struct s_smc *smc);
+static void ess_send_alc_req(struct s_smc *smc);
+static void ess_send_frame(struct s_smc *smc, SMbuf *mb);
+
+/*
+       -------------------------------------------------------------
+       EXTERNAL FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+/*
+       -------------------------------------------------------------
+       PUBLIC FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+void ess_timer_poll(struct s_smc *smc);
+void ess_para_change(struct s_smc *smc);
+int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
+                         int fs);
+static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);
+
+
+/*
+ * --------------------------------------------------------------------------
+ *     End Station Support     (ESS)
+ * --------------------------------------------------------------------------
+ */
+
+/*
+ * evaluate the RAF frame
+ */
+int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
+                         int fs)
+{
+       void                    *p ;            /* universal pointer */
+       struct smt_p_0016       *cmd ;          /* para: command for the ESS */
+       SMbuf                   *db ;
+       u_long                  msg_res_type ;  /* recource type */
+       u_long                  payload, overhead ;
+       int                     local ;
+       int                     i ;
+
+       /*
+        * Message Processing Code
+        */
+        local = ((fs & L_INDICATOR) != 0) ;
+
+       /*
+        * get the resource type
+        */
+       if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
+               DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
+               return fs;
+       }
+       msg_res_type = ((struct smt_p_0015 *)p)->res_type ;
+
+       /*
+        * get the pointer to the ESS command
+        */
+       if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {
+               /*
+                * error in frame: para ESS command was not found
+                */
+                DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
+                return fs;
+       }
+
+       DB_ESSN(2,"fc %x        ft %x\n",sm->smt_class,sm->smt_type) ;
+       DB_ESSN(2,"ver %x       tran %lx\n",sm->smt_version,sm->smt_tid) ;
+       DB_ESSN(2,"stn_id %s\n",addr_to_string(&sm->smt_source),0) ;
+
+       DB_ESSN(2,"infolen %x   res %x\n",sm->smt_len, msg_res_type) ;
+       DB_ESSN(2,"sbacmd %x\n",cmd->sba_cmd,0) ;
+
+       /*
+        * evaluate the ESS command
+        */
+       switch (cmd->sba_cmd) {
+
+       /*
+        * Process an ESS Allocation Request
+        */
+       case REQUEST_ALLOCATION :
+               /*
+                * check for an RAF Request (Allocation Request)
+                */
+               if (sm->smt_type == SMT_REQUEST) {
+                       /*
+                        * process the Allocation request only if the frame is
+                        * local and no static allocation is used
+                        */
+                       if (!local || smc->mib.fddiESSPayload)
+                               return fs;
+                       
+                       p = (void *) sm_to_para(smc,sm,SMT_P0019)  ;
+                       for (i = 0; i < 5; i++) {
+                               if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
+                                       return fs;
+                               }
+                       }
+
+                       /*
+                        * Note: The Application should send a LAN_LOC_FRAME.
+                        *       The ESS do not send the Frame to the network!
+                        */
+                       smc->ess.alloc_trans_id = sm->smt_tid ;
+                       DB_ESS("ESS: save Alloc Req Trans ID %lx\n",sm->smt_tid,0);
+                       p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
+                       ((struct smt_p_320f *)p)->mib_payload =
+                               smc->mib.a[PATH0].fddiPATHSbaPayload ;
+                       p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
+                       ((struct smt_p_3210 *)p)->mib_overhead =
+                               smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+                       sm->smt_dest = smt_sba_da ;
+
+                       if (smc->ess.local_sba_active)
+                               return fs | I_INDICATOR;
+
+                       if (!(db = smt_get_mbuf(smc)))
+                               return fs;
+
+                       db->sm_len = mb->sm_len ;
+                       db->sm_off = mb->sm_off ;
+                       memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,
+                               (int)db->sm_len) ;
+                       dump_smt(smc,
+                               (struct smt_header *)(db->sm_data+db->sm_off),
+                               "RAF") ;
+                       smt_send_frame(smc,db,FC_SMT_INFO,0) ;
+                       return fs;
+               }
+
+               /*
+                * The RAF frame is an Allocation Response !
+                * check the parameters
+                */
+               if (smt_check_para(smc,sm,plist_raf_alc_res)) {
+                       DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
+                       return fs;
+               }
+
+               /*
+                * VERIFY THE FRAME IS WELL BUILT:
+                *
+                *      1. path index = primary ring only
+                *      2. resource type = sync bw only
+                *      3. trans action id = alloc_trans_id
+                *      4. reason code = success
+                *
+                * If any are violated, discard the RAF frame
+                */
+               if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
+                       != PRIMARY_RING) ||
+                       (msg_res_type != SYNC_BW) ||
+               (((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason
+                       != SMT_RDF_SUCCESS) ||
+                       (sm->smt_tid != smc->ess.alloc_trans_id)) {
+
+                       DB_ESS("ESS: Allocation Response not accepted\n",0,0) ;
+                       return fs;
+               }
+
+               /*
+                * Extract message parameters
+                */
+               p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
+                if (!p) {
+                        printk(KERN_ERR "ESS: sm_to_para failed");
+                        return fs;
+                }       
+               payload = ((struct smt_p_320f *)p)->mib_payload ;
+               p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
+                if (!p) {
+                        printk(KERN_ERR "ESS: sm_to_para failed");
+                        return fs;
+                }       
+               overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
+
+               DB_ESSN(2,"payload= %lx overhead= %lx\n",payload,overhead) ;
+
+               /*
+                * process the bandwidth allocation
+                */
+               (void)process_bw_alloc(smc,(long)payload,(long)overhead) ;
+
+               return fs;
+               /* end of Process Allocation Request */
+
+       /*
+        * Process an ESS Change Request
+        */
+       case CHANGE_ALLOCATION :
+               /*
+                * except only replies
+                */
+               if (sm->smt_type != SMT_REQUEST) {
+                       DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
+                       return fs;
+               }
+
+               /*
+                * check the para for the Change Request
+                */
+               if (smt_check_para(smc,sm,plist_raf_chg_req)) {
+                       DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
+                       return fs;
+               }
+
+               /*
+                * Verify the path index and resource
+                * type are correct. If any of
+                * these are false, don't process this
+                * change request frame.
+                */
+               if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
+                       != PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
+                       DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
+                       return fs;
+               }
+
+               /*
+                * Extract message queue parameters
+                */
+               p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
+               payload = ((struct smt_p_320f *)p)->mib_payload ;
+               p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
+               overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
+
+               DB_ESSN(2,"ESS: Change Request from %s\n",
+                       addr_to_string(&sm->smt_source),0) ;
+               DB_ESSN(2,"payload= %lx overhead= %lx\n",payload,overhead) ;
+
+               /*
+                * process the bandwidth allocation
+                */
+               if(!process_bw_alloc(smc,(long)payload,(long)overhead))
+                       return fs;
+
+               /*
+                * send an RAF Change Reply
+                */
+               ess_send_response(smc,sm,CHANGE_ALLOCATION) ;
+
+               return fs;
+               /* end of Process Change Request */
+
+       /*
+        * Process Report Response
+        */
+       case REPORT_ALLOCATION :
+               /*
+                * except only requests
+                */
+               if (sm->smt_type != SMT_REQUEST) {
+                       DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
+                       return fs;
+               }
+
+               DB_ESSN(2,"ESS: Report Request from %s\n",
+                       addr_to_string(&(sm->smt_source)),0) ;
+
+               /*
+                * verify that the resource type is sync bw only
+                */
+               if (msg_res_type != SYNC_BW) {
+                       DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
+                       return fs;
+               }
+
+               /*
+                * send an RAF Change Reply
+                */
+               ess_send_response(smc,sm,REPORT_ALLOCATION) ;
+
+               return fs;
+               /* end of Process Report Request */
+
+       default:
+               /*
+                * error in frame
+                */
+               DB_ESS("ESS: ignoring RAF with bad sba_cmd\n",0,0) ;
+               break ;
+       }
+
+       return fs;
+}
+
+/*
+ * determines the synchronous bandwidth, set the TSYNC register and the
+ * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG.
+ */
+static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)
+{
+       /*
+        * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG,
+        * if the payload is greater than zero.
+        * For the SBAPayload and the SBAOverhead we have the following
+        * unite quations
+        *                    _           _
+        *                   |       bytes |
+        *      SBAPayload = | 8000 ------ |
+        *                   |          s  |
+        *                    -           -
+        *                     _       _
+        *                    |  bytes  |
+        *      SBAOverhead = | ------  |
+        *                    |  T-NEG  |
+        *                     -       -
+        *
+        * T-NEG is described by the equation:
+        *
+        *                   (-) fddiMACT-NEG
+        *      T-NEG =     -------------------
+        *                      12500000 1/s
+        *
+        * The number of bytes we are able to send is the payload
+        * plus the overhead.
+        *
+        *                        bytes    T-NEG SBAPayload 8000 bytes/s
+        * sync_bw =  SBAOverhead ------ + -----------------------------
+        *                        T-NEG         T-NEG
+        *
+        *
+        *                           1
+        * sync_bw =  SBAOverhead + ---- (-)fddiMACT-NEG * SBAPayload
+        *                          1562
+        *
+        */
+
+       /*
+        * set the mib attributes fddiPATHSbaOverhead, fddiPATHSbaPayload
+        */
+/*     if (smt_set_obj(smc,SMT_P320F,payload,S_SET)) {
+               DB_ESS("ESS: SMT does not accept the payload value\n",0,0) ;
+               return FALSE;
+       }
+       if (smt_set_obj(smc,SMT_P3210,overhead,S_SET)) {
+               DB_ESS("ESS: SMT does not accept the overhead value\n",0,0) ;
+               return FALSE;
+       } */
+
+       /* premliminary */
+       if (payload > MAX_PAYLOAD || overhead > 5000) {
+               DB_ESS("ESS: payload / overhead not accepted\n",0,0) ;
+               return FALSE;
+       }
+
+       /*
+        * start the iterative allocation process if the payload or the overhead
+        * are smaller than the parsed values
+        */
+       if (smc->mib.fddiESSPayload &&
+               ((u_long)payload != smc->mib.fddiESSPayload ||
+               (u_long)overhead != smc->mib.fddiESSOverhead)) {
+               smc->ess.raf_act_timer_poll = TRUE ;
+               smc->ess.timer_count = 0 ;
+       }
+
+       /*
+        * evulate the Payload
+        */
+       if (payload) {
+               DB_ESSN(2,"ESS: turn SMT_ST_SYNC_SERVICE bit on\n",0,0) ;
+               smc->ess.sync_bw_available = TRUE ;
+
+               smc->ess.sync_bw = overhead -
+                       (long)smc->mib.m[MAC0].fddiMACT_Neg *
+                       payload / 1562 ;
+       }
+       else {
+               DB_ESSN(2,"ESS: turn SMT_ST_SYNC_SERVICE bit off\n",0,0) ;
+               smc->ess.sync_bw_available = FALSE ;
+               smc->ess.sync_bw = 0 ;
+               overhead = 0 ;
+       }
+
+       smc->mib.a[PATH0].fddiPATHSbaPayload = payload ;
+       smc->mib.a[PATH0].fddiPATHSbaOverhead = overhead ;
+
+
+       DB_ESSN(2,"tsync = %lx\n",smc->ess.sync_bw,0) ;
+
+       ess_config_fifo(smc) ;
+       set_formac_tsync(smc,smc->ess.sync_bw) ;
+       return TRUE;
+}
+
+static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
+                             int sba_cmd)
+{
+       struct smt_sba_chg      *chg ;
+       SMbuf                   *mb ;
+       void                    *p ;
+
+       /*
+        * get and initialize the response frame
+        */
+       if (sba_cmd == CHANGE_ALLOCATION) {
+               if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
+                               sizeof(struct smt_sba_chg))))
+                               return ;
+       }
+       else {
+               if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
+                               sizeof(struct smt_sba_rep_res))))
+                               return ;
+       }
+
+       chg = smtod(mb,struct smt_sba_chg *) ;
+       chg->smt.smt_tid = sm->smt_tid ;
+       chg->smt.smt_dest = sm->smt_source ;
+
+       /* set P15 */
+       chg->s_type.para.p_type = SMT_P0015 ;
+       chg->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
+       chg->s_type.res_type = SYNC_BW ;
+
+       /* set P16 */
+       chg->cmd.para.p_type = SMT_P0016 ;
+       chg->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
+       chg->cmd.sba_cmd = sba_cmd ;
+
+       /* set P320B */
+       chg->path.para.p_type = SMT_P320B ;
+       chg->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
+       chg->path.mib_index = SBAPATHINDEX ;
+       chg->path.path_pad = 0;
+       chg->path.path_index = PRIMARY_RING ;
+
+       /* set P320F */
+       chg->payload.para.p_type = SMT_P320F ;
+       chg->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
+       chg->payload.mib_index = SBAPATHINDEX ;
+       chg->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
+
+       /* set P3210 */
+       chg->overhead.para.p_type = SMT_P3210 ;
+       chg->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
+       chg->overhead.mib_index = SBAPATHINDEX ;
+       chg->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+
+       if (sba_cmd == CHANGE_ALLOCATION) {
+               /* set P1A */
+               chg->cat.para.p_type = SMT_P001A ;
+               chg->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
+               p = (void *) sm_to_para(smc,sm,SMT_P001A) ;
+               chg->cat.category = ((struct smt_p_001a *)p)->category ;
+       }
+       dump_smt(smc,(struct smt_header *)chg,"RAF") ;
+       ess_send_frame(smc,mb) ;
+}
+
+void ess_timer_poll(struct s_smc *smc)
+{
+       if (!smc->ess.raf_act_timer_poll)
+               return ;
+
+       DB_ESSN(2,"ESS: timer_poll\n",0,0) ;
+
+       smc->ess.timer_count++ ;
+       if (smc->ess.timer_count == 10) {
+               smc->ess.timer_count = 0 ;
+               ess_send_alc_req(smc) ;
+       }
+}
+
+static void ess_send_alc_req(struct s_smc *smc)
+{
+       struct smt_sba_alc_req *req ;
+       SMbuf   *mb ;
+
+       /*
+        * send never allocation request where the requested payload and
+        * overhead is zero or deallocate bandwidth when no bandwidth is
+        * parsed
+        */
+       if (!smc->mib.fddiESSPayload) {
+               smc->mib.fddiESSOverhead = 0 ;
+       }
+       else {
+               if (!smc->mib.fddiESSOverhead)
+                       smc->mib.fddiESSOverhead = DEFAULT_OV ;
+       }
+
+       if (smc->mib.fddiESSOverhead ==
+               smc->mib.a[PATH0].fddiPATHSbaOverhead &&
+               smc->mib.fddiESSPayload ==
+               smc->mib.a[PATH0].fddiPATHSbaPayload){
+               smc->ess.raf_act_timer_poll = FALSE ;
+               smc->ess.timer_count = 7 ;      /* next RAF alc req after 3 s */
+               return ;
+       }
+       
+       /*
+        * get and initialize the response frame
+        */
+       if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST,
+                       sizeof(struct smt_sba_alc_req))))
+                       return ;
+       req = smtod(mb,struct smt_sba_alc_req *) ;
+       req->smt.smt_tid = smc->ess.alloc_trans_id = smt_get_tid(smc) ;
+       req->smt.smt_dest = smt_sba_da ;
+
+       /* set P15 */
+       req->s_type.para.p_type = SMT_P0015 ;
+       req->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
+       req->s_type.res_type = SYNC_BW ;
+
+       /* set P16 */
+       req->cmd.para.p_type = SMT_P0016 ;
+       req->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
+       req->cmd.sba_cmd = REQUEST_ALLOCATION ;
+
+       /*
+        * set the parameter type and parameter length of all used
+        * parameters
+        */
+
+       /* set P320B */
+       req->path.para.p_type = SMT_P320B ;
+       req->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
+       req->path.mib_index = SBAPATHINDEX ;
+       req->path.path_pad = 0;
+       req->path.path_index = PRIMARY_RING ;
+
+       /* set P0017 */
+       req->pl_req.para.p_type = SMT_P0017 ;
+       req->pl_req.para.p_len = sizeof(struct smt_p_0017) - PARA_LEN ;
+       req->pl_req.sba_pl_req = smc->mib.fddiESSPayload -
+               smc->mib.a[PATH0].fddiPATHSbaPayload ;
+
+       /* set P0018 */
+       req->ov_req.para.p_type = SMT_P0018 ;
+       req->ov_req.para.p_len = sizeof(struct smt_p_0018) - PARA_LEN ;
+       req->ov_req.sba_ov_req = smc->mib.fddiESSOverhead -
+               smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+
+       /* set P320F */
+       req->payload.para.p_type = SMT_P320F ;
+       req->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
+       req->payload.mib_index = SBAPATHINDEX ;
+       req->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
+
+       /* set P3210 */
+       req->overhead.para.p_type = SMT_P3210 ;
+       req->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
+       req->overhead.mib_index = SBAPATHINDEX ;
+       req->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
+
+       /* set P19 */
+       req->a_addr.para.p_type = SMT_P0019 ;
+       req->a_addr.para.p_len = sizeof(struct smt_p_0019) - PARA_LEN ;
+       req->a_addr.sba_pad = 0;
+       req->a_addr.alloc_addr = null_addr ;
+
+       /* set P1A */
+       req->cat.para.p_type = SMT_P001A ;
+       req->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
+       req->cat.category = smc->mib.fddiESSCategory ;
+
+       /* set P1B */
+       req->tneg.para.p_type = SMT_P001B ;
+       req->tneg.para.p_len = sizeof(struct smt_p_001b) - PARA_LEN ;
+       req->tneg.max_t_neg = smc->mib.fddiESSMaxTNeg ;
+
+       /* set P1C */
+       req->segm.para.p_type = SMT_P001C ;
+       req->segm.para.p_len = sizeof(struct smt_p_001c) - PARA_LEN ;
+       req->segm.min_seg_siz = smc->mib.fddiESSMinSegmentSize ;
+
+       dump_smt(smc,(struct smt_header *)req,"RAF") ;
+       ess_send_frame(smc,mb) ;
+}
+
+static void ess_send_frame(struct s_smc *smc, SMbuf *mb)
+{
+       /*
+        * check if the frame must be send to the own ESS
+        */
+       if (smc->ess.local_sba_active) {
+               /*
+                * Send the Change Reply to the local SBA
+                */
+               DB_ESS("ESS:Send to the local SBA\n",0,0) ;
+               if (!smc->ess.sba_reply_pend)
+                       smc->ess.sba_reply_pend = mb ;
+               else {
+                       DB_ESS("Frame is lost - another frame was pending\n",0,0);
+                       smt_free_mbuf(smc,mb) ;
+               }
+       }
+       else {
+               /*
+                * Send the SBA RAF Change Reply to the network
+                */
+               DB_ESS("ESS:Send to the network\n",0,0) ;
+               smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
+       }
+}
+
+void ess_para_change(struct s_smc *smc)
+{
+       (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload,
+               (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ;
+}
+
+static void ess_config_fifo(struct s_smc *smc)
+{
+       /*
+        * if nothing to do exit 
+        */
+       if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
+               if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON &&
+                       (smc->hw.fp.fifo.fifo_config_mode&SEND_ASYNC_AS_SYNC) ==
+                       smc->mib.fddiESSSynchTxMode) {
+                       return ;
+               }
+       }
+       else {
+               if (!(smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON)) {
+                       return ;
+               }
+       }
+
+       /*
+        * split up the FIFO and reinitialize the queues
+        */
+       formac_reinit_tx(smc) ;
+}
+
+#endif /* ESS */
+
+#endif /* no SLIM_SMT */
+
diff --git a/drivers/net/fddi/skfp/fplustm.c b/drivers/net/fddi/skfp/fplustm.c
new file mode 100644 (file)
index 0000000..a20ed1a
--- /dev/null
@@ -0,0 +1,1491 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * FORMAC+ Driver for tag mode
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#include <linux/bitrev.h>
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)fplustm.c   1.32 99/02/23 (C) SK " ;
+#endif
+
+#ifndef UNUSED
+#ifdef  lint
+#define UNUSED(x)      (x) = (x)
+#else
+#define UNUSED(x)
+#endif
+#endif
+
+#define FM_ADDRX        (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
+#define MS2BCLK(x)     ((x)*12500L)
+#define US2BCLK(x)     ((x)*1250L)
+
+/*
+ * prototypes for static function
+ */
+static void build_claim_beacon(struct s_smc *smc, u_long t_request);
+static int init_mac(struct s_smc *smc, int all);
+static void rtm_init(struct s_smc *smc);
+static void smt_split_up_fifo(struct s_smc *smc);
+
+#if (!defined(NO_SMT_PANIC) || defined(DEBUG))
+static char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
+static char cam_warning [] = "E_SMT_004: CAM still busy\n";
+#endif
+
+#define        DUMMY_READ()    smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
+
+#define        CHECK_NPP() {   unsigned k = 10000 ;\
+                       while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\
+                       if (!k) { \
+                               SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \
+                       }       \
+               }
+
+#define        CHECK_CAM() {   unsigned k = 10 ;\
+                       while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\
+                       if (!k) { \
+                               SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \
+                       }       \
+               }
+
+const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+static const struct fddi_addr null_addr = {{0,0,0,0,0,0}};
+static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}};
+
+static const u_short my_said = 0xffff ;        /* short address (n.u.) */
+static const u_short my_sagp = 0xffff ;        /* short group address (n.u.) */
+
+/*
+ * define my address
+ */
+#ifdef USE_CAN_ADDR
+#define MA     smc->hw.fddi_canon_addr
+#else
+#define MA     smc->hw.fddi_home_addr
+#endif
+
+
+/*
+ * useful interrupt bits
+ */
+static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
+static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
+                       FM_STBURS | FM_STBURA0 ;
+
+       /* delete FM_SRBFL after tests */
+static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
+                       FM_SMYCLM ;
+static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
+                       FM_SERRCTR | FM_SLSTCTR |
+                       FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
+
+static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
+static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
+
+static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
+                       FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
+
+
+static u_long mac_get_tneg(struct s_smc *smc)
+{
+       u_long  tneg ;
+
+       tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
+       return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
+               0xffe00000L) ;
+}
+
+void mac_update_counter(struct s_smc *smc)
+{
+       smc->mib.m[MAC0].fddiMACFrame_Ct =
+               (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
+               + (u_short) inpw(FM_A(FM_FCNTR)) ;
+       smc->mib.m[MAC0].fddiMACLost_Ct =
+               (smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)
+               + (u_short) inpw(FM_A(FM_LCNTR)) ;
+       smc->mib.m[MAC0].fddiMACError_Ct =
+               (smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)
+               + (u_short) inpw(FM_A(FM_ECNTR)) ;
+       smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;
+#ifdef SMT_REAL_TOKEN_CT
+       /*
+        * If the token counter is emulated it is updated in smt_event.
+        */
+       TBD
+#else
+       smt_emulate_token_ct( smc, MAC0 );
+#endif
+}
+
+/*
+ * write long value into buffer memory over memory data register (MDR),
+ */
+static void write_mdr(struct s_smc *smc, u_long val)
+{
+       CHECK_NPP() ;
+       MDRW(val) ;
+}
+
+#if 0
+/*
+ * read long value from buffer memory over memory data register (MDR),
+ */
+static u_long read_mdr(struct s_smc *smc, unsigned int addr)
+{
+       long p ;
+       CHECK_NPP() ;
+       MARR(addr) ;
+       outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;
+       CHECK_NPP() ;   /* needed for PCI to prevent from timeing violations */
+/*     p = MDRR() ; */ /* bad read values if the workaround */
+                       /* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/
+                       /* is used */
+       p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
+       p += (u_long)inpw(FM_A(FM_MDRL)) ;
+       return p;
+}
+#endif
+
+/*
+ * clear buffer memory
+ */
+static void init_ram(struct s_smc *smc)
+{
+       u_short i ;
+
+       smc->hw.fp.fifo.rbc_ram_start = 0 ;
+       smc->hw.fp.fifo.rbc_ram_end =
+               smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
+       CHECK_NPP() ;
+       MARW(smc->hw.fp.fifo.rbc_ram_start) ;
+       for (i = smc->hw.fp.fifo.rbc_ram_start;
+               i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
+               write_mdr(smc,0L) ;
+       /* Erase the last byte too */
+       write_mdr(smc,0L) ;
+}
+
+/*
+ * set receive FIFO pointer
+ */
+static void set_recvptr(struct s_smc *smc)
+{
+       /*
+        * initialize the pointer for receive queue 1
+        */
+       outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* RPR1 */
+       outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ;  /* SWPR1 */
+       outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* WPR1 */
+       outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ;    /* EARV1 */
+
+       /*
+        * initialize the pointer for receive queue 2
+        */
+       if (smc->hw.fp.fifo.rx2_fifo_size) {
+               outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
+               outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
+               outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
+               outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+       }
+       else {
+               outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+               outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+               outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+               outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
+       }
+}
+
+/*
+ * set transmit FIFO pointer
+ */
+static void set_txptr(struct s_smc *smc)
+{
+       outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;      /* reset transmit queues */
+
+       /*
+        * initialize the pointer for asynchronous transmit queue
+        */
+       outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ;     /* RPXA0 */
+       outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ;    /* SWPXA0 */
+       outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ;     /* WPXA0 */
+       outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */
+
+       /*
+        * initialize the pointer for synchronous transmit queue
+        */
+       if (smc->hw.fp.fifo.tx_s_size) {
+               outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
+               outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
+               outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
+               outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
+       }
+       else {
+               outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
+               outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
+               outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
+               outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
+       }
+}
+
+/*
+ * init memory buffer management registers
+ */
+static void init_rbc(struct s_smc *smc)
+{
+       u_short rbc_ram_addr ;
+
+       /*
+        * set unused pointers or permanent pointers
+        */
+       rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
+
+       outpw(FM_A(FM_RPXA1),rbc_ram_addr) ;    /* a1-send pointer */
+       outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
+       outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
+       outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
+
+       set_recvptr(smc) ;
+       set_txptr(smc) ;
+}
+
+/*
+ * init rx pointer
+ */
+static void init_rx(struct s_smc *smc)
+{
+       struct s_smt_rx_queue   *queue ;
+
+       /*
+        * init all tx data structures for receive queue 1
+        */
+       smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
+       queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
+       queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
+
+       /*
+        * init all tx data structures for receive queue 2
+        */
+       smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
+       queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
+       queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
+}
+
+/*
+ * set the TSYNC register of the FORMAC to regulate synchronous transmission
+ */
+void set_formac_tsync(struct s_smc *smc, long sync_bw)
+{
+       outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
+}
+
+/*
+ * init all tx data structures
+ */
+static void init_tx(struct s_smc *smc)
+{
+       struct s_smt_tx_queue   *queue ;
+
+       /*
+        * init all tx data structures for the synchronous queue
+        */
+       smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
+       queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
+       queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
+
+#ifdef ESS
+       set_formac_tsync(smc,smc->ess.sync_bw) ;
+#endif
+
+       /*
+        * init all tx data structures for the asynchronous queue 0
+        */
+       smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
+       queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
+       queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
+
+
+       llc_recover_tx(smc) ;
+}
+
+static void mac_counter_init(struct s_smc *smc)
+{
+       int i ;
+       u_long *ec ;
+
+       /*
+        * clear FORMAC+ frame-, lost- and error counter
+        */
+       outpw(FM_A(FM_FCNTR),0) ;
+       outpw(FM_A(FM_LCNTR),0) ;
+       outpw(FM_A(FM_ECNTR),0) ;
+       /*
+        * clear internal error counter structure
+        */
+       ec = (u_long *)&smc->hw.fp.err_stats ;
+       for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
+               *ec++ = 0L ;
+       smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
+}
+
+/*
+ * set FORMAC address, and t_request
+ */
+static void set_formac_addr(struct s_smc *smc)
+{
+       long    t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
+
+       outpw(FM_A(FM_SAID),my_said) ;  /* set short address */
+       outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) +
+                                       smc->hw.fddi_home_addr.a[5])) ;
+       outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) +
+                                       smc->hw.fddi_home_addr.a[3])) ;
+       outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) +
+                                       smc->hw.fddi_home_addr.a[1])) ;
+
+       outpw(FM_A(FM_SAGP),my_sagp) ;  /* set short group address */
+
+       outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) +
+                                       smc->hw.fp.group_addr.a[5])) ;
+       outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) +
+                                       smc->hw.fp.group_addr.a[3])) ;
+       outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) +
+                                       smc->hw.fp.group_addr.a[1])) ;
+
+       /* set r_request regs. (MSW & LSW of TRT ) */
+       outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ;
+       outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;
+}
+
+static void set_int(char *p, int l)
+{
+       p[0] = (char)(l >> 24) ;
+       p[1] = (char)(l >> 16) ;
+       p[2] = (char)(l >> 8) ;
+       p[3] = (char)(l >> 0) ;
+}
+
+/*
+ * copy TX descriptor to buffer mem
+ * append FC field and MAC frame
+ * if more bit is set in descr
+ *     append pointer to descriptor (endless loop)
+ * else
+ *     append 'end of chain' pointer
+ */
+static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+                       unsigned off, int len)
+/* u_long td;           transmit descriptor */
+/* struct fddi_mac *mac; mac frame pointer */
+/* unsigned off;        start address within buffer memory */
+/* int len ;            length of the frame including the FC */
+{
+       int     i ;
+       __le32  *p ;
+
+       CHECK_NPP() ;
+       MARW(off) ;             /* set memory address reg for writes */
+
+       p = (__le32 *) mac ;
+       for (i = (len + 3)/4 ; i ; i--) {
+               if (i == 1) {
+                       /* last word, set the tag bit */
+                       outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
+               }
+               write_mdr(smc,le32_to_cpu(*p)) ;
+               p++ ;
+       }
+
+       outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;      /* set the tag bit */
+       write_mdr(smc,td) ;     /* write over memory data reg to buffer */
+}
+
+/*
+       BEGIN_MANUAL_ENTRY(module;tests;3)
+       How to test directed beacon frames
+       ----------------------------------------------------------------
+
+       o Insert a break point in the function build_claim_beacon()
+         before calling copy_tx_mac() for building the claim frame.
+       o Modify the RM3_DETECT case so that the RM6_DETECT state
+         will always entered from the RM3_DETECT state (function rmt_fsm(),
+         rmt.c)
+       o Compile the driver.
+       o Set the parameter TREQ in the protocol.ini or net.cfg to a
+         small value to make sure your station will win the claim
+         process.
+       o Start the driver.
+       o When you reach the break point, modify the SA and DA address
+         of the claim frame (e.g. SA = DA = 10005affffff).
+       o When you see RM3_DETECT and RM6_DETECT, observe the direct
+         beacon frames on the UPPSLANA.
+
+       END_MANUAL_ENTRY
+ */
+static void directed_beacon(struct s_smc *smc)
+{
+       SK_LOC_DECL(__le32,a[2]) ;
+
+       /*
+        * set UNA in frame
+        * enable FORMAC to send endless queue of directed beacon
+        * important: the UNA starts at byte 1 (not at byte 0)
+        */
+       * (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
+       a[1] = 0 ;
+       memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ;
+
+       CHECK_NPP() ;
+        /* set memory address reg for writes */
+       MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
+       write_mdr(smc,le32_to_cpu(a[0])) ;
+       outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;      /* set the tag bit */
+       write_mdr(smc,le32_to_cpu(a[1])) ;
+
+       outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
+}
+
+/*
+       setup claim & beacon pointer
+       NOTE :
+               special frame packets end with a pointer to their own
+               descriptor, and the MORE bit is set in the descriptor
+*/
+static void build_claim_beacon(struct s_smc *smc, u_long t_request)
+{
+       u_int   td ;
+       int     len ;
+       struct fddi_mac_sf *mac ;
+
+       /*
+        * build claim packet
+        */
+       len = 17 ;
+       td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
+       mac = &smc->hw.fp.mac_sfb ;
+       mac->mac_fc = FC_CLAIM ;
+       /* DA == SA in claim frame */
+       mac->mac_source = mac->mac_dest = MA ;
+       /* 2's complement */
+       set_int((char *)mac->mac_info,(int)t_request) ;
+
+       copy_tx_mac(smc,td,(struct fddi_mac *)mac,
+               smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
+       /* set CLAIM start pointer */
+       outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
+
+       /*
+        * build beacon packet
+        */
+       len = 17 ;
+       td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
+       mac->mac_fc = FC_BEACON ;
+       mac->mac_source = MA ;
+       mac->mac_dest = null_addr ;             /* DA == 0 in beacon frame */
+       set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;
+
+       copy_tx_mac(smc,td,(struct fddi_mac *)mac,
+               smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
+       /* set beacon start pointer */
+       outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
+
+       /*
+        * build directed beacon packet
+        * contains optional UNA
+        */
+       len = 23 ;
+       td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
+       mac->mac_fc = FC_BEACON ;
+       mac->mac_source = MA ;
+       mac->mac_dest = dbeacon_multi ;         /* multicast */
+       set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;
+       set_int((char *) mac->mac_info+4,0) ;
+       set_int((char *) mac->mac_info+8,0) ;
+
+       copy_tx_mac(smc,td,(struct fddi_mac *)mac,
+               smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
+
+       /* end of claim/beacon queue */
+       outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
+
+       outpw(FM_A(FM_WPXSF),0) ;
+       outpw(FM_A(FM_RPXSF),0) ;
+}
+
+static void formac_rcv_restart(struct s_smc *smc)
+{
+       /* enable receive function */
+       SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
+
+       outpw(FM_A(FM_CMDREG1),FM_ICLLR) ;      /* clear receive lock */
+}
+
+void formac_tx_restart(struct s_smc *smc)
+{
+       outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;      /* clear s-frame lock */
+       outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;     /* clear a-frame lock */
+}
+
+static void enable_formac(struct s_smc *smc)
+{
+       /* set formac IMSK : 0 enables irq */
+       outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u);
+       outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l);
+       outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u);
+       outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l);
+       outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u);
+       outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l);
+}
+
+#if 0  /* Removed because the driver should use the ASICs TX complete IRQ. */
+       /* The FORMACs tx complete IRQ should be used any longer */
+
+/*
+       BEGIN_MANUAL_ENTRY(if,func;others;4)
+
+       void enable_tx_irq(smc, queue)
+       struct s_smc *smc ;
+       u_short queue ;
+
+Function       DOWNCALL        (SMT, fplustm.c)
+               enable_tx_irq() enables the FORMACs transmit complete
+               interrupt of the queue.
+
+Para   queue   = QUEUE_S:      synchronous queue
+               = QUEUE_A0:     asynchronous queue
+
+Note   After any ring operational change the transmit complete
+       interrupts are disabled.
+       The operating system dependent module must enable
+       the transmit complete interrupt of a queue,
+               - when it queues the first frame,
+                 because of no transmit resources are beeing
+                 available and
+               - when it escapes from the function llc_restart_tx
+                 while some frames are still queued.
+
+       END_MANUAL_ENTRY
+ */
+void enable_tx_irq(struct s_smc *smc, u_short queue)
+/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
+{
+       u_short imask ;
+
+       imask = ~(inpw(FM_A(FM_IMSK1U))) ;
+
+       if (queue == 0) {
+               outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ;
+       }
+       if (queue == 1) {
+               outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ;
+       }
+}
+
+/*
+       BEGIN_MANUAL_ENTRY(if,func;others;4)
+
+       void disable_tx_irq(smc, queue)
+       struct s_smc *smc ;
+       u_short queue ;
+
+Function       DOWNCALL        (SMT, fplustm.c)
+               disable_tx_irq disables the FORMACs transmit complete
+               interrupt of the queue
+
+Para   queue   = QUEUE_S:      synchronous queue
+               = QUEUE_A0:     asynchronous queue
+
+Note   The operating system dependent module should disable
+       the transmit complete interrupts if it escapes from the
+       function llc_restart_tx and no frames are queued.
+
+       END_MANUAL_ENTRY
+ */
+void disable_tx_irq(struct s_smc *smc, u_short queue)
+/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
+{
+       u_short imask ;
+
+       imask = ~(inpw(FM_A(FM_IMSK1U))) ;
+
+       if (queue == 0) {
+               outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ;
+       }
+       if (queue == 1) {
+               outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ;
+       }
+}
+#endif
+
+static void disable_formac(struct s_smc *smc)
+{
+       /* clear formac IMSK : 1 disables irq */
+       outpw(FM_A(FM_IMSK1U),MW) ;
+       outpw(FM_A(FM_IMSK1L),MW) ;
+       outpw(FM_A(FM_IMSK2U),MW) ;
+       outpw(FM_A(FM_IMSK2L),MW) ;
+       outpw(FM_A(FM_IMSK3U),MW) ;
+       outpw(FM_A(FM_IMSK3L),MW) ;
+}
+
+
+static void mac_ring_up(struct s_smc *smc, int up)
+{
+       if (up) {
+               formac_rcv_restart(smc) ;       /* enable receive function */
+               smc->hw.mac_ring_is_up = TRUE ;
+               llc_restart_tx(smc) ;           /* TX queue */
+       }
+       else {
+               /* disable receive function */
+               SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
+
+               /* abort current transmit activity */
+               outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
+
+               smc->hw.mac_ring_is_up = FALSE ;
+       }
+}
+
+/*--------------------------- ISR handling ----------------------------------*/
+/*
+ * mac1_irq is in drvfbi.c
+ */
+
+/*
+ * mac2_irq:   status bits for the receive queue 1, and ring status
+ *             ring status indication bits
+ */
+void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
+{
+       u_short change_s2l ;
+       u_short change_s2u ;
+
+       /* (jd) 22-Feb-1999
+        * Restart 2_DMax Timer after end of claiming or beaconing
+        */
+       if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
+               queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
+       }
+       else if (code_s2l & (FM_STKISS)) {
+               queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
+       }
+
+       /*
+        * XOR current st bits with the last to avoid useless RMT event queuing
+        */
+       change_s2l = smc->hw.fp.s2l ^ code_s2l ;
+       change_s2u = smc->hw.fp.s2u ^ code_s2u ;
+
+       if ((change_s2l & FM_SRNGOP) ||
+               (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
+               if (code_s2l & FM_SRNGOP) {
+                       mac_ring_up(smc,1) ;
+                       queue_event(smc,EVENT_RMT,RM_RING_OP) ;
+                       smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
+               }
+               else {
+                       mac_ring_up(smc,0) ;
+                       queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
+               }
+               goto mac2_end ;
+       }
+       if (code_s2l & FM_SMISFRM) {    /* missed frame */
+               smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
+       }
+       if (code_s2u & (FM_SRCVOVR |    /* recv. FIFO overflow */
+                       FM_SRBFL)) {    /* recv. buffer full */
+               smc->hw.mac_ct.mac_r_restart_counter++ ;
+/*             formac_rcv_restart(smc) ;       */
+               smt_stat_counter(smc,1) ;
+/*             goto mac2_end ;                 */
+       }
+       if (code_s2u & FM_SOTRBEC)
+               queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
+       if (code_s2u & FM_SMYBEC)
+               queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
+       if (change_s2u & code_s2u & FM_SLOCLM) {
+               DB_RMTN(2,"RMT : lower claim received\n",0,0) ;
+       }
+       if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
+               /*
+                * This is my claim and that claim is not detected as a
+                * duplicate one.
+                */
+               queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
+       }
+       if (code_s2l & FM_SDUPCLM) {
+               /*
+                * If a duplicate claim frame (same SA but T_Bid != T_Req)
+                * this flag will be set.
+                * In the RMT state machine we need a RM_VALID_CLAIM event
+                * to do the appropriate state change.
+                * RM(34c)
+                */
+               queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
+       }
+       if (change_s2u & code_s2u & FM_SHICLM) {
+               DB_RMTN(2,"RMT : higher claim received\n",0,0) ;
+       }
+       if ( (code_s2l & FM_STRTEXP) ||
+            (code_s2l & FM_STRTEXR) )
+               queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
+       if (code_s2l & FM_SMULTDA) {
+               /*
+                * The MAC has found a 2. MAC with the same address.
+                * Signal dup_addr_test = failed to RMT state machine.
+                * RM(25)
+                */
+               smc->r.dup_addr_test = DA_FAILED ;
+               queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
+       }
+       if (code_s2u & FM_SBEC)
+               smc->hw.fp.err_stats.err_bec_stat++ ;
+       if (code_s2u & FM_SCLM)
+               smc->hw.fp.err_stats.err_clm_stat++ ;
+       if (code_s2l & FM_STVXEXP)
+               smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
+       if ((code_s2u & (FM_SBEC|FM_SCLM))) {
+               if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
+                       mac_ring_up(smc,0) ;
+                       queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
+
+                       mac_ring_up(smc,1) ;
+                       queue_event(smc,EVENT_RMT,RM_RING_OP) ;
+                       smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
+               }
+       }
+       if (code_s2l & FM_SPHINV)
+               smc->hw.fp.err_stats.err_phinv++ ;
+       if (code_s2l & FM_SSIFG)
+               smc->hw.fp.err_stats.err_sifg_det++ ;
+       if (code_s2l & FM_STKISS)
+               smc->hw.fp.err_stats.err_tkiss++ ;
+       if (code_s2l & FM_STKERR)
+               smc->hw.fp.err_stats.err_tkerr++ ;
+       if (code_s2l & FM_SFRMCTR)
+               smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
+       if (code_s2l & FM_SERRCTR)
+               smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
+       if (code_s2l & FM_SLSTCTR)
+               smc->mib.m[MAC0].fddiMACLost_Ct  += 0x10000L ;
+       if (code_s2u & FM_SERRSF) {
+               SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
+       }
+mac2_end:
+       /* notice old status */
+       smc->hw.fp.s2l = code_s2l ;
+       smc->hw.fp.s2u = code_s2u ;
+       outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
+}
+
+/*
+ * mac3_irq:   receive queue 2 bits and address detection bits
+ */
+void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
+{
+       UNUSED(code_s3l) ;
+
+       if (code_s3u & (FM_SRCVOVR2 |   /* recv. FIFO overflow */
+                       FM_SRBFL2)) {   /* recv. buffer full */
+               smc->hw.mac_ct.mac_r_restart_counter++ ;
+               smt_stat_counter(smc,1);
+       }
+
+
+       if (code_s3u & FM_SRPERRQ2) {   /* parity error receive queue 2 */
+               SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
+       }
+       if (code_s3u & FM_SRPERRQ1) {   /* parity error receive queue 2 */
+               SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
+       }
+}
+
+
+/*
+ * take formac offline
+ */
+static void formac_offline(struct s_smc *smc)
+{
+       outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
+
+       /* disable receive function */
+       SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
+
+       /* FORMAC+ 'Initialize Mode' */
+       SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
+
+       disable_formac(smc) ;
+       smc->hw.mac_ring_is_up = FALSE ;
+       smc->hw.hw_state = STOPPED ;
+}
+
+/*
+ * bring formac online
+ */
+static void formac_online(struct s_smc *smc)
+{
+       enable_formac(smc) ;
+       SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
+               smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
+}
+
+/*
+ * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
+ */
+int init_fplus(struct s_smc *smc)
+{
+       smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
+       smc->hw.fp.rx_mode = FM_MDAMA ;
+       smc->hw.fp.group_addr = fddi_broadcast ;
+       smc->hw.fp.func_addr = 0 ;
+       smc->hw.fp.frselreg_init = 0 ;
+
+       init_driver_fplus(smc) ;
+       if (smc->s.sas == SMT_DAS)
+               smc->hw.fp.mdr3init |= FM_MENDAS ;
+
+       smc->hw.mac_ct.mac_nobuf_counter = 0 ;
+       smc->hw.mac_ct.mac_r_restart_counter = 0 ;
+
+       smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
+       smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
+       smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
+       smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
+       smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
+       smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
+
+       smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
+       smc->hw.mac_ring_is_up = 0 ;
+
+       mac_counter_init(smc) ;
+
+       /* convert BCKL units to symbol time */
+       smc->hw.mac_pa.t_neg = (u_long)0 ;
+       smc->hw.mac_pa.t_pri = (u_long)0 ;
+
+       /* make sure all PCI settings are correct */
+       mac_do_pci_fix(smc) ;
+
+       return init_mac(smc, 1);
+       /* enable_formac(smc) ; */
+}
+
+static int init_mac(struct s_smc *smc, int all)
+{
+       u_short t_max,x ;
+       u_long  time=0 ;
+
+       /*
+        * clear memory
+        */
+       outpw(FM_A(FM_MDREG1),FM_MINIT) ;       /* FORMAC+ init mode */
+       set_formac_addr(smc) ;
+       outpw(FM_A(FM_MDREG1),FM_MMEMACT) ;     /* FORMAC+ memory activ mode */
+       /* Note: Mode register 2 is set here, incase parity is enabled. */
+       outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
+
+       if (all) {
+               init_ram(smc) ;
+       }
+       else {
+               /*
+                * reset the HPI, the Master and the BMUs
+                */
+               outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
+               time = hwt_quick_read(smc) ;
+       }
+
+       /*
+        * set all pointers, frames etc
+        */
+       smt_split_up_fifo(smc) ;
+
+       init_tx(smc) ;
+       init_rx(smc) ;
+       init_rbc(smc) ;
+
+       build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
+
+       /* set RX threshold */
+       /* see Errata #SN2 Phantom receive overflow */
+       outpw(FM_A(FM_FRMTHR),14<<12) ;         /* switch on */
+
+       /* set formac work mode */
+       outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
+       outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
+       outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
+       outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
+
+       /* set timer */
+       /*
+        * errata #22 fplus:
+        * T_MAX must not be FFFE
+        * or one of FFDF, FFB8, FF91 (-0x27 etc..)
+        */
+       t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
+       x = t_max/0x27 ;
+       x *= 0x27 ;
+       if ((t_max == 0xfffe) || (t_max - x == 0x16))
+               t_max-- ;
+       outpw(FM_A(FM_TMAX),(u_short)t_max) ;
+
+       /* BugFix for report #10204 */
+       if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
+               outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
+       } else {
+               outpw(FM_A(FM_TVX),
+                       (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
+       }
+
+       outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;      /* clear s-frame lock */
+       outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;     /* clear a-frame lock */
+       outpw(FM_A(FM_CMDREG1),FM_ICLLR);       /* clear receive lock */
+
+       /* Auto unlock receice threshold for receive queue 1 and 2 */
+       outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
+
+       rtm_init(smc) ;                         /* RT-Monitor */
+
+       if (!all) {
+               /*
+                * after 10ms, reset the BMUs and repair the rings
+                */
+               hwt_wait_time(smc,time,MS2BCLK(10)) ;
+               outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
+               outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
+               outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
+               outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
+               outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
+               outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
+               outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
+               if (!smc->hw.hw_is_64bit) {
+                       outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
+                       outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
+                       outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
+               }
+               smc->hw.hw_state = STOPPED ;
+               mac_drv_repair_descr(smc) ;
+       }
+       smc->hw.hw_state = STARTED ;
+
+       return 0;
+}
+
+
+/*
+ * called by CFM
+ */
+void config_mux(struct s_smc *smc, int mux)
+{
+       plc_config_mux(smc,mux) ;
+
+       SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
+}
+
+/*
+ * called by RMT
+ * enable CLAIM/BEACON interrupts
+ * (only called if these events are of interest, e.g. in DETECT state
+ * the interrupt must not be permanently enabled
+ * RMT calls this function periodically (timer driven polling)
+ */
+void sm_mac_check_beacon_claim(struct s_smc *smc)
+{
+       /* set formac IMSK : 0 enables irq */
+       outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
+       /* the driver must receive the directed beacons */
+       formac_rcv_restart(smc) ;
+       process_receive(smc) ;
+}
+
+/*-------------------------- interface functions ----------------------------*/
+/*
+ * control MAC layer   (called by RMT)
+ */
+void sm_ma_control(struct s_smc *smc, int mode)
+{
+       switch(mode) {
+       case MA_OFFLINE :
+               /* Add to make the MAC offline in RM0_ISOLATED state */
+               formac_offline(smc) ;
+               break ;
+       case MA_RESET :
+               (void)init_mac(smc,0) ;
+               break ;
+       case MA_BEACON :
+               formac_online(smc) ;
+               break ;
+       case MA_DIRECTED :
+               directed_beacon(smc) ;
+               break ;
+       case MA_TREQ :
+               /*
+                * no actions necessary, TREQ is already set
+                */
+               break ;
+       }
+}
+
+int sm_mac_get_tx_state(struct s_smc *smc)
+{
+       return (inpw(FM_A(FM_STMCHN))>>4) & 7;
+}
+
+/*
+ * multicast functions
+ */
+
+static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
+                                      struct fddi_addr *user,
+                                      struct fddi_addr *own,
+                                      int del, int can)
+{
+       struct s_fpmc   *tb ;
+       struct s_fpmc   *slot ;
+       u_char  *p ;
+       int i ;
+
+       /*
+        * set own = can(user)
+        */
+       *own = *user ;
+       if (can) {
+               p = own->a ;
+               for (i = 0 ; i < 6 ; i++, p++)
+                       *p = bitrev8(*p);
+       }
+       slot = NULL;
+       for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
+               if (!tb->n) {           /* not used */
+                       if (!del && !slot)      /* if !del save first free */
+                               slot = tb ;
+                       continue ;
+               }
+               if (memcmp((char *)&tb->a,(char *)own,6))
+                       continue ;
+               return tb;
+       }
+       return slot;                    /* return first free or NULL */
+}
+
+/*
+       BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+       void mac_clear_multicast(smc)
+       struct s_smc *smc ;
+
+Function       DOWNCALL        (SMT, fplustm.c)
+               Clear all multicast entries
+
+       END_MANUAL_ENTRY()
+ */
+void mac_clear_multicast(struct s_smc *smc)
+{
+       struct s_fpmc   *tb ;
+       int i ;
+
+       smc->hw.fp.os_slots_used = 0 ;  /* note the SMT addresses */
+                                       /* will not be deleted */
+       for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
+               if (!tb->perm) {
+                       tb->n = 0 ;
+               }
+       }
+}
+
+/*
+       BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+       int mac_add_multicast(smc,addr,can)
+       struct s_smc *smc ;
+       struct fddi_addr *addr ;
+       int can ;
+
+Function       DOWNCALL        (SMC, fplustm.c)
+               Add an entry to the multicast table
+
+Para   addr    pointer to a multicast address
+       can     = 0:    the multicast address has the physical format
+               = 1:    the multicast address has the canonical format
+               | 0x80  permanent
+
+Returns        0: success
+       1: address table full
+
+Note   After a 'driver reset' or a 'station set address' all
+       entries of the multicast table are cleared.
+       In this case the driver has to fill the multicast table again.
+       After the operating system dependent module filled
+       the multicast table it must call mac_update_multicast
+       to activate the new multicast addresses!
+
+       END_MANUAL_ENTRY()
+ */
+int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
+{
+       SK_LOC_DECL(struct fddi_addr,own) ;
+       struct s_fpmc   *tb ;
+
+       /*
+        * check if there are free table entries
+        */
+       if (can & 0x80) {
+               if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
+                       return 1;
+               }
+       }
+       else {
+               if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
+                       return 1;
+               }
+       }
+
+       /*
+        * find empty slot
+        */
+       if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
+               return 1;
+       tb->n++ ;
+       tb->a = own ;
+       tb->perm = (can & 0x80) ? 1 : 0 ;
+
+       if (can & 0x80)
+               smc->hw.fp.smt_slots_used++ ;
+       else
+               smc->hw.fp.os_slots_used++ ;
+
+       return 0;
+}
+
+/*
+ * mode
+ */
+
+#define RX_MODE_PROM           0x1
+#define RX_MODE_ALL_MULTI      0x2
+
+/*
+       BEGIN_MANUAL_ENTRY(if,func;others;2)
+
+       void mac_update_multicast(smc)
+       struct s_smc *smc ;
+
+Function       DOWNCALL        (SMT, fplustm.c)
+               Update FORMAC multicast registers
+
+       END_MANUAL_ENTRY()
+ */
+void mac_update_multicast(struct s_smc *smc)
+{
+       struct s_fpmc   *tb ;
+       u_char  *fu ;
+       int     i ;
+
+       /*
+        * invalidate the CAM
+        */
+       outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
+
+       /*
+        * set the functional address
+        */
+       if (smc->hw.fp.func_addr) {
+               fu = (u_char *) &smc->hw.fp.func_addr ;
+               outpw(FM_A(FM_AFMASK2),0xffff) ;
+               outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
+               outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
+               outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
+               outpw(FM_A(FM_AFCOMP2), 0xc000) ;
+               outpw(FM_A(FM_AFCOMP1), 0x0000) ;
+               outpw(FM_A(FM_AFCOMP0), 0x0000) ;
+               outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
+       }
+
+       /*
+        * set the mask and the personality register(s)
+        */
+       outpw(FM_A(FM_AFMASK0),0xffff) ;
+       outpw(FM_A(FM_AFMASK1),0xffff) ;
+       outpw(FM_A(FM_AFMASK2),0xffff) ;
+       outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
+
+       for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
+               if (tb->n) {
+                       CHECK_CAM() ;
+
+                       /*
+                        * write the multicast address into the CAM
+                        */
+                       outpw(FM_A(FM_AFCOMP2),
+                               (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
+                       outpw(FM_A(FM_AFCOMP1),
+                               (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
+                       outpw(FM_A(FM_AFCOMP0),
+                               (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
+                       outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
+               }
+       }
+}
+
+/*
+       BEGIN_MANUAL_ENTRY(if,func;others;3)
+
+       void mac_set_rx_mode(smc,mode)
+       struct s_smc *smc ;
+       int mode ;
+
+Function       DOWNCALL/INTERN (SMT, fplustm.c)
+               This function enables / disables the selected receive.
+               Don't call this function if the hardware module is
+               used -- use mac_drv_rx_mode() instead of.
+
+Para   mode =  1       RX_ENABLE_ALLMULTI      enable all multicasts
+               2       RX_DISABLE_ALLMULTI     disable "enable all multicasts"
+               3       RX_ENABLE_PROMISC       enable promiscuous
+               4       RX_DISABLE_PROMISC      disable promiscuous
+               5       RX_ENABLE_NSA           enable reception of NSA frames
+               6       RX_DISABLE_NSA          disable reception of NSA frames
+
+Note   The selected receive modes will be lost after 'driver reset'
+       or 'set station address'
+
+       END_MANUAL_ENTRY
+ */
+void mac_set_rx_mode(struct s_smc *smc, int mode)
+{
+       switch (mode) {
+       case RX_ENABLE_ALLMULTI :
+               smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
+               break ;
+       case RX_DISABLE_ALLMULTI :
+               smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
+               break ;
+       case RX_ENABLE_PROMISC :
+               smc->hw.fp.rx_prom |= RX_MODE_PROM ;
+               break ;
+       case RX_DISABLE_PROMISC :
+               smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
+               break ;
+       case RX_ENABLE_NSA :
+               smc->hw.fp.nsa_mode = FM_MDAMA ;
+               smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
+                       smc->hw.fp.nsa_mode ;
+               break ;
+       case RX_DISABLE_NSA :
+               smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
+               smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
+                       smc->hw.fp.nsa_mode ;
+               break ;
+       }
+       if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
+               smc->hw.fp.rx_mode = FM_MLIMPROM ;
+       }
+       else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
+               smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
+       }
+       else
+               smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
+       SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
+       mac_update_multicast(smc) ;
+}
+
+/*
+       BEGIN_MANUAL_ENTRY(module;tests;3)
+       How to test the Restricted Token Monitor
+       ----------------------------------------------------------------
+
+       o Insert a break point in the function rtm_irq()
+       o Remove all stations with a restricted token monitor from the
+         network.
+       o Connect a UPPS ISA or EISA station to the network.
+       o Give the FORMAC of UPPS station the command to send
+         restricted tokens until the ring becomes instable.
+       o Now connect your test test client.
+       o The restricted token monitor should detect the restricted token,
+         and your break point will be reached.
+       o You can ovserve how the station will clean the ring.
+
+       END_MANUAL_ENTRY
+ */
+void rtm_irq(struct s_smc *smc)
+{
+       outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ;           /* clear IRQ */
+       if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
+               outpw(FM_A(FM_CMDREG1),FM_ICL) ;        /* force claim */
+               DB_RMT("RMT: fddiPATHT_Rmode expired\n",0,0) ;
+               AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
+                               (u_long) FDDI_SMT_EVENT,
+                               (u_long) FDDI_RTT, smt_get_event_word(smc));
+       }
+       outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable RTM monitoring */
+}
+
+static void rtm_init(struct s_smc *smc)
+{
+       outpd(ADDR(B2_RTM_INI),0) ;             /* timer = 0 */
+       outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable IRQ */
+}
+
+void rtm_set_timer(struct s_smc *smc)
+{
+       /*
+        * MIB timer and hardware timer have the same resolution of 80nS
+        */
+       DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns\n",
+               (int) smc->mib.a[PATH0].fddiPATHT_Rmode,0) ;
+       outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
+}
+
+static void smt_split_up_fifo(struct s_smc *smc)
+{
+
+/*
+       BEGIN_MANUAL_ENTRY(module;mem;1)
+       -------------------------------------------------------------
+       RECEIVE BUFFER MEMORY DIVERSION
+       -------------------------------------------------------------
+
+       R1_RxD == SMT_R1_RXD_COUNT
+       R2_RxD == SMT_R2_RXD_COUNT
+
+       SMT_R1_RXD_COUNT must be unequal zero
+
+                  | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
+                  |   x      0    |  x     1-3   |   x     < 3
+       ----------------------------------------------------------------------
+                  |   63,75 kB    |    54,75     |     R1_RxD
+       rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
+                  |               |              | R1_RxD+R2_RxD
+       ----------------------------------------------------------------------
+                  |               |    9 kB      |     R2_RxD
+       rx queue 2 |    0 kB       | RX_SMALL_FIFO| ------------- * 63,75 kB
+                  |  (not used)   |              | R1_RxD+R2_RxD
+
+       END_MANUAL_ENTRY
+*/
+
+       if (SMT_R1_RXD_COUNT == 0) {
+               SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
+       }
+
+       switch(SMT_R2_RXD_COUNT) {
+       case 0:
+               smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
+               smc->hw.fp.fifo.rx2_fifo_size = 0 ;
+               break ;
+       case 1:
+       case 2:
+       case 3:
+               smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
+               smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
+               break ;
+       default:        /* this is not the real defaule */
+               smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
+               SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
+               smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
+               SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
+               break ;
+       }
+
+/*
+       BEGIN_MANUAL_ENTRY(module;mem;1)
+       -------------------------------------------------------------
+       TRANSMIT BUFFER MEMORY DIVERSION
+       -------------------------------------------------------------
+
+
+                | no sync bw   | sync bw available and | sync bw available and
+                | available    | SynchTxMode = SPLIT   | SynchTxMode = ALL
+       -----------------------------------------------------------------------
+       sync tx  |     0 kB     |       32 kB           |       55 kB
+       queue    |              |   TX_MEDIUM_FIFO      |   TX_LARGE_FIFO
+       -----------------------------------------------------------------------
+       async tx |    64 kB     |       32 kB           |        9 k
+       queue    | TX_FIFO_SPACE|   TX_MEDIUM_FIFO      |   TX_SMALL_FIFO
+
+       END_MANUAL_ENTRY
+*/
+
+       /*
+        * set the tx mode bits
+        */
+       if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
+#ifdef ESS
+               smc->hw.fp.fifo.fifo_config_mode |=
+                       smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
+#endif
+       }
+       else {
+               smc->hw.fp.fifo.fifo_config_mode &=
+                       ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
+       }
+
+       /*
+        * split up the FIFO
+        */
+       if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
+               if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
+                       smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
+                       smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
+               }
+               else {
+                       smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
+                       smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
+               }
+       }
+       else {
+                       smc->hw.fp.fifo.tx_s_size = 0 ;
+                       smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
+       }
+
+       smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
+               RX_FIFO_OFF ;
+       smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
+               smc->hw.fp.fifo.rx1_fifo_size ;
+       smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
+               smc->hw.fp.fifo.tx_s_size ;
+       smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
+               smc->hw.fp.fifo.tx_a0_size ;
+
+       DB_SMT("FIFO split: mode = %x\n",smc->hw.fp.fifo.fifo_config_mode,0) ;
+       DB_SMT("rbc_ram_start = %x       rbc_ram_end =  %x\n",
+               smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end) ;
+       DB_SMT("rx1_fifo_start = %x      tx_s_start =   %x\n",
+               smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start) ;
+       DB_SMT("tx_a0_start =   %x       rx2_fifo_start =       %x\n",
+               smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ;
+}
+
+void formac_reinit_tx(struct s_smc *smc)
+{
+       /*
+        * Split up the FIFO and reinitialize the MAC if synchronous
+        * bandwidth becomes available but no synchronous queue is
+        * configured.
+        */
+       if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
+               (void)init_mac(smc,0) ;
+       }
+}
+
diff --git a/drivers/net/fddi/skfp/h/cmtdef.h b/drivers/net/fddi/skfp/h/cmtdef.h
new file mode 100644 (file)
index 0000000..f5bc90f
--- /dev/null
@@ -0,0 +1,756 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _CMTDEF_
+#define _CMTDEF_
+
+/* **************************************************************** */
+
+/*
+ * implementation specific constants
+ * MODIIFY THE FOLLOWING THREE DEFINES
+ */
+#define AMDPLC                 /* if Amd PLC chip used */
+#ifdef CONC
+#define NUMPHYS                12      /* 2 for SAS or DAS, more for Concentrator */
+#else
+#ifdef CONC_II
+#define NUMPHYS                24      /* 2 for SAS or DAS, more for Concentrator */
+#else
+#define NUMPHYS                2       /* 2 for SAS or DAS, more for Concentrator */
+#endif
+#endif
+#define NUMMACS                1       /* only 1 supported at the moment */
+#define NUMPATHS       2       /* primary and secondary path supported */
+
+/*
+ * DO NOT MODIFY BEYOND THIS POINT
+ */
+
+/* **************************************************************** */
+
+#if    NUMPHYS > 2
+#define CONCENTRATOR
+#endif
+
+/*
+ * Definitions for comfortable LINT usage
+ */
+#ifdef lint
+#define LINT_USE(x)    (x)=(x)
+#else
+#define LINT_USE(x)
+#endif
+
+#ifdef DEBUG
+#define        DB_PR(flag,a,b,c)       { if (flag) printf(a,b,c) ; }
+#else
+#define        DB_PR(flag,a,b,c)
+#endif
+
+#ifdef DEBUG_BRD
+#define DB_ECM(a,b,c)          DB_PR((smc->debug.d_smt&1),a,b,c)
+#define DB_ECMN(n,a,b,c)       DB_PR((smc->debug.d_ecm >=(n)),a,b,c)
+#define DB_RMT(a,b,c)          DB_PR((smc->debug.d_smt&2),a,b,c)
+#define DB_RMTN(n,a,b,c)       DB_PR((smc->debug.d_rmt >=(n)),a,b,c)
+#define DB_CFM(a,b,c)          DB_PR((smc->debug.d_smt&4),a,b,c)
+#define DB_CFMN(n,a,b,c)       DB_PR((smc->debug.d_cfm >=(n)),a,b,c)
+#define DB_PCM(a,b,c)          DB_PR((smc->debug.d_smt&8),a,b,c)
+#define DB_PCMN(n,a,b,c)       DB_PR((smc->debug.d_pcm >=(n)),a,b,c)
+#define DB_SMT(a,b,c)          DB_PR((smc->debug.d_smtf),a,b,c)
+#define DB_SMTN(n,a,b,c)       DB_PR((smc->debug.d_smtf >=(n)),a,b,c)
+#define DB_SBA(a,b,c)          DB_PR((smc->debug.d_sba),a,b,c)
+#define DB_SBAN(n,a,b,c)       DB_PR((smc->debug.d_sba >=(n)),a,b,c)
+#define DB_ESS(a,b,c)          DB_PR((smc->debug.d_ess),a,b,c)
+#define DB_ESSN(n,a,b,c)       DB_PR((smc->debug.d_ess >=(n)),a,b,c)
+#else
+#define DB_ECM(a,b,c)          DB_PR((debug.d_smt&1),a,b,c)
+#define DB_ECMN(n,a,b,c)       DB_PR((debug.d_ecm >=(n)),a,b,c)
+#define DB_RMT(a,b,c)          DB_PR((debug.d_smt&2),a,b,c)
+#define DB_RMTN(n,a,b,c)       DB_PR((debug.d_rmt >=(n)),a,b,c)
+#define DB_CFM(a,b,c)          DB_PR((debug.d_smt&4),a,b,c)
+#define DB_CFMN(n,a,b,c)       DB_PR((debug.d_cfm >=(n)),a,b,c)
+#define DB_PCM(a,b,c)          DB_PR((debug.d_smt&8),a,b,c)
+#define DB_PCMN(n,a,b,c)       DB_PR((debug.d_pcm >=(n)),a,b,c)
+#define DB_SMT(a,b,c)          DB_PR((debug.d_smtf),a,b,c)
+#define DB_SMTN(n,a,b,c)       DB_PR((debug.d_smtf >=(n)),a,b,c)
+#define DB_SBA(a,b,c)          DB_PR((debug.d_sba),a,b,c)
+#define DB_SBAN(n,a,b,c)       DB_PR((debug.d_sba >=(n)),a,b,c)
+#define DB_ESS(a,b,c)          DB_PR((debug.d_ess),a,b,c)
+#define DB_ESSN(n,a,b,c)       DB_PR((debug.d_ess >=(n)),a,b,c)
+#endif
+
+#ifndef        SS_NOT_DS
+#define        SK_LOC_DECL(type,var)   type var
+#else
+#define        SK_LOC_DECL(type,var)   static type var
+#endif
+/*
+ * PHYs and PORTS
+ * Note: Don't touch the definition of PA and PB. Those might be used
+ *     by some "for" loops.
+ */
+#define PA             0
+#define PB             1
+#if    defined(SUPERNET_3) || defined(CONC_II)
+/*
+ * The port indices have to be different,
+ * because the MAC output goes through the 2. PLC
+ * Conc II: It has to be the first port in the row.
+ */
+#define PS             0       /* Internal PLC which is the same as PA */
+#else
+#define PS             1
+#endif
+#define PM             2               /* PM .. PA+NUM_PHYS-1 */
+
+/*
+ * PHY types - as in path descriptor 'fddiPHYType'
+ */
+#define TA                     0       /* A port */
+#define TB                     1       /* B port */
+#define TS                     2       /* S port */
+#define TM                     3       /* M port */
+#define TNONE                  4
+
+
+/*
+ * indexes in MIB
+ */
+#define INDEX_MAC      1
+#define INDEX_PATH     1
+#define INDEX_PORT     1
+
+
+/*
+ * policies
+ */
+#define POLICY_AA      (1<<0)          /* reject AA */
+#define POLICY_AB      (1<<1)          /* reject AB */
+#define POLICY_AS      (1<<2)          /* reject AS */
+#define POLICY_AM      (1<<3)          /* reject AM */
+#define POLICY_BA      (1<<4)          /* reject BA */
+#define POLICY_BB      (1<<5)          /* reject BB */
+#define POLICY_BS      (1<<6)          /* reject BS */
+#define POLICY_BM      (1<<7)          /* reject BM */
+#define POLICY_SA      (1<<8)          /* reject SA */
+#define POLICY_SB      (1<<9)          /* reject SB */
+#define POLICY_SS      (1<<10)         /* reject SS */
+#define POLICY_SM      (1<<11)         /* reject SM */
+#define POLICY_MA      (1<<12)         /* reject MA */
+#define POLICY_MB      (1<<13)         /* reject MB */
+#define POLICY_MS      (1<<14)         /* reject MS */
+#define POLICY_MM      (1<<15)         /* reject MM */
+
+/*
+ * commands
+ */
+
+/*
+ * EVENTS
+ * event classes
+ */
+#define EVENT_ECM      1               /* event class ECM */
+#define EVENT_CFM      2               /* event class CFM */
+#define EVENT_RMT      3               /* event class RMT */
+#define EVENT_SMT      4               /* event class SMT */
+#define EVENT_PCM      5               /* event class PCM */
+#define EVENT_PCMA     5               /* event class PCMA */
+#define EVENT_PCMB     6               /* event class PCMB */
+
+/* WARNING :
+ * EVENT_PCM* must be last in the above list
+ * if more than two ports are used, EVENT_PCM .. EVENT_PCMA+NUM_PHYS-1
+ * are used !
+ */
+
+#define EV_TOKEN(class,event)  (((u_long)(class)<<16L)|((u_long)(event)))
+#define EV_T_CLASS(token)      ((int)((token)>>16)&0xffff)
+#define EV_T_EVENT(token)      ((int)(token)&0xffff)
+
+/*
+ * ECM events
+ */
+#define EC_CONNECT     1               /* connect request */
+#define EC_DISCONNECT  2               /* disconnect request */
+#define EC_TRACE_PROP  3               /* trace propagation */
+#define EC_PATH_TEST   4               /* path test */
+#define EC_TIMEOUT_TD  5               /* timer TD_min */
+#define EC_TIMEOUT_TMAX        6               /* timer trace_max */
+#define EC_TIMEOUT_IMAX        7               /* timer I_max */
+#define EC_TIMEOUT_INMAX 8             /* timer IN_max */
+#define EC_TEST_DONE   9               /* path test done */
+
+/*
+ * CFM events
+ */
+#define CF_LOOP                1               /* cf_loop flag from PCM */
+#define CF_LOOP_A      1               /* cf_loop flag from PCM */
+#define CF_LOOP_B      2               /* cf_loop flag from PCM */
+#define CF_JOIN                3               /* cf_join flag from PCM */
+#define CF_JOIN_A      3               /* cf_join flag from PCM */
+#define CF_JOIN_B      4               /* cf_join flag from PCM */
+
+/*
+ * PCM events
+ */
+#define PC_START               1
+#define PC_STOP                        2
+#define PC_LOOP                        3
+#define PC_JOIN                        4
+#define PC_SIGNAL              5
+#define PC_REJECT              6
+#define PC_MAINT               7
+#define PC_TRACE               8
+#define PC_PDR                 9
+#define PC_ENABLE              10
+#define PC_DISABLE             11
+
+/*
+ * must be ordered as in LineStateType
+ */
+#define PC_QLS                 12
+#define PC_ILS                 13
+#define PC_MLS                 14
+#define PC_HLS                 15
+#define PC_LS_PDR              16
+#define PC_LS_NONE             17
+#define LS2MIB(x)      ((x)-PC_QLS)
+#define MIB2LS(x)      ((x)+PC_QLS)
+
+#define PC_TIMEOUT_TB_MAX      18      /* timer TB_max */
+#define PC_TIMEOUT_TB_MIN      19      /* timer TB_min */
+#define PC_TIMEOUT_C_MIN       20      /* timer C_Min */
+#define PC_TIMEOUT_T_OUT       21      /* timer T_Out */
+#define PC_TIMEOUT_TL_MIN      22      /* timer TL_Min */
+#define PC_TIMEOUT_T_NEXT      23      /* timer t_next[] */
+#define PC_TIMEOUT_LCT         24
+#define PC_NSE                 25      /* NOISE hardware timer */
+#define PC_LEM                 26      /* LEM done */
+
+/*
+ * RMT events                            meaning               from
+ */
+#define RM_RING_OP     1               /* ring operational     MAC     */
+#define RM_RING_NON_OP 2               /* ring not operational MAC     */
+#define RM_MY_BEACON   3               /* recvd my beacon      MAC     */
+#define RM_OTHER_BEACON        4               /* recvd other beacon   MAC     */
+#define RM_MY_CLAIM    5               /* recvd my claim       MAC     */
+#define RM_TRT_EXP     6               /* TRT exp              MAC     */
+#define RM_VALID_CLAIM 7               /* claim from dup addr  MAC     */
+#define RM_JOIN                8               /* signal rm_join       CFM     */
+#define RM_LOOP                9               /* signal rm_loop       CFM     */
+#define RM_DUP_ADDR    10              /* dup_addr_test hange  SMT-NIF */
+#define RM_ENABLE_FLAG 11              /* enable flag */
+
+#define RM_TIMEOUT_NON_OP      12      /* timeout T_Non_OP     */
+#define RM_TIMEOUT_T_STUCK     13      /* timeout T_Stuck      */
+#define RM_TIMEOUT_ANNOUNCE    14      /* timeout T_Announce   */
+#define RM_TIMEOUT_T_DIRECT    15      /* timeout T_Direct     */
+#define RM_TIMEOUT_D_MAX       16      /* timeout D_Max        */
+#define RM_TIMEOUT_POLL                17      /* claim/beacon poller  */
+#define RM_TX_STATE_CHANGE     18      /* To restart timer for D_Max */
+
+/*
+ * SMT events
+ */
+#define SM_TIMER       1               /* timer */
+#define SM_FAST                2               /* smt_force_irq */
+
+/* PC modes */
+#define PM_NONE                0
+#define PM_PEER                1
+#define PM_TREE                2
+
+/*
+ * PCM withhold codes
+ * MIB PC-WithholdType ENUM
+ */
+#define PC_WH_NONE     0               /* ok */
+#define PC_WH_M_M      1               /* M to M */
+#define PC_WH_OTHER    2               /* other incompatible phys */
+#define PC_WH_PATH     3               /* path not available */
+/*
+ * LCT duration
+ */
+#define LC_SHORT       1               /* short LCT */
+#define LC_MEDIUM      2               /* medium LCT */
+#define LC_LONG                3               /* long LCT */
+#define LC_EXTENDED    4               /* extended LCT */
+
+/*
+ * path_test values
+ */
+#define PT_NONE                0
+#define PT_TESTING     1               /* test is running */
+#define PT_PASSED      2               /* test passed */
+#define PT_FAILED      3               /* test failed */
+#define PT_PENDING     4               /* path test follows */
+#define PT_EXITING     5               /* disconnected while in trace/leave */
+
+/*
+ * duplicate address test
+ * MIB DupAddressTest ENUM
+ */
+#define DA_NONE                0               /*              */
+#define DA_PASSED      1               /* test passed */
+#define DA_FAILED      2               /* test failed */
+
+
+/*
+ * optical bypass
+ */
+#define BP_DEINSERT    0               /* disable bypass */
+#define BP_INSERT      1               /* enable bypass */
+
+/*
+ * ODL enable/disable
+ */
+#define PM_TRANSMIT_DISABLE    0       /* disable xmit */
+#define PM_TRANSMIT_ENABLE     1       /* enable xmit */
+
+/*
+ * parameter for config_mux
+ * note : number is index in config_endec table !
+ */
+#define MUX_THRUA      0               /* through A */
+#define MUX_THRUB      1               /* through B */
+#define MUX_WRAPA      2               /* wrap A */
+#define MUX_WRAPB      3               /* wrap B */
+#define MUX_ISOLATE    4               /* isolated */
+#define MUX_WRAPS      5               /* SAS */
+
+/*
+ * MAC control
+ */
+#define MA_RESET       0
+#define MA_BEACON      1
+#define MA_CLAIM       2
+#define MA_DIRECTED    3               /* directed beacon */
+#define MA_TREQ                4               /* change T_Req */
+#define MA_OFFLINE     5               /* switch MAC to offline */
+
+
+/*
+ * trace prop
+ * bit map for trace propagation
+ */
+#define ENTITY_MAC     (NUMPHYS)
+#define ENTITY_PHY(p)  (p)
+#define ENTITY_BIT(m)  (1<<(m))
+
+/*
+ * Resource Tag Types
+ */
+#define PATH_ISO       0       /* isolated */
+#define PATH_PRIM      3       /* primary path */
+#define PATH_THRU      5       /* through path */
+
+#define RES_MAC                2       /* resource type MAC */
+#define RES_PORT       4       /* resource type PORT */
+
+
+/*
+ * CFM state
+ * oops: MUST MATCH CF-StateType in SMT7.2 !
+ */
+#define SC0_ISOLATED   0               /* isolated */
+#define SC1_WRAP_A     5               /* wrap A (not used) */
+#define SC2_WRAP_B     6               /* wrap B (not used) */
+#define SC4_THRU_A     12              /* through A */
+#define SC5_THRU_B     7               /* through B (used in SMT 6.2) */
+#define SC7_WRAP_S     8               /* SAS (not used) */
+#define SC9_C_WRAP_A   9               /* c wrap A */
+#define SC10_C_WRAP_B  10              /* c wrap B */
+#define SC11_C_WRAP_S  11              /* c wrap S */
+
+/*
+ * convert MIB time in units of 80nS to uS
+ */
+#define MIB2US(t)              ((t)/12)
+#define SEC2MIB(s)     ((s)*12500000L)
+/*
+ * SMT timer
+ */
+struct smt_timer {
+       struct smt_timer        *tm_next ;      /* linked list */
+       struct s_smc            *tm_smc ;       /* pointer to context */
+       u_long                  tm_delta ;      /* delta time */
+       u_long                  tm_token ;      /* token value */
+       u_short                 tm_active ;     /* flag : active/inactive */
+       u_short                 tm_pad ;        /* pad field */
+} ;
+
+/*
+ * communication structures
+ */
+struct mac_parameter {
+       u_long  t_neg ;         /* T_Neg parameter */
+       u_long  t_pri ;         /* T_Pri register in MAC */
+} ;
+
+/*
+ * MAC counters
+ */
+struct mac_counter {
+       u_long  mac_nobuf_counter ;     /* MAC SW counter: no buffer */
+       u_long  mac_r_restart_counter ; /* MAC SW counter: rx restarted */
+} ;
+
+/*
+ * para struct context for SMT parameters
+ */
+struct s_pcon {
+       int     pc_len ;
+       int     pc_err ;
+       int     pc_badset ;
+       void    *pc_p ;
+} ;
+
+/*
+ * link error monitor
+ */
+#define LEM_AVG        5
+struct lem_counter {
+#ifdef AM29K
+       int     lem_on  ;
+       u_long  lem_errors ;
+       u_long  lem_symbols ;
+       u_long  lem_tsymbols ;
+       int     lem_s_count ;
+       int     lem_n_s ;
+       int     lem_values ;
+       int     lem_index ;
+       int     lem_avg_ber[LEM_AVG] ;
+       int     lem_sum ;
+#else
+       u_short lem_float_ber ;         /* 10E-nn bit error rate */
+       u_long  lem_errors ;            /* accumulated error count */
+       u_short lem_on  ;
+#endif
+} ;
+
+#define NUMBITS        10
+
+#ifdef AMDPLC
+
+/*
+ * PLC state table
+ */
+struct s_plc {
+       u_short p_state ;               /* current state */
+       u_short p_bits ;                /* number of bits to send */
+       u_short p_start ;               /* first bit pos */
+       u_short p_pad ;                 /* padding for alignment */
+       u_long soft_err ;               /* error counter */
+       u_long parity_err ;             /* error counter */
+       u_long ebuf_err ;               /* error counter */
+       u_long ebuf_cont ;              /* continuous error counter */
+       u_long phyinv ;                 /* error counter */
+       u_long vsym_ctr ;               /* error counter */
+       u_long mini_ctr ;               /* error counter */
+       u_long tpc_exp ;                /* error counter */
+       u_long np_err ;                 /* error counter */
+       u_long b_pcs ;                  /* error counter */
+       u_long b_tpc ;                  /* error counter */
+       u_long b_tne ;                  /* error counter */
+       u_long b_qls ;                  /* error counter */
+       u_long b_ils ;                  /* error counter */
+       u_long b_hls ;                  /* error counter */
+} ;
+#endif
+
+#ifdef PROTOTYP_INC
+#include "fddi/driver.pro"
+#else  /* PROTOTYP_INC */
+/*
+ * function prototypes
+ */
+#include "mbuf.h"      /* Type definitions for MBUFs */
+#include "smtstate.h"  /* struct smt_state */
+
+void hwt_restart(struct s_smc *smc);   /* hwt.c */
+SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
+                      int length);     /* smt.c */
+SMbuf *smt_get_mbuf(struct s_smc *smc);        /* drvsr.c */
+void *sm_to_para(struct s_smc *smc, struct smt_header *sm,
+                int para);             /* smt.c */
+
+#ifndef SK_UNUSED
+#define SK_UNUSED(var)         (void)(var)
+#endif
+
+void queue_event(struct s_smc *smc, int class, int event);
+void ecm(struct s_smc *smc, int event);
+void ecm_init(struct s_smc *smc);
+void rmt(struct s_smc *smc, int event);
+void rmt_init(struct s_smc *smc);
+void pcm(struct s_smc *smc, const int np, int event);
+void pcm_init(struct s_smc *smc);
+void cfm(struct s_smc *smc, int event);
+void cfm_init(struct s_smc *smc);
+void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
+                    u_long token);
+void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer);
+void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
+                     int *remote, int *mac);
+void plc_config_mux(struct s_smc *smc, int mux);
+void sm_lem_evaluate(struct s_smc *smc);
+void mac_update_counter(struct s_smc *smc);
+void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off);
+void sm_ma_control(struct s_smc *smc, int mode);
+void sm_mac_check_beacon_claim(struct s_smc *smc);
+void config_mux(struct s_smc *smc, int mux);
+void smt_agent_init(struct s_smc *smc);
+void smt_timer_init(struct s_smc *smc);
+void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs);
+void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
+                 int index, int local);
+void smt_swap_para(struct smt_header *sm, int len, int direction);
+void ev_init(struct s_smc *smc);
+void hwt_init(struct s_smc *smc);
+u_long hwt_read(struct s_smc *smc);
+void hwt_stop(struct s_smc *smc);
+void hwt_start(struct s_smc *smc, u_long time);
+void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc);
+void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
+void sm_pm_bypass_req(struct s_smc *smc, int mode);
+void rmt_indication(struct s_smc *smc, int i);
+void cfm_state_change(struct s_smc *smc, int c_state);
+
+#if defined(DEBUG) || !defined(NO_SMT_PANIC)
+void smt_panic(struct s_smc *smc, char *text);
+#else
+#define        smt_panic(smc,text)
+#endif /* DEBUG || !NO_SMT_PANIC */
+
+void smt_stat_counter(struct s_smc *smc, int stat);
+void smt_timer_poll(struct s_smc *smc);
+u_long smt_get_time(void);
+u_long smt_get_tid(struct s_smc *smc);
+void smt_timer_done(struct s_smc *smc);
+void smt_fixup_mib(struct s_smc *smc);
+void smt_reset_defaults(struct s_smc *smc, int level);
+void smt_agent_task(struct s_smc *smc);
+int smt_check_para(struct s_smc *smc, struct smt_header *sm,
+                  const u_short list[]);
+void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr);
+
+#ifdef SUPERNET_3
+void drv_reset_indication(struct s_smc *smc);
+#endif /* SUPERNET_3 */
+
+void smt_start_watchdog(struct s_smc *smc);
+void smt_event(struct s_smc *smc, int event);
+void timer_event(struct s_smc *smc, u_long token);
+void ev_dispatcher(struct s_smc *smc);
+void pcm_get_state(struct s_smc *smc, struct smt_state *state);
+void ecm_state_change(struct s_smc *smc, int e_state);
+int sm_pm_bypass_present(struct s_smc *smc);
+void pcm_state_change(struct s_smc *smc, int plc, int p_state);
+void rmt_state_change(struct s_smc *smc, int r_state);
+int sm_pm_get_ls(struct s_smc *smc, int phy);
+int pcm_get_s_port(struct s_smc *smc);
+int pcm_rooted_station(struct s_smc *smc);
+int cfm_get_mac_input(struct s_smc *smc);
+int cfm_get_mac_output(struct s_smc *smc);
+int cem_build_path(struct s_smc *smc, char *to, int path_index);
+int sm_mac_get_tx_state(struct s_smc *smc);
+char *get_pcmstate(struct s_smc *smc, int np);
+int smt_action(struct s_smc *smc, int class, int code, int index);
+u_short smt_online(struct s_smc *smc, int on);
+void smt_force_irq(struct s_smc *smc);
+void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local);
+void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local);
+void smt_set_timestamp(struct s_smc *smc, u_char *p);
+void mac_set_rx_mode(struct s_smc *smc,        int mode);
+int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can);
+void mac_update_multicast(struct s_smc *smc);
+void mac_clear_multicast(struct s_smc *smc);
+void set_formac_tsync(struct s_smc *smc, long sync_bw);
+void formac_reinit_tx(struct s_smc *smc);
+void formac_tx_restart(struct s_smc *smc);
+void process_receive(struct s_smc *smc);
+void init_driver_fplus(struct s_smc *smc);
+void rtm_irq(struct s_smc *smc);
+void rtm_set_timer(struct s_smc *smc);
+void ring_status_indication(struct s_smc *smc, u_long status);
+void llc_recover_tx(struct s_smc *smc);
+void llc_restart_tx(struct s_smc *smc);
+void plc_clear_irq(struct s_smc *smc, int p);
+void plc_irq(struct s_smc *smc,        int np, unsigned int cmd);
+int smt_set_mac_opvalues(struct s_smc *smc);
+
+#ifdef TAG_MODE
+void mac_do_pci_fix(struct s_smc *smc);
+void mac_drv_clear_tx_queue(struct s_smc *smc);
+void mac_drv_repair_descr(struct s_smc *smc);
+u_long hwt_quick_read(struct s_smc *smc);
+void hwt_wait_time(struct s_smc *smc, u_long start, long duration);
+#endif
+
+#ifdef SMT_PNMI
+int pnmi_init(struct s_smc* smc);
+int pnmi_process_ndis_id(struct s_smc *smc, u_long ndis_oid, void *buf, int len,
+                        int *BytesAccessed, int *BytesNeeded, u_char action);
+#endif
+
+#ifdef SBA
+#ifndef _H2INC
+void sba();
+#endif
+void sba_raf_received_pack();
+void sba_timer_poll();
+void smt_init_sba();
+#endif
+
+#ifdef ESS
+int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
+                         int fs);
+void ess_timer_poll(struct s_smc *smc);
+void ess_para_change(struct s_smc *smc);
+#endif
+
+#ifndef        BOOT
+void smt_init_evc(struct s_smc *smc);
+void smt_srf_event(struct s_smc *smc, int code, int index, int cond);
+#else
+#define smt_init_evc(smc)
+#define smt_srf_event(smc,code,index,cond)
+#endif
+
+#ifndef SMT_REAL_TOKEN_CT
+void smt_emulate_token_ct(struct s_smc *smc, int mac_index);
+#endif
+
+#if defined(DEBUG) && !defined(BOOT)
+void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text);
+#else
+#define        dump_smt(smc,sm,text)
+#endif
+
+#ifdef DEBUG
+char* addr_to_string(struct fddi_addr *addr);
+void dump_hex(char *p, int len);
+#endif
+
+#endif /* PROTOTYP_INC */
+
+/* PNMI default defines */
+#ifndef PNMI_INIT
+#define        PNMI_INIT(smc)  /* Nothing */
+#endif
+#ifndef PNMI_GET_ID
+#define PNMI_GET_ID( smc, ndis_oid, buf, len, BytesWritten, BytesNeeded ) \
+               ( 1 ? (-1) : (-1) )
+#endif
+#ifndef PNMI_SET_ID
+#define PNMI_SET_ID( smc, ndis_oid, buf, len, BytesRead, BytesNeeded, \
+               set_type) ( 1 ? (-1) : (-1) )
+#endif
+
+/*
+ * SMT_PANIC defines
+ */
+#ifndef        SMT_PANIC
+#define        SMT_PANIC(smc,nr,msg)   smt_panic (smc, msg)
+#endif
+
+#ifndef        SMT_ERR_LOG
+#define        SMT_ERR_LOG(smc,nr,msg) SMT_PANIC (smc, nr, msg)
+#endif
+
+#ifndef        SMT_EBASE
+#define        SMT_EBASE       100
+#endif
+
+#define        SMT_E0100       SMT_EBASE + 0
+#define        SMT_E0100_MSG   "cfm FSM: invalid ce_type"
+#define        SMT_E0101       SMT_EBASE + 1
+#define        SMT_E0101_MSG   "CEM: case ???"
+#define        SMT_E0102       SMT_EBASE + 2
+#define        SMT_E0102_MSG   "CEM A: invalid state"
+#define        SMT_E0103       SMT_EBASE + 3
+#define        SMT_E0103_MSG   "CEM B: invalid state"
+#define        SMT_E0104       SMT_EBASE + 4
+#define        SMT_E0104_MSG   "CEM M: invalid state"
+#define        SMT_E0105       SMT_EBASE + 5
+#define        SMT_E0105_MSG   "CEM S: invalid state"
+#define        SMT_E0106       SMT_EBASE + 6
+#define        SMT_E0106_MSG   "CFM : invalid state"
+#define        SMT_E0107       SMT_EBASE + 7
+#define        SMT_E0107_MSG   "ECM : invalid state"
+#define        SMT_E0108       SMT_EBASE + 8
+#define        SMT_E0108_MSG   "prop_actions : NAC in DAS CFM"
+#define        SMT_E0109       SMT_EBASE + 9
+#define        SMT_E0109_MSG   "ST2U.FM_SERRSF error in special frame"
+#define        SMT_E0110       SMT_EBASE + 10
+#define        SMT_E0110_MSG   "ST2U.FM_SRFRCTOV recv. count. overflow"
+#define        SMT_E0111       SMT_EBASE + 11
+#define        SMT_E0111_MSG   "ST2U.FM_SNFSLD NP & FORMAC simult. load"
+#define        SMT_E0112       SMT_EBASE + 12
+#define        SMT_E0112_MSG   "ST2U.FM_SRCVFRM single-frame recv.-mode"
+#define        SMT_E0113       SMT_EBASE + 13
+#define        SMT_E0113_MSG   "FPLUS: Buffer Memory Error"
+#define        SMT_E0114       SMT_EBASE + 14
+#define        SMT_E0114_MSG   "ST2U.FM_SERRSF error in special frame"
+#define        SMT_E0115       SMT_EBASE + 15
+#define        SMT_E0115_MSG   "ST3L: parity error in receive queue 2"
+#define        SMT_E0116       SMT_EBASE + 16
+#define        SMT_E0116_MSG   "ST3L: parity error in receive queue 1"
+#define        SMT_E0117       SMT_EBASE + 17
+#define        SMT_E0117_MSG   "E_SMT_001: RxD count for receive queue 1 = 0"
+#define        SMT_E0118       SMT_EBASE + 18
+#define        SMT_E0118_MSG   "PCM : invalid state"
+#define        SMT_E0119       SMT_EBASE + 19
+#define        SMT_E0119_MSG   "smt_add_para"
+#define        SMT_E0120       SMT_EBASE + 20
+#define        SMT_E0120_MSG   "smt_set_para"
+#define        SMT_E0121       SMT_EBASE + 21
+#define        SMT_E0121_MSG   "invalid event in dispatcher"
+#define        SMT_E0122       SMT_EBASE + 22
+#define        SMT_E0122_MSG   "RMT : invalid state"
+#define        SMT_E0123       SMT_EBASE + 23
+#define        SMT_E0123_MSG   "SBA: state machine has invalid state"
+#define        SMT_E0124       SMT_EBASE + 24
+#define        SMT_E0124_MSG   "sba_free_session() called with NULL pointer"
+#define        SMT_E0125       SMT_EBASE + 25
+#define        SMT_E0125_MSG   "SBA : invalid session pointer"
+#define        SMT_E0126       SMT_EBASE + 26
+#define        SMT_E0126_MSG   "smt_free_mbuf() called with NULL pointer\n"
+#define        SMT_E0127       SMT_EBASE + 27
+#define        SMT_E0127_MSG   "sizeof evcs"
+#define        SMT_E0128       SMT_EBASE + 28
+#define        SMT_E0128_MSG   "evc->evc_cond_state = 0"
+#define        SMT_E0129       SMT_EBASE + 29
+#define        SMT_E0129_MSG   "evc->evc_multiple = 0"
+#define        SMT_E0130       SMT_EBASE + 30
+#define        SMT_E0130_MSG   write_mdr_warning
+#define        SMT_E0131       SMT_EBASE + 31
+#define        SMT_E0131_MSG   cam_warning
+#define SMT_E0132      SMT_EBASE + 32
+#define SMT_E0132_MSG  "ST1L.FM_SPCEPDx parity/coding error"
+#define SMT_E0133      SMT_EBASE + 33
+#define SMT_E0133_MSG  "ST1L.FM_STBURx tx buffer underrun"
+#define SMT_E0134      SMT_EBASE + 34
+#define SMT_E0134_MSG  "ST1L.FM_SPCEPDx parity error"
+#define SMT_E0135      SMT_EBASE + 35
+#define SMT_E0135_MSG  "RMT: duplicate MAC address detected. Ring left!"
+#define SMT_E0136      SMT_EBASE + 36
+#define SMT_E0136_MSG  "Elasticity Buffer hang-up"
+#define SMT_E0137      SMT_EBASE + 37
+#define SMT_E0137_MSG  "SMT: queue overrun"
+#define SMT_E0138      SMT_EBASE + 38
+#define SMT_E0138_MSG  "RMT: duplicate MAC address detected. Ring NOT left!"
+#endif /* _CMTDEF_ */
diff --git a/drivers/net/fddi/skfp/h/fddi.h b/drivers/net/fddi/skfp/h/fddi.h
new file mode 100644 (file)
index 0000000..c9a28a8
--- /dev/null
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _FDDI_
+#define _FDDI_
+
+struct fddi_addr {
+       u_char  a[6] ;
+} ;
+
+#define GROUP_ADDR     0x80            /* MSB in a[0] */
+
+struct fddi_mac {
+       struct fddi_addr        mac_dest ;
+       struct fddi_addr        mac_source ;
+       u_char                  mac_info[4478] ;
+} ;
+
+#define FDDI_MAC_SIZE  (12)
+#define FDDI_RAW_MTU   (4500-5)        /* exl. Pr,SD, ED/FS */
+#define FDDI_RAW       (4500)
+
+/*
+ * FC values
+ */
+#define FC_VOID                0x40            /* void frame */
+#define FC_TOKEN       0x80            /* token */
+#define FC_RES_TOKEN   0xc0            /* restricted token */
+#define FC_SMT_INFO    0x41            /* SMT Info frame */
+/*
+ * FC_SMT_LAN_LOC && FC_SMT_LOC are SK specific !
+ */
+#define FC_SMT_LAN_LOC 0x42            /* local SMT Info frame */
+#define FC_SMT_LOC     0x43            /* local SMT Info frame */
+#define FC_SMT_NSA     0x4f            /* SMT NSA frame */
+#define FC_MAC         0xc0            /* MAC frame */
+#define FC_BEACON      0xc2            /* MAC beacon frame */
+#define FC_CLAIM       0xc3            /* MAC claim frame */
+#define FC_SYNC_LLC    0xd0            /* sync. LLC frame */
+#define FC_ASYNC_LLC   0x50            /* async. LLC frame */
+#define FC_SYNC_BIT    0x80            /* sync. bit in FC */
+
+#define FC_LLC_PRIOR   0x07            /* priority bits */
+
+#define BEACON_INFO    0               /* beacon type */
+#define DBEACON_INFO   1               /* beacon type DIRECTED */
+
+
+/*
+ * indicator bits
+ */
+#define C_INDICATOR    (1<<0)
+#define A_INDICATOR    (1<<1)
+#define E_INDICATOR    (1<<2)
+#define I_INDICATOR    (1<<6)          /* SK specific */ 
+#define L_INDICATOR    (1<<7)          /* SK specific */
+
+#endif /* _FDDI_ */
diff --git a/drivers/net/fddi/skfp/h/fddimib.h b/drivers/net/fddi/skfp/h/fddimib.h
new file mode 100644 (file)
index 0000000..d1acdc7
--- /dev/null
@@ -0,0 +1,349 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * FDDI MIB
+ */
+
+/*
+ * typedefs
+ */
+
+typedef        u_long  Counter ;
+typedef u_char TimeStamp[8] ;
+typedef struct fddi_addr LongAddr ;
+typedef        u_long  Timer_2 ;
+typedef        u_long  Timer ;
+typedef        u_short ResId ;
+typedef u_short        SMTEnum ;
+typedef        u_char  SMTFlag ;
+
+typedef struct {
+       Counter         count ;
+       TimeStamp       timestamp ;
+} SetCountType ;
+
+/*
+ * bits for bit string "available_path"
+ */
+#define MIB_PATH_P     (1<<0)
+#define MIB_PATH_S     (1<<1)
+#define MIB_PATH_L     (1<<2)
+
+/*
+ * bits for bit string PermittedPaths & RequestedPaths (SIZE(8))
+ */
+#define MIB_P_PATH_LOCAL       (1<<0)
+#define MIB_P_PATH_SEC_ALTER   (1<<1)
+#define MIB_P_PATH_PRIM_ALTER  (1<<2)
+#define MIB_P_PATH_CON_ALTER   (1<<3)
+#define MIB_P_PATH_SEC_PREFER  (1<<4)
+#define MIB_P_PATH_PRIM_PREFER (1<<5)
+#define MIB_P_PATH_CON_PREFER  (1<<6)
+#define MIB_P_PATH_THRU                (1<<7)
+
+/*
+ * enum current path
+ */
+#define MIB_PATH_ISOLATED      0
+#define MIB_PATH_LOCAL         1
+#define MIB_PATH_SECONDARY     2
+#define MIB_PATH_PRIMARY       3
+#define MIB_PATH_CONCATENATED  4
+#define MIB_PATH_THRU          5
+
+/*
+ * enum PMDClass
+ */
+#define MIB_PMDCLASS_MULTI     0
+#define MIB_PMDCLASS_SINGLE1   1
+#define MIB_PMDCLASS_SINGLE2   2
+#define MIB_PMDCLASS_SONET     3
+#define MIB_PMDCLASS_LCF       4
+#define MIB_PMDCLASS_TP                5
+#define MIB_PMDCLASS_UNKNOWN   6
+#define MIB_PMDCLASS_UNSPEC    7
+
+/*
+ * enum SMTStationStatus
+ */
+#define MIB_SMT_STASTA_CON     0
+#define MIB_SMT_STASTA_SEPA    1
+#define MIB_SMT_STASTA_THRU    2
+
+
+struct fddi_mib {
+       /*
+        * private
+        */
+       u_char                  fddiPRPMFPasswd[8] ;
+       struct smt_sid          fddiPRPMFStation ;
+
+#ifdef ESS
+       /*
+        * private variables for static allocation of the
+        * End Station Support
+        */
+       u_long  fddiESSPayload ;        /* payload for static alloc */
+       u_long  fddiESSOverhead ;       /* frame ov for static alloc */
+       u_long  fddiESSMaxTNeg ;        /* maximum of T-NEG */
+       u_long  fddiESSMinSegmentSize ; /* min size of the sync frames */
+       u_long  fddiESSCategory ;       /* category for the Alloc req */
+       short   fddiESSSynchTxMode ;    /* send all LLC frames as sync */
+#endif /* ESS */
+#ifdef SBA
+       /*
+        * private variables for the Synchronous Bandwidth Allocator
+        */
+       char    fddiSBACommand ;        /* holds the parsed SBA cmd */
+       u_char  fddiSBAAvailable ;      /* SBA allocatable value */
+#endif /* SBA */
+
+       /*
+        * SMT standard mib
+        */
+       struct smt_sid          fddiSMTStationId ;
+       u_short                 fddiSMTOpVersionId ;
+       u_short                 fddiSMTHiVersionId ;
+       u_short                 fddiSMTLoVersionId ;
+       u_char                  fddiSMTManufacturerData[32] ;
+       u_char                  fddiSMTUserData[32] ;
+       u_short                 fddiSMTMIBVersionId ;
+
+       /*
+        * ConfigGrp
+        */
+       u_char                  fddiSMTMac_Ct ;
+       u_char                  fddiSMTNonMaster_Ct ;
+       u_char                  fddiSMTMaster_Ct ;
+       u_char                  fddiSMTAvailablePaths ;
+       u_short                 fddiSMTConfigCapabilities ;
+       u_short                 fddiSMTConfigPolicy ;
+       u_short                 fddiSMTConnectionPolicy ;
+       u_short                 fddiSMTTT_Notify ;
+       u_char                  fddiSMTStatRptPolicy ;
+       u_long                  fddiSMTTrace_MaxExpiration ;
+       u_short                 fddiSMTPORTIndexes[NUMPHYS] ;
+       u_short                 fddiSMTMACIndexes ;
+       u_char                  fddiSMTBypassPresent ;
+
+       /*
+        * StatusGrp
+        */
+       SMTEnum                 fddiSMTECMState ;
+       SMTEnum                 fddiSMTCF_State ;
+       SMTEnum                 fddiSMTStationStatus ;
+       u_char                  fddiSMTRemoteDisconnectFlag ;
+       u_char                  fddiSMTPeerWrapFlag ;
+
+       /*
+        * MIBOperationGrp
+        */
+       TimeStamp               fddiSMTTimeStamp ;
+       TimeStamp               fddiSMTTransitionTimeStamp ;
+       SetCountType            fddiSMTSetCount ;
+       struct smt_sid          fddiSMTLastSetStationId ;
+
+       struct fddi_mib_m {
+               u_short         fddiMACFrameStatusFunctions ;
+               Timer_2         fddiMACT_MaxCapabilitiy ;
+               Timer_2         fddiMACTVXCapabilitiy ;
+
+               /* ConfigGrp */
+               u_char          fddiMACMultiple_N ;     /* private */
+               u_char          fddiMACMultiple_P ;     /* private */
+               u_char          fddiMACDuplicateAddressCond ;/* private */
+               u_char          fddiMACAvailablePaths ;
+               u_short         fddiMACCurrentPath ;
+               LongAddr        fddiMACUpstreamNbr ;
+               LongAddr        fddiMACDownstreamNbr ;
+               LongAddr        fddiMACOldUpstreamNbr ;
+               LongAddr        fddiMACOldDownstreamNbr ;
+               SMTEnum         fddiMACDupAddressTest ;
+               u_short         fddiMACRequestedPaths ;
+               SMTEnum         fddiMACDownstreamPORTType ;
+               ResId           fddiMACIndex ;
+
+               /* AddressGrp */
+               LongAddr        fddiMACSMTAddress ;
+
+               /* OperationGrp */
+               Timer_2         fddiMACT_Min ;  /* private */
+               Timer_2         fddiMACT_ReqMIB ;
+               Timer_2         fddiMACT_Req ;  /* private */
+               Timer_2         fddiMACT_Neg ;
+               Timer_2         fddiMACT_MaxMIB ;
+               Timer_2         fddiMACT_Max ;  /* private */
+               Timer_2         fddiMACTvxValueMIB ;
+               Timer_2         fddiMACTvxValue ; /* private */
+               Timer_2         fddiMACT_Pri0 ;
+               Timer_2         fddiMACT_Pri1 ;
+               Timer_2         fddiMACT_Pri2 ;
+               Timer_2         fddiMACT_Pri3 ;
+               Timer_2         fddiMACT_Pri4 ;
+               Timer_2         fddiMACT_Pri5 ;
+               Timer_2         fddiMACT_Pri6 ;
+
+               /* CountersGrp */
+               Counter         fddiMACFrame_Ct ;
+               Counter         fddiMACCopied_Ct ;
+               Counter         fddiMACTransmit_Ct ;
+               Counter         fddiMACToken_Ct ;
+               Counter         fddiMACError_Ct ;
+               Counter         fddiMACLost_Ct ;
+               Counter         fddiMACTvxExpired_Ct ;
+               Counter         fddiMACNotCopied_Ct ;
+               Counter         fddiMACRingOp_Ct ;
+
+               Counter         fddiMACSMTCopied_Ct ;           /* private */
+               Counter         fddiMACSMTTransmit_Ct ;         /* private */
+
+               /* private for delta ratio */
+               Counter         fddiMACOld_Frame_Ct ;
+               Counter         fddiMACOld_Copied_Ct ;
+               Counter         fddiMACOld_Error_Ct ;
+               Counter         fddiMACOld_Lost_Ct ;
+               Counter         fddiMACOld_NotCopied_Ct ;
+
+               /* FrameErrorConditionGrp */
+               u_short         fddiMACFrameErrorThreshold ;
+               u_short         fddiMACFrameErrorRatio ;
+
+               /* NotCopiedConditionGrp */
+               u_short         fddiMACNotCopiedThreshold ;
+               u_short         fddiMACNotCopiedRatio ;
+
+               /* StatusGrp */
+               SMTEnum         fddiMACRMTState ;
+               SMTFlag         fddiMACDA_Flag ;
+               SMTFlag         fddiMACUNDA_Flag ;
+               SMTFlag         fddiMACFrameErrorFlag ;
+               SMTFlag         fddiMACNotCopiedFlag ;
+               SMTFlag         fddiMACMA_UnitdataAvailable ;
+               SMTFlag         fddiMACHardwarePresent ;
+               SMTFlag         fddiMACMA_UnitdataEnable ;
+
+       } m[NUMMACS] ;
+#define MAC0   0
+
+       struct fddi_mib_a {
+               ResId           fddiPATHIndex ;
+               u_long          fddiPATHSbaPayload ;
+               u_long          fddiPATHSbaOverhead ;
+               /* fddiPATHConfiguration is built on demand */
+               /* u_long               fddiPATHConfiguration ; */
+               Timer           fddiPATHT_Rmode ;
+               u_long          fddiPATHSbaAvailable ;
+               Timer_2         fddiPATHTVXLowerBound ;
+               Timer_2         fddiPATHT_MaxLowerBound ;
+               Timer_2         fddiPATHMaxT_Req ;
+       } a[NUMPATHS] ;
+#define PATH0  0
+
+       struct fddi_mib_p {
+               /* ConfigGrp */
+               SMTEnum         fddiPORTMy_Type ;
+               SMTEnum         fddiPORTNeighborType ;
+               u_char          fddiPORTConnectionPolicies ;
+               struct {
+                       u_char  T_val ;
+                       u_char  R_val ;
+               } fddiPORTMacIndicated ;
+               SMTEnum         fddiPORTCurrentPath ;
+               /* must be 4: is 32 bit in SMT format
+                * indices :
+                *      1       none
+                *      2       tree
+                *      3       peer
+                */
+               u_char          fddiPORTRequestedPaths[4] ;
+               u_short         fddiPORTMACPlacement ;
+               u_char          fddiPORTAvailablePaths ;
+               u_char          fddiPORTConnectionCapabilities ;
+               SMTEnum         fddiPORTPMDClass ;
+               ResId           fddiPORTIndex ;
+
+               /* OperationGrp */
+               SMTEnum         fddiPORTMaint_LS ;
+               SMTEnum         fddiPORTPC_LS ;
+               u_char          fddiPORTBS_Flag ;
+
+               /* ErrorCtrsGrp */
+               Counter         fddiPORTLCTFail_Ct ;
+               Counter         fddiPORTEBError_Ct ;
+               Counter         fddiPORTOldEBError_Ct ;
+
+               /* LerGrp */
+               Counter         fddiPORTLem_Reject_Ct ;
+               Counter         fddiPORTLem_Ct ;
+               u_char          fddiPORTLer_Estimate ;
+               u_char          fddiPORTLer_Cutoff ;
+               u_char          fddiPORTLer_Alarm ;
+
+               /* StatusGrp */
+               SMTEnum         fddiPORTConnectState ;
+               SMTEnum         fddiPORTPCMState ;      /* real value */
+               SMTEnum         fddiPORTPCMStateX ;     /* value for MIB */
+               SMTEnum         fddiPORTPC_Withhold ;
+               SMTFlag         fddiPORTHardwarePresent ;
+               u_char          fddiPORTLerFlag ;
+
+               u_char          fddiPORTMultiple_U ;    /* private */
+               u_char          fddiPORTMultiple_P ;    /* private */
+               u_char          fddiPORTEB_Condition ;  /* private */
+       } p[NUMPHYS] ;
+       struct {
+               Counter         fddiPRIVECF_Req_Rx ;    /* ECF req received */
+               Counter         fddiPRIVECF_Reply_Rx ;  /* ECF repl received */
+               Counter         fddiPRIVECF_Req_Tx ;    /* ECF req transm */
+               Counter         fddiPRIVECF_Reply_Tx ;  /* ECF repl transm */
+               Counter         fddiPRIVPMF_Get_Rx ;    /* PMF Get rec */
+               Counter         fddiPRIVPMF_Set_Rx ;    /* PMF Set rec */
+               Counter         fddiPRIVRDF_Rx ;        /* RDF received */
+               Counter         fddiPRIVRDF_Tx ;        /* RDF transmitted */
+       } priv ;
+} ;
+
+/*
+ * OIDs for statistics
+ */
+#define        SMT_OID_CF_STATE        1       /* fddiSMTCF_State */
+#define        SMT_OID_PCM_STATE_A     2       /* fddiPORTPCMState port A */
+#define        SMT_OID_PCM_STATE_B     17      /* fddiPORTPCMState port B */
+#define        SMT_OID_RMT_STATE       3       /* fddiMACRMTState */
+#define        SMT_OID_UNA             4       /* fddiMACUpstreamNbr */
+#define        SMT_OID_DNA             5       /* fddiMACOldDownstreamNbr */
+#define        SMT_OID_ERROR_CT        6       /* fddiMACError_Ct */
+#define        SMT_OID_LOST_CT         7       /* fddiMACLost_Ct */
+#define        SMT_OID_LEM_CT          8       /* fddiPORTLem_Ct */
+#define        SMT_OID_LEM_CT_A        11      /* fddiPORTLem_Ct port A */
+#define        SMT_OID_LEM_CT_B        12      /* fddiPORTLem_Ct port B */
+#define        SMT_OID_LCT_FAIL_CT     9       /* fddiPORTLCTFail_Ct */
+#define        SMT_OID_LCT_FAIL_CT_A   13      /* fddiPORTLCTFail_Ct port A */
+#define        SMT_OID_LCT_FAIL_CT_B   14      /* fddiPORTLCTFail_Ct port B */
+#define        SMT_OID_LEM_REJECT_CT   10      /* fddiPORTLem_Reject_Ct */
+#define        SMT_OID_LEM_REJECT_CT_A 15      /* fddiPORTLem_Reject_Ct port A */
+#define        SMT_OID_LEM_REJECT_CT_B 16      /* fddiPORTLem_Reject_Ct port B */
+
+/*
+ * SK MIB
+ */
+#define SMT_OID_ECF_REQ_RX     20      /* ECF requests received */
+#define SMT_OID_ECF_REPLY_RX   21      /* ECF replies received */
+#define SMT_OID_ECF_REQ_TX     22      /* ECF requests transmitted */
+#define SMT_OID_ECF_REPLY_TX   23      /* ECF replies transmitted */
+#define SMT_OID_PMF_GET_RX     24      /* PMF get requests received */
+#define SMT_OID_PMF_SET_RX     25      /* PMF set requests received */
+#define SMT_OID_RDF_RX         26      /* RDF received */
+#define SMT_OID_RDF_TX         27      /* RDF transmitted */
diff --git a/drivers/net/fddi/skfp/h/fplustm.h b/drivers/net/fddi/skfp/h/fplustm.h
new file mode 100644 (file)
index 0000000..d43191e
--- /dev/null
@@ -0,0 +1,274 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ *     AMD Fplus in tag mode data structs
+ *     defs for fplustm.c
+ */
+
+#ifndef        _FPLUS_
+#define _FPLUS_
+
+#ifndef        HW_PTR
+#define        HW_PTR  void __iomem *
+#endif
+
+/*
+ * fplus error statistic structure
+ */
+struct err_st {
+       u_long err_valid ;              /* memory status valid */
+       u_long err_abort ;              /* memory status receive abort */
+       u_long err_e_indicator ;        /* error indicator */
+       u_long err_crc ;                /* error detected (CRC or length) */
+       u_long err_llc_frame ;          /* LLC frame */
+       u_long err_mac_frame ;          /* MAC frame */
+       u_long err_smt_frame ;          /* SMT frame */
+       u_long err_imp_frame ;          /* implementer frame */
+       u_long err_no_buf ;             /* no buffer available */
+       u_long err_too_long ;           /* longer than max. buffer */
+       u_long err_bec_stat ;           /* beacon state entered */
+       u_long err_clm_stat ;           /* claim state entered */
+       u_long err_sifg_det ;           /* short interframe gap detect */
+       u_long err_phinv ;              /* PHY invalid */
+       u_long err_tkiss ;              /* token issued */
+       u_long err_tkerr ;              /* token error */
+} ;
+
+/*
+ *     Transmit Descriptor struct
+ */
+struct s_smt_fp_txd {
+       __le32 txd_tbctrl ;             /* transmit buffer control */
+       __le32 txd_txdscr ;             /* transmit frame status word */
+       __le32 txd_tbadr ;              /* physical tx buffer address */
+       __le32 txd_ntdadr ;             /* physical pointer to the next TxD */
+#ifdef ENA_64BIT_SUP
+       __le32 txd_tbadr_hi ;           /* physical tx buffer addr (high dword)*/
+#endif
+       char far *txd_virt ;            /* virtual pointer to the data frag */
+                                       /* virt pointer to the next TxD */
+       struct s_smt_fp_txd volatile far *txd_next ;
+       struct s_txd_os txd_os ;        /* OS - specific struct */
+} ;
+
+/*
+ *     Receive Descriptor struct
+ */
+struct s_smt_fp_rxd {
+       __le32 rxd_rbctrl ;             /* receive buffer control */
+       __le32 rxd_rfsw ;               /* receive frame status word */
+       __le32 rxd_rbadr ;              /* physical rx buffer address */
+       __le32 rxd_nrdadr ;             /* physical pointer to the next RxD */
+#ifdef ENA_64BIT_SUP
+       __le32 rxd_rbadr_hi ;           /* physical tx buffer addr (high dword)*/
+#endif
+       char far *rxd_virt ;            /* virtual pointer to the data frag */
+                                       /* virt pointer to the next RxD */
+       struct s_smt_fp_rxd volatile far *rxd_next ;
+       struct s_rxd_os rxd_os ;        /* OS - specific struct */
+} ;
+
+/*
+ *     Descriptor Union Definition
+ */
+union s_fp_descr {
+       struct  s_smt_fp_txd t ;                /* pointer to the TxD */
+       struct  s_smt_fp_rxd r ;                /* pointer to the RxD */
+} ;
+
+/*
+ *     TxD Ring Control struct
+ */
+struct s_smt_tx_queue {
+       struct s_smt_fp_txd volatile *tx_curr_put ; /* next free TxD */
+       struct s_smt_fp_txd volatile *tx_prev_put ; /* shadow put pointer */
+       struct s_smt_fp_txd volatile *tx_curr_get ; /* next TxD to release*/
+       u_short tx_free ;                       /* count of free TxD's */
+       u_short tx_used ;                       /* count of used TxD's */
+       HW_PTR tx_bmu_ctl ;                     /* BMU addr for tx start */
+       HW_PTR tx_bmu_dsc ;                     /* BMU addr for curr dsc. */
+} ;
+
+/*
+ *     RxD Ring Control struct
+ */
+struct s_smt_rx_queue {
+       struct s_smt_fp_rxd volatile *rx_curr_put ; /* next RxD to queue into */
+       struct s_smt_fp_rxd volatile *rx_prev_put ; /* shadow put pointer */
+       struct s_smt_fp_rxd volatile *rx_curr_get ; /* next RxD to fill */
+       u_short rx_free ;                       /* count of free RxD's */
+       u_short rx_used ;                       /* count of used RxD's */
+       HW_PTR rx_bmu_ctl ;                     /* BMU addr for rx start */
+       HW_PTR rx_bmu_dsc ;                     /* BMU addr for curr dsc. */
+} ;
+
+#define VOID_FRAME_OFF         0x00
+#define CLAIM_FRAME_OFF                0x08
+#define BEACON_FRAME_OFF       0x10
+#define DBEACON_FRAME_OFF      0x18
+#define RX_FIFO_OFF            0x21            /* to get a prime number for */
+                                               /* the RX_FIFO_SPACE */
+
+#define RBC_MEM_SIZE           0x8000
+#define SEND_ASYNC_AS_SYNC     0x1
+#define        SYNC_TRAFFIC_ON         0x2
+
+/* big FIFO memory */
+#define        RX_FIFO_SPACE           0x4000 - RX_FIFO_OFF
+#define        TX_FIFO_SPACE           0x4000
+
+#define        TX_SMALL_FIFO           0x0900
+#define        TX_MEDIUM_FIFO          TX_FIFO_SPACE / 2       
+#define        TX_LARGE_FIFO           TX_FIFO_SPACE - TX_SMALL_FIFO   
+
+#define        RX_SMALL_FIFO           0x0900
+#define        RX_LARGE_FIFO           RX_FIFO_SPACE - RX_SMALL_FIFO   
+
+struct s_smt_fifo_conf {
+       u_short rbc_ram_start ;         /* FIFO start address */
+       u_short rbc_ram_end ;           /* FIFO size */
+       u_short rx1_fifo_start ;        /* rx queue start address */
+       u_short rx1_fifo_size ;         /* rx queue size */
+       u_short rx2_fifo_start ;        /* rx queue start address */
+       u_short rx2_fifo_size ;         /* rx queue size */
+       u_short tx_s_start ;            /* sync queue start address */
+       u_short tx_s_size ;             /* sync queue size */
+       u_short tx_a0_start ;           /* async queue A0 start address */
+       u_short tx_a0_size ;            /* async queue A0 size */
+       u_short fifo_config_mode ;      /* FIFO configuration mode */
+} ;
+
+#define FM_ADDRX       (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
+
+struct s_smt_fp {
+       u_short mdr2init ;              /* mode register 2 init value */
+       u_short mdr3init ;              /* mode register 3 init value */
+       u_short frselreg_init ;         /* frame selection register init val */
+       u_short rx_mode ;               /* address mode broad/multi/promisc */
+       u_short nsa_mode ;
+       u_short rx_prom ;
+       u_short exgpa ;
+
+       struct err_st err_stats ;       /* error statistics */
+
+       /*
+        * MAC buffers
+        */
+       struct fddi_mac_sf {            /* special frame build buffer */
+               u_char                  mac_fc ;
+               struct fddi_addr        mac_dest ;
+               struct fddi_addr        mac_source ;
+               u_char                  mac_info[0x20] ;
+       } mac_sfb ;
+
+
+       /*
+        * queues
+        */
+#define QUEUE_S                        0
+#define QUEUE_A0               1
+#define QUEUE_R1               0
+#define QUEUE_R2               1
+#define USED_QUEUES            2
+
+       /*
+        * queue pointers; points to the queue dependent variables
+        */
+       struct s_smt_tx_queue *tx[USED_QUEUES] ;
+       struct s_smt_rx_queue *rx[USED_QUEUES] ;
+
+       /*
+        * queue dependent variables
+        */
+       struct s_smt_tx_queue tx_q[USED_QUEUES] ;
+       struct s_smt_rx_queue rx_q[USED_QUEUES] ;
+
+       /*
+        * FIFO configuration struct
+        */
+       struct  s_smt_fifo_conf fifo ;
+
+       /* last formac status */
+       u_short  s2u ;
+       u_short  s2l ;
+
+       /* calculated FORMAC+ reg.addr. */
+       HW_PTR  fm_st1u ;
+       HW_PTR  fm_st1l ;
+       HW_PTR  fm_st2u ;
+       HW_PTR  fm_st2l ;
+       HW_PTR  fm_st3u ;
+       HW_PTR  fm_st3l ;
+
+
+       /*
+        * multicast table
+        */
+#define FPMAX_MULTICAST 32 
+#define        SMT_MAX_MULTI   4
+       struct {
+               struct s_fpmc {
+                       struct fddi_addr        a ;     /* mc address */
+                       u_char                  n ;     /* usage counter */
+                       u_char                  perm ;  /* flag: permanent */
+               } table[FPMAX_MULTICAST] ;
+       } mc ;
+       struct fddi_addr        group_addr ;
+       u_long  func_addr ;             /* functional address */
+       int     smt_slots_used ;        /* count of table entries for the SMT */
+       int     os_slots_used ;         /* count of table entries */ 
+                                       /* used by the os-specific module */
+} ;
+
+/*
+ * modes for mac_set_rx_mode()
+ */
+#define RX_ENABLE_ALLMULTI     1       /* enable all multicasts */
+#define RX_DISABLE_ALLMULTI    2       /* disable "enable all multicasts" */
+#define RX_ENABLE_PROMISC      3       /* enable promiscuous */
+#define RX_DISABLE_PROMISC     4       /* disable promiscuous */
+#define RX_ENABLE_NSA          5       /* enable reception of NSA frames */
+#define RX_DISABLE_NSA         6       /* disable reception of NSA frames */
+
+
+/*
+ * support for byte reversal in AIX
+ * (descriptors and pointers must be byte reversed in memory
+ *  CPU is big endian; M-Channel is little endian)
+ */
+#ifdef AIX
+#define MDR_REV
+#define        AIX_REVERSE(x)          ((((x)<<24L)&0xff000000L)       +       \
+                                (((x)<< 8L)&0x00ff0000L)       +       \
+                                (((x)>> 8L)&0x0000ff00L)       +       \
+                                (((x)>>24L)&0x000000ffL))
+#else
+#ifndef AIX_REVERSE
+#define        AIX_REVERSE(x)  (x)
+#endif
+#endif
+
+#ifdef MDR_REV 
+#define        MDR_REVERSE(x)          ((((x)<<24L)&0xff000000L)       +       \
+                                (((x)<< 8L)&0x00ff0000L)       +       \
+                                (((x)>> 8L)&0x0000ff00L)       +       \
+                                (((x)>>24L)&0x000000ffL))
+#else
+#ifndef MDR_REVERSE
+#define        MDR_REVERSE(x)  (x)
+#endif
+#endif
+
+#endif
diff --git a/drivers/net/fddi/skfp/h/hwmtm.h b/drivers/net/fddi/skfp/h/hwmtm.h
new file mode 100644 (file)
index 0000000..5924d42
--- /dev/null
@@ -0,0 +1,399 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _HWM_
+#define        _HWM_
+
+#include "mbuf.h"
+
+/*
+ * MACRO for DMA synchronization:
+ *     The descriptor 'desc' is flushed for the device 'flag'.
+ *     Devices are the CPU (DDI_DMA_SYNC_FORCPU) and the
+ *     adapter (DDI_DMA_SYNC_FORDEV).
+ *
+ *     'desc'  Pointer to a Rx or Tx descriptor.
+ *     'flag'  Flag for direction (view for CPU or DEVICE) that
+ *             should be synchronized.
+ *
+ *     Empty macros and defines are specified here. The real macro
+ *     is os-specific and should be defined in osdef1st.h.
+ */
+#ifndef DRV_BUF_FLUSH
+#define DRV_BUF_FLUSH(desc,flag)
+#define DDI_DMA_SYNC_FORCPU
+#define DDI_DMA_SYNC_FORDEV
+#endif
+
+       /*
+        * hardware modul dependent receive modes
+        */
+#define        RX_ENABLE_PASS_SMT      21
+#define        RX_DISABLE_PASS_SMT     22
+#define        RX_ENABLE_PASS_NSA      23
+#define        RX_DISABLE_PASS_NSA     24
+#define        RX_ENABLE_PASS_DB       25
+#define        RX_DISABLE_PASS_DB      26
+#define        RX_DISABLE_PASS_ALL     27
+#define        RX_DISABLE_LLC_PROMISC  28
+#define        RX_ENABLE_LLC_PROMISC   29
+
+
+#ifndef        DMA_RD
+#define DMA_RD         1       /* memory -> hw */
+#endif
+#ifndef DMA_WR
+#define DMA_WR         2       /* hw -> memory */
+#endif
+#define SMT_BUF                0x80
+
+       /*
+        * bits of the frame status byte
+        */
+#define EN_IRQ_EOF     0x02    /* get IRQ after end of frame transmission */
+#define        LOC_TX          0x04    /* send frame to the local SMT */
+#define LAST_FRAG      0x08    /* last TxD of the frame */
+#define        FIRST_FRAG      0x10    /* first TxD of the frame */
+#define        LAN_TX          0x20    /* send frame to network if set */
+#define RING_DOWN      0x40    /* error: unable to send, ring down */
+#define OUT_OF_TXD     0x80    /* error: not enough TxDs available */
+
+
+#ifndef NULL
+#define NULL           0
+#endif
+
+#ifdef LITTLE_ENDIAN
+#define HWM_REVERSE(x) (x)
+#else
+#define        HWM_REVERSE(x)          ((((x)<<24L)&0xff000000L)       +       \
+                                (((x)<< 8L)&0x00ff0000L)       +       \
+                                (((x)>> 8L)&0x0000ff00L)       +       \
+                                (((x)>>24L)&0x000000ffL))
+#endif
+
+#define C_INDIC                (1L<<25)
+#define A_INDIC                (1L<<26)
+#define        RD_FS_LOCAL     0x80
+
+       /*
+        * DEBUG FLAGS
+        */
+#define        DEBUG_SMTF      1
+#define        DEBUG_SMT       2
+#define        DEBUG_ECM       3
+#define        DEBUG_RMT       4
+#define        DEBUG_CFM       5
+#define        DEBUG_PCM       6
+#define        DEBUG_SBA       7
+#define        DEBUG_ESS       8
+
+#define        DB_HWM_RX       10
+#define        DB_HWM_TX       11
+#define DB_HWM_GEN     12
+
+struct s_mbuf_pool {
+#ifndef        MB_OUTSIDE_SMC
+       SMbuf           mb[MAX_MBUF] ;          /* mbuf pool */
+#endif
+       SMbuf           *mb_start ;             /* points to the first mb */
+       SMbuf           *mb_free ;              /* free queue */
+} ;
+
+struct hwm_r {
+       /*
+        * hardware modul specific receive variables
+        */
+       u_int                   len ;           /* length of the whole frame */
+       char                    *mb_pos ;       /* SMbuf receive position */
+} ;
+
+struct hw_modul {
+       /*
+        * All hardware modul specific variables
+        */
+       struct  s_mbuf_pool     mbuf_pool ;
+       struct  hwm_r   r ;
+
+       union s_fp_descr volatile *descr_p ; /* points to the desriptor area */
+
+       u_short pass_SMT ;              /* pass SMT frames */
+       u_short pass_NSA ;              /* pass all NSA frames */
+       u_short pass_DB ;               /* pass Direct Beacon Frames */
+       u_short pass_llc_promisc ;      /* pass all llc frames (default ON) */
+
+       SMbuf   *llc_rx_pipe ;          /* points to the first queued llc fr */
+       SMbuf   *llc_rx_tail ;          /* points to the last queued llc fr */
+       int     queued_rx_frames ;      /* number of queued frames */
+
+       SMbuf   *txd_tx_pipe ;          /* points to first mb in the txd ring */
+       SMbuf   *txd_tx_tail ;          /* points to last mb in the txd ring */
+       int     queued_txd_mb ;         /* number of SMT MBufs in txd ring */
+
+       int     rx_break ;              /* rev. was breaked because ind. off */
+       int     leave_isr ;             /* leave fddi_isr immedeately if set */
+       int     isr_flag ;              /* set, when HWM is entered from isr */
+       /*
+        * variables for the current transmit frame
+        */
+       struct s_smt_tx_queue *tx_p ;   /* pointer to the transmit queue */
+       u_long  tx_descr ;              /* tx descriptor for FORMAC+ */
+       int     tx_len ;                /* tx frame length */
+       SMbuf   *tx_mb ;                /* SMT tx MBuf pointer */
+       char    *tx_data ;              /* data pointer to the SMT tx Mbuf */
+
+       int     detec_count ;           /* counter for out of RxD condition */
+       u_long  rx_len_error ;          /* rx len FORMAC != sum of fragments */
+} ;
+
+
+/*
+ * DEBUG structs and macros
+ */
+
+#ifdef DEBUG
+struct os_debug {
+       int     hwm_rx ;
+       int     hwm_tx ;
+       int     hwm_gen ;
+} ;
+#endif
+
+#ifdef DEBUG
+#ifdef DEBUG_BRD
+#define        DB_P    smc->debug
+#else
+#define DB_P   debug
+#endif
+
+#define DB_RX(a,b,c,lev) if (DB_P.d_os.hwm_rx >= (lev))        printf(a,b,c)
+#define DB_TX(a,b,c,lev) if (DB_P.d_os.hwm_tx >= (lev))        printf(a,b,c)
+#define DB_GEN(a,b,c,lev) if (DB_P.d_os.hwm_gen >= (lev)) printf(a,b,c)
+#else  /* DEBUG */
+#define DB_RX(a,b,c,lev)
+#define DB_TX(a,b,c,lev)
+#define DB_GEN(a,b,c,lev)
+#endif /* DEBUG */
+
+#ifndef        SK_BREAK
+#define        SK_BREAK()
+#endif
+
+
+/*
+ * HWM Macros
+ */
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_TX_PHYS)
+ *     u_long HWM_GET_TX_PHYS(txd)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to read
+ *             the physical address of the specified TxD.
+ *
+ * para        txd     pointer to the TxD
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_TX_PHYS(txd)            (u_long)AIX_REVERSE((txd)->txd_tbadr)
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_TX_LEN)
+ *     int HWM_GET_TX_LEN(txd)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to read
+ *             the fragment length of the specified TxD
+ *
+ * para        rxd     pointer to the TxD
+ *
+ * return      the length of the fragment in bytes
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_TX_LEN(txd)     ((int)AIX_REVERSE((txd)->txd_tbctrl)& RD_LENGTH)
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_TX_USED)
+ *     txd *HWM_GET_TX_USED(smc,queue)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to get the
+ *             number of used TxDs for the queue, specified by the index.
+ *
+ * para        queue   the number of the send queue: Can be specified by
+ *             QUEUE_A0, QUEUE_S or (frame_status & QUEUE_A0)
+ *
+ * return      number of used TxDs for this send queue
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_TX_USED(smc,queue)      (int) (smc)->hw.fp.tx_q[queue].tx_used
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_CURR_TXD)
+ *     txd *HWM_GET_CURR_TXD(smc,queue)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to get the
+ *             pointer to the TxD which points to the current queue put
+ *             position.
+ *
+ * para        queue   the number of the send queue: Can be specified by
+ *             QUEUE_A0, QUEUE_S or (frame_status & QUEUE_A0)
+ *
+ * return      pointer to the current TxD
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_CURR_TXD(smc,queue)     (struct s_smt_fp_txd volatile *)\
+                                       (smc)->hw.fp.tx_q[queue].tx_curr_put
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN)
+ *     int HWM_GET_RX_FRAG_LEN(rxd)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to read
+ *             the fragment length of the specified RxD
+ *
+ * para        rxd     pointer to the RxD
+ *
+ * return      the length of the fragment in bytes
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_RX_FRAG_LEN(rxd)        ((int)AIX_REVERSE((rxd)->rxd_rbctrl)& \
+                               RD_LENGTH)
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_PHYS)
+ *     u_long HWM_GET_RX_PHYS(rxd)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to read
+ *             the physical address of the specified RxD.
+ *
+ * para        rxd     pointer to the RxD
+ *
+ * return      the RxD's physical pointer to the data fragment
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_RX_PHYS(rxd)    (u_long)AIX_REVERSE((rxd)->rxd_rbadr)
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_USED)
+ *     int HWM_GET_RX_USED(smc)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to get
+ *             the count of used RXDs in receive queue 1.
+ *
+ * return      the used RXD count of receive queue 1
+ *
+ * NOTE: Remember, because of an ASIC bug at least one RXD should be unused
+ *      in the descriptor ring !
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_RX_USED(smc)    ((int)(smc)->hw.fp.rx_q[QUEUE_R1].rx_used)
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_FREE)
+ *     int HWM_GET_RX_FREE(smc)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to get
+ *             the rxd_free count of receive queue 1.
+ *
+ * return      the rxd_free count of receive queue 1
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_RX_FREE(smc)    ((int)(smc)->hw.fp.rx_q[QUEUE_R1].rx_free-1)
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_GET_CURR_RXD)
+ *     rxd *HWM_GET_CURR_RXD(smc)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro may be invoked by the OS-specific module to get the
+ *             pointer to the RxD which points to the current queue put
+ *             position.
+ *
+ * return      pointer to the current RxD
+ *
+ *     END_MANUAL_ENTRY
+ */
+#define        HWM_GET_CURR_RXD(smc)   (struct s_smt_fp_rxd volatile *)\
+                               (smc)->hw.fp.rx_q[QUEUE_R1].rx_curr_put
+
+/*
+ *     BEGIN_MANUAL_ENTRY(HWM_RX_CHECK)
+ *     void HWM_RX_CHECK(smc,low_water)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This macro is invoked by the OS-specific before it left the
+ *             function mac_drv_rx_complete. This macro calls mac_drv_fill_rxd
+ *             if the number of used RxDs is equal or lower than the
+ *             the given low water mark.
+ *
+ * para        low_water       low water mark of used RxD's
+ *
+ *     END_MANUAL_ENTRY
+ */
+#ifndef HWM_NO_FLOW_CTL
+#define        HWM_RX_CHECK(smc,low_water) {\
+       if ((low_water) >= (smc)->hw.fp.rx_q[QUEUE_R1].rx_used) {\
+               mac_drv_fill_rxd(smc) ;\
+       }\
+}
+#else
+#define        HWM_RX_CHECK(smc,low_water)             mac_drv_fill_rxd(smc)
+#endif
+
+#ifndef        HWM_EBASE
+#define        HWM_EBASE       500
+#endif
+
+#define        HWM_E0001       HWM_EBASE + 1
+#define        HWM_E0001_MSG   "HWM: Wrong size of s_rxd_os struct"
+#define        HWM_E0002       HWM_EBASE + 2
+#define        HWM_E0002_MSG   "HWM: Wrong size of s_txd_os struct"
+#define        HWM_E0003       HWM_EBASE + 3
+#define        HWM_E0003_MSG   "HWM: smt_free_mbuf() called with NULL pointer"
+#define        HWM_E0004       HWM_EBASE + 4
+#define        HWM_E0004_MSG   "HWM: Parity error rx queue 1"
+#define        HWM_E0005       HWM_EBASE + 5
+#define        HWM_E0005_MSG   "HWM: Encoding error rx queue 1"
+#define        HWM_E0006       HWM_EBASE + 6
+#define        HWM_E0006_MSG   "HWM: Encoding error async tx queue"
+#define        HWM_E0007       HWM_EBASE + 7
+#define        HWM_E0007_MSG   "HWM: Encoding error sync tx queue"
+#define        HWM_E0008       HWM_EBASE + 8
+#define        HWM_E0008_MSG   ""
+#define        HWM_E0009       HWM_EBASE + 9
+#define        HWM_E0009_MSG   "HWM: Out of RxD condition detected"
+#define        HWM_E0010       HWM_EBASE + 10
+#define        HWM_E0010_MSG   "HWM: A protocol layer has tried to send a frame with an invalid frame control"
+#define HWM_E0011      HWM_EBASE + 11
+#define HWM_E0011_MSG  "HWM: mac_drv_clear_tx_queue was called although the hardware wasn't stopped"
+#define HWM_E0012      HWM_EBASE + 12
+#define HWM_E0012_MSG  "HWM: mac_drv_clear_rx_queue was called although the hardware wasn't stopped"
+#define HWM_E0013      HWM_EBASE + 13
+#define HWM_E0013_MSG  "HWM: mac_drv_repair_descr was called although the hardware wasn't stopped"
+
+#endif
diff --git a/drivers/net/fddi/skfp/h/mbuf.h b/drivers/net/fddi/skfp/h/mbuf.h
new file mode 100644 (file)
index 0000000..f2aadcd
--- /dev/null
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _MBUF_
+#define _MBUF_
+
+#define M_SIZE 4504
+
+#ifndef MAX_MBUF
+#define MAX_MBUF       4
+#endif
+
+#ifndef NO_STD_MBUF
+#define sm_next         m_next
+#define sm_off          m_off
+#define sm_len          m_len
+#define sm_data         m_data
+#define SMbuf           Mbuf
+#define mtod           smtod
+#define mtodoff                smtodoff
+#endif
+
+struct s_mbuf {
+       struct s_mbuf   *sm_next ;              /* low level linked list */
+       short           sm_off ;                        /* offset in m_data */
+       u_int           sm_len ;                        /* len of data */
+#ifdef PCI
+       int             sm_use_count ;
+#endif
+       char            sm_data[M_SIZE] ;
+} ;
+
+typedef struct s_mbuf SMbuf ;
+
+/* mbuf head, to typed data */
+#define        smtod(x,t)      ((t)((x)->sm_data + (x)->sm_off))
+#define        smtodoff(x,t,o) ((t)((x)->sm_data + (o)))
+
+#endif /* _MBUF_ */
diff --git a/drivers/net/fddi/skfp/h/osdef1st.h b/drivers/net/fddi/skfp/h/osdef1st.h
new file mode 100644 (file)
index 0000000..763ca18
--- /dev/null
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/* 
+ * Operating system-dependent definitions that have to be defined
+ * before any other header files are included.
+ */
+
+// HWM (HardWare Module) Definitions
+// -----------------------
+
+#include <asm/byteorder.h>
+
+#ifdef __LITTLE_ENDIAN
+#define LITTLE_ENDIAN
+#else
+#define BIG_ENDIAN
+#endif
+
+// this is set in the makefile
+// #define PCI                 /* only PCI adapters supported by this driver */
+// #define MEM_MAPPED_IO       /* use memory mapped I/O */
+
+
+#define USE_CAN_ADDR           /* DA and SA in MAC header are canonical. */
+
+#define MB_OUTSIDE_SMC         /* SMT Mbufs outside of smc struct. */
+
+// -----------------------
+
+
+// SMT Definitions 
+// -----------------------
+#define SYNC                   /* allow synchronous frames */
+
+// #define SBA                 /* Synchronous Bandwidth Allocator support */
+                               /* not available as free source */
+
+#define ESS                    /* SBA End Station Support */
+
+#define        SMT_PANIC(smc, nr, msg) printk(KERN_INFO "SMT PANIC: code: %d, msg: %s\n",nr,msg)
+
+
+#ifdef DEBUG
+#define printf(s,args...) printk(KERN_INFO s, ## args)
+#endif
+
+// #define HW_PTR      u_long
+// -----------------------
+
+
+
+// HWM and OS-specific buffer definitions
+// -----------------------
+
+// default number of receive buffers.
+#define NUM_RECEIVE_BUFFERS            10
+
+// default number of transmit buffers.
+#define NUM_TRANSMIT_BUFFERS           10
+
+// Number of SMT buffers (Mbufs).
+#define NUM_SMT_BUF    4
+
+// Number of TXDs for asynchronous transmit queue.
+#define HWM_ASYNC_TXD_COUNT    (NUM_TRANSMIT_BUFFERS + NUM_SMT_BUF)
+
+// Number of TXDs for synchronous transmit queue.
+#define HWM_SYNC_TXD_COUNT     HWM_ASYNC_TXD_COUNT
+
+
+// Number of RXDs for receive queue #1.
+// Note: Workaround for ASIC Errata #7: One extra RXD is required.
+#if (NUM_RECEIVE_BUFFERS > 100)
+#define SMT_R1_RXD_COUNT       (1 + 100)
+#else
+#define SMT_R1_RXD_COUNT       (1 + NUM_RECEIVE_BUFFERS)
+#endif
+
+// Number of RXDs for receive queue #2.
+#define SMT_R2_RXD_COUNT       0       // Not used.
+// -----------------------
+
+
+
+/*
+ * OS-specific part of the transmit/receive descriptor structure (TXD/RXD).
+ *
+ * Note: The size of these structures must follow this rule:
+ *
+ *     sizeof(struct) + 2*sizeof(void*) == n * 16, n >= 1
+ *
+ * We use the dma_addr fields under Linux to keep track of the
+ * DMA address of the packet data, for later pci_unmap_single. -DaveM
+ */
+
+struct s_txd_os {      // os-specific part of transmit descriptor
+       struct sk_buff *skb;
+       dma_addr_t dma_addr;
+} ;
+
+struct s_rxd_os {      // os-specific part of receive descriptor
+       struct sk_buff *skb;
+       dma_addr_t dma_addr;
+} ;
+
+
+/*
+ * So we do not need to make too many modifications to the generic driver
+ * parts, we take advantage of the AIX byte swapping macro interface.
+ */
+
+#define AIX_REVERSE(x)         ((u32)le32_to_cpu((u32)(x)))
+#define MDR_REVERSE(x)         ((u32)le32_to_cpu((u32)(x)))
diff --git a/drivers/net/fddi/skfp/h/sba.h b/drivers/net/fddi/skfp/h/sba.h
new file mode 100644 (file)
index 0000000..35ddb44
--- /dev/null
@@ -0,0 +1,142 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Synchronous Bandwidth Allocation (SBA) structs
+ */
+#ifndef _SBA_
+#define _SBA_
+
+#include "mbuf.h"
+#include "sba_def.h"
+
+#ifdef SBA
+
+/* Timer Cell Template */
+struct timer_cell {
+       struct timer_cell       *next_ptr ;
+       struct timer_cell       *prev_ptr ;
+       u_long                  start_time ;
+       struct s_sba_node_vars  *node_var ;
+} ;
+
+/*
+ * Node variables
+ */
+struct s_sba_node_vars {
+       u_char                  change_resp_flag ;
+       u_char                  report_resp_flag ;
+       u_char                  change_req_flag ;
+       u_char                  report_req_flag ;
+       long                    change_amount ;
+       long                    node_overhead ;
+       long                    node_payload ;
+       u_long                  node_status ;
+       u_char                  deallocate_status ;
+       u_char                  timer_state ;
+       u_short                 report_cnt ;
+       long                    lastrep_req_tranid ;
+       struct fddi_addr        mac_address ;
+       struct s_sba_sessions   *node_sessions ;
+       struct timer_cell       timer ;
+} ;
+
+/*
+ * Session variables
+ */
+struct s_sba_sessions {
+       u_long                  deallocate_status ;
+       long                    session_overhead ;
+       u_long                  min_segment_size ;
+       long                    session_payload ;
+       u_long                  session_status ;
+       u_long                  sba_category ;
+       long                    lastchg_req_tranid ;
+       u_short                 session_id ;
+       u_char                  class ;
+       u_char                  fddi2 ;
+       u_long                  max_t_neg ;
+       struct s_sba_sessions   *next_session ;
+} ;
+
+struct s_sba {
+
+       struct s_sba_node_vars  node[MAX_NODES] ;
+       struct s_sba_sessions   session[MAX_SESSIONS] ;
+
+       struct s_sba_sessions   *free_session ; /* points to the first */
+                                               /* free session */
+
+       struct timer_cell       *tail_timer ;   /* points to the last timer cell */
+
+       /*
+        * variables for allocation actions
+        */
+       long    total_payload ;         /* Total Payload */
+       long    total_overhead ;        /* Total Overhead */
+       long    sba_allocatable ;       /* allocatable sync bandwidth */
+
+       /*
+        * RAF message receive parameters
+        */
+       long            msg_path_index ;        /* Path Type */
+       long            msg_sba_pl_req ;        /* Payload Request */
+       long            msg_sba_ov_req ;        /* Overhead Request */
+       long            msg_mib_pl ;            /* Current Payload for this Path */
+       long            msg_mib_ov ;            /* Current Overhead for this Path*/
+       long            msg_category ;          /* Category of the Allocation */
+       u_long          msg_max_t_neg ;         /* longest T_Neg acceptable */
+       u_long          msg_min_seg_siz ;       /* minimum segement size */
+       struct smt_header       *sm ;           /* points to the rec message */
+       struct fddi_addr        *msg_alloc_addr ;       /* Allocation Address */
+
+       /*
+        * SBA variables
+        */
+       u_long  sba_t_neg ;             /* holds the last T_NEG */
+       long    sba_max_alloc ;         /* the parsed value of SBAAvailable */  
+
+       /*
+        * SBA state machine variables
+        */
+       short   sba_next_state ;        /* the next state of the SBA */
+       char    sba_command ;           /* holds the execuded SBA cmd */
+       u_char  sba_available ;         /* parsed value after possible check */
+} ;
+
+#endif /* SBA */
+
+       /*
+        * variables for the End Station Support
+        */
+struct s_ess {
+
+       /*
+        * flags and counters
+        */
+       u_char  sync_bw_available ;     /* is set if sync bw is allocated */
+       u_char  local_sba_active ;      /* set when a local sba is available */
+       char    raf_act_timer_poll ;    /* activate the timer to send allc req */
+       char    timer_count ;           /* counts every timer function call */
+
+       SMbuf   *sba_reply_pend ;       /* local reply for the sba is pending */
+       
+       /*
+        * variables for the ess bandwidth control
+        */
+       long    sync_bw ;               /* holds the allocaed sync bw */
+       u_long  alloc_trans_id ;        /* trans id of the last alloc req */
+} ;
+#endif
diff --git a/drivers/net/fddi/skfp/h/sba_def.h b/drivers/net/fddi/skfp/h/sba_def.h
new file mode 100644 (file)
index 0000000..0459a09
--- /dev/null
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#define PHYS                   0               /* physical addr */
+#define PERM_ADDR              0x80            /* permanet address */
+#define SB_STATIC              0x00000001
+#define MAX_PAYLOAD            1562
+#define PRIMARY_RING           0x00000001
+#ifndef NULL
+#define NULL                   0x00
+#endif
+
+/*********************** SB_Input Variable Values ***********************/
+/*      may be needed when ever the SBA state machine is called        */
+
+#define UNKNOWN_SYNC_SOURCE    0x0001
+#define REQ_ALLOCATION         0x0002
+#define REPORT_RESP            0x0003
+#define CHANGE_RESP            0x0004
+#define TNEG                   0x0005
+#define NIF                    0x0006
+#define SB_STOP                        0x0007
+#define SB_START               0x0008
+#define REPORT_TIMER           0x0009
+#define CHANGE_REQUIRED                0x000A
+
+#define DEFAULT_OV             50
+
+#ifdef SBA
+/**************************** SBA STATES *****************************/
+
+#define SBA_STANDBY            0x00000000
+#define SBA_ACTIVE             0x00000001
+#define SBA_RECOVERY           0x00000002
+#define SBA_REPORT             0x00000003
+#define SBA_CHANGE             0x00000004
+
+/**************************** OTHERS *********************************/
+
+#define FIFTY_PERCENT          50              /* bytes per second */
+#define MAX_SESSIONS           150     
+#define TWO_MINUTES            13079           /* 9.175 ms/tick */
+#define FIFTY_BYTES            50
+#define SBA_DENIED             0x0000000D
+#define I_NEED_ONE             0x00000000
+#define MAX_NODES              50
+/*#define T_REPORT             0x59682F00L*/   /* 120s/80ns in Hex */
+#define        TWO_MIN                 120             /* seconds */
+#define SBA_ST_UNKNOWN         0x00000002
+#define SBA_ST_ACTIVE          0x00000001
+#define S_CLEAR                        0x00000000L
+#define ZERO                   0x00000000
+#define FULL                   0x00000000      /* old: 0xFFFFFFFFF */
+#define S_SET                  0x00000001L
+#define LOW_PRIO               0x02            /* ??????? */
+#define OK                     0x01            /* ??????? */
+#define NOT_OK                 0x00            /* ??????? */
+
+/****************************************/
+/* deallocate_status[ni][si] values    */
+/****************************************/
+#define TX_CHANGE              0X00000001L
+#define PENDING                        0x00000002L
+#define NONE                   0X00000000L
+#endif
diff --git a/drivers/net/fddi/skfp/h/skfbi.h b/drivers/net/fddi/skfp/h/skfbi.h
new file mode 100644 (file)
index 0000000..c1ba26c
--- /dev/null
@@ -0,0 +1,1133 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _SKFBI_H_
+#define        _SKFBI_H_
+
+/*
+ * FDDI-Fx (x := {I(SA), P(CI)})
+ *     address calculation & function defines
+ */
+
+/*--------------------------------------------------------------------------*/
+#ifdef PCI
+
+/*
+ *     (DV)    = only defined for Da Vinci
+ *     (ML)    = only defined for Monalisa
+ */
+
+/*
+ * Configuration Space header
+ */
+#define        PCI_VENDOR_ID   0x00    /* 16 bit       Vendor ID */
+#define        PCI_DEVICE_ID   0x02    /* 16 bit       Device ID */
+#define        PCI_COMMAND     0x04    /* 16 bit       Command */
+#define        PCI_STATUS      0x06    /* 16 bit       Status */
+#define        PCI_REV_ID      0x08    /*  8 bit       Revision ID */
+#define        PCI_CLASS_CODE  0x09    /* 24 bit       Class Code */
+#define        PCI_CACHE_LSZ   0x0c    /*  8 bit       Cache Line Size */
+#define        PCI_LAT_TIM     0x0d    /*  8 bit       Latency Timer */
+#define        PCI_HEADER_T    0x0e    /*  8 bit       Header Type */
+#define        PCI_BIST        0x0f    /*  8 bit       Built-in selftest */
+#define        PCI_BASE_1ST    0x10    /* 32 bit       1st Base address */
+#define        PCI_BASE_2ND    0x14    /* 32 bit       2nd Base address */
+/* Byte 18..2b:        Reserved */
+#define        PCI_SUB_VID     0x2c    /* 16 bit       Subsystem Vendor ID */
+#define        PCI_SUB_ID      0x2e    /* 16 bit       Subsystem ID */
+#define        PCI_BASE_ROM    0x30    /* 32 bit       Expansion ROM Base Address */
+/* Byte 34..33:        Reserved */
+#define PCI_CAP_PTR    0x34    /*  8 bit (ML)  Capabilities Ptr */
+/* Byte 35..3b:        Reserved */
+#define        PCI_IRQ_LINE    0x3c    /*  8 bit       Interrupt Line */
+#define        PCI_IRQ_PIN     0x3d    /*  8 bit       Interrupt Pin */
+#define        PCI_MIN_GNT     0x3e    /*  8 bit       Min_Gnt */
+#define        PCI_MAX_LAT     0x3f    /*  8 bit       Max_Lat */
+/* Device Dependent Region */
+#define        PCI_OUR_REG     0x40    /* 32 bit (DV)  Our Register */
+#define        PCI_OUR_REG_1   0x40    /* 32 bit (ML)  Our Register 1 */
+#define        PCI_OUR_REG_2   0x44    /* 32 bit (ML)  Our Register 2 */
+/* Power Management Region */
+#define PCI_PM_CAP_ID  0x48    /*  8 bit (ML)  Power Management Cap. ID */
+#define PCI_PM_NITEM   0x49    /*  8 bit (ML)  Next Item Ptr */
+#define PCI_PM_CAP_REG 0x4a    /* 16 bit (ML)  Power Management Capabilities */
+#define PCI_PM_CTL_STS 0x4c    /* 16 bit (ML)  Power Manag. Control/Status */
+/* Byte 0x4e:  Reserved */
+#define PCI_PM_DAT_REG 0x4f    /*  8 bit (ML)  Power Manag. Data Register */
+/* VPD Region */
+#define        PCI_VPD_CAP_ID  0x50    /*  8 bit (ML)  VPD Cap. ID */
+#define PCI_VPD_NITEM  0x51    /*  8 bit (ML)  Next Item Ptr */
+#define PCI_VPD_ADR_REG        0x52    /* 16 bit (ML)  VPD Address Register */
+#define PCI_VPD_DAT_REG        0x54    /* 32 bit (ML)  VPD Data Register */
+/* Byte 58..ff:        Reserved */
+
+/*
+ * I2C Address (PCI Config)
+ *
+ * Note: The temperature and voltage sensors are relocated on a different
+ *      I2C bus.
+ */
+#define I2C_ADDR_VPD   0xA0    /* I2C address for the VPD EEPROM */ 
+
+/*
+ * Define Bits and Values of the registers
+ */
+/*     PCI_VENDOR_ID   16 bit  Vendor ID */
+/*     PCI_DEVICE_ID   16 bit  Device ID */
+/* Values for Vendor ID and Device ID shall be patched into the code */
+/*     PCI_COMMAND     16 bit  Command */
+#define        PCI_FBTEN       0x0200  /* Bit 9:       Fast Back-To-Back enable */
+#define        PCI_SERREN      0x0100  /* Bit 8:       SERR enable */
+#define        PCI_ADSTEP      0x0080  /* Bit 7:       Address Stepping */
+#define        PCI_PERREN      0x0040  /* Bit 6:       Parity Report Response enable */
+#define        PCI_VGA_SNOOP   0x0020  /* Bit 5:       VGA palette snoop */
+#define        PCI_MWIEN       0x0010  /* Bit 4:       Memory write an inv cycl ena */
+#define        PCI_SCYCEN      0x0008  /* Bit 3:       Special Cycle enable */
+#define        PCI_BMEN        0x0004  /* Bit 2:       Bus Master enable */
+#define        PCI_MEMEN       0x0002  /* Bit 1:       Memory Space Access enable */
+#define        PCI_IOEN        0x0001  /* Bit 0:       IO Space Access enable */
+
+/*     PCI_STATUS      16 bit  Status */
+#define        PCI_PERR        0x8000  /* Bit 15:      Parity Error */
+#define        PCI_SERR        0x4000  /* Bit 14:      Signaled SERR */
+#define        PCI_RMABORT     0x2000  /* Bit 13:      Received Master Abort */
+#define        PCI_RTABORT     0x1000  /* Bit 12:      Received Target Abort */
+#define        PCI_STABORT     0x0800  /* Bit 11:      Sent Target Abort */
+#define        PCI_DEVSEL      0x0600  /* Bit 10..9:   DEVSEL Timing */
+#define        PCI_DEV_FAST    (0<<9)  /*              fast */
+#define        PCI_DEV_MEDIUM  (1<<9)  /*              medium */
+#define        PCI_DEV_SLOW    (2<<9)  /*              slow */
+#define        PCI_DATAPERR    0x0100  /* Bit 8:       DATA Parity error detected */
+#define        PCI_FB2BCAP     0x0080  /* Bit 7:       Fast Back-to-Back Capability */
+#define        PCI_UDF         0x0040  /* Bit 6:       User Defined Features */
+#define PCI_66MHZCAP   0x0020  /* Bit 5:       66 MHz PCI bus clock capable */
+#define PCI_NEWCAP     0x0010  /* Bit 4:       New cap. list implemented */
+
+#define PCI_ERRBITS    (PCI_PERR|PCI_SERR|PCI_RMABORT|PCI_STABORT|PCI_DATAPERR)
+
+/*     PCI_REV_ID      8 bit   Revision ID */
+/*     PCI_CLASS_CODE  24 bit  Class Code */
+/*     Byte 2:         Base Class              (02) */
+/*     Byte 1:         SubClass                (02) */
+/*     Byte 0:         Programming Interface   (00) */
+
+/*     PCI_CACHE_LSZ   8 bit   Cache Line Size */
+/*     Possible values: 0,2,4,8,16     */
+
+/*     PCI_LAT_TIM     8 bit   Latency Timer */
+
+/*     PCI_HEADER_T    8 bit   Header Type */
+#define        PCI_HD_MF_DEV   0x80    /* Bit 7:       0= single, 1= multi-func dev */
+#define        PCI_HD_TYPE     0x7f    /* Bit 6..0:    Header Layout 0= normal */
+
+/*     PCI_BIST        8 bit   Built-in selftest */
+#define        PCI_BIST_CAP    0x80    /* Bit 7:       BIST Capable */
+#define        PCI_BIST_ST     0x40    /* Bit 6:       Start BIST */
+#define        PCI_BIST_RET    0x0f    /* Bit 3..0:    Completion Code */
+
+/*     PCI_BASE_1ST    32 bit  1st Base address */
+#define        PCI_MEMSIZE     0x800L       /* use 2 kB Memory Base */
+#define        PCI_MEMBASE_BITS 0xfffff800L /* Bit 31..11:     Memory Base Address */
+#define        PCI_MEMSIZE_BIIS 0x000007f0L /* Bit 10..4:      Memory Size Req. */
+#define        PCI_PREFEN      0x00000008L  /* Bit 3:          Prefetchable */
+#define        PCI_MEM_TYP     0x00000006L  /* Bit 2..1:       Memory Type */
+#define        PCI_MEM32BIT    (0<<1)       /* Base addr anywhere in 32 Bit range */
+#define        PCI_MEM1M       (1<<1)       /* Base addr below 1 MegaByte */
+#define        PCI_MEM64BIT    (2<<1)       /* Base addr anywhere in 64 Bit range */
+#define        PCI_MEMSPACE    0x00000001L  /* Bit 0:  Memory Space Indic. */
+
+/*     PCI_BASE_2ND    32 bit  2nd Base address */
+#define        PCI_IOBASE      0xffffff00L  /* Bit 31..8:  I/O Base address */
+#define        PCI_IOSIZE      0x000000fcL  /* Bit 7..2:   I/O Size Requirements */
+#define        PCI_IOSPACE     0x00000001L  /* Bit 0:      I/O Space Indicator */
+
+/*     PCI_SUB_VID     16 bit  Subsystem Vendor ID */
+/*     PCI_SUB_ID      16 bit  Subsystem ID */
+
+/*     PCI_BASE_ROM    32 bit  Expansion ROM Base Address */
+#define        PCI_ROMBASE     0xfffe0000L  /* Bit 31..17: ROM BASE address (1st) */
+#define        PCI_ROMBASZ     0x0001c000L  /* Bit 16..14: Treat as BASE or SIZE */
+#define        PCI_ROMSIZE     0x00003800L  /* Bit 13..11: ROM Size Requirements */
+#define        PCI_ROMEN       0x00000001L  /* Bit 0:      Address Decode enable */
+
+/*     PCI_CAP_PTR     8 bit   New Capabilities Pointers */
+/*     PCI_IRQ_LINE    8 bit   Interrupt Line */
+/*     PCI_IRQ_PIN     8 bit   Interrupt Pin */
+/*     PCI_MIN_GNT     8 bit   Min_Gnt */
+/*     PCI_MAX_LAT     8 bit   Max_Lat */
+/* Device Dependent Region */
+/*     PCI_OUR_REG     (DV)    32 bit  Our Register */
+/*     PCI_OUR_REG_1   (ML)    32 bit  Our Register 1 */
+                                 /*     Bit 31..29:    reserved */
+#define        PCI_PATCH_DIR   (3L<<27)  /*(DV) Bit 28..27:    Ext Patchs direction */
+#define PCI_PATCH_DIR_0        (1L<<27)  /*(DV) Type of the pins EXT_PATCHS<1..0>   */
+#define PCI_PATCH_DIR_1 (1L<<28)  /*      0 = input                         */
+                                 /*       1 = output                        */
+#define        PCI_EXT_PATCHS  (3L<<25)  /*(DV) Bit 26..25:    Extended Patches     */
+#define PCI_EXT_PATCH_0 (1L<<25)  /*(DV)                                    */
+#define PCI_EXT_PATCH_1 (1L<<26)  /*    CLK for MicroWire (ML)              */
+#define PCI_VIO                (1L<<25)  /*(ML)                                     */
+#define        PCI_EN_BOOT     (1L<<24)  /*     Bit 24:        Enable BOOT via ROM  */
+                                 /*       1 = Don't boot with ROM           */
+                                 /*       0 = Boot with ROM                 */
+#define        PCI_EN_IO       (1L<<23)  /*     Bit 23:        Mapping to IO space  */
+#define        PCI_EN_FPROM    (1L<<22)  /*     Bit 22:        FLASH mapped to mem? */
+                                 /*       1 = Map Flash to Memory           */
+                                 /*       0 = Disable all addr. decoding    */
+#define        PCI_PAGESIZE    (3L<<20)  /*     Bit 21..20:    FLASH Page Size      */
+#define        PCI_PAGE_16     (0L<<20)  /*            16 k pages                   */
+#define        PCI_PAGE_32K    (1L<<20)  /*            32 k pages                   */
+#define        PCI_PAGE_64K    (2L<<20)  /*            64 k pages                   */
+#define        PCI_PAGE_128K   (3L<<20)  /*            128 k pages                  */
+                                 /*     Bit 19: reserved (ML) and (DV)      */
+#define        PCI_PAGEREG     (7L<<16)  /*     Bit 18..16:    Page Register        */
+                                 /*     Bit 15:        reserved             */
+#define        PCI_FORCE_BE    (1L<<14)  /*     Bit 14:        Assert all BEs on MR */
+#define        PCI_DIS_MRL     (1L<<13)  /*     Bit 13:        Disable Mem R Line   */
+#define        PCI_DIS_MRM     (1L<<12)  /*     Bit 12:        Disable Mem R multip */
+#define        PCI_DIS_MWI     (1L<<11)  /*     Bit 11:        Disable Mem W & inv  */
+#define        PCI_DISC_CLS    (1L<<10)  /*     Bit 10:        Disc: cacheLsz bound */
+#define        PCI_BURST_DIS   (1L<<9)   /*     Bit  9:        Burst Disable        */
+#define        PCI_BYTE_SWAP   (1L<<8)   /*(DV) Bit  8:        Byte Swap in DATA    */
+#define        PCI_SKEW_DAS    (0xfL<<4) /*     Bit 7..4:      Skew Ctrl, DAS Ext   */
+#define        PCI_SKEW_BASE   (0xfL<<0) /*     Bit 3..0:      Skew Ctrl, Base      */
+
+/*     PCI_OUR_REG_2   (ML)    32 bit  Our Register 2 (Monalisa only) */
+#define PCI_VPD_WR_TH  (0xffL<<24)     /* Bit 24..31   VPD Write Threshold  */
+#define        PCI_DEV_SEL     (0x7fL<<17)     /* Bit 17..23   EEPROM Device Select */
+#define        PCI_VPD_ROM_SZ  (7L<<14)        /* Bit 14..16   VPD ROM Size         */
+                                       /* Bit 12..13   reserved             */
+#define        PCI_PATCH_DIR2  (0xfL<<8)       /* Bit  8..11   Ext Patchs dir 2..5  */
+#define        PCI_PATCH_DIR_2 (1L<<8)         /* Bit  8       CS for MicroWire     */
+#define        PCI_PATCH_DIR_3 (1L<<9)
+#define        PCI_PATCH_DIR_4 (1L<<10)
+#define        PCI_PATCH_DIR_5 (1L<<11)
+#define PCI_EXT_PATCHS2 (0xfL<<4)      /* Bit  4..7    Extended Patches     */
+#define        PCI_EXT_PATCH_2 (1L<<4)         /* Bit  4       CS for MicroWire     */
+#define        PCI_EXT_PATCH_3 (1L<<5)
+#define        PCI_EXT_PATCH_4 (1L<<6)
+#define        PCI_EXT_PATCH_5 (1L<<7)
+#define        PCI_EN_DUMMY_RD (1L<<3)         /* Bit  3       Enable Dummy Read    */
+#define PCI_REV_DESC   (1L<<2)         /* Bit  2       Reverse Desc. Bytes  */
+#define PCI_USEADDR64  (1L<<1)         /* Bit  1       Use 64 Bit Addresse  */
+#define PCI_USEDATA64  (1L<<0)         /* Bit  0       Use 64 Bit Data bus ext*/
+
+/* Power Management Region */
+/*     PCI_PM_CAP_ID            8 bit (ML)     Power Management Cap. ID */
+/*     PCI_PM_NITEM             8 bit (ML)     Next Item Ptr */
+/*     PCI_PM_CAP_REG          16 bit (ML)     Power Management Capabilities*/
+#define        PCI_PME_SUP     (0x1f<<11)      /* Bit 11..15   PM Manag. Event Support*/
+#define PCI_PM_D2_SUB  (1<<10)         /* Bit 10       D2 Support Bit       */
+#define PCI_PM_D1_SUB  (1<<9)          /* Bit 9        D1 Support Bit       */
+                                       /* Bit 6..8 reserved                 */
+#define PCI_PM_DSI     (1<<5)          /* Bit 5        Device Specific Init.*/
+#define PCI_PM_APS     (1<<4)          /* Bit 4        Auxialiary Power Src */
+#define PCI_PME_CLOCK  (1<<3)          /* Bit 3        PM Event Clock       */
+#define PCI_PM_VER     (7<<0)          /* Bit 0..2     PM PCI Spec. version */
+
+/*     PCI_PM_CTL_STS          16 bit (ML)     Power Manag. Control/Status  */
+#define        PCI_PME_STATUS  (1<<15)         /* Bit 15       PFA doesn't sup. PME#*/
+#define PCI_PM_DAT_SCL (3<<13)         /* Bit 13..14   dat reg Scaling factor */
+#define PCI_PM_DAT_SEL (0xf<<9)        /* Bit  9..12   PM data selector field */
+                                       /* Bit  7.. 2   reserved             */
+#define PCI_PM_STATE   (3<<0)          /* Bit  0.. 1   Power Management State */
+#define PCI_PM_STATE_D0        (0<<0)          /* D0:  Operational (default) */
+#define        PCI_PM_STATE_D1 (1<<0)          /* D1:  not supported */
+#define PCI_PM_STATE_D2        (2<<0)          /* D2:  not supported */
+#define PCI_PM_STATE_D3 (3<<0)         /* D3:  HOT, Power Down and Reset */
+
+/*     PCI_PM_DAT_REG           8 bit (ML)     Power Manag. Data Register */
+/* VPD Region */
+/*     PCI_VPD_CAP_ID           8 bit (ML)     VPD Cap. ID */
+/*     PCI_VPD_NITEM            8 bit (ML)     Next Item Ptr */
+/*     PCI_VPD_ADR_REG         16 bit (ML)     VPD Address Register */
+#define        PCI_VPD_FLAG    (1<<15)         /* Bit 15       starts VPD rd/wd cycle*/
+
+/*     PCI_VPD_DAT_REG         32 bit (ML)     VPD Data Register */
+
+/*
+ *     Control Register File:
+ *     Bank 0
+ */
+#define        B0_RAP          0x0000  /*  8 bit register address port */
+       /* 0x0001 - 0x0003:     reserved */
+#define        B0_CTRL         0x0004  /*  8 bit control register */
+#define        B0_DAS          0x0005  /*  8 Bit control register (DAS) */
+#define        B0_LED          0x0006  /*  8 Bit LED register */
+#define        B0_TST_CTRL     0x0007  /*  8 bit test control register */
+#define        B0_ISRC         0x0008  /* 32 bit Interrupt source register */
+#define        B0_IMSK         0x000c  /* 32 bit Interrupt mask register */
+
+/* 0x0010 - 0x006b:    formac+ (supernet_3) fequently used registers */
+#define B0_CMDREG1     0x0010  /* write command reg 1 instruction */
+#define B0_CMDREG2     0x0014  /* write command reg 2 instruction */
+#define B0_ST1U                0x0010  /* read upper 16-bit of status reg 1 */
+#define B0_ST1L                0x0014  /* read lower 16-bit of status reg 1 */
+#define B0_ST2U                0x0018  /* read upper 16-bit of status reg 2 */
+#define B0_ST2L                0x001c  /* read lower 16-bit of status reg 2 */
+
+#define B0_MARR                0x0020  /* r/w the memory read addr register */
+#define B0_MARW                0x0024  /* r/w the memory write addr register*/
+#define B0_MDRU                0x0028  /* r/w upper 16-bit of mem. data reg */
+#define B0_MDRL                0x002c  /* r/w lower 16-bit of mem. data reg */
+
+#define        B0_MDREG3       0x0030  /* r/w Mode Register 3 */
+#define        B0_ST3U         0x0034  /* read upper 16-bit of status reg 3 */
+#define        B0_ST3L         0x0038  /* read lower 16-bit of status reg 3 */
+#define        B0_IMSK3U       0x003c  /* r/w upper 16-bit of IMSK reg 3 */
+#define        B0_IMSK3L       0x0040  /* r/w lower 16-bit of IMSK reg 3 */
+#define        B0_IVR          0x0044  /* read Interrupt Vector register */
+#define        B0_IMR          0x0048  /* r/w Interrupt mask register */
+/* 0x4c        Hidden */
+
+#define B0_CNTRL_A     0x0050  /* control register A (r/w) */
+#define B0_CNTRL_B     0x0054  /* control register B (r/w) */
+#define B0_INTR_MASK   0x0058  /* interrupt mask (r/w) */
+#define B0_XMIT_VECTOR 0x005c  /* transmit vector register (r/w) */
+
+#define B0_STATUS_A    0x0060  /* status register A (read only) */
+#define B0_STATUS_B    0x0064  /* status register B (read only) */
+#define B0_CNTRL_C     0x0068  /* control register C (r/w) */
+#define        B0_MDREG1       0x006c  /* r/w Mode Register 1 */
+
+#define        B0_R1_CSR       0x0070  /* 32 bit BMU control/status reg (rec q 1) */
+#define        B0_R2_CSR       0x0074  /* 32 bit BMU control/status reg (rec q 2)(DV)*/
+#define        B0_XA_CSR       0x0078  /* 32 bit BMU control/status reg (a xmit q) */
+#define        B0_XS_CSR       0x007c  /* 32 bit BMU control/status reg (s xmit q) */
+
+/*
+ *     Bank 1
+ *     - completely empty (this is the RAP Block window)
+ *     Note: if RAP = 1 this page is reserved
+ */
+
+/*
+ *     Bank 2
+ */
+#define        B2_MAC_0        0x0100  /*  8 bit MAC address Byte 0 */
+#define        B2_MAC_1        0x0101  /*  8 bit MAC address Byte 1 */
+#define        B2_MAC_2        0x0102  /*  8 bit MAC address Byte 2 */
+#define        B2_MAC_3        0x0103  /*  8 bit MAC address Byte 3 */
+#define        B2_MAC_4        0x0104  /*  8 bit MAC address Byte 4 */
+#define        B2_MAC_5        0x0105  /*  8 bit MAC address Byte 5 */
+#define        B2_MAC_6        0x0106  /*  8 bit MAC address Byte 6 (== 0) (DV) */
+#define        B2_MAC_7        0x0107  /*  8 bit MAC address Byte 7 (== 0) (DV) */
+
+#define B2_CONN_TYP    0x0108  /*  8 bit Connector type */
+#define B2_PMD_TYP     0x0109  /*  8 bit PMD type */
+                               /* 0x010a - 0x010b:     reserved */
+       /* Eprom registers are currently of no use */
+#define B2_E_0         0x010c  /*  8 bit EPROM Byte 0 */
+#define B2_E_1         0x010d  /*  8 bit EPROM Byte 1 */
+#define B2_E_2         0x010e  /*  8 bit EPROM Byte 2 */
+#define B2_E_3         0x010f  /*  8 bit EPROM Byte 3 */
+#define B2_FAR         0x0110  /* 32 bit Flash-Prom Address Register/Counter */
+#define B2_FDP         0x0114  /*  8 bit Flash-Prom Data Port */
+                               /* 0x0115 - 0x0117:     reserved */
+#define B2_LD_CRTL     0x0118  /*  8 bit loader control */
+#define B2_LD_TEST     0x0119  /*  8 bit loader test */
+                               /* 0x011a - 0x011f:     reserved */
+#define B2_TI_INI      0x0120  /* 32 bit Timer init value */
+#define B2_TI_VAL      0x0124  /* 32 bit Timer value */
+#define B2_TI_CRTL     0x0128  /*  8 bit Timer control */
+#define B2_TI_TEST     0x0129  /*  8 Bit Timer Test */
+                               /* 0x012a - 0x012f:     reserved */
+#define B2_WDOG_INI    0x0130  /* 32 bit Watchdog init value */
+#define B2_WDOG_VAL    0x0134  /* 32 bit Watchdog value */
+#define B2_WDOG_CRTL   0x0138  /*  8 bit Watchdog control */
+#define B2_WDOG_TEST   0x0139  /*  8 Bit Watchdog Test */
+                               /* 0x013a - 0x013f:     reserved */
+#define B2_RTM_INI     0x0140  /* 32 bit RTM init value */
+#define B2_RTM_VAL     0x0144  /* 32 bit RTM value */
+#define B2_RTM_CRTL    0x0148  /*  8 bit RTM control */
+#define B2_RTM_TEST    0x0149  /*  8 Bit RTM Test */
+
+#define B2_TOK_COUNT   0x014c  /* (ML) 32 bit  Token Counter */
+#define B2_DESC_ADDR_H 0x0150  /* (ML) 32 bit  Desciptor Base Addr Reg High */
+#define B2_CTRL_2      0x0154  /* (ML)  8 bit  Control Register 2 */
+#define B2_IFACE_REG   0x0155  /* (ML)  8 bit  Interface Register */
+                               /* 0x0156:              reserved */
+#define B2_TST_CTRL_2  0x0157  /* (ML)  8 bit  Test Control Register 2 */
+#define B2_I2C_CTRL    0x0158  /* (ML) 32 bit  I2C Control Register */
+#define B2_I2C_DATA    0x015c  /* (ML) 32 bit  I2C Data Register */
+
+#define B2_IRQ_MOD_INI 0x0160  /* (ML) 32 bit  IRQ Moderation Timer Init Reg. */
+#define B2_IRQ_MOD_VAL 0x0164  /* (ML) 32 bit  IRQ Moderation Timer Value */
+#define B2_IRQ_MOD_CTRL        0x0168  /* (ML)  8 bit  IRQ Moderation Timer Control */
+#define B2_IRQ_MOD_TEST        0x0169  /* (ML)  8 bit  IRQ Moderation Timer Test */
+                               /* 0x016a - 0x017f:     reserved */
+
+/*
+ *     Bank 3
+ */
+/*
+ * This is a copy of the Configuration register file (lower half)
+ */
+#define B3_CFG_SPC     0x180
+
+/*
+ *     Bank 4
+ */
+#define B4_R1_D                0x0200  /*      4*32 bit current receive Descriptor  */
+#define B4_R1_DA       0x0210  /*      32 bit current rec desc address      */
+#define B4_R1_AC       0x0214  /*      32 bit current receive Address Count */
+#define B4_R1_BC       0x0218  /*      32 bit current receive Byte Counter  */
+#define B4_R1_CSR      0x021c  /*      32 bit BMU Control/Status Register   */
+#define B4_R1_F                0x0220  /*      32 bit flag register                 */
+#define B4_R1_T1       0x0224  /*      32 bit Test Register 1               */
+#define B4_R1_T1_TR    0x0224  /*      8 bit Test Register 1 TR             */
+#define B4_R1_T1_WR    0x0225  /*      8 bit Test Register 1 WR             */
+#define B4_R1_T1_RD    0x0226  /*      8 bit Test Register 1 RD             */
+#define B4_R1_T1_SV    0x0227  /*      8 bit Test Register 1 SV             */
+#define B4_R1_T2       0x0228  /*      32 bit Test Register 2               */
+#define B4_R1_T3       0x022c  /*      32 bit Test Register 3               */
+#define B4_R1_DA_H     0x0230  /* (ML) 32 bit Curr Rx Desc Address High     */
+#define B4_R1_AC_H     0x0234  /* (ML) 32 bit Curr Addr Counter High dword  */
+                               /* 0x0238 - 0x023f:     reserved          */
+                               /* Receive queue 2 is removed on Monalisa */
+#define B4_R2_D                0x0240  /* 4*32 bit current receive Descriptor  (q2) */
+#define B4_R2_DA       0x0250  /* 32 bit current rec desc address      (q2) */
+#define B4_R2_AC       0x0254  /* 32 bit current receive Address Count (q2) */
+#define B4_R2_BC       0x0258  /* 32 bit current receive Byte Counter  (q2) */
+#define B4_R2_CSR      0x025c  /* 32 bit BMU Control/Status Register   (q2) */
+#define B4_R2_F                0x0260  /* 32 bit flag register                 (q2) */
+#define B4_R2_T1       0x0264  /* 32 bit Test Register 1               (q2) */
+#define B4_R2_T1_TR    0x0264  /* 8 bit Test Register 1 TR             (q2) */
+#define B4_R2_T1_WR    0x0265  /* 8 bit Test Register 1 WR             (q2) */
+#define B4_R2_T1_RD    0x0266  /* 8 bit Test Register 1 RD             (q2) */
+#define B4_R2_T1_SV    0x0267  /* 8 bit Test Register 1 SV             (q2) */
+#define B4_R2_T2       0x0268  /* 32 bit Test Register 2               (q2) */
+#define B4_R2_T3       0x026c  /* 32 bit Test Register 3               (q2) */
+                               /* 0x0270 - 0x027c:     reserved */
+
+/*
+ *     Bank 5
+ */
+#define B5_XA_D                0x0280  /* 4*32 bit current transmit Descriptor (xa) */
+#define B5_XA_DA       0x0290  /* 32 bit current tx desc address       (xa) */
+#define B5_XA_AC       0x0294  /* 32 bit current tx Address Count      (xa) */
+#define B5_XA_BC       0x0298  /* 32 bit current tx Byte Counter       (xa) */
+#define B5_XA_CSR      0x029c  /* 32 bit BMU Control/Status Register   (xa) */
+#define B5_XA_F                0x02a0  /* 32 bit flag register                 (xa) */
+#define B5_XA_T1       0x02a4  /* 32 bit Test Register 1               (xa) */
+#define B5_XA_T1_TR    0x02a4  /* 8 bit Test Register 1 TR             (xa) */
+#define B5_XA_T1_WR    0x02a5  /* 8 bit Test Register 1 WR             (xa) */
+#define B5_XA_T1_RD    0x02a6  /* 8 bit Test Register 1 RD             (xa) */
+#define B5_XA_T1_SV    0x02a7  /* 8 bit Test Register 1 SV             (xa) */
+#define B5_XA_T2       0x02a8  /* 32 bit Test Register 2               (xa) */
+#define B5_XA_T3       0x02ac  /* 32 bit Test Register 3               (xa) */
+#define B5_XA_DA_H     0x02b0  /* (ML) 32 bit Curr Tx Desc Address High     */
+#define B5_XA_AC_H     0x02b4  /* (ML) 32 bit Curr Addr Counter High dword  */
+                               /* 0x02b8 - 0x02bc:     reserved */
+#define B5_XS_D                0x02c0  /* 4*32 bit current transmit Descriptor (xs) */
+#define B5_XS_DA       0x02d0  /* 32 bit current tx desc address       (xs) */
+#define B5_XS_AC       0x02d4  /* 32 bit current transmit Address Count(xs) */
+#define B5_XS_BC       0x02d8  /* 32 bit current transmit Byte Counter (xs) */
+#define B5_XS_CSR      0x02dc  /* 32 bit BMU Control/Status Register   (xs) */
+#define B5_XS_F                0x02e0  /* 32 bit flag register                 (xs) */
+#define B5_XS_T1       0x02e4  /* 32 bit Test Register 1               (xs) */
+#define B5_XS_T1_TR    0x02e4  /* 8 bit Test Register 1 TR             (xs) */
+#define B5_XS_T1_WR    0x02e5  /* 8 bit Test Register 1 WR             (xs) */
+#define B5_XS_T1_RD    0x02e6  /* 8 bit Test Register 1 RD             (xs) */
+#define B5_XS_T1_SV    0x02e7  /* 8 bit Test Register 1 SV             (xs) */
+#define B5_XS_T2       0x02e8  /* 32 bit Test Register 2               (xs) */
+#define B5_XS_T3       0x02ec  /* 32 bit Test Register 3               (xs) */
+#define B5_XS_DA_H     0x02f0  /* (ML) 32 bit Curr Tx Desc Address High     */
+#define B5_XS_AC_H     0x02f4  /* (ML) 32 bit Curr Addr Counter High dword  */
+                               /* 0x02f8 - 0x02fc:     reserved */
+
+/*
+ *     Bank 6
+ */
+/* External PLC-S registers (SN2 compatibility for DV) */
+/* External registers (ML) */
+#define B6_EXT_REG     0x300
+
+/*
+ *     Bank 7
+ */
+/* DAS PLC-S Registers */
+
+/*
+ *     Bank 8 - 15
+ */
+/* IFCP registers */
+
+/*---------------------------------------------------------------------------*/
+/* Definitions of the Bits in the registers */
+
+/*     B0_RAP          16 bit register address port */
+#define        RAP_RAP         0x0f    /* Bit 3..0:    0 = block0, .., f = block15 */
+
+/*     B0_CTRL         8 bit control register */
+#define CTRL_FDDI_CLR  (1<<7)  /* Bit 7: (ML)  Clear FDDI Reset */
+#define CTRL_FDDI_SET  (1<<6)  /* Bit 6: (ML)  Set FDDI Reset */
+#define        CTRL_HPI_CLR    (1<<5)  /* Bit 5:       Clear HPI SM reset */
+#define        CTRL_HPI_SET    (1<<4)  /* Bit 4:       Set HPI SM reset */
+#define        CTRL_MRST_CLR   (1<<3)  /* Bit 3:       Clear Master reset */
+#define        CTRL_MRST_SET   (1<<2)  /* Bit 2:       Set Master reset */
+#define        CTRL_RST_CLR    (1<<1)  /* Bit 1:       Clear Software reset */
+#define        CTRL_RST_SET    (1<<0)  /* Bit 0:       Set Software reset */
+
+/*     B0_DAS          8 Bit control register (DAS) */
+#define BUS_CLOCK      (1<<7)  /* Bit 7: (ML)  Bus Clock 0/1 = 33/66MHz */
+#define BUS_SLOT_SZ    (1<<6)  /* Bit 6: (ML)  Slot Size 0/1 = 32/64 bit slot*/
+                               /* Bit 5..4:    reserved */
+#define        DAS_AVAIL       (1<<3)  /* Bit 3:       1 = DAS, 0 = SAS */
+#define DAS_BYP_ST     (1<<2)  /* Bit 2:       1 = avail,SAS, 0 = not avail */
+#define DAS_BYP_INS    (1<<1)  /* Bit 1:       1 = insert Bypass */
+#define DAS_BYP_RMV    (1<<0)  /* Bit 0:       1 = remove Bypass */
+
+/*     B0_LED          8 Bit LED register */
+                               /* Bit 7..6:    reserved */
+#define LED_2_ON       (1<<5)  /* Bit 5:       1 = switch LED_2 on (left,gn)*/
+#define LED_2_OFF      (1<<4)  /* Bit 4:       1 = switch LED_2 off */
+#define LED_1_ON       (1<<3)  /* Bit 3:       1 = switch LED_1 on (mid,yel)*/
+#define LED_1_OFF      (1<<2)  /* Bit 2:       1 = switch LED_1 off */
+#define LED_0_ON       (1<<1)  /* Bit 1:       1 = switch LED_0 on (rght,gn)*/
+#define LED_0_OFF      (1<<0)  /* Bit 0:       1 = switch LED_0 off */
+/* This hardware defines are very ugly therefore we define some others */
+
+#define LED_GA_ON      LED_2_ON        /* S port = A port */
+#define LED_GA_OFF     LED_2_OFF       /* S port = A port */
+#define LED_MY_ON      LED_1_ON
+#define LED_MY_OFF     LED_1_OFF
+#define LED_GB_ON      LED_0_ON
+#define LED_GB_OFF     LED_0_OFF
+
+/*     B0_TST_CTRL     8 bit test control register */
+#define        TST_FRC_DPERR_MR        (1<<7)  /* Bit 7:  force DATAPERR on MST RE. */
+#define        TST_FRC_DPERR_MW        (1<<6)  /* Bit 6:  force DATAPERR on MST WR. */
+#define        TST_FRC_DPERR_TR        (1<<5)  /* Bit 5:  force DATAPERR on TRG RE. */
+#define        TST_FRC_DPERR_TW        (1<<4)  /* Bit 4:  force DATAPERR on TRG WR. */
+#define        TST_FRC_APERR_M         (1<<3)  /* Bit 3:  force ADDRPERR on MST     */
+#define        TST_FRC_APERR_T         (1<<2)  /* Bit 2:  force ADDRPERR on TRG     */
+#define        TST_CFG_WRITE_ON        (1<<1)  /* Bit 1:  ena configuration reg. WR */
+#define        TST_CFG_WRITE_OFF       (1<<0)  /* Bit 0:  dis configuration reg. WR */
+
+/*     B0_ISRC         32 bit Interrupt source register */
+                                       /* Bit 31..28:  reserved             */
+#define IS_I2C_READY   (1L<<27)        /* Bit 27: (ML) IRQ on end of I2C tx */
+#define IS_IRQ_SW      (1L<<26)        /* Bit 26: (ML) SW forced IRQ        */
+#define IS_EXT_REG     (1L<<25)        /* Bit 25: (ML) IRQ from external reg*/
+#define        IS_IRQ_STAT     (1L<<24)        /* Bit 24:      IRQ status exception */
+                                       /*   PERR, RMABORT, RTABORT DATAPERR */
+#define        IS_IRQ_MST_ERR  (1L<<23)        /* Bit 23:      IRQ master error     */
+                                       /*   RMABORT, RTABORT, DATAPERR      */
+#define        IS_TIMINT       (1L<<22)        /* Bit 22:      IRQ_TIMER       */
+#define        IS_TOKEN        (1L<<21)        /* Bit 21:      IRQ_RTM         */
+/*
+ * Note: The DAS is our First Port (!=PA)
+ */
+#define        IS_PLINT1       (1L<<20)        /* Bit 20:      IRQ_PHY_DAS     */
+#define        IS_PLINT2       (1L<<19)        /* Bit 19:      IRQ_IFCP_4      */
+#define        IS_MINTR3       (1L<<18)        /* Bit 18:      IRQ_IFCP_3/IRQ_PHY */
+#define        IS_MINTR2       (1L<<17)        /* Bit 17:      IRQ_IFCP_2/IRQ_MAC_2 */
+#define        IS_MINTR1       (1L<<16)        /* Bit 16:      IRQ_IFCP_1/IRQ_MAC_1 */
+/* Receive Queue 1 */
+#define        IS_R1_P         (1L<<15)        /* Bit 15:      Parity Error (q1) */
+#define        IS_R1_B         (1L<<14)        /* Bit 14:      End of Buffer (q1) */
+#define        IS_R1_F         (1L<<13)        /* Bit 13:      End of Frame (q1) */
+#define        IS_R1_C         (1L<<12)        /* Bit 12:      Encoding Error (q1) */
+/* Receive Queue 2 */
+#define        IS_R2_P         (1L<<11)        /* Bit 11: (DV) Parity Error (q2) */
+#define        IS_R2_B         (1L<<10)        /* Bit 10: (DV) End of Buffer (q2) */
+#define        IS_R2_F         (1L<<9)         /* Bit  9: (DV) End of Frame (q2) */
+#define        IS_R2_C         (1L<<8)         /* Bit  8: (DV) Encoding Error (q2) */
+/* Asynchronous Transmit queue */
+                                       /* Bit  7:      reserved */
+#define        IS_XA_B         (1L<<6)         /* Bit  6:      End of Buffer (xa) */
+#define        IS_XA_F         (1L<<5)         /* Bit  5:      End of Frame (xa) */
+#define        IS_XA_C         (1L<<4)         /* Bit  4:      Encoding Error (xa) */
+/* Synchronous Transmit queue */
+                                       /* Bit  3:      reserved */
+#define        IS_XS_B         (1L<<2)         /* Bit  2:      End of Buffer (xs) */
+#define        IS_XS_F         (1L<<1)         /* Bit  1:      End of Frame (xs) */
+#define        IS_XS_C         (1L<<0)         /* Bit  0:      Encoding Error (xs) */
+
+/*
+ * Define all valid interrupt source Bits from GET_ISR ()
+ */
+#define        ALL_IRSR        0x01ffff77L     /* (DV) */
+#define        ALL_IRSR_ML     0x0ffff077L     /* (ML) */
+
+
+/*     B0_IMSK         32 bit Interrupt mask register */
+/*
+ * The Bit definnition of this register are the same as of the interrupt
+ * source register. These definition are directly derived from the Hardware
+ * spec.
+ */
+                                       /* Bit 31..28:  reserved             */
+#define IRQ_I2C_READY  (1L<<27)        /* Bit 27: (ML) IRQ on end of I2C tx */
+#define IRQ_SW         (1L<<26)        /* Bit 26: (ML) SW forced IRQ        */
+#define IRQ_EXT_REG    (1L<<25)        /* Bit 25: (ML) IRQ from external reg*/
+#define        IRQ_STAT        (1L<<24)        /* Bit 24:      IRQ status exception */
+                                       /*   PERR, RMABORT, RTABORT DATAPERR */
+#define        IRQ_MST_ERR     (1L<<23)        /* Bit 23:      IRQ master error     */
+                                       /*   RMABORT, RTABORT, DATAPERR      */
+#define        IRQ_TIMER       (1L<<22)        /* Bit 22:      IRQ_TIMER       */
+#define        IRQ_RTM         (1L<<21)        /* Bit 21:      IRQ_RTM         */
+#define        IRQ_DAS         (1L<<20)        /* Bit 20:      IRQ_PHY_DAS     */
+#define        IRQ_IFCP_4      (1L<<19)        /* Bit 19:      IRQ_IFCP_4      */
+#define        IRQ_IFCP_3      (1L<<18)        /* Bit 18:      IRQ_IFCP_3/IRQ_PHY */
+#define        IRQ_IFCP_2      (1L<<17)        /* Bit 17:      IRQ_IFCP_2/IRQ_MAC_2 */
+#define        IRQ_IFCP_1      (1L<<16)        /* Bit 16:      IRQ_IFCP_1/IRQ_MAC_1 */
+/* Receive Queue 1 */
+#define        IRQ_R1_P        (1L<<15)        /* Bit 15:      Parity Error (q1) */
+#define        IRQ_R1_B        (1L<<14)        /* Bit 14:      End of Buffer (q1) */
+#define        IRQ_R1_F        (1L<<13)        /* Bit 13:      End of Frame (q1) */
+#define        IRQ_R1_C        (1L<<12)        /* Bit 12:      Encoding Error (q1) */
+/* Receive Queue 2 */
+#define        IRQ_R2_P        (1L<<11)        /* Bit 11: (DV) Parity Error (q2) */
+#define        IRQ_R2_B        (1L<<10)        /* Bit 10: (DV) End of Buffer (q2) */
+#define        IRQ_R2_F        (1L<<9)         /* Bit  9: (DV) End of Frame (q2) */
+#define        IRQ_R2_C        (1L<<8)         /* Bit  8: (DV) Encoding Error (q2) */
+/* Asynchronous Transmit queue */
+                                       /* Bit  7:      reserved */
+#define        IRQ_XA_B        (1L<<6)         /* Bit  6:      End of Buffer (xa) */
+#define        IRQ_XA_F        (1L<<5)         /* Bit  5:      End of Frame (xa) */
+#define        IRQ_XA_C        (1L<<4)         /* Bit  4:      Encoding Error (xa) */
+/* Synchronous Transmit queue */
+                                       /* Bit  3:      reserved */
+#define        IRQ_XS_B        (1L<<2)         /* Bit  2:      End of Buffer (xs) */
+#define        IRQ_XS_F        (1L<<1)         /* Bit  1:      End of Frame (xs) */
+#define        IRQ_XS_C        (1L<<0)         /* Bit  0:      Encoding Error (xs) */
+
+/* 0x0010 - 0x006b:    formac+ (supernet_3) fequently used registers */
+/*     B0_R1_CSR       32 bit BMU control/status reg (rec q 1 ) */
+/*     B0_R2_CSR       32 bit BMU control/status reg (rec q 2 ) */
+/*     B0_XA_CSR       32 bit BMU control/status reg (a xmit q ) */
+/*     B0_XS_CSR       32 bit BMU control/status reg (s xmit q ) */
+/* The registers are the same as B4_R1_CSR, B4_R2_CSR, B5_Xa_CSR, B5_XS_CSR */
+
+/*     B2_MAC_0        8 bit MAC address Byte 0 */
+/*     B2_MAC_1        8 bit MAC address Byte 1 */
+/*     B2_MAC_2        8 bit MAC address Byte 2 */
+/*     B2_MAC_3        8 bit MAC address Byte 3 */
+/*     B2_MAC_4        8 bit MAC address Byte 4 */
+/*     B2_MAC_5        8 bit MAC address Byte 5 */
+/*     B2_MAC_6        8 bit MAC address Byte 6 (== 0) (DV) */
+/*     B2_MAC_7        8 bit MAC address Byte 7 (== 0) (DV) */
+
+/*     B2_CONN_TYP     8 bit Connector type */
+/*     B2_PMD_TYP      8 bit PMD type */
+/*     Values of connector and PMD type comply to SysKonnect internal std */
+
+/*     The EPROM register are currently of no use */
+/*     B2_E_0          8 bit EPROM Byte 0 */
+/*     B2_E_1          8 bit EPROM Byte 1 */
+/*     B2_E_2          8 bit EPROM Byte 2 */
+/*     B2_E_3          8 bit EPROM Byte 3 */
+
+/*     B2_FAR          32 bit Flash-Prom Address Register/Counter */
+#define        FAR_ADDR        0x1ffffL        /* Bit 16..0:   FPROM Address mask */
+
+/*     B2_FDP          8 bit Flash-Prom Data Port */
+
+/*     B2_LD_CRTL      8 bit loader control */
+/*     Bits are currently reserved */
+
+/*     B2_LD_TEST      8 bit loader test */
+#define        LD_T_ON         (1<<3)  /* Bit 3:    Loader Testmode on */
+#define        LD_T_OFF        (1<<2)  /* Bit 2:    Loader Testmode off */
+#define        LD_T_STEP       (1<<1)  /* Bit 1:    Decrement FPROM addr. Counter */
+#define        LD_START        (1<<0)  /* Bit 0:    Start loading FPROM */
+
+/*     B2_TI_INI       32 bit Timer init value */
+/*     B2_TI_VAL       32 bit Timer value */
+/*     B2_TI_CRTL      8 bit Timer control */
+/*     B2_TI_TEST      8 Bit Timer Test */
+/*     B2_WDOG_INI     32 bit Watchdog init value */
+/*     B2_WDOG_VAL     32 bit Watchdog value */
+/*     B2_WDOG_CRTL    8 bit Watchdog control */
+/*     B2_WDOG_TEST    8 Bit Watchdog Test */
+/*     B2_RTM_INI      32 bit RTM init value */
+/*     B2_RTM_VAL      32 bit RTM value */
+/*     B2_RTM_CRTL     8 bit RTM control */
+/*     B2_RTM_TEST     8 Bit RTM Test */
+/*     B2_<TIM>_CRTL   8 bit <TIM> control */
+/*     B2_IRQ_MOD_INI  32 bit IRQ Moderation Timer Init Reg.   (ML) */
+/*     B2_IRQ_MOD_VAL  32 bit IRQ Moderation Timer Value       (ML) */
+/*     B2_IRQ_MOD_CTRL 8 bit IRQ Moderation Timer Control      (ML) */
+/*     B2_IRQ_MOD_TEST 8 bit IRQ Moderation Timer Test         (ML) */
+#define GET_TOK_CT     (1<<4)  /* Bit 4: Get the Token Counter (RTM) */
+#define TIM_RES_TOK    (1<<3)  /* Bit 3: RTM Status: 1 == restricted */
+#define TIM_ALARM      (1<<3)  /* Bit 3: Timer Alarm (WDOG) */
+#define TIM_START      (1<<2)  /* Bit 2: Start Timer (TI,WDOG,RTM,IRQ_MOD)*/
+#define TIM_STOP       (1<<1)  /* Bit 1: Stop Timer (TI,WDOG,RTM,IRQ_MOD) */
+#define TIM_CL_IRQ     (1<<0)  /* Bit 0: Clear Timer IRQ (TI,WDOG,RTM) */
+/*     B2_<TIM>_TEST   8 Bit <TIM> Test */
+#define        TIM_T_ON        (1<<2)  /* Bit 2: Test mode on (TI,WDOG,RTM,IRQ_MOD) */
+#define        TIM_T_OFF       (1<<1)  /* Bit 1: Test mode off (TI,WDOG,RTM,IRQ_MOD) */
+#define        TIM_T_STEP      (1<<0)  /* Bit 0: Test step (TI,WDOG,RTM,IRQ_MOD) */
+
+/*     B2_TOK_COUNT    0x014c  (ML)    32 bit  Token Counter */
+/*     B2_DESC_ADDR_H  0x0150  (ML)    32 bit  Desciptor Base Addr Reg High */
+/*     B2_CTRL_2       0x0154  (ML)     8 bit  Control Register 2 */
+                               /* Bit 7..5:    reserved                */
+#define CTRL_CL_I2C_IRQ (1<<4) /* Bit 4:       Clear I2C IRQ           */
+#define CTRL_ST_SW_IRQ (1<<3)  /* Bit 3:       Set IRQ SW Request      */
+#define CTRL_CL_SW_IRQ (1<<2)  /* Bit 2:       Clear IRQ SW Request    */
+#define CTRL_STOP_DONE (1<<1)  /* Bit 1:       Stop Master is finished */
+#define        CTRL_STOP_MAST  (1<<0)  /* Bit 0:       Command Bit to stop the master*/
+
+/*     B2_IFACE_REG    0x0155  (ML)     8 bit  Interface Register */
+                               /* Bit 7..3:    reserved                */
+#define        IF_I2C_DATA_DIR (1<<2)  /* Bit 2:       direction of IF_I2C_DATA*/
+#define IF_I2C_DATA    (1<<1)  /* Bit 1:       I2C Data Port           */
+#define        IF_I2C_CLK      (1<<0)  /* Bit 0:       I2C Clock Port          */
+
+                               /* 0x0156:              reserved */
+/*     B2_TST_CTRL_2   0x0157  (ML)     8 bit  Test Control Register 2 */
+                                       /* Bit 7..4:    reserved */
+                                       /* force the following error on */
+                                       /* the next master read/write   */
+#define TST_FRC_DPERR_MR64     (1<<3)  /* Bit 3:       DataPERR RD 64  */
+#define TST_FRC_DPERR_MW64     (1<<2)  /* Bit 2:       DataPERR WR 64  */
+#define TST_FRC_APERR_1M64     (1<<1)  /* Bit 1:       AddrPERR on 1. phase */
+#define TST_FRC_APERR_2M64     (1<<0)  /* Bit 0:       AddrPERR on 2. phase */
+
+/*     B2_I2C_CTRL     0x0158  (ML)    32 bit  I2C Control Register           */
+#define        I2C_FLAG        (1L<<31)        /* Bit 31:      Start read/write if WR */
+#define I2C_ADDR       (0x7fffL<<16)   /* Bit 30..16:  Addr to be read/written*/
+#define        I2C_DEV_SEL     (0x7fL<<9)      /* Bit  9..15:  I2C Device Select      */
+                                       /* Bit  5.. 8:  reserved               */
+#define I2C_BURST_LEN  (1L<<4)         /* Bit  4       Burst Len, 1/4 bytes   */
+#define I2C_DEV_SIZE   (7L<<1)         /* Bit  1.. 3:  I2C Device Size        */
+#define I2C_025K_DEV   (0L<<1)         /*              0: 256 Bytes or smaller*/
+#define I2C_05K_DEV    (1L<<1)         /*              1: 512  Bytes          */
+#define        I2C_1K_DEV      (2L<<1)         /*              2: 1024 Bytes          */
+#define I2C_2K_DEV     (3L<<1)         /*              3: 2048 Bytes          */
+#define        I2C_4K_DEV      (4L<<1)         /*              4: 4096 Bytes          */
+#define        I2C_8K_DEV      (5L<<1)         /*              5: 8192 Bytes          */
+#define        I2C_16K_DEV     (6L<<1)         /*              6: 16384 Bytes         */
+#define        I2C_32K_DEV     (7L<<1)         /*              7: 32768 Bytes         */
+#define I2C_STOP_BIT   (1<<0)          /* Bit  0:      Interrupt I2C transfer */
+
+/*
+ * I2C Addresses
+ *
+ * The temperature sensor and the voltage sensor are on the same I2C bus.
+ * Note: The voltage sensor (Micorwire) will be selected by PCI_EXT_PATCH_1
+ *      in PCI_OUR_REG 1.
+ */
+#define        I2C_ADDR_TEMP   0x90    /* I2C Address Temperature Sensor */
+
+/*     B2_I2C_DATA     0x015c  (ML)    32 bit  I2C Data Register */
+
+/*     B4_R1_D         4*32 bit current receive Descriptor     (q1) */
+/*     B4_R1_DA        32 bit current rec desc address         (q1) */
+/*     B4_R1_AC        32 bit current receive Address Count    (q1) */
+/*     B4_R1_BC        32 bit current receive Byte Counter     (q1) */
+/*     B4_R1_CSR       32 bit BMU Control/Status Register      (q1) */
+/*     B4_R1_F         32 bit flag register                    (q1) */
+/*     B4_R1_T1        32 bit Test Register 1                  (q1) */
+/*     B4_R1_T2        32 bit Test Register 2                  (q1) */
+/*     B4_R1_T3        32 bit Test Register 3                  (q1) */
+/*     B4_R2_D         4*32 bit current receive Descriptor     (q2) */
+/*     B4_R2_DA        32 bit current rec desc address         (q2) */
+/*     B4_R2_AC        32 bit current receive Address Count    (q2) */
+/*     B4_R2_BC        32 bit current receive Byte Counter     (q2) */
+/*     B4_R2_CSR       32 bit BMU Control/Status Register      (q2) */
+/*     B4_R2_F         32 bit flag register                    (q2) */
+/*     B4_R2_T1        32 bit Test Register 1                  (q2) */
+/*     B4_R2_T2        32 bit Test Register 2                  (q2) */
+/*     B4_R2_T3        32 bit Test Register 3                  (q2) */
+/*     B5_XA_D         4*32 bit current receive Descriptor     (xa) */
+/*     B5_XA_DA        32 bit current rec desc address         (xa) */
+/*     B5_XA_AC        32 bit current receive Address Count    (xa) */
+/*     B5_XA_BC        32 bit current receive Byte Counter     (xa) */
+/*     B5_XA_CSR       32 bit BMU Control/Status Register      (xa) */
+/*     B5_XA_F         32 bit flag register                    (xa) */
+/*     B5_XA_T1        32 bit Test Register 1                  (xa) */
+/*     B5_XA_T2        32 bit Test Register 2                  (xa) */
+/*     B5_XA_T3        32 bit Test Register 3                  (xa) */
+/*     B5_XS_D         4*32 bit current receive Descriptor     (xs) */
+/*     B5_XS_DA        32 bit current rec desc address         (xs) */
+/*     B5_XS_AC        32 bit current receive Address Count    (xs) */
+/*     B5_XS_BC        32 bit current receive Byte Counter     (xs) */
+/*     B5_XS_CSR       32 bit BMU Control/Status Register      (xs) */
+/*     B5_XS_F         32 bit flag register                    (xs) */
+/*     B5_XS_T1        32 bit Test Register 1                  (xs) */
+/*     B5_XS_T2        32 bit Test Register 2                  (xs) */
+/*     B5_XS_T3        32 bit Test Register 3                  (xs) */
+/*     B5_<xx>_CSR     32 bit BMU Control/Status Register      (xx) */
+#define        CSR_DESC_CLEAR  (1L<<21)    /* Bit 21:  Clear Reset for Descr */
+#define        CSR_DESC_SET    (1L<<20)    /* Bit 20:  Set Reset for Descr */
+#define        CSR_FIFO_CLEAR  (1L<<19)    /* Bit 19:  Clear Reset for FIFO */
+#define        CSR_FIFO_SET    (1L<<18)    /* Bit 18:  Set Reset for FIFO */
+#define        CSR_HPI_RUN     (1L<<17)    /* Bit 17:  Release HPI SM */
+#define        CSR_HPI_RST     (1L<<16)    /* Bit 16:  Reset HPI SM to Idle */
+#define        CSR_SV_RUN      (1L<<15)    /* Bit 15:  Release Supervisor SM */
+#define        CSR_SV_RST      (1L<<14)    /* Bit 14:  Reset Supervisor SM */
+#define        CSR_DREAD_RUN   (1L<<13)    /* Bit 13:  Release Descr Read SM */
+#define        CSR_DREAD_RST   (1L<<12)    /* Bit 12:  Reset Descr Read SM */
+#define        CSR_DWRITE_RUN  (1L<<11)    /* Bit 11:  Rel. Descr Write SM */
+#define        CSR_DWRITE_RST  (1L<<10)    /* Bit 10:  Reset Descr Write SM */
+#define        CSR_TRANS_RUN   (1L<<9)     /* Bit 9:   Release Transfer SM */
+#define        CSR_TRANS_RST   (1L<<8)     /* Bit 8:   Reset Transfer SM */
+                                   /* Bit 7..5: reserved */
+#define        CSR_START       (1L<<4)     /* Bit 4:   Start Rec/Xmit Queue */
+#define        CSR_IRQ_CL_P    (1L<<3)     /* Bit 3:   Clear Parity IRQ, Rcv */
+#define        CSR_IRQ_CL_B    (1L<<2)     /* Bit 2:   Clear EOB IRQ */
+#define        CSR_IRQ_CL_F    (1L<<1)     /* Bit 1:   Clear EOF IRQ */
+#define        CSR_IRQ_CL_C    (1L<<0)     /* Bit 0:   Clear ERR IRQ */
+
+#define CSR_SET_RESET  (CSR_DESC_SET|CSR_FIFO_SET|CSR_HPI_RST|CSR_SV_RST|\
+                       CSR_DREAD_RST|CSR_DWRITE_RST|CSR_TRANS_RST)
+#define CSR_CLR_RESET  (CSR_DESC_CLEAR|CSR_FIFO_CLEAR|CSR_HPI_RUN|CSR_SV_RUN|\
+                       CSR_DREAD_RUN|CSR_DWRITE_RUN|CSR_TRANS_RUN)
+
+
+/*     B5_<xx>_F       32 bit flag register             (xx) */
+                                       /* Bit 28..31:  reserved              */
+#define F_ALM_FULL     (1L<<27)        /* Bit 27: (ML) FIFO almost full      */
+#define F_FIFO_EOF     (1L<<26)        /* Bit 26: (ML) Fag bit in FIFO       */
+#define F_WM_REACHED   (1L<<25)        /* Bit 25: (ML) Watermark reached     */
+#define F_UP_DW_USED   (1L<<24)        /* Bit 24: (ML) Upper Dword used (bug)*/
+                                       /* Bit 23:      reserved              */
+#define F_FIFO_LEVEL   (0x1fL<<16)     /* Bit 16..22:(ML) # of Qwords in FIFO*/
+                                       /* Bit  8..15:  reserved              */
+#define F_ML_WATER_M   0x0000ffL       /* Bit  0.. 7:(ML) Watermark          */
+#define        FLAG_WATER      0x00001fL       /* Bit 4..0:(DV) Level of req data tr.*/
+
+/*     B5_<xx>_T1      32 bit Test Register 1           (xx) */
+/*             Holds four State Machine control Bytes */
+#define        SM_CRTL_SV      (0xffL<<24) /* Bit 31..24:  Control Supervisor SM */
+#define        SM_CRTL_RD      (0xffL<<16) /* Bit 23..16:  Control Read Desc SM */
+#define        SM_CRTL_WR      (0xffL<<8)  /* Bit 15..8:   Control Write Desc SM */
+#define        SM_CRTL_TR      (0xffL<<0)  /* Bit 7..0:    Control Transfer SM */
+
+/*     B4_<xx>_T1_TR   8 bit Test Register 1 TR                (xx) */
+/*     B4_<xx>_T1_WR   8 bit Test Register 1 WR                (xx) */
+/*     B4_<xx>_T1_RD   8 bit Test Register 1 RD                (xx) */
+/*     B4_<xx>_T1_SV   8 bit Test Register 1 SV                (xx) */
+/* The control status byte of each machine looks like ... */
+#define        SM_STATE        0xf0    /* Bit 7..4:    State which shall be loaded */
+#define        SM_LOAD         0x08    /* Bit 3:       Load the SM with SM_STATE */
+#define        SM_TEST_ON      0x04    /* Bit 2:       Switch on SM Test Mode */
+#define        SM_TEST_OFF     0x02    /* Bit 1:       Go off the Test Mode */
+#define        SM_STEP         0x01    /* Bit 0:       Step the State Machine */
+
+/* The coding of the states */
+#define        SM_SV_IDLE      0x0     /* Supervisor   Idle            Tr/Re        */
+#define        SM_SV_RES_START 0x1     /* Supervisor   Res_Start       Tr/Re        */
+#define        SM_SV_GET_DESC  0x3     /* Supervisor   Get_Desc        Tr/Re        */
+#define        SM_SV_CHECK     0x2     /* Supervisor   Check           Tr/Re        */
+#define        SM_SV_MOV_DATA  0x6     /* Supervisor   Move_Data       Tr/Re        */
+#define        SM_SV_PUT_DESC  0x7     /* Supervisor   Put_Desc        Tr/Re        */
+#define        SM_SV_SET_IRQ   0x5     /* Supervisor   Set_Irq         Tr/Re        */
+
+#define        SM_RD_IDLE      0x0     /* Read Desc.   Idle            Tr/Re        */
+#define        SM_RD_LOAD      0x1     /* Read Desc.   Load            Tr/Re        */
+#define        SM_RD_WAIT_TC   0x3     /* Read Desc.   Wait_TC         Tr/Re        */
+#define        SM_RD_RST_EOF   0x6     /* Read Desc.   Reset_EOF          Re        */
+#define        SM_RD_WDONE_R   0x2     /* Read Desc.   Wait_Done          Re        */
+#define        SM_RD_WDONE_T   0x4     /* Read Desc.   Wait_Done       Tr           */
+
+#define        SM_TR_IDLE      0x0     /* Trans. Data  Idle            Tr/Re        */
+#define        SM_TR_LOAD      0x3     /* Trans. Data  Load            Tr/Re        */
+#define        SM_TR_LOAD_R_ML 0x1     /* Trans. Data  Load              /Re   (ML) */
+#define        SM_TR_WAIT_TC   0x2     /* Trans. Data  Wait_TC         Tr/Re        */
+#define        SM_TR_WDONE     0x4     /* Trans. Data  Wait_Done       Tr/Re        */
+
+#define        SM_WR_IDLE      0x0     /* Write Desc.  Idle            Tr/Re        */
+#define        SM_WR_ABLEN     0x1     /* Write Desc.  Act_Buf_Length  Tr/Re        */
+#define        SM_WR_LD_A4     0x2     /* Write Desc.  Load_A4            Re        */
+#define        SM_WR_RES_OWN   0x2     /* Write Desc.  Res_OWN         Tr           */
+#define        SM_WR_WAIT_EOF  0x3     /* Write Desc.  Wait_EOF           Re        */
+#define        SM_WR_LD_N2C_R  0x4     /* Write Desc.  Load_N2C           Re        */
+#define        SM_WR_WAIT_TC_R 0x5     /* Write Desc.  Wait_TC            Re        */
+#define        SM_WR_WAIT_TC4  0x6     /* Write Desc.  Wait_TC4           Re        */
+#define        SM_WR_LD_A_T    0x6     /* Write Desc.  Load_A          Tr           */
+#define        SM_WR_LD_A_R    0x7     /* Write Desc.  Load_A             Re        */
+#define        SM_WR_WAIT_TC_T 0x7     /* Write Desc.  Wait_TC         Tr           */
+#define        SM_WR_LD_N2C_T  0xc     /* Write Desc.  Load_N2C        Tr           */
+#define        SM_WR_WDONE_T   0x9     /* Write Desc.  Wait_Done       Tr           */
+#define        SM_WR_WDONE_R   0xc     /* Write Desc.  Wait_Done          Re        */
+#define SM_WR_LD_D_AD  0xe     /* Write Desc.  Load_Dumr_A        Re   (ML) */
+#define SM_WR_WAIT_D_TC        0xf     /* Write Desc.  Wait_Dumr_TC       Re   (ML) */
+
+/*     B5_<xx>_T2      32 bit Test Register 2           (xx) */
+/* Note: This register is only defined for the transmit queues */
+                               /* Bit 31..8:   reserved */
+#define        AC_TEST_ON      (1<<7)  /* Bit 7:       Address Counter Test Mode on */
+#define        AC_TEST_OFF     (1<<6)  /* Bit 6:       Address Counter Test Mode off*/
+#define        BC_TEST_ON      (1<<5)  /* Bit 5:       Byte Counter Test Mode on */
+#define        BC_TEST_OFF     (1<<4)  /* Bit 4:       Byte Counter Test Mode off */
+#define        TEST_STEP04     (1<<3)  /* Bit 3:       Inc AC/Dec BC by 4 */
+#define        TEST_STEP03     (1<<2)  /* Bit 2:       Inc AC/Dec BC by 3 */
+#define        TEST_STEP02     (1<<1)  /* Bit 1:       Inc AC/Dec BC by 2 */
+#define        TEST_STEP01     (1<<0)  /* Bit 0:       Inc AC/Dec BC by 1 */
+
+/*     B5_<xx>_T3      32 bit Test Register 3           (xx) */
+/* Note: This register is only defined for the transmit queues */
+                               /* Bit 31..8:   reserved */
+#define T3_MUX_2       (1<<7)  /* Bit 7: (ML)  Mux position MSB */
+#define T3_VRAM_2      (1<<6)  /* Bit 6: (ML)  Virtual RAM buffer addr MSB */
+#define        T3_LOOP         (1<<5)  /* Bit 5:       Set Loopback (Xmit) */
+#define        T3_UNLOOP       (1<<4)  /* Bit 4:       Unset Loopback (Xmit) */
+#define        T3_MUX          (3<<2)  /* Bit 3..2:    Mux position */
+#define        T3_VRAM         (3<<0)  /* Bit 1..0:    Virtual RAM buffer Address */
+
+/* PCI card IDs */
+/*
+ * Note: The following 4 byte definitions shall not be used! Use OEM Concept!
+ */
+#define        PCI_VEND_ID0    0x48            /* PCI vendor ID (SysKonnect) */
+#define        PCI_VEND_ID1    0x11            /* PCI vendor ID (SysKonnect) */
+                                       /*               (High byte) */
+#define        PCI_DEV_ID0     0x00            /* PCI device ID */
+#define        PCI_DEV_ID1     0x40            /* PCI device ID (High byte) */
+
+/*#define PCI_CLASS    0x02*/          /* PCI class code: network device */
+#define PCI_NW_CLASS   0x02            /* PCI class code: network device */
+#define PCI_SUB_CLASS  0x02            /* PCI subclass ID: FDDI device */
+#define PCI_PROG_INTFC 0x00            /* PCI programming Interface (=0) */
+
+/*
+ * address transmission from logical to physical offset address on board
+ */
+#define        FMA(a)  (0x0400|((a)<<2))       /* FORMAC+ (r/w) (SN3) */
+#define        P1(a)   (0x0380|((a)<<2))       /* PLC1 (r/w) (DAS) */
+#define        P2(a)   (0x0600|((a)<<2))       /* PLC2 (r/w) (covered by the SN3) */
+#define PRA(a) (B2_MAC_0 + (a))        /* configuration PROM (MAC address) */
+
+/*
+ * FlashProm specification
+ */
+#define        MAX_PAGES       0x20000L        /* Every byte has a single page */
+#define        MAX_FADDR       1               /* 1 byte per page */
+
+/*
+ * Receive / Transmit Buffer Control word
+ */
+#define        BMU_OWN         (1UL<<31)       /* OWN bit: 0 == host, 1 == adapter */
+#define        BMU_STF         (1L<<30)        /* Start of Frame ?             */
+#define        BMU_EOF         (1L<<29)        /* End of Frame ?               */
+#define        BMU_EN_IRQ_EOB  (1L<<28)        /* Enable "End of Buffer" IRQ   */
+#define        BMU_EN_IRQ_EOF  (1L<<27)        /* Enable "End of Frame" IRQ    */
+#define        BMU_DEV_0       (1L<<26)        /* RX: don't transfer to system mem */
+#define BMU_SMT_TX     (1L<<25)        /* TX: if set, buffer type SMT_MBuf */
+#define BMU_ST_BUF     (1L<<25)        /* RX: copy of start of frame */
+#define BMU_UNUSED     (1L<<24)        /* Set if the Descr is curr unused */
+#define BMU_SW         (3L<<24)        /* 2 Bits reserved for SW usage */
+#define        BMU_CHECK       0x00550000L     /* To identify the control word */
+#define        BMU_BBC         0x0000FFFFL     /* R/T Buffer Byte Count        */
+
+/*
+ * physical address offset + IO-Port base address
+ */
+#ifdef MEM_MAPPED_IO
+#define        ADDR(a)         (char far *) smc->hw.iop+(a)
+#define        ADDRS(smc,a)    (char far *) (smc)->hw.iop+(a)
+#else
+#define        ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), \
+       (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0)))) : \
+       (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
+#define        ADDRS(smc,a) (((a)>>7) ? (outp((smc)->hw.iop+B0_RAP,(a)>>7), \
+       ((smc)->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0)))) : \
+       ((smc)->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
+#endif
+
+/*
+ * Define a macro to access the configuration space
+ */
+#define PCI_C(a)       ADDR(B3_CFG_SPC + (a))  /* PCI Config Space */
+
+#define EXT_R(a)       ADDR(B6_EXT_REG + (a))  /* External Registers */
+
+/*
+ * Define some values needed for the MAC address (PROM)
+ */
+#define        SA_MAC          (0)     /* start addr. MAC_AD within the PROM */
+#define        PRA_OFF         (0)     /* offset correction when 4th byte reading */
+
+#define        SKFDDI_PSZ      8       /* address PROM size */
+
+#define        FM_A(a) ADDR(FMA(a))    /* FORMAC Plus physical addr */
+#define        P1_A(a) ADDR(P1(a))     /* PLC1 (r/w) */
+#define        P2_A(a) ADDR(P2(a))     /* PLC2 (r/w) (DAS) */
+#define PR_A(a)        ADDR(PRA(a))    /* config. PROM (MAC address) */
+
+/*
+ * Macro to read the PROM
+ */
+#define        READ_PROM(a)    ((u_char)inp(a))
+
+#define        GET_PAGE(bank)  outpd(ADDR(B2_FAR),bank)
+#define        VPP_ON()
+#define        VPP_OFF()
+
+/*
+ * Note: Values of the Interrupt Source Register are defined above
+ */
+#define ISR_A          ADDR(B0_ISRC)
+#define        GET_ISR()               inpd(ISR_A)
+#define GET_ISR_SMP(iop)       inpd((iop)+B0_ISRC)
+#define        CHECK_ISR()             (inpd(ISR_A) & inpd(ADDR(B0_IMSK)))
+#define CHECK_ISR_SMP(iop)     (inpd((iop)+B0_ISRC) & inpd((iop)+B0_IMSK))
+
+#define        BUS_CHECK()
+
+/*
+ * CLI_FBI:    Disable Board Interrupts
+ * STI_FBI:    Enable Board Interrupts
+ */
+#ifndef UNIX
+#define        CLI_FBI()       outpd(ADDR(B0_IMSK),0)
+#else
+#define        CLI_FBI(smc)    outpd(ADDRS((smc),B0_IMSK),0)
+#endif
+
+#ifndef UNIX
+#define        STI_FBI()       outpd(ADDR(B0_IMSK),smc->hw.is_imask)
+#else
+#define        STI_FBI(smc)    outpd(ADDRS((smc),B0_IMSK),(smc)->hw.is_imask)
+#endif
+
+#define CLI_FBI_SMP(iop)       outpd((iop)+B0_IMSK,0)
+#define        STI_FBI_SMP(smc,iop)    outpd((iop)+B0_IMSK,(smc)->hw.is_imask)
+
+#endif /* PCI */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * 12 bit transfer (dword) counter:
+ *     (ISA:   2*trc = number of byte)
+ *     (EISA:  4*trc = number of byte)
+ *     (MCA:   4*trc = number of byte)
+ */
+#define        MAX_TRANS       (0x0fff)
+
+/*
+ * PC PIC
+ */
+#define        MST_8259 (0x20)
+#define        SLV_8259 (0xA0)
+
+#define TPS            (18)            /* ticks per second */
+
+/*
+ * error timer defs
+ */
+#define        TN              (4)     /* number of supported timer = TN+1 */
+#define        SNPPND_TIME     (5)     /* buffer memory access over mem. data reg. */
+
+#define        MAC_AD  0x405a0000
+
+#define MODR1  FM_A(FM_MDREG1) /* mode register 1 */
+#define MODR2  FM_A(FM_MDREG2) /* mode register 2 */
+
+#define CMDR1  FM_A(FM_CMDREG1)        /* command register 1 */
+#define CMDR2  FM_A(FM_CMDREG2)        /* command register 2 */
+
+
+/*
+ * function defines
+ */
+#define        CLEAR(io,mask)          outpw((io),inpw(io)&(~(mask)))
+#define        SET(io,mask)            outpw((io),inpw(io)|(mask))
+#define        GET(io,mask)            (inpw(io)&(mask))
+#define        SETMASK(io,val,mask)    outpw((io),(inpw(io) & ~(mask)) | (val))
+
+/*
+ * PHY Port A (PA) = PLC 1
+ * With SuperNet 3 PHY-A and PHY S are identical.
+ */
+#define        PLC(np,reg)     (((np) == PA) ? P2_A(reg) : P1_A(reg))
+
+/*
+ * set memory address register for write and read
+ */
+#define        MARW(ma)        outpw(FM_A(FM_MARW),(unsigned int)(ma))
+#define        MARR(ma)        outpw(FM_A(FM_MARR),(unsigned int)(ma))
+
+/*
+ * read/write from/to memory data register
+ */
+/* write double word */
+#define        MDRW(dd)        outpw(FM_A(FM_MDRU),(unsigned int)((dd)>>16)) ;\
+                       outpw(FM_A(FM_MDRL),(unsigned int)(dd))
+
+#ifndef WINNT
+/* read double word */
+#define        MDRR()          (((long)inpw(FM_A(FM_MDRU))<<16) + inpw(FM_A(FM_MDRL)))
+
+/* read FORMAC+ 32-bit status register */
+#define        GET_ST1()       (((long)inpw(FM_A(FM_ST1U))<<16) + inpw(FM_A(FM_ST1L)))
+#define        GET_ST2()       (((long)inpw(FM_A(FM_ST2U))<<16) + inpw(FM_A(FM_ST2L)))
+#ifdef SUPERNET_3
+#define        GET_ST3()       (((long)inpw(FM_A(FM_ST3U))<<16) + inpw(FM_A(FM_ST3L)))
+#endif
+#else
+/* read double word */
+#define MDRR()         inp2w((FM_A(FM_MDRU)),(FM_A(FM_MDRL)))
+
+/* read FORMAC+ 32-bit status register */
+#define GET_ST1()      inp2w((FM_A(FM_ST1U)),(FM_A(FM_ST1L)))
+#define GET_ST2()      inp2w((FM_A(FM_ST2U)),(FM_A(FM_ST2L)))
+#ifdef SUPERNET_3
+#define GET_ST3()      inp2w((FM_A(FM_ST3U)),(FM_A(FM_ST3L)))
+#endif
+#endif
+
+/* Special timer macro for 82c54 */
+                               /* timer access over data bus bit 8..15 */
+#define        OUT_82c54_TIMER(port,val)       outpw(TI_A(port),(val)<<8)
+#define        IN_82c54_TIMER(port)            ((inpw(TI_A(port))>>8) & 0xff)
+
+
+#ifdef DEBUG
+#define        DB_MAC(mac,st) {if (debug_mac & 0x1)\
+                               printf("M") ;\
+                       if (debug_mac & 0x2)\
+                               printf("\tMAC %d status 0x%08lx\n",mac,st) ;\
+                       if (debug_mac & 0x4)\
+                               dp_mac(mac,st) ;\
+}
+
+#define        DB_PLC(p,iev) { if (debug_plc & 0x1)\
+                               printf("P") ;\
+                       if (debug_plc & 0x2)\
+                               printf("\tPLC %s Int 0x%04x\n", \
+                                       (p == PA) ? "A" : "B", iev) ;\
+                       if (debug_plc & 0x4)\
+                               dp_plc(p,iev) ;\
+}
+
+#define        DB_TIMER() {    if (debug_timer & 0x1)\
+                               printf("T") ;\
+                       if (debug_timer & 0x2)\
+                               printf("\tTimer ISR\n") ;\
+}
+
+#else  /* no DEBUG */
+
+#define        DB_MAC(mac,st)
+#define        DB_PLC(p,iev)
+#define        DB_TIMER()
+
+#endif /* no DEBUG */
+
+#define        INC_PTR(sp,cp,ep)       if (++cp == ep) cp = sp
+/*
+ * timer defs
+ */
+#define        COUNT(t)        ((t)<<6)        /* counter */
+#define        RW_OP(o)        ((o)<<4)        /* read/write operation */
+#define        TMODE(m)        ((m)<<1)        /* timer mode */
+
+#endif
diff --git a/drivers/net/fddi/skfp/h/skfbiinc.h b/drivers/net/fddi/skfp/h/skfbiinc.h
new file mode 100644 (file)
index 0000000..ce72557
--- /dev/null
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _SKFBIINC_
+#define _SKFBIINC_
+
+#include "supern_2.h"
+
+/*
+ * special defines for use into .asm files
+ */
+#define ERR_FLAGS (FS_MSRABT | FS_SEAC2 | FS_SFRMERR | FS_SFRMTY1)
+
+#ifdef PCI
+#define        IMASK_FAST      (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+                        IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
+                        IS_R1_C | IS_XA_C | IS_XS_C)
+#endif
+
+#ifdef PCI
+#define        ISR_MASK        (IS_MINTR1 | IS_R1_F | IS_XS_F| IS_XA_F | IMASK_FAST)
+#else
+#define        ISR_MASK        (IS_MINTR1 | IS_MINTR2 | IMASK_FAST)
+#endif
+
+#define        FMA_FM_CMDREG1  FMA(FM_CMDREG1)
+#define        FMA_FM_CMDREG2  FMA(FM_CMDREG2)
+#define        FMA_FM_STMCHN   FMA(FM_STMCHN)
+#define        FMA_FM_RPR      FMA(FM_RPR)
+#define        FMA_FM_WPXA0    FMA(FM_WPXA0)
+#define        FMA_FM_WPXA2    FMA(FM_WPXA2)
+#define        FMA_FM_MARR     FMA(FM_MARR)
+#define        FMA_FM_MARW     FMA(FM_MARW)
+#define        FMA_FM_MDRU     FMA(FM_MDRU)
+#define        FMA_FM_MDRL     FMA(FM_MDRL)
+#define        FMA_ST1L        FMA(FM_ST1L)
+#define        FMA_ST1U        FMA(FM_ST1U)
+#define        FMA_ST2L        FMA(FM_ST2L)
+#define        FMA_ST2U        FMA(FM_ST2U)
+#ifdef SUPERNET_3
+#define FMA_ST3L       FMA(FM_ST3L)
+#define FMA_ST3U       FMA(FM_ST3U)
+#endif
+
+#define TMODE_RRQ      RQ_RRQ
+#define TMODE_WAQ2     RQ_WA2
+#define        HSRA            HSR(0)
+
+
+#define FMA_FM_ST1L    FMA_ST1L
+#define FMA_FM_ST1U    FMA_ST1U
+#define FMA_FM_ST2L    FMA_ST2L
+#define FMA_FM_ST2U    FMA_ST2U
+#ifdef SUPERNET_3
+#define FMA_FM_ST3L    FMA_ST3L
+#define FMA_FM_ST3U    FMA_ST3U
+#endif
+
+#define FMA_FM_SWPR    FMA(FM_SWPR)
+
+#define FMA_FM_RPXA0   FMA(FM_RPXA0)
+
+#define        FMA_FM_RPXS     FMA(FM_RPXS)
+#define        FMA_FM_WPXS     FMA(FM_WPXS)
+
+#define        FMA_FM_IMSK1U   FMA(FM_IMSK1U)
+#define        FMA_FM_IMSK1L   FMA(FM_IMSK1L)
+
+#define        FMA_FM_EAS      FMA(FM_EAS)
+#define        FMA_FM_EAA0     FMA(FM_EAA0)
+
+#define        TMODE_WAQ0      RQ_WA0
+#define TMODE_WSQ      RQ_WSQ
+
+/* Define default for DRV_PCM_STATE_CHANGE */
+#ifndef        DRV_PCM_STATE_CHANGE
+#define        DRV_PCM_STATE_CHANGE(smc,plc,p_state)   /* nothing */
+#endif
+
+/* Define default for DRV_RMT_INDICATION */
+#ifndef        DRV_RMT_INDICATION
+#define        DRV_RMT_INDICATION(smc,i)       /* nothing */
+#endif
+
+#endif /* n_SKFBIINC_ */
+
diff --git a/drivers/net/fddi/skfp/h/smc.h b/drivers/net/fddi/skfp/h/smc.h
new file mode 100644 (file)
index 0000000..3ca308b
--- /dev/null
@@ -0,0 +1,488 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _SCMECM_
+#define _SCMECM_
+
+#if    defined(PCI) && !defined(OSDEF)
+/*
+ * In the case of the PCI bus the file osdef1st.h must be present
+ */
+#define        OSDEF
+#endif
+
+#ifdef PCI
+#ifndef        SUPERNET_3
+#define        SUPERNET_3
+#endif
+#ifndef        TAG_MODE
+#define        TAG_MODE
+#endif
+#endif
+
+/*
+ * include all other files in required order
+ * the following files must have been included before:
+ *     types.h
+ *     fddi.h
+ */
+#ifdef OSDEF
+#include "osdef1st.h"
+#endif /* OSDEF */
+#ifdef OEM_CONCEPT
+#include "oemdef.h"
+#endif /* OEM_CONCEPT */
+#include "smt.h"
+#include "cmtdef.h"
+#include "fddimib.h"
+#include "targethw.h"          /* all target hw dependencies */
+#include "targetos.h"          /* all target os dependencies */
+#ifdef ESS
+#include "sba.h"
+#endif
+
+/*
+ * Event Queue
+ *     queue.c
+ * events are class/value pairs
+ *     class   is addressee, e.g. RMT, PCM etc.
+ *     value   is command, e.g. line state change, ring op change etc.
+ */
+struct event_queue {
+       u_short class ;                 /* event class */
+       u_short event ;                 /* event value */
+} ;
+
+/*
+ * define event queue as circular buffer
+ */
+#ifdef CONCENTRATOR
+#define MAX_EVENT      128
+#else  /* nCONCENTRATOR */
+#define MAX_EVENT      64
+#endif /* nCONCENTRATOR */
+
+struct s_queue {
+
+       struct event_queue ev_queue[MAX_EVENT];
+       struct event_queue *ev_put ;
+       struct event_queue *ev_get ;
+} ;
+
+/*
+ * ECM - Entity Coordination Management
+ * ecm.c
+ */
+struct s_ecm {
+       u_char path_test ;              /* ECM path test variable */
+       u_char sb_flag ;                /* ECM stuck bypass */
+       u_char DisconnectFlag ;         /* jd 05-Aug-1999 Bug #10419 
+                                        * ECM disconnected */
+       u_char ecm_line_state ;         /* flag to dispatcher : line states */
+       u_long trace_prop ;             /* ECM Trace_Prop flag >= 16 bits !! */
+       /* NUMPHYS note:
+        * this variable must have enough bits to hold all entiies in
+        * the station. So NUMPHYS may not be greater than 31.
+        */
+       char    ec_pad[2] ;
+       struct smt_timer ecm_timer ;    /* timer */
+} ;
+
+
+/*
+ * RMT - Ring Management
+ * rmt.c
+ */
+struct s_rmt {
+       u_char dup_addr_test ;          /* state of dupl. addr. test */
+       u_char da_flag ;                /* flag : duplicate address det. */
+       u_char loop_avail ;             /* flag : MAC available for loopback */
+       u_char sm_ma_avail ;            /* flag : MAC available for SMT */
+       u_char no_flag ;                /* flag : ring not operational */
+       u_char bn_flag ;                /* flag : MAC reached beacon state */
+       u_char jm_flag ;                /* flag : jamming in NON_OP_DUP */
+       u_char rm_join ;                /* CFM flag RM_Join */
+       u_char rm_loop ;                /* CFM flag RM_Loop */
+
+       long fast_rm_join ;             /* bit mask of active ports */
+       /*
+        * timer and flags
+        */
+       struct smt_timer rmt_timer0 ;   /* timer 0 */
+       struct smt_timer rmt_timer1 ;   /* timer 1 */
+       struct smt_timer rmt_timer2 ;   /* timer 2 */
+       u_char timer0_exp ;             /* flag : timer 0 expired */
+       u_char timer1_exp ;             /* flag : timer 1 expired */
+       u_char timer2_exp ;             /* flag : timer 2 expired */
+
+       u_char rm_pad1[1] ;
+} ;
+
+/*
+ * CFM - Configuration Management
+ * cfm.c
+ * used for SAS and DAS
+ */
+struct s_cfm {
+       u_char cf_state;                /* CFM state machine current state */
+       u_char cf_pad[3] ;
+} ;
+
+/*
+ * CEM - Configuration Element Management
+ * cem.c
+ * used for Concentrator
+ */
+#ifdef CONCENTRATOR
+struct s_cem {
+       int     ce_state ;      /* CEM state */
+       int     ce_port ;       /* PA PB PM PM+1 .. */
+       int     ce_type ;       /* TA TB TS TM */
+} ;
+
+/*
+ * linked list of CCEs in current token path
+ */
+struct s_c_ring {
+       struct s_c_ring *c_next ;
+       char            c_entity ;
+} ;
+
+struct mib_path_config {
+       u_long  fddimibPATHConfigSMTIndex;
+       u_long  fddimibPATHConfigPATHIndex;
+       u_long  fddimibPATHConfigTokenOrder;
+       u_long  fddimibPATHConfigResourceType;
+#define SNMP_RES_TYPE_MAC      2       /* Resource is a MAC */
+#define SNMP_RES_TYPE_PORT     4       /* Resource is a PORT */
+       u_long  fddimibPATHConfigResourceIndex;
+       u_long  fddimibPATHConfigCurrentPath;
+#define SNMP_PATH_ISOLATED     1       /* Current path is isolated */
+#define SNMP_PATH_LOCAL                2       /* Current path is local */
+#define SNMP_PATH_SECONDARY    3       /* Current path is secondary */
+#define SNMP_PATH_PRIMARY      4       /* Current path is primary */
+#define SNMP_PATH_CONCATENATED 5       /* Current path is concatenated */
+#define SNMP_PATH_THRU         6       /* Current path is thru */
+};
+
+
+#endif
+
+/*
+ * PCM connect states
+ */
+#define PCM_DISABLED   0
+#define PCM_CONNECTING 1
+#define PCM_STANDBY    2
+#define PCM_ACTIVE     3
+
+struct s_pcm {
+       u_char  pcm_pad[3] ;
+} ;
+
+/*
+ * PHY struct
+ * one per physical port
+ */
+struct s_phy {
+       /* Inter Module Globals */
+       struct fddi_mib_p       *mib ;
+
+       u_char np ;             /* index 0 .. NUMPHYS */
+       u_char cf_join ;
+       u_char cf_loop ;
+       u_char wc_flag ;        /* withhold connection flag */
+       u_char pc_mode ;        /* Holds the negotiated mode of the PCM */
+       u_char pc_lem_fail ;    /* flag : LCT failed */
+       u_char lc_test ;
+       u_char scrub ;          /* CFM flag Scrub -> PCM */
+       char phy_name ;
+       u_char pmd_type[2] ;    /* SK connector/transceiver type codes */
+#define PMD_SK_CONN    0       /* pmd_type[PMD_SK_CONN] = Connector */
+#define PMD_SK_PMD     1       /* pmd_type[PMD_SK_PMD] = Xver */
+       u_char pmd_scramble ;   /* scrambler on/off */
+
+       /* inner Module Globals */
+       u_char curr_ls ;        /* current line state */
+       u_char ls_flag ;
+       u_char rc_flag ;
+       u_char tc_flag ;
+       u_char td_flag ;
+       u_char bitn ;
+       u_char tr_flag ;        /* trace recvd while in active */
+       u_char twisted ;        /* flag to indicate an A-A or B-B connection */
+       u_char t_val[NUMBITS] ; /* transmit bits for signaling */
+       u_char r_val[NUMBITS] ; /* receive bits for signaling */
+       u_long t_next[NUMBITS] ;
+       struct smt_timer pcm_timer0 ;
+       struct smt_timer pcm_timer1 ;
+       struct smt_timer pcm_timer2 ;
+       u_char timer0_exp ;
+       u_char timer1_exp ;
+       u_char timer2_exp ;
+       u_char pcm_pad1[1] ;
+       int     cem_pst ;       /* CEM privae state; used for dual homing */
+       struct lem_counter lem ;
+#ifdef AMDPLC
+       struct s_plc    plc ;
+#endif
+} ;
+
+/*
+ * timer package
+ * smttimer.c
+ */
+struct s_timer {
+       struct smt_timer        *st_queue ;
+       struct smt_timer        st_fast ;
+} ;
+
+/*
+ * SRF types and data
+ */
+#define SMT_EVENT_BASE                 1
+#define SMT_EVENT_MAC_PATH_CHANGE      (SMT_EVENT_BASE+0)
+#define SMT_EVENT_MAC_NEIGHBOR_CHANGE  (SMT_EVENT_BASE+1)
+#define SMT_EVENT_PORT_PATH_CHANGE     (SMT_EVENT_BASE+2)
+#define SMT_EVENT_PORT_CONNECTION      (SMT_EVENT_BASE+3)
+
+#define SMT_IS_CONDITION(x)                    ((x)>=SMT_COND_BASE)
+
+#define SMT_COND_BASE          (SMT_EVENT_PORT_CONNECTION+1)
+#define SMT_COND_SMT_PEER_WRAP         (SMT_COND_BASE+0)
+#define SMT_COND_SMT_HOLD              (SMT_COND_BASE+1)
+#define SMT_COND_MAC_FRAME_ERROR       (SMT_COND_BASE+2)
+#define SMT_COND_MAC_DUP_ADDR          (SMT_COND_BASE+3)
+#define SMT_COND_MAC_NOT_COPIED                (SMT_COND_BASE+4)
+#define SMT_COND_PORT_EB_ERROR         (SMT_COND_BASE+5)
+#define SMT_COND_PORT_LER              (SMT_COND_BASE+6)
+
+#define SR0_WAIT       0
+#define SR1_HOLDOFF    1
+#define SR2_DISABLED   2
+
+struct s_srf {
+       u_long  SRThreshold ;                   /* threshold value */
+       u_char  RT_Flag ;                       /* report transmitted flag */
+       u_char  sr_state ;                      /* state-machine */
+       u_char  any_report ;                    /* any report required */
+       u_long  TSR ;                           /* timer */
+       u_short ring_status ;                   /* IBM ring status */
+} ;
+
+/*
+ * IBM token ring status
+ */
+#define RS_RES15       (1<<15)                 /* reserved */
+#define RS_HARDERROR   (1<<14)                 /* ring down */
+#define RS_SOFTERROR   (1<<13)                 /* sent SRF */
+#define RS_BEACON      (1<<12)                 /* transmitted beacon */
+#define RS_PATHTEST    (1<<11)                 /* path test failed */
+#define RS_SELFTEST    (1<<10)                 /* selftest required */
+#define RS_RES9                (1<< 9)                 /* reserved */
+#define RS_DISCONNECT  (1<< 8)                 /* remote disconnect */
+#define RS_RES7                (1<< 7)                 /* reserved */
+#define RS_DUPADDR     (1<< 6)                 /* duplicate address */
+#define RS_NORINGOP    (1<< 5)                 /* no ring op */
+#define RS_VERSION     (1<< 4)                 /* SMT version mismatch */
+#define RS_STUCKBYPASSS        (1<< 3)                 /* stuck bypass */
+#define RS_EVENT       (1<< 2)                 /* FDDI event occurred */
+#define RS_RINGOPCHANGE        (1<< 1)                 /* ring op changed */
+#define RS_RES0                (1<< 0)                 /* reserved */
+
+#define RS_SET(smc,bit) \
+       ring_status_indication(smc,smc->srf.ring_status |= bit)
+#define RS_CLEAR(smc,bit)      \
+       ring_status_indication(smc,smc->srf.ring_status &= ~bit)
+
+#define RS_CLEAR_EVENT (0xffff & ~(RS_NORINGOP))
+
+/* Define the AIX-event-Notification as null function if it isn't defined */
+/* in the targetos.h file */
+#ifndef AIX_EVENT
+#define AIX_EVENT(smc,opt0,opt1,opt2,opt3)     /* nothing */
+#endif
+
+struct s_srf_evc {
+       u_char  evc_code ;                      /* event code type */
+       u_char  evc_index ;                     /* index for mult. instances */
+       u_char  evc_rep_required ;              /* report required */
+       u_short evc_para ;                      /* SMT Para Number */
+       u_char  *evc_cond_state ;               /* condition state */
+       u_char  *evc_multiple ;                 /* multiple occurrence */
+} ;
+
+/*
+ * Values used by frame based services
+ * smt.c
+ */
+#define SMT_MAX_TEST           5
+#define SMT_TID_NIF            0               /* pending NIF request */
+#define SMT_TID_NIF_TEST       1               /* pending NIF test */
+#define SMT_TID_ECF_UNA                2               /* pending ECF UNA test */
+#define SMT_TID_ECF_DNA                3               /* pending ECF DNA test */
+#define SMT_TID_ECF            4               /* pending ECF test */
+
+struct smt_values {
+       u_long          smt_tvu ;               /* timer valid una */
+       u_long          smt_tvd ;               /* timer valid dna */
+       u_long          smt_tid ;               /* transaction id */
+       u_long          pend[SMT_MAX_TEST] ;    /* TID of requests */
+       u_long          uniq_time ;             /* unique time stamp */
+       u_short         uniq_ticks  ;           /* unique time stamp */
+       u_short         please_reconnect ;      /* flag : reconnect */
+       u_long          smt_last_lem ;
+       u_long          smt_last_notify ;
+       struct smt_timer        smt_timer ;     /* SMT NIF timer */
+       u_long          last_tok_time[NUMMACS]; /* token cnt emulation */
+} ;
+
+/*
+ * SMT/CMT configurable parameters
+ */
+#define SMT_DAS        0                       /* dual attach */
+#define SMT_SAS        1                       /* single attach */
+#define SMT_NAC        2                       /* null attach concentrator */
+
+struct smt_config {
+       u_char  attach_s ;              /* CFM attach to secondary path */
+       u_char  sas ;                   /* SMT_DAS/SAS/NAC */
+       u_char  build_ring_map ;        /* build ringmap if TRUE */
+       u_char  numphys ;               /* number of active phys */
+       u_char  sc_pad[1] ;
+
+       u_long  pcm_tb_min ;            /* PCM : TB_Min timer value */
+       u_long  pcm_tb_max ;            /* PCM : TB_Max timer value */
+       u_long  pcm_c_min ;             /* PCM : C_Min timer value */
+       u_long  pcm_t_out ;             /* PCM : T_Out timer value */
+       u_long  pcm_tl_min ;            /* PCM : TL_min timer value */
+       u_long  pcm_lc_short ;          /* PCM : LC_Short timer value */
+       u_long  pcm_lc_medium ;         /* PCM : LC_Medium timer value */
+       u_long  pcm_lc_long ;           /* PCM : LC_Long timer value */
+       u_long  pcm_lc_extended ;       /* PCM : LC_Extended timer value */
+       u_long  pcm_t_next_9 ;          /* PCM : T_Next[9] timer value */
+       u_long  pcm_ns_max ;            /* PCM : NS_Max timer value */
+
+       u_long  ecm_i_max ;             /* ECM : I_Max timer value */
+       u_long  ecm_in_max ;            /* ECM : IN_Max timer value */
+       u_long  ecm_td_min ;            /* ECM : TD_Min timer */
+       u_long  ecm_test_done ;         /* ECM : path test done timer */
+       u_long  ecm_check_poll ;        /* ECM : check bypass poller */
+
+       u_long  rmt_t_non_op ;          /* RMT : T_Non_OP timer value */
+       u_long  rmt_t_stuck ;           /* RMT : T_Stuck timer value */
+       u_long  rmt_t_direct ;          /* RMT : T_Direct timer value */
+       u_long  rmt_t_jam ;             /* RMT : T_Jam timer value */
+       u_long  rmt_t_announce ;        /* RMT : T_Announce timer value */
+       u_long  rmt_t_poll ;            /* RMT : claim/beacon poller */
+       u_long  rmt_dup_mac_behavior ;  /* Flag for the beavior of SMT if
+                                        * a Duplicate MAC Address was detected.
+                                        * FALSE: SMT will leave finally the ring
+                                        * TRUE:  SMT will reinstert into the ring
+                                        */
+       u_long  mac_d_max ;             /* MAC : D_Max timer value */
+
+       u_long lct_short ;              /* LCT : error threshold */
+       u_long lct_medium ;             /* LCT : error threshold */
+       u_long lct_long ;               /* LCT : error threshold */
+       u_long lct_extended ;           /* LCT : error threshold */
+} ;
+
+#ifdef DEBUG
+/*
+ * Debugging struct sometimes used in smc
+ */
+struct smt_debug {
+       int     d_smtf ;
+       int     d_smt ;
+       int     d_ecm ;
+       int     d_rmt ;
+       int     d_cfm ;
+       int     d_pcm ;
+       int     d_plc ;
+#ifdef ESS
+       int     d_ess ;
+#endif
+#ifdef SBA
+       int     d_sba ;
+#endif
+       struct  os_debug        d_os;   /* Include specific OS DEBUG struct */
+} ;
+
+#ifndef        DEBUG_BRD
+/* all boards shall be debugged with one debug struct */
+extern struct  smt_debug       debug;  /* Declaration of debug struct */
+#endif /* DEBUG_BRD */
+
+#endif /* DEBUG */
+
+/*
+ * the SMT Context Struct SMC
+ * this struct contains ALL global variables of SMT
+ */
+struct s_smc {
+       struct s_smt_os os ;            /* os specific */
+       struct s_smt_hw hw ;            /* hardware */
+
+/*
+ * NOTE: os and hw MUST BE the first two structs
+ * anything beyond hw WILL BE SET TO ZERO in smt_set_defaults()
+ */
+       struct smt_config s ;           /* smt constants */
+       struct smt_values sm ;          /* smt variables */
+       struct s_ecm    e ;             /* ecm */
+       struct s_rmt    r ;             /* rmt */
+       struct s_cfm    cf ;            /* cfm/cem */
+#ifdef CONCENTRATOR
+       struct s_cem    ce[NUMPHYS] ;   /* cem */
+       struct s_c_ring cr[NUMPHYS+NUMMACS] ;
+#endif
+       struct s_pcm    p ;             /* pcm */
+       struct s_phy    y[NUMPHYS] ;    /* phy */
+       struct s_queue  q ;             /* queue */
+       struct s_timer  t ;             /* timer */
+       struct s_srf srf ;              /* SRF */
+       struct s_srf_evc evcs[6+NUMPHYS*4] ;
+       struct fddi_mib mib ;           /* __THE_MIB__ */
+#ifdef SBA
+       struct s_sba    sba ;           /* SBA variables */
+#endif
+#ifdef ESS
+       struct s_ess    ess ;           /* Ess variables */
+#endif
+#if    defined(DEBUG) && defined(DEBUG_BRD)
+       /* If you want all single board to be debugged separately */
+       struct smt_debug        debug;  /* Declaration of debug struct */
+#endif /* DEBUG_BRD && DEBUG */
+} ;
+
+extern const struct fddi_addr fddi_broadcast;
+
+extern void all_selection_criteria(struct s_smc *smc);
+extern void card_stop(struct s_smc *smc);
+extern void init_board(struct s_smc *smc, u_char *mac_addr);
+extern int init_fplus(struct s_smc *smc);
+extern void init_plc(struct s_smc *smc);
+extern int init_smt(struct s_smc *smc, u_char * mac_addr);
+extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
+extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
+extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
+extern int pcm_status_twisted(struct s_smc *smc);
+extern void plc1_irq(struct s_smc *smc);
+extern void plc2_irq(struct s_smc *smc);
+extern void read_address(struct s_smc *smc, u_char * mac_addr);
+extern void timer_irq(struct s_smc *smc);
+
+#endif /* _SCMECM_ */
+
diff --git a/drivers/net/fddi/skfp/h/smt.h b/drivers/net/fddi/skfp/h/smt.h
new file mode 100644 (file)
index 0000000..2030f9c
--- /dev/null
@@ -0,0 +1,882 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ *     SMT 7.2 frame definitions
+ */
+
+#ifndef        _SMT_
+#define _SMT_
+
+/* #define SMT5_10 */
+#define SMT6_10
+#define SMT7_20
+
+#define        OPT_PMF         /* if parameter management is supported */
+#define        OPT_SRF         /* if status report is supported */
+
+/*
+ * SMT frame version 5.1
+ */
+
+#define SMT_VID        0x0001                  /* V 5.1 .. 6.1 */
+#define SMT_VID_2 0x0002               /* V 7.2 */
+
+struct smt_sid {
+       u_char  sid_oem[2] ;                    /* implementation spec. */
+       struct fddi_addr sid_node ;             /* node address */
+} ;
+
+typedef u_char t_station_id[8] ;
+
+/*
+ * note on alignment :
+ * sizeof(struct smt_header) = 32
+ * all parameters are long aligned
+ * if struct smt_header starts at offset 0, all longs are aligned correctly
+ * (FC starts at offset 3)
+ */
+_packed struct smt_header {
+       struct fddi_addr        smt_dest ;      /* destination address */
+       struct fddi_addr        smt_source ;    /* source address */
+       u_char                  smt_class ;     /* NIF, SIF ... */
+       u_char                  smt_type ;      /* req., response .. */
+       u_short                 smt_version ;   /* version id */
+       u_int                   smt_tid ;       /* transaction ID */
+       struct smt_sid          smt_sid ;       /* station ID */
+       u_short                 smt_pad ;       /* pad with 0 */
+       u_short                 smt_len ;       /* length of info field */
+} ;
+#define SWAP_SMTHEADER "662sl8ss"
+
+#if    0
+/*
+ * MAC FC values
+ */
+#define FC_SMT_INFO    0x41            /* SMT info */
+#define FC_SMT_NSA     0x4f            /* SMT Next Station Addressing */
+#endif
+
+
+/*
+ * type codes
+ */
+#define SMT_ANNOUNCE   0x01            /* announcement */
+#define SMT_REQUEST    0x02            /* request */
+#define SMT_REPLY      0x03            /* reply */
+
+/*
+ * class codes
+ */
+#define SMT_NIF                0x01            /* neighbor information frames */
+#define SMT_SIF_CONFIG 0x02            /* station information configuration */
+#define SMT_SIF_OPER   0x03            /* station information operation */
+#define SMT_ECF                0x04            /* echo frames */
+#define SMT_RAF                0x05            /* resource allocation */
+#define SMT_RDF                0x06            /* request denied */
+#define SMT_SRF                0x07            /* status report */
+#define SMT_PMF_GET    0x08            /* parameter management get */
+#define SMT_PMF_SET    0x09            /* parameter management set */
+#define SMT_ESF                0xff            /* extended service */
+
+#define SMT_MAX_ECHO_LEN       4458    /* max length of SMT Echo */
+#if    defined(CONC) || defined(CONC_II)
+#define SMT_TEST_ECHO_LEN      50      /* test length of SMT Echo */
+#else
+#define SMT_TEST_ECHO_LEN      SMT_MAX_ECHO_LEN        /* test length */
+#endif
+
+#define SMT_MAX_INFO_LEN       (4352-20)       /* max length for SMT info */
+
+
+/*
+ * parameter types
+ */
+
+struct smt_para {
+       u_short p_type ;                /* type */
+       u_short p_len ;                 /* length of parameter */
+} ;
+
+#define PARA_LEN       (sizeof(struct smt_para))
+
+#define SMTSETPARA(p,t)                (p)->para.p_type = (t),\
+                               (p)->para.p_len = sizeof(*(p)) - PARA_LEN
+
+/*
+ * P01 : Upstream Neighbor Address, UNA
+ */
+#define SMT_P_UNA      0x0001          /* upstream neighbor address */
+#define SWAP_SMT_P_UNA "s6"
+
+struct smt_p_una {
+       struct smt_para para ;          /* generic parameter header */
+       u_short una_pad ;
+       struct fddi_addr una_node ;     /* node address, zero if unknown */
+} ;
+
+/*
+ * P02 : Station Descriptor
+ */
+#define SMT_P_SDE      0x0002          /* station descriptor */
+#define SWAP_SMT_P_SDE "1111"
+
+#define SMT_SDE_STATION                0       /* end node */
+#define SMT_SDE_CONCENTRATOR   1       /* concentrator */
+
+struct smt_p_sde {
+       struct smt_para para ;          /* generic parameter header */
+       u_char  sde_type ;              /* station type */
+       u_char  sde_mac_count ;         /* number of MACs */
+       u_char  sde_non_master ;        /* number of A,B or S ports */
+       u_char  sde_master ;            /* number of S ports on conc. */
+} ;
+
+/*
+ * P03 : Station State
+ */
+#define SMT_P_STATE    0x0003          /* station state */
+#define SWAP_SMT_P_STATE       "scc"
+
+struct smt_p_state {
+       struct smt_para para ;          /* generic parameter header */
+       u_short st_pad ;
+       u_char  st_topology ;           /* topology */
+       u_char  st_dupl_addr ;          /* duplicate address detected */
+} ;
+#define SMT_ST_WRAPPED         (1<<0)  /* station wrapped */
+#define SMT_ST_UNATTACHED      (1<<1)  /* unattached concentrator */
+#define SMT_ST_TWISTED_A       (1<<2)  /* A-A connection, twisted ring */
+#define SMT_ST_TWISTED_B       (1<<3)  /* B-B connection, twisted ring */
+#define SMT_ST_ROOTED_S                (1<<4)  /* rooted station */
+#define SMT_ST_SRF             (1<<5)  /* SRF protocol supported */
+#define SMT_ST_SYNC_SERVICE    (1<<6)  /* use synchronous bandwidth */
+
+#define SMT_ST_MY_DUPA         (1<<0)  /* my station detected dupl. */
+#define SMT_ST_UNA_DUPA                (1<<1)  /* my UNA detected duplicate */
+
+/*
+ * P04 : timestamp
+ */
+#define SMT_P_TIMESTAMP        0x0004          /* time stamp */
+#define SWAP_SMT_P_TIMESTAMP   "8"
+struct smt_p_timestamp {
+       struct smt_para para ;          /* generic parameter header */
+       u_char  ts_time[8] ;            /* time, resolution 80nS, unique */
+} ;
+
+/*
+ * P05 : station policies
+ */
+#define SMT_P_POLICY   0x0005          /* station policies */
+#define SWAP_SMT_P_POLICY      "ss"
+
+struct smt_p_policy {
+       struct smt_para para ;          /* generic parameter header */
+       u_short pl_config ;
+       u_short pl_connect ;            /* bit string POLICY_AA ... */
+} ;
+#define SMT_PL_HOLD            1       /* hold policy supported (Dual MAC) */
+
+/*
+ * P06 : latency equivalent
+ */
+#define SMT_P_LATENCY  0x0006          /* latency */
+#define SWAP_SMT_P_LATENCY     "ssss"
+
+/*
+ * note: latency has two phy entries by definition
+ * for a SAS, the 2nd one is null
+ */
+struct smt_p_latency {
+       struct smt_para para ;          /* generic parameter header */
+       u_short lt_phyout_idx1 ;        /* index */
+       u_short lt_latency1 ;           /* latency , unit : byte clock */
+       u_short lt_phyout_idx2 ;        /* 0 if SAS */
+       u_short lt_latency2 ;           /* 0 if SAS */
+} ;
+
+/*
+ * P07 : MAC neighbors
+ */
+#define SMT_P_NEIGHBORS        0x0007          /* MAC neighbor description */
+#define SWAP_SMT_P_NEIGHBORS   "ss66"
+
+struct smt_p_neighbor {
+       struct smt_para para ;          /* generic parameter header */
+       u_short nb_mib_index ;          /* MIB index */
+       u_short nb_mac_index ;          /* n+1 .. n+m, m = #MACs, n = #PHYs */
+       struct fddi_addr nb_una ;       /* UNA , 0 for unknown */
+       struct fddi_addr nb_dna ;       /* DNA , 0 for unknown */
+} ;
+
+/*
+ * PHY record
+ */
+#define SMT_PHY_A      0               /* A port */
+#define SMT_PHY_B      1               /* B port */
+#define SMT_PHY_S      2               /* slave port */
+#define SMT_PHY_M      3               /* master port */
+
+#define SMT_CS_DISABLED        0               /* connect state : disabled */
+#define SMT_CS_CONNECTING      1       /* connect state : connecting */
+#define SMT_CS_STANDBY 2               /* connect state : stand by */
+#define SMT_CS_ACTIVE  3               /* connect state : active */
+
+#define SMT_RM_NONE    0
+#define SMT_RM_MAC     1
+
+struct smt_phy_rec {
+       u_short phy_mib_index ;         /* MIB index */
+       u_char  phy_type ;              /* A/B/S/M */
+       u_char  phy_connect_state ;     /* disabled/connecting/active */
+       u_char  phy_remote_type ;       /* A/B/S/M */
+       u_char  phy_remote_mac ;        /* none/remote */
+       u_short phy_resource_idx ;      /* 1 .. n */
+} ;
+
+/*
+ * MAC record
+ */
+struct smt_mac_rec {
+       struct fddi_addr mac_addr ;             /* MAC address */
+       u_short         mac_resource_idx ;      /* n+1 .. n+m */
+} ;
+
+/*
+ * P08 : path descriptors
+ * should be really an array ; however our environment has a fixed number of
+ * PHYs and MACs
+ */
+#define SMT_P_PATH     0x0008                  /* path descriptor */
+#define SWAP_SMT_P_PATH        "[6s]"
+
+struct smt_p_path {
+       struct smt_para para ;          /* generic parameter header */
+       struct smt_phy_rec      pd_phy[2] ;     /* PHY A */
+       struct smt_mac_rec      pd_mac ;        /* MAC record */
+} ;
+
+/*
+ * P09 : MAC status
+ */
+#define SMT_P_MAC_STATUS       0x0009          /* MAC status */
+#define SWAP_SMT_P_MAC_STATUS  "sslllllllll"
+
+struct smt_p_mac_status {
+       struct smt_para para ;          /* generic parameter header */
+       u_short st_mib_index ;          /* MIB index */
+       u_short st_mac_index ;          /* n+1 .. n+m */
+       u_int   st_t_req ;              /* T_Req */
+       u_int   st_t_neg ;              /* T_Neg */
+       u_int   st_t_max ;              /* T_Max */
+       u_int   st_tvx_value ;          /* TVX_Value */
+       u_int   st_t_min ;              /* T_Min */
+       u_int   st_sba ;                /* synchr. bandwidth alloc */
+       u_int   st_frame_ct ;           /* frame counter */
+       u_int   st_error_ct ;           /* error counter */
+       u_int   st_lost_ct ;            /* lost frames counter */
+} ;
+
+/*
+ * P0A : PHY link error rate monitoring
+ */
+#define SMT_P_LEM      0x000a          /* link error monitor */
+#define SWAP_SMT_P_LEM "ssccccll"
+/*
+ * units of lem_cutoff,lem_alarm,lem_estimate : 10**-x
+ */
+struct smt_p_lem {
+       struct smt_para para ;          /* generic parameter header */
+       u_short lem_mib_index ;         /* MIB index */
+       u_short lem_phy_index ;         /* 1 .. n */
+       u_char  lem_pad2 ;              /* be nice and make it even . */
+       u_char  lem_cutoff ;            /* 0x4 .. 0xf, default 0x7 */
+       u_char  lem_alarm ;             /* 0x4 .. 0xf, default 0x8 */
+       u_char  lem_estimate ;          /* 0x0 .. 0xff */
+       u_int   lem_reject_ct ;         /* 0x00000000 .. 0xffffffff */
+       u_int   lem_ct ;                /* 0x00000000 .. 0xffffffff */
+} ;
+
+/*
+ * P0B : MAC frame counters
+ */
+#define SMT_P_MAC_COUNTER 0x000b       /* MAC frame counters */
+#define SWAP_SMT_P_MAC_COUNTER "ssll"
+
+struct smt_p_mac_counter {
+       struct smt_para para ;          /* generic parameter header */
+       u_short mc_mib_index ;          /* MIB index */
+       u_short mc_index ;              /* mac index */
+       u_int   mc_receive_ct ;         /* receive counter */
+       u_int   mc_transmit_ct ;        /* transmit counter */
+} ;
+
+/*
+ * P0C : MAC frame not copied counter
+ */
+#define SMT_P_MAC_FNC  0x000c          /* MAC frame not copied counter */
+#define SWAP_SMT_P_MAC_FNC     "ssl"
+
+struct smt_p_mac_fnc {
+       struct smt_para para ;          /* generic parameter header */
+       u_short nc_mib_index ;          /* MIB index */
+       u_short nc_index ;              /* mac index */
+       u_int   nc_counter ;            /* not copied counter */
+} ;
+
+
+/*
+ * P0D : MAC priority values
+ */
+#define SMT_P_PRIORITY 0x000d          /* MAC priority values */
+#define SWAP_SMT_P_PRIORITY    "ssl"
+
+struct smt_p_priority {
+       struct smt_para para ;          /* generic parameter header */
+       u_short pr_mib_index ;          /* MIB index */
+       u_short pr_index ;              /* mac index */
+       u_int   pr_priority[7] ;        /* priority values */
+} ;
+
+/*
+ * P0E : PHY elasticity buffer status
+ */
+#define SMT_P_EB       0x000e          /* PHY EB status */
+#define SWAP_SMT_P_EB  "ssl"
+
+struct smt_p_eb {
+       struct smt_para para ;          /* generic parameter header */
+       u_short eb_mib_index ;          /* MIB index */
+       u_short eb_index ;              /* phy index */
+       u_int   eb_error_ct ;           /* # of eb overflows */
+} ;
+
+/*
+ * P0F : manufacturer field
+ */
+#define SMT_P_MANUFACTURER     0x000f  /* manufacturer field */
+#define SWAP_SMT_P_MANUFACTURER        ""
+
+struct smp_p_manufacturer {
+       struct smt_para para ;          /* generic parameter header */
+       u_char mf_data[32] ;            /* OUI + arbitrary data */
+} ;
+
+/*
+ * P10 : user field
+ */
+#define SMT_P_USER             0x0010  /* manufacturer field */
+#define SWAP_SMT_P_USER        ""
+
+struct smp_p_user {
+       struct smt_para para ;          /* generic parameter header */
+       u_char us_data[32] ;            /* arbitrary data */
+} ;
+
+
+
+/*
+ * P11 : echo data
+ */
+#define SMT_P_ECHODATA 0x0011          /* echo data */
+#define SWAP_SMT_P_ECHODATA    ""
+
+struct smt_p_echo {
+       struct smt_para para ;          /* generic parameter header */
+       u_char  ec_data[SMT_MAX_ECHO_LEN-4] ;   /* echo data */
+} ;
+
+/*
+ * P12 : reason code
+ */
+#define SMT_P_REASON   0x0012          /* reason code */
+#define SWAP_SMT_P_REASON      "l"
+
+struct smt_p_reason {
+       struct smt_para para ;          /* generic parameter header */
+       u_int   rdf_reason ;            /* CLASS/VERSION */
+} ;
+#define SMT_RDF_CLASS  0x00000001      /* class not supported */
+#define SMT_RDF_VERSION        0x00000002      /* version not supported */
+#define SMT_RDF_SUCCESS        0x00000003      /* success (PMF) */
+#define SMT_RDF_BADSET 0x00000004      /* bad set count (PMF) */
+#define SMT_RDF_ILLEGAL 0x00000005     /* read only (PMF) */
+#define SMT_RDF_NOPARAM        0x6             /* parameter not supported (PMF) */
+#define SMT_RDF_RANGE  0x8             /* out of range */
+#define SMT_RDF_AUTHOR 0x9             /* not autohorized */
+#define SMT_RDF_LENGTH 0x0a            /* length error */
+#define SMT_RDF_TOOLONG        0x0b            /* length error */
+#define SMT_RDF_SBA    0x0d            /* SBA denied */
+
+/*
+ * P13 : refused frame beginning
+ */
+#define SMT_P_REFUSED  0x0013          /* refused frame beginning */
+#define SWAP_SMT_P_REFUSED     "l"
+
+struct smt_p_refused {
+       struct smt_para para ;          /* generic parameter header */
+       u_int   ref_fc ;                /* 3 bytes 0 + FC */
+       struct smt_header       ref_header ;    /* refused header */
+} ;
+
+/*
+ * P14 : supported SMT versions
+ */
+#define SMT_P_VERSION  0x0014          /* SMT supported versions */
+#define SWAP_SMT_P_VERSION     "sccss"
+
+struct smt_p_version {
+       struct smt_para para ;          /* generic parameter header */
+       u_short v_pad ;
+       u_char  v_n ;                   /* 1 .. 0xff, #versions */
+       u_char  v_index ;               /* 1 .. 0xff, index of op. v. */
+       u_short v_version[1] ;          /* list of min. 1 version */
+       u_short v_pad2 ;                /* pad if necessary */
+} ;
+
+/*
+ * P15 : Resource Type
+ */
+#define        SWAP_SMT_P0015          "l"
+
+struct smt_p_0015 {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           res_type ;      /* recsource type */
+} ;
+
+#define        SYNC_BW         0x00000001L     /* Synchronous Bandwidth */
+
+/*
+ * P16 : SBA Command
+ */
+#define        SWAP_SMT_P0016          "l"
+
+struct smt_p_0016 {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           sba_cmd ;       /* command for the SBA */
+} ;
+
+#define        REQUEST_ALLOCATION      0x1     /* req allocation of sync bandwidth */
+#define        REPORT_ALLOCATION       0x2     /* rep of sync bandwidth allocation */
+#define        CHANGE_ALLOCATION       0x3     /* forces a station using sync band-*/
+                                       /* width to change its current allo-*/
+                                       /* cation */
+
+/*
+ * P17 : SBA Payload Request
+ */
+#define        SWAP_SMT_P0017          "l"
+
+struct smt_p_0017 {
+       struct smt_para para ;          /* generic parameter header */
+       int             sba_pl_req ;    /* total sync bandwidth measured in */
+} ;                                    /* bytes per 125 us */
+
+/*
+ * P18 : SBA Overhead Request
+ */
+#define        SWAP_SMT_P0018          "l"
+
+struct smt_p_0018 {
+       struct smt_para para ;          /* generic parameter header */
+       int             sba_ov_req ;    /* total sync bandwidth req for overhead*/
+} ;                                    /* measuered in bytes per T_Neg */
+
+/*
+ * P19 : SBA Allocation Address
+ */
+#define        SWAP_SMT_P0019          "s6"
+
+struct smt_p_0019 {
+       struct smt_para para ;          /* generic parameter header */
+       u_short         sba_pad ;
+       struct fddi_addr alloc_addr ;   /* Allocation Address */
+} ;
+
+/*
+ * P1A : SBA Category
+ */
+#define        SWAP_SMT_P001A          "l"
+
+struct smt_p_001a {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           category ;      /* Allocator defined classification */
+} ;
+
+/*
+ * P1B : Maximum T_Neg
+ */
+#define        SWAP_SMT_P001B          "l"
+
+struct smt_p_001b {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           max_t_neg ;     /* longest T_NEG for the sync service*/
+} ;
+
+/*
+ * P1C : Minimum SBA Segment Size
+ */
+#define        SWAP_SMT_P001C          "l"
+
+struct smt_p_001c {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           min_seg_siz ;   /* smallest number of bytes per frame*/
+} ;
+
+/*
+ * P1D : SBA Allocatable
+ */
+#define        SWAP_SMT_P001D          "l"
+
+struct smt_p_001d {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           allocatable ;   /* total sync bw available for alloc */
+} ;
+
+/*
+ * P20 0B : frame status capabilities
+ * NOTE: not in swap table, is used by smt.c AND PMF table
+ */
+#define SMT_P_FSC      0x200b
+/* #define SWAP_SMT_P_FSC      "ssss" */
+
+struct smt_p_fsc {
+       struct smt_para para ;          /* generic parameter header */
+       u_short fsc_pad0 ;
+       u_short fsc_mac_index ;         /* mac index 1 .. ff */
+       u_short fsc_pad1 ;
+       u_short fsc_value ;             /* FSC_TYPE[0-2] */
+} ;
+
+#define FSC_TYPE0      0               /* "normal" node (A/C handling) */
+#define FSC_TYPE1      1               /* Special A/C indicator forwarding */
+#define FSC_TYPE2      2               /* Special A/C indicator forwarding */
+
+/*
+ * P00 21 : user defined authoriziation (see pmf.c)
+ */
+#define SMT_P_AUTHOR   0x0021
+
+/*
+ * notification parameters
+ */
+#define SWAP_SMT_P1048 "ll"
+struct smt_p_1048 {
+       u_int p1048_flag ;
+       u_int p1048_cf_state ;
+} ;
+
+/*
+ * NOTE: all 2xxx 3xxx and 4xxx must include the INDEX in the swap string,
+ *     even so the INDEX is NOT part of the struct.
+ *     INDEX is already swapped in pmf.c, format in string is '4'
+ */
+#define SWAP_SMT_P208C "4lss66"
+struct smt_p_208c {
+       u_int                   p208c_flag ;
+       u_short                 p208c_pad ;
+       u_short                 p208c_dupcondition ;
+       struct  fddi_addr       p208c_fddilong ;
+       struct  fddi_addr       p208c_fddiunalong ;
+} ;
+
+#define SWAP_SMT_P208D "4lllll"
+struct smt_p_208d {
+       u_int                   p208d_flag ;
+       u_int                   p208d_frame_ct ;
+       u_int                   p208d_error_ct ;
+       u_int                   p208d_lost_ct ;
+       u_int                   p208d_ratio ;
+} ;
+
+#define SWAP_SMT_P208E "4llll"
+struct smt_p_208e {
+       u_int                   p208e_flag ;
+       u_int                   p208e_not_copied ;
+       u_int                   p208e_copied ;
+       u_int                   p208e_not_copied_ratio ;
+} ;
+
+#define SWAP_SMT_P208F "4ll6666s6"
+
+struct smt_p_208f {
+       u_int                   p208f_multiple ;
+       u_int                   p208f_nacondition ;
+       struct fddi_addr        p208f_old_una ;
+       struct fddi_addr        p208f_new_una ;
+       struct fddi_addr        p208f_old_dna ;
+       struct fddi_addr        p208f_new_dna ;
+       u_short                 p208f_curren_path ;
+       struct fddi_addr        p208f_smt_address ;
+} ;
+
+#define SWAP_SMT_P2090 "4lssl"
+
+struct smt_p_2090 {
+       u_int                   p2090_multiple ;
+       u_short                 p2090_availablepaths ;
+       u_short                 p2090_currentpath ;
+       u_int                   p2090_requestedpaths ;
+} ;
+
+/*
+ * NOTE:
+ * special kludge for parameters 320b,320f,3210
+ * these parameters are part of RAF frames
+ * RAF frames are parsed in SBA.C and must be swapped
+ * PMF.C has special code to avoid double swapping
+ */
+#ifdef LITTLE_ENDIAN
+#define SBAPATHINDEX   (0x01000000L)
+#else
+#define SBAPATHINDEX   (0x01L)
+#endif
+
+#define        SWAP_SMT_P320B  "42s"
+
+struct smt_p_320b {
+       struct smt_para para ;  /* generic parameter header */
+       u_int   mib_index ;
+       u_short path_pad ;
+       u_short path_index ;
+} ;
+
+#define        SWAP_SMT_P320F  "4l"
+
+struct smt_p_320f {
+       struct smt_para para ;  /* generic parameter header */
+       u_int   mib_index ;
+       u_int   mib_payload ;
+} ;
+
+#define        SWAP_SMT_P3210  "4l"
+
+struct smt_p_3210 {
+       struct smt_para para ;  /* generic parameter header */
+       u_int   mib_index ;
+       u_int   mib_overhead ;
+} ;
+
+#define SWAP_SMT_P4050 "4l1111ll"
+
+struct smt_p_4050 {
+       u_int                   p4050_flag ;
+       u_char                  p4050_pad ;
+       u_char                  p4050_cutoff ;
+       u_char                  p4050_alarm ;
+       u_char                  p4050_estimate ;
+       u_int                   p4050_reject_ct ;
+       u_int                   p4050_ct ;
+} ;
+
+#define SWAP_SMT_P4051 "4lssss"
+struct smt_p_4051 {
+       u_int                   p4051_multiple ;
+       u_short                 p4051_porttype ;
+       u_short                 p4051_connectstate ;
+       u_short                 p4051_pc_neighbor ;
+       u_short                 p4051_pc_withhold ;
+} ;
+
+#define SWAP_SMT_P4052 "4ll"
+struct smt_p_4052 {
+       u_int                   p4052_flag ;
+       u_int                   p4052_eberrorcount ;
+} ;
+
+#define SWAP_SMT_P4053 "4lsslss"
+
+struct smt_p_4053 {
+       u_int                   p4053_multiple ;
+       u_short                 p4053_availablepaths ;
+       u_short                 p4053_currentpath ;
+       u_int                   p4053_requestedpaths ;
+       u_short                 p4053_mytype ;
+       u_short                 p4053_neighbortype ;
+} ;
+
+
+#define SMT_P_SETCOUNT 0x1035
+#define SWAP_SMT_P_SETCOUNT    "l8"
+
+struct smt_p_setcount {
+       struct smt_para para ;          /* generic parameter header */
+       u_int           count ;
+       u_char          timestamp[8] ;
+} ;
+
+/*
+ * SMT FRAMES
+ */
+
+/*
+ * NIF : neighbor information frames
+ */
+struct smt_nif {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_una        una ;           /* UNA */
+       struct smt_p_sde        sde ;           /* station descriptor */
+       struct smt_p_state      state ;         /* station state */
+#ifdef SMT6_10
+       struct smt_p_fsc        fsc ;           /* frame status cap. */
+#endif
+} ;
+
+/*
+ * SIF : station information frames
+ */
+struct smt_sif_config {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_timestamp  ts ;            /* time stamp */
+       struct smt_p_sde        sde ;           /* station descriptor */
+       struct smt_p_version    version ;       /* supported versions */
+       struct smt_p_state      state ;         /* station state */
+       struct smt_p_policy     policy ;        /* station policy */
+       struct smt_p_latency    latency ;       /* path latency */
+       struct smt_p_neighbor   neighbor ;      /* neighbors, we have only one*/
+#ifdef OPT_PMF
+       struct smt_p_setcount   setcount ;       /* Set Count mandatory */
+#endif
+       /* WARNING : path MUST BE LAST FIELD !!! (see smt.c:smt_fill_path) */
+       struct smt_p_path       path ;          /* path descriptor */
+} ;
+#define SIZEOF_SMT_SIF_CONFIG  (sizeof(struct smt_sif_config)- \
+                                sizeof(struct smt_p_path))
+
+struct smt_sif_operation {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_timestamp  ts ;            /* time stamp */
+       struct smt_p_mac_status status ;        /* mac status */
+       struct smt_p_mac_counter mc ;           /* MAC counter */
+       struct smt_p_mac_fnc    fnc ;           /* MAC frame not copied */
+       struct smp_p_manufacturer man ;         /* manufacturer field */
+       struct smp_p_user       user ;          /* user field */
+#ifdef OPT_PMF
+       struct smt_p_setcount   setcount ;       /* Set Count mandatory */
+#endif
+       /* must be last */
+       struct smt_p_lem        lem[1] ;        /* phy lem status */
+} ;
+#define SIZEOF_SMT_SIF_OPERATION       (sizeof(struct smt_sif_operation)- \
+                                        sizeof(struct smt_p_lem))
+
+/*
+ * ECF : echo frame
+ */
+struct smt_ecf {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_echo       ec_echo ;       /* echo parameter */
+} ;
+#define SMT_ECF_LEN    (sizeof(struct smt_header)+sizeof(struct smt_para))
+
+/*
+ * RDF : request denied frame
+ */
+struct smt_rdf {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_reason     reason ;        /* reason code */
+       struct smt_p_version    version ;       /* supported versions */
+       struct smt_p_refused    refused ;       /* refused frame fragment */
+} ;
+
+/*
+ * SBA Request Allocation Response Frame
+ */
+struct smt_sba_alc_res {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_0015       s_type ;        /* resource type */
+       struct smt_p_0016       cmd ;           /* SBA command */
+       struct smt_p_reason     reason ;        /* reason code */
+       struct smt_p_320b       path ;          /* path type */
+       struct smt_p_320f       payload ;       /* current SBA payload */
+       struct smt_p_3210       overhead ;      /* current SBA overhead */
+       struct smt_p_0019       a_addr ;        /* Allocation Address */
+       struct smt_p_001a       cat ;           /* Category - from the request */
+       struct smt_p_001d       alloc ;         /* SBA Allocatable */
+} ;
+
+/*
+ * SBA Request Allocation Request Frame
+ */
+struct smt_sba_alc_req {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_0015       s_type ;        /* resource type */
+       struct smt_p_0016       cmd ;           /* SBA command */
+       struct smt_p_320b       path ;          /* path type */
+       struct smt_p_0017       pl_req ;        /* requested payload */
+       struct smt_p_0018       ov_req ;        /* requested SBA overhead */
+       struct smt_p_320f       payload ;       /* current SBA payload */
+       struct smt_p_3210       overhead ;      /* current SBA overhead */
+       struct smt_p_0019       a_addr ;        /* Allocation Address */
+       struct smt_p_001a       cat ;           /* Category - from the request */
+       struct smt_p_001b       tneg ;          /* max T-NEG */
+       struct smt_p_001c       segm ;          /* minimum segment size */
+} ;
+
+/*
+ * SBA Change Allocation Request Frame
+ */
+struct smt_sba_chg {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_0015       s_type ;        /* resource type */
+       struct smt_p_0016       cmd ;           /* SBA command */
+       struct smt_p_320b       path ;          /* path type */
+       struct smt_p_320f       payload ;       /* current SBA payload */
+       struct smt_p_3210       overhead ;      /* current SBA overhead */
+       struct smt_p_001a       cat ;           /* Category - from the request */
+} ;
+
+/*
+ * SBA Report Allocation Request Frame
+ */
+struct smt_sba_rep_req {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_0015       s_type ;        /* resource type */
+       struct smt_p_0016       cmd ;           /* SBA command */
+} ;
+
+/*
+ * SBA Report Allocation Response Frame
+ */
+struct smt_sba_rep_res {
+       struct smt_header       smt ;           /* generic header */
+       struct smt_p_0015       s_type ;        /* resource type */
+       struct smt_p_0016       cmd ;           /* SBA command */
+       struct smt_p_320b       path ;          /* path type */
+       struct smt_p_320f       payload ;       /* current SBA payload */
+       struct smt_p_3210       overhead ;      /* current SBA overhead */
+} ;
+
+/*
+ * actions
+ */
+#define SMT_STATION_ACTION     1
+#define SMT_STATION_ACTION_CONNECT     0
+#define SMT_STATION_ACTION_DISCONNECT  1
+#define SMT_STATION_ACTION_PATHTEST    2
+#define SMT_STATION_ACTION_SELFTEST    3
+#define SMT_STATION_ACTION_DISABLE_A   4
+#define SMT_STATION_ACTION_DISABLE_B   5
+#define SMT_STATION_ACTION_DISABLE_M   6
+
+#define SMT_PORT_ACTION                2
+#define SMT_PORT_ACTION_MAINT  0
+#define SMT_PORT_ACTION_ENABLE 1
+#define SMT_PORT_ACTION_DISABLE        2
+#define SMT_PORT_ACTION_START  3
+#define SMT_PORT_ACTION_STOP   4
+
+#endif /* _SMT_ */
diff --git a/drivers/net/fddi/skfp/h/smt_p.h b/drivers/net/fddi/skfp/h/smt_p.h
new file mode 100644 (file)
index 0000000..99f9be9
--- /dev/null
@@ -0,0 +1,326 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * defines for all SMT attributes
+ */
+
+/*
+ * this boring file was produced by perl
+ * thanks Larry !
+ */
+#define        SMT_P0012       0x0012
+
+#define        SMT_P0015       0x0015
+#define        SMT_P0016       0x0016
+#define        SMT_P0017       0x0017
+#define        SMT_P0018       0x0018
+#define        SMT_P0019       0x0019
+
+#define        SMT_P001A       0x001a
+#define        SMT_P001B       0x001b
+#define        SMT_P001C       0x001c
+#define        SMT_P001D       0x001d
+
+#define        SMT_P100A       0x100a
+#define        SMT_P100B       0x100b
+#define        SMT_P100C       0x100c
+#define        SMT_P100D       0x100d
+#define        SMT_P100E       0x100e
+#define        SMT_P100F       0x100f
+#define        SMT_P1010       0x1010
+#define        SMT_P1011       0x1011
+#define        SMT_P1012       0x1012
+#define        SMT_P1013       0x1013
+#define        SMT_P1014       0x1014
+#define        SMT_P1015       0x1015
+#define        SMT_P1016       0x1016
+#define        SMT_P1017       0x1017
+#define        SMT_P1018       0x1018
+#define        SMT_P1019       0x1019
+#define        SMT_P101A       0x101a
+#define        SMT_P101B       0x101b
+#define        SMT_P101C       0x101c
+#define        SMT_P101D       0x101d
+#define        SMT_P101E       0x101e
+#define        SMT_P101F       0x101f
+#define        SMT_P1020       0x1020
+#define        SMT_P1021       0x1021
+#define        SMT_P1022       0x1022
+#define        SMT_P1023       0x1023
+#define        SMT_P1024       0x1024
+#define        SMT_P1025       0x1025
+#define        SMT_P1026       0x1026
+#define        SMT_P1027       0x1027
+#define        SMT_P1028       0x1028
+#define        SMT_P1029       0x1029
+#define        SMT_P102A       0x102a
+#define        SMT_P102B       0x102b
+#define        SMT_P102C       0x102c
+#define        SMT_P102D       0x102d
+#define        SMT_P102E       0x102e
+#define        SMT_P102F       0x102f
+#define        SMT_P1030       0x1030
+#define        SMT_P1031       0x1031
+#define        SMT_P1032       0x1032
+#define        SMT_P1033       0x1033
+#define        SMT_P1034       0x1034
+#define        SMT_P1035       0x1035
+#define        SMT_P1036       0x1036
+#define        SMT_P1037       0x1037
+#define        SMT_P1038       0x1038
+#define        SMT_P1039       0x1039
+#define        SMT_P103A       0x103a
+#define        SMT_P103B       0x103b
+#define        SMT_P103C       0x103c
+#define        SMT_P103D       0x103d
+#define        SMT_P103E       0x103e
+#define        SMT_P103F       0x103f
+#define        SMT_P1040       0x1040
+#define        SMT_P1041       0x1041
+#define        SMT_P1042       0x1042
+#define        SMT_P1043       0x1043
+#define        SMT_P1044       0x1044
+#define        SMT_P1045       0x1045
+#define        SMT_P1046       0x1046
+#define        SMT_P1047       0x1047
+#define        SMT_P1048       0x1048
+#define        SMT_P1049       0x1049
+#define        SMT_P104A       0x104a
+#define        SMT_P104B       0x104b
+#define        SMT_P104C       0x104c
+#define        SMT_P104D       0x104d
+#define        SMT_P104E       0x104e
+#define        SMT_P104F       0x104f
+#define        SMT_P1050       0x1050
+#define        SMT_P1051       0x1051
+#define        SMT_P1052       0x1052
+#define        SMT_P1053       0x1053
+#define        SMT_P1054       0x1054
+
+#define        SMT_P10F0       0x10f0
+#define        SMT_P10F1       0x10f1
+#ifdef ESS
+#define        SMT_P10F2       0x10f2
+#define        SMT_P10F3       0x10f3
+#define        SMT_P10F4       0x10f4
+#define        SMT_P10F5       0x10f5
+#define        SMT_P10F6       0x10f6
+#define        SMT_P10F7       0x10f7
+#endif
+#ifdef SBA
+#define        SMT_P10F8       0x10f8
+#define        SMT_P10F9       0x10f9
+#endif
+
+#define        SMT_P200A       0x200a
+#define        SMT_P200B       0x200b
+#define        SMT_P200C       0x200c
+#define        SMT_P200D       0x200d
+#define        SMT_P200E       0x200e
+#define        SMT_P200F       0x200f
+#define        SMT_P2010       0x2010
+#define        SMT_P2011       0x2011
+#define        SMT_P2012       0x2012
+#define        SMT_P2013       0x2013
+#define        SMT_P2014       0x2014
+#define        SMT_P2015       0x2015
+#define        SMT_P2016       0x2016
+#define        SMT_P2017       0x2017
+#define        SMT_P2018       0x2018
+#define        SMT_P2019       0x2019
+#define        SMT_P201A       0x201a
+#define        SMT_P201B       0x201b
+#define        SMT_P201C       0x201c
+#define        SMT_P201D       0x201d
+#define        SMT_P201E       0x201e
+#define        SMT_P201F       0x201f
+#define        SMT_P2020       0x2020
+#define        SMT_P2021       0x2021
+#define        SMT_P2022       0x2022
+#define        SMT_P2023       0x2023
+#define        SMT_P2024       0x2024
+#define        SMT_P2025       0x2025
+#define        SMT_P2026       0x2026
+#define        SMT_P2027       0x2027
+#define        SMT_P2028       0x2028
+#define        SMT_P2029       0x2029
+#define        SMT_P202A       0x202a
+#define        SMT_P202B       0x202b
+#define        SMT_P202C       0x202c
+#define        SMT_P202D       0x202d
+#define        SMT_P202E       0x202e
+#define        SMT_P202F       0x202f
+#define        SMT_P2030       0x2030
+#define        SMT_P2031       0x2031
+#define        SMT_P2032       0x2032
+#define        SMT_P2033       0x2033
+#define        SMT_P2034       0x2034
+#define        SMT_P2035       0x2035
+#define        SMT_P2036       0x2036
+#define        SMT_P2037       0x2037
+#define        SMT_P2038       0x2038
+#define        SMT_P2039       0x2039
+#define        SMT_P203A       0x203a
+#define        SMT_P203B       0x203b
+#define        SMT_P203C       0x203c
+#define        SMT_P203D       0x203d
+#define        SMT_P203E       0x203e
+#define        SMT_P203F       0x203f
+#define        SMT_P2040       0x2040
+#define        SMT_P2041       0x2041
+#define        SMT_P2042       0x2042
+#define        SMT_P2043       0x2043
+#define        SMT_P2044       0x2044
+#define        SMT_P2045       0x2045
+#define        SMT_P2046       0x2046
+#define        SMT_P2047       0x2047
+#define        SMT_P2048       0x2048
+#define        SMT_P2049       0x2049
+#define        SMT_P204A       0x204a
+#define        SMT_P204B       0x204b
+#define        SMT_P204C       0x204c
+#define        SMT_P204D       0x204d
+#define        SMT_P204E       0x204e
+#define        SMT_P204F       0x204f
+#define        SMT_P2050       0x2050
+#define        SMT_P2051       0x2051
+#define        SMT_P2052       0x2052
+#define        SMT_P2053       0x2053
+#define        SMT_P2054       0x2054
+#define        SMT_P2055       0x2055
+#define        SMT_P2056       0x2056
+#define        SMT_P2057       0x2057
+#define        SMT_P2058       0x2058
+#define        SMT_P2059       0x2059
+#define        SMT_P205A       0x205a
+#define        SMT_P205B       0x205b
+#define        SMT_P205C       0x205c
+#define        SMT_P205D       0x205d
+#define        SMT_P205E       0x205e
+#define        SMT_P205F       0x205f
+#define        SMT_P2060       0x2060
+#define        SMT_P2061       0x2061
+#define        SMT_P2062       0x2062
+#define        SMT_P2063       0x2063
+#define        SMT_P2064       0x2064
+#define        SMT_P2065       0x2065
+#define        SMT_P2066       0x2066
+#define        SMT_P2067       0x2067
+#define        SMT_P2068       0x2068
+#define        SMT_P2069       0x2069
+#define        SMT_P206A       0x206a
+#define        SMT_P206B       0x206b
+#define        SMT_P206C       0x206c
+#define        SMT_P206D       0x206d
+#define        SMT_P206E       0x206e
+#define        SMT_P206F       0x206f
+#define        SMT_P2070       0x2070
+#define        SMT_P2071       0x2071
+#define        SMT_P2072       0x2072
+#define        SMT_P2073       0x2073
+#define        SMT_P2074       0x2074
+#define        SMT_P2075       0x2075
+#define        SMT_P2076       0x2076
+
+#define        SMT_P208C       0x208c
+#define        SMT_P208D       0x208d
+#define        SMT_P208E       0x208e
+#define        SMT_P208F       0x208f
+#define        SMT_P2090       0x2090
+
+#define        SMT_P20F0       0x20F0
+#define        SMT_P20F1       0x20F1
+
+#define        SMT_P320A       0x320a
+#define        SMT_P320B       0x320b
+#define        SMT_P320C       0x320c
+#define        SMT_P320D       0x320d
+#define        SMT_P320E       0x320e
+#define        SMT_P320F       0x320f
+#define        SMT_P3210       0x3210
+#define        SMT_P3211       0x3211
+#define        SMT_P3212       0x3212
+#define        SMT_P3213       0x3213
+#define        SMT_P3214       0x3214
+#define        SMT_P3215       0x3215
+#define        SMT_P3216       0x3216
+#define        SMT_P3217       0x3217
+
+#define        SMT_P400A       0x400a
+#define        SMT_P400B       0x400b
+#define        SMT_P400C       0x400c
+#define        SMT_P400D       0x400d
+#define        SMT_P400E       0x400e
+#define        SMT_P400F       0x400f
+#define        SMT_P4010       0x4010
+#define        SMT_P4011       0x4011
+#define        SMT_P4012       0x4012
+#define        SMT_P4013       0x4013
+#define        SMT_P4014       0x4014
+#define        SMT_P4015       0x4015
+#define        SMT_P4016       0x4016
+#define        SMT_P4017       0x4017
+#define        SMT_P4018       0x4018
+#define        SMT_P4019       0x4019
+#define        SMT_P401A       0x401a
+#define        SMT_P401B       0x401b
+#define        SMT_P401C       0x401c
+#define        SMT_P401D       0x401d
+#define        SMT_P401E       0x401e
+#define        SMT_P401F       0x401f
+#define        SMT_P4020       0x4020
+#define        SMT_P4021       0x4021
+#define        SMT_P4022       0x4022
+#define        SMT_P4023       0x4023
+#define        SMT_P4024       0x4024
+#define        SMT_P4025       0x4025
+#define        SMT_P4026       0x4026
+#define        SMT_P4027       0x4027
+#define        SMT_P4028       0x4028
+#define        SMT_P4029       0x4029
+#define        SMT_P402A       0x402a
+#define        SMT_P402B       0x402b
+#define        SMT_P402C       0x402c
+#define        SMT_P402D       0x402d
+#define        SMT_P402E       0x402e
+#define        SMT_P402F       0x402f
+#define        SMT_P4030       0x4030
+#define        SMT_P4031       0x4031
+#define        SMT_P4032       0x4032
+#define        SMT_P4033       0x4033
+#define        SMT_P4034       0x4034
+#define        SMT_P4035       0x4035
+#define        SMT_P4036       0x4036
+#define        SMT_P4037       0x4037
+#define        SMT_P4038       0x4038
+#define        SMT_P4039       0x4039
+#define        SMT_P403A       0x403a
+#define        SMT_P403B       0x403b
+#define        SMT_P403C       0x403c
+#define        SMT_P403D       0x403d
+#define        SMT_P403E       0x403e
+#define        SMT_P403F       0x403f
+#define        SMT_P4040       0x4040
+#define        SMT_P4041       0x4041
+#define        SMT_P4042       0x4042
+#define        SMT_P4043       0x4043
+#define        SMT_P4044       0x4044
+#define        SMT_P4045       0x4045
+#define        SMT_P4046       0x4046
+
+#define        SMT_P4050       0x4050
+#define        SMT_P4051       0x4051
+#define        SMT_P4052       0x4052
+#define        SMT_P4053       0x4053
diff --git a/drivers/net/fddi/skfp/h/smtstate.h b/drivers/net/fddi/skfp/h/smtstate.h
new file mode 100644 (file)
index 0000000..62fe695
--- /dev/null
@@ -0,0 +1,106 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef _SKFP_H_SMTSTATE_H_
+#define _SKFP_H_SMTSTATE_H_
+
+/*
+ *     SMT state definitions
+ */
+
+#ifndef        KERNEL
+/*
+ * PCM states
+ */
+#define PC0_OFF                        0
+#define PC1_BREAK              1
+#define PC2_TRACE              2
+#define PC3_CONNECT            3
+#define PC4_NEXT               4
+#define PC5_SIGNAL             5
+#define PC6_JOIN               6
+#define PC7_VERIFY             7
+#define PC8_ACTIVE             8
+#define PC9_MAINT              9
+
+/*
+ * PCM modes
+ */
+#define PM_NONE                        0
+#define PM_PEER                        1
+#define PM_TREE                        2
+
+/*
+ * PCM type
+ */
+#define TA                     0
+#define TB                     1
+#define TS                     2
+#define TM                     3
+#define TNONE                  4
+
+/*
+ * CFM states
+ */
+#define SC0_ISOLATED   0               /* isolated */
+#define SC1_WRAP_A     5               /* wrap A */
+#define SC2_WRAP_B     6               /* wrap B */
+#define SC4_THRU_A     12              /* through A */
+#define SC5_THRU_B     7               /* through B (SMt 6.2) */
+#define SC7_WRAP_S     8               /* SAS */
+
+/*
+ * ECM states
+ */
+#define EC0_OUT                0
+#define EC1_IN         1
+#define EC2_TRACE      2
+#define EC3_LEAVE      3
+#define EC4_PATH_TEST  4
+#define EC5_INSERT     5
+#define EC6_CHECK      6
+#define EC7_DEINSERT   7
+
+/*
+ * RMT states
+ */
+#define RM0_ISOLATED   0
+#define RM1_NON_OP     1               /* not operational */
+#define RM2_RING_OP    2               /* ring operational */
+#define RM3_DETECT     3               /* detect dupl addresses */
+#define RM4_NON_OP_DUP 4               /* dupl. addr detected */
+#define RM5_RING_OP_DUP        5               /* ring oper. with dupl. addr */
+#define RM6_DIRECTED   6               /* sending directed beacons */
+#define RM7_TRACE      7               /* trace initiated */
+#endif
+
+struct pcm_state {
+       unsigned char   pcm_type ;              /* TA TB TS TM */
+       unsigned char   pcm_state ;             /* state PC[0-9]_* */
+       unsigned char   pcm_mode ;              /* PM_{NONE,PEER,TREE} */
+       unsigned char   pcm_neighbor ;          /* TA TB TS TM */
+       unsigned char   pcm_bsf ;               /* flag bs : TRUE/FALSE */
+       unsigned char   pcm_lsf ;               /* flag ls : TRUE/FALSE */
+       unsigned char   pcm_lct_fail ;          /* counter lct_fail */
+       unsigned char   pcm_ls_rx ;             /* rx line state */
+       short           pcm_r_val ;             /* signaling bits */
+       short           pcm_t_val ;             /* signaling bits */
+} ;
+
+struct smt_state {
+       struct pcm_state pcm_state[NUMPHYS] ;   /* port A & port B */
+} ;
+
+#endif
+
diff --git a/drivers/net/fddi/skfp/h/supern_2.h b/drivers/net/fddi/skfp/h/supern_2.h
new file mode 100644 (file)
index 0000000..0b73690
--- /dev/null
@@ -0,0 +1,1059 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       defines for AMD Supernet II chip set
+       the chips are referred to as
+               FPLUS   Formac Plus
+               PLC     Physical Layer
+
+       added defines for AMD Supernet III chip set
+       added comments on differences between Supernet II and Supernet III
+       added defines for the Motorola ELM (MOT_ELM)
+*/
+
+#ifndef        _SUPERNET_
+#define _SUPERNET_
+
+/*
+ * Define Supernet 3 when used
+ */
+#ifdef PCI
+#ifndef        SUPERNET_3
+#define        SUPERNET_3
+#endif
+#define TAG
+#endif
+
+#define        MB      0xff
+#define        MW      0xffff
+#define        MD      0xffffffff
+
+/*
+ * FORMAC frame status (rx_msext)
+ */
+#define        FS_EI           (1<<2)
+#define        FS_AI           (1<<1)
+#define        FS_CI           (1<<0)
+
+#define FS_MSVALID     (1<<15)         /* end of queue */
+#define FS_MSRABT      (1<<14)         /* frame was aborted during reception*/
+#define FS_SSRCRTG     (1<<12)         /* if SA has set MSB (source-routing)*/
+#define FS_SEAC2       (FS_EI<<9)      /* error indicator */
+#define FS_SEAC1       (FS_AI<<9)      /* address indicator */
+#define FS_SEAC0       (FS_CI<<9)      /* copy indicator */
+#define FS_SFRMERR     (1<<8)          /* error detected (CRC or length) */
+#define FS_SADRRG      (1<<7)          /* address recognized */
+#define FS_SFRMTY2     (1<<6)          /* frame-class bit */
+#define FS_SFRMTY1     (1<<5)          /* frame-type bit (impementor) */
+#define FS_SFRMTY0     (1<<4)          /* frame-type bit (LLC) */
+#define FS_ERFBB1      (1<<1)          /* byte offset (depends on LSB bit) */
+#define FS_ERFBB0      (1<<0)          /*  - " - */
+
+/*
+ * status frame type
+ */
+#define        FRM_SMT         (0)     /* asynchr. frames */
+#define        FRM_LLCA        (1)
+#define        FRM_IMPA        (2)     
+#define        FRM_MAC         (4)     /* synchr. frames */
+#define        FRM_LLCS        (5)
+#define        FRM_IMPS        (6)
+
+/*
+ * bits in rx_descr.i  (receive frame status word)
+ */
+#define RX_MSVALID     ((long)1<<31)   /* memory status valid */
+#define RX_MSRABT      ((long)1<<30)   /* memory status receive abort */
+#define RX_FS_E                ((long)FS_SEAC2<<16)    /* error indicator */
+#define RX_FS_A                ((long)FS_SEAC1<<16)    /* address indicator */
+#define RX_FS_C                ((long)FS_SEAC0<<16)    /* copy indicator */
+#define RX_FS_CRC      ((long)FS_SFRMERR<<16)/* error detected */
+#define RX_FS_ADDRESS  ((long)FS_SADRRG<<16)   /* address recognized */
+#define RX_FS_MAC      ((long)FS_SFRMTY2<<16)/* MAC frame */
+#define RX_FS_SMT      ((long)0<<16)           /* SMT frame */
+#define RX_FS_IMPL     ((long)FS_SFRMTY1<<16)/* implementer frame */
+#define RX_FS_LLC      ((long)FS_SFRMTY0<<16)/* LLC frame */
+
+/*
+ * receive frame descriptor
+ */
+union rx_descr {
+       struct {
+#ifdef LITTLE_ENDIAN
+       unsigned        rx_length :16 ; /* frame length lower/upper byte */
+       unsigned        rx_erfbb  :2 ;  /* received frame byte boundary */
+       unsigned        rx_reserv2:2 ;  /* reserved */  
+       unsigned        rx_sfrmty :3 ;  /* frame type bits */
+       unsigned        rx_sadrrg :1 ;  /* DA == MA or broad-/multicast */
+       unsigned        rx_sfrmerr:1 ;  /* received frame not valid */
+       unsigned        rx_seac0  :1 ;  /* frame-copied  C-indicator */
+       unsigned        rx_seac1  :1 ;  /* address-match A-indicator */
+       unsigned        rx_seac2  :1 ;  /* frame-error   E-indicator */
+       unsigned        rx_ssrcrtg:1 ;  /* == 1 SA has MSB set */
+       unsigned        rx_reserv1:1 ;  /* reserved */  
+       unsigned        rx_msrabt :1 ;  /* memory status receive abort */
+       unsigned        rx_msvalid:1 ;  /* memory status valid */
+#else
+       unsigned        rx_msvalid:1 ;  /* memory status valid */
+       unsigned        rx_msrabt :1 ;  /* memory status receive abort */
+       unsigned        rx_reserv1:1 ;  /* reserved */  
+       unsigned        rx_ssrcrtg:1 ;  /* == 1 SA has MSB set */
+       unsigned        rx_seac2  :1 ;  /* frame-error   E-indicator */
+       unsigned        rx_seac1  :1 ;  /* address-match A-indicator */
+       unsigned        rx_seac0  :1 ;  /* frame-copied  C-indicator */
+       unsigned        rx_sfrmerr:1 ;  /* received frame not valid */
+       unsigned        rx_sadrrg :1 ;  /* DA == MA or broad-/multicast */
+       unsigned        rx_sfrmty :3 ;  /* frame type bits */
+       unsigned        rx_erfbb  :2 ;  /* received frame byte boundary */
+       unsigned        rx_reserv2:2 ;  /* reserved */  
+       unsigned        rx_length :16 ; /* frame length lower/upper byte */
+#endif
+       } r ;
+       long    i ;
+} ;
+
+/* defines for Receive Frame Descriptor access */
+#define RD_S_ERFBB     0x00030000L     /* received frame byte boundary */
+#define RD_S_RES2      0x000c0000L     /* reserved */
+#define RD_S_SFRMTY    0x00700000L     /* frame type bits */
+#define RD_S_SADRRG    0x00800000L     /* DA == MA or broad-/multicast */
+#define RD_S_SFRMERR   0x01000000L     /* received frame not valid */
+#define        RD_S_SEAC       0x0e000000L     /* frame status indicators */
+#define RD_S_SEAC0     0x02000000L     /* frame-copied  case-indicator */
+#define RD_S_SEAC1     0x04000000L     /* address-match A-indicator */
+#define RD_S_SEAC2     0x08000000L     /* frame-error   E-indicator */
+#define RD_S_SSRCRTG   0x10000000L     /* == 1 SA has MSB set */
+#define RD_S_RES1      0x20000000L     /* reserved */
+#define RD_S_MSRABT    0x40000000L     /* memory status receive abort */
+#define RD_S_MSVALID   0x80000000L     /* memory status valid */
+
+#define        RD_STATUS       0xffff0000L
+#define        RD_LENGTH       0x0000ffffL
+
+/* defines for Receive Frames Status Word values */
+/*RD_S_SFRMTY*/
+#define RD_FRM_SMT     (unsigned long)(0<<20)     /* asynchr. frames */
+#define RD_FRM_LLCA    (unsigned long)(1<<20)
+#define RD_FRM_IMPA    (unsigned long)(2<<20)
+#define RD_FRM_MAC     (unsigned long)(4<<20)     /* synchr. frames */
+#define RD_FRM_LLCS    (unsigned long)(5<<20)
+#define RD_FRM_IMPS    (unsigned long)(6<<20)
+
+#define TX_DESCRIPTOR  0x40000000L
+#define TX_OFFSET_3    0x18000000L
+
+#define TXP1   2
+
+/*
+ * transmit frame descriptor
+ */
+union tx_descr {
+       struct {
+#ifdef LITTLE_ENDIAN
+       unsigned        tx_length:16 ;  /* frame length lower/upper byte */
+       unsigned        tx_res   :8 ;   /* reserved      (bit 16..23) */
+       unsigned        tx_xmtabt:1 ;   /* transmit abort */
+       unsigned        tx_nfcs  :1 ;   /* no frame check sequence */
+       unsigned        tx_xdone :1 ;   /* give up token */
+       unsigned        tx_rpxm  :2 ;   /* byte offset */
+       unsigned        tx_pat1  :2 ;   /* must be TXP1 */
+       unsigned        tx_more  :1 ;   /* more frame in chain */
+#else
+       unsigned        tx_more  :1 ;   /* more frame in chain */
+       unsigned        tx_pat1  :2 ;   /* must be TXP1 */
+       unsigned        tx_rpxm  :2 ;   /* byte offset */
+       unsigned        tx_xdone :1 ;   /* give up token */
+       unsigned        tx_nfcs  :1 ;   /* no frame check sequence */
+       unsigned        tx_xmtabt:1 ;   /* transmit abort */
+       unsigned        tx_res   :8 ;   /* reserved      (bit 16..23) */
+       unsigned        tx_length:16 ;  /* frame length lower/upper byte */
+#endif
+       } t ;
+       long    i ;
+} ;
+
+/* defines for Transmit Descriptor access */
+#define        TD_C_MORE       0x80000000L     /* more frame in chain */
+#define        TD_C_DESCR      0x60000000L     /* must be TXP1 */
+#define        TD_C_TXFBB      0x18000000L     /* byte offset */
+#define        TD_C_XDONE      0x04000000L     /* give up token */
+#define TD_C_NFCS      0x02000000L     /* no frame check sequence */
+#define TD_C_XMTABT    0x01000000L     /* transmit abort */
+
+#define        TD_C_LNCNU      0x0000ff00L     
+#define TD_C_LNCNL     0x000000ffL
+#define TD_C_LNCN      0x0000ffffL     /* frame length lower/upper byte */
+/*
+ * transmit pointer
+ */
+union tx_pointer {
+       struct t {
+#ifdef LITTLE_ENDIAN
+       unsigned        tp_pointer:16 ; /* pointer to tx_descr (low/high) */
+       unsigned        tp_res    :8 ;  /* reserved      (bit 16..23) */
+       unsigned        tp_pattern:8 ;  /* fixed pattern (bit 24..31) */
+#else
+       unsigned        tp_pattern:8 ;  /* fixed pattern (bit 24..31) */
+       unsigned        tp_res    :8 ;  /* reserved      (bit 16..23) */
+       unsigned        tp_pointer:16 ; /* pointer to tx_descr (low/high) */
+#endif
+       } t ;
+       long    i ;
+} ;
+
+/* defines for Nontag Mode Pointer access */
+#define        TD_P_CNTRL      0xff000000L
+#define TD_P_RPXU      0x0000ff00L
+#define TD_P_RPXL      0x000000ffL
+#define TD_P_RPX       0x0000ffffL
+
+
+#define TX_PATTERN     0xa0
+#define TX_POINTER_END 0xa0000000L
+#define TX_INT_PATTERN 0xa0000000L
+
+struct tx_queue {
+       struct tx_queue *tq_next ;
+       u_short tq_pack_offset ;        /* offset buffer memory */
+       u_char  tq_pad[2] ;
+} ;
+
+/*
+       defines for FORMAC Plus (Am79C830)
+*/
+
+/*
+ *  FORMAC+ read/write (r/w) registers
+ */
+#define FM_CMDREG1     0x00            /* write command reg 1 instruction */
+#define FM_CMDREG2     0x01            /* write command reg 2 instruction */
+#define FM_ST1U                0x00            /* read upper 16-bit of status reg 1 */
+#define FM_ST1L                0x01            /* read lower 16-bit of status reg 1 */
+#define FM_ST2U                0x02            /* read upper 16-bit of status reg 2 */
+#define FM_ST2L                0x03            /* read lower 16-bit of status reg 2 */
+#define FM_IMSK1U      0x04            /* r/w upper 16-bit of IMSK 1 */
+#define FM_IMSK1L      0x05            /* r/w lower 16-bit of IMSK 1 */
+#define FM_IMSK2U      0x06            /* r/w upper 16-bit of IMSK 2 */
+#define FM_IMSK2L      0x07            /* r/w lower 16-bit of IMSK 2 */
+#define FM_SAID                0x08            /* r/w short addr.-individual */
+#define FM_LAIM                0x09            /* r/w long addr.-ind. (MSW of LAID) */
+#define FM_LAIC                0x0a            /* r/w long addr.-ind. (middle)*/
+#define FM_LAIL                0x0b            /* r/w long addr.-ind. (LSW) */
+#define FM_SAGP                0x0c            /* r/w short address-group */
+#define FM_LAGM                0x0d            /* r/w long addr.-gr. (MSW of LAGP) */
+#define FM_LAGC                0x0e            /* r/w long addr.-gr. (middle) */
+#define FM_LAGL                0x0f            /* r/w long addr.-gr. (LSW) */
+#define FM_MDREG1      0x10            /* r/w 16-bit mode reg 1 */
+#define FM_STMCHN      0x11            /* read state-machine reg */
+#define FM_MIR1                0x12            /* read upper 16-bit of MAC Info Reg */
+#define FM_MIR0                0x13            /* read lower 16-bit of MAC Info Reg */
+#define FM_TMAX                0x14            /* r/w 16-bit TMAX reg */
+#define FM_TVX         0x15            /* write 8-bit TVX reg with NP7-0
+                                          read TVX on NP7-0, timer on NP15-8*/
+#define FM_TRT         0x16            /* r/w upper 16-bit of TRT timer */
+#define FM_THT         0x17            /* r/w upper 16-bit of THT timer */
+#define FM_TNEG                0x18            /* read upper 16-bit of TNEG (TTRT) */
+#define FM_TMRS                0x19            /* read lower 5-bit of TNEG,TRT,THT */
+                       /* F E D C  B A 9 8  7 6 5 4  3 2 1 0
+                          x |-TNEG4-0| |-TRT4-0-| |-THT4-0-| (x-late count) */
+#define FM_TREQ0       0x1a            /* r/w 16-bit TREQ0 reg (LSW of TRT) */
+#define FM_TREQ1       0x1b            /* r/w 16-bit TREQ1 reg (MSW of TRT) */
+#define FM_PRI0                0x1c            /* r/w priority r. for asyn.-queue 0 */
+#define FM_PRI1                0x1d            /* r/w priority r. for asyn.-queue 1 */
+#define FM_PRI2                0x1e            /* r/w priority r. for asyn.-queue 2 */
+#define FM_TSYNC       0x1f            /* r/w 16-bit of the TSYNC register */
+#define FM_MDREG2      0x20            /* r/w 16-bit mode reg 2 */
+#define FM_FRMTHR      0x21            /* r/w the frame threshold register */
+#define FM_EACB                0x22            /* r/w end addr of claim/beacon area */
+#define FM_EARV                0x23            /* r/w end addr of receive queue */
+/* Supernet 3 */
+#define        FM_EARV1        FM_EARV
+
+#define FM_EAS         0x24            /* r/w end addr of synchr. queue */
+#define FM_EAA0                0x25            /* r/w end addr of asyn. queue 0 */
+#define FM_EAA1                0x26            /* r/w end addr of asyn. queue 1 */
+#define FM_EAA2                0x27            /* r/w end addr of asyn. queue 2 */
+#define FM_SACL                0x28            /* r/w start addr of claim frame */
+#define FM_SABC                0x29            /* r/w start addr of beacon frame */
+#define FM_WPXSF       0x2a            /* r/w the write ptr. for special fr.*/
+#define FM_RPXSF       0x2b            /* r/w the read ptr. for special fr. */
+#define FM_RPR         0x2d            /* r/w the read ptr. for receive qu. */
+#define FM_WPR         0x2e            /* r/w the write ptr. for receive qu.*/
+#define FM_SWPR                0x2f            /* r/w the shadow wr.-ptr. for rec.q.*/
+/* Supernet 3 */ 
+#define FM_RPR1         FM_RPR   
+#define FM_WPR1         FM_WPR 
+#define FM_SWPR1        FM_SWPR
+
+#define FM_WPXS                0x30            /* r/w the write ptr. for synchr. qu.*/
+#define FM_WPXA0       0x31            /* r/w the write ptr. for asyn. qu.0 */
+#define FM_WPXA1       0x32            /* r/w the write ptr. for asyn. qu.1 */
+#define FM_WPXA2       0x33            /* r/w the write ptr. for asyn. qu.2 */
+#define FM_SWPXS       0x34            /* r/w the shadow wr.-ptr. for syn.q.*/
+#define FM_SWPXA0      0x35            /* r/w the shad. wr.-ptr. for asyn.q0*/
+#define FM_SWPXA1      0x36            /* r/w the shad. wr.-ptr. for asyn.q1*/
+#define FM_SWPXA2      0x37            /* r/w the shad. wr.-ptr. for asyn.q2*/
+#define FM_RPXS                0x38            /* r/w the read ptr. for synchr. qu. */
+#define FM_RPXA0       0x39            /* r/w the read ptr. for asyn. qu. 0 */
+#define FM_RPXA1       0x3a            /* r/w the read ptr. for asyn. qu. 1 */
+#define FM_RPXA2       0x3b            /* r/w the read ptr. for asyn. qu. 2 */
+#define FM_MARR                0x3c            /* r/w the memory read addr register */
+#define FM_MARW                0x3d            /* r/w the memory write addr register*/
+#define FM_MDRU                0x3e            /* r/w upper 16-bit of mem. data reg */
+#define FM_MDRL                0x3f            /* r/w lower 16-bit of mem. data reg */
+
+/* following instructions relate to MAC counters and timer */
+#define FM_TMSYNC      0x40            /* r/w upper 16 bits of TMSYNC timer */
+#define FM_FCNTR       0x41            /* r/w the 16-bit frame counter */
+#define FM_LCNTR       0x42            /* r/w the 16-bit lost counter */
+#define FM_ECNTR       0x43            /* r/w the 16-bit error counter */
+
+/* Supernet 3: extensions to old register block */
+#define        FM_FSCNTR       0x44            /* r/? Frame Strip Counter */
+#define        FM_FRSELREG     0x45            /* r/w Frame Selection Register */
+
+/* Supernet 3: extensions for 2. receive queue etc. */
+#define        FM_MDREG3       0x60            /* r/w Mode Register 3 */
+#define        FM_ST3U         0x61            /* read upper 16-bit of status reg 3 */
+#define        FM_ST3L         0x62            /* read lower 16-bit of status reg 3 */
+#define        FM_IMSK3U       0x63            /* r/w upper 16-bit of IMSK reg 3 */
+#define        FM_IMSK3L       0x64            /* r/w lower 16-bit of IMSK reg 3 */
+#define        FM_IVR          0x65            /* read Interrupt Vector register */
+#define        FM_IMR          0x66            /* r/w Interrupt mask register */
+/* 0x67        Hidden */
+#define        FM_RPR2         0x68            /* r/w the read ptr. for rec. qu. 2 */
+#define        FM_WPR2         0x69            /* r/w the write ptr. for rec. qu. 2 */
+#define        FM_SWPR2        0x6a            /* r/w the shadow wptr. for rec. q. 2 */
+#define        FM_EARV2        0x6b            /* r/w end addr of rec. qu. 2 */
+#define        FM_UNLCKDLY     0x6c            /* r/w Auto Unlock Delay register */
+                                       /* Bit 15-8: RECV2 unlock threshold */
+                                       /* Bit  7-0: RECV1 unlock threshold */
+/* 0x6f-0x73   Hidden */
+#define        FM_LTDPA1       0x79            /* r/w Last Trans desc ptr for A1 qu. */
+/* 0x80-0x9a   PLCS registers of built-in PLCS  (Supernet 3 only) */
+
+/* Supernet 3: Adderss Filter Registers */
+#define        FM_AFCMD        0xb0            /* r/w Address Filter Command Reg */
+#define        FM_AFSTAT       0xb2            /* r/w Address Filter Status Reg */
+#define        FM_AFBIST       0xb4            /* r/w Address Filter BIST signature */
+#define        FM_AFCOMP2      0xb6            /* r/w Address Filter Comparand 2 */
+#define        FM_AFCOMP1      0xb8            /* r/w Address Filter Comparand 1 */
+#define        FM_AFCOMP0      0xba            /* r/w Address Filter Comparand 0 */
+#define        FM_AFMASK2      0xbc            /* r/w Address Filter Mask 2 */
+#define        FM_AFMASK1      0xbe            /* r/w Address Filter Mask 1 */
+#define        FM_AFMASK0      0xc0            /* r/w Address Filter Mask 0 */
+#define        FM_AFPERS       0xc2            /* r/w Address Filter Personality Reg */
+
+/* Supernet 3: Orion (PDX?) Registers */
+#define        FM_ORBIST       0xd0            /* r/w Orion BIST signature */
+#define        FM_ORSTAT       0xd2            /* r/w Orion Status Register */
+
+
+/*
+ * Mode Register 1 (MDREG1)
+ */
+#define FM_RES0                0x0001          /* reserved */
+                                       /* SN3: other definition */
+#define        FM_XMTINH_HOLD  0x0002          /* transmit-inhibit/hold bit */
+                                       /* SN3: other definition */
+#define        FM_HOFLXI       0x0003          /* SN3: Hold / Flush / Inhibit */
+#define        FM_FULL_HALF    0x0004          /* full-duplex/half-duplex bit */
+#define        FM_LOCKTX       0x0008          /* lock-transmit-asynchr.-queues bit */
+#define FM_EXGPA0      0x0010          /* extended-group-addressing bit 0 */
+#define FM_EXGPA1      0x0020          /* extended-group-addressing bit 1 */
+#define FM_DISCRY      0x0040          /* disable-carry bit */
+                                       /* SN3: reserved */
+#define FM_SELRA       0x0080          /* select input from PHY (1=RA,0=RB) */
+
+#define FM_ADDET       0x0700          /* address detection */
+#define FM_MDAMA       (0<<8)          /* address detection : DA = MA */
+#define FM_MDASAMA     (1<<8)          /* address detection : DA=MA||SA=MA */
+#define        FM_MRNNSAFNMA   (2<<8)          /* rec. non-NSA frames DA=MA&&SA!=MA */
+#define        FM_MRNNSAF      (3<<8)          /* rec. non-NSA frames DA = MA */
+#define        FM_MDISRCV      (4<<8)          /* disable receive function */
+#define        FM_MRES0        (5<<8)          /* reserve */
+#define        FM_MLIMPROM     (6<<8)          /* limited-promiscuous mode */
+#define FM_MPROMISCOUS (7<<8)          /* address detection : promiscuous */
+
+#define FM_SELSA       0x0800          /* select-short-address bit */
+
+#define FM_MMODE       0x7000          /* mode select */
+#define FM_MINIT       (0<<12)         /* initialize */
+#define FM_MMEMACT     (1<<12)         /* memory activate */
+#define FM_MONLINESP   (2<<12)         /* on-line special */
+#define FM_MONLINE     (3<<12)         /* on-line (FDDI operational mode) */
+#define FM_MILOOP      (4<<12)         /* internal loopback */
+#define FM_MRES1       (5<<12)         /* reserved */
+#define FM_MRES2       (6<<12)         /* reserved */
+#define FM_MELOOP      (7<<12)         /* external loopback */
+
+#define        FM_SNGLFRM      0x8000          /* single-frame-receive mode */
+                                       /* SN3: reserved */
+
+#define        MDR1INIT        (FM_MINIT | FM_MDAMA)
+
+/*
+ * Mode Register 2 (MDREG2)
+ */
+#define        FM_AFULL        0x000f          /* 4-bit value (empty loc.in txqueue)*/
+#define        FM_RCVERR       0x0010          /* rec.-errored-frames bit */
+#define        FM_SYMCTL       0x0020          /* sysmbol-control bit */
+                                       /* SN3: reserved */
+#define        FM_SYNPRQ       0x0040          /* synchron.-NP-DMA-request bit */
+#define        FM_ENNPRQ       0x0080          /* enable-NP-DMA-request bit */
+#define        FM_ENHSRQ       0x0100          /* enable-host-request bit */
+#define        FM_RXFBB01      0x0600          /* rec. frame byte boundary bit0 & 1 */
+#define        FM_LSB          0x0800          /* determ. ordering of bytes in buffer*/
+#define        FM_PARITY       0x1000          /* 1 = even, 0 = odd */
+#define        FM_CHKPAR       0x2000          /* 1 = parity of 32-bit buffer BD-bus*/
+#define        FM_STRPFCS      0x4000          /* 1 = strips FCS field of rec.frame */
+#define        FM_BMMODE       0x8000          /* Buffer-Memory-Mode (1 = tag mode) */
+                                       /* SN3: 1 = tag, 0 = modified tag */
+
+/*
+ * Status Register 1, Upper 16 Bits (ST1U)
+ */
+#define FM_STEFRMS     0x0001          /* transmit end of frame: synchr. qu.*/
+#define FM_STEFRMA0    0x0002          /* transmit end of frame: asyn. qu.0 */
+#define FM_STEFRMA1    0x0004          /* transmit end of frame: asyn. qu.1 */
+#define FM_STEFRMA2    0x0008          /* transmit end of frame: asyn. qu.2 */
+                                       /* SN3: reserved */
+#define FM_STECFRMS    0x0010          /* transmit end of chain of syn. qu. */
+                                       /* SN3: reserved */
+#define FM_STECFRMA0   0x0020          /* transmit end of chain of asyn. q0 */
+                                       /* SN3: reserved */
+#define FM_STECFRMA1   0x0040          /* transmit end of chain of asyn. q1 */
+                                       /* SN3: STECMDA1 */
+#define FM_STECMDA1    0x0040          /* SN3: 'no description' */
+#define FM_STECFRMA2   0x0080          /* transmit end of chain of asyn. q2 */
+                                       /* SN3: reserved */
+#define        FM_STEXDONS     0x0100          /* transmit until XDONE in syn. qu. */
+#define        FM_STBFLA       0x0200          /* asynchr.-queue trans. buffer full */
+#define        FM_STBFLS       0x0400          /* synchr.-queue transm. buffer full */
+#define        FM_STXABRS      0x0800          /* synchr. queue transmit-abort */
+#define        FM_STXABRA0     0x1000          /* asynchr. queue 0 transmit-abort */
+#define        FM_STXABRA1     0x2000          /* asynchr. queue 1 transmit-abort */
+#define        FM_STXABRA2     0x4000          /* asynchr. queue 2 transmit-abort */
+                                       /* SN3: reserved */
+#define        FM_SXMTABT      0x8000          /* transmit abort */
+
+/*
+ * Status Register 1, Lower 16 Bits (ST1L)
+ */
+#define FM_SQLCKS      0x0001          /* queue lock for synchr. queue */
+#define FM_SQLCKA0     0x0002          /* queue lock for asynchr. queue 0 */
+#define FM_SQLCKA1     0x0004          /* queue lock for asynchr. queue 1 */
+#define FM_SQLCKA2     0x0008          /* queue lock for asynchr. queue 2 */
+                                       /* SN3: reserved */
+#define FM_STXINFLS    0x0010          /* transmit instruction full: syn. */
+                                       /* SN3: reserved */
+#define FM_STXINFLA0   0x0020          /* transmit instruction full: asyn.0 */
+                                       /* SN3: reserved */
+#define FM_STXINFLA1   0x0040          /* transmit instruction full: asyn.1 */
+                                       /* SN3: reserved */
+#define FM_STXINFLA2   0x0080          /* transmit instruction full: asyn.2 */
+                                       /* SN3: reserved */
+#define FM_SPCEPDS     0x0100          /* parity/coding error: syn. queue */
+#define FM_SPCEPDA0    0x0200          /* parity/coding error: asyn. queue0 */
+#define FM_SPCEPDA1    0x0400          /* parity/coding error: asyn. queue1 */
+#define FM_SPCEPDA2    0x0800          /* parity/coding error: asyn. queue2 */
+                                       /* SN3: reserved */
+#define FM_STBURS      0x1000          /* transmit buffer underrun: syn. q. */
+#define FM_STBURA0     0x2000          /* transmit buffer underrun: asyn.0 */
+#define FM_STBURA1     0x4000          /* transmit buffer underrun: asyn.1 */
+#define FM_STBURA2     0x8000          /* transmit buffer underrun: asyn.2 */
+                                       /* SN3: reserved */
+
+/*
+ * Status Register 2, Upper 16 Bits (ST2U)
+ */
+#define FM_SOTRBEC     0x0001          /* other beacon received */
+#define FM_SMYBEC      0x0002          /* my beacon received */
+#define FM_SBEC                0x0004          /* beacon state entered */
+#define FM_SLOCLM      0x0008          /* low claim received */
+#define FM_SHICLM      0x0010          /* high claim received */
+#define FM_SMYCLM      0x0020          /* my claim received */
+#define FM_SCLM                0x0040          /* claim state entered */
+#define FM_SERRSF      0x0080          /* error in special frame */
+#define FM_SNFSLD      0x0100          /* NP and FORMAC+ simultaneous load */
+#define FM_SRFRCTOV    0x0200          /* receive frame counter overflow */
+                                       /* SN3: reserved */
+#define FM_SRCVFRM     0x0400          /* receive frame */
+                                       /* SN3: reserved */
+#define FM_SRCVOVR     0x0800          /* receive FIFO overflow */
+#define FM_SRBFL       0x1000          /* receive buffer full */
+#define FM_SRABT       0x2000          /* receive abort */
+#define FM_SRBMT       0x4000          /* receive buffer empty */
+#define FM_SRCOMP      0x8000          /* receive complete. Nontag mode */
+
+/*
+ * Status Register 2, Lower 16 Bits (ST2L)
+ * Attention: SN3 docu shows these bits the other way around
+ */
+#define FM_SRES0       0x0001          /* reserved */
+#define FM_SESTRIPTK   0x0001          /* SN3: 'no description' */
+#define FM_STRTEXR     0x0002          /* TRT expired in claim | beacon st. */
+#define FM_SDUPCLM     0x0004          /* duplicate claim received */
+#define FM_SSIFG       0x0008          /* short interframe gap */
+#define FM_SFRMCTR     0x0010          /* frame counter overflow */
+#define FM_SERRCTR     0x0020          /* error counter overflow */
+#define FM_SLSTCTR     0x0040          /* lost counter overflow */
+#define FM_SPHINV      0x0080          /* PHY invalid */
+#define FM_SADET       0x0100          /* address detect */
+#define FM_SMISFRM     0x0200          /* missed frame */
+#define FM_STRTEXP     0x0400          /* TRT expired and late count > 0 */
+#define FM_STVXEXP     0x0800          /* TVX expired */
+#define FM_STKISS      0x1000          /* token issued */
+#define FM_STKERR      0x2000          /* token error */
+#define FM_SMULTDA     0x4000          /* multiple destination address */
+#define FM_SRNGOP      0x8000          /* ring operational */
+
+/*
+ * Supernet 3:
+ * Status Register 3, Upper 16 Bits (ST3U)
+ */
+#define        FM_SRQUNLCK1    0x0001          /* receive queue unlocked queue 1 */
+#define        FM_SRQUNLCK2    0x0002          /* receive queue unlocked queue 2 */
+#define        FM_SRPERRQ1     0x0004          /* receive parity error rx queue 1 */
+#define        FM_SRPERRQ2     0x0008          /* receive parity error rx queue 2 */
+                                       /* Bit 4-10: reserved */
+#define        FM_SRCVOVR2     0x0800          /* receive FIFO overfull rx queue 2 */
+#define        FM_SRBFL2       0x1000          /* receive buffer full rx queue 2 */
+#define        FM_SRABT2       0x2000          /* receive abort rx queue 2 */
+#define        FM_SRBMT2       0x4000          /* receive buf empty rx queue 2 */
+#define        FM_SRCOMP2      0x8000          /* receive comp rx queue 2 */
+
+/*
+ * Supernet 3:
+ * Status Register 3, Lower 16 Bits (ST3L)
+ */
+#define        FM_AF_BIST_DONE         0x0001  /* Address Filter BIST is done */
+#define        FM_PLC_BIST_DONE        0x0002  /* internal PLC Bist is done */
+#define        FM_PDX_BIST_DONE        0x0004  /* PDX BIST is done */
+                                       /* Bit  3: reserved */
+#define        FM_SICAMDAMAT           0x0010  /* Status internal CAM DA match */
+#define        FM_SICAMDAXACT          0x0020  /* Status internal CAM DA exact match */
+#define        FM_SICAMSAMAT           0x0040  /* Status internal CAM SA match */
+#define        FM_SICAMSAXACT          0x0080  /* Status internal CAM SA exact match */
+
+/*
+ * MAC State-Machine Register FM_STMCHN
+ */
+#define        FM_MDRTAG       0x0004          /* tag bit of long word read */
+#define        FM_SNPPND       0x0008          /* r/w from buffer mem. is pending */
+#define        FM_TXSTAT       0x0070          /* transmitter state machine state */
+#define        FM_RCSTAT       0x0380          /* receiver state machine state */
+#define        FM_TM01         0x0c00          /* indicate token mode */
+#define        FM_SIM          0x1000          /* indicate send immediate-mode */
+#define        FM_REV          0xe000          /* FORMAC Plus revision number */
+
+/*
+ * Supernet 3
+ * Mode Register 3
+ */
+#define        FM_MENRS        0x0001          /* Ena enhanced rec status encoding */
+#define        FM_MENXS        0x0002          /* Ena enhanced xmit status encoding */
+#define        FM_MENXCT       0x0004          /* Ena EXACT/INEXACT matching */
+#define        FM_MENAFULL     0x0008          /* Ena enh QCTRL encoding for AFULL */
+#define        FM_MEIND        0x0030          /* Ena enh A,C indicator settings */
+#define        FM_MENQCTRL     0x0040          /* Ena enh QCTRL encoding */
+#define        FM_MENRQAUNLCK  0x0080          /* Ena rec q auto unlock */
+#define        FM_MENDAS       0x0100          /* Ena DAS connections by cntr MUX */
+#define        FM_MENPLCCST    0x0200          /* Ena Counter Segm test in PLC blck */
+#define        FM_MENSGLINT    0x0400          /* Ena Vectored Interrupt reading */
+#define        FM_MENDRCV      0x0800          /* Ena dual receive queue operation */
+#define        FM_MENFCLOC     0x3000          /* Ena FC location within frm data */
+#define        FM_MENTRCMD     0x4000          /* Ena ASYNC1 xmit only after command */
+#define        FM_MENTDLPBK    0x8000          /* Ena TDAT to RDAT lkoopback */
+
+/*
+ * Supernet 3
+ * Frame Selection Register
+ */
+#define        FM_RECV1        0x000f          /* options for receive queue 1 */
+#define        FM_RCV1_ALL     (0<<0)          /* receive all frames */
+#define        FM_RCV1_LLC     (1<<0)          /* rec all LLC frames */
+#define        FM_RCV1_SMT     (2<<0)          /* rec all SMT frames */
+#define        FM_RCV1_NSMT    (3<<0)          /* rec non-SMT frames */
+#define        FM_RCV1_IMP     (4<<0)          /* rec Implementor frames */
+#define        FM_RCV1_MAC     (5<<0)          /* rec all MAC frames */
+#define        FM_RCV1_SLLC    (6<<0)          /* rec all sync LLC frames */
+#define        FM_RCV1_ALLC    (7<<0)          /* rec all async LLC frames */
+#define        FM_RCV1_VOID    (8<<0)          /* rec all void frames */
+#define        FM_RCV1_ALSMT   (9<<0)          /* rec all async LLC & SMT frames */
+#define        FM_RECV2        0x00f0          /* options for receive queue 2 */
+#define        FM_RCV2_ALL     (0<<4)          /* receive all other frames */
+#define        FM_RCV2_LLC     (1<<4)          /* rec all LLC frames */
+#define        FM_RCV2_SMT     (2<<4)          /* rec all SMT frames */
+#define        FM_RCV2_NSMT    (3<<4)          /* rec non-SMT frames */
+#define        FM_RCV2_IMP     (4<<4)          /* rec Implementor frames */
+#define        FM_RCV2_MAC     (5<<4)          /* rec all MAC frames */
+#define        FM_RCV2_SLLC    (6<<4)          /* rec all sync LLC frames */
+#define        FM_RCV2_ALLC    (7<<4)          /* rec all async LLC frames */
+#define        FM_RCV2_VOID    (8<<4)          /* rec all void frames */
+#define        FM_RCV2_ALSMT   (9<<4)          /* rec all async LLC & SMT frames */
+#define        FM_ENXMTADSWAP  0x4000          /* enh rec addr swap (phys -> can) */
+#define        FM_ENRCVADSWAP  0x8000          /* enh tx addr swap (can -> phys) */
+
+/*
+ * Supernet 3:
+ * Address Filter Command Register (AFCMD)
+ */
+#define        FM_INST         0x0007          /* Address Filter Operation */
+#define FM_IINV_CAM    (0<<0)          /* Invalidate CAM */
+#define FM_IWRITE_CAM  (1<<0)          /* Write CAM */
+#define FM_IREAD_CAM   (2<<0)          /* Read CAM */
+#define FM_IRUN_BIST   (3<<0)          /* Run BIST */
+#define FM_IFIND       (4<<0)          /* Find */
+#define FM_IINV                (5<<0)          /* Invalidate */
+#define FM_ISKIP       (6<<0)          /* Skip */
+#define FM_ICL_SKIP    (7<<0)          /* Clear all SKIP bits */
+
+/*
+ * Supernet 3:
+ * Address Filter Status Register (AFSTAT)
+ */
+                                       /* Bit  0-4: reserved */
+#define        FM_REV_NO       0x00e0          /* Revision Number of Address Filter */
+#define        FM_BIST_DONE    0x0100          /* BIST complete */
+#define        FM_EMPTY        0x0200          /* CAM empty */
+#define        FM_ERROR        0x0400          /* Error (improper operation) */
+#define        FM_MULT         0x0800          /* Multiple Match */
+#define        FM_EXACT        0x1000          /* Exact Match */
+#define        FM_FOUND        0x2000          /* Comparand found in CAM */
+#define        FM_FULL         0x4000          /* CAM full */
+#define        FM_DONE         0x8000          /* DONE indicator */
+
+/*
+ * Supernet 3:
+ * BIST Signature Register (AFBIST)
+ */
+#define        AF_BIST_SIGNAT  0x0553          /* Address Filter BIST Signature */
+
+/*
+ * Supernet 3:
+ * Personality Register (AFPERS)
+ */
+#define        FM_VALID        0x0001          /* CAM Entry Valid */
+#define        FM_DA           0x0002          /* Destination Address */
+#define        FM_DAX          0x0004          /* Destination Address Exact */
+#define        FM_SA           0x0008          /* Source Address */
+#define        FM_SAX          0x0010          /* Source Address Exact */
+#define        FM_SKIP         0x0020          /* Skip this entry */
+
+/*
+ * instruction set for command register 1 (NPADDR6-0 = 0x00)
+ */
+#define FM_IRESET      0x01            /* software reset */
+#define FM_IRMEMWI     0x02            /* load Memory Data Reg., inc MARR */
+#define FM_IRMEMWO     0x03            /* load MDR from buffer memory, n.i. */
+#define FM_IIL         0x04            /* idle/listen */
+#define FM_ICL         0x05            /* claim/listen */
+#define FM_IBL         0x06            /* beacon/listen */
+#define FM_ILTVX       0x07            /* load TVX timer from TVX reg */
+#define FM_INRTM       0x08            /* nonrestricted token mode */
+#define FM_IENTM       0x09            /* enter nonrestricted token mode */
+#define FM_IERTM       0x0a            /* enter restricted token mode */
+#define FM_IRTM                0x0b            /* restricted token mode */
+#define FM_ISURT       0x0c            /* send unrestricted token */
+#define FM_ISRT                0x0d            /* send restricted token */
+#define FM_ISIM                0x0e            /* enter send-immediate mode */
+#define FM_IESIM       0x0f            /* exit send-immediate mode */
+#define FM_ICLLS       0x11            /* clear synchronous queue lock */
+#define FM_ICLLA0      0x12            /* clear asynchronous queue 0 lock */
+#define FM_ICLLA1      0x14            /* clear asynchronous queue 1 lock */
+#define FM_ICLLA2      0x18            /* clear asynchronous queue 2 lock */
+                                       /* SN3: reserved */
+#define FM_ICLLR       0x20            /* clear receive queue (SN3:1) lock */
+#define FM_ICLLR2      0x21            /* SN3: clear receive queue 2 lock */
+#define FM_ITRXBUS     0x22            /* SN3: Tristate X-Bus (SAS only) */
+#define FM_IDRXBUS     0x23            /* SN3: drive X-Bus */
+#define FM_ICLLAL      0x3f            /* clear all queue locks */
+
+/*
+ * instruction set for command register 2 (NPADDR6-0 = 0x01)
+ */
+#define FM_ITRS                0x01            /* transmit synchronous queue */
+                                       /* SN3: reserved */
+#define FM_ITRA0       0x02            /* transmit asynchronous queue 0 */
+                                       /* SN3: reserved */
+#define FM_ITRA1       0x04            /* transmit asynchronous queue 1 */
+                                       /* SN3: reserved */
+#define FM_ITRA2       0x08            /* transmit asynchronous queue 2 */
+                                       /* SN3: reserved */
+#define FM_IACTR       0x10            /* abort current transmit activity */
+#define FM_IRSTQ       0x20            /* reset transmit queues */
+#define FM_ISTTB       0x30            /* set tag bit */
+#define FM_IERSF       0x40            /* enable receive single frame */
+                                       /* SN3: reserved */
+#define        FM_ITR          0x50            /* SN3: Transmit Command */
+
+
+/*
+ *     defines for PLC (Am79C864)
+ */
+
+/*
+ *  PLC read/write (r/w) registers
+ */
+#define PL_CNTRL_A     0x00            /* control register A (r/w) */
+#define PL_CNTRL_B     0x01            /* control register B (r/w) */
+#define PL_INTR_MASK   0x02            /* interrupt mask (r/w) */
+#define PL_XMIT_VECTOR 0x03            /* transmit vector register (r/w) */
+#define PL_VECTOR_LEN  0x04            /* transmit vector length (r/w) */
+#define PL_LE_THRESHOLD        0x05            /* link error event threshold (r/w) */
+#define PL_C_MIN       0x06            /* minimum connect state time (r/w) */
+#define PL_TL_MIN      0x07            /* min. line state transmit t. (r/w) */
+#define PL_TB_MIN      0x08            /* minimum break time (r/w) */
+#define PL_T_OUT       0x09            /* signal timeout (r/w) */
+#define PL_CNTRL_C     0x0a            /* control register C (r/w) */
+#define PL_LC_LENGTH   0x0b            /* link confidence test time (r/w) */
+#define PL_T_SCRUB     0x0c            /* scrub time = MAC TVX (r/w) */
+#define PL_NS_MAX      0x0d            /* max. noise time before break (r/w)*/
+#define PL_TPC_LOAD_V  0x0e            /* TPC timer load value (write only) */
+#define PL_TNE_LOAD_V  0x0f            /* TNE timer load value (write only) */
+#define PL_STATUS_A    0x10            /* status register A (read only) */
+#define PL_STATUS_B    0x11            /* status register B (read only) */
+#define PL_TPC         0x12            /* timer for PCM (ro) [20.48 us] */
+#define PL_TNE         0x13            /* time of noise event [0.32 us] */
+#define PL_CLK_DIV     0x14            /* TNE clock divider (read only) */
+#define PL_BIST_SIGNAT 0x15            /* built in self test signature (ro)*/
+#define PL_RCV_VECTOR  0x16            /* receive vector reg. (read only) */
+#define PL_INTR_EVENT  0x17            /* interrupt event reg. (read only) */
+#define PL_VIOL_SYM_CTR        0x18            /* violation symbol count. (read o) */
+#define PL_MIN_IDLE_CTR        0x19            /* minimum idle counter (read only) */
+#define PL_LINK_ERR_CTR        0x1a            /* link error event ctr.(read only) */
+#ifdef MOT_ELM
+#define        PL_T_FOT_ASS    0x1e            /* FOTOFF Assert Timer */
+#define        PL_T_FOT_DEASS  0x1f            /* FOTOFF Deassert Timer */
+#endif /* MOT_ELM */
+
+#ifdef MOT_ELM
+/*
+ * Special Quad-Elm Registers.
+ * A Quad-ELM consists of for ELMs and these additional registers.
+ */
+#define        QELM_XBAR_W     0x80            /* Crossbar Control ELM W */
+#define        QELM_XBAR_X     0x81            /* Crossbar Control ELM X */
+#define        QELM_XBAR_Y     0x82            /* Crossbar Control ELM Y */
+#define        QELM_XBAR_Z     0x83            /* Crossbar Control ELM Z */
+#define        QELM_XBAR_P     0x84            /* Crossbar Control Bus P */
+#define        QELM_XBAR_S     0x85            /* Crossbar Control Bus S */
+#define        QELM_XBAR_R     0x86            /* Crossbar Control Bus R */
+#define        QELM_WR_XBAR    0x87            /* Write the Crossbar now (write) */
+#define        QELM_CTR_W      0x88            /* Counter W */
+#define        QELM_CTR_X      0x89            /* Counter X */
+#define        QELM_CTR_Y      0x8a            /* Counter Y */
+#define        QELM_CTR_Z      0x8b            /* Counter Z */
+#define        QELM_INT_MASK   0x8c            /* Interrupt mask register */
+#define        QELM_INT_DATA   0x8d            /* Interrupt data (event) register */
+#define        QELM_ELMB       0x00            /* Elm base */
+#define        QELM_ELM_SIZE   0x20            /* ELM size */
+#endif /* MOT_ELM */
+/*
+ * PLC control register A (PL_CNTRL_A: log. addr. 0x00)
+ * It is used for timer configuration, specification of PCM MAINT state option,
+ * counter interrupt frequency, PLC data path config. and Built In Self Test.
+ */
+#define        PL_RUN_BIST     0x0001          /* begin running its Built In Self T.*/
+#define        PL_RF_DISABLE   0x0002          /* disable the Repeat Filter state m.*/
+#define        PL_SC_REM_LOOP  0x0004          /* remote loopback path */
+#define        PL_SC_BYPASS    0x0008          /* by providing a physical bypass */
+#define        PL_LM_LOC_LOOP  0x0010          /* loop path just after elastic buff.*/
+#define        PL_EB_LOC_LOOP  0x0020          /* loop path just prior to PDT/PDR IF*/
+#define        PL_FOT_OFF      0x0040          /* assertion of /FOTOFF pin of PLC */
+#define        PL_LOOPBACK     0x0080          /* it cause the /LPBCK pin ass. low */
+#define        PL_MINI_CTR_INT 0x0100          /* partially contr. when bit is ass. */
+#define        PL_VSYM_CTR_INT 0x0200          /* controls when int bit is asserted */
+#define        PL_ENA_PAR_CHK  0x0400          /* enable parity check */
+#define        PL_REQ_SCRUB    0x0800          /* limited access to scrub capability*/
+#define        PL_TPC_16BIT    0x1000          /* causes the TPC as a 16 bit timer */
+#define        PL_TNE_16BIT    0x2000          /* causes the TNE as a 16 bit timer */
+#define        PL_NOISE_TIMER  0x4000          /* allows the noise timing function */
+
+/*
+ * PLC control register B (PL_CNTRL_B: log. addr. 0x01)
+ * It contains signals and requeste to direct the process of PCM and it is also
+ * used to control the Line State Match interrupt.
+ */
+#define        PL_PCM_CNTRL    0x0003          /* control PCM state machine */
+#define        PL_PCM_NAF      (0)             /* state is not affected */
+#define        PL_PCM_START    (1)             /* goes to the BREAK state */
+#define        PL_PCM_TRACE    (2)             /* goes to the TRACE state */
+#define        PL_PCM_STOP     (3)             /* goes to the OFF state */
+
+#define        PL_MAINT        0x0004          /* if OFF state --> MAINT state */
+#define        PL_LONG         0x0008          /* perf. a long Link Confid.Test(LCT)*/
+#define        PL_PC_JOIN      0x0010          /* if NEXT state --> JOIN state */
+
+#define        PL_PC_LOOP      0x0060          /* loopback used in the LCT */
+#define        PL_NOLCT        (0<<5)          /* no LCT is performed */
+#define        PL_TPDR         (1<<5)          /* PCM asserts transmit PDR */
+#define        PL_TIDLE        (2<<5)          /* PCM asserts transmit idle */
+#define        PL_RLBP         (3<<5)          /* trans. PDR & remote loopb. path */
+
+#define        PL_CLASS_S      0x0080          /* signif. that single att. station */
+
+#define        PL_MAINT_LS     0x0700          /* line state while in the MAINT st. */
+#define        PL_M_QUI0       (0<<8)          /* transmit QUIET line state */
+#define        PL_M_IDLE       (1<<8)          /* transmit IDLE line state */
+#define        PL_M_HALT       (2<<8)          /* transmit HALT line state */
+#define        PL_M_MASTR      (3<<8)          /* transmit MASTER line state */
+#define        PL_M_QUI1       (4<<8)          /* transmit QUIET line state */
+#define        PL_M_QUI2       (5<<8)          /* transmit QUIET line state */
+#define        PL_M_TPDR       (6<<8)          /* tr. PHY_DATA requ.-symbol is tr.ed*/
+#define        PL_M_QUI3       (7<<8)          /* transmit QUIET line state */
+
+#define        PL_MATCH_LS     0x7800          /* line state to be comp. with curr.*/
+#define        PL_I_ANY        (0<<11)         /* Int. on any change in *_LINE_ST */
+#define        PL_I_IDLE       (1<<11)         /* Interrupt on IDLE line state */
+#define        PL_I_HALT       (2<<11)         /* Interrupt on HALT line state */
+#define        PL_I_MASTR      (4<<11)         /* Interrupt on MASTER line state */
+#define        PL_I_QUIET      (8<<11)         /* Interrupt on QUIET line state */
+
+#define        PL_CONFIG_CNTRL 0x8000          /* control over scrub, byp. & loopb.*/
+
+/*
+ * PLC control register C (PL_CNTRL_C: log. addr. 0x0a)
+ * It contains the scrambling control registers (PLC-S only)
+ */
+#define PL_C_CIPHER_ENABLE     (1<<0)  /* enable scrambler */
+#define PL_C_CIPHER_LPBCK      (1<<1)  /* loopback scrambler */
+#define PL_C_SDOFF_ENABLE      (1<<6)  /* enable SDOFF timer */
+#define PL_C_SDON_ENABLE       (1<<7)  /* enable SDON timer */
+#ifdef MOT_ELM
+#define PL_C_FOTOFF_CTRL       (3<<2)  /* FOTOFF timer control */
+#define PL_C_FOTOFF_TIM                (0<<2)  /* FOTOFF use timer for (de)-assert */
+#define PL_C_FOTOFF_INA                (2<<2)  /* FOTOFF forced inactive */
+#define PL_C_FOTOFF_ACT                (3<<2)  /* FOTOFF forced active */
+#define PL_C_FOTOFF_SRCE       (1<<4)  /* FOTOFF source is PCM state != OFF */
+#define        PL_C_RXDATA_EN          (1<<5)  /* Rec scr data forced to 0 */
+#define        PL_C_SDNRZEN            (1<<8)  /* Monitor rec descr. data for act */
+#else  /* nMOT_ELM */
+#define PL_C_FOTOFF_CTRL       (3<<8)  /* FOTOFF timer control */
+#define PL_C_FOTOFF_0          (0<<8)  /* timer off */
+#define PL_C_FOTOFF_30         (1<<8)  /* 30uS */
+#define PL_C_FOTOFF_50         (2<<8)  /* 50uS */
+#define PL_C_FOTOFF_NEVER      (3<<8)  /* never */
+#define PL_C_SDON_TIMER                (3<<10) /* SDON timer control */
+#define PL_C_SDON_084          (0<<10) /* 0.84 uS */
+#define PL_C_SDON_132          (1<<10) /* 1.32 uS */
+#define PL_C_SDON_252          (2<<10) /* 2.52 uS */
+#define PL_C_SDON_512          (3<<10) /* 5.12 uS */
+#define PL_C_SOFF_TIMER                (3<<12) /* SDOFF timer control */
+#define PL_C_SOFF_076          (0<<12) /* 0.76 uS */
+#define PL_C_SOFF_132          (1<<12) /* 1.32 uS */
+#define PL_C_SOFF_252          (2<<12) /* 2.52 uS */
+#define PL_C_SOFF_512          (3<<12) /* 5.12 uS */
+#define PL_C_TSEL              (3<<14) /* scrambler path select */
+#endif /* nMOT_ELM */
+
+/*
+ * PLC status register A (PL_STATUS_A: log. addr. 0x10)
+ * It is used to report status information to the Node Processor about the 
+ * Line State Machine (LSM).
+ */
+#ifdef MOT_ELM
+#define PLC_INT_MASK   0xc000          /* ELM integration bits in status A */
+#define PLC_INT_C      0x0000          /* ELM Revision Band C */
+#define PLC_INT_CAMEL  0x4000          /* ELM integrated into CAMEL */
+#define PLC_INT_QE     0x8000          /* ELM integrated into Quad ELM */
+#define PLC_REV_MASK   0x3800          /* revision bits in status A */
+#define PLC_REVISION_B 0x0000          /* rev bits for ELM Rev B */
+#define PLC_REVISION_QA        0x0800          /* rev bits for ELM core in QELM-A */
+#else  /* nMOT_ELM */
+#define PLC_REV_MASK   0xf800          /* revision bits in status A */
+#define PLC_REVISION_A 0x0000          /* revision bits for PLC */
+#define PLC_REVISION_S 0xf800          /* revision bits for PLC-S */
+#define PLC_REV_SN3    0x7800          /* revision bits for PLC-S in IFCP */
+#endif /* nMOT_ELM */
+#define        PL_SYM_PR_CTR   0x0007          /* contains the LSM symbol pair Ctr. */
+#define        PL_UNKN_LINE_ST 0x0008          /* unknown line state bit from LSM */
+#define        PL_LSM_STATE    0x0010          /* state bit of LSM */
+
+#define        PL_LINE_ST      0x00e0          /* contains recogn. line state of LSM*/
+#define        PL_L_NLS        (0<<5)          /* noise line state */
+#define        PL_L_ALS        (1<<5)          /* activ line state */
+#define        PL_L_UND        (2<<5)          /* undefined */
+#define        PL_L_ILS4       (3<<5)          /* idle l. s. (after 4 idle symbols) */
+#define        PL_L_QLS        (4<<5)          /* quiet line state */
+#define        PL_L_MLS        (5<<5)          /* master line state */
+#define        PL_L_HLS        (6<<5)          /* halt line state */
+#define        PL_L_ILS16      (7<<5)          /* idle line state (after 16 idle s.)*/
+
+#define        PL_PREV_LINE_ST 0x0300          /* value of previous line state */
+#define        PL_P_QLS        (0<<8)          /* quiet line state */
+#define        PL_P_MLS        (1<<8)          /* master line state */
+#define        PL_P_HLS        (2<<8)          /* halt line state */
+#define        PL_P_ILS16      (3<<8)          /* idle line state (after 16 idle s.)*/
+
+#define        PL_SIGNAL_DET   0x0400          /* 1=that signal detect is deasserted*/
+
+
+/*
+ * PLC status register B (PL_STATUS_B: log. addr. 0x11)
+ * It contains signals and status from the repeat filter and PCM state machine.
+ */
+#define        PL_BREAK_REASON 0x0007          /* reason for PCM state mach.s to br.*/
+#define        PL_B_NOT        (0)             /* PCM SM has not gone to BREAK state*/
+#define        PL_B_PCS        (1)             /* PC_Start issued */
+#define        PL_B_TPC        (2)             /* TPC timer expired after T_OUT */
+#define        PL_B_TNE        (3)             /* TNE timer expired after NS_MAX */
+#define        PL_B_QLS        (4)             /* quit line state detected */
+#define        PL_B_ILS        (5)             /* idle line state detected */
+#define        PL_B_HLS        (6)             /* halt line state detected */
+
+#define        PL_TCF          0x0008          /* transmit code flag (start exec.) */
+#define        PL_RCF          0x0010          /* receive code flag (start exec.) */
+#define        PL_LSF          0x0020          /* line state flag (l.s. has been r.)*/
+#define        PL_PCM_SIGNAL   0x0040          /* indic. that XMIT_VECTOR hb.written*/
+
+#define        PL_PCM_STATE    0x0780          /* state bits of PCM state machine */
+#define        PL_PC0          (0<<7)          /* OFF     - when /RST or PCM_CNTRL */
+#define        PL_PC1          (1<<7)          /* BREAK   - entry point in start PCM*/
+#define        PL_PC2          (2<<7)          /* TRACE   - to localize stuck Beacon*/
+#define        PL_PC3          (3<<7)          /* CONNECT - synchronize ends of conn*/
+#define        PL_PC4          (4<<7)          /* NEXT    - to separate the signalng*/
+#define        PL_PC5          (5<<7)          /* SIGNAL  - PCM trans/rec. bit infos*/
+#define        PL_PC6          (6<<7)          /* JOIN    - 1. state to activ conn. */
+#define        PL_PC7          (7<<7)          /* VERIFY  - 2. - " - (3. ACTIVE) */
+#define        PL_PC8          (8<<7)          /* ACTIVE  - PHY has been incorporated*/
+#define        PL_PC9          (9<<7)          /* MAINT   - for test purposes or so 
+                                          that PCM op. completely in softw. */
+
+#define        PL_PCI_SCRUB    0x0800          /* scrubbing function is being exec. */
+
+#define        PL_PCI_STATE    0x3000          /* Physical Connect. Insertion SM */
+#define        PL_CI_REMV      (0<<12)         /* REMOVED */
+#define        PL_CI_ISCR      (1<<12)         /* INSERT_SCRUB */
+#define        PL_CI_RSCR      (2<<12)         /* REMOVE_SCRUB */
+#define        PL_CI_INS       (3<<12)         /* INSERTED */
+
+#define        PL_RF_STATE     0xc000          /* state bit of repeate filter SM */
+#define        PL_RF_REPT      (0<<14)         /* REPEAT */
+#define        PL_RF_IDLE      (1<<14)         /* IDLE */
+#define        PL_RF_HALT1     (2<<14)         /* HALT1 */
+#define        PL_RF_HALT2     (3<<14)         /* HALT2 */
+
+
+/*
+ * PLC interrupt event register (PL_INTR_EVENT: log. addr. 0x17)
+ * It is read only and is clearde whenever it is read!
+ * It is used by the PLC to report events to the node processor.
+ */
+#define        PL_PARITY_ERR   0x0001          /* p. error h.b.detected on TX9-0 inp*/
+#define        PL_LS_MATCH     0x0002          /* l.s.== l.s. PLC_CNTRL_B's MATCH_LS*/
+#define        PL_PCM_CODE     0x0004          /* transmit&receive | LCT complete */
+#define        PL_TRACE_PROP   0x0008          /* master l.s. while PCM ACTIV|TRACE */
+#define        PL_SELF_TEST    0x0010          /* QUIET|HALT while PCM in TRACE st. */
+#define        PL_PCM_BREAK    0x0020          /* PCM has entered the BREAK state */
+#define        PL_PCM_ENABLED  0x0040          /* asserted SC_JOIN, scrub. & ACTIV */
+#define        PL_TPC_EXPIRED  0x0080          /* TPC timer reached zero */
+#define        PL_TNE_EXPIRED  0x0100          /* TNE timer reached zero */
+#define        PL_EBUF_ERR     0x0200          /* elastic buff. det. over-|underflow*/
+#define        PL_PHYINV       0x0400          /* physical layer invalid signal */
+#define        PL_VSYM_CTR     0x0800          /* violation symbol counter has incr.*/
+#define        PL_MINI_CTR     0x1000          /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
+#define        PL_LE_CTR       0x2000          /* link error event counter */
+#define        PL_LSDO         0x4000          /* SDO input pin changed to a 1 */
+#define        PL_NP_ERR       0x8000          /* NP has requested to r/w an inv. r.*/
+
+/*
+ * The PLC interrupt mask register (PL_INTR_MASK: log. addr. 0x02) constr. is
+ * equal PL_INTR_EVENT register.
+ * For each set bit, the setting of corresponding bit generate an int to NP. 
+ */
+
+#ifdef MOT_ELM
+/*
+ * Quad ELM Crosbar Control register values (QELM_XBAR_?)
+ */
+#define        QELM_XOUT_IDLE  0x0000          /* Idles/Passthrough */
+#define        QELM_XOUT_P     0x0001          /* Output to: Bus P */
+#define        QELM_XOUT_S     0x0002          /* Output to: Bus S */
+#define        QELM_XOUT_R     0x0003          /* Output to: Bus R */
+#define        QELM_XOUT_W     0x0004          /* Output to: ELM W */
+#define        QELM_XOUT_X     0x0005          /* Output to: ELM X */
+#define        QELM_XOUT_Y     0x0006          /* Output to: ELM Y */
+#define        QELM_XOUT_Z     0x0007          /* Output to: ELM Z */
+
+/*
+ * Quad ELM Interrupt data and event registers.
+ */
+#define        QELM_NP_ERR     (1<<15)         /* Node Processor Error */
+#define        QELM_COUNT_Z    (1<<7)          /* Counter Z Interrupt */
+#define        QELM_COUNT_Y    (1<<6)          /* Counter Y Interrupt */
+#define        QELM_COUNT_X    (1<<5)          /* Counter X Interrupt */
+#define        QELM_COUNT_W    (1<<4)          /* Counter W Interrupt */
+#define        QELM_ELM_Z      (1<<3)          /* ELM Z Interrupt */
+#define        QELM_ELM_Y      (1<<2)          /* ELM Y Interrupt */
+#define        QELM_ELM_X      (1<<1)          /* ELM X Interrupt */
+#define        QELM_ELM_W      (1<<0)          /* ELM W Interrupt */
+#endif /* MOT_ELM */
+/*
+ * PLC Timing Parameters
+ */
+#define        TP_C_MIN        0xff9c  /*   2    ms */
+#define        TP_TL_MIN       0xfff0  /*   0.3  ms */
+#define        TP_TB_MIN       0xff10  /*   5    ms */
+#define        TP_T_OUT        0xd9db  /* 200    ms */
+#define        TP_LC_LENGTH    0xf676  /*  50    ms */
+#define        TP_LC_LONGLN    0xa0a2  /* 500    ms */
+#define        TP_T_SCRUB      0xff6d  /*   3.5  ms */
+#define        TP_NS_MAX       0xf021  /*   1.3   ms */
+
+/*
+ * BIST values
+ */
+#define PLC_BIST       0x6ecd          /* BIST signature for PLC */
+#define PLCS_BIST      0x5b6b          /* BIST signature for PLC-S */
+#define        PLC_ELM_B_BIST  0x6ecd          /* BIST signature of ELM Rev. B */
+#define        PLC_ELM_D_BIST  0x5b6b          /* BIST signature of ELM Rev. D */
+#define        PLC_CAM_A_BIST  0x9e75          /* BIST signature of CAMEL Rev. A */
+#define        PLC_CAM_B_BIST  0x5b6b          /* BIST signature of CAMEL Rev. B */
+#define        PLC_IFD_A_BIST  0x9e75          /* BIST signature of IFDDI Rev. A */
+#define        PLC_IFD_B_BIST  0x5b6b          /* BIST signature of IFDDI Rev. B */
+#define        PLC_QELM_A_BIST 0x5b6b          /* BIST signature of QELM Rev. A */
+
+/*
+       FDDI board recources    
+ */
+
+/*
+ * request register array (log. addr: RQA_A + a<<1 {a=0..7}) write only.
+ * It specifies to FORMAC+ the type of buffer memory access the host requires.
+ */
+#define        RQ_NOT          0               /* not request */
+#define        RQ_RES          1               /* reserved */
+#define        RQ_SFW          2               /* special frame write */
+#define        RQ_RRQ          3               /* read request: receive queue */
+#define        RQ_WSQ          4               /* write request: synchronous queue */
+#define        RQ_WA0          5               /* write requ.: asynchronous queue 0 */
+#define        RQ_WA1          6               /* write requ.: asynchronous queue 1 */
+#define        RQ_WA2          7               /* write requ.: asynchronous queue 2 */
+
+#define        SZ_LONG         (sizeof(long))
+
+/*
+ * FDDI defaults
+ * NOTE : In the ANSI docs, times are specified in units of "symbol time".
+ *       AMD chips use BCLK as unit. 1 BCKL == 2 symbols
+ */
+#define        COMPLREF        ((u_long)32*256*256)    /* two's complement 21 bit */
+#define MSTOBCLK(x)    ((u_long)(x)*12500L)
+#define MSTOTVX(x)     (((u_long)(x)*1000L)/80/255)
+
+#endif /* _SUPERNET_ */
diff --git a/drivers/net/fddi/skfp/h/targethw.h b/drivers/net/fddi/skfp/h/targethw.h
new file mode 100644 (file)
index 0000000..842a690
--- /dev/null
@@ -0,0 +1,138 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        _TARGETHW_
+#define _TARGETHW_
+
+       /*
+        *  PCI Watermark definition
+        */
+#ifdef PCI
+#define        RX_WATERMARK    24
+#define TX_WATERMARK   24
+#define SK_ML_ID_1     0x20
+#define SK_ML_ID_2     0x30
+#endif
+
+#include       "skfbi.h"
+#ifndef TAG_MODE       
+#include       "fplus.h"
+#else
+#include       "fplustm.h"
+#endif
+
+#ifndef        HW_PTR
+#define HW_PTR  void __iomem *
+#endif
+
+#ifdef MULT_OEM
+#define        OI_STAT_LAST            0       /* end of OEM data base */
+#define        OI_STAT_PRESENT         1       /* entry present but not empty */
+#define        OI_STAT_VALID           2       /* holds valid ID, but is not active */ 
+#define        OI_STAT_ACTIVE          3       /* holds valid ID, entry is active */
+                                       /* active = adapter is supported */
+
+/* Memory representation of IDs must match representation in adapter. */
+struct s_oem_ids {
+       u_char  oi_status ;             /* Stat: last, present, valid, active */
+       u_char  oi_mark[5] ;            /* "PID00" .. "PID07" ..        */
+       u_char  oi_id[4] ;              /* id bytes, representation as  */
+                                       /* defined by hardware,         */      
+#ifdef PCI
+       u_char  oi_sub_id[4] ;          /* sub id bytes, representation as */
+                                       /* defined by hardware,         */
+#endif
+} ;
+#endif /* MULT_OEM */
+
+
+struct s_smt_hw {
+       /*
+        * global
+        */
+       HW_PTR  iop ;                   /* IO base address */
+       short   dma ;                   /* DMA channel */
+       short   irq ;                   /* IRQ level */
+       short   eprom ;                 /* FLASH prom */
+
+#ifndef SYNC
+       u_short n_a_send ;              /* pending send requests */
+#endif
+
+#if    defined(PCI)
+       short   slot ;                  /* slot number */
+       short   max_slots ;             /* maximum number of slots */
+       short   wdog_used ;             /* TRUE if the watch dog is used */
+#endif
+
+#ifdef PCI
+       u_short pci_handle ;            /* handle to access the BIOS func */
+       u_long  is_imask ;              /* int maske for the int source reg */
+       u_long  phys_mem_addr ;         /* physical memory address */
+       u_short mc_dummy ;              /* work around for MC compiler bug */   
+       /*
+        * state of the hardware
+        */
+       u_short hw_state ;              /* started or stopped */
+
+#define        STARTED         1
+#define        STOPPED         0
+
+       int     hw_is_64bit ;           /* does we have a 64 bit adapter */
+#endif
+
+#ifdef TAG_MODE
+       u_long  pci_fix_value ;         /* value parsed by PCIFIX */
+#endif
+
+       /*
+        * hwt.c
+        */
+       u_long  t_start ;               /* HWT start */
+       u_long  t_stop ;                /* HWT stop */
+       u_short timer_activ ;           /* HWT timer active */
+
+       /*
+        * PIC
+        */
+       u_char  pic_a1 ;
+       u_char  pic_21 ;
+
+       /*
+        * GENERIC ; do not modify beyond this line
+        */
+
+       /*
+        * physical and canonical address
+        */
+       struct fddi_addr fddi_home_addr ;
+       struct fddi_addr fddi_canon_addr ;
+       struct fddi_addr fddi_phys_addr ;
+
+       /*
+        * mac variables
+        */
+       struct mac_parameter mac_pa ;   /* tmin, tmax, tvx, treq .. */
+       struct mac_counter mac_ct ;     /* recv., lost, error  */
+       u_short mac_ring_is_up ;        /* ring is up flag */
+
+       struct s_smt_fp fp ;            /* formac+ */
+
+#ifdef MULT_OEM
+       struct s_oem_ids *oem_id ;      /* pointer to selected id */
+       int oem_min_status ;            /* IDs to take care of */
+#endif /* MULT_OEM */
+
+} ;
+#endif
diff --git a/drivers/net/fddi/skfp/h/targetos.h b/drivers/net/fddi/skfp/h/targetos.h
new file mode 100644 (file)
index 0000000..53bacc1
--- /dev/null
@@ -0,0 +1,165 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ *     Operating system specific definitions for driver and
+ *     hardware module.
+ */
+
+#ifndef        TARGETOS_H
+#define TARGETOS_H
+
+
+//-------- those should go into include/linux/pci.h
+#define PCI_VENDOR_ID_SK               0x1148
+#define PCI_DEVICE_ID_SK_FP            0x4000
+//--------
+
+
+
+//-------- those should go into include/linux/if_fddi.h
+#define FDDI_MAC_HDR_LEN 13
+
+#define FDDI_RII       0x01 /* routing information bit */
+#define FDDI_RCF_DIR_BIT 0x80
+#define FDDI_RCF_LEN_MASK 0x1f
+#define FDDI_RCF_BROADCAST 0x8000
+#define FDDI_RCF_LIMITED_BROADCAST 0xA000
+#define FDDI_RCF_FRAME2K 0x20
+#define FDDI_RCF_FRAME4K 0x30
+//--------
+
+
+#undef ADDR
+
+#include <asm/io.h>
+#include <linux/netdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+// is redefined by linux, but we need our definition
+#undef ADDR
+#ifdef MEM_MAPPED_IO
+#define        ADDR(a) (smc->hw.iop+(a))
+#else
+#define        ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), (smc->hw.iop+( ((a)&0x7F) | ((a)>>7 ? 0x80:0)) )) : (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
+#endif
+
+#include "hwmtm.h"
+
+#define TRUE  1
+#define FALSE 0
+
+// HWM Definitions
+// -----------------------
+#define FDDI_TRACE(string, arg1, arg2, arg3)   // Performance analysis.
+#ifdef PCI
+#define NDD_TRACE(string, arg1, arg2, arg3)    // Performance analysis.
+#endif // PCI
+#define SMT_PAGESIZE   PAGE_SIZE       // Size of a memory page (power of 2).
+// -----------------------
+
+
+// SMT Definitions
+// -----------------------
+#define        TICKS_PER_SECOND        HZ
+#define SMC_VERSION                    1
+// -----------------------
+
+
+// OS-Driver Definitions
+// -----------------------
+#define NO_ADDRESS 0xffe0      /* No Device (I/O) Address */
+#define SKFP_MAX_NUM_BOARDS 8  /* maximum number of PCI boards */
+
+#define SK_BUS_TYPE_PCI                0
+#define SK_BUS_TYPE_EISA       1
+
+#define FP_IO_LEN              256     /* length of IO area used */
+
+#define u8     unsigned char
+#define u16    unsigned short
+#define u32    unsigned int
+
+#define MAX_TX_QUEUE_LEN       20 // number of packets queued by driver
+#define MAX_FRAME_SIZE         4550
+
+#define        RX_LOW_WATERMARK        NUM_RECEIVE_BUFFERS  / 2
+#define TX_LOW_WATERMARK       NUM_TRANSMIT_BUFFERS - 2
+
+/*
+** Include the IOCTL stuff
+*/
+#include <linux/sockios.h>
+
+#define        SKFPIOCTL       SIOCDEVPRIVATE
+
+struct s_skfp_ioctl {
+       unsigned short cmd;                /* Command to run */
+       unsigned short len;                /* Length of the data buffer */
+       unsigned char __user *data;        /* Pointer to the data buffer */
+};
+
+/* 
+** Recognised ioctl commands for the driver 
+*/
+#define SKFP_GET_STATS         0x05 /* Get the driver statistics */
+#define SKFP_CLR_STATS         0x06 /* Zero out the driver statistics */
+
+// The per-adapter driver structure
+struct s_smt_os {
+       struct net_device *dev;
+       struct net_device *next_module;
+       u32     bus_type;               /* bus type (0 == PCI, 1 == EISA) */
+       struct pci_dev  pdev;           /* PCI device structure */
+       
+       unsigned long base_addr;
+       unsigned char factory_mac_addr[8];
+       ulong   SharedMemSize;
+       ulong   SharedMemHeap;
+       void*   SharedMemAddr;
+       dma_addr_t SharedMemDMA;
+
+       ulong   QueueSkb;
+       struct  sk_buff_head SendSkbQueue;
+
+       ulong   MaxFrameSize;
+       u8      ResetRequested;
+
+       // MAC statistics structure
+       struct fddi_statistics MacStat;
+
+       // receive into this local buffer if no skb available
+       // data will be not valid, because multiple RxDs can
+       // point here at the same time, it must be at least
+       // MAX_FRAME_SIZE bytes in size
+       unsigned char *LocalRxBuffer;
+       dma_addr_t LocalRxBufferDMA;
+       
+       // Version (required by SMT module).
+       u_long smc_version ;
+
+       // Required by Hardware Module (HWM).
+       struct hw_modul hwm ;
+       
+       // For SMP-savety
+       spinlock_t DriverLock;
+       
+};
+
+typedef struct s_smt_os skfddi_priv;
+
+#endif  // _TARGETOS_
diff --git a/drivers/net/fddi/skfp/h/types.h b/drivers/net/fddi/skfp/h/types.h
new file mode 100644 (file)
index 0000000..5a3bf83
--- /dev/null
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#include       <linux/types.h>
+/*
+       ----------------------
+       Basic SMT system types
+       ----------------------
+*/
+#ifndef _TYPES_
+#define        _TYPES_
+
+#define _packed
+#ifndef far
+#define far
+#endif
+#ifndef _far
+#define _far
+#endif
+
+#define inp(p)  ioread8(p)
+#define inpw(p)        ioread16(p)
+#define inpd(p) ioread32(p)
+#define outp(p,c)  iowrite8(c,p)
+#define outpw(p,s) iowrite16(s,p)
+#define outpd(p,l) iowrite32(l,p)
+
+#endif /* _TYPES_ */
diff --git a/drivers/net/fddi/skfp/hwmtm.c b/drivers/net/fddi/skfp/hwmtm.c
new file mode 100644 (file)
index 0000000..e26398b
--- /dev/null
@@ -0,0 +1,2178 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#ifndef        lint
+static char const ID_sccs[] = "@(#)hwmtm.c     1.40 99/05/31 (C) SK" ;
+#endif
+
+#define        HWMTM
+
+#ifndef FDDI
+#define        FDDI
+#endif
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#include "h/skfbiinc.h"
+
+/*
+       -------------------------------------------------------------
+       DOCUMENTATION
+       -------------------------------------------------------------
+       BEGIN_MANUAL_ENTRY(DOCUMENTATION)
+
+                       T B D
+
+       END_MANUAL_ENTRY
+*/
+/*
+       -------------------------------------------------------------
+       LOCAL VARIABLES:
+       -------------------------------------------------------------
+*/
+#ifdef COMMON_MB_POOL
+static SMbuf *mb_start = 0 ;
+static SMbuf *mb_free = 0 ;
+static int mb_init = FALSE ;
+static int call_count = 0 ;
+#endif
+
+/*
+       -------------------------------------------------------------
+       EXTERNE VARIABLES:
+       -------------------------------------------------------------
+*/
+
+#ifdef DEBUG
+#ifndef        DEBUG_BRD
+extern struct smt_debug        debug ;
+#endif
+#endif
+
+#ifdef NDIS_OS2
+extern u_char  offDepth ;
+extern u_char  force_irq_pending ;
+#endif
+
+/*
+       -------------------------------------------------------------
+       LOCAL FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);
+static void smt_to_llc(struct s_smc *smc, SMbuf *mb);
+static void init_txd_ring(struct s_smc *smc);
+static void init_rxd_ring(struct s_smc *smc);
+static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);
+static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,
+                             int count);
+static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
+static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
+static SMbuf* get_llc_rx(struct s_smc *smc);
+static SMbuf* get_txd_mb(struct s_smc *smc);
+static void mac_drv_clear_txd(struct s_smc *smc);
+
+/*
+       -------------------------------------------------------------
+       EXTERNAL FUNCTIONS:
+       -------------------------------------------------------------
+*/
+/*     The external SMT functions are listed in cmtdef.h */
+
+extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);
+extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);
+extern void mac_drv_fill_rxd(struct s_smc *smc);
+extern void mac_drv_tx_complete(struct s_smc *smc,
+                               volatile struct s_smt_fp_txd *txd);
+extern void mac_drv_rx_complete(struct s_smc *smc,
+                               volatile struct s_smt_fp_rxd *rxd,
+                               int frag_count, int len);
+extern void mac_drv_requeue_rxd(struct s_smc *smc, 
+                               volatile struct s_smt_fp_rxd *rxd,
+                               int frag_count);
+extern void mac_drv_clear_rxd(struct s_smc *smc,
+                             volatile struct s_smt_fp_rxd *rxd, int frag_count);
+
+#ifdef USE_OS_CPY
+extern void hwm_cpy_rxd2mb(void);
+extern void hwm_cpy_txd2mb(void);
+#endif
+
+#ifdef ALL_RX_COMPLETE
+extern void mac_drv_all_receives_complete(void);
+#endif
+
+extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);
+extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);
+
+#ifdef NDIS_OS2
+extern void post_proc(void);
+#else
+extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
+                        int flag);
+#endif
+
+extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
+                          int la_len);
+
+/*
+       -------------------------------------------------------------
+       PUBLIC FUNCTIONS:
+       -------------------------------------------------------------
+*/
+void process_receive(struct s_smc *smc);
+void fddi_isr(struct s_smc *smc);
+void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
+void init_driver_fplus(struct s_smc *smc);
+void mac_drv_rx_mode(struct s_smc *smc, int mode);
+void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
+void mac_drv_clear_tx_queue(struct s_smc *smc);
+void mac_drv_clear_rx_queue(struct s_smc *smc);
+void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+                int frame_status);
+void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+                int frame_status);
+
+int mac_drv_init(struct s_smc *smc);
+int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
+               int frame_status);
+
+u_int mac_drv_check_space(void);
+
+SMbuf* smt_get_mbuf(struct s_smc *smc);
+
+#ifdef DEBUG
+       void mac_drv_debug_lev(void);
+#endif
+
+/*
+       -------------------------------------------------------------
+       MACROS:
+       -------------------------------------------------------------
+*/
+#ifndef        UNUSED
+#ifdef lint
+#define UNUSED(x)      (x) = (x)
+#else
+#define UNUSED(x)
+#endif
+#endif
+
+#ifdef USE_CAN_ADDR
+#define MA             smc->hw.fddi_canon_addr.a
+#define        GROUP_ADDR_BIT  0x01
+#else
+#define        MA              smc->hw.fddi_home_addr.a
+#define        GROUP_ADDR_BIT  0x80
+#endif
+
+#define RXD_TXD_COUNT  (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\
+                       SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)
+
+#ifdef MB_OUTSIDE_SMC
+#define        EXT_VIRT_MEM    ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\
+                       MAX_MBUF*sizeof(SMbuf))
+#define        EXT_VIRT_MEM_2  ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
+#else
+#define        EXT_VIRT_MEM    ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
+#endif
+
+       /*
+        * define critical read for 16 Bit drivers
+        */
+#if    defined(NDIS_OS2) || defined(ODI2)
+#define CR_READ(var)   ((var) & 0xffff0000 | ((var) & 0xffff))
+#else
+#define CR_READ(var)   (__le32)(var)
+#endif
+
+#define IMASK_SLOW     (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
+                        IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
+                        IS_R1_C | IS_XA_C | IS_XS_C)
+
+/*
+       -------------------------------------------------------------
+       INIT- AND SMT FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+
+/*
+ *     BEGIN_MANUAL_ENTRY(mac_drv_check_space)
+ *     u_int mac_drv_check_space()
+ *
+ *     function        DOWNCALL        (drvsr.c)
+ *                     This function calculates the needed non virtual
+ *                     memory for MBufs, RxD and TxD descriptors etc.
+ *                     needed by the driver.
+ *
+ *     return          u_int   memory in bytes
+ *
+ *     END_MANUAL_ENTRY
+ */
+u_int mac_drv_check_space(void)
+{
+#ifdef MB_OUTSIDE_SMC
+#ifdef COMMON_MB_POOL
+       call_count++ ;
+       if (call_count == 1) {
+               return EXT_VIRT_MEM;
+       }
+       else {
+               return EXT_VIRT_MEM_2;
+       }
+#else
+       return EXT_VIRT_MEM;
+#endif
+#else
+       return 0;
+#endif
+}
+
+/*
+ *     BEGIN_MANUAL_ENTRY(mac_drv_init)
+ *     void mac_drv_init(smc)
+ *
+ *     function        DOWNCALL        (drvsr.c)
+ *                     In this function the hardware module allocates it's
+ *                     memory.
+ *                     The operating system dependent module should call
+ *                     mac_drv_init once, after the adatper is detected.
+ *     END_MANUAL_ENTRY
+ */
+int mac_drv_init(struct s_smc *smc)
+{
+       if (sizeof(struct s_smt_fp_rxd) % 16) {
+               SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
+       }
+       if (sizeof(struct s_smt_fp_txd) % 16) {
+               SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;
+       }
+
+       /*
+        * get the required memory for the RxDs and TxDs
+        */
+       if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
+               mac_drv_get_desc_mem(smc,(u_int)
+               (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
+               return 1;       /* no space the hwm modul can't work */
+       }
+
+       /*
+        * get the memory for the SMT MBufs
+        */
+#ifndef        MB_OUTSIDE_SMC
+       smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;
+#else
+#ifndef        COMMON_MB_POOL
+       if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
+               MAX_MBUF*sizeof(SMbuf)))) {
+               return 1;       /* no space the hwm modul can't work */
+       }
+#else
+       if (!mb_start) {
+               if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
+                       MAX_MBUF*sizeof(SMbuf)))) {
+                       return 1;       /* no space the hwm modul can't work */
+               }
+       }
+#endif
+#endif
+       return 0;
+}
+
+/*
+ *     BEGIN_MANUAL_ENTRY(init_driver_fplus)
+ *     init_driver_fplus(smc)
+ *
+ * Sets hardware modul specific values for the mode register 2
+ * (e.g. the byte alignment for the received frames, the position of the
+ *      least significant byte etc.)
+ *     END_MANUAL_ENTRY
+ */
+void init_driver_fplus(struct s_smc *smc)
+{
+       smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
+
+#ifdef PCI
+       smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;
+#endif
+       smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;
+
+#ifdef USE_CAN_ADDR
+       /* enable address bit swapping */
+       smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;
+#endif
+}
+
+static u_long init_descr_ring(struct s_smc *smc,
+                             union s_fp_descr volatile *start,
+                             int count)
+{
+       int i ;
+       union s_fp_descr volatile *d1 ;
+       union s_fp_descr volatile *d2 ;
+       u_long  phys ;
+
+       DB_GEN("descr ring starts at = %x ",(void *)start,0,3) ;
+       for (i=count-1, d1=start; i ; i--) {
+               d2 = d1 ;
+               d1++ ;          /* descr is owned by the host */
+               d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
+               d2->r.rxd_next = &d1->r ;
+               phys = mac_drv_virt2phys(smc,(void *)d1) ;
+               d2->r.rxd_nrdadr = cpu_to_le32(phys) ;
+       }
+       DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
+       d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
+       d1->r.rxd_next = &start->r ;
+       phys = mac_drv_virt2phys(smc,(void *)start) ;
+       d1->r.rxd_nrdadr = cpu_to_le32(phys) ;
+
+       for (i=count, d1=start; i ; i--) {
+               DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
+               d1++;
+       }
+       return phys;
+}
+
+static void init_txd_ring(struct s_smc *smc)
+{
+       struct s_smt_fp_txd volatile *ds ;
+       struct s_smt_tx_queue *queue ;
+       u_long  phys ;
+
+       /*
+        * initialize the transmit descriptors
+        */
+       ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +
+               SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;
+       queue = smc->hw.fp.tx[QUEUE_A0] ;
+       DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
+       (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+               HWM_ASYNC_TXD_COUNT) ;
+       phys = le32_to_cpu(ds->txd_ntdadr) ;
+       ds++ ;
+       queue->tx_curr_put = queue->tx_curr_get = ds ;
+       ds-- ;
+       queue->tx_free = HWM_ASYNC_TXD_COUNT ;
+       queue->tx_used = 0 ;
+       outpd(ADDR(B5_XA_DA),phys) ;
+
+       ds = (struct s_smt_fp_txd volatile *) ((char *)ds +
+               HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;
+       queue = smc->hw.fp.tx[QUEUE_S] ;
+       DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
+       (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+               HWM_SYNC_TXD_COUNT) ;
+       phys = le32_to_cpu(ds->txd_ntdadr) ;
+       ds++ ;
+       queue->tx_curr_put = queue->tx_curr_get = ds ;
+       queue->tx_free = HWM_SYNC_TXD_COUNT ;
+       queue->tx_used = 0 ;
+       outpd(ADDR(B5_XS_DA),phys) ;
+}
+
+static void init_rxd_ring(struct s_smc *smc)
+{
+       struct s_smt_fp_rxd volatile *ds ;
+       struct s_smt_rx_queue *queue ;
+       u_long  phys ;
+
+       /*
+        * initialize the receive descriptors
+        */
+       ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;
+       queue = smc->hw.fp.rx[QUEUE_R1] ;
+       DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
+       (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
+               SMT_R1_RXD_COUNT) ;
+       phys = le32_to_cpu(ds->rxd_nrdadr) ;
+       ds++ ;
+       queue->rx_curr_put = queue->rx_curr_get = ds ;
+       queue->rx_free = SMT_R1_RXD_COUNT ;
+       queue->rx_used = 0 ;
+       outpd(ADDR(B4_R1_DA),phys) ;
+}
+
+/*
+ *     BEGIN_MANUAL_ENTRY(init_fddi_driver)
+ *     void init_fddi_driver(smc,mac_addr)
+ *
+ * initializes the driver and it's variables
+ *
+ *     END_MANUAL_ENTRY
+ */
+void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)
+{
+       SMbuf   *mb ;
+       int     i ;
+
+       init_board(smc,mac_addr) ;
+       (void)init_fplus(smc) ;
+
+       /*
+        * initialize the SMbufs for the SMT
+        */
+#ifndef        COMMON_MB_POOL
+       mb = smc->os.hwm.mbuf_pool.mb_start ;
+       smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;
+       for (i = 0; i < MAX_MBUF; i++) {
+               mb->sm_use_count = 1 ;
+               smt_free_mbuf(smc,mb)   ;
+               mb++ ;
+       }
+#else
+       mb = mb_start ;
+       if (!mb_init) {
+               mb_free = 0 ;
+               for (i = 0; i < MAX_MBUF; i++) {
+                       mb->sm_use_count = 1 ;
+                       smt_free_mbuf(smc,mb)   ;
+                       mb++ ;
+               }
+               mb_init = TRUE ;
+       }
+#endif
+
+       /*
+        * initialize the other variables
+        */
+       smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;
+       smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;
+       smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;
+       smc->os.hwm.pass_llc_promisc = TRUE ;
+       smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;
+       smc->os.hwm.detec_count = 0 ;
+       smc->os.hwm.rx_break = 0 ;
+       smc->os.hwm.rx_len_error = 0 ;
+       smc->os.hwm.isr_flag = FALSE ;
+
+       /*
+        * make sure that the start pointer is 16 byte aligned
+        */
+       i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ;
+       if (i != 16) {
+               DB_GEN("i = %d",i,0,3) ;
+               smc->os.hwm.descr_p = (union s_fp_descr volatile *)
+                       ((char *)smc->os.hwm.descr_p+i) ;
+       }
+       DB_GEN("pt to descr area = %x",(void *)smc->os.hwm.descr_p,0,3) ;
+
+       init_txd_ring(smc) ;
+       init_rxd_ring(smc) ;
+       mac_drv_fill_rxd(smc) ;
+
+       init_plc(smc) ;
+}
+
+
+SMbuf *smt_get_mbuf(struct s_smc *smc)
+{
+       register SMbuf  *mb ;
+
+#ifndef        COMMON_MB_POOL
+       mb = smc->os.hwm.mbuf_pool.mb_free ;
+#else
+       mb = mb_free ;
+#endif
+       if (mb) {
+#ifndef        COMMON_MB_POOL
+               smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;
+#else
+               mb_free = mb->sm_next ;
+#endif
+               mb->sm_off = 8 ;
+               mb->sm_use_count = 1 ;
+       }
+       DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
+       return mb;      /* May be NULL */
+}
+
+void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
+{
+
+       if (mb) {
+               mb->sm_use_count-- ;
+               DB_GEN("free_mbuf: sm_use_count = %d",mb->sm_use_count,0,3) ;
+               /*
+                * If the use_count is != zero the MBuf is queued
+                * more than once and must not queued into the
+                * free MBuf queue
+                */
+               if (!mb->sm_use_count) {
+                       DB_GEN("free SMbuf: mb = %x",(void *)mb,0,3) ;
+#ifndef        COMMON_MB_POOL
+                       mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;
+                       smc->os.hwm.mbuf_pool.mb_free = mb ;
+#else
+                       mb->sm_next = mb_free ;
+                       mb_free = mb ;
+#endif
+               }
+       }
+       else
+               SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;
+}
+
+
+/*
+ *     BEGIN_MANUAL_ENTRY(mac_drv_repair_descr)
+ *     void mac_drv_repair_descr(smc)
+ *
+ * function    called from SMT (HWM / hwmtm.c)
+ *             The BMU is idle when this function is called.
+ *             Mac_drv_repair_descr sets up the physical address
+ *             for all receive and transmit queues where the BMU
+ *             should continue.
+ *             It may be that the BMU was reseted during a fragmented
+ *             transfer. In this case there are some fragments which will
+ *             never completed by the BMU. The OWN bit of this fragments
+ *             must be switched to be owned by the host.
+ *
+ *             Give a start command to the receive BMU.
+ *             Start the transmit BMUs if transmit frames pending.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void mac_drv_repair_descr(struct s_smc *smc)
+{
+       u_long  phys ;
+
+       if (smc->hw.hw_state != STOPPED) {
+               SK_BREAK() ;
+               SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;
+               return ;
+       }
+
+       /*
+        * repair tx queues: don't start
+        */
+       phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;
+       outpd(ADDR(B5_XA_DA),phys) ;
+       if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {
+               outpd(ADDR(B0_XA_CSR),CSR_START) ;
+       }
+       phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;
+       outpd(ADDR(B5_XS_DA),phys) ;
+       if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {
+               outpd(ADDR(B0_XS_CSR),CSR_START) ;
+       }
+
+       /*
+        * repair rx queues
+        */
+       phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;
+       outpd(ADDR(B4_R1_DA),phys) ;
+       outpd(ADDR(B0_R1_CSR),CSR_START) ;
+}
+
+static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
+{
+       int i ;
+       int tx_used ;
+       u_long phys ;
+       u_long tbctrl ;
+       struct s_smt_fp_txd volatile *t ;
+
+       SK_UNUSED(smc) ;
+
+       t = queue->tx_curr_get ;
+       tx_used = queue->tx_used ;
+       for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
+               t = t->txd_next ;
+       }
+       phys = le32_to_cpu(t->txd_ntdadr) ;
+
+       t = queue->tx_curr_get ;
+       while (tx_used) {
+               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+               tbctrl = le32_to_cpu(t->txd_tbctrl) ;
+
+               if (tbctrl & BMU_OWN) {
+                       if (tbctrl & BMU_STF) {
+                               break ;         /* exit the loop */
+                       }
+                       else {
+                               /*
+                                * repair the descriptor
+                                */
+                               t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
+                       }
+               }
+               phys = le32_to_cpu(t->txd_ntdadr) ;
+               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+               t = t->txd_next ;
+               tx_used-- ;
+       }
+       return phys;
+}
+
+/*
+ * Repairs the receive descriptor ring and returns the physical address
+ * where the BMU should continue working.
+ *
+ *     o The physical address where the BMU was stopped has to be
+ *       determined. This is the next RxD after rx_curr_get with an OWN
+ *       bit set.
+ *     o The BMU should start working at beginning of the next frame.
+ *       RxDs with an OWN bit set but with a reset STF bit should be
+ *       skipped and owned by the driver (OWN = 0). 
+ */
+static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
+{
+       int i ;
+       int rx_used ;
+       u_long phys ;
+       u_long rbctrl ;
+       struct s_smt_fp_rxd volatile *r ;
+
+       SK_UNUSED(smc) ;
+
+       r = queue->rx_curr_get ;
+       rx_used = queue->rx_used ;
+       for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
+               r = r->rxd_next ;
+       }
+       phys = le32_to_cpu(r->rxd_nrdadr) ;
+
+       r = queue->rx_curr_get ;
+       while (rx_used) {
+               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+               rbctrl = le32_to_cpu(r->rxd_rbctrl) ;
+
+               if (rbctrl & BMU_OWN) {
+                       if (rbctrl & BMU_STF) {
+                               break ;         /* exit the loop */
+                       }
+                       else {
+                               /*
+                                * repair the descriptor
+                                */
+                               r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+                       }
+               }
+               phys = le32_to_cpu(r->rxd_nrdadr) ;
+               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+               r = r->rxd_next ;
+               rx_used-- ;
+       }
+       return phys;
+}
+
+
+/*
+       -------------------------------------------------------------
+       INTERRUPT SERVICE ROUTINE:
+       -------------------------------------------------------------
+*/
+
+/*
+ *     BEGIN_MANUAL_ENTRY(fddi_isr)
+ *     void fddi_isr(smc)
+ *
+ * function    DOWNCALL        (drvsr.c)
+ *             interrupt service routine, handles the interrupt requests
+ *             generated by the FDDI adapter.
+ *
+ * NOTE:       The operating system dependent module must guarantee that the
+ *             interrupts of the adapter are disabled when it calls fddi_isr.
+ *
+ *     About the USE_BREAK_ISR mechanismn:
+ *
+ *     The main requirement of this mechanismn is to force an timer IRQ when
+ *     leaving process_receive() with leave_isr set. process_receive() may
+ *     be called at any time from anywhere!
+ *     To be sure we don't miss such event we set 'force_irq' per default.
+ *     We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND
+ *     'force_irq' are set. 'force_irq' may be reset if a receive complete
+ *     IRQ is pending.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void fddi_isr(struct s_smc *smc)
+{
+       u_long          is ;            /* ISR source */
+       u_short         stu, stl ;
+       SMbuf           *mb ;
+
+#ifdef USE_BREAK_ISR
+       int     force_irq ;
+#endif
+
+#ifdef ODI2
+       if (smc->os.hwm.rx_break) {
+               mac_drv_fill_rxd(smc) ;
+               if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
+                       smc->os.hwm.rx_break = 0 ;
+                       process_receive(smc) ;
+               }
+               else {
+                       smc->os.hwm.detec_count = 0 ;
+                       smt_force_irq(smc) ;
+               }
+       }
+#endif
+       smc->os.hwm.isr_flag = TRUE ;
+
+#ifdef USE_BREAK_ISR
+       force_irq = TRUE ;
+       if (smc->os.hwm.leave_isr) {
+               smc->os.hwm.leave_isr = FALSE ;
+               process_receive(smc) ;
+       }
+#endif
+
+       while ((is = GET_ISR() & ISR_MASK)) {
+               NDD_TRACE("CH0B",is,0,0) ;
+               DB_GEN("ISA = 0x%x",is,0,7) ;
+
+               if (is & IMASK_SLOW) {
+                       NDD_TRACE("CH1b",is,0,0) ;
+                       if (is & IS_PLINT1) {   /* PLC1 */
+                               plc1_irq(smc) ;
+                       }
+                       if (is & IS_PLINT2) {   /* PLC2 */
+                               plc2_irq(smc) ;
+                       }
+                       if (is & IS_MINTR1) {   /* FORMAC+ STU1(U/L) */
+                               stu = inpw(FM_A(FM_ST1U)) ;
+                               stl = inpw(FM_A(FM_ST1L)) ;
+                               DB_GEN("Slow transmit complete",0,0,6) ;
+                               mac1_irq(smc,stu,stl) ;
+                       }
+                       if (is & IS_MINTR2) {   /* FORMAC+ STU2(U/L) */
+                               stu= inpw(FM_A(FM_ST2U)) ;
+                               stl= inpw(FM_A(FM_ST2L)) ;
+                               DB_GEN("Slow receive complete",0,0,6) ;
+                               DB_GEN("stl = %x : stu = %x",stl,stu,7) ;
+                               mac2_irq(smc,stu,stl) ;
+                       }
+                       if (is & IS_MINTR3) {   /* FORMAC+ STU3(U/L) */
+                               stu= inpw(FM_A(FM_ST3U)) ;
+                               stl= inpw(FM_A(FM_ST3L)) ;
+                               DB_GEN("FORMAC Mode Register 3",0,0,6) ;
+                               mac3_irq(smc,stu,stl) ;
+                       }
+                       if (is & IS_TIMINT) {   /* Timer 82C54-2 */
+                               timer_irq(smc) ;
+#ifdef NDIS_OS2
+                               force_irq_pending = 0 ;
+#endif
+                               /*
+                                * out of RxD detection
+                                */
+                               if (++smc->os.hwm.detec_count > 4) {
+                                       /*
+                                        * check out of RxD condition
+                                        */
+                                        process_receive(smc) ;
+                               }
+                       }
+                       if (is & IS_TOKEN) {    /* Restricted Token Monitor */
+                               rtm_irq(smc) ;
+                       }
+                       if (is & IS_R1_P) {     /* Parity error rx queue 1 */
+                               /* clear IRQ */
+                               outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
+                               SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
+                       }
+                       if (is & IS_R1_C) {     /* Encoding error rx queue 1 */
+                               /* clear IRQ */
+                               outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
+                               SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
+                       }
+                       if (is & IS_XA_C) {     /* Encoding error async tx q */
+                               /* clear IRQ */
+                               outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
+                               SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
+                       }
+                       if (is & IS_XS_C) {     /* Encoding error sync tx q */
+                               /* clear IRQ */
+                               outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
+                               SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
+                       }
+               }
+
+               /*
+                *      Fast Tx complete Async/Sync Queue (BMU service)
+                */
+               if (is & (IS_XS_F|IS_XA_F)) {
+                       DB_GEN("Fast tx complete queue",0,0,6) ;
+                       /*
+                        * clear IRQ, Note: no IRQ is lost, because
+                        *      we always service both queues
+                        */
+                       outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
+                       outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
+                       mac_drv_clear_txd(smc) ;
+                       llc_restart_tx(smc) ;
+               }
+
+               /*
+                *      Fast Rx Complete (BMU service)
+                */
+               if (is & IS_R1_F) {
+                       DB_GEN("Fast receive complete",0,0,6) ;
+                       /* clear IRQ */
+#ifndef USE_BREAK_ISR
+                       outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
+                       process_receive(smc) ;
+#else
+                       process_receive(smc) ;
+                       if (smc->os.hwm.leave_isr) {
+                               force_irq = FALSE ;
+                       } else {
+                               outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
+                               process_receive(smc) ;
+                       }
+#endif
+               }
+
+#ifndef        NDIS_OS2
+               while ((mb = get_llc_rx(smc))) {
+                       smt_to_llc(smc,mb) ;
+               }
+#else
+               if (offDepth)
+                       post_proc() ;
+
+               while (!offDepth && (mb = get_llc_rx(smc))) {
+                       smt_to_llc(smc,mb) ;
+               }
+
+               if (!offDepth && smc->os.hwm.rx_break) {
+                       process_receive(smc) ;
+               }
+#endif
+               if (smc->q.ev_get != smc->q.ev_put) {
+                       NDD_TRACE("CH2a",0,0,0) ;
+                       ev_dispatcher(smc) ;
+               }
+#ifdef NDIS_OS2
+               post_proc() ;
+               if (offDepth) {         /* leave fddi_isr because */
+                       break ;         /* indications not allowed */
+               }
+#endif
+#ifdef USE_BREAK_ISR
+               if (smc->os.hwm.leave_isr) {
+                       break ;         /* leave fddi_isr */
+               }
+#endif
+
+               /* NOTE: when the isr is left, no rx is pending */
+       }       /* end of interrupt source polling loop */
+
+#ifdef USE_BREAK_ISR
+       if (smc->os.hwm.leave_isr && force_irq) {
+               smt_force_irq(smc) ;
+       }
+#endif
+       smc->os.hwm.isr_flag = FALSE ;
+       NDD_TRACE("CH0E",0,0,0) ;
+}
+
+
+/*
+       -------------------------------------------------------------
+       RECEIVE FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+#ifndef        NDIS_OS2
+/*
+ *     BEGIN_MANUAL_ENTRY(mac_drv_rx_mode)
+ *     void mac_drv_rx_mode(smc,mode)
+ *
+ * function    DOWNCALL        (fplus.c)
+ *             Corresponding to the parameter mode, the operating system
+ *             dependent module can activate several receive modes.
+ *
+ * para        mode    = 1:    RX_ENABLE_ALLMULTI      enable all multicasts
+ *             = 2:    RX_DISABLE_ALLMULTI     disable "enable all multicasts"
+ *             = 3:    RX_ENABLE_PROMISC       enable promiscuous
+ *             = 4:    RX_DISABLE_PROMISC      disable promiscuous
+ *             = 5:    RX_ENABLE_NSA           enable rec. of all NSA frames
+ *                     (disabled after 'driver reset' & 'set station address')
+ *             = 6:    RX_DISABLE_NSA          disable rec. of all NSA frames
+ *
+ *             = 21:   RX_ENABLE_PASS_SMT      ( see description )
+ *             = 22:   RX_DISABLE_PASS_SMT     (  "       "      )
+ *             = 23:   RX_ENABLE_PASS_NSA      (  "       "      )
+ *             = 24:   RX_DISABLE_PASS_NSA     (  "       "      )
+ *             = 25:   RX_ENABLE_PASS_DB       (  "       "      )
+ *             = 26:   RX_DISABLE_PASS_DB      (  "       "      )
+ *             = 27:   RX_DISABLE_PASS_ALL     (  "       "      )
+ *             = 28:   RX_DISABLE_LLC_PROMISC  (  "       "      )
+ *             = 29:   RX_ENABLE_LLC_PROMISC   (  "       "      )
+ *
+ *
+ *             RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT
+ *
+ *             If the operating system dependent module activates the
+ *             mode RX_ENABLE_PASS_SMT, the hardware module
+ *             duplicates all SMT frames with the frame control
+ *             FC_SMT_INFO and passes them to the LLC receive channel
+ *             by calling mac_drv_rx_init.
+ *             The SMT Frames which are sent by the local SMT and the NSA
+ *             frames whose A- and C-Indicator is not set are also duplicated
+ *             and passed.
+ *             The receive mode RX_DISABLE_PASS_SMT disables the passing
+ *             of SMT frames.
+ *
+ *             RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA
+ *
+ *             If the operating system dependent module activates the
+ *             mode RX_ENABLE_PASS_NSA, the hardware module
+ *             duplicates all NSA frames with frame control FC_SMT_NSA
+ *             and a set A-Indicator and passed them to the LLC
+ *             receive channel by calling mac_drv_rx_init.
+ *             All NSA Frames which are sent by the local SMT
+ *             are also duplicated and passed.
+ *             The receive mode RX_DISABLE_PASS_NSA disables the passing
+ *             of NSA frames with the A- or C-Indicator set.
+ *
+ * NOTE:       For fear that the hardware module receives NSA frames with
+ *             a reset A-Indicator, the operating system dependent module
+ *             has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA
+ *             before activate the RX_ENABLE_PASS_NSA mode and after every
+ *             'driver reset' and 'set station address'.
+ *
+ *             RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB
+ *
+ *             If the operating system dependent module activates the
+ *             mode RX_ENABLE_PASS_DB, direct BEACON frames
+ *             (FC_BEACON frame control) are passed to the LLC receive
+ *             channel by mac_drv_rx_init.
+ *             The receive mode RX_DISABLE_PASS_DB disables the passing
+ *             of direct BEACON frames.
+ *
+ *             RX_DISABLE_PASS_ALL
+ *
+ *             Disables all special receives modes. It is equal to
+ *             call mac_drv_set_rx_mode successively with the
+ *             parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT,
+ *             RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB.
+ *
+ *             RX_ENABLE_LLC_PROMISC
+ *
+ *             (default) all received LLC frames and all SMT/NSA/DBEACON
+ *             frames depending on the attitude of the flags
+ *             PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the
+ *             LLC layer
+ *
+ *             RX_DISABLE_LLC_PROMISC
+ *
+ *             all received SMT/NSA/DBEACON frames depending on the
+ *             attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON
+ *             will be delivered to the LLC layer.
+ *             all received LLC frames with a directed address, Multicast
+ *             or Broadcast address will be delivered to the LLC
+ *             layer too.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void mac_drv_rx_mode(struct s_smc *smc, int mode)
+{
+       switch(mode) {
+       case RX_ENABLE_PASS_SMT:
+               smc->os.hwm.pass_SMT = TRUE ;
+               break ;
+       case RX_DISABLE_PASS_SMT:
+               smc->os.hwm.pass_SMT = FALSE ;
+               break ;
+       case RX_ENABLE_PASS_NSA:
+               smc->os.hwm.pass_NSA = TRUE ;
+               break ;
+       case RX_DISABLE_PASS_NSA:
+               smc->os.hwm.pass_NSA = FALSE ;
+               break ;
+       case RX_ENABLE_PASS_DB:
+               smc->os.hwm.pass_DB = TRUE ;
+               break ;
+       case RX_DISABLE_PASS_DB:
+               smc->os.hwm.pass_DB = FALSE ;
+               break ;
+       case RX_DISABLE_PASS_ALL:
+               smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;
+               smc->os.hwm.pass_DB = FALSE ;
+               smc->os.hwm.pass_llc_promisc = TRUE ;
+               mac_set_rx_mode(smc,RX_DISABLE_NSA) ;
+               break ;
+       case RX_DISABLE_LLC_PROMISC:
+               smc->os.hwm.pass_llc_promisc = FALSE ;
+               break ;
+       case RX_ENABLE_LLC_PROMISC:
+               smc->os.hwm.pass_llc_promisc = TRUE ;
+               break ;
+       case RX_ENABLE_ALLMULTI:
+       case RX_DISABLE_ALLMULTI:
+       case RX_ENABLE_PROMISC:
+       case RX_DISABLE_PROMISC:
+       case RX_ENABLE_NSA:
+       case RX_DISABLE_NSA:
+       default:
+               mac_set_rx_mode(smc,mode) ;
+               break ;
+       }
+}
+#endif /* ifndef NDIS_OS2 */
+
+/*
+ * process receive queue
+ */
+void process_receive(struct s_smc *smc)
+{
+       int i ;
+       int n ;
+       int frag_count ;                /* number of RxDs of the curr rx buf */
+       int used_frags ;                /* number of RxDs of the curr frame */
+       struct s_smt_rx_queue *queue ;  /* points to the queue ctl struct */
+       struct s_smt_fp_rxd volatile *r ;       /* rxd pointer */
+       struct s_smt_fp_rxd volatile *rxd ;     /* first rxd of rx frame */
+       u_long rbctrl ;                 /* receive buffer control word */
+       u_long rfsw ;                   /* receive frame status word */
+       u_short rx_used ;
+       u_char far *virt ;
+       char far *data ;
+       SMbuf *mb ;
+       u_char fc ;                     /* Frame control */
+       int len ;                       /* Frame length */
+
+       smc->os.hwm.detec_count = 0 ;
+       queue = smc->hw.fp.rx[QUEUE_R1] ;
+       NDD_TRACE("RHxB",0,0,0) ;
+       for ( ; ; ) {
+               r = queue->rx_curr_get ;
+               rx_used = queue->rx_used ;
+               frag_count = 0 ;
+
+#ifdef USE_BREAK_ISR
+               if (smc->os.hwm.leave_isr) {
+                       goto rx_end ;
+               }
+#endif
+#ifdef NDIS_OS2
+               if (offDepth) {
+                       smc->os.hwm.rx_break = 1 ;
+                       goto rx_end ;
+               }
+               smc->os.hwm.rx_break = 0 ;
+#endif
+#ifdef ODI2
+               if (smc->os.hwm.rx_break) {
+                       goto rx_end ;
+               }
+#endif
+               n = 0 ;
+               do {
+                       DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
+                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+                       rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));
+
+                       if (rbctrl & BMU_OWN) {
+                               NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
+                               DB_RX("End of RxDs",0,0,4) ;
+                               goto rx_end ;
+                       }
+                       /*
+                        * out of RxD detection
+                        */
+                       if (!rx_used) {
+                               SK_BREAK() ;
+                               SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
+                               /* Either we don't have an RxD or all
+                                * RxDs are filled. Therefore it's allowed
+                                * for to set the STOPPED flag */
+                               smc->hw.hw_state = STOPPED ;
+                               mac_drv_clear_rx_queue(smc) ;
+                               smc->hw.hw_state = STARTED ;
+                               mac_drv_fill_rxd(smc) ;
+                               smc->os.hwm.detec_count = 0 ;
+                               goto rx_end ;
+                       }
+                       rfsw = le32_to_cpu(r->rxd_rfsw) ;
+                       if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
+                               /*
+                                * The BMU_STF bit is deleted, 1 frame is
+                                * placed into more than 1 rx buffer
+                                *
+                                * skip frame by setting the rx len to 0
+                                *
+                                * if fragment count == 0
+                                *      The missing STF bit belongs to the
+                                *      current frame, search for the
+                                *      EOF bit to complete the frame
+                                * else
+                                *      the fragment belongs to the next frame,
+                                *      exit the loop and process the frame
+                                */
+                               SK_BREAK() ;
+                               rfsw = 0 ;
+                               if (frag_count) {
+                                       break ;
+                               }
+                       }
+                       n += rbctrl & 0xffff ;
+                       r = r->rxd_next ;
+                       frag_count++ ;
+                       rx_used-- ;
+               } while (!(rbctrl & BMU_EOF)) ;
+               used_frags = frag_count ;
+               DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;
+
+               /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
+               /* BMU_ST_BUF will not be changed by the ASIC */
+               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+               while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
+                       DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+                       r = r->rxd_next ;
+                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+                       frag_count++ ;
+                       rx_used-- ;
+               }
+               DB_RX("STF bit found",0,0,5) ;
+
+               /*
+                * The received frame is finished for the process receive
+                */
+               rxd = queue->rx_curr_get ;
+               queue->rx_curr_get = r ;
+               queue->rx_free += frag_count ;
+               queue->rx_used = rx_used ;
+
+               /*
+                * ASIC Errata no. 7 (STF - Bit Bug)
+                */
+               rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;
+
+               for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
+                       DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
+                       dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
+               }
+               smc->hw.fp.err_stats.err_valid++ ;
+               smc->mib.m[MAC0].fddiMACCopied_Ct++ ;
+
+               /* the length of the data including the FC */
+               len = (rfsw & RD_LENGTH) - 4 ;
+
+               DB_RX("frame length = %d",len,0,4) ;
+               /*
+                * check the frame_length and all error flags
+                */
+               if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
+                       if (rfsw & RD_S_MSRABT) {
+                               DB_RX("Frame aborted by the FORMAC",0,0,2) ;
+                               smc->hw.fp.err_stats.err_abort++ ;
+                       }
+                       /*
+                        * check frame status
+                        */
+                       if (rfsw & RD_S_SEAC2) {
+                               DB_RX("E-Indicator set",0,0,2) ;
+                               smc->hw.fp.err_stats.err_e_indicator++ ;
+                       }
+                       if (rfsw & RD_S_SFRMERR) {
+                               DB_RX("CRC error",0,0,2) ;
+                               smc->hw.fp.err_stats.err_crc++ ;
+                       }
+                       if (rfsw & RX_FS_IMPL) {
+                               DB_RX("Implementer frame",0,0,2) ;
+                               smc->hw.fp.err_stats.err_imp_frame++ ;
+                       }
+                       goto abort_frame ;
+               }
+               if (len > FDDI_RAW_MTU-4) {
+                       DB_RX("Frame too long error",0,0,2) ;
+                       smc->hw.fp.err_stats.err_too_long++ ;
+                       goto abort_frame ;
+               }
+               /*
+                * SUPERNET 3 Bug: FORMAC delivers status words
+                * of aborded frames to the BMU
+                */
+               if (len <= 4) {
+                       DB_RX("Frame length = 0",0,0,2) ;
+                       goto abort_frame ;
+               }
+
+               if (len != (n-4)) {
+                       DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);
+                       smc->os.hwm.rx_len_error++ ;
+                       goto abort_frame ;
+               }
+
+               /*
+                * Check SA == MA
+                */
+               virt = (u_char far *) rxd->rxd_virt ;
+               DB_RX("FC = %x",*virt,0,2) ;
+               if (virt[12] == MA[5] &&
+                   virt[11] == MA[4] &&
+                   virt[10] == MA[3] &&
+                   virt[9] == MA[2] &&
+                   virt[8] == MA[1] &&
+                   (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
+                       goto abort_frame ;
+               }
+
+               /*
+                * test if LLC frame
+                */
+               if (rfsw & RX_FS_LLC) {
+                       /*
+                        * if pass_llc_promisc is disable
+                        *      if DA != Multicast or Broadcast or DA!=MA
+                        *              abort the frame
+                        */
+                       if (!smc->os.hwm.pass_llc_promisc) {
+                               if(!(virt[1] & GROUP_ADDR_BIT)) {
+                                       if (virt[6] != MA[5] ||
+                                           virt[5] != MA[4] ||
+                                           virt[4] != MA[3] ||
+                                           virt[3] != MA[2] ||
+                                           virt[2] != MA[1] ||
+                                           virt[1] != MA[0]) {
+                                               DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;
+                                               goto abort_frame ;
+                                       }
+                               }
+                       }
+
+                       /*
+                        * LLC frame received
+                        */
+                       DB_RX("LLC - receive",0,0,4) ;
+                       mac_drv_rx_complete(smc,rxd,frag_count,len) ;
+               }
+               else {
+                       if (!(mb = smt_get_mbuf(smc))) {
+                               smc->hw.fp.err_stats.err_no_buf++ ;
+                               DB_RX("No SMbuf; receive terminated",0,0,4) ;
+                               goto abort_frame ;
+                       }
+                       data = smtod(mb,char *) - 1 ;
+
+                       /*
+                        * copy the frame into a SMT_MBuf
+                        */
+#ifdef USE_OS_CPY
+                       hwm_cpy_rxd2mb(rxd,data,len) ;
+#else
+                       for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
+                               n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;
+                               DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
+                               memcpy(data,r->rxd_virt,n) ;
+                               data += n ;
+                       }
+                       data = smtod(mb,char *) - 1 ;
+#endif
+                       fc = *(char *)mb->sm_data = *data ;
+                       mb->sm_len = len - 1 ;          /* len - fc */
+                       data++ ;
+
+                       /*
+                        * SMT frame received
+                        */
+                       switch(fc) {
+                       case FC_SMT_INFO :
+                               smc->hw.fp.err_stats.err_smt_frame++ ;
+                               DB_RX("SMT frame received ",0,0,5) ;
+
+                               if (smc->os.hwm.pass_SMT) {
+                                       DB_RX("pass SMT frame ",0,0,5) ;
+                                       mac_drv_rx_complete(smc, rxd,
+                                               frag_count,len) ;
+                               }
+                               else {
+                                       DB_RX("requeue RxD",0,0,5) ;
+                                       mac_drv_requeue_rxd(smc,rxd,frag_count);
+                               }
+
+                               smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
+                               break ;
+                       case FC_SMT_NSA :
+                               smc->hw.fp.err_stats.err_smt_frame++ ;
+                               DB_RX("SMT frame received ",0,0,5) ;
+
+                               /* if pass_NSA set pass the NSA frame or */
+                               /* pass_SMT set and the A-Indicator */
+                               /* is not set, pass the NSA frame */
+                               if (smc->os.hwm.pass_NSA ||
+                                       (smc->os.hwm.pass_SMT &&
+                                       !(rfsw & A_INDIC))) {
+                                       DB_RX("pass SMT frame ",0,0,5) ;
+                                       mac_drv_rx_complete(smc, rxd,
+                                               frag_count,len) ;
+                               }
+                               else {
+                                       DB_RX("requeue RxD",0,0,5) ;
+                                       mac_drv_requeue_rxd(smc,rxd,frag_count);
+                               }
+
+                               smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
+                               break ;
+                       case FC_BEACON :
+                               if (smc->os.hwm.pass_DB) {
+                                       DB_RX("pass DB frame ",0,0,5) ;
+                                       mac_drv_rx_complete(smc, rxd,
+                                               frag_count,len) ;
+                               }
+                               else {
+                                       DB_RX("requeue RxD",0,0,5) ;
+                                       mac_drv_requeue_rxd(smc,rxd,frag_count);
+                               }
+                               smt_free_mbuf(smc,mb) ;
+                               break ;
+                       default :
+                               /*
+                                * unknown FC abord the frame
+                                */
+                               DB_RX("unknown FC error",0,0,2) ;
+                               smt_free_mbuf(smc,mb) ;
+                               DB_RX("requeue RxD",0,0,5) ;
+                               mac_drv_requeue_rxd(smc,rxd,frag_count) ;
+                               if ((fc & 0xf0) == FC_MAC)
+                                       smc->hw.fp.err_stats.err_mac_frame++ ;
+                               else
+                                       smc->hw.fp.err_stats.err_imp_frame++ ;
+
+                               break ;
+                       }
+               }
+
+               DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
+               NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;
+
+               continue ;
+       /*--------------------------------------------------------------------*/
+abort_frame:
+               DB_RX("requeue RxD",0,0,5) ;
+               mac_drv_requeue_rxd(smc,rxd,frag_count) ;
+
+               DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
+               NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
+       }
+rx_end:
+#ifdef ALL_RX_COMPLETE
+       mac_drv_all_receives_complete(smc) ;
+#endif
+       return ;        /* lint bug: needs return detect end of function */
+}
+
+static void smt_to_llc(struct s_smc *smc, SMbuf *mb)
+{
+       u_char  fc ;
+
+       DB_RX("send a queued frame to the llc layer",0,0,4) ;
+       smc->os.hwm.r.len = mb->sm_len ;
+       smc->os.hwm.r.mb_pos = smtod(mb,char *) ;
+       fc = *smc->os.hwm.r.mb_pos ;
+       (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,
+               smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;
+       smt_free_mbuf(smc,mb) ;
+}
+
+/*
+ *     BEGIN_MANUAL_ENTRY(hwm_rx_frag)
+ *     void hwm_rx_frag(smc,virt,phys,len,frame_status)
+ *
+ * function    MACRO           (hardware module, hwmtm.h)
+ *             This function calls dma_master for preparing the
+ *             system hardware for the DMA transfer and initializes
+ *             the current RxD with the length and the physical and
+ *             virtual address of the fragment. Furthermore, it sets the
+ *             STF and EOF bits depending on the frame status byte,
+ *             switches the OWN flag of the RxD, so that it is owned by the
+ *             adapter and issues an rx_start.
+ *
+ * para        virt    virtual pointer to the fragment
+ *     len     the length of the fragment
+ *     frame_status    status of the frame, see design description
+ *
+ * NOTE:       It is possible to call this function with a fragment length
+ *             of zero.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+                int frame_status)
+{
+       struct s_smt_fp_rxd volatile *r ;
+       __le32  rbctrl;
+
+       NDD_TRACE("RHfB",virt,len,frame_status) ;
+       DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
+       r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
+       r->rxd_virt = virt ;
+       r->rxd_rbadr = cpu_to_le32(phys) ;
+       rbctrl = cpu_to_le32( (((__u32)frame_status &
+               (FIRST_FRAG|LAST_FRAG))<<26) |
+               (((u_long) frame_status & FIRST_FRAG) << 21) |
+               BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
+       r->rxd_rbctrl = rbctrl ;
+
+       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+       outpd(ADDR(B0_R1_CSR),CSR_START) ;
+       smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
+       smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
+       smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
+       NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ;
+}
+
+/*
+ *     BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)
+ *
+ * void mac_drv_clear_rx_queue(smc)
+ * struct s_smc *smc ;
+ *
+ * function    DOWNCALL        (hardware module, hwmtm.c)
+ *             mac_drv_clear_rx_queue is called by the OS-specific module
+ *             after it has issued a card_stop.
+ *             In this case, the frames in the receive queue are obsolete and
+ *             should be removed. For removing mac_drv_clear_rx_queue
+ *             calls dma_master for each RxD and mac_drv_clear_rxd for each
+ *             receive buffer.
+ *
+ * NOTE:       calling sequence card_stop:
+ *             CLI_FBI(), card_stop(),
+ *             mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
+ *
+ * NOTE:       The caller is responsible that the BMUs are idle
+ *             when this function is called.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void mac_drv_clear_rx_queue(struct s_smc *smc)
+{
+       struct s_smt_fp_rxd volatile *r ;
+       struct s_smt_fp_rxd volatile *next_rxd ;
+       struct s_smt_rx_queue *queue ;
+       int frag_count ;
+       int i ;
+
+       if (smc->hw.hw_state != STOPPED) {
+               SK_BREAK() ;
+               SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;
+               return ;
+       }
+
+       queue = smc->hw.fp.rx[QUEUE_R1] ;
+       DB_RX("clear_rx_queue",0,0,5) ;
+
+       /*
+        * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers
+        */
+       r = queue->rx_curr_get ;
+       while (queue->rx_used) {
+               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+               DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
+               r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+               frag_count = 1 ;
+               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+               r = r->rxd_next ;
+               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+               while (r != queue->rx_curr_put &&
+                       !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
+                       DB_RX("Check STF bit in %x",(void *)r,0,5) ;
+                       r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
+                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
+                       r = r->rxd_next ;
+                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
+                       frag_count++ ;
+               }
+               DB_RX("STF bit found",0,0,5) ;
+               next_rxd = r ;
+
+               for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){
+                       DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
+                       dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
+               }
+
+               DB_RX("mac_drv_clear_rxd: RxD %x frag_count %d ",
+                       (void *)queue->rx_curr_get,frag_count,5) ;
+               mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;
+
+               queue->rx_curr_get = next_rxd ;
+               queue->rx_used -= frag_count ;
+               queue->rx_free += frag_count ;
+       }
+}
+
+
+/*
+       -------------------------------------------------------------
+       SEND FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+/*
+ *     BEGIN_MANUAL_ENTRY(hwm_tx_init)
+ *     int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
+ *
+ * function    DOWN_CALL       (hardware module, hwmtm.c)
+ *             hwm_tx_init checks if the frame can be sent through the
+ *             corresponding send queue.
+ *
+ * para        fc      the frame control. To determine through which
+ *             send queue the frame should be transmitted.
+ *             0x50 - 0x57:    asynchronous LLC frame
+ *             0xD0 - 0xD7:    synchronous LLC frame
+ *             0x41, 0x4F:     SMT frame to the network
+ *             0x42:           SMT frame to the network and to the local SMT
+ *             0x43:           SMT frame to the local SMT
+ *     frag_count      count of the fragments for this frame
+ *     frame_len       length of the frame
+ *     frame_status    status of the frame, the send queue bit is already
+ *                     specified
+ *
+ * return              frame_status
+ *
+ *     END_MANUAL_ENTRY
+ */
+int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
+               int frame_status)
+{
+       NDD_TRACE("THiB",fc,frag_count,frame_len) ;
+       smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
+       smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;
+       smc->os.hwm.tx_len = frame_len ;
+       DB_TX("hwm_tx_init: fc = %x, len = %d",fc,frame_len,3) ;
+       if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
+               frame_status |= LAN_TX ;
+       }
+       else {
+               switch (fc) {
+               case FC_SMT_INFO :
+               case FC_SMT_NSA :
+                       frame_status |= LAN_TX ;
+                       break ;
+               case FC_SMT_LOC :
+                       frame_status |= LOC_TX ;
+                       break ;
+               case FC_SMT_LAN_LOC :
+                       frame_status |= LAN_TX | LOC_TX ;
+                       break ;
+               default :
+                       SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;
+               }
+       }
+       if (!smc->hw.mac_ring_is_up) {
+               frame_status &= ~LAN_TX ;
+               frame_status |= RING_DOWN ;
+               DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
+       }
+       if (frag_count > smc->os.hwm.tx_p->tx_free) {
+#ifndef        NDIS_OS2
+               mac_drv_clear_txd(smc) ;
+               if (frag_count > smc->os.hwm.tx_p->tx_free) {
+                       DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
+                       frame_status &= ~LAN_TX ;
+                       frame_status |= OUT_OF_TXD ;
+               }
+#else
+               DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
+               frame_status &= ~LAN_TX ;
+               frame_status |= OUT_OF_TXD ;
+#endif
+       }
+       DB_TX("frame_status = %x",frame_status,0,3) ;
+       NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
+       return frame_status;
+}
+
+/*
+ *     BEGIN_MANUAL_ENTRY(hwm_tx_frag)
+ *     void hwm_tx_frag(smc,virt,phys,len,frame_status)
+ *
+ * function    DOWNCALL        (hardware module, hwmtm.c)
+ *             If the frame should be sent to the LAN, this function calls
+ *             dma_master, fills the current TxD with the virtual and the
+ *             physical address, sets the STF and EOF bits dependent on
+ *             the frame status, and requests the BMU to start the
+ *             transmit.
+ *             If the frame should be sent to the local SMT, an SMT_MBuf
+ *             is allocated if the FIRST_FRAG bit is set in the frame_status.
+ *             The fragment of the frame is copied into the SMT MBuf.
+ *             The function smt_received_pack is called if the LAST_FRAG
+ *             bit is set in the frame_status word.
+ *
+ * para        virt    virtual pointer to the fragment
+ *     len     the length of the fragment
+ *     frame_status    status of the frame, see design description
+ *
+ * return      nothing returned, no parameter is modified
+ *
+ * NOTE:       It is possible to invoke this macro with a fragment length
+ *             of zero.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
+                int frame_status)
+{
+       struct s_smt_fp_txd volatile *t ;
+       struct s_smt_tx_queue *queue ;
+       __le32  tbctrl ;
+
+       queue = smc->os.hwm.tx_p ;
+
+       NDD_TRACE("THfB",virt,len,frame_status) ;
+       /* Bug fix: AF / May 31 1999 (#missing)
+        * snmpinfo problem reported by IBM is caused by invalid
+        * t-pointer (txd) if LAN_TX is not set but LOC_TX only.
+        * Set: t = queue->tx_curr_put  here !
+        */
+       t = queue->tx_curr_put ;
+
+       DB_TX("hwm_tx_frag: len = %d, frame_status = %x ",len,frame_status,2) ;
+       if (frame_status & LAN_TX) {
+               /* '*t' is already defined */
+               DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
+               t->txd_virt = virt ;
+               t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;
+               t->txd_tbadr = cpu_to_le32(phys) ;
+               tbctrl = cpu_to_le32((((__u32)frame_status &
+                       (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
+                       BMU_OWN|BMU_CHECK |len) ;
+               t->txd_tbctrl = tbctrl ;
+
+#ifndef        AIX
+               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+               outpd(queue->tx_bmu_ctl,CSR_START) ;
+#else  /* ifndef AIX */
+               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+               if (frame_status & QUEUE_A0) {
+                       outpd(ADDR(B0_XA_CSR),CSR_START) ;
+               }
+               else {
+                       outpd(ADDR(B0_XS_CSR),CSR_START) ;
+               }
+#endif
+               queue->tx_free-- ;
+               queue->tx_used++ ;
+               queue->tx_curr_put = t->txd_next ;
+               if (frame_status & LAST_FRAG) {
+                       smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
+               }
+       }
+       if (frame_status & LOC_TX) {
+               DB_TX("LOC_TX: ",0,0,3) ;
+               if (frame_status & FIRST_FRAG) {
+                       if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
+                               smc->hw.fp.err_stats.err_no_buf++ ;
+                               DB_TX("No SMbuf; transmit terminated",0,0,4) ;
+                       }
+                       else {
+                               smc->os.hwm.tx_data =
+                                       smtod(smc->os.hwm.tx_mb,char *) - 1 ;
+#ifdef USE_OS_CPY
+#ifdef PASS_1ST_TXD_2_TX_COMP
+                               hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
+                                       smc->os.hwm.tx_len) ;
+#endif
+#endif
+                       }
+               }
+               if (smc->os.hwm.tx_mb) {
+#ifndef        USE_OS_CPY
+                       DB_TX("copy fragment into MBuf ",0,0,3) ;
+                       memcpy(smc->os.hwm.tx_data,virt,len) ;
+                       smc->os.hwm.tx_data += len ;
+#endif
+                       if (frame_status & LAST_FRAG) {
+#ifdef USE_OS_CPY
+#ifndef PASS_1ST_TXD_2_TX_COMP
+                               /*
+                                * hwm_cpy_txd2mb(txd,data,len) copies 'len' 
+                                * bytes from the virtual pointer in 'rxd'
+                                * to 'data'. The virtual pointer of the 
+                                * os-specific tx-buffer should be written
+                                * in the LAST txd.
+                                */ 
+                               hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
+                                       smc->os.hwm.tx_len) ;
+#endif /* nPASS_1ST_TXD_2_TX_COMP */
+#endif /* USE_OS_CPY */
+                               smc->os.hwm.tx_data =
+                                       smtod(smc->os.hwm.tx_mb,char *) - 1 ;
+                               *(char *)smc->os.hwm.tx_mb->sm_data =
+                                       *smc->os.hwm.tx_data ;
+                               smc->os.hwm.tx_data++ ;
+                               smc->os.hwm.tx_mb->sm_len =
+                                       smc->os.hwm.tx_len - 1 ;
+                               DB_TX("pass LLC frame to SMT ",0,0,3) ;
+                               smt_received_pack(smc,smc->os.hwm.tx_mb,
+                                               RD_FS_LOCAL) ;
+                       }
+               }
+       }
+       NDD_TRACE("THfE",t,queue->tx_free,0) ;
+}
+
+
+/*
+ * queues a receive for later send
+ */
+static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
+{
+       DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
+       smc->os.hwm.queued_rx_frames++ ;
+       mb->sm_next = (SMbuf *)NULL ;
+       if (smc->os.hwm.llc_rx_pipe == NULL) {
+               smc->os.hwm.llc_rx_pipe = mb ;
+       }
+       else {
+               smc->os.hwm.llc_rx_tail->sm_next = mb ;
+       }
+       smc->os.hwm.llc_rx_tail = mb ;
+
+       /*
+        * force an timer IRQ to receive the data
+        */
+       if (!smc->os.hwm.isr_flag) {
+               smt_force_irq(smc) ;
+       }
+}
+
+/*
+ * get a SMbuf from the llc_rx_queue
+ */
+static SMbuf *get_llc_rx(struct s_smc *smc)
+{
+       SMbuf   *mb ;
+
+       if ((mb = smc->os.hwm.llc_rx_pipe)) {
+               smc->os.hwm.queued_rx_frames-- ;
+               smc->os.hwm.llc_rx_pipe = mb->sm_next ;
+       }
+       DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
+       return mb;
+}
+
+/*
+ * queues a transmit SMT MBuf during the time were the MBuf is
+ * queued the TxD ring
+ */
+static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)
+{
+       DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ;
+       smc->os.hwm.queued_txd_mb++ ;
+       mb->sm_next = (SMbuf *)NULL ;
+       if (smc->os.hwm.txd_tx_pipe == NULL) {
+               smc->os.hwm.txd_tx_pipe = mb ;
+       }
+       else {
+               smc->os.hwm.txd_tx_tail->sm_next = mb ;
+       }
+       smc->os.hwm.txd_tx_tail = mb ;
+}
+
+/*
+ * get a SMbuf from the txd_tx_queue
+ */
+static SMbuf *get_txd_mb(struct s_smc *smc)
+{
+       SMbuf *mb ;
+
+       if ((mb = smc->os.hwm.txd_tx_pipe)) {
+               smc->os.hwm.queued_txd_mb-- ;
+               smc->os.hwm.txd_tx_pipe = mb->sm_next ;
+       }
+       DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
+       return mb;
+}
+
+/*
+ *     SMT Send function
+ */
+void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
+{
+       char far *data ;
+       int     len ;
+       int     n ;
+       int     i ;
+       int     frag_count ;
+       int     frame_status ;
+       SK_LOC_DECL(char far,*virt[3]) ;
+       int     frag_len[3] ;
+       struct s_smt_tx_queue *queue ;
+       struct s_smt_fp_txd volatile *t ;
+       u_long  phys ;
+       __le32  tbctrl;
+
+       NDD_TRACE("THSB",mb,fc,0) ;
+       DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
+
+       mb->sm_off-- ;  /* set to fc */
+       mb->sm_len++ ;  /* + fc */
+       data = smtod(mb,char *) ;
+       *data = fc ;
+       if (fc == FC_SMT_LOC)
+               *data = FC_SMT_INFO ;
+
+       /*
+        * determine the frag count and the virt addresses of the frags
+        */
+       frag_count = 0 ;
+       len = mb->sm_len ;
+       while (len) {
+               n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ;
+               if (n >= len) {
+                       n = len ;
+               }
+               DB_TX("frag: virt/len = 0x%x/%d ",(void *)data,n,5) ;
+               virt[frag_count] = data ;
+               frag_len[frag_count] = n ;
+               frag_count++ ;
+               len -= n ;
+               data += n ;
+       }
+
+       /*
+        * determine the frame status
+        */
+       queue = smc->hw.fp.tx[QUEUE_A0] ;
+       if (fc == FC_BEACON || fc == FC_SMT_LOC) {
+               frame_status = LOC_TX ;
+       }
+       else {
+               frame_status = LAN_TX ;
+               if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||
+                  (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))
+                       frame_status |= LOC_TX ;
+       }
+
+       if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
+               frame_status &= ~LAN_TX;
+               if (frame_status) {
+                       DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
+               }
+               else {
+                       DB_TX("Ring is down: terminate transmission",0,0,2) ;
+                       smt_free_mbuf(smc,mb) ;
+                       return ;
+               }
+       }
+       DB_TX("frame_status = 0x%x ",frame_status,0,5) ;
+
+       if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {
+               mb->sm_use_count = 2 ;
+       }
+
+       if (frame_status & LAN_TX) {
+               t = queue->tx_curr_put ;
+               frame_status |= FIRST_FRAG ;
+               for (i = 0; i < frag_count; i++) {
+                       DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
+                       if (i == frag_count-1) {
+                               frame_status |= LAST_FRAG ;
+                               t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR |
+                                       (((__u32)(mb->sm_len-1)&3) << 27)) ;
+                       }
+                       t->txd_virt = virt[i] ;
+                       phys = dma_master(smc, (void far *)virt[i],
+                               frag_len[i], DMA_RD|SMT_BUF) ;
+                       t->txd_tbadr = cpu_to_le32(phys) ;
+                       tbctrl = cpu_to_le32((((__u32)frame_status &
+                               (FIRST_FRAG|LAST_FRAG)) << 26) |
+                               BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
+                       t->txd_tbctrl = tbctrl ;
+#ifndef        AIX
+                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+                       outpd(queue->tx_bmu_ctl,CSR_START) ;
+#else
+                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+                       outpd(ADDR(B0_XA_CSR),CSR_START) ;
+#endif
+                       frame_status &= ~FIRST_FRAG ;
+                       queue->tx_curr_put = t = t->txd_next ;
+                       queue->tx_free-- ;
+                       queue->tx_used++ ;
+               }
+               smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
+               queue_txd_mb(smc,mb) ;
+       }
+
+       if (frame_status & LOC_TX) {
+               DB_TX("pass Mbuf to LLC queue",0,0,5) ;
+               queue_llc_rx(smc,mb) ;
+       }
+
+       /*
+        * We need to unqueue the free SMT_MBUFs here, because it may
+        * be that the SMT want's to send more than 1 frame for one down call
+        */
+       mac_drv_clear_txd(smc) ;
+       NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;
+}
+
+/*     BEGIN_MANUAL_ENTRY(mac_drv_clear_txd)
+ *     void mac_drv_clear_txd(smc)
+ *
+ * function    DOWNCALL        (hardware module, hwmtm.c)
+ *             mac_drv_clear_txd searches in both send queues for TxD's
+ *             which were finished by the adapter. It calls dma_complete
+ *             for each TxD. If the last fragment of an LLC frame is
+ *             reached, it calls mac_drv_tx_complete to release the
+ *             send buffer.
+ *
+ * return      nothing
+ *
+ *     END_MANUAL_ENTRY
+ */
+static void mac_drv_clear_txd(struct s_smc *smc)
+{
+       struct s_smt_tx_queue *queue ;
+       struct s_smt_fp_txd volatile *t1 ;
+       struct s_smt_fp_txd volatile *t2 = NULL ;
+       SMbuf *mb ;
+       u_long  tbctrl ;
+       int i ;
+       int frag_count ;
+       int n ;
+
+       NDD_TRACE("THcB",0,0,0) ;
+       for (i = QUEUE_S; i <= QUEUE_A0; i++) {
+               queue = smc->hw.fp.tx[i] ;
+               t1 = queue->tx_curr_get ;
+               DB_TX("clear_txd: QUEUE = %d (0=sync/1=async)",i,0,5) ;
+
+               for ( ; ; ) {
+                       frag_count = 0 ;
+
+                       do {
+                               DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
+                               DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
+                               tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl));
+
+                               if (tbctrl & BMU_OWN || !queue->tx_used){
+                                       DB_TX("End of TxDs queue %d",i,0,4) ;
+                                       goto free_next_queue ;  /* next queue */
+                               }
+                               t1 = t1->txd_next ;
+                               frag_count++ ;
+                       } while (!(tbctrl & BMU_EOF)) ;
+
+                       t1 = queue->tx_curr_get ;
+                       for (n = frag_count; n; n--) {
+                               tbctrl = le32_to_cpu(t1->txd_tbctrl) ;
+                               dma_complete(smc,
+                                       (union s_fp_descr volatile *) t1,
+                                       (int) (DMA_RD |
+                                       ((tbctrl & BMU_SMT_TX) >> 18))) ;
+                               t2 = t1 ;
+                               t1 = t1->txd_next ;
+                       }
+
+                       if (tbctrl & BMU_SMT_TX) {
+                               mb = get_txd_mb(smc) ;
+                               smt_free_mbuf(smc,mb) ;
+                       }
+                       else {
+#ifndef PASS_1ST_TXD_2_TX_COMP
+                               DB_TX("mac_drv_tx_comp for TxD 0x%x",t2,0,4) ;
+                               mac_drv_tx_complete(smc,t2) ;
+#else
+                               DB_TX("mac_drv_tx_comp for TxD 0x%x",
+                                       queue->tx_curr_get,0,4) ;
+                               mac_drv_tx_complete(smc,queue->tx_curr_get) ;
+#endif
+                       }
+                       queue->tx_curr_get = t1 ;
+                       queue->tx_free += frag_count ;
+                       queue->tx_used -= frag_count ;
+               }
+free_next_queue: ;
+       }
+       NDD_TRACE("THcE",0,0,0) ;
+}
+
+/*
+ *     BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue)
+ *
+ * void mac_drv_clear_tx_queue(smc)
+ * struct s_smc *smc ;
+ *
+ * function    DOWNCALL        (hardware module, hwmtm.c)
+ *             mac_drv_clear_tx_queue is called from the SMT when
+ *             the RMT state machine has entered the ISOLATE state.
+ *             This function is also called by the os-specific module
+ *             after it has called the function card_stop().
+ *             In this case, the frames in the send queues are obsolete and
+ *             should be removed.
+ *
+ * note                calling sequence:
+ *             CLI_FBI(), card_stop(),
+ *             mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
+ *
+ * NOTE:       The caller is responsible that the BMUs are idle
+ *             when this function is called.
+ *
+ *     END_MANUAL_ENTRY
+ */
+void mac_drv_clear_tx_queue(struct s_smc *smc)
+{
+       struct s_smt_fp_txd volatile *t ;
+       struct s_smt_tx_queue *queue ;
+       int tx_used ;
+       int i ;
+
+       if (smc->hw.hw_state != STOPPED) {
+               SK_BREAK() ;
+               SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;
+               return ;
+       }
+
+       for (i = QUEUE_S; i <= QUEUE_A0; i++) {
+               queue = smc->hw.fp.tx[i] ;
+               DB_TX("clear_tx_queue: QUEUE = %d (0=sync/1=async)",i,0,5) ;
+
+               /*
+                * switch the OWN bit of all pending frames to the host
+                */
+               t = queue->tx_curr_get ;
+               tx_used = queue->tx_used ;
+               while (tx_used) {
+                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
+                       DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
+                       t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
+                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
+                       t = t->txd_next ;
+                       tx_used-- ;
+               }
+       }
+
+       /*
+        * release all TxD's for both send queues
+        */
+       mac_drv_clear_txd(smc) ;
+
+       for (i = QUEUE_S; i <= QUEUE_A0; i++) {
+               queue = smc->hw.fp.tx[i] ;
+               t = queue->tx_curr_get ;
+
+               /*
+                * write the phys pointer of the NEXT descriptor into the
+                * BMU's current address descriptor pointer and set
+                * tx_curr_get and tx_curr_put to this position
+                */
+               if (i == QUEUE_S) {
+                       outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ;
+               }
+               else {
+                       outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ;
+               }
+
+               queue->tx_curr_put = queue->tx_curr_get->txd_next ;
+               queue->tx_curr_get = queue->tx_curr_put ;
+       }
+}
+
+
+/*
+       -------------------------------------------------------------
+       TEST FUNCTIONS:
+       -------------------------------------------------------------
+*/
+
+#ifdef DEBUG
+/*
+ *     BEGIN_MANUAL_ENTRY(mac_drv_debug_lev)
+ *     void mac_drv_debug_lev(smc,flag,lev)
+ *
+ * function    DOWNCALL        (drvsr.c)
+ *             To get a special debug info the user can assign a debug level
+ *             to any debug flag.
+ *
+ * para        flag    debug flag, possible values are:
+ *                     = 0:    reset all debug flags (the defined level is
+ *                             ignored)
+ *                     = 1:    debug.d_smtf
+ *                     = 2:    debug.d_smt
+ *                     = 3:    debug.d_ecm
+ *                     = 4:    debug.d_rmt
+ *                     = 5:    debug.d_cfm
+ *                     = 6:    debug.d_pcm
+ *
+ *                     = 10:   debug.d_os.hwm_rx (hardware module receive path)
+ *                     = 11:   debug.d_os.hwm_tx(hardware module transmit path)
+ *                     = 12:   debug.d_os.hwm_gen(hardware module general flag)
+ *
+ *     lev     debug level
+ *
+ *     END_MANUAL_ENTRY
+ */
+void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)
+{
+       switch(flag) {
+       case (int)NULL:
+               DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;
+               DB_P.d_cfm = 0 ;
+               DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;
+#ifdef SBA
+               DB_P.d_sba = 0 ;
+#endif
+#ifdef ESS
+               DB_P.d_ess = 0 ;
+#endif
+               break ;
+       case DEBUG_SMTF:
+               DB_P.d_smtf = lev ;
+               break ;
+       case DEBUG_SMT:
+               DB_P.d_smt = lev ;
+               break ;
+       case DEBUG_ECM:
+               DB_P.d_ecm = lev ;
+               break ;
+       case DEBUG_RMT:
+               DB_P.d_rmt = lev ;
+               break ;
+       case DEBUG_CFM:
+               DB_P.d_cfm = lev ;
+               break ;
+       case DEBUG_PCM:
+               DB_P.d_pcm = lev ;
+               break ;
+       case DEBUG_SBA:
+#ifdef SBA
+               DB_P.d_sba = lev ;
+#endif
+               break ;
+       case DEBUG_ESS:
+#ifdef ESS
+               DB_P.d_ess = lev ;
+#endif
+               break ;
+       case DB_HWM_RX:
+               DB_P.d_os.hwm_rx = lev ;
+               break ;
+       case DB_HWM_TX:
+               DB_P.d_os.hwm_tx = lev ;
+               break ;
+       case DB_HWM_GEN:
+               DB_P.d_os.hwm_gen = lev ;
+               break ;
+       default:
+               break ;
+       }
+}
+#endif
diff --git a/drivers/net/fddi/skfp/hwt.c b/drivers/net/fddi/skfp/hwt.c
new file mode 100644 (file)
index 0000000..c0798fd
--- /dev/null
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Timer Driver for FBI board (timer chip 82C54)
+ */
+
+/*
+ * Modifications:
+ *
+ *     28-Jun-1994 sw  Edit v1.6.
+ *                     MCA: Added support for the SK-NET FDDI-FM2 adapter. The
+ *                      following functions have been added(+) or modified(*):
+ *                      hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*)
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)hwt.c       1.13 97/04/23 (C) SK " ;
+#endif
+
+/*
+ * Prototypes of local functions.
+ */
+/* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
+/*static void hwt_restart() ; */
+
+/************************
+ *
+ *     hwt_start
+ *
+ *     Start hardware timer (clock ticks are 16us).
+ *
+ *     void hwt_start(
+ *             struct s_smc *smc,
+ *             u_long time) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ *
+ *     time - The time in units of 16us to load the timer with.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+#define        HWT_MAX (65000)
+
+void hwt_start(struct s_smc *smc, u_long time)
+{
+       u_short cnt ;
+
+       if (time > HWT_MAX)
+               time = HWT_MAX ;
+
+       smc->hw.t_start = time ;
+       smc->hw.t_stop = 0L ;
+
+       cnt = (u_short)time ;
+       /*
+        * if time < 16 us
+        *      time = 16 us
+        */
+       if (!cnt)
+               cnt++ ;
+
+       outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ;    /* Load timer value. */
+       outpw(ADDR(B2_TI_CRTL), TIM_START) ;            /* Start timer. */
+
+       smc->hw.timer_activ = TRUE ;
+}
+
+/************************
+ *
+ *     hwt_stop
+ *
+ *     Stop hardware timer.
+ *
+ *     void hwt_stop(
+ *             struct s_smc *smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void hwt_stop(struct s_smc *smc)
+{
+       outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+       outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;
+
+       smc->hw.timer_activ = FALSE ;
+}
+
+/************************
+ *
+ *     hwt_init
+ *
+ *     Initialize hardware timer.
+ *
+ *     void hwt_init(
+ *             struct s_smc *smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void hwt_init(struct s_smc *smc)
+{
+       smc->hw.t_start = 0 ;
+       smc->hw.t_stop  = 0 ;
+       smc->hw.timer_activ = FALSE ;
+
+       hwt_restart(smc) ;
+}
+
+/************************
+ *
+ *     hwt_restart
+ *
+ *     Clear timer interrupt.
+ *
+ *     void hwt_restart(
+ *             struct s_smc *smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void hwt_restart(struct s_smc *smc)
+{
+       hwt_stop(smc) ;
+}
+
+/************************
+ *
+ *     hwt_read
+ *
+ *     Stop hardware timer and read time elapsed since last start.
+ *
+ *     u_long hwt_read(smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     The elapsed time since last start in units of 16us.
+ *
+ ************************/
+u_long hwt_read(struct s_smc *smc)
+{
+       u_short tr ;
+       u_long  is ;
+
+       if (smc->hw.timer_activ) {
+               hwt_stop(smc) ;
+               tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;
+
+               is = GET_ISR() ;
+               /* Check if timer expired (or wraparound). */
+               if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {
+                       hwt_restart(smc) ;
+                       smc->hw.t_stop = smc->hw.t_start ;
+               }
+               else
+                       smc->hw.t_stop = smc->hw.t_start - tr ;
+       }
+       return smc->hw.t_stop;
+}
+
+#ifdef PCI
+/************************
+ *
+ *     hwt_quick_read
+ *
+ *     Stop hardware timer and read timer value and start the timer again.
+ *
+ *     u_long hwt_read(smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     current timer value in units of 80ns.
+ *
+ ************************/
+u_long hwt_quick_read(struct s_smc *smc)
+{
+       u_long interval ;
+       u_long time ;
+
+       interval = inpd(ADDR(B2_TI_INI)) ;
+       outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+       time = inpd(ADDR(B2_TI_VAL)) ;
+       outpd(ADDR(B2_TI_INI),time) ;
+       outpw(ADDR(B2_TI_CRTL), TIM_START) ;
+       outpd(ADDR(B2_TI_INI),interval) ;
+
+       return time;
+}
+
+/************************
+ *
+ *     hwt_wait_time(smc,start,duration)
+ *
+ *     This function returnes after the amount of time is elapsed
+ *     since the start time.
+ * 
+ * para        start           start time
+ *     duration        time to wait
+ *
+ * NOTE: The function will return immediately, if the timer is not
+ *      started
+ ************************/
+void hwt_wait_time(struct s_smc *smc, u_long start, long int duration)
+{
+       long    diff ;
+       long    interval ;
+       int     wrapped ;
+
+       /*
+        * check if timer is running
+        */
+       if (smc->hw.timer_activ == FALSE ||
+               hwt_quick_read(smc) == hwt_quick_read(smc)) {
+               return ;
+       }
+
+       interval = inpd(ADDR(B2_TI_INI)) ;
+       if (interval > duration) {
+               do {
+                       diff = (long)(start - hwt_quick_read(smc)) ;
+                       if (diff < 0) {
+                               diff += interval ;
+                       }
+               } while (diff <= duration) ;
+       }
+       else {
+               diff = interval ;
+               wrapped = 0 ;
+               do {
+                       if (!wrapped) {
+                               if (hwt_quick_read(smc) >= start) {
+                                       diff += interval ;
+                                       wrapped = 1 ;
+                               }
+                       }
+                       else {
+                               if (hwt_quick_read(smc) < start) {
+                                       wrapped = 0 ;
+                               }
+                       }
+               } while (diff <= duration) ;
+       }
+}
+#endif
+
diff --git a/drivers/net/fddi/skfp/pcmplc.c b/drivers/net/fddi/skfp/pcmplc.c
new file mode 100644 (file)
index 0000000..88d02d0
--- /dev/null
@@ -0,0 +1,2014 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       PCM
+       Physical Connection Management
+*/
+
+/*
+ * Hardware independent state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ *             queue_event()
+ *             smt_timer_start()
+ *             smt_timer_stop()
+ *
+ *     The following external HW dependent functions are referenced :
+ *             sm_pm_control()
+ *             sm_ph_linestate()
+ *             sm_pm_ls_latch()
+ *
+ *     The following HW dependent events are required :
+ *             PC_QLS
+ *             PC_ILS
+ *             PC_HLS
+ *             PC_MLS
+ *             PC_NSE
+ *             PC_LEM
+ *
+ */
+
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/supern_2.h"
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)pcmplc.c    2.55 99/08/05 (C) SK " ;
+#endif
+
+#ifdef FDDI_MIB
+extern int snmp_fddi_trap(
+#ifdef ANSIC
+struct s_smc   * smc, int  type, int  index
+#endif
+);
+#endif
+#ifdef CONCENTRATOR
+extern int plc_is_installed(
+#ifdef ANSIC
+struct s_smc *smc ,
+int p
+#endif
+) ;
+#endif
+/*
+ * FSM Macros
+ */
+#define AFLAG          (0x20)
+#define GO_STATE(x)    (mib->fddiPORTPCMState = (x)|AFLAG)
+#define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG)
+#define ACTIONS(x)     (x|AFLAG)
+
+/*
+ * PCM states
+ */
+#define PC0_OFF                        0
+#define PC1_BREAK              1
+#define PC2_TRACE              2
+#define PC3_CONNECT            3
+#define PC4_NEXT               4
+#define PC5_SIGNAL             5
+#define PC6_JOIN               6
+#define PC7_VERIFY             7
+#define PC8_ACTIVE             8
+#define PC9_MAINT              9
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const pcm_states[] =  {
+       "PC0_OFF","PC1_BREAK","PC2_TRACE","PC3_CONNECT","PC4_NEXT",
+       "PC5_SIGNAL","PC6_JOIN","PC7_VERIFY","PC8_ACTIVE","PC9_MAINT"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const pcm_events[] = {
+       "NONE","PC_START","PC_STOP","PC_LOOP","PC_JOIN","PC_SIGNAL",
+       "PC_REJECT","PC_MAINT","PC_TRACE","PC_PDR",
+       "PC_ENABLE","PC_DISABLE",
+       "PC_QLS","PC_ILS","PC_MLS","PC_HLS","PC_LS_PDR","PC_LS_NONE",
+       "PC_TIMEOUT_TB_MAX","PC_TIMEOUT_TB_MIN",
+       "PC_TIMEOUT_C_MIN","PC_TIMEOUT_T_OUT",
+       "PC_TIMEOUT_TL_MIN","PC_TIMEOUT_T_NEXT","PC_TIMEOUT_LCT",
+       "PC_NSE","PC_LEM"
+} ;
+#endif
+
+#ifdef MOT_ELM
+/*
+ * PCL-S control register
+ * this register in the PLC-S controls the scrambling parameters
+ */
+#define PLCS_CONTROL_C_U       0
+#define PLCS_CONTROL_C_S       (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \
+                                PL_C_CIPHER_ENABLE)
+#define        PLCS_FASSERT_U          0
+#define        PLCS_FASSERT_S          0xFd76  /* 52.0 us */
+#define        PLCS_FDEASSERT_U        0
+#define        PLCS_FDEASSERT_S        0
+#else  /* nMOT_ELM */
+/*
+ * PCL-S control register
+ * this register in the PLC-S controls the scrambling parameters
+ * can be patched for ANSI compliance if standard changes
+ */
+static const u_char plcs_control_c_u[17] = "PLC_CNTRL_C_U=\0\0" ;
+static const u_char plcs_control_c_s[17] = "PLC_CNTRL_C_S=\01\02" ;
+
+#define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8))
+#define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8))
+#endif /* nMOT_ELM */
+
+/*
+ * external vars
+ */
+/* struct definition see 'cmtdef.h' (also used by CFM) */
+
+#define PS_OFF         0
+#define PS_BIT3                1
+#define PS_BIT4                2
+#define PS_BIT7                3
+#define PS_LCT         4
+#define PS_BIT8                5
+#define PS_JOIN                6
+#define PS_ACTIVE      7
+
+#define LCT_LEM_MAX    255
+
+/*
+ * PLC timing parameter
+ */
+
+#define PLC_MS(m)      ((int)((0x10000L-(m*100000L/2048))))
+#define SLOW_TL_MIN    PLC_MS(6)
+#define SLOW_C_MIN     PLC_MS(10)
+
+static const struct plt {
+       int     timer ;                 /* relative plc timer address */
+       int     para ;                  /* default timing parameters */
+} pltm[] = {
+       { PL_C_MIN, SLOW_C_MIN },       /* min t. to remain Connect State */
+       { PL_TL_MIN, SLOW_TL_MIN },     /* min t. to transmit a Line State */
+       { PL_TB_MIN, TP_TB_MIN },       /* min break time */
+       { PL_T_OUT, TP_T_OUT },         /* Signaling timeout */
+       { PL_LC_LENGTH, TP_LC_LENGTH }, /* Link Confidence Test Time */
+       { PL_T_SCRUB, TP_T_SCRUB },     /* Scrub Time == MAC TVX time ! */
+       { PL_NS_MAX, TP_NS_MAX },       /* max t. that noise is tolerated */
+       { 0,0 }
+} ;
+
+/*
+ * interrupt mask
+ */
+#ifdef SUPERNET_3
+/*
+ * Do we need the EBUF error during signaling, too, to detect SUPERNET_3
+ * PLL bug?
+ */
+static const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+                       PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
+#else  /* SUPERNET_3 */
+/*
+ * We do NOT need the elasticity buffer error during signaling.
+ */
+static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+                       PL_PCM_ENABLED | PL_SELF_TEST ;
+#endif /* SUPERNET_3 */
+static const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
+                       PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
+
+/* internal functions */
+static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd);
+static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy);
+static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy);
+static void reset_lem_struct(struct s_phy *phy);
+static void plc_init(struct s_smc *smc, int p);
+static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold);
+static void sm_ph_lem_stop(struct s_smc *smc, int np);
+static void sm_ph_linestate(struct s_smc *smc, int phy, int ls);
+static void real_init_plc(struct s_smc *smc);
+
+/*
+ * SMT timer interface
+ *      start PCM timer 0
+ */
+static void start_pcm_timer0(struct s_smc *smc, u_long value, int event,
+                            struct s_phy *phy)
+{
+       phy->timer0_exp = FALSE ;       /* clear timer event flag */
+       smt_timer_start(smc,&phy->pcm_timer0,value,
+               EV_TOKEN(EVENT_PCM+phy->np,event)) ;
+}
+/*
+ * SMT timer interface
+ *      stop PCM timer 0
+ */
+static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy)
+{
+       if (phy->pcm_timer0.tm_active)
+               smt_timer_stop(smc,&phy->pcm_timer0) ;
+}
+
+/*
+       init PCM state machine (called by driver)
+       clear all PCM vars and flags
+*/
+void pcm_init(struct s_smc *smc)
+{
+       int             i ;
+       int             np ;
+       struct s_phy    *phy ;
+       struct fddi_mib_p       *mib ;
+
+       for (np = 0,phy = smc->y ; np < NUMPHYS ; np++,phy++) {
+               /* Indicates the type of PHY being used */
+               mib = phy->mib ;
+               mib->fddiPORTPCMState = ACTIONS(PC0_OFF) ;
+               phy->np = np ;
+               switch (smc->s.sas) {
+#ifdef CONCENTRATOR
+               case SMT_SAS :
+                       mib->fddiPORTMy_Type = (np == PS) ? TS : TM ;
+                       break ;
+               case SMT_DAS :
+                       mib->fddiPORTMy_Type = (np == PA) ? TA :
+                                       (np == PB) ? TB : TM ;
+                       break ;
+               case SMT_NAC :
+                       mib->fddiPORTMy_Type = TM ;
+                       break;
+#else
+               case SMT_SAS :
+                       mib->fddiPORTMy_Type = (np == PS) ? TS : TNONE ;
+                       mib->fddiPORTHardwarePresent = (np == PS) ? TRUE :
+                                       FALSE ;
+#ifndef        SUPERNET_3
+                       smc->y[PA].mib->fddiPORTPCMState = PC0_OFF ;
+#else
+                       smc->y[PB].mib->fddiPORTPCMState = PC0_OFF ;
+#endif
+                       break ;
+               case SMT_DAS :
+                       mib->fddiPORTMy_Type = (np == PB) ? TB : TA ;
+                       break ;
+#endif
+               }
+               /*
+                * set PMD-type
+                */
+               phy->pmd_scramble = 0 ;
+               switch (phy->pmd_type[PMD_SK_PMD]) {
+               case 'P' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
+                       break ;
+               case 'L' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_LCF ;
+                       break ;
+               case 'D' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+                       break ;
+               case 'S' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+                       phy->pmd_scramble = TRUE ;
+                       break ;
+               case 'U' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+                       phy->pmd_scramble = TRUE ;
+                       break ;
+               case '1' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
+                       break ;
+               case '2' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
+                       break ;
+               case '3' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
+                       break ;
+               case '4' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
+                       break ;
+               case 'H' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
+                       break ;
+               case 'I' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+                       break ;
+               case 'G' :
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
+                       break ;
+               default:
+                       mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
+                       break ;
+               }
+               /*
+                * A and B port can be on primary and secondary path
+                */
+               switch (mib->fddiPORTMy_Type) {
+               case TA :
+                       mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
+                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+                       mib->fddiPORTRequestedPaths[2] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_CON_ALTER |
+                               MIB_P_PATH_SEC_PREFER ;
+                       mib->fddiPORTRequestedPaths[3] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_CON_ALTER |
+                               MIB_P_PATH_SEC_PREFER |
+                               MIB_P_PATH_THRU ;
+                       break ;
+               case TB :
+                       mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
+                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+                       mib->fddiPORTRequestedPaths[2] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_PRIM_PREFER ;
+                       mib->fddiPORTRequestedPaths[3] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_PRIM_PREFER |
+                               MIB_P_PATH_CON_PREFER |
+                               MIB_P_PATH_THRU ;
+                       break ;
+               case TS :
+                       mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
+                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+                       mib->fddiPORTRequestedPaths[2] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_CON_ALTER |
+                               MIB_P_PATH_PRIM_PREFER ;
+                       mib->fddiPORTRequestedPaths[3] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_CON_ALTER |
+                               MIB_P_PATH_PRIM_PREFER ;
+                       break ;
+               case TM :
+                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
+                       mib->fddiPORTRequestedPaths[2] =
+                               MIB_P_PATH_LOCAL |
+                               MIB_P_PATH_SEC_ALTER |
+                               MIB_P_PATH_PRIM_ALTER ;
+                       mib->fddiPORTRequestedPaths[3] = 0 ;
+                       break ;
+               }
+
+               phy->pc_lem_fail = FALSE ;
+               mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ;
+               mib->fddiPORTLCTFail_Ct = 0 ;
+               mib->fddiPORTBS_Flag = 0 ;
+               mib->fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
+               mib->fddiPORTNeighborType = TNONE ;
+               phy->ls_flag = 0 ;
+               phy->rc_flag = 0 ;
+               phy->tc_flag = 0 ;
+               phy->td_flag = 0 ;
+               if (np >= PM)
+                       phy->phy_name = '0' + np - PM ;
+               else
+                       phy->phy_name = 'A' + np ;
+               phy->wc_flag = FALSE ;          /* set by SMT */
+               memset((char *)&phy->lem,0,sizeof(struct lem_counter)) ;
+               reset_lem_struct(phy) ;
+               memset((char *)&phy->plc,0,sizeof(struct s_plc)) ;
+               phy->plc.p_state = PS_OFF ;
+               for (i = 0 ; i < NUMBITS ; i++) {
+                       phy->t_next[i] = 0 ;
+               }
+       }
+       real_init_plc(smc) ;
+}
+
+void init_plc(struct s_smc *smc)
+{
+       SK_UNUSED(smc) ;
+
+       /*
+        * dummy
+        * this is an obsolete public entry point that has to remain
+        * for compat. It is used by various drivers.
+        * the work is now done in real_init_plc()
+        * which is called from pcm_init() ;
+        */
+}
+
+static void real_init_plc(struct s_smc *smc)
+{
+       int     p ;
+
+       for (p = 0 ; p < NUMPHYS ; p++)
+               plc_init(smc,p) ;
+}
+
+static void plc_init(struct s_smc *smc, int p)
+{
+       int     i ;
+#ifndef        MOT_ELM
+       int     rev ;   /* Revision of PLC-x */
+#endif /* MOT_ELM */
+
+       /* transit PCM state machine to MAINT state */
+       outpw(PLC(p,PL_CNTRL_B),0) ;
+       outpw(PLC(p,PL_CNTRL_B),PL_PCM_STOP) ;
+       outpw(PLC(p,PL_CNTRL_A),0) ;
+
+       /*
+        * if PLC-S then set control register C
+        */
+#ifndef        MOT_ELM
+       rev = inpw(PLC(p,PL_STATUS_A)) & PLC_REV_MASK ;
+       if (rev != PLC_REVISION_A)
+#endif /* MOT_ELM */
+       {
+               if (smc->y[p].pmd_scramble) {
+                       outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_S) ;
+#ifdef MOT_ELM
+                       outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ;
+                       outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ;
+#endif /* MOT_ELM */
+               }
+               else {
+                       outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_U) ;
+#ifdef MOT_ELM
+                       outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ;
+                       outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ;
+#endif /* MOT_ELM */
+               }
+       }
+
+       /*
+        * set timer register
+        */
+       for ( i = 0 ; pltm[i].timer; i++)       /* set timer parameter reg */
+               outpw(PLC(p,pltm[i].timer),pltm[i].para) ;
+
+       (void)inpw(PLC(p,PL_INTR_EVENT)) ;      /* clear interrupt event reg */
+       plc_clear_irq(smc,p) ;
+       outpw(PLC(p,PL_INTR_MASK),plc_imsk_na); /* enable non active irq's */
+
+       /*
+        * if PCM is configured for class s, it will NOT go to the
+        * REMOVE state if offline (page 3-36;)
+        * in the concentrator, all inactive PHYS always must be in
+        * the remove state
+        * there's no real need to use this feature at all ..
+        */
+#ifndef        CONCENTRATOR
+       if ((smc->s.sas == SMT_SAS) && (p == PS)) {
+               outpw(PLC(p,PL_CNTRL_B),PL_CLASS_S) ;
+       }
+#endif
+}
+
+/*
+ * control PCM state machine
+ */
+static void plc_go_state(struct s_smc *smc, int p, int state)
+{
+       HW_PTR port ;
+       int val ;
+
+       SK_UNUSED(smc) ;
+
+       port = (HW_PTR) (PLC(p,PL_CNTRL_B)) ;
+       val = inpw(port) & ~(PL_PCM_CNTRL | PL_MAINT) ;
+       outpw(port,val) ;
+       outpw(port,val | state) ;
+}
+
+/*
+ * read current line state (called by ECM & PCM)
+ */
+int sm_pm_get_ls(struct s_smc *smc, int phy)
+{
+       int     state ;
+
+#ifdef CONCENTRATOR
+       if (!plc_is_installed(smc,phy))
+               return PC_QLS;
+#endif
+
+       state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
+       switch(state) {
+       case PL_L_QLS:
+               state = PC_QLS ;
+               break ;
+       case PL_L_MLS:
+               state = PC_MLS ;
+               break ;
+       case PL_L_HLS:
+               state = PC_HLS ;
+               break ;
+       case PL_L_ILS4:
+       case PL_L_ILS16:
+               state = PC_ILS ;
+               break ;
+       case PL_L_ALS:
+               state = PC_LS_PDR ;
+               break ;
+       default :
+               state = PC_LS_NONE ;
+       }
+       return state;
+}
+
+static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
+{
+       int np = phy->np ;              /* PHY index */
+       int     n ;
+       int     i ;
+
+       SK_UNUSED(smc) ;
+
+       /* create bit vector */
+       for (i = len-1,n = 0 ; i >= 0 ; i--) {
+               n = (n<<1) | phy->t_val[phy->bitn+i] ;
+       }
+       if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
+#if    0
+               printf("PL_PCM_SIGNAL is set\n") ;
+#endif
+               return 1;
+       }
+       /* write bit[n] & length = 1 to regs */
+       outpw(PLC(np,PL_VECTOR_LEN),len-1) ;    /* len=nr-1 */
+       outpw(PLC(np,PL_XMIT_VECTOR),n) ;
+#ifdef DEBUG
+#if 1
+#ifdef DEBUG_BRD
+       if (smc->debug.d_plc & 0x80)
+#else
+       if (debug.d_plc & 0x80)
+#endif
+               printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
+#endif
+#endif
+       return 0;
+}
+
+/*
+ * config plc muxes
+ */
+void plc_config_mux(struct s_smc *smc, int mux)
+{
+       if (smc->s.sas != SMT_DAS)
+               return ;
+       if (mux == MUX_WRAPB) {
+               SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
+               SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
+       }
+       else {
+               CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
+               CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ;
+       }
+       CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
+       CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ;
+}
+
+/*
+       PCM state machine
+       called by dispatcher  & fddi_init() (driver)
+       do
+               display state change
+               process event
+       until SM is stable
+*/
+void pcm(struct s_smc *smc, const int np, int event)
+{
+       int     state ;
+       int     oldstate ;
+       struct s_phy    *phy ;
+       struct fddi_mib_p       *mib ;
+
+#ifndef        CONCENTRATOR
+       /*
+        * ignore 2nd PHY if SAS
+        */
+       if ((np != PS) && (smc->s.sas == SMT_SAS))
+               return ;
+#endif
+       phy = &smc->y[np] ;
+       mib = phy->mib ;
+       oldstate = mib->fddiPORTPCMState ;
+       do {
+               DB_PCM("PCM %c: state %s",
+                       phy->phy_name,
+                       (mib->fddiPORTPCMState & AFLAG) ? "ACTIONS " : "") ;
+               DB_PCM("%s, event %s\n",
+                       pcm_states[mib->fddiPORTPCMState & ~AFLAG],
+                       pcm_events[event]) ;
+               state = mib->fddiPORTPCMState ;
+               pcm_fsm(smc,phy,event) ;
+               event = 0 ;
+       } while (state != mib->fddiPORTPCMState) ;
+       /*
+        * because the PLC does the bit signaling for us,
+        * we're always in SIGNAL state
+        * the MIB want's to see CONNECT
+        * we therefore fake an entry in the MIB
+        */
+       if (state == PC5_SIGNAL)
+               mib->fddiPORTPCMStateX = PC3_CONNECT ;
+       else
+               mib->fddiPORTPCMStateX = state ;
+
+#ifndef        SLIM_SMT
+       /*
+        * path change
+        */
+       if (    mib->fddiPORTPCMState != oldstate &&
+               ((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {
+               smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,
+                       (int) (INDEX_PORT+ phy->np),0) ;
+       }
+#endif
+
+#ifdef FDDI_MIB
+       /* check whether a snmp-trap has to be sent */
+
+       if ( mib->fddiPORTPCMState != oldstate ) {
+               /* a real state change took place */
+               DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
+               if ( mib->fddiPORTPCMState == PC0_OFF ) {
+                       /* send first trap */
+                       snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );
+               } else if ( oldstate == PC0_OFF ) {
+                       /* send second trap */
+                       snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );
+               } else if ( mib->fddiPORTPCMState != PC2_TRACE &&
+                       oldstate == PC8_ACTIVE ) {
+                       /* send third trap */
+                       snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );
+               } else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {
+                       /* send fourth trap */
+                       snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );
+               }
+       }
+#endif
+
+       pcm_state_change(smc,np,state) ;
+}
+
+/*
+ * PCM state machine
+ */
+static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd)
+{
+       int     i ;
+       int     np = phy->np ;          /* PHY index */
+       struct s_plc    *plc ;
+       struct fddi_mib_p       *mib ;
+#ifndef        MOT_ELM
+       u_short plc_rev ;               /* Revision of the plc */
+#endif /* nMOT_ELM */
+
+       plc = &phy->plc ;
+       mib = phy->mib ;
+
+       /*
+        * general transitions independent of state
+        */
+       switch (cmd) {
+       case PC_STOP :
+               /*PC00-PC80*/
+               if (mib->fddiPORTPCMState != PC9_MAINT) {
+                       GO_STATE(PC0_OFF) ;
+                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                               FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP,
+                               smt_get_port_event_word(smc));
+               }
+               return ;
+       case PC_START :
+               /*PC01-PC81*/
+               if (mib->fddiPORTPCMState != PC9_MAINT)
+                       GO_STATE(PC1_BREAK) ;
+               return ;
+       case PC_DISABLE :
+               /* PC09-PC99 */
+               GO_STATE(PC9_MAINT) ;
+               AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                       FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED,
+                       smt_get_port_event_word(smc));
+               return ;
+       case PC_TIMEOUT_LCT :
+               /* if long or extended LCT */
+               stop_pcm_timer0(smc,phy) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+               /* end of LCT is indicate by PCM_CODE (initiate PCM event) */
+               return ;
+       }
+
+       switch(mib->fddiPORTPCMState) {
+       case ACTIONS(PC0_OFF) :
+               stop_pcm_timer0(smc,phy) ;
+               outpw(PLC(np,PL_CNTRL_A),0) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+               sm_ph_lem_stop(smc,np) ;                /* disable LEM */
+               phy->cf_loop = FALSE ;
+               phy->cf_join = FALSE ;
+               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+               plc_go_state(smc,np,PL_PCM_STOP) ;
+               mib->fddiPORTConnectState = PCM_DISABLED ;
+               ACTIONS_DONE() ;
+               break ;
+       case PC0_OFF:
+               /*PC09*/
+               if (cmd == PC_MAINT) {
+                       GO_STATE(PC9_MAINT) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(PC1_BREAK) :
+               /* Stop the LCT timer if we came from Signal state */
+               stop_pcm_timer0(smc,phy) ;
+               ACTIONS_DONE() ;
+               plc_go_state(smc,np,0) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+               sm_ph_lem_stop(smc,np) ;                /* disable LEM */
+               /*
+                * if vector is already loaded, go to OFF to clear PCM_SIGNAL
+                */
+#if    0
+               if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
+                       plc_go_state(smc,np,PL_PCM_STOP) ;
+                       /* TB_MIN ? */
+               }
+#endif
+               /*
+                * Go to OFF state in any case.
+                */
+               plc_go_state(smc,np,PL_PCM_STOP) ;
+
+               if (mib->fddiPORTPC_Withhold == PC_WH_NONE)
+                       mib->fddiPORTConnectState = PCM_CONNECTING ;
+               phy->cf_loop = FALSE ;
+               phy->cf_join = FALSE ;
+               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+               phy->ls_flag = FALSE ;
+               phy->pc_mode = PM_NONE ;        /* needed by CFM */
+               phy->bitn = 0 ;                 /* bit signaling start bit */
+               for (i = 0 ; i < 3 ; i++)
+                       pc_tcode_actions(smc,i,phy) ;
+
+               /* Set the non-active interrupt mask register */
+               outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ;
+
+               /*
+                * If the LCT was stopped. There might be a
+                * PCM_CODE interrupt event present.
+                * This must be cleared.
+                */
+               (void)inpw(PLC(np,PL_INTR_EVENT)) ;
+#ifndef        MOT_ELM
+               /* Get the plc revision for revision dependent code */
+               plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ;
+
+               if (plc_rev != PLC_REV_SN3)
+#endif /* MOT_ELM */
+               {
+                       /*
+                        * No supernet III PLC, so set Xmit verctor and
+                        * length BEFORE starting the state machine.
+                        */
+                       if (plc_send_bits(smc,phy,3)) {
+                               return ;
+                       }
+               }
+
+               /*
+                * Now give the Start command.
+                * - The start command shall be done before setting the bits
+                *   to be signaled. (In PLC-S description and PLCS in SN3.
+                * - The start command shall be issued AFTER setting the
+                *   XMIT vector and the XMIT length register.
+                *
+                * We do it exactly according this specs for the old PLC and
+                * the new PLCS inside the SN3.
+                * For the usual PLCS we try it the way it is done for the
+                * old PLC and set the XMIT registers again, if the PLC is
+                * not in SIGNAL state. This is done according to an PLCS
+                * errata workaround.
+                */
+
+               plc_go_state(smc,np,PL_PCM_START) ;
+
+               /*
+                * workaround for PLC-S eng. sample errata
+                */
+#ifdef MOT_ELM
+               if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
+#else  /* nMOT_ELM */
+               if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) !=
+                       PLC_REVISION_A) &&
+                       !(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
+#endif /* nMOT_ELM */
+               {
+                       /*
+                        * Set register again (PLCS errata) or the first time
+                        * (new SN3 PLCS).
+                        */
+                       (void) plc_send_bits(smc,phy,3) ;
+               }
+               /*
+                * end of workaround
+                */
+
+               GO_STATE(PC5_SIGNAL) ;
+               plc->p_state = PS_BIT3 ;
+               plc->p_bits = 3 ;
+               plc->p_start = 0 ;
+
+               break ;
+       case PC1_BREAK :
+               break ;
+       case ACTIONS(PC2_TRACE) :
+               plc_go_state(smc,np,PL_PCM_TRACE) ;
+               ACTIONS_DONE() ;
+               break ;
+       case PC2_TRACE :
+               break ;
+
+       case PC3_CONNECT :      /* these states are done by hardware */
+       case PC4_NEXT :
+               break ;
+
+       case ACTIONS(PC5_SIGNAL) :
+               ACTIONS_DONE() ;
+       case PC5_SIGNAL :
+               if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))
+                       break ;
+               switch (plc->p_state) {
+               case PS_BIT3 :
+                       for (i = 0 ; i <= 2 ; i++)
+                               pc_rcode_actions(smc,i,phy) ;
+                       pc_tcode_actions(smc,3,phy) ;
+                       plc->p_state = PS_BIT4 ;
+                       plc->p_bits = 1 ;
+                       plc->p_start = 3 ;
+                       phy->bitn = 3 ;
+                       if (plc_send_bits(smc,phy,1)) {
+                               return ;
+                       }
+                       break ;
+               case PS_BIT4 :
+                       pc_rcode_actions(smc,3,phy) ;
+                       for (i = 4 ; i <= 6 ; i++)
+                               pc_tcode_actions(smc,i,phy) ;
+                       plc->p_state = PS_BIT7 ;
+                       plc->p_bits = 3 ;
+                       plc->p_start = 4 ;
+                       phy->bitn = 4 ;
+                       if (plc_send_bits(smc,phy,3)) {
+                               return ;
+                       }
+                       break ;
+               case PS_BIT7 :
+                       for (i = 3 ; i <= 6 ; i++)
+                               pc_rcode_actions(smc,i,phy) ;
+                       plc->p_state = PS_LCT ;
+                       plc->p_bits = 0 ;
+                       plc->p_start = 7 ;
+                       phy->bitn = 7 ;
+               sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ; /* enable LEM */
+                       /* start LCT */
+                       i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ;
+                       outpw(PLC(np,PL_CNTRL_B),i) ;   /* must be cleared */
+                       outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ;
+                       break ;
+               case PS_LCT :
+                       /* check for local LCT failure */
+                       pc_tcode_actions(smc,7,phy) ;
+                       /*
+                        * set tval[7]
+                        */
+                       plc->p_state = PS_BIT8 ;
+                       plc->p_bits = 1 ;
+                       plc->p_start = 7 ;
+                       phy->bitn = 7 ;
+                       if (plc_send_bits(smc,phy,1)) {
+                               return ;
+                       }
+                       break ;
+               case PS_BIT8 :
+                       /* check for remote LCT failure */
+                       pc_rcode_actions(smc,7,phy) ;
+                       if (phy->t_val[7] || phy->r_val[7]) {
+                               plc_go_state(smc,np,PL_PCM_STOP) ;
+                               GO_STATE(PC1_BREAK) ;
+                               break ;
+                       }
+                       for (i = 8 ; i <= 9 ; i++)
+                               pc_tcode_actions(smc,i,phy) ;
+                       plc->p_state = PS_JOIN ;
+                       plc->p_bits = 2 ;
+                       plc->p_start = 8 ;
+                       phy->bitn = 8 ;
+                       if (plc_send_bits(smc,phy,2)) {
+                               return ;
+                       }
+                       break ;
+               case PS_JOIN :
+                       for (i = 8 ; i <= 9 ; i++)
+                               pc_rcode_actions(smc,i,phy) ;
+                       plc->p_state = PS_ACTIVE ;
+                       GO_STATE(PC6_JOIN) ;
+                       break ;
+               }
+               break ;
+
+       case ACTIONS(PC6_JOIN) :
+               /*
+                * prevent mux error when going from WRAP_A to WRAP_B
+                */
+               if (smc->s.sas == SMT_DAS && np == PB &&
+                       (smc->y[PA].pc_mode == PM_TREE ||
+                        smc->y[PB].pc_mode == PM_TREE)) {
+                       SETMASK(PLC(np,PL_CNTRL_A),
+                               PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
+                       SETMASK(PLC(np,PL_CNTRL_B),
+                               PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
+               }
+               SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
+               SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
+               ACTIONS_DONE() ;
+               cmd = 0 ;
+               /* fall thru */
+       case PC6_JOIN :
+               switch (plc->p_state) {
+               case PS_ACTIVE:
+                       /*PC88b*/
+                       if (!phy->cf_join) {
+                               phy->cf_join = TRUE ;
+                               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+                       }
+                       if (cmd == PC_JOIN)
+                               GO_STATE(PC8_ACTIVE) ;
+                       /*PC82*/
+                       if (cmd == PC_TRACE) {
+                               GO_STATE(PC2_TRACE) ;
+                               break ;
+                       }
+                       break ;
+               }
+               break ;
+
+       case PC7_VERIFY :
+               break ;
+
+       case ACTIONS(PC8_ACTIVE) :
+               /*
+                * start LEM for SMT
+                */
+               sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ;
+
+               phy->tr_flag = FALSE ;
+               mib->fddiPORTConnectState = PCM_ACTIVE ;
+
+               /* Set the active interrupt mask register */
+               outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ;
+
+               ACTIONS_DONE() ;
+               break ;
+       case PC8_ACTIVE :
+               /*PC81 is done by PL_TNE_EXPIRED irq */
+               /*PC82*/
+               if (cmd == PC_TRACE) {
+                       GO_STATE(PC2_TRACE) ;
+                       break ;
+               }
+               /*PC88c: is done by TRACE_PROP irq */
+
+               break ;
+       case ACTIONS(PC9_MAINT) :
+               stop_pcm_timer0(smc,phy) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
+               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
+               CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ; /* disable LEM int. */
+               sm_ph_lem_stop(smc,np) ;                /* disable LEM */
+               phy->cf_loop = FALSE ;
+               phy->cf_join = FALSE ;
+               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
+               plc_go_state(smc,np,PL_PCM_STOP) ;
+               mib->fddiPORTConnectState = PCM_DISABLED ;
+               SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ;
+               sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ;
+               outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ;
+               ACTIONS_DONE() ;
+               break ;
+       case PC9_MAINT :
+               DB_PCMN(1,"PCM %c : MAINT\n",phy->phy_name,0) ;
+               /*PC90*/
+               if (cmd == PC_ENABLE) {
+                       GO_STATE(PC0_OFF) ;
+                       break ;
+               }
+               break ;
+
+       default:
+               SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ;
+               break ;
+       }
+}
+
+/*
+ * force line state on a PHY output    (only in MAINT state)
+ */
+static void sm_ph_linestate(struct s_smc *smc, int phy, int ls)
+{
+       int     cntrl ;
+
+       SK_UNUSED(smc) ;
+
+       cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) |
+                                               PL_PCM_STOP | PL_MAINT ;
+       switch(ls) {
+       case PC_QLS:            /* Force Quiet */
+               cntrl |= PL_M_QUI0 ;
+               break ;
+       case PC_MLS:            /* Force Master */
+               cntrl |= PL_M_MASTR ;
+               break ;
+       case PC_HLS:            /* Force Halt */
+               cntrl |= PL_M_HALT ;
+               break ;
+       default :
+       case PC_ILS:            /* Force Idle */
+               cntrl |= PL_M_IDLE ;
+               break ;
+       case PC_LS_PDR:         /* Enable repeat filter */
+               cntrl |= PL_M_TPDR ;
+               break ;
+       }
+       outpw(PLC(phy,PL_CNTRL_B),cntrl) ;
+}
+
+static void reset_lem_struct(struct s_phy *phy)
+{
+       struct lem_counter *lem = &phy->lem ;
+
+       phy->mib->fddiPORTLer_Estimate = 15 ;
+       lem->lem_float_ber = 15 * 100 ;
+}
+
+/*
+ * link error monitor
+ */
+static void lem_evaluate(struct s_smc *smc, struct s_phy *phy)
+{
+       int ber ;
+       u_long errors ;
+       struct lem_counter *lem = &phy->lem ;
+       struct fddi_mib_p       *mib ;
+       int                     cond ;
+
+       mib = phy->mib ;
+
+       if (!lem->lem_on)
+               return ;
+
+       errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ;
+       lem->lem_errors += errors ;
+       mib->fddiPORTLem_Ct += errors ;
+
+       errors = lem->lem_errors ;
+       /*
+        * calculation is called on a intervall of 8 seconds
+        *      -> this means, that one error in 8 sec. is one of 8*125*10E6
+        *      the same as BER = 10E-9
+        * Please note:
+        *      -> 9 errors in 8 seconds mean:
+        *         BER = 9 * 10E-9  and this is
+        *          < 10E-8, so the limit of 10E-8 is not reached!
+        */
+
+               if (!errors)            ber = 15 ;
+       else    if (errors <= 9)        ber = 9 ;
+       else    if (errors <= 99)       ber = 8 ;
+       else    if (errors <= 999)      ber = 7 ;
+       else    if (errors <= 9999)     ber = 6 ;
+       else    if (errors <= 99999)    ber = 5 ;
+       else    if (errors <= 999999)   ber = 4 ;
+       else    if (errors <= 9999999)  ber = 3 ;
+       else    if (errors <= 99999999) ber = 2 ;
+       else    if (errors <= 999999999) ber = 1 ;
+       else                            ber = 0 ;
+
+       /*
+        * weighted average
+        */
+       ber *= 100 ;
+       lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ;
+       lem->lem_float_ber /= 10 ;
+       mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ;
+       if (mib->fddiPORTLer_Estimate < 4) {
+               mib->fddiPORTLer_Estimate = 4 ;
+       }
+
+       if (lem->lem_errors) {
+               DB_PCMN(1,"LEM %c :\n",phy->np == PB? 'B' : 'A',0) ;
+               DB_PCMN(1,"errors      : %ld\n",lem->lem_errors,0) ;
+               DB_PCMN(1,"sum_errors  : %ld\n",mib->fddiPORTLem_Ct,0) ;
+               DB_PCMN(1,"current BER : 10E-%d\n",ber/100,0) ;
+               DB_PCMN(1,"float BER   : 10E-(%d/100)\n",lem->lem_float_ber,0) ;
+               DB_PCMN(1,"avg. BER    : 10E-%d\n",
+                       mib->fddiPORTLer_Estimate,0) ;
+       }
+
+       lem->lem_errors = 0L ;
+
+#ifndef        SLIM_SMT
+       cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
+               TRUE : FALSE ;
+#ifdef SMT_EXT_CUTOFF
+       smt_ler_alarm_check(smc,phy,cond) ;
+#endif /* nSMT_EXT_CUTOFF */
+       if (cond != mib->fddiPORTLerFlag) {
+               smt_srf_event(smc,SMT_COND_PORT_LER,
+                       (int) (INDEX_PORT+ phy->np) ,cond) ;
+       }
+#endif
+
+       if (    mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
+               phy->pc_lem_fail = TRUE ;               /* flag */
+               mib->fddiPORTLem_Reject_Ct++ ;
+               /*
+                * "forgive 10e-2" if we cutoff so we can come
+                * up again ..
+                */
+               lem->lem_float_ber += 2*100 ;
+
+               /*PC81b*/
+#ifdef CONCENTRATOR
+               DB_PCMN(1,"PCM: LER cutoff on port %d cutoff %d\n",
+                       phy->np, mib->fddiPORTLer_Cutoff) ;
+#endif
+#ifdef SMT_EXT_CUTOFF
+               smt_port_off_event(smc,phy->np);
+#else  /* nSMT_EXT_CUTOFF */
+               queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
+#endif /* nSMT_EXT_CUTOFF */
+       }
+}
+
+/*
+ * called by SMT to calculate LEM bit error rate
+ */
+void sm_lem_evaluate(struct s_smc *smc)
+{
+       int np ;
+
+       for (np = 0 ; np < NUMPHYS ; np++)
+               lem_evaluate(smc,&smc->y[np]) ;
+}
+
+static void lem_check_lct(struct s_smc *smc, struct s_phy *phy)
+{
+       struct lem_counter      *lem = &phy->lem ;
+       struct fddi_mib_p       *mib ;
+       int errors ;
+
+       mib = phy->mib ;
+
+       phy->pc_lem_fail = FALSE ;              /* flag */
+       errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ;
+       lem->lem_errors += errors ;
+       mib->fddiPORTLem_Ct += errors ;
+       if (lem->lem_errors) {
+               switch(phy->lc_test) {
+               case LC_SHORT:
+                       if (lem->lem_errors >= smc->s.lct_short)
+                               phy->pc_lem_fail = TRUE ;
+                       break ;
+               case LC_MEDIUM:
+                       if (lem->lem_errors >= smc->s.lct_medium)
+                               phy->pc_lem_fail = TRUE ;
+                       break ;
+               case LC_LONG:
+                       if (lem->lem_errors >= smc->s.lct_long)
+                               phy->pc_lem_fail = TRUE ;
+                       break ;
+               case LC_EXTENDED:
+                       if (lem->lem_errors >= smc->s.lct_extended)
+                               phy->pc_lem_fail = TRUE ;
+                       break ;
+               }
+               DB_PCMN(1," >>errors : %d\n",lem->lem_errors,0) ;
+       }
+       if (phy->pc_lem_fail) {
+               mib->fddiPORTLCTFail_Ct++ ;
+               mib->fddiPORTLem_Reject_Ct++ ;
+       }
+       else
+               mib->fddiPORTLCTFail_Ct = 0 ;
+}
+
+/*
+ * LEM functions
+ */
+static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold)
+{
+       struct lem_counter *lem = &smc->y[np].lem ;
+
+       lem->lem_on = 1 ;
+       lem->lem_errors = 0L ;
+
+       /* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too
+        * often.
+        */
+
+       outpw(PLC(np,PL_LE_THRESHOLD),threshold) ;
+       (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ;   /* clear error counter */
+
+       /* enable LE INT */
+       SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
+}
+
+static void sm_ph_lem_stop(struct s_smc *smc, int np)
+{
+       struct lem_counter *lem = &smc->y[np].lem ;
+
+       lem->lem_on = 0 ;
+       CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;
+}
+
+/* ARGSUSED */
+void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off)
+/* int on_off; en- or disable ident. ls */
+{
+       SK_UNUSED(smc) ;
+
+       phy = phy ; on_off = on_off ;
+}
+
+
+/*
+ * PCM pseudo code
+ * receive actions are called AFTER the bit n is received,
+ * i.e. if pc_rcode_actions(5) is called, bit 6 is the next bit to be received
+ */
+
+/*
+ * PCM pseudo code 5.1 .. 6.1
+ */
+static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy)
+{
+       struct fddi_mib_p       *mib ;
+
+       mib = phy->mib ;
+
+       DB_PCMN(1,"SIG rec %x %x:\n", bit,phy->r_val[bit] ) ;
+       bit++ ;
+
+       switch(bit) {
+       case 0:
+       case 1:
+       case 2:
+               break ;
+       case 3 :
+               if (phy->r_val[1] == 0 && phy->r_val[2] == 0)
+                       mib->fddiPORTNeighborType = TA ;
+               else if (phy->r_val[1] == 0 && phy->r_val[2] == 1)
+                       mib->fddiPORTNeighborType = TB ;
+               else if (phy->r_val[1] == 1 && phy->r_val[2] == 0)
+                       mib->fddiPORTNeighborType = TS ;
+               else if (phy->r_val[1] == 1 && phy->r_val[2] == 1)
+                       mib->fddiPORTNeighborType = TM ;
+               break ;
+       case 4:
+               if (mib->fddiPORTMy_Type == TM &&
+                       mib->fddiPORTNeighborType == TM) {
+                       DB_PCMN(1,"PCM %c : E100 withhold M-M\n",
+                               phy->phy_name,0) ;
+                       mib->fddiPORTPC_Withhold = PC_WH_M_M ;
+                       RS_SET(smc,RS_EVENT) ;
+               }
+               else if (phy->t_val[3] || phy->r_val[3]) {
+                       mib->fddiPORTPC_Withhold = PC_WH_NONE ;
+                       if (mib->fddiPORTMy_Type == TM ||
+                           mib->fddiPORTNeighborType == TM)
+                               phy->pc_mode = PM_TREE ;
+                       else
+                               phy->pc_mode = PM_PEER ;
+
+                       /* reevaluate the selection criteria (wc_flag) */
+                       all_selection_criteria (smc);
+
+                       if (phy->wc_flag) {
+                               mib->fddiPORTPC_Withhold = PC_WH_PATH ;
+                       }
+               }
+               else {
+                       mib->fddiPORTPC_Withhold = PC_WH_OTHER ;
+                       RS_SET(smc,RS_EVENT) ;
+                       DB_PCMN(1,"PCM %c : E101 withhold other\n",
+                               phy->phy_name,0) ;
+               }
+               phy->twisted = ((mib->fddiPORTMy_Type != TS) &&
+                               (mib->fddiPORTMy_Type != TM) &&
+                               (mib->fddiPORTNeighborType ==
+                               mib->fddiPORTMy_Type)) ;
+               if (phy->twisted) {
+                       DB_PCMN(1,"PCM %c : E102 !!! TWISTED !!!\n",
+                               phy->phy_name,0) ;
+               }
+               break ;
+       case 5 :
+               break ;
+       case 6:
+               if (phy->t_val[4] || phy->r_val[4]) {
+                       if ((phy->t_val[4] && phy->t_val[5]) ||
+                           (phy->r_val[4] && phy->r_val[5]) )
+                               phy->lc_test = LC_EXTENDED ;
+                       else
+                               phy->lc_test = LC_LONG ;
+               }
+               else if (phy->t_val[5] || phy->r_val[5])
+                       phy->lc_test = LC_MEDIUM ;
+               else
+                       phy->lc_test = LC_SHORT ;
+               switch (phy->lc_test) {
+               case LC_SHORT :                         /* 50ms */
+                       outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ;
+                       phy->t_next[7] = smc->s.pcm_lc_short ;
+                       break ;
+               case LC_MEDIUM :                        /* 500ms */
+                       outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ;
+                       phy->t_next[7] = smc->s.pcm_lc_medium ;
+                       break ;
+               case LC_LONG :
+                       SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
+                       phy->t_next[7] = smc->s.pcm_lc_long ;
+                       break ;
+               case LC_EXTENDED :
+                       SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
+                       phy->t_next[7] = smc->s.pcm_lc_extended ;
+                       break ;
+               }
+               if (phy->t_next[7] > smc->s.pcm_lc_medium) {
+                       start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy);
+               }
+               DB_PCMN(1,"LCT timer = %ld us\n", phy->t_next[7], 0) ;
+               phy->t_next[9] = smc->s.pcm_t_next_9 ;
+               break ;
+       case 7:
+               if (phy->t_val[6]) {
+                       phy->cf_loop = TRUE ;
+               }
+               phy->td_flag = TRUE ;
+               break ;
+       case 8:
+               if (phy->t_val[7] || phy->r_val[7]) {
+                       DB_PCMN(1,"PCM %c : E103 LCT fail %s\n",
+                               phy->phy_name,phy->t_val[7]? "local":"remote") ;
+                       queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
+               }
+               break ;
+       case 9:
+               if (phy->t_val[8] || phy->r_val[8]) {
+                       if (phy->t_val[8])
+                               phy->cf_loop = TRUE ;
+                       phy->td_flag = TRUE ;
+               }
+               break ;
+       case 10:
+               if (phy->r_val[9]) {
+                       /* neighbor intends to have MAC on output */ ;
+                       mib->fddiPORTMacIndicated.R_val = TRUE ;
+               }
+               else {
+                       /* neighbor does not intend to have MAC on output */ ;
+                       mib->fddiPORTMacIndicated.R_val = FALSE ;
+               }
+               break ;
+       }
+}
+
+/*
+ * PCM pseudo code 5.1 .. 6.1
+ */
+static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy)
+{
+       int     np = phy->np ;
+       struct fddi_mib_p       *mib ;
+
+       mib = phy->mib ;
+
+       switch(bit) {
+       case 0:
+               phy->t_val[0] = 0 ;             /* no escape used */
+               break ;
+       case 1:
+               if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM)
+                       phy->t_val[1] = 1 ;
+               else
+                       phy->t_val[1] = 0 ;
+               break ;
+       case 2 :
+               if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM)
+                       phy->t_val[2] = 1 ;
+               else
+                       phy->t_val[2] = 0 ;
+               break ;
+       case 3:
+               {
+               int     type,ne ;
+               int     policy ;
+
+               type = mib->fddiPORTMy_Type ;
+               ne = mib->fddiPORTNeighborType ;
+               policy = smc->mib.fddiSMTConnectionPolicy ;
+
+               phy->t_val[3] = 1 ;     /* Accept connection */
+               switch (type) {
+               case TA :
+                       if (
+                               ((policy & POLICY_AA) && ne == TA) ||
+                               ((policy & POLICY_AB) && ne == TB) ||
+                               ((policy & POLICY_AS) && ne == TS) ||
+                               ((policy & POLICY_AM) && ne == TM) )
+                               phy->t_val[3] = 0 ;     /* Reject */
+                       break ;
+               case TB :
+                       if (
+                               ((policy & POLICY_BA) && ne == TA) ||
+                               ((policy & POLICY_BB) && ne == TB) ||
+                               ((policy & POLICY_BS) && ne == TS) ||
+                               ((policy & POLICY_BM) && ne == TM) )
+                               phy->t_val[3] = 0 ;     /* Reject */
+                       break ;
+               case TS :
+                       if (
+                               ((policy & POLICY_SA) && ne == TA) ||
+                               ((policy & POLICY_SB) && ne == TB) ||
+                               ((policy & POLICY_SS) && ne == TS) ||
+                               ((policy & POLICY_SM) && ne == TM) )
+                               phy->t_val[3] = 0 ;     /* Reject */
+                       break ;
+               case TM :
+                       if (    ne == TM ||
+                               ((policy & POLICY_MA) && ne == TA) ||
+                               ((policy & POLICY_MB) && ne == TB) ||
+                               ((policy & POLICY_MS) && ne == TS) ||
+                               ((policy & POLICY_MM) && ne == TM) )
+                               phy->t_val[3] = 0 ;     /* Reject */
+                       break ;
+               }
+#ifndef        SLIM_SMT
+               /*
+                * detect undesirable connection attempt event
+                */
+               if (    (type == TA && ne == TA ) ||
+                       (type == TA && ne == TS ) ||
+                       (type == TB && ne == TB ) ||
+                       (type == TB && ne == TS ) ||
+                       (type == TS && ne == TA ) ||
+                       (type == TS && ne == TB ) ) {
+                       smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION,
+                               (int) (INDEX_PORT+ phy->np) ,0) ;
+               }
+#endif
+               }
+               break ;
+       case 4:
+               if (mib->fddiPORTPC_Withhold == PC_WH_NONE) {
+                       if (phy->pc_lem_fail) {
+                               phy->t_val[4] = 1 ;     /* long */
+                               phy->t_val[5] = 0 ;
+                       }
+                       else {
+                               phy->t_val[4] = 0 ;
+                               if (mib->fddiPORTLCTFail_Ct > 0)
+                                       phy->t_val[5] = 1 ;     /* medium */
+                               else
+                                       phy->t_val[5] = 0 ;     /* short */
+
+                               /*
+                                * Implementers choice: use medium
+                                * instead of short when undesired
+                                * connection attempt is made.
+                                */
+                               if (phy->wc_flag)
+                                       phy->t_val[5] = 1 ;     /* medium */
+                       }
+                       mib->fddiPORTConnectState = PCM_CONNECTING ;
+               }
+               else {
+                       mib->fddiPORTConnectState = PCM_STANDBY ;
+                       phy->t_val[4] = 1 ;     /* extended */
+                       phy->t_val[5] = 1 ;
+               }
+               break ;
+       case 5:
+               break ;
+       case 6:
+               /* we do NOT have a MAC for LCT */
+               phy->t_val[6] = 0 ;
+               break ;
+       case 7:
+               phy->cf_loop = FALSE ;
+               lem_check_lct(smc,phy) ;
+               if (phy->pc_lem_fail) {
+                       DB_PCMN(1,"PCM %c : E104 LCT failed\n",
+                               phy->phy_name,0) ;
+                       phy->t_val[7] = 1 ;
+               }
+               else
+                       phy->t_val[7] = 0 ;
+               break ;
+       case 8:
+               phy->t_val[8] = 0 ;     /* Don't request MAC loopback */
+               break ;
+       case 9:
+               phy->cf_loop = 0 ;
+               if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) ||
+                    ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) {
+                       queue_event(smc,EVENT_PCM+np,PC_START) ;
+                       break ;
+               }
+               phy->t_val[9] = FALSE ;
+               switch (smc->s.sas) {
+               case SMT_DAS :
+                       /*
+                        * MAC intended on output
+                        */
+                       if (phy->pc_mode == PM_TREE) {
+                               if ((np == PB) || ((np == PA) &&
+                               (smc->y[PB].mib->fddiPORTConnectState !=
+                                       PCM_ACTIVE)))
+                                       phy->t_val[9] = TRUE ;
+                       }
+                       else {
+                               if (np == PB)
+                                       phy->t_val[9] = TRUE ;
+                       }
+                       break ;
+               case SMT_SAS :
+                       if (np == PS)
+                               phy->t_val[9] = TRUE ;
+                       break ;
+#ifdef CONCENTRATOR
+               case SMT_NAC :
+                       /*
+                        * MAC intended on output
+                        */
+                       if (np == PB)
+                               phy->t_val[9] = TRUE ;
+                       break ;
+#endif
+               }
+               mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ;
+               break ;
+       }
+       DB_PCMN(1,"SIG snd %x %x:\n", bit,phy->t_val[bit] ) ;
+}
+
+/*
+ * return status twisted (called by SMT)
+ */
+int pcm_status_twisted(struct s_smc *smc)
+{
+       int     twist = 0 ;
+       if (smc->s.sas != SMT_DAS)
+               return 0;
+       if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
+               twist |= 1 ;
+       if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
+               twist |= 2 ;
+       return twist;
+}
+
+/*
+ * return status       (called by SMT)
+ *     type
+ *     state
+ *     remote phy type
+ *     remote mac yes/no
+ */
+void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
+                     int *remote, int *mac)
+{
+       struct s_phy    *phy = &smc->y[np] ;
+       struct fddi_mib_p       *mib ;
+
+       mib = phy->mib ;
+
+       /* remote PHY type and MAC - set only if active */
+       *mac = 0 ;
+       *type = mib->fddiPORTMy_Type ;          /* our PHY type */
+       *state = mib->fddiPORTConnectState ;
+       *remote = mib->fddiPORTNeighborType ;
+
+       switch(mib->fddiPORTPCMState) {
+       case PC8_ACTIVE :
+               *mac = mib->fddiPORTMacIndicated.R_val ;
+               break ;
+       }
+}
+
+/*
+ * return rooted station status (called by SMT)
+ */
+int pcm_rooted_station(struct s_smc *smc)
+{
+       int     n ;
+
+       for (n = 0 ; n < NUMPHYS ; n++) {
+               if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
+                   smc->y[n].mib->fddiPORTNeighborType == TM)
+                       return 0;
+       }
+       return 1;
+}
+
+/*
+ * Interrupt actions for PLC & PCM events
+ */
+void plc_irq(struct s_smc *smc, int np, unsigned int cmd)
+/* int np;     PHY index */
+{
+       struct s_phy *phy = &smc->y[np] ;
+       struct s_plc *plc = &phy->plc ;
+       int             n ;
+#ifdef SUPERNET_3
+       int             corr_mask ;
+#endif /* SUPERNET_3 */
+       int             i ;
+
+       if (np >= smc->s.numphys) {
+               plc->soft_err++ ;
+               return ;
+       }
+       if (cmd & PL_EBUF_ERR) {        /* elastic buff. det. over-|underflow*/
+               /*
+                * Check whether the SRF Condition occurred.
+                */
+               if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){
+                       /*
+                        * This is the real Elasticity Error.
+                        * More than one in a row are treated as a
+                        * single one.
+                        * Only count this in the active state.
+                        */
+                       phy->mib->fddiPORTEBError_Ct ++ ;
+
+               }
+
+               plc->ebuf_err++ ;
+               if (plc->ebuf_cont <= 1000) {
+                       /*
+                        * Prevent counter from being wrapped after
+                        * hanging years in that interrupt.
+                        */
+                       plc->ebuf_cont++ ;      /* Ebuf continuous error */
+               }
+
+#ifdef SUPERNET_3
+               if (plc->ebuf_cont == 1000 &&
+                       ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) ==
+                       PLC_REV_SN3)) {
+                       /*
+                        * This interrupt remeained high for at least
+                        * 1000 consecutive interrupt calls.
+                        *
+                        * This is caused by a hardware error of the
+                        * ORION part of the Supernet III chipset.
+                        *
+                        * Disable this bit from the mask.
+                        */
+                       corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ;
+                       outpw(PLC(np,PL_INTR_MASK),corr_mask);
+
+                       /*
+                        * Disconnect from the ring.
+                        * Call the driver with the reset indication.
+                        */
+                       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+
+                       /*
+                        * Make an error log entry.
+                        */
+                       SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ;
+
+                       /*
+                        * Indicate the Reset.
+                        */
+                       drv_reset_indication(smc) ;
+               }
+#endif /* SUPERNET_3 */
+       } else {
+               /* Reset the continuous error variable */
+               plc->ebuf_cont = 0 ;    /* reset Ebuf continuous error */
+       }
+       if (cmd & PL_PHYINV) {          /* physical layer invalid signal */
+               plc->phyinv++ ;
+       }
+       if (cmd & PL_VSYM_CTR) {        /* violation symbol counter has incr.*/
+               plc->vsym_ctr++ ;
+       }
+       if (cmd & PL_MINI_CTR) {        /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
+               plc->mini_ctr++ ;
+       }
+       if (cmd & PL_LE_CTR) {          /* link error event counter */
+               int     j ;
+
+               /*
+                * note: PL_LINK_ERR_CTR MUST be read to clear it
+                */
+               j = inpw(PLC(np,PL_LE_THRESHOLD)) ;
+               i = inpw(PLC(np,PL_LINK_ERR_CTR)) ;
+
+               if (i < j) {
+                       /* wrapped around */
+                       i += 256 ;
+               }
+
+               if (phy->lem.lem_on) {
+                       /* Note: Lem errors shall only be counted when
+                        * link is ACTIVE or LCT is active.
+                        */
+                       phy->lem.lem_errors += i ;
+                       phy->mib->fddiPORTLem_Ct += i ;
+               }
+       }
+       if (cmd & PL_TPC_EXPIRED) {     /* TPC timer reached zero */
+               if (plc->p_state == PS_LCT) {
+                       /*
+                        * end of LCT
+                        */
+                       ;
+               }
+               plc->tpc_exp++ ;
+       }
+       if (cmd & PL_LS_MATCH) {        /* LS == LS in PLC_CNTRL_B's MATCH_LS*/
+               switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) {
+               case PL_I_IDLE :        phy->curr_ls = PC_ILS ;         break ;
+               case PL_I_HALT :        phy->curr_ls = PC_HLS ;         break ;
+               case PL_I_MASTR :       phy->curr_ls = PC_MLS ;         break ;
+               case PL_I_QUIET :       phy->curr_ls = PC_QLS ;         break ;
+               }
+       }
+       if (cmd & PL_PCM_BREAK) {       /* PCM has entered the BREAK state */
+               int     reason;
+
+               reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ;
+
+               switch (reason) {
+               case PL_B_PCS :         plc->b_pcs++ ;  break ;
+               case PL_B_TPC :         plc->b_tpc++ ;  break ;
+               case PL_B_TNE :         plc->b_tne++ ;  break ;
+               case PL_B_QLS :         plc->b_qls++ ;  break ;
+               case PL_B_ILS :         plc->b_ils++ ;  break ;
+               case PL_B_HLS :         plc->b_hls++ ;  break ;
+               }
+
+               /*jd 05-Aug-1999 changed: Bug #10419 */
+               DB_PCMN(1,"PLC %d: MDcF = %x\n", np, smc->e.DisconnectFlag);
+               if (smc->e.DisconnectFlag == FALSE) {
+                       DB_PCMN(1,"PLC %d: restart (reason %x)\n", np, reason);
+                       queue_event(smc,EVENT_PCM+np,PC_START) ;
+               }
+               else {
+                       DB_PCMN(1,"PLC %d: NO!! restart (reason %x)\n", np, reason);
+               }
+               return ;
+       }
+       /*
+        * If both CODE & ENABLE are set ignore enable
+        */
+       if (cmd & PL_PCM_CODE) { /* receive last sign.-bit | LCT complete */
+               queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ;
+               n = inpw(PLC(np,PL_RCV_VECTOR)) ;
+               for (i = 0 ; i < plc->p_bits ; i++) {
+                       phy->r_val[plc->p_start+i] = n & 1 ;
+                       n >>= 1 ;
+               }
+       }
+       else if (cmd & PL_PCM_ENABLED) { /* asserted SC_JOIN, scrub.completed*/
+               queue_event(smc,EVENT_PCM+np,PC_JOIN) ;
+       }
+       if (cmd & PL_TRACE_PROP) {      /* MLS while PC8_ACTIV || PC2_TRACE */
+               /*PC22b*/
+               if (!phy->tr_flag) {
+                       DB_PCMN(1,"PCM : irq TRACE_PROP %d %d\n",
+                               np,smc->mib.fddiSMTECMState) ;
+                       phy->tr_flag = TRUE ;
+                       smc->e.trace_prop |= ENTITY_BIT(ENTITY_PHY(np)) ;
+                       queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
+               }
+       }
+       /*
+        * filter PLC glitch ???
+        * QLS || HLS only while in PC2_TRACE state
+        */
+       if ((cmd & PL_SELF_TEST) && (phy->mib->fddiPORTPCMState == PC2_TRACE)) {
+               /*PC22a*/
+               if (smc->e.path_test == PT_PASSED) {
+                       DB_PCMN(1,"PCM : state = %s %d\n", get_pcmstate(smc,np),
+                               phy->mib->fddiPORTPCMState) ;
+
+                       smc->e.path_test = PT_PENDING ;
+                       queue_event(smc,EVENT_ECM,EC_PATH_TEST) ;
+               }
+       }
+       if (cmd & PL_TNE_EXPIRED) {     /* TNE: length of noise events */
+               /* break_required (TNE > NS_Max) */
+               if (phy->mib->fddiPORTPCMState == PC8_ACTIVE) {
+                       if (!phy->tr_flag) {
+                          DB_PCMN(1,"PCM %c : PC81 %s\n",phy->phy_name,"NSE");
+                          queue_event(smc,EVENT_PCM+np,PC_START) ;
+                          return ;
+                       }
+               }
+       }
+#if    0
+       if (cmd & PL_NP_ERR) {          /* NP has requested to r/w an inv reg*/
+               /*
+                * It's a bug by AMD
+                */
+               plc->np_err++ ;
+       }
+       /* pin inactiv (GND) */
+       if (cmd & PL_PARITY_ERR) {      /* p. error dedected on TX9-0 inp */
+               plc->parity_err++ ;
+       }
+       if (cmd & PL_LSDO) {            /* carrier detected */
+               ;
+       }
+#endif
+}
+
+#ifdef DEBUG
+/*
+ * fill state struct
+ */
+void pcm_get_state(struct s_smc *smc, struct smt_state *state)
+{
+       struct s_phy    *phy ;
+       struct pcm_state *pcs ;
+       int     i ;
+       int     ii ;
+       short   rbits ;
+       short   tbits ;
+       struct fddi_mib_p       *mib ;
+
+       for (i = 0, phy = smc->y, pcs = state->pcm_state ; i < NUMPHYS ;
+               i++ , phy++, pcs++ ) {
+               mib = phy->mib ;
+               pcs->pcm_type = (u_char) mib->fddiPORTMy_Type ;
+               pcs->pcm_state = (u_char) mib->fddiPORTPCMState ;
+               pcs->pcm_mode = phy->pc_mode ;
+               pcs->pcm_neighbor = (u_char) mib->fddiPORTNeighborType ;
+               pcs->pcm_bsf = mib->fddiPORTBS_Flag ;
+               pcs->pcm_lsf = phy->ls_flag ;
+               pcs->pcm_lct_fail = (u_char) mib->fddiPORTLCTFail_Ct ;
+               pcs->pcm_ls_rx = LS2MIB(sm_pm_get_ls(smc,i)) ;
+               for (ii = 0, rbits = tbits = 0 ; ii < NUMBITS ; ii++) {
+                       rbits <<= 1 ;
+                       tbits <<= 1 ;
+                       if (phy->r_val[NUMBITS-1-ii])
+                               rbits |= 1 ;
+                       if (phy->t_val[NUMBITS-1-ii])
+                               tbits |= 1 ;
+               }
+               pcs->pcm_r_val = rbits ;
+               pcs->pcm_t_val = tbits ;
+       }
+}
+
+int get_pcm_state(struct s_smc *smc, int np)
+{
+       int pcs ;
+
+       SK_UNUSED(smc) ;
+
+       switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
+               case PL_PC0 :   pcs = PC_STOP ;         break ;
+               case PL_PC1 :   pcs = PC_START ;        break ;
+               case PL_PC2 :   pcs = PC_TRACE ;        break ;
+               case PL_PC3 :   pcs = PC_SIGNAL ;       break ;
+               case PL_PC4 :   pcs = PC_SIGNAL ;       break ;
+               case PL_PC5 :   pcs = PC_SIGNAL ;       break ;
+               case PL_PC6 :   pcs = PC_JOIN ;         break ;
+               case PL_PC7 :   pcs = PC_JOIN ;         break ;
+               case PL_PC8 :   pcs = PC_ENABLE ;       break ;
+               case PL_PC9 :   pcs = PC_MAINT ;        break ;
+               default :       pcs = PC_DISABLE ;      break ;
+       }
+       return pcs;
+}
+
+char *get_linestate(struct s_smc *smc, int np)
+{
+       char *ls = "" ;
+
+       SK_UNUSED(smc) ;
+
+       switch (inpw(PLC(np,PL_STATUS_A)) & PL_LINE_ST) {
+               case PL_L_NLS : ls = "NOISE" ;  break ;
+               case PL_L_ALS : ls = "ACTIV" ;  break ;
+               case PL_L_UND : ls = "UNDEF" ;  break ;
+               case PL_L_ILS4: ls = "ILS 4" ;  break ;
+               case PL_L_QLS : ls = "QLS" ;    break ;
+               case PL_L_MLS : ls = "MLS" ;    break ;
+               case PL_L_HLS : ls = "HLS" ;    break ;
+               case PL_L_ILS16:ls = "ILS16" ;  break ;
+#ifdef lint
+               default:        ls = "unknown" ; break ;
+#endif
+       }
+       return ls;
+}
+
+char *get_pcmstate(struct s_smc *smc, int np)
+{
+       char *pcs ;
+       
+       SK_UNUSED(smc) ;
+
+       switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
+               case PL_PC0 :   pcs = "OFF" ;           break ;
+               case PL_PC1 :   pcs = "BREAK" ;         break ;
+               case PL_PC2 :   pcs = "TRACE" ;         break ;
+               case PL_PC3 :   pcs = "CONNECT";        break ;
+               case PL_PC4 :   pcs = "NEXT" ;          break ;
+               case PL_PC5 :   pcs = "SIGNAL" ;        break ;
+               case PL_PC6 :   pcs = "JOIN" ;          break ;
+               case PL_PC7 :   pcs = "VERIFY" ;        break ;
+               case PL_PC8 :   pcs = "ACTIV" ;         break ;
+               case PL_PC9 :   pcs = "MAINT" ;         break ;
+               default :       pcs = "UNKNOWN" ;       break ;
+       }
+       return pcs;
+}
+
+void list_phy(struct s_smc *smc)
+{
+       struct s_plc *plc ;
+       int np ;
+
+       for (np = 0 ; np < NUMPHYS ; np++) {
+               plc  = &smc->y[np].plc ;
+               printf("PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ;
+               printf("\tsoft_error: %ld \t\tPC_Start : %ld\n",
+                                               plc->soft_err,plc->b_pcs);
+               printf("\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n",
+                       plc->parity_err,plc->b_tpc,get_linestate(smc,np)) ;
+               printf("\tebuf_error: %ld \t\tTNE exp. : %ld\n",
+                                               plc->ebuf_err,plc->b_tne) ;
+               printf("\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n",
+                       plc->phyinv,plc->b_qls,get_pcmstate(smc,np)) ;
+               printf("\tviosym_ctr: %ld \t\tILS det. : %ld\n",
+                                               plc->vsym_ctr,plc->b_ils)  ;
+               printf("\tmingap_ctr: %ld \t\tHLS det. : %ld\n",
+                                               plc->mini_ctr,plc->b_hls) ;
+               printf("\tnodepr_err: %ld\n",plc->np_err) ;
+               printf("\tTPC_exp : %ld\n",plc->tpc_exp) ;
+               printf("\tLEM_err : %ld\n",smc->y[np].lem.lem_errors) ;
+       }
+}
+
+
+#ifdef CONCENTRATOR
+void pcm_lem_dump(struct s_smc *smc)
+{
+       int             i ;
+       struct s_phy    *phy ;
+       struct fddi_mib_p       *mib ;
+
+       char            *entostring() ;
+
+       printf("PHY     errors  BER\n") ;
+       printf("----------------------\n") ;
+       for (i = 0,phy = smc->y ; i < NUMPHYS ; i++,phy++) {
+               if (!plc_is_installed(smc,i))
+                       continue ;
+               mib = phy->mib ;
+               printf("%s\t%ld\t10E-%d\n",
+                       entostring(smc,ENTITY_PHY(i)),
+                       mib->fddiPORTLem_Ct,
+                       mib->fddiPORTLer_Estimate) ;
+       }
+}
+#endif
+#endif
diff --git a/drivers/net/fddi/skfp/pmf.c b/drivers/net/fddi/skfp/pmf.c
new file mode 100644 (file)
index 0000000..9ac4665
--- /dev/null
@@ -0,0 +1,1663 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       Parameter Management Frame processing for SMT 7.2
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        SLIM_SMT
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)pmf.c       1.37 97/08/04 (C) SK " ;
+#endif
+
+static int smt_authorize(struct s_smc *smc, struct smt_header *sm);
+static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm);
+static const struct s_p_tab* smt_get_ptab(u_short para);
+static int smt_mib_phys(struct s_smc *smc);
+static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
+                       int local, int set);
+void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
+                 int index, int local);
+static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
+                                    int set, int local);
+static int port_to_mib(struct s_smc *smc, int p);
+
+#define MOFFSS(e)      offsetof(struct fddi_mib, e)
+#define MOFFMS(e)      offsetof(struct fddi_mib_m, e)
+#define MOFFAS(e)      offsetof(struct fddi_mib_a, e)
+#define MOFFPS(e)      offsetof(struct fddi_mib_p, e)
+
+
+#define AC_G   0x01            /* Get */
+#define AC_GR  0x02            /* Get/Set */
+#define AC_S   0x04            /* Set */
+#define AC_NA  0x08
+#define AC_GROUP       0x10            /* Group */
+#define MS2BCLK(x)     ((x)*12500L)
+/*
+       F       LFag (byte)
+       B       byte
+       S       u_short 16 bit
+       C       Counter 32 bit
+       L       Long 32 bit
+       T       Timer_2 32 bit
+       P       TimeStamp ;
+       A       LongAddress (6 byte)
+       E       Enum 16 bit
+       R       ResId 16 Bit
+*/
+static const struct s_p_tab {
+       u_short p_num ;         /* parameter code */
+       u_char  p_access ;      /* access rights */
+       u_short p_offset ;      /* offset in mib */
+       char    p_swap[3] ;     /* format string */
+} p_tab[] = {
+       /* StationIdGrp */
+       { SMT_P100A,AC_GROUP    } ,
+       { SMT_P100B,AC_G,       MOFFSS(fddiSMTStationId),       "8"     } ,
+       { SMT_P100D,AC_G,       MOFFSS(fddiSMTOpVersionId),     "S"     } ,
+       { SMT_P100E,AC_G,       MOFFSS(fddiSMTHiVersionId),     "S"     } ,
+       { SMT_P100F,AC_G,       MOFFSS(fddiSMTLoVersionId),     "S"     } ,
+       { SMT_P1010,AC_G,       MOFFSS(fddiSMTManufacturerData), "D" } ,
+       { SMT_P1011,AC_GR,      MOFFSS(fddiSMTUserData),        "D"     } ,
+       { SMT_P1012,AC_G,       MOFFSS(fddiSMTMIBVersionId),    "S"     } ,
+
+       /* StationConfigGrp */
+       { SMT_P1014,AC_GROUP    } ,
+       { SMT_P1015,AC_G,       MOFFSS(fddiSMTMac_Ct),          "B"     } ,
+       { SMT_P1016,AC_G,       MOFFSS(fddiSMTNonMaster_Ct),    "B"     } ,
+       { SMT_P1017,AC_G,       MOFFSS(fddiSMTMaster_Ct),       "B"     } ,
+       { SMT_P1018,AC_G,       MOFFSS(fddiSMTAvailablePaths),  "B"     } ,
+       { SMT_P1019,AC_G,       MOFFSS(fddiSMTConfigCapabilities),"S"   } ,
+       { SMT_P101A,AC_GR,      MOFFSS(fddiSMTConfigPolicy),    "wS"    } ,
+       { SMT_P101B,AC_GR,      MOFFSS(fddiSMTConnectionPolicy),"wS"    } ,
+       { SMT_P101D,AC_GR,      MOFFSS(fddiSMTTT_Notify),       "wS"    } ,
+       { SMT_P101E,AC_GR,      MOFFSS(fddiSMTStatRptPolicy),   "bB"    } ,
+       { SMT_P101F,AC_GR,      MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } ,
+       { SMT_P1020,AC_G,       MOFFSS(fddiSMTPORTIndexes),     "II"    } ,
+       { SMT_P1021,AC_G,       MOFFSS(fddiSMTMACIndexes),      "I"     } ,
+       { SMT_P1022,AC_G,       MOFFSS(fddiSMTBypassPresent),   "F"     } ,
+
+       /* StatusGrp */
+       { SMT_P1028,AC_GROUP    } ,
+       { SMT_P1029,AC_G,       MOFFSS(fddiSMTECMState),        "E"     } ,
+       { SMT_P102A,AC_G,       MOFFSS(fddiSMTCF_State),        "E"     } ,
+       { SMT_P102C,AC_G,       MOFFSS(fddiSMTRemoteDisconnectFlag),"F" } ,
+       { SMT_P102D,AC_G,       MOFFSS(fddiSMTStationStatus),   "E"     } ,
+       { SMT_P102E,AC_G,       MOFFSS(fddiSMTPeerWrapFlag),    "F"     } ,
+
+       /* MIBOperationGrp */
+       { SMT_P1032,AC_GROUP    } ,
+       { SMT_P1033,AC_G,       MOFFSS(fddiSMTTimeStamp),"P"            } ,
+       { SMT_P1034,AC_G,       MOFFSS(fddiSMTTransitionTimeStamp),"P"  } ,
+       /* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */
+       { SMT_P1035,AC_G,       MOFFSS(fddiSMTSetCount),"4P"            } ,
+       { SMT_P1036,AC_G,       MOFFSS(fddiSMTLastSetStationId),"8"     } ,
+
+       { SMT_P103C,AC_S,       0,                              "wS"    } ,
+
+       /*
+        * PRIVATE EXTENSIONS
+        * only accessible locally to get/set passwd
+        */
+       { SMT_P10F0,AC_GR,      MOFFSS(fddiPRPMFPasswd),        "8"     } ,
+       { SMT_P10F1,AC_GR,      MOFFSS(fddiPRPMFStation),       "8"     } ,
+#ifdef ESS
+       { SMT_P10F2,AC_GR,      MOFFSS(fddiESSPayload),         "lL"    } ,
+       { SMT_P10F3,AC_GR,      MOFFSS(fddiESSOverhead),        "lL"    } ,
+       { SMT_P10F4,AC_GR,      MOFFSS(fddiESSMaxTNeg),         "lL"    } ,
+       { SMT_P10F5,AC_GR,      MOFFSS(fddiESSMinSegmentSize),  "lL"    } ,
+       { SMT_P10F6,AC_GR,      MOFFSS(fddiESSCategory),        "lL"    } ,
+       { SMT_P10F7,AC_GR,      MOFFSS(fddiESSSynchTxMode),     "wS"    } ,
+#endif
+#ifdef SBA
+       { SMT_P10F8,AC_GR,      MOFFSS(fddiSBACommand),         "bF"    } ,
+       { SMT_P10F9,AC_GR,      MOFFSS(fddiSBAAvailable),       "bF"    } ,
+#endif
+       /* MAC Attributes */
+       { SMT_P200A,AC_GROUP    } ,
+       { SMT_P200B,AC_G,       MOFFMS(fddiMACFrameStatusFunctions),"S" } ,
+       { SMT_P200D,AC_G,       MOFFMS(fddiMACT_MaxCapabilitiy),"T"     } ,
+       { SMT_P200E,AC_G,       MOFFMS(fddiMACTVXCapabilitiy),"T"       } ,
+
+       /* ConfigGrp */
+       { SMT_P2014,AC_GROUP    } ,
+       { SMT_P2016,AC_G,       MOFFMS(fddiMACAvailablePaths),  "B"     } ,
+       { SMT_P2017,AC_G,       MOFFMS(fddiMACCurrentPath),     "S"     } ,
+       { SMT_P2018,AC_G,       MOFFMS(fddiMACUpstreamNbr),     "A"     } ,
+       { SMT_P2019,AC_G,       MOFFMS(fddiMACDownstreamNbr),   "A"     } ,
+       { SMT_P201A,AC_G,       MOFFMS(fddiMACOldUpstreamNbr),  "A"     } ,
+       { SMT_P201B,AC_G,       MOFFMS(fddiMACOldDownstreamNbr),"A"     } ,
+       { SMT_P201D,AC_G,       MOFFMS(fddiMACDupAddressTest),  "E"     } ,
+       { SMT_P2020,AC_GR,      MOFFMS(fddiMACRequestedPaths),  "wS"    } ,
+       { SMT_P2021,AC_G,       MOFFMS(fddiMACDownstreamPORTType),"E"   } ,
+       { SMT_P2022,AC_G,       MOFFMS(fddiMACIndex),           "S"     } ,
+
+       /* AddressGrp */
+       { SMT_P2028,AC_GROUP    } ,
+       { SMT_P2029,AC_G,       MOFFMS(fddiMACSMTAddress),      "A"     } ,
+
+       /* OperationGrp */
+       { SMT_P2032,AC_GROUP    } ,
+       { SMT_P2033,AC_G,       MOFFMS(fddiMACT_Req),           "T"     } ,
+       { SMT_P2034,AC_G,       MOFFMS(fddiMACT_Neg),           "T"     } ,
+       { SMT_P2035,AC_G,       MOFFMS(fddiMACT_Max),           "T"     } ,
+       { SMT_P2036,AC_G,       MOFFMS(fddiMACTvxValue),        "T"     } ,
+       { SMT_P2038,AC_G,       MOFFMS(fddiMACT_Pri0),          "T"     } ,
+       { SMT_P2039,AC_G,       MOFFMS(fddiMACT_Pri1),          "T"     } ,
+       { SMT_P203A,AC_G,       MOFFMS(fddiMACT_Pri2),          "T"     } ,
+       { SMT_P203B,AC_G,       MOFFMS(fddiMACT_Pri3),          "T"     } ,
+       { SMT_P203C,AC_G,       MOFFMS(fddiMACT_Pri4),          "T"     } ,
+       { SMT_P203D,AC_G,       MOFFMS(fddiMACT_Pri5),          "T"     } ,
+       { SMT_P203E,AC_G,       MOFFMS(fddiMACT_Pri6),          "T"     } ,
+
+
+       /* CountersGrp */
+       { SMT_P2046,AC_GROUP    } ,
+       { SMT_P2047,AC_G,       MOFFMS(fddiMACFrame_Ct),        "C"     } ,
+       { SMT_P2048,AC_G,       MOFFMS(fddiMACCopied_Ct),       "C"     } ,
+       { SMT_P2049,AC_G,       MOFFMS(fddiMACTransmit_Ct),     "C"     } ,
+       { SMT_P204A,AC_G,       MOFFMS(fddiMACToken_Ct),        "C"     } ,
+       { SMT_P2051,AC_G,       MOFFMS(fddiMACError_Ct),        "C"     } ,
+       { SMT_P2052,AC_G,       MOFFMS(fddiMACLost_Ct),         "C"     } ,
+       { SMT_P2053,AC_G,       MOFFMS(fddiMACTvxExpired_Ct),   "C"     } ,
+       { SMT_P2054,AC_G,       MOFFMS(fddiMACNotCopied_Ct),    "C"     } ,
+       { SMT_P2056,AC_G,       MOFFMS(fddiMACRingOp_Ct),       "C"     } ,
+
+       /* FrameErrorConditionGrp */
+       { SMT_P205A,AC_GROUP    } ,
+       { SMT_P205F,AC_GR,      MOFFMS(fddiMACFrameErrorThreshold),"wS" } ,
+       { SMT_P2060,AC_G,       MOFFMS(fddiMACFrameErrorRatio), "S"     } ,
+
+       /* NotCopiedConditionGrp */
+       { SMT_P2064,AC_GROUP    } ,
+       { SMT_P2067,AC_GR,      MOFFMS(fddiMACNotCopiedThreshold),"wS"  } ,
+       { SMT_P2069,AC_G,       MOFFMS(fddiMACNotCopiedRatio),  "S"     } ,
+
+       /* StatusGrp */
+       { SMT_P206E,AC_GROUP    } ,
+       { SMT_P206F,AC_G,       MOFFMS(fddiMACRMTState),        "S"     } ,
+       { SMT_P2070,AC_G,       MOFFMS(fddiMACDA_Flag), "F"     } ,
+       { SMT_P2071,AC_G,       MOFFMS(fddiMACUNDA_Flag),       "F"     } ,
+       { SMT_P2072,AC_G,       MOFFMS(fddiMACFrameErrorFlag),  "F"     } ,
+       { SMT_P2073,AC_G,       MOFFMS(fddiMACNotCopiedFlag),   "F"     } ,
+       { SMT_P2074,AC_G,       MOFFMS(fddiMACMA_UnitdataAvailable),"F" } ,
+       { SMT_P2075,AC_G,       MOFFMS(fddiMACHardwarePresent), "F"     } ,
+       { SMT_P2076,AC_GR,      MOFFMS(fddiMACMA_UnitdataEnable),"bF"   } ,
+
+       /*
+        * PRIVATE EXTENSIONS
+        * only accessible locally to get/set TMIN
+        */
+       { SMT_P20F0,AC_NA                                               } ,
+       { SMT_P20F1,AC_GR,      MOFFMS(fddiMACT_Min),           "lT"    } ,
+
+       /* Path Attributes */
+       /*
+        * DON't swap 320B,320F,3210: they are already swapped in swap_para()
+        */
+       { SMT_P320A,AC_GROUP    } ,
+       { SMT_P320B,AC_G,       MOFFAS(fddiPATHIndex),          "r"     } ,
+       { SMT_P320F,AC_GR,      MOFFAS(fddiPATHSbaPayload),     "l4"    } ,
+       { SMT_P3210,AC_GR,      MOFFAS(fddiPATHSbaOverhead),    "l4"    } ,
+       /* fddiPATHConfiguration */
+       { SMT_P3212,AC_G,       0,                              ""      } ,
+       { SMT_P3213,AC_GR,      MOFFAS(fddiPATHT_Rmode),        "lT"    } ,
+       { SMT_P3214,AC_GR,      MOFFAS(fddiPATHSbaAvailable),   "lL"    } ,
+       { SMT_P3215,AC_GR,      MOFFAS(fddiPATHTVXLowerBound),  "lT"    } ,
+       { SMT_P3216,AC_GR,      MOFFAS(fddiPATHT_MaxLowerBound),"lT"    } ,
+       { SMT_P3217,AC_GR,      MOFFAS(fddiPATHMaxT_Req),       "lT"    } ,
+
+       /* Port Attributes */
+       /* ConfigGrp */
+       { SMT_P400A,AC_GROUP    } ,
+       { SMT_P400C,AC_G,       MOFFPS(fddiPORTMy_Type),        "E"     } ,
+       { SMT_P400D,AC_G,       MOFFPS(fddiPORTNeighborType),   "E"     } ,
+       { SMT_P400E,AC_GR,      MOFFPS(fddiPORTConnectionPolicies),"bB" } ,
+       { SMT_P400F,AC_G,       MOFFPS(fddiPORTMacIndicated),   "2"     } ,
+       { SMT_P4010,AC_G,       MOFFPS(fddiPORTCurrentPath),    "E"     } ,
+       { SMT_P4011,AC_GR,      MOFFPS(fddiPORTRequestedPaths), "l4"    } ,
+       { SMT_P4012,AC_G,       MOFFPS(fddiPORTMACPlacement),   "S"     } ,
+       { SMT_P4013,AC_G,       MOFFPS(fddiPORTAvailablePaths), "B"     } ,
+       { SMT_P4016,AC_G,       MOFFPS(fddiPORTPMDClass),       "E"     } ,
+       { SMT_P4017,AC_G,       MOFFPS(fddiPORTConnectionCapabilities), "B"} ,
+       { SMT_P401D,AC_G,       MOFFPS(fddiPORTIndex),          "R"     } ,
+
+       /* OperationGrp */
+       { SMT_P401E,AC_GROUP    } ,
+       { SMT_P401F,AC_GR,      MOFFPS(fddiPORTMaint_LS),       "wE"    } ,
+       { SMT_P4021,AC_G,       MOFFPS(fddiPORTBS_Flag),        "F"     } ,
+       { SMT_P4022,AC_G,       MOFFPS(fddiPORTPC_LS),          "E"     } ,
+
+       /* ErrorCtrsGrp */
+       { SMT_P4028,AC_GROUP    } ,
+       { SMT_P4029,AC_G,       MOFFPS(fddiPORTEBError_Ct),     "C"     } ,
+       { SMT_P402A,AC_G,       MOFFPS(fddiPORTLCTFail_Ct),     "C"     } ,
+
+       /* LerGrp */
+       { SMT_P4032,AC_GROUP    } ,
+       { SMT_P4033,AC_G,       MOFFPS(fddiPORTLer_Estimate),   "F"     } ,
+       { SMT_P4034,AC_G,       MOFFPS(fddiPORTLem_Reject_Ct),  "C"     } ,
+       { SMT_P4035,AC_G,       MOFFPS(fddiPORTLem_Ct),         "C"     } ,
+       { SMT_P403A,AC_GR,      MOFFPS(fddiPORTLer_Cutoff),     "bB"    } ,
+       { SMT_P403B,AC_GR,      MOFFPS(fddiPORTLer_Alarm),      "bB"    } ,
+
+       /* StatusGrp */
+       { SMT_P403C,AC_GROUP    } ,
+       { SMT_P403D,AC_G,       MOFFPS(fddiPORTConnectState),   "E"     } ,
+       { SMT_P403E,AC_G,       MOFFPS(fddiPORTPCMStateX),      "E"     } ,
+       { SMT_P403F,AC_G,       MOFFPS(fddiPORTPC_Withhold),    "E"     } ,
+       { SMT_P4040,AC_G,       MOFFPS(fddiPORTLerFlag),        "F"     } ,
+       { SMT_P4041,AC_G,       MOFFPS(fddiPORTHardwarePresent),"F"     } ,
+
+       { SMT_P4046,AC_S,       0,                              "wS"    } ,
+
+       { 0,    AC_GROUP        } ,
+       { 0 }
+} ;
+
+void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local)
+{
+       struct smt_header       *sm ;
+       SMbuf           *reply ;
+
+       sm = smtod(mb,struct smt_header *) ;
+       DB_SMT("SMT: processing PMF frame at %x len %d\n",sm,mb->sm_len) ;
+#ifdef DEBUG
+       dump_smt(smc,sm,"PMF Received") ;
+#endif
+       /*
+        * Start the watchdog: It may be a long, long packet and
+        * maybe the watchdog occurs ...
+        */
+       smt_start_watchdog(smc) ;
+
+       if (sm->smt_class == SMT_PMF_GET ||
+           sm->smt_class == SMT_PMF_SET) {
+               reply = smt_build_pmf_response(smc,sm,
+                       sm->smt_class == SMT_PMF_SET,local) ;
+               if (reply) {
+                       sm = smtod(reply,struct smt_header *) ;
+#ifdef DEBUG
+                       dump_smt(smc,sm,"PMF Reply") ;
+#endif
+                       smt_send_frame(smc,reply,FC_SMT_INFO,local) ;
+               }
+       }
+}
+
+static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
+                                    int set, int local)
+{
+       SMbuf                   *mb ;
+       struct smt_header       *smt ;
+       struct smt_para         *pa ;
+       struct smt_p_reason     *res ;
+       const struct s_p_tab    *pt ;
+       int                     len ;
+       int                     index ;
+       int                     idx_end ;
+       int                     error ;
+       int                     range ;
+       SK_LOC_DECL(struct s_pcon,pcon) ;
+       SK_LOC_DECL(struct s_pcon,set_pcon) ;
+
+       /*
+        * build SMT header
+        */
+       if (!(mb = smt_get_mbuf(smc)))
+               return mb;
+
+       smt = smtod(mb, struct smt_header *) ;
+       smt->smt_dest = req->smt_source ;       /* DA == source of request */
+       smt->smt_class = req->smt_class ;       /* same class (GET/SET) */
+       smt->smt_type = SMT_REPLY ;
+       smt->smt_version = SMT_VID_2 ;
+       smt->smt_tid = req->smt_tid ;           /* same TID */
+       smt->smt_pad = 0 ;
+       smt->smt_len = 0 ;
+
+       /*
+        * setup parameter status
+        */
+       pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
+       pcon.pc_err = 0 ;                       /* no error */
+       pcon.pc_badset = 0 ;                    /* no bad set count */
+       pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
+
+       /*
+        * check authoriziation and set count
+        */
+       error = 0 ;
+       if (set) {
+               if (!local && smt_authorize(smc,req))
+                       error = SMT_RDF_AUTHOR ;
+               else if (smt_check_set_count(smc,req))
+                       pcon.pc_badset = SMT_RDF_BADSET ;
+       }
+       /*
+        * add reason code and all mandatory parameters
+        */
+       res = (struct smt_p_reason *) pcon.pc_p ;
+       smt_add_para(smc,&pcon,(u_short) SMT_P_REASON,0,0) ;
+       smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
+       /* update 1035 and 1036 later if set */
+       set_pcon = pcon ;
+       smt_add_para(smc,&pcon,(u_short) SMT_P1035,0,0) ;
+       smt_add_para(smc,&pcon,(u_short) SMT_P1036,0,0) ;
+
+       pcon.pc_err = error ;
+       len = req->smt_len ;
+       pa = (struct smt_para *) (req + 1) ;
+       /*
+        * process list of paras
+        */
+       while (!pcon.pc_err && len > 0 ) {
+               if (((u_short)len < pa->p_len + PARA_LEN) || (pa->p_len & 3)) {
+                       pcon.pc_err = SMT_RDF_LENGTH ;
+                       break ;
+               }
+
+               if (((range = (pa->p_type & 0xf000)) == 0x2000) ||
+                       range == 0x3000 || range == 0x4000) {
+                       /*
+                        * get index for PART,MAC ad PATH group
+                        */
+                       index = *((u_char *)pa + PARA_LEN + 3) ;/* index */
+                       idx_end = index ;
+                       if (!set && (pa->p_len != 4)) {
+                               pcon.pc_err = SMT_RDF_LENGTH ;
+                               break ;
+                       }
+                       if (!index && !set) {
+                               switch (range) {
+                               case 0x2000 :
+                                       index = INDEX_MAC ;
+                                       idx_end = index - 1 + NUMMACS ;
+                                       break ;
+                               case 0x3000 :
+                                       index = INDEX_PATH ;
+                                       idx_end = index - 1 + NUMPATHS ;
+                                       break ;
+                               case 0x4000 :
+                                       index = INDEX_PORT ;
+                                       idx_end = index - 1 + NUMPHYS ;
+#ifndef        CONCENTRATOR
+                                       if (smc->s.sas == SMT_SAS)
+                                               idx_end = INDEX_PORT ;
+#endif
+                                       break ;
+                               }
+                       }
+               }
+               else {
+                       /*
+                        * smt group has no index
+                        */
+                       if (!set && (pa->p_len != 0)) {
+                               pcon.pc_err = SMT_RDF_LENGTH ;
+                               break ;
+                       }
+                       index = 0 ;
+                       idx_end = 0 ;
+               }
+               while (index <= idx_end) {
+                       /*
+                        * if group
+                        *      add all paras of group
+                        */
+                       pt = smt_get_ptab(pa->p_type) ;
+                       if (pt && pt->p_access == AC_GROUP && !set) {
+                               pt++ ;
+                               while (pt->p_access == AC_G ||
+                                       pt->p_access == AC_GR) {
+                                       smt_add_para(smc,&pcon,pt->p_num,
+                                               index,local);
+                                       pt++ ;
+                               }
+                       }
+                       /*
+                        * ignore
+                        *      AUTHORIZATION in get/set
+                        *      SET COUNT in set
+                        */
+                       else if (pa->p_type != SMT_P_AUTHOR &&
+                                (!set || (pa->p_type != SMT_P1035))) {
+                               int     st ;
+                               if (pcon.pc_badset) {
+                                       smt_add_para(smc,&pcon,pa->p_type,
+                                               index,local) ;
+                               }
+                               else if (set) {
+                                       st = smt_set_para(smc,pa,index,local,1);
+                                       /*
+                                        * return para even if error
+                                        */
+                                       smt_add_para(smc,&pcon,pa->p_type,
+                                               index,local) ;
+                                       pcon.pc_err = st ;
+                               }
+                               else {
+                                       if (pt && pt->p_access == AC_S) {
+                                               pcon.pc_err =
+                                                       SMT_RDF_ILLEGAL ;
+                                       }
+                                       smt_add_para(smc,&pcon,pa->p_type,
+                                               index,local) ;
+                               }
+                       }
+                       if (pcon.pc_err)
+                               break ;
+                       index++ ;
+               }
+               len -= pa->p_len + PARA_LEN ;
+               pa = (struct smt_para *) ((char *)pa + pa->p_len + PARA_LEN) ;
+       }
+       smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
+       mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
+
+       /* update reason code */
+       res->rdf_reason = pcon.pc_badset ? pcon.pc_badset :
+                       pcon.pc_err ? pcon.pc_err : SMT_RDF_SUCCESS ;
+       if (set && (res->rdf_reason == SMT_RDF_SUCCESS)) {
+               /*
+                * increment set count
+                * set time stamp
+                * store station id of last set
+                */
+               smc->mib.fddiSMTSetCount.count++ ;
+               smt_set_timestamp(smc,smc->mib.fddiSMTSetCount.timestamp) ;
+               smc->mib.fddiSMTLastSetStationId = req->smt_sid ;
+               smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
+               smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
+       }
+       return mb;
+}
+
+static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
+{
+       struct smt_para *pa ;
+       int             i ;
+       char            *p ;
+
+       /*
+        * check source station id if not zero
+        */
+       p = (char *) &smc->mib.fddiPRPMFStation ;
+       for (i = 0 ; i < 8 && !p[i] ; i++)
+               ;
+       if (i != 8) {
+               if (memcmp((char *) &sm->smt_sid,
+                       (char *) &smc->mib.fddiPRPMFStation,8))
+                       return 1;
+       }
+       /*
+        * check authoriziation parameter if passwd not zero
+        */
+       p = (char *) smc->mib.fddiPRPMFPasswd ;
+       for (i = 0 ; i < 8 && !p[i] ; i++)
+               ;
+       if (i != 8) {
+               pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
+               if (!pa)
+                       return 1;
+               if (pa->p_len != 8)
+                       return 1;
+               if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
+                       return 1;
+       }
+       return 0;
+}
+
+static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
+{
+       struct smt_para *pa ;
+       struct smt_p_setcount   *sc ;
+
+       pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P1035) ;
+       if (pa) {
+               sc = (struct smt_p_setcount *) pa ;
+               if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
+                       memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
+                       (char *)sc->timestamp,8))
+                       return 1;
+       }
+       return 0;
+}
+
+void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
+                 int index, int local)
+{
+       struct smt_para *pa ;
+       const struct s_p_tab    *pt ;
+       struct fddi_mib_m *mib_m = NULL;
+       struct fddi_mib_p *mib_p = NULL;
+       int             len ;
+       int             plen ;
+       char            *from ;
+       char            *to ;
+       const char      *swap ;
+       char            c ;
+       int             range ;
+       char            *mib_addr ;
+       int             mac ;
+       int             path ;
+       int             port ;
+       int             sp_len ;
+
+       /*
+        * skip if error
+        */
+       if (pcon->pc_err)
+               return ;
+
+       /*
+        * actions don't have a value
+        */
+       pt = smt_get_ptab(para) ;
+       if (pt && pt->p_access == AC_S)
+               return ;
+
+       to = (char *) (pcon->pc_p) ;    /* destination pointer */
+       len = pcon->pc_len ;            /* free space */
+       plen = len ;                    /* remember start length */
+       pa = (struct smt_para *) to ;   /* type/length pointer */
+       to += PARA_LEN ;                /* skip smt_para */
+       len -= PARA_LEN ;
+       /*
+        * set index if required
+        */
+       if (((range = (para & 0xf000)) == 0x2000) ||
+               range == 0x3000 || range == 0x4000) {
+               if (len < 4)
+                       goto wrong_error ;
+               to[0] = 0 ;
+               to[1] = 0 ;
+               to[2] = 0 ;
+               to[3] = index ;
+               len -= 4 ;
+               to += 4 ;
+       }
+       mac = index - INDEX_MAC ;
+       path = index - INDEX_PATH ;
+       port = index - INDEX_PORT ;
+       /*
+        * get pointer to mib
+        */
+       switch (range) {
+       case 0x1000 :
+       default :
+               mib_addr = (char *) (&smc->mib) ;
+               break ;
+       case 0x2000 :
+               if (mac < 0 || mac >= NUMMACS) {
+                       pcon->pc_err = SMT_RDF_NOPARAM ;
+                       return ;
+               }
+               mib_addr = (char *) (&smc->mib.m[mac]) ;
+               mib_m = (struct fddi_mib_m *) mib_addr ;
+               break ;
+       case 0x3000 :
+               if (path < 0 || path >= NUMPATHS) {
+                       pcon->pc_err = SMT_RDF_NOPARAM ;
+                       return ;
+               }
+               mib_addr = (char *) (&smc->mib.a[path]) ;
+               break ;
+       case 0x4000 :
+               if (port < 0 || port >= smt_mib_phys(smc)) {
+                       pcon->pc_err = SMT_RDF_NOPARAM ;
+                       return ;
+               }
+               mib_addr = (char *) (&smc->mib.p[port_to_mib(smc,port)]) ;
+               mib_p = (struct fddi_mib_p *) mib_addr ;
+               break ;
+       }
+       /*
+        * check special paras
+        */
+       swap = NULL;
+       switch (para) {
+       case SMT_P10F0 :
+       case SMT_P10F1 :
+#ifdef ESS
+       case SMT_P10F2 :
+       case SMT_P10F3 :
+       case SMT_P10F4 :
+       case SMT_P10F5 :
+       case SMT_P10F6 :
+       case SMT_P10F7 :
+#endif
+#ifdef SBA
+       case SMT_P10F8 :
+       case SMT_P10F9 :
+#endif
+       case SMT_P20F1 :
+               if (!local) {
+                       pcon->pc_err = SMT_RDF_NOPARAM ;
+                       return ;
+               }
+               break ;
+       case SMT_P2034 :
+       case SMT_P2046 :
+       case SMT_P2047 :
+       case SMT_P204A :
+       case SMT_P2051 :
+       case SMT_P2052 :
+               mac_update_counter(smc) ;
+               break ;
+       case SMT_P4022:
+               mib_p->fddiPORTPC_LS = LS2MIB(
+                       sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
+               break ;
+       case SMT_P_REASON :
+               * (u_long *) to = 0 ;
+               sp_len = 4 ;
+               goto sp_done ;
+       case SMT_P1033 :                        /* time stamp */
+               smt_set_timestamp(smc,smc->mib.fddiSMTTimeStamp) ;
+               break ;
+
+       case SMT_P1020:                         /* port indexes */
+#if    NUMPHYS == 12
+               swap = "IIIIIIIIIIII" ;
+#else
+#if    NUMPHYS == 2
+               if (smc->s.sas == SMT_SAS)
+                       swap = "I" ;
+               else
+                       swap = "II" ;
+#else
+#if    NUMPHYS == 24
+               swap = "IIIIIIIIIIIIIIIIIIIIIIII" ;
+#else
+       ????
+#endif
+#endif
+#endif
+               break ;
+       case SMT_P3212 :
+               {
+                       sp_len = cem_build_path(smc,to,path) ;
+                       goto sp_done ;
+               }
+       case SMT_P1048 :                /* peer wrap condition */
+               {
+                       struct smt_p_1048       *sp ;
+                       sp = (struct smt_p_1048 *) to ;
+                       sp->p1048_flag = smc->mib.fddiSMTPeerWrapFlag ;
+                       sp->p1048_cf_state = smc->mib.fddiSMTCF_State ;
+                       sp_len = sizeof(struct smt_p_1048) ;
+                       goto sp_done ;
+               }
+       case SMT_P208C :
+               {
+                       struct smt_p_208c       *sp ;
+                       sp = (struct smt_p_208c *) to ;
+                       sp->p208c_flag =
+                               smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
+                       sp->p208c_dupcondition =
+                               (mib_m->fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0) |
+                               (mib_m->fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0);
+                       sp->p208c_fddilong =
+                               mib_m->fddiMACSMTAddress ;
+                       sp->p208c_fddiunalong =
+                               mib_m->fddiMACUpstreamNbr ;
+                       sp->p208c_pad = 0 ;
+                       sp_len = sizeof(struct smt_p_208c) ;
+                       goto sp_done ;
+               }
+       case SMT_P208D :                /* frame error condition */
+               {
+                       struct smt_p_208d       *sp ;
+                       sp = (struct smt_p_208d *) to ;
+                       sp->p208d_flag =
+                               mib_m->fddiMACFrameErrorFlag ;
+                       sp->p208d_frame_ct =
+                               mib_m->fddiMACFrame_Ct ;
+                       sp->p208d_error_ct =
+                               mib_m->fddiMACError_Ct ;
+                       sp->p208d_lost_ct =
+                               mib_m->fddiMACLost_Ct ;
+                       sp->p208d_ratio =
+                               mib_m->fddiMACFrameErrorRatio ;
+                       sp_len = sizeof(struct smt_p_208d) ;
+                       goto sp_done ;
+               }
+       case SMT_P208E :                /* not copied condition */
+               {
+                       struct smt_p_208e       *sp ;
+                       sp = (struct smt_p_208e *) to ;
+                       sp->p208e_flag =
+                               mib_m->fddiMACNotCopiedFlag ;
+                       sp->p208e_not_copied =
+                               mib_m->fddiMACNotCopied_Ct ;
+                       sp->p208e_copied =
+                               mib_m->fddiMACCopied_Ct ;
+                       sp->p208e_not_copied_ratio =
+                               mib_m->fddiMACNotCopiedRatio ;
+                       sp_len = sizeof(struct smt_p_208e) ;
+                       goto sp_done ;
+               }
+       case SMT_P208F :        /* neighbor change event */
+               {
+                       struct smt_p_208f       *sp ;
+                       sp = (struct smt_p_208f *) to ;
+                       sp->p208f_multiple =
+                               mib_m->fddiMACMultiple_N ;
+                       sp->p208f_nacondition =
+                               mib_m->fddiMACDuplicateAddressCond ;
+                       sp->p208f_old_una =
+                               mib_m->fddiMACOldUpstreamNbr ;
+                       sp->p208f_new_una =
+                               mib_m->fddiMACUpstreamNbr ;
+                       sp->p208f_old_dna =
+                               mib_m->fddiMACOldDownstreamNbr ;
+                       sp->p208f_new_dna =
+                               mib_m->fddiMACDownstreamNbr ;
+                       sp->p208f_curren_path =
+                               mib_m->fddiMACCurrentPath ;
+                       sp->p208f_smt_address =
+                               mib_m->fddiMACSMTAddress ;
+                       sp_len = sizeof(struct smt_p_208f) ;
+                       goto sp_done ;
+               }
+       case SMT_P2090 :
+               {
+                       struct smt_p_2090       *sp ;
+                       sp = (struct smt_p_2090 *) to ;
+                       sp->p2090_multiple =
+                               mib_m->fddiMACMultiple_P ;
+                       sp->p2090_availablepaths =
+                               mib_m->fddiMACAvailablePaths ;
+                       sp->p2090_currentpath =
+                               mib_m->fddiMACCurrentPath ;
+                       sp->p2090_requestedpaths =
+                               mib_m->fddiMACRequestedPaths ;
+                       sp_len = sizeof(struct smt_p_2090) ;
+                       goto sp_done ;
+               }
+       case SMT_P4050 :
+               {
+                       struct smt_p_4050       *sp ;
+                       sp = (struct smt_p_4050 *) to ;
+                       sp->p4050_flag =
+                               mib_p->fddiPORTLerFlag ;
+                       sp->p4050_pad = 0 ;
+                       sp->p4050_cutoff =
+                               mib_p->fddiPORTLer_Cutoff ;
+                       sp->p4050_alarm =
+                               mib_p->fddiPORTLer_Alarm ;
+                       sp->p4050_estimate =
+                               mib_p->fddiPORTLer_Estimate ;
+                       sp->p4050_reject_ct =
+                               mib_p->fddiPORTLem_Reject_Ct ;
+                       sp->p4050_ct =
+                               mib_p->fddiPORTLem_Ct ;
+                       sp_len = sizeof(struct smt_p_4050) ;
+                       goto sp_done ;
+               }
+
+       case SMT_P4051 :
+               {
+                       struct smt_p_4051       *sp ;
+                       sp = (struct smt_p_4051 *) to ;
+                       sp->p4051_multiple =
+                               mib_p->fddiPORTMultiple_U ;
+                       sp->p4051_porttype =
+                               mib_p->fddiPORTMy_Type ;
+                       sp->p4051_connectstate =
+                               mib_p->fddiPORTConnectState ;
+                       sp->p4051_pc_neighbor =
+                               mib_p->fddiPORTNeighborType ;
+                       sp->p4051_pc_withhold =
+                               mib_p->fddiPORTPC_Withhold ;
+                       sp_len = sizeof(struct smt_p_4051) ;
+                       goto sp_done ;
+               }
+       case SMT_P4052 :
+               {
+                       struct smt_p_4052       *sp ;
+                       sp = (struct smt_p_4052 *) to ;
+                       sp->p4052_flag =
+                               mib_p->fddiPORTEB_Condition ;
+                       sp->p4052_eberrorcount =
+                               mib_p->fddiPORTEBError_Ct ;
+                       sp_len = sizeof(struct smt_p_4052) ;
+                       goto sp_done ;
+               }
+       case SMT_P4053 :
+               {
+                       struct smt_p_4053       *sp ;
+                       sp = (struct smt_p_4053 *) to ;
+                       sp->p4053_multiple =
+                               mib_p->fddiPORTMultiple_P ;
+                       sp->p4053_availablepaths =
+                               mib_p->fddiPORTAvailablePaths ;
+                       sp->p4053_currentpath =
+                               mib_p->fddiPORTCurrentPath ;
+                       memcpy( (char *) &sp->p4053_requestedpaths,
+                               (char *) mib_p->fddiPORTRequestedPaths,4) ;
+                       sp->p4053_mytype =
+                               mib_p->fddiPORTMy_Type ;
+                       sp->p4053_neighbortype =
+                               mib_p->fddiPORTNeighborType ;
+                       sp_len = sizeof(struct smt_p_4053) ;
+                       goto sp_done ;
+               }
+       default :
+               break ;
+       }
+       /*
+        * in table ?
+        */
+       if (!pt) {
+               pcon->pc_err = (para & 0xff00) ? SMT_RDF_NOPARAM :
+                                               SMT_RDF_ILLEGAL ;
+               return ;
+       }
+       /*
+        * check access rights
+        */
+       switch (pt->p_access) {
+       case AC_G :
+       case AC_GR :
+               break ;
+       default :
+               pcon->pc_err = SMT_RDF_ILLEGAL ;
+               return ;
+       }
+       from = mib_addr + pt->p_offset ;
+       if (!swap)
+               swap = pt->p_swap ;             /* pointer to swap string */
+
+       /*
+        * copy values
+        */
+       while ((c = *swap++)) {
+               switch(c) {
+               case 'b' :
+               case 'w' :
+               case 'l' :
+                       break ;
+               case 'S' :
+               case 'E' :
+               case 'R' :
+               case 'r' :
+                       if (len < 4)
+                               goto len_error ;
+                       to[0] = 0 ;
+                       to[1] = 0 ;
+#ifdef LITTLE_ENDIAN
+                       if (c == 'r') {
+                               to[2] = *from++ ;
+                               to[3] = *from++ ;
+                       }
+                       else {
+                               to[3] = *from++ ;
+                               to[2] = *from++ ;
+                       }
+#else
+                       to[2] = *from++ ;
+                       to[3] = *from++ ;
+#endif
+                       to += 4 ;
+                       len -= 4 ;
+                       break ;
+               case 'I' :              /* for SET of port indexes */
+                       if (len < 2)
+                               goto len_error ;
+#ifdef LITTLE_ENDIAN
+                       to[1] = *from++ ;
+                       to[0] = *from++ ;
+#else
+                       to[0] = *from++ ;
+                       to[1] = *from++ ;
+#endif
+                       to += 2 ;
+                       len -= 2 ;
+                       break ;
+               case 'F' :
+               case 'B' :
+                       if (len < 4)
+                               goto len_error ;
+                       len -= 4 ;
+                       to[0] = 0 ;
+                       to[1] = 0 ;
+                       to[2] = 0 ;
+                       to[3] = *from++ ;
+                       to += 4 ;
+                       break ;
+               case 'C' :
+               case 'T' :
+               case 'L' :
+                       if (len < 4)
+                               goto len_error ;
+#ifdef LITTLE_ENDIAN
+                       to[3] = *from++ ;
+                       to[2] = *from++ ;
+                       to[1] = *from++ ;
+                       to[0] = *from++ ;
+#else
+                       to[0] = *from++ ;
+                       to[1] = *from++ ;
+                       to[2] = *from++ ;
+                       to[3] = *from++ ;
+#endif
+                       len -= 4 ;
+                       to += 4 ;
+                       break ;
+               case '2' :              /* PortMacIndicated */
+                       if (len < 4)
+                               goto len_error ;
+                       to[0] = 0 ;
+                       to[1] = 0 ;
+                       to[2] = *from++ ;
+                       to[3] = *from++ ;
+                       len -= 4 ;
+                       to += 4 ;
+                       break ;
+               case '4' :
+                       if (len < 4)
+                               goto len_error ;
+                       to[0] = *from++ ;
+                       to[1] = *from++ ;
+                       to[2] = *from++ ;
+                       to[3] = *from++ ;
+                       len -= 4 ;
+                       to += 4 ;
+                       break ;
+               case 'A' :
+                       if (len < 8)
+                               goto len_error ;
+                       to[0] = 0 ;
+                       to[1] = 0 ;
+                       memcpy((char *) to+2,(char *) from,6) ;
+                       to += 8 ;
+                       from += 8 ;
+                       len -= 8 ;
+                       break ;
+               case '8' :
+                       if (len < 8)
+                               goto len_error ;
+                       memcpy((char *) to,(char *) from,8) ;
+                       to += 8 ;
+                       from += 8 ;
+                       len -= 8 ;
+                       break ;
+               case 'D' :
+                       if (len < 32)
+                               goto len_error ;
+                       memcpy((char *) to,(char *) from,32) ;
+                       to += 32 ;
+                       from += 32 ;
+                       len -= 32 ;
+                       break ;
+               case 'P' :              /* timestamp is NOT swapped */
+                       if (len < 8)
+                               goto len_error ;
+                       to[0] = *from++ ;
+                       to[1] = *from++ ;
+                       to[2] = *from++ ;
+                       to[3] = *from++ ;
+                       to[4] = *from++ ;
+                       to[5] = *from++ ;
+                       to[6] = *from++ ;
+                       to[7] = *from++ ;
+                       to += 8 ;
+                       len -= 8 ;
+                       break ;
+               default :
+                       SMT_PANIC(smc,SMT_E0119, SMT_E0119_MSG) ;
+                       break ;
+               }
+       }
+
+done:
+       /*
+        * make it even (in case of 'I' encoding)
+        * note: len is DECREMENTED
+        */
+       if (len & 3) {
+               to[0] = 0 ;
+               to[1] = 0 ;
+               to += 4 - (len & 3 ) ;
+               len = len & ~ 3 ;
+       }
+
+       /* set type and length */
+       pa->p_type = para ;
+       pa->p_len = plen - len - PARA_LEN ;
+       /* return values */
+       pcon->pc_p = (void *) to ;
+       pcon->pc_len = len ;
+       return ;
+
+sp_done:
+       len -= sp_len ;
+       to += sp_len ;
+       goto done ;
+
+len_error:
+       /* parameter does not fit in frame */
+       pcon->pc_err = SMT_RDF_TOOLONG ;
+       return ;
+
+wrong_error:
+       pcon->pc_err = SMT_RDF_LENGTH ;
+}
+
+/*
+ * set parameter
+ */
+static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
+                       int local, int set)
+{
+#define IFSET(x)       if (set) (x)
+
+       const struct s_p_tab    *pt ;
+       int             len ;
+       char            *from ;
+       char            *to ;
+       const char      *swap ;
+       char            c ;
+       char            *mib_addr ;
+       struct fddi_mib *mib ;
+       struct fddi_mib_m       *mib_m = NULL;
+       struct fddi_mib_a       *mib_a = NULL;
+       struct fddi_mib_p       *mib_p = NULL;
+       int             mac ;
+       int             path ;
+       int             port ;
+       SK_LOC_DECL(u_char,byte_val) ;
+       SK_LOC_DECL(u_short,word_val) ;
+       SK_LOC_DECL(u_long,long_val) ;
+
+       mac = index - INDEX_MAC ;
+       path = index - INDEX_PATH ;
+       port = index - INDEX_PORT ;
+       len = pa->p_len ;
+       from = (char *) (pa + 1 ) ;
+
+       mib = &smc->mib ;
+       switch (pa->p_type & 0xf000) {
+       case 0x1000 :
+       default :
+               mib_addr = (char *) mib ;
+               break ;
+       case 0x2000 :
+               if (mac < 0 || mac >= NUMMACS) {
+                       return SMT_RDF_NOPARAM;
+               }
+               mib_m = &smc->mib.m[mac] ;
+               mib_addr = (char *) mib_m ;
+               from += 4 ;             /* skip index */
+               len -= 4 ;
+               break ;
+       case 0x3000 :
+               if (path < 0 || path >= NUMPATHS) {
+                       return SMT_RDF_NOPARAM;
+               }
+               mib_a = &smc->mib.a[path] ;
+               mib_addr = (char *) mib_a ;
+               from += 4 ;             /* skip index */
+               len -= 4 ;
+               break ;
+       case 0x4000 :
+               if (port < 0 || port >= smt_mib_phys(smc)) {
+                       return SMT_RDF_NOPARAM;
+               }
+               mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
+               mib_addr = (char *) mib_p ;
+               from += 4 ;             /* skip index */
+               len -= 4 ;
+               break ;
+       }
+       switch (pa->p_type) {
+       case SMT_P10F0 :
+       case SMT_P10F1 :
+#ifdef ESS
+       case SMT_P10F2 :
+       case SMT_P10F3 :
+       case SMT_P10F4 :
+       case SMT_P10F5 :
+       case SMT_P10F6 :
+       case SMT_P10F7 :
+#endif
+#ifdef SBA
+       case SMT_P10F8 :
+       case SMT_P10F9 :
+#endif
+       case SMT_P20F1 :
+               if (!local)
+                       return SMT_RDF_NOPARAM;
+               break ;
+       }
+       pt = smt_get_ptab(pa->p_type) ;
+       if (!pt)
+               return (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
+                                              SMT_RDF_ILLEGAL;
+       switch (pt->p_access) {
+       case AC_GR :
+       case AC_S :
+               break ;
+       default :
+               return SMT_RDF_ILLEGAL;
+       }
+       to = mib_addr + pt->p_offset ;
+       swap = pt->p_swap ;             /* pointer to swap string */
+
+       while (swap && (c = *swap++)) {
+               switch(c) {
+               case 'b' :
+                       to = (char *) &byte_val ;
+                       break ;
+               case 'w' :
+                       to = (char *) &word_val ;
+                       break ;
+               case 'l' :
+                       to = (char *) &long_val ;
+                       break ;
+               case 'S' :
+               case 'E' :
+               case 'R' :
+               case 'r' :
+                       if (len < 4) {
+                               goto len_error ;
+                       }
+                       if (from[0] | from[1])
+                               goto val_error ;
+#ifdef LITTLE_ENDIAN
+                       if (c == 'r') {
+                               to[0] = from[2] ;
+                               to[1] = from[3] ;
+                       }
+                       else {
+                               to[1] = from[2] ;
+                               to[0] = from[3] ;
+                       }
+#else
+                       to[0] = from[2] ;
+                       to[1] = from[3] ;
+#endif
+                       from += 4 ;
+                       to += 2 ;
+                       len -= 4 ;
+                       break ;
+               case 'F' :
+               case 'B' :
+                       if (len < 4) {
+                               goto len_error ;
+                       }
+                       if (from[0] | from[1] | from[2])
+                               goto val_error ;
+                       to[0] = from[3] ;
+                       len -= 4 ;
+                       from += 4 ;
+                       to += 4 ;
+                       break ;
+               case 'C' :
+               case 'T' :
+               case 'L' :
+                       if (len < 4) {
+                               goto len_error ;
+                       }
+#ifdef LITTLE_ENDIAN
+                       to[3] = *from++ ;
+                       to[2] = *from++ ;
+                       to[1] = *from++ ;
+                       to[0] = *from++ ;
+#else
+                       to[0] = *from++ ;
+                       to[1] = *from++ ;
+                       to[2] = *from++ ;
+                       to[3] = *from++ ;
+#endif
+                       len -= 4 ;
+                       to += 4 ;
+                       break ;
+               case 'A' :
+                       if (len < 8)
+                               goto len_error ;
+                       if (set)
+                               memcpy((char *) to,(char *) from+2,6) ;
+                       to += 8 ;
+                       from += 8 ;
+                       len -= 8 ;
+                       break ;
+               case '4' :
+                       if (len < 4)
+                               goto len_error ;
+                       if (set)
+                               memcpy((char *) to,(char *) from,4) ;
+                       to += 4 ;
+                       from += 4 ;
+                       len -= 4 ;
+                       break ;
+               case '8' :
+                       if (len < 8)
+                               goto len_error ;
+                       if (set)
+                               memcpy((char *) to,(char *) from,8) ;
+                       to += 8 ;
+                       from += 8 ;
+                       len -= 8 ;
+                       break ;
+               case 'D' :
+                       if (len < 32)
+                               goto len_error ;
+                       if (set)
+                               memcpy((char *) to,(char *) from,32) ;
+                       to += 32 ;
+                       from += 32 ;
+                       len -= 32 ;
+                       break ;
+               case 'P' :              /* timestamp is NOT swapped */
+                       if (set) {
+                               to[0] = *from++ ;
+                               to[1] = *from++ ;
+                               to[2] = *from++ ;
+                               to[3] = *from++ ;
+                               to[4] = *from++ ;
+                               to[5] = *from++ ;
+                               to[6] = *from++ ;
+                               to[7] = *from++ ;
+                       }
+                       to += 8 ;
+                       len -= 8 ;
+                       break ;
+               default :
+                       SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
+                       return SMT_RDF_ILLEGAL;
+               }
+       }
+       /*
+        * actions and internal updates
+        */
+       switch (pa->p_type) {
+       case SMT_P101A:                 /* fddiSMTConfigPolicy */
+               if (word_val & ~1)
+                       goto val_error ;
+               IFSET(mib->fddiSMTConfigPolicy = word_val) ;
+               break ;
+       case SMT_P101B :                /* fddiSMTConnectionPolicy */
+               if (!(word_val & POLICY_MM))
+                       goto val_error ;
+               IFSET(mib->fddiSMTConnectionPolicy = word_val) ;
+               break ;
+       case SMT_P101D :                /* fddiSMTTT_Notify */
+               if (word_val < 2 || word_val > 30)
+                       goto val_error ;
+               IFSET(mib->fddiSMTTT_Notify = word_val) ;
+               break ;
+       case SMT_P101E :                /* fddiSMTStatRptPolicy */
+               if (byte_val & ~1)
+                       goto val_error ;
+               IFSET(mib->fddiSMTStatRptPolicy = byte_val) ;
+               break ;
+       case SMT_P101F :                /* fddiSMTTrace_MaxExpiration */
+               /*
+                * note: lower limit trace_max = 6.001773... s
+                * NO upper limit
+                */
+               if (long_val < (long)0x478bf51L)
+                       goto val_error ;
+               IFSET(mib->fddiSMTTrace_MaxExpiration = long_val) ;
+               break ;
+#ifdef ESS
+       case SMT_P10F2 :                /* fddiESSPayload */
+               if (long_val > 1562)
+                       goto val_error ;
+               if (set && smc->mib.fddiESSPayload != long_val) {
+                       smc->ess.raf_act_timer_poll = TRUE ;
+                       smc->mib.fddiESSPayload = long_val ;
+               }
+               break ;
+       case SMT_P10F3 :                /* fddiESSOverhead */
+               if (long_val < 50 || long_val > 5000)
+                       goto val_error ;
+               if (set && smc->mib.fddiESSPayload &&
+                       smc->mib.fddiESSOverhead != long_val) {
+                       smc->ess.raf_act_timer_poll = TRUE ;
+                       smc->mib.fddiESSOverhead = long_val ;
+               }
+               break ;
+       case SMT_P10F4 :                /* fddiESSMaxTNeg */
+               if (long_val > -MS2BCLK(5) || long_val < -MS2BCLK(165))
+                       goto val_error ;
+               IFSET(mib->fddiESSMaxTNeg = long_val) ;
+               break ;
+       case SMT_P10F5 :                /* fddiESSMinSegmentSize */
+               if (long_val < 1 || long_val > 4478)
+                       goto val_error ;
+               IFSET(mib->fddiESSMinSegmentSize = long_val) ;
+               break ;
+       case SMT_P10F6 :                /* fddiESSCategory */
+               if ((long_val & 0xffff) != 1)
+                       goto val_error ;
+               IFSET(mib->fddiESSCategory = long_val) ;
+               break ;
+       case SMT_P10F7 :                /* fddiESSSyncTxMode */
+               if (word_val > 1)
+                       goto val_error ;
+               IFSET(mib->fddiESSSynchTxMode = word_val) ;
+               break ;
+#endif
+#ifdef SBA
+       case SMT_P10F8 :                /* fddiSBACommand */
+               if (byte_val != SB_STOP && byte_val != SB_START)
+                       goto val_error ;
+               IFSET(mib->fddiSBACommand = byte_val) ;
+               break ;
+       case SMT_P10F9 :                /* fddiSBAAvailable */
+               if (byte_val > 100)
+                       goto val_error ;
+               IFSET(mib->fddiSBAAvailable = byte_val) ;
+               break ;
+#endif
+       case SMT_P2020 :                /* fddiMACRequestedPaths */
+               if ((word_val & (MIB_P_PATH_PRIM_PREFER |
+                       MIB_P_PATH_PRIM_ALTER)) == 0 )
+                       goto val_error ;
+               IFSET(mib_m->fddiMACRequestedPaths = word_val) ;
+               break ;
+       case SMT_P205F :                /* fddiMACFrameErrorThreshold */
+               /* 0 .. ffff acceptable */
+               IFSET(mib_m->fddiMACFrameErrorThreshold = word_val) ;
+               break ;
+       case SMT_P2067 :                /* fddiMACNotCopiedThreshold */
+               /* 0 .. ffff acceptable */
+               IFSET(mib_m->fddiMACNotCopiedThreshold = word_val) ;
+               break ;
+       case SMT_P2076:                 /* fddiMACMA_UnitdataEnable */
+               if (byte_val & ~1)
+                       goto val_error ;
+               if (set) {
+                       mib_m->fddiMACMA_UnitdataEnable = byte_val ;
+                       queue_event(smc,EVENT_RMT,RM_ENABLE_FLAG) ;
+               }
+               break ;
+       case SMT_P20F1 :                /* fddiMACT_Min */
+               IFSET(mib_m->fddiMACT_Min = long_val) ;
+               break ;
+       case SMT_P320F :
+               if (long_val > 1562)
+                       goto val_error ;
+               IFSET(mib_a->fddiPATHSbaPayload = long_val) ;
+#ifdef ESS
+               if (set)
+                       ess_para_change(smc) ;
+#endif
+               break ;
+       case SMT_P3210 :
+               if (long_val > 5000)
+                       goto val_error ;
+               
+               if (long_val != 0 && mib_a->fddiPATHSbaPayload == 0)
+                       goto val_error ;
+
+               IFSET(mib_a->fddiPATHSbaOverhead = long_val) ;
+#ifdef ESS
+               if (set)
+                       ess_para_change(smc) ;
+#endif
+               break ;
+       case SMT_P3213:                 /* fddiPATHT_Rmode */
+               /* no limit :
+                * 0 .. 343.597 => 0 .. 2e32 * 80nS
+                */
+               if (set) {
+                       mib_a->fddiPATHT_Rmode = long_val ;
+                       rtm_set_timer(smc) ;
+               }
+               break ;
+       case SMT_P3214 :                /* fddiPATHSbaAvailable */
+               if (long_val > 0x00BEBC20L)
+                       goto val_error ;
+#ifdef SBA 
+               if (set && mib->fddiSBACommand == SB_STOP)
+                       goto val_error ;
+#endif
+               IFSET(mib_a->fddiPATHSbaAvailable = long_val) ;
+               break ;
+       case SMT_P3215 :                /* fddiPATHTVXLowerBound */
+               IFSET(mib_a->fddiPATHTVXLowerBound = long_val) ;
+               goto change_mac_para ;
+       case SMT_P3216 :                /* fddiPATHT_MaxLowerBound */
+               IFSET(mib_a->fddiPATHT_MaxLowerBound = long_val) ;
+               goto change_mac_para ;
+       case SMT_P3217 :                /* fddiPATHMaxT_Req */
+               IFSET(mib_a->fddiPATHMaxT_Req = long_val) ;
+
+change_mac_para:
+               if (set && smt_set_mac_opvalues(smc)) {
+                       RS_SET(smc,RS_EVENT) ;
+                       smc->sm.please_reconnect = 1 ;
+                       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+               }
+               break ;
+       case SMT_P400E :                /* fddiPORTConnectionPolicies */
+               if (byte_val > 1)
+                       goto val_error ;
+               IFSET(mib_p->fddiPORTConnectionPolicies = byte_val) ;
+               break ;
+       case SMT_P4011 :                /* fddiPORTRequestedPaths */
+               /* all 3*8 bits allowed */
+               IFSET(memcpy((char *)mib_p->fddiPORTRequestedPaths,
+                       (char *)&long_val,4)) ;
+               break ;
+       case SMT_P401F:                 /* fddiPORTMaint_LS */
+               if (word_val > 4)
+                       goto val_error ;
+               IFSET(mib_p->fddiPORTMaint_LS = word_val) ;
+               break ;
+       case SMT_P403A :                /* fddiPORTLer_Cutoff */
+               if (byte_val < 4 || byte_val > 15)
+                       goto val_error ;
+               IFSET(mib_p->fddiPORTLer_Cutoff = byte_val) ;
+               break ;
+       case SMT_P403B :                /* fddiPORTLer_Alarm */
+               if (byte_val < 4 || byte_val > 15)
+                       goto val_error ;
+               IFSET(mib_p->fddiPORTLer_Alarm = byte_val) ;
+               break ;
+
+       /*
+        * Actions
+        */
+       case SMT_P103C :                /* fddiSMTStationAction */
+               if (smt_action(smc,SMT_STATION_ACTION, (int) word_val, 0))
+                       goto val_error ;
+               break ;
+       case SMT_P4046:                 /* fddiPORTAction */
+               if (smt_action(smc,SMT_PORT_ACTION, (int) word_val,
+                       port_to_mib(smc,port)))
+                       goto val_error ;
+               break ;
+       default :
+               break ;
+       }
+       return 0;
+
+val_error:
+       /* parameter value in frame is out of range */
+       return SMT_RDF_RANGE;
+
+len_error:
+       /* parameter value in frame is too short */
+       return SMT_RDF_LENGTH;
+
+#if    0
+no_author_error:
+       /* parameter not setable, because the SBA is not active
+        * Please note: we give the return code 'not authorizeed
+        *  because SBA denied is not a valid return code in the
+        * PMF protocol.
+        */
+       return SMT_RDF_AUTHOR;
+#endif
+}
+
+static const struct s_p_tab *smt_get_ptab(u_short para)
+{
+       const struct s_p_tab    *pt ;
+       for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
+               ;
+       return pt->p_num ? pt : NULL;
+}
+
+static int smt_mib_phys(struct s_smc *smc)
+{
+#ifdef CONCENTRATOR
+       SK_UNUSED(smc) ;
+
+       return NUMPHYS;
+#else
+       if (smc->s.sas == SMT_SAS)
+               return 1;
+       return NUMPHYS;
+#endif
+}
+
+static int port_to_mib(struct s_smc *smc, int p)
+{
+#ifdef CONCENTRATOR
+       SK_UNUSED(smc) ;
+
+       return p;
+#else
+       if (smc->s.sas == SMT_SAS)
+               return PS;
+       return p;
+#endif
+}
+
+
+#ifdef DEBUG
+#ifndef        BOOT
+void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text)
+{
+       int     len ;
+       struct smt_para *pa ;
+       char    *c ;
+       int     n ;
+       int     nn ;
+#ifdef LITTLE_ENDIAN
+       int     smtlen ;
+#endif
+
+       SK_UNUSED(smc) ;
+
+#ifdef DEBUG_BRD
+       if (smc->debug.d_smtf < 2)
+#else
+       if (debug.d_smtf < 2)
+#endif
+               return ;
+#ifdef LITTLE_ENDIAN
+       smtlen = sm->smt_len + sizeof(struct smt_header) ;
+#endif
+       printf("SMT Frame [%s]:\nDA  ",text) ;
+       dump_hex((char *) &sm->smt_dest,6) ;
+       printf("\tSA ") ;
+       dump_hex((char *) &sm->smt_source,6) ;
+       printf(" Class %x Type %x Version %x\n",
+               sm->smt_class,sm->smt_type,sm->smt_version)  ;
+       printf("TID %lx\t\tSID ",sm->smt_tid) ;
+       dump_hex((char *) &sm->smt_sid,8) ;
+       printf(" LEN %x\n",sm->smt_len) ;
+
+       len = sm->smt_len ;
+       pa = (struct smt_para *) (sm + 1) ;
+       while (len > 0 ) {
+               int     plen ;
+#ifdef UNIX
+               printf("TYPE %x LEN %x VALUE\t",pa->p_type,pa->p_len) ;
+#else
+               printf("TYPE %04x LEN %2x VALUE\t",pa->p_type,pa->p_len) ;
+#endif
+               n = pa->p_len ;
+               if ( (n < 0 ) || (n > (int)(len - PARA_LEN))) {
+                       n = len - PARA_LEN ;
+                       printf(" BAD LENGTH\n") ;
+                       break ;
+               }
+#ifdef LITTLE_ENDIAN
+               smt_swap_para(sm,smtlen,0) ;
+#endif
+               if (n < 24) {
+                       dump_hex((char *)(pa+1),(int) n) ;
+                       printf("\n") ;
+               }
+               else {
+                       int     first = 0 ;
+                       c = (char *)(pa+1) ;
+                       dump_hex(c,16) ;
+                       printf("\n") ;
+                       n -= 16 ;
+                       c += 16 ;
+                       while (n > 0) {
+                               nn = (n > 16) ? 16 : n ;
+                               if (n > 64) {
+                                       if (first == 0)
+                                               printf("\t\t\t...\n") ;
+                                       first = 1 ;
+                               }
+                               else {
+                                       printf("\t\t\t") ;
+                                       dump_hex(c,nn) ;
+                                       printf("\n") ;
+                               }
+                               n -= nn ;
+                               c += 16 ;
+                       }
+               }
+#ifdef LITTLE_ENDIAN
+               smt_swap_para(sm,smtlen,1) ;
+#endif
+               plen = (pa->p_len + PARA_LEN + 3) & ~3 ;
+               len -= plen ;
+               pa = (struct smt_para *)((char *)pa + plen) ;
+       }
+       printf("-------------------------------------------------\n\n") ;
+}
+
+void dump_hex(char *p, int len)
+{
+       int     n = 0 ;
+       while (len--) {
+               n++ ;
+#ifdef UNIX
+               printf("%x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
+#else
+               printf("%02x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
+#endif
+       }
+}
+#endif /* no BOOT */
+#endif /* DEBUG */
+
+
+#endif /* no SLIM_SMT */
diff --git a/drivers/net/fddi/skfp/queue.c b/drivers/net/fddi/skfp/queue.c
new file mode 100644 (file)
index 0000000..c1a0df4
--- /dev/null
@@ -0,0 +1,173 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT Event Queue Management
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)queue.c     2.9 97/08/04 (C) SK " ;
+#endif
+
+#define PRINTF(a,b,c)
+
+/*
+ * init event queue management
+ */
+void ev_init(struct s_smc *smc)
+{
+       smc->q.ev_put = smc->q.ev_get = smc->q.ev_queue ;
+}
+
+/*
+ * add event to queue
+ */
+void queue_event(struct s_smc *smc, int class, int event)
+{
+       PRINTF("queue class %d event %d\n",class,event) ;
+       smc->q.ev_put->class = class ;
+       smc->q.ev_put->event = event ;
+       if (++smc->q.ev_put == &smc->q.ev_queue[MAX_EVENT])
+               smc->q.ev_put = smc->q.ev_queue ;
+
+       if (smc->q.ev_put == smc->q.ev_get) {
+               SMT_ERR_LOG(smc,SMT_E0137, SMT_E0137_MSG) ;
+       }
+}
+
+/*
+ * timer_event is called from HW timer package.
+ */
+void timer_event(struct s_smc *smc, u_long token)
+{
+       PRINTF("timer event class %d token %d\n",
+               EV_T_CLASS(token),
+               EV_T_EVENT(token)) ;
+       queue_event(smc,EV_T_CLASS(token),EV_T_EVENT(token));
+}
+
+/*
+ * event dispatcher
+ *     while event queue is not empty
+ *             get event from queue
+ *             send command to state machine
+ *     end
+ */
+void ev_dispatcher(struct s_smc *smc)
+{
+       struct event_queue *ev ;        /* pointer into queue */
+       int             class ;
+
+       ev = smc->q.ev_get ;
+       PRINTF("dispatch get %x put %x\n",ev,smc->q.ev_put) ;
+       while (ev != smc->q.ev_put) {
+               PRINTF("dispatch class %d event %d\n",ev->class,ev->event) ;
+               switch(class = ev->class) {
+               case EVENT_ECM :                /* Entity Corordination  Man. */
+                       ecm(smc,(int)ev->event) ;
+                       break ;
+               case EVENT_CFM :                /* Configuration Man. */
+                       cfm(smc,(int)ev->event) ;
+                       break ;
+               case EVENT_RMT :                /* Ring Man. */
+                       rmt(smc,(int)ev->event) ;
+                       break ;
+               case EVENT_SMT :
+                       smt_event(smc,(int)ev->event) ;
+                       break ;
+#ifdef CONCENTRATOR
+               case 99 :
+                       timer_test_event(smc,(int)ev->event) ;
+                       break ;
+#endif
+               case EVENT_PCMA :               /* PHY A */
+               case EVENT_PCMB :               /* PHY B */
+               default :
+                       if (class >= EVENT_PCMA &&
+                           class < EVENT_PCMA + NUMPHYS) {
+                               pcm(smc,class - EVENT_PCMA,(int)ev->event) ;
+                               break ;
+                       }
+                       SMT_PANIC(smc,SMT_E0121, SMT_E0121_MSG) ;
+                       return ;
+               }
+
+               if (++ev == &smc->q.ev_queue[MAX_EVENT])
+                       ev = smc->q.ev_queue ;
+
+               /* Renew get: it is used in queue_events to detect overruns */
+               smc->q.ev_get = ev;
+       }
+}
+
+/*
+ * smt_online connects to or disconnects from the ring
+ * MUST be called to initiate connection establishment
+ *
+ *     on      0       disconnect
+ *     on      1       connect
+ */
+u_short smt_online(struct s_smc *smc, int on)
+{
+       queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ;
+       ev_dispatcher(smc) ;
+       return smc->mib.fddiSMTCF_State;
+}
+
+/*
+ * set SMT flag to value
+ *     flag            flag name
+ *     value           flag value
+ * dump current flag setting
+ */
+#ifdef CONCENTRATOR
+void do_smt_flag(struct s_smc *smc, char *flag, int value)
+{
+#ifdef DEBUG
+       struct smt_debug        *deb;
+
+       SK_UNUSED(smc) ;
+
+#ifdef DEBUG_BRD
+       deb = &smc->debug;
+#else
+       deb = &debug;
+#endif
+       if (!strcmp(flag,"smt"))
+               deb->d_smt = value ;
+       else if (!strcmp(flag,"smtf"))
+               deb->d_smtf = value ;
+       else if (!strcmp(flag,"pcm"))
+               deb->d_pcm = value ;
+       else if (!strcmp(flag,"rmt"))
+               deb->d_rmt = value ;
+       else if (!strcmp(flag,"cfm"))
+               deb->d_cfm = value ;
+       else if (!strcmp(flag,"ecm"))
+               deb->d_ecm = value ;
+       printf("smt     %d\n",deb->d_smt) ;
+       printf("smtf    %d\n",deb->d_smtf) ;
+       printf("pcm     %d\n",deb->d_pcm) ;
+       printf("rmt     %d\n",deb->d_rmt) ;
+       printf("cfm     %d\n",deb->d_cfm) ;
+       printf("ecm     %d\n",deb->d_ecm) ;
+#endif /* DEBUG */
+}
+#endif
diff --git a/drivers/net/fddi/skfp/rmt.c b/drivers/net/fddi/skfp/rmt.c
new file mode 100644 (file)
index 0000000..ef8d567
--- /dev/null
@@ -0,0 +1,654 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT RMT
+       Ring Management
+*/
+
+/*
+ * Hardware independent state machine implemantation
+ * The following external SMT functions are referenced :
+ *
+ *             queue_event()
+ *             smt_timer_start()
+ *             smt_timer_stop()
+ *
+ *     The following external HW dependent functions are referenced :
+ *             sm_ma_control()
+ *             sm_mac_check_beacon_claim()
+ *
+ *     The following HW dependent events are required :
+ *             RM_RING_OP
+ *             RM_RING_NON_OP
+ *             RM_MY_BEACON
+ *             RM_OTHER_BEACON
+ *             RM_MY_CLAIM
+ *             RM_TRT_EXP
+ *             RM_VALID_CLAIM
+ *
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)rmt.c       2.13 99/07/02 (C) SK " ;
+#endif
+
+/*
+ * FSM Macros
+ */
+#define AFLAG  0x10
+#define GO_STATE(x)    (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG)
+#define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG)
+#define ACTIONS(x)     (x|AFLAG)
+
+#define RM0_ISOLATED   0
+#define RM1_NON_OP     1               /* not operational */
+#define RM2_RING_OP    2               /* ring operational */
+#define RM3_DETECT     3               /* detect dupl addresses */
+#define RM4_NON_OP_DUP 4               /* dupl. addr detected */
+#define RM5_RING_OP_DUP        5               /* ring oper. with dupl. addr */
+#define RM6_DIRECTED   6               /* sending directed beacons */
+#define RM7_TRACE      7               /* trace initiated */
+
+#ifdef DEBUG
+/*
+ * symbolic state names
+ */
+static const char * const rmt_states[] = {
+       "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT",
+       "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED",
+       "RM7_TRACE"
+} ;
+
+/*
+ * symbolic event names
+ */
+static const char * const rmt_events[] = {
+       "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON",
+       "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM",
+       "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG",
+       "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK",
+       "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT",
+       "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE"
+} ;
+#endif
+
+/*
+ * Globals
+ * in struct s_rmt
+ */
+
+
+/*
+ * function declarations
+ */
+static void rmt_fsm(struct s_smc *smc, int cmd);
+static void start_rmt_timer0(struct s_smc *smc, u_long value, int event);
+static void start_rmt_timer1(struct s_smc *smc, u_long value, int event);
+static void start_rmt_timer2(struct s_smc *smc, u_long value, int event);
+static void stop_rmt_timer0(struct s_smc *smc);
+static void stop_rmt_timer1(struct s_smc *smc);
+static void stop_rmt_timer2(struct s_smc *smc);
+static void rmt_dup_actions(struct s_smc *smc);
+static void rmt_reinsert_actions(struct s_smc *smc);
+static void rmt_leave_actions(struct s_smc *smc);
+static void rmt_new_dup_actions(struct s_smc *smc);
+
+#ifndef SUPERNET_3
+extern void restart_trt_for_dbcn() ;
+#endif /*SUPERNET_3*/
+
+/*
+       init RMT state machine
+       clear all RMT vars and flags
+*/
+void rmt_init(struct s_smc *smc)
+{
+       smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
+       smc->r.dup_addr_test = DA_NONE ;
+       smc->r.da_flag = 0 ;
+       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+       smc->r.sm_ma_avail = FALSE ;
+       smc->r.loop_avail = 0 ;
+       smc->r.bn_flag = 0 ;
+       smc->r.jm_flag = 0 ;
+       smc->r.no_flag = TRUE ;
+}
+
+/*
+       RMT state machine
+       called by dispatcher
+
+       do
+               display state change
+               process event
+       until SM is stable
+*/
+void rmt(struct s_smc *smc, int event)
+{
+       int     state ;
+
+       do {
+               DB_RMT("RMT : state %s%s",
+                       (smc->mib.m[MAC0].fddiMACRMTState & AFLAG) ? "ACTIONS " : "",
+                       rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG]) ;
+               DB_RMT(" event %s\n",rmt_events[event],0) ;
+               state = smc->mib.m[MAC0].fddiMACRMTState ;
+               rmt_fsm(smc,event) ;
+               event = 0 ;
+       } while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
+       rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ;
+}
+
+/*
+       process RMT event
+*/
+static void rmt_fsm(struct s_smc *smc, int cmd)
+{
+       /*
+        * RM00-RM70 : from all states
+        */
+       if (!smc->r.rm_join && !smc->r.rm_loop &&
+               smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
+               smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
+               RS_SET(smc,RS_NORINGOP) ;
+               rmt_indication(smc,0) ;
+               GO_STATE(RM0_ISOLATED) ;
+               return ;
+       }
+
+       switch(smc->mib.m[MAC0].fddiMACRMTState) {
+       case ACTIONS(RM0_ISOLATED) :
+               stop_rmt_timer0(smc) ;
+               stop_rmt_timer1(smc) ;
+               stop_rmt_timer2(smc) ;
+
+               /*
+                * Disable MAC.
+                */
+               sm_ma_control(smc,MA_OFFLINE) ;
+               smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+               smc->r.loop_avail = FALSE ;
+               smc->r.sm_ma_avail = FALSE ;
+               smc->r.no_flag = TRUE ;
+               DB_RMTN(1,"RMT : ISOLATED\n",0,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM0_ISOLATED :
+               /*RM01*/
+               if (smc->r.rm_join || smc->r.rm_loop) {
+                       /*
+                        * According to the standard the MAC must be reset
+                        * here. The FORMAC will be initialized and Claim
+                        * and Beacon Frames will be uploaded to the MAC.
+                        * So any change of Treq will take effect NOW.
+                        */
+                       sm_ma_control(smc,MA_RESET) ;
+                       GO_STATE(RM1_NON_OP) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM1_NON_OP) :
+               start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
+               stop_rmt_timer1(smc) ;
+               stop_rmt_timer2(smc) ;
+               sm_ma_control(smc,MA_BEACON) ;
+               DB_RMTN(1,"RMT : RING DOWN\n",0,0) ;
+               RS_SET(smc,RS_NORINGOP) ;
+               smc->r.sm_ma_avail = FALSE ;
+               rmt_indication(smc,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM1_NON_OP :
+               /*RM12*/
+               if (cmd == RM_RING_OP) {
+                       RS_SET(smc,RS_RINGOPCHANGE) ;
+                       GO_STATE(RM2_RING_OP) ;
+                       break ;
+               }
+               /*RM13*/
+               else if (cmd == RM_TIMEOUT_NON_OP) {
+                       smc->r.bn_flag = FALSE ;
+                       smc->r.no_flag = TRUE ;
+                       GO_STATE(RM3_DETECT) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM2_RING_OP) :
+               stop_rmt_timer0(smc) ;
+               stop_rmt_timer1(smc) ;
+               stop_rmt_timer2(smc) ;
+               smc->r.no_flag = FALSE ;
+               if (smc->r.rm_loop)
+                       smc->r.loop_avail = TRUE ;
+               if (smc->r.rm_join) {
+                       smc->r.sm_ma_avail = TRUE ;
+                       if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
+                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
+                               else
+                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+               }
+               DB_RMTN(1,"RMT : RING UP\n",0,0) ;
+               RS_CLEAR(smc,RS_NORINGOP) ;
+               RS_SET(smc,RS_RINGOPCHANGE) ;
+               rmt_indication(smc,1) ;
+               smt_stat_counter(smc,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM2_RING_OP :
+               /*RM21*/
+               if (cmd == RM_RING_NON_OP) {
+                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+                       smc->r.loop_avail = FALSE ;
+                       RS_SET(smc,RS_RINGOPCHANGE) ;
+                       GO_STATE(RM1_NON_OP) ;
+                       break ;
+               }
+               /*RM22a*/
+               else if (cmd == RM_ENABLE_FLAG) {
+                       if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
+                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
+                               else
+                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+               }
+               /*RM25*/
+               else if (smc->r.dup_addr_test == DA_FAILED) {
+                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
+                       smc->r.loop_avail = FALSE ;
+                       smc->r.da_flag = TRUE ;
+                       GO_STATE(RM5_RING_OP_DUP) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM3_DETECT) :
+               start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
+               start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
+               start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
+               sm_mac_check_beacon_claim(smc) ;
+               DB_RMTN(1,"RMT : RM3_DETECT\n",0,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM3_DETECT :
+               if (cmd == RM_TIMEOUT_POLL) {
+                       start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
+                       sm_mac_check_beacon_claim(smc) ;
+                       break ;
+               }
+               if (cmd == RM_TIMEOUT_D_MAX) {
+                       smc->r.timer0_exp = TRUE ;
+               }
+               /*
+                *jd(22-Feb-1999)
+                * We need a time ">= 2*mac_d_max" since we had finished
+                * Claim or Beacon state. So we will restart timer0 at
+                * every state change.
+                */
+               if (cmd == RM_TX_STATE_CHANGE) {
+                       start_rmt_timer0(smc,
+                                        smc->s.mac_d_max*2,
+                                        RM_TIMEOUT_D_MAX) ;
+               }
+               /*RM32*/
+               if (cmd == RM_RING_OP) {
+                       GO_STATE(RM2_RING_OP) ;
+                       break ;
+               }
+               /*RM33a*/
+               else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
+                       && smc->r.bn_flag) {
+                       smc->r.bn_flag = FALSE ;
+               }
+               /*RM33b*/
+               else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
+                       int     tx ;
+                       /*
+                        * set bn_flag only if in state T4 or T5:
+                        * only if we're the beaconer should we start the
+                        * trace !
+                        */
+                       if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
+                       DB_RMTN(2,"RMT : DETECT && TRT_EXPIRED && T4/T5\n",0,0);
+                               smc->r.bn_flag = TRUE ;
+                               /*
+                                * If one of the upstream stations beaconed
+                                * and the link to the upstream neighbor is
+                                * lost we need to restart the stuck timer to
+                                * check the "stuck beacon" condition.
+                                */
+                               start_rmt_timer1(smc,smc->s.rmt_t_stuck,
+                                       RM_TIMEOUT_T_STUCK) ;
+                       }
+                       /*
+                        * We do NOT need to clear smc->r.bn_flag in case of
+                        * not being in state T4 or T5, because the flag
+                        * must be cleared in order to get in this condition.
+                        */
+
+                       DB_RMTN(2,
+                       "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
+                       tx,smc->r.bn_flag) ;
+               }
+               /*RM34a*/
+               else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
+                       rmt_new_dup_actions(smc) ;
+                       GO_STATE(RM4_NON_OP_DUP) ;
+                       break ;
+               }
+               /*RM34b*/
+               else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
+                       rmt_new_dup_actions(smc) ;
+                       GO_STATE(RM4_NON_OP_DUP) ;
+                       break ;
+               }
+               /*RM34c*/
+               else if (cmd == RM_VALID_CLAIM) {
+                       rmt_new_dup_actions(smc) ;
+                       GO_STATE(RM4_NON_OP_DUP) ;
+                       break ;
+               }
+               /*RM36*/
+               else if (cmd == RM_TIMEOUT_T_STUCK &&
+                       smc->r.rm_join && smc->r.bn_flag) {
+                       GO_STATE(RM6_DIRECTED) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM4_NON_OP_DUP) :
+               start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
+               start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
+               start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
+               sm_mac_check_beacon_claim(smc) ;
+               DB_RMTN(1,"RMT : RM4_NON_OP_DUP\n",0,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM4_NON_OP_DUP :
+               if (cmd == RM_TIMEOUT_POLL) {
+                       start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
+                       sm_mac_check_beacon_claim(smc) ;
+                       break ;
+               }
+               /*RM41*/
+               if (!smc->r.da_flag) {
+                       GO_STATE(RM1_NON_OP) ;
+                       break ;
+               }
+               /*RM44a*/
+               else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
+                       smc->r.bn_flag) {
+                       smc->r.bn_flag = FALSE ;
+               }
+               /*RM44b*/
+               else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
+                       int     tx ;
+                       /*
+                        * set bn_flag only if in state T4 or T5:
+                        * only if we're the beaconer should we start the
+                        * trace !
+                        */
+                       if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
+                       DB_RMTN(2,"RMT : NOPDUP && TRT_EXPIRED && T4/T5\n",0,0);
+                               smc->r.bn_flag = TRUE ;
+                               /*
+                                * If one of the upstream stations beaconed
+                                * and the link to the upstream neighbor is
+                                * lost we need to restart the stuck timer to
+                                * check the "stuck beacon" condition.
+                                */
+                               start_rmt_timer1(smc,smc->s.rmt_t_stuck,
+                                       RM_TIMEOUT_T_STUCK) ;
+                       }
+                       /*
+                        * We do NOT need to clear smc->r.bn_flag in case of
+                        * not being in state T4 or T5, because the flag
+                        * must be cleared in order to get in this condition.
+                        */
+
+                       DB_RMTN(2,
+                       "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
+                       tx,smc->r.bn_flag) ;
+               }
+               /*RM44c*/
+               else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
+                       rmt_dup_actions(smc) ;
+               }
+               /*RM45*/
+               else if (cmd == RM_RING_OP) {
+                       smc->r.no_flag = FALSE ;
+                       GO_STATE(RM5_RING_OP_DUP) ;
+                       break ;
+               }
+               /*RM46*/
+               else if (cmd == RM_TIMEOUT_T_STUCK &&
+                       smc->r.rm_join && smc->r.bn_flag) {
+                       GO_STATE(RM6_DIRECTED) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM5_RING_OP_DUP) :
+               stop_rmt_timer0(smc) ;
+               stop_rmt_timer1(smc) ;
+               stop_rmt_timer2(smc) ;
+               DB_RMTN(1,"RMT : RM5_RING_OP_DUP\n",0,0) ;
+               ACTIONS_DONE() ;
+               break;
+       case RM5_RING_OP_DUP :
+               /*RM52*/
+               if (smc->r.dup_addr_test == DA_PASSED) {
+                       smc->r.da_flag = FALSE ;
+                       GO_STATE(RM2_RING_OP) ;
+                       break ;
+               }
+               /*RM54*/
+               else if (cmd == RM_RING_NON_OP) {
+                       smc->r.jm_flag = FALSE ;
+                       smc->r.bn_flag = FALSE ;
+                       GO_STATE(RM4_NON_OP_DUP) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM6_DIRECTED) :
+               start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
+               stop_rmt_timer1(smc) ;
+               start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
+               sm_ma_control(smc,MA_DIRECTED) ;
+               RS_SET(smc,RS_BEACON) ;
+               DB_RMTN(1,"RMT : RM6_DIRECTED\n",0,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM6_DIRECTED :
+               /*RM63*/
+               if (cmd == RM_TIMEOUT_POLL) {
+                       start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
+                       sm_mac_check_beacon_claim(smc) ;
+#ifndef SUPERNET_3
+                       /* Because of problems with the Supernet II chip set
+                        * sending of Directed Beacon will stop after 165ms
+                        * therefore restart_trt_for_dbcn(smc) will be called
+                        * to prevent this.
+                        */
+                       restart_trt_for_dbcn(smc) ;
+#endif /*SUPERNET_3*/
+                       break ;
+               }
+               if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
+                       !smc->r.da_flag) {
+                       smc->r.bn_flag = FALSE ;
+                       GO_STATE(RM3_DETECT) ;
+                       break ;
+               }
+               /*RM64*/
+               else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
+                       smc->r.da_flag) {
+                       smc->r.bn_flag = FALSE ;
+                       GO_STATE(RM4_NON_OP_DUP) ;
+                       break ;
+               }
+               /*RM67*/
+               else if (cmd == RM_TIMEOUT_T_DIRECT) {
+                       GO_STATE(RM7_TRACE) ;
+                       break ;
+               }
+               break ;
+       case ACTIONS(RM7_TRACE) :
+               stop_rmt_timer0(smc) ;
+               stop_rmt_timer1(smc) ;
+               stop_rmt_timer2(smc) ;
+               smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
+               queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
+               DB_RMTN(1,"RMT : RM7_TRACE\n",0,0) ;
+               ACTIONS_DONE() ;
+               break ;
+       case RM7_TRACE :
+               break ;
+       default:
+               SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
+               break;
+       }
+}
+
+/*
+ * (jd) RMT duplicate address actions
+ * leave the ring or reinsert just as configured
+ */
+static void rmt_dup_actions(struct s_smc *smc)
+{
+       if (smc->r.jm_flag) {
+       }
+       else {
+               if (smc->s.rmt_dup_mac_behavior) {
+                       SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
+                        rmt_reinsert_actions(smc) ;
+               }
+               else {
+                       SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
+                       rmt_leave_actions(smc) ;
+               }
+       }
+}
+
+/*
+ * Reconnect to the Ring
+ */
+static void rmt_reinsert_actions(struct s_smc *smc)
+{
+       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+       queue_event(smc,EVENT_ECM,EC_CONNECT) ;
+}
+
+/*
+ * duplicate address detected
+ */
+static void rmt_new_dup_actions(struct s_smc *smc)
+{
+       smc->r.da_flag = TRUE ;
+       smc->r.bn_flag = FALSE ;
+       smc->r.jm_flag = FALSE ;
+       /*
+        * we have three options : change address, jam or leave
+        * we leave the ring as default 
+        * Optionally it's possible to reinsert after leaving the Ring
+        * but this will not conform with SMT Spec.
+        */
+       if (smc->s.rmt_dup_mac_behavior) {
+               SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
+               rmt_reinsert_actions(smc) ;
+       }
+       else {
+               SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
+               rmt_leave_actions(smc) ;
+       }
+}
+
+
+/*
+ * leave the ring
+ */
+static void rmt_leave_actions(struct s_smc *smc)
+{
+       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+       /*
+        * Note: Do NOT try again later. (with please reconnect)
+        * The station must be left from the ring!
+        */
+}
+
+/*
+ * SMT timer interface
+ *     start RMT timer 0
+ */
+static void start_rmt_timer0(struct s_smc *smc, u_long value, int event)
+{
+       smc->r.timer0_exp = FALSE ;             /* clear timer event flag */
+       smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
+}
+
+/*
+ * SMT timer interface
+ *     start RMT timer 1
+ */
+static void start_rmt_timer1(struct s_smc *smc, u_long value, int event)
+{
+       smc->r.timer1_exp = FALSE ;     /* clear timer event flag */
+       smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
+}
+
+/*
+ * SMT timer interface
+ *     start RMT timer 2
+ */
+static void start_rmt_timer2(struct s_smc *smc, u_long value, int event)
+{
+       smc->r.timer2_exp = FALSE ;             /* clear timer event flag */
+       smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
+}
+
+/*
+ * SMT timer interface
+ *     stop RMT timer 0
+ */
+static void stop_rmt_timer0(struct s_smc *smc)
+{
+       if (smc->r.rmt_timer0.tm_active)
+               smt_timer_stop(smc,&smc->r.rmt_timer0) ;
+}
+
+/*
+ * SMT timer interface
+ *     stop RMT timer 1
+ */
+static void stop_rmt_timer1(struct s_smc *smc)
+{
+       if (smc->r.rmt_timer1.tm_active)
+               smt_timer_stop(smc,&smc->r.rmt_timer1) ;
+}
+
+/*
+ * SMT timer interface
+ *     stop RMT timer 2
+ */
+static void stop_rmt_timer2(struct s_smc *smc)
+{
+       if (smc->r.rmt_timer2.tm_active)
+               smt_timer_stop(smc,&smc->r.rmt_timer2) ;
+}
+
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
new file mode 100644 (file)
index 0000000..3d9a459
--- /dev/null
@@ -0,0 +1,2260 @@
+/*
+ * File Name:
+ *   skfddi.c
+ *
+ * Copyright Information:
+ *   Copyright SysKonnect 1998,1999.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ * Abstract:
+ *   A Linux device driver supporting the SysKonnect FDDI PCI controller
+ *   familie.
+ *
+ * Maintainers:
+ *   CG    Christoph Goos (cgoos@syskonnect.de)
+ *
+ * Contributors:
+ *   DM    David S. Miller
+ *
+ * Address all question to:
+ *   linux@syskonnect.de
+ *
+ * The technical manual for the adapters is available from SysKonnect's
+ * web pages: www.syskonnect.com
+ * Goto "Support" and search Knowledge Base for "manual".
+ *
+ * Driver Architecture:
+ *   The driver architecture is based on the DEC FDDI driver by
+ *   Lawrence V. Stefani and several ethernet drivers.
+ *   I also used an existing Windows NT miniport driver.
+ *   All hardware dependent functions are handled by the SysKonnect
+ *   Hardware Module.
+ *   The only headerfiles that are directly related to this source
+ *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h.
+ *   The others belong to the SysKonnect FDDI Hardware Module and
+ *   should better not be changed.
+ *
+ * Modification History:
+ *              Date            Name    Description
+ *              02-Mar-98       CG     Created.
+ *
+ *             10-Mar-99       CG      Support for 2.2.x added.
+ *             25-Mar-99       CG      Corrected IRQ routing for SMP (APIC)
+ *             26-Oct-99       CG      Fixed compilation error on 2.2.13
+ *             12-Nov-99       CG      Source code release
+ *             22-Nov-99       CG      Included in kernel source.
+ *             07-May-00       DM      64 bit fixes, new dma interface
+ *             31-Jul-03       DB      Audit copy_*_user in skfp_ioctl
+ *                                       Daniele Bellucci <bellucda@tiscali.it>
+ *             03-Dec-03       SH      Convert to PCI device model
+ *
+ * Compilation options (-Dxxx):
+ *              DRIVERDEBUG     print lots of messages to log file
+ *              DUMPPACKETS     print received/transmitted packets to logfile
+ * 
+ * Tested cpu architectures:
+ *     - i386
+ *     - sparc64
+ */
+
+/* Version information string - should be updated prior to */
+/* each new release!!! */
+#define VERSION                "2.07"
+
+static const char * const boot_msg = 
+       "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
+       "  SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)";
+
+/* Include files */
+
+#include <linux/capability.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/gfp.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include       "h/types.h"
+#undef ADDR                    // undo Linux definition
+#include       "h/skfbi.h"
+#include       "h/fddi.h"
+#include       "h/smc.h"
+#include       "h/smtstate.h"
+
+
+// Define module-wide (static) routines
+static int skfp_driver_init(struct net_device *dev);
+static int skfp_open(struct net_device *dev);
+static int skfp_close(struct net_device *dev);
+static irqreturn_t skfp_interrupt(int irq, void *dev_id);
+static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev);
+static void skfp_ctl_set_multicast_list(struct net_device *dev);
+static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);
+static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr);
+static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
+                                      struct net_device *dev);
+static void send_queued_packets(struct s_smc *smc);
+static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr);
+static void ResetAdapter(struct s_smc *smc);
+
+
+// Functions needed by the hardware module
+void *mac_drv_get_space(struct s_smc *smc, u_int size);
+void *mac_drv_get_desc_mem(struct s_smc *smc, u_int size);
+unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt);
+unsigned long dma_master(struct s_smc *smc, void *virt, int len, int flag);
+void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
+                 int flag);
+void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd);
+void llc_restart_tx(struct s_smc *smc);
+void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+                        int frag_count, int len);
+void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+                        int frag_count);
+void mac_drv_fill_rxd(struct s_smc *smc);
+void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+                      int frag_count);
+int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
+                   int la_len);
+void dump_data(unsigned char *Data, int length);
+
+// External functions from the hardware module
+extern u_int mac_drv_check_space(void);
+extern int mac_drv_init(struct s_smc *smc);
+extern void hwm_tx_frag(struct s_smc *smc, char far * virt, u_long phys,
+                       int len, int frame_status);
+extern int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count,
+                      int frame_len, int frame_status);
+extern void fddi_isr(struct s_smc *smc);
+extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,
+                       int len, int frame_status);
+extern void mac_drv_rx_mode(struct s_smc *smc, int mode);
+extern void mac_drv_clear_rx_queue(struct s_smc *smc);
+extern void enable_tx_irq(struct s_smc *smc, u_short queue);
+
+static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = {
+       { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },
+       { }                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, skfddi_pci_tbl);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
+
+// Define module-wide (static) variables
+
+static int num_boards; /* total number of adapters configured */
+
+static const struct net_device_ops skfp_netdev_ops = {
+       .ndo_open               = skfp_open,
+       .ndo_stop               = skfp_close,
+       .ndo_start_xmit         = skfp_send_pkt,
+       .ndo_get_stats          = skfp_ctl_get_stats,
+       .ndo_change_mtu         = fddi_change_mtu,
+       .ndo_set_rx_mode        = skfp_ctl_set_multicast_list,
+       .ndo_set_mac_address    = skfp_ctl_set_mac_address,
+       .ndo_do_ioctl           = skfp_ioctl,
+};
+
+/*
+ * =================
+ * = skfp_init_one =
+ * =================
+ *   
+ * Overview:
+ *   Probes for supported FDDI PCI controllers
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   pdev - pointer to PCI device information
+ *
+ * Functional Description:
+ *   This is now called by PCI driver registration process
+ *   for each board found.
+ *   
+ * Return Codes:
+ *   0           - This device (fddi0, fddi1, etc) configured successfully
+ *   -ENODEV - No devices present, or no SysKonnect FDDI PCI device
+ *                         present for this device name
+ *
+ *
+ * Side Effects:
+ *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ *   initialized and the board resources are read and stored in
+ *   the device structure.
+ */
+static int skfp_init_one(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
+{
+       struct net_device *dev;
+       struct s_smc *smc;      /* board pointer */
+       void __iomem *mem;
+       int err;
+
+       pr_debug("entering skfp_init_one\n");
+
+       if (num_boards == 0) 
+               printk("%s\n", boot_msg);
+
+       err = pci_enable_device(pdev);
+       if (err)
+               return err;
+
+       err = pci_request_regions(pdev, "skfddi");
+       if (err)
+               goto err_out1;
+
+       pci_set_master(pdev);
+
+#ifdef MEM_MAPPED_IO
+       if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+               printk(KERN_ERR "skfp: region is not an MMIO resource\n");
+               err = -EIO;
+               goto err_out2;
+       }
+
+       mem = ioremap(pci_resource_start(pdev, 0), 0x4000);
+#else
+       if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) {
+               printk(KERN_ERR "skfp: region is not PIO resource\n");
+               err = -EIO;
+               goto err_out2;
+       }
+
+       mem = ioport_map(pci_resource_start(pdev, 1), FP_IO_LEN);
+#endif
+       if (!mem) {
+               printk(KERN_ERR "skfp:  Unable to map register, "
+                               "FDDI adapter will be disabled.\n");
+               err = -EIO;
+               goto err_out2;
+       }
+
+       dev = alloc_fddidev(sizeof(struct s_smc));
+       if (!dev) {
+               printk(KERN_ERR "skfp: Unable to allocate fddi device, "
+                               "FDDI adapter will be disabled.\n");
+               err = -ENOMEM;
+               goto err_out3;
+       }
+
+       dev->irq = pdev->irq;
+       dev->netdev_ops = &skfp_netdev_ops;
+
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       /* Initialize board structure with bus-specific info */
+       smc = netdev_priv(dev);
+       smc->os.dev = dev;
+       smc->os.bus_type = SK_BUS_TYPE_PCI;
+       smc->os.pdev = *pdev;
+       smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
+       smc->os.MaxFrameSize = MAX_FRAME_SIZE;
+       smc->os.dev = dev;
+       smc->hw.slot = -1;
+       smc->hw.iop = mem;
+       smc->os.ResetRequested = FALSE;
+       skb_queue_head_init(&smc->os.SendSkbQueue);
+
+       dev->base_addr = (unsigned long)mem;
+
+       err = skfp_driver_init(dev);
+       if (err)
+               goto err_out4;
+
+       err = register_netdev(dev);
+       if (err)
+               goto err_out5;
+
+       ++num_boards;
+       pci_set_drvdata(pdev, dev);
+
+       if ((pdev->subsystem_device & 0xff00) == 0x5500 ||
+           (pdev->subsystem_device & 0xff00) == 0x5800) 
+               printk("%s: SysKonnect FDDI PCI adapter"
+                      " found (SK-%04X)\n", dev->name, 
+                      pdev->subsystem_device);
+       else
+               printk("%s: FDDI PCI adapter found\n", dev->name);
+
+       return 0;
+err_out5:
+       if (smc->os.SharedMemAddr) 
+               pci_free_consistent(pdev, smc->os.SharedMemSize,
+                                   smc->os.SharedMemAddr, 
+                                   smc->os.SharedMemDMA);
+       pci_free_consistent(pdev, MAX_FRAME_SIZE,
+                           smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
+err_out4:
+       free_netdev(dev);
+err_out3:
+#ifdef MEM_MAPPED_IO
+       iounmap(mem);
+#else
+       ioport_unmap(mem);
+#endif
+err_out2:
+       pci_release_regions(pdev);
+err_out1:
+       pci_disable_device(pdev);
+       return err;
+}
+
+/*
+ * Called for each adapter board from pci_unregister_driver
+ */
+static void __devexit skfp_remove_one(struct pci_dev *pdev)
+{
+       struct net_device *p = pci_get_drvdata(pdev);
+       struct s_smc *lp = netdev_priv(p);
+
+       unregister_netdev(p);
+
+       if (lp->os.SharedMemAddr) {
+               pci_free_consistent(&lp->os.pdev,
+                                   lp->os.SharedMemSize,
+                                   lp->os.SharedMemAddr,
+                                   lp->os.SharedMemDMA);
+               lp->os.SharedMemAddr = NULL;
+       }
+       if (lp->os.LocalRxBuffer) {
+               pci_free_consistent(&lp->os.pdev,
+                                   MAX_FRAME_SIZE,
+                                   lp->os.LocalRxBuffer,
+                                   lp->os.LocalRxBufferDMA);
+               lp->os.LocalRxBuffer = NULL;
+       }
+#ifdef MEM_MAPPED_IO
+       iounmap(lp->hw.iop);
+#else
+       ioport_unmap(lp->hw.iop);
+#endif
+       pci_release_regions(pdev);
+       free_netdev(p);
+
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+/*
+ * ====================
+ * = skfp_driver_init =
+ * ====================
+ *   
+ * Overview:
+ *   Initializes remaining adapter board structure information
+ *   and makes sure adapter is in a safe state prior to skfp_open().
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This function allocates additional resources such as the host memory
+ *   blocks needed by the adapter.
+ *   The adapter is also reset. The OS must call skfp_open() to open 
+ *   the adapter and bring it on-line.
+ *
+ * Return Codes:
+ *    0 - initialization succeeded
+ *   -1 - initialization failed
+ */
+static  int skfp_driver_init(struct net_device *dev)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       skfddi_priv *bp = &smc->os;
+       int err = -EIO;
+
+       pr_debug("entering skfp_driver_init\n");
+
+       // set the io address in private structures
+       bp->base_addr = dev->base_addr;
+
+       // Get the interrupt level from the PCI Configuration Table
+       smc->hw.irq = dev->irq;
+
+       spin_lock_init(&bp->DriverLock);
+       
+       // Allocate invalid frame
+       bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA);
+       if (!bp->LocalRxBuffer) {
+               printk("could not allocate mem for ");
+               printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE);
+               goto fail;
+       }
+
+       // Determine the required size of the 'shared' memory area.
+       bp->SharedMemSize = mac_drv_check_space();
+       pr_debug("Memory for HWM: %ld\n", bp->SharedMemSize);
+       if (bp->SharedMemSize > 0) {
+               bp->SharedMemSize += 16;        // for descriptor alignment
+
+               bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
+                                                        bp->SharedMemSize,
+                                                        &bp->SharedMemDMA);
+               if (!bp->SharedMemAddr) {
+                       printk("could not allocate mem for ");
+                       printk("hardware module: %ld byte\n",
+                              bp->SharedMemSize);
+                       goto fail;
+               }
+               bp->SharedMemHeap = 0;  // Nothing used yet.
+
+       } else {
+               bp->SharedMemAddr = NULL;
+               bp->SharedMemHeap = 0;
+       }                       // SharedMemSize > 0
+
+       memset(bp->SharedMemAddr, 0, bp->SharedMemSize);
+
+       card_stop(smc);         // Reset adapter.
+
+       pr_debug("mac_drv_init()..\n");
+       if (mac_drv_init(smc) != 0) {
+               pr_debug("mac_drv_init() failed\n");
+               goto fail;
+       }
+       read_address(smc, NULL);
+       pr_debug("HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
+       memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
+
+       smt_reset_defaults(smc, 0);
+
+       return 0;
+
+fail:
+       if (bp->SharedMemAddr) {
+               pci_free_consistent(&bp->pdev,
+                                   bp->SharedMemSize,
+                                   bp->SharedMemAddr,
+                                   bp->SharedMemDMA);
+               bp->SharedMemAddr = NULL;
+       }
+       if (bp->LocalRxBuffer) {
+               pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE,
+                                   bp->LocalRxBuffer, bp->LocalRxBufferDMA);
+               bp->LocalRxBuffer = NULL;
+       }
+       return err;
+}                              // skfp_driver_init
+
+
+/*
+ * =============
+ * = skfp_open =
+ * =============
+ *   
+ * Overview:
+ *   Opens the adapter
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This function brings the adapter to an operational state.
+ *
+ * Return Codes:
+ *   0           - Adapter was successfully opened
+ *   -EAGAIN - Could not register IRQ
+ */
+static int skfp_open(struct net_device *dev)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       int err;
+
+       pr_debug("entering skfp_open\n");
+       /* Register IRQ - support shared interrupts by passing device ptr */
+       err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
+                         dev->name, dev);
+       if (err)
+               return err;
+
+       /*
+        * Set current address to factory MAC address
+        *
+        * Note: We've already done this step in skfp_driver_init.
+        *       However, it's possible that a user has set a node
+        *               address override, then closed and reopened the
+        *               adapter.  Unless we reset the device address field
+        *               now, we'll continue to use the existing modified
+        *               address.
+        */
+       read_address(smc, NULL);
+       memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
+
+       init_smt(smc, NULL);
+       smt_online(smc, 1);
+       STI_FBI();
+
+       /* Clear local multicast address tables */
+       mac_clear_multicast(smc);
+
+       /* Disable promiscuous filter settings */
+       mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
+
+       netif_start_queue(dev);
+       return 0;
+}                              // skfp_open
+
+
+/*
+ * ==============
+ * = skfp_close =
+ * ==============
+ *   
+ * Overview:
+ *   Closes the device/module.
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This routine closes the adapter and brings it to a safe state.
+ *   The interrupt service routine is deregistered with the OS.
+ *   The adapter can be opened again with another call to skfp_open().
+ *
+ * Return Codes:
+ *   Always return 0.
+ *
+ * Assumptions:
+ *   No further requests for this adapter are made after this routine is
+ *   called.  skfp_open() can be called to reset and reinitialize the
+ *   adapter.
+ */
+static int skfp_close(struct net_device *dev)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       skfddi_priv *bp = &smc->os;
+
+       CLI_FBI();
+       smt_reset_defaults(smc, 1);
+       card_stop(smc);
+       mac_drv_clear_tx_queue(smc);
+       mac_drv_clear_rx_queue(smc);
+
+       netif_stop_queue(dev);
+       /* Deregister (free) IRQ */
+       free_irq(dev->irq, dev);
+
+       skb_queue_purge(&bp->SendSkbQueue);
+       bp->QueueSkb = MAX_TX_QUEUE_LEN;
+
+       return 0;
+}                              // skfp_close
+
+
+/*
+ * ==================
+ * = skfp_interrupt =
+ * ==================
+ *   
+ * Overview:
+ *   Interrupt processing routine
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   irq        - interrupt vector
+ *   dev_id     - pointer to device information
+ *
+ * Functional Description:
+ *   This routine calls the interrupt processing routine for this adapter.  It
+ *   disables and reenables adapter interrupts, as appropriate.  We can support
+ *   shared interrupts since the incoming dev_id pointer provides our device
+ *   structure context. All the real work is done in the hardware module.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
+ *   on Intel-based systems) is done by the operating system outside this
+ *   routine.
+ *
+ *       System interrupts are enabled through this call.
+ *
+ * Side Effects:
+ *   Interrupts are disabled, then reenabled at the adapter.
+ */
+
+static irqreturn_t skfp_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct s_smc *smc;      /* private board structure pointer */
+       skfddi_priv *bp;
+
+       smc = netdev_priv(dev);
+       bp = &smc->os;
+
+       // IRQs enabled or disabled ?
+       if (inpd(ADDR(B0_IMSK)) == 0) {
+               // IRQs are disabled: must be shared interrupt
+               return IRQ_NONE;
+       }
+       // Note: At this point, IRQs are enabled.
+       if ((inpd(ISR_A) & smc->hw.is_imask) == 0) {    // IRQ?
+               // Adapter did not issue an IRQ: must be shared interrupt
+               return IRQ_NONE;
+       }
+       CLI_FBI();              // Disable IRQs from our adapter.
+       spin_lock(&bp->DriverLock);
+
+       // Call interrupt handler in hardware module (HWM).
+       fddi_isr(smc);
+
+       if (smc->os.ResetRequested) {
+               ResetAdapter(smc);
+               smc->os.ResetRequested = FALSE;
+       }
+       spin_unlock(&bp->DriverLock);
+       STI_FBI();              // Enable IRQs from our adapter.
+
+       return IRQ_HANDLED;
+}                              // skfp_interrupt
+
+
+/*
+ * ======================
+ * = skfp_ctl_get_stats =
+ * ======================
+ *   
+ * Overview:
+ *   Get statistics for FDDI adapter
+ *  
+ * Returns:
+ *   Pointer to FDDI statistics structure
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Gets current MIB objects from adapter, then
+ *   returns FDDI statistics structure as defined
+ *   in if_fddi.h.
+ *
+ *   Note: Since the FDDI statistics structure is
+ *   still new and the device structure doesn't
+ *   have an FDDI-specific get statistics handler,
+ *   we'll return the FDDI statistics structure as
+ *   a pointer to an Ethernet statistics structure.
+ *   That way, at least the first part of the statistics
+ *   structure can be decoded properly.
+ *   We'll have to pay attention to this routine as the
+ *   device structure becomes more mature and LAN media
+ *   independent.
+ *
+ */
+static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev)
+{
+       struct s_smc *bp = netdev_priv(dev);
+
+       /* Fill the bp->stats structure with driver-maintained counters */
+
+       bp->os.MacStat.port_bs_flag[0] = 0x1234;
+       bp->os.MacStat.port_bs_flag[1] = 0x5678;
+// goos: need to fill out fddi statistic
+#if 0
+       /* Get FDDI SMT MIB objects */
+
+/* Fill the bp->stats structure with the SMT MIB object values */
+
+       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));
+       bp->stats.smt_op_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
+       bp->stats.smt_hi_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
+       bp->stats.smt_lo_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
+       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));
+       bp->stats.smt_mib_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
+       bp->stats.smt_mac_cts = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
+       bp->stats.smt_non_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
+       bp->stats.smt_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
+       bp->stats.smt_available_paths = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
+       bp->stats.smt_config_capabilities = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
+       bp->stats.smt_config_policy = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
+       bp->stats.smt_connection_policy = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
+       bp->stats.smt_t_notify = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
+       bp->stats.smt_stat_rpt_policy = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
+       bp->stats.smt_trace_max_expiration = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
+       bp->stats.smt_bypass_present = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
+       bp->stats.smt_ecm_state = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
+       bp->stats.smt_cf_state = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
+       bp->stats.smt_remote_disconnect_flag = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
+       bp->stats.smt_station_status = bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
+       bp->stats.smt_peer_wrap_flag = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
+       bp->stats.smt_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
+       bp->stats.smt_transition_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
+       bp->stats.mac_frame_status_functions = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
+       bp->stats.mac_t_max_capability = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
+       bp->stats.mac_tvx_capability = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
+       bp->stats.mac_available_paths = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
+       bp->stats.mac_current_path = bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
+       memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
+       memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
+       memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
+       memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
+       bp->stats.mac_dup_address_test = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
+       bp->stats.mac_requested_paths = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
+       bp->stats.mac_downstream_port_type = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
+       memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
+       bp->stats.mac_t_req = bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
+       bp->stats.mac_t_neg = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
+       bp->stats.mac_t_max = bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
+       bp->stats.mac_tvx_value = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
+       bp->stats.mac_frame_error_threshold = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
+       bp->stats.mac_frame_error_ratio = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
+       bp->stats.mac_rmt_state = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
+       bp->stats.mac_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
+       bp->stats.mac_una_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
+       bp->stats.mac_frame_error_flag = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
+       bp->stats.mac_ma_unitdata_available = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
+       bp->stats.mac_hardware_present = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
+       bp->stats.mac_ma_unitdata_enable = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
+       bp->stats.path_tvx_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
+       bp->stats.path_t_max_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
+       bp->stats.path_max_t_req = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
+       memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
+       bp->stats.port_my_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
+       bp->stats.port_my_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
+       bp->stats.port_neighbor_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
+       bp->stats.port_neighbor_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
+       bp->stats.port_connection_policies[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
+       bp->stats.port_connection_policies[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
+       bp->stats.port_mac_indicated[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
+       bp->stats.port_mac_indicated[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
+       bp->stats.port_current_path[0] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
+       bp->stats.port_current_path[1] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
+       memcpy(&bp->stats.port_requested_paths[0 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
+       memcpy(&bp->stats.port_requested_paths[1 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
+       bp->stats.port_mac_placement[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
+       bp->stats.port_mac_placement[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
+       bp->stats.port_available_paths[0] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
+       bp->stats.port_available_paths[1] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
+       bp->stats.port_pmd_class[0] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
+       bp->stats.port_pmd_class[1] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
+       bp->stats.port_connection_capabilities[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
+       bp->stats.port_connection_capabilities[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
+       bp->stats.port_bs_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
+       bp->stats.port_bs_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
+       bp->stats.port_ler_estimate[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
+       bp->stats.port_ler_estimate[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
+       bp->stats.port_ler_cutoff[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
+       bp->stats.port_ler_cutoff[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
+       bp->stats.port_ler_alarm[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
+       bp->stats.port_ler_alarm[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
+       bp->stats.port_connect_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
+       bp->stats.port_connect_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
+       bp->stats.port_pcm_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
+       bp->stats.port_pcm_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
+       bp->stats.port_pc_withhold[0] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
+       bp->stats.port_pc_withhold[1] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
+       bp->stats.port_ler_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
+       bp->stats.port_ler_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
+       bp->stats.port_hardware_present[0] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
+       bp->stats.port_hardware_present[1] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
+
+
+       /* Fill the bp->stats structure with the FDDI counter values */
+
+       bp->stats.mac_frame_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
+       bp->stats.mac_copied_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
+       bp->stats.mac_transmit_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
+       bp->stats.mac_error_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
+       bp->stats.mac_lost_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
+       bp->stats.port_lct_fail_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
+       bp->stats.port_lct_fail_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
+       bp->stats.port_lem_reject_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
+       bp->stats.port_lem_reject_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
+       bp->stats.port_lem_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
+       bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
+
+#endif
+       return (struct net_device_stats *)&bp->os.MacStat;
+}                              // ctl_get_stat
+
+
+/*
+ * ==============================
+ * = skfp_ctl_set_multicast_list =
+ * ==============================
+ *   
+ * Overview:
+ *   Enable/Disable LLC frame promiscuous mode reception
+ *   on the adapter and/or update multicast address table.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This function acquires the driver lock and only calls
+ *   skfp_ctl_set_multicast_list_wo_lock then.
+ *   This routine follows a fairly simple algorithm for setting the
+ *   adapter filters and CAM:
+ *
+ *      if IFF_PROMISC flag is set
+ *              enable promiscuous mode
+ *      else
+ *              disable promiscuous mode
+ *              if number of multicast addresses <= max. multicast number
+ *                      add mc addresses to adapter table
+ *              else
+ *                      enable promiscuous mode
+ *              update adapter filters
+ *
+ * Assumptions:
+ *   Multicast addresses are presented in canonical (LSB) format.
+ *
+ * Side Effects:
+ *   On-board adapter filters are updated.
+ */
+static void skfp_ctl_set_multicast_list(struct net_device *dev)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       skfddi_priv *bp = &smc->os;
+       unsigned long Flags;
+
+       spin_lock_irqsave(&bp->DriverLock, Flags);
+       skfp_ctl_set_multicast_list_wo_lock(dev);
+       spin_unlock_irqrestore(&bp->DriverLock, Flags);
+}                              // skfp_ctl_set_multicast_list
+
+
+
+static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       struct netdev_hw_addr *ha;
+
+       /* Enable promiscuous mode, if necessary */
+       if (dev->flags & IFF_PROMISC) {
+               mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
+               pr_debug("PROMISCUOUS MODE ENABLED\n");
+       }
+       /* Else, update multicast address table */
+       else {
+               mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
+               pr_debug("PROMISCUOUS MODE DISABLED\n");
+
+               // Reset all MC addresses
+               mac_clear_multicast(smc);
+               mac_drv_rx_mode(smc, RX_DISABLE_ALLMULTI);
+
+               if (dev->flags & IFF_ALLMULTI) {
+                       mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
+                       pr_debug("ENABLE ALL MC ADDRESSES\n");
+               } else if (!netdev_mc_empty(dev)) {
+                       if (netdev_mc_count(dev) <= FPMAX_MULTICAST) {
+                               /* use exact filtering */
+
+                               // point to first multicast addr
+                               netdev_for_each_mc_addr(ha, dev) {
+                                       mac_add_multicast(smc,
+                                               (struct fddi_addr *)ha->addr,
+                                               1);
+
+                                       pr_debug("ENABLE MC ADDRESS: %pMF\n",
+                                                ha->addr);
+                               }
+
+                       } else {        // more MC addresses than HW supports
+
+                               mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
+                               pr_debug("ENABLE ALL MC ADDRESSES\n");
+                       }
+               } else {        // no MC addresses
+
+                       pr_debug("DISABLE ALL MC ADDRESSES\n");
+               }
+
+               /* Update adapter filters */
+               mac_update_multicast(smc);
+       }
+}                              // skfp_ctl_set_multicast_list_wo_lock
+
+
+/*
+ * ===========================
+ * = skfp_ctl_set_mac_address =
+ * ===========================
+ *   
+ * Overview:
+ *   set new mac address on adapter and update dev_addr field in device table.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   dev  - pointer to device information
+ *   addr - pointer to sockaddr structure containing unicast address to set
+ *
+ * Assumptions:
+ *   The address pointed to by addr->sa_data is a valid unicast
+ *   address and is presented in canonical (LSB) format.
+ */
+static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
+       skfddi_priv *bp = &smc->os;
+       unsigned long Flags;
+
+
+       memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);
+       spin_lock_irqsave(&bp->DriverLock, Flags);
+       ResetAdapter(smc);
+       spin_unlock_irqrestore(&bp->DriverLock, Flags);
+
+       return 0;               /* always return zero */
+}                              // skfp_ctl_set_mac_address
+
+
+/*
+ * ==============
+ * = skfp_ioctl =
+ * ==============
+ *   
+ * Overview:
+ *
+ * Perform IOCTL call functions here. Some are privileged operations and the
+ * effective uid is checked in those cases.
+ *  
+ * Returns:
+ *   status value
+ *   0 - success
+ *   other - failure
+ *       
+ * Arguments:
+ *   dev  - pointer to device information
+ *   rq - pointer to ioctl request structure
+ *   cmd - ?
+ *
+ */
+
+
+static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       skfddi_priv *lp = &smc->os;
+       struct s_skfp_ioctl ioc;
+       int status = 0;
+
+       if (copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl)))
+               return -EFAULT;
+
+       switch (ioc.cmd) {
+       case SKFP_GET_STATS:    /* Get the driver statistics */
+               ioc.len = sizeof(lp->MacStat);
+               status = copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len)
+                               ? -EFAULT : 0;
+               break;
+       case SKFP_CLR_STATS:    /* Zero out the driver statistics */
+               if (!capable(CAP_NET_ADMIN)) {
+                       status = -EPERM;
+               } else {
+                       memset(&lp->MacStat, 0, sizeof(lp->MacStat));
+               }
+               break;
+       default:
+               printk("ioctl for %s: unknown cmd: %04x\n", dev->name, ioc.cmd);
+               status = -EOPNOTSUPP;
+
+       }                       // switch
+
+       return status;
+}                              // skfp_ioctl
+
+
+/*
+ * =====================
+ * = skfp_send_pkt     =
+ * =====================
+ *   
+ * Overview:
+ *   Queues a packet for transmission and try to transmit it.
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   skb - pointer to sk_buff to queue for transmission
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Here we assume that an incoming skb transmit request
+ *   is contained in a single physically contiguous buffer
+ *   in which the virtual address of the start of packet
+ *   (skb->data) can be converted to a physical address
+ *   by using pci_map_single().
+ *
+ *   We have an internal queue for packets we can not send 
+ *   immediately. Packets in this queue can be given to the 
+ *   adapter if transmit buffers are freed.
+ *
+ *   We can't free the skb until after it's been DMA'd
+ *   out by the adapter, so we'll keep it in the driver and
+ *   return it in mac_drv_tx_complete.
+ *
+ * Return Codes:
+ *   0 - driver has queued and/or sent packet
+ *       1 - caller should requeue the sk_buff for later transmission
+ *
+ * Assumptions:
+ *   The entire packet is stored in one physically
+ *   contiguous buffer which is not cached and whose
+ *   32-bit physical address can be determined.
+ *
+ *   It's vital that this routine is NOT reentered for the
+ *   same board and that the OS is not in another section of
+ *   code (eg. skfp_interrupt) for the same board on a
+ *   different thread.
+ *
+ * Side Effects:
+ *   None
+ */
+static netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
+                                      struct net_device *dev)
+{
+       struct s_smc *smc = netdev_priv(dev);
+       skfddi_priv *bp = &smc->os;
+
+       pr_debug("skfp_send_pkt\n");
+
+       /*
+        * Verify that incoming transmit request is OK
+        *
+        * Note: The packet size check is consistent with other
+        *               Linux device drivers, although the correct packet
+        *               size should be verified before calling the
+        *               transmit routine.
+        */
+
+       if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {
+               bp->MacStat.gen.tx_errors++;    /* bump error counter */
+               // dequeue packets from xmt queue and send them
+               netif_start_queue(dev);
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;    /* return "success" */
+       }
+       if (bp->QueueSkb == 0) {        // return with tbusy set: queue full
+
+               netif_stop_queue(dev);
+               return NETDEV_TX_BUSY;
+       }
+       bp->QueueSkb--;
+       skb_queue_tail(&bp->SendSkbQueue, skb);
+       send_queued_packets(netdev_priv(dev));
+       if (bp->QueueSkb == 0) {
+               netif_stop_queue(dev);
+       }
+       return NETDEV_TX_OK;
+
+}                              // skfp_send_pkt
+
+
+/*
+ * =======================
+ * = send_queued_packets =
+ * =======================
+ *   
+ * Overview:
+ *   Send packets from the driver queue as long as there are some and
+ *   transmit resources are available.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   smc - pointer to smc (adapter) structure
+ *
+ * Functional Description:
+ *   Take a packet from queue if there is any. If not, then we are done.
+ *   Check if there are resources to send the packet. If not, requeue it
+ *   and exit. 
+ *   Set packet descriptor flags and give packet to adapter.
+ *   Check if any send resources can be freed (we do not use the
+ *   transmit complete interrupt).
+ */
+static void send_queued_packets(struct s_smc *smc)
+{
+       skfddi_priv *bp = &smc->os;
+       struct sk_buff *skb;
+       unsigned char fc;
+       int queue;
+       struct s_smt_fp_txd *txd;       // Current TxD.
+       dma_addr_t dma_address;
+       unsigned long Flags;
+
+       int frame_status;       // HWM tx frame status.
+
+       pr_debug("send queued packets\n");
+       for (;;) {
+               // send first buffer from queue
+               skb = skb_dequeue(&bp->SendSkbQueue);
+
+               if (!skb) {
+                       pr_debug("queue empty\n");
+                       return;
+               }               // queue empty !
+
+               spin_lock_irqsave(&bp->DriverLock, Flags);
+               fc = skb->data[0];
+               queue = (fc & FC_SYNC_BIT) ? QUEUE_S : QUEUE_A0;
+#ifdef ESS
+               // Check if the frame may/must be sent as a synchronous frame.
+
+               if ((fc & ~(FC_SYNC_BIT | FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
+                       // It's an LLC frame.
+                       if (!smc->ess.sync_bw_available)
+                               fc &= ~FC_SYNC_BIT; // No bandwidth available.
+
+                       else {  // Bandwidth is available.
+
+                               if (smc->mib.fddiESSSynchTxMode) {
+                                       // Send as sync. frame.
+                                       fc |= FC_SYNC_BIT;
+                               }
+                       }
+               }
+#endif                         // ESS
+               frame_status = hwm_tx_init(smc, fc, 1, skb->len, queue);
+
+               if ((frame_status & (LOC_TX | LAN_TX)) == 0) {
+                       // Unable to send the frame.
+
+                       if ((frame_status & RING_DOWN) != 0) {
+                               // Ring is down.
+                               pr_debug("Tx attempt while ring down.\n");
+                       } else if ((frame_status & OUT_OF_TXD) != 0) {
+                               pr_debug("%s: out of TXDs.\n", bp->dev->name);
+                       } else {
+                               pr_debug("%s: out of transmit resources",
+                                       bp->dev->name);
+                       }
+
+                       // Note: We will retry the operation as soon as
+                       // transmit resources become available.
+                       skb_queue_head(&bp->SendSkbQueue, skb);
+                       spin_unlock_irqrestore(&bp->DriverLock, Flags);
+                       return; // Packet has been queued.
+
+               }               // if (unable to send frame)
+
+               bp->QueueSkb++; // one packet less in local queue
+
+               // source address in packet ?
+               CheckSourceAddress(skb->data, smc->hw.fddi_canon_addr.a);
+
+               txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue);
+
+               dma_address = pci_map_single(&bp->pdev, skb->data,
+                                            skb->len, PCI_DMA_TODEVICE);
+               if (frame_status & LAN_TX) {
+                       txd->txd_os.skb = skb;                  // save skb
+                       txd->txd_os.dma_addr = dma_address;     // save dma mapping
+               }
+               hwm_tx_frag(smc, skb->data, dma_address, skb->len,
+                      frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF);
+
+               if (!(frame_status & LAN_TX)) {         // local only frame
+                       pci_unmap_single(&bp->pdev, dma_address,
+                                        skb->len, PCI_DMA_TODEVICE);
+                       dev_kfree_skb_irq(skb);
+               }
+               spin_unlock_irqrestore(&bp->DriverLock, Flags);
+       }                       // for
+
+       return;                 // never reached
+
+}                              // send_queued_packets
+
+
+/************************
+ * 
+ * CheckSourceAddress
+ *
+ * Verify if the source address is set. Insert it if necessary.
+ *
+ ************************/
+static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
+{
+       unsigned char SRBit;
+
+       if ((((unsigned long) frame[1 + 6]) & ~0x01) != 0) // source routing bit
+
+               return;
+       if ((unsigned short) frame[1 + 10] != 0)
+               return;
+       SRBit = frame[1 + 6] & 0x01;
+       memcpy(&frame[1 + 6], hw_addr, 6);
+       frame[8] |= SRBit;
+}                              // CheckSourceAddress
+
+
+/************************
+ *
+ *     ResetAdapter
+ *
+ *     Reset the adapter and bring it back to operational mode.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+static void ResetAdapter(struct s_smc *smc)
+{
+
+       pr_debug("[fddi: ResetAdapter]\n");
+
+       // Stop the adapter.
+
+       card_stop(smc);         // Stop all activity.
+
+       // Clear the transmit and receive descriptor queues.
+       mac_drv_clear_tx_queue(smc);
+       mac_drv_clear_rx_queue(smc);
+
+       // Restart the adapter.
+
+       smt_reset_defaults(smc, 1);     // Initialize the SMT module.
+
+       init_smt(smc, (smc->os.dev)->dev_addr); // Initialize the hardware.
+
+       smt_online(smc, 1);     // Insert into the ring again.
+       STI_FBI();
+
+       // Restore original receive mode (multicasts, promiscuous, etc.).
+       skfp_ctl_set_multicast_list_wo_lock(smc->os.dev);
+}                              // ResetAdapter
+
+
+//--------------- functions called by hardware module ----------------
+
+/************************
+ *
+ *     llc_restart_tx
+ *
+ *     The hardware driver calls this routine when the transmit complete
+ *     interrupt bits (end of frame) for the synchronous or asynchronous
+ *     queue is set.
+ *
+ * NOTE The hardware driver calls this function also if no packets are queued.
+ *     The routine must be able to handle this case.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void llc_restart_tx(struct s_smc *smc)
+{
+       skfddi_priv *bp = &smc->os;
+
+       pr_debug("[llc_restart_tx]\n");
+
+       // Try to send queued packets
+       spin_unlock(&bp->DriverLock);
+       send_queued_packets(smc);
+       spin_lock(&bp->DriverLock);
+       netif_start_queue(bp->dev);// system may send again if it was blocked
+
+}                              // llc_restart_tx
+
+
+/************************
+ *
+ *     mac_drv_get_space
+ *
+ *     The hardware module calls this function to allocate the memory
+ *     for the SMT MBufs if the define MB_OUTSIDE_SMC is specified.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     size - Size of memory in bytes to allocate.
+ * Out
+ *     != 0    A pointer to the virtual address of the allocated memory.
+ *     == 0    Allocation error.
+ *
+ ************************/
+void *mac_drv_get_space(struct s_smc *smc, unsigned int size)
+{
+       void *virt;
+
+       pr_debug("mac_drv_get_space (%d bytes), ", size);
+       virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
+
+       if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
+               printk("Unexpected SMT memory size requested: %d\n", size);
+               return NULL;
+       }
+       smc->os.SharedMemHeap += size;  // Move heap pointer.
+
+       pr_debug("mac_drv_get_space end\n");
+       pr_debug("virt addr: %lx\n", (ulong) virt);
+       pr_debug("bus  addr: %lx\n", (ulong)
+              (smc->os.SharedMemDMA +
+               ((char *) virt - (char *)smc->os.SharedMemAddr)));
+       return virt;
+}                              // mac_drv_get_space
+
+
+/************************
+ *
+ *     mac_drv_get_desc_mem
+ *
+ *     This function is called by the hardware dependent module.
+ *     It allocates the memory for the RxD and TxD descriptors.
+ *
+ *     This memory must be non-cached, non-movable and non-swappable.
+ *     This memory should start at a physical page boundary.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     size - Size of memory in bytes to allocate.
+ * Out
+ *     != 0    A pointer to the virtual address of the allocated memory.
+ *     == 0    Allocation error.
+ *
+ ************************/
+void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
+{
+
+       char *virt;
+
+       pr_debug("mac_drv_get_desc_mem\n");
+
+       // Descriptor memory must be aligned on 16-byte boundary.
+
+       virt = mac_drv_get_space(smc, size);
+
+       size = (u_int) (16 - (((unsigned long) virt) & 15UL));
+       size = size % 16;
+
+       pr_debug("Allocate %u bytes alignment gap ", size);
+       pr_debug("for descriptor memory.\n");
+
+       if (!mac_drv_get_space(smc, size)) {
+               printk("fddi: Unable to align descriptor memory.\n");
+               return NULL;
+       }
+       return virt + size;
+}                              // mac_drv_get_desc_mem
+
+
+/************************
+ *
+ *     mac_drv_virt2phys
+ *
+ *     Get the physical address of a given virtual address.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     virt - A (virtual) pointer into our 'shared' memory area.
+ * Out
+ *     Physical address of the given virtual address.
+ *
+ ************************/
+unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
+{
+       return smc->os.SharedMemDMA +
+               ((char *) virt - (char *)smc->os.SharedMemAddr);
+}                              // mac_drv_virt2phys
+
+
+/************************
+ *
+ *     dma_master
+ *
+ *     The HWM calls this function, when the driver leads through a DMA
+ *     transfer. If the OS-specific module must prepare the system hardware
+ *     for the DMA transfer, it should do it in this function.
+ *
+ *     The hardware module calls this dma_master if it wants to send an SMT
+ *     frame.  This means that the virt address passed in here is part of
+ *      the 'shared' memory area.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     virt - The virtual address of the data.
+ *
+ *     len - The length in bytes of the data.
+ *
+ *     flag - Indicates the transmit direction and the buffer type:
+ *             DMA_RD  (0x01)  system RAM ==> adapter buffer memory
+ *             DMA_WR  (0x02)  adapter buffer memory ==> system RAM
+ *             SMT_BUF (0x80)  SMT buffer
+ *
+ *     >> NOTE: SMT_BUF and DMA_RD are always set for PCI. <<
+ * Out
+ *     Returns the pyhsical address for the DMA transfer.
+ *
+ ************************/
+u_long dma_master(struct s_smc * smc, void *virt, int len, int flag)
+{
+       return smc->os.SharedMemDMA +
+               ((char *) virt - (char *)smc->os.SharedMemAddr);
+}                              // dma_master
+
+
+/************************
+ *
+ *     dma_complete
+ *
+ *     The hardware module calls this routine when it has completed a DMA
+ *     transfer. If the operating system dependent module has set up the DMA
+ *     channel via dma_master() (e.g. Windows NT or AIX) it should clean up
+ *     the DMA channel.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     descr - A pointer to a TxD or RxD, respectively.
+ *
+ *     flag - Indicates the DMA transfer direction / SMT buffer:
+ *             DMA_RD  (0x01)  system RAM ==> adapter buffer memory
+ *             DMA_WR  (0x02)  adapter buffer memory ==> system RAM
+ *             SMT_BUF (0x80)  SMT buffer (managed by HWM)
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag)
+{
+       /* For TX buffers, there are two cases.  If it is an SMT transmit
+        * buffer, there is nothing to do since we use consistent memory
+        * for the 'shared' memory area.  The other case is for normal
+        * transmit packets given to us by the networking stack, and in
+        * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete
+        * below.
+        *
+        * For RX buffers, we have to unmap dynamic PCI DMA mappings here
+        * because the hardware module is about to potentially look at
+        * the contents of the buffer.  If we did not call the PCI DMA
+        * unmap first, the hardware module could read inconsistent data.
+        */
+       if (flag & DMA_WR) {
+               skfddi_priv *bp = &smc->os;
+               volatile struct s_smt_fp_rxd *r = &descr->r;
+
+               /* If SKB is NULL, we used the local buffer. */
+               if (r->rxd_os.skb && r->rxd_os.dma_addr) {
+                       int MaxFrameSize = bp->MaxFrameSize;
+
+                       pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr,
+                                        MaxFrameSize, PCI_DMA_FROMDEVICE);
+                       r->rxd_os.dma_addr = 0;
+               }
+       }
+}                              // dma_complete
+
+
+/************************
+ *
+ *     mac_drv_tx_complete
+ *
+ *     Transmit of a packet is complete. Release the tx staging buffer.
+ *
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     txd - A pointer to the last TxD which is used by the frame.
+ * Out
+ *     Returns nothing.
+ *
+ ************************/
+void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
+{
+       struct sk_buff *skb;
+
+       pr_debug("entering mac_drv_tx_complete\n");
+       // Check if this TxD points to a skb
+
+       if (!(skb = txd->txd_os.skb)) {
+               pr_debug("TXD with no skb assigned.\n");
+               return;
+       }
+       txd->txd_os.skb = NULL;
+
+       // release the DMA mapping
+       pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr,
+                        skb->len, PCI_DMA_TODEVICE);
+       txd->txd_os.dma_addr = 0;
+
+       smc->os.MacStat.gen.tx_packets++;       // Count transmitted packets.
+       smc->os.MacStat.gen.tx_bytes+=skb->len; // Count bytes
+
+       // free the skb
+       dev_kfree_skb_irq(skb);
+
+       pr_debug("leaving mac_drv_tx_complete\n");
+}                              // mac_drv_tx_complete
+
+
+/************************
+ *
+ * dump packets to logfile
+ *
+ ************************/
+#ifdef DUMPPACKETS
+void dump_data(unsigned char *Data, int length)
+{
+       int i, j;
+       unsigned char s[255], sh[10];
+       if (length > 64) {
+               length = 64;
+       }
+       printk(KERN_INFO "---Packet start---\n");
+       for (i = 0, j = 0; i < length / 8; i++, j += 8)
+               printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+                      Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3],
+                      Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]);
+       strcpy(s, "");
+       for (i = 0; i < length % 8; i++) {
+               sprintf(sh, "%02x ", Data[j + i]);
+               strcat(s, sh);
+       }
+       printk(KERN_INFO "%s\n", s);
+       printk(KERN_INFO "------------------\n");
+}                              // dump_data
+#else
+#define dump_data(data,len)
+#endif                         // DUMPPACKETS
+
+/************************
+ *
+ *     mac_drv_rx_complete
+ *
+ *     The hardware module calls this function if an LLC frame is received
+ *     in a receive buffer. Also the SMT, NSA, and directed beacon frames
+ *     from the network will be passed to the LLC layer by this function
+ *     if passing is enabled.
+ *
+ *     mac_drv_rx_complete forwards the frame to the LLC layer if it should
+ *     be received. It also fills the RxD ring with new receive buffers if
+ *     some can be queued.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     rxd - A pointer to the first RxD which is used by the receive frame.
+ *
+ *     frag_count - Count of RxDs used by the received frame.
+ *
+ *     len - Frame length.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+                        int frag_count, int len)
+{
+       skfddi_priv *bp = &smc->os;
+       struct sk_buff *skb;
+       unsigned char *virt, *cp;
+       unsigned short ri;
+       u_int RifLength;
+
+       pr_debug("entering mac_drv_rx_complete (len=%d)\n", len);
+       if (frag_count != 1) {  // This is not allowed to happen.
+
+               printk("fddi: Multi-fragment receive!\n");
+               goto RequeueRxd;        // Re-use the given RXD(s).
+
+       }
+       skb = rxd->rxd_os.skb;
+       if (!skb) {
+               pr_debug("No skb in rxd\n");
+               smc->os.MacStat.gen.rx_errors++;
+               goto RequeueRxd;
+       }
+       virt = skb->data;
+
+       // The DMA mapping was released in dma_complete above.
+
+       dump_data(skb->data, len);
+
+       /*
+        * FDDI Frame format:
+        * +-------+-------+-------+------------+--------+------------+
+        * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] |
+        * +-------+-------+-------+------------+--------+------------+
+        *
+        * FC = Frame Control
+        * DA = Destination Address
+        * SA = Source Address
+        * RIF = Routing Information Field
+        * LLC = Logical Link Control
+        */
+
+       // Remove Routing Information Field (RIF), if present.
+
+       if ((virt[1 + 6] & FDDI_RII) == 0)
+               RifLength = 0;
+       else {
+               int n;
+// goos: RIF removal has still to be tested
+               pr_debug("RIF found\n");
+               // Get RIF length from Routing Control (RC) field.
+               cp = virt + FDDI_MAC_HDR_LEN;   // Point behind MAC header.
+
+               ri = ntohs(*((__be16 *) cp));
+               RifLength = ri & FDDI_RCF_LEN_MASK;
+               if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
+                       printk("fddi: Invalid RIF.\n");
+                       goto RequeueRxd;        // Discard the frame.
+
+               }
+               virt[1 + 6] &= ~FDDI_RII;       // Clear RII bit.
+               // regions overlap
+
+               virt = cp + RifLength;
+               for (n = FDDI_MAC_HDR_LEN; n; n--)
+                       *--virt = *--cp;
+               // adjust sbd->data pointer
+               skb_pull(skb, RifLength);
+               len -= RifLength;
+               RifLength = 0;
+       }
+
+       // Count statistics.
+       smc->os.MacStat.gen.rx_packets++;       // Count indicated receive
+                                               // packets.
+       smc->os.MacStat.gen.rx_bytes+=len;      // Count bytes.
+
+       // virt points to header again
+       if (virt[1] & 0x01) {   // Check group (multicast) bit.
+
+               smc->os.MacStat.gen.multicast++;
+       }
+
+       // deliver frame to system
+       rxd->rxd_os.skb = NULL;
+       skb_trim(skb, len);
+       skb->protocol = fddi_type_trans(skb, bp->dev);
+
+       netif_rx(skb);
+
+       HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
+       return;
+
+      RequeueRxd:
+       pr_debug("Rx: re-queue RXD.\n");
+       mac_drv_requeue_rxd(smc, rxd, frag_count);
+       smc->os.MacStat.gen.rx_errors++;        // Count receive packets
+                                               // not indicated.
+
+}                              // mac_drv_rx_complete
+
+
+/************************
+ *
+ *     mac_drv_requeue_rxd
+ *
+ *     The hardware module calls this function to request the OS-specific
+ *     module to queue the receive buffer(s) represented by the pointer
+ *     to the RxD and the frag_count into the receive queue again. This
+ *     buffer was filled with an invalid frame or an SMT frame.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     rxd - A pointer to the first RxD which is used by the receive frame.
+ *
+ *     frag_count - Count of RxDs used by the received frame.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+                        int frag_count)
+{
+       volatile struct s_smt_fp_rxd *next_rxd;
+       volatile struct s_smt_fp_rxd *src_rxd;
+       struct sk_buff *skb;
+       int MaxFrameSize;
+       unsigned char *v_addr;
+       dma_addr_t b_addr;
+
+       if (frag_count != 1)    // This is not allowed to happen.
+
+               printk("fddi: Multi-fragment requeue!\n");
+
+       MaxFrameSize = smc->os.MaxFrameSize;
+       src_rxd = rxd;
+       for (; frag_count > 0; frag_count--) {
+               next_rxd = src_rxd->rxd_next;
+               rxd = HWM_GET_CURR_RXD(smc);
+
+               skb = src_rxd->rxd_os.skb;
+               if (skb == NULL) {      // this should not happen
+
+                       pr_debug("Requeue with no skb in rxd!\n");
+                       skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
+                       if (skb) {
+                               // we got a skb
+                               rxd->rxd_os.skb = skb;
+                               skb_reserve(skb, 3);
+                               skb_put(skb, MaxFrameSize);
+                               v_addr = skb->data;
+                               b_addr = pci_map_single(&smc->os.pdev,
+                                                       v_addr,
+                                                       MaxFrameSize,
+                                                       PCI_DMA_FROMDEVICE);
+                               rxd->rxd_os.dma_addr = b_addr;
+                       } else {
+                               // no skb available, use local buffer
+                               pr_debug("Queueing invalid buffer!\n");
+                               rxd->rxd_os.skb = NULL;
+                               v_addr = smc->os.LocalRxBuffer;
+                               b_addr = smc->os.LocalRxBufferDMA;
+                       }
+               } else {
+                       // we use skb from old rxd
+                       rxd->rxd_os.skb = skb;
+                       v_addr = skb->data;
+                       b_addr = pci_map_single(&smc->os.pdev,
+                                               v_addr,
+                                               MaxFrameSize,
+                                               PCI_DMA_FROMDEVICE);
+                       rxd->rxd_os.dma_addr = b_addr;
+               }
+               hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
+                           FIRST_FRAG | LAST_FRAG);
+
+               src_rxd = next_rxd;
+       }
+}                              // mac_drv_requeue_rxd
+
+
+/************************
+ *
+ *     mac_drv_fill_rxd
+ *
+ *     The hardware module calls this function at initialization time
+ *     to fill the RxD ring with receive buffers. It is also called by
+ *     mac_drv_rx_complete if rx_free is large enough to queue some new
+ *     receive buffers into the RxD ring. mac_drv_fill_rxd queues new
+ *     receive buffers as long as enough RxDs and receive buffers are
+ *     available.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void mac_drv_fill_rxd(struct s_smc *smc)
+{
+       int MaxFrameSize;
+       unsigned char *v_addr;
+       unsigned long b_addr;
+       struct sk_buff *skb;
+       volatile struct s_smt_fp_rxd *rxd;
+
+       pr_debug("entering mac_drv_fill_rxd\n");
+
+       // Walk through the list of free receive buffers, passing receive
+       // buffers to the HWM as long as RXDs are available.
+
+       MaxFrameSize = smc->os.MaxFrameSize;
+       // Check if there is any RXD left.
+       while (HWM_GET_RX_FREE(smc) > 0) {
+               pr_debug(".\n");
+
+               rxd = HWM_GET_CURR_RXD(smc);
+               skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
+               if (skb) {
+                       // we got a skb
+                       skb_reserve(skb, 3);
+                       skb_put(skb, MaxFrameSize);
+                       v_addr = skb->data;
+                       b_addr = pci_map_single(&smc->os.pdev,
+                                               v_addr,
+                                               MaxFrameSize,
+                                               PCI_DMA_FROMDEVICE);
+                       rxd->rxd_os.dma_addr = b_addr;
+               } else {
+                       // no skb available, use local buffer
+                       // System has run out of buffer memory, but we want to
+                       // keep the receiver running in hope of better times.
+                       // Multiple descriptors may point to this local buffer,
+                       // so data in it must be considered invalid.
+                       pr_debug("Queueing invalid buffer!\n");
+                       v_addr = smc->os.LocalRxBuffer;
+                       b_addr = smc->os.LocalRxBufferDMA;
+               }
+
+               rxd->rxd_os.skb = skb;
+
+               // Pass receive buffer to HWM.
+               hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
+                           FIRST_FRAG | LAST_FRAG);
+       }
+       pr_debug("leaving mac_drv_fill_rxd\n");
+}                              // mac_drv_fill_rxd
+
+
+/************************
+ *
+ *     mac_drv_clear_rxd
+ *
+ *     The hardware module calls this function to release unused
+ *     receive buffers.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     rxd - A pointer to the first RxD which is used by the receive buffer.
+ *
+ *     frag_count - Count of RxDs used by the receive buffer.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
+                      int frag_count)
+{
+
+       struct sk_buff *skb;
+
+       pr_debug("entering mac_drv_clear_rxd\n");
+
+       if (frag_count != 1)    // This is not allowed to happen.
+
+               printk("fddi: Multi-fragment clear!\n");
+
+       for (; frag_count > 0; frag_count--) {
+               skb = rxd->rxd_os.skb;
+               if (skb != NULL) {
+                       skfddi_priv *bp = &smc->os;
+                       int MaxFrameSize = bp->MaxFrameSize;
+
+                       pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr,
+                                        MaxFrameSize, PCI_DMA_FROMDEVICE);
+
+                       dev_kfree_skb(skb);
+                       rxd->rxd_os.skb = NULL;
+               }
+               rxd = rxd->rxd_next;    // Next RXD.
+
+       }
+}                              // mac_drv_clear_rxd
+
+
+/************************
+ *
+ *     mac_drv_rx_init
+ *
+ *     The hardware module calls this routine when an SMT or NSA frame of the
+ *     local SMT should be delivered to the LLC layer.
+ *
+ *     It is necessary to have this function, because there is no other way to
+ *     copy the contents of SMT MBufs into receive buffers.
+ *
+ *     mac_drv_rx_init allocates the required target memory for this frame,
+ *     and receives the frame fragment by fragment by calling mac_drv_rx_frag.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     len - The length (in bytes) of the received frame (FC, DA, SA, Data).
+ *
+ *     fc - The Frame Control field of the received frame.
+ *
+ *     look_ahead - A pointer to the lookahead data buffer (may be NULL).
+ *
+ *     la_len - The length of the lookahead data stored in the lookahead
+ *     buffer (may be zero).
+ * Out
+ *     Always returns zero (0).
+ *
+ ************************/
+int mac_drv_rx_init(struct s_smc *smc, int len, int fc,
+                   char *look_ahead, int la_len)
+{
+       struct sk_buff *skb;
+
+       pr_debug("entering mac_drv_rx_init(len=%d)\n", len);
+
+       // "Received" a SMT or NSA frame of the local SMT.
+
+       if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) {
+               pr_debug("fddi: Discard invalid local SMT frame\n");
+               pr_debug("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
+                      len, la_len, (unsigned long) look_ahead);
+               return 0;
+       }
+       skb = alloc_skb(len + 3, GFP_ATOMIC);
+       if (!skb) {
+               pr_debug("fddi: Local SMT: skb memory exhausted.\n");
+               return 0;
+       }
+       skb_reserve(skb, 3);
+       skb_put(skb, len);
+       skb_copy_to_linear_data(skb, look_ahead, len);
+
+       // deliver frame to system
+       skb->protocol = fddi_type_trans(skb, smc->os.dev);
+       netif_rx(skb);
+
+       return 0;
+}                              // mac_drv_rx_init
+
+
+/************************
+ *
+ *     smt_timer_poll
+ *
+ *     This routine is called periodically by the SMT module to clean up the
+ *     driver.
+ *
+ *     Return any queued frames back to the upper protocol layers if the ring
+ *     is down.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void smt_timer_poll(struct s_smc *smc)
+{
+}                              // smt_timer_poll
+
+
+/************************
+ *
+ *     ring_status_indication
+ *
+ *     This function indicates a change of the ring state.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     status - The current ring status.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void ring_status_indication(struct s_smc *smc, u_long status)
+{
+       pr_debug("ring_status_indication( ");
+       if (status & RS_RES15)
+               pr_debug("RS_RES15 ");
+       if (status & RS_HARDERROR)
+               pr_debug("RS_HARDERROR ");
+       if (status & RS_SOFTERROR)
+               pr_debug("RS_SOFTERROR ");
+       if (status & RS_BEACON)
+               pr_debug("RS_BEACON ");
+       if (status & RS_PATHTEST)
+               pr_debug("RS_PATHTEST ");
+       if (status & RS_SELFTEST)
+               pr_debug("RS_SELFTEST ");
+       if (status & RS_RES9)
+               pr_debug("RS_RES9 ");
+       if (status & RS_DISCONNECT)
+               pr_debug("RS_DISCONNECT ");
+       if (status & RS_RES7)
+               pr_debug("RS_RES7 ");
+       if (status & RS_DUPADDR)
+               pr_debug("RS_DUPADDR ");
+       if (status & RS_NORINGOP)
+               pr_debug("RS_NORINGOP ");
+       if (status & RS_VERSION)
+               pr_debug("RS_VERSION ");
+       if (status & RS_STUCKBYPASSS)
+               pr_debug("RS_STUCKBYPASSS ");
+       if (status & RS_EVENT)
+               pr_debug("RS_EVENT ");
+       if (status & RS_RINGOPCHANGE)
+               pr_debug("RS_RINGOPCHANGE ");
+       if (status & RS_RES0)
+               pr_debug("RS_RES0 ");
+       pr_debug("]\n");
+}                              // ring_status_indication
+
+
+/************************
+ *
+ *     smt_get_time
+ *
+ *     Gets the current time from the system.
+ * Args
+ *     None.
+ * Out
+ *     The current time in TICKS_PER_SECOND.
+ *
+ *     TICKS_PER_SECOND has the unit 'count of timer ticks per second'. It is
+ *     defined in "targetos.h". The definition of TICKS_PER_SECOND must comply
+ *     to the time returned by smt_get_time().
+ *
+ ************************/
+unsigned long smt_get_time(void)
+{
+       return jiffies;
+}                              // smt_get_time
+
+
+/************************
+ *
+ *     smt_stat_counter
+ *
+ *     Status counter update (ring_op, fifo full).
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     stat -  = 0: A ring operational change occurred.
+ *             = 1: The FORMAC FIFO buffer is full / FIFO overflow.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void smt_stat_counter(struct s_smc *smc, int stat)
+{
+//      BOOLEAN RingIsUp ;
+
+       pr_debug("smt_stat_counter\n");
+       switch (stat) {
+       case 0:
+               pr_debug("Ring operational change.\n");
+               break;
+       case 1:
+               pr_debug("Receive fifo overflow.\n");
+               smc->os.MacStat.gen.rx_errors++;
+               break;
+       default:
+               pr_debug("Unknown status (%d).\n", stat);
+               break;
+       }
+}                              // smt_stat_counter
+
+
+/************************
+ *
+ *     cfm_state_change
+ *
+ *     Sets CFM state in custom statistics.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     c_state - Possible values are:
+ *
+ *             EC0_OUT, EC1_IN, EC2_TRACE, EC3_LEAVE, EC4_PATH_TEST,
+ *             EC5_INSERT, EC6_CHECK, EC7_DEINSERT
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void cfm_state_change(struct s_smc *smc, int c_state)
+{
+#ifdef DRIVERDEBUG
+       char *s;
+
+       switch (c_state) {
+       case SC0_ISOLATED:
+               s = "SC0_ISOLATED";
+               break;
+       case SC1_WRAP_A:
+               s = "SC1_WRAP_A";
+               break;
+       case SC2_WRAP_B:
+               s = "SC2_WRAP_B";
+               break;
+       case SC4_THRU_A:
+               s = "SC4_THRU_A";
+               break;
+       case SC5_THRU_B:
+               s = "SC5_THRU_B";
+               break;
+       case SC7_WRAP_S:
+               s = "SC7_WRAP_S";
+               break;
+       case SC9_C_WRAP_A:
+               s = "SC9_C_WRAP_A";
+               break;
+       case SC10_C_WRAP_B:
+               s = "SC10_C_WRAP_B";
+               break;
+       case SC11_C_WRAP_S:
+               s = "SC11_C_WRAP_S";
+               break;
+       default:
+               pr_debug("cfm_state_change: unknown %d\n", c_state);
+               return;
+       }
+       pr_debug("cfm_state_change: %s\n", s);
+#endif                         // DRIVERDEBUG
+}                              // cfm_state_change
+
+
+/************************
+ *
+ *     ecm_state_change
+ *
+ *     Sets ECM state in custom statistics.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     e_state - Possible values are:
+ *
+ *             SC0_ISOLATED, SC1_WRAP_A (5), SC2_WRAP_B (6), SC4_THRU_A (12),
+ *             SC5_THRU_B (7), SC7_WRAP_S (8)
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void ecm_state_change(struct s_smc *smc, int e_state)
+{
+#ifdef DRIVERDEBUG
+       char *s;
+
+       switch (e_state) {
+       case EC0_OUT:
+               s = "EC0_OUT";
+               break;
+       case EC1_IN:
+               s = "EC1_IN";
+               break;
+       case EC2_TRACE:
+               s = "EC2_TRACE";
+               break;
+       case EC3_LEAVE:
+               s = "EC3_LEAVE";
+               break;
+       case EC4_PATH_TEST:
+               s = "EC4_PATH_TEST";
+               break;
+       case EC5_INSERT:
+               s = "EC5_INSERT";
+               break;
+       case EC6_CHECK:
+               s = "EC6_CHECK";
+               break;
+       case EC7_DEINSERT:
+               s = "EC7_DEINSERT";
+               break;
+       default:
+               s = "unknown";
+               break;
+       }
+       pr_debug("ecm_state_change: %s\n", s);
+#endif                         //DRIVERDEBUG
+}                              // ecm_state_change
+
+
+/************************
+ *
+ *     rmt_state_change
+ *
+ *     Sets RMT state in custom statistics.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ *
+ *     r_state - Possible values are:
+ *
+ *             RM0_ISOLATED, RM1_NON_OP, RM2_RING_OP, RM3_DETECT,
+ *             RM4_NON_OP_DUP, RM5_RING_OP_DUP, RM6_DIRECTED, RM7_TRACE
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void rmt_state_change(struct s_smc *smc, int r_state)
+{
+#ifdef DRIVERDEBUG
+       char *s;
+
+       switch (r_state) {
+       case RM0_ISOLATED:
+               s = "RM0_ISOLATED";
+               break;
+       case RM1_NON_OP:
+               s = "RM1_NON_OP - not operational";
+               break;
+       case RM2_RING_OP:
+               s = "RM2_RING_OP - ring operational";
+               break;
+       case RM3_DETECT:
+               s = "RM3_DETECT - detect dupl addresses";
+               break;
+       case RM4_NON_OP_DUP:
+               s = "RM4_NON_OP_DUP - dupl. addr detected";
+               break;
+       case RM5_RING_OP_DUP:
+               s = "RM5_RING_OP_DUP - ring oper. with dupl. addr";
+               break;
+       case RM6_DIRECTED:
+               s = "RM6_DIRECTED - sending directed beacons";
+               break;
+       case RM7_TRACE:
+               s = "RM7_TRACE - trace initiated";
+               break;
+       default:
+               s = "unknown";
+               break;
+       }
+       pr_debug("[rmt_state_change: %s]\n", s);
+#endif                         // DRIVERDEBUG
+}                              // rmt_state_change
+
+
+/************************
+ *
+ *     drv_reset_indication
+ *
+ *     This function is called by the SMT when it has detected a severe
+ *     hardware problem. The driver should perform a reset on the adapter
+ *     as soon as possible, but not from within this function.
+ * Args
+ *     smc - A pointer to the SMT context struct.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void drv_reset_indication(struct s_smc *smc)
+{
+       pr_debug("entering drv_reset_indication\n");
+
+       smc->os.ResetRequested = TRUE;  // Set flag.
+
+}                              // drv_reset_indication
+
+static struct pci_driver skfddi_pci_driver = {
+       .name           = "skfddi",
+       .id_table       = skfddi_pci_tbl,
+       .probe          = skfp_init_one,
+       .remove         = __devexit_p(skfp_remove_one),
+};
+
+static int __init skfd_init(void)
+{
+       return pci_register_driver(&skfddi_pci_driver);
+}
+
+static void __exit skfd_exit(void)
+{
+       pci_unregister_driver(&skfddi_pci_driver);
+}
+
+module_init(skfd_init);
+module_exit(skfd_exit);
diff --git a/drivers/net/fddi/skfp/smt.c b/drivers/net/fddi/skfp/smt.c
new file mode 100644 (file)
index 0000000..08d9432
--- /dev/null
@@ -0,0 +1,2046 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+#include <linux/bitrev.h>
+#include <linux/kernel.h>
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)smt.c       2.43 98/11/23 (C) SK " ;
+#endif
+
+/*
+ * FC in SMbuf
+ */
+#define m_fc(mb)       ((mb)->sm_data[0])
+
+#define SMT_TID_MAGIC  0x1f0a7b3c
+
+#ifdef DEBUG
+static const char *const smt_type_name[] = {
+       "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",
+       "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",
+       "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",
+       "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"
+} ;
+
+static const char *const smt_class_name[] = {
+       "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",
+       "SRF","PMF_GET","PMF_SET","ESF"
+} ;
+#endif
+#define LAST_CLASS     (SMT_PMF_SET)
+
+static const struct fddi_addr SMT_Unknown = {
+       { 0,0,0x1f,0,0,0 }
+} ;
+
+/*
+ * function prototypes
+ */
+#ifdef LITTLE_ENDIAN
+static int smt_swap_short(u_short s);
+#endif
+static int mac_index(struct s_smc *smc, int mac);
+static int phy_index(struct s_smc *smc, int phy);
+static int mac_con_resource_index(struct s_smc *smc, int mac);
+static int phy_con_resource_index(struct s_smc *smc, int phy);
+static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
+                        int local);
+static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 
+                        int fc, u_long tid, int type, int local);
+static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
+                         u_long tid, int type, int len);
+static void smt_echo_test(struct s_smc *smc, int dna);
+static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
+                               u_long tid, int local);
+static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
+                                  u_long tid, int local);
+#ifdef LITTLE_ENDIAN
+static void smt_string_swap(char *data, const char *format, int len);
+#endif
+static void smt_add_frame_len(SMbuf *mb, int len);
+static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);
+static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde);
+static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state);
+static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts);
+static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy);
+static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency);
+static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor);
+static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path);
+static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st);
+static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy);
+static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers);
+static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc);
+static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc);
+static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc);
+static void smt_fill_manufacturer(struct s_smc *smc, 
+                                 struct smp_p_manufacturer *man);
+static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user);
+static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount);
+static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
+                         int len);
+
+static void smt_clear_una_dna(struct s_smc *smc);
+static void smt_clear_old_una_dna(struct s_smc *smc);
+#ifdef CONCENTRATOR
+static int entity_to_index(void);
+#endif
+static void update_dac(struct s_smc *smc, int report);
+static int div_ratio(u_long upper, u_long lower);
+#ifdef  USE_CAN_ADDR
+static void    hwm_conv_can(struct s_smc *smc, char *data, int len);
+#else
+#define                hwm_conv_can(smc,data,len)
+#endif
+
+
+static inline int is_my_addr(const struct s_smc *smc, 
+                            const struct fddi_addr *addr)
+{
+       return(*(short *)(&addr->a[0]) ==
+               *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
+         && *(short *)(&addr->a[2]) ==
+               *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])
+         && *(short *)(&addr->a[4]) ==
+               *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
+}
+
+static inline int is_broadcast(const struct fddi_addr *addr)
+{
+       return *(u_short *)(&addr->a[0]) == 0xffff &&
+              *(u_short *)(&addr->a[2]) == 0xffff &&
+              *(u_short *)(&addr->a[4]) == 0xffff;
+}
+
+static inline int is_individual(const struct fddi_addr *addr)
+{
+       return !(addr->a[0] & GROUP_ADDR);
+}
+
+static inline int is_equal(const struct fddi_addr *addr1, 
+                          const struct fddi_addr *addr2)
+{
+       return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
+              *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
+              *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]);
+}
+
+/*
+ * list of mandatory paras in frames
+ */
+static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;
+
+/*
+ * init SMT agent
+ */
+void smt_agent_init(struct s_smc *smc)
+{
+       int             i ;
+
+       /*
+        * get MAC address
+        */
+       smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ;
+
+       /*
+        * get OUI address from driver (bia == built-in-address)
+        */
+       smc->mib.fddiSMTStationId.sid_oem[0] = 0 ;
+       smc->mib.fddiSMTStationId.sid_oem[1] = 0 ;
+       driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ;
+       for (i = 0 ; i < 6 ; i ++) {
+               smc->mib.fddiSMTStationId.sid_node.a[i] =
+                       bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]);
+       }
+       smc->mib.fddiSMTManufacturerData[0] =
+               smc->mib.fddiSMTStationId.sid_node.a[0] ;
+       smc->mib.fddiSMTManufacturerData[1] =
+               smc->mib.fddiSMTStationId.sid_node.a[1] ;
+       smc->mib.fddiSMTManufacturerData[2] =
+               smc->mib.fddiSMTStationId.sid_node.a[2] ;
+       smc->sm.smt_tid = 0 ;
+       smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ;
+       smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
+#ifndef        SLIM_SMT
+       smt_clear_una_dna(smc) ;
+       smt_clear_old_una_dna(smc) ;
+#endif
+       for (i = 0 ; i < SMT_MAX_TEST ; i++)
+               smc->sm.pend[i] = 0 ;
+       smc->sm.please_reconnect = 0 ;
+       smc->sm.uniq_ticks = 0 ;
+}
+
+/*
+ * SMT task
+ * forever
+ *     delay 30 seconds
+ *     send NIF
+ *     check tvu & tvd
+ * end
+ */
+void smt_agent_task(struct s_smc *smc)
+{
+       smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
+               EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
+       DB_SMT("SMT agent task\n",0,0) ;
+}
+
+#ifndef SMT_REAL_TOKEN_CT
+void smt_emulate_token_ct(struct s_smc *smc, int mac_index)
+{
+       u_long  count;
+       u_long  time;
+
+
+       time = smt_get_time();
+       count = ((time - smc->sm.last_tok_time[mac_index]) *
+                                       100)/TICKS_PER_SECOND;
+
+       /*
+        * Only when ring is up we will have a token count. The
+        * flag is unfortunately a single instance value. This
+        * doesn't matter now, because we currently have only
+        * one MAC instance.
+        */
+       if (smc->hw.mac_ring_is_up){
+               smc->mib.m[mac_index].fddiMACToken_Ct += count;
+       }
+
+       /* Remember current time */
+       smc->sm.last_tok_time[mac_index] = time;
+
+}
+#endif
+
+/*ARGSUSED1*/
+void smt_event(struct s_smc *smc, int event)
+{
+       u_long          time ;
+#ifndef SMT_REAL_TOKEN_CT
+       int             i ;
+#endif
+
+
+       if (smc->sm.please_reconnect) {
+               smc->sm.please_reconnect -- ;
+               if (smc->sm.please_reconnect == 0) {
+                       /* Counted down */
+                       queue_event(smc,EVENT_ECM,EC_CONNECT) ;
+               }
+       }
+
+       if (event == SM_FAST)
+               return ;
+
+       /*
+        * timer for periodic cleanup in driver
+        * reset and start the watchdog (FM2)
+        * ESS timer
+        * SBA timer
+        */
+       smt_timer_poll(smc) ;
+       smt_start_watchdog(smc) ;
+#ifndef        SLIM_SMT
+#ifndef BOOT
+#ifdef ESS
+       ess_timer_poll(smc) ;
+#endif
+#endif
+#ifdef SBA
+       sba_timer_poll(smc) ;
+#endif
+
+       smt_srf_event(smc,0,0,0) ;
+
+#endif /* no SLIM_SMT */
+
+       time = smt_get_time() ;
+
+       if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {
+               /*
+                * Use 8 sec. for the time intervall, it simplifies the
+                * LER estimation.
+                */
+               struct fddi_mib_m       *mib ;
+               u_long                  upper ;
+               u_long                  lower ;
+               int                     cond ;
+               int                     port;
+               struct s_phy            *phy ;
+               /*
+                * calculate LEM bit error rate
+                */
+               sm_lem_evaluate(smc) ;
+               smc->sm.smt_last_lem = time ;
+
+               /*
+                * check conditions
+                */
+#ifndef        SLIM_SMT
+               mac_update_counter(smc) ;
+               mib = smc->mib.m ;
+               upper =
+               (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +
+               (mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;
+               lower =
+               (mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +
+               (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;
+               mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;
+
+               cond =
+                       ((!mib->fddiMACFrameErrorThreshold &&
+                       mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||
+                       (mib->fddiMACFrameErrorRatio >
+                       mib->fddiMACFrameErrorThreshold)) ;
+
+               if (cond != mib->fddiMACFrameErrorFlag)
+                       smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,
+                               INDEX_MAC,cond) ;
+
+               upper =
+               (mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;
+               lower =
+               upper +
+               (mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;
+               mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;
+
+               cond =
+                       ((!mib->fddiMACNotCopiedThreshold &&
+                       mib->fddiMACNotCopied_Ct !=
+                               mib->fddiMACOld_NotCopied_Ct)||
+                       (mib->fddiMACNotCopiedRatio >
+                       mib->fddiMACNotCopiedThreshold)) ;
+
+               if (cond != mib->fddiMACNotCopiedFlag)
+                       smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,
+                               INDEX_MAC,cond) ;
+
+               /*
+                * set old values
+                */
+               mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;
+               mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;
+               mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;
+               mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;
+               mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;
+
+               /*
+                * Check port EBError Condition
+                */
+               for (port = 0; port < NUMPHYS; port ++) {
+                       phy = &smc->y[port] ;
+
+                       if (!phy->mib->fddiPORTHardwarePresent) {
+                               continue;
+                       }
+
+                       cond = (phy->mib->fddiPORTEBError_Ct -
+                               phy->mib->fddiPORTOldEBError_Ct > 5) ;
+
+                       /* If ratio is more than 5 in 8 seconds
+                        * Set the condition.
+                        */
+                       smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,
+                               (int) (INDEX_PORT+ phy->np) ,cond) ;
+
+                       /*
+                        * set old values
+                        */
+                       phy->mib->fddiPORTOldEBError_Ct =
+                               phy->mib->fddiPORTEBError_Ct ;
+               }
+
+#endif /* no SLIM_SMT */
+       }
+
+#ifndef        SLIM_SMT
+
+       if (time - smc->sm.smt_last_notify >= (u_long)
+               (smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {
+               /*
+                * we can either send an announcement or a request
+                * a request will trigger a reply so that we can update
+                * our dna
+                * note: same tid must be used until reply is received
+                */
+               if (!smc->sm.pend[SMT_TID_NIF])
+                       smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
+               smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,
+                       smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
+               smc->sm.smt_last_notify = time ;
+       }
+
+       /*
+        * check timer
+        */
+       if (smc->sm.smt_tvu &&
+           time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {
+               DB_SMT("SMT : UNA expired\n",0,0) ;
+               smc->sm.smt_tvu = 0 ;
+
+               if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,
+                       &SMT_Unknown)){
+                       /* Do not update unknown address */
+                       smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
+                               smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+               }
+               smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
+               smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
+               /*
+                * Make sure the fddiMACUNDA_Flag = FALSE is
+                * included in the SRF so we don't generate
+                * a separate SRF for the deassertion of this
+                * condition
+                */
+               update_dac(smc,0) ;
+               smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+                       INDEX_MAC,0) ;
+       }
+       if (smc->sm.smt_tvd &&
+           time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {
+               DB_SMT("SMT : DNA expired\n",0,0) ;
+               smc->sm.smt_tvd = 0 ;
+               if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,
+                       &SMT_Unknown)){
+                       /* Do not update unknown address */
+                       smc->mib.m[MAC0].fddiMACOldDownstreamNbr=
+                               smc->mib.m[MAC0].fddiMACDownstreamNbr ;
+               }
+               smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
+               smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+                       INDEX_MAC,0) ;
+       }
+
+#endif /* no SLIM_SMT */
+
+#ifndef SMT_REAL_TOKEN_CT
+       /*
+        * Token counter emulation section. If hardware supports the token
+        * count, the token counter will be updated in mac_update_counter.
+        */
+       for (i = MAC0; i < NUMMACS; i++ ){
+               if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){
+                       smt_emulate_token_ct( smc, i );
+               }
+       }
+#endif
+
+       smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
+               EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
+}
+
+static int div_ratio(u_long upper, u_long lower)
+{
+       if ((upper<<16L) < upper)
+               upper = 0xffff0000L ;
+       else
+               upper <<= 16L ;
+       if (!lower)
+               return 0;
+       return (int)(upper/lower) ;
+}
+
+#ifndef        SLIM_SMT
+
+/*
+ * receive packet handler
+ */
+void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)
+/* int fs;  frame status */
+{
+       struct smt_header       *sm ;
+       int                     local ;
+
+       int                     illegal = 0 ;
+
+       switch (m_fc(mb)) {
+       case FC_SMT_INFO :
+       case FC_SMT_LAN_LOC :
+       case FC_SMT_LOC :
+       case FC_SMT_NSA :
+               break ;
+       default :
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+
+       smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;
+       sm = smtod(mb,struct smt_header *) ;
+       local = ((fs & L_INDICATOR) != 0) ;
+       hwm_conv_can(smc,(char *)sm,12) ;
+
+       /* check destination address */
+       if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+#if    0               /* for DUP recognition, do NOT filter them */
+       /* ignore loop back packets */
+       if (is_my_addr(smc,&sm->smt_source) && !local) {
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+#endif
+
+       smt_swap_para(sm,(int) mb->sm_len,1) ;
+       DB_SMT("SMT : received packet [%s] at 0x%x\n",
+               smt_type_name[m_fc(mb) & 0xf],sm) ;
+       DB_SMT("SMT : version %d, class %s\n",sm->smt_version,
+               smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ;
+
+#ifdef SBA
+       /*
+        * check if NSA frame
+        */
+       if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&
+               (sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {
+                       smc->sba.sm = sm ;
+                       sba(smc,NIF) ;
+       }
+#endif
+
+       /*
+        * ignore any packet with NSA and A-indicator set
+        */
+       if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {
+               DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",
+                       addr_to_string(&sm->smt_source),0) ;
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+
+       /*
+        * ignore frames with illegal length
+        */
+       if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||
+           ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+
+       /*
+        * check SMT version
+        */
+       switch (sm->smt_class) {
+       case SMT_NIF :
+       case SMT_SIF_CONFIG :
+       case SMT_SIF_OPER :
+       case SMT_ECF :
+               if (sm->smt_version != SMT_VID)
+                       illegal = 1;
+               break ;
+       default :
+               if (sm->smt_version != SMT_VID_2)
+                       illegal = 1;
+               break ;
+       }
+       if (illegal) {
+               DB_SMT("SMT : version = %d, dest = %s\n",
+                       sm->smt_version,addr_to_string(&sm->smt_source)) ;
+               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+       if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||
+           ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {
+               DB_SMT("SMT: info length error, len = %d\n",sm->smt_len,0) ;
+               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+       switch (sm->smt_class) {
+       case SMT_NIF :
+               if (smt_check_para(smc,sm,plist_nif)) {
+                       DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ;
+                       break ;
+               }
+               switch (sm->smt_type) {
+               case SMT_ANNOUNCE :
+               case SMT_REQUEST :
+                       if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA
+                               && is_broadcast(&sm->smt_dest)) {
+                               struct smt_p_state      *st ;
+
+                               /* set my UNA */
+                               if (!is_equal(
+                                       &smc->mib.m[MAC0].fddiMACUpstreamNbr,
+                                       &sm->smt_source)) {
+                                       DB_SMT("SMT : updated my UNA = %s\n",
+                                       addr_to_string(&sm->smt_source),0) ;
+                                       if (!is_equal(&smc->mib.m[MAC0].
+                                           fddiMACUpstreamNbr,&SMT_Unknown)){
+                                        /* Do not update unknown address */
+                                        smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
+                                        smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+                                       }
+
+                                       smc->mib.m[MAC0].fddiMACUpstreamNbr =
+                                               sm->smt_source ;
+                                       smt_srf_event(smc,
+                                               SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+                                               INDEX_MAC,0) ;
+                                       smt_echo_test(smc,0) ;
+                               }
+                               smc->sm.smt_tvu = smt_get_time() ;
+                               st = (struct smt_p_state *)
+                                       sm_to_para(smc,sm,SMT_P_STATE) ;
+                               if (st) {
+                                       smc->mib.m[MAC0].fddiMACUNDA_Flag =
+                                       (st->st_dupl_addr & SMT_ST_MY_DUPA) ?
+                                       TRUE : FALSE ;
+                                       update_dac(smc,1) ;
+                               }
+                       }
+                       if ((sm->smt_type == SMT_REQUEST) &&
+                           is_individual(&sm->smt_source) &&
+                           ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||
+                            (m_fc(mb) != FC_SMT_NSA))) {
+                               DB_SMT("SMT : replying to NIF request %s\n",
+                                       addr_to_string(&sm->smt_source),0) ;
+                               smt_send_nif(smc,&sm->smt_source,
+                                       FC_SMT_INFO,
+                                       sm->smt_tid,
+                                       SMT_REPLY,local) ;
+                       }
+                       break ;
+               case SMT_REPLY :
+                       DB_SMT("SMT : received NIF response from %s\n",
+                               addr_to_string(&sm->smt_source),0) ;
+                       if (fs & A_INDICATOR) {
+                               smc->sm.pend[SMT_TID_NIF] = 0 ;
+                               DB_SMT("SMT : duplicate address\n",0,0) ;
+                               smc->mib.m[MAC0].fddiMACDupAddressTest =
+                                       DA_FAILED ;
+                               smc->r.dup_addr_test = DA_FAILED ;
+                               queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
+                               smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;
+                               update_dac(smc,1) ;
+                               break ;
+                       }
+                       if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {
+                               smc->sm.pend[SMT_TID_NIF] = 0 ;
+                               /* set my DNA */
+                               if (!is_equal(
+                                       &smc->mib.m[MAC0].fddiMACDownstreamNbr,
+                                       &sm->smt_source)) {
+                                       DB_SMT("SMT : updated my DNA\n",0,0) ;
+                                       if (!is_equal(&smc->mib.m[MAC0].
+                                        fddiMACDownstreamNbr, &SMT_Unknown)){
+                                        /* Do not update unknown address */
+                               smc->mib.m[MAC0].fddiMACOldDownstreamNbr =
+                                        smc->mib.m[MAC0].fddiMACDownstreamNbr ;
+                                       }
+
+                                       smc->mib.m[MAC0].fddiMACDownstreamNbr =
+                                               sm->smt_source ;
+                                       smt_srf_event(smc,
+                                               SMT_EVENT_MAC_NEIGHBOR_CHANGE,
+                                               INDEX_MAC,0) ;
+                                       smt_echo_test(smc,1) ;
+                               }
+                               smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;
+                               update_dac(smc,1) ;
+                               smc->sm.smt_tvd = smt_get_time() ;
+                               smc->mib.m[MAC0].fddiMACDupAddressTest =
+                                       DA_PASSED ;
+                               if (smc->r.dup_addr_test != DA_PASSED) {
+                                       smc->r.dup_addr_test = DA_PASSED ;
+                                       queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
+                               }
+                       }
+                       else if (sm->smt_tid ==
+                               smc->sm.pend[SMT_TID_NIF_TEST]) {
+                               DB_SMT("SMT : NIF test TID ok\n",0,0) ;
+                       }
+                       else {
+                               DB_SMT("SMT : expected TID %lx, got %lx\n",
+                               smc->sm.pend[SMT_TID_NIF],sm->smt_tid) ;
+                       }
+                       break ;
+               default :
+                       illegal = 2 ;
+                       break ;
+               }
+               break ;
+       case SMT_SIF_CONFIG :   /* station information */
+               if (sm->smt_type != SMT_REQUEST)
+                       break ;
+               DB_SMT("SMT : replying to SIF Config request from %s\n",
+                       addr_to_string(&sm->smt_source),0) ;
+               smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;
+               break ;
+       case SMT_SIF_OPER :     /* station information */
+               if (sm->smt_type != SMT_REQUEST)
+                       break ;
+               DB_SMT("SMT : replying to SIF Operation request from %s\n",
+                       addr_to_string(&sm->smt_source),0) ;
+               smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;
+               break ;
+       case SMT_ECF :          /* echo frame */
+               switch (sm->smt_type) {
+               case SMT_REPLY :
+                       smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;
+                       DB_SMT("SMT: received ECF reply from %s\n",
+                               addr_to_string(&sm->smt_source),0) ;
+                       if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) {
+                               DB_SMT("SMT: ECHODATA missing\n",0,0) ;
+                               break ;
+                       }
+                       if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {
+                               DB_SMT("SMT : ECF test TID ok\n",0,0) ;
+                       }
+                       else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {
+                               DB_SMT("SMT : ECF test UNA ok\n",0,0) ;
+                       }
+                       else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {
+                               DB_SMT("SMT : ECF test DNA ok\n",0,0) ;
+                       }
+                       else {
+                               DB_SMT("SMT : expected TID %lx, got %lx\n",
+                                       smc->sm.pend[SMT_TID_ECF],
+                                       sm->smt_tid) ;
+                       }
+                       break ;
+               case SMT_REQUEST :
+                       smc->mib.priv.fddiPRIVECF_Req_Rx++ ;
+                       {
+                       if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {
+                       DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ;
+                               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,
+                                       local) ;
+                               break ;
+                       }
+                       DB_SMT("SMT - sending ECF reply to %s\n",
+                               addr_to_string(&sm->smt_source),0) ;
+
+                       /* set destination addr.  & reply */
+                       sm->smt_dest = sm->smt_source ;
+                       sm->smt_type = SMT_REPLY ;
+                       dump_smt(smc,sm,"ECF REPLY") ;
+                       smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;
+                       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+                       return ;                /* DON'T free mbuf */
+                       }
+               default :
+                       illegal = 1 ;
+                       break ;
+               }
+               break ;
+#ifndef        BOOT
+       case SMT_RAF :          /* resource allocation */
+#ifdef ESS
+               DB_ESSN(2,"ESS: RAF frame received\n",0,0) ;
+               fs = ess_raf_received_pack(smc,mb,sm,fs) ;
+#endif
+
+#ifdef SBA
+               DB_SBAN(2,"SBA: RAF frame received\n",0,0) ;
+               sba_raf_received_pack(smc,sm,fs) ;
+#endif
+               break ;
+       case SMT_RDF :          /* request denied */
+               smc->mib.priv.fddiPRIVRDF_Rx++ ;
+               break ;
+       case SMT_ESF :          /* extended service - not supported */
+               if (sm->smt_type == SMT_REQUEST) {
+                       DB_SMT("SMT - received ESF, sending RDF\n",0,0) ;
+                       smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
+               }
+               break ;
+       case SMT_PMF_GET :
+       case SMT_PMF_SET :
+               if (sm->smt_type != SMT_REQUEST)
+                       break ;
+               /* update statistics */
+               if (sm->smt_class == SMT_PMF_GET)
+                       smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;
+               else
+                       smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;
+               /*
+                * ignore PMF SET with I/G set
+                */
+               if ((sm->smt_class == SMT_PMF_SET) &&
+                       !is_individual(&sm->smt_dest)) {
+                       DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ;
+                       break ;
+               }
+               smt_pmf_received_pack(smc,mb, local) ;
+               break ;
+       case SMT_SRF :
+               dump_smt(smc,sm,"SRF received") ;
+               break ;
+       default :
+               if (sm->smt_type != SMT_REQUEST)
+                       break ;
+               /*
+                * For frames with unknown class:
+                * we need to send a RDF frame according to 8.1.3.1.1,
+                * only if it is a REQUEST.
+                */
+               DB_SMT("SMT : class = %d, send RDF to %s\n",
+                       sm->smt_class, addr_to_string(&sm->smt_source)) ;
+
+               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
+               break ;
+#endif
+       }
+       if (illegal) {
+               DB_SMT("SMT: discarding invalid frame, reason = %d\n",
+                       illegal,0) ;
+       }
+       smt_free_mbuf(smc,mb) ;
+}
+
+static void update_dac(struct s_smc *smc, int report)
+{
+       int     cond ;
+
+       cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |
+               smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;
+       if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))
+               smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;
+       else
+               smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;
+}
+
+/*
+ * send SMT frame
+ *     set source address
+ *     set station ID
+ *     send frame
+ */
+void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local)
+/* SMbuf *mb;  buffer to send */
+/* int fc;     FC value */
+{
+       struct smt_header       *sm ;
+
+       if (!smc->r.sm_ma_avail && !local) {
+               smt_free_mbuf(smc,mb) ;
+               return ;
+       }
+       sm = smtod(mb,struct smt_header *) ;
+       sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
+       sm->smt_sid = smc->mib.fddiSMTStationId ;
+
+       smt_swap_para(sm,(int) mb->sm_len,0) ;          /* swap para & header */
+       hwm_conv_can(smc,(char *)sm,12) ;               /* convert SA and DA */
+       smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ;
+       smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ;
+}
+
+/*
+ * generate and send RDF
+ */
+static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
+                        int local)
+/* SMbuf *rej; mbuf of offending frame */
+/* int fc;     FC of denied frame */
+/* int reason; reason code */
+{
+       SMbuf   *mb ;
+       struct smt_header       *sm ;   /* header of offending frame */
+       struct smt_rdf  *rdf ;
+       int             len ;
+       int             frame_len ;
+
+       sm = smtod(rej,struct smt_header *) ;
+       if (sm->smt_type != SMT_REQUEST)
+               return ;
+
+       DB_SMT("SMT: sending RDF to %s,reason = 0x%x\n",
+               addr_to_string(&sm->smt_source),reason) ;
+
+
+       /*
+        * note: get framelength from MAC length, NOT from SMT header
+        * smt header length is included in sm_len
+        */
+       frame_len = rej->sm_len ;
+
+       if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf))))
+               return ;
+       rdf = smtod(mb,struct smt_rdf *) ;
+       rdf->smt.smt_tid = sm->smt_tid ;                /* use TID from sm */
+       rdf->smt.smt_dest = sm->smt_source ;            /* set dest = source */
+
+       /* set P12 */
+       rdf->reason.para.p_type = SMT_P_REASON ;
+       rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ;
+       rdf->reason.rdf_reason = reason ;
+
+       /* set P14 */
+       rdf->version.para.p_type = SMT_P_VERSION ;
+       rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ;
+       rdf->version.v_pad = 0 ;
+       rdf->version.v_n = 1 ;
+       rdf->version.v_index = 1 ;
+       rdf->version.v_version[0] = SMT_VID_2 ;
+       rdf->version.v_pad2 = 0 ;
+
+       /* set P13 */
+       if ((unsigned) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) +
+               2*sizeof(struct smt_header))
+               len = frame_len ;
+       else
+               len = SMT_MAX_INFO_LEN - sizeof(*rdf) +
+                       2*sizeof(struct smt_header) ;
+       /* make length multiple of 4 */
+       len &= ~3 ;
+       rdf->refused.para.p_type = SMT_P_REFUSED ;
+       /* length of para is smt_frame + ref_fc */
+       rdf->refused.para.p_len = len + 4 ;
+       rdf->refused.ref_fc = fc ;
+
+       /* swap it back */
+       smt_swap_para(sm,frame_len,0) ;
+
+       memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ;
+
+       len -= sizeof(struct smt_header) ;
+       mb->sm_len += len ;
+       rdf->smt.smt_len += len ;
+
+       dump_smt(smc,(struct smt_header *)rdf,"RDF") ;
+       smc->mib.priv.fddiPRIVRDF_Tx++ ;
+       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+}
+
+/*
+ * generate and send NIF
+ */
+static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 
+                        int fc, u_long tid, int type, int local)
+/* struct fddi_addr *dest;     dest address */
+/* int fc;                     frame control */
+/* u_long tid;                 transaction id */
+/* int type;                   frame type */
+{
+       struct smt_nif  *nif ;
+       SMbuf           *mb ;
+
+       if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif))))
+               return ;
+       nif = smtod(mb, struct smt_nif *) ;
+       smt_fill_una(smc,&nif->una) ;   /* set UNA */
+       smt_fill_sde(smc,&nif->sde) ;   /* set station descriptor */
+       smt_fill_state(smc,&nif->state) ;       /* set state information */
+#ifdef SMT6_10
+       smt_fill_fsc(smc,&nif->fsc) ;   /* set frame status cap. */
+#endif
+       nif->smt.smt_dest = *dest ;     /* destination address */
+       nif->smt.smt_tid = tid ;        /* transaction ID */
+       dump_smt(smc,(struct smt_header *)nif,"NIF") ;
+       smt_send_frame(smc,mb,fc,local) ;
+}
+
+#ifdef DEBUG
+/*
+ * send NIF request (test purpose)
+ */
+static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest)
+{
+       smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;
+       smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],
+               SMT_REQUEST,0) ;
+}
+
+/*
+ * send ECF request (test purpose)
+ */
+static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest,
+                                int len)
+{
+       smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;
+       smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],
+               SMT_REQUEST,len) ;
+}
+#endif
+
+/*
+ * echo test
+ */
+static void smt_echo_test(struct s_smc *smc, int dna)
+{
+       u_long  tid ;
+
+       smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] =
+               tid = smt_get_tid(smc) ;
+       smt_send_ecf(smc, dna ?
+               &smc->mib.m[MAC0].fddiMACDownstreamNbr :
+               &smc->mib.m[MAC0].fddiMACUpstreamNbr,
+               FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ;
+}
+
+/*
+ * generate and send ECF
+ */
+static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
+                        u_long tid, int type, int len)
+/* struct fddi_addr *dest;     dest address */
+/* int fc;                     frame control */
+/* u_long tid;                 transaction id */
+/* int type;                   frame type */
+/* int len;                    frame length */
+{
+       struct smt_ecf  *ecf ;
+       SMbuf           *mb ;
+
+       if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len)))
+               return ;
+       ecf = smtod(mb, struct smt_ecf *) ;
+
+       smt_fill_echo(smc,&ecf->ec_echo,tid,len) ;      /* set ECHO */
+       ecf->smt.smt_dest = *dest ;     /* destination address */
+       ecf->smt.smt_tid = tid ;        /* transaction ID */
+       smc->mib.priv.fddiPRIVECF_Req_Tx++ ;
+       smt_send_frame(smc,mb,fc,0) ;
+}
+
+/*
+ * generate and send SIF config response
+ */
+
+static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
+                               u_long tid, int local)
+/* struct fddi_addr *dest;     dest address */
+/* u_long tid;                 transaction id */
+{
+       struct smt_sif_config   *sif ;
+       SMbuf                   *mb ;
+       int                     len ;
+       if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY,
+               SIZEOF_SMT_SIF_CONFIG)))
+               return ;
+
+       sif = smtod(mb, struct smt_sif_config *) ;
+       smt_fill_timestamp(smc,&sif->ts) ;      /* set time stamp */
+       smt_fill_sde(smc,&sif->sde) ;           /* set station descriptor */
+       smt_fill_version(smc,&sif->version) ;   /* set version information */
+       smt_fill_state(smc,&sif->state) ;       /* set state information */
+       smt_fill_policy(smc,&sif->policy) ;     /* set station policy */
+       smt_fill_latency(smc,&sif->latency);    /* set station latency */
+       smt_fill_neighbor(smc,&sif->neighbor);  /* set station neighbor */
+       smt_fill_setcount(smc,&sif->setcount) ; /* set count */
+       len = smt_fill_path(smc,&sif->path);    /* set station path descriptor*/
+       sif->smt.smt_dest = *dest ;             /* destination address */
+       sif->smt.smt_tid = tid ;                /* transaction ID */
+       smt_add_frame_len(mb,len) ;             /* adjust length fields */
+       dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ;
+       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+}
+
+/*
+ * generate and send SIF operation response
+ */
+
+static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
+                                  u_long tid, int local)
+/* struct fddi_addr *dest;     dest address */
+/* u_long tid;                 transaction id */
+{
+       struct smt_sif_operation *sif ;
+       SMbuf                   *mb ;
+       int                     ports ;
+       int                     i ;
+
+       ports = NUMPHYS ;
+#ifndef        CONCENTRATOR
+       if (smc->s.sas == SMT_SAS)
+               ports = 1 ;
+#endif
+
+       if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY,
+               SIZEOF_SMT_SIF_OPERATION+ports*sizeof(struct smt_p_lem))))
+               return ;
+       sif = smtod(mb, struct smt_sif_operation *) ;
+       smt_fill_timestamp(smc,&sif->ts) ;      /* set time stamp */
+       smt_fill_mac_status(smc,&sif->status) ; /* set mac status */
+       smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */
+       smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */
+       smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */
+       smt_fill_user(smc,&sif->user) ;         /* set user field */
+       smt_fill_setcount(smc,&sif->setcount) ; /* set count */
+       /*
+        * set link error mon information
+        */
+       if (ports == 1) {
+               smt_fill_lem(smc,sif->lem,PS) ;
+       }
+       else {
+               for (i = 0 ; i < ports ; i++) {
+                       smt_fill_lem(smc,&sif->lem[i],i) ;
+               }
+       }
+
+       sif->smt.smt_dest = *dest ;     /* destination address */
+       sif->smt.smt_tid = tid ;        /* transaction ID */
+       dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ;
+       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
+}
+
+/*
+ * get and initialize SMT frame
+ */
+SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
+                                 int length)
+{
+       SMbuf                   *mb ;
+       struct smt_header       *smt ;
+
+#if    0
+       if (!smc->r.sm_ma_avail) {
+               return 0;
+       }
+#endif
+       if (!(mb = smt_get_mbuf(smc)))
+               return mb;
+
+       mb->sm_len = length ;
+       smt = smtod(mb, struct smt_header *) ;
+       smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */
+       smt->smt_class = class ;
+       smt->smt_type = type ;
+       switch (class) {
+       case SMT_NIF :
+       case SMT_SIF_CONFIG :
+       case SMT_SIF_OPER :
+       case SMT_ECF :
+               smt->smt_version = SMT_VID ;
+               break ;
+       default :
+               smt->smt_version = SMT_VID_2 ;
+               break ;
+       }
+       smt->smt_tid = smt_get_tid(smc) ;       /* set transaction ID */
+       smt->smt_pad = 0 ;
+       smt->smt_len = length - sizeof(struct smt_header) ;
+       return mb;
+}
+
+static void smt_add_frame_len(SMbuf *mb, int len)
+{
+       struct smt_header       *smt ;
+
+       smt = smtod(mb, struct smt_header *) ;
+       smt->smt_len += len ;
+       mb->sm_len += len ;
+}
+
+
+
+/*
+ * fill values in UNA parameter
+ */
+static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una)
+{
+       SMTSETPARA(una,SMT_P_UNA) ;
+       una->una_pad = 0 ;
+       una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+}
+
+/*
+ * fill values in SDE parameter
+ */
+static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde)
+{
+       SMTSETPARA(sde,SMT_P_SDE) ;
+       sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ;
+       sde->sde_master = smc->mib.fddiSMTMaster_Ct ;
+       sde->sde_mac_count = NUMMACS ;          /* only 1 MAC */
+#ifdef CONCENTRATOR
+       sde->sde_type = SMT_SDE_CONCENTRATOR ;
+#else
+       sde->sde_type = SMT_SDE_STATION ;
+#endif
+}
+
+/*
+ * fill in values in station state parameter
+ */
+static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state)
+{
+       int     top ;
+       int     twist ;
+
+       SMTSETPARA(state,SMT_P_STATE) ;
+       state->st_pad = 0 ;
+
+       /* determine topology */
+       top = 0 ;
+       if (smc->mib.fddiSMTPeerWrapFlag) {
+               top |= SMT_ST_WRAPPED ;         /* state wrapped */
+       }
+#ifdef CONCENTRATOR
+       if (cfm_status_unattached(smc)) {
+               top |= SMT_ST_UNATTACHED ;      /* unattached concentrator */
+       }
+#endif
+       if ((twist = pcm_status_twisted(smc)) & 1) {
+               top |= SMT_ST_TWISTED_A ;       /* twisted cable */
+       }
+       if (twist & 2) {
+               top |= SMT_ST_TWISTED_B ;       /* twisted cable */
+       }
+#ifdef OPT_SRF
+       top |= SMT_ST_SRF ;
+#endif
+       if (pcm_rooted_station(smc))
+               top |= SMT_ST_ROOTED_S ;
+       if (smc->mib.a[0].fddiPATHSbaPayload != 0)
+               top |= SMT_ST_SYNC_SERVICE ;
+       state->st_topology = top ;
+       state->st_dupl_addr =
+               ((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) |
+                (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ;
+}
+
+/*
+ * fill values in timestamp parameter
+ */
+static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts)
+{
+
+       SMTSETPARA(ts,SMT_P_TIMESTAMP) ;
+       smt_set_timestamp(smc,ts->ts_time) ;
+}
+
+void smt_set_timestamp(struct s_smc *smc, u_char *p)
+{
+       u_long  time ;
+       u_long  utime ;
+
+       /*
+        * timestamp is 64 bits long ; resolution is 80 nS
+        * our clock resolution is 10mS
+        * 10mS/80ns = 125000 ~ 2^17 = 131072
+        */
+       utime = smt_get_time() ;
+       time = utime * 100 ;
+       time /= TICKS_PER_SECOND ;
+       p[0] = 0 ;
+       p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ;
+       p[2] = (u_char)(time>>(8+8+8-1)) ;
+       p[3] = (u_char)(time>>(8+8-1)) ;
+       p[4] = (u_char)(time>>(8-1)) ;
+       p[5] = (u_char)(time<<1) ;
+       p[6] = (u_char)(smc->sm.uniq_ticks>>8) ;
+       p[7] = (u_char)smc->sm.uniq_ticks ;
+       /*
+        * make sure we don't wrap: restart whenever the upper digits change
+        */
+       if (utime != smc->sm.uniq_time) {
+               smc->sm.uniq_ticks = 0 ;
+       }
+       smc->sm.uniq_ticks++ ;
+       smc->sm.uniq_time = utime ;
+}
+
+/*
+ * fill values in station policy parameter
+ */
+static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy)
+{
+       int     i ;
+       const u_char *map ;
+       u_short in ;
+       u_short out ;
+
+       /*
+        * MIB para 101b (fddiSMTConnectionPolicy) coding
+        * is different from 0005 coding
+        */
+       static const u_char ansi_weirdness[16] = {
+               0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15
+       } ;
+       SMTSETPARA(policy,SMT_P_POLICY) ;
+
+       out = 0 ;
+       in = smc->mib.fddiSMTConnectionPolicy ;
+       for (i = 0, map = ansi_weirdness ; i < 16 ; i++) {
+               if (in & 1)
+                       out |= (1<<*map) ;
+               in >>= 1 ;
+               map++ ;
+       }
+       policy->pl_config = smc->mib.fddiSMTConfigPolicy ;
+       policy->pl_connect = out ;
+}
+
+/*
+ * fill values in latency equivalent parameter
+ */
+static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency)
+{
+       SMTSETPARA(latency,SMT_P_LATENCY) ;
+
+       latency->lt_phyout_idx1 = phy_index(smc,0) ;
+       latency->lt_latency1 = 10 ;     /* in octets (byte clock) */
+       /*
+        * note: latency has two phy entries by definition
+        * for a SAS, the 2nd one is null
+        */
+       if (smc->s.sas == SMT_DAS) {
+               latency->lt_phyout_idx2 = phy_index(smc,1) ;
+               latency->lt_latency2 = 10 ;     /* in octets (byte clock) */
+       }
+       else {
+               latency->lt_phyout_idx2 = 0 ;
+               latency->lt_latency2 = 0 ;
+       }
+}
+
+/*
+ * fill values in MAC neighbors parameter
+ */
+static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor)
+{
+       SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ;
+
+       neighbor->nb_mib_index = INDEX_MAC ;
+       neighbor->nb_mac_index = mac_index(smc,1) ;
+       neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
+       neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ;
+}
+
+/*
+ * fill values in path descriptor
+ */
+#ifdef CONCENTRATOR
+#define ALLPHYS        NUMPHYS
+#else
+#define ALLPHYS        ((smc->s.sas == SMT_SAS) ? 1 : 2)
+#endif
+
+static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path)
+{
+       SK_LOC_DECL(int,type) ;
+       SK_LOC_DECL(int,state) ;
+       SK_LOC_DECL(int,remote) ;
+       SK_LOC_DECL(int,mac) ;
+       int     len ;
+       int     p ;
+       int     physp ;
+       struct smt_phy_rec      *phy ;
+       struct smt_mac_rec      *pd_mac ;
+
+       len =   PARA_LEN +
+               sizeof(struct smt_mac_rec) * NUMMACS +
+               sizeof(struct smt_phy_rec) * ALLPHYS ;
+       path->para.p_type = SMT_P_PATH ;
+       path->para.p_len = len - PARA_LEN ;
+
+       /* PHYs */
+       for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) {
+               physp = p ;
+#ifndef        CONCENTRATOR
+               if (smc->s.sas == SMT_SAS)
+                       physp = PS ;
+#endif
+               pcm_status_state(smc,physp,&type,&state,&remote,&mac) ;
+#ifdef LITTLE_ENDIAN
+               phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ;
+#else
+               phy->phy_mib_index = p+INDEX_PORT ;
+#endif
+               phy->phy_type = type ;
+               phy->phy_connect_state = state ;
+               phy->phy_remote_type = remote ;
+               phy->phy_remote_mac = mac ;
+               phy->phy_resource_idx = phy_con_resource_index(smc,p) ;
+       }
+
+       /* MAC */
+       pd_mac = (struct smt_mac_rec *) phy ;
+       pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;
+       pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;
+       return len;
+}
+
+/*
+ * fill values in mac status
+ */
+static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st)
+{
+       SMTSETPARA(st,SMT_P_MAC_STATUS) ;
+
+       st->st_mib_index = INDEX_MAC ;
+       st->st_mac_index = mac_index(smc,1) ;
+
+       mac_update_counter(smc) ;
+       /*
+        * timer values are represented in SMT as 2's complement numbers
+        * units :      internal :  2's complement BCLK
+        */
+       st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ;
+       st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ;
+       st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ;
+       st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ;
+       st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ;
+
+       st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ;
+       st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ;
+       st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ;
+       st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ;
+}
+
+/*
+ * fill values in LEM status
+ */
+static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy)
+{
+       struct fddi_mib_p       *mib ;
+
+       mib = smc->y[phy].mib ;
+
+       SMTSETPARA(lem,SMT_P_LEM) ;
+       lem->lem_mib_index = phy+INDEX_PORT ;
+       lem->lem_phy_index = phy_index(smc,phy) ;
+       lem->lem_pad2 = 0 ;
+       lem->lem_cutoff = mib->fddiPORTLer_Cutoff ;
+       lem->lem_alarm = mib->fddiPORTLer_Alarm ;
+       /* long term bit error rate */
+       lem->lem_estimate = mib->fddiPORTLer_Estimate ;
+       /* # of rejected connections */
+       lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ;
+       lem->lem_ct = mib->fddiPORTLem_Ct ;     /* total number of errors */
+}
+
+/*
+ * fill version parameter
+ */
+static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers)
+{
+       SK_UNUSED(smc) ;
+       SMTSETPARA(vers,SMT_P_VERSION) ;
+       vers->v_pad = 0 ;
+       vers->v_n = 1 ;                         /* one version is enough .. */
+       vers->v_index = 1 ;
+       vers->v_version[0] = SMT_VID_2 ;
+       vers->v_pad2 = 0 ;
+}
+
+#ifdef SMT6_10
+/*
+ * fill frame status capabilities
+ */
+/*
+ * note: this para 200B is NOT in swap table, because it's also set in
+ * PMF add_para
+ */
+static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc)
+{
+       SK_UNUSED(smc) ;
+       SMTSETPARA(fsc,SMT_P_FSC) ;
+       fsc->fsc_pad0 = 0 ;
+       fsc->fsc_mac_index = INDEX_MAC ;        /* this is MIB ; MIB is NOT
+                                                * mac_index ()i !
+                                                */
+       fsc->fsc_pad1 = 0 ;
+       fsc->fsc_value = FSC_TYPE0 ;            /* "normal" node */
+#ifdef LITTLE_ENDIAN
+       fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ;
+       fsc->fsc_value = smt_swap_short(FSC_TYPE0) ;
+#endif
+}
+#endif
+
+/*
+ * fill mac counter field
+ */
+static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc)
+{
+       SMTSETPARA(mc,SMT_P_MAC_COUNTER) ;
+       mc->mc_mib_index = INDEX_MAC ;
+       mc->mc_index = mac_index(smc,1) ;
+       mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ;
+       mc->mc_transmit_ct =  smc->mib.m[MAC0].fddiMACTransmit_Ct ;
+}
+
+/*
+ * fill mac frame not copied counter
+ */
+static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc)
+{
+       SMTSETPARA(fnc,SMT_P_MAC_FNC) ;
+       fnc->nc_mib_index = INDEX_MAC ;
+       fnc->nc_index = mac_index(smc,1) ;
+       fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ;
+}
+
+
+/*
+ * fill manufacturer field
+ */
+static void smt_fill_manufacturer(struct s_smc *smc, 
+                                 struct smp_p_manufacturer *man)
+{
+       SMTSETPARA(man,SMT_P_MANUFACTURER) ;
+       memcpy((char *) man->mf_data,
+               (char *) smc->mib.fddiSMTManufacturerData,
+               sizeof(man->mf_data)) ;
+}
+
+/*
+ * fill user field
+ */
+static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user)
+{
+       SMTSETPARA(user,SMT_P_USER) ;
+       memcpy((char *) user->us_data,
+               (char *) smc->mib.fddiSMTUserData,
+               sizeof(user->us_data)) ;
+}
+
+/*
+ * fill set count
+ */
+static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount)
+{
+       SK_UNUSED(smc) ;
+       SMTSETPARA(setcount,SMT_P_SETCOUNT) ;
+       setcount->count = smc->mib.fddiSMTSetCount.count ;
+       memcpy((char *)setcount->timestamp,
+               (char *)smc->mib.fddiSMTSetCount.timestamp,8) ;
+}
+
+/*
+ * fill echo data
+ */
+static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
+                         int len)
+{
+       u_char  *p ;
+
+       SK_UNUSED(smc) ;
+       SMTSETPARA(echo,SMT_P_ECHODATA) ;
+       echo->para.p_len = len ;
+       for (p = echo->ec_data ; len ; len--) {
+               *p++ = (u_char) seed ;
+               seed += 13 ;
+       }
+}
+
+/*
+ * clear DNA and UNA
+ * called from CFM if configuration changes
+ */
+static void smt_clear_una_dna(struct s_smc *smc)
+{
+       smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
+       smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
+}
+
+static void smt_clear_old_una_dna(struct s_smc *smc)
+{
+       smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ;
+       smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ;
+}
+
+u_long smt_get_tid(struct s_smc *smc)
+{
+       u_long  tid ;
+       while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
+               ;
+       return tid & 0x3fffffffL;
+}
+
+
+/*
+ * table of parameter lengths
+ */
+static const struct smt_pdef {
+       int     ptype ;
+       int     plen ;
+       const char      *pswap ;
+} smt_pdef[] = {
+       { SMT_P_UNA,    sizeof(struct smt_p_una) ,
+               SWAP_SMT_P_UNA                                  } ,
+       { SMT_P_SDE,    sizeof(struct smt_p_sde) ,
+               SWAP_SMT_P_SDE                                  } ,
+       { SMT_P_STATE,  sizeof(struct smt_p_state) ,
+               SWAP_SMT_P_STATE                                } ,
+       { SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) ,
+               SWAP_SMT_P_TIMESTAMP                            } ,
+       { SMT_P_POLICY, sizeof(struct smt_p_policy) ,
+               SWAP_SMT_P_POLICY                               } ,
+       { SMT_P_LATENCY,        sizeof(struct smt_p_latency) ,
+               SWAP_SMT_P_LATENCY                              } ,
+       { SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) ,
+               SWAP_SMT_P_NEIGHBORS                            } ,
+       { SMT_P_PATH,   sizeof(struct smt_p_path) ,
+               SWAP_SMT_P_PATH                                 } ,
+       { SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) ,
+               SWAP_SMT_P_MAC_STATUS                           } ,
+       { SMT_P_LEM,    sizeof(struct smt_p_lem) ,
+               SWAP_SMT_P_LEM                                  } ,
+       { SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) ,
+               SWAP_SMT_P_MAC_COUNTER                          } ,
+       { SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) ,
+               SWAP_SMT_P_MAC_FNC                              } ,
+       { SMT_P_PRIORITY,sizeof(struct smt_p_priority) ,
+               SWAP_SMT_P_PRIORITY                             } ,
+       { SMT_P_EB,sizeof(struct smt_p_eb) ,
+               SWAP_SMT_P_EB                                   } ,
+       { SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) ,
+               SWAP_SMT_P_MANUFACTURER                         } ,
+       { SMT_P_REASON, sizeof(struct smt_p_reason) ,
+               SWAP_SMT_P_REASON                               } ,
+       { SMT_P_REFUSED, sizeof(struct smt_p_refused) ,
+               SWAP_SMT_P_REFUSED                              } ,
+       { SMT_P_VERSION, sizeof(struct smt_p_version) ,
+               SWAP_SMT_P_VERSION                              } ,
+#ifdef ESS
+       { SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } ,
+       { SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } ,
+       { SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } ,
+       { SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } ,
+       { SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } ,
+       { SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } ,
+       { SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } ,
+       { SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } ,
+       { SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } ,
+#endif
+#if    0
+       { SMT_P_FSC,    sizeof(struct smt_p_fsc) ,
+               SWAP_SMT_P_FSC                                  } ,
+#endif
+
+       { SMT_P_SETCOUNT,0,     SWAP_SMT_P_SETCOUNT             } ,
+       { SMT_P1048,    0,      SWAP_SMT_P1048                  } ,
+       { SMT_P208C,    0,      SWAP_SMT_P208C                  } ,
+       { SMT_P208D,    0,      SWAP_SMT_P208D                  } ,
+       { SMT_P208E,    0,      SWAP_SMT_P208E                  } ,
+       { SMT_P208F,    0,      SWAP_SMT_P208F                  } ,
+       { SMT_P2090,    0,      SWAP_SMT_P2090                  } ,
+#ifdef ESS
+       { SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } ,
+       { SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } ,
+       { SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } ,
+#endif
+       { SMT_P4050,    0,      SWAP_SMT_P4050                  } ,
+       { SMT_P4051,    0,      SWAP_SMT_P4051                  } ,
+       { SMT_P4052,    0,      SWAP_SMT_P4052                  } ,
+       { SMT_P4053,    0,      SWAP_SMT_P4053                  } ,
+} ;
+
+#define N_SMT_PLEN     ARRAY_SIZE(smt_pdef)
+
+int smt_check_para(struct s_smc *smc, struct smt_header        *sm,
+                  const u_short list[])
+{
+       const u_short           *p = list ;
+       while (*p) {
+               if (!sm_to_para(smc,sm,(int) *p)) {
+                       DB_SMT("SMT: smt_check_para - missing para %x\n",*p,0);
+                       return -1;
+               }
+               p++ ;
+       }
+       return 0;
+}
+
+void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
+{
+       char    *p ;
+       int     len ;
+       int     plen ;
+       void    *found = NULL;
+
+       SK_UNUSED(smc) ;
+
+       len = sm->smt_len ;
+       p = (char *)(sm+1) ;            /* pointer to info */
+       while (len > 0 ) {
+               if (((struct smt_para *)p)->p_type == para)
+                       found = (void *) p ;
+               plen = ((struct smt_para *)p)->p_len + PARA_LEN ;
+               p += plen ;
+               len -= plen ;
+               if (len < 0) {
+                       DB_SMT("SMT : sm_to_para - length error %d\n",plen,0) ;
+                       return NULL;
+               }
+               if ((plen & 3) && (para != SMT_P_ECHODATA)) {
+                       DB_SMT("SMT : sm_to_para - odd length %d\n",plen,0) ;
+                       return NULL;
+               }
+               if (found)
+                       return found;
+       }
+       return NULL;
+}
+
+#if    0
+/*
+ * send ANTC data test frame
+ */
+void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest)
+{
+       SK_UNUSED(smc) ;
+       SK_UNUSED(dest) ;
+#if    0
+       SMbuf                   *mb ;
+       struct smt_header       *smt ;
+       int                     i ;
+       char                    *p ;
+
+       mb = smt_get_mbuf() ;
+       mb->sm_len = 3000+12 ;
+       p = smtod(mb, char *) + 12 ;
+       for (i = 0 ; i < 3000 ; i++)
+               *p++ = 1 << (i&7) ;
+
+       smt = smtod(mb, struct smt_header *) ;
+       smt->smt_dest = *dest ;
+       smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
+       smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ;
+#endif
+}
+#endif
+
+#ifdef DEBUG
+char *addr_to_string(struct fddi_addr *addr)
+{
+       int     i ;
+       static char     string[6*3] = "****" ;
+
+       for (i = 0 ; i < 6 ; i++) {
+               string[i * 3] = hex_asc_hi(addr->a[i]);
+               string[i * 3 + 1] = hex_asc_lo(addr->a[i]);
+               string[i * 3 + 2] = ':';
+       }
+       string[5 * 3 + 2] = 0;
+       return string;
+}
+#endif
+
+#ifdef AM29K
+int smt_ifconfig(int argc, char *argv[])
+{
+       if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
+           !strcmp(argv[1],"yes")) {
+               smc->mib.fddiSMTBypassPresent = 1 ;
+               return 0;
+       }
+       return amdfddi_config(0, argc, argv);
+}
+#endif
+
+/*
+ * return static mac index
+ */
+static int mac_index(struct s_smc *smc, int mac)
+{
+       SK_UNUSED(mac) ;
+#ifdef CONCENTRATOR
+       SK_UNUSED(smc) ;
+       return NUMPHYS + 1;
+#else
+       return (smc->s.sas == SMT_SAS) ? 2 : 3;
+#endif
+}
+
+/*
+ * return static phy index
+ */
+static int phy_index(struct s_smc *smc, int phy)
+{
+       SK_UNUSED(smc) ;
+       return phy + 1;
+}
+
+/*
+ * return dynamic mac connection resource index
+ */
+static int mac_con_resource_index(struct s_smc *smc, int mac)
+{
+#ifdef CONCENTRATOR
+       SK_UNUSED(smc) ;
+       SK_UNUSED(mac) ;
+       return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC));
+#else
+       SK_UNUSED(mac) ;
+       switch (smc->mib.fddiSMTCF_State) {
+       case SC9_C_WRAP_A :
+       case SC5_THRU_B :
+       case SC11_C_WRAP_S :
+               return 1;
+       case SC10_C_WRAP_B :
+       case SC4_THRU_A :
+               return 2;
+       }
+       return smc->s.sas == SMT_SAS ? 2 : 3;
+#endif
+}
+
+/*
+ * return dynamic phy connection resource index
+ */
+static int phy_con_resource_index(struct s_smc *smc, int phy)
+{
+#ifdef CONCENTRATOR
+       return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ;
+#else
+       switch (smc->mib.fddiSMTCF_State) {
+       case SC9_C_WRAP_A :
+               return phy == PA ? 3 : 2;
+       case SC10_C_WRAP_B :
+               return phy == PA ? 1 : 3;
+       case SC4_THRU_A :
+               return phy == PA ? 3 : 1;
+       case SC5_THRU_B :
+               return phy == PA ? 2 : 3;
+       case SC11_C_WRAP_S :
+               return 2;
+       }
+       return phy;
+#endif
+}
+
+#ifdef CONCENTRATOR
+static int entity_to_index(struct s_smc *smc, int e)
+{
+       if (e == ENTITY_MAC)
+               return mac_index(smc, 1);
+       else
+               return phy_index(smc, e - ENTITY_PHY(0));
+}
+#endif
+
+#ifdef LITTLE_ENDIAN
+static int smt_swap_short(u_short s)
+{
+       return ((s>>8)&0xff) | ((s&0xff)<<8);
+}
+
+void smt_swap_para(struct smt_header *sm, int len, int direction)
+/* int direction;      0 encode 1 decode */
+{
+       struct smt_para *pa ;
+       const  struct smt_pdef  *pd ;
+       char    *p ;
+       int     plen ;
+       int     type ;
+       int     i ;
+
+/*     printf("smt_swap_para sm %x len %d dir %d\n",
+               sm,len,direction) ;
+ */
+       smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ;
+
+       /* swap args */
+       len -= sizeof(struct smt_header) ;
+
+       p = (char *) (sm + 1) ;
+       while (len > 0) {
+               pa = (struct smt_para *) p ;
+               plen = pa->p_len ;
+               type = pa->p_type ;
+               pa->p_type = smt_swap_short(pa->p_type) ;
+               pa->p_len = smt_swap_short(pa->p_len) ;
+               if (direction) {
+                       plen = pa->p_len ;
+                       type = pa->p_type ;
+               }
+               /*
+                * note: paras can have 0 length !
+                */
+               if (plen < 0)
+                       break ;
+               plen += PARA_LEN ;
+               for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) {
+                       if (pd->ptype == type)
+                               break ;
+               }
+               if (i && pd->pswap) {
+                       smt_string_swap(p+PARA_LEN,pd->pswap,len) ;
+               }
+               len -= plen ;
+               p += plen ;
+       }
+}
+
+static void smt_string_swap(char *data, const char *format, int len)
+{
+       const char      *open_paren = NULL ;
+       int     x ;
+
+       while (len > 0  && *format) {
+               switch (*format) {
+               case '[' :
+                       open_paren = format ;
+                       break ;
+               case ']' :
+                       format = open_paren ;
+                       break ;
+               case '1' :
+               case '2' :
+               case '3' :
+               case '4' :
+               case '5' :
+               case '6' :
+               case '7' :
+               case '8' :
+               case '9' :
+                       data  += *format - '0' ;
+                       len   -= *format - '0' ;
+                       break ;
+               case 'c':
+                       data++ ;
+                       len-- ;
+                       break ;
+               case 's' :
+                       x = data[0] ;
+                       data[0] = data[1] ;
+                       data[1] = x ;
+                       data += 2 ;
+                       len -= 2 ;
+                       break ;
+               case 'l' :
+                       x = data[0] ;
+                       data[0] = data[3] ;
+                       data[3] = x ;
+                       x = data[1] ;
+                       data[1] = data[2] ;
+                       data[2] = x ;
+                       data += 4 ;
+                       len -= 4 ;
+                       break ;
+               }
+               format++ ;
+       }
+}
+#else
+void smt_swap_para(struct smt_header *sm, int len, int direction)
+/* int direction;      0 encode 1 decode */
+{
+       SK_UNUSED(sm) ;
+       SK_UNUSED(len) ;
+       SK_UNUSED(direction) ;
+}
+#endif
+
+/*
+ * PMF actions
+ */
+int smt_action(struct s_smc *smc, int class, int code, int index)
+{
+       int     event ;
+       int     port ;
+       DB_SMT("SMT: action %d code %d\n",class,code) ;
+       switch(class) {
+       case SMT_STATION_ACTION :
+               switch(code) {
+               case SMT_STATION_ACTION_CONNECT :
+                       smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
+                       queue_event(smc,EVENT_ECM,EC_CONNECT) ;
+                       break ;
+               case SMT_STATION_ACTION_DISCONNECT :
+                       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
+                       smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ;
+                       RS_SET(smc,RS_DISCONNECT) ;
+                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                               FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT,
+                               smt_get_event_word(smc));
+                       break ;
+               case SMT_STATION_ACTION_PATHTEST :
+                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                               FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST,
+                               smt_get_event_word(smc));
+                       break ;
+               case SMT_STATION_ACTION_SELFTEST :
+                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                               FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST,
+                               smt_get_event_word(smc));
+                       break ;
+               case SMT_STATION_ACTION_DISABLE_A :
+                       if (smc->y[PA].pc_mode == PM_PEER) {
+                               RS_SET(smc,RS_EVENT) ;
+                               queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ;
+                       }
+                       break ;
+               case SMT_STATION_ACTION_DISABLE_B :
+                       if (smc->y[PB].pc_mode == PM_PEER) {
+                               RS_SET(smc,RS_EVENT) ;
+                               queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ;
+                       }
+                       break ;
+               case SMT_STATION_ACTION_DISABLE_M :
+                       for (port = 0 ; port <  NUMPHYS ; port++) {
+                               if (smc->mib.p[port].fddiPORTMy_Type != TM)
+                                       continue ;
+                               RS_SET(smc,RS_EVENT) ;
+                               queue_event(smc,EVENT_PCM+port,PC_DISABLE) ;
+                       }
+                       break ;
+               default :
+                       return 1;
+               }
+               break ;
+       case SMT_PORT_ACTION :
+               switch(code) {
+               case SMT_PORT_ACTION_ENABLE :
+                       event = PC_ENABLE ;
+                       break ;
+               case SMT_PORT_ACTION_DISABLE :
+                       event = PC_DISABLE ;
+                       break ;
+               case SMT_PORT_ACTION_MAINT :
+                       event = PC_MAINT ;
+                       break ;
+               case SMT_PORT_ACTION_START :
+                       event = PC_START ;
+                       break ;
+               case SMT_PORT_ACTION_STOP :
+                       event = PC_STOP ;
+                       break ;
+               default :
+                       return 1;
+               }
+               queue_event(smc,EVENT_PCM+index,event) ;
+               break ;
+       default :
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * canonical conversion of <len> bytes beginning form *data
+ */
+#ifdef  USE_CAN_ADDR
+static void hwm_conv_can(struct s_smc *smc, char *data, int len)
+{
+       int i ;
+
+       SK_UNUSED(smc) ;
+
+       for (i = len; i ; i--, data++)
+               *data = bitrev8(*data);
+}
+#endif
+
+#endif /* no SLIM_SMT */
+
diff --git a/drivers/net/fddi/skfp/smtdef.c b/drivers/net/fddi/skfp/smtdef.c
new file mode 100644 (file)
index 0000000..1acab0b
--- /dev/null
@@ -0,0 +1,355 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT/CMT defaults
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef OEM_USER_DATA
+#define OEM_USER_DATA  "SK-NET FDDI V2.0 Userdata"
+#endif
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)smtdef.c    2.53 99/08/11 (C) SK " ;
+#endif
+
+/*
+ * defaults
+ */
+#define TTMS(x)        ((u_long)(x)*1000L)
+#define TTS(x) ((u_long)(x)*1000000L)
+#define TTUS(x)        ((u_long)(x))
+
+#define DEFAULT_TB_MIN         TTMS(5)
+#define DEFAULT_TB_MAX         TTMS(50)
+#define DEFAULT_C_MIN          TTUS(1600)
+#define DEFAULT_T_OUT          TTMS(100+5)
+#define DEFAULT_TL_MIN         TTUS(30)
+#define DEFAULT_LC_SHORT       TTMS(50+5)
+#define DEFAULT_LC_MEDIUM      TTMS(500+20)
+#define DEFAULT_LC_LONG                TTS(5)+TTMS(50)
+#define DEFAULT_LC_EXTENDED    TTS(50)+TTMS(50)
+#define DEFAULT_T_NEXT_9       TTMS(200+10)
+#define DEFAULT_NS_MAX         TTUS(1310)
+#define DEFAULT_I_MAX          TTMS(25)
+#define DEFAULT_IN_MAX         TTMS(40)
+#define DEFAULT_TD_MIN         TTMS(5)
+#define DEFAULT_T_NON_OP       TTS(1)
+#define DEFAULT_T_STUCK                TTS(8)
+#define DEFAULT_T_DIRECT       TTMS(370)
+#define DEFAULT_T_JAM          TTMS(370)
+#define DEFAULT_T_ANNOUNCE     TTMS(2500)
+#define DEFAULT_D_MAX          TTUS(1617)
+#define DEFAULT_LEM_ALARM      (8)
+#define DEFAULT_LEM_CUTOFF     (7)
+#define DEFAULT_TEST_DONE      TTS(1)
+#define DEFAULT_CHECK_POLL     TTS(1)
+#define DEFAULT_POLL           TTMS(50)
+
+/*
+ * LCT errors threshold
+ */
+#define DEFAULT_LCT_SHORT      1
+#define DEFAULT_LCT_MEDIUM     3
+#define DEFAULT_LCT_LONG       5
+#define DEFAULT_LCT_EXTEND     50
+
+/* Forward declarations */
+void smt_reset_defaults(struct s_smc *smc, int level);
+static void smt_init_mib(struct s_smc *smc, int level);
+static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper);
+
+#define MS2BCLK(x)     ((x)*12500L)
+#define US2BCLK(x)     ((x)*1250L)
+
+void smt_reset_defaults(struct s_smc *smc, int level)
+{
+       struct smt_config       *smt ;
+       int                     i ;
+       u_long                  smt_boot_time;
+
+
+       smt_init_mib(smc,level) ;
+
+       smc->os.smc_version = SMC_VERSION ;
+       smt_boot_time = smt_get_time();
+       for( i = 0; i < NUMMACS; i++ )
+               smc->sm.last_tok_time[i] = smt_boot_time ;
+       smt = &smc->s ;
+       smt->attach_s = 0 ;
+       smt->build_ring_map = 1 ;
+       smt->sas = SMT_DAS ;
+       smt->numphys = NUMPHYS ;
+       smt->pcm_tb_min = DEFAULT_TB_MIN ;
+       smt->pcm_tb_max = DEFAULT_TB_MAX ;
+       smt->pcm_c_min = DEFAULT_C_MIN ;
+       smt->pcm_t_out = DEFAULT_T_OUT ;
+       smt->pcm_tl_min = DEFAULT_TL_MIN ;
+       smt->pcm_lc_short = DEFAULT_LC_SHORT ;
+       smt->pcm_lc_medium = DEFAULT_LC_MEDIUM ;
+       smt->pcm_lc_long = DEFAULT_LC_LONG ;
+       smt->pcm_lc_extended = DEFAULT_LC_EXTENDED ;
+       smt->pcm_t_next_9 = DEFAULT_T_NEXT_9 ;
+       smt->pcm_ns_max = DEFAULT_NS_MAX ;
+       smt->ecm_i_max = DEFAULT_I_MAX ;
+       smt->ecm_in_max = DEFAULT_IN_MAX ;
+       smt->ecm_td_min = DEFAULT_TD_MIN ;
+       smt->ecm_test_done = DEFAULT_TEST_DONE ;
+       smt->ecm_check_poll = DEFAULT_CHECK_POLL ;
+       smt->rmt_t_non_op = DEFAULT_T_NON_OP ;
+       smt->rmt_t_stuck = DEFAULT_T_STUCK ;
+       smt->rmt_t_direct = DEFAULT_T_DIRECT ;
+       smt->rmt_t_jam = DEFAULT_T_JAM ;
+       smt->rmt_t_announce = DEFAULT_T_ANNOUNCE ;
+       smt->rmt_t_poll = DEFAULT_POLL ;
+        smt->rmt_dup_mac_behavior = FALSE ;  /* See Struct smt_config */
+       smt->mac_d_max = DEFAULT_D_MAX ;
+
+       smt->lct_short = DEFAULT_LCT_SHORT ;
+       smt->lct_medium = DEFAULT_LCT_MEDIUM ;
+       smt->lct_long = DEFAULT_LCT_LONG ;
+       smt->lct_extended = DEFAULT_LCT_EXTEND ;
+
+#ifndef        SLIM_SMT
+#ifdef ESS
+       if (level == 0) {
+               smc->ess.sync_bw_available = FALSE ;
+               smc->mib.fddiESSPayload = 0 ;
+               smc->mib.fddiESSOverhead = 0 ;
+               smc->mib.fddiESSMaxTNeg = (u_long)(- MS2BCLK(25)) ;
+               smc->mib.fddiESSMinSegmentSize = 1 ;
+               smc->mib.fddiESSCategory = SB_STATIC ;
+               smc->mib.fddiESSSynchTxMode = FALSE ;
+               smc->ess.raf_act_timer_poll = FALSE ;
+               smc->ess.timer_count = 7 ;      /* first RAF alc req after 3s */
+       }
+       smc->ess.local_sba_active = FALSE ;
+       smc->ess.sba_reply_pend = NULL ;
+#endif
+#ifdef SBA
+       smt_init_sba(smc,level) ;
+#endif
+#endif /* no SLIM_SMT */
+#ifdef TAG_MODE
+       if (level == 0) {
+               smc->hw.pci_fix_value = 0 ;
+       }
+#endif
+}
+
+/*
+ * manufacturer data
+ */
+static const char man_data[32] =
+/*      01234567890123456789012345678901       */
+       "xxxSK-NET FDDI SMT 7.3 - V2.8.8" ;
+
+static void smt_init_mib(struct s_smc *smc, int level)
+{
+       struct fddi_mib         *mib ;
+       struct fddi_mib_p       *pm ;
+       int                     port ;
+       int                     path ;
+
+       mib = &smc->mib ;
+       if (level == 0) {
+               /*
+                * set EVERYTHING to ZERO
+                * EXCEPT hw and os
+                */
+               memset(((char *)smc)+
+                       sizeof(struct s_smt_os)+sizeof(struct s_smt_hw), 0,
+                       sizeof(struct s_smc) -
+                       sizeof(struct s_smt_os) - sizeof(struct s_smt_hw)) ;
+       }
+       else {
+               mib->fddiSMTRemoteDisconnectFlag = 0 ;
+               mib->fddiSMTPeerWrapFlag = 0 ;
+       }
+
+       mib->fddiSMTOpVersionId = 2 ;
+       mib->fddiSMTHiVersionId = 2 ;
+       mib->fddiSMTLoVersionId = 2 ;
+       memcpy((char *) mib->fddiSMTManufacturerData,man_data,32) ;
+       if (level == 0) {
+               strcpy(mib->fddiSMTUserData,OEM_USER_DATA) ;
+       }
+       mib->fddiSMTMIBVersionId = 1 ;
+       mib->fddiSMTMac_Ct = NUMMACS ;
+       mib->fddiSMTConnectionPolicy = POLICY_MM | POLICY_AA | POLICY_BB ;
+
+       /*
+        * fddiSMTNonMaster_Ct and fddiSMTMaster_Ct are set in smt_fixup_mib
+        * s.sas is not set yet (is set in init driver)
+        */
+       mib->fddiSMTAvailablePaths = MIB_PATH_P | MIB_PATH_S ;
+
+       mib->fddiSMTConfigCapabilities = 0 ;    /* no hold,no wrap_ab*/
+       mib->fddiSMTTT_Notify = 10 ;
+       mib->fddiSMTStatRptPolicy = TRUE ;
+       mib->fddiSMTTrace_MaxExpiration = SEC2MIB(7) ;
+       mib->fddiSMTMACIndexes = INDEX_MAC ;
+       mib->fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;       /* separated */
+
+       mib->m[MAC0].fddiMACIndex = INDEX_MAC ;
+       mib->m[MAC0].fddiMACFrameStatusFunctions = FSC_TYPE0 ;
+       mib->m[MAC0].fddiMACRequestedPaths =
+               MIB_P_PATH_LOCAL |
+               MIB_P_PATH_SEC_ALTER |
+               MIB_P_PATH_PRIM_ALTER ;
+       mib->m[MAC0].fddiMACAvailablePaths = MIB_PATH_P ;
+       mib->m[MAC0].fddiMACCurrentPath = MIB_PATH_PRIMARY ;
+       mib->m[MAC0].fddiMACT_MaxCapabilitiy = (u_long)(- MS2BCLK(165)) ;
+       mib->m[MAC0].fddiMACTVXCapabilitiy = (u_long)(- US2BCLK(52)) ;
+       if (level == 0) {
+               mib->m[MAC0].fddiMACTvxValue = (u_long)(- US2BCLK(27)) ;
+               mib->m[MAC0].fddiMACTvxValueMIB = (u_long)(- US2BCLK(27)) ;
+               mib->m[MAC0].fddiMACT_Req = (u_long)(- MS2BCLK(165)) ;
+               mib->m[MAC0].fddiMACT_ReqMIB = (u_long)(- MS2BCLK(165)) ;
+               mib->m[MAC0].fddiMACT_Max = (u_long)(- MS2BCLK(165)) ;
+               mib->m[MAC0].fddiMACT_MaxMIB = (u_long)(- MS2BCLK(165)) ;
+               mib->m[MAC0].fddiMACT_Min = (u_long)(- MS2BCLK(4)) ;
+       }
+       mib->m[MAC0].fddiMACHardwarePresent = TRUE ;
+       mib->m[MAC0].fddiMACMA_UnitdataEnable = TRUE ;
+       mib->m[MAC0].fddiMACFrameErrorThreshold = 1 ;
+       mib->m[MAC0].fddiMACNotCopiedThreshold = 1 ;
+       /*
+        * Path attributes
+        */
+       for (path = 0 ; path < NUMPATHS ; path++) {
+               mib->a[path].fddiPATHIndex = INDEX_PATH + path ;
+               if (level == 0) {
+                       mib->a[path].fddiPATHTVXLowerBound =
+                               (u_long)(- US2BCLK(27)) ;
+                       mib->a[path].fddiPATHT_MaxLowerBound =
+                               (u_long)(- MS2BCLK(165)) ;
+                       mib->a[path].fddiPATHMaxT_Req =
+                               (u_long)(- MS2BCLK(165)) ;
+               }
+       }
+
+
+       /*
+        * Port attributes
+        */
+       pm = mib->p ;
+       for (port = 0 ; port <  NUMPHYS ; port++) {
+               /*
+                * set MIB pointer in phy
+                */
+               /* Attention: don't initialize mib pointer here! */
+               /*  It must be initialized during phase 2 */
+               smc->y[port].mib = NULL;
+               mib->fddiSMTPORTIndexes[port] = port+INDEX_PORT ;
+
+               pm->fddiPORTIndex = port+INDEX_PORT ;
+               pm->fddiPORTHardwarePresent = TRUE ;
+               if (level == 0) {
+                       pm->fddiPORTLer_Alarm = DEFAULT_LEM_ALARM ;
+                       pm->fddiPORTLer_Cutoff = DEFAULT_LEM_CUTOFF ;
+               }
+               /*
+                * fddiPORTRequestedPaths are set in pcmplc.c
+                * we don't know the port type yet !
+                */
+               pm->fddiPORTRequestedPaths[1] = 0 ;
+               pm->fddiPORTRequestedPaths[2] = 0 ;
+               pm->fddiPORTRequestedPaths[3] = 0 ;
+               pm->fddiPORTAvailablePaths = MIB_PATH_P ;
+               pm->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
+               pm++ ;
+       }
+
+       (void) smt_set_mac_opvalues(smc) ;
+}
+
+int smt_set_mac_opvalues(struct s_smc *smc)
+{
+       int     st ;
+       int     st2 ;
+
+       st = set_min_max(1,smc->mib.m[MAC0].fddiMACTvxValueMIB,
+               smc->mib.a[PATH0].fddiPATHTVXLowerBound,
+               &smc->mib.m[MAC0].fddiMACTvxValue) ;
+       st |= set_min_max(0,smc->mib.m[MAC0].fddiMACT_MaxMIB,
+               smc->mib.a[PATH0].fddiPATHT_MaxLowerBound,
+               &smc->mib.m[MAC0].fddiMACT_Max) ;
+       st |= (st2 = set_min_max(0,smc->mib.m[MAC0].fddiMACT_ReqMIB,
+               smc->mib.a[PATH0].fddiPATHMaxT_Req,
+               &smc->mib.m[MAC0].fddiMACT_Req)) ;
+       if (st2) {
+               /* Treq attribute changed remotely. So send an AIX_EVENT to the
+                * user
+                */
+               AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
+                       FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_T_REQ,
+                       smt_get_event_word(smc));
+       }
+       return st;
+}
+
+void smt_fixup_mib(struct s_smc *smc)
+{
+#ifdef CONCENTRATOR
+       switch (smc->s.sas) {
+       case SMT_SAS :
+               smc->mib.fddiSMTNonMaster_Ct = 1 ;
+               break ;
+       case SMT_DAS :
+               smc->mib.fddiSMTNonMaster_Ct = 2 ;
+               break ;
+       case SMT_NAC :
+               smc->mib.fddiSMTNonMaster_Ct = 0 ;
+               break ;
+       }
+       smc->mib.fddiSMTMaster_Ct = NUMPHYS - smc->mib.fddiSMTNonMaster_Ct ;
+#else
+       switch (smc->s.sas) {
+       case SMT_SAS :
+               smc->mib.fddiSMTNonMaster_Ct = 1 ;
+               break ;
+       case SMT_DAS :
+               smc->mib.fddiSMTNonMaster_Ct = 2 ;
+               break ;
+       }
+       smc->mib.fddiSMTMaster_Ct = 0 ;
+#endif
+}
+
+/*
+ * determine new setting for operational value
+ * if limit is lower than mib
+ *     use limit
+ * else
+ *     use mib
+ * NOTE : numbers are negative, negate comparison !
+ */
+static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper)
+{
+       u_long  old ;
+       old = *oper ;
+       if ((limit > mib) ^ maxflag)
+               *oper = limit ;
+       else
+               *oper = mib ;
+       return old != *oper;
+}
+
diff --git a/drivers/net/fddi/skfp/smtinit.c b/drivers/net/fddi/skfp/smtinit.c
new file mode 100644 (file)
index 0000000..e3a0c0b
--- /dev/null
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       Init SMT
+       call all module level initialization routines
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)smtinit.c   1.15 97/05/06 (C) SK " ;
+#endif
+
+void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
+
+/* define global debug variable */
+#if defined(DEBUG) && !defined(DEBUG_BRD)
+struct smt_debug debug;
+#endif
+
+#ifndef MULT_OEM
+#define OEMID(smc,i)   oem_id[i]
+       extern u_char   oem_id[] ;
+#else  /* MULT_OEM */
+#define OEMID(smc,i)   smc->hw.oem_id->oi_mark[i]
+       extern struct s_oem_ids oem_ids[] ;
+#endif /* MULT_OEM */
+
+/*
+ * Set OEM specific values
+ *
+ * Can not be called in smt_reset_defaults, because it is not sure that
+ * the OEM ID is already defined.
+ */
+static void set_oem_spec_val(struct s_smc *smc)
+{
+       struct fddi_mib *mib ;
+
+       mib = &smc->mib ;
+
+       /*
+        * set IBM specific values
+        */
+       if (OEMID(smc,0) == 'I') {
+               mib->fddiSMTConnectionPolicy = POLICY_MM ;
+       }
+}
+
+/*
+ * Init SMT
+ */
+int init_smt(struct s_smc *smc, u_char *mac_addr)
+/* u_char *mac_addr;   canonical address or NULL */
+{
+       int     p ;
+
+#if defined(DEBUG) && !defined(DEBUG_BRD)
+       debug.d_smt = 0 ;
+       debug.d_smtf = 0 ;
+       debug.d_rmt = 0 ;
+       debug.d_ecm = 0 ;
+       debug.d_pcm = 0 ;
+       debug.d_cfm = 0 ;
+
+       debug.d_plc = 0 ;
+#ifdef ESS
+       debug.d_ess = 0 ;
+#endif
+#ifdef SBA
+       debug.d_sba = 0 ;
+#endif
+#endif /* DEBUG && !DEBUG_BRD */
+
+       /* First initialize the ports mib->pointers */
+       for ( p = 0; p < NUMPHYS; p ++ ) {
+               smc->y[p].mib = & smc->mib.p[p] ;
+       }
+
+       set_oem_spec_val(smc) ; 
+       (void) smt_set_mac_opvalues(smc) ;
+       init_fddi_driver(smc,mac_addr) ;        /* HW driver */
+       smt_fixup_mib(smc) ;            /* update values that depend on s.sas */
+
+       ev_init(smc) ;                  /* event queue */
+#ifndef        SLIM_SMT
+       smt_init_evc(smc) ;             /* evcs in MIB */
+#endif /* no SLIM_SMT */
+       smt_timer_init(smc) ;           /* timer package */
+       smt_agent_init(smc) ;           /* SMT frame manager */
+
+       pcm_init(smc) ;                 /* PCM state machine */
+       ecm_init(smc) ;                 /* ECM state machine */
+       cfm_init(smc) ;                 /* CFM state machine */
+       rmt_init(smc) ;                 /* RMT state machine */
+
+       for (p = 0 ; p < NUMPHYS ; p++) {
+               pcm(smc,p,0) ;          /* PCM A state machine */
+       }
+       ecm(smc,0) ;                    /* ECM state machine */
+       cfm(smc,0) ;                    /* CFM state machine */
+       rmt(smc,0) ;                    /* RMT state machine */
+
+       smt_agent_task(smc) ;           /* NIF FSM etc */
+
+        PNMI_INIT(smc) ;                /* PNMI initialization */
+
+       return 0;
+}
+
diff --git a/drivers/net/fddi/skfp/smttimer.c b/drivers/net/fddi/skfp/smttimer.c
new file mode 100644 (file)
index 0000000..531795e
--- /dev/null
@@ -0,0 +1,156 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT timer
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)smttimer.c  2.4 97/08/04 (C) SK " ;
+#endif
+
+static void timer_done(struct s_smc *smc, int restart);
+
+void smt_timer_init(struct s_smc *smc)
+{
+       smc->t.st_queue = NULL;
+       smc->t.st_fast.tm_active = FALSE ;
+       smc->t.st_fast.tm_next = NULL;
+       hwt_init(smc) ;
+}
+
+void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
+{
+       struct smt_timer        **prev ;
+       struct smt_timer        *tm ;
+
+       /*
+        * remove timer from queue
+        */
+       timer->tm_active = FALSE ;
+       if (smc->t.st_queue == timer && !timer->tm_next) {
+               hwt_stop(smc) ;
+       }
+       for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
+               if (tm == timer) {
+                       *prev = tm->tm_next ;
+                       if (tm->tm_next) {
+                               tm->tm_next->tm_delta += tm->tm_delta ;
+                       }
+                       return ;
+               }
+       }
+}
+
+void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
+                    u_long token)
+{
+       struct smt_timer        **prev ;
+       struct smt_timer        *tm ;
+       u_long                  delta = 0 ;
+
+       time /= 16 ;            /* input is uS, clock ticks are 16uS */
+       if (!time)
+               time = 1 ;
+       smt_timer_stop(smc,timer) ;
+       timer->tm_smc = smc ;
+       timer->tm_token = token ;
+       timer->tm_active = TRUE ;
+       if (!smc->t.st_queue) {
+               smc->t.st_queue = timer ;
+               timer->tm_next = NULL;
+               timer->tm_delta = time ;
+               hwt_start(smc,time) ;
+               return ;
+       }
+       /*
+        * timer correction
+        */
+       timer_done(smc,0) ;
+
+       /*
+        * find position in queue
+        */
+       delta = 0 ;
+       for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
+               if (delta + tm->tm_delta > time) {
+                       break ;
+               }
+               delta += tm->tm_delta ;
+       }
+       /* insert in queue */
+       *prev = timer ;
+       timer->tm_next = tm ;
+       timer->tm_delta = time - delta ;
+       if (tm)
+               tm->tm_delta -= timer->tm_delta ;
+       /*
+        * start new with first
+        */
+       hwt_start(smc,smc->t.st_queue->tm_delta) ;
+}
+
+void smt_force_irq(struct s_smc *smc)
+{
+       smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
+}
+
+void smt_timer_done(struct s_smc *smc)
+{
+       timer_done(smc,1) ;
+}
+
+static void timer_done(struct s_smc *smc, int restart)
+{
+       u_long                  delta ;
+       struct smt_timer        *tm ;
+       struct smt_timer        *next ;
+       struct smt_timer        **last ;
+       int                     done = 0 ;
+
+       delta = hwt_read(smc) ;
+       last = &smc->t.st_queue ;
+       tm = smc->t.st_queue ;
+       while (tm && !done) {
+               if (delta >= tm->tm_delta) {
+                       tm->tm_active = FALSE ;
+                       delta -= tm->tm_delta ;
+                       last = &tm->tm_next ;
+                       tm = tm->tm_next ;
+               }
+               else {
+                       tm->tm_delta -= delta ;
+                       delta = 0 ;
+                       done = 1 ;
+               }
+       }
+       *last = NULL;
+       next = smc->t.st_queue ;
+       smc->t.st_queue = tm ;
+
+       for ( tm = next ; tm ; tm = next) {
+               next = tm->tm_next ;
+               timer_event(smc,tm->tm_token) ;
+       }
+
+       if (restart && smc->t.st_queue)
+               hwt_start(smc,smc->t.st_queue->tm_delta) ;
+}
+
diff --git a/drivers/net/fddi/skfp/srf.c b/drivers/net/fddi/skfp/srf.c
new file mode 100644 (file)
index 0000000..f6f7baf
--- /dev/null
@@ -0,0 +1,429 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+       SMT 7.2 Status Response Frame Implementation
+       SRF state machine and frame generation
+*/
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+#include "h/smt_p.h"
+
+#define KERNEL
+#include "h/smtstate.h"
+
+#ifndef        SLIM_SMT
+#ifndef        BOOT
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)srf.c       1.18 97/08/04 (C) SK " ;
+#endif
+
+
+/*
+ * function declarations
+ */
+static void clear_all_rep(struct s_smc *smc);
+static void clear_reported(struct s_smc *smc);
+static void smt_send_srf(struct s_smc *smc);
+static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
+
+#define MAX_EVCS       ARRAY_SIZE(smc->evcs)
+
+struct evc_init {
+       u_char code ;
+       u_char index ;
+       u_char n ;
+       u_short para ;
+}  ;
+
+static const struct evc_init evc_inits[] = {
+       { SMT_COND_SMT_PEER_WRAP,               0,1,SMT_P1048   } ,
+
+       { SMT_COND_MAC_DUP_ADDR,                INDEX_MAC, NUMMACS,SMT_P208C } ,
+       { SMT_COND_MAC_FRAME_ERROR,             INDEX_MAC, NUMMACS,SMT_P208D } ,
+       { SMT_COND_MAC_NOT_COPIED,              INDEX_MAC, NUMMACS,SMT_P208E } ,
+       { SMT_EVENT_MAC_NEIGHBOR_CHANGE,        INDEX_MAC, NUMMACS,SMT_P208F } ,
+       { SMT_EVENT_MAC_PATH_CHANGE,            INDEX_MAC, NUMMACS,SMT_P2090 } ,
+
+       { SMT_COND_PORT_LER,                    INDEX_PORT,NUMPHYS,SMT_P4050 } ,
+       { SMT_COND_PORT_EB_ERROR,               INDEX_PORT,NUMPHYS,SMT_P4052 } ,
+       { SMT_EVENT_PORT_CONNECTION,            INDEX_PORT,NUMPHYS,SMT_P4051 } ,
+       { SMT_EVENT_PORT_PATH_CHANGE,           INDEX_PORT,NUMPHYS,SMT_P4053 } ,
+} ;
+
+#define MAX_INIT_EVC   ARRAY_SIZE(evc_inits)
+
+void smt_init_evc(struct s_smc *smc)
+{
+       struct s_srf_evc        *evc ;
+       const struct evc_init   *init ;
+       int                     i ;
+       int                     index ;
+       int                     offset ;
+
+       static u_char           fail_safe = FALSE ;
+
+       memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
+
+       evc = smc->evcs ;
+       init = evc_inits ;
+
+       for (i = 0 ; (unsigned) i < MAX_INIT_EVC ; i++) {
+               for (index = 0 ; index < init->n ; index++) {
+                       evc->evc_code = init->code ;
+                       evc->evc_para = init->para ;
+                       evc->evc_index = init->index + index ;
+#ifndef        DEBUG
+                       evc->evc_multiple = &fail_safe ;
+                       evc->evc_cond_state = &fail_safe ;
+#endif
+                       evc++ ;
+               }
+               init++ ;
+       }
+
+       if ((unsigned) (evc - smc->evcs) > MAX_EVCS) {
+               SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
+       }
+
+       /*
+        * conditions
+        */
+       smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
+       smc->evcs[1].evc_cond_state =
+               &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
+       smc->evcs[2].evc_cond_state =
+               &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
+       smc->evcs[3].evc_cond_state =
+               &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
+
+       /*
+        * events
+        */
+       smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
+       smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
+
+       offset = 6 ;
+       for (i = 0 ; i < NUMPHYS ; i++) {
+               /*
+                * conditions
+                */
+               smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
+                       &smc->mib.p[i].fddiPORTLerFlag ;
+               smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
+                       &smc->mib.p[i].fddiPORTEB_Condition ;
+
+               /*
+                * events
+                */
+               smc->evcs[offset + 2*NUMPHYS].evc_multiple =
+                       &smc->mib.p[i].fddiPORTMultiple_U ;
+               smc->evcs[offset + 3*NUMPHYS].evc_multiple =
+                       &smc->mib.p[i].fddiPORTMultiple_P ;
+               offset++ ;
+       }
+#ifdef DEBUG
+       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+               if (SMT_IS_CONDITION(evc->evc_code)) {
+                       if (!evc->evc_cond_state) {
+                               SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
+                       }
+                       evc->evc_multiple = &fail_safe ;
+               }
+               else {
+                       if (!evc->evc_multiple) {
+                               SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
+                       }
+                       evc->evc_cond_state = &fail_safe ;
+               }
+       }
+#endif
+       smc->srf.TSR = smt_get_time() ;
+       smc->srf.sr_state = SR0_WAIT ;
+}
+
+static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
+{
+       int                     i ;
+       struct s_srf_evc        *evc ;
+
+       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+               if (evc->evc_code == code && evc->evc_index == index)
+                       return evc;
+       }
+       return NULL;
+}
+
+#define THRESHOLD_2    (2*TICKS_PER_SECOND)
+#define THRESHOLD_32   (32*TICKS_PER_SECOND)
+
+#ifdef DEBUG
+static const char * const srf_names[] = {
+       "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
+       "PORTPathChangeEvent",          "PORTUndesiredConnectionAttemptEvent",
+       "SMTPeerWrapCondition",         "SMTHoldCondition",
+       "MACFrameErrorCondition",       "MACDuplicateAddressCondition",
+       "MACNotCopiedCondition",        "PORTEBErrorCondition",
+       "PORTLerCondition"
+} ;
+#endif
+
+void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
+{
+       struct s_srf_evc        *evc ;
+       int                     cond_asserted = 0 ;
+       int                     cond_deasserted = 0 ;
+       int                     event_occurred = 0 ;
+       int                     tsr ;
+       int                     T_Limit = 2*TICKS_PER_SECOND ;
+
+       if (code == SMT_COND_MAC_DUP_ADDR && cond) {
+               RS_SET(smc,RS_DUPADDR) ;
+       }
+
+       if (code) {
+               DB_SMT("SRF: %s index %d\n",srf_names[code],index) ;
+
+               if (!(evc = smt_get_evc(smc,code,index))) {
+                       DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
+                       return ;
+               }
+               /*
+                * ignore condition if no change
+                */
+               if (SMT_IS_CONDITION(code)) {
+                       if (*evc->evc_cond_state == cond)
+                               return ;
+               }
+
+               /*
+                * set transition time stamp
+                */
+               smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
+               if (SMT_IS_CONDITION(code)) {
+                       DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ;
+                       if (cond) {
+                               *evc->evc_cond_state = TRUE ;
+                               evc->evc_rep_required = TRUE ;
+                               smc->srf.any_report = TRUE ;
+                               cond_asserted = TRUE ;
+                       }
+                       else {
+                               *evc->evc_cond_state = FALSE ;
+                               cond_deasserted = TRUE ;
+                       }
+               }
+               else {
+                       if (evc->evc_rep_required) {
+                               *evc->evc_multiple  = TRUE ;
+                       }
+                       else {
+                               evc->evc_rep_required = TRUE ;
+                               *evc->evc_multiple  = FALSE ;
+                       }
+                       smc->srf.any_report = TRUE ;
+                       event_occurred = TRUE ;
+               }
+#ifdef FDDI_MIB
+               snmp_srf_event(smc,evc) ;
+#endif /* FDDI_MIB */
+       }
+       tsr = smt_get_time() - smc->srf.TSR ;
+
+       switch (smc->srf.sr_state) {
+       case SR0_WAIT :
+               /* SR01a */
+               if (cond_asserted && tsr < T_Limit) {
+                       smc->srf.SRThreshold = THRESHOLD_2 ;
+                       smc->srf.sr_state = SR1_HOLDOFF ;
+                       break ;
+               }
+               /* SR01b */
+               if (cond_deasserted && tsr < T_Limit) {
+                       smc->srf.sr_state = SR1_HOLDOFF ;
+                       break ;
+               }
+               /* SR01c */
+               if (event_occurred && tsr < T_Limit) {
+                       smc->srf.sr_state = SR1_HOLDOFF ;
+                       break ;
+               }
+               /* SR00b */
+               if (cond_asserted && tsr >= T_Limit) {
+                       smc->srf.SRThreshold = THRESHOLD_2 ;
+                       smc->srf.TSR = smt_get_time() ;
+                       smt_send_srf(smc) ;
+                       break ;
+               }
+               /* SR00c */
+               if (cond_deasserted && tsr >= T_Limit) {
+                       smc->srf.TSR = smt_get_time() ;
+                       smt_send_srf(smc) ;
+                       break ;
+               }
+               /* SR00d */
+               if (event_occurred && tsr >= T_Limit) {
+                       smc->srf.TSR = smt_get_time() ;
+                       smt_send_srf(smc) ;
+                       break ;
+               }
+               /* SR00e */
+               if (smc->srf.any_report && (u_long) tsr >=
+                       smc->srf.SRThreshold) {
+                       smc->srf.SRThreshold *= 2 ;
+                       if (smc->srf.SRThreshold > THRESHOLD_32)
+                               smc->srf.SRThreshold = THRESHOLD_32 ;
+                       smc->srf.TSR = smt_get_time() ;
+                       smt_send_srf(smc) ;
+                       break ;
+               }
+               /* SR02 */
+               if (!smc->mib.fddiSMTStatRptPolicy) {
+                       smc->srf.sr_state = SR2_DISABLED ;
+                       break ;
+               }
+               break ;
+       case SR1_HOLDOFF :
+               /* SR10b */
+               if (tsr >= T_Limit) {
+                       smc->srf.sr_state = SR0_WAIT ;
+                       smc->srf.TSR = smt_get_time() ;
+                       smt_send_srf(smc) ;
+                       break ;
+               }
+               /* SR11a */
+               if (cond_asserted) {
+                       smc->srf.SRThreshold = THRESHOLD_2 ;
+               }
+               /* SR11b */
+               /* SR11c */
+               /* handled above */
+               /* SR12 */
+               if (!smc->mib.fddiSMTStatRptPolicy) {
+                       smc->srf.sr_state = SR2_DISABLED ;
+                       break ;
+               }
+               break ;
+       case SR2_DISABLED :
+               if (smc->mib.fddiSMTStatRptPolicy) {
+                       smc->srf.sr_state = SR0_WAIT ;
+                       smc->srf.TSR = smt_get_time() ;
+                       smc->srf.SRThreshold = THRESHOLD_2 ;
+                       clear_all_rep(smc) ;
+                       break ;
+               }
+               break ;
+       }
+}
+
+static void clear_all_rep(struct s_smc *smc)
+{
+       struct s_srf_evc        *evc ;
+       int                     i ;
+
+       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+               evc->evc_rep_required = FALSE ;
+               if (SMT_IS_CONDITION(evc->evc_code))
+                       *evc->evc_cond_state = FALSE ;
+       }
+       smc->srf.any_report = FALSE ;
+}
+
+static void clear_reported(struct s_smc *smc)
+{
+       struct s_srf_evc        *evc ;
+       int                     i ;
+
+       smc->srf.any_report = FALSE ;
+       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+               if (SMT_IS_CONDITION(evc->evc_code)) {
+                       if (*evc->evc_cond_state == FALSE)
+                               evc->evc_rep_required = FALSE ;
+                       else
+                               smc->srf.any_report = TRUE ;
+               }
+               else {
+                       evc->evc_rep_required = FALSE ;
+                       *evc->evc_multiple = FALSE ;
+               }
+       }
+}
+
+/*
+ * build and send SMT SRF frame
+ */
+static void smt_send_srf(struct s_smc *smc)
+{
+
+       struct smt_header       *smt ;
+       struct s_srf_evc        *evc ;
+       SK_LOC_DECL(struct s_pcon,pcon) ;
+       SMbuf                   *mb ;
+       int                     i ;
+
+       static const struct fddi_addr SMT_SRF_DA = {
+               { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
+       } ;
+
+       /*
+        * build SMT header
+        */
+       if (!smc->r.sm_ma_avail)
+               return ;
+       if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
+               return ;
+
+       RS_SET(smc,RS_SOFTERROR) ;
+
+       smt = smtod(mb, struct smt_header *) ;
+       smt->smt_dest = SMT_SRF_DA ;            /* DA == SRF multicast */
+
+       /*
+        * setup parameter status
+        */
+       pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
+       pcon.pc_err = 0 ;                       /* no error */
+       pcon.pc_badset = 0 ;                    /* no bad set count */
+       pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
+
+       smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
+       smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
+
+       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
+               if (evc->evc_rep_required) {
+                       smt_add_para(smc,&pcon,evc->evc_para,
+                               (int)evc->evc_index,0) ;
+               }
+       }
+       smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
+       mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
+
+       DB_SMT("SRF: sending SRF at %x, len %d\n",smt,mb->sm_len) ;
+       DB_SMT("SRF: state SR%d Threshold %d\n",
+               smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ;
+#ifdef DEBUG
+       dump_smt(smc,smt,"SRF Send") ;
+#endif
+       smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
+       clear_reported(smc) ;
+}
+
+#endif /* no BOOT */
+#endif /* no SLIM_SMT */
+
diff --git a/drivers/net/hippi/Kconfig b/drivers/net/hippi/Kconfig
new file mode 100644 (file)
index 0000000..7393eb7
--- /dev/null
@@ -0,0 +1,39 @@
+#
+# HIPPI network device configuration
+#
+
+config HIPPI
+       bool "HIPPI driver support (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && INET && PCI
+       ---help---
+         HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
+         1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
+         can run over copper (25m) or fiber (300m on multi-mode or 10km on
+         single-mode). HIPPI networks are commonly used for clusters and to
+         connect to super computers. If you are connected to a HIPPI network
+         and have a HIPPI network card in your computer that you want to use
+         under Linux, say Y here (you must also remember to enable the driver
+         for your HIPPI card below). Most people will say N here.
+
+if HIPPI
+
+config ROADRUNNER
+       tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
+       depends on PCI
+       ---help---
+         Say Y here if this is your PCI HIPPI network card.
+
+         To compile this driver as a module, choose M here: the module
+         will be called rrunner.  If unsure, say N.
+
+config ROADRUNNER_LARGE_RINGS
+       bool "Use large TX/RX rings (EXPERIMENTAL)"
+       depends on ROADRUNNER
+       ---help---
+         If you say Y here, the RoadRunner driver will preallocate up to 2 MB
+         of additional memory to allow for fastest operation, both for
+         transmitting and receiving. This memory cannot be used by any other
+         kernel code or by user space programs. Say Y here only if you have
+         the memory.
+
+endif /* HIPPI */
diff --git a/drivers/net/hippi/Makefile b/drivers/net/hippi/Makefile
new file mode 100644 (file)
index 0000000..b95d629
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the HIPPI network device drivers.
+#
+
+obj-$(CONFIG_ROADRUNNER) += rrunner.o
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
new file mode 100644 (file)
index 0000000..e68c941
--- /dev/null
@@ -0,0 +1,1716 @@
+/*
+ * rrunner.c: Linux driver for the Essential RoadRunner HIPPI board.
+ *
+ * Copyright (C) 1998-2002 by Jes Sorensen, <jes@wildopensource.com>.
+ *
+ * Thanks to Essential Communication for providing us with hardware
+ * and very comprehensive documentation without which I would not have
+ * been able to write this driver. A special thank you to John Gibbon
+ * for sorting out the legal issues, with the NDA, allowing the code to
+ * be released under the GPL.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Thanks to Jayaram Bhat from ODS/Essential for fixing some of the
+ * stupid bugs in my code.
+ *
+ * Softnet support and various other patches from Val Henson of
+ * ODS/Essential.
+ *
+ * PCI DMA mapping code partly based on work by Francois Romieu.
+ */
+
+
+#define DEBUG 1
+#define RX_DMA_SKBUFF 1
+#define PKT_COPY_THRESHOLD 512
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/hippidevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <net/sock.h>
+
+#include <asm/system.h>
+#include <asm/cache.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define rr_if_busy(dev)     netif_queue_stopped(dev)
+#define rr_if_running(dev)  netif_running(dev)
+
+#include "rrunner.h"
+
+#define RUN_AT(x) (jiffies + (x))
+
+
+MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
+MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
+MODULE_LICENSE("GPL");
+
+static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
+
+
+static const struct net_device_ops rr_netdev_ops = {
+       .ndo_open               = rr_open,
+       .ndo_stop               = rr_close,
+       .ndo_do_ioctl           = rr_ioctl,
+       .ndo_start_xmit         = rr_start_xmit,
+       .ndo_change_mtu         = hippi_change_mtu,
+       .ndo_set_mac_address    = hippi_mac_addr,
+};
+
+/*
+ * Implementation notes:
+ *
+ * The DMA engine only allows for DMA within physical 64KB chunks of
+ * memory. The current approach of the driver (and stack) is to use
+ * linear blocks of memory for the skbuffs. However, as the data block
+ * is always the first part of the skb and skbs are 2^n aligned so we
+ * are guarantted to get the whole block within one 64KB align 64KB
+ * chunk.
+ *
+ * On the long term, relying on being able to allocate 64KB linear
+ * chunks of memory is not feasible and the skb handling code and the
+ * stack will need to know about I/O vectors or something similar.
+ */
+
+static int __devinit rr_init_one(struct pci_dev *pdev,
+       const struct pci_device_id *ent)
+{
+       struct net_device *dev;
+       static int version_disp;
+       u8 pci_latency;
+       struct rr_private *rrpriv;
+       void *tmpptr;
+       dma_addr_t ring_dma;
+       int ret = -ENOMEM;
+
+       dev = alloc_hippi_dev(sizeof(struct rr_private));
+       if (!dev)
+               goto out3;
+
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               ret = -ENODEV;
+               goto out2;
+       }
+
+       rrpriv = netdev_priv(dev);
+
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       if (pci_request_regions(pdev, "rrunner")) {
+               ret = -EIO;
+               goto out;
+       }
+
+       pci_set_drvdata(pdev, dev);
+
+       rrpriv->pci_dev = pdev;
+
+       spin_lock_init(&rrpriv->lock);
+
+       dev->irq = pdev->irq;
+       dev->netdev_ops = &rr_netdev_ops;
+
+       dev->base_addr = pci_resource_start(pdev, 0);
+
+       /* display version info if adapter is found */
+       if (!version_disp) {
+               /* set display flag to TRUE so that */
+               /* we only display this string ONCE */
+               version_disp = 1;
+               printk(version);
+       }
+
+       pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+       if (pci_latency <= 0x58){
+               pci_latency = 0x58;
+               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_latency);
+       }
+
+       pci_set_master(pdev);
+
+       printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
+              "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,
+              dev->base_addr, dev->irq, pci_latency);
+
+       /*
+        * Remap the regs into kernel space.
+        */
+
+       rrpriv->regs = ioremap(dev->base_addr, 0x1000);
+
+       if (!rrpriv->regs){
+               printk(KERN_ERR "%s:  Unable to map I/O register, "
+                       "RoadRunner will be disabled.\n", dev->name);
+               ret = -EIO;
+               goto out;
+       }
+
+       tmpptr = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+       rrpriv->tx_ring = tmpptr;
+       rrpriv->tx_ring_dma = ring_dma;
+
+       if (!tmpptr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       tmpptr = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+       rrpriv->rx_ring = tmpptr;
+       rrpriv->rx_ring_dma = ring_dma;
+
+       if (!tmpptr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       tmpptr = pci_alloc_consistent(pdev, EVT_RING_SIZE, &ring_dma);
+       rrpriv->evt_ring = tmpptr;
+       rrpriv->evt_ring_dma = ring_dma;
+
+       if (!tmpptr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /*
+        * Don't access any register before this point!
+        */
+#ifdef __BIG_ENDIAN
+       writel(readl(&rrpriv->regs->HostCtrl) | NO_SWAP,
+               &rrpriv->regs->HostCtrl);
+#endif
+       /*
+        * Need to add a case for little-endian 64-bit hosts here.
+        */
+
+       rr_init(dev);
+
+       dev->base_addr = 0;
+
+       ret = register_netdev(dev);
+       if (ret)
+               goto out;
+       return 0;
+
+ out:
+       if (rrpriv->rx_ring)
+               pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring,
+                                   rrpriv->rx_ring_dma);
+       if (rrpriv->tx_ring)
+               pci_free_consistent(pdev, TX_TOTAL_SIZE, rrpriv->tx_ring,
+                                   rrpriv->tx_ring_dma);
+       if (rrpriv->regs)
+               iounmap(rrpriv->regs);
+       if (pdev) {
+               pci_release_regions(pdev);
+               pci_set_drvdata(pdev, NULL);
+       }
+ out2:
+       free_netdev(dev);
+ out3:
+       return ret;
+}
+
+static void __devexit rr_remove_one (struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       if (dev) {
+               struct rr_private *rr = netdev_priv(dev);
+
+               if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){
+                       printk(KERN_ERR "%s: trying to unload running NIC\n",
+                              dev->name);
+                       writel(HALT_NIC, &rr->regs->HostCtrl);
+               }
+
+               pci_free_consistent(pdev, EVT_RING_SIZE, rr->evt_ring,
+                                   rr->evt_ring_dma);
+               pci_free_consistent(pdev, RX_TOTAL_SIZE, rr->rx_ring,
+                                   rr->rx_ring_dma);
+               pci_free_consistent(pdev, TX_TOTAL_SIZE, rr->tx_ring,
+                                   rr->tx_ring_dma);
+               unregister_netdev(dev);
+               iounmap(rr->regs);
+               free_netdev(dev);
+               pci_release_regions(pdev);
+               pci_disable_device(pdev);
+               pci_set_drvdata(pdev, NULL);
+       }
+}
+
+
+/*
+ * Commands are considered to be slow, thus there is no reason to
+ * inline this.
+ */
+static void rr_issue_cmd(struct rr_private *rrpriv, struct cmd *cmd)
+{
+       struct rr_regs __iomem *regs;
+       u32 idx;
+
+       regs = rrpriv->regs;
+       /*
+        * This is temporary - it will go away in the final version.
+        * We probably also want to make this function inline.
+        */
+       if (readl(&regs->HostCtrl) & NIC_HALTED){
+               printk("issuing command for halted NIC, code 0x%x, "
+                      "HostCtrl %08x\n", cmd->code, readl(&regs->HostCtrl));
+               if (readl(&regs->Mode) & FATAL_ERR)
+                       printk("error codes Fail1 %02x, Fail2 %02x\n",
+                              readl(&regs->Fail1), readl(&regs->Fail2));
+       }
+
+       idx = rrpriv->info->cmd_ctrl.pi;
+
+       writel(*(u32*)(cmd), &regs->CmdRing[idx]);
+       wmb();
+
+       idx = (idx - 1) % CMD_RING_ENTRIES;
+       rrpriv->info->cmd_ctrl.pi = idx;
+       wmb();
+
+       if (readl(&regs->Mode) & FATAL_ERR)
+               printk("error code %02x\n", readl(&regs->Fail1));
+}
+
+
+/*
+ * Reset the board in a sensible manner. The NIC is already halted
+ * when we get here and a spin-lock is held.
+ */
+static int rr_reset(struct net_device *dev)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       u32 start_pc;
+       int i;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       rr_load_firmware(dev);
+
+       writel(0x01000000, &regs->TX_state);
+       writel(0xff800000, &regs->RX_state);
+       writel(0, &regs->AssistState);
+       writel(CLEAR_INTA, &regs->LocalCtrl);
+       writel(0x01, &regs->BrkPt);
+       writel(0, &regs->Timer);
+       writel(0, &regs->TimerRef);
+       writel(RESET_DMA, &regs->DmaReadState);
+       writel(RESET_DMA, &regs->DmaWriteState);
+       writel(0, &regs->DmaWriteHostHi);
+       writel(0, &regs->DmaWriteHostLo);
+       writel(0, &regs->DmaReadHostHi);
+       writel(0, &regs->DmaReadHostLo);
+       writel(0, &regs->DmaReadLen);
+       writel(0, &regs->DmaWriteLen);
+       writel(0, &regs->DmaWriteLcl);
+       writel(0, &regs->DmaWriteIPchecksum);
+       writel(0, &regs->DmaReadLcl);
+       writel(0, &regs->DmaReadIPchecksum);
+       writel(0, &regs->PciState);
+#if (BITS_PER_LONG == 64) && defined __LITTLE_ENDIAN
+       writel(SWAP_DATA | PTR64BIT | PTR_WD_SWAP, &regs->Mode);
+#elif (BITS_PER_LONG == 64)
+       writel(SWAP_DATA | PTR64BIT | PTR_WD_NOSWAP, &regs->Mode);
+#else
+       writel(SWAP_DATA | PTR32BIT | PTR_WD_NOSWAP, &regs->Mode);
+#endif
+
+#if 0
+       /*
+        * Don't worry, this is just black magic.
+        */
+       writel(0xdf000, &regs->RxBase);
+       writel(0xdf000, &regs->RxPrd);
+       writel(0xdf000, &regs->RxCon);
+       writel(0xce000, &regs->TxBase);
+       writel(0xce000, &regs->TxPrd);
+       writel(0xce000, &regs->TxCon);
+       writel(0, &regs->RxIndPro);
+       writel(0, &regs->RxIndCon);
+       writel(0, &regs->RxIndRef);
+       writel(0, &regs->TxIndPro);
+       writel(0, &regs->TxIndCon);
+       writel(0, &regs->TxIndRef);
+       writel(0xcc000, &regs->pad10[0]);
+       writel(0, &regs->DrCmndPro);
+       writel(0, &regs->DrCmndCon);
+       writel(0, &regs->DwCmndPro);
+       writel(0, &regs->DwCmndCon);
+       writel(0, &regs->DwCmndRef);
+       writel(0, &regs->DrDataPro);
+       writel(0, &regs->DrDataCon);
+       writel(0, &regs->DrDataRef);
+       writel(0, &regs->DwDataPro);
+       writel(0, &regs->DwDataCon);
+       writel(0, &regs->DwDataRef);
+#endif
+
+       writel(0xffffffff, &regs->MbEvent);
+       writel(0, &regs->Event);
+
+       writel(0, &regs->TxPi);
+       writel(0, &regs->IpRxPi);
+
+       writel(0, &regs->EvtCon);
+       writel(0, &regs->EvtPrd);
+
+       rrpriv->info->evt_ctrl.pi = 0;
+
+       for (i = 0; i < CMD_RING_ENTRIES; i++)
+               writel(0, &regs->CmdRing[i]);
+
+/*
+ * Why 32 ? is this not cache line size dependent?
+ */
+       writel(RBURST_64|WBURST_64, &regs->PciState);
+       wmb();
+
+       start_pc = rr_read_eeprom_word(rrpriv,
+                       offsetof(struct eeprom, rncd_info.FwStart));
+
+#if (DEBUG > 1)
+       printk("%s: Executing firmware at address 0x%06x\n",
+              dev->name, start_pc);
+#endif
+
+       writel(start_pc + 0x800, &regs->Pc);
+       wmb();
+       udelay(5);
+
+       writel(start_pc, &regs->Pc);
+       wmb();
+
+       return 0;
+}
+
+
+/*
+ * Read a string from the EEPROM.
+ */
+static unsigned int rr_read_eeprom(struct rr_private *rrpriv,
+                               unsigned long offset,
+                               unsigned char *buf,
+                               unsigned long length)
+{
+       struct rr_regs __iomem *regs = rrpriv->regs;
+       u32 misc, io, host, i;
+
+       io = readl(&regs->ExtIo);
+       writel(0, &regs->ExtIo);
+       misc = readl(&regs->LocalCtrl);
+       writel(0, &regs->LocalCtrl);
+       host = readl(&regs->HostCtrl);
+       writel(host | HALT_NIC, &regs->HostCtrl);
+       mb();
+
+       for (i = 0; i < length; i++){
+               writel((EEPROM_BASE + ((offset+i) << 3)), &regs->WinBase);
+               mb();
+               buf[i] = (readl(&regs->WinData) >> 24) & 0xff;
+               mb();
+       }
+
+       writel(host, &regs->HostCtrl);
+       writel(misc, &regs->LocalCtrl);
+       writel(io, &regs->ExtIo);
+       mb();
+       return i;
+}
+
+
+/*
+ * Shortcut to read one word (4 bytes) out of the EEPROM and convert
+ * it to our CPU byte-order.
+ */
+static u32 rr_read_eeprom_word(struct rr_private *rrpriv,
+                           size_t offset)
+{
+       __be32 word;
+
+       if ((rr_read_eeprom(rrpriv, offset,
+                           (unsigned char *)&word, 4) == 4))
+               return be32_to_cpu(word);
+       return 0;
+}
+
+
+/*
+ * Write a string to the EEPROM.
+ *
+ * This is only called when the firmware is not running.
+ */
+static unsigned int write_eeprom(struct rr_private *rrpriv,
+                                unsigned long offset,
+                                unsigned char *buf,
+                                unsigned long length)
+{
+       struct rr_regs __iomem *regs = rrpriv->regs;
+       u32 misc, io, data, i, j, ready, error = 0;
+
+       io = readl(&regs->ExtIo);
+       writel(0, &regs->ExtIo);
+       misc = readl(&regs->LocalCtrl);
+       writel(ENABLE_EEPROM_WRITE, &regs->LocalCtrl);
+       mb();
+
+       for (i = 0; i < length; i++){
+               writel((EEPROM_BASE + ((offset+i) << 3)), &regs->WinBase);
+               mb();
+               data = buf[i] << 24;
+               /*
+                * Only try to write the data if it is not the same
+                * value already.
+                */
+               if ((readl(&regs->WinData) & 0xff000000) != data){
+                       writel(data, &regs->WinData);
+                       ready = 0;
+                       j = 0;
+                       mb();
+                       while(!ready){
+                               udelay(20);
+                               if ((readl(&regs->WinData) & 0xff000000) ==
+                                   data)
+                                       ready = 1;
+                               mb();
+                               if (j++ > 5000){
+                                       printk("data mismatch: %08x, "
+                                              "WinData %08x\n", data,
+                                              readl(&regs->WinData));
+                                       ready = 1;
+                                       error = 1;
+                               }
+                       }
+               }
+       }
+
+       writel(misc, &regs->LocalCtrl);
+       writel(io, &regs->ExtIo);
+       mb();
+
+       return error;
+}
+
+
+static int __devinit rr_init(struct net_device *dev)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       u32 sram_size, rev;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       rev = readl(&regs->FwRev);
+       rrpriv->fw_rev = rev;
+       if (rev > 0x00020024)
+               printk("  Firmware revision: %i.%i.%i\n", (rev >> 16),
+                      ((rev >> 8) & 0xff), (rev & 0xff));
+       else if (rev >= 0x00020000) {
+               printk("  Firmware revision: %i.%i.%i (2.0.37 or "
+                      "later is recommended)\n", (rev >> 16),
+                      ((rev >> 8) & 0xff), (rev & 0xff));
+       }else{
+               printk("  Firmware revision too old: %i.%i.%i, please "
+                      "upgrade to 2.0.37 or later.\n",
+                      (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff));
+       }
+
+#if (DEBUG > 2)
+       printk("  Maximum receive rings %i\n", readl(&regs->MaxRxRng));
+#endif
+
+       /*
+        * Read the hardware address from the eeprom.  The HW address
+        * is not really necessary for HIPPI but awfully convenient.
+        * The pointer arithmetic to put it in dev_addr is ugly, but
+        * Donald Becker does it this way for the GigE version of this
+        * card and it's shorter and more portable than any
+        * other method I've seen.  -VAL
+        */
+
+       *(__be16 *)(dev->dev_addr) =
+         htons(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA)));
+       *(__be32 *)(dev->dev_addr+2) =
+         htonl(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA[4])));
+
+       printk("  MAC: %pM\n", dev->dev_addr);
+
+       sram_size = rr_read_eeprom_word(rrpriv, 8);
+       printk("  SRAM size 0x%06x\n", sram_size);
+
+       return 0;
+}
+
+
+static int rr_init1(struct net_device *dev)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       unsigned long myjif, flags;
+       struct cmd cmd;
+       u32 hostctrl;
+       int ecode = 0;
+       short i;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       spin_lock_irqsave(&rrpriv->lock, flags);
+
+       hostctrl = readl(&regs->HostCtrl);
+       writel(hostctrl | HALT_NIC | RR_CLEAR_INT, &regs->HostCtrl);
+       wmb();
+
+       if (hostctrl & PARITY_ERR){
+               printk("%s: Parity error halting NIC - this is serious!\n",
+                      dev->name);
+               spin_unlock_irqrestore(&rrpriv->lock, flags);
+               ecode = -EFAULT;
+               goto error;
+       }
+
+       set_rxaddr(regs, rrpriv->rx_ctrl_dma);
+       set_infoaddr(regs, rrpriv->info_dma);
+
+       rrpriv->info->evt_ctrl.entry_size = sizeof(struct event);
+       rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES;
+       rrpriv->info->evt_ctrl.mode = 0;
+       rrpriv->info->evt_ctrl.pi = 0;
+       set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring_dma);
+
+       rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd);
+       rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES;
+       rrpriv->info->cmd_ctrl.mode = 0;
+       rrpriv->info->cmd_ctrl.pi = 15;
+
+       for (i = 0; i < CMD_RING_ENTRIES; i++) {
+               writel(0, &regs->CmdRing[i]);
+       }
+
+       for (i = 0; i < TX_RING_ENTRIES; i++) {
+               rrpriv->tx_ring[i].size = 0;
+               set_rraddr(&rrpriv->tx_ring[i].addr, 0);
+               rrpriv->tx_skbuff[i] = NULL;
+       }
+       rrpriv->info->tx_ctrl.entry_size = sizeof(struct tx_desc);
+       rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES;
+       rrpriv->info->tx_ctrl.mode = 0;
+       rrpriv->info->tx_ctrl.pi = 0;
+       set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring_dma);
+
+       /*
+        * Set dirty_tx before we start receiving interrupts, otherwise
+        * the interrupt handler might think it is supposed to process
+        * tx ints before we are up and running, which may cause a null
+        * pointer access in the int handler.
+        */
+       rrpriv->tx_full = 0;
+       rrpriv->cur_rx = 0;
+       rrpriv->dirty_rx = rrpriv->dirty_tx = 0;
+
+       rr_reset(dev);
+
+       /* Tuning values */
+       writel(0x5000, &regs->ConRetry);
+       writel(0x100, &regs->ConRetryTmr);
+       writel(0x500000, &regs->ConTmout);
+       writel(0x60, &regs->IntrTmr);
+       writel(0x500000, &regs->TxDataMvTimeout);
+       writel(0x200000, &regs->RxDataMvTimeout);
+       writel(0x80, &regs->WriteDmaThresh);
+       writel(0x80, &regs->ReadDmaThresh);
+
+       rrpriv->fw_running = 0;
+       wmb();
+
+       hostctrl &= ~(HALT_NIC | INVALID_INST_B | PARITY_ERR);
+       writel(hostctrl, &regs->HostCtrl);
+       wmb();
+
+       spin_unlock_irqrestore(&rrpriv->lock, flags);
+
+       for (i = 0; i < RX_RING_ENTRIES; i++) {
+               struct sk_buff *skb;
+               dma_addr_t addr;
+
+               rrpriv->rx_ring[i].mode = 0;
+               skb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC);
+               if (!skb) {
+                       printk(KERN_WARNING "%s: Unable to allocate memory "
+                              "for receive ring - halting NIC\n", dev->name);
+                       ecode = -ENOMEM;
+                       goto error;
+               }
+               rrpriv->rx_skbuff[i] = skb;
+               addr = pci_map_single(rrpriv->pci_dev, skb->data,
+                       dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+               /*
+                * Sanity test to see if we conflict with the DMA
+                * limitations of the Roadrunner.
+                */
+               if ((((unsigned long)skb->data) & 0xfff) > ~65320)
+                       printk("skb alloc error\n");
+
+               set_rraddr(&rrpriv->rx_ring[i].addr, addr);
+               rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN;
+       }
+
+       rrpriv->rx_ctrl[4].entry_size = sizeof(struct rx_desc);
+       rrpriv->rx_ctrl[4].entries = RX_RING_ENTRIES;
+       rrpriv->rx_ctrl[4].mode = 8;
+       rrpriv->rx_ctrl[4].pi = 0;
+       wmb();
+       set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring_dma);
+
+       udelay(1000);
+
+       /*
+        * Now start the FirmWare.
+        */
+       cmd.code = C_START_FW;
+       cmd.ring = 0;
+       cmd.index = 0;
+
+       rr_issue_cmd(rrpriv, &cmd);
+
+       /*
+        * Give the FirmWare time to chew on the `get running' command.
+        */
+       myjif = jiffies + 5 * HZ;
+       while (time_before(jiffies, myjif) && !rrpriv->fw_running)
+               cpu_relax();
+
+       netif_start_queue(dev);
+
+       return ecode;
+
+ error:
+       /*
+        * We might have gotten here because we are out of memory,
+        * make sure we release everything we allocated before failing
+        */
+       for (i = 0; i < RX_RING_ENTRIES; i++) {
+               struct sk_buff *skb = rrpriv->rx_skbuff[i];
+
+               if (skb) {
+                       pci_unmap_single(rrpriv->pci_dev,
+                                        rrpriv->rx_ring[i].addr.addrlo,
+                                        dev->mtu + HIPPI_HLEN,
+                                        PCI_DMA_FROMDEVICE);
+                       rrpriv->rx_ring[i].size = 0;
+                       set_rraddr(&rrpriv->rx_ring[i].addr, 0);
+                       dev_kfree_skb(skb);
+                       rrpriv->rx_skbuff[i] = NULL;
+               }
+       }
+       return ecode;
+}
+
+
+/*
+ * All events are considered to be slow (RX/TX ints do not generate
+ * events) and are handled here, outside the main interrupt handler,
+ * to reduce the size of the handler.
+ */
+static u32 rr_handle_event(struct net_device *dev, u32 prodidx, u32 eidx)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       u32 tmp;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       while (prodidx != eidx){
+               switch (rrpriv->evt_ring[eidx].code){
+               case E_NIC_UP:
+                       tmp = readl(&regs->FwRev);
+                       printk(KERN_INFO "%s: Firmware revision %i.%i.%i "
+                              "up and running\n", dev->name,
+                              (tmp >> 16), ((tmp >> 8) & 0xff), (tmp & 0xff));
+                       rrpriv->fw_running = 1;
+                       writel(RX_RING_ENTRIES - 1, &regs->IpRxPi);
+                       wmb();
+                       break;
+               case E_LINK_ON:
+                       printk(KERN_INFO "%s: Optical link ON\n", dev->name);
+                       break;
+               case E_LINK_OFF:
+                       printk(KERN_INFO "%s: Optical link OFF\n", dev->name);
+                       break;
+               case E_RX_IDLE:
+                       printk(KERN_WARNING "%s: RX data not moving\n",
+                              dev->name);
+                       goto drop;
+               case E_WATCHDOG:
+                       printk(KERN_INFO "%s: The watchdog is here to see "
+                              "us\n", dev->name);
+                       break;
+               case E_INTERN_ERR:
+                       printk(KERN_ERR "%s: HIPPI Internal NIC error\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_HOST_ERR:
+                       printk(KERN_ERR "%s: Host software error\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               /*
+                * TX events.
+                */
+               case E_CON_REJ:
+                       printk(KERN_WARNING "%s: Connection rejected\n",
+                              dev->name);
+                       dev->stats.tx_aborted_errors++;
+                       break;
+               case E_CON_TMOUT:
+                       printk(KERN_WARNING "%s: Connection timeout\n",
+                              dev->name);
+                       break;
+               case E_DISC_ERR:
+                       printk(KERN_WARNING "%s: HIPPI disconnect error\n",
+                              dev->name);
+                       dev->stats.tx_aborted_errors++;
+                       break;
+               case E_INT_PRTY:
+                       printk(KERN_ERR "%s: HIPPI Internal Parity error\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_TX_IDLE:
+                       printk(KERN_WARNING "%s: Transmitter idle\n",
+                              dev->name);
+                       break;
+               case E_TX_LINK_DROP:
+                       printk(KERN_WARNING "%s: Link lost during transmit\n",
+                              dev->name);
+                       dev->stats.tx_aborted_errors++;
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_TX_INV_RNG:
+                       printk(KERN_ERR "%s: Invalid send ring block\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_TX_INV_BUF:
+                       printk(KERN_ERR "%s: Invalid send buffer address\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_TX_INV_DSC:
+                       printk(KERN_ERR "%s: Invalid descriptor address\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               /*
+                * RX events.
+                */
+               case E_RX_RNG_OUT:
+                       printk(KERN_INFO "%s: Receive ring full\n", dev->name);
+                       break;
+
+               case E_RX_PAR_ERR:
+                       printk(KERN_WARNING "%s: Receive parity error\n",
+                              dev->name);
+                       goto drop;
+               case E_RX_LLRC_ERR:
+                       printk(KERN_WARNING "%s: Receive LLRC error\n",
+                              dev->name);
+                       goto drop;
+               case E_PKT_LN_ERR:
+                       printk(KERN_WARNING "%s: Receive packet length "
+                              "error\n", dev->name);
+                       goto drop;
+               case E_DTA_CKSM_ERR:
+                       printk(KERN_WARNING "%s: Data checksum error\n",
+                              dev->name);
+                       goto drop;
+               case E_SHT_BST:
+                       printk(KERN_WARNING "%s: Unexpected short burst "
+                              "error\n", dev->name);
+                       goto drop;
+               case E_STATE_ERR:
+                       printk(KERN_WARNING "%s: Recv. state transition"
+                              " error\n", dev->name);
+                       goto drop;
+               case E_UNEXP_DATA:
+                       printk(KERN_WARNING "%s: Unexpected data error\n",
+                              dev->name);
+                       goto drop;
+               case E_LST_LNK_ERR:
+                       printk(KERN_WARNING "%s: Link lost error\n",
+                              dev->name);
+                       goto drop;
+               case E_FRM_ERR:
+                       printk(KERN_WARNING "%s: Framming Error\n",
+                              dev->name);
+                       goto drop;
+               case E_FLG_SYN_ERR:
+                       printk(KERN_WARNING "%s: Flag sync. lost during "
+                              "packet\n", dev->name);
+                       goto drop;
+               case E_RX_INV_BUF:
+                       printk(KERN_ERR "%s: Invalid receive buffer "
+                              "address\n", dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_RX_INV_DSC:
+                       printk(KERN_ERR "%s: Invalid receive descriptor "
+                              "address\n", dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               case E_RNG_BLK:
+                       printk(KERN_ERR "%s: Invalid ring block\n",
+                              dev->name);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       wmb();
+                       break;
+               drop:
+                       /* Label packet to be dropped.
+                        * Actual dropping occurs in rx
+                        * handling.
+                        *
+                        * The index of packet we get to drop is
+                        * the index of the packet following
+                        * the bad packet. -kbf
+                        */
+                       {
+                               u16 index = rrpriv->evt_ring[eidx].index;
+                               index = (index + (RX_RING_ENTRIES - 1)) %
+                                       RX_RING_ENTRIES;
+                               rrpriv->rx_ring[index].mode |=
+                                       (PACKET_BAD | PACKET_END);
+                       }
+                       break;
+               default:
+                       printk(KERN_WARNING "%s: Unhandled event 0x%02x\n",
+                              dev->name, rrpriv->evt_ring[eidx].code);
+               }
+               eidx = (eidx + 1) % EVT_RING_ENTRIES;
+       }
+
+       rrpriv->info->evt_ctrl.pi = eidx;
+       wmb();
+       return eidx;
+}
+
+
+static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
+{
+       struct rr_private *rrpriv = netdev_priv(dev);
+       struct rr_regs __iomem *regs = rrpriv->regs;
+
+       do {
+               struct rx_desc *desc;
+               u32 pkt_len;
+
+               desc = &(rrpriv->rx_ring[index]);
+               pkt_len = desc->size;
+#if (DEBUG > 2)
+               printk("index %i, rxlimit %i\n", index, rxlimit);
+               printk("len %x, mode %x\n", pkt_len, desc->mode);
+#endif
+               if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){
+                       dev->stats.rx_dropped++;
+                       goto defer;
+               }
+
+               if (pkt_len > 0){
+                       struct sk_buff *skb, *rx_skb;
+
+                       rx_skb = rrpriv->rx_skbuff[index];
+
+                       if (pkt_len < PKT_COPY_THRESHOLD) {
+                               skb = alloc_skb(pkt_len, GFP_ATOMIC);
+                               if (skb == NULL){
+                                       printk(KERN_WARNING "%s: Unable to allocate skb (%i bytes), deferring packet\n", dev->name, pkt_len);
+                                       dev->stats.rx_dropped++;
+                                       goto defer;
+                               } else {
+                                       pci_dma_sync_single_for_cpu(rrpriv->pci_dev,
+                                                                   desc->addr.addrlo,
+                                                                   pkt_len,
+                                                                   PCI_DMA_FROMDEVICE);
+
+                                       memcpy(skb_put(skb, pkt_len),
+                                              rx_skb->data, pkt_len);
+
+                                       pci_dma_sync_single_for_device(rrpriv->pci_dev,
+                                                                      desc->addr.addrlo,
+                                                                      pkt_len,
+                                                                      PCI_DMA_FROMDEVICE);
+                               }
+                       }else{
+                               struct sk_buff *newskb;
+
+                               newskb = alloc_skb(dev->mtu + HIPPI_HLEN,
+                                       GFP_ATOMIC);
+                               if (newskb){
+                                       dma_addr_t addr;
+
+                                       pci_unmap_single(rrpriv->pci_dev,
+                                               desc->addr.addrlo, dev->mtu +
+                                               HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+                                       skb = rx_skb;
+                                       skb_put(skb, pkt_len);
+                                       rrpriv->rx_skbuff[index] = newskb;
+                                       addr = pci_map_single(rrpriv->pci_dev,
+                                               newskb->data,
+                                               dev->mtu + HIPPI_HLEN,
+                                               PCI_DMA_FROMDEVICE);
+                                       set_rraddr(&desc->addr, addr);
+                               } else {
+                                       printk("%s: Out of memory, deferring "
+                                              "packet\n", dev->name);
+                                       dev->stats.rx_dropped++;
+                                       goto defer;
+                               }
+                       }
+                       skb->protocol = hippi_type_trans(skb, dev);
+
+                       netif_rx(skb);          /* send it up */
+
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += pkt_len;
+               }
+       defer:
+               desc->mode = 0;
+               desc->size = dev->mtu + HIPPI_HLEN;
+
+               if ((index & 7) == 7)
+                       writel(index, &regs->IpRxPi);
+
+               index = (index + 1) % RX_RING_ENTRIES;
+       } while(index != rxlimit);
+
+       rrpriv->cur_rx = index;
+       wmb();
+}
+
+
+static irqreturn_t rr_interrupt(int irq, void *dev_id)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       struct net_device *dev = (struct net_device *)dev_id;
+       u32 prodidx, rxindex, eidx, txcsmr, rxlimit, txcon;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       if (!(readl(&regs->HostCtrl) & RR_INT))
+               return IRQ_NONE;
+
+       spin_lock(&rrpriv->lock);
+
+       prodidx = readl(&regs->EvtPrd);
+       txcsmr = (prodidx >> 8) & 0xff;
+       rxlimit = (prodidx >> 16) & 0xff;
+       prodidx &= 0xff;
+
+#if (DEBUG > 2)
+       printk("%s: interrupt, prodidx = %i, eidx = %i\n", dev->name,
+              prodidx, rrpriv->info->evt_ctrl.pi);
+#endif
+       /*
+        * Order here is important.  We must handle events
+        * before doing anything else in order to catch
+        * such things as LLRC errors, etc -kbf
+        */
+
+       eidx = rrpriv->info->evt_ctrl.pi;
+       if (prodidx != eidx)
+               eidx = rr_handle_event(dev, prodidx, eidx);
+
+       rxindex = rrpriv->cur_rx;
+       if (rxindex != rxlimit)
+               rx_int(dev, rxlimit, rxindex);
+
+       txcon = rrpriv->dirty_tx;
+       if (txcsmr != txcon) {
+               do {
+                       /* Due to occational firmware TX producer/consumer out
+                        * of sync. error need to check entry in ring -kbf
+                        */
+                       if(rrpriv->tx_skbuff[txcon]){
+                               struct tx_desc *desc;
+                               struct sk_buff *skb;
+
+                               desc = &(rrpriv->tx_ring[txcon]);
+                               skb = rrpriv->tx_skbuff[txcon];
+
+                               dev->stats.tx_packets++;
+                               dev->stats.tx_bytes += skb->len;
+
+                               pci_unmap_single(rrpriv->pci_dev,
+                                                desc->addr.addrlo, skb->len,
+                                                PCI_DMA_TODEVICE);
+                               dev_kfree_skb_irq(skb);
+
+                               rrpriv->tx_skbuff[txcon] = NULL;
+                               desc->size = 0;
+                               set_rraddr(&rrpriv->tx_ring[txcon].addr, 0);
+                               desc->mode = 0;
+                       }
+                       txcon = (txcon + 1) % TX_RING_ENTRIES;
+               } while (txcsmr != txcon);
+               wmb();
+
+               rrpriv->dirty_tx = txcon;
+               if (rrpriv->tx_full && rr_if_busy(dev) &&
+                   (((rrpriv->info->tx_ctrl.pi + 1) % TX_RING_ENTRIES)
+                    != rrpriv->dirty_tx)){
+                       rrpriv->tx_full = 0;
+                       netif_wake_queue(dev);
+               }
+       }
+
+       eidx |= ((txcsmr << 8) | (rxlimit << 16));
+       writel(eidx, &regs->EvtCon);
+       wmb();
+
+       spin_unlock(&rrpriv->lock);
+       return IRQ_HANDLED;
+}
+
+static inline void rr_raz_tx(struct rr_private *rrpriv,
+                            struct net_device *dev)
+{
+       int i;
+
+       for (i = 0; i < TX_RING_ENTRIES; i++) {
+               struct sk_buff *skb = rrpriv->tx_skbuff[i];
+
+               if (skb) {
+                       struct tx_desc *desc = &(rrpriv->tx_ring[i]);
+
+                       pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
+                               skb->len, PCI_DMA_TODEVICE);
+                       desc->size = 0;
+                       set_rraddr(&desc->addr, 0);
+                       dev_kfree_skb(skb);
+                       rrpriv->tx_skbuff[i] = NULL;
+               }
+       }
+}
+
+
+static inline void rr_raz_rx(struct rr_private *rrpriv,
+                            struct net_device *dev)
+{
+       int i;
+
+       for (i = 0; i < RX_RING_ENTRIES; i++) {
+               struct sk_buff *skb = rrpriv->rx_skbuff[i];
+
+               if (skb) {
+                       struct rx_desc *desc = &(rrpriv->rx_ring[i]);
+
+                       pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
+                               dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+                       desc->size = 0;
+                       set_rraddr(&desc->addr, 0);
+                       dev_kfree_skb(skb);
+                       rrpriv->rx_skbuff[i] = NULL;
+               }
+       }
+}
+
+static void rr_timer(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct rr_private *rrpriv = netdev_priv(dev);
+       struct rr_regs __iomem *regs = rrpriv->regs;
+       unsigned long flags;
+
+       if (readl(&regs->HostCtrl) & NIC_HALTED){
+               printk("%s: Restarting nic\n", dev->name);
+               memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl));
+               memset(rrpriv->info, 0, sizeof(struct rr_info));
+               wmb();
+
+               rr_raz_tx(rrpriv, dev);
+               rr_raz_rx(rrpriv, dev);
+
+               if (rr_init1(dev)) {
+                       spin_lock_irqsave(&rrpriv->lock, flags);
+                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
+                              &regs->HostCtrl);
+                       spin_unlock_irqrestore(&rrpriv->lock, flags);
+               }
+       }
+       rrpriv->timer.expires = RUN_AT(5*HZ);
+       add_timer(&rrpriv->timer);
+}
+
+
+static int rr_open(struct net_device *dev)
+{
+       struct rr_private *rrpriv = netdev_priv(dev);
+       struct pci_dev *pdev = rrpriv->pci_dev;
+       struct rr_regs __iomem *regs;
+       int ecode = 0;
+       unsigned long flags;
+       dma_addr_t dma_addr;
+
+       regs = rrpriv->regs;
+
+       if (rrpriv->fw_rev < 0x00020000) {
+               printk(KERN_WARNING "%s: trying to configure device with "
+                      "obsolete firmware\n", dev->name);
+               ecode = -EBUSY;
+               goto error;
+       }
+
+       rrpriv->rx_ctrl = pci_alloc_consistent(pdev,
+                                              256 * sizeof(struct ring_ctrl),
+                                              &dma_addr);
+       if (!rrpriv->rx_ctrl) {
+               ecode = -ENOMEM;
+               goto error;
+       }
+       rrpriv->rx_ctrl_dma = dma_addr;
+       memset(rrpriv->rx_ctrl, 0, 256*sizeof(struct ring_ctrl));
+
+       rrpriv->info = pci_alloc_consistent(pdev, sizeof(struct rr_info),
+                                           &dma_addr);
+       if (!rrpriv->info) {
+               ecode = -ENOMEM;
+               goto error;
+       }
+       rrpriv->info_dma = dma_addr;
+       memset(rrpriv->info, 0, sizeof(struct rr_info));
+       wmb();
+
+       spin_lock_irqsave(&rrpriv->lock, flags);
+       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);
+       readl(&regs->HostCtrl);
+       spin_unlock_irqrestore(&rrpriv->lock, flags);
+
+       if (request_irq(dev->irq, rr_interrupt, IRQF_SHARED, dev->name, dev)) {
+               printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
+                      dev->name, dev->irq);
+               ecode = -EAGAIN;
+               goto error;
+       }
+
+       if ((ecode = rr_init1(dev)))
+               goto error;
+
+       /* Set the timer to switch to check for link beat and perhaps switch
+          to an alternate media type. */
+       init_timer(&rrpriv->timer);
+       rrpriv->timer.expires = RUN_AT(5*HZ);           /* 5 sec. watchdog */
+       rrpriv->timer.data = (unsigned long)dev;
+       rrpriv->timer.function = rr_timer;               /* timer handler */
+       add_timer(&rrpriv->timer);
+
+       netif_start_queue(dev);
+
+       return ecode;
+
+ error:
+       spin_lock_irqsave(&rrpriv->lock, flags);
+       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);
+       spin_unlock_irqrestore(&rrpriv->lock, flags);
+
+       if (rrpriv->info) {
+               pci_free_consistent(pdev, sizeof(struct rr_info), rrpriv->info,
+                                   rrpriv->info_dma);
+               rrpriv->info = NULL;
+       }
+       if (rrpriv->rx_ctrl) {
+               pci_free_consistent(pdev, sizeof(struct ring_ctrl),
+                                   rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
+               rrpriv->rx_ctrl = NULL;
+       }
+
+       netif_stop_queue(dev);
+
+       return ecode;
+}
+
+
+static void rr_dump(struct net_device *dev)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       u32 index, cons;
+       short i;
+       int len;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       printk("%s: dumping NIC TX rings\n", dev->name);
+
+       printk("RxPrd %08x, TxPrd %02x, EvtPrd %08x, TxPi %02x, TxCtrlPi %02x\n",
+              readl(&regs->RxPrd), readl(&regs->TxPrd),
+              readl(&regs->EvtPrd), readl(&regs->TxPi),
+              rrpriv->info->tx_ctrl.pi);
+
+       printk("Error code 0x%x\n", readl(&regs->Fail1));
+
+       index = (((readl(&regs->EvtPrd) >> 8) & 0xff) - 1) % TX_RING_ENTRIES;
+       cons = rrpriv->dirty_tx;
+       printk("TX ring index %i, TX consumer %i\n",
+              index, cons);
+
+       if (rrpriv->tx_skbuff[index]){
+               len = min_t(int, 0x80, rrpriv->tx_skbuff[index]->len);
+               printk("skbuff for index %i is valid - dumping data (0x%x bytes - DMA len 0x%x)\n", index, len, rrpriv->tx_ring[index].size);
+               for (i = 0; i < len; i++){
+                       if (!(i & 7))
+                               printk("\n");
+                       printk("%02x ", (unsigned char) rrpriv->tx_skbuff[index]->data[i]);
+               }
+               printk("\n");
+       }
+
+       if (rrpriv->tx_skbuff[cons]){
+               len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len);
+               printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len);
+               printk("mode 0x%x, size 0x%x,\n phys %08Lx, skbuff-addr %08lx, truesize 0x%x\n",
+                      rrpriv->tx_ring[cons].mode,
+                      rrpriv->tx_ring[cons].size,
+                      (unsigned long long) rrpriv->tx_ring[cons].addr.addrlo,
+                      (unsigned long)rrpriv->tx_skbuff[cons]->data,
+                      (unsigned int)rrpriv->tx_skbuff[cons]->truesize);
+               for (i = 0; i < len; i++){
+                       if (!(i & 7))
+                               printk("\n");
+                       printk("%02x ", (unsigned char)rrpriv->tx_ring[cons].size);
+               }
+               printk("\n");
+       }
+
+       printk("dumping TX ring info:\n");
+       for (i = 0; i < TX_RING_ENTRIES; i++)
+               printk("mode 0x%x, size 0x%x, phys-addr %08Lx\n",
+                      rrpriv->tx_ring[i].mode,
+                      rrpriv->tx_ring[i].size,
+                      (unsigned long long) rrpriv->tx_ring[i].addr.addrlo);
+
+}
+
+
+static int rr_close(struct net_device *dev)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       unsigned long flags;
+       u32 tmp;
+       short i;
+
+       netif_stop_queue(dev);
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       /*
+        * Lock to make sure we are not cleaning up while another CPU
+        * is handling interrupts.
+        */
+       spin_lock_irqsave(&rrpriv->lock, flags);
+
+       tmp = readl(&regs->HostCtrl);
+       if (tmp & NIC_HALTED){
+               printk("%s: NIC already halted\n", dev->name);
+               rr_dump(dev);
+       }else{
+               tmp |= HALT_NIC | RR_CLEAR_INT;
+               writel(tmp, &regs->HostCtrl);
+               readl(&regs->HostCtrl);
+       }
+
+       rrpriv->fw_running = 0;
+
+       del_timer_sync(&rrpriv->timer);
+
+       writel(0, &regs->TxPi);
+       writel(0, &regs->IpRxPi);
+
+       writel(0, &regs->EvtCon);
+       writel(0, &regs->EvtPrd);
+
+       for (i = 0; i < CMD_RING_ENTRIES; i++)
+               writel(0, &regs->CmdRing[i]);
+
+       rrpriv->info->tx_ctrl.entries = 0;
+       rrpriv->info->cmd_ctrl.pi = 0;
+       rrpriv->info->evt_ctrl.pi = 0;
+       rrpriv->rx_ctrl[4].entries = 0;
+
+       rr_raz_tx(rrpriv, dev);
+       rr_raz_rx(rrpriv, dev);
+
+       pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl),
+                           rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
+       rrpriv->rx_ctrl = NULL;
+
+       pci_free_consistent(rrpriv->pci_dev, sizeof(struct rr_info),
+                           rrpriv->info, rrpriv->info_dma);
+       rrpriv->info = NULL;
+
+       free_irq(dev->irq, dev);
+       spin_unlock_irqrestore(&rrpriv->lock, flags);
+
+       return 0;
+}
+
+
+static netdev_tx_t rr_start_xmit(struct sk_buff *skb,
+                                struct net_device *dev)
+{
+       struct rr_private *rrpriv = netdev_priv(dev);
+       struct rr_regs __iomem *regs = rrpriv->regs;
+       struct hippi_cb *hcb = (struct hippi_cb *) skb->cb;
+       struct ring_ctrl *txctrl;
+       unsigned long flags;
+       u32 index, len = skb->len;
+       u32 *ifield;
+       struct sk_buff *new_skb;
+
+       if (readl(&regs->Mode) & FATAL_ERR)
+               printk("error codes Fail1 %02x, Fail2 %02x\n",
+                      readl(&regs->Fail1), readl(&regs->Fail2));
+
+       /*
+        * We probably need to deal with tbusy here to prevent overruns.
+        */
+
+       if (skb_headroom(skb) < 8){
+               printk("incoming skb too small - reallocating\n");
+               if (!(new_skb = dev_alloc_skb(len + 8))) {
+                       dev_kfree_skb(skb);
+                       netif_wake_queue(dev);
+                       return NETDEV_TX_OK;
+               }
+               skb_reserve(new_skb, 8);
+               skb_put(new_skb, len);
+               skb_copy_from_linear_data(skb, new_skb->data, len);
+               dev_kfree_skb(skb);
+               skb = new_skb;
+       }
+
+       ifield = (u32 *)skb_push(skb, 8);
+
+       ifield[0] = 0;
+       ifield[1] = hcb->ifield;
+
+       /*
+        * We don't need the lock before we are actually going to start
+        * fiddling with the control blocks.
+        */
+       spin_lock_irqsave(&rrpriv->lock, flags);
+
+       txctrl = &rrpriv->info->tx_ctrl;
+
+       index = txctrl->pi;
+
+       rrpriv->tx_skbuff[index] = skb;
+       set_rraddr(&rrpriv->tx_ring[index].addr, pci_map_single(
+               rrpriv->pci_dev, skb->data, len + 8, PCI_DMA_TODEVICE));
+       rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */
+       rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END;
+       txctrl->pi = (index + 1) % TX_RING_ENTRIES;
+       wmb();
+       writel(txctrl->pi, &regs->TxPi);
+
+       if (txctrl->pi == rrpriv->dirty_tx){
+               rrpriv->tx_full = 1;
+               netif_stop_queue(dev);
+       }
+
+       spin_unlock_irqrestore(&rrpriv->lock, flags);
+
+       return NETDEV_TX_OK;
+}
+
+
+/*
+ * Read the firmware out of the EEPROM and put it into the SRAM
+ * (or from user space - later)
+ *
+ * This operation requires the NIC to be halted and is performed with
+ * interrupts disabled and with the spinlock hold.
+ */
+static int rr_load_firmware(struct net_device *dev)
+{
+       struct rr_private *rrpriv;
+       struct rr_regs __iomem *regs;
+       size_t eptr, segptr;
+       int i, j;
+       u32 localctrl, sptr, len, tmp;
+       u32 p2len, p2size, nr_seg, revision, io, sram_size;
+
+       rrpriv = netdev_priv(dev);
+       regs = rrpriv->regs;
+
+       if (dev->flags & IFF_UP)
+               return -EBUSY;
+
+       if (!(readl(&regs->HostCtrl) & NIC_HALTED)){
+               printk("%s: Trying to load firmware to a running NIC.\n",
+                      dev->name);
+               return -EBUSY;
+       }
+
+       localctrl = readl(&regs->LocalCtrl);
+       writel(0, &regs->LocalCtrl);
+
+       writel(0, &regs->EvtPrd);
+       writel(0, &regs->RxPrd);
+       writel(0, &regs->TxPrd);
+
+       /*
+        * First wipe the entire SRAM, otherwise we might run into all
+        * kinds of trouble ... sigh, this took almost all afternoon
+        * to track down ;-(
+        */
+       io = readl(&regs->ExtIo);
+       writel(0, &regs->ExtIo);
+       sram_size = rr_read_eeprom_word(rrpriv, 8);
+
+       for (i = 200; i < sram_size / 4; i++){
+               writel(i * 4, &regs->WinBase);
+               mb();
+               writel(0, &regs->WinData);
+               mb();
+       }
+       writel(io, &regs->ExtIo);
+       mb();
+
+       eptr = rr_read_eeprom_word(rrpriv,
+                      offsetof(struct eeprom, rncd_info.AddrRunCodeSegs));
+       eptr = ((eptr & 0x1fffff) >> 3);
+
+       p2len = rr_read_eeprom_word(rrpriv, 0x83*4);
+       p2len = (p2len << 2);
+       p2size = rr_read_eeprom_word(rrpriv, 0x84*4);
+       p2size = ((p2size & 0x1fffff) >> 3);
+
+       if ((eptr < p2size) || (eptr > (p2size + p2len))){
+               printk("%s: eptr is invalid\n", dev->name);
+               goto out;
+       }
+
+       revision = rr_read_eeprom_word(rrpriv,
+                       offsetof(struct eeprom, manf.HeaderFmt));
+
+       if (revision != 1){
+               printk("%s: invalid firmware format (%i)\n",
+                      dev->name, revision);
+               goto out;
+       }
+
+       nr_seg = rr_read_eeprom_word(rrpriv, eptr);
+       eptr +=4;
+#if (DEBUG > 1)
+       printk("%s: nr_seg %i\n", dev->name, nr_seg);
+#endif
+
+       for (i = 0; i < nr_seg; i++){
+               sptr = rr_read_eeprom_word(rrpriv, eptr);
+               eptr += 4;
+               len = rr_read_eeprom_word(rrpriv, eptr);
+               eptr += 4;
+               segptr = rr_read_eeprom_word(rrpriv, eptr);
+               segptr = ((segptr & 0x1fffff) >> 3);
+               eptr += 4;
+#if (DEBUG > 1)
+               printk("%s: segment %i, sram address %06x, length %04x, segptr %06x\n",
+                      dev->name, i, sptr, len, segptr);
+#endif
+               for (j = 0; j < len; j++){
+                       tmp = rr_read_eeprom_word(rrpriv, segptr);
+                       writel(sptr, &regs->WinBase);
+                       mb();
+                       writel(tmp, &regs->WinData);
+                       mb();
+                       segptr += 4;
+                       sptr += 4;
+               }
+       }
+
+out:
+       writel(localctrl, &regs->LocalCtrl);
+       mb();
+       return 0;
+}
+
+
+static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct rr_private *rrpriv;
+       unsigned char *image, *oldimage;
+       unsigned long flags;
+       unsigned int i;
+       int error = -EOPNOTSUPP;
+
+       rrpriv = netdev_priv(dev);
+
+       switch(cmd){
+       case SIOCRRGFW:
+               if (!capable(CAP_SYS_RAWIO)){
+                       return -EPERM;
+               }
+
+               image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+               if (!image){
+                       printk(KERN_ERR "%s: Unable to allocate memory "
+                              "for EEPROM image\n", dev->name);
+                       return -ENOMEM;
+               }
+
+
+               if (rrpriv->fw_running){
+                       printk("%s: Firmware already running\n", dev->name);
+                       error = -EPERM;
+                       goto gf_out;
+               }
+
+               spin_lock_irqsave(&rrpriv->lock, flags);
+               i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
+               spin_unlock_irqrestore(&rrpriv->lock, flags);
+               if (i != EEPROM_BYTES){
+                       printk(KERN_ERR "%s: Error reading EEPROM\n",
+                              dev->name);
+                       error = -EFAULT;
+                       goto gf_out;
+               }
+               error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
+               if (error)
+                       error = -EFAULT;
+       gf_out:
+               kfree(image);
+               return error;
+
+       case SIOCRRPFW:
+               if (!capable(CAP_SYS_RAWIO)){
+                       return -EPERM;
+               }
+
+               image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+               oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+               if (!image || !oldimage) {
+                       printk(KERN_ERR "%s: Unable to allocate memory "
+                              "for EEPROM image\n", dev->name);
+                       error = -ENOMEM;
+                       goto wf_out;
+               }
+
+               error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
+               if (error) {
+                       error = -EFAULT;
+                       goto wf_out;
+               }
+
+               if (rrpriv->fw_running){
+                       printk("%s: Firmware already running\n", dev->name);
+                       error = -EPERM;
+                       goto wf_out;
+               }
+
+               printk("%s: Updating EEPROM firmware\n", dev->name);
+
+               spin_lock_irqsave(&rrpriv->lock, flags);
+               error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
+               if (error)
+                       printk(KERN_ERR "%s: Error writing EEPROM\n",
+                              dev->name);
+
+               i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);
+               spin_unlock_irqrestore(&rrpriv->lock, flags);
+
+               if (i != EEPROM_BYTES)
+                       printk(KERN_ERR "%s: Error reading back EEPROM "
+                              "image\n", dev->name);
+
+               error = memcmp(image, oldimage, EEPROM_BYTES);
+               if (error){
+                       printk(KERN_ERR "%s: Error verifying EEPROM image\n",
+                              dev->name);
+                       error = -EFAULT;
+               }
+       wf_out:
+               kfree(oldimage);
+               kfree(image);
+               return error;
+
+       case SIOCRRID:
+               return put_user(0x52523032, (int __user *)rq->ifr_data);
+       default:
+               return error;
+       }
+}
+
+static DEFINE_PCI_DEVICE_TABLE(rr_pci_tbl) = {
+       { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { 0,}
+};
+MODULE_DEVICE_TABLE(pci, rr_pci_tbl);
+
+static struct pci_driver rr_driver = {
+       .name           = "rrunner",
+       .id_table       = rr_pci_tbl,
+       .probe          = rr_init_one,
+       .remove         = __devexit_p(rr_remove_one),
+};
+
+static int __init rr_init_module(void)
+{
+       return pci_register_driver(&rr_driver);
+}
+
+static void __exit rr_cleanup_module(void)
+{
+       pci_unregister_driver(&rr_driver);
+}
+
+module_init(rr_init_module);
+module_exit(rr_cleanup_module);
diff --git a/drivers/net/hippi/rrunner.h b/drivers/net/hippi/rrunner.h
new file mode 100644 (file)
index 0000000..2816904
--- /dev/null
@@ -0,0 +1,846 @@
+#ifndef _RRUNNER_H_
+#define _RRUNNER_H_
+
+#include <linux/interrupt.h>
+
+#if ((BITS_PER_LONG != 32) && (BITS_PER_LONG != 64))
+#error "BITS_PER_LONG not defined or not valid"
+#endif
+
+
+struct rr_regs {
+
+       u32     pad0[16];
+
+       u32     HostCtrl;
+       u32     LocalCtrl;
+       u32     Pc;
+       u32     BrkPt;
+
+/* Timer increments every 0.97 micro-seconds (unsigned int) */
+       u32     Timer_Hi;
+       u32     Timer;
+       u32     TimerRef;
+       u32     PciState;
+
+       u32     Event;
+       u32     MbEvent;
+
+       u32     WinBase;
+       u32     WinData;
+       u32     RX_state;
+       u32     TX_state;
+
+       u32     Overhead;
+       u32     ExtIo;
+
+       u32     DmaWriteHostHi;
+       u32     DmaWriteHostLo;
+
+       u32     pad1[2];
+
+       u32     DmaReadHostHi;
+       u32     DmaReadHostLo;
+
+       u32     pad2;
+
+       u32     DmaReadLen;
+       u32     DmaWriteState;
+
+       u32     DmaWriteLcl;
+       u32     DmaWriteIPchecksum;
+       u32     DmaWriteLen;
+       u32     DmaReadState;
+       u32     DmaReadLcl;
+       u32     DmaReadIPchecksum;
+       u32     pad3;
+
+       u32     RxBase;
+       u32     RxPrd;
+       u32     RxCon;
+
+       u32     pad4;
+
+       u32     TxBase;
+       u32     TxPrd;
+       u32     TxCon;
+
+       u32     pad5;
+
+       u32     RxIndPro;
+       u32     RxIndCon;
+       u32     RxIndRef;
+
+       u32     pad6;
+
+       u32     TxIndPro;
+       u32     TxIndCon;
+       u32     TxIndRef;
+
+       u32     pad7[17];
+
+       u32     DrCmndPro;
+       u32     DrCmndCon;
+       u32     DrCmndRef;
+
+       u32     pad8;
+
+       u32     DwCmndPro;
+       u32     DwCmndCon;
+       u32     DwCmndRef;
+
+       u32     AssistState;
+
+       u32     DrDataPro;
+       u32     DrDataCon;
+       u32     DrDataRef;
+
+       u32     pad9;
+
+       u32     DwDataPro;
+       u32     DwDataCon;
+       u32     DwDataRef;
+
+       u32     pad10[33];
+
+       u32     EvtCon;
+
+       u32     pad11[5];
+
+       u32     TxPi;
+       u32     IpRxPi;
+
+       u32     pad11a[8];
+
+       u32     CmdRing[16];
+
+/* The ULA is in two registers the high order two bytes of the first
+ * word contain the RunCode features.
+ * ula0                res     res     byte0   byte1
+ * ula1                byte2   byte3   byte4   byte5
+ */
+       u32     Ula0;
+       u32     Ula1;
+
+       u32     RxRingHi;
+       u32     RxRingLo;
+
+       u32     InfoPtrHi;
+       u32     InfoPtrLo;
+
+       u32     Mode;
+
+       u32     ConRetry;
+       u32     ConRetryTmr;
+
+       u32     ConTmout;
+       u32     CtatTmr;
+
+       u32     MaxRxRng;
+
+       u32     IntrTmr;
+       u32     TxDataMvTimeout;
+       u32     RxDataMvTimeout;
+
+       u32     EvtPrd;
+       u32     TraceIdx;
+
+       u32     Fail1;
+       u32     Fail2;
+
+       u32     DrvPrm;
+
+       u32     FilterLA;
+
+       u32     FwRev;
+       u32     FwRes1;
+       u32     FwRes2;
+       u32     FwRes3;
+
+       u32     WriteDmaThresh;
+       u32     ReadDmaThresh;
+
+       u32     pad12[325];
+       u32     Window[512];
+};
+
+/*
+ * Host control register bits.
+ */
+
+#define RR_INT         0x01
+#define RR_CLEAR_INT   0x02
+#define NO_SWAP                0x04000004
+#define NO_SWAP1       0x00000004
+#define PCI_RESET_NIC  0x08
+#define HALT_NIC       0x10
+#define SSTEP_NIC      0x20
+#define MEM_READ_MULTI 0x40
+#define NIC_HALTED     0x100
+#define HALT_INST      0x200
+#define PARITY_ERR     0x400
+#define INVALID_INST_B 0x800
+#define RR_REV_2       0x20000000
+#define RR_REV_MASK    0xf0000000
+
+/*
+ * Local control register bits.
+ */
+
+#define INTA_STATE             0x01
+#define CLEAR_INTA             0x02
+#define FAST_EEPROM_ACCESS     0x08
+#define ENABLE_EXTRA_SRAM      0x100
+#define ENABLE_EXTRA_DESC      0x200
+#define ENABLE_PARITY          0x400
+#define FORCE_DMA_PARITY_ERROR 0x800
+#define ENABLE_EEPROM_WRITE    0x1000
+#define ENABLE_DATA_CACHE      0x2000
+#define SRAM_LO_PARITY_ERR     0x4000
+#define SRAM_HI_PARITY_ERR     0x8000
+
+/*
+ * PCI state bits.
+ */
+
+#define FORCE_PCI_RESET                0x01
+#define PROVIDE_LENGTH         0x02
+#define MASK_DMA_READ_MAX      0x1C
+#define RBURST_DISABLE         0x00
+#define RBURST_4               0x04
+#define RBURST_16              0x08
+#define RBURST_32              0x0C
+#define RBURST_64              0x10
+#define RBURST_128             0x14
+#define RBURST_256             0x18
+#define RBURST_1024            0x1C
+#define MASK_DMA_WRITE_MAX     0xE0
+#define WBURST_DISABLE         0x00
+#define WBURST_4               0x20
+#define WBURST_16              0x40
+#define WBURST_32              0x60
+#define WBURST_64              0x80
+#define WBURST_128             0xa0
+#define WBURST_256             0xc0
+#define WBURST_1024            0xe0
+#define MASK_MIN_DMA           0xFF00
+#define FIFO_RETRY_ENABLE      0x10000
+
+/*
+ * Event register
+ */
+
+#define DMA_WRITE_DONE         0x10000
+#define DMA_READ_DONE          0x20000
+#define DMA_WRITE_ERR          0x40000
+#define DMA_READ_ERR           0x80000
+
+/*
+ * Receive state
+ *
+ * RoadRunner HIPPI Receive State Register controls and monitors the
+ * HIPPI receive interface in the NIC. Look at err bits when a HIPPI
+ * receive Error Event occurs.
+ */
+
+#define ENABLE_NEW_CON         0x01
+#define RESET_RECV             0x02
+#define RECV_ALL               0x00
+#define RECV_1K                        0x20
+#define RECV_2K                        0x40
+#define RECV_4K                        0x60
+#define RECV_8K                        0x80
+#define RECV_16K               0xa0
+#define RECV_32K               0xc0
+#define RECV_64K               0xe0
+
+/*
+ * Transmit status.
+ */
+
+#define ENA_XMIT               0x01
+#define PERM_CON               0x02
+
+/*
+ * DMA write state
+ */
+
+#define RESET_DMA              0x01
+#define NO_SWAP_DMA            0x02
+#define DMA_ACTIVE             0x04
+#define THRESH_MASK            0x1F
+#define DMA_ERROR_MASK         0xff000000
+
+/*
+ * Gooddies stored in the ULA registers.
+ */
+
+#define TRACE_ON_WHAT_BIT      0x00020000    /* Traces on */
+#define ONEM_BUF_WHAT_BIT      0x00040000    /* 1Meg vs 256K */
+#define CHAR_API_WHAT_BIT      0x00080000    /* Char API vs network only */
+#define CMD_EVT_WHAT_BIT       0x00200000    /* Command event */
+#define LONG_TX_WHAT_BIT       0x00400000
+#define LONG_RX_WHAT_BIT       0x00800000
+#define WHAT_BIT_MASK          0xFFFD0000    /* Feature bit mask */
+
+/*
+ * Mode status
+ */
+
+#define EVENT_OVFL             0x80000000
+#define FATAL_ERR              0x40000000
+#define LOOP_BACK              0x01
+#define MODE_PH                        0x02
+#define MODE_FP                        0x00
+#define PTR64BIT               0x04
+#define PTR32BIT               0x00
+#define PTR_WD_SWAP            0x08
+#define PTR_WD_NOSWAP          0x00
+#define POST_WARN_EVENT                0x10
+#define ERR_TERM               0x20
+#define DIRECT_CONN            0x40
+#define NO_NIC_WATCHDOG                0x80
+#define SWAP_DATA              0x100
+#define SWAP_CONTROL           0x200
+#define NIC_HALT_ON_ERR                0x400
+#define NIC_NO_RESTART         0x800
+#define HALF_DUP_TX            0x1000
+#define HALF_DUP_RX            0x2000
+
+
+/*
+ * Error codes
+ */
+
+/* Host Error Codes - values of fail1 */
+#define ERR_UNKNOWN_MBOX       0x1001
+#define ERR_UNKNOWN_CMD                0x1002
+#define ERR_MAX_RING           0x1003
+#define ERR_RING_CLOSED                0x1004
+#define ERR_RING_OPEN          0x1005
+/* Firmware internal errors */
+#define ERR_EVENT_RING_FULL    0x01
+#define ERR_DW_PEND_CMND_FULL  0x02
+#define ERR_DR_PEND_CMND_FULL  0x03
+#define ERR_DW_PEND_DATA_FULL  0x04
+#define ERR_DR_PEND_DATA_FULL  0x05
+#define ERR_ILLEGAL_JUMP       0x06
+#define ERR_UNIMPLEMENTED      0x07
+#define ERR_TX_INFO_FULL       0x08
+#define ERR_RX_INFO_FULL       0x09
+#define ERR_ILLEGAL_MODE       0x0A
+#define ERR_MAIN_TIMEOUT       0x0B
+#define ERR_EVENT_BITS         0x0C
+#define ERR_UNPEND_FULL                0x0D
+#define ERR_TIMER_QUEUE_FULL   0x0E
+#define ERR_TIMER_QUEUE_EMPTY  0x0F
+#define ERR_TIMER_NO_FREE      0x10
+#define ERR_INTR_START         0x11
+#define ERR_BAD_STARTUP                0x12
+#define ERR_NO_PKT_END         0x13
+#define ERR_HALTED_ON_ERR      0x14
+/* Hardware NIC Errors */
+#define ERR_WRITE_DMA          0x0101
+#define ERR_READ_DMA           0x0102
+#define ERR_EXT_SERIAL         0x0103
+#define ERR_TX_INT_PARITY      0x0104
+
+
+/*
+ * Event definitions
+ */
+
+#define EVT_RING_ENTRIES       64
+#define EVT_RING_SIZE          (EVT_RING_ENTRIES * sizeof(struct event))
+
+struct event {
+#ifdef __LITTLE_ENDIAN
+       u16     index;
+       u8      ring;
+       u8      code;
+#else
+       u8      code;
+       u8      ring;
+       u16     index;
+#endif
+       u32     timestamp;
+};
+
+/*
+ * General Events
+ */
+
+#define E_NIC_UP       0x01
+#define E_WATCHDOG     0x02
+
+#define E_STAT_UPD     0x04
+#define E_INVAL_CMD    0x05
+#define E_SET_CMD_CONS 0x06
+#define E_LINK_ON      0x07
+#define E_LINK_OFF     0x08
+#define E_INTERN_ERR   0x09
+#define E_HOST_ERR     0x0A
+#define E_STATS_UPDATE 0x0B
+#define E_REJECTING    0x0C
+
+/*
+ * Send  Events
+ */
+#define E_CON_REJ      0x13
+#define E_CON_TMOUT    0x14
+#define E_CON_NC_TMOUT 0x15    /* I  , Connection No Campon Timeout */
+#define E_DISC_ERR     0x16
+#define E_INT_PRTY     0x17
+#define E_TX_IDLE      0x18
+#define E_TX_LINK_DROP 0x19
+#define E_TX_INV_RNG   0x1A
+#define E_TX_INV_BUF   0x1B
+#define E_TX_INV_DSC   0x1C
+
+/*
+ * Destination Events
+ */
+/*
+ * General Receive events
+ */
+#define E_VAL_RNG      0x20
+#define E_RX_RNG_ENER  0x21
+#define E_INV_RNG      0x22
+#define E_RX_RNG_SPC   0x23
+#define E_RX_RNG_OUT   0x24
+#define E_PKT_DISCARD  0x25
+#define E_INFO_EVT     0x27
+
+/*
+ * Data corrupted events
+ */
+#define E_RX_PAR_ERR   0x2B
+#define E_RX_LLRC_ERR  0x2C
+#define E_IP_CKSM_ERR  0x2D
+#define E_DTA_CKSM_ERR 0x2E
+#define E_SHT_BST      0x2F
+
+/*
+ * Data lost events
+ */
+#define E_LST_LNK_ERR  0x30
+#define E_FLG_SYN_ERR  0x31
+#define E_FRM_ERR      0x32
+#define E_RX_IDLE      0x33
+#define E_PKT_LN_ERR   0x34
+#define E_STATE_ERR    0x35
+#define E_UNEXP_DATA   0x3C
+
+/*
+ * Fatal events
+ */
+#define E_RX_INV_BUF   0x36
+#define E_RX_INV_DSC   0x37
+#define E_RNG_BLK      0x38
+
+/*
+ * Warning events
+ */
+#define E_RX_TO                0x39
+#define E_BFR_SPC      0x3A
+#define E_INV_ULP      0x3B
+
+#define E_NOT_IMPLEMENTED 0x40
+
+
+/*
+ * Commands
+ */
+
+#define CMD_RING_ENTRIES       16
+
+struct cmd {
+#ifdef __LITTLE_ENDIAN
+       u16     index;
+       u8      ring;
+       u8      code;
+#else
+       u8      code;
+       u8      ring;
+       u16     index;
+#endif
+};
+
+#define C_START_FW     0x01
+#define C_UPD_STAT     0x02
+#define C_WATCHDOG     0x05
+#define C_DEL_RNG      0x09
+#define C_NEW_RNG      0x0A
+#define C_CONN         0x0D
+
+
+/*
+ * Mode bits
+ */
+
+#define  PACKET_BAD            0x01 /* Packet had link-layer error */
+#define  INTERRUPT             0x02
+#define  TX_IP_CKSUM           0x04
+#define  PACKET_END            0x08
+#define  PACKET_START          0x10
+#define  SAME_IFIELD           0x80
+
+
+typedef struct {
+#if (BITS_PER_LONG == 64)
+       u64 addrlo;
+#else
+       u32 addrhi;
+       u32 addrlo;
+#endif
+} rraddr;
+
+
+static inline void set_rraddr(rraddr *ra, dma_addr_t addr)
+{
+       unsigned long baddr = addr;
+#if (BITS_PER_LONG == 64)
+       ra->addrlo = baddr;
+#else
+    /* Don't bother setting zero every time */
+       ra->addrlo = baddr;
+#endif
+       mb();
+}
+
+
+static inline void set_rxaddr(struct rr_regs __iomem *regs, volatile dma_addr_t addr)
+{
+       unsigned long baddr = addr;
+#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
+       writel(baddr & 0xffffffff, &regs->RxRingHi);
+       writel(baddr >> 32, &regs->RxRingLo);
+#elif (BITS_PER_LONG == 64)
+       writel(baddr >> 32, &regs->RxRingHi);
+       writel(baddr & 0xffffffff, &regs->RxRingLo);
+#else
+       writel(0, &regs->RxRingHi);
+       writel(baddr, &regs->RxRingLo);
+#endif
+       mb();
+}
+
+
+static inline void set_infoaddr(struct rr_regs __iomem *regs, volatile dma_addr_t addr)
+{
+       unsigned long baddr = addr;
+#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
+       writel(baddr & 0xffffffff, &regs->InfoPtrHi);
+       writel(baddr >> 32, &regs->InfoPtrLo);
+#elif (BITS_PER_LONG == 64)
+       writel(baddr >> 32, &regs->InfoPtrHi);
+       writel(baddr & 0xffffffff, &regs->InfoPtrLo);
+#else
+       writel(0, &regs->InfoPtrHi);
+       writel(baddr, &regs->InfoPtrLo);
+#endif
+       mb();
+}
+
+
+/*
+ * TX ring
+ */
+
+#ifdef CONFIG_ROADRUNNER_LARGE_RINGS
+#define TX_RING_ENTRIES        32
+#else
+#define TX_RING_ENTRIES        16
+#endif
+#define TX_TOTAL_SIZE  (TX_RING_ENTRIES * sizeof(struct tx_desc))
+
+struct tx_desc{
+       rraddr  addr;
+       u32     res;
+#ifdef __LITTLE_ENDIAN
+       u16     size;
+       u8      pad;
+       u8      mode;
+#else
+       u8      mode;
+       u8      pad;
+       u16     size;
+#endif
+};
+
+
+#ifdef CONFIG_ROADRUNNER_LARGE_RINGS
+#define RX_RING_ENTRIES        32
+#else
+#define RX_RING_ENTRIES 16
+#endif
+#define RX_TOTAL_SIZE  (RX_RING_ENTRIES * sizeof(struct rx_desc))
+
+struct rx_desc{
+       rraddr  addr;
+       u32     res;
+#ifdef __LITTLE_ENDIAN
+       u16     size;
+       u8      pad;
+       u8      mode;
+#else
+       u8      mode;
+       u8      pad;
+       u16     size;
+#endif
+};
+
+
+/*
+ * ioctl's
+ */
+
+#define SIOCRRPFW      SIOCDEVPRIVATE          /* put firmware */
+#define SIOCRRGFW      SIOCDEVPRIVATE+1        /* get firmware */
+#define SIOCRRID       SIOCDEVPRIVATE+2        /* identify */
+
+
+struct seg_hdr {
+       u32     seg_start;
+       u32     seg_len;
+       u32     seg_eestart;
+};
+
+
+#define EEPROM_BASE 0x80000000
+#define EEPROM_WORDS 8192
+#define EEPROM_BYTES (EEPROM_WORDS * sizeof(u32))
+
+struct eeprom_boot {
+       u32     key1;
+       u32     key2;
+       u32     sram_size;
+       struct  seg_hdr loader;
+       u32     init_chksum;
+       u32     reserved1;
+};
+
+struct eeprom_manf {
+       u32     HeaderFmt;
+       u32     Firmware;
+       u32     BoardRevision;
+       u32     RoadrunnerRev;
+       char    OpticsPart[8];
+       u32     OpticsRev;
+       u32     pad1;
+       char    SramPart[8];
+       u32     SramRev;
+       u32     pad2;
+       char    EepromPart[8];
+       u32     EepromRev;
+       u32     EepromSize;
+       char    PalPart[8];
+       u32     PalRev;
+       u32     pad3;
+       char    PalCodeFile[12];
+       u32     PalCodeRev;
+       char    BoardULA[8];
+       char    SerialNo[8];
+       char    MfgDate[8];
+       char    MfgTime[8];
+       char    ModifyDate[8];
+       u32     ModCount;
+       u32     pad4[13];
+};
+
+
+struct eeprom_phase_info {
+       char    phase1File[12];
+       u32     phase1Rev;
+       char    phase1Date[8];
+       char    phase2File[12];
+       u32     phase2Rev;
+       char    phase2Date[8];
+       u32     reserved7[4];
+};
+
+struct eeprom_rncd_info {
+       u32     FwStart;
+       u32     FwRev;
+       char    FwDate[8];
+       u32     AddrRunCodeSegs;
+       u32     FileNames;
+       char    File[13][8];
+};
+
+
+/* Phase 1 region (starts are word offset 0x80) */
+struct phase1_hdr{
+       u32     jump;
+       u32     noop;
+       struct seg_hdr phase2Seg;
+};
+
+struct eeprom {
+       struct eeprom_boot      boot;
+       u32                     pad1[8];
+       struct eeprom_manf      manf;
+       struct eeprom_phase_info phase_info;
+       struct eeprom_rncd_info rncd_info;
+       u32                     pad2[15];
+       u32                     hdr_checksum;
+       struct phase1_hdr       phase1;
+};
+
+
+struct rr_stats {
+       u32     NicTimeStamp;
+       u32     RngCreated;
+       u32     RngDeleted;
+       u32     IntrGen;
+       u32     NEvtOvfl;
+       u32     InvCmd;
+       u32     DmaReadErrs;
+       u32     DmaWriteErrs;
+       u32     StatUpdtT;
+       u32     StatUpdtC;
+       u32     WatchDog;
+       u32     Trace;
+
+       /* Serial HIPPI */
+       u32     LnkRdyEst;
+       u32     GLinkErr;
+       u32     AltFlgErr;
+       u32     OvhdBit8Sync;
+       u32     RmtSerPrtyErr;
+       u32     RmtParPrtyErr;
+       u32     RmtLoopBk;
+       u32     pad1;
+
+       /* HIPPI tx */
+       u32     ConEst;
+       u32     ConRejS;
+       u32     ConRetry;
+       u32     ConTmOut;
+       u32     SndConDiscon;
+       u32     SndParErr;
+       u32     PktSnt;
+       u32     pad2[2];
+       u32     ShFBstSnt;
+       u64     BytSent;
+       u32     TxTimeout;
+       u32     pad3[3];
+
+       /* HIPPI rx */
+       u32     ConAcc;
+       u32     ConRejdiPrty;
+       u32     ConRejd64b;
+       u32     ConRejdBuf;
+       u32     RxConDiscon;
+       u32     RxConNoData;
+       u32     PktRx;
+       u32     pad4[2];
+       u32     ShFBstRx;
+       u64     BytRx;
+       u32     RxParErr;
+       u32     RxLLRCerr;
+       u32     RxBstSZerr;
+       u32     RxStateErr;
+       u32     RxRdyErr;
+       u32     RxInvULP;
+       u32     RxSpcBuf;
+       u32     RxSpcDesc;
+       u32     RxRngSpc;
+       u32     RxRngFull;
+       u32     RxPktLenErr;
+       u32     RxCksmErr;
+       u32     RxPktDrp;
+       u32     RngLowSpc;
+       u32     RngDataClose;
+       u32     RxTimeout;
+       u32     RxIdle;
+};
+
+
+/*
+ * This struct is shared with the NIC firmware.
+ */
+struct ring_ctrl {
+       rraddr  rngptr;
+#ifdef __LITTLE_ENDIAN
+       u16     entries;
+       u8      pad;
+       u8      entry_size;
+       u16     pi;
+       u16     mode;
+#else
+       u8      entry_size;
+       u8      pad;
+       u16     entries;
+       u16     mode;
+       u16     pi;
+#endif
+};
+
+struct rr_info {
+       union {
+               struct rr_stats stats;
+               u32 stati[128];
+       } s;
+       struct ring_ctrl        evt_ctrl;
+       struct ring_ctrl        cmd_ctrl;
+       struct ring_ctrl        tx_ctrl;
+       u8                      pad[464];
+       u8                      trace[3072];
+};
+
+/*
+ * The linux structure for the RoadRunner.
+ *
+ * RX/TX descriptors are put first to make sure they are properly
+ * aligned and do not cross cache-line boundaries.
+ */
+
+struct rr_private
+{
+       struct rx_desc          *rx_ring;
+       struct tx_desc          *tx_ring;
+       struct event            *evt_ring;
+       dma_addr_t              tx_ring_dma;
+       dma_addr_t              rx_ring_dma;
+       dma_addr_t              evt_ring_dma;
+       /* Alignment ok ? */
+       struct sk_buff          *rx_skbuff[RX_RING_ENTRIES];
+       struct sk_buff          *tx_skbuff[TX_RING_ENTRIES];
+       struct rr_regs          __iomem *regs;          /* Register base */
+       struct ring_ctrl        *rx_ctrl;       /* Receive ring control */
+       struct rr_info          *info;          /* Shared info page */
+       dma_addr_t              rx_ctrl_dma;
+       dma_addr_t              info_dma;
+       spinlock_t              lock;
+       struct timer_list       timer;
+       u32                     cur_rx, cur_cmd, cur_evt;
+       u32                     dirty_rx, dirty_tx;
+       u32                     tx_full;
+       u32                     fw_rev;
+       volatile short          fw_running;
+       struct pci_dev          *pci_dev;
+};
+
+
+/*
+ * Prototypes
+ */
+static int rr_init(struct net_device *dev);
+static int rr_init1(struct net_device *dev);
+static irqreturn_t rr_interrupt(int irq, void *dev_id);
+
+static int rr_open(struct net_device *dev);
+static netdev_tx_t rr_start_xmit(struct sk_buff *skb,
+                                struct net_device *dev);
+static int rr_close(struct net_device *dev);
+static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static unsigned int rr_read_eeprom(struct rr_private *rrpriv,
+                                  unsigned long offset,
+                                  unsigned char *buf,
+                                  unsigned long length);
+static u32 rr_read_eeprom_word(struct rr_private *rrpriv, size_t offset);
+static int rr_load_firmware(struct net_device *dev);
+static inline void rr_raz_tx(struct rr_private *, struct net_device *);
+static inline void rr_raz_rx(struct rr_private *, struct net_device *);
+#endif /* _RRUNNER_H_ */
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
deleted file mode 100644 (file)
index 12e7ae4..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# PCMCIA Network device configuration
-#
-
-menuconfig NET_PCMCIA
-       bool "PCMCIA network device support"
-       depends on PCMCIA
-       ---help---
-         Say Y if you would like to include support for any PCMCIA or CardBus
-         network adapters, then say Y to the driver for your particular card
-         below.  PCMCIA- or PC-cards are credit-card size devices often used
-         with laptops computers; CardBus is the newer and faster version of
-         PCMCIA.
-
-         To use your PC-cards, you will need supporting software from David
-         Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
-         for location).  You also want to check out the PCMCIA-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         If unsure, say N.
-
-if NET_PCMCIA && PCMCIA
-
-config ARCNET_COM20020_CS
-       tristate "COM20020 ARCnet PCMCIA support"
-       depends on ARCNET_COM20020
-       help
-         Say Y here if you intend to attach this type of ARCnet PCMCIA card
-         to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called com20020_cs.  If unsure, say N.
-
-config PCMCIA_IBMTR
-       tristate "IBM PCMCIA tokenring adapter support"
-       depends on IBMTR!=y && TR
-       help
-         Say Y here if you intend to attach this type of Token Ring PCMCIA
-         card to your computer. You then also need to say Y to "Token Ring
-         driver support".
-
-         To compile this driver as a module, choose M here: the module will be
-         called ibmtr_cs.
-
-endif # NET_PCMCIA
diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile
deleted file mode 100644 (file)
index 618e816..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Linux PCMCIA network device drivers.
-#
-
-# 16-bit client drivers
-obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
-
-obj-$(CONFIG_PCMCIA_IBMTR)     += ibmtr_cs.o
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
deleted file mode 100644 (file)
index 980e65c..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Linux ARCnet driver - COM20020 PCMCIA support
- * 
- * Written 1994-1999 by Avery Pennarun,
- *    based on an ISA version by David Woodhouse.
- * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4)
- *    which was derived from pcnet_cs.c by David Hinds.
- * Some additional portions derived from skeleton.c by Donald Becker.
- *
- * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
- *  for sponsoring the further development of this driver.
- *
- * **********************
- *
- * The original copyright of skeleton.c was as follows:
- *
- * skeleton.c Written 1993 by Donald Becker.
- * Copyright 1993 United States Government as represented by the
- * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU General Public License as
- * modified by SRC, incorporated herein by reference.
- * 
- * **********************
- * Changes:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
- * - reorganize kmallocs in com20020_attach, checking all for failure
- *   and releasing the previous allocations if one fails
- * **********************
- * 
- * For more details, see drivers/net/arcnet.c
- *
- * **********************
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/arcdevice.h>
-#include <linux/com20020.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n"
-
-
-static void regdump(struct net_device *dev)
-{
-#ifdef DEBUG
-    int ioaddr = dev->base_addr;
-    int count;
-    
-    netdev_dbg(dev, "register dump:\n");
-    for (count = ioaddr; count < ioaddr + 16; count++)
-    {
-       if (!(count % 16))
-           pr_cont("%04X:", count);
-       pr_cont(" %02X", inb(count));
-    }
-    pr_cont("\n");
-    
-    netdev_dbg(dev, "buffer0 dump:\n");
-       /* set up the address register */
-        count = 0;
-       outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI);
-       outb(count & 0xff, _ADDR_LO);
-    
-    for (count = 0; count < 256+32; count++)
-    {
-       if (!(count % 16))
-           pr_cont("%04X:", count);
-       
-       /* copy the data */
-       pr_cont(" %02X", inb(_MEMDATA));
-    }
-    pr_cont("\n");
-#endif
-}
-
-
-
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-static int node;
-static int timeout = 3;
-static int backplane;
-static int clockp;
-static int clockm;
-
-module_param(node, int, 0);
-module_param(timeout, int, 0);
-module_param(backplane, int, 0);
-module_param(clockp, int, 0);
-module_param(clockm, int, 0);
-
-MODULE_LICENSE("GPL");
-
-/*====================================================================*/
-
-static int com20020_config(struct pcmcia_device *link);
-static void com20020_release(struct pcmcia_device *link);
-
-static void com20020_detach(struct pcmcia_device *p_dev);
-
-/*====================================================================*/
-
-typedef struct com20020_dev_t {
-    struct net_device       *dev;
-} com20020_dev_t;
-
-static int com20020_probe(struct pcmcia_device *p_dev)
-{
-    com20020_dev_t *info;
-    struct net_device *dev;
-    struct arcnet_local *lp;
-
-    dev_dbg(&p_dev->dev, "com20020_attach()\n");
-
-    /* Create new network device */
-    info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
-    if (!info)
-       goto fail_alloc_info;
-
-    dev = alloc_arcdev("");
-    if (!dev)
-       goto fail_alloc_dev;
-
-    lp = netdev_priv(dev);
-    lp->timeout = timeout;
-    lp->backplane = backplane;
-    lp->clockp = clockp;
-    lp->clockm = clockm & 3;
-    lp->hw.owner = THIS_MODULE;
-
-    /* fill in our module parameters as defaults */
-    dev->dev_addr[0] = node;
-
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    p_dev->resource[0]->end = 16;
-    p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-    info->dev = dev;
-    p_dev->priv = info;
-
-    return com20020_config(p_dev);
-
-fail_alloc_dev:
-    kfree(info);
-fail_alloc_info:
-    return -ENOMEM;
-} /* com20020_attach */
-
-static void com20020_detach(struct pcmcia_device *link)
-{
-    struct com20020_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
-
-    dev_dbg(&link->dev, "detach...\n");
-
-    dev_dbg(&link->dev, "com20020_detach\n");
-
-    dev_dbg(&link->dev, "unregister...\n");
-
-    unregister_netdev(dev);
-
-    /*
-     * this is necessary because we register our IRQ separately
-     * from card services.
-     */
-    if (dev->irq)
-           free_irq(dev->irq, dev);
-
-    com20020_release(link);
-
-    /* Unlink device structure, free bits */
-    dev_dbg(&link->dev, "unlinking...\n");
-    if (link->priv)
-    {
-       dev = info->dev;
-       if (dev)
-       {
-           dev_dbg(&link->dev, "kfree...\n");
-           free_netdev(dev);
-       }
-       dev_dbg(&link->dev, "kfree2...\n");
-       kfree(info);
-    }
-
-} /* com20020_detach */
-
-static int com20020_config(struct pcmcia_device *link)
-{
-    struct arcnet_local *lp;
-    com20020_dev_t *info;
-    struct net_device *dev;
-    int i, ret;
-    int ioaddr;
-
-    info = link->priv;
-    dev = info->dev;
-
-    dev_dbg(&link->dev, "config...\n");
-
-    dev_dbg(&link->dev, "com20020_config\n");
-
-    dev_dbg(&link->dev, "baseport1 is %Xh\n",
-           (unsigned int) link->resource[0]->start);
-
-    i = -ENODEV;
-    link->io_lines = 16;
-
-    if (!link->resource[0]->start)
-    {
-       for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
-       {
-           link->resource[0]->start = ioaddr;
-           i = pcmcia_request_io(link);
-           if (i == 0)
-               break;
-       }
-    }
-    else
-       i = pcmcia_request_io(link);
-    
-    if (i != 0)
-    {
-       dev_dbg(&link->dev, "requestIO failed totally!\n");
-       goto failed;
-    }
-       
-    ioaddr = dev->base_addr = link->resource[0]->start;
-    dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
-
-    dev_dbg(&link->dev, "request IRQ %d\n",
-           link->irq);
-    if (!link->irq)
-    {
-       dev_dbg(&link->dev, "requestIRQ failed totally!\n");
-       goto failed;
-    }
-
-    dev->irq = link->irq;
-
-    ret = pcmcia_enable_device(link);
-    if (ret)
-           goto failed;
-
-    if (com20020_check(dev))
-    {
-       regdump(dev);
-       goto failed;
-    }
-    
-    lp = netdev_priv(dev);
-    lp->card_name = "PCMCIA COM20020";
-    lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
-
-    SET_NETDEV_DEV(dev, &link->dev);
-
-    i = com20020_found(dev, 0);        /* calls register_netdev */
-    
-    if (i != 0) {
-       dev_notice(&link->dev,
-                  "com20020_found() failed\n");
-       goto failed;
-    }
-
-    netdev_dbg(dev, "port %#3lx, irq %d\n",
-              dev->base_addr, dev->irq);
-    return 0;
-
-failed:
-    dev_dbg(&link->dev, "com20020_config failed...\n");
-    com20020_release(link);
-    return -ENODEV;
-} /* com20020_config */
-
-static void com20020_release(struct pcmcia_device *link)
-{
-       dev_dbg(&link->dev, "com20020_release\n");
-       pcmcia_disable_device(link);
-}
-
-static int com20020_suspend(struct pcmcia_device *link)
-{
-       com20020_dev_t *info = link->priv;
-       struct net_device *dev = info->dev;
-
-       if (link->open)
-               netif_device_detach(dev);
-
-       return 0;
-}
-
-static int com20020_resume(struct pcmcia_device *link)
-{
-       com20020_dev_t *info = link->priv;
-       struct net_device *dev = info->dev;
-
-       if (link->open) {
-               int ioaddr = dev->base_addr;
-               struct arcnet_local *lp = netdev_priv(dev);
-               ARCRESET;
-       }
-
-       return 0;
-}
-
-static const struct pcmcia_device_id com20020_ids[] = {
-       PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
-                       "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
-       PCMCIA_DEVICE_PROD_ID12("SoHard AG",
-                       "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
-       PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
-
-static struct pcmcia_driver com20020_cs_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "com20020_cs",
-       .probe          = com20020_probe,
-       .remove         = com20020_detach,
-       .id_table       = com20020_ids,
-       .suspend        = com20020_suspend,
-       .resume         = com20020_resume,
-};
-
-static int __init init_com20020_cs(void)
-{
-       return pcmcia_register_driver(&com20020_cs_driver);
-}
-
-static void __exit exit_com20020_cs(void)
-{
-       pcmcia_unregister_driver(&com20020_cs_driver);
-}
-
-module_init(init_com20020_cs);
-module_exit(exit_com20020_cs);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
deleted file mode 100644 (file)
index 6006d54..0000000
+++ /dev/null
@@ -1,371 +0,0 @@
-/*======================================================================
-
-    A PCMCIA token-ring driver for IBM-based cards
-
-    This driver supports the IBM PCMCIA Token-Ring Card.
-    Written by Steve Kipisz, kipisz@vnet.ibm.com or
-                             bungy@ibm.net
-
-    Written 1995,1996.
-
-    This code is based on pcnet_cs.c from David Hinds.
-    
-    V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com
-
-    Linux V2.2.x presented significant changes to the underlying
-    ibmtr.c code.  Mainly the code became a lot more organized and
-    modular.
-
-    This caused the old PCMCIA Token Ring driver to give up and go 
-    home early. Instead of just patching the old code to make it 
-    work, the PCMCIA code has been streamlined, updated and possibly
-    improved.
-
-    This code now only contains code required for the Card Services.
-    All we do here is set the card up enough so that the real ibmtr.c
-    driver can find it and work with it properly.
-
-    i.e. We set up the io port, irq, mmio memory and shared ram
-    memory.  This enables ibmtr_probe in ibmtr.c to find the card and
-    configure it as though it was a normal ISA and/or PnP card.
-
-    CHANGES
-
-    v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com)
-    Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c
-    
-    v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com)
-    Updated to version 2.2.7 to match the first version of the kernel
-    that the modification to ibmtr.c were incorporated into.
-    
-    v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com)
-    Address translation feature of PCMCIA controller is usable so
-    memory windows can be placed in High memory (meaning above
-    0xFFFFF.)
-
-======================================================================*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/trdevice.h>
-#include <linux/ibmtr.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#define PCMCIA
-#include "../tokenring/ibmtr.c"
-
-
-/*====================================================================*/
-
-/* Parameters that can be set with 'insmod' */
-
-/* MMIO base address */
-static u_long mmiobase = 0xce000;
-
-/* SRAM base address */
-static u_long srambase = 0xd0000;
-
-/* SRAM size 8,16,32,64 */
-static u_long sramsize = 64;
-
-/* Ringspeed 4,16 */
-static int ringspeed = 16;
-
-module_param(mmiobase, ulong, 0);
-module_param(srambase, ulong, 0);
-module_param(sramsize, ulong, 0);
-module_param(ringspeed, int, 0);
-MODULE_LICENSE("GPL");
-
-/*====================================================================*/
-
-static int ibmtr_config(struct pcmcia_device *link);
-static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
-static void ibmtr_release(struct pcmcia_device *link);
-static void ibmtr_detach(struct pcmcia_device *p_dev);
-
-/*====================================================================*/
-
-typedef struct ibmtr_dev_t {
-       struct pcmcia_device    *p_dev;
-       struct net_device       *dev;
-       struct tok_info         *ti;
-} ibmtr_dev_t;
-
-static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) {
-       ibmtr_dev_t *info = dev_id;
-       struct net_device *dev = info->dev;
-       return tok_interrupt(irq, dev);
-};
-
-static int __devinit ibmtr_attach(struct pcmcia_device *link)
-{
-    ibmtr_dev_t *info;
-    struct net_device *dev;
-
-    dev_dbg(&link->dev, "ibmtr_attach()\n");
-
-    /* Create new token-ring device */
-    info = kzalloc(sizeof(*info), GFP_KERNEL);
-    if (!info) return -ENOMEM;
-    dev = alloc_trdev(sizeof(struct tok_info));
-    if (!dev) {
-       kfree(info);
-       return -ENOMEM;
-    }
-
-    info->p_dev = link;
-    link->priv = info;
-    info->ti = netdev_priv(dev);
-
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[0]->end = 4;
-    link->config_flags |= CONF_ENABLE_IRQ;
-    link->config_regs = PRESENT_OPTION;
-
-    info->dev = dev;
-
-    return ibmtr_config(link);
-} /* ibmtr_attach */
-
-static void ibmtr_detach(struct pcmcia_device *link)
-{
-    struct ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
-     struct tok_info *ti = netdev_priv(dev);
-
-    dev_dbg(&link->dev, "ibmtr_detach\n");
-    
-    /* 
-     * When the card removal interrupt hits tok_interrupt(), 
-     * bail out early, so we don't crash the machine 
-     */
-    ti->sram_phys |= 1;
-
-    unregister_netdev(dev);
-    
-    del_timer_sync(&(ti->tr_timer));
-
-    ibmtr_release(link);
-
-    free_netdev(dev);
-    kfree(info);
-} /* ibmtr_detach */
-
-static int __devinit ibmtr_config(struct pcmcia_device *link)
-{
-    ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
-    struct tok_info *ti = netdev_priv(dev);
-    int i, ret;
-
-    dev_dbg(&link->dev, "ibmtr_config\n");
-
-    link->io_lines = 16;
-    link->config_index = 0x61;
-
-    /* Determine if this is PRIMARY or ALTERNATE. */
-
-    /* Try PRIMARY card at 0xA20-0xA23 */
-    link->resource[0]->start = 0xA20;
-    i = pcmcia_request_io(link);
-    if (i != 0) {
-       /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
-       link->resource[0]->start = 0xA24;
-       ret = pcmcia_request_io(link);
-       if (ret)
-               goto failed;
-    }
-    dev->base_addr = link->resource[0]->start;
-
-    ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt);
-    if (ret)
-           goto failed;
-    dev->irq = link->irq;
-    ti->irq = link->irq;
-    ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
-
-    /* Allocate the MMIO memory window */
-    link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    link->resource[2]->flags |= WIN_USE_WAIT;
-    link->resource[2]->start = 0;
-    link->resource[2]->end = 0x2000;
-    ret = pcmcia_request_window(link, link->resource[2], 250);
-    if (ret)
-           goto failed;
-
-    ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
-    if (ret)
-           goto failed;
-    ti->mmio = ioremap(link->resource[2]->start,
-                   resource_size(link->resource[2]));
-
-    /* Allocate the SRAM memory window */
-    link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    link->resource[3]->flags |= WIN_USE_WAIT;
-    link->resource[3]->start = 0;
-    link->resource[3]->end = sramsize * 1024;
-    ret = pcmcia_request_window(link, link->resource[3], 250);
-    if (ret)
-           goto failed;
-
-    ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
-    if (ret)
-           goto failed;
-
-    ti->sram_base = srambase >> 12;
-    ti->sram_virt = ioremap(link->resource[3]->start,
-                   resource_size(link->resource[3]));
-    ti->sram_phys = link->resource[3]->start;
-
-    ret = pcmcia_enable_device(link);
-    if (ret)
-           goto failed;
-
-    /*  Set up the Token-Ring Controller Configuration Register and
-        turn on the card.  Check the "Local Area Network Credit Card
-        Adapters Technical Reference"  SC30-3585 for this info.  */
-    ibmtr_hw_setup(dev, mmiobase);
-
-    SET_NETDEV_DEV(dev, &link->dev);
-
-    i = ibmtr_probe_card(dev);
-    if (i != 0) {
-       pr_notice("register_netdev() failed\n");
-       goto failed;
-    }
-
-    netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
-               dev->base_addr, dev->irq,
-               (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
-               dev->dev_addr);
-    return 0;
-
-failed:
-    ibmtr_release(link);
-    return -ENODEV;
-} /* ibmtr_config */
-
-static void ibmtr_release(struct pcmcia_device *link)
-{
-       ibmtr_dev_t *info = link->priv;
-       struct net_device *dev = info->dev;
-
-       dev_dbg(&link->dev, "ibmtr_release\n");
-
-       if (link->resource[2]->end) {
-               struct tok_info *ti = netdev_priv(dev);
-               iounmap(ti->mmio);
-       }
-       pcmcia_disable_device(link);
-}
-
-static int ibmtr_suspend(struct pcmcia_device *link)
-{
-       ibmtr_dev_t *info = link->priv;
-       struct net_device *dev = info->dev;
-
-       if (link->open)
-               netif_device_detach(dev);
-
-       return 0;
-}
-
-static int __devinit ibmtr_resume(struct pcmcia_device *link)
-{
-       ibmtr_dev_t *info = link->priv;
-       struct net_device *dev = info->dev;
-
-       if (link->open) {
-               ibmtr_probe(dev);       /* really? */
-               netif_device_attach(dev);
-       }
-
-       return 0;
-}
-
-
-/*====================================================================*/
-
-static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
-{
-    int i;
-
-    /* Bizarre IBM behavior, there are 16 bits of information we
-       need to set, but the card only allows us to send 4 bits at a 
-       time.  For each byte sent to base_addr, bits 7-4 tell the
-       card which part of the 16 bits we are setting, bits 3-0 contain 
-       the actual information */
-
-    /* First nibble provides 4 bits of mmio */
-    i = (mmiobase >> 16) & 0x0F;
-    outb(i, dev->base_addr);
-
-    /* Second nibble provides 3 bits of mmio */
-    i = 0x10 | ((mmiobase >> 12) & 0x0E);
-    outb(i, dev->base_addr);
-
-    /* Third nibble, hard-coded values */
-    i = 0x26;
-    outb(i, dev->base_addr);
-
-    /* Fourth nibble sets shared ram page size */
-
-    /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */          
-    i = (sramsize >> 4) & 0x07;
-    i = ((i == 4) ? 3 : i) << 2;
-    i |= 0x30;
-
-    if (ringspeed == 16)
-       i |= 2;
-    if (dev->base_addr == 0xA24)
-       i |= 1;
-    outb(i, dev->base_addr);
-
-    /* 0x40 will release the card for use */
-    outb(0x40, dev->base_addr);
-}
-
-static const struct pcmcia_device_id ibmtr_ids[] = {
-       PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
-       PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
-       PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
-
-static struct pcmcia_driver ibmtr_cs_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "ibmtr_cs",
-       .probe          = ibmtr_attach,
-       .remove         = ibmtr_detach,
-       .id_table       = ibmtr_ids,
-       .suspend        = ibmtr_suspend,
-       .resume         = ibmtr_resume,
-};
-
-static int __init init_ibmtr_cs(void)
-{
-       return pcmcia_register_driver(&ibmtr_cs_driver);
-}
-
-static void __exit exit_ibmtr_cs(void)
-{
-       pcmcia_unregister_driver(&ibmtr_cs_driver);
-}
-
-module_init(init_ibmtr_cs);
-module_exit(exit_ibmtr_cs);
index a70244306c9462830c4ebde0b87334ef7667fa0e..bb88e12101c78b86b91def144677e4ecb10d8091 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menuconfig PHYLIB
-       tristate "PHY Device support and infrastructure"
+       bool "PHY Device support and infrastructure"
        depends on !S390
        depends on NETDEVICES
        help
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
deleted file mode 100644 (file)
index a9e9ca8..0000000
+++ /dev/null
@@ -1,1403 +0,0 @@
-/* $Id: plip.c,v 1.3.6.2 1997/04/16 15:07:56 phil Exp $ */
-/* PLIP: A parallel port "network" driver for Linux. */
-/* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
-/*
- * Authors:    Donald Becker <becker@scyld.com>
- *             Tommy Thorn <thorn@daimi.aau.dk>
- *             Tanabe Hiroyasu <hiro@sanpo.t.u-tokyo.ac.jp>
- *             Alan Cox <gw4pts@gw4pts.ampr.org>
- *             Peter Bauer <100136.3530@compuserve.com>
- *             Niibe Yutaka <gniibe@mri.co.jp>
- *             Nimrod Zimerman <zimerman@mailandnews.com>
- *
- * Enhancements:
- *             Modularization and ifreq/ifmap support by Alan Cox.
- *             Rewritten by Niibe Yutaka.
- *             parport-sharing awareness code by Philip Blundell.
- *             SMP locking by Niibe Yutaka.
- *             Support for parallel ports with no IRQ (poll mode),
- *             Modifications to use the parallel port API
- *             by Nimrod Zimerman.
- *
- * Fixes:
- *             Niibe Yutaka
- *               - Module initialization.
- *               - MTU fix.
- *               - Make sure other end is OK, before sending a packet.
- *               - Fix immediate timer problem.
- *
- *             Al Viro
- *               - Changed {enable,disable}_irq handling to make it work
- *                 with new ("stack") semantics.
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-
-/*
- * Original version and the name 'PLIP' from Donald Becker <becker@scyld.com>
- * inspired by Russ Nelson's parallel port packet driver.
- *
- * NOTE:
- *     Tanabe Hiroyasu had changed the protocol, and it was in Linux v1.0.
- *     Because of the necessity to communicate to DOS machines with the
- *     Crynwr packet driver, Peter Bauer changed the protocol again
- *     back to original protocol.
- *
- *     This version follows original PLIP protocol.
- *     So, this PLIP can't communicate the PLIP of Linux v1.0.
- */
-
-/*
- *     To use with DOS box, please do (Turn on ARP switch):
- *     # ifconfig plip[0-2] arp
- */
-static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n";
-
-/*
-  Sources:
-       Ideas and protocols came from Russ Nelson's <nelson@crynwr.com>
-       "parallel.asm" parallel port packet driver.
-
-  The "Crynwr" parallel port standard specifies the following protocol:
-    Trigger by sending nibble '0x8' (this causes interrupt on other end)
-    count-low octet
-    count-high octet
-    ... data octets
-    checksum octet
-  Each octet is sent as <wait for rx. '0x1?'> <send 0x10+(octet&0x0F)>
-                       <wait for rx. '0x0?'> <send 0x00+((octet>>4)&0x0F)>
-
-  The packet is encapsulated as if it were ethernet.
-
-  The cable used is a de facto standard parallel null cable -- sold as
-  a "LapLink" cable by various places.  You'll need a 12-conductor cable to
-  make one yourself.  The wiring is:
-    SLCTIN     17 - 17
-    GROUND     25 - 25
-    D0->ERROR  2 - 15          15 - 2
-    D1->SLCT   3 - 13          13 - 3
-    D2->PAPOUT 4 - 12          12 - 4
-    D3->ACK    5 - 10          10 - 5
-    D4->BUSY   6 - 11          11 - 6
-  Do not connect the other pins.  They are
-    D5,D6,D7 are 7,8,9
-    STROBE is 1, FEED is 14, INIT is 16
-    extra grounds are 18,19,20,21,22,23,24
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/if_ether.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/skbuff.h>
-#include <linux/if_plip.h>
-#include <linux/workqueue.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/parport.h>
-#include <linux/bitops.h>
-
-#include <net/neighbour.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-
-/* Maximum number of devices to support. */
-#define PLIP_MAX  8
-
-/* Use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 1
-#endif
-static const unsigned int net_debug = NET_DEBUG;
-
-#define ENABLE(irq)  if (irq != -1) enable_irq(irq)
-#define DISABLE(irq) if (irq != -1) disable_irq(irq)
-
-/* In micro second */
-#define PLIP_DELAY_UNIT                   1
-
-/* Connection time out = PLIP_TRIGGER_WAIT * PLIP_DELAY_UNIT usec */
-#define PLIP_TRIGGER_WAIT       500
-
-/* Nibble time out = PLIP_NIBBLE_WAIT * PLIP_DELAY_UNIT usec */
-#define PLIP_NIBBLE_WAIT        3000
-
-/* Bottom halves */
-static void plip_kick_bh(struct work_struct *work);
-static void plip_bh(struct work_struct *work);
-static void plip_timer_bh(struct work_struct *work);
-
-/* Interrupt handler */
-static void plip_interrupt(void *dev_id);
-
-/* Functions for DEV methods */
-static int plip_tx_packet(struct sk_buff *skb, struct net_device *dev);
-static int plip_hard_header(struct sk_buff *skb, struct net_device *dev,
-                            unsigned short type, const void *daddr,
-                           const void *saddr, unsigned len);
-static int plip_hard_header_cache(const struct neighbour *neigh,
-                                  struct hh_cache *hh, __be16 type);
-static int plip_open(struct net_device *dev);
-static int plip_close(struct net_device *dev);
-static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int plip_preempt(void *handle);
-static void plip_wakeup(void *handle);
-
-enum plip_connection_state {
-       PLIP_CN_NONE=0,
-       PLIP_CN_RECEIVE,
-       PLIP_CN_SEND,
-       PLIP_CN_CLOSING,
-       PLIP_CN_ERROR
-};
-
-enum plip_packet_state {
-       PLIP_PK_DONE=0,
-       PLIP_PK_TRIGGER,
-       PLIP_PK_LENGTH_LSB,
-       PLIP_PK_LENGTH_MSB,
-       PLIP_PK_DATA,
-       PLIP_PK_CHECKSUM
-};
-
-enum plip_nibble_state {
-       PLIP_NB_BEGIN,
-       PLIP_NB_1,
-       PLIP_NB_2,
-};
-
-struct plip_local {
-       enum plip_packet_state state;
-       enum plip_nibble_state nibble;
-       union {
-               struct {
-#if defined(__LITTLE_ENDIAN)
-                       unsigned char lsb;
-                       unsigned char msb;
-#elif defined(__BIG_ENDIAN)
-                       unsigned char msb;
-                       unsigned char lsb;
-#else
-#error "Please fix the endianness defines in <asm/byteorder.h>"
-#endif
-               } b;
-               unsigned short h;
-       } length;
-       unsigned short byte;
-       unsigned char  checksum;
-       unsigned char  data;
-       struct sk_buff *skb;
-};
-
-struct net_local {
-       struct net_device *dev;
-       struct work_struct immediate;
-       struct delayed_work deferred;
-       struct delayed_work timer;
-       struct plip_local snd_data;
-       struct plip_local rcv_data;
-       struct pardevice *pardev;
-       unsigned long  trigger;
-       unsigned long  nibble;
-       enum plip_connection_state connection;
-       unsigned short timeout_count;
-       int is_deferred;
-       int port_owner;
-       int should_relinquish;
-       spinlock_t lock;
-       atomic_t kill_timer;
-       struct completion killed_timer_cmp;
-};
-
-static inline void enable_parport_interrupts (struct net_device *dev)
-{
-       if (dev->irq != -1)
-       {
-               struct parport *port =
-                  ((struct net_local *)netdev_priv(dev))->pardev->port;
-               port->ops->enable_irq (port);
-       }
-}
-
-static inline void disable_parport_interrupts (struct net_device *dev)
-{
-       if (dev->irq != -1)
-       {
-               struct parport *port =
-                  ((struct net_local *)netdev_priv(dev))->pardev->port;
-               port->ops->disable_irq (port);
-       }
-}
-
-static inline void write_data (struct net_device *dev, unsigned char data)
-{
-       struct parport *port =
-          ((struct net_local *)netdev_priv(dev))->pardev->port;
-
-       port->ops->write_data (port, data);
-}
-
-static inline unsigned char read_status (struct net_device *dev)
-{
-       struct parport *port =
-          ((struct net_local *)netdev_priv(dev))->pardev->port;
-
-       return port->ops->read_status (port);
-}
-
-static const struct header_ops plip_header_ops = {
-       .create = plip_hard_header,
-       .cache  = plip_hard_header_cache,
-};
-
-static const struct net_device_ops plip_netdev_ops = {
-       .ndo_open                = plip_open,
-       .ndo_stop                = plip_close,
-       .ndo_start_xmit          = plip_tx_packet,
-       .ndo_do_ioctl            = plip_ioctl,
-       .ndo_change_mtu          = eth_change_mtu,
-       .ndo_set_mac_address     = eth_mac_addr,
-       .ndo_validate_addr       = eth_validate_addr,
-};
-
-/* Entry point of PLIP driver.
-   Probe the hardware, and register/initialize the driver.
-
-   PLIP is rather weird, because of the way it interacts with the parport
-   system.  It is _not_ initialised from Space.c.  Instead, plip_init()
-   is called, and that function makes up a "struct net_device" for each port, and
-   then calls us here.
-
-   */
-static void
-plip_init_netdev(struct net_device *dev)
-{
-       struct net_local *nl = netdev_priv(dev);
-
-       /* Then, override parts of it */
-       dev->tx_queue_len        = 10;
-       dev->flags               = IFF_POINTOPOINT|IFF_NOARP;
-       memset(dev->dev_addr, 0xfc, ETH_ALEN);
-
-       dev->netdev_ops          = &plip_netdev_ops;
-       dev->header_ops          = &plip_header_ops;
-
-
-       nl->port_owner = 0;
-
-       /* Initialize constants */
-       nl->trigger     = PLIP_TRIGGER_WAIT;
-       nl->nibble      = PLIP_NIBBLE_WAIT;
-
-       /* Initialize task queue structures */
-       INIT_WORK(&nl->immediate, plip_bh);
-       INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh);
-
-       if (dev->irq == -1)
-               INIT_DELAYED_WORK(&nl->timer, plip_timer_bh);
-
-       spin_lock_init(&nl->lock);
-}
-
-/* Bottom half handler for the delayed request.
-   This routine is kicked by do_timer().
-   Request `plip_bh' to be invoked. */
-static void
-plip_kick_bh(struct work_struct *work)
-{
-       struct net_local *nl =
-               container_of(work, struct net_local, deferred.work);
-
-       if (nl->is_deferred)
-               schedule_work(&nl->immediate);
-}
-
-/* Forward declarations of internal routines */
-static int plip_none(struct net_device *, struct net_local *,
-                    struct plip_local *, struct plip_local *);
-static int plip_receive_packet(struct net_device *, struct net_local *,
-                              struct plip_local *, struct plip_local *);
-static int plip_send_packet(struct net_device *, struct net_local *,
-                           struct plip_local *, struct plip_local *);
-static int plip_connection_close(struct net_device *, struct net_local *,
-                                struct plip_local *, struct plip_local *);
-static int plip_error(struct net_device *, struct net_local *,
-                     struct plip_local *, struct plip_local *);
-static int plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
-                                struct plip_local *snd,
-                                struct plip_local *rcv,
-                                int error);
-
-#define OK        0
-#define TIMEOUT   1
-#define ERROR     2
-#define HS_TIMEOUT     3
-
-typedef int (*plip_func)(struct net_device *dev, struct net_local *nl,
-                        struct plip_local *snd, struct plip_local *rcv);
-
-static const plip_func connection_state_table[] =
-{
-       plip_none,
-       plip_receive_packet,
-       plip_send_packet,
-       plip_connection_close,
-       plip_error
-};
-
-/* Bottom half handler of PLIP. */
-static void
-plip_bh(struct work_struct *work)
-{
-       struct net_local *nl = container_of(work, struct net_local, immediate);
-       struct plip_local *snd = &nl->snd_data;
-       struct plip_local *rcv = &nl->rcv_data;
-       plip_func f;
-       int r;
-
-       nl->is_deferred = 0;
-       f = connection_state_table[nl->connection];
-       if ((r = (*f)(nl->dev, nl, snd, rcv)) != OK &&
-           (r = plip_bh_timeout_error(nl->dev, nl, snd, rcv, r)) != OK) {
-               nl->is_deferred = 1;
-               schedule_delayed_work(&nl->deferred, 1);
-       }
-}
-
-static void
-plip_timer_bh(struct work_struct *work)
-{
-       struct net_local *nl =
-               container_of(work, struct net_local, timer.work);
-
-       if (!(atomic_read (&nl->kill_timer))) {
-               plip_interrupt (nl->dev);
-
-               schedule_delayed_work(&nl->timer, 1);
-       }
-       else {
-               complete(&nl->killed_timer_cmp);
-       }
-}
-
-static int
-plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
-                     struct plip_local *snd, struct plip_local *rcv,
-                     int error)
-{
-       unsigned char c0;
-       /*
-        * This is tricky. If we got here from the beginning of send (either
-        * with ERROR or HS_TIMEOUT) we have IRQ enabled. Otherwise it's
-        * already disabled. With the old variant of {enable,disable}_irq()
-        * extra disable_irq() was a no-op. Now it became mortal - it's
-        * unbalanced and thus we'll never re-enable IRQ (until rmmod plip,
-        * that is). So we have to treat HS_TIMEOUT and ERROR from send
-        * in a special way.
-        */
-
-       spin_lock_irq(&nl->lock);
-       if (nl->connection == PLIP_CN_SEND) {
-
-               if (error != ERROR) { /* Timeout */
-                       nl->timeout_count++;
-                       if ((error == HS_TIMEOUT && nl->timeout_count <= 10) ||
-                           nl->timeout_count <= 3) {
-                               spin_unlock_irq(&nl->lock);
-                               /* Try again later */
-                               return TIMEOUT;
-                       }
-                       c0 = read_status(dev);
-                       printk(KERN_WARNING "%s: transmit timeout(%d,%02x)\n",
-                              dev->name, snd->state, c0);
-               } else
-                       error = HS_TIMEOUT;
-               dev->stats.tx_errors++;
-               dev->stats.tx_aborted_errors++;
-       } else if (nl->connection == PLIP_CN_RECEIVE) {
-               if (rcv->state == PLIP_PK_TRIGGER) {
-                       /* Transmission was interrupted. */
-                       spin_unlock_irq(&nl->lock);
-                       return OK;
-               }
-               if (error != ERROR) { /* Timeout */
-                       if (++nl->timeout_count <= 3) {
-                               spin_unlock_irq(&nl->lock);
-                               /* Try again later */
-                               return TIMEOUT;
-                       }
-                       c0 = read_status(dev);
-                       printk(KERN_WARNING "%s: receive timeout(%d,%02x)\n",
-                              dev->name, rcv->state, c0);
-               }
-               dev->stats.rx_dropped++;
-       }
-       rcv->state = PLIP_PK_DONE;
-       if (rcv->skb) {
-               kfree_skb(rcv->skb);
-               rcv->skb = NULL;
-       }
-       snd->state = PLIP_PK_DONE;
-       if (snd->skb) {
-               dev_kfree_skb(snd->skb);
-               snd->skb = NULL;
-       }
-       spin_unlock_irq(&nl->lock);
-       if (error == HS_TIMEOUT) {
-               DISABLE(dev->irq);
-               synchronize_irq(dev->irq);
-       }
-       disable_parport_interrupts (dev);
-       netif_stop_queue (dev);
-       nl->connection = PLIP_CN_ERROR;
-       write_data (dev, 0x00);
-
-       return TIMEOUT;
-}
-
-static int
-plip_none(struct net_device *dev, struct net_local *nl,
-         struct plip_local *snd, struct plip_local *rcv)
-{
-       return OK;
-}
-
-/* PLIP_RECEIVE --- receive a byte(two nibbles)
-   Returns OK on success, TIMEOUT on timeout */
-static inline int
-plip_receive(unsigned short nibble_timeout, struct net_device *dev,
-            enum plip_nibble_state *ns_p, unsigned char *data_p)
-{
-       unsigned char c0, c1;
-       unsigned int cx;
-
-       switch (*ns_p) {
-       case PLIP_NB_BEGIN:
-               cx = nibble_timeout;
-               while (1) {
-                       c0 = read_status(dev);
-                       udelay(PLIP_DELAY_UNIT);
-                       if ((c0 & 0x80) == 0) {
-                               c1 = read_status(dev);
-                               if (c0 == c1)
-                                       break;
-                       }
-                       if (--cx == 0)
-                               return TIMEOUT;
-               }
-               *data_p = (c0 >> 3) & 0x0f;
-               write_data (dev, 0x10); /* send ACK */
-               *ns_p = PLIP_NB_1;
-
-       case PLIP_NB_1:
-               cx = nibble_timeout;
-               while (1) {
-                       c0 = read_status(dev);
-                       udelay(PLIP_DELAY_UNIT);
-                       if (c0 & 0x80) {
-                               c1 = read_status(dev);
-                               if (c0 == c1)
-                                       break;
-                       }
-                       if (--cx == 0)
-                               return TIMEOUT;
-               }
-               *data_p |= (c0 << 1) & 0xf0;
-               write_data (dev, 0x00); /* send ACK */
-               *ns_p = PLIP_NB_BEGIN;
-       case PLIP_NB_2:
-               break;
-       }
-       return OK;
-}
-
-/*
- *     Determine the packet's protocol ID. The rule here is that we
- *     assume 802.3 if the type field is short enough to be a length.
- *     This is normal practice and works for any 'now in use' protocol.
- *
- *     PLIP is ethernet ish but the daddr might not be valid if unicast.
- *     PLIP fortunately has no bus architecture (its Point-to-point).
- *
- *     We can't fix the daddr thing as that quirk (more bug) is embedded
- *     in far too many old systems not all even running Linux.
- */
-
-static __be16 plip_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-       struct ethhdr *eth;
-       unsigned char *rawp;
-
-       skb_reset_mac_header(skb);
-       skb_pull(skb,dev->hard_header_len);
-       eth = eth_hdr(skb);
-
-       if(*eth->h_dest&1)
-       {
-               if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
-                       skb->pkt_type=PACKET_BROADCAST;
-               else
-                       skb->pkt_type=PACKET_MULTICAST;
-       }
-
-       /*
-        *      This ALLMULTI check should be redundant by 1.4
-        *      so don't forget to remove it.
-        */
-
-       if (ntohs(eth->h_proto) >= 1536)
-               return eth->h_proto;
-
-       rawp = skb->data;
-
-       /*
-        *      This is a magic hack to spot IPX packets. Older Novell breaks
-        *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
-        *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-        *      won't work for fault tolerant netware but does for the rest.
-        */
-       if (*(unsigned short *)rawp == 0xFFFF)
-               return htons(ETH_P_802_3);
-
-       /*
-        *      Real 802.2 LLC
-        */
-       return htons(ETH_P_802_2);
-}
-
-/* PLIP_RECEIVE_PACKET --- receive a packet */
-static int
-plip_receive_packet(struct net_device *dev, struct net_local *nl,
-                   struct plip_local *snd, struct plip_local *rcv)
-{
-       unsigned short nibble_timeout = nl->nibble;
-       unsigned char *lbuf;
-
-       switch (rcv->state) {
-       case PLIP_PK_TRIGGER:
-               DISABLE(dev->irq);
-               /* Don't need to synchronize irq, as we can safely ignore it */
-               disable_parport_interrupts (dev);
-               write_data (dev, 0x01); /* send ACK */
-               if (net_debug > 2)
-                       printk(KERN_DEBUG "%s: receive start\n", dev->name);
-               rcv->state = PLIP_PK_LENGTH_LSB;
-               rcv->nibble = PLIP_NB_BEGIN;
-
-       case PLIP_PK_LENGTH_LSB:
-               if (snd->state != PLIP_PK_DONE) {
-                       if (plip_receive(nl->trigger, dev,
-                                        &rcv->nibble, &rcv->length.b.lsb)) {
-                               /* collision, here dev->tbusy == 1 */
-                               rcv->state = PLIP_PK_DONE;
-                               nl->is_deferred = 1;
-                               nl->connection = PLIP_CN_SEND;
-                               schedule_delayed_work(&nl->deferred, 1);
-                               enable_parport_interrupts (dev);
-                               ENABLE(dev->irq);
-                               return OK;
-                       }
-               } else {
-                       if (plip_receive(nibble_timeout, dev,
-                                        &rcv->nibble, &rcv->length.b.lsb))
-                               return TIMEOUT;
-               }
-               rcv->state = PLIP_PK_LENGTH_MSB;
-
-       case PLIP_PK_LENGTH_MSB:
-               if (plip_receive(nibble_timeout, dev,
-                                &rcv->nibble, &rcv->length.b.msb))
-                       return TIMEOUT;
-               if (rcv->length.h > dev->mtu + dev->hard_header_len ||
-                   rcv->length.h < 8) {
-                       printk(KERN_WARNING "%s: bogus packet size %d.\n", dev->name, rcv->length.h);
-                       return ERROR;
-               }
-               /* Malloc up new buffer. */
-               rcv->skb = dev_alloc_skb(rcv->length.h + 2);
-               if (rcv->skb == NULL) {
-                       printk(KERN_ERR "%s: Memory squeeze.\n", dev->name);
-                       return ERROR;
-               }
-               skb_reserve(rcv->skb, 2);       /* Align IP on 16 byte boundaries */
-               skb_put(rcv->skb,rcv->length.h);
-               rcv->skb->dev = dev;
-               rcv->state = PLIP_PK_DATA;
-               rcv->byte = 0;
-               rcv->checksum = 0;
-
-       case PLIP_PK_DATA:
-               lbuf = rcv->skb->data;
-               do {
-                       if (plip_receive(nibble_timeout, dev,
-                                        &rcv->nibble, &lbuf[rcv->byte]))
-                               return TIMEOUT;
-               } while (++rcv->byte < rcv->length.h);
-               do {
-                       rcv->checksum += lbuf[--rcv->byte];
-               } while (rcv->byte);
-               rcv->state = PLIP_PK_CHECKSUM;
-
-       case PLIP_PK_CHECKSUM:
-               if (plip_receive(nibble_timeout, dev,
-                                &rcv->nibble, &rcv->data))
-                       return TIMEOUT;
-               if (rcv->data != rcv->checksum) {
-                       dev->stats.rx_crc_errors++;
-                       if (net_debug)
-                               printk(KERN_DEBUG "%s: checksum error\n", dev->name);
-                       return ERROR;
-               }
-               rcv->state = PLIP_PK_DONE;
-
-       case PLIP_PK_DONE:
-               /* Inform the upper layer for the arrival of a packet. */
-               rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
-               netif_rx_ni(rcv->skb);
-               dev->stats.rx_bytes += rcv->length.h;
-               dev->stats.rx_packets++;
-               rcv->skb = NULL;
-               if (net_debug > 2)
-                       printk(KERN_DEBUG "%s: receive end\n", dev->name);
-
-               /* Close the connection. */
-               write_data (dev, 0x00);
-               spin_lock_irq(&nl->lock);
-               if (snd->state != PLIP_PK_DONE) {
-                       nl->connection = PLIP_CN_SEND;
-                       spin_unlock_irq(&nl->lock);
-                       schedule_work(&nl->immediate);
-                       enable_parport_interrupts (dev);
-                       ENABLE(dev->irq);
-                       return OK;
-               } else {
-                       nl->connection = PLIP_CN_NONE;
-                       spin_unlock_irq(&nl->lock);
-                       enable_parport_interrupts (dev);
-                       ENABLE(dev->irq);
-                       return OK;
-               }
-       }
-       return OK;
-}
-
-/* PLIP_SEND --- send a byte (two nibbles)
-   Returns OK on success, TIMEOUT when timeout    */
-static inline int
-plip_send(unsigned short nibble_timeout, struct net_device *dev,
-         enum plip_nibble_state *ns_p, unsigned char data)
-{
-       unsigned char c0;
-       unsigned int cx;
-
-       switch (*ns_p) {
-       case PLIP_NB_BEGIN:
-               write_data (dev, data & 0x0f);
-               *ns_p = PLIP_NB_1;
-
-       case PLIP_NB_1:
-               write_data (dev, 0x10 | (data & 0x0f));
-               cx = nibble_timeout;
-               while (1) {
-                       c0 = read_status(dev);
-                       if ((c0 & 0x80) == 0)
-                               break;
-                       if (--cx == 0)
-                               return TIMEOUT;
-                       udelay(PLIP_DELAY_UNIT);
-               }
-               write_data (dev, 0x10 | (data >> 4));
-               *ns_p = PLIP_NB_2;
-
-       case PLIP_NB_2:
-               write_data (dev, (data >> 4));
-               cx = nibble_timeout;
-               while (1) {
-                       c0 = read_status(dev);
-                       if (c0 & 0x80)
-                               break;
-                       if (--cx == 0)
-                               return TIMEOUT;
-                       udelay(PLIP_DELAY_UNIT);
-               }
-               *ns_p = PLIP_NB_BEGIN;
-               return OK;
-       }
-       return OK;
-}
-
-/* PLIP_SEND_PACKET --- send a packet */
-static int
-plip_send_packet(struct net_device *dev, struct net_local *nl,
-                struct plip_local *snd, struct plip_local *rcv)
-{
-       unsigned short nibble_timeout = nl->nibble;
-       unsigned char *lbuf;
-       unsigned char c0;
-       unsigned int cx;
-
-       if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) {
-               printk(KERN_DEBUG "%s: send skb lost\n", dev->name);
-               snd->state = PLIP_PK_DONE;
-               snd->skb = NULL;
-               return ERROR;
-       }
-
-       switch (snd->state) {
-       case PLIP_PK_TRIGGER:
-               if ((read_status(dev) & 0xf8) != 0x80)
-                       return HS_TIMEOUT;
-
-               /* Trigger remote rx interrupt. */
-               write_data (dev, 0x08);
-               cx = nl->trigger;
-               while (1) {
-                       udelay(PLIP_DELAY_UNIT);
-                       spin_lock_irq(&nl->lock);
-                       if (nl->connection == PLIP_CN_RECEIVE) {
-                               spin_unlock_irq(&nl->lock);
-                               /* Interrupted. */
-                               dev->stats.collisions++;
-                               return OK;
-                       }
-                       c0 = read_status(dev);
-                       if (c0 & 0x08) {
-                               spin_unlock_irq(&nl->lock);
-                               DISABLE(dev->irq);
-                               synchronize_irq(dev->irq);
-                               if (nl->connection == PLIP_CN_RECEIVE) {
-                                       /* Interrupted.
-                                          We don't need to enable irq,
-                                          as it is soon disabled.    */
-                                       /* Yes, we do. New variant of
-                                          {enable,disable}_irq *counts*
-                                          them.  -- AV  */
-                                       ENABLE(dev->irq);
-                                       dev->stats.collisions++;
-                                       return OK;
-                               }
-                               disable_parport_interrupts (dev);
-                               if (net_debug > 2)
-                                       printk(KERN_DEBUG "%s: send start\n", dev->name);
-                               snd->state = PLIP_PK_LENGTH_LSB;
-                               snd->nibble = PLIP_NB_BEGIN;
-                               nl->timeout_count = 0;
-                               break;
-                       }
-                       spin_unlock_irq(&nl->lock);
-                       if (--cx == 0) {
-                               write_data (dev, 0x00);
-                               return HS_TIMEOUT;
-                       }
-               }
-
-       case PLIP_PK_LENGTH_LSB:
-               if (plip_send(nibble_timeout, dev,
-                             &snd->nibble, snd->length.b.lsb))
-                       return TIMEOUT;
-               snd->state = PLIP_PK_LENGTH_MSB;
-
-       case PLIP_PK_LENGTH_MSB:
-               if (plip_send(nibble_timeout, dev,
-                             &snd->nibble, snd->length.b.msb))
-                       return TIMEOUT;
-               snd->state = PLIP_PK_DATA;
-               snd->byte = 0;
-               snd->checksum = 0;
-
-       case PLIP_PK_DATA:
-               do {
-                       if (plip_send(nibble_timeout, dev,
-                                     &snd->nibble, lbuf[snd->byte]))
-                               return TIMEOUT;
-               } while (++snd->byte < snd->length.h);
-               do {
-                       snd->checksum += lbuf[--snd->byte];
-               } while (snd->byte);
-               snd->state = PLIP_PK_CHECKSUM;
-
-       case PLIP_PK_CHECKSUM:
-               if (plip_send(nibble_timeout, dev,
-                             &snd->nibble, snd->checksum))
-                       return TIMEOUT;
-
-               dev->stats.tx_bytes += snd->skb->len;
-               dev_kfree_skb(snd->skb);
-               dev->stats.tx_packets++;
-               snd->state = PLIP_PK_DONE;
-
-       case PLIP_PK_DONE:
-               /* Close the connection */
-               write_data (dev, 0x00);
-               snd->skb = NULL;
-               if (net_debug > 2)
-                       printk(KERN_DEBUG "%s: send end\n", dev->name);
-               nl->connection = PLIP_CN_CLOSING;
-               nl->is_deferred = 1;
-               schedule_delayed_work(&nl->deferred, 1);
-               enable_parport_interrupts (dev);
-               ENABLE(dev->irq);
-               return OK;
-       }
-       return OK;
-}
-
-static int
-plip_connection_close(struct net_device *dev, struct net_local *nl,
-                     struct plip_local *snd, struct plip_local *rcv)
-{
-       spin_lock_irq(&nl->lock);
-       if (nl->connection == PLIP_CN_CLOSING) {
-               nl->connection = PLIP_CN_NONE;
-               netif_wake_queue (dev);
-       }
-       spin_unlock_irq(&nl->lock);
-       if (nl->should_relinquish) {
-               nl->should_relinquish = nl->port_owner = 0;
-               parport_release(nl->pardev);
-       }
-       return OK;
-}
-
-/* PLIP_ERROR --- wait till other end settled */
-static int
-plip_error(struct net_device *dev, struct net_local *nl,
-          struct plip_local *snd, struct plip_local *rcv)
-{
-       unsigned char status;
-
-       status = read_status(dev);
-       if ((status & 0xf8) == 0x80) {
-               if (net_debug > 2)
-                       printk(KERN_DEBUG "%s: reset interface.\n", dev->name);
-               nl->connection = PLIP_CN_NONE;
-               nl->should_relinquish = 0;
-               netif_start_queue (dev);
-               enable_parport_interrupts (dev);
-               ENABLE(dev->irq);
-               netif_wake_queue (dev);
-       } else {
-               nl->is_deferred = 1;
-               schedule_delayed_work(&nl->deferred, 1);
-       }
-
-       return OK;
-}
-
-/* Handle the parallel port interrupts. */
-static void
-plip_interrupt(void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       struct net_local *nl;
-       struct plip_local *rcv;
-       unsigned char c0;
-       unsigned long flags;
-
-       nl = netdev_priv(dev);
-       rcv = &nl->rcv_data;
-
-       spin_lock_irqsave (&nl->lock, flags);
-
-       c0 = read_status(dev);
-       if ((c0 & 0xf8) != 0xc0) {
-               if ((dev->irq != -1) && (net_debug > 1))
-                       printk(KERN_DEBUG "%s: spurious interrupt\n", dev->name);
-               spin_unlock_irqrestore (&nl->lock, flags);
-               return;
-       }
-
-       if (net_debug > 3)
-               printk(KERN_DEBUG "%s: interrupt.\n", dev->name);
-
-       switch (nl->connection) {
-       case PLIP_CN_CLOSING:
-               netif_wake_queue (dev);
-       case PLIP_CN_NONE:
-       case PLIP_CN_SEND:
-               rcv->state = PLIP_PK_TRIGGER;
-               nl->connection = PLIP_CN_RECEIVE;
-               nl->timeout_count = 0;
-               schedule_work(&nl->immediate);
-               break;
-
-       case PLIP_CN_RECEIVE:
-               /* May occur because there is race condition
-                  around test and set of dev->interrupt.
-                  Ignore this interrupt. */
-               break;
-
-       case PLIP_CN_ERROR:
-               printk(KERN_ERR "%s: receive interrupt in error state\n", dev->name);
-               break;
-       }
-
-       spin_unlock_irqrestore(&nl->lock, flags);
-}
-
-static int
-plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
-{
-       struct net_local *nl = netdev_priv(dev);
-       struct plip_local *snd = &nl->snd_data;
-
-       if (netif_queue_stopped(dev))
-               return NETDEV_TX_BUSY;
-
-       /* We may need to grab the bus */
-       if (!nl->port_owner) {
-               if (parport_claim(nl->pardev))
-                       return NETDEV_TX_BUSY;
-               nl->port_owner = 1;
-       }
-
-       netif_stop_queue (dev);
-
-       if (skb->len > dev->mtu + dev->hard_header_len) {
-               printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len);
-               netif_start_queue (dev);
-               return NETDEV_TX_BUSY;
-       }
-
-       if (net_debug > 2)
-               printk(KERN_DEBUG "%s: send request\n", dev->name);
-
-       spin_lock_irq(&nl->lock);
-       snd->skb = skb;
-       snd->length.h = skb->len;
-       snd->state = PLIP_PK_TRIGGER;
-       if (nl->connection == PLIP_CN_NONE) {
-               nl->connection = PLIP_CN_SEND;
-               nl->timeout_count = 0;
-       }
-       schedule_work(&nl->immediate);
-       spin_unlock_irq(&nl->lock);
-
-       return NETDEV_TX_OK;
-}
-
-static void
-plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
-{
-       const struct in_device *in_dev;
-
-       rcu_read_lock();
-       in_dev = __in_dev_get_rcu(dev);
-       if (in_dev) {
-               /* Any address will do - we take the first */
-               const struct in_ifaddr *ifa = in_dev->ifa_list;
-               if (ifa) {
-                       memcpy(eth->h_source, dev->dev_addr, 6);
-                       memset(eth->h_dest, 0xfc, 2);
-                       memcpy(eth->h_dest+2, &ifa->ifa_address, 4);
-               }
-       }
-       rcu_read_unlock();
-}
-
-static int
-plip_hard_header(struct sk_buff *skb, struct net_device *dev,
-                unsigned short type, const void *daddr,
-                const void *saddr, unsigned len)
-{
-       int ret;
-
-       ret = eth_header(skb, dev, type, daddr, saddr, len);
-       if (ret >= 0)
-               plip_rewrite_address (dev, (struct ethhdr *)skb->data);
-
-       return ret;
-}
-
-static int plip_hard_header_cache(const struct neighbour *neigh,
-                                 struct hh_cache *hh, __be16 type)
-{
-       int ret;
-
-       ret = eth_header_cache(neigh, hh, type);
-       if (ret == 0) {
-               struct ethhdr *eth;
-
-               eth = (struct ethhdr*)(((u8*)hh->hh_data) +
-                                      HH_DATA_OFF(sizeof(*eth)));
-               plip_rewrite_address (neigh->dev, eth);
-       }
-
-       return ret;
-}
-
-/* Open/initialize the board.  This is called (in the current kernel)
-   sometime after booting when the 'ifconfig' program is run.
-
-   This routine gets exclusive access to the parallel port by allocating
-   its IRQ line.
- */
-static int
-plip_open(struct net_device *dev)
-{
-       struct net_local *nl = netdev_priv(dev);
-       struct in_device *in_dev;
-
-       /* Grab the port */
-       if (!nl->port_owner) {
-               if (parport_claim(nl->pardev)) return -EAGAIN;
-               nl->port_owner = 1;
-       }
-
-       nl->should_relinquish = 0;
-
-       /* Clear the data port. */
-       write_data (dev, 0x00);
-
-       /* Enable rx interrupt. */
-       enable_parport_interrupts (dev);
-       if (dev->irq == -1)
-       {
-               atomic_set (&nl->kill_timer, 0);
-               schedule_delayed_work(&nl->timer, 1);
-       }
-
-       /* Initialize the state machine. */
-       nl->rcv_data.state = nl->snd_data.state = PLIP_PK_DONE;
-       nl->rcv_data.skb = nl->snd_data.skb = NULL;
-       nl->connection = PLIP_CN_NONE;
-       nl->is_deferred = 0;
-
-       /* Fill in the MAC-level header.
-          We used to abuse dev->broadcast to store the point-to-point
-          MAC address, but we no longer do it. Instead, we fetch the
-          interface address whenever it is needed, which is cheap enough
-          because we use the hh_cache. Actually, abusing dev->broadcast
-          didn't work, because when using plip_open the point-to-point
-          address isn't yet known.
-          PLIP doesn't have a real MAC address, but we need it to be
-          DOS compatible, and to properly support taps (otherwise,
-          when the device address isn't identical to the address of a
-          received frame, the kernel incorrectly drops it).             */
-
-       in_dev=__in_dev_get_rtnl(dev);
-       if (in_dev) {
-               /* Any address will do - we take the first. We already
-                  have the first two bytes filled with 0xfc, from
-                  plip_init_dev(). */
-               struct in_ifaddr *ifa=in_dev->ifa_list;
-               if (ifa != NULL) {
-                       memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
-               }
-       }
-
-       netif_start_queue (dev);
-
-       return 0;
-}
-
-/* The inverse routine to plip_open (). */
-static int
-plip_close(struct net_device *dev)
-{
-       struct net_local *nl = netdev_priv(dev);
-       struct plip_local *snd = &nl->snd_data;
-       struct plip_local *rcv = &nl->rcv_data;
-
-       netif_stop_queue (dev);
-       DISABLE(dev->irq);
-       synchronize_irq(dev->irq);
-
-       if (dev->irq == -1)
-       {
-               init_completion(&nl->killed_timer_cmp);
-               atomic_set (&nl->kill_timer, 1);
-               wait_for_completion(&nl->killed_timer_cmp);
-       }
-
-#ifdef NOTDEF
-       outb(0x00, PAR_DATA(dev));
-#endif
-       nl->is_deferred = 0;
-       nl->connection = PLIP_CN_NONE;
-       if (nl->port_owner) {
-               parport_release(nl->pardev);
-               nl->port_owner = 0;
-       }
-
-       snd->state = PLIP_PK_DONE;
-       if (snd->skb) {
-               dev_kfree_skb(snd->skb);
-               snd->skb = NULL;
-       }
-       rcv->state = PLIP_PK_DONE;
-       if (rcv->skb) {
-               kfree_skb(rcv->skb);
-               rcv->skb = NULL;
-       }
-
-#ifdef NOTDEF
-       /* Reset. */
-       outb(0x00, PAR_CONTROL(dev));
-#endif
-       return 0;
-}
-
-static int
-plip_preempt(void *handle)
-{
-       struct net_device *dev = (struct net_device *)handle;
-       struct net_local *nl = netdev_priv(dev);
-
-       /* Stand our ground if a datagram is on the wire */
-       if (nl->connection != PLIP_CN_NONE) {
-               nl->should_relinquish = 1;
-               return 1;
-       }
-
-       nl->port_owner = 0;     /* Remember that we released the bus */
-       return 0;
-}
-
-static void
-plip_wakeup(void *handle)
-{
-       struct net_device *dev = (struct net_device *)handle;
-       struct net_local *nl = netdev_priv(dev);
-
-       if (nl->port_owner) {
-               /* Why are we being woken up? */
-               printk(KERN_DEBUG "%s: why am I being woken up?\n", dev->name);
-               if (!parport_claim(nl->pardev))
-                       /* bus_owner is already set (but why?) */
-                       printk(KERN_DEBUG "%s: I'm broken.\n", dev->name);
-               else
-                       return;
-       }
-
-       if (!(dev->flags & IFF_UP))
-               /* Don't need the port when the interface is down */
-               return;
-
-       if (!parport_claim(nl->pardev)) {
-               nl->port_owner = 1;
-               /* Clear the data port. */
-               write_data (dev, 0x00);
-       }
-}
-
-static int
-plip_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct net_local *nl = netdev_priv(dev);
-       struct plipconf *pc = (struct plipconf *) &rq->ifr_ifru;
-
-       if (cmd != SIOCDEVPLIP)
-               return -EOPNOTSUPP;
-
-       switch(pc->pcmd) {
-       case PLIP_GET_TIMEOUT:
-               pc->trigger = nl->trigger;
-               pc->nibble  = nl->nibble;
-               break;
-       case PLIP_SET_TIMEOUT:
-               if(!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-               nl->trigger = pc->trigger;
-               nl->nibble  = pc->nibble;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-       return 0;
-}
-
-static int parport[PLIP_MAX] = { [0 ... PLIP_MAX-1] = -1 };
-static int timid;
-
-module_param_array(parport, int, NULL, 0);
-module_param(timid, int, 0);
-MODULE_PARM_DESC(parport, "List of parport device numbers to use by plip");
-
-static struct net_device *dev_plip[PLIP_MAX] = { NULL, };
-
-static inline int
-plip_searchfor(int list[], int a)
-{
-       int i;
-       for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {
-               if (list[i] == a) return 1;
-       }
-       return 0;
-}
-
-/* plip_attach() is called (by the parport code) when a port is
- * available to use. */
-static void plip_attach (struct parport *port)
-{
-       static int unit;
-       struct net_device *dev;
-       struct net_local *nl;
-       char name[IFNAMSIZ];
-
-       if ((parport[0] == -1 && (!timid || !port->devices)) ||
-           plip_searchfor(parport, port->number)) {
-               if (unit == PLIP_MAX) {
-                       printk(KERN_ERR "plip: too many devices\n");
-                       return;
-               }
-
-               sprintf(name, "plip%d", unit);
-               dev = alloc_etherdev(sizeof(struct net_local));
-               if (!dev) {
-                       printk(KERN_ERR "plip: memory squeeze\n");
-                       return;
-               }
-
-               strcpy(dev->name, name);
-
-               dev->irq = port->irq;
-               dev->base_addr = port->base;
-               if (port->irq == -1) {
-                       printk(KERN_INFO "plip: %s has no IRQ. Using IRQ-less mode,"
-                                "which is fairly inefficient!\n", port->name);
-               }
-
-               nl = netdev_priv(dev);
-               nl->dev = dev;
-               nl->pardev = parport_register_device(port, dev->name, plip_preempt,
-                                                plip_wakeup, plip_interrupt,
-                                                0, dev);
-
-               if (!nl->pardev) {
-                       printk(KERN_ERR "%s: parport_register failed\n", name);
-                       goto err_free_dev;
-               }
-
-               plip_init_netdev(dev);
-
-               if (register_netdev(dev)) {
-                       printk(KERN_ERR "%s: network register failed\n", name);
-                       goto err_parport_unregister;
-               }
-
-               printk(KERN_INFO "%s", version);
-               if (dev->irq != -1)
-                       printk(KERN_INFO "%s: Parallel port at %#3lx, "
-                                        "using IRQ %d.\n",
-                                        dev->name, dev->base_addr, dev->irq);
-               else
-                       printk(KERN_INFO "%s: Parallel port at %#3lx, "
-                                        "not using IRQ.\n",
-                                        dev->name, dev->base_addr);
-               dev_plip[unit++] = dev;
-       }
-       return;
-
-err_parport_unregister:
-       parport_unregister_device(nl->pardev);
-err_free_dev:
-       free_netdev(dev);
-}
-
-/* plip_detach() is called (by the parport code) when a port is
- * no longer available to use. */
-static void plip_detach (struct parport *port)
-{
-       /* Nothing to do */
-}
-
-static struct parport_driver plip_driver = {
-       .name   = "plip",
-       .attach = plip_attach,
-       .detach = plip_detach
-};
-
-static void __exit plip_cleanup_module (void)
-{
-       struct net_device *dev;
-       int i;
-
-       parport_unregister_driver (&plip_driver);
-
-       for (i=0; i < PLIP_MAX; i++) {
-               if ((dev = dev_plip[i])) {
-                       struct net_local *nl = netdev_priv(dev);
-                       unregister_netdev(dev);
-                       if (nl->port_owner)
-                               parport_release(nl->pardev);
-                       parport_unregister_device(nl->pardev);
-                       free_netdev(dev);
-                       dev_plip[i] = NULL;
-               }
-       }
-}
-
-#ifndef MODULE
-
-static int parport_ptr;
-
-static int __init plip_setup(char *str)
-{
-       int ints[4];
-
-       str = get_options(str, ARRAY_SIZE(ints), ints);
-
-       /* Ugh. */
-       if (!strncmp(str, "parport", 7)) {
-               int n = simple_strtoul(str+7, NULL, 10);
-               if (parport_ptr < PLIP_MAX)
-                       parport[parport_ptr++] = n;
-               else
-                       printk(KERN_INFO "plip: too many ports, %s ignored.\n",
-                              str);
-       } else if (!strcmp(str, "timid")) {
-               timid = 1;
-       } else {
-               if (ints[0] == 0 || ints[1] == 0) {
-                       /* disable driver on "plip=" or "plip=0" */
-                       parport[0] = -2;
-               } else {
-                       printk(KERN_WARNING "warning: 'plip=0x%x' ignored\n",
-                              ints[1]);
-               }
-       }
-       return 1;
-}
-
-__setup("plip=", plip_setup);
-
-#endif /* !MODULE */
-
-static int __init plip_init (void)
-{
-       if (parport[0] == -2)
-               return 0;
-
-       if (parport[0] != -1 && timid) {
-               printk(KERN_WARNING "plip: warning, ignoring `timid' since specific ports given.\n");
-               timid = 0;
-       }
-
-       if (parport_register_driver (&plip_driver)) {
-               printk (KERN_WARNING "plip: couldn't register driver\n");
-               return 1;
-       }
-
-       return 0;
-}
-
-module_init(plip_init);
-module_exit(plip_cleanup_module);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/plip/Kconfig b/drivers/net/plip/Kconfig
new file mode 100644 (file)
index 0000000..80c4a33
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Parallel Line Internet Protocol (PLIP) network device configuration
+#
+
+config PLIP
+       tristate "PLIP (parallel port) support"
+       depends on PARPORT
+       ---help---
+         PLIP (Parallel Line Internet Protocol) is used to create a
+         reasonably fast mini network consisting of two (or, rarely, more)
+         local machines.  A PLIP link from a Linux box is a popular means to
+         install a Linux distribution on a machine which doesn't have a
+         CD-ROM drive (a minimal system has to be transferred with floppies
+         first). The kernels on both machines need to have this PLIP option
+         enabled for this to work.
+
+         The PLIP driver has two modes, mode 0 and mode 1.  The parallel
+         ports (the connectors at the computers with 25 holes) are connected
+         with "null printer" or "Turbo Laplink" cables which can transmit 4
+         bits at a time (mode 0) or with special PLIP cables, to be used on
+         bidirectional parallel ports only, which can transmit 8 bits at a
+         time (mode 1); you can find the wiring of these cables in
+         <file:Documentation/networking/PLIP.txt>.  The cables can be up to
+         15m long.  Mode 0 works also if one of the machines runs DOS/Windows
+         and has some PLIP software installed, e.g. the Crynwr PLIP packet
+         driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
+         and winsock or NCSA's telnet.
+
+         If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
+         as the NET-3-HOWTO, both available from
+         <http://www.tldp.org/docs.html#howto>.  Note that the PLIP
+         protocol has been changed and this PLIP driver won't work together
+         with the PLIP support in Linux versions 1.0.x.  This option enlarges
+         your kernel by about 8 KB.
+
+         To compile this driver as a module, choose M here. The module
+         will be called plip. If unsure, say Y or M, in case you buy
+         a laptop later.
diff --git a/drivers/net/plip/Makefile b/drivers/net/plip/Makefile
new file mode 100644 (file)
index 0000000..ed95879
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the PLIP network device drivers.
+#
+
+obj-$(CONFIG_PLIP) += plip.o
diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c
new file mode 100644 (file)
index 0000000..a9e9ca8
--- /dev/null
@@ -0,0 +1,1403 @@
+/* $Id: plip.c,v 1.3.6.2 1997/04/16 15:07:56 phil Exp $ */
+/* PLIP: A parallel port "network" driver for Linux. */
+/* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
+/*
+ * Authors:    Donald Becker <becker@scyld.com>
+ *             Tommy Thorn <thorn@daimi.aau.dk>
+ *             Tanabe Hiroyasu <hiro@sanpo.t.u-tokyo.ac.jp>
+ *             Alan Cox <gw4pts@gw4pts.ampr.org>
+ *             Peter Bauer <100136.3530@compuserve.com>
+ *             Niibe Yutaka <gniibe@mri.co.jp>
+ *             Nimrod Zimerman <zimerman@mailandnews.com>
+ *
+ * Enhancements:
+ *             Modularization and ifreq/ifmap support by Alan Cox.
+ *             Rewritten by Niibe Yutaka.
+ *             parport-sharing awareness code by Philip Blundell.
+ *             SMP locking by Niibe Yutaka.
+ *             Support for parallel ports with no IRQ (poll mode),
+ *             Modifications to use the parallel port API
+ *             by Nimrod Zimerman.
+ *
+ * Fixes:
+ *             Niibe Yutaka
+ *               - Module initialization.
+ *               - MTU fix.
+ *               - Make sure other end is OK, before sending a packet.
+ *               - Fix immediate timer problem.
+ *
+ *             Al Viro
+ *               - Changed {enable,disable}_irq handling to make it work
+ *                 with new ("stack") semantics.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Original version and the name 'PLIP' from Donald Becker <becker@scyld.com>
+ * inspired by Russ Nelson's parallel port packet driver.
+ *
+ * NOTE:
+ *     Tanabe Hiroyasu had changed the protocol, and it was in Linux v1.0.
+ *     Because of the necessity to communicate to DOS machines with the
+ *     Crynwr packet driver, Peter Bauer changed the protocol again
+ *     back to original protocol.
+ *
+ *     This version follows original PLIP protocol.
+ *     So, this PLIP can't communicate the PLIP of Linux v1.0.
+ */
+
+/*
+ *     To use with DOS box, please do (Turn on ARP switch):
+ *     # ifconfig plip[0-2] arp
+ */
+static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n";
+
+/*
+  Sources:
+       Ideas and protocols came from Russ Nelson's <nelson@crynwr.com>
+       "parallel.asm" parallel port packet driver.
+
+  The "Crynwr" parallel port standard specifies the following protocol:
+    Trigger by sending nibble '0x8' (this causes interrupt on other end)
+    count-low octet
+    count-high octet
+    ... data octets
+    checksum octet
+  Each octet is sent as <wait for rx. '0x1?'> <send 0x10+(octet&0x0F)>
+                       <wait for rx. '0x0?'> <send 0x00+((octet>>4)&0x0F)>
+
+  The packet is encapsulated as if it were ethernet.
+
+  The cable used is a de facto standard parallel null cable -- sold as
+  a "LapLink" cable by various places.  You'll need a 12-conductor cable to
+  make one yourself.  The wiring is:
+    SLCTIN     17 - 17
+    GROUND     25 - 25
+    D0->ERROR  2 - 15          15 - 2
+    D1->SLCT   3 - 13          13 - 3
+    D2->PAPOUT 4 - 12          12 - 4
+    D3->ACK    5 - 10          10 - 5
+    D4->BUSY   6 - 11          11 - 6
+  Do not connect the other pins.  They are
+    D5,D6,D7 are 7,8,9
+    STROBE is 1, FEED is 14, INIT is 16
+    extra grounds are 18,19,20,21,22,23,24
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_plip.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/parport.h>
+#include <linux/bitops.h>
+
+#include <net/neighbour.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+
+/* Maximum number of devices to support. */
+#define PLIP_MAX  8
+
+/* Use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 1
+#endif
+static const unsigned int net_debug = NET_DEBUG;
+
+#define ENABLE(irq)  if (irq != -1) enable_irq(irq)
+#define DISABLE(irq) if (irq != -1) disable_irq(irq)
+
+/* In micro second */
+#define PLIP_DELAY_UNIT                   1
+
+/* Connection time out = PLIP_TRIGGER_WAIT * PLIP_DELAY_UNIT usec */
+#define PLIP_TRIGGER_WAIT       500
+
+/* Nibble time out = PLIP_NIBBLE_WAIT * PLIP_DELAY_UNIT usec */
+#define PLIP_NIBBLE_WAIT        3000
+
+/* Bottom halves */
+static void plip_kick_bh(struct work_struct *work);
+static void plip_bh(struct work_struct *work);
+static void plip_timer_bh(struct work_struct *work);
+
+/* Interrupt handler */
+static void plip_interrupt(void *dev_id);
+
+/* Functions for DEV methods */
+static int plip_tx_packet(struct sk_buff *skb, struct net_device *dev);
+static int plip_hard_header(struct sk_buff *skb, struct net_device *dev,
+                            unsigned short type, const void *daddr,
+                           const void *saddr, unsigned len);
+static int plip_hard_header_cache(const struct neighbour *neigh,
+                                  struct hh_cache *hh, __be16 type);
+static int plip_open(struct net_device *dev);
+static int plip_close(struct net_device *dev);
+static int plip_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int plip_preempt(void *handle);
+static void plip_wakeup(void *handle);
+
+enum plip_connection_state {
+       PLIP_CN_NONE=0,
+       PLIP_CN_RECEIVE,
+       PLIP_CN_SEND,
+       PLIP_CN_CLOSING,
+       PLIP_CN_ERROR
+};
+
+enum plip_packet_state {
+       PLIP_PK_DONE=0,
+       PLIP_PK_TRIGGER,
+       PLIP_PK_LENGTH_LSB,
+       PLIP_PK_LENGTH_MSB,
+       PLIP_PK_DATA,
+       PLIP_PK_CHECKSUM
+};
+
+enum plip_nibble_state {
+       PLIP_NB_BEGIN,
+       PLIP_NB_1,
+       PLIP_NB_2,
+};
+
+struct plip_local {
+       enum plip_packet_state state;
+       enum plip_nibble_state nibble;
+       union {
+               struct {
+#if defined(__LITTLE_ENDIAN)
+                       unsigned char lsb;
+                       unsigned char msb;
+#elif defined(__BIG_ENDIAN)
+                       unsigned char msb;
+                       unsigned char lsb;
+#else
+#error "Please fix the endianness defines in <asm/byteorder.h>"
+#endif
+               } b;
+               unsigned short h;
+       } length;
+       unsigned short byte;
+       unsigned char  checksum;
+       unsigned char  data;
+       struct sk_buff *skb;
+};
+
+struct net_local {
+       struct net_device *dev;
+       struct work_struct immediate;
+       struct delayed_work deferred;
+       struct delayed_work timer;
+       struct plip_local snd_data;
+       struct plip_local rcv_data;
+       struct pardevice *pardev;
+       unsigned long  trigger;
+       unsigned long  nibble;
+       enum plip_connection_state connection;
+       unsigned short timeout_count;
+       int is_deferred;
+       int port_owner;
+       int should_relinquish;
+       spinlock_t lock;
+       atomic_t kill_timer;
+       struct completion killed_timer_cmp;
+};
+
+static inline void enable_parport_interrupts (struct net_device *dev)
+{
+       if (dev->irq != -1)
+       {
+               struct parport *port =
+                  ((struct net_local *)netdev_priv(dev))->pardev->port;
+               port->ops->enable_irq (port);
+       }
+}
+
+static inline void disable_parport_interrupts (struct net_device *dev)
+{
+       if (dev->irq != -1)
+       {
+               struct parport *port =
+                  ((struct net_local *)netdev_priv(dev))->pardev->port;
+               port->ops->disable_irq (port);
+       }
+}
+
+static inline void write_data (struct net_device *dev, unsigned char data)
+{
+       struct parport *port =
+          ((struct net_local *)netdev_priv(dev))->pardev->port;
+
+       port->ops->write_data (port, data);
+}
+
+static inline unsigned char read_status (struct net_device *dev)
+{
+       struct parport *port =
+          ((struct net_local *)netdev_priv(dev))->pardev->port;
+
+       return port->ops->read_status (port);
+}
+
+static const struct header_ops plip_header_ops = {
+       .create = plip_hard_header,
+       .cache  = plip_hard_header_cache,
+};
+
+static const struct net_device_ops plip_netdev_ops = {
+       .ndo_open                = plip_open,
+       .ndo_stop                = plip_close,
+       .ndo_start_xmit          = plip_tx_packet,
+       .ndo_do_ioctl            = plip_ioctl,
+       .ndo_change_mtu          = eth_change_mtu,
+       .ndo_set_mac_address     = eth_mac_addr,
+       .ndo_validate_addr       = eth_validate_addr,
+};
+
+/* Entry point of PLIP driver.
+   Probe the hardware, and register/initialize the driver.
+
+   PLIP is rather weird, because of the way it interacts with the parport
+   system.  It is _not_ initialised from Space.c.  Instead, plip_init()
+   is called, and that function makes up a "struct net_device" for each port, and
+   then calls us here.
+
+   */
+static void
+plip_init_netdev(struct net_device *dev)
+{
+       struct net_local *nl = netdev_priv(dev);
+
+       /* Then, override parts of it */
+       dev->tx_queue_len        = 10;
+       dev->flags               = IFF_POINTOPOINT|IFF_NOARP;
+       memset(dev->dev_addr, 0xfc, ETH_ALEN);
+
+       dev->netdev_ops          = &plip_netdev_ops;
+       dev->header_ops          = &plip_header_ops;
+
+
+       nl->port_owner = 0;
+
+       /* Initialize constants */
+       nl->trigger     = PLIP_TRIGGER_WAIT;
+       nl->nibble      = PLIP_NIBBLE_WAIT;
+
+       /* Initialize task queue structures */
+       INIT_WORK(&nl->immediate, plip_bh);
+       INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh);
+
+       if (dev->irq == -1)
+               INIT_DELAYED_WORK(&nl->timer, plip_timer_bh);
+
+       spin_lock_init(&nl->lock);
+}
+
+/* Bottom half handler for the delayed request.
+   This routine is kicked by do_timer().
+   Request `plip_bh' to be invoked. */
+static void
+plip_kick_bh(struct work_struct *work)
+{
+       struct net_local *nl =
+               container_of(work, struct net_local, deferred.work);
+
+       if (nl->is_deferred)
+               schedule_work(&nl->immediate);
+}
+
+/* Forward declarations of internal routines */
+static int plip_none(struct net_device *, struct net_local *,
+                    struct plip_local *, struct plip_local *);
+static int plip_receive_packet(struct net_device *, struct net_local *,
+                              struct plip_local *, struct plip_local *);
+static int plip_send_packet(struct net_device *, struct net_local *,
+                           struct plip_local *, struct plip_local *);
+static int plip_connection_close(struct net_device *, struct net_local *,
+                                struct plip_local *, struct plip_local *);
+static int plip_error(struct net_device *, struct net_local *,
+                     struct plip_local *, struct plip_local *);
+static int plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
+                                struct plip_local *snd,
+                                struct plip_local *rcv,
+                                int error);
+
+#define OK        0
+#define TIMEOUT   1
+#define ERROR     2
+#define HS_TIMEOUT     3
+
+typedef int (*plip_func)(struct net_device *dev, struct net_local *nl,
+                        struct plip_local *snd, struct plip_local *rcv);
+
+static const plip_func connection_state_table[] =
+{
+       plip_none,
+       plip_receive_packet,
+       plip_send_packet,
+       plip_connection_close,
+       plip_error
+};
+
+/* Bottom half handler of PLIP. */
+static void
+plip_bh(struct work_struct *work)
+{
+       struct net_local *nl = container_of(work, struct net_local, immediate);
+       struct plip_local *snd = &nl->snd_data;
+       struct plip_local *rcv = &nl->rcv_data;
+       plip_func f;
+       int r;
+
+       nl->is_deferred = 0;
+       f = connection_state_table[nl->connection];
+       if ((r = (*f)(nl->dev, nl, snd, rcv)) != OK &&
+           (r = plip_bh_timeout_error(nl->dev, nl, snd, rcv, r)) != OK) {
+               nl->is_deferred = 1;
+               schedule_delayed_work(&nl->deferred, 1);
+       }
+}
+
+static void
+plip_timer_bh(struct work_struct *work)
+{
+       struct net_local *nl =
+               container_of(work, struct net_local, timer.work);
+
+       if (!(atomic_read (&nl->kill_timer))) {
+               plip_interrupt (nl->dev);
+
+               schedule_delayed_work(&nl->timer, 1);
+       }
+       else {
+               complete(&nl->killed_timer_cmp);
+       }
+}
+
+static int
+plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
+                     struct plip_local *snd, struct plip_local *rcv,
+                     int error)
+{
+       unsigned char c0;
+       /*
+        * This is tricky. If we got here from the beginning of send (either
+        * with ERROR or HS_TIMEOUT) we have IRQ enabled. Otherwise it's
+        * already disabled. With the old variant of {enable,disable}_irq()
+        * extra disable_irq() was a no-op. Now it became mortal - it's
+        * unbalanced and thus we'll never re-enable IRQ (until rmmod plip,
+        * that is). So we have to treat HS_TIMEOUT and ERROR from send
+        * in a special way.
+        */
+
+       spin_lock_irq(&nl->lock);
+       if (nl->connection == PLIP_CN_SEND) {
+
+               if (error != ERROR) { /* Timeout */
+                       nl->timeout_count++;
+                       if ((error == HS_TIMEOUT && nl->timeout_count <= 10) ||
+                           nl->timeout_count <= 3) {
+                               spin_unlock_irq(&nl->lock);
+                               /* Try again later */
+                               return TIMEOUT;
+                       }
+                       c0 = read_status(dev);
+                       printk(KERN_WARNING "%s: transmit timeout(%d,%02x)\n",
+                              dev->name, snd->state, c0);
+               } else
+                       error = HS_TIMEOUT;
+               dev->stats.tx_errors++;
+               dev->stats.tx_aborted_errors++;
+       } else if (nl->connection == PLIP_CN_RECEIVE) {
+               if (rcv->state == PLIP_PK_TRIGGER) {
+                       /* Transmission was interrupted. */
+                       spin_unlock_irq(&nl->lock);
+                       return OK;
+               }
+               if (error != ERROR) { /* Timeout */
+                       if (++nl->timeout_count <= 3) {
+                               spin_unlock_irq(&nl->lock);
+                               /* Try again later */
+                               return TIMEOUT;
+                       }
+                       c0 = read_status(dev);
+                       printk(KERN_WARNING "%s: receive timeout(%d,%02x)\n",
+                              dev->name, rcv->state, c0);
+               }
+               dev->stats.rx_dropped++;
+       }
+       rcv->state = PLIP_PK_DONE;
+       if (rcv->skb) {
+               kfree_skb(rcv->skb);
+               rcv->skb = NULL;
+       }
+       snd->state = PLIP_PK_DONE;
+       if (snd->skb) {
+               dev_kfree_skb(snd->skb);
+               snd->skb = NULL;
+       }
+       spin_unlock_irq(&nl->lock);
+       if (error == HS_TIMEOUT) {
+               DISABLE(dev->irq);
+               synchronize_irq(dev->irq);
+       }
+       disable_parport_interrupts (dev);
+       netif_stop_queue (dev);
+       nl->connection = PLIP_CN_ERROR;
+       write_data (dev, 0x00);
+
+       return TIMEOUT;
+}
+
+static int
+plip_none(struct net_device *dev, struct net_local *nl,
+         struct plip_local *snd, struct plip_local *rcv)
+{
+       return OK;
+}
+
+/* PLIP_RECEIVE --- receive a byte(two nibbles)
+   Returns OK on success, TIMEOUT on timeout */
+static inline int
+plip_receive(unsigned short nibble_timeout, struct net_device *dev,
+            enum plip_nibble_state *ns_p, unsigned char *data_p)
+{
+       unsigned char c0, c1;
+       unsigned int cx;
+
+       switch (*ns_p) {
+       case PLIP_NB_BEGIN:
+               cx = nibble_timeout;
+               while (1) {
+                       c0 = read_status(dev);
+                       udelay(PLIP_DELAY_UNIT);
+                       if ((c0 & 0x80) == 0) {
+                               c1 = read_status(dev);
+                               if (c0 == c1)
+                                       break;
+                       }
+                       if (--cx == 0)
+                               return TIMEOUT;
+               }
+               *data_p = (c0 >> 3) & 0x0f;
+               write_data (dev, 0x10); /* send ACK */
+               *ns_p = PLIP_NB_1;
+
+       case PLIP_NB_1:
+               cx = nibble_timeout;
+               while (1) {
+                       c0 = read_status(dev);
+                       udelay(PLIP_DELAY_UNIT);
+                       if (c0 & 0x80) {
+                               c1 = read_status(dev);
+                               if (c0 == c1)
+                                       break;
+                       }
+                       if (--cx == 0)
+                               return TIMEOUT;
+               }
+               *data_p |= (c0 << 1) & 0xf0;
+               write_data (dev, 0x00); /* send ACK */
+               *ns_p = PLIP_NB_BEGIN;
+       case PLIP_NB_2:
+               break;
+       }
+       return OK;
+}
+
+/*
+ *     Determine the packet's protocol ID. The rule here is that we
+ *     assume 802.3 if the type field is short enough to be a length.
+ *     This is normal practice and works for any 'now in use' protocol.
+ *
+ *     PLIP is ethernet ish but the daddr might not be valid if unicast.
+ *     PLIP fortunately has no bus architecture (its Point-to-point).
+ *
+ *     We can't fix the daddr thing as that quirk (more bug) is embedded
+ *     in far too many old systems not all even running Linux.
+ */
+
+static __be16 plip_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ethhdr *eth;
+       unsigned char *rawp;
+
+       skb_reset_mac_header(skb);
+       skb_pull(skb,dev->hard_header_len);
+       eth = eth_hdr(skb);
+
+       if(*eth->h_dest&1)
+       {
+               if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+                       skb->pkt_type=PACKET_BROADCAST;
+               else
+                       skb->pkt_type=PACKET_MULTICAST;
+       }
+
+       /*
+        *      This ALLMULTI check should be redundant by 1.4
+        *      so don't forget to remove it.
+        */
+
+       if (ntohs(eth->h_proto) >= 1536)
+               return eth->h_proto;
+
+       rawp = skb->data;
+
+       /*
+        *      This is a magic hack to spot IPX packets. Older Novell breaks
+        *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
+        *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+        *      won't work for fault tolerant netware but does for the rest.
+        */
+       if (*(unsigned short *)rawp == 0xFFFF)
+               return htons(ETH_P_802_3);
+
+       /*
+        *      Real 802.2 LLC
+        */
+       return htons(ETH_P_802_2);
+}
+
+/* PLIP_RECEIVE_PACKET --- receive a packet */
+static int
+plip_receive_packet(struct net_device *dev, struct net_local *nl,
+                   struct plip_local *snd, struct plip_local *rcv)
+{
+       unsigned short nibble_timeout = nl->nibble;
+       unsigned char *lbuf;
+
+       switch (rcv->state) {
+       case PLIP_PK_TRIGGER:
+               DISABLE(dev->irq);
+               /* Don't need to synchronize irq, as we can safely ignore it */
+               disable_parport_interrupts (dev);
+               write_data (dev, 0x01); /* send ACK */
+               if (net_debug > 2)
+                       printk(KERN_DEBUG "%s: receive start\n", dev->name);
+               rcv->state = PLIP_PK_LENGTH_LSB;
+               rcv->nibble = PLIP_NB_BEGIN;
+
+       case PLIP_PK_LENGTH_LSB:
+               if (snd->state != PLIP_PK_DONE) {
+                       if (plip_receive(nl->trigger, dev,
+                                        &rcv->nibble, &rcv->length.b.lsb)) {
+                               /* collision, here dev->tbusy == 1 */
+                               rcv->state = PLIP_PK_DONE;
+                               nl->is_deferred = 1;
+                               nl->connection = PLIP_CN_SEND;
+                               schedule_delayed_work(&nl->deferred, 1);
+                               enable_parport_interrupts (dev);
+                               ENABLE(dev->irq);
+                               return OK;
+                       }
+               } else {
+                       if (plip_receive(nibble_timeout, dev,
+                                        &rcv->nibble, &rcv->length.b.lsb))
+                               return TIMEOUT;
+               }
+               rcv->state = PLIP_PK_LENGTH_MSB;
+
+       case PLIP_PK_LENGTH_MSB:
+               if (plip_receive(nibble_timeout, dev,
+                                &rcv->nibble, &rcv->length.b.msb))
+                       return TIMEOUT;
+               if (rcv->length.h > dev->mtu + dev->hard_header_len ||
+                   rcv->length.h < 8) {
+                       printk(KERN_WARNING "%s: bogus packet size %d.\n", dev->name, rcv->length.h);
+                       return ERROR;
+               }
+               /* Malloc up new buffer. */
+               rcv->skb = dev_alloc_skb(rcv->length.h + 2);
+               if (rcv->skb == NULL) {
+                       printk(KERN_ERR "%s: Memory squeeze.\n", dev->name);
+                       return ERROR;
+               }
+               skb_reserve(rcv->skb, 2);       /* Align IP on 16 byte boundaries */
+               skb_put(rcv->skb,rcv->length.h);
+               rcv->skb->dev = dev;
+               rcv->state = PLIP_PK_DATA;
+               rcv->byte = 0;
+               rcv->checksum = 0;
+
+       case PLIP_PK_DATA:
+               lbuf = rcv->skb->data;
+               do {
+                       if (plip_receive(nibble_timeout, dev,
+                                        &rcv->nibble, &lbuf[rcv->byte]))
+                               return TIMEOUT;
+               } while (++rcv->byte < rcv->length.h);
+               do {
+                       rcv->checksum += lbuf[--rcv->byte];
+               } while (rcv->byte);
+               rcv->state = PLIP_PK_CHECKSUM;
+
+       case PLIP_PK_CHECKSUM:
+               if (plip_receive(nibble_timeout, dev,
+                                &rcv->nibble, &rcv->data))
+                       return TIMEOUT;
+               if (rcv->data != rcv->checksum) {
+                       dev->stats.rx_crc_errors++;
+                       if (net_debug)
+                               printk(KERN_DEBUG "%s: checksum error\n", dev->name);
+                       return ERROR;
+               }
+               rcv->state = PLIP_PK_DONE;
+
+       case PLIP_PK_DONE:
+               /* Inform the upper layer for the arrival of a packet. */
+               rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
+               netif_rx_ni(rcv->skb);
+               dev->stats.rx_bytes += rcv->length.h;
+               dev->stats.rx_packets++;
+               rcv->skb = NULL;
+               if (net_debug > 2)
+                       printk(KERN_DEBUG "%s: receive end\n", dev->name);
+
+               /* Close the connection. */
+               write_data (dev, 0x00);
+               spin_lock_irq(&nl->lock);
+               if (snd->state != PLIP_PK_DONE) {
+                       nl->connection = PLIP_CN_SEND;
+                       spin_unlock_irq(&nl->lock);
+                       schedule_work(&nl->immediate);
+                       enable_parport_interrupts (dev);
+                       ENABLE(dev->irq);
+                       return OK;
+               } else {
+                       nl->connection = PLIP_CN_NONE;
+                       spin_unlock_irq(&nl->lock);
+                       enable_parport_interrupts (dev);
+                       ENABLE(dev->irq);
+                       return OK;
+               }
+       }
+       return OK;
+}
+
+/* PLIP_SEND --- send a byte (two nibbles)
+   Returns OK on success, TIMEOUT when timeout    */
+static inline int
+plip_send(unsigned short nibble_timeout, struct net_device *dev,
+         enum plip_nibble_state *ns_p, unsigned char data)
+{
+       unsigned char c0;
+       unsigned int cx;
+
+       switch (*ns_p) {
+       case PLIP_NB_BEGIN:
+               write_data (dev, data & 0x0f);
+               *ns_p = PLIP_NB_1;
+
+       case PLIP_NB_1:
+               write_data (dev, 0x10 | (data & 0x0f));
+               cx = nibble_timeout;
+               while (1) {
+                       c0 = read_status(dev);
+                       if ((c0 & 0x80) == 0)
+                               break;
+                       if (--cx == 0)
+                               return TIMEOUT;
+                       udelay(PLIP_DELAY_UNIT);
+               }
+               write_data (dev, 0x10 | (data >> 4));
+               *ns_p = PLIP_NB_2;
+
+       case PLIP_NB_2:
+               write_data (dev, (data >> 4));
+               cx = nibble_timeout;
+               while (1) {
+                       c0 = read_status(dev);
+                       if (c0 & 0x80)
+                               break;
+                       if (--cx == 0)
+                               return TIMEOUT;
+                       udelay(PLIP_DELAY_UNIT);
+               }
+               *ns_p = PLIP_NB_BEGIN;
+               return OK;
+       }
+       return OK;
+}
+
+/* PLIP_SEND_PACKET --- send a packet */
+static int
+plip_send_packet(struct net_device *dev, struct net_local *nl,
+                struct plip_local *snd, struct plip_local *rcv)
+{
+       unsigned short nibble_timeout = nl->nibble;
+       unsigned char *lbuf;
+       unsigned char c0;
+       unsigned int cx;
+
+       if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) {
+               printk(KERN_DEBUG "%s: send skb lost\n", dev->name);
+               snd->state = PLIP_PK_DONE;
+               snd->skb = NULL;
+               return ERROR;
+       }
+
+       switch (snd->state) {
+       case PLIP_PK_TRIGGER:
+               if ((read_status(dev) & 0xf8) != 0x80)
+                       return HS_TIMEOUT;
+
+               /* Trigger remote rx interrupt. */
+               write_data (dev, 0x08);
+               cx = nl->trigger;
+               while (1) {
+                       udelay(PLIP_DELAY_UNIT);
+                       spin_lock_irq(&nl->lock);
+                       if (nl->connection == PLIP_CN_RECEIVE) {
+                               spin_unlock_irq(&nl->lock);
+                               /* Interrupted. */
+                               dev->stats.collisions++;
+                               return OK;
+                       }
+                       c0 = read_status(dev);
+                       if (c0 & 0x08) {
+                               spin_unlock_irq(&nl->lock);
+                               DISABLE(dev->irq);
+                               synchronize_irq(dev->irq);
+                               if (nl->connection == PLIP_CN_RECEIVE) {
+                                       /* Interrupted.
+                                          We don't need to enable irq,
+                                          as it is soon disabled.    */
+                                       /* Yes, we do. New variant of
+                                          {enable,disable}_irq *counts*
+                                          them.  -- AV  */
+                                       ENABLE(dev->irq);
+                                       dev->stats.collisions++;
+                                       return OK;
+                               }
+                               disable_parport_interrupts (dev);
+                               if (net_debug > 2)
+                                       printk(KERN_DEBUG "%s: send start\n", dev->name);
+                               snd->state = PLIP_PK_LENGTH_LSB;
+                               snd->nibble = PLIP_NB_BEGIN;
+                               nl->timeout_count = 0;
+                               break;
+                       }
+                       spin_unlock_irq(&nl->lock);
+                       if (--cx == 0) {
+                               write_data (dev, 0x00);
+                               return HS_TIMEOUT;
+                       }
+               }
+
+       case PLIP_PK_LENGTH_LSB:
+               if (plip_send(nibble_timeout, dev,
+                             &snd->nibble, snd->length.b.lsb))
+                       return TIMEOUT;
+               snd->state = PLIP_PK_LENGTH_MSB;
+
+       case PLIP_PK_LENGTH_MSB:
+               if (plip_send(nibble_timeout, dev,
+                             &snd->nibble, snd->length.b.msb))
+                       return TIMEOUT;
+               snd->state = PLIP_PK_DATA;
+               snd->byte = 0;
+               snd->checksum = 0;
+
+       case PLIP_PK_DATA:
+               do {
+                       if (plip_send(nibble_timeout, dev,
+                                     &snd->nibble, lbuf[snd->byte]))
+                               return TIMEOUT;
+               } while (++snd->byte < snd->length.h);
+               do {
+                       snd->checksum += lbuf[--snd->byte];
+               } while (snd->byte);
+               snd->state = PLIP_PK_CHECKSUM;
+
+       case PLIP_PK_CHECKSUM:
+               if (plip_send(nibble_timeout, dev,
+                             &snd->nibble, snd->checksum))
+                       return TIMEOUT;
+
+               dev->stats.tx_bytes += snd->skb->len;
+               dev_kfree_skb(snd->skb);
+               dev->stats.tx_packets++;
+               snd->state = PLIP_PK_DONE;
+
+       case PLIP_PK_DONE:
+               /* Close the connection */
+               write_data (dev, 0x00);
+               snd->skb = NULL;
+               if (net_debug > 2)
+                       printk(KERN_DEBUG "%s: send end\n", dev->name);
+               nl->connection = PLIP_CN_CLOSING;
+               nl->is_deferred = 1;
+               schedule_delayed_work(&nl->deferred, 1);
+               enable_parport_interrupts (dev);
+               ENABLE(dev->irq);
+               return OK;
+       }
+       return OK;
+}
+
+static int
+plip_connection_close(struct net_device *dev, struct net_local *nl,
+                     struct plip_local *snd, struct plip_local *rcv)
+{
+       spin_lock_irq(&nl->lock);
+       if (nl->connection == PLIP_CN_CLOSING) {
+               nl->connection = PLIP_CN_NONE;
+               netif_wake_queue (dev);
+       }
+       spin_unlock_irq(&nl->lock);
+       if (nl->should_relinquish) {
+               nl->should_relinquish = nl->port_owner = 0;
+               parport_release(nl->pardev);
+       }
+       return OK;
+}
+
+/* PLIP_ERROR --- wait till other end settled */
+static int
+plip_error(struct net_device *dev, struct net_local *nl,
+          struct plip_local *snd, struct plip_local *rcv)
+{
+       unsigned char status;
+
+       status = read_status(dev);
+       if ((status & 0xf8) == 0x80) {
+               if (net_debug > 2)
+                       printk(KERN_DEBUG "%s: reset interface.\n", dev->name);
+               nl->connection = PLIP_CN_NONE;
+               nl->should_relinquish = 0;
+               netif_start_queue (dev);
+               enable_parport_interrupts (dev);
+               ENABLE(dev->irq);
+               netif_wake_queue (dev);
+       } else {
+               nl->is_deferred = 1;
+               schedule_delayed_work(&nl->deferred, 1);
+       }
+
+       return OK;
+}
+
+/* Handle the parallel port interrupts. */
+static void
+plip_interrupt(void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct net_local *nl;
+       struct plip_local *rcv;
+       unsigned char c0;
+       unsigned long flags;
+
+       nl = netdev_priv(dev);
+       rcv = &nl->rcv_data;
+
+       spin_lock_irqsave (&nl->lock, flags);
+
+       c0 = read_status(dev);
+       if ((c0 & 0xf8) != 0xc0) {
+               if ((dev->irq != -1) && (net_debug > 1))
+                       printk(KERN_DEBUG "%s: spurious interrupt\n", dev->name);
+               spin_unlock_irqrestore (&nl->lock, flags);
+               return;
+       }
+
+       if (net_debug > 3)
+               printk(KERN_DEBUG "%s: interrupt.\n", dev->name);
+
+       switch (nl->connection) {
+       case PLIP_CN_CLOSING:
+               netif_wake_queue (dev);
+       case PLIP_CN_NONE:
+       case PLIP_CN_SEND:
+               rcv->state = PLIP_PK_TRIGGER;
+               nl->connection = PLIP_CN_RECEIVE;
+               nl->timeout_count = 0;
+               schedule_work(&nl->immediate);
+               break;
+
+       case PLIP_CN_RECEIVE:
+               /* May occur because there is race condition
+                  around test and set of dev->interrupt.
+                  Ignore this interrupt. */
+               break;
+
+       case PLIP_CN_ERROR:
+               printk(KERN_ERR "%s: receive interrupt in error state\n", dev->name);
+               break;
+       }
+
+       spin_unlock_irqrestore(&nl->lock, flags);
+}
+
+static int
+plip_tx_packet(struct sk_buff *skb, struct net_device *dev)
+{
+       struct net_local *nl = netdev_priv(dev);
+       struct plip_local *snd = &nl->snd_data;
+
+       if (netif_queue_stopped(dev))
+               return NETDEV_TX_BUSY;
+
+       /* We may need to grab the bus */
+       if (!nl->port_owner) {
+               if (parport_claim(nl->pardev))
+                       return NETDEV_TX_BUSY;
+               nl->port_owner = 1;
+       }
+
+       netif_stop_queue (dev);
+
+       if (skb->len > dev->mtu + dev->hard_header_len) {
+               printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len);
+               netif_start_queue (dev);
+               return NETDEV_TX_BUSY;
+       }
+
+       if (net_debug > 2)
+               printk(KERN_DEBUG "%s: send request\n", dev->name);
+
+       spin_lock_irq(&nl->lock);
+       snd->skb = skb;
+       snd->length.h = skb->len;
+       snd->state = PLIP_PK_TRIGGER;
+       if (nl->connection == PLIP_CN_NONE) {
+               nl->connection = PLIP_CN_SEND;
+               nl->timeout_count = 0;
+       }
+       schedule_work(&nl->immediate);
+       spin_unlock_irq(&nl->lock);
+
+       return NETDEV_TX_OK;
+}
+
+static void
+plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
+{
+       const struct in_device *in_dev;
+
+       rcu_read_lock();
+       in_dev = __in_dev_get_rcu(dev);
+       if (in_dev) {
+               /* Any address will do - we take the first */
+               const struct in_ifaddr *ifa = in_dev->ifa_list;
+               if (ifa) {
+                       memcpy(eth->h_source, dev->dev_addr, 6);
+                       memset(eth->h_dest, 0xfc, 2);
+                       memcpy(eth->h_dest+2, &ifa->ifa_address, 4);
+               }
+       }
+       rcu_read_unlock();
+}
+
+static int
+plip_hard_header(struct sk_buff *skb, struct net_device *dev,
+                unsigned short type, const void *daddr,
+                const void *saddr, unsigned len)
+{
+       int ret;
+
+       ret = eth_header(skb, dev, type, daddr, saddr, len);
+       if (ret >= 0)
+               plip_rewrite_address (dev, (struct ethhdr *)skb->data);
+
+       return ret;
+}
+
+static int plip_hard_header_cache(const struct neighbour *neigh,
+                                 struct hh_cache *hh, __be16 type)
+{
+       int ret;
+
+       ret = eth_header_cache(neigh, hh, type);
+       if (ret == 0) {
+               struct ethhdr *eth;
+
+               eth = (struct ethhdr*)(((u8*)hh->hh_data) +
+                                      HH_DATA_OFF(sizeof(*eth)));
+               plip_rewrite_address (neigh->dev, eth);
+       }
+
+       return ret;
+}
+
+/* Open/initialize the board.  This is called (in the current kernel)
+   sometime after booting when the 'ifconfig' program is run.
+
+   This routine gets exclusive access to the parallel port by allocating
+   its IRQ line.
+ */
+static int
+plip_open(struct net_device *dev)
+{
+       struct net_local *nl = netdev_priv(dev);
+       struct in_device *in_dev;
+
+       /* Grab the port */
+       if (!nl->port_owner) {
+               if (parport_claim(nl->pardev)) return -EAGAIN;
+               nl->port_owner = 1;
+       }
+
+       nl->should_relinquish = 0;
+
+       /* Clear the data port. */
+       write_data (dev, 0x00);
+
+       /* Enable rx interrupt. */
+       enable_parport_interrupts (dev);
+       if (dev->irq == -1)
+       {
+               atomic_set (&nl->kill_timer, 0);
+               schedule_delayed_work(&nl->timer, 1);
+       }
+
+       /* Initialize the state machine. */
+       nl->rcv_data.state = nl->snd_data.state = PLIP_PK_DONE;
+       nl->rcv_data.skb = nl->snd_data.skb = NULL;
+       nl->connection = PLIP_CN_NONE;
+       nl->is_deferred = 0;
+
+       /* Fill in the MAC-level header.
+          We used to abuse dev->broadcast to store the point-to-point
+          MAC address, but we no longer do it. Instead, we fetch the
+          interface address whenever it is needed, which is cheap enough
+          because we use the hh_cache. Actually, abusing dev->broadcast
+          didn't work, because when using plip_open the point-to-point
+          address isn't yet known.
+          PLIP doesn't have a real MAC address, but we need it to be
+          DOS compatible, and to properly support taps (otherwise,
+          when the device address isn't identical to the address of a
+          received frame, the kernel incorrectly drops it).             */
+
+       in_dev=__in_dev_get_rtnl(dev);
+       if (in_dev) {
+               /* Any address will do - we take the first. We already
+                  have the first two bytes filled with 0xfc, from
+                  plip_init_dev(). */
+               struct in_ifaddr *ifa=in_dev->ifa_list;
+               if (ifa != NULL) {
+                       memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
+               }
+       }
+
+       netif_start_queue (dev);
+
+       return 0;
+}
+
+/* The inverse routine to plip_open (). */
+static int
+plip_close(struct net_device *dev)
+{
+       struct net_local *nl = netdev_priv(dev);
+       struct plip_local *snd = &nl->snd_data;
+       struct plip_local *rcv = &nl->rcv_data;
+
+       netif_stop_queue (dev);
+       DISABLE(dev->irq);
+       synchronize_irq(dev->irq);
+
+       if (dev->irq == -1)
+       {
+               init_completion(&nl->killed_timer_cmp);
+               atomic_set (&nl->kill_timer, 1);
+               wait_for_completion(&nl->killed_timer_cmp);
+       }
+
+#ifdef NOTDEF
+       outb(0x00, PAR_DATA(dev));
+#endif
+       nl->is_deferred = 0;
+       nl->connection = PLIP_CN_NONE;
+       if (nl->port_owner) {
+               parport_release(nl->pardev);
+               nl->port_owner = 0;
+       }
+
+       snd->state = PLIP_PK_DONE;
+       if (snd->skb) {
+               dev_kfree_skb(snd->skb);
+               snd->skb = NULL;
+       }
+       rcv->state = PLIP_PK_DONE;
+       if (rcv->skb) {
+               kfree_skb(rcv->skb);
+               rcv->skb = NULL;
+       }
+
+#ifdef NOTDEF
+       /* Reset. */
+       outb(0x00, PAR_CONTROL(dev));
+#endif
+       return 0;
+}
+
+static int
+plip_preempt(void *handle)
+{
+       struct net_device *dev = (struct net_device *)handle;
+       struct net_local *nl = netdev_priv(dev);
+
+       /* Stand our ground if a datagram is on the wire */
+       if (nl->connection != PLIP_CN_NONE) {
+               nl->should_relinquish = 1;
+               return 1;
+       }
+
+       nl->port_owner = 0;     /* Remember that we released the bus */
+       return 0;
+}
+
+static void
+plip_wakeup(void *handle)
+{
+       struct net_device *dev = (struct net_device *)handle;
+       struct net_local *nl = netdev_priv(dev);
+
+       if (nl->port_owner) {
+               /* Why are we being woken up? */
+               printk(KERN_DEBUG "%s: why am I being woken up?\n", dev->name);
+               if (!parport_claim(nl->pardev))
+                       /* bus_owner is already set (but why?) */
+                       printk(KERN_DEBUG "%s: I'm broken.\n", dev->name);
+               else
+                       return;
+       }
+
+       if (!(dev->flags & IFF_UP))
+               /* Don't need the port when the interface is down */
+               return;
+
+       if (!parport_claim(nl->pardev)) {
+               nl->port_owner = 1;
+               /* Clear the data port. */
+               write_data (dev, 0x00);
+       }
+}
+
+static int
+plip_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct net_local *nl = netdev_priv(dev);
+       struct plipconf *pc = (struct plipconf *) &rq->ifr_ifru;
+
+       if (cmd != SIOCDEVPLIP)
+               return -EOPNOTSUPP;
+
+       switch(pc->pcmd) {
+       case PLIP_GET_TIMEOUT:
+               pc->trigger = nl->trigger;
+               pc->nibble  = nl->nibble;
+               break;
+       case PLIP_SET_TIMEOUT:
+               if(!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               nl->trigger = pc->trigger;
+               nl->nibble  = pc->nibble;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
+static int parport[PLIP_MAX] = { [0 ... PLIP_MAX-1] = -1 };
+static int timid;
+
+module_param_array(parport, int, NULL, 0);
+module_param(timid, int, 0);
+MODULE_PARM_DESC(parport, "List of parport device numbers to use by plip");
+
+static struct net_device *dev_plip[PLIP_MAX] = { NULL, };
+
+static inline int
+plip_searchfor(int list[], int a)
+{
+       int i;
+       for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {
+               if (list[i] == a) return 1;
+       }
+       return 0;
+}
+
+/* plip_attach() is called (by the parport code) when a port is
+ * available to use. */
+static void plip_attach (struct parport *port)
+{
+       static int unit;
+       struct net_device *dev;
+       struct net_local *nl;
+       char name[IFNAMSIZ];
+
+       if ((parport[0] == -1 && (!timid || !port->devices)) ||
+           plip_searchfor(parport, port->number)) {
+               if (unit == PLIP_MAX) {
+                       printk(KERN_ERR "plip: too many devices\n");
+                       return;
+               }
+
+               sprintf(name, "plip%d", unit);
+               dev = alloc_etherdev(sizeof(struct net_local));
+               if (!dev) {
+                       printk(KERN_ERR "plip: memory squeeze\n");
+                       return;
+               }
+
+               strcpy(dev->name, name);
+
+               dev->irq = port->irq;
+               dev->base_addr = port->base;
+               if (port->irq == -1) {
+                       printk(KERN_INFO "plip: %s has no IRQ. Using IRQ-less mode,"
+                                "which is fairly inefficient!\n", port->name);
+               }
+
+               nl = netdev_priv(dev);
+               nl->dev = dev;
+               nl->pardev = parport_register_device(port, dev->name, plip_preempt,
+                                                plip_wakeup, plip_interrupt,
+                                                0, dev);
+
+               if (!nl->pardev) {
+                       printk(KERN_ERR "%s: parport_register failed\n", name);
+                       goto err_free_dev;
+               }
+
+               plip_init_netdev(dev);
+
+               if (register_netdev(dev)) {
+                       printk(KERN_ERR "%s: network register failed\n", name);
+                       goto err_parport_unregister;
+               }
+
+               printk(KERN_INFO "%s", version);
+               if (dev->irq != -1)
+                       printk(KERN_INFO "%s: Parallel port at %#3lx, "
+                                        "using IRQ %d.\n",
+                                        dev->name, dev->base_addr, dev->irq);
+               else
+                       printk(KERN_INFO "%s: Parallel port at %#3lx, "
+                                        "not using IRQ.\n",
+                                        dev->name, dev->base_addr);
+               dev_plip[unit++] = dev;
+       }
+       return;
+
+err_parport_unregister:
+       parport_unregister_device(nl->pardev);
+err_free_dev:
+       free_netdev(dev);
+}
+
+/* plip_detach() is called (by the parport code) when a port is
+ * no longer available to use. */
+static void plip_detach (struct parport *port)
+{
+       /* Nothing to do */
+}
+
+static struct parport_driver plip_driver = {
+       .name   = "plip",
+       .attach = plip_attach,
+       .detach = plip_detach
+};
+
+static void __exit plip_cleanup_module (void)
+{
+       struct net_device *dev;
+       int i;
+
+       parport_unregister_driver (&plip_driver);
+
+       for (i=0; i < PLIP_MAX; i++) {
+               if ((dev = dev_plip[i])) {
+                       struct net_local *nl = netdev_priv(dev);
+                       unregister_netdev(dev);
+                       if (nl->port_owner)
+                               parport_release(nl->pardev);
+                       parport_unregister_device(nl->pardev);
+                       free_netdev(dev);
+                       dev_plip[i] = NULL;
+               }
+       }
+}
+
+#ifndef MODULE
+
+static int parport_ptr;
+
+static int __init plip_setup(char *str)
+{
+       int ints[4];
+
+       str = get_options(str, ARRAY_SIZE(ints), ints);
+
+       /* Ugh. */
+       if (!strncmp(str, "parport", 7)) {
+               int n = simple_strtoul(str+7, NULL, 10);
+               if (parport_ptr < PLIP_MAX)
+                       parport[parport_ptr++] = n;
+               else
+                       printk(KERN_INFO "plip: too many ports, %s ignored.\n",
+                              str);
+       } else if (!strcmp(str, "timid")) {
+               timid = 1;
+       } else {
+               if (ints[0] == 0 || ints[1] == 0) {
+                       /* disable driver on "plip=" or "plip=0" */
+                       parport[0] = -2;
+               } else {
+                       printk(KERN_WARNING "warning: 'plip=0x%x' ignored\n",
+                              ints[1]);
+               }
+       }
+       return 1;
+}
+
+__setup("plip=", plip_setup);
+
+#endif /* !MODULE */
+
+static int __init plip_init (void)
+{
+       if (parport[0] == -2)
+               return 0;
+
+       if (parport[0] != -1 && timid) {
+               printk(KERN_WARNING "plip: warning, ignoring `timid' since specific ports given.\n");
+               timid = 0;
+       }
+
+       if (parport_register_driver (&plip_driver)) {
+               printk (KERN_WARNING "plip: couldn't register driver\n");
+               return 1;
+       }
+
+       return 0;
+}
+
+module_init(plip_init);
+module_exit(plip_cleanup_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig
new file mode 100644 (file)
index 0000000..872df3e
--- /dev/null
@@ -0,0 +1,175 @@
+#
+# PPP network device configuration
+#
+
+config PPP
+       tristate "PPP (point-to-point protocol) support"
+       select SLHC
+       ---help---
+         PPP (Point to Point Protocol) is a newer and better SLIP.  It serves
+         the same purpose: sending Internet traffic over telephone (and other
+         serial) lines.  Ask your access provider if they support it, because
+         otherwise you can't use it; most Internet access providers these
+         days support PPP rather than SLIP.
+
+         To use PPP, you need an additional program called pppd as described
+         in the PPP-HOWTO, available at
+         <http://www.tldp.org/docs.html#howto>.  Make sure that you have
+         the version of pppd recommended in <file:Documentation/Changes>.
+         The PPP option enlarges your kernel by about 16 KB.
+
+         There are actually two versions of PPP: the traditional PPP for
+         asynchronous lines, such as regular analog phone lines, and
+         synchronous PPP which can be used over digital ISDN lines for
+         example.  If you want to use PPP over phone lines or other
+         asynchronous serial lines, you need to say Y (or M) here and also to
+         the next option, "PPP support for async serial ports".  For PPP over
+         synchronous lines, you should say Y (or M) here and to "Support
+         synchronous PPP", below.
+
+         If you said Y to "Version information on all symbols" above, then
+         you cannot compile the PPP driver into the kernel; you can then only
+         compile it as a module. To compile this driver as a module, choose M
+         here. The module will be called ppp_generic.
+
+if PPP
+
+config PPP_BSDCOMP
+       tristate "PPP BSD-Compress compression"
+       depends on PPP
+       ---help---
+         Support for the BSD-Compress compression method for PPP, which uses
+         the LZW compression method to compress each PPP packet before it is
+         sent over the wire. The machine at the other end of the PPP link
+         (usually your ISP) has to support the BSD-Compress compression
+         method as well for this to be useful. Even if they don't support it,
+         it is safe to say Y here.
+
+         The PPP Deflate compression method ("PPP Deflate compression",
+         above) is preferable to BSD-Compress, because it compresses better
+         and is patent-free.
+
+         Note that the BSD compression code will always be compiled as a
+         module; it is called bsd_comp and will show up in the directory
+         modules once you have said "make modules". If unsure, say N.
+
+config PPP_DEFLATE
+       tristate "PPP Deflate compression"
+       depends on PPP
+       select ZLIB_INFLATE
+       select ZLIB_DEFLATE
+       ---help---
+         Support for the Deflate compression method for PPP, which uses the
+         Deflate algorithm (the same algorithm that gzip uses) to compress
+         each PPP packet before it is sent over the wire.  The machine at the
+         other end of the PPP link (usually your ISP) has to support the
+         Deflate compression method as well for this to be useful.  Even if
+         they don't support it, it is safe to say Y here.
+
+         To compile this driver as a module, choose M here.
+
+config PPP_FILTER
+       bool "PPP filtering"
+       depends on PPP
+       ---help---
+         Say Y here if you want to be able to filter the packets passing over
+         PPP interfaces.  This allows you to control which packets count as
+         activity (i.e. which packets will reset the idle timer or bring up
+         a demand-dialed link) and which packets are to be dropped entirely.
+         You need to say Y here if you wish to use the pass-filter and
+         active-filter options to pppd.
+
+         If unsure, say N.
+
+config PPP_MPPE
+       tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
+       depends on PPP && EXPERIMENTAL
+       select CRYPTO
+       select CRYPTO_SHA1
+       select CRYPTO_ARC4
+       select CRYPTO_ECB
+       ---help---
+         Support for the MPPE Encryption protocol, as employed by the
+         Microsoft Point-to-Point Tunneling Protocol.
+
+         See http://pptpclient.sourceforge.net/ for information on
+         configuring PPTP clients and servers to utilize this method.
+
+config PPP_MULTILINK
+       bool "PPP multilink support (EXPERIMENTAL)"
+       depends on PPP && EXPERIMENTAL
+       ---help---
+         PPP multilink is a protocol (defined in RFC 1990) which allows you
+         to combine several (logical or physical) lines into one logical PPP
+         connection, so that you can utilize your full bandwidth.
+
+         This has to be supported at the other end as well and you need a
+         version of the pppd daemon which understands the multilink protocol.
+
+         If unsure, say N.
+
+config PPPOATM
+       tristate "PPP over ATM"
+       depends on ATM && PPP
+       ---help---
+         Support PPP (Point to Point Protocol) encapsulated in ATM frames.
+         This implementation does not yet comply with section 8 of RFC2364,
+         which can lead to bad results if the ATM peer loses state and
+         changes its encapsulation unilaterally.
+
+config PPPOE
+       tristate "PPP over Ethernet (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && PPP
+       ---help---
+         Support for PPP over Ethernet.
+
+         This driver requires the latest version of pppd from the CVS
+         repository at cvs.samba.org.  Alternatively, see the
+         RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
+         which contains instruction on how to use this driver (under
+         the heading "Kernel mode PPPoE").
+
+config PPTP
+       tristate "PPP over IPv4 (PPTP) (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && PPP && NET_IPGRE_DEMUX
+       ---help---
+         Support for PPP over IPv4.(Point-to-Point Tunneling Protocol)
+
+         This driver requires pppd plugin to work in client mode or
+         modified pptpd (poptop) to work in server mode.
+         See http://accel-pptp.sourceforge.net/ for information how to
+         utilize this module.
+
+config PPPOL2TP
+       tristate "PPP over L2TP (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && L2TP && PPP
+       ---help---
+         Support for PPP-over-L2TP socket family. L2TP is a protocol
+         used by ISPs and enterprises to tunnel PPP traffic over UDP
+         tunnels. L2TP is replacing PPTP for VPN uses.
+
+config PPP_ASYNC
+       tristate "PPP support for async serial ports"
+       depends on PPP
+       select CRC_CCITT
+       ---help---
+         Say Y (or M) here if you want to be able to use PPP over standard
+         asynchronous serial ports, such as COM1 or COM2 on a PC.  If you use
+         a modem (not a synchronous or ISDN modem) to contact your ISP, you
+         need this option.
+
+         To compile this driver as a module, choose M here.
+
+         If unsure, say Y.
+
+config PPP_SYNC_TTY
+       tristate "PPP support for sync tty ports"
+       depends on PPP
+       ---help---
+         Say Y (or M) here if you want to be able to use PPP over synchronous
+         (HDLC) tty devices, such as the SyncLink adapter. These devices
+         are often used for high-speed leased lines like T1/E1.
+
+         To compile this driver as a module, choose M here.
+
+endif # PPP
diff --git a/drivers/net/ppp/Makefile b/drivers/net/ppp/Makefile
new file mode 100644 (file)
index 0000000..a6b6297
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux PPP network device drivers.
+#
+
+obj-$(CONFIG_PPP) += ppp_generic.o
+obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
+obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
+obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
+obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
+obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
+obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+obj-$(CONFIG_PPPOL2TP) += pppox.o
+obj-$(CONFIG_PPTP) += pppox.o pptp.o
diff --git a/drivers/net/ppp/bsd_comp.c b/drivers/net/ppp/bsd_comp.c
new file mode 100644 (file)
index 0000000..a9b759a
--- /dev/null
@@ -0,0 +1,1170 @@
+/*
+ * Update: The Berkeley copyright was changed, and the change
+ * is retroactive to all "true" BSD software (ie everything
+ * from UCB as opposed to other peoples code that just carried
+ * the same license). The new copyright doesn't clash with the
+ * GPL, so the module-only restriction has been removed..
+ */
+
+/* Because this code is derived from the 4.3BSD compress source:
+ *
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This version is for use with contiguous buffers on Linux-derived systems.
+ *
+ *  ==FILEVERSION 20000226==
+ *
+ *  NOTE TO MAINTAINERS:
+ *     If you modify this file at all, please set the number above to the
+ *     date of the modification as YYMMDD (year month day).
+ *     bsd_comp.c is shipped with a PPP distribution as well as with
+ *     the kernel; if everyone increases the FILEVERSION number above,
+ *     then scripts can do the right thing when deciding whether to
+ *     install a new bsd_comp.c file. Don't change the format of that
+ *     line otherwise, so the installation script can recognize it.
+ *
+ * From: bsd_comp.c,v 1.3 1994/12/08 01:59:58 paulus Exp
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+
+#include <linux/ppp_defs.h>
+
+#undef   PACKETPTR
+#define  PACKETPTR 1
+#include <linux/ppp-comp.h>
+#undef   PACKETPTR
+
+#include <asm/byteorder.h>
+
+/*
+ * PPP "BSD compress" compression
+ *  The differences between this compression and the classic BSD LZW
+ *  source are obvious from the requirement that the classic code worked
+ *  with files while this handles arbitrarily long streams that
+ *  are broken into packets.  They are:
+ *
+ *     When the code size expands, a block of junk is not emitted by
+ *         the compressor and not expected by the decompressor.
+ *
+ *     New codes are not necessarily assigned every time an old
+ *         code is output by the compressor.  This is because a packet
+ *         end forces a code to be emitted, but does not imply that a
+ *         new sequence has been seen.
+ *
+ *     The compression ratio is checked at the first end of a packet
+ *         after the appropriate gap.  Besides simplifying and speeding
+ *         things up, this makes it more likely that the transmitter
+ *         and receiver will agree when the dictionary is cleared when
+ *         compression is not going well.
+ */
+
+/*
+ * Macros to extract protocol version and number of bits
+ * from the third byte of the BSD Compress CCP configuration option.
+ */
+
+#define BSD_VERSION(x) ((x) >> 5)
+#define BSD_NBITS(x)   ((x) & 0x1F)
+
+#define BSD_CURRENT_VERSION    1
+
+/*
+ * A dictionary for doing BSD compress.
+ */
+
+struct bsd_dict {
+    union {                            /* hash value */
+       unsigned long   fcode;
+       struct {
+#if defined(__LITTLE_ENDIAN)           /* Little endian order */
+           unsigned short      prefix; /* preceding code */
+           unsigned char       suffix; /* last character of new code */
+           unsigned char       pad;
+#elif defined(__BIG_ENDIAN)            /* Big endian order */
+           unsigned char       pad;
+           unsigned char       suffix; /* last character of new code */
+           unsigned short      prefix; /* preceding code */
+#else
+#error Endianness not defined...
+#endif
+       } hs;
+    } f;
+    unsigned short codem1;             /* output of hash table -1 */
+    unsigned short cptr;               /* map code to hash table entry */
+};
+
+struct bsd_db {
+    int            totlen;                     /* length of this structure */
+    unsigned int   hsize;              /* size of the hash table */
+    unsigned char  hshift;             /* used in hash function */
+    unsigned char  n_bits;             /* current bits/code */
+    unsigned char  maxbits;            /* maximum bits/code */
+    unsigned char  debug;              /* non-zero if debug desired */
+    unsigned char  unit;               /* ppp unit number */
+    unsigned short seqno;              /* sequence # of next packet */
+    unsigned int   mru;                        /* size of receive (decompress) bufr */
+    unsigned int   maxmaxcode;         /* largest valid code */
+    unsigned int   max_ent;            /* largest code in use */
+    unsigned int   in_count;           /* uncompressed bytes, aged */
+    unsigned int   bytes_out;          /* compressed bytes, aged */
+    unsigned int   ratio;              /* recent compression ratio */
+    unsigned int   checkpoint;         /* when to next check the ratio */
+    unsigned int   clear_count;                /* times dictionary cleared */
+    unsigned int   incomp_count;       /* incompressible packets */
+    unsigned int   incomp_bytes;       /* incompressible bytes */
+    unsigned int   uncomp_count;       /* uncompressed packets */
+    unsigned int   uncomp_bytes;       /* uncompressed bytes */
+    unsigned int   comp_count;         /* compressed packets */
+    unsigned int   comp_bytes;         /* compressed bytes */
+    unsigned short  *lens;             /* array of lengths of codes */
+    struct bsd_dict *dict;             /* dictionary */
+};
+
+#define BSD_OVHD       2               /* BSD compress overhead/packet */
+#define MIN_BSD_BITS   9
+#define BSD_INIT_BITS  MIN_BSD_BITS
+#define MAX_BSD_BITS   15
+
+static void    bsd_free (void *state);
+static void    *bsd_alloc(unsigned char *options, int opt_len, int decomp);
+static void    *bsd_comp_alloc (unsigned char *options, int opt_len);
+static void    *bsd_decomp_alloc (unsigned char *options, int opt_len);
+
+static int     bsd_init        (void *db, unsigned char *options,
+                                int opt_len, int unit, int debug, int decomp);
+static int     bsd_comp_init   (void *state, unsigned char *options,
+                                int opt_len, int unit, int opthdr, int debug);
+static int     bsd_decomp_init (void *state, unsigned char *options,
+                                int opt_len, int unit, int opthdr, int mru,
+                                int debug);
+
+static void    bsd_reset (void *state);
+static void    bsd_comp_stats (void *state, struct compstat *stats);
+
+static int     bsd_compress (void *state, unsigned char *rptr,
+                             unsigned char *obuf, int isize, int osize);
+static void    bsd_incomp (void *state, unsigned char *ibuf, int icnt);
+
+static int     bsd_decompress (void *state, unsigned char *ibuf, int isize,
+                               unsigned char *obuf, int osize);
+
+/* These are in ppp_generic.c */
+extern int  ppp_register_compressor   (struct compressor *cp);
+extern void ppp_unregister_compressor (struct compressor *cp);
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define CLEAR  256                     /* table clear output code */
+#define FIRST  257                     /* first free entry */
+#define LAST   255
+
+#define MAXCODE(b)     ((1 << (b)) - 1)
+#define BADCODEM1      MAXCODE(MAX_BSD_BITS)
+
+#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
+                                        ^ (unsigned long)(prefix))
+#define BSD_KEY(prefix,suffix)         ((((unsigned long)(suffix)) << 16) \
+                                        + (unsigned long)(prefix))
+
+#define CHECK_GAP      10000           /* Ratio check interval */
+
+#define RATIO_SCALE_LOG        8
+#define RATIO_SCALE    (1<<RATIO_SCALE_LOG)
+#define RATIO_MAX      (0x7fffffff>>RATIO_SCALE_LOG)
+
+/*
+ * clear the dictionary
+ */
+
+static void
+bsd_clear(struct bsd_db *db)
+{
+    db->clear_count++;
+    db->max_ent      = FIRST-1;
+    db->n_bits       = BSD_INIT_BITS;
+    db->bytes_out    = 0;
+    db->in_count     = 0;
+    db->ratio       = 0;
+    db->checkpoint   = CHECK_GAP;
+}
+
+/*
+ * If the dictionary is full, then see if it is time to reset it.
+ *
+ * Compute the compression ratio using fixed-point arithmetic
+ * with 8 fractional bits.
+ *
+ * Since we have an infinite stream instead of a single file,
+ * watch only the local compression ratio.
+ *
+ * Since both peers must reset the dictionary at the same time even in
+ * the absence of CLEAR codes (while packets are incompressible), they
+ * must compute the same ratio.
+ */
+
+static int bsd_check (struct bsd_db *db)       /* 1=output CLEAR */
+  {
+    unsigned int new_ratio;
+
+    if (db->in_count >= db->checkpoint)
+      {
+       /* age the ratio by limiting the size of the counts */
+       if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
+         {
+           db->in_count  -= (db->in_count  >> 2);
+           db->bytes_out -= (db->bytes_out >> 2);
+         }
+
+       db->checkpoint = db->in_count + CHECK_GAP;
+
+       if (db->max_ent >= db->maxmaxcode)
+         {
+           /* Reset the dictionary only if the ratio is worse,
+            * or if it looks as if it has been poisoned
+            * by incompressible data.
+            *
+            * This does not overflow, because
+            *  db->in_count <= RATIO_MAX.
+            */
+
+           new_ratio = db->in_count << RATIO_SCALE_LOG;
+           if (db->bytes_out != 0)
+             {
+               new_ratio /= db->bytes_out;
+             }
+
+           if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
+             {
+               bsd_clear (db);
+               return 1;
+             }
+           db->ratio = new_ratio;
+         }
+      }
+    return 0;
+  }
+
+/*
+ * Return statistics.
+ */
+
+static void bsd_comp_stats (void *state, struct compstat *stats)
+  {
+    struct bsd_db *db = (struct bsd_db *) state;
+
+    stats->unc_bytes    = db->uncomp_bytes;
+    stats->unc_packets  = db->uncomp_count;
+    stats->comp_bytes   = db->comp_bytes;
+    stats->comp_packets = db->comp_count;
+    stats->inc_bytes    = db->incomp_bytes;
+    stats->inc_packets  = db->incomp_count;
+    stats->in_count     = db->in_count;
+    stats->bytes_out    = db->bytes_out;
+  }
+
+/*
+ * Reset state, as on a CCP ResetReq.
+ */
+
+static void bsd_reset (void *state)
+  {
+    struct bsd_db *db = (struct bsd_db *) state;
+
+    bsd_clear(db);
+
+    db->seqno       = 0;
+    db->clear_count = 0;
+  }
+
+/*
+ * Release the compression structure
+ */
+
+static void bsd_free (void *state)
+{
+       struct bsd_db *db = state;
+
+       if (!db)
+               return;
+
+/*
+ * Release the dictionary
+ */
+       vfree(db->dict);
+       db->dict = NULL;
+/*
+ * Release the string buffer
+ */
+       vfree(db->lens);
+       db->lens = NULL;
+/*
+ * Finally release the structure itself.
+ */
+       kfree(db);
+}
+
+/*
+ * Allocate space for a (de) compressor.
+ */
+
+static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
+  {
+    int bits;
+    unsigned int hsize, hshift, maxmaxcode;
+    struct bsd_db *db;
+
+    if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
+       || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
+      {
+       return NULL;
+      }
+
+    bits = BSD_NBITS(options[2]);
+
+    switch (bits)
+      {
+    case 9:                    /* needs 82152 for both directions */
+    case 10:                   /* needs 84144 */
+    case 11:                   /* needs 88240 */
+    case 12:                   /* needs 96432 */
+       hsize = 5003;
+       hshift = 4;
+       break;
+    case 13:                   /* needs 176784 */
+       hsize = 9001;
+       hshift = 5;
+       break;
+    case 14:                   /* needs 353744 */
+       hsize = 18013;
+       hshift = 6;
+       break;
+    case 15:                   /* needs 691440 */
+       hsize = 35023;
+       hshift = 7;
+       break;
+    case 16:                   /* needs 1366160--far too much, */
+       /* hsize = 69001; */    /* and 69001 is too big for cptr */
+       /* hshift = 8; */       /* in struct bsd_db */
+       /* break; */
+    default:
+       return NULL;
+      }
+/*
+ * Allocate the main control structure for this instance.
+ */
+    maxmaxcode = MAXCODE(bits);
+    db         = kzalloc(sizeof (struct bsd_db),
+                                           GFP_KERNEL);
+    if (!db)
+      {
+       return NULL;
+      }
+
+/*
+ * Allocate space for the dictionary. This may be more than one page in
+ * length.
+ */
+    db->dict = vmalloc(hsize * sizeof(struct bsd_dict));
+    if (!db->dict)
+      {
+       bsd_free (db);
+       return NULL;
+      }
+
+/*
+ * If this is the compression buffer then there is no length data.
+ */
+    if (!decomp)
+      {
+       db->lens = NULL;
+      }
+/*
+ * For decompression, the length information is needed as well.
+ */
+    else
+      {
+        db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0]));
+       if (!db->lens)
+         {
+           bsd_free (db);
+           return NULL;
+         }
+      }
+/*
+ * Initialize the data information for the compression code
+ */
+    db->totlen     = sizeof (struct bsd_db)   +
+                   (sizeof (struct bsd_dict) * hsize);
+
+    db->hsize      = hsize;
+    db->hshift     = hshift;
+    db->maxmaxcode = maxmaxcode;
+    db->maxbits    = bits;
+
+    return (void *) db;
+  }
+
+static void *bsd_comp_alloc (unsigned char *options, int opt_len)
+  {
+    return bsd_alloc (options, opt_len, 0);
+  }
+
+static void *bsd_decomp_alloc (unsigned char *options, int opt_len)
+  {
+    return bsd_alloc (options, opt_len, 1);
+  }
+
+/*
+ * Initialize the database.
+ */
+
+static int bsd_init (void *state, unsigned char *options,
+                    int opt_len, int unit, int debug, int decomp)
+  {
+    struct bsd_db *db = state;
+    int indx;
+
+    if ((opt_len != 3) || (options[0] != CI_BSD_COMPRESS) || (options[1] != 3)
+       || (BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
+       || (BSD_NBITS(options[2]) != db->maxbits)
+       || (decomp && db->lens == NULL))
+      {
+       return 0;
+      }
+
+    if (decomp)
+      {
+       indx = LAST;
+       do
+         {
+           db->lens[indx] = 1;
+         }
+       while (indx-- > 0);
+      }
+
+    indx = db->hsize;
+    while (indx-- != 0)
+      {
+       db->dict[indx].codem1 = BADCODEM1;
+       db->dict[indx].cptr   = 0;
+      }
+
+    db->unit = unit;
+    db->mru  = 0;
+#ifndef DEBUG
+    if (debug)
+#endif
+      db->debug = 1;
+
+    bsd_reset(db);
+
+    return 1;
+  }
+
+static int bsd_comp_init (void *state, unsigned char *options,
+                         int opt_len, int unit, int opthdr, int debug)
+  {
+    return bsd_init (state, options, opt_len, unit, debug, 0);
+  }
+
+static int bsd_decomp_init (void *state, unsigned char *options,
+                           int opt_len, int unit, int opthdr, int mru,
+                           int debug)
+  {
+    return bsd_init (state, options, opt_len, unit, debug, 1);
+  }
+
+/*
+ * Obtain pointers to the various structures in the compression tables
+ */
+
+#define dict_ptrx(p,idx) &(p->dict[idx])
+#define lens_ptrx(p,idx) &(p->lens[idx])
+
+#ifdef DEBUG
+static unsigned short *lens_ptr(struct bsd_db *db, int idx)
+  {
+    if ((unsigned int) idx > (unsigned int) db->maxmaxcode)
+      {
+       printk ("<9>ppp: lens_ptr(%d) > max\n", idx);
+       idx = 0;
+      }
+    return lens_ptrx (db, idx);
+  }
+
+static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
+  {
+    if ((unsigned int) idx >= (unsigned int) db->hsize)
+      {
+       printk ("<9>ppp: dict_ptr(%d) > max\n", idx);
+       idx = 0;
+      }
+    return dict_ptrx (db, idx);
+  }
+
+#else
+#define lens_ptr(db,idx) lens_ptrx(db,idx)
+#define dict_ptr(db,idx) dict_ptrx(db,idx)
+#endif
+
+/*
+ * compress a packet
+ *
+ *     The result of this function is the size of the compressed
+ *     packet. A zero is returned if the packet was not compressed
+ *     for some reason, such as the size being larger than uncompressed.
+ *
+ *     One change from the BSD compress command is that when the
+ *     code size expands, we do not output a bunch of padding.
+ */
+
+static int bsd_compress (void *state, unsigned char *rptr, unsigned char *obuf,
+                        int isize, int osize)
+  {
+    struct bsd_db *db;
+    int hshift;
+    unsigned int max_ent;
+    unsigned int n_bits;
+    unsigned int bitno;
+    unsigned long accm;
+    int ent;
+    unsigned long fcode;
+    struct bsd_dict *dictp;
+    unsigned char c;
+    int hval;
+    int disp;
+    int ilen;
+    int mxcode;
+    unsigned char *wptr;
+    int olen;
+
+#define PUTBYTE(v)                     \
+  {                                    \
+    ++olen;                            \
+    if (wptr)                          \
+      {                                        \
+       *wptr++ = (unsigned char) (v);  \
+       if (olen >= osize)              \
+         {                             \
+           wptr = NULL;                \
+         }                             \
+      }                                        \
+  }
+
+#define OUTPUT(ent)                    \
+  {                                    \
+    bitno -= n_bits;                   \
+    accm |= ((ent) << bitno);          \
+    do                                 \
+      {                                        \
+       PUTBYTE(accm >> 24);            \
+       accm <<= 8;                     \
+       bitno += 8;                     \
+      }                                        \
+    while (bitno <= 24);               \
+  }
+
+  /*
+   * If the protocol is not in the range we're interested in,
+   * just return without compressing the packet.  If it is,
+   * the protocol becomes the first byte to compress.
+   */
+
+    ent = PPP_PROTOCOL(rptr);
+    if (ent < 0x21 || ent > 0xf9)
+      {
+       return 0;
+      }
+
+    db      = (struct bsd_db *) state;
+    hshift  = db->hshift;
+    max_ent = db->max_ent;
+    n_bits  = db->n_bits;
+    bitno   = 32;
+    accm    = 0;
+    mxcode  = MAXCODE (n_bits);
+
+    /* Initialize the output pointers */
+    wptr  = obuf;
+    olen  = PPP_HDRLEN + BSD_OVHD;
+
+    if (osize > isize)
+      {
+       osize = isize;
+      }
+
+    /* This is the PPP header information */
+    if (wptr)
+      {
+       *wptr++ = PPP_ADDRESS(rptr);
+       *wptr++ = PPP_CONTROL(rptr);
+       *wptr++ = 0;
+       *wptr++ = PPP_COMP;
+       *wptr++ = db->seqno >> 8;
+       *wptr++ = db->seqno;
+      }
+
+    /* Skip the input header */
+    rptr  += PPP_HDRLEN;
+    isize -= PPP_HDRLEN;
+    ilen   = ++isize;  /* Low byte of protocol is counted as input */
+
+    while (--ilen > 0)
+      {
+       c     = *rptr++;
+       fcode = BSD_KEY  (ent, c);
+       hval  = BSD_HASH (ent, c, hshift);
+       dictp = dict_ptr (db, hval);
+
+       /* Validate and then check the entry. */
+       if (dictp->codem1 >= max_ent)
+         {
+           goto nomatch;
+         }
+
+       if (dictp->f.fcode == fcode)
+         {
+           ent = dictp->codem1 + 1;
+           continue;   /* found (prefix,suffix) */
+         }
+
+       /* continue probing until a match or invalid entry */
+       disp = (hval == 0) ? 1 : hval;
+
+       do
+         {
+           hval += disp;
+           if (hval >= db->hsize)
+             {
+               hval -= db->hsize;
+             }
+           dictp = dict_ptr (db, hval);
+           if (dictp->codem1 >= max_ent)
+             {
+               goto nomatch;
+             }
+         }
+       while (dictp->f.fcode != fcode);
+
+       ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
+       continue;
+
+nomatch:
+       OUTPUT(ent);            /* output the prefix */
+
+       /* code -> hashtable */
+       if (max_ent < db->maxmaxcode)
+         {
+           struct bsd_dict *dictp2;
+           struct bsd_dict *dictp3;
+           int    indx;
+
+           /* expand code size if needed */
+           if (max_ent >= mxcode)
+             {
+               db->n_bits = ++n_bits;
+               mxcode     = MAXCODE (n_bits);
+             }
+
+           /* Invalidate old hash table entry using
+            * this code, and then take it over.
+            */
+
+           dictp2 = dict_ptr (db, max_ent + 1);
+           indx   = dictp2->cptr;
+           dictp3 = dict_ptr (db, indx);
+
+           if (dictp3->codem1 == max_ent)
+             {
+               dictp3->codem1 = BADCODEM1;
+             }
+
+           dictp2->cptr   = hval;
+           dictp->codem1  = max_ent;
+           dictp->f.fcode = fcode;
+           db->max_ent    = ++max_ent;
+
+           if (db->lens)
+             {
+               unsigned short *len1 = lens_ptr (db, max_ent);
+               unsigned short *len2 = lens_ptr (db, ent);
+               *len1 = *len2 + 1;
+             }
+         }
+       ent = c;
+      }
+
+    OUTPUT(ent);               /* output the last code */
+
+    db->bytes_out    += olen - PPP_HDRLEN - BSD_OVHD;
+    db->uncomp_bytes += isize;
+    db->in_count     += isize;
+    ++db->uncomp_count;
+    ++db->seqno;
+
+    if (bitno < 32)
+      {
+       ++db->bytes_out; /* must be set before calling bsd_check */
+      }
+
+    /*
+     * Generate the clear command if needed
+     */
+
+    if (bsd_check(db))
+      {
+       OUTPUT (CLEAR);
+      }
+
+    /*
+     * Pad dribble bits of last code with ones.
+     * Do not emit a completely useless byte of ones.
+     */
+
+    if (bitno != 32)
+      {
+       PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
+      }
+
+    /*
+     * Increase code size if we would have without the packet
+     * boundary because the decompressor will do so.
+     */
+
+    if (max_ent >= mxcode && max_ent < db->maxmaxcode)
+      {
+       db->n_bits++;
+      }
+
+    /* If output length is too large then this is an incomplete frame. */
+    if (wptr == NULL)
+      {
+       ++db->incomp_count;
+       db->incomp_bytes += isize;
+       olen              = 0;
+      }
+    else /* Count the number of compressed frames */
+      {
+       ++db->comp_count;
+       db->comp_bytes += olen;
+      }
+
+    /* Return the resulting output length */
+    return olen;
+#undef OUTPUT
+#undef PUTBYTE
+  }
+
+/*
+ * Update the "BSD Compress" dictionary on the receiver for
+ * incompressible data by pretending to compress the incoming data.
+ */
+
+static void bsd_incomp (void *state, unsigned char *ibuf, int icnt)
+  {
+    (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0);
+  }
+
+/*
+ * Decompress "BSD Compress".
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+
+static int bsd_decompress (void *state, unsigned char *ibuf, int isize,
+                          unsigned char *obuf, int osize)
+  {
+    struct bsd_db *db;
+    unsigned int max_ent;
+    unsigned long accm;
+    unsigned int bitno;                /* 1st valid bit in accm */
+    unsigned int n_bits;
+    unsigned int tgtbitno;     /* bitno when we have a code */
+    struct bsd_dict *dictp;
+    int explen;
+    int seq;
+    unsigned int incode;
+    unsigned int oldcode;
+    unsigned int finchar;
+    unsigned char *p;
+    unsigned char *wptr;
+    int adrs;
+    int ctrl;
+    int ilen;
+    int codelen;
+    int extra;
+
+    db       = (struct bsd_db *) state;
+    max_ent  = db->max_ent;
+    accm     = 0;
+    bitno    = 32;             /* 1st valid bit in accm */
+    n_bits   = db->n_bits;
+    tgtbitno = 32 - n_bits;    /* bitno when we have a code */
+
+    /*
+     * Save the address/control from the PPP header
+     * and then get the sequence number.
+     */
+
+    adrs  = PPP_ADDRESS (ibuf);
+    ctrl  = PPP_CONTROL (ibuf);
+
+    seq   = (ibuf[4] << 8) + ibuf[5];
+
+    ibuf += (PPP_HDRLEN + 2);
+    ilen  = isize - (PPP_HDRLEN + 2);
+
+    /*
+     * Check the sequence number and give up if it differs from
+     * the value we're expecting.
+     */
+
+    if (seq != db->seqno)
+      {
+       if (db->debug)
+         {
+           printk("bsd_decomp%d: bad sequence # %d, expected %d\n",
+                  db->unit, seq, db->seqno - 1);
+         }
+       return DECOMP_ERROR;
+      }
+
+    ++db->seqno;
+    db->bytes_out += ilen;
+
+    /*
+     * Fill in the ppp header, but not the last byte of the protocol
+     * (that comes from the decompressed data).
+     */
+
+    wptr    = obuf;
+    *wptr++ = adrs;
+    *wptr++ = ctrl;
+    *wptr++ = 0;
+
+    oldcode = CLEAR;
+    explen  = 3;
+
+    /*
+     * Keep the checkpoint correctly so that incompressible packets
+     * clear the dictionary at the proper times.
+     */
+
+    for (;;)
+      {
+       if (ilen-- <= 0)
+         {
+           db->in_count += (explen - 3); /* don't count the header */
+           break;
+         }
+
+       /*
+        * Accumulate bytes until we have a complete code.
+        * Then get the next code, relying on the 32-bit,
+        * unsigned accm to mask the result.
+        */
+
+       bitno -= 8;
+       accm  |= *ibuf++ << bitno;
+       if (tgtbitno < bitno)
+         {
+           continue;
+         }
+
+       incode = accm >> tgtbitno;
+       accm <<= n_bits;
+       bitno += n_bits;
+
+       /*
+        * The dictionary must only be cleared at the end of a packet.
+        */
+
+       if (incode == CLEAR)
+         {
+           if (ilen > 0)
+             {
+               if (db->debug)
+                 {
+                   printk("bsd_decomp%d: bad CLEAR\n", db->unit);
+                 }
+               return DECOMP_FATALERROR;       /* probably a bug */
+             }
+
+           bsd_clear(db);
+           break;
+         }
+
+       if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
+           || (incode > max_ent && oldcode == CLEAR))
+         {
+           if (db->debug)
+             {
+               printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
+                      db->unit, incode, oldcode);
+               printk("max_ent=0x%x explen=%d seqno=%d\n",
+                      max_ent, explen, db->seqno);
+             }
+           return DECOMP_FATALERROR;   /* probably a bug */
+         }
+
+       /* Special case for KwKwK string. */
+       if (incode > max_ent)
+         {
+           finchar = oldcode;
+           extra   = 1;
+         }
+       else
+         {
+           finchar = incode;
+           extra   = 0;
+         }
+
+       codelen = *(lens_ptr (db, finchar));
+       explen += codelen + extra;
+       if (explen > osize)
+         {
+           if (db->debug)
+             {
+               printk("bsd_decomp%d: ran out of mru\n", db->unit);
+#ifdef DEBUG
+               printk("  len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
+                      ilen, finchar, codelen, explen);
+#endif
+             }
+           return DECOMP_FATALERROR;
+         }
+
+       /*
+        * Decode this code and install it in the decompressed buffer.
+        */
+
+       wptr += codelen;
+       p     = wptr;
+       while (finchar > LAST)
+         {
+           struct bsd_dict *dictp2 = dict_ptr (db, finchar);
+
+           dictp = dict_ptr (db, dictp2->cptr);
+#ifdef DEBUG
+           if (--codelen <= 0 || dictp->codem1 != finchar-1)
+             {
+               if (codelen <= 0)
+                 {
+                   printk("bsd_decomp%d: fell off end of chain ", db->unit);
+                   printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
+                          incode, finchar, dictp2->cptr, max_ent);
+                 }
+               else
+                 {
+                   if (dictp->codem1 != finchar-1)
+                     {
+                       printk("bsd_decomp%d: bad code chain 0x%x "
+                              "finchar=0x%x ",
+                              db->unit, incode, finchar);
+
+                       printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n",
+                              oldcode, dictp2->cptr, dictp->codem1);
+                     }
+                 }
+               return DECOMP_FATALERROR;
+             }
+#endif
+           *--p    = dictp->f.hs.suffix;
+           finchar = dictp->f.hs.prefix;
+         }
+       *--p = finchar;
+
+#ifdef DEBUG
+       if (--codelen != 0)
+         {
+           printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
+                  db->unit, codelen, incode, max_ent);
+         }
+#endif
+
+       if (extra)              /* the KwKwK case again */
+         {
+           *wptr++ = finchar;
+         }
+
+       /*
+        * If not first code in a packet, and
+        * if not out of code space, then allocate a new code.
+        *
+        * Keep the hash table correct so it can be used
+        * with uncompressed packets.
+        */
+
+       if (oldcode != CLEAR && max_ent < db->maxmaxcode)
+         {
+           struct bsd_dict *dictp2, *dictp3;
+           unsigned short  *lens1,  *lens2;
+           unsigned long fcode;
+           int hval, disp, indx;
+
+           fcode = BSD_KEY(oldcode,finchar);
+           hval  = BSD_HASH(oldcode,finchar,db->hshift);
+           dictp = dict_ptr (db, hval);
+
+           /* look for a free hash table entry */
+           if (dictp->codem1 < max_ent)
+             {
+               disp = (hval == 0) ? 1 : hval;
+               do
+                 {
+                   hval += disp;
+                   if (hval >= db->hsize)
+                     {
+                       hval -= db->hsize;
+                     }
+                   dictp = dict_ptr (db, hval);
+                 }
+               while (dictp->codem1 < max_ent);
+             }
+
+           /*
+            * Invalidate previous hash table entry
+            * assigned this code, and then take it over
+            */
+
+           dictp2 = dict_ptr (db, max_ent + 1);
+           indx   = dictp2->cptr;
+           dictp3 = dict_ptr (db, indx);
+
+           if (dictp3->codem1 == max_ent)
+             {
+               dictp3->codem1 = BADCODEM1;
+             }
+
+           dictp2->cptr   = hval;
+           dictp->codem1  = max_ent;
+           dictp->f.fcode = fcode;
+           db->max_ent    = ++max_ent;
+
+           /* Update the length of this string. */
+           lens1  = lens_ptr (db, max_ent);
+           lens2  = lens_ptr (db, oldcode);
+           *lens1 = *lens2 + 1;
+
+           /* Expand code size if needed. */
+           if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
+             {
+               db->n_bits = ++n_bits;
+               tgtbitno   = 32-n_bits;
+             }
+         }
+       oldcode = incode;
+      }
+
+    ++db->comp_count;
+    ++db->uncomp_count;
+    db->comp_bytes   += isize - BSD_OVHD - PPP_HDRLEN;
+    db->uncomp_bytes += explen;
+
+    if (bsd_check(db))
+      {
+       if (db->debug)
+         {
+           printk("bsd_decomp%d: peer should have cleared dictionary on %d\n",
+                  db->unit, db->seqno - 1);
+         }
+      }
+    return explen;
+  }
+
+/*************************************************************
+ * Table of addresses for the BSD compression module
+ *************************************************************/
+
+static struct compressor ppp_bsd_compress = {
+       .compress_proto =       CI_BSD_COMPRESS,
+       .comp_alloc =           bsd_comp_alloc,
+       .comp_free =            bsd_free,
+       .comp_init =            bsd_comp_init,
+       .comp_reset =           bsd_reset,
+       .compress =             bsd_compress,
+       .comp_stat =            bsd_comp_stats,
+       .decomp_alloc =         bsd_decomp_alloc,
+       .decomp_free =          bsd_free,
+       .decomp_init =          bsd_decomp_init,
+       .decomp_reset =         bsd_reset,
+       .decompress =           bsd_decompress,
+       .incomp =               bsd_incomp,
+       .decomp_stat =          bsd_comp_stats,
+       .owner =                THIS_MODULE
+};
+
+/*************************************************************
+ * Module support routines
+ *************************************************************/
+
+static int __init bsdcomp_init(void)
+{
+       int answer = ppp_register_compressor(&ppp_bsd_compress);
+       if (answer == 0)
+               printk(KERN_INFO "PPP BSD Compression module registered\n");
+       return answer;
+}
+
+static void __exit bsdcomp_cleanup(void)
+{
+       ppp_unregister_compressor(&ppp_bsd_compress);
+}
+
+module_init(bsdcomp_init);
+module_exit(bsdcomp_cleanup);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("ppp-compress-" __stringify(CI_BSD_COMPRESS));
diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
new file mode 100644 (file)
index 0000000..c6ba643
--- /dev/null
@@ -0,0 +1,1028 @@
+/*
+ * PPP async serial channel driver for Linux.
+ *
+ * Copyright 1999 Paul Mackerras.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ * This driver provides the encapsulation and framing for sending
+ * and receiving PPP frames over async serial lines.  It relies on
+ * the generic PPP layer to give it frames to send and to process
+ * received frames.  It implements the PPP line discipline.
+ *
+ * Part of the code in this driver was inspired by the old async-only
+ * PPP driver, written by Michael Callahan and Al Longyear, and
+ * subsequently hacked by Paul Mackerras.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/tty.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/crc-ccitt.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <asm/uaccess.h>
+#include <asm/string.h>
+
+#define PPP_VERSION    "2.4.2"
+
+#define OBUFSIZE       4096
+
+/* Structure for storing local state. */
+struct asyncppp {
+       struct tty_struct *tty;
+       unsigned int    flags;
+       unsigned int    state;
+       unsigned int    rbits;
+       int             mru;
+       spinlock_t      xmit_lock;
+       spinlock_t      recv_lock;
+       unsigned long   xmit_flags;
+       u32             xaccm[8];
+       u32             raccm;
+       unsigned int    bytes_sent;
+       unsigned int    bytes_rcvd;
+
+       struct sk_buff  *tpkt;
+       int             tpkt_pos;
+       u16             tfcs;
+       unsigned char   *optr;
+       unsigned char   *olim;
+       unsigned long   last_xmit;
+
+       struct sk_buff  *rpkt;
+       int             lcp_fcs;
+       struct sk_buff_head rqueue;
+
+       struct tasklet_struct tsk;
+
+       atomic_t        refcnt;
+       struct semaphore dead_sem;
+       struct ppp_channel chan;        /* interface to generic ppp layer */
+       unsigned char   obuf[OBUFSIZE];
+};
+
+/* Bit numbers in xmit_flags */
+#define XMIT_WAKEUP    0
+#define XMIT_FULL      1
+#define XMIT_BUSY      2
+
+/* State bits */
+#define SC_TOSS                1
+#define SC_ESCAPE      2
+#define SC_PREV_ERROR  4
+
+/* Bits in rbits */
+#define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+static int flag_time = HZ;
+module_param(flag_time, int, 0);
+MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_LDISC(N_PPP);
+
+/*
+ * Prototypes.
+ */
+static int ppp_async_encode(struct asyncppp *ap);
+static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb);
+static int ppp_async_push(struct asyncppp *ap);
+static void ppp_async_flush_output(struct asyncppp *ap);
+static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
+                           char *flags, int count);
+static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,
+                          unsigned long arg);
+static void ppp_async_process(unsigned long arg);
+
+static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
+                          int len, int inbound);
+
+static const struct ppp_channel_ops async_ops = {
+       .start_xmit = ppp_async_send,
+       .ioctl      = ppp_async_ioctl,
+};
+
+/*
+ * Routines implementing the PPP line discipline.
+ */
+
+/*
+ * We have a potential race on dereferencing tty->disc_data,
+ * because the tty layer provides no locking at all - thus one
+ * cpu could be running ppp_asynctty_receive while another
+ * calls ppp_asynctty_close, which zeroes tty->disc_data and
+ * frees the memory that ppp_asynctty_receive is using.  The best
+ * way to fix this is to use a rwlock in the tty struct, but for now
+ * we use a single global rwlock for all ttys in ppp line discipline.
+ *
+ * FIXME: this is no longer true. The _close path for the ldisc is
+ * now guaranteed to be sane.
+ */
+static DEFINE_RWLOCK(disc_data_lock);
+
+static struct asyncppp *ap_get(struct tty_struct *tty)
+{
+       struct asyncppp *ap;
+
+       read_lock(&disc_data_lock);
+       ap = tty->disc_data;
+       if (ap != NULL)
+               atomic_inc(&ap->refcnt);
+       read_unlock(&disc_data_lock);
+       return ap;
+}
+
+static void ap_put(struct asyncppp *ap)
+{
+       if (atomic_dec_and_test(&ap->refcnt))
+               up(&ap->dead_sem);
+}
+
+/*
+ * Called when a tty is put into PPP line discipline. Called in process
+ * context.
+ */
+static int
+ppp_asynctty_open(struct tty_struct *tty)
+{
+       struct asyncppp *ap;
+       int err;
+       int speed;
+
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
+       err = -ENOMEM;
+       ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+       if (!ap)
+               goto out;
+
+       /* initialize the asyncppp structure */
+       ap->tty = tty;
+       ap->mru = PPP_MRU;
+       spin_lock_init(&ap->xmit_lock);
+       spin_lock_init(&ap->recv_lock);
+       ap->xaccm[0] = ~0U;
+       ap->xaccm[3] = 0x60000000U;
+       ap->raccm = ~0U;
+       ap->optr = ap->obuf;
+       ap->olim = ap->obuf;
+       ap->lcp_fcs = -1;
+
+       skb_queue_head_init(&ap->rqueue);
+       tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
+
+       atomic_set(&ap->refcnt, 1);
+       sema_init(&ap->dead_sem, 0);
+
+       ap->chan.private = ap;
+       ap->chan.ops = &async_ops;
+       ap->chan.mtu = PPP_MRU;
+       speed = tty_get_baud_rate(tty);
+       ap->chan.speed = speed;
+       err = ppp_register_channel(&ap->chan);
+       if (err)
+               goto out_free;
+
+       tty->disc_data = ap;
+       tty->receive_room = 65536;
+       return 0;
+
+ out_free:
+       kfree(ap);
+ out:
+       return err;
+}
+
+/*
+ * Called when the tty is put into another line discipline
+ * or it hangs up.  We have to wait for any cpu currently
+ * executing in any of the other ppp_asynctty_* routines to
+ * finish before we can call ppp_unregister_channel and free
+ * the asyncppp struct.  This routine must be called from
+ * process context, not interrupt or softirq context.
+ */
+static void
+ppp_asynctty_close(struct tty_struct *tty)
+{
+       struct asyncppp *ap;
+
+       write_lock_irq(&disc_data_lock);
+       ap = tty->disc_data;
+       tty->disc_data = NULL;
+       write_unlock_irq(&disc_data_lock);
+       if (!ap)
+               return;
+
+       /*
+        * We have now ensured that nobody can start using ap from now
+        * on, but we have to wait for all existing users to finish.
+        * Note that ppp_unregister_channel ensures that no calls to
+        * our channel ops (i.e. ppp_async_send/ioctl) are in progress
+        * by the time it returns.
+        */
+       if (!atomic_dec_and_test(&ap->refcnt))
+               down(&ap->dead_sem);
+       tasklet_kill(&ap->tsk);
+
+       ppp_unregister_channel(&ap->chan);
+       kfree_skb(ap->rpkt);
+       skb_queue_purge(&ap->rqueue);
+       kfree_skb(ap->tpkt);
+       kfree(ap);
+}
+
+/*
+ * Called on tty hangup in process context.
+ *
+ * Wait for I/O to driver to complete and unregister PPP channel.
+ * This is already done by the close routine, so just call that.
+ */
+static int ppp_asynctty_hangup(struct tty_struct *tty)
+{
+       ppp_asynctty_close(tty);
+       return 0;
+}
+
+/*
+ * Read does nothing - no data is ever available this way.
+ * Pppd reads and writes packets via /dev/ppp instead.
+ */
+static ssize_t
+ppp_asynctty_read(struct tty_struct *tty, struct file *file,
+                 unsigned char __user *buf, size_t count)
+{
+       return -EAGAIN;
+}
+
+/*
+ * Write on the tty does nothing, the packets all come in
+ * from the ppp generic stuff.
+ */
+static ssize_t
+ppp_asynctty_write(struct tty_struct *tty, struct file *file,
+                  const unsigned char *buf, size_t count)
+{
+       return -EAGAIN;
+}
+
+/*
+ * Called in process context only. May be re-entered by multiple
+ * ioctl calling threads.
+ */
+
+static int
+ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
+                  unsigned int cmd, unsigned long arg)
+{
+       struct asyncppp *ap = ap_get(tty);
+       int err, val;
+       int __user *p = (int __user *)arg;
+
+       if (!ap)
+               return -ENXIO;
+       err = -EFAULT;
+       switch (cmd) {
+       case PPPIOCGCHAN:
+               err = -EFAULT;
+               if (put_user(ppp_channel_index(&ap->chan), p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGUNIT:
+               err = -EFAULT;
+               if (put_user(ppp_unit_number(&ap->chan), p))
+                       break;
+               err = 0;
+               break;
+
+       case TCFLSH:
+               /* flush our buffers and the serial port's buffer */
+               if (arg == TCIOFLUSH || arg == TCOFLUSH)
+                       ppp_async_flush_output(ap);
+               err = tty_perform_flush(tty, arg);
+               break;
+
+       case FIONREAD:
+               val = 0;
+               if (put_user(val, p))
+                       break;
+               err = 0;
+               break;
+
+       default:
+               /* Try the various mode ioctls */
+               err = tty_mode_ioctl(tty, file, cmd, arg);
+       }
+
+       ap_put(ap);
+       return err;
+}
+
+/* No kernel lock - fine */
+static unsigned int
+ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
+{
+       return 0;
+}
+
+/* May sleep, don't call from interrupt level or with interrupts disabled */
+static void
+ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
+                 char *cflags, int count)
+{
+       struct asyncppp *ap = ap_get(tty);
+       unsigned long flags;
+
+       if (!ap)
+               return;
+       spin_lock_irqsave(&ap->recv_lock, flags);
+       ppp_async_input(ap, buf, cflags, count);
+       spin_unlock_irqrestore(&ap->recv_lock, flags);
+       if (!skb_queue_empty(&ap->rqueue))
+               tasklet_schedule(&ap->tsk);
+       ap_put(ap);
+       tty_unthrottle(tty);
+}
+
+static void
+ppp_asynctty_wakeup(struct tty_struct *tty)
+{
+       struct asyncppp *ap = ap_get(tty);
+
+       clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+       if (!ap)
+               return;
+       set_bit(XMIT_WAKEUP, &ap->xmit_flags);
+       tasklet_schedule(&ap->tsk);
+       ap_put(ap);
+}
+
+
+static struct tty_ldisc_ops ppp_ldisc = {
+       .owner  = THIS_MODULE,
+       .magic  = TTY_LDISC_MAGIC,
+       .name   = "ppp",
+       .open   = ppp_asynctty_open,
+       .close  = ppp_asynctty_close,
+       .hangup = ppp_asynctty_hangup,
+       .read   = ppp_asynctty_read,
+       .write  = ppp_asynctty_write,
+       .ioctl  = ppp_asynctty_ioctl,
+       .poll   = ppp_asynctty_poll,
+       .receive_buf = ppp_asynctty_receive,
+       .write_wakeup = ppp_asynctty_wakeup,
+};
+
+static int __init
+ppp_async_init(void)
+{
+       int err;
+
+       err = tty_register_ldisc(N_PPP, &ppp_ldisc);
+       if (err != 0)
+               printk(KERN_ERR "PPP_async: error %d registering line disc.\n",
+                      err);
+       return err;
+}
+
+/*
+ * The following routines provide the PPP channel interface.
+ */
+static int
+ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
+{
+       struct asyncppp *ap = chan->private;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int err, val;
+       u32 accm[8];
+
+       err = -EFAULT;
+       switch (cmd) {
+       case PPPIOCGFLAGS:
+               val = ap->flags | ap->rbits;
+               if (put_user(val, p))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSFLAGS:
+               if (get_user(val, p))
+                       break;
+               ap->flags = val & ~SC_RCV_BITS;
+               spin_lock_irq(&ap->recv_lock);
+               ap->rbits = val & SC_RCV_BITS;
+               spin_unlock_irq(&ap->recv_lock);
+               err = 0;
+               break;
+
+       case PPPIOCGASYNCMAP:
+               if (put_user(ap->xaccm[0], (u32 __user *)argp))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSASYNCMAP:
+               if (get_user(ap->xaccm[0], (u32 __user *)argp))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGRASYNCMAP:
+               if (put_user(ap->raccm, (u32 __user *)argp))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSRASYNCMAP:
+               if (get_user(ap->raccm, (u32 __user *)argp))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGXASYNCMAP:
+               if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSXASYNCMAP:
+               if (copy_from_user(accm, argp, sizeof(accm)))
+                       break;
+               accm[2] &= ~0x40000000U;        /* can't escape 0x5e */
+               accm[3] |= 0x60000000U;         /* must escape 0x7d, 0x7e */
+               memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
+               err = 0;
+               break;
+
+       case PPPIOCGMRU:
+               if (put_user(ap->mru, p))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSMRU:
+               if (get_user(val, p))
+                       break;
+               if (val < PPP_MRU)
+                       val = PPP_MRU;
+               ap->mru = val;
+               err = 0;
+               break;
+
+       default:
+               err = -ENOTTY;
+       }
+
+       return err;
+}
+
+/*
+ * This is called at softirq level to deliver received packets
+ * to the ppp_generic code, and to tell the ppp_generic code
+ * if we can accept more output now.
+ */
+static void ppp_async_process(unsigned long arg)
+{
+       struct asyncppp *ap = (struct asyncppp *) arg;
+       struct sk_buff *skb;
+
+       /* process received packets */
+       while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
+               if (skb->cb[0])
+                       ppp_input_error(&ap->chan, 0);
+               ppp_input(&ap->chan, skb);
+       }
+
+       /* try to push more stuff out */
+       if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_async_push(ap))
+               ppp_output_wakeup(&ap->chan);
+}
+
+/*
+ * Procedures for encapsulation and framing.
+ */
+
+/*
+ * Procedure to encode the data for async serial transmission.
+ * Does octet stuffing (escaping), puts the address/control bytes
+ * on if A/C compression is disabled, and does protocol compression.
+ * Assumes ap->tpkt != 0 on entry.
+ * Returns 1 if we finished the current frame, 0 otherwise.
+ */
+
+#define PUT_BYTE(ap, buf, c, islcp)    do {            \
+       if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
+               *buf++ = PPP_ESCAPE;                    \
+               *buf++ = c ^ PPP_TRANS;                 \
+       } else                                          \
+               *buf++ = c;                             \
+} while (0)
+
+static int
+ppp_async_encode(struct asyncppp *ap)
+{
+       int fcs, i, count, c, proto;
+       unsigned char *buf, *buflim;
+       unsigned char *data;
+       int islcp;
+
+       buf = ap->obuf;
+       ap->olim = buf;
+       ap->optr = buf;
+       i = ap->tpkt_pos;
+       data = ap->tpkt->data;
+       count = ap->tpkt->len;
+       fcs = ap->tfcs;
+       proto = get_unaligned_be16(data);
+
+       /*
+        * LCP packets with code values between 1 (configure-reqest)
+        * and 7 (code-reject) must be sent as though no options
+        * had been negotiated.
+        */
+       islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+       if (i == 0) {
+               if (islcp)
+                       async_lcp_peek(ap, data, count, 0);
+
+               /*
+                * Start of a new packet - insert the leading FLAG
+                * character if necessary.
+                */
+               if (islcp || flag_time == 0 ||
+                   time_after_eq(jiffies, ap->last_xmit + flag_time))
+                       *buf++ = PPP_FLAG;
+               ap->last_xmit = jiffies;
+               fcs = PPP_INITFCS;
+
+               /*
+                * Put in the address/control bytes if necessary
+                */
+               if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
+                       PUT_BYTE(ap, buf, 0xff, islcp);
+                       fcs = PPP_FCS(fcs, 0xff);
+                       PUT_BYTE(ap, buf, 0x03, islcp);
+                       fcs = PPP_FCS(fcs, 0x03);
+               }
+       }
+
+       /*
+        * Once we put in the last byte, we need to put in the FCS
+        * and closing flag, so make sure there is at least 7 bytes
+        * of free space in the output buffer.
+        */
+       buflim = ap->obuf + OBUFSIZE - 6;
+       while (i < count && buf < buflim) {
+               c = data[i++];
+               if (i == 1 && c == 0 && (ap->flags & SC_COMP_PROT))
+                       continue;       /* compress protocol field */
+               fcs = PPP_FCS(fcs, c);
+               PUT_BYTE(ap, buf, c, islcp);
+       }
+
+       if (i < count) {
+               /*
+                * Remember where we are up to in this packet.
+                */
+               ap->olim = buf;
+               ap->tpkt_pos = i;
+               ap->tfcs = fcs;
+               return 0;
+       }
+
+       /*
+        * We have finished the packet.  Add the FCS and flag.
+        */
+       fcs = ~fcs;
+       c = fcs & 0xff;
+       PUT_BYTE(ap, buf, c, islcp);
+       c = (fcs >> 8) & 0xff;
+       PUT_BYTE(ap, buf, c, islcp);
+       *buf++ = PPP_FLAG;
+       ap->olim = buf;
+
+       kfree_skb(ap->tpkt);
+       ap->tpkt = NULL;
+       return 1;
+}
+
+/*
+ * Transmit-side routines.
+ */
+
+/*
+ * Send a packet to the peer over an async tty line.
+ * Returns 1 iff the packet was accepted.
+ * If the packet was not accepted, we will call ppp_output_wakeup
+ * at some later time.
+ */
+static int
+ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb)
+{
+       struct asyncppp *ap = chan->private;
+
+       ppp_async_push(ap);
+
+       if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
+               return 0;       /* already full */
+       ap->tpkt = skb;
+       ap->tpkt_pos = 0;
+
+       ppp_async_push(ap);
+       return 1;
+}
+
+/*
+ * Push as much data as possible out to the tty.
+ */
+static int
+ppp_async_push(struct asyncppp *ap)
+{
+       int avail, sent, done = 0;
+       struct tty_struct *tty = ap->tty;
+       int tty_stuffed = 0;
+
+       /*
+        * We can get called recursively here if the tty write
+        * function calls our wakeup function.  This can happen
+        * for example on a pty with both the master and slave
+        * set to PPP line discipline.
+        * We use the XMIT_BUSY bit to detect this and get out,
+        * leaving the XMIT_WAKEUP bit set to tell the other
+        * instance that it may now be able to write more now.
+        */
+       if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
+               return 0;
+       spin_lock_bh(&ap->xmit_lock);
+       for (;;) {
+               if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
+                       tty_stuffed = 0;
+               if (!tty_stuffed && ap->optr < ap->olim) {
+                       avail = ap->olim - ap->optr;
+                       set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+                       sent = tty->ops->write(tty, ap->optr, avail);
+                       if (sent < 0)
+                               goto flush;     /* error, e.g. loss of CD */
+                       ap->optr += sent;
+                       if (sent < avail)
+                               tty_stuffed = 1;
+                       continue;
+               }
+               if (ap->optr >= ap->olim && ap->tpkt) {
+                       if (ppp_async_encode(ap)) {
+                               /* finished processing ap->tpkt */
+                               clear_bit(XMIT_FULL, &ap->xmit_flags);
+                               done = 1;
+                       }
+                       continue;
+               }
+               /*
+                * We haven't made any progress this time around.
+                * Clear XMIT_BUSY to let other callers in, but
+                * after doing so we have to check if anyone set
+                * XMIT_WAKEUP since we last checked it.  If they
+                * did, we should try again to set XMIT_BUSY and go
+                * around again in case XMIT_BUSY was still set when
+                * the other caller tried.
+                */
+               clear_bit(XMIT_BUSY, &ap->xmit_flags);
+               /* any more work to do? if not, exit the loop */
+               if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||
+                     (!tty_stuffed && ap->tpkt)))
+                       break;
+               /* more work to do, see if we can do it now */
+               if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
+                       break;
+       }
+       spin_unlock_bh(&ap->xmit_lock);
+       return done;
+
+flush:
+       clear_bit(XMIT_BUSY, &ap->xmit_flags);
+       if (ap->tpkt) {
+               kfree_skb(ap->tpkt);
+               ap->tpkt = NULL;
+               clear_bit(XMIT_FULL, &ap->xmit_flags);
+               done = 1;
+       }
+       ap->optr = ap->olim;
+       spin_unlock_bh(&ap->xmit_lock);
+       return done;
+}
+
+/*
+ * Flush output from our internal buffers.
+ * Called for the TCFLSH ioctl. Can be entered in parallel
+ * but this is covered by the xmit_lock.
+ */
+static void
+ppp_async_flush_output(struct asyncppp *ap)
+{
+       int done = 0;
+
+       spin_lock_bh(&ap->xmit_lock);
+       ap->optr = ap->olim;
+       if (ap->tpkt != NULL) {
+               kfree_skb(ap->tpkt);
+               ap->tpkt = NULL;
+               clear_bit(XMIT_FULL, &ap->xmit_flags);
+               done = 1;
+       }
+       spin_unlock_bh(&ap->xmit_lock);
+       if (done)
+               ppp_output_wakeup(&ap->chan);
+}
+
+/*
+ * Receive-side routines.
+ */
+
+/* see how many ordinary chars there are at the start of buf */
+static inline int
+scan_ordinary(struct asyncppp *ap, const unsigned char *buf, int count)
+{
+       int i, c;
+
+       for (i = 0; i < count; ++i) {
+               c = buf[i];
+               if (c == PPP_ESCAPE || c == PPP_FLAG ||
+                   (c < 0x20 && (ap->raccm & (1 << c)) != 0))
+                       break;
+       }
+       return i;
+}
+
+/* called when a flag is seen - do end-of-packet processing */
+static void
+process_input_packet(struct asyncppp *ap)
+{
+       struct sk_buff *skb;
+       unsigned char *p;
+       unsigned int len, fcs, proto;
+
+       skb = ap->rpkt;
+       if (ap->state & (SC_TOSS | SC_ESCAPE))
+               goto err;
+
+       if (skb == NULL)
+               return;         /* 0-length packet */
+
+       /* check the FCS */
+       p = skb->data;
+       len = skb->len;
+       if (len < 3)
+               goto err;       /* too short */
+       fcs = PPP_INITFCS;
+       for (; len > 0; --len)
+               fcs = PPP_FCS(fcs, *p++);
+       if (fcs != PPP_GOODFCS)
+               goto err;       /* bad FCS */
+       skb_trim(skb, skb->len - 2);
+
+       /* check for address/control and protocol compression */
+       p = skb->data;
+       if (p[0] == PPP_ALLSTATIONS) {
+               /* chop off address/control */
+               if (p[1] != PPP_UI || skb->len < 3)
+                       goto err;
+               p = skb_pull(skb, 2);
+       }
+       proto = p[0];
+       if (proto & 1) {
+               /* protocol is compressed */
+               skb_push(skb, 1)[0] = 0;
+       } else {
+               if (skb->len < 2)
+                       goto err;
+               proto = (proto << 8) + p[1];
+               if (proto == PPP_LCP)
+                       async_lcp_peek(ap, p, skb->len, 1);
+       }
+
+       /* queue the frame to be processed */
+       skb->cb[0] = ap->state;
+       skb_queue_tail(&ap->rqueue, skb);
+       ap->rpkt = NULL;
+       ap->state = 0;
+       return;
+
+ err:
+       /* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
+       ap->state = SC_PREV_ERROR;
+       if (skb) {
+               /* make skb appear as freshly allocated */
+               skb_trim(skb, 0);
+               skb_reserve(skb, - skb_headroom(skb));
+       }
+}
+
+/* Called when the tty driver has data for us. Runs parallel with the
+   other ldisc functions but will not be re-entered */
+
+static void
+ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
+               char *flags, int count)
+{
+       struct sk_buff *skb;
+       int c, i, j, n, s, f;
+       unsigned char *sp;
+
+       /* update bits used for 8-bit cleanness detection */
+       if (~ap->rbits & SC_RCV_BITS) {
+               s = 0;
+               for (i = 0; i < count; ++i) {
+                       c = buf[i];
+                       if (flags && flags[i] != 0)
+                               continue;
+                       s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
+                       c = ((c >> 4) ^ c) & 0xf;
+                       s |= (0x6996 & (1 << c))? SC_RCV_ODDP: SC_RCV_EVNP;
+               }
+               ap->rbits |= s;
+       }
+
+       while (count > 0) {
+               /* scan through and see how many chars we can do in bulk */
+               if ((ap->state & SC_ESCAPE) && buf[0] == PPP_ESCAPE)
+                       n = 1;
+               else
+                       n = scan_ordinary(ap, buf, count);
+
+               f = 0;
+               if (flags && (ap->state & SC_TOSS) == 0) {
+                       /* check the flags to see if any char had an error */
+                       for (j = 0; j < n; ++j)
+                               if ((f = flags[j]) != 0)
+                                       break;
+               }
+               if (f != 0) {
+                       /* start tossing */
+                       ap->state |= SC_TOSS;
+
+               } else if (n > 0 && (ap->state & SC_TOSS) == 0) {
+                       /* stuff the chars in the skb */
+                       skb = ap->rpkt;
+                       if (!skb) {
+                               skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
+                               if (!skb)
+                                       goto nomem;
+                               ap->rpkt = skb;
+                       }
+                       if (skb->len == 0) {
+                               /* Try to get the payload 4-byte aligned.
+                                * This should match the
+                                * PPP_ALLSTATIONS/PPP_UI/compressed tests in
+                                * process_input_packet, but we do not have
+                                * enough chars here to test buf[1] and buf[2].
+                                */
+                               if (buf[0] != PPP_ALLSTATIONS)
+                                       skb_reserve(skb, 2 + (buf[0] & 1));
+                       }
+                       if (n > skb_tailroom(skb)) {
+                               /* packet overflowed MRU */
+                               ap->state |= SC_TOSS;
+                       } else {
+                               sp = skb_put(skb, n);
+                               memcpy(sp, buf, n);
+                               if (ap->state & SC_ESCAPE) {
+                                       sp[0] ^= PPP_TRANS;
+                                       ap->state &= ~SC_ESCAPE;
+                               }
+                       }
+               }
+
+               if (n >= count)
+                       break;
+
+               c = buf[n];
+               if (flags != NULL && flags[n] != 0) {
+                       ap->state |= SC_TOSS;
+               } else if (c == PPP_FLAG) {
+                       process_input_packet(ap);
+               } else if (c == PPP_ESCAPE) {
+                       ap->state |= SC_ESCAPE;
+               } else if (I_IXON(ap->tty)) {
+                       if (c == START_CHAR(ap->tty))
+                               start_tty(ap->tty);
+                       else if (c == STOP_CHAR(ap->tty))
+                               stop_tty(ap->tty);
+               }
+               /* otherwise it's a char in the recv ACCM */
+               ++n;
+
+               buf += n;
+               if (flags)
+                       flags += n;
+               count -= n;
+       }
+       return;
+
+ nomem:
+       printk(KERN_ERR "PPPasync: no memory (input pkt)\n");
+       ap->state |= SC_TOSS;
+}
+
+/*
+ * We look at LCP frames going past so that we can notice
+ * and react to the LCP configure-ack from the peer.
+ * In the situation where the peer has been sent a configure-ack
+ * already, LCP is up once it has sent its configure-ack
+ * so the immediately following packet can be sent with the
+ * configured LCP options.  This allows us to process the following
+ * packet correctly without pppd needing to respond quickly.
+ *
+ * We only respond to the received configure-ack if we have just
+ * sent a configure-request, and the configure-ack contains the
+ * same data (this is checked using a 16-bit crc of the data).
+ */
+#define CONFREQ                1       /* LCP code field values */
+#define CONFACK                2
+#define LCP_MRU                1       /* LCP option numbers */
+#define LCP_ASYNCMAP   2
+
+static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
+                          int len, int inbound)
+{
+       int dlen, fcs, i, code;
+       u32 val;
+
+       data += 2;              /* skip protocol bytes */
+       len -= 2;
+       if (len < 4)            /* 4 = code, ID, length */
+               return;
+       code = data[0];
+       if (code != CONFACK && code != CONFREQ)
+               return;
+       dlen = get_unaligned_be16(data + 2);
+       if (len < dlen)
+               return;         /* packet got truncated or length is bogus */
+
+       if (code == (inbound? CONFACK: CONFREQ)) {
+               /*
+                * sent confreq or received confack:
+                * calculate the crc of the data from the ID field on.
+                */
+               fcs = PPP_INITFCS;
+               for (i = 1; i < dlen; ++i)
+                       fcs = PPP_FCS(fcs, data[i]);
+
+               if (!inbound) {
+                       /* outbound confreq - remember the crc for later */
+                       ap->lcp_fcs = fcs;
+                       return;
+               }
+
+               /* received confack, check the crc */
+               fcs ^= ap->lcp_fcs;
+               ap->lcp_fcs = -1;
+               if (fcs != 0)
+                       return;
+       } else if (inbound)
+               return; /* not interested in received confreq */
+
+       /* process the options in the confack */
+       data += 4;
+       dlen -= 4;
+       /* data[0] is code, data[1] is length */
+       while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {
+               switch (data[0]) {
+               case LCP_MRU:
+                       val = get_unaligned_be16(data + 2);
+                       if (inbound)
+                               ap->mru = val;
+                       else
+                               ap->chan.mtu = val;
+                       break;
+               case LCP_ASYNCMAP:
+                       val = get_unaligned_be32(data + 2);
+                       if (inbound)
+                               ap->raccm = val;
+                       else
+                               ap->xaccm[0] = val;
+                       break;
+               }
+               dlen -= data[1];
+               data += data[1];
+       }
+}
+
+static void __exit ppp_async_cleanup(void)
+{
+       if (tty_unregister_ldisc(N_PPP) != 0)
+               printk(KERN_ERR "failed to unregister PPP line discipline\n");
+}
+
+module_init(ppp_async_init);
+module_exit(ppp_async_cleanup);
diff --git a/drivers/net/ppp/ppp_deflate.c b/drivers/net/ppp/ppp_deflate.c
new file mode 100644 (file)
index 0000000..1dbdf82
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ *  ==FILEVERSION 980319==
+ *
+ * ppp_deflate.c - interface the zlib procedures for Deflate compression
+ * and decompression (as used by gzip) to the PPP code.
+ * This version is for use with Linux kernel 1.3.X.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <linux/ppp_defs.h>
+#include <linux/ppp-comp.h>
+
+#include <linux/zlib.h>
+#include <asm/unaligned.h>
+
+/*
+ * State for a Deflate (de)compressor.
+ */
+struct ppp_deflate_state {
+    int                seqno;
+    int                w_size;
+    int                unit;
+    int                mru;
+    int                debug;
+    z_stream   strm;
+    struct compstat stats;
+};
+
+#define DEFLATE_OVHD   2               /* Deflate overhead/packet */
+
+static void    *z_comp_alloc(unsigned char *options, int opt_len);
+static void    *z_decomp_alloc(unsigned char *options, int opt_len);
+static void    z_comp_free(void *state);
+static void    z_decomp_free(void *state);
+static int     z_comp_init(void *state, unsigned char *options,
+                                int opt_len,
+                                int unit, int hdrlen, int debug);
+static int     z_decomp_init(void *state, unsigned char *options,
+                                  int opt_len,
+                                  int unit, int hdrlen, int mru, int debug);
+static int     z_compress(void *state, unsigned char *rptr,
+                               unsigned char *obuf,
+                               int isize, int osize);
+static void    z_incomp(void *state, unsigned char *ibuf, int icnt);
+static int     z_decompress(void *state, unsigned char *ibuf,
+                               int isize, unsigned char *obuf, int osize);
+static void    z_comp_reset(void *state);
+static void    z_decomp_reset(void *state);
+static void    z_comp_stats(void *state, struct compstat *stats);
+
+/**
+ *     z_comp_free - free the memory used by a compressor
+ *     @arg:   pointer to the private state for the compressor.
+ */
+static void z_comp_free(void *arg)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       if (state) {
+               zlib_deflateEnd(&state->strm);
+               vfree(state->strm.workspace);
+               kfree(state);
+       }
+}
+
+/**
+ *     z_comp_alloc - allocate space for a compressor.
+ *     @options: pointer to CCP option data
+ *     @opt_len: length of the CCP option at @options.
+ *
+ *     The @options pointer points to the a buffer containing the
+ *     CCP option data for the compression being negotiated.  It is
+ *     formatted according to RFC1979, and describes the window
+ *     size that the peer is requesting that we use in compressing
+ *     data to be sent to it.
+ *
+ *     Returns the pointer to the private state for the compressor,
+ *     or NULL if we could not allocate enough memory.
+ */
+static void *z_comp_alloc(unsigned char *options, int opt_len)
+{
+       struct ppp_deflate_state *state;
+       int w_size;
+
+       if (opt_len != CILEN_DEFLATE ||
+           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
+           options[1] != CILEN_DEFLATE ||
+           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
+           options[3] != DEFLATE_CHK_SEQUENCE)
+               return NULL;
+       w_size = DEFLATE_SIZE(options[2]);
+       if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+               return NULL;
+
+       state = kzalloc(sizeof(*state),
+                                                    GFP_KERNEL);
+       if (state == NULL)
+               return NULL;
+
+       state->strm.next_in   = NULL;
+       state->w_size         = w_size;
+       state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
+       if (state->strm.workspace == NULL)
+               goto out_free;
+
+       if (zlib_deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
+                        DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
+           != Z_OK)
+               goto out_free;
+       return (void *) state;
+
+out_free:
+       z_comp_free(state);
+       return NULL;
+}
+
+/**
+ *     z_comp_init - initialize a previously-allocated compressor.
+ *     @arg:   pointer to the private state for the compressor
+ *     @options: pointer to the CCP option data describing the
+ *             compression that was negotiated with the peer
+ *     @opt_len: length of the CCP option data at @options
+ *     @unit:  PPP unit number for diagnostic messages
+ *     @hdrlen: ignored (present for backwards compatibility)
+ *     @debug: debug flag; if non-zero, debug messages are printed.
+ *
+ *     The CCP options described by @options must match the options
+ *     specified when the compressor was allocated.  The compressor
+ *     history is reset.  Returns 0 for failure (CCP options don't
+ *     match) or 1 for success.
+ */
+static int z_comp_init(void *arg, unsigned char *options, int opt_len,
+                      int unit, int hdrlen, int debug)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       if (opt_len < CILEN_DEFLATE ||
+           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
+           options[1] != CILEN_DEFLATE ||
+           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
+           DEFLATE_SIZE(options[2]) != state->w_size ||
+           options[3] != DEFLATE_CHK_SEQUENCE)
+               return 0;
+
+       state->seqno = 0;
+       state->unit  = unit;
+       state->debug = debug;
+
+       zlib_deflateReset(&state->strm);
+
+       return 1;
+}
+
+/**
+ *     z_comp_reset - reset a previously-allocated compressor.
+ *     @arg:   pointer to private state for the compressor.
+ *
+ *     This clears the history for the compressor and makes it
+ *     ready to start emitting a new compressed stream.
+ */
+static void z_comp_reset(void *arg)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       state->seqno = 0;
+       zlib_deflateReset(&state->strm);
+}
+
+/**
+ *     z_compress - compress a PPP packet with Deflate compression.
+ *     @arg:   pointer to private state for the compressor
+ *     @rptr:  uncompressed packet (input)
+ *     @obuf:  compressed packet (output)
+ *     @isize: size of uncompressed packet
+ *     @osize: space available at @obuf
+ *
+ *     Returns the length of the compressed packet, or 0 if the
+ *     packet is incompressible.
+ */
+static int z_compress(void *arg, unsigned char *rptr, unsigned char *obuf,
+              int isize, int osize)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+       int r, proto, off, olen, oavail;
+       unsigned char *wptr;
+
+       /*
+        * Check that the protocol is in the range we handle.
+        */
+       proto = PPP_PROTOCOL(rptr);
+       if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+               return 0;
+
+       /* Don't generate compressed packets which are larger than
+          the uncompressed packet. */
+       if (osize > isize)
+               osize = isize;
+
+       wptr = obuf;
+
+       /*
+        * Copy over the PPP header and store the 2-byte sequence number.
+        */
+       wptr[0] = PPP_ADDRESS(rptr);
+       wptr[1] = PPP_CONTROL(rptr);
+       put_unaligned_be16(PPP_COMP, wptr + 2);
+       wptr += PPP_HDRLEN;
+       put_unaligned_be16(state->seqno, wptr);
+       wptr += DEFLATE_OVHD;
+       olen = PPP_HDRLEN + DEFLATE_OVHD;
+       state->strm.next_out = wptr;
+       state->strm.avail_out = oavail = osize - olen;
+       ++state->seqno;
+
+       off = (proto > 0xff) ? 2 : 3;   /* skip 1st proto byte if 0 */
+       rptr += off;
+       state->strm.next_in = rptr;
+       state->strm.avail_in = (isize - off);
+
+       for (;;) {
+               r = zlib_deflate(&state->strm, Z_PACKET_FLUSH);
+               if (r != Z_OK) {
+                       if (state->debug)
+                               printk(KERN_ERR
+                                      "z_compress: deflate returned %d\n", r);
+                       break;
+               }
+               if (state->strm.avail_out == 0) {
+                       olen += oavail;
+                       state->strm.next_out = NULL;
+                       state->strm.avail_out = oavail = 1000000;
+               } else {
+                       break;          /* all done */
+               }
+       }
+       olen += oavail - state->strm.avail_out;
+
+       /*
+        * See if we managed to reduce the size of the packet.
+        */
+       if (olen < isize) {
+               state->stats.comp_bytes += olen;
+               state->stats.comp_packets++;
+       } else {
+               state->stats.inc_bytes += isize;
+               state->stats.inc_packets++;
+               olen = 0;
+       }
+       state->stats.unc_bytes += isize;
+       state->stats.unc_packets++;
+
+       return olen;
+}
+
+/**
+ *     z_comp_stats - return compression statistics for a compressor
+ *             or decompressor.
+ *     @arg:   pointer to private space for the (de)compressor
+ *     @stats: pointer to a struct compstat to receive the result.
+ */
+static void z_comp_stats(void *arg, struct compstat *stats)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       *stats = state->stats;
+}
+
+/**
+ *     z_decomp_free - Free the memory used by a decompressor.
+ *     @arg:   pointer to private space for the decompressor.
+ */
+static void z_decomp_free(void *arg)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       if (state) {
+               zlib_inflateEnd(&state->strm);
+               vfree(state->strm.workspace);
+               kfree(state);
+       }
+}
+
+/**
+ *     z_decomp_alloc - allocate space for a decompressor.
+ *     @options: pointer to CCP option data
+ *     @opt_len: length of the CCP option at @options.
+ *
+ *     The @options pointer points to the a buffer containing the
+ *     CCP option data for the compression being negotiated.  It is
+ *     formatted according to RFC1979, and describes the window
+ *     size that we are requesting the peer to use in compressing
+ *     data to be sent to us.
+ *
+ *     Returns the pointer to the private state for the decompressor,
+ *     or NULL if we could not allocate enough memory.
+ */
+static void *z_decomp_alloc(unsigned char *options, int opt_len)
+{
+       struct ppp_deflate_state *state;
+       int w_size;
+
+       if (opt_len != CILEN_DEFLATE ||
+           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
+           options[1] != CILEN_DEFLATE ||
+           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
+           options[3] != DEFLATE_CHK_SEQUENCE)
+               return NULL;
+       w_size = DEFLATE_SIZE(options[2]);
+       if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+               return NULL;
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (state == NULL)
+               return NULL;
+
+       state->w_size         = w_size;
+       state->strm.next_out  = NULL;
+       state->strm.workspace = vmalloc(zlib_inflate_workspacesize());
+       if (state->strm.workspace == NULL)
+               goto out_free;
+
+       if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK)
+               goto out_free;
+       return (void *) state;
+
+out_free:
+       z_decomp_free(state);
+       return NULL;
+}
+
+/**
+ *     z_decomp_init - initialize a previously-allocated decompressor.
+ *     @arg:   pointer to the private state for the decompressor
+ *     @options: pointer to the CCP option data describing the
+ *             compression that was negotiated with the peer
+ *     @opt_len: length of the CCP option data at @options
+ *     @unit:  PPP unit number for diagnostic messages
+ *     @hdrlen: ignored (present for backwards compatibility)
+ *     @mru:   maximum length of decompressed packets
+ *     @debug: debug flag; if non-zero, debug messages are printed.
+ *
+ *     The CCP options described by @options must match the options
+ *     specified when the decompressor was allocated.  The decompressor
+ *     history is reset.  Returns 0 for failure (CCP options don't
+ *     match) or 1 for success.
+ */
+static int z_decomp_init(void *arg, unsigned char *options, int opt_len,
+                        int unit, int hdrlen, int mru, int debug)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       if (opt_len < CILEN_DEFLATE ||
+           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
+           options[1] != CILEN_DEFLATE ||
+           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
+           DEFLATE_SIZE(options[2]) != state->w_size ||
+           options[3] != DEFLATE_CHK_SEQUENCE)
+               return 0;
+
+       state->seqno = 0;
+       state->unit  = unit;
+       state->debug = debug;
+       state->mru   = mru;
+
+       zlib_inflateReset(&state->strm);
+
+       return 1;
+}
+
+/**
+ *     z_decomp_reset - reset a previously-allocated decompressor.
+ *     @arg:   pointer to private state for the decompressor.
+ *
+ *     This clears the history for the decompressor and makes it
+ *     ready to receive a new compressed stream.
+ */
+static void z_decomp_reset(void *arg)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+
+       state->seqno = 0;
+       zlib_inflateReset(&state->strm);
+}
+
+/**
+ *     z_decompress - decompress a Deflate-compressed packet.
+ *     @arg:   pointer to private state for the decompressor
+ *     @ibuf:  pointer to input (compressed) packet data
+ *     @isize: length of input packet
+ *     @obuf:  pointer to space for output (decompressed) packet
+ *     @osize: amount of space available at @obuf
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+static int z_decompress(void *arg, unsigned char *ibuf, int isize,
+                unsigned char *obuf, int osize)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+       int olen, seq, r;
+       int decode_proto, overflow;
+       unsigned char overflow_buf[1];
+
+       if (isize <= PPP_HDRLEN + DEFLATE_OVHD) {
+               if (state->debug)
+                       printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",
+                              state->unit, isize);
+               return DECOMP_ERROR;
+       }
+
+       /* Check the sequence number. */
+       seq = get_unaligned_be16(ibuf + PPP_HDRLEN);
+       if (seq != (state->seqno & 0xffff)) {
+               if (state->debug)
+                       printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",
+                              state->unit, seq, state->seqno & 0xffff);
+               return DECOMP_ERROR;
+       }
+       ++state->seqno;
+
+       /*
+        * Fill in the first part of the PPP header.  The protocol field
+        * comes from the decompressed data.
+        */
+       obuf[0] = PPP_ADDRESS(ibuf);
+       obuf[1] = PPP_CONTROL(ibuf);
+       obuf[2] = 0;
+
+       /*
+        * Set up to call inflate.  We set avail_out to 1 initially so we can
+        * look at the first byte of the output and decide whether we have
+        * a 1-byte or 2-byte protocol field.
+        */
+       state->strm.next_in = ibuf + PPP_HDRLEN + DEFLATE_OVHD;
+       state->strm.avail_in = isize - (PPP_HDRLEN + DEFLATE_OVHD);
+       state->strm.next_out = obuf + 3;
+       state->strm.avail_out = 1;
+       decode_proto = 1;
+       overflow = 0;
+
+       /*
+        * Call inflate, supplying more input or output as needed.
+        */
+       for (;;) {
+               r = zlib_inflate(&state->strm, Z_PACKET_FLUSH);
+               if (r != Z_OK) {
+                       if (state->debug)
+                               printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",
+                                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
+                       return DECOMP_FATALERROR;
+               }
+               if (state->strm.avail_out != 0)
+                       break;          /* all done */
+               if (decode_proto) {
+                       state->strm.avail_out = osize - PPP_HDRLEN;
+                       if ((obuf[3] & 1) == 0) {
+                               /* 2-byte protocol field */
+                               obuf[2] = obuf[3];
+                               --state->strm.next_out;
+                               ++state->strm.avail_out;
+                       }
+                       decode_proto = 0;
+               } else if (!overflow) {
+                       /*
+                        * We've filled up the output buffer; the only way to
+                        * find out whether inflate has any more characters
+                        * left is to give it another byte of output space.
+                        */
+                       state->strm.next_out = overflow_buf;
+                       state->strm.avail_out = 1;
+                       overflow = 1;
+               } else {
+                       if (state->debug)
+                               printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",
+                                      state->unit);
+                       return DECOMP_FATALERROR;
+               }
+       }
+
+       if (decode_proto) {
+               if (state->debug)
+                       printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",
+                              state->unit);
+               return DECOMP_ERROR;
+       }
+
+       olen = osize + overflow - state->strm.avail_out;
+       state->stats.unc_bytes += olen;
+       state->stats.unc_packets++;
+       state->stats.comp_bytes += isize;
+       state->stats.comp_packets++;
+
+       return olen;
+}
+
+/**
+ *     z_incomp - add incompressible input data to the history.
+ *     @arg:   pointer to private state for the decompressor
+ *     @ibuf:  pointer to input packet data
+ *     @icnt:  length of input data.
+ */
+static void z_incomp(void *arg, unsigned char *ibuf, int icnt)
+{
+       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
+       int proto, r;
+
+       /*
+        * Check that the protocol is one we handle.
+        */
+       proto = PPP_PROTOCOL(ibuf);
+       if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+               return;
+
+       ++state->seqno;
+
+       /*
+        * We start at the either the 1st or 2nd byte of the protocol field,
+        * depending on whether the protocol value is compressible.
+        */
+       state->strm.next_in = ibuf + 3;
+       state->strm.avail_in = icnt - 3;
+       if (proto > 0xff) {
+               --state->strm.next_in;
+               ++state->strm.avail_in;
+       }
+
+       r = zlib_inflateIncomp(&state->strm);
+       if (r != Z_OK) {
+               /* gak! */
+               if (state->debug) {
+                       printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",
+                              state->unit, r, (state->strm.msg? state->strm.msg: ""));
+               }
+               return;
+       }
+
+       /*
+        * Update stats.
+        */
+       state->stats.inc_bytes += icnt;
+       state->stats.inc_packets++;
+       state->stats.unc_bytes += icnt;
+       state->stats.unc_packets++;
+}
+
+/*************************************************************
+ * Module interface table
+ *************************************************************/
+
+/* These are in ppp_generic.c */
+extern int  ppp_register_compressor   (struct compressor *cp);
+extern void ppp_unregister_compressor (struct compressor *cp);
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+static struct compressor ppp_deflate = {
+       .compress_proto =       CI_DEFLATE,
+       .comp_alloc =           z_comp_alloc,
+       .comp_free =            z_comp_free,
+       .comp_init =            z_comp_init,
+       .comp_reset =           z_comp_reset,
+       .compress =             z_compress,
+       .comp_stat =            z_comp_stats,
+       .decomp_alloc =         z_decomp_alloc,
+       .decomp_free =          z_decomp_free,
+       .decomp_init =          z_decomp_init,
+       .decomp_reset =         z_decomp_reset,
+       .decompress =           z_decompress,
+       .incomp =               z_incomp,
+       .decomp_stat =          z_comp_stats,
+       .owner =                THIS_MODULE
+};
+
+static struct compressor ppp_deflate_draft = {
+       .compress_proto =       CI_DEFLATE_DRAFT,
+       .comp_alloc =           z_comp_alloc,
+       .comp_free =            z_comp_free,
+       .comp_init =            z_comp_init,
+       .comp_reset =           z_comp_reset,
+       .compress =             z_compress,
+       .comp_stat =            z_comp_stats,
+       .decomp_alloc =         z_decomp_alloc,
+       .decomp_free =          z_decomp_free,
+       .decomp_init =          z_decomp_init,
+       .decomp_reset =         z_decomp_reset,
+       .decompress =           z_decompress,
+       .incomp =               z_incomp,
+       .decomp_stat =          z_comp_stats,
+       .owner =                THIS_MODULE
+};
+
+static int __init deflate_init(void)
+{
+        int answer = ppp_register_compressor(&ppp_deflate);
+        if (answer == 0)
+                printk(KERN_INFO
+                      "PPP Deflate Compression module registered\n");
+       ppp_register_compressor(&ppp_deflate_draft);
+        return answer;
+}
+
+static void __exit deflate_cleanup(void)
+{
+       ppp_unregister_compressor(&ppp_deflate);
+       ppp_unregister_compressor(&ppp_deflate_draft);
+}
+
+module_init(deflate_init);
+module_exit(deflate_cleanup);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));
+MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
new file mode 100644 (file)
index 0000000..10e5d98
--- /dev/null
@@ -0,0 +1,2954 @@
+/*
+ * Generic PPP layer for Linux.
+ *
+ * Copyright 1999-2002 Paul Mackerras.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ * The generic PPP layer handles the PPP network interfaces, the
+ * /dev/ppp device, packet and VJ compression, and multilink.
+ * It talks to PPP `channels' via the interface defined in
+ * include/linux/ppp_channel.h.  Channels provide the basic means for
+ * sending and receiving PPP frames on some kind of communications
+ * channel.
+ *
+ * Part of the code in this driver was inspired by the old async-only
+ * PPP driver, written by Michael Callahan and Al Longyear, and
+ * subsequently hacked by Paul Mackerras.
+ *
+ * ==FILEVERSION 20041108==
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/idr.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/ppp_defs.h>
+#include <linux/filter.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp-comp.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/spinlock.h>
+#include <linux/rwsem.h>
+#include <linux/stddef.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <net/slhc_vj.h>
+#include <linux/atomic.h>
+
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+#define PPP_VERSION    "2.4.2"
+
+/*
+ * Network protocols we support.
+ */
+#define NP_IP  0               /* Internet Protocol V4 */
+#define NP_IPV6        1               /* Internet Protocol V6 */
+#define NP_IPX 2               /* IPX protocol */
+#define NP_AT  3               /* Appletalk protocol */
+#define NP_MPLS_UC 4           /* MPLS unicast */
+#define NP_MPLS_MC 5           /* MPLS multicast */
+#define NUM_NP 6               /* Number of NPs. */
+
+#define MPHDRLEN       6       /* multilink protocol header length */
+#define MPHDRLEN_SSN   4       /* ditto with short sequence numbers */
+
+/*
+ * An instance of /dev/ppp can be associated with either a ppp
+ * interface unit or a ppp channel.  In both cases, file->private_data
+ * points to one of these.
+ */
+struct ppp_file {
+       enum {
+               INTERFACE=1, CHANNEL
+       }               kind;
+       struct sk_buff_head xq;         /* pppd transmit queue */
+       struct sk_buff_head rq;         /* receive queue for pppd */
+       wait_queue_head_t rwait;        /* for poll on reading /dev/ppp */
+       atomic_t        refcnt;         /* # refs (incl /dev/ppp attached) */
+       int             hdrlen;         /* space to leave for headers */
+       int             index;          /* interface unit / channel number */
+       int             dead;           /* unit/channel has been shut down */
+};
+
+#define PF_TO_X(pf, X)         container_of(pf, X, file)
+
+#define PF_TO_PPP(pf)          PF_TO_X(pf, struct ppp)
+#define PF_TO_CHANNEL(pf)      PF_TO_X(pf, struct channel)
+
+/*
+ * Data structure describing one ppp unit.
+ * A ppp unit corresponds to a ppp network interface device
+ * and represents a multilink bundle.
+ * It can have 0 or more ppp channels connected to it.
+ */
+struct ppp {
+       struct ppp_file file;           /* stuff for read/write/poll 0 */
+       struct file     *owner;         /* file that owns this unit 48 */
+       struct list_head channels;      /* list of attached channels 4c */
+       int             n_channels;     /* how many channels are attached 54 */
+       spinlock_t      rlock;          /* lock for receive side 58 */
+       spinlock_t      wlock;          /* lock for transmit side 5c */
+       int             mru;            /* max receive unit 60 */
+       unsigned int    flags;          /* control bits 64 */
+       unsigned int    xstate;         /* transmit state bits 68 */
+       unsigned int    rstate;         /* receive state bits 6c */
+       int             debug;          /* debug flags 70 */
+       struct slcompress *vj;          /* state for VJ header compression */
+       enum NPmode     npmode[NUM_NP]; /* what to do with each net proto 78 */
+       struct sk_buff  *xmit_pending;  /* a packet ready to go out 88 */
+       struct compressor *xcomp;       /* transmit packet compressor 8c */
+       void            *xc_state;      /* its internal state 90 */
+       struct compressor *rcomp;       /* receive decompressor 94 */
+       void            *rc_state;      /* its internal state 98 */
+       unsigned long   last_xmit;      /* jiffies when last pkt sent 9c */
+       unsigned long   last_recv;      /* jiffies when last pkt rcvd a0 */
+       struct net_device *dev;         /* network interface device a4 */
+       int             closing;        /* is device closing down? a8 */
+#ifdef CONFIG_PPP_MULTILINK
+       int             nxchan;         /* next channel to send something on */
+       u32             nxseq;          /* next sequence number to send */
+       int             mrru;           /* MP: max reconst. receive unit */
+       u32             nextseq;        /* MP: seq no of next packet */
+       u32             minseq;         /* MP: min of most recent seqnos */
+       struct sk_buff_head mrq;        /* MP: receive reconstruction queue */
+#endif /* CONFIG_PPP_MULTILINK */
+#ifdef CONFIG_PPP_FILTER
+       struct sock_filter *pass_filter;        /* filter for packets to pass */
+       struct sock_filter *active_filter;/* filter for pkts to reset idle */
+       unsigned pass_len, active_len;
+#endif /* CONFIG_PPP_FILTER */
+       struct net      *ppp_net;       /* the net we belong to */
+};
+
+/*
+ * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC,
+ * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP,
+ * SC_MUST_COMP
+ * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR.
+ * Bits in xstate: SC_COMP_RUN
+ */
+#define SC_FLAG_BITS   (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \
+                        |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \
+                        |SC_COMP_TCP|SC_REJ_COMP_TCP|SC_MUST_COMP)
+
+/*
+ * Private data structure for each channel.
+ * This includes the data structure used for multilink.
+ */
+struct channel {
+       struct ppp_file file;           /* stuff for read/write/poll */
+       struct list_head list;          /* link in all/new_channels list */
+       struct ppp_channel *chan;       /* public channel data structure */
+       struct rw_semaphore chan_sem;   /* protects `chan' during chan ioctl */
+       spinlock_t      downl;          /* protects `chan', file.xq dequeue */
+       struct ppp      *ppp;           /* ppp unit we're connected to */
+       struct net      *chan_net;      /* the net channel belongs to */
+       struct list_head clist;         /* link in list of channels per unit */
+       rwlock_t        upl;            /* protects `ppp' */
+#ifdef CONFIG_PPP_MULTILINK
+       u8              avail;          /* flag used in multilink stuff */
+       u8              had_frag;       /* >= 1 fragments have been sent */
+       u32             lastseq;        /* MP: last sequence # received */
+       int             speed;          /* speed of the corresponding ppp channel*/
+#endif /* CONFIG_PPP_MULTILINK */
+};
+
+/*
+ * SMP locking issues:
+ * Both the ppp.rlock and ppp.wlock locks protect the ppp.channels
+ * list and the ppp.n_channels field, you need to take both locks
+ * before you modify them.
+ * The lock ordering is: channel.upl -> ppp.wlock -> ppp.rlock ->
+ * channel.downl.
+ */
+
+static DEFINE_MUTEX(ppp_mutex);
+static atomic_t ppp_unit_count = ATOMIC_INIT(0);
+static atomic_t channel_count = ATOMIC_INIT(0);
+
+/* per-net private data for this module */
+static int ppp_net_id __read_mostly;
+struct ppp_net {
+       /* units to ppp mapping */
+       struct idr units_idr;
+
+       /*
+        * all_ppp_mutex protects the units_idr mapping.
+        * It also ensures that finding a ppp unit in the units_idr
+        * map and updating its file.refcnt field is atomic.
+        */
+       struct mutex all_ppp_mutex;
+
+       /* channels */
+       struct list_head all_channels;
+       struct list_head new_channels;
+       int last_channel_index;
+
+       /*
+        * all_channels_lock protects all_channels and
+        * last_channel_index, and the atomicity of find
+        * a channel and updating its file.refcnt field.
+        */
+       spinlock_t all_channels_lock;
+};
+
+/* Get the PPP protocol number from a skb */
+#define PPP_PROTO(skb) get_unaligned_be16((skb)->data)
+
+/* We limit the length of ppp->file.rq to this (arbitrary) value */
+#define PPP_MAX_RQLEN  32
+
+/*
+ * Maximum number of multilink fragments queued up.
+ * This has to be large enough to cope with the maximum latency of
+ * the slowest channel relative to the others.  Strictly it should
+ * depend on the number of channels and their characteristics.
+ */
+#define PPP_MP_MAX_QLEN        128
+
+/* Multilink header bits. */
+#define B      0x80            /* this fragment begins a packet */
+#define E      0x40            /* this fragment ends a packet */
+
+/* Compare multilink sequence numbers (assumed to be 32 bits wide) */
+#define seq_before(a, b)       ((s32)((a) - (b)) < 0)
+#define seq_after(a, b)                ((s32)((a) - (b)) > 0)
+
+/* Prototypes. */
+static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
+                       struct file *file, unsigned int cmd, unsigned long arg);
+static void ppp_xmit_process(struct ppp *ppp);
+static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
+static void ppp_push(struct ppp *ppp);
+static void ppp_channel_push(struct channel *pch);
+static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb,
+                             struct channel *pch);
+static void ppp_receive_error(struct ppp *ppp);
+static void ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb);
+static struct sk_buff *ppp_decompress_frame(struct ppp *ppp,
+                                           struct sk_buff *skb);
+#ifdef CONFIG_PPP_MULTILINK
+static void ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb,
+                               struct channel *pch);
+static void ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb);
+static struct sk_buff *ppp_mp_reconstruct(struct ppp *ppp);
+static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb);
+#endif /* CONFIG_PPP_MULTILINK */
+static int ppp_set_compress(struct ppp *ppp, unsigned long arg);
+static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
+static void ppp_ccp_closed(struct ppp *ppp);
+static struct compressor *find_compressor(int type);
+static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
+static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
+static void init_ppp_file(struct ppp_file *pf, int kind);
+static void ppp_shutdown_interface(struct ppp *ppp);
+static void ppp_destroy_interface(struct ppp *ppp);
+static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
+static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
+static int ppp_connect_channel(struct channel *pch, int unit);
+static int ppp_disconnect_channel(struct channel *pch);
+static void ppp_destroy_channel(struct channel *pch);
+static int unit_get(struct idr *p, void *ptr);
+static int unit_set(struct idr *p, void *ptr, int n);
+static void unit_put(struct idr *p, int n);
+static void *unit_find(struct idr *p, int n);
+
+static struct class *ppp_class;
+
+/* per net-namespace data */
+static inline struct ppp_net *ppp_pernet(struct net *net)
+{
+       BUG_ON(!net);
+
+       return net_generic(net, ppp_net_id);
+}
+
+/* Translates a PPP protocol number to a NP index (NP == network protocol) */
+static inline int proto_to_npindex(int proto)
+{
+       switch (proto) {
+       case PPP_IP:
+               return NP_IP;
+       case PPP_IPV6:
+               return NP_IPV6;
+       case PPP_IPX:
+               return NP_IPX;
+       case PPP_AT:
+               return NP_AT;
+       case PPP_MPLS_UC:
+               return NP_MPLS_UC;
+       case PPP_MPLS_MC:
+               return NP_MPLS_MC;
+       }
+       return -EINVAL;
+}
+
+/* Translates an NP index into a PPP protocol number */
+static const int npindex_to_proto[NUM_NP] = {
+       PPP_IP,
+       PPP_IPV6,
+       PPP_IPX,
+       PPP_AT,
+       PPP_MPLS_UC,
+       PPP_MPLS_MC,
+};
+
+/* Translates an ethertype into an NP index */
+static inline int ethertype_to_npindex(int ethertype)
+{
+       switch (ethertype) {
+       case ETH_P_IP:
+               return NP_IP;
+       case ETH_P_IPV6:
+               return NP_IPV6;
+       case ETH_P_IPX:
+               return NP_IPX;
+       case ETH_P_PPPTALK:
+       case ETH_P_ATALK:
+               return NP_AT;
+       case ETH_P_MPLS_UC:
+               return NP_MPLS_UC;
+       case ETH_P_MPLS_MC:
+               return NP_MPLS_MC;
+       }
+       return -1;
+}
+
+/* Translates an NP index into an ethertype */
+static const int npindex_to_ethertype[NUM_NP] = {
+       ETH_P_IP,
+       ETH_P_IPV6,
+       ETH_P_IPX,
+       ETH_P_PPPTALK,
+       ETH_P_MPLS_UC,
+       ETH_P_MPLS_MC,
+};
+
+/*
+ * Locking shorthand.
+ */
+#define ppp_xmit_lock(ppp)     spin_lock_bh(&(ppp)->wlock)
+#define ppp_xmit_unlock(ppp)   spin_unlock_bh(&(ppp)->wlock)
+#define ppp_recv_lock(ppp)     spin_lock_bh(&(ppp)->rlock)
+#define ppp_recv_unlock(ppp)   spin_unlock_bh(&(ppp)->rlock)
+#define ppp_lock(ppp)          do { ppp_xmit_lock(ppp); \
+                                    ppp_recv_lock(ppp); } while (0)
+#define ppp_unlock(ppp)                do { ppp_recv_unlock(ppp); \
+                                    ppp_xmit_unlock(ppp); } while (0)
+
+/*
+ * /dev/ppp device routines.
+ * The /dev/ppp device is used by pppd to control the ppp unit.
+ * It supports the read, write, ioctl and poll functions.
+ * Open instances of /dev/ppp can be in one of three states:
+ * unattached, attached to a ppp unit, or attached to a ppp channel.
+ */
+static int ppp_open(struct inode *inode, struct file *file)
+{
+       /*
+        * This could (should?) be enforced by the permissions on /dev/ppp.
+        */
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+       return 0;
+}
+
+static int ppp_release(struct inode *unused, struct file *file)
+{
+       struct ppp_file *pf = file->private_data;
+       struct ppp *ppp;
+
+       if (pf) {
+               file->private_data = NULL;
+               if (pf->kind == INTERFACE) {
+                       ppp = PF_TO_PPP(pf);
+                       if (file == ppp->owner)
+                               ppp_shutdown_interface(ppp);
+               }
+               if (atomic_dec_and_test(&pf->refcnt)) {
+                       switch (pf->kind) {
+                       case INTERFACE:
+                               ppp_destroy_interface(PF_TO_PPP(pf));
+                               break;
+                       case CHANNEL:
+                               ppp_destroy_channel(PF_TO_CHANNEL(pf));
+                               break;
+                       }
+               }
+       }
+       return 0;
+}
+
+static ssize_t ppp_read(struct file *file, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct ppp_file *pf = file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
+       ssize_t ret;
+       struct sk_buff *skb = NULL;
+       struct iovec iov;
+
+       ret = count;
+
+       if (!pf)
+               return -ENXIO;
+       add_wait_queue(&pf->rwait, &wait);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               skb = skb_dequeue(&pf->rq);
+               if (skb)
+                       break;
+               ret = 0;
+               if (pf->dead)
+                       break;
+               if (pf->kind == INTERFACE) {
+                       /*
+                        * Return 0 (EOF) on an interface that has no
+                        * channels connected, unless it is looping
+                        * network traffic (demand mode).
+                        */
+                       struct ppp *ppp = PF_TO_PPP(pf);
+                       if (ppp->n_channels == 0 &&
+                           (ppp->flags & SC_LOOP_TRAFFIC) == 0)
+                               break;
+               }
+               ret = -EAGAIN;
+               if (file->f_flags & O_NONBLOCK)
+                       break;
+               ret = -ERESTARTSYS;
+               if (signal_pending(current))
+                       break;
+               schedule();
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&pf->rwait, &wait);
+
+       if (!skb)
+               goto out;
+
+       ret = -EOVERFLOW;
+       if (skb->len > count)
+               goto outf;
+       ret = -EFAULT;
+       iov.iov_base = buf;
+       iov.iov_len = count;
+       if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len))
+               goto outf;
+       ret = skb->len;
+
+ outf:
+       kfree_skb(skb);
+ out:
+       return ret;
+}
+
+static ssize_t ppp_write(struct file *file, const char __user *buf,
+                        size_t count, loff_t *ppos)
+{
+       struct ppp_file *pf = file->private_data;
+       struct sk_buff *skb;
+       ssize_t ret;
+
+       if (!pf)
+               return -ENXIO;
+       ret = -ENOMEM;
+       skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
+       if (!skb)
+               goto out;
+       skb_reserve(skb, pf->hdrlen);
+       ret = -EFAULT;
+       if (copy_from_user(skb_put(skb, count), buf, count)) {
+               kfree_skb(skb);
+               goto out;
+       }
+
+       skb_queue_tail(&pf->xq, skb);
+
+       switch (pf->kind) {
+       case INTERFACE:
+               ppp_xmit_process(PF_TO_PPP(pf));
+               break;
+       case CHANNEL:
+               ppp_channel_push(PF_TO_CHANNEL(pf));
+               break;
+       }
+
+       ret = count;
+
+ out:
+       return ret;
+}
+
+/* No kernel lock - fine */
+static unsigned int ppp_poll(struct file *file, poll_table *wait)
+{
+       struct ppp_file *pf = file->private_data;
+       unsigned int mask;
+
+       if (!pf)
+               return 0;
+       poll_wait(file, &pf->rwait, wait);
+       mask = POLLOUT | POLLWRNORM;
+       if (skb_peek(&pf->rq))
+               mask |= POLLIN | POLLRDNORM;
+       if (pf->dead)
+               mask |= POLLHUP;
+       else if (pf->kind == INTERFACE) {
+               /* see comment in ppp_read */
+               struct ppp *ppp = PF_TO_PPP(pf);
+               if (ppp->n_channels == 0 &&
+                   (ppp->flags & SC_LOOP_TRAFFIC) == 0)
+                       mask |= POLLIN | POLLRDNORM;
+       }
+
+       return mask;
+}
+
+#ifdef CONFIG_PPP_FILTER
+static int get_filter(void __user *arg, struct sock_filter **p)
+{
+       struct sock_fprog uprog;
+       struct sock_filter *code = NULL;
+       int len, err;
+
+       if (copy_from_user(&uprog, arg, sizeof(uprog)))
+               return -EFAULT;
+
+       if (!uprog.len) {
+               *p = NULL;
+               return 0;
+       }
+
+       len = uprog.len * sizeof(struct sock_filter);
+       code = memdup_user(uprog.filter, len);
+       if (IS_ERR(code))
+               return PTR_ERR(code);
+
+       err = sk_chk_filter(code, uprog.len);
+       if (err) {
+               kfree(code);
+               return err;
+       }
+
+       *p = code;
+       return uprog.len;
+}
+#endif /* CONFIG_PPP_FILTER */
+
+static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct ppp_file *pf = file->private_data;
+       struct ppp *ppp;
+       int err = -EFAULT, val, val2, i;
+       struct ppp_idle idle;
+       struct npioctl npi;
+       int unit, cflags;
+       struct slcompress *vj;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+
+       if (!pf)
+               return ppp_unattached_ioctl(current->nsproxy->net_ns,
+                                       pf, file, cmd, arg);
+
+       if (cmd == PPPIOCDETACH) {
+               /*
+                * We have to be careful here... if the file descriptor
+                * has been dup'd, we could have another process in the
+                * middle of a poll using the same file *, so we had
+                * better not free the interface data structures -
+                * instead we fail the ioctl.  Even in this case, we
+                * shut down the interface if we are the owner of it.
+                * Actually, we should get rid of PPPIOCDETACH, userland
+                * (i.e. pppd) could achieve the same effect by closing
+                * this fd and reopening /dev/ppp.
+                */
+               err = -EINVAL;
+               mutex_lock(&ppp_mutex);
+               if (pf->kind == INTERFACE) {
+                       ppp = PF_TO_PPP(pf);
+                       if (file == ppp->owner)
+                               ppp_shutdown_interface(ppp);
+               }
+               if (atomic_long_read(&file->f_count) <= 2) {
+                       ppp_release(NULL, file);
+                       err = 0;
+               } else
+                       pr_warn("PPPIOCDETACH file->f_count=%ld\n",
+                               atomic_long_read(&file->f_count));
+               mutex_unlock(&ppp_mutex);
+               return err;
+       }
+
+       if (pf->kind == CHANNEL) {
+               struct channel *pch;
+               struct ppp_channel *chan;
+
+               mutex_lock(&ppp_mutex);
+               pch = PF_TO_CHANNEL(pf);
+
+               switch (cmd) {
+               case PPPIOCCONNECT:
+                       if (get_user(unit, p))
+                               break;
+                       err = ppp_connect_channel(pch, unit);
+                       break;
+
+               case PPPIOCDISCONN:
+                       err = ppp_disconnect_channel(pch);
+                       break;
+
+               default:
+                       down_read(&pch->chan_sem);
+                       chan = pch->chan;
+                       err = -ENOTTY;
+                       if (chan && chan->ops->ioctl)
+                               err = chan->ops->ioctl(chan, cmd, arg);
+                       up_read(&pch->chan_sem);
+               }
+               mutex_unlock(&ppp_mutex);
+               return err;
+       }
+
+       if (pf->kind != INTERFACE) {
+               /* can't happen */
+               pr_err("PPP: not interface or channel??\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&ppp_mutex);
+       ppp = PF_TO_PPP(pf);
+       switch (cmd) {
+       case PPPIOCSMRU:
+               if (get_user(val, p))
+                       break;
+               ppp->mru = val;
+               err = 0;
+               break;
+
+       case PPPIOCSFLAGS:
+               if (get_user(val, p))
+                       break;
+               ppp_lock(ppp);
+               cflags = ppp->flags & ~val;
+               ppp->flags = val & SC_FLAG_BITS;
+               ppp_unlock(ppp);
+               if (cflags & SC_CCP_OPEN)
+                       ppp_ccp_closed(ppp);
+               err = 0;
+               break;
+
+       case PPPIOCGFLAGS:
+               val = ppp->flags | ppp->xstate | ppp->rstate;
+               if (put_user(val, p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCSCOMPRESS:
+               err = ppp_set_compress(ppp, arg);
+               break;
+
+       case PPPIOCGUNIT:
+               if (put_user(ppp->file.index, p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCSDEBUG:
+               if (get_user(val, p))
+                       break;
+               ppp->debug = val;
+               err = 0;
+               break;
+
+       case PPPIOCGDEBUG:
+               if (put_user(ppp->debug, p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGIDLE:
+               idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
+               idle.recv_idle = (jiffies - ppp->last_recv) / HZ;
+               if (copy_to_user(argp, &idle, sizeof(idle)))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCSMAXCID:
+               if (get_user(val, p))
+                       break;
+               val2 = 15;
+               if ((val >> 16) != 0) {
+                       val2 = val >> 16;
+                       val &= 0xffff;
+               }
+               vj = slhc_init(val2+1, val+1);
+               if (!vj) {
+                       netdev_err(ppp->dev,
+                                  "PPP: no memory (VJ compressor)\n");
+                       err = -ENOMEM;
+                       break;
+               }
+               ppp_lock(ppp);
+               if (ppp->vj)
+                       slhc_free(ppp->vj);
+               ppp->vj = vj;
+               ppp_unlock(ppp);
+               err = 0;
+               break;
+
+       case PPPIOCGNPMODE:
+       case PPPIOCSNPMODE:
+               if (copy_from_user(&npi, argp, sizeof(npi)))
+                       break;
+               err = proto_to_npindex(npi.protocol);
+               if (err < 0)
+                       break;
+               i = err;
+               if (cmd == PPPIOCGNPMODE) {
+                       err = -EFAULT;
+                       npi.mode = ppp->npmode[i];
+                       if (copy_to_user(argp, &npi, sizeof(npi)))
+                               break;
+               } else {
+                       ppp->npmode[i] = npi.mode;
+                       /* we may be able to transmit more packets now (??) */
+                       netif_wake_queue(ppp->dev);
+               }
+               err = 0;
+               break;
+
+#ifdef CONFIG_PPP_FILTER
+       case PPPIOCSPASS:
+       {
+               struct sock_filter *code;
+               err = get_filter(argp, &code);
+               if (err >= 0) {
+                       ppp_lock(ppp);
+                       kfree(ppp->pass_filter);
+                       ppp->pass_filter = code;
+                       ppp->pass_len = err;
+                       ppp_unlock(ppp);
+                       err = 0;
+               }
+               break;
+       }
+       case PPPIOCSACTIVE:
+       {
+               struct sock_filter *code;
+               err = get_filter(argp, &code);
+               if (err >= 0) {
+                       ppp_lock(ppp);
+                       kfree(ppp->active_filter);
+                       ppp->active_filter = code;
+                       ppp->active_len = err;
+                       ppp_unlock(ppp);
+                       err = 0;
+               }
+               break;
+       }
+#endif /* CONFIG_PPP_FILTER */
+
+#ifdef CONFIG_PPP_MULTILINK
+       case PPPIOCSMRRU:
+               if (get_user(val, p))
+                       break;
+               ppp_recv_lock(ppp);
+               ppp->mrru = val;
+               ppp_recv_unlock(ppp);
+               err = 0;
+               break;
+#endif /* CONFIG_PPP_MULTILINK */
+
+       default:
+               err = -ENOTTY;
+       }
+       mutex_unlock(&ppp_mutex);
+       return err;
+}
+
+static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
+                       struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int unit, err = -EFAULT;
+       struct ppp *ppp;
+       struct channel *chan;
+       struct ppp_net *pn;
+       int __user *p = (int __user *)arg;
+
+       mutex_lock(&ppp_mutex);
+       switch (cmd) {
+       case PPPIOCNEWUNIT:
+               /* Create a new ppp unit */
+               if (get_user(unit, p))
+                       break;
+               ppp = ppp_create_interface(net, unit, &err);
+               if (!ppp)
+                       break;
+               file->private_data = &ppp->file;
+               ppp->owner = file;
+               err = -EFAULT;
+               if (put_user(ppp->file.index, p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCATTACH:
+               /* Attach to an existing ppp unit */
+               if (get_user(unit, p))
+                       break;
+               err = -ENXIO;
+               pn = ppp_pernet(net);
+               mutex_lock(&pn->all_ppp_mutex);
+               ppp = ppp_find_unit(pn, unit);
+               if (ppp) {
+                       atomic_inc(&ppp->file.refcnt);
+                       file->private_data = &ppp->file;
+                       err = 0;
+               }
+               mutex_unlock(&pn->all_ppp_mutex);
+               break;
+
+       case PPPIOCATTCHAN:
+               if (get_user(unit, p))
+                       break;
+               err = -ENXIO;
+               pn = ppp_pernet(net);
+               spin_lock_bh(&pn->all_channels_lock);
+               chan = ppp_find_channel(pn, unit);
+               if (chan) {
+                       atomic_inc(&chan->file.refcnt);
+                       file->private_data = &chan->file;
+                       err = 0;
+               }
+               spin_unlock_bh(&pn->all_channels_lock);
+               break;
+
+       default:
+               err = -ENOTTY;
+       }
+       mutex_unlock(&ppp_mutex);
+       return err;
+}
+
+static const struct file_operations ppp_device_fops = {
+       .owner          = THIS_MODULE,
+       .read           = ppp_read,
+       .write          = ppp_write,
+       .poll           = ppp_poll,
+       .unlocked_ioctl = ppp_ioctl,
+       .open           = ppp_open,
+       .release        = ppp_release,
+       .llseek         = noop_llseek,
+};
+
+static __net_init int ppp_init_net(struct net *net)
+{
+       struct ppp_net *pn = net_generic(net, ppp_net_id);
+
+       idr_init(&pn->units_idr);
+       mutex_init(&pn->all_ppp_mutex);
+
+       INIT_LIST_HEAD(&pn->all_channels);
+       INIT_LIST_HEAD(&pn->new_channels);
+
+       spin_lock_init(&pn->all_channels_lock);
+
+       return 0;
+}
+
+static __net_exit void ppp_exit_net(struct net *net)
+{
+       struct ppp_net *pn = net_generic(net, ppp_net_id);
+
+       idr_destroy(&pn->units_idr);
+}
+
+static struct pernet_operations ppp_net_ops = {
+       .init = ppp_init_net,
+       .exit = ppp_exit_net,
+       .id   = &ppp_net_id,
+       .size = sizeof(struct ppp_net),
+};
+
+#define PPP_MAJOR      108
+
+/* Called at boot time if ppp is compiled into the kernel,
+   or at module load time (from init_module) if compiled as a module. */
+static int __init ppp_init(void)
+{
+       int err;
+
+       pr_info("PPP generic driver version " PPP_VERSION "\n");
+
+       err = register_pernet_device(&ppp_net_ops);
+       if (err) {
+               pr_err("failed to register PPP pernet device (%d)\n", err);
+               goto out;
+       }
+
+       err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
+       if (err) {
+               pr_err("failed to register PPP device (%d)\n", err);
+               goto out_net;
+       }
+
+       ppp_class = class_create(THIS_MODULE, "ppp");
+       if (IS_ERR(ppp_class)) {
+               err = PTR_ERR(ppp_class);
+               goto out_chrdev;
+       }
+
+       /* not a big deal if we fail here :-) */
+       device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+
+       return 0;
+
+out_chrdev:
+       unregister_chrdev(PPP_MAJOR, "ppp");
+out_net:
+       unregister_pernet_device(&ppp_net_ops);
+out:
+       return err;
+}
+
+/*
+ * Network interface unit routines.
+ */
+static netdev_tx_t
+ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ppp *ppp = netdev_priv(dev);
+       int npi, proto;
+       unsigned char *pp;
+
+       npi = ethertype_to_npindex(ntohs(skb->protocol));
+       if (npi < 0)
+               goto outf;
+
+       /* Drop, accept or reject the packet */
+       switch (ppp->npmode[npi]) {
+       case NPMODE_PASS:
+               break;
+       case NPMODE_QUEUE:
+               /* it would be nice to have a way to tell the network
+                  system to queue this one up for later. */
+               goto outf;
+       case NPMODE_DROP:
+       case NPMODE_ERROR:
+               goto outf;
+       }
+
+       /* Put the 2-byte PPP protocol number on the front,
+          making sure there is room for the address and control fields. */
+       if (skb_cow_head(skb, PPP_HDRLEN))
+               goto outf;
+
+       pp = skb_push(skb, 2);
+       proto = npindex_to_proto[npi];
+       put_unaligned_be16(proto, pp);
+
+       netif_stop_queue(dev);
+       skb_queue_tail(&ppp->file.xq, skb);
+       ppp_xmit_process(ppp);
+       return NETDEV_TX_OK;
+
+ outf:
+       kfree_skb(skb);
+       ++dev->stats.tx_dropped;
+       return NETDEV_TX_OK;
+}
+
+static int
+ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       struct ppp *ppp = netdev_priv(dev);
+       int err = -EFAULT;
+       void __user *addr = (void __user *) ifr->ifr_ifru.ifru_data;
+       struct ppp_stats stats;
+       struct ppp_comp_stats cstats;
+       char *vers;
+
+       switch (cmd) {
+       case SIOCGPPPSTATS:
+               ppp_get_stats(ppp, &stats);
+               if (copy_to_user(addr, &stats, sizeof(stats)))
+                       break;
+               err = 0;
+               break;
+
+       case SIOCGPPPCSTATS:
+               memset(&cstats, 0, sizeof(cstats));
+               if (ppp->xc_state)
+                       ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c);
+               if (ppp->rc_state)
+                       ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d);
+               if (copy_to_user(addr, &cstats, sizeof(cstats)))
+                       break;
+               err = 0;
+               break;
+
+       case SIOCGPPPVER:
+               vers = PPP_VERSION;
+               if (copy_to_user(addr, vers, strlen(vers) + 1))
+                       break;
+               err = 0;
+               break;
+
+       default:
+               err = -EINVAL;
+       }
+
+       return err;
+}
+
+static const struct net_device_ops ppp_netdev_ops = {
+       .ndo_start_xmit = ppp_start_xmit,
+       .ndo_do_ioctl   = ppp_net_ioctl,
+};
+
+static void ppp_setup(struct net_device *dev)
+{
+       dev->netdev_ops = &ppp_netdev_ops;
+       dev->hard_header_len = PPP_HDRLEN;
+       dev->mtu = PPP_MTU;
+       dev->addr_len = 0;
+       dev->tx_queue_len = 3;
+       dev->type = ARPHRD_PPP;
+       dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
+       dev->features |= NETIF_F_NETNS_LOCAL;
+       dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+}
+
+/*
+ * Transmit-side routines.
+ */
+
+/*
+ * Called to do any work queued up on the transmit side
+ * that can now be done.
+ */
+static void
+ppp_xmit_process(struct ppp *ppp)
+{
+       struct sk_buff *skb;
+
+       ppp_xmit_lock(ppp);
+       if (!ppp->closing) {
+               ppp_push(ppp);
+               while (!ppp->xmit_pending &&
+                      (skb = skb_dequeue(&ppp->file.xq)))
+                       ppp_send_frame(ppp, skb);
+               /* If there's no work left to do, tell the core net
+                  code that we can accept some more. */
+               if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
+                       netif_wake_queue(ppp->dev);
+       }
+       ppp_xmit_unlock(ppp);
+}
+
+static inline struct sk_buff *
+pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
+{
+       struct sk_buff *new_skb;
+       int len;
+       int new_skb_size = ppp->dev->mtu +
+               ppp->xcomp->comp_extra + ppp->dev->hard_header_len;
+       int compressor_skb_size = ppp->dev->mtu +
+               ppp->xcomp->comp_extra + PPP_HDRLEN;
+       new_skb = alloc_skb(new_skb_size, GFP_ATOMIC);
+       if (!new_skb) {
+               if (net_ratelimit())
+                       netdev_err(ppp->dev, "PPP: no memory (comp pkt)\n");
+               return NULL;
+       }
+       if (ppp->dev->hard_header_len > PPP_HDRLEN)
+               skb_reserve(new_skb,
+                           ppp->dev->hard_header_len - PPP_HDRLEN);
+
+       /* compressor still expects A/C bytes in hdr */
+       len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2,
+                                  new_skb->data, skb->len + 2,
+                                  compressor_skb_size);
+       if (len > 0 && (ppp->flags & SC_CCP_UP)) {
+               kfree_skb(skb);
+               skb = new_skb;
+               skb_put(skb, len);
+               skb_pull(skb, 2);       /* pull off A/C bytes */
+       } else if (len == 0) {
+               /* didn't compress, or CCP not up yet */
+               kfree_skb(new_skb);
+               new_skb = skb;
+       } else {
+               /*
+                * (len < 0)
+                * MPPE requires that we do not send unencrypted
+                * frames.  The compressor will return -1 if we
+                * should drop the frame.  We cannot simply test
+                * the compress_proto because MPPE and MPPC share
+                * the same number.
+                */
+               if (net_ratelimit())
+                       netdev_err(ppp->dev, "ppp: compressor dropped pkt\n");
+               kfree_skb(skb);
+               kfree_skb(new_skb);
+               new_skb = NULL;
+       }
+       return new_skb;
+}
+
+/*
+ * Compress and send a frame.
+ * The caller should have locked the xmit path,
+ * and xmit_pending should be 0.
+ */
+static void
+ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
+{
+       int proto = PPP_PROTO(skb);
+       struct sk_buff *new_skb;
+       int len;
+       unsigned char *cp;
+
+       if (proto < 0x8000) {
+#ifdef CONFIG_PPP_FILTER
+               /* check if we should pass this packet */
+               /* the filter instructions are constructed assuming
+                  a four-byte PPP header on each packet */
+               *skb_push(skb, 2) = 1;
+               if (ppp->pass_filter &&
+                   sk_run_filter(skb, ppp->pass_filter) == 0) {
+                       if (ppp->debug & 1)
+                               netdev_printk(KERN_DEBUG, ppp->dev,
+                                             "PPP: outbound frame "
+                                             "not passed\n");
+                       kfree_skb(skb);
+                       return;
+               }
+               /* if this packet passes the active filter, record the time */
+               if (!(ppp->active_filter &&
+                     sk_run_filter(skb, ppp->active_filter) == 0))
+                       ppp->last_xmit = jiffies;
+               skb_pull(skb, 2);
+#else
+               /* for data packets, record the time */
+               ppp->last_xmit = jiffies;
+#endif /* CONFIG_PPP_FILTER */
+       }
+
+       ++ppp->dev->stats.tx_packets;
+       ppp->dev->stats.tx_bytes += skb->len - 2;
+
+       switch (proto) {
+       case PPP_IP:
+               if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0)
+                       break;
+               /* try to do VJ TCP header compression */
+               new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
+                                   GFP_ATOMIC);
+               if (!new_skb) {
+                       netdev_err(ppp->dev, "PPP: no memory (VJ comp pkt)\n");
+                       goto drop;
+               }
+               skb_reserve(new_skb, ppp->dev->hard_header_len - 2);
+               cp = skb->data + 2;
+               len = slhc_compress(ppp->vj, cp, skb->len - 2,
+                                   new_skb->data + 2, &cp,
+                                   !(ppp->flags & SC_NO_TCP_CCID));
+               if (cp == skb->data + 2) {
+                       /* didn't compress */
+                       kfree_skb(new_skb);
+               } else {
+                       if (cp[0] & SL_TYPE_COMPRESSED_TCP) {
+                               proto = PPP_VJC_COMP;
+                               cp[0] &= ~SL_TYPE_COMPRESSED_TCP;
+                       } else {
+                               proto = PPP_VJC_UNCOMP;
+                               cp[0] = skb->data[2];
+                       }
+                       kfree_skb(skb);
+                       skb = new_skb;
+                       cp = skb_put(skb, len + 2);
+                       cp[0] = 0;
+                       cp[1] = proto;
+               }
+               break;
+
+       case PPP_CCP:
+               /* peek at outbound CCP frames */
+               ppp_ccp_peek(ppp, skb, 0);
+               break;
+       }
+
+       /* try to do packet compression */
+       if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state &&
+           proto != PPP_LCP && proto != PPP_CCP) {
+               if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
+                       if (net_ratelimit())
+                               netdev_err(ppp->dev,
+                                          "ppp: compression required but "
+                                          "down - pkt dropped.\n");
+                       goto drop;
+               }
+               skb = pad_compress_skb(ppp, skb);
+               if (!skb)
+                       goto drop;
+       }
+
+       /*
+        * If we are waiting for traffic (demand dialling),
+        * queue it up for pppd to receive.
+        */
+       if (ppp->flags & SC_LOOP_TRAFFIC) {
+               if (ppp->file.rq.qlen > PPP_MAX_RQLEN)
+                       goto drop;
+               skb_queue_tail(&ppp->file.rq, skb);
+               wake_up_interruptible(&ppp->file.rwait);
+               return;
+       }
+
+       ppp->xmit_pending = skb;
+       ppp_push(ppp);
+       return;
+
+ drop:
+       kfree_skb(skb);
+       ++ppp->dev->stats.tx_errors;
+}
+
+/*
+ * Try to send the frame in xmit_pending.
+ * The caller should have the xmit path locked.
+ */
+static void
+ppp_push(struct ppp *ppp)
+{
+       struct list_head *list;
+       struct channel *pch;
+       struct sk_buff *skb = ppp->xmit_pending;
+
+       if (!skb)
+               return;
+
+       list = &ppp->channels;
+       if (list_empty(list)) {
+               /* nowhere to send the packet, just drop it */
+               ppp->xmit_pending = NULL;
+               kfree_skb(skb);
+               return;
+       }
+
+       if ((ppp->flags & SC_MULTILINK) == 0) {
+               /* not doing multilink: send it down the first channel */
+               list = list->next;
+               pch = list_entry(list, struct channel, clist);
+
+               spin_lock_bh(&pch->downl);
+               if (pch->chan) {
+                       if (pch->chan->ops->start_xmit(pch->chan, skb))
+                               ppp->xmit_pending = NULL;
+               } else {
+                       /* channel got unregistered */
+                       kfree_skb(skb);
+                       ppp->xmit_pending = NULL;
+               }
+               spin_unlock_bh(&pch->downl);
+               return;
+       }
+
+#ifdef CONFIG_PPP_MULTILINK
+       /* Multilink: fragment the packet over as many links
+          as can take the packet at the moment. */
+       if (!ppp_mp_explode(ppp, skb))
+               return;
+#endif /* CONFIG_PPP_MULTILINK */
+
+       ppp->xmit_pending = NULL;
+       kfree_skb(skb);
+}
+
+#ifdef CONFIG_PPP_MULTILINK
+static bool mp_protocol_compress __read_mostly = true;
+module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mp_protocol_compress,
+                "compress protocol id in multilink fragments");
+
+/*
+ * Divide a packet to be transmitted into fragments and
+ * send them out the individual links.
+ */
+static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
+{
+       int len, totlen;
+       int i, bits, hdrlen, mtu;
+       int flen;
+       int navail, nfree, nzero;
+       int nbigger;
+       int totspeed;
+       int totfree;
+       unsigned char *p, *q;
+       struct list_head *list;
+       struct channel *pch;
+       struct sk_buff *frag;
+       struct ppp_channel *chan;
+
+       totspeed = 0; /*total bitrate of the bundle*/
+       nfree = 0; /* # channels which have no packet already queued */
+       navail = 0; /* total # of usable channels (not deregistered) */
+       nzero = 0; /* number of channels with zero speed associated*/
+       totfree = 0; /*total # of channels available and
+                                 *having no queued packets before
+                                 *starting the fragmentation*/
+
+       hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
+       i = 0;
+       list_for_each_entry(pch, &ppp->channels, clist) {
+               if (pch->chan) {
+                       pch->avail = 1;
+                       navail++;
+                       pch->speed = pch->chan->speed;
+               } else {
+                       pch->avail = 0;
+               }
+               if (pch->avail) {
+                       if (skb_queue_empty(&pch->file.xq) ||
+                               !pch->had_frag) {
+                                       if (pch->speed == 0)
+                                               nzero++;
+                                       else
+                                               totspeed += pch->speed;
+
+                                       pch->avail = 2;
+                                       ++nfree;
+                                       ++totfree;
+                               }
+                       if (!pch->had_frag && i < ppp->nxchan)
+                               ppp->nxchan = i;
+               }
+               ++i;
+       }
+       /*
+        * Don't start sending this packet unless at least half of
+        * the channels are free.  This gives much better TCP
+        * performance if we have a lot of channels.
+        */
+       if (nfree == 0 || nfree < navail / 2)
+               return 0; /* can't take now, leave it in xmit_pending */
+
+       /* Do protocol field compression */
+       p = skb->data;
+       len = skb->len;
+       if (*p == 0 && mp_protocol_compress) {
+               ++p;
+               --len;
+       }
+
+       totlen = len;
+       nbigger = len % nfree;
+
+       /* skip to the channel after the one we last used
+          and start at that one */
+       list = &ppp->channels;
+       for (i = 0; i < ppp->nxchan; ++i) {
+               list = list->next;
+               if (list == &ppp->channels) {
+                       i = 0;
+                       break;
+               }
+       }
+
+       /* create a fragment for each channel */
+       bits = B;
+       while (len > 0) {
+               list = list->next;
+               if (list == &ppp->channels) {
+                       i = 0;
+                       continue;
+               }
+               pch = list_entry(list, struct channel, clist);
+               ++i;
+               if (!pch->avail)
+                       continue;
+
+               /*
+                * Skip this channel if it has a fragment pending already and
+                * we haven't given a fragment to all of the free channels.
+                */
+               if (pch->avail == 1) {
+                       if (nfree > 0)
+                               continue;
+               } else {
+                       pch->avail = 1;
+               }
+
+               /* check the channel's mtu and whether it is still attached. */
+               spin_lock_bh(&pch->downl);
+               if (pch->chan == NULL) {
+                       /* can't use this channel, it's being deregistered */
+                       if (pch->speed == 0)
+                               nzero--;
+                       else
+                               totspeed -= pch->speed;
+
+                       spin_unlock_bh(&pch->downl);
+                       pch->avail = 0;
+                       totlen = len;
+                       totfree--;
+                       nfree--;
+                       if (--navail == 0)
+                               break;
+                       continue;
+               }
+
+               /*
+               *if the channel speed is not set divide
+               *the packet evenly among the free channels;
+               *otherwise divide it according to the speed
+               *of the channel we are going to transmit on
+               */
+               flen = len;
+               if (nfree > 0) {
+                       if (pch->speed == 0) {
+                               flen = len/nfree;
+                               if (nbigger > 0) {
+                                       flen++;
+                                       nbigger--;
+                               }
+                       } else {
+                               flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
+                                       ((totspeed*totfree)/pch->speed)) - hdrlen;
+                               if (nbigger > 0) {
+                                       flen += ((totfree - nzero)*pch->speed)/totspeed;
+                                       nbigger -= ((totfree - nzero)*pch->speed)/
+                                                       totspeed;
+                               }
+                       }
+                       nfree--;
+               }
+
+               /*
+                *check if we are on the last channel or
+                *we exceded the length of the data to
+                *fragment
+                */
+               if ((nfree <= 0) || (flen > len))
+                       flen = len;
+               /*
+                *it is not worth to tx on slow channels:
+                *in that case from the resulting flen according to the
+                *above formula will be equal or less than zero.
+                *Skip the channel in this case
+                */
+               if (flen <= 0) {
+                       pch->avail = 2;
+                       spin_unlock_bh(&pch->downl);
+                       continue;
+               }
+
+               mtu = pch->chan->mtu - hdrlen;
+               if (mtu < 4)
+                       mtu = 4;
+               if (flen > mtu)
+                       flen = mtu;
+               if (flen == len)
+                       bits |= E;
+               frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
+               if (!frag)
+                       goto noskb;
+               q = skb_put(frag, flen + hdrlen);
+
+               /* make the MP header */
+               put_unaligned_be16(PPP_MP, q);
+               if (ppp->flags & SC_MP_XSHORTSEQ) {
+                       q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
+                       q[3] = ppp->nxseq;
+               } else {
+                       q[2] = bits;
+                       q[3] = ppp->nxseq >> 16;
+                       q[4] = ppp->nxseq >> 8;
+                       q[5] = ppp->nxseq;
+               }
+
+               memcpy(q + hdrlen, p, flen);
+
+               /* try to send it down the channel */
+               chan = pch->chan;
+               if (!skb_queue_empty(&pch->file.xq) ||
+                       !chan->ops->start_xmit(chan, frag))
+                       skb_queue_tail(&pch->file.xq, frag);
+               pch->had_frag = 1;
+               p += flen;
+               len -= flen;
+               ++ppp->nxseq;
+               bits = 0;
+               spin_unlock_bh(&pch->downl);
+       }
+       ppp->nxchan = i;
+
+       return 1;
+
+ noskb:
+       spin_unlock_bh(&pch->downl);
+       if (ppp->debug & 1)
+               netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
+       ++ppp->dev->stats.tx_errors;
+       ++ppp->nxseq;
+       return 1;       /* abandon the frame */
+}
+#endif /* CONFIG_PPP_MULTILINK */
+
+/*
+ * Try to send data out on a channel.
+ */
+static void
+ppp_channel_push(struct channel *pch)
+{
+       struct sk_buff *skb;
+       struct ppp *ppp;
+
+       spin_lock_bh(&pch->downl);
+       if (pch->chan) {
+               while (!skb_queue_empty(&pch->file.xq)) {
+                       skb = skb_dequeue(&pch->file.xq);
+                       if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
+                               /* put the packet back and try again later */
+                               skb_queue_head(&pch->file.xq, skb);
+                               break;
+                       }
+               }
+       } else {
+               /* channel got deregistered */
+               skb_queue_purge(&pch->file.xq);
+       }
+       spin_unlock_bh(&pch->downl);
+       /* see if there is anything from the attached unit to be sent */
+       if (skb_queue_empty(&pch->file.xq)) {
+               read_lock_bh(&pch->upl);
+               ppp = pch->ppp;
+               if (ppp)
+                       ppp_xmit_process(ppp);
+               read_unlock_bh(&pch->upl);
+       }
+}
+
+/*
+ * Receive-side routines.
+ */
+
+struct ppp_mp_skb_parm {
+       u32             sequence;
+       u8              BEbits;
+};
+#define PPP_MP_CB(skb) ((struct ppp_mp_skb_parm *)((skb)->cb))
+
+static inline void
+ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+{
+       ppp_recv_lock(ppp);
+       if (!ppp->closing)
+               ppp_receive_frame(ppp, skb, pch);
+       else
+               kfree_skb(skb);
+       ppp_recv_unlock(ppp);
+}
+
+void
+ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
+{
+       struct channel *pch = chan->ppp;
+       int proto;
+
+       if (!pch) {
+               kfree_skb(skb);
+               return;
+       }
+
+       read_lock_bh(&pch->upl);
+       if (!pskb_may_pull(skb, 2)) {
+               kfree_skb(skb);
+               if (pch->ppp) {
+                       ++pch->ppp->dev->stats.rx_length_errors;
+                       ppp_receive_error(pch->ppp);
+               }
+               goto done;
+       }
+
+       proto = PPP_PROTO(skb);
+       if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {
+               /* put it on the channel queue */
+               skb_queue_tail(&pch->file.rq, skb);
+               /* drop old frames if queue too long */
+               while (pch->file.rq.qlen > PPP_MAX_RQLEN &&
+                      (skb = skb_dequeue(&pch->file.rq)))
+                       kfree_skb(skb);
+               wake_up_interruptible(&pch->file.rwait);
+       } else {
+               ppp_do_recv(pch->ppp, skb, pch);
+       }
+
+done:
+       read_unlock_bh(&pch->upl);
+}
+
+/* Put a 0-length skb in the receive queue as an error indication */
+void
+ppp_input_error(struct ppp_channel *chan, int code)
+{
+       struct channel *pch = chan->ppp;
+       struct sk_buff *skb;
+
+       if (!pch)
+               return;
+
+       read_lock_bh(&pch->upl);
+       if (pch->ppp) {
+               skb = alloc_skb(0, GFP_ATOMIC);
+               if (skb) {
+                       skb->len = 0;           /* probably unnecessary */
+                       skb->cb[0] = code;
+                       ppp_do_recv(pch->ppp, skb, pch);
+               }
+       }
+       read_unlock_bh(&pch->upl);
+}
+
+/*
+ * We come in here to process a received frame.
+ * The receive side of the ppp unit is locked.
+ */
+static void
+ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+{
+       /* note: a 0-length skb is used as an error indication */
+       if (skb->len > 0) {
+#ifdef CONFIG_PPP_MULTILINK
+               /* XXX do channel-level decompression here */
+               if (PPP_PROTO(skb) == PPP_MP)
+                       ppp_receive_mp_frame(ppp, skb, pch);
+               else
+#endif /* CONFIG_PPP_MULTILINK */
+                       ppp_receive_nonmp_frame(ppp, skb);
+       } else {
+               kfree_skb(skb);
+               ppp_receive_error(ppp);
+       }
+}
+
+static void
+ppp_receive_error(struct ppp *ppp)
+{
+       ++ppp->dev->stats.rx_errors;
+       if (ppp->vj)
+               slhc_toss(ppp->vj);
+}
+
+static void
+ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
+{
+       struct sk_buff *ns;
+       int proto, len, npi;
+
+       /*
+        * Decompress the frame, if compressed.
+        * Note that some decompressors need to see uncompressed frames
+        * that come in as well as compressed frames.
+        */
+       if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN) &&
+           (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0)
+               skb = ppp_decompress_frame(ppp, skb);
+
+       if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR)
+               goto err;
+
+       proto = PPP_PROTO(skb);
+       switch (proto) {
+       case PPP_VJC_COMP:
+               /* decompress VJ compressed packets */
+               if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
+                       goto err;
+
+               if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
+                       /* copy to a new sk_buff with more tailroom */
+                       ns = dev_alloc_skb(skb->len + 128);
+                       if (!ns) {
+                               netdev_err(ppp->dev, "PPP: no memory "
+                                          "(VJ decomp)\n");
+                               goto err;
+                       }
+                       skb_reserve(ns, 2);
+                       skb_copy_bits(skb, 0, skb_put(ns, skb->len), skb->len);
+                       kfree_skb(skb);
+                       skb = ns;
+               }
+               else
+                       skb->ip_summed = CHECKSUM_NONE;
+
+               len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
+               if (len <= 0) {
+                       netdev_printk(KERN_DEBUG, ppp->dev,
+                                     "PPP: VJ decompression error\n");
+                       goto err;
+               }
+               len += 2;
+               if (len > skb->len)
+                       skb_put(skb, len - skb->len);
+               else if (len < skb->len)
+                       skb_trim(skb, len);
+               proto = PPP_IP;
+               break;
+
+       case PPP_VJC_UNCOMP:
+               if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
+                       goto err;
+
+               /* Until we fix the decompressor need to make sure
+                * data portion is linear.
+                */
+               if (!pskb_may_pull(skb, skb->len))
+                       goto err;
+
+               if (slhc_remember(ppp->vj, skb->data + 2, skb->len - 2) <= 0) {
+                       netdev_err(ppp->dev, "PPP: VJ uncompressed error\n");
+                       goto err;
+               }
+               proto = PPP_IP;
+               break;
+
+       case PPP_CCP:
+               ppp_ccp_peek(ppp, skb, 1);
+               break;
+       }
+
+       ++ppp->dev->stats.rx_packets;
+       ppp->dev->stats.rx_bytes += skb->len - 2;
+
+       npi = proto_to_npindex(proto);
+       if (npi < 0) {
+               /* control or unknown frame - pass it to pppd */
+               skb_queue_tail(&ppp->file.rq, skb);
+               /* limit queue length by dropping old frames */
+               while (ppp->file.rq.qlen > PPP_MAX_RQLEN &&
+                      (skb = skb_dequeue(&ppp->file.rq)))
+                       kfree_skb(skb);
+               /* wake up any process polling or blocking on read */
+               wake_up_interruptible(&ppp->file.rwait);
+
+       } else {
+               /* network protocol frame - give it to the kernel */
+
+#ifdef CONFIG_PPP_FILTER
+               /* check if the packet passes the pass and active filters */
+               /* the filter instructions are constructed assuming
+                  a four-byte PPP header on each packet */
+               if (ppp->pass_filter || ppp->active_filter) {
+                       if (skb_cloned(skb) &&
+                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+                               goto err;
+
+                       *skb_push(skb, 2) = 0;
+                       if (ppp->pass_filter &&
+                           sk_run_filter(skb, ppp->pass_filter) == 0) {
+                               if (ppp->debug & 1)
+                                       netdev_printk(KERN_DEBUG, ppp->dev,
+                                                     "PPP: inbound frame "
+                                                     "not passed\n");
+                               kfree_skb(skb);
+                               return;
+                       }
+                       if (!(ppp->active_filter &&
+                             sk_run_filter(skb, ppp->active_filter) == 0))
+                               ppp->last_recv = jiffies;
+                       __skb_pull(skb, 2);
+               } else
+#endif /* CONFIG_PPP_FILTER */
+                       ppp->last_recv = jiffies;
+
+               if ((ppp->dev->flags & IFF_UP) == 0 ||
+                   ppp->npmode[npi] != NPMODE_PASS) {
+                       kfree_skb(skb);
+               } else {
+                       /* chop off protocol */
+                       skb_pull_rcsum(skb, 2);
+                       skb->dev = ppp->dev;
+                       skb->protocol = htons(npindex_to_ethertype[npi]);
+                       skb_reset_mac_header(skb);
+                       netif_rx(skb);
+               }
+       }
+       return;
+
+ err:
+       kfree_skb(skb);
+       ppp_receive_error(ppp);
+}
+
+static struct sk_buff *
+ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
+{
+       int proto = PPP_PROTO(skb);
+       struct sk_buff *ns;
+       int len;
+
+       /* Until we fix all the decompressor's need to make sure
+        * data portion is linear.
+        */
+       if (!pskb_may_pull(skb, skb->len))
+               goto err;
+
+       if (proto == PPP_COMP) {
+               int obuff_size;
+
+               switch(ppp->rcomp->compress_proto) {
+               case CI_MPPE:
+                       obuff_size = ppp->mru + PPP_HDRLEN + 1;
+                       break;
+               default:
+                       obuff_size = ppp->mru + PPP_HDRLEN;
+                       break;
+               }
+
+               ns = dev_alloc_skb(obuff_size);
+               if (!ns) {
+                       netdev_err(ppp->dev, "ppp_decompress_frame: "
+                                  "no memory\n");
+                       goto err;
+               }
+               /* the decompressor still expects the A/C bytes in the hdr */
+               len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2,
+                               skb->len + 2, ns->data, obuff_size);
+               if (len < 0) {
+                       /* Pass the compressed frame to pppd as an
+                          error indication. */
+                       if (len == DECOMP_FATALERROR)
+                               ppp->rstate |= SC_DC_FERROR;
+                       kfree_skb(ns);
+                       goto err;
+               }
+
+               kfree_skb(skb);
+               skb = ns;
+               skb_put(skb, len);
+               skb_pull(skb, 2);       /* pull off the A/C bytes */
+
+       } else {
+               /* Uncompressed frame - pass to decompressor so it
+                  can update its dictionary if necessary. */
+               if (ppp->rcomp->incomp)
+                       ppp->rcomp->incomp(ppp->rc_state, skb->data - 2,
+                                          skb->len + 2);
+       }
+
+       return skb;
+
+ err:
+       ppp->rstate |= SC_DC_ERROR;
+       ppp_receive_error(ppp);
+       return skb;
+}
+
+#ifdef CONFIG_PPP_MULTILINK
+/*
+ * Receive a multilink frame.
+ * We put it on the reconstruction queue and then pull off
+ * as many completed frames as we can.
+ */
+static void
+ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+{
+       u32 mask, seq;
+       struct channel *ch;
+       int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
+
+       if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
+               goto err;               /* no good, throw it away */
+
+       /* Decode sequence number and begin/end bits */
+       if (ppp->flags & SC_MP_SHORTSEQ) {
+               seq = ((skb->data[2] & 0x0f) << 8) | skb->data[3];
+               mask = 0xfff;
+       } else {
+               seq = (skb->data[3] << 16) | (skb->data[4] << 8)| skb->data[5];
+               mask = 0xffffff;
+       }
+       PPP_MP_CB(skb)->BEbits = skb->data[2];
+       skb_pull(skb, mphdrlen);        /* pull off PPP and MP headers */
+
+       /*
+        * Do protocol ID decompression on the first fragment of each packet.
+        */
+       if ((PPP_MP_CB(skb)->BEbits & B) && (skb->data[0] & 1))
+               *skb_push(skb, 1) = 0;
+
+       /*
+        * Expand sequence number to 32 bits, making it as close
+        * as possible to ppp->minseq.
+        */
+       seq |= ppp->minseq & ~mask;
+       if ((int)(ppp->minseq - seq) > (int)(mask >> 1))
+               seq += mask + 1;
+       else if ((int)(seq - ppp->minseq) > (int)(mask >> 1))
+               seq -= mask + 1;        /* should never happen */
+       PPP_MP_CB(skb)->sequence = seq;
+       pch->lastseq = seq;
+
+       /*
+        * If this packet comes before the next one we were expecting,
+        * drop it.
+        */
+       if (seq_before(seq, ppp->nextseq)) {
+               kfree_skb(skb);
+               ++ppp->dev->stats.rx_dropped;
+               ppp_receive_error(ppp);
+               return;
+       }
+
+       /*
+        * Reevaluate minseq, the minimum over all channels of the
+        * last sequence number received on each channel.  Because of
+        * the increasing sequence number rule, we know that any fragment
+        * before `minseq' which hasn't arrived is never going to arrive.
+        * The list of channels can't change because we have the receive
+        * side of the ppp unit locked.
+        */
+       list_for_each_entry(ch, &ppp->channels, clist) {
+               if (seq_before(ch->lastseq, seq))
+                       seq = ch->lastseq;
+       }
+       if (seq_before(ppp->minseq, seq))
+               ppp->minseq = seq;
+
+       /* Put the fragment on the reconstruction queue */
+       ppp_mp_insert(ppp, skb);
+
+       /* If the queue is getting long, don't wait any longer for packets
+          before the start of the queue. */
+       if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) {
+               struct sk_buff *mskb = skb_peek(&ppp->mrq);
+               if (seq_before(ppp->minseq, PPP_MP_CB(mskb)->sequence))
+                       ppp->minseq = PPP_MP_CB(mskb)->sequence;
+       }
+
+       /* Pull completed packets off the queue and receive them. */
+       while ((skb = ppp_mp_reconstruct(ppp))) {
+               if (pskb_may_pull(skb, 2))
+                       ppp_receive_nonmp_frame(ppp, skb);
+               else {
+                       ++ppp->dev->stats.rx_length_errors;
+                       kfree_skb(skb);
+                       ppp_receive_error(ppp);
+               }
+       }
+
+       return;
+
+ err:
+       kfree_skb(skb);
+       ppp_receive_error(ppp);
+}
+
+/*
+ * Insert a fragment on the MP reconstruction queue.
+ * The queue is ordered by increasing sequence number.
+ */
+static void
+ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb)
+{
+       struct sk_buff *p;
+       struct sk_buff_head *list = &ppp->mrq;
+       u32 seq = PPP_MP_CB(skb)->sequence;
+
+       /* N.B. we don't need to lock the list lock because we have the
+          ppp unit receive-side lock. */
+       skb_queue_walk(list, p) {
+               if (seq_before(seq, PPP_MP_CB(p)->sequence))
+                       break;
+       }
+       __skb_queue_before(list, p, skb);
+}
+
+/*
+ * Reconstruct a packet from the MP fragment queue.
+ * We go through increasing sequence numbers until we find a
+ * complete packet, or we get to the sequence number for a fragment
+ * which hasn't arrived but might still do so.
+ */
+static struct sk_buff *
+ppp_mp_reconstruct(struct ppp *ppp)
+{
+       u32 seq = ppp->nextseq;
+       u32 minseq = ppp->minseq;
+       struct sk_buff_head *list = &ppp->mrq;
+       struct sk_buff *p, *tmp;
+       struct sk_buff *head, *tail;
+       struct sk_buff *skb = NULL;
+       int lost = 0, len = 0;
+
+       if (ppp->mrru == 0)     /* do nothing until mrru is set */
+               return NULL;
+       head = list->next;
+       tail = NULL;
+       skb_queue_walk_safe(list, p, tmp) {
+       again:
+               if (seq_before(PPP_MP_CB(p)->sequence, seq)) {
+                       /* this can't happen, anyway ignore the skb */
+                       netdev_err(ppp->dev, "ppp_mp_reconstruct bad "
+                                  "seq %u < %u\n",
+                                  PPP_MP_CB(p)->sequence, seq);
+                       __skb_unlink(p, list);
+                       kfree_skb(p);
+                       continue;
+               }
+               if (PPP_MP_CB(p)->sequence != seq) {
+                       /* Fragment `seq' is missing.  If it is after
+                          minseq, it might arrive later, so stop here. */
+                       if (seq_after(seq, minseq))
+                               break;
+                       /* Fragment `seq' is lost, keep going. */
+                       lost = 1;
+                       seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
+                               minseq + 1: PPP_MP_CB(p)->sequence;
+                       goto again;
+               }
+
+               /*
+                * At this point we know that all the fragments from
+                * ppp->nextseq to seq are either present or lost.
+                * Also, there are no complete packets in the queue
+                * that have no missing fragments and end before this
+                * fragment.
+                */
+
+               /* B bit set indicates this fragment starts a packet */
+               if (PPP_MP_CB(p)->BEbits & B) {
+                       head = p;
+                       lost = 0;
+                       len = 0;
+               }
+
+               len += p->len;
+
+               /* Got a complete packet yet? */
+               if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) &&
+                   (PPP_MP_CB(head)->BEbits & B)) {
+                       if (len > ppp->mrru + 2) {
+                               ++ppp->dev->stats.rx_length_errors;
+                               netdev_printk(KERN_DEBUG, ppp->dev,
+                                             "PPP: reconstructed packet"
+                                             " is too long (%d)\n", len);
+                       } else {
+                               tail = p;
+                               break;
+                       }
+                       ppp->nextseq = seq + 1;
+               }
+
+               /*
+                * If this is the ending fragment of a packet,
+                * and we haven't found a complete valid packet yet,
+                * we can discard up to and including this fragment.
+                */
+               if (PPP_MP_CB(p)->BEbits & E) {
+                       struct sk_buff *tmp2;
+
+                       skb_queue_reverse_walk_from_safe(list, p, tmp2) {
+                               __skb_unlink(p, list);
+                               kfree_skb(p);
+                       }
+                       head = skb_peek(list);
+                       if (!head)
+                               break;
+               }
+               ++seq;
+       }
+
+       /* If we have a complete packet, copy it all into one skb. */
+       if (tail != NULL) {
+               /* If we have discarded any fragments,
+                  signal a receive error. */
+               if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
+                       if (ppp->debug & 1)
+                               netdev_printk(KERN_DEBUG, ppp->dev,
+                                             "  missed pkts %u..%u\n",
+                                             ppp->nextseq,
+                                             PPP_MP_CB(head)->sequence-1);
+                       ++ppp->dev->stats.rx_dropped;
+                       ppp_receive_error(ppp);
+               }
+
+               skb = head;
+               if (head != tail) {
+                       struct sk_buff **fragpp = &skb_shinfo(skb)->frag_list;
+                       p = skb_queue_next(list, head);
+                       __skb_unlink(skb, list);
+                       skb_queue_walk_from_safe(list, p, tmp) {
+                               __skb_unlink(p, list);
+                               *fragpp = p;
+                               p->next = NULL;
+                               fragpp = &p->next;
+
+                               skb->len += p->len;
+                               skb->data_len += p->len;
+                               skb->truesize += p->len;
+
+                               if (p == tail)
+                                       break;
+                       }
+               } else {
+                       __skb_unlink(skb, list);
+               }
+
+               ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
+       }
+
+       return skb;
+}
+#endif /* CONFIG_PPP_MULTILINK */
+
+/*
+ * Channel interface.
+ */
+
+/* Create a new, unattached ppp channel. */
+int ppp_register_channel(struct ppp_channel *chan)
+{
+       return ppp_register_net_channel(current->nsproxy->net_ns, chan);
+}
+
+/* Create a new, unattached ppp channel for specified net. */
+int ppp_register_net_channel(struct net *net, struct ppp_channel *chan)
+{
+       struct channel *pch;
+       struct ppp_net *pn;
+
+       pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
+       if (!pch)
+               return -ENOMEM;
+
+       pn = ppp_pernet(net);
+
+       pch->ppp = NULL;
+       pch->chan = chan;
+       pch->chan_net = net;
+       chan->ppp = pch;
+       init_ppp_file(&pch->file, CHANNEL);
+       pch->file.hdrlen = chan->hdrlen;
+#ifdef CONFIG_PPP_MULTILINK
+       pch->lastseq = -1;
+#endif /* CONFIG_PPP_MULTILINK */
+       init_rwsem(&pch->chan_sem);
+       spin_lock_init(&pch->downl);
+       rwlock_init(&pch->upl);
+
+       spin_lock_bh(&pn->all_channels_lock);
+       pch->file.index = ++pn->last_channel_index;
+       list_add(&pch->list, &pn->new_channels);
+       atomic_inc(&channel_count);
+       spin_unlock_bh(&pn->all_channels_lock);
+
+       return 0;
+}
+
+/*
+ * Return the index of a channel.
+ */
+int ppp_channel_index(struct ppp_channel *chan)
+{
+       struct channel *pch = chan->ppp;
+
+       if (pch)
+               return pch->file.index;
+       return -1;
+}
+
+/*
+ * Return the PPP unit number to which a channel is connected.
+ */
+int ppp_unit_number(struct ppp_channel *chan)
+{
+       struct channel *pch = chan->ppp;
+       int unit = -1;
+
+       if (pch) {
+               read_lock_bh(&pch->upl);
+               if (pch->ppp)
+                       unit = pch->ppp->file.index;
+               read_unlock_bh(&pch->upl);
+       }
+       return unit;
+}
+
+/*
+ * Return the PPP device interface name of a channel.
+ */
+char *ppp_dev_name(struct ppp_channel *chan)
+{
+       struct channel *pch = chan->ppp;
+       char *name = NULL;
+
+       if (pch) {
+               read_lock_bh(&pch->upl);
+               if (pch->ppp && pch->ppp->dev)
+                       name = pch->ppp->dev->name;
+               read_unlock_bh(&pch->upl);
+       }
+       return name;
+}
+
+
+/*
+ * Disconnect a channel from the generic layer.
+ * This must be called in process context.
+ */
+void
+ppp_unregister_channel(struct ppp_channel *chan)
+{
+       struct channel *pch = chan->ppp;
+       struct ppp_net *pn;
+
+       if (!pch)
+               return;         /* should never happen */
+
+       chan->ppp = NULL;
+
+       /*
+        * This ensures that we have returned from any calls into the
+        * the channel's start_xmit or ioctl routine before we proceed.
+        */
+       down_write(&pch->chan_sem);
+       spin_lock_bh(&pch->downl);
+       pch->chan = NULL;
+       spin_unlock_bh(&pch->downl);
+       up_write(&pch->chan_sem);
+       ppp_disconnect_channel(pch);
+
+       pn = ppp_pernet(pch->chan_net);
+       spin_lock_bh(&pn->all_channels_lock);
+       list_del(&pch->list);
+       spin_unlock_bh(&pn->all_channels_lock);
+
+       pch->file.dead = 1;
+       wake_up_interruptible(&pch->file.rwait);
+       if (atomic_dec_and_test(&pch->file.refcnt))
+               ppp_destroy_channel(pch);
+}
+
+/*
+ * Callback from a channel when it can accept more to transmit.
+ * This should be called at BH/softirq level, not interrupt level.
+ */
+void
+ppp_output_wakeup(struct ppp_channel *chan)
+{
+       struct channel *pch = chan->ppp;
+
+       if (!pch)
+               return;
+       ppp_channel_push(pch);
+}
+
+/*
+ * Compression control.
+ */
+
+/* Process the PPPIOCSCOMPRESS ioctl. */
+static int
+ppp_set_compress(struct ppp *ppp, unsigned long arg)
+{
+       int err;
+       struct compressor *cp, *ocomp;
+       struct ppp_option_data data;
+       void *state, *ostate;
+       unsigned char ccp_option[CCP_MAX_OPTION_LENGTH];
+
+       err = -EFAULT;
+       if (copy_from_user(&data, (void __user *) arg, sizeof(data)) ||
+           (data.length <= CCP_MAX_OPTION_LENGTH &&
+            copy_from_user(ccp_option, (void __user *) data.ptr, data.length)))
+               goto out;
+       err = -EINVAL;
+       if (data.length > CCP_MAX_OPTION_LENGTH ||
+           ccp_option[1] < 2 || ccp_option[1] > data.length)
+               goto out;
+
+       cp = try_then_request_module(
+               find_compressor(ccp_option[0]),
+               "ppp-compress-%d", ccp_option[0]);
+       if (!cp)
+               goto out;
+
+       err = -ENOBUFS;
+       if (data.transmit) {
+               state = cp->comp_alloc(ccp_option, data.length);
+               if (state) {
+                       ppp_xmit_lock(ppp);
+                       ppp->xstate &= ~SC_COMP_RUN;
+                       ocomp = ppp->xcomp;
+                       ostate = ppp->xc_state;
+                       ppp->xcomp = cp;
+                       ppp->xc_state = state;
+                       ppp_xmit_unlock(ppp);
+                       if (ostate) {
+                               ocomp->comp_free(ostate);
+                               module_put(ocomp->owner);
+                       }
+                       err = 0;
+               } else
+                       module_put(cp->owner);
+
+       } else {
+               state = cp->decomp_alloc(ccp_option, data.length);
+               if (state) {
+                       ppp_recv_lock(ppp);
+                       ppp->rstate &= ~SC_DECOMP_RUN;
+                       ocomp = ppp->rcomp;
+                       ostate = ppp->rc_state;
+                       ppp->rcomp = cp;
+                       ppp->rc_state = state;
+                       ppp_recv_unlock(ppp);
+                       if (ostate) {
+                               ocomp->decomp_free(ostate);
+                               module_put(ocomp->owner);
+                       }
+                       err = 0;
+               } else
+                       module_put(cp->owner);
+       }
+
+ out:
+       return err;
+}
+
+/*
+ * Look at a CCP packet and update our state accordingly.
+ * We assume the caller has the xmit or recv path locked.
+ */
+static void
+ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
+{
+       unsigned char *dp;
+       int len;
+
+       if (!pskb_may_pull(skb, CCP_HDRLEN + 2))
+               return; /* no header */
+       dp = skb->data + 2;
+
+       switch (CCP_CODE(dp)) {
+       case CCP_CONFREQ:
+
+               /* A ConfReq starts negotiation of compression
+                * in one direction of transmission,
+                * and hence brings it down...but which way?
+                *
+                * Remember:
+                * A ConfReq indicates what the sender would like to receive
+                */
+               if(inbound)
+                       /* He is proposing what I should send */
+                       ppp->xstate &= ~SC_COMP_RUN;
+               else
+                       /* I am proposing to what he should send */
+                       ppp->rstate &= ~SC_DECOMP_RUN;
+
+               break;
+
+       case CCP_TERMREQ:
+       case CCP_TERMACK:
+               /*
+                * CCP is going down, both directions of transmission
+                */
+               ppp->rstate &= ~SC_DECOMP_RUN;
+               ppp->xstate &= ~SC_COMP_RUN;
+               break;
+
+       case CCP_CONFACK:
+               if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN)
+                       break;
+               len = CCP_LENGTH(dp);
+               if (!pskb_may_pull(skb, len + 2))
+                       return;         /* too short */
+               dp += CCP_HDRLEN;
+               len -= CCP_HDRLEN;
+               if (len < CCP_OPT_MINLEN || len < CCP_OPT_LENGTH(dp))
+                       break;
+               if (inbound) {
+                       /* we will start receiving compressed packets */
+                       if (!ppp->rc_state)
+                               break;
+                       if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
+                                       ppp->file.index, 0, ppp->mru, ppp->debug)) {
+                               ppp->rstate |= SC_DECOMP_RUN;
+                               ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR);
+                       }
+               } else {
+                       /* we will soon start sending compressed packets */
+                       if (!ppp->xc_state)
+                               break;
+                       if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
+                                       ppp->file.index, 0, ppp->debug))
+                               ppp->xstate |= SC_COMP_RUN;
+               }
+               break;
+
+       case CCP_RESETACK:
+               /* reset the [de]compressor */
+               if ((ppp->flags & SC_CCP_UP) == 0)
+                       break;
+               if (inbound) {
+                       if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN)) {
+                               ppp->rcomp->decomp_reset(ppp->rc_state);
+                               ppp->rstate &= ~SC_DC_ERROR;
+                       }
+               } else {
+                       if (ppp->xc_state && (ppp->xstate & SC_COMP_RUN))
+                               ppp->xcomp->comp_reset(ppp->xc_state);
+               }
+               break;
+       }
+}
+
+/* Free up compression resources. */
+static void
+ppp_ccp_closed(struct ppp *ppp)
+{
+       void *xstate, *rstate;
+       struct compressor *xcomp, *rcomp;
+
+       ppp_lock(ppp);
+       ppp->flags &= ~(SC_CCP_OPEN | SC_CCP_UP);
+       ppp->xstate = 0;
+       xcomp = ppp->xcomp;
+       xstate = ppp->xc_state;
+       ppp->xc_state = NULL;
+       ppp->rstate = 0;
+       rcomp = ppp->rcomp;
+       rstate = ppp->rc_state;
+       ppp->rc_state = NULL;
+       ppp_unlock(ppp);
+
+       if (xstate) {
+               xcomp->comp_free(xstate);
+               module_put(xcomp->owner);
+       }
+       if (rstate) {
+               rcomp->decomp_free(rstate);
+               module_put(rcomp->owner);
+       }
+}
+
+/* List of compressors. */
+static LIST_HEAD(compressor_list);
+static DEFINE_SPINLOCK(compressor_list_lock);
+
+struct compressor_entry {
+       struct list_head list;
+       struct compressor *comp;
+};
+
+static struct compressor_entry *
+find_comp_entry(int proto)
+{
+       struct compressor_entry *ce;
+
+       list_for_each_entry(ce, &compressor_list, list) {
+               if (ce->comp->compress_proto == proto)
+                       return ce;
+       }
+       return NULL;
+}
+
+/* Register a compressor */
+int
+ppp_register_compressor(struct compressor *cp)
+{
+       struct compressor_entry *ce;
+       int ret;
+       spin_lock(&compressor_list_lock);
+       ret = -EEXIST;
+       if (find_comp_entry(cp->compress_proto))
+               goto out;
+       ret = -ENOMEM;
+       ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC);
+       if (!ce)
+               goto out;
+       ret = 0;
+       ce->comp = cp;
+       list_add(&ce->list, &compressor_list);
+ out:
+       spin_unlock(&compressor_list_lock);
+       return ret;
+}
+
+/* Unregister a compressor */
+void
+ppp_unregister_compressor(struct compressor *cp)
+{
+       struct compressor_entry *ce;
+
+       spin_lock(&compressor_list_lock);
+       ce = find_comp_entry(cp->compress_proto);
+       if (ce && ce->comp == cp) {
+               list_del(&ce->list);
+               kfree(ce);
+       }
+       spin_unlock(&compressor_list_lock);
+}
+
+/* Find a compressor. */
+static struct compressor *
+find_compressor(int type)
+{
+       struct compressor_entry *ce;
+       struct compressor *cp = NULL;
+
+       spin_lock(&compressor_list_lock);
+       ce = find_comp_entry(type);
+       if (ce) {
+               cp = ce->comp;
+               if (!try_module_get(cp->owner))
+                       cp = NULL;
+       }
+       spin_unlock(&compressor_list_lock);
+       return cp;
+}
+
+/*
+ * Miscelleneous stuff.
+ */
+
+static void
+ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
+{
+       struct slcompress *vj = ppp->vj;
+
+       memset(st, 0, sizeof(*st));
+       st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
+       st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
+       st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
+       st->p.ppp_opackets = ppp->dev->stats.tx_packets;
+       st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
+       st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
+       if (!vj)
+               return;
+       st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
+       st->vj.vjs_compressed = vj->sls_o_compressed;
+       st->vj.vjs_searches = vj->sls_o_searches;
+       st->vj.vjs_misses = vj->sls_o_misses;
+       st->vj.vjs_errorin = vj->sls_i_error;
+       st->vj.vjs_tossed = vj->sls_i_tossed;
+       st->vj.vjs_uncompressedin = vj->sls_i_uncompressed;
+       st->vj.vjs_compressedin = vj->sls_i_compressed;
+}
+
+/*
+ * Stuff for handling the lists of ppp units and channels
+ * and for initialization.
+ */
+
+/*
+ * Create a new ppp interface unit.  Fails if it can't allocate memory
+ * or if there is already a unit with the requested number.
+ * unit == -1 means allocate a new number.
+ */
+static struct ppp *
+ppp_create_interface(struct net *net, int unit, int *retp)
+{
+       struct ppp *ppp;
+       struct ppp_net *pn;
+       struct net_device *dev = NULL;
+       int ret = -ENOMEM;
+       int i;
+
+       dev = alloc_netdev(sizeof(struct ppp), "", ppp_setup);
+       if (!dev)
+               goto out1;
+
+       pn = ppp_pernet(net);
+
+       ppp = netdev_priv(dev);
+       ppp->dev = dev;
+       ppp->mru = PPP_MRU;
+       init_ppp_file(&ppp->file, INTERFACE);
+       ppp->file.hdrlen = PPP_HDRLEN - 2;      /* don't count proto bytes */
+       for (i = 0; i < NUM_NP; ++i)
+               ppp->npmode[i] = NPMODE_PASS;
+       INIT_LIST_HEAD(&ppp->channels);
+       spin_lock_init(&ppp->rlock);
+       spin_lock_init(&ppp->wlock);
+#ifdef CONFIG_PPP_MULTILINK
+       ppp->minseq = -1;
+       skb_queue_head_init(&ppp->mrq);
+#endif /* CONFIG_PPP_MULTILINK */
+
+       /*
+        * drum roll: don't forget to set
+        * the net device is belong to
+        */
+       dev_net_set(dev, net);
+
+       mutex_lock(&pn->all_ppp_mutex);
+
+       if (unit < 0) {
+               unit = unit_get(&pn->units_idr, ppp);
+               if (unit < 0) {
+                       ret = unit;
+                       goto out2;
+               }
+       } else {
+               ret = -EEXIST;
+               if (unit_find(&pn->units_idr, unit))
+                       goto out2; /* unit already exists */
+               /*
+                * if caller need a specified unit number
+                * lets try to satisfy him, otherwise --
+                * he should better ask us for new unit number
+                *
+                * NOTE: yes I know that returning EEXIST it's not
+                * fair but at least pppd will ask us to allocate
+                * new unit in this case so user is happy :)
+                */
+               unit = unit_set(&pn->units_idr, ppp, unit);
+               if (unit < 0)
+                       goto out2;
+       }
+
+       /* Initialize the new ppp unit */
+       ppp->file.index = unit;
+       sprintf(dev->name, "ppp%d", unit);
+
+       ret = register_netdev(dev);
+       if (ret != 0) {
+               unit_put(&pn->units_idr, unit);
+               netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n",
+                          dev->name, ret);
+               goto out2;
+       }
+
+       ppp->ppp_net = net;
+
+       atomic_inc(&ppp_unit_count);
+       mutex_unlock(&pn->all_ppp_mutex);
+
+       *retp = 0;
+       return ppp;
+
+out2:
+       mutex_unlock(&pn->all_ppp_mutex);
+       free_netdev(dev);
+out1:
+       *retp = ret;
+       return NULL;
+}
+
+/*
+ * Initialize a ppp_file structure.
+ */
+static void
+init_ppp_file(struct ppp_file *pf, int kind)
+{
+       pf->kind = kind;
+       skb_queue_head_init(&pf->xq);
+       skb_queue_head_init(&pf->rq);
+       atomic_set(&pf->refcnt, 1);
+       init_waitqueue_head(&pf->rwait);
+}
+
+/*
+ * Take down a ppp interface unit - called when the owning file
+ * (the one that created the unit) is closed or detached.
+ */
+static void ppp_shutdown_interface(struct ppp *ppp)
+{
+       struct ppp_net *pn;
+
+       pn = ppp_pernet(ppp->ppp_net);
+       mutex_lock(&pn->all_ppp_mutex);
+
+       /* This will call dev_close() for us. */
+       ppp_lock(ppp);
+       if (!ppp->closing) {
+               ppp->closing = 1;
+               ppp_unlock(ppp);
+               unregister_netdev(ppp->dev);
+               unit_put(&pn->units_idr, ppp->file.index);
+       } else
+               ppp_unlock(ppp);
+
+       ppp->file.dead = 1;
+       ppp->owner = NULL;
+       wake_up_interruptible(&ppp->file.rwait);
+
+       mutex_unlock(&pn->all_ppp_mutex);
+}
+
+/*
+ * Free the memory used by a ppp unit.  This is only called once
+ * there are no channels connected to the unit and no file structs
+ * that reference the unit.
+ */
+static void ppp_destroy_interface(struct ppp *ppp)
+{
+       atomic_dec(&ppp_unit_count);
+
+       if (!ppp->file.dead || ppp->n_channels) {
+               /* "can't happen" */
+               netdev_err(ppp->dev, "ppp: destroying ppp struct %p "
+                          "but dead=%d n_channels=%d !\n",
+                          ppp, ppp->file.dead, ppp->n_channels);
+               return;
+       }
+
+       ppp_ccp_closed(ppp);
+       if (ppp->vj) {
+               slhc_free(ppp->vj);
+               ppp->vj = NULL;
+       }
+       skb_queue_purge(&ppp->file.xq);
+       skb_queue_purge(&ppp->file.rq);
+#ifdef CONFIG_PPP_MULTILINK
+       skb_queue_purge(&ppp->mrq);
+#endif /* CONFIG_PPP_MULTILINK */
+#ifdef CONFIG_PPP_FILTER
+       kfree(ppp->pass_filter);
+       ppp->pass_filter = NULL;
+       kfree(ppp->active_filter);
+       ppp->active_filter = NULL;
+#endif /* CONFIG_PPP_FILTER */
+
+       kfree_skb(ppp->xmit_pending);
+
+       free_netdev(ppp->dev);
+}
+
+/*
+ * Locate an existing ppp unit.
+ * The caller should have locked the all_ppp_mutex.
+ */
+static struct ppp *
+ppp_find_unit(struct ppp_net *pn, int unit)
+{
+       return unit_find(&pn->units_idr, unit);
+}
+
+/*
+ * Locate an existing ppp channel.
+ * The caller should have locked the all_channels_lock.
+ * First we look in the new_channels list, then in the
+ * all_channels list.  If found in the new_channels list,
+ * we move it to the all_channels list.  This is for speed
+ * when we have a lot of channels in use.
+ */
+static struct channel *
+ppp_find_channel(struct ppp_net *pn, int unit)
+{
+       struct channel *pch;
+
+       list_for_each_entry(pch, &pn->new_channels, list) {
+               if (pch->file.index == unit) {
+                       list_move(&pch->list, &pn->all_channels);
+                       return pch;
+               }
+       }
+
+       list_for_each_entry(pch, &pn->all_channels, list) {
+               if (pch->file.index == unit)
+                       return pch;
+       }
+
+       return NULL;
+}
+
+/*
+ * Connect a PPP channel to a PPP interface unit.
+ */
+static int
+ppp_connect_channel(struct channel *pch, int unit)
+{
+       struct ppp *ppp;
+       struct ppp_net *pn;
+       int ret = -ENXIO;
+       int hdrlen;
+
+       pn = ppp_pernet(pch->chan_net);
+
+       mutex_lock(&pn->all_ppp_mutex);
+       ppp = ppp_find_unit(pn, unit);
+       if (!ppp)
+               goto out;
+       write_lock_bh(&pch->upl);
+       ret = -EINVAL;
+       if (pch->ppp)
+               goto outl;
+
+       ppp_lock(ppp);
+       if (pch->file.hdrlen > ppp->file.hdrlen)
+               ppp->file.hdrlen = pch->file.hdrlen;
+       hdrlen = pch->file.hdrlen + 2;  /* for protocol bytes */
+       if (hdrlen > ppp->dev->hard_header_len)
+               ppp->dev->hard_header_len = hdrlen;
+       list_add_tail(&pch->clist, &ppp->channels);
+       ++ppp->n_channels;
+       pch->ppp = ppp;
+       atomic_inc(&ppp->file.refcnt);
+       ppp_unlock(ppp);
+       ret = 0;
+
+ outl:
+       write_unlock_bh(&pch->upl);
+ out:
+       mutex_unlock(&pn->all_ppp_mutex);
+       return ret;
+}
+
+/*
+ * Disconnect a channel from its ppp unit.
+ */
+static int
+ppp_disconnect_channel(struct channel *pch)
+{
+       struct ppp *ppp;
+       int err = -EINVAL;
+
+       write_lock_bh(&pch->upl);
+       ppp = pch->ppp;
+       pch->ppp = NULL;
+       write_unlock_bh(&pch->upl);
+       if (ppp) {
+               /* remove it from the ppp unit's list */
+               ppp_lock(ppp);
+               list_del(&pch->clist);
+               if (--ppp->n_channels == 0)
+                       wake_up_interruptible(&ppp->file.rwait);
+               ppp_unlock(ppp);
+               if (atomic_dec_and_test(&ppp->file.refcnt))
+                       ppp_destroy_interface(ppp);
+               err = 0;
+       }
+       return err;
+}
+
+/*
+ * Free up the resources used by a ppp channel.
+ */
+static void ppp_destroy_channel(struct channel *pch)
+{
+       atomic_dec(&channel_count);
+
+       if (!pch->file.dead) {
+               /* "can't happen" */
+               pr_err("ppp: destroying undead channel %p !\n", pch);
+               return;
+       }
+       skb_queue_purge(&pch->file.xq);
+       skb_queue_purge(&pch->file.rq);
+       kfree(pch);
+}
+
+static void __exit ppp_cleanup(void)
+{
+       /* should never happen */
+       if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
+               pr_err("PPP: removing module but units remain!\n");
+       unregister_chrdev(PPP_MAJOR, "ppp");
+       device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
+       class_destroy(ppp_class);
+       unregister_pernet_device(&ppp_net_ops);
+}
+
+/*
+ * Units handling. Caller must protect concurrent access
+ * by holding all_ppp_mutex
+ */
+
+static int __unit_alloc(struct idr *p, void *ptr, int n)
+{
+       int unit, err;
+
+again:
+       if (!idr_pre_get(p, GFP_KERNEL)) {
+               pr_err("PPP: No free memory for idr\n");
+               return -ENOMEM;
+       }
+
+       err = idr_get_new_above(p, ptr, n, &unit);
+       if (err < 0) {
+               if (err == -EAGAIN)
+                       goto again;
+               return err;
+       }
+
+       return unit;
+}
+
+/* associate pointer with specified number */
+static int unit_set(struct idr *p, void *ptr, int n)
+{
+       int unit;
+
+       unit = __unit_alloc(p, ptr, n);
+       if (unit < 0)
+               return unit;
+       else if (unit != n) {
+               idr_remove(p, unit);
+               return -EINVAL;
+       }
+
+       return unit;
+}
+
+/* get new free unit number and associate pointer with it */
+static int unit_get(struct idr *p, void *ptr)
+{
+       return __unit_alloc(p, ptr, 0);
+}
+
+/* put unit number back to a pool */
+static void unit_put(struct idr *p, int n)
+{
+       idr_remove(p, n);
+}
+
+/* get pointer associated with the number */
+static void *unit_find(struct idr *p, int n)
+{
+       return idr_find(p, n);
+}
+
+/* Module/initialization stuff */
+
+module_init(ppp_init);
+module_exit(ppp_cleanup);
+
+EXPORT_SYMBOL(ppp_register_net_channel);
+EXPORT_SYMBOL(ppp_register_channel);
+EXPORT_SYMBOL(ppp_unregister_channel);
+EXPORT_SYMBOL(ppp_channel_index);
+EXPORT_SYMBOL(ppp_unit_number);
+EXPORT_SYMBOL(ppp_dev_name);
+EXPORT_SYMBOL(ppp_input);
+EXPORT_SYMBOL(ppp_input_error);
+EXPORT_SYMBOL(ppp_output_wakeup);
+EXPORT_SYMBOL(ppp_register_compressor);
+EXPORT_SYMBOL(ppp_unregister_compressor);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0);
+MODULE_ALIAS("devname:ppp");
diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c
new file mode 100644 (file)
index 0000000..9a1849a
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * ppp_mppe.c - interface MPPE to the PPP code.
+ * This version is for use with Linux kernel 2.6.14+
+ *
+ * By Frank Cusack <fcusack@fcusack.com>.
+ * Copyright (c) 2002,2003,2004 Google, Inc.
+ * All rights reserved.
+ *
+ * License:
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied.
+ *
+ * ALTERNATIVELY, provided that this notice is retained in full, this product
+ * may be distributed under the terms of the GNU General Public License (GPL),
+ * in which case the provisions of the GPL apply INSTEAD OF those given above.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Changelog:
+ *      08/12/05 - Matt Domsch <Matt_Domsch@dell.com>
+ *                 Only need extra skb padding on transmit, not receive.
+ *      06/18/04 - Matt Domsch <Matt_Domsch@dell.com>, Oleg Makarenko <mole@quadra.ru>
+ *                 Use Linux kernel 2.6 arc4 and sha1 routines rather than
+ *                 providing our own.
+ *      2/15/04 - TS: added #include <version.h> and testing for Kernel
+ *                    version before using
+ *                    MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are
+ *                    deprecated in 2.6
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/ppp_defs.h>
+#include <linux/ppp-comp.h>
+#include <linux/scatterlist.h>
+#include <asm/unaligned.h>
+
+#include "ppp_mppe.h"
+
+MODULE_AUTHOR("Frank Cusack <fcusack@fcusack.com>");
+MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE));
+MODULE_VERSION("1.0.2");
+
+static unsigned int
+setup_sg(struct scatterlist *sg, const void *address, unsigned int length)
+{
+       sg_set_buf(sg, address, length);
+       return length;
+}
+
+#define SHA1_PAD_SIZE 40
+
+/*
+ * kernel crypto API needs its arguments to be in kmalloc'd memory, not in the module
+ * static data area.  That means sha_pad needs to be kmalloc'd.
+ */
+
+struct sha_pad {
+       unsigned char sha_pad1[SHA1_PAD_SIZE];
+       unsigned char sha_pad2[SHA1_PAD_SIZE];
+};
+static struct sha_pad *sha_pad;
+
+static inline void sha_pad_init(struct sha_pad *shapad)
+{
+       memset(shapad->sha_pad1, 0x00, sizeof(shapad->sha_pad1));
+       memset(shapad->sha_pad2, 0xF2, sizeof(shapad->sha_pad2));
+}
+
+/*
+ * State for an MPPE (de)compressor.
+ */
+struct ppp_mppe_state {
+       struct crypto_blkcipher *arc4;
+       struct crypto_hash *sha1;
+       unsigned char *sha1_digest;
+       unsigned char master_key[MPPE_MAX_KEY_LEN];
+       unsigned char session_key[MPPE_MAX_KEY_LEN];
+       unsigned keylen;        /* key length in bytes             */
+       /* NB: 128-bit == 16, 40-bit == 8! */
+       /* If we want to support 56-bit,   */
+       /* the unit has to change to bits  */
+       unsigned char bits;     /* MPPE control bits */
+       unsigned ccount;        /* 12-bit coherency count (seqno)  */
+       unsigned stateful;      /* stateful mode flag */
+       int discard;            /* stateful mode packet loss flag */
+       int sanity_errors;      /* take down LCP if too many */
+       int unit;
+       int debug;
+       struct compstat stats;
+};
+
+/* struct ppp_mppe_state.bits definitions */
+#define MPPE_BIT_A     0x80    /* Encryption table were (re)inititalized */
+#define MPPE_BIT_B     0x40    /* MPPC only (not implemented) */
+#define MPPE_BIT_C     0x20    /* MPPC only (not implemented) */
+#define MPPE_BIT_D     0x10    /* This is an encrypted frame */
+
+#define MPPE_BIT_FLUSHED       MPPE_BIT_A
+#define MPPE_BIT_ENCRYPTED     MPPE_BIT_D
+
+#define MPPE_BITS(p) ((p)[4] & 0xf0)
+#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5])
+#define MPPE_CCOUNT_SPACE 0x1000       /* The size of the ccount space */
+
+#define MPPE_OVHD      2       /* MPPE overhead/packet */
+#define SANITY_MAX     1600    /* Max bogon factor we will tolerate */
+
+/*
+ * Key Derivation, from RFC 3078, RFC 3079.
+ * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
+ */
+static void get_new_key_from_sha(struct ppp_mppe_state * state)
+{
+       struct hash_desc desc;
+       struct scatterlist sg[4];
+       unsigned int nbytes;
+
+       sg_init_table(sg, 4);
+
+       nbytes = setup_sg(&sg[0], state->master_key, state->keylen);
+       nbytes += setup_sg(&sg[1], sha_pad->sha_pad1,
+                          sizeof(sha_pad->sha_pad1));
+       nbytes += setup_sg(&sg[2], state->session_key, state->keylen);
+       nbytes += setup_sg(&sg[3], sha_pad->sha_pad2,
+                          sizeof(sha_pad->sha_pad2));
+
+       desc.tfm = state->sha1;
+       desc.flags = 0;
+
+       crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest);
+}
+
+/*
+ * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3.
+ * Well, not what's written there, but rather what they meant.
+ */
+static void mppe_rekey(struct ppp_mppe_state * state, int initial_key)
+{
+       struct scatterlist sg_in[1], sg_out[1];
+       struct blkcipher_desc desc = { .tfm = state->arc4 };
+
+       get_new_key_from_sha(state);
+       if (!initial_key) {
+               crypto_blkcipher_setkey(state->arc4, state->sha1_digest,
+                                       state->keylen);
+               sg_init_table(sg_in, 1);
+               sg_init_table(sg_out, 1);
+               setup_sg(sg_in, state->sha1_digest, state->keylen);
+               setup_sg(sg_out, state->session_key, state->keylen);
+               if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
+                                            state->keylen) != 0) {
+                   printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n");
+               }
+       } else {
+               memcpy(state->session_key, state->sha1_digest, state->keylen);
+       }
+       if (state->keylen == 8) {
+               /* See RFC 3078 */
+               state->session_key[0] = 0xd1;
+               state->session_key[1] = 0x26;
+               state->session_key[2] = 0x9e;
+       }
+       crypto_blkcipher_setkey(state->arc4, state->session_key, state->keylen);
+}
+
+/*
+ * Allocate space for a (de)compressor.
+ */
+static void *mppe_alloc(unsigned char *options, int optlen)
+{
+       struct ppp_mppe_state *state;
+       unsigned int digestsize;
+
+       if (optlen != CILEN_MPPE + sizeof(state->master_key) ||
+           options[0] != CI_MPPE || options[1] != CILEN_MPPE)
+               goto out;
+
+       state = kzalloc(sizeof(*state), GFP_KERNEL);
+       if (state == NULL)
+               goto out;
+
+
+       state->arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(state->arc4)) {
+               state->arc4 = NULL;
+               goto out_free;
+       }
+
+       state->sha1 = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
+       if (IS_ERR(state->sha1)) {
+               state->sha1 = NULL;
+               goto out_free;
+       }
+
+       digestsize = crypto_hash_digestsize(state->sha1);
+       if (digestsize < MPPE_MAX_KEY_LEN)
+               goto out_free;
+
+       state->sha1_digest = kmalloc(digestsize, GFP_KERNEL);
+       if (!state->sha1_digest)
+               goto out_free;
+
+       /* Save keys. */
+       memcpy(state->master_key, &options[CILEN_MPPE],
+              sizeof(state->master_key));
+       memcpy(state->session_key, state->master_key,
+              sizeof(state->master_key));
+
+       /*
+        * We defer initial key generation until mppe_init(), as mppe_alloc()
+        * is called frequently during negotiation.
+        */
+
+       return (void *)state;
+
+       out_free:
+           if (state->sha1_digest)
+               kfree(state->sha1_digest);
+           if (state->sha1)
+               crypto_free_hash(state->sha1);
+           if (state->arc4)
+               crypto_free_blkcipher(state->arc4);
+           kfree(state);
+       out:
+       return NULL;
+}
+
+/*
+ * Deallocate space for a (de)compressor.
+ */
+static void mppe_free(void *arg)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+       if (state) {
+           if (state->sha1_digest)
+               kfree(state->sha1_digest);
+           if (state->sha1)
+               crypto_free_hash(state->sha1);
+           if (state->arc4)
+               crypto_free_blkcipher(state->arc4);
+           kfree(state);
+       }
+}
+
+/*
+ * Initialize (de)compressor state.
+ */
+static int
+mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug,
+         const char *debugstr)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+       unsigned char mppe_opts;
+
+       if (optlen != CILEN_MPPE ||
+           options[0] != CI_MPPE || options[1] != CILEN_MPPE)
+               return 0;
+
+       MPPE_CI_TO_OPTS(&options[2], mppe_opts);
+       if (mppe_opts & MPPE_OPT_128)
+               state->keylen = 16;
+       else if (mppe_opts & MPPE_OPT_40)
+               state->keylen = 8;
+       else {
+               printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr,
+                      unit);
+               return 0;
+       }
+       if (mppe_opts & MPPE_OPT_STATEFUL)
+               state->stateful = 1;
+
+       /* Generate the initial session key. */
+       mppe_rekey(state, 1);
+
+       if (debug) {
+               int i;
+               char mkey[sizeof(state->master_key) * 2 + 1];
+               char skey[sizeof(state->session_key) * 2 + 1];
+
+               printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n",
+                      debugstr, unit, (state->keylen == 16) ? 128 : 40,
+                      (state->stateful) ? "stateful" : "stateless");
+
+               for (i = 0; i < sizeof(state->master_key); i++)
+                       sprintf(mkey + i * 2, "%02x", state->master_key[i]);
+               for (i = 0; i < sizeof(state->session_key); i++)
+                       sprintf(skey + i * 2, "%02x", state->session_key[i]);
+               printk(KERN_DEBUG
+                      "%s[%d]: keys: master: %s initial session: %s\n",
+                      debugstr, unit, mkey, skey);
+       }
+
+       /*
+        * Initialize the coherency count.  The initial value is not specified
+        * in RFC 3078, but we can make a reasonable assumption that it will
+        * start at 0.  Setting it to the max here makes the comp/decomp code
+        * do the right thing (determined through experiment).
+        */
+       state->ccount = MPPE_CCOUNT_SPACE - 1;
+
+       /*
+        * Note that even though we have initialized the key table, we don't
+        * set the FLUSHED bit.  This is contrary to RFC 3078, sec. 3.1.
+        */
+       state->bits = MPPE_BIT_ENCRYPTED;
+
+       state->unit = unit;
+       state->debug = debug;
+
+       return 1;
+}
+
+static int
+mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit,
+              int hdrlen, int debug)
+{
+       /* ARGSUSED */
+       return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init");
+}
+
+/*
+ * We received a CCP Reset-Request (actually, we are sending a Reset-Ack),
+ * tell the compressor to rekey.  Note that we MUST NOT rekey for
+ * every CCP Reset-Request; we only rekey on the next xmit packet.
+ * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost.
+ * So, rekeying for every CCP Reset-Request is broken as the peer will not
+ * know how many times we've rekeyed.  (If we rekey and THEN get another
+ * CCP Reset-Request, we must rekey again.)
+ */
+static void mppe_comp_reset(void *arg)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+
+       state->bits |= MPPE_BIT_FLUSHED;
+}
+
+/*
+ * Compress (encrypt) a packet.
+ * It's strange to call this a compressor, since the output is always
+ * MPPE_OVHD + 2 bytes larger than the input.
+ */
+static int
+mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
+             int isize, int osize)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+       struct blkcipher_desc desc = { .tfm = state->arc4 };
+       int proto;
+       struct scatterlist sg_in[1], sg_out[1];
+
+       /*
+        * Check that the protocol is in the range we handle.
+        */
+       proto = PPP_PROTOCOL(ibuf);
+       if (proto < 0x0021 || proto > 0x00fa)
+               return 0;
+
+       /* Make sure we have enough room to generate an encrypted packet. */
+       if (osize < isize + MPPE_OVHD + 2) {
+               /* Drop the packet if we should encrypt it, but can't. */
+               printk(KERN_DEBUG "mppe_compress[%d]: osize too small! "
+                      "(have: %d need: %d)\n", state->unit,
+                      osize, osize + MPPE_OVHD + 2);
+               return -1;
+       }
+
+       osize = isize + MPPE_OVHD + 2;
+
+       /*
+        * Copy over the PPP header and set control bits.
+        */
+       obuf[0] = PPP_ADDRESS(ibuf);
+       obuf[1] = PPP_CONTROL(ibuf);
+       put_unaligned_be16(PPP_COMP, obuf + 2);
+       obuf += PPP_HDRLEN;
+
+       state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
+       if (state->debug >= 7)
+               printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,
+                      state->ccount);
+       put_unaligned_be16(state->ccount, obuf);
+
+       if (!state->stateful || /* stateless mode     */
+           ((state->ccount & 0xff) == 0xff) || /* "flag" packet      */
+           (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request  */
+               /* We must rekey */
+               if (state->debug && state->stateful)
+                       printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n",
+                              state->unit);
+               mppe_rekey(state, 0);
+               state->bits |= MPPE_BIT_FLUSHED;
+       }
+       obuf[0] |= state->bits;
+       state->bits &= ~MPPE_BIT_FLUSHED;       /* reset for next xmit */
+
+       obuf += MPPE_OVHD;
+       ibuf += 2;              /* skip to proto field */
+       isize -= 2;
+
+       /* Encrypt packet */
+       sg_init_table(sg_in, 1);
+       sg_init_table(sg_out, 1);
+       setup_sg(sg_in, ibuf, isize);
+       setup_sg(sg_out, obuf, osize);
+       if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) {
+               printk(KERN_DEBUG "crypto_cypher_encrypt failed\n");
+               return -1;
+       }
+
+       state->stats.unc_bytes += isize;
+       state->stats.unc_packets++;
+       state->stats.comp_bytes += osize;
+       state->stats.comp_packets++;
+
+       return osize;
+}
+
+/*
+ * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going
+ * to look bad ... and the longer the link is up the worse it will get.
+ */
+static void mppe_comp_stats(void *arg, struct compstat *stats)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+
+       *stats = state->stats;
+}
+
+static int
+mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit,
+                int hdrlen, int mru, int debug)
+{
+       /* ARGSUSED */
+       return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init");
+}
+
+/*
+ * We received a CCP Reset-Ack.  Just ignore it.
+ */
+static void mppe_decomp_reset(void *arg)
+{
+       /* ARGSUSED */
+       return;
+}
+
+/*
+ * Decompress (decrypt) an MPPE packet.
+ */
+static int
+mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
+               int osize)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+       struct blkcipher_desc desc = { .tfm = state->arc4 };
+       unsigned ccount;
+       int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
+       int sanity = 0;
+       struct scatterlist sg_in[1], sg_out[1];
+
+       if (isize <= PPP_HDRLEN + MPPE_OVHD) {
+               if (state->debug)
+                       printk(KERN_DEBUG
+                              "mppe_decompress[%d]: short pkt (%d)\n",
+                              state->unit, isize);
+               return DECOMP_ERROR;
+       }
+
+       /*
+        * Make sure we have enough room to decrypt the packet.
+        * Note that for our test we only subtract 1 byte whereas in
+        * mppe_compress() we added 2 bytes (+MPPE_OVHD);
+        * this is to account for possible PFC.
+        */
+       if (osize < isize - MPPE_OVHD - 1) {
+               printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! "
+                      "(have: %d need: %d)\n", state->unit,
+                      osize, isize - MPPE_OVHD - 1);
+               return DECOMP_ERROR;
+       }
+       osize = isize - MPPE_OVHD - 2;  /* assume no PFC */
+
+       ccount = MPPE_CCOUNT(ibuf);
+       if (state->debug >= 7)
+               printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n",
+                      state->unit, ccount);
+
+       /* sanity checks -- terminate with extreme prejudice */
+       if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
+               printk(KERN_DEBUG
+                      "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
+                      state->unit);
+               state->sanity_errors += 100;
+               sanity = 1;
+       }
+       if (!state->stateful && !flushed) {
+               printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
+                      "stateless mode!\n", state->unit);
+               state->sanity_errors += 100;
+               sanity = 1;
+       }
+       if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
+               printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
+                      "flag packet!\n", state->unit);
+               state->sanity_errors += 100;
+               sanity = 1;
+       }
+
+       if (sanity) {
+               if (state->sanity_errors < SANITY_MAX)
+                       return DECOMP_ERROR;
+               else
+                       /*
+                        * Take LCP down if the peer is sending too many bogons.
+                        * We don't want to do this for a single or just a few
+                        * instances since it could just be due to packet corruption.
+                        */
+                       return DECOMP_FATALERROR;
+       }
+
+       /*
+        * Check the coherency count.
+        */
+
+       if (!state->stateful) {
+               /* RFC 3078, sec 8.1.  Rekey for every packet. */
+               while (state->ccount != ccount) {
+                       mppe_rekey(state, 0);
+                       state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
+               }
+       } else {
+               /* RFC 3078, sec 8.2. */
+               if (!state->discard) {
+                       /* normal state */
+                       state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
+                       if (ccount != state->ccount) {
+                               /*
+                                * (ccount > state->ccount)
+                                * Packet loss detected, enter the discard state.
+                                * Signal the peer to rekey (by sending a CCP Reset-Request).
+                                */
+                               state->discard = 1;
+                               return DECOMP_ERROR;
+                       }
+               } else {
+                       /* discard state */
+                       if (!flushed) {
+                               /* ccp.c will be silent (no additional CCP Reset-Requests). */
+                               return DECOMP_ERROR;
+                       } else {
+                               /* Rekey for every missed "flag" packet. */
+                               while ((ccount & ~0xff) !=
+                                      (state->ccount & ~0xff)) {
+                                       mppe_rekey(state, 0);
+                                       state->ccount =
+                                           (state->ccount +
+                                            256) % MPPE_CCOUNT_SPACE;
+                               }
+
+                               /* reset */
+                               state->discard = 0;
+                               state->ccount = ccount;
+                               /*
+                                * Another problem with RFC 3078 here.  It implies that the
+                                * peer need not send a Reset-Ack packet.  But RFC 1962
+                                * requires it.  Hopefully, M$ does send a Reset-Ack; even
+                                * though it isn't required for MPPE synchronization, it is
+                                * required to reset CCP state.
+                                */
+                       }
+               }
+               if (flushed)
+                       mppe_rekey(state, 0);
+       }
+
+       /*
+        * Fill in the first part of the PPP header.  The protocol field
+        * comes from the decrypted data.
+        */
+       obuf[0] = PPP_ADDRESS(ibuf);    /* +1 */
+       obuf[1] = PPP_CONTROL(ibuf);    /* +1 */
+       obuf += 2;
+       ibuf += PPP_HDRLEN + MPPE_OVHD;
+       isize -= PPP_HDRLEN + MPPE_OVHD;        /* -6 */
+       /* net osize: isize-4 */
+
+       /*
+        * Decrypt the first byte in order to check if it is
+        * a compressed or uncompressed protocol field.
+        */
+       sg_init_table(sg_in, 1);
+       sg_init_table(sg_out, 1);
+       setup_sg(sg_in, ibuf, 1);
+       setup_sg(sg_out, obuf, 1);
+       if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) {
+               printk(KERN_DEBUG "crypto_cypher_decrypt failed\n");
+               return DECOMP_ERROR;
+       }
+
+       /*
+        * Do PFC decompression.
+        * This would be nicer if we were given the actual sk_buff
+        * instead of a char *.
+        */
+       if ((obuf[0] & 0x01) != 0) {
+               obuf[1] = obuf[0];
+               obuf[0] = 0;
+               obuf++;
+               osize++;
+       }
+
+       /* And finally, decrypt the rest of the packet. */
+       setup_sg(sg_in, ibuf + 1, isize - 1);
+       setup_sg(sg_out, obuf + 1, osize - 1);
+       if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, isize - 1)) {
+               printk(KERN_DEBUG "crypto_cypher_decrypt failed\n");
+               return DECOMP_ERROR;
+       }
+
+       state->stats.unc_bytes += osize;
+       state->stats.unc_packets++;
+       state->stats.comp_bytes += isize;
+       state->stats.comp_packets++;
+
+       /* good packet credit */
+       state->sanity_errors >>= 1;
+
+       return osize;
+}
+
+/*
+ * Incompressible data has arrived (this should never happen!).
+ * We should probably drop the link if the protocol is in the range
+ * of what should be encrypted.  At the least, we should drop this
+ * packet.  (How to do this?)
+ */
+static void mppe_incomp(void *arg, unsigned char *ibuf, int icnt)
+{
+       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
+
+       if (state->debug &&
+           (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa))
+               printk(KERN_DEBUG
+                      "mppe_incomp[%d]: incompressible (unencrypted) data! "
+                      "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf));
+
+       state->stats.inc_bytes += icnt;
+       state->stats.inc_packets++;
+       state->stats.unc_bytes += icnt;
+       state->stats.unc_packets++;
+}
+
+/*************************************************************
+ * Module interface table
+ *************************************************************/
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+static struct compressor ppp_mppe = {
+       .compress_proto = CI_MPPE,
+       .comp_alloc     = mppe_alloc,
+       .comp_free      = mppe_free,
+       .comp_init      = mppe_comp_init,
+       .comp_reset     = mppe_comp_reset,
+       .compress       = mppe_compress,
+       .comp_stat      = mppe_comp_stats,
+       .decomp_alloc   = mppe_alloc,
+       .decomp_free    = mppe_free,
+       .decomp_init    = mppe_decomp_init,
+       .decomp_reset   = mppe_decomp_reset,
+       .decompress     = mppe_decompress,
+       .incomp         = mppe_incomp,
+       .decomp_stat    = mppe_comp_stats,
+       .owner          = THIS_MODULE,
+       .comp_extra     = MPPE_PAD,
+};
+
+/*
+ * ppp_mppe_init()
+ *
+ * Prior to allowing load, try to load the arc4 and sha1 crypto
+ * libraries.  The actual use will be allocated later, but
+ * this way the module will fail to insmod if they aren't available.
+ */
+
+static int __init ppp_mppe_init(void)
+{
+       int answer;
+       if (!(crypto_has_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) &&
+             crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC)))
+               return -ENODEV;
+
+       sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL);
+       if (!sha_pad)
+               return -ENOMEM;
+       sha_pad_init(sha_pad);
+
+       answer = ppp_register_compressor(&ppp_mppe);
+
+       if (answer == 0)
+               printk(KERN_INFO "PPP MPPE Compression module registered\n");
+       else
+               kfree(sha_pad);
+
+       return answer;
+}
+
+static void __exit ppp_mppe_cleanup(void)
+{
+       ppp_unregister_compressor(&ppp_mppe);
+       kfree(sha_pad);
+}
+
+module_init(ppp_mppe_init);
+module_exit(ppp_mppe_cleanup);
diff --git a/drivers/net/ppp/ppp_mppe.h b/drivers/net/ppp/ppp_mppe.h
new file mode 100644 (file)
index 0000000..7a14e05
--- /dev/null
@@ -0,0 +1,86 @@
+#define MPPE_PAD                4      /* MPPE growth per frame */
+#define MPPE_MAX_KEY_LEN       16      /* largest key length (128-bit) */
+
+/* option bits for ccp_options.mppe */
+#define MPPE_OPT_40            0x01    /* 40 bit */
+#define MPPE_OPT_128           0x02    /* 128 bit */
+#define MPPE_OPT_STATEFUL      0x04    /* stateful mode */
+/* unsupported opts */
+#define MPPE_OPT_56            0x08    /* 56 bit */
+#define MPPE_OPT_MPPC          0x10    /* MPPC compression */
+#define MPPE_OPT_D             0x20    /* Unknown */
+#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
+#define MPPE_OPT_UNKNOWN       0x40    /* Bits !defined in RFC 3078 were set */
+
+/*
+ * This is not nice ... the alternative is a bitfield struct though.
+ * And unfortunately, we cannot share the same bits for the option
+ * names above since C and H are the same bit.  We could do a u_int32
+ * but then we have to do a htonl() all the time and/or we still need
+ * to know which octet is which.
+ */
+#define MPPE_C_BIT             0x01    /* MPPC */
+#define MPPE_D_BIT             0x10    /* Obsolete, usage unknown */
+#define MPPE_L_BIT             0x20    /* 40-bit */
+#define MPPE_S_BIT             0x40    /* 128-bit */
+#define MPPE_M_BIT             0x80    /* 56-bit, not supported */
+#define MPPE_H_BIT             0x01    /* Stateless (in a different byte) */
+
+/* Does not include H bit; used for least significant octet only. */
+#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
+
+/* Build a CI from mppe opts (see RFC 3078) */
+#define MPPE_OPTS_TO_CI(opts, ci)              \
+    do {                                       \
+       u_char *ptr = ci; /* u_char[4] */       \
+                                               \
+       /* H bit */                             \
+       if (opts & MPPE_OPT_STATEFUL)           \
+           *ptr++ = 0x0;                       \
+       else                                    \
+           *ptr++ = MPPE_H_BIT;                \
+       *ptr++ = 0;                             \
+       *ptr++ = 0;                             \
+                                               \
+       /* S,L bits */                          \
+       *ptr = 0;                               \
+       if (opts & MPPE_OPT_128)                \
+           *ptr |= MPPE_S_BIT;                 \
+       if (opts & MPPE_OPT_40)                 \
+           *ptr |= MPPE_L_BIT;                 \
+       /* M,D,C bits not supported */          \
+    } while (/* CONSTCOND */ 0)
+
+/* The reverse of the above */
+#define MPPE_CI_TO_OPTS(ci, opts)              \
+    do {                                       \
+       u_char *ptr = ci; /* u_char[4] */       \
+                                               \
+       opts = 0;                               \
+                                               \
+       /* H bit */                             \
+       if (!(ptr[0] & MPPE_H_BIT))             \
+           opts |= MPPE_OPT_STATEFUL;          \
+                                               \
+       /* S,L bits */                          \
+       if (ptr[3] & MPPE_S_BIT)                \
+           opts |= MPPE_OPT_128;               \
+       if (ptr[3] & MPPE_L_BIT)                \
+           opts |= MPPE_OPT_40;                \
+                                               \
+       /* M,D,C bits */                        \
+       if (ptr[3] & MPPE_M_BIT)                \
+           opts |= MPPE_OPT_56;                \
+       if (ptr[3] & MPPE_D_BIT)                \
+           opts |= MPPE_OPT_D;                 \
+       if (ptr[3] & MPPE_C_BIT)                \
+           opts |= MPPE_OPT_MPPC;              \
+                                               \
+       /* Other bits */                        \
+       if (ptr[0] & ~MPPE_H_BIT)               \
+           opts |= MPPE_OPT_UNKNOWN;           \
+       if (ptr[1] || ptr[2])                   \
+           opts |= MPPE_OPT_UNKNOWN;           \
+       if (ptr[3] & ~MPPE_ALL_BITS)            \
+           opts |= MPPE_OPT_UNKNOWN;           \
+    } while (/* CONSTCOND */ 0)
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
new file mode 100644 (file)
index 0000000..736a39e
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ * PPP synchronous tty channel driver for Linux.
+ *
+ * This is a ppp channel driver that can be used with tty device drivers
+ * that are frame oriented, such as synchronous HDLC devices.
+ *
+ * Complete PPP frames without encoding/decoding are exchanged between
+ * the channel driver and the device driver.
+ *
+ * The async map IOCTL codes are implemented to keep the user mode
+ * applications happy if they call them. Synchronous PPP does not use
+ * the async maps.
+ *
+ * Copyright 1999 Paul Mackerras.
+ *
+ * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.com
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ * This driver provides the encapsulation and framing for sending
+ * and receiving PPP frames over sync serial lines.  It relies on
+ * the generic PPP layer to give it frames to send and to process
+ * received frames.  It implements the PPP line discipline.
+ *
+ * Part of the code in this driver was inspired by the old async-only
+ * PPP driver, written by Michael Callahan and Al Longyear, and
+ * subsequently hacked by Paul Mackerras.
+ *
+ * ==FILEVERSION 20040616==
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/tty.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <asm/uaccess.h>
+
+#define PPP_VERSION    "2.4.2"
+
+/* Structure for storing local state. */
+struct syncppp {
+       struct tty_struct *tty;
+       unsigned int    flags;
+       unsigned int    rbits;
+       int             mru;
+       spinlock_t      xmit_lock;
+       spinlock_t      recv_lock;
+       unsigned long   xmit_flags;
+       u32             xaccm[8];
+       u32             raccm;
+       unsigned int    bytes_sent;
+       unsigned int    bytes_rcvd;
+
+       struct sk_buff  *tpkt;
+       unsigned long   last_xmit;
+
+       struct sk_buff_head rqueue;
+
+       struct tasklet_struct tsk;
+
+       atomic_t        refcnt;
+       struct completion dead_cmp;
+       struct ppp_channel chan;        /* interface to generic ppp layer */
+};
+
+/* Bit numbers in xmit_flags */
+#define XMIT_WAKEUP    0
+#define XMIT_FULL      1
+
+/* Bits in rbits */
+#define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define PPPSYNC_MAX_RQLEN      32      /* arbitrary */
+
+/*
+ * Prototypes.
+ */
+static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *);
+static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
+static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
+                         unsigned long arg);
+static void ppp_sync_process(unsigned long arg);
+static int ppp_sync_push(struct syncppp *ap);
+static void ppp_sync_flush_output(struct syncppp *ap);
+static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+                          char *flags, int count);
+
+static const struct ppp_channel_ops sync_ops = {
+       .start_xmit = ppp_sync_send,
+       .ioctl      = ppp_sync_ioctl,
+};
+
+/*
+ * Utility procedures to print a buffer in hex/ascii
+ */
+static void
+ppp_print_hex (register __u8 * out, const __u8 * in, int count)
+{
+       register __u8 next_ch;
+       static const char hex[] = "0123456789ABCDEF";
+
+       while (count-- > 0) {
+               next_ch = *in++;
+               *out++ = hex[(next_ch >> 4) & 0x0F];
+               *out++ = hex[next_ch & 0x0F];
+               ++out;
+       }
+}
+
+static void
+ppp_print_char (register __u8 * out, const __u8 * in, int count)
+{
+       register __u8 next_ch;
+
+       while (count-- > 0) {
+               next_ch = *in++;
+
+               if (next_ch < 0x20 || next_ch > 0x7e)
+                       *out++ = '.';
+               else {
+                       *out++ = next_ch;
+                       if (next_ch == '%')   /* printk/syslogd has a bug !! */
+                               *out++ = '%';
+               }
+       }
+       *out = '\0';
+}
+
+static void
+ppp_print_buffer (const char *name, const __u8 *buf, int count)
+{
+       __u8 line[44];
+
+       if (name != NULL)
+               printk(KERN_DEBUG "ppp_synctty: %s, count = %d\n", name, count);
+
+       while (count > 8) {
+               memset (line, 32, 44);
+               ppp_print_hex (line, buf, 8);
+               ppp_print_char (&line[8 * 3], buf, 8);
+               printk(KERN_DEBUG "%s\n", line);
+               count -= 8;
+               buf += 8;
+       }
+
+       if (count > 0) {
+               memset (line, 32, 44);
+               ppp_print_hex (line, buf, count);
+               ppp_print_char (&line[8 * 3], buf, count);
+               printk(KERN_DEBUG "%s\n", line);
+       }
+}
+
+
+/*
+ * Routines implementing the synchronous PPP line discipline.
+ */
+
+/*
+ * We have a potential race on dereferencing tty->disc_data,
+ * because the tty layer provides no locking at all - thus one
+ * cpu could be running ppp_synctty_receive while another
+ * calls ppp_synctty_close, which zeroes tty->disc_data and
+ * frees the memory that ppp_synctty_receive is using.  The best
+ * way to fix this is to use a rwlock in the tty struct, but for now
+ * we use a single global rwlock for all ttys in ppp line discipline.
+ *
+ * FIXME: Fixed in tty_io nowadays.
+ */
+static DEFINE_RWLOCK(disc_data_lock);
+
+static struct syncppp *sp_get(struct tty_struct *tty)
+{
+       struct syncppp *ap;
+
+       read_lock(&disc_data_lock);
+       ap = tty->disc_data;
+       if (ap != NULL)
+               atomic_inc(&ap->refcnt);
+       read_unlock(&disc_data_lock);
+       return ap;
+}
+
+static void sp_put(struct syncppp *ap)
+{
+       if (atomic_dec_and_test(&ap->refcnt))
+               complete(&ap->dead_cmp);
+}
+
+/*
+ * Called when a tty is put into sync-PPP line discipline.
+ */
+static int
+ppp_sync_open(struct tty_struct *tty)
+{
+       struct syncppp *ap;
+       int err;
+       int speed;
+
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
+       ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+       err = -ENOMEM;
+       if (!ap)
+               goto out;
+
+       /* initialize the syncppp structure */
+       ap->tty = tty;
+       ap->mru = PPP_MRU;
+       spin_lock_init(&ap->xmit_lock);
+       spin_lock_init(&ap->recv_lock);
+       ap->xaccm[0] = ~0U;
+       ap->xaccm[3] = 0x60000000U;
+       ap->raccm = ~0U;
+
+       skb_queue_head_init(&ap->rqueue);
+       tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
+
+       atomic_set(&ap->refcnt, 1);
+       init_completion(&ap->dead_cmp);
+
+       ap->chan.private = ap;
+       ap->chan.ops = &sync_ops;
+       ap->chan.mtu = PPP_MRU;
+       ap->chan.hdrlen = 2;    /* for A/C bytes */
+       speed = tty_get_baud_rate(tty);
+       ap->chan.speed = speed;
+       err = ppp_register_channel(&ap->chan);
+       if (err)
+               goto out_free;
+
+       tty->disc_data = ap;
+       tty->receive_room = 65536;
+       return 0;
+
+ out_free:
+       kfree(ap);
+ out:
+       return err;
+}
+
+/*
+ * Called when the tty is put into another line discipline
+ * or it hangs up.  We have to wait for any cpu currently
+ * executing in any of the other ppp_synctty_* routines to
+ * finish before we can call ppp_unregister_channel and free
+ * the syncppp struct.  This routine must be called from
+ * process context, not interrupt or softirq context.
+ */
+static void
+ppp_sync_close(struct tty_struct *tty)
+{
+       struct syncppp *ap;
+
+       write_lock_irq(&disc_data_lock);
+       ap = tty->disc_data;
+       tty->disc_data = NULL;
+       write_unlock_irq(&disc_data_lock);
+       if (!ap)
+               return;
+
+       /*
+        * We have now ensured that nobody can start using ap from now
+        * on, but we have to wait for all existing users to finish.
+        * Note that ppp_unregister_channel ensures that no calls to
+        * our channel ops (i.e. ppp_sync_send/ioctl) are in progress
+        * by the time it returns.
+        */
+       if (!atomic_dec_and_test(&ap->refcnt))
+               wait_for_completion(&ap->dead_cmp);
+       tasklet_kill(&ap->tsk);
+
+       ppp_unregister_channel(&ap->chan);
+       skb_queue_purge(&ap->rqueue);
+       kfree_skb(ap->tpkt);
+       kfree(ap);
+}
+
+/*
+ * Called on tty hangup in process context.
+ *
+ * Wait for I/O to driver to complete and unregister PPP channel.
+ * This is already done by the close routine, so just call that.
+ */
+static int ppp_sync_hangup(struct tty_struct *tty)
+{
+       ppp_sync_close(tty);
+       return 0;
+}
+
+/*
+ * Read does nothing - no data is ever available this way.
+ * Pppd reads and writes packets via /dev/ppp instead.
+ */
+static ssize_t
+ppp_sync_read(struct tty_struct *tty, struct file *file,
+              unsigned char __user *buf, size_t count)
+{
+       return -EAGAIN;
+}
+
+/*
+ * Write on the tty does nothing, the packets all come in
+ * from the ppp generic stuff.
+ */
+static ssize_t
+ppp_sync_write(struct tty_struct *tty, struct file *file,
+               const unsigned char *buf, size_t count)
+{
+       return -EAGAIN;
+}
+
+static int
+ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
+                 unsigned int cmd, unsigned long arg)
+{
+       struct syncppp *ap = sp_get(tty);
+       int __user *p = (int __user *)arg;
+       int err, val;
+
+       if (!ap)
+               return -ENXIO;
+       err = -EFAULT;
+       switch (cmd) {
+       case PPPIOCGCHAN:
+               err = -EFAULT;
+               if (put_user(ppp_channel_index(&ap->chan), p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGUNIT:
+               err = -EFAULT;
+               if (put_user(ppp_unit_number(&ap->chan), p))
+                       break;
+               err = 0;
+               break;
+
+       case TCFLSH:
+               /* flush our buffers and the serial port's buffer */
+               if (arg == TCIOFLUSH || arg == TCOFLUSH)
+                       ppp_sync_flush_output(ap);
+               err = tty_perform_flush(tty, arg);
+               break;
+
+       case FIONREAD:
+               val = 0;
+               if (put_user(val, p))
+                       break;
+               err = 0;
+               break;
+
+       default:
+               err = tty_mode_ioctl(tty, file, cmd, arg);
+               break;
+       }
+
+       sp_put(ap);
+       return err;
+}
+
+/* No kernel lock - fine */
+static unsigned int
+ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
+{
+       return 0;
+}
+
+/* May sleep, don't call from interrupt level or with interrupts disabled */
+static void
+ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
+                 char *cflags, int count)
+{
+       struct syncppp *ap = sp_get(tty);
+       unsigned long flags;
+
+       if (!ap)
+               return;
+       spin_lock_irqsave(&ap->recv_lock, flags);
+       ppp_sync_input(ap, buf, cflags, count);
+       spin_unlock_irqrestore(&ap->recv_lock, flags);
+       if (!skb_queue_empty(&ap->rqueue))
+               tasklet_schedule(&ap->tsk);
+       sp_put(ap);
+       tty_unthrottle(tty);
+}
+
+static void
+ppp_sync_wakeup(struct tty_struct *tty)
+{
+       struct syncppp *ap = sp_get(tty);
+
+       clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+       if (!ap)
+               return;
+       set_bit(XMIT_WAKEUP, &ap->xmit_flags);
+       tasklet_schedule(&ap->tsk);
+       sp_put(ap);
+}
+
+
+static struct tty_ldisc_ops ppp_sync_ldisc = {
+       .owner  = THIS_MODULE,
+       .magic  = TTY_LDISC_MAGIC,
+       .name   = "pppsync",
+       .open   = ppp_sync_open,
+       .close  = ppp_sync_close,
+       .hangup = ppp_sync_hangup,
+       .read   = ppp_sync_read,
+       .write  = ppp_sync_write,
+       .ioctl  = ppp_synctty_ioctl,
+       .poll   = ppp_sync_poll,
+       .receive_buf = ppp_sync_receive,
+       .write_wakeup = ppp_sync_wakeup,
+};
+
+static int __init
+ppp_sync_init(void)
+{
+       int err;
+
+       err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc);
+       if (err != 0)
+               printk(KERN_ERR "PPP_sync: error %d registering line disc.\n",
+                      err);
+       return err;
+}
+
+/*
+ * The following routines provide the PPP channel interface.
+ */
+static int
+ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
+{
+       struct syncppp *ap = chan->private;
+       int err, val;
+       u32 accm[8];
+       void __user *argp = (void __user *)arg;
+       u32 __user *p = argp;
+
+       err = -EFAULT;
+       switch (cmd) {
+       case PPPIOCGFLAGS:
+               val = ap->flags | ap->rbits;
+               if (put_user(val, (int __user *) argp))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSFLAGS:
+               if (get_user(val, (int __user *) argp))
+                       break;
+               ap->flags = val & ~SC_RCV_BITS;
+               spin_lock_irq(&ap->recv_lock);
+               ap->rbits = val & SC_RCV_BITS;
+               spin_unlock_irq(&ap->recv_lock);
+               err = 0;
+               break;
+
+       case PPPIOCGASYNCMAP:
+               if (put_user(ap->xaccm[0], p))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSASYNCMAP:
+               if (get_user(ap->xaccm[0], p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGRASYNCMAP:
+               if (put_user(ap->raccm, p))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSRASYNCMAP:
+               if (get_user(ap->raccm, p))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCGXASYNCMAP:
+               if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSXASYNCMAP:
+               if (copy_from_user(accm, argp, sizeof(accm)))
+                       break;
+               accm[2] &= ~0x40000000U;        /* can't escape 0x5e */
+               accm[3] |= 0x60000000U;         /* must escape 0x7d, 0x7e */
+               memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
+               err = 0;
+               break;
+
+       case PPPIOCGMRU:
+               if (put_user(ap->mru, (int __user *) argp))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSMRU:
+               if (get_user(val, (int __user *) argp))
+                       break;
+               if (val < PPP_MRU)
+                       val = PPP_MRU;
+               ap->mru = val;
+               err = 0;
+               break;
+
+       default:
+               err = -ENOTTY;
+       }
+       return err;
+}
+
+/*
+ * This is called at softirq level to deliver received packets
+ * to the ppp_generic code, and to tell the ppp_generic code
+ * if we can accept more output now.
+ */
+static void ppp_sync_process(unsigned long arg)
+{
+       struct syncppp *ap = (struct syncppp *) arg;
+       struct sk_buff *skb;
+
+       /* process received packets */
+       while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
+               if (skb->len == 0) {
+                       /* zero length buffers indicate error */
+                       ppp_input_error(&ap->chan, 0);
+                       kfree_skb(skb);
+               }
+               else
+                       ppp_input(&ap->chan, skb);
+       }
+
+       /* try to push more stuff out */
+       if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_sync_push(ap))
+               ppp_output_wakeup(&ap->chan);
+}
+
+/*
+ * Procedures for encapsulation and framing.
+ */
+
+static struct sk_buff*
+ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
+{
+       int proto;
+       unsigned char *data;
+       int islcp;
+
+       data  = skb->data;
+       proto = get_unaligned_be16(data);
+
+       /* LCP packets with codes between 1 (configure-request)
+        * and 7 (code-reject) must be sent as though no options
+        * have been negotiated.
+        */
+       islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+       /* compress protocol field if option enabled */
+       if (data[0] == 0 && (ap->flags & SC_COMP_PROT) && !islcp)
+               skb_pull(skb,1);
+
+       /* prepend address/control fields if necessary */
+       if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
+               if (skb_headroom(skb) < 2) {
+                       struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
+                       if (npkt == NULL) {
+                               kfree_skb(skb);
+                               return NULL;
+                       }
+                       skb_reserve(npkt,2);
+                       skb_copy_from_linear_data(skb,
+                                     skb_put(npkt, skb->len), skb->len);
+                       kfree_skb(skb);
+                       skb = npkt;
+               }
+               skb_push(skb,2);
+               skb->data[0] = PPP_ALLSTATIONS;
+               skb->data[1] = PPP_UI;
+       }
+
+       ap->last_xmit = jiffies;
+
+       if (skb && ap->flags & SC_LOG_OUTPKT)
+               ppp_print_buffer ("send buffer", skb->data, skb->len);
+
+       return skb;
+}
+
+/*
+ * Transmit-side routines.
+ */
+
+/*
+ * Send a packet to the peer over an sync tty line.
+ * Returns 1 iff the packet was accepted.
+ * If the packet was not accepted, we will call ppp_output_wakeup
+ * at some later time.
+ */
+static int
+ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb)
+{
+       struct syncppp *ap = chan->private;
+
+       ppp_sync_push(ap);
+
+       if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
+               return 0;       /* already full */
+       skb = ppp_sync_txmunge(ap, skb);
+       if (skb != NULL)
+               ap->tpkt = skb;
+       else
+               clear_bit(XMIT_FULL, &ap->xmit_flags);
+
+       ppp_sync_push(ap);
+       return 1;
+}
+
+/*
+ * Push as much data as possible out to the tty.
+ */
+static int
+ppp_sync_push(struct syncppp *ap)
+{
+       int sent, done = 0;
+       struct tty_struct *tty = ap->tty;
+       int tty_stuffed = 0;
+
+       if (!spin_trylock_bh(&ap->xmit_lock))
+               return 0;
+       for (;;) {
+               if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
+                       tty_stuffed = 0;
+               if (!tty_stuffed && ap->tpkt) {
+                       set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+                       sent = tty->ops->write(tty, ap->tpkt->data, ap->tpkt->len);
+                       if (sent < 0)
+                               goto flush;     /* error, e.g. loss of CD */
+                       if (sent < ap->tpkt->len) {
+                               tty_stuffed = 1;
+                       } else {
+                               kfree_skb(ap->tpkt);
+                               ap->tpkt = NULL;
+                               clear_bit(XMIT_FULL, &ap->xmit_flags);
+                               done = 1;
+                       }
+                       continue;
+               }
+               /* haven't made any progress */
+               spin_unlock_bh(&ap->xmit_lock);
+               if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||
+                     (!tty_stuffed && ap->tpkt)))
+                       break;
+               if (!spin_trylock_bh(&ap->xmit_lock))
+                       break;
+       }
+       return done;
+
+flush:
+       if (ap->tpkt) {
+               kfree_skb(ap->tpkt);
+               ap->tpkt = NULL;
+               clear_bit(XMIT_FULL, &ap->xmit_flags);
+               done = 1;
+       }
+       spin_unlock_bh(&ap->xmit_lock);
+       return done;
+}
+
+/*
+ * Flush output from our internal buffers.
+ * Called for the TCFLSH ioctl.
+ */
+static void
+ppp_sync_flush_output(struct syncppp *ap)
+{
+       int done = 0;
+
+       spin_lock_bh(&ap->xmit_lock);
+       if (ap->tpkt != NULL) {
+               kfree_skb(ap->tpkt);
+               ap->tpkt = NULL;
+               clear_bit(XMIT_FULL, &ap->xmit_flags);
+               done = 1;
+       }
+       spin_unlock_bh(&ap->xmit_lock);
+       if (done)
+               ppp_output_wakeup(&ap->chan);
+}
+
+/*
+ * Receive-side routines.
+ */
+
+/* called when the tty driver has data for us.
+ *
+ * Data is frame oriented: each call to ppp_sync_input is considered
+ * a whole frame. If the 1st flag byte is non-zero then the whole
+ * frame is considered to be in error and is tossed.
+ */
+static void
+ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+               char *flags, int count)
+{
+       struct sk_buff *skb;
+       unsigned char *p;
+
+       if (count == 0)
+               return;
+
+       if (ap->flags & SC_LOG_INPKT)
+               ppp_print_buffer ("receive buffer", buf, count);
+
+       /* stuff the chars in the skb */
+       skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
+       if (!skb) {
+               printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
+               goto err;
+       }
+       /* Try to get the payload 4-byte aligned */
+       if (buf[0] != PPP_ALLSTATIONS)
+               skb_reserve(skb, 2 + (buf[0] & 1));
+
+       if (flags && *flags) {
+               /* error flag set, ignore frame */
+               goto err;
+       } else if (count > skb_tailroom(skb)) {
+               /* packet overflowed MRU */
+               goto err;
+       }
+
+       p = skb_put(skb, count);
+       memcpy(p, buf, count);
+
+       /* strip address/control field if present */
+       p = skb->data;
+       if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+               /* chop off address/control */
+               if (skb->len < 3)
+                       goto err;
+               p = skb_pull(skb, 2);
+       }
+
+       /* decompress protocol field if compressed */
+       if (p[0] & 1) {
+               /* protocol is compressed */
+               skb_push(skb, 1)[0] = 0;
+       } else if (skb->len < 2)
+               goto err;
+
+       /* queue the frame to be processed */
+       skb_queue_tail(&ap->rqueue, skb);
+       return;
+
+err:
+       /* queue zero length packet as error indication */
+       if (skb || (skb = dev_alloc_skb(0))) {
+               skb_trim(skb, 0);
+               skb_queue_tail(&ap->rqueue, skb);
+       }
+}
+
+static void __exit
+ppp_sync_cleanup(void)
+{
+       if (tty_unregister_ldisc(N_SYNC_PPP) != 0)
+               printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
+}
+
+module_init(ppp_sync_init);
+module_exit(ppp_sync_cleanup);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_LDISC(N_SYNC_PPP);
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
new file mode 100644 (file)
index 0000000..bc9a4bb
--- /dev/null
@@ -0,0 +1,1208 @@
+/** -*- linux-c -*- ***********************************************************
+ * Linux PPP over Ethernet (PPPoX/PPPoE) Sockets
+ *
+ * PPPoX --- Generic PPP encapsulation socket family
+ * PPPoE --- PPP over Ethernet (RFC 2516)
+ *
+ *
+ * Version:    0.7.0
+ *
+ * 070228 :    Fix to allow multiple sessions with same remote MAC and same
+ *             session id by including the local device ifindex in the
+ *             tuple identifying a session. This also ensures packets can't
+ *             be injected into a session from interfaces other than the one
+ *             specified by userspace. Florian Zumbiehl <florz@florz.de>
+ *             (Oh, BTW, this one is YYMMDD, in case you were wondering ...)
+ * 220102 :    Fix module use count on failure in pppoe_create, pppox_sk -acme
+ * 030700 :    Fixed connect logic to allow for disconnect.
+ * 270700 :    Fixed potential SMP problems; we must protect against
+ *             simultaneous invocation of ppp_input
+ *             and ppp_unregister_channel.
+ * 040800 :    Respect reference count mechanisms on net-devices.
+ * 200800 :    fix kfree(skb) in pppoe_rcv (acme)
+ *             Module reference count is decremented in the right spot now,
+ *             guards against sock_put not actually freeing the sk
+ *             in pppoe_release.
+ * 051000 :    Initialization cleanup.
+ * 111100 :    Fix recvmsg.
+ * 050101 :    Fix PADT procesing.
+ * 140501 :    Use pppoe_rcv_core to handle all backlog. (Alexey)
+ * 170701 :    Do not lock_sock with rwlock held. (DaveM)
+ *             Ignore discovery frames if user has socket
+ *             locked. (DaveM)
+ *             Ignore return value of dev_queue_xmit in __pppoe_xmit
+ *             or else we may kfree an SKB twice. (DaveM)
+ * 190701 :    When doing copies of skb's in __pppoe_xmit, always delete
+ *             the original skb that was passed in on success, never on
+ *             failure.  Delete the copy of the skb on failure to avoid
+ *             a memory leak.
+ * 081001 :    Misc. cleanup (licence string, non-blocking, prevent
+ *             reference of device on close).
+ * 121301 :    New ppp channels interface; cannot unregister a channel
+ *             from interrupts.  Thus, we mark the socket as a ZOMBIE
+ *             and do the unregistration later.
+ * 081002 :    seq_file support for proc stuff -acme
+ * 111602 :    Merge all 2.4 fixes into 2.5/2.6 tree.  Label 2.5/2.6
+ *             as version 0.7.  Spacing cleanup.
+ * Author:     Michal Ostrowski <mostrows@speakeasy.net>
+ * Contributors:
+ *             Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *             David S. Miller (davem@redhat.com)
+ *
+ * License:
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/if_ether.h>
+#include <linux/if_pppox.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/notifier.h>
+#include <linux/file.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/nsproxy.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include <net/sock.h>
+
+#include <asm/uaccess.h>
+
+#define PPPOE_HASH_BITS 4
+#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
+#define PPPOE_HASH_MASK        (PPPOE_HASH_SIZE - 1)
+
+static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
+
+static const struct proto_ops pppoe_ops;
+static const struct ppp_channel_ops pppoe_chan_ops;
+
+/* per-net private data for this module */
+static int pppoe_net_id __read_mostly;
+struct pppoe_net {
+       /*
+        * we could use _single_ hash table for all
+        * nets by injecting net id into the hash but
+        * it would increase hash chains and add
+        * a few additional math comparations messy
+        * as well, moreover in case of SMP less locking
+        * controversy here
+        */
+       struct pppox_sock *hash_table[PPPOE_HASH_SIZE];
+       rwlock_t hash_lock;
+};
+
+/*
+ * PPPoE could be in the following stages:
+ * 1) Discovery stage (to obtain remote MAC and Session ID)
+ * 2) Session stage (MAC and SID are known)
+ *
+ * Ethernet frames have a special tag for this but
+ * we use simpler approach based on session id
+ */
+static inline bool stage_session(__be16 sid)
+{
+       return sid != 0;
+}
+
+static inline struct pppoe_net *pppoe_pernet(struct net *net)
+{
+       BUG_ON(!net);
+
+       return net_generic(net, pppoe_net_id);
+}
+
+static inline int cmp_2_addr(struct pppoe_addr *a, struct pppoe_addr *b)
+{
+       return a->sid == b->sid && !memcmp(a->remote, b->remote, ETH_ALEN);
+}
+
+static inline int cmp_addr(struct pppoe_addr *a, __be16 sid, char *addr)
+{
+       return a->sid == sid && !memcmp(a->remote, addr, ETH_ALEN);
+}
+
+#if 8 % PPPOE_HASH_BITS
+#error 8 must be a multiple of PPPOE_HASH_BITS
+#endif
+
+static int hash_item(__be16 sid, unsigned char *addr)
+{
+       unsigned char hash = 0;
+       unsigned int i;
+
+       for (i = 0; i < ETH_ALEN; i++)
+               hash ^= addr[i];
+       for (i = 0; i < sizeof(sid_t) * 8; i += 8)
+               hash ^= (__force __u32)sid >> i;
+       for (i = 8; (i >>= 1) >= PPPOE_HASH_BITS;)
+               hash ^= hash >> i;
+
+       return hash & PPPOE_HASH_MASK;
+}
+
+/**********************************************************************
+ *
+ *  Set/get/delete/rehash items  (internal versions)
+ *
+ **********************************************************************/
+static struct pppox_sock *__get_item(struct pppoe_net *pn, __be16 sid,
+                               unsigned char *addr, int ifindex)
+{
+       int hash = hash_item(sid, addr);
+       struct pppox_sock *ret;
+
+       ret = pn->hash_table[hash];
+       while (ret) {
+               if (cmp_addr(&ret->pppoe_pa, sid, addr) &&
+                   ret->pppoe_ifindex == ifindex)
+                       return ret;
+
+               ret = ret->next;
+       }
+
+       return NULL;
+}
+
+static int __set_item(struct pppoe_net *pn, struct pppox_sock *po)
+{
+       int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+       struct pppox_sock *ret;
+
+       ret = pn->hash_table[hash];
+       while (ret) {
+               if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) &&
+                   ret->pppoe_ifindex == po->pppoe_ifindex)
+                       return -EALREADY;
+
+               ret = ret->next;
+       }
+
+       po->next = pn->hash_table[hash];
+       pn->hash_table[hash] = po;
+
+       return 0;
+}
+
+static struct pppox_sock *__delete_item(struct pppoe_net *pn, __be16 sid,
+                                       char *addr, int ifindex)
+{
+       int hash = hash_item(sid, addr);
+       struct pppox_sock *ret, **src;
+
+       ret = pn->hash_table[hash];
+       src = &pn->hash_table[hash];
+
+       while (ret) {
+               if (cmp_addr(&ret->pppoe_pa, sid, addr) &&
+                   ret->pppoe_ifindex == ifindex) {
+                       *src = ret->next;
+                       break;
+               }
+
+               src = &ret->next;
+               ret = ret->next;
+       }
+
+       return ret;
+}
+
+/**********************************************************************
+ *
+ *  Set/get/delete/rehash items
+ *
+ **********************************************************************/
+static inline struct pppox_sock *get_item(struct pppoe_net *pn, __be16 sid,
+                                       unsigned char *addr, int ifindex)
+{
+       struct pppox_sock *po;
+
+       read_lock_bh(&pn->hash_lock);
+       po = __get_item(pn, sid, addr, ifindex);
+       if (po)
+               sock_hold(sk_pppox(po));
+       read_unlock_bh(&pn->hash_lock);
+
+       return po;
+}
+
+static inline struct pppox_sock *get_item_by_addr(struct net *net,
+                                               struct sockaddr_pppox *sp)
+{
+       struct net_device *dev;
+       struct pppoe_net *pn;
+       struct pppox_sock *pppox_sock = NULL;
+
+       int ifindex;
+
+       rcu_read_lock();
+       dev = dev_get_by_name_rcu(net, sp->sa_addr.pppoe.dev);
+       if (dev) {
+               ifindex = dev->ifindex;
+               pn = pppoe_pernet(net);
+               pppox_sock = get_item(pn, sp->sa_addr.pppoe.sid,
+                               sp->sa_addr.pppoe.remote, ifindex);
+       }
+       rcu_read_unlock();
+       return pppox_sock;
+}
+
+static inline struct pppox_sock *delete_item(struct pppoe_net *pn, __be16 sid,
+                                       char *addr, int ifindex)
+{
+       struct pppox_sock *ret;
+
+       write_lock_bh(&pn->hash_lock);
+       ret = __delete_item(pn, sid, addr, ifindex);
+       write_unlock_bh(&pn->hash_lock);
+
+       return ret;
+}
+
+/***************************************************************************
+ *
+ *  Handler for device events.
+ *  Certain device events require that sockets be unconnected.
+ *
+ **************************************************************************/
+
+static void pppoe_flush_dev(struct net_device *dev)
+{
+       struct pppoe_net *pn;
+       int i;
+
+       pn = pppoe_pernet(dev_net(dev));
+       write_lock_bh(&pn->hash_lock);
+       for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+               struct pppox_sock *po = pn->hash_table[i];
+               struct sock *sk;
+
+               while (po) {
+                       while (po && po->pppoe_dev != dev) {
+                               po = po->next;
+                       }
+
+                       if (!po)
+                               break;
+
+                       sk = sk_pppox(po);
+
+                       /* We always grab the socket lock, followed by the
+                        * hash_lock, in that order.  Since we should hold the
+                        * sock lock while doing any unbinding, we need to
+                        * release the lock we're holding.  Hold a reference to
+                        * the sock so it doesn't disappear as we're jumping
+                        * between locks.
+                        */
+
+                       sock_hold(sk);
+                       write_unlock_bh(&pn->hash_lock);
+                       lock_sock(sk);
+
+                       if (po->pppoe_dev == dev &&
+                           sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+                               pppox_unbind_sock(sk);
+                               sk->sk_state = PPPOX_ZOMBIE;
+                               sk->sk_state_change(sk);
+                               po->pppoe_dev = NULL;
+                               dev_put(dev);
+                       }
+
+                       release_sock(sk);
+                       sock_put(sk);
+
+                       /* Restart the process from the start of the current
+                        * hash chain. We dropped locks so the world may have
+                        * change from underneath us.
+                        */
+
+                       BUG_ON(pppoe_pernet(dev_net(dev)) == NULL);
+                       write_lock_bh(&pn->hash_lock);
+                       po = pn->hash_table[i];
+               }
+       }
+       write_unlock_bh(&pn->hash_lock);
+}
+
+static int pppoe_device_event(struct notifier_block *this,
+                             unsigned long event, void *ptr)
+{
+       struct net_device *dev = (struct net_device *)ptr;
+
+       /* Only look at sockets that are using this specific device. */
+       switch (event) {
+       case NETDEV_CHANGEADDR:
+       case NETDEV_CHANGEMTU:
+               /* A change in mtu or address is a bad thing, requiring
+                * LCP re-negotiation.
+                */
+
+       case NETDEV_GOING_DOWN:
+       case NETDEV_DOWN:
+               /* Find every socket on this device and kill it. */
+               pppoe_flush_dev(dev);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block pppoe_notifier = {
+       .notifier_call = pppoe_device_event,
+};
+
+/************************************************************************
+ *
+ * Do the real work of receiving a PPPoE Session frame.
+ *
+ ***********************************************************************/
+static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
+{
+       struct pppox_sock *po = pppox_sk(sk);
+       struct pppox_sock *relay_po;
+
+       /* Backlog receive. Semantics of backlog rcv preclude any code from
+        * executing in lock_sock()/release_sock() bounds; meaning sk->sk_state
+        * can't change.
+        */
+
+       if (sk->sk_state & PPPOX_BOUND) {
+               ppp_input(&po->chan, skb);
+       } else if (sk->sk_state & PPPOX_RELAY) {
+               relay_po = get_item_by_addr(sock_net(sk),
+                                           &po->pppoe_relay);
+               if (relay_po == NULL)
+                       goto abort_kfree;
+
+               if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0)
+                       goto abort_put;
+
+               if (!__pppoe_xmit(sk_pppox(relay_po), skb))
+                       goto abort_put;
+       } else {
+               if (sock_queue_rcv_skb(sk, skb))
+                       goto abort_kfree;
+       }
+
+       return NET_RX_SUCCESS;
+
+abort_put:
+       sock_put(sk_pppox(relay_po));
+
+abort_kfree:
+       kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+/************************************************************************
+ *
+ * Receive wrapper called in BH context.
+ *
+ ***********************************************************************/
+static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
+                    struct packet_type *pt, struct net_device *orig_dev)
+{
+       struct pppoe_hdr *ph;
+       struct pppox_sock *po;
+       struct pppoe_net *pn;
+       int len;
+
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               goto out;
+
+       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+               goto drop;
+
+       ph = pppoe_hdr(skb);
+       len = ntohs(ph->length);
+
+       skb_pull_rcsum(skb, sizeof(*ph));
+       if (skb->len < len)
+               goto drop;
+
+       if (pskb_trim_rcsum(skb, len))
+               goto drop;
+
+       pn = pppoe_pernet(dev_net(dev));
+
+       /* Note that get_item does a sock_hold(), so sk_pppox(po)
+        * is known to be safe.
+        */
+       po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
+       if (!po)
+               goto drop;
+
+       return sk_receive_skb(sk_pppox(po), skb, 0);
+
+drop:
+       kfree_skb(skb);
+out:
+       return NET_RX_DROP;
+}
+
+/************************************************************************
+ *
+ * Receive a PPPoE Discovery frame.
+ * This is solely for detection of PADT frames
+ *
+ ***********************************************************************/
+static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev,
+                         struct packet_type *pt, struct net_device *orig_dev)
+
+{
+       struct pppoe_hdr *ph;
+       struct pppox_sock *po;
+       struct pppoe_net *pn;
+
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               goto out;
+
+       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
+               goto abort;
+
+       ph = pppoe_hdr(skb);
+       if (ph->code != PADT_CODE)
+               goto abort;
+
+       pn = pppoe_pernet(dev_net(dev));
+       po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
+       if (po) {
+               struct sock *sk = sk_pppox(po);
+
+               bh_lock_sock(sk);
+
+               /* If the user has locked the socket, just ignore
+                * the packet.  With the way two rcv protocols hook into
+                * one socket family type, we cannot (easily) distinguish
+                * what kind of SKB it is during backlog rcv.
+                */
+               if (sock_owned_by_user(sk) == 0) {
+                       /* We're no longer connect at the PPPOE layer,
+                        * and must wait for ppp channel to disconnect us.
+                        */
+                       sk->sk_state = PPPOX_ZOMBIE;
+               }
+
+               bh_unlock_sock(sk);
+               sock_put(sk);
+       }
+
+abort:
+       kfree_skb(skb);
+out:
+       return NET_RX_SUCCESS; /* Lies... :-) */
+}
+
+static struct packet_type pppoes_ptype __read_mostly = {
+       .type   = cpu_to_be16(ETH_P_PPP_SES),
+       .func   = pppoe_rcv,
+};
+
+static struct packet_type pppoed_ptype __read_mostly = {
+       .type   = cpu_to_be16(ETH_P_PPP_DISC),
+       .func   = pppoe_disc_rcv,
+};
+
+static struct proto pppoe_sk_proto __read_mostly = {
+       .name     = "PPPOE",
+       .owner    = THIS_MODULE,
+       .obj_size = sizeof(struct pppox_sock),
+};
+
+/***********************************************************************
+ *
+ * Initialize a new struct sock.
+ *
+ **********************************************************************/
+static int pppoe_create(struct net *net, struct socket *sock)
+{
+       struct sock *sk;
+
+       sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto);
+       if (!sk)
+               return -ENOMEM;
+
+       sock_init_data(sock, sk);
+
+       sock->state     = SS_UNCONNECTED;
+       sock->ops       = &pppoe_ops;
+
+       sk->sk_backlog_rcv      = pppoe_rcv_core;
+       sk->sk_state            = PPPOX_NONE;
+       sk->sk_type             = SOCK_STREAM;
+       sk->sk_family           = PF_PPPOX;
+       sk->sk_protocol         = PX_PROTO_OE;
+
+       return 0;
+}
+
+static int pppoe_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       struct pppox_sock *po;
+       struct pppoe_net *pn;
+       struct net *net = NULL;
+
+       if (!sk)
+               return 0;
+
+       lock_sock(sk);
+       if (sock_flag(sk, SOCK_DEAD)) {
+               release_sock(sk);
+               return -EBADF;
+       }
+
+       po = pppox_sk(sk);
+
+       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+               dev_put(po->pppoe_dev);
+               po->pppoe_dev = NULL;
+       }
+
+       pppox_unbind_sock(sk);
+
+       /* Signal the death of the socket. */
+       sk->sk_state = PPPOX_DEAD;
+
+       net = sock_net(sk);
+       pn = pppoe_pernet(net);
+
+       /*
+        * protect "po" from concurrent updates
+        * on pppoe_flush_dev
+        */
+       delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
+                   po->pppoe_ifindex);
+
+       sock_orphan(sk);
+       sock->sk = NULL;
+
+       skb_queue_purge(&sk->sk_receive_queue);
+       release_sock(sk);
+       sock_put(sk);
+
+       return 0;
+}
+
+static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
+                 int sockaddr_len, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr;
+       struct pppox_sock *po = pppox_sk(sk);
+       struct net_device *dev = NULL;
+       struct pppoe_net *pn;
+       struct net *net = NULL;
+       int error;
+
+       lock_sock(sk);
+
+       error = -EINVAL;
+       if (sp->sa_protocol != PX_PROTO_OE)
+               goto end;
+
+       /* Check for already bound sockets */
+       error = -EBUSY;
+       if ((sk->sk_state & PPPOX_CONNECTED) &&
+            stage_session(sp->sa_addr.pppoe.sid))
+               goto end;
+
+       /* Check for already disconnected sockets, on attempts to disconnect */
+       error = -EALREADY;
+       if ((sk->sk_state & PPPOX_DEAD) &&
+            !stage_session(sp->sa_addr.pppoe.sid))
+               goto end;
+
+       error = 0;
+
+       /* Delete the old binding */
+       if (stage_session(po->pppoe_pa.sid)) {
+               pppox_unbind_sock(sk);
+               pn = pppoe_pernet(sock_net(sk));
+               delete_item(pn, po->pppoe_pa.sid,
+                           po->pppoe_pa.remote, po->pppoe_ifindex);
+               if (po->pppoe_dev) {
+                       dev_put(po->pppoe_dev);
+                       po->pppoe_dev = NULL;
+               }
+
+               memset(sk_pppox(po) + 1, 0,
+                      sizeof(struct pppox_sock) - sizeof(struct sock));
+               sk->sk_state = PPPOX_NONE;
+       }
+
+       /* Re-bind in session stage only */
+       if (stage_session(sp->sa_addr.pppoe.sid)) {
+               error = -ENODEV;
+               net = sock_net(sk);
+               dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev);
+               if (!dev)
+                       goto err_put;
+
+               po->pppoe_dev = dev;
+               po->pppoe_ifindex = dev->ifindex;
+               pn = pppoe_pernet(net);
+               if (!(dev->flags & IFF_UP)) {
+                       goto err_put;
+               }
+
+               memcpy(&po->pppoe_pa,
+                      &sp->sa_addr.pppoe,
+                      sizeof(struct pppoe_addr));
+
+               write_lock_bh(&pn->hash_lock);
+               error = __set_item(pn, po);
+               write_unlock_bh(&pn->hash_lock);
+               if (error < 0)
+                       goto err_put;
+
+               po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
+                                  dev->hard_header_len);
+
+               po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
+               po->chan.private = sk;
+               po->chan.ops = &pppoe_chan_ops;
+
+               error = ppp_register_net_channel(dev_net(dev), &po->chan);
+               if (error) {
+                       delete_item(pn, po->pppoe_pa.sid,
+                                   po->pppoe_pa.remote, po->pppoe_ifindex);
+                       goto err_put;
+               }
+
+               sk->sk_state = PPPOX_CONNECTED;
+       }
+
+       po->num = sp->sa_addr.pppoe.sid;
+
+end:
+       release_sock(sk);
+       return error;
+err_put:
+       if (po->pppoe_dev) {
+               dev_put(po->pppoe_dev);
+               po->pppoe_dev = NULL;
+       }
+       goto end;
+}
+
+static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr,
+                 int *usockaddr_len, int peer)
+{
+       int len = sizeof(struct sockaddr_pppox);
+       struct sockaddr_pppox sp;
+
+       sp.sa_family    = AF_PPPOX;
+       sp.sa_protocol  = PX_PROTO_OE;
+       memcpy(&sp.sa_addr.pppoe, &pppox_sk(sock->sk)->pppoe_pa,
+              sizeof(struct pppoe_addr));
+
+       memcpy(uaddr, &sp, len);
+
+       *usockaddr_len = len;
+
+       return 0;
+}
+
+static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
+               unsigned long arg)
+{
+       struct sock *sk = sock->sk;
+       struct pppox_sock *po = pppox_sk(sk);
+       int val;
+       int err;
+
+       switch (cmd) {
+       case PPPIOCGMRU:
+               err = -ENXIO;
+               if (!(sk->sk_state & PPPOX_CONNECTED))
+                       break;
+
+               err = -EFAULT;
+               if (put_user(po->pppoe_dev->mtu -
+                            sizeof(struct pppoe_hdr) -
+                            PPP_HDRLEN,
+                            (int __user *)arg))
+                       break;
+               err = 0;
+               break;
+
+       case PPPIOCSMRU:
+               err = -ENXIO;
+               if (!(sk->sk_state & PPPOX_CONNECTED))
+                       break;
+
+               err = -EFAULT;
+               if (get_user(val, (int __user *)arg))
+                       break;
+
+               if (val < (po->pppoe_dev->mtu
+                          - sizeof(struct pppoe_hdr)
+                          - PPP_HDRLEN))
+                       err = 0;
+               else
+                       err = -EINVAL;
+               break;
+
+       case PPPIOCSFLAGS:
+               err = -EFAULT;
+               if (get_user(val, (int __user *)arg))
+                       break;
+               err = 0;
+               break;
+
+       case PPPOEIOCSFWD:
+       {
+               struct pppox_sock *relay_po;
+
+               err = -EBUSY;
+               if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD))
+                       break;
+
+               err = -ENOTCONN;
+               if (!(sk->sk_state & PPPOX_CONNECTED))
+                       break;
+
+               /* PPPoE address from the user specifies an outbound
+                  PPPoE address which frames are forwarded to */
+               err = -EFAULT;
+               if (copy_from_user(&po->pppoe_relay,
+                                  (void __user *)arg,
+                                  sizeof(struct sockaddr_pppox)))
+                       break;
+
+               err = -EINVAL;
+               if (po->pppoe_relay.sa_family != AF_PPPOX ||
+                   po->pppoe_relay.sa_protocol != PX_PROTO_OE)
+                       break;
+
+               /* Check that the socket referenced by the address
+                  actually exists. */
+               relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay);
+               if (!relay_po)
+                       break;
+
+               sock_put(sk_pppox(relay_po));
+               sk->sk_state |= PPPOX_RELAY;
+               err = 0;
+               break;
+       }
+
+       case PPPOEIOCDFWD:
+               err = -EALREADY;
+               if (!(sk->sk_state & PPPOX_RELAY))
+                       break;
+
+               sk->sk_state &= ~PPPOX_RELAY;
+               err = 0;
+               break;
+
+       default:
+               err = -ENOTTY;
+       }
+
+       return err;
+}
+
+static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
+                 struct msghdr *m, size_t total_len)
+{
+       struct sk_buff *skb;
+       struct sock *sk = sock->sk;
+       struct pppox_sock *po = pppox_sk(sk);
+       int error;
+       struct pppoe_hdr hdr;
+       struct pppoe_hdr *ph;
+       struct net_device *dev;
+       char *start;
+
+       lock_sock(sk);
+       if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) {
+               error = -ENOTCONN;
+               goto end;
+       }
+
+       hdr.ver = 1;
+       hdr.type = 1;
+       hdr.code = 0;
+       hdr.sid = po->num;
+
+       dev = po->pppoe_dev;
+
+       error = -EMSGSIZE;
+       if (total_len > (dev->mtu + dev->hard_header_len))
+               goto end;
+
+
+       skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
+                          0, GFP_KERNEL);
+       if (!skb) {
+               error = -ENOMEM;
+               goto end;
+       }
+
+       /* Reserve space for headers. */
+       skb_reserve(skb, dev->hard_header_len);
+       skb_reset_network_header(skb);
+
+       skb->dev = dev;
+
+       skb->priority = sk->sk_priority;
+       skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
+
+       ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr));
+       start = (char *)&ph->tag[0];
+
+       error = memcpy_fromiovec(start, m->msg_iov, total_len);
+       if (error < 0) {
+               kfree_skb(skb);
+               goto end;
+       }
+
+       error = total_len;
+       dev_hard_header(skb, dev, ETH_P_PPP_SES,
+                       po->pppoe_pa.remote, NULL, total_len);
+
+       memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
+
+       ph->length = htons(total_len);
+
+       dev_queue_xmit(skb);
+
+end:
+       release_sock(sk);
+       return error;
+}
+
+/************************************************************************
+ *
+ * xmit function for internal use.
+ *
+ ***********************************************************************/
+static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
+{
+       struct pppox_sock *po = pppox_sk(sk);
+       struct net_device *dev = po->pppoe_dev;
+       struct pppoe_hdr *ph;
+       int data_len = skb->len;
+
+       /* The higher-level PPP code (ppp_unregister_channel()) ensures the PPP
+        * xmit operations conclude prior to an unregistration call.  Thus
+        * sk->sk_state cannot change, so we don't need to do lock_sock().
+        * But, we also can't do a lock_sock since that introduces a potential
+        * deadlock as we'd reverse the lock ordering used when calling
+        * ppp_unregister_channel().
+        */
+
+       if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+               goto abort;
+
+       if (!dev)
+               goto abort;
+
+       /* Copy the data if there is no space for the header or if it's
+        * read-only.
+        */
+       if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len))
+               goto abort;
+
+       __skb_push(skb, sizeof(*ph));
+       skb_reset_network_header(skb);
+
+       ph = pppoe_hdr(skb);
+       ph->ver = 1;
+       ph->type = 1;
+       ph->code = 0;
+       ph->sid = po->num;
+       ph->length = htons(data_len);
+
+       skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
+       skb->dev = dev;
+
+       dev_hard_header(skb, dev, ETH_P_PPP_SES,
+                       po->pppoe_pa.remote, NULL, data_len);
+
+       dev_queue_xmit(skb);
+       return 1;
+
+abort:
+       kfree_skb(skb);
+       return 1;
+}
+
+/************************************************************************
+ *
+ * xmit function called by generic PPP driver
+ * sends PPP frame over PPPoE socket
+ *
+ ***********************************************************************/
+static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+       struct sock *sk = (struct sock *)chan->private;
+       return __pppoe_xmit(sk, skb);
+}
+
+static const struct ppp_channel_ops pppoe_chan_ops = {
+       .start_xmit = pppoe_xmit,
+};
+
+static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
+                 struct msghdr *m, size_t total_len, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct sk_buff *skb;
+       int error = 0;
+
+       if (sk->sk_state & PPPOX_BOUND) {
+               error = -EIO;
+               goto end;
+       }
+
+       skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+                               flags & MSG_DONTWAIT, &error);
+       if (error < 0)
+               goto end;
+
+       m->msg_namelen = 0;
+
+       if (skb) {
+               total_len = min_t(size_t, total_len, skb->len);
+               error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
+               if (error == 0)
+                       error = total_len;
+       }
+
+       kfree_skb(skb);
+end:
+       return error;
+}
+
+#ifdef CONFIG_PROC_FS
+static int pppoe_seq_show(struct seq_file *seq, void *v)
+{
+       struct pppox_sock *po;
+       char *dev_name;
+
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(seq, "Id       Address              Device\n");
+               goto out;
+       }
+
+       po = v;
+       dev_name = po->pppoe_pa.dev;
+
+       seq_printf(seq, "%08X %pM %8s\n",
+               po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name);
+out:
+       return 0;
+}
+
+static inline struct pppox_sock *pppoe_get_idx(struct pppoe_net *pn, loff_t pos)
+{
+       struct pppox_sock *po;
+       int i;
+
+       for (i = 0; i < PPPOE_HASH_SIZE; i++) {
+               po = pn->hash_table[i];
+               while (po) {
+                       if (!pos--)
+                               goto out;
+                       po = po->next;
+               }
+       }
+
+out:
+       return po;
+}
+
+static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(pn->hash_lock)
+{
+       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
+       loff_t l = *pos;
+
+       read_lock_bh(&pn->hash_lock);
+       return l ? pppoe_get_idx(pn, --l) : SEQ_START_TOKEN;
+}
+
+static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
+       struct pppox_sock *po;
+
+       ++*pos;
+       if (v == SEQ_START_TOKEN) {
+               po = pppoe_get_idx(pn, 0);
+               goto out;
+       }
+       po = v;
+       if (po->next)
+               po = po->next;
+       else {
+               int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
+
+               po = NULL;
+               while (++hash < PPPOE_HASH_SIZE) {
+                       po = pn->hash_table[hash];
+                       if (po)
+                               break;
+               }
+       }
+
+out:
+       return po;
+}
+
+static void pppoe_seq_stop(struct seq_file *seq, void *v)
+       __releases(pn->hash_lock)
+{
+       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
+       read_unlock_bh(&pn->hash_lock);
+}
+
+static const struct seq_operations pppoe_seq_ops = {
+       .start          = pppoe_seq_start,
+       .next           = pppoe_seq_next,
+       .stop           = pppoe_seq_stop,
+       .show           = pppoe_seq_show,
+};
+
+static int pppoe_seq_open(struct inode *inode, struct file *file)
+{
+       return seq_open_net(inode, file, &pppoe_seq_ops,
+                       sizeof(struct seq_net_private));
+}
+
+static const struct file_operations pppoe_seq_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pppoe_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_net,
+};
+
+#endif /* CONFIG_PROC_FS */
+
+static const struct proto_ops pppoe_ops = {
+       .family         = AF_PPPOX,
+       .owner          = THIS_MODULE,
+       .release        = pppoe_release,
+       .bind           = sock_no_bind,
+       .connect        = pppoe_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = sock_no_accept,
+       .getname        = pppoe_getname,
+       .poll           = datagram_poll,
+       .listen         = sock_no_listen,
+       .shutdown       = sock_no_shutdown,
+       .setsockopt     = sock_no_setsockopt,
+       .getsockopt     = sock_no_getsockopt,
+       .sendmsg        = pppoe_sendmsg,
+       .recvmsg        = pppoe_recvmsg,
+       .mmap           = sock_no_mmap,
+       .ioctl          = pppox_ioctl,
+};
+
+static const struct pppox_proto pppoe_proto = {
+       .create = pppoe_create,
+       .ioctl  = pppoe_ioctl,
+       .owner  = THIS_MODULE,
+};
+
+static __net_init int pppoe_init_net(struct net *net)
+{
+       struct pppoe_net *pn = pppoe_pernet(net);
+       struct proc_dir_entry *pde;
+
+       rwlock_init(&pn->hash_lock);
+
+       pde = proc_net_fops_create(net, "pppoe", S_IRUGO, &pppoe_seq_fops);
+#ifdef CONFIG_PROC_FS
+       if (!pde)
+               return -ENOMEM;
+#endif
+
+       return 0;
+}
+
+static __net_exit void pppoe_exit_net(struct net *net)
+{
+       proc_net_remove(net, "pppoe");
+}
+
+static struct pernet_operations pppoe_net_ops = {
+       .init = pppoe_init_net,
+       .exit = pppoe_exit_net,
+       .id   = &pppoe_net_id,
+       .size = sizeof(struct pppoe_net),
+};
+
+static int __init pppoe_init(void)
+{
+       int err;
+
+       err = register_pernet_device(&pppoe_net_ops);
+       if (err)
+               goto out;
+
+       err = proto_register(&pppoe_sk_proto, 0);
+       if (err)
+               goto out_unregister_net_ops;
+
+       err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
+       if (err)
+               goto out_unregister_pppoe_proto;
+
+       dev_add_pack(&pppoes_ptype);
+       dev_add_pack(&pppoed_ptype);
+       register_netdevice_notifier(&pppoe_notifier);
+
+       return 0;
+
+out_unregister_pppoe_proto:
+       proto_unregister(&pppoe_sk_proto);
+out_unregister_net_ops:
+       unregister_pernet_device(&pppoe_net_ops);
+out:
+       return err;
+}
+
+static void __exit pppoe_exit(void)
+{
+       unregister_netdevice_notifier(&pppoe_notifier);
+       dev_remove_pack(&pppoed_ptype);
+       dev_remove_pack(&pppoes_ptype);
+       unregister_pppox_proto(PX_PROTO_OE);
+       proto_unregister(&pppoe_sk_proto);
+       unregister_pernet_device(&pppoe_net_ops);
+}
+
+module_init(pppoe_init);
+module_exit(pppoe_exit);
+
+MODULE_AUTHOR("Michal Ostrowski <mostrows@speakeasy.net>");
+MODULE_DESCRIPTION("PPP over Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NETPROTO(PF_PPPOX);
diff --git a/drivers/net/ppp/pppox.c b/drivers/net/ppp/pppox.c
new file mode 100644 (file)
index 0000000..8c0d170
--- /dev/null
@@ -0,0 +1,149 @@
+/** -*- linux-c -*- ***********************************************************
+ * Linux PPP over X/Ethernet (PPPoX/PPPoE) Sockets
+ *
+ * PPPoX --- Generic PPP encapsulation socket family
+ * PPPoE --- PPP over Ethernet (RFC 2516)
+ *
+ *
+ * Version:    0.5.2
+ *
+ * Author:     Michal Ostrowski <mostrows@speakeasy.net>
+ *
+ * 051000 :    Initialization cleanup
+ *
+ * License:
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/init.h>
+#include <linux/if_pppox.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <linux/kmod.h>
+
+#include <net/sock.h>
+
+#include <asm/uaccess.h>
+
+static const struct pppox_proto *pppox_protos[PX_MAX_PROTO + 1];
+
+int register_pppox_proto(int proto_num, const struct pppox_proto *pp)
+{
+       if (proto_num < 0 || proto_num > PX_MAX_PROTO)
+               return -EINVAL;
+       if (pppox_protos[proto_num])
+               return -EALREADY;
+       pppox_protos[proto_num] = pp;
+       return 0;
+}
+
+void unregister_pppox_proto(int proto_num)
+{
+       if (proto_num >= 0 && proto_num <= PX_MAX_PROTO)
+               pppox_protos[proto_num] = NULL;
+}
+
+void pppox_unbind_sock(struct sock *sk)
+{
+       /* Clear connection to ppp device, if attached. */
+
+       if (sk->sk_state & (PPPOX_BOUND | PPPOX_CONNECTED | PPPOX_ZOMBIE)) {
+               ppp_unregister_channel(&pppox_sk(sk)->chan);
+               sk->sk_state = PPPOX_DEAD;
+       }
+}
+
+EXPORT_SYMBOL(register_pppox_proto);
+EXPORT_SYMBOL(unregister_pppox_proto);
+EXPORT_SYMBOL(pppox_unbind_sock);
+
+int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       struct sock *sk = sock->sk;
+       struct pppox_sock *po = pppox_sk(sk);
+       int rc;
+
+       lock_sock(sk);
+
+       switch (cmd) {
+       case PPPIOCGCHAN: {
+               int index;
+               rc = -ENOTCONN;
+               if (!(sk->sk_state & PPPOX_CONNECTED))
+                       break;
+
+               rc = -EINVAL;
+               index = ppp_channel_index(&po->chan);
+               if (put_user(index , (int __user *) arg))
+                       break;
+
+               rc = 0;
+               sk->sk_state |= PPPOX_BOUND;
+               break;
+       }
+       default:
+               rc = pppox_protos[sk->sk_protocol]->ioctl ?
+                       pppox_protos[sk->sk_protocol]->ioctl(sock, cmd, arg) : -ENOTTY;
+       }
+
+       release_sock(sk);
+       return rc;
+}
+
+EXPORT_SYMBOL(pppox_ioctl);
+
+static int pppox_create(struct net *net, struct socket *sock, int protocol,
+                       int kern)
+{
+       int rc = -EPROTOTYPE;
+
+       if (protocol < 0 || protocol > PX_MAX_PROTO)
+               goto out;
+
+       rc = -EPROTONOSUPPORT;
+       if (!pppox_protos[protocol])
+               request_module("pppox-proto-%d", protocol);
+       if (!pppox_protos[protocol] ||
+           !try_module_get(pppox_protos[protocol]->owner))
+               goto out;
+
+       rc = pppox_protos[protocol]->create(net, sock);
+
+       module_put(pppox_protos[protocol]->owner);
+out:
+       return rc;
+}
+
+static const struct net_proto_family pppox_proto_family = {
+       .family = PF_PPPOX,
+       .create = pppox_create,
+       .owner  = THIS_MODULE,
+};
+
+static int __init pppox_init(void)
+{
+       return sock_register(&pppox_proto_family);
+}
+
+static void __exit pppox_exit(void)
+{
+       sock_unregister(PF_PPPOX);
+}
+
+module_init(pppox_init);
+module_exit(pppox_exit);
+
+MODULE_AUTHOR("Michal Ostrowski <mostrows@speakeasy.net>");
+MODULE_DESCRIPTION("PPP over Ethernet driver (generic socket layer)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
new file mode 100644 (file)
index 0000000..eae542a
--- /dev/null
@@ -0,0 +1,717 @@
+/*
+ *  Point-to-Point Tunneling Protocol for Linux
+ *
+ *     Authors: Dmitry Kozlov <xeb@mail.ru>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_pppox.h>
+#include <linux/if_ppp.h>
+#include <linux/notifier.h>
+#include <linux/file.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+
+#include <net/sock.h>
+#include <net/protocol.h>
+#include <net/ip.h>
+#include <net/icmp.h>
+#include <net/route.h>
+#include <net/gre.h>
+
+#include <linux/uaccess.h>
+
+#define PPTP_DRIVER_VERSION "0.8.5"
+
+#define MAX_CALLID 65535
+
+static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
+static struct pppox_sock **callid_sock;
+
+static DEFINE_SPINLOCK(chan_lock);
+
+static struct proto pptp_sk_proto __read_mostly;
+static const struct ppp_channel_ops pptp_chan_ops;
+static const struct proto_ops pptp_ops;
+
+#define PPP_LCP_ECHOREQ 0x09
+#define PPP_LCP_ECHOREP 0x0A
+#define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define MISSING_WINDOW 20
+#define WRAPPED(curseq, lastseq)\
+       ((((curseq) & 0xffffff00) == 0) &&\
+       (((lastseq) & 0xffffff00) == 0xffffff00))
+
+#define PPTP_GRE_PROTO  0x880B
+#define PPTP_GRE_VER    0x1
+
+#define PPTP_GRE_FLAG_C        0x80
+#define PPTP_GRE_FLAG_R        0x40
+#define PPTP_GRE_FLAG_K        0x20
+#define PPTP_GRE_FLAG_S        0x10
+#define PPTP_GRE_FLAG_A        0x80
+
+#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
+#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
+#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
+#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
+#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
+
+#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header))
+struct pptp_gre_header {
+       u8  flags;
+       u8  ver;
+       u16 protocol;
+       u16 payload_len;
+       u16 call_id;
+       u32 seq;
+       u32 ack;
+} __packed;
+
+static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr)
+{
+       struct pppox_sock *sock;
+       struct pptp_opt *opt;
+
+       rcu_read_lock();
+       sock = rcu_dereference(callid_sock[call_id]);
+       if (sock) {
+               opt = &sock->proto.pptp;
+               if (opt->dst_addr.sin_addr.s_addr != s_addr)
+                       sock = NULL;
+               else
+                       sock_hold(sk_pppox(sock));
+       }
+       rcu_read_unlock();
+
+       return sock;
+}
+
+static int lookup_chan_dst(u16 call_id, __be32 d_addr)
+{
+       struct pppox_sock *sock;
+       struct pptp_opt *opt;
+       int i;
+
+       rcu_read_lock();
+       for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID;
+            i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) {
+               sock = rcu_dereference(callid_sock[i]);
+               if (!sock)
+                       continue;
+               opt = &sock->proto.pptp;
+               if (opt->dst_addr.call_id == call_id &&
+                         opt->dst_addr.sin_addr.s_addr == d_addr)
+                       break;
+       }
+       rcu_read_unlock();
+
+       return i < MAX_CALLID;
+}
+
+static int add_chan(struct pppox_sock *sock)
+{
+       static int call_id;
+
+       spin_lock(&chan_lock);
+       if (!sock->proto.pptp.src_addr.call_id) {
+               call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+               if (call_id == MAX_CALLID) {
+                       call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+                       if (call_id == MAX_CALLID)
+                               goto out_err;
+               }
+               sock->proto.pptp.src_addr.call_id = call_id;
+       } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
+               goto out_err;
+
+       set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+       rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
+       spin_unlock(&chan_lock);
+
+       return 0;
+
+out_err:
+       spin_unlock(&chan_lock);
+       return -1;
+}
+
+static void del_chan(struct pppox_sock *sock)
+{
+       spin_lock(&chan_lock);
+       clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+       rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
+       spin_unlock(&chan_lock);
+       synchronize_rcu();
+}
+
+static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+       struct sock *sk = (struct sock *) chan->private;
+       struct pppox_sock *po = pppox_sk(sk);
+       struct pptp_opt *opt = &po->proto.pptp;
+       struct pptp_gre_header *hdr;
+       unsigned int header_len = sizeof(*hdr);
+       struct flowi4 fl4;
+       int islcp;
+       int len;
+       unsigned char *data;
+       __u32 seq_recv;
+
+
+       struct rtable *rt;
+       struct net_device *tdev;
+       struct iphdr  *iph;
+       int    max_headroom;
+
+       if (sk_pppox(po)->sk_state & PPPOX_DEAD)
+               goto tx_error;
+
+       rt = ip_route_output_ports(&init_net, &fl4, NULL,
+                                  opt->dst_addr.sin_addr.s_addr,
+                                  opt->src_addr.sin_addr.s_addr,
+                                  0, 0, IPPROTO_GRE,
+                                  RT_TOS(0), 0);
+       if (IS_ERR(rt))
+               goto tx_error;
+
+       tdev = rt->dst.dev;
+
+       max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
+
+       if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+               struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
+               if (!new_skb) {
+                       ip_rt_put(rt);
+                       goto tx_error;
+               }
+               if (skb->sk)
+                       skb_set_owner_w(new_skb, skb->sk);
+               kfree_skb(skb);
+               skb = new_skb;
+       }
+
+       data = skb->data;
+       islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+       /* compress protocol field */
+       if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp)
+               skb_pull(skb, 1);
+
+       /* Put in the address/control bytes if necessary */
+       if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) {
+               data = skb_push(skb, 2);
+               data[0] = PPP_ALLSTATIONS;
+               data[1] = PPP_UI;
+       }
+
+       len = skb->len;
+
+       seq_recv = opt->seq_recv;
+
+       if (opt->ack_sent == seq_recv)
+               header_len -= sizeof(hdr->ack);
+
+       /* Push down and install GRE header */
+       skb_push(skb, header_len);
+       hdr = (struct pptp_gre_header *)(skb->data);
+
+       hdr->flags       = PPTP_GRE_FLAG_K;
+       hdr->ver         = PPTP_GRE_VER;
+       hdr->protocol    = htons(PPTP_GRE_PROTO);
+       hdr->call_id     = htons(opt->dst_addr.call_id);
+
+       hdr->flags      |= PPTP_GRE_FLAG_S;
+       hdr->seq         = htonl(++opt->seq_sent);
+       if (opt->ack_sent != seq_recv)  {
+               /* send ack with this message */
+               hdr->ver |= PPTP_GRE_FLAG_A;
+               hdr->ack  = htonl(seq_recv);
+               opt->ack_sent = seq_recv;
+       }
+       hdr->payload_len = htons(len);
+
+       /*      Push down and install the IP header. */
+
+       skb_reset_transport_header(skb);
+       skb_push(skb, sizeof(*iph));
+       skb_reset_network_header(skb);
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
+
+       iph =   ip_hdr(skb);
+       iph->version =  4;
+       iph->ihl =      sizeof(struct iphdr) >> 2;
+       if (ip_dont_fragment(sk, &rt->dst))
+               iph->frag_off   =       htons(IP_DF);
+       else
+               iph->frag_off   =       0;
+       iph->protocol = IPPROTO_GRE;
+       iph->tos      = 0;
+       iph->daddr    = fl4.daddr;
+       iph->saddr    = fl4.saddr;
+       iph->ttl      = ip4_dst_hoplimit(&rt->dst);
+       iph->tot_len  = htons(skb->len);
+
+       skb_dst_drop(skb);
+       skb_dst_set(skb, &rt->dst);
+
+       nf_reset(skb);
+
+       skb->ip_summed = CHECKSUM_NONE;
+       ip_select_ident(iph, &rt->dst, NULL);
+       ip_send_check(iph);
+
+       ip_local_out(skb);
+
+tx_error:
+       return 1;
+}
+
+static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)
+{
+       struct pppox_sock *po = pppox_sk(sk);
+       struct pptp_opt *opt = &po->proto.pptp;
+       int headersize, payload_len, seq;
+       __u8 *payload;
+       struct pptp_gre_header *header;
+
+       if (!(sk->sk_state & PPPOX_CONNECTED)) {
+               if (sock_queue_rcv_skb(sk, skb))
+                       goto drop;
+               return NET_RX_SUCCESS;
+       }
+
+       header = (struct pptp_gre_header *)(skb->data);
+
+       /* test if acknowledgement present */
+       if (PPTP_GRE_IS_A(header->ver)) {
+               __u32 ack = (PPTP_GRE_IS_S(header->flags)) ?
+                               header->ack : header->seq; /* ack in different place if S = 0 */
+
+               ack = ntohl(ack);
+
+               if (ack > opt->ack_recv)
+                       opt->ack_recv = ack;
+               /* also handle sequence number wrap-around  */
+               if (WRAPPED(ack, opt->ack_recv))
+                       opt->ack_recv = ack;
+       }
+
+       /* test if payload present */
+       if (!PPTP_GRE_IS_S(header->flags))
+               goto drop;
+
+       headersize  = sizeof(*header);
+       payload_len = ntohs(header->payload_len);
+       seq         = ntohl(header->seq);
+
+       /* no ack present? */
+       if (!PPTP_GRE_IS_A(header->ver))
+               headersize -= sizeof(header->ack);
+       /* check for incomplete packet (length smaller than expected) */
+       if (skb->len - headersize < payload_len)
+               goto drop;
+
+       payload = skb->data + headersize;
+       /* check for expected sequence number */
+       if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) {
+               if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
+                               (PPP_PROTOCOL(payload) == PPP_LCP) &&
+                               ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP)))
+                       goto allow_packet;
+       } else {
+               opt->seq_recv = seq;
+allow_packet:
+               skb_pull(skb, headersize);
+
+               if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) {
+                       /* chop off address/control */
+                       if (skb->len < 3)
+                               goto drop;
+                       skb_pull(skb, 2);
+               }
+
+               if ((*skb->data) & 1) {
+                       /* protocol is compressed */
+                       skb_push(skb, 1)[0] = 0;
+               }
+
+               skb->ip_summed = CHECKSUM_NONE;
+               skb_set_network_header(skb, skb->head-skb->data);
+               ppp_input(&po->chan, skb);
+
+               return NET_RX_SUCCESS;
+       }
+drop:
+       kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+static int pptp_rcv(struct sk_buff *skb)
+{
+       struct pppox_sock *po;
+       struct pptp_gre_header *header;
+       struct iphdr *iph;
+
+       if (skb->pkt_type != PACKET_HOST)
+               goto drop;
+
+       if (!pskb_may_pull(skb, 12))
+               goto drop;
+
+       iph = ip_hdr(skb);
+
+       header = (struct pptp_gre_header *)skb->data;
+
+       if (ntohs(header->protocol) != PPTP_GRE_PROTO || /* PPTP-GRE protocol for PPTP */
+               PPTP_GRE_IS_C(header->flags) ||                /* flag C should be clear */
+               PPTP_GRE_IS_R(header->flags) ||                /* flag R should be clear */
+               !PPTP_GRE_IS_K(header->flags) ||               /* flag K should be set */
+               (header->flags&0xF) != 0)                      /* routing and recursion ctrl = 0 */
+               /* if invalid, discard this packet */
+               goto drop;
+
+       po = lookup_chan(htons(header->call_id), iph->saddr);
+       if (po) {
+               skb_dst_drop(skb);
+               nf_reset(skb);
+               return sk_receive_skb(sk_pppox(po), skb, 0);
+       }
+drop:
+       kfree_skb(skb);
+       return NET_RX_DROP;
+}
+
+static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
+       int sockaddr_len)
+{
+       struct sock *sk = sock->sk;
+       struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+       struct pppox_sock *po = pppox_sk(sk);
+       struct pptp_opt *opt = &po->proto.pptp;
+       int error = 0;
+
+       lock_sock(sk);
+
+       opt->src_addr = sp->sa_addr.pptp;
+       if (add_chan(po)) {
+               release_sock(sk);
+               error = -EBUSY;
+       }
+
+       release_sock(sk);
+       return error;
+}
+
+static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
+       int sockaddr_len, int flags)
+{
+       struct sock *sk = sock->sk;
+       struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+       struct pppox_sock *po = pppox_sk(sk);
+       struct pptp_opt *opt = &po->proto.pptp;
+       struct rtable *rt;
+       struct flowi4 fl4;
+       int error = 0;
+
+       if (sp->sa_protocol != PX_PROTO_PPTP)
+               return -EINVAL;
+
+       if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr))
+               return -EALREADY;
+
+       lock_sock(sk);
+       /* Check for already bound sockets */
+       if (sk->sk_state & PPPOX_CONNECTED) {
+               error = -EBUSY;
+               goto end;
+       }
+
+       /* Check for already disconnected sockets, on attempts to disconnect */
+       if (sk->sk_state & PPPOX_DEAD) {
+               error = -EALREADY;
+               goto end;
+       }
+
+       if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) {
+               error = -EINVAL;
+               goto end;
+       }
+
+       po->chan.private = sk;
+       po->chan.ops = &pptp_chan_ops;
+
+       rt = ip_route_output_ports(&init_net, &fl4, sk,
+                                  opt->dst_addr.sin_addr.s_addr,
+                                  opt->src_addr.sin_addr.s_addr,
+                                  0, 0,
+                                  IPPROTO_GRE, RT_CONN_FLAGS(sk), 0);
+       if (IS_ERR(rt)) {
+               error = -EHOSTUNREACH;
+               goto end;
+       }
+       sk_setup_caps(sk, &rt->dst);
+
+       po->chan.mtu = dst_mtu(&rt->dst);
+       if (!po->chan.mtu)
+               po->chan.mtu = PPP_MTU;
+       ip_rt_put(rt);
+       po->chan.mtu -= PPTP_HEADER_OVERHEAD;
+
+       po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
+       error = ppp_register_channel(&po->chan);
+       if (error) {
+               pr_err("PPTP: failed to register PPP channel (%d)\n", error);
+               goto end;
+       }
+
+       opt->dst_addr = sp->sa_addr.pptp;
+       sk->sk_state = PPPOX_CONNECTED;
+
+ end:
+       release_sock(sk);
+       return error;
+}
+
+static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
+       int *usockaddr_len, int peer)
+{
+       int len = sizeof(struct sockaddr_pppox);
+       struct sockaddr_pppox sp;
+
+       sp.sa_family      = AF_PPPOX;
+       sp.sa_protocol  = PX_PROTO_PPTP;
+       sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
+
+       memcpy(uaddr, &sp, len);
+
+       *usockaddr_len = len;
+
+       return 0;
+}
+
+static int pptp_release(struct socket *sock)
+{
+       struct sock *sk = sock->sk;
+       struct pppox_sock *po;
+       struct pptp_opt *opt;
+       int error = 0;
+
+       if (!sk)
+               return 0;
+
+       lock_sock(sk);
+
+       if (sock_flag(sk, SOCK_DEAD)) {
+               release_sock(sk);
+               return -EBADF;
+       }
+
+       po = pppox_sk(sk);
+       opt = &po->proto.pptp;
+       del_chan(po);
+
+       pppox_unbind_sock(sk);
+       sk->sk_state = PPPOX_DEAD;
+
+       sock_orphan(sk);
+       sock->sk = NULL;
+
+       release_sock(sk);
+       sock_put(sk);
+
+       return error;
+}
+
+static void pptp_sock_destruct(struct sock *sk)
+{
+       if (!(sk->sk_state & PPPOX_DEAD)) {
+               del_chan(pppox_sk(sk));
+               pppox_unbind_sock(sk);
+       }
+       skb_queue_purge(&sk->sk_receive_queue);
+}
+
+static int pptp_create(struct net *net, struct socket *sock)
+{
+       int error = -ENOMEM;
+       struct sock *sk;
+       struct pppox_sock *po;
+       struct pptp_opt *opt;
+
+       sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto);
+       if (!sk)
+               goto out;
+
+       sock_init_data(sock, sk);
+
+       sock->state = SS_UNCONNECTED;
+       sock->ops   = &pptp_ops;
+
+       sk->sk_backlog_rcv = pptp_rcv_core;
+       sk->sk_state       = PPPOX_NONE;
+       sk->sk_type        = SOCK_STREAM;
+       sk->sk_family      = PF_PPPOX;
+       sk->sk_protocol    = PX_PROTO_PPTP;
+       sk->sk_destruct    = pptp_sock_destruct;
+
+       po = pppox_sk(sk);
+       opt = &po->proto.pptp;
+
+       opt->seq_sent = 0; opt->seq_recv = 0;
+       opt->ack_recv = 0; opt->ack_sent = 0;
+
+       error = 0;
+out:
+       return error;
+}
+
+static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
+       unsigned long arg)
+{
+       struct sock *sk = (struct sock *) chan->private;
+       struct pppox_sock *po = pppox_sk(sk);
+       struct pptp_opt *opt = &po->proto.pptp;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
+       int err, val;
+
+       err = -EFAULT;
+       switch (cmd) {
+       case PPPIOCGFLAGS:
+               val = opt->ppp_flags;
+               if (put_user(val, p))
+                       break;
+               err = 0;
+               break;
+       case PPPIOCSFLAGS:
+               if (get_user(val, p))
+                       break;
+               opt->ppp_flags = val & ~SC_RCV_BITS;
+               err = 0;
+               break;
+       default:
+               err = -ENOTTY;
+       }
+
+       return err;
+}
+
+static const struct ppp_channel_ops pptp_chan_ops = {
+       .start_xmit = pptp_xmit,
+       .ioctl      = pptp_ppp_ioctl,
+};
+
+static struct proto pptp_sk_proto __read_mostly = {
+       .name     = "PPTP",
+       .owner    = THIS_MODULE,
+       .obj_size = sizeof(struct pppox_sock),
+};
+
+static const struct proto_ops pptp_ops = {
+       .family     = AF_PPPOX,
+       .owner      = THIS_MODULE,
+       .release    = pptp_release,
+       .bind       = pptp_bind,
+       .connect    = pptp_connect,
+       .socketpair = sock_no_socketpair,
+       .accept     = sock_no_accept,
+       .getname    = pptp_getname,
+       .poll       = sock_no_poll,
+       .listen     = sock_no_listen,
+       .shutdown   = sock_no_shutdown,
+       .setsockopt = sock_no_setsockopt,
+       .getsockopt = sock_no_getsockopt,
+       .sendmsg    = sock_no_sendmsg,
+       .recvmsg    = sock_no_recvmsg,
+       .mmap       = sock_no_mmap,
+       .ioctl      = pppox_ioctl,
+};
+
+static const struct pppox_proto pppox_pptp_proto = {
+       .create = pptp_create,
+       .owner  = THIS_MODULE,
+};
+
+static const struct gre_protocol gre_pptp_protocol = {
+       .handler = pptp_rcv,
+};
+
+static int __init pptp_init_module(void)
+{
+       int err = 0;
+       pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
+
+       callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *));
+       if (!callid_sock) {
+               pr_err("PPTP: cann't allocate memory\n");
+               return -ENOMEM;
+       }
+
+       err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+       if (err) {
+               pr_err("PPTP: can't add gre protocol\n");
+               goto out_mem_free;
+       }
+
+       err = proto_register(&pptp_sk_proto, 0);
+       if (err) {
+               pr_err("PPTP: can't register sk_proto\n");
+               goto out_gre_del_protocol;
+       }
+
+       err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto);
+       if (err) {
+               pr_err("PPTP: can't register pppox_proto\n");
+               goto out_unregister_sk_proto;
+       }
+
+       return 0;
+
+out_unregister_sk_proto:
+       proto_unregister(&pptp_sk_proto);
+out_gre_del_protocol:
+       gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+out_mem_free:
+       vfree(callid_sock);
+
+       return err;
+}
+
+static void __exit pptp_exit_module(void)
+{
+       unregister_pppox_proto(PX_PROTO_PPTP);
+       proto_unregister(&pptp_sk_proto);
+       gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
+       vfree(callid_sock);
+}
+
+module_init(pptp_init_module);
+module_exit(pptp_exit_module);
+
+MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
+MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
deleted file mode 100644 (file)
index c6ba643..0000000
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*
- * PPP async serial channel driver for Linux.
- *
- * Copyright 1999 Paul Mackerras.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- * This driver provides the encapsulation and framing for sending
- * and receiving PPP frames over async serial lines.  It relies on
- * the generic PPP layer to give it frames to send and to process
- * received frames.  It implements the PPP line discipline.
- *
- * Part of the code in this driver was inspired by the old async-only
- * PPP driver, written by Michael Callahan and Al Longyear, and
- * subsequently hacked by Paul Mackerras.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/tty.h>
-#include <linux/netdevice.h>
-#include <linux/poll.h>
-#include <linux/crc-ccitt.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/ppp_channel.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-#include <asm/uaccess.h>
-#include <asm/string.h>
-
-#define PPP_VERSION    "2.4.2"
-
-#define OBUFSIZE       4096
-
-/* Structure for storing local state. */
-struct asyncppp {
-       struct tty_struct *tty;
-       unsigned int    flags;
-       unsigned int    state;
-       unsigned int    rbits;
-       int             mru;
-       spinlock_t      xmit_lock;
-       spinlock_t      recv_lock;
-       unsigned long   xmit_flags;
-       u32             xaccm[8];
-       u32             raccm;
-       unsigned int    bytes_sent;
-       unsigned int    bytes_rcvd;
-
-       struct sk_buff  *tpkt;
-       int             tpkt_pos;
-       u16             tfcs;
-       unsigned char   *optr;
-       unsigned char   *olim;
-       unsigned long   last_xmit;
-
-       struct sk_buff  *rpkt;
-       int             lcp_fcs;
-       struct sk_buff_head rqueue;
-
-       struct tasklet_struct tsk;
-
-       atomic_t        refcnt;
-       struct semaphore dead_sem;
-       struct ppp_channel chan;        /* interface to generic ppp layer */
-       unsigned char   obuf[OBUFSIZE];
-};
-
-/* Bit numbers in xmit_flags */
-#define XMIT_WAKEUP    0
-#define XMIT_FULL      1
-#define XMIT_BUSY      2
-
-/* State bits */
-#define SC_TOSS                1
-#define SC_ESCAPE      2
-#define SC_PREV_ERROR  4
-
-/* Bits in rbits */
-#define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
-
-static int flag_time = HZ;
-module_param(flag_time, int, 0);
-MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_LDISC(N_PPP);
-
-/*
- * Prototypes.
- */
-static int ppp_async_encode(struct asyncppp *ap);
-static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb);
-static int ppp_async_push(struct asyncppp *ap);
-static void ppp_async_flush_output(struct asyncppp *ap);
-static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
-                           char *flags, int count);
-static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,
-                          unsigned long arg);
-static void ppp_async_process(unsigned long arg);
-
-static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
-                          int len, int inbound);
-
-static const struct ppp_channel_ops async_ops = {
-       .start_xmit = ppp_async_send,
-       .ioctl      = ppp_async_ioctl,
-};
-
-/*
- * Routines implementing the PPP line discipline.
- */
-
-/*
- * We have a potential race on dereferencing tty->disc_data,
- * because the tty layer provides no locking at all - thus one
- * cpu could be running ppp_asynctty_receive while another
- * calls ppp_asynctty_close, which zeroes tty->disc_data and
- * frees the memory that ppp_asynctty_receive is using.  The best
- * way to fix this is to use a rwlock in the tty struct, but for now
- * we use a single global rwlock for all ttys in ppp line discipline.
- *
- * FIXME: this is no longer true. The _close path for the ldisc is
- * now guaranteed to be sane.
- */
-static DEFINE_RWLOCK(disc_data_lock);
-
-static struct asyncppp *ap_get(struct tty_struct *tty)
-{
-       struct asyncppp *ap;
-
-       read_lock(&disc_data_lock);
-       ap = tty->disc_data;
-       if (ap != NULL)
-               atomic_inc(&ap->refcnt);
-       read_unlock(&disc_data_lock);
-       return ap;
-}
-
-static void ap_put(struct asyncppp *ap)
-{
-       if (atomic_dec_and_test(&ap->refcnt))
-               up(&ap->dead_sem);
-}
-
-/*
- * Called when a tty is put into PPP line discipline. Called in process
- * context.
- */
-static int
-ppp_asynctty_open(struct tty_struct *tty)
-{
-       struct asyncppp *ap;
-       int err;
-       int speed;
-
-       if (tty->ops->write == NULL)
-               return -EOPNOTSUPP;
-
-       err = -ENOMEM;
-       ap = kzalloc(sizeof(*ap), GFP_KERNEL);
-       if (!ap)
-               goto out;
-
-       /* initialize the asyncppp structure */
-       ap->tty = tty;
-       ap->mru = PPP_MRU;
-       spin_lock_init(&ap->xmit_lock);
-       spin_lock_init(&ap->recv_lock);
-       ap->xaccm[0] = ~0U;
-       ap->xaccm[3] = 0x60000000U;
-       ap->raccm = ~0U;
-       ap->optr = ap->obuf;
-       ap->olim = ap->obuf;
-       ap->lcp_fcs = -1;
-
-       skb_queue_head_init(&ap->rqueue);
-       tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
-
-       atomic_set(&ap->refcnt, 1);
-       sema_init(&ap->dead_sem, 0);
-
-       ap->chan.private = ap;
-       ap->chan.ops = &async_ops;
-       ap->chan.mtu = PPP_MRU;
-       speed = tty_get_baud_rate(tty);
-       ap->chan.speed = speed;
-       err = ppp_register_channel(&ap->chan);
-       if (err)
-               goto out_free;
-
-       tty->disc_data = ap;
-       tty->receive_room = 65536;
-       return 0;
-
- out_free:
-       kfree(ap);
- out:
-       return err;
-}
-
-/*
- * Called when the tty is put into another line discipline
- * or it hangs up.  We have to wait for any cpu currently
- * executing in any of the other ppp_asynctty_* routines to
- * finish before we can call ppp_unregister_channel and free
- * the asyncppp struct.  This routine must be called from
- * process context, not interrupt or softirq context.
- */
-static void
-ppp_asynctty_close(struct tty_struct *tty)
-{
-       struct asyncppp *ap;
-
-       write_lock_irq(&disc_data_lock);
-       ap = tty->disc_data;
-       tty->disc_data = NULL;
-       write_unlock_irq(&disc_data_lock);
-       if (!ap)
-               return;
-
-       /*
-        * We have now ensured that nobody can start using ap from now
-        * on, but we have to wait for all existing users to finish.
-        * Note that ppp_unregister_channel ensures that no calls to
-        * our channel ops (i.e. ppp_async_send/ioctl) are in progress
-        * by the time it returns.
-        */
-       if (!atomic_dec_and_test(&ap->refcnt))
-               down(&ap->dead_sem);
-       tasklet_kill(&ap->tsk);
-
-       ppp_unregister_channel(&ap->chan);
-       kfree_skb(ap->rpkt);
-       skb_queue_purge(&ap->rqueue);
-       kfree_skb(ap->tpkt);
-       kfree(ap);
-}
-
-/*
- * Called on tty hangup in process context.
- *
- * Wait for I/O to driver to complete and unregister PPP channel.
- * This is already done by the close routine, so just call that.
- */
-static int ppp_asynctty_hangup(struct tty_struct *tty)
-{
-       ppp_asynctty_close(tty);
-       return 0;
-}
-
-/*
- * Read does nothing - no data is ever available this way.
- * Pppd reads and writes packets via /dev/ppp instead.
- */
-static ssize_t
-ppp_asynctty_read(struct tty_struct *tty, struct file *file,
-                 unsigned char __user *buf, size_t count)
-{
-       return -EAGAIN;
-}
-
-/*
- * Write on the tty does nothing, the packets all come in
- * from the ppp generic stuff.
- */
-static ssize_t
-ppp_asynctty_write(struct tty_struct *tty, struct file *file,
-                  const unsigned char *buf, size_t count)
-{
-       return -EAGAIN;
-}
-
-/*
- * Called in process context only. May be re-entered by multiple
- * ioctl calling threads.
- */
-
-static int
-ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
-                  unsigned int cmd, unsigned long arg)
-{
-       struct asyncppp *ap = ap_get(tty);
-       int err, val;
-       int __user *p = (int __user *)arg;
-
-       if (!ap)
-               return -ENXIO;
-       err = -EFAULT;
-       switch (cmd) {
-       case PPPIOCGCHAN:
-               err = -EFAULT;
-               if (put_user(ppp_channel_index(&ap->chan), p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGUNIT:
-               err = -EFAULT;
-               if (put_user(ppp_unit_number(&ap->chan), p))
-                       break;
-               err = 0;
-               break;
-
-       case TCFLSH:
-               /* flush our buffers and the serial port's buffer */
-               if (arg == TCIOFLUSH || arg == TCOFLUSH)
-                       ppp_async_flush_output(ap);
-               err = tty_perform_flush(tty, arg);
-               break;
-
-       case FIONREAD:
-               val = 0;
-               if (put_user(val, p))
-                       break;
-               err = 0;
-               break;
-
-       default:
-               /* Try the various mode ioctls */
-               err = tty_mode_ioctl(tty, file, cmd, arg);
-       }
-
-       ap_put(ap);
-       return err;
-}
-
-/* No kernel lock - fine */
-static unsigned int
-ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
-{
-       return 0;
-}
-
-/* May sleep, don't call from interrupt level or with interrupts disabled */
-static void
-ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
-                 char *cflags, int count)
-{
-       struct asyncppp *ap = ap_get(tty);
-       unsigned long flags;
-
-       if (!ap)
-               return;
-       spin_lock_irqsave(&ap->recv_lock, flags);
-       ppp_async_input(ap, buf, cflags, count);
-       spin_unlock_irqrestore(&ap->recv_lock, flags);
-       if (!skb_queue_empty(&ap->rqueue))
-               tasklet_schedule(&ap->tsk);
-       ap_put(ap);
-       tty_unthrottle(tty);
-}
-
-static void
-ppp_asynctty_wakeup(struct tty_struct *tty)
-{
-       struct asyncppp *ap = ap_get(tty);
-
-       clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-       if (!ap)
-               return;
-       set_bit(XMIT_WAKEUP, &ap->xmit_flags);
-       tasklet_schedule(&ap->tsk);
-       ap_put(ap);
-}
-
-
-static struct tty_ldisc_ops ppp_ldisc = {
-       .owner  = THIS_MODULE,
-       .magic  = TTY_LDISC_MAGIC,
-       .name   = "ppp",
-       .open   = ppp_asynctty_open,
-       .close  = ppp_asynctty_close,
-       .hangup = ppp_asynctty_hangup,
-       .read   = ppp_asynctty_read,
-       .write  = ppp_asynctty_write,
-       .ioctl  = ppp_asynctty_ioctl,
-       .poll   = ppp_asynctty_poll,
-       .receive_buf = ppp_asynctty_receive,
-       .write_wakeup = ppp_asynctty_wakeup,
-};
-
-static int __init
-ppp_async_init(void)
-{
-       int err;
-
-       err = tty_register_ldisc(N_PPP, &ppp_ldisc);
-       if (err != 0)
-               printk(KERN_ERR "PPP_async: error %d registering line disc.\n",
-                      err);
-       return err;
-}
-
-/*
- * The following routines provide the PPP channel interface.
- */
-static int
-ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
-{
-       struct asyncppp *ap = chan->private;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int err, val;
-       u32 accm[8];
-
-       err = -EFAULT;
-       switch (cmd) {
-       case PPPIOCGFLAGS:
-               val = ap->flags | ap->rbits;
-               if (put_user(val, p))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSFLAGS:
-               if (get_user(val, p))
-                       break;
-               ap->flags = val & ~SC_RCV_BITS;
-               spin_lock_irq(&ap->recv_lock);
-               ap->rbits = val & SC_RCV_BITS;
-               spin_unlock_irq(&ap->recv_lock);
-               err = 0;
-               break;
-
-       case PPPIOCGASYNCMAP:
-               if (put_user(ap->xaccm[0], (u32 __user *)argp))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSASYNCMAP:
-               if (get_user(ap->xaccm[0], (u32 __user *)argp))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGRASYNCMAP:
-               if (put_user(ap->raccm, (u32 __user *)argp))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSRASYNCMAP:
-               if (get_user(ap->raccm, (u32 __user *)argp))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGXASYNCMAP:
-               if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSXASYNCMAP:
-               if (copy_from_user(accm, argp, sizeof(accm)))
-                       break;
-               accm[2] &= ~0x40000000U;        /* can't escape 0x5e */
-               accm[3] |= 0x60000000U;         /* must escape 0x7d, 0x7e */
-               memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
-               err = 0;
-               break;
-
-       case PPPIOCGMRU:
-               if (put_user(ap->mru, p))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSMRU:
-               if (get_user(val, p))
-                       break;
-               if (val < PPP_MRU)
-                       val = PPP_MRU;
-               ap->mru = val;
-               err = 0;
-               break;
-
-       default:
-               err = -ENOTTY;
-       }
-
-       return err;
-}
-
-/*
- * This is called at softirq level to deliver received packets
- * to the ppp_generic code, and to tell the ppp_generic code
- * if we can accept more output now.
- */
-static void ppp_async_process(unsigned long arg)
-{
-       struct asyncppp *ap = (struct asyncppp *) arg;
-       struct sk_buff *skb;
-
-       /* process received packets */
-       while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
-               if (skb->cb[0])
-                       ppp_input_error(&ap->chan, 0);
-               ppp_input(&ap->chan, skb);
-       }
-
-       /* try to push more stuff out */
-       if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_async_push(ap))
-               ppp_output_wakeup(&ap->chan);
-}
-
-/*
- * Procedures for encapsulation and framing.
- */
-
-/*
- * Procedure to encode the data for async serial transmission.
- * Does octet stuffing (escaping), puts the address/control bytes
- * on if A/C compression is disabled, and does protocol compression.
- * Assumes ap->tpkt != 0 on entry.
- * Returns 1 if we finished the current frame, 0 otherwise.
- */
-
-#define PUT_BYTE(ap, buf, c, islcp)    do {            \
-       if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
-               *buf++ = PPP_ESCAPE;                    \
-               *buf++ = c ^ PPP_TRANS;                 \
-       } else                                          \
-               *buf++ = c;                             \
-} while (0)
-
-static int
-ppp_async_encode(struct asyncppp *ap)
-{
-       int fcs, i, count, c, proto;
-       unsigned char *buf, *buflim;
-       unsigned char *data;
-       int islcp;
-
-       buf = ap->obuf;
-       ap->olim = buf;
-       ap->optr = buf;
-       i = ap->tpkt_pos;
-       data = ap->tpkt->data;
-       count = ap->tpkt->len;
-       fcs = ap->tfcs;
-       proto = get_unaligned_be16(data);
-
-       /*
-        * LCP packets with code values between 1 (configure-reqest)
-        * and 7 (code-reject) must be sent as though no options
-        * had been negotiated.
-        */
-       islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
-
-       if (i == 0) {
-               if (islcp)
-                       async_lcp_peek(ap, data, count, 0);
-
-               /*
-                * Start of a new packet - insert the leading FLAG
-                * character if necessary.
-                */
-               if (islcp || flag_time == 0 ||
-                   time_after_eq(jiffies, ap->last_xmit + flag_time))
-                       *buf++ = PPP_FLAG;
-               ap->last_xmit = jiffies;
-               fcs = PPP_INITFCS;
-
-               /*
-                * Put in the address/control bytes if necessary
-                */
-               if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
-                       PUT_BYTE(ap, buf, 0xff, islcp);
-                       fcs = PPP_FCS(fcs, 0xff);
-                       PUT_BYTE(ap, buf, 0x03, islcp);
-                       fcs = PPP_FCS(fcs, 0x03);
-               }
-       }
-
-       /*
-        * Once we put in the last byte, we need to put in the FCS
-        * and closing flag, so make sure there is at least 7 bytes
-        * of free space in the output buffer.
-        */
-       buflim = ap->obuf + OBUFSIZE - 6;
-       while (i < count && buf < buflim) {
-               c = data[i++];
-               if (i == 1 && c == 0 && (ap->flags & SC_COMP_PROT))
-                       continue;       /* compress protocol field */
-               fcs = PPP_FCS(fcs, c);
-               PUT_BYTE(ap, buf, c, islcp);
-       }
-
-       if (i < count) {
-               /*
-                * Remember where we are up to in this packet.
-                */
-               ap->olim = buf;
-               ap->tpkt_pos = i;
-               ap->tfcs = fcs;
-               return 0;
-       }
-
-       /*
-        * We have finished the packet.  Add the FCS and flag.
-        */
-       fcs = ~fcs;
-       c = fcs & 0xff;
-       PUT_BYTE(ap, buf, c, islcp);
-       c = (fcs >> 8) & 0xff;
-       PUT_BYTE(ap, buf, c, islcp);
-       *buf++ = PPP_FLAG;
-       ap->olim = buf;
-
-       kfree_skb(ap->tpkt);
-       ap->tpkt = NULL;
-       return 1;
-}
-
-/*
- * Transmit-side routines.
- */
-
-/*
- * Send a packet to the peer over an async tty line.
- * Returns 1 iff the packet was accepted.
- * If the packet was not accepted, we will call ppp_output_wakeup
- * at some later time.
- */
-static int
-ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb)
-{
-       struct asyncppp *ap = chan->private;
-
-       ppp_async_push(ap);
-
-       if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
-               return 0;       /* already full */
-       ap->tpkt = skb;
-       ap->tpkt_pos = 0;
-
-       ppp_async_push(ap);
-       return 1;
-}
-
-/*
- * Push as much data as possible out to the tty.
- */
-static int
-ppp_async_push(struct asyncppp *ap)
-{
-       int avail, sent, done = 0;
-       struct tty_struct *tty = ap->tty;
-       int tty_stuffed = 0;
-
-       /*
-        * We can get called recursively here if the tty write
-        * function calls our wakeup function.  This can happen
-        * for example on a pty with both the master and slave
-        * set to PPP line discipline.
-        * We use the XMIT_BUSY bit to detect this and get out,
-        * leaving the XMIT_WAKEUP bit set to tell the other
-        * instance that it may now be able to write more now.
-        */
-       if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
-               return 0;
-       spin_lock_bh(&ap->xmit_lock);
-       for (;;) {
-               if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
-                       tty_stuffed = 0;
-               if (!tty_stuffed && ap->optr < ap->olim) {
-                       avail = ap->olim - ap->optr;
-                       set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-                       sent = tty->ops->write(tty, ap->optr, avail);
-                       if (sent < 0)
-                               goto flush;     /* error, e.g. loss of CD */
-                       ap->optr += sent;
-                       if (sent < avail)
-                               tty_stuffed = 1;
-                       continue;
-               }
-               if (ap->optr >= ap->olim && ap->tpkt) {
-                       if (ppp_async_encode(ap)) {
-                               /* finished processing ap->tpkt */
-                               clear_bit(XMIT_FULL, &ap->xmit_flags);
-                               done = 1;
-                       }
-                       continue;
-               }
-               /*
-                * We haven't made any progress this time around.
-                * Clear XMIT_BUSY to let other callers in, but
-                * after doing so we have to check if anyone set
-                * XMIT_WAKEUP since we last checked it.  If they
-                * did, we should try again to set XMIT_BUSY and go
-                * around again in case XMIT_BUSY was still set when
-                * the other caller tried.
-                */
-               clear_bit(XMIT_BUSY, &ap->xmit_flags);
-               /* any more work to do? if not, exit the loop */
-               if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||
-                     (!tty_stuffed && ap->tpkt)))
-                       break;
-               /* more work to do, see if we can do it now */
-               if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
-                       break;
-       }
-       spin_unlock_bh(&ap->xmit_lock);
-       return done;
-
-flush:
-       clear_bit(XMIT_BUSY, &ap->xmit_flags);
-       if (ap->tpkt) {
-               kfree_skb(ap->tpkt);
-               ap->tpkt = NULL;
-               clear_bit(XMIT_FULL, &ap->xmit_flags);
-               done = 1;
-       }
-       ap->optr = ap->olim;
-       spin_unlock_bh(&ap->xmit_lock);
-       return done;
-}
-
-/*
- * Flush output from our internal buffers.
- * Called for the TCFLSH ioctl. Can be entered in parallel
- * but this is covered by the xmit_lock.
- */
-static void
-ppp_async_flush_output(struct asyncppp *ap)
-{
-       int done = 0;
-
-       spin_lock_bh(&ap->xmit_lock);
-       ap->optr = ap->olim;
-       if (ap->tpkt != NULL) {
-               kfree_skb(ap->tpkt);
-               ap->tpkt = NULL;
-               clear_bit(XMIT_FULL, &ap->xmit_flags);
-               done = 1;
-       }
-       spin_unlock_bh(&ap->xmit_lock);
-       if (done)
-               ppp_output_wakeup(&ap->chan);
-}
-
-/*
- * Receive-side routines.
- */
-
-/* see how many ordinary chars there are at the start of buf */
-static inline int
-scan_ordinary(struct asyncppp *ap, const unsigned char *buf, int count)
-{
-       int i, c;
-
-       for (i = 0; i < count; ++i) {
-               c = buf[i];
-               if (c == PPP_ESCAPE || c == PPP_FLAG ||
-                   (c < 0x20 && (ap->raccm & (1 << c)) != 0))
-                       break;
-       }
-       return i;
-}
-
-/* called when a flag is seen - do end-of-packet processing */
-static void
-process_input_packet(struct asyncppp *ap)
-{
-       struct sk_buff *skb;
-       unsigned char *p;
-       unsigned int len, fcs, proto;
-
-       skb = ap->rpkt;
-       if (ap->state & (SC_TOSS | SC_ESCAPE))
-               goto err;
-
-       if (skb == NULL)
-               return;         /* 0-length packet */
-
-       /* check the FCS */
-       p = skb->data;
-       len = skb->len;
-       if (len < 3)
-               goto err;       /* too short */
-       fcs = PPP_INITFCS;
-       for (; len > 0; --len)
-               fcs = PPP_FCS(fcs, *p++);
-       if (fcs != PPP_GOODFCS)
-               goto err;       /* bad FCS */
-       skb_trim(skb, skb->len - 2);
-
-       /* check for address/control and protocol compression */
-       p = skb->data;
-       if (p[0] == PPP_ALLSTATIONS) {
-               /* chop off address/control */
-               if (p[1] != PPP_UI || skb->len < 3)
-                       goto err;
-               p = skb_pull(skb, 2);
-       }
-       proto = p[0];
-       if (proto & 1) {
-               /* protocol is compressed */
-               skb_push(skb, 1)[0] = 0;
-       } else {
-               if (skb->len < 2)
-                       goto err;
-               proto = (proto << 8) + p[1];
-               if (proto == PPP_LCP)
-                       async_lcp_peek(ap, p, skb->len, 1);
-       }
-
-       /* queue the frame to be processed */
-       skb->cb[0] = ap->state;
-       skb_queue_tail(&ap->rqueue, skb);
-       ap->rpkt = NULL;
-       ap->state = 0;
-       return;
-
- err:
-       /* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
-       ap->state = SC_PREV_ERROR;
-       if (skb) {
-               /* make skb appear as freshly allocated */
-               skb_trim(skb, 0);
-               skb_reserve(skb, - skb_headroom(skb));
-       }
-}
-
-/* Called when the tty driver has data for us. Runs parallel with the
-   other ldisc functions but will not be re-entered */
-
-static void
-ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
-               char *flags, int count)
-{
-       struct sk_buff *skb;
-       int c, i, j, n, s, f;
-       unsigned char *sp;
-
-       /* update bits used for 8-bit cleanness detection */
-       if (~ap->rbits & SC_RCV_BITS) {
-               s = 0;
-               for (i = 0; i < count; ++i) {
-                       c = buf[i];
-                       if (flags && flags[i] != 0)
-                               continue;
-                       s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
-                       c = ((c >> 4) ^ c) & 0xf;
-                       s |= (0x6996 & (1 << c))? SC_RCV_ODDP: SC_RCV_EVNP;
-               }
-               ap->rbits |= s;
-       }
-
-       while (count > 0) {
-               /* scan through and see how many chars we can do in bulk */
-               if ((ap->state & SC_ESCAPE) && buf[0] == PPP_ESCAPE)
-                       n = 1;
-               else
-                       n = scan_ordinary(ap, buf, count);
-
-               f = 0;
-               if (flags && (ap->state & SC_TOSS) == 0) {
-                       /* check the flags to see if any char had an error */
-                       for (j = 0; j < n; ++j)
-                               if ((f = flags[j]) != 0)
-                                       break;
-               }
-               if (f != 0) {
-                       /* start tossing */
-                       ap->state |= SC_TOSS;
-
-               } else if (n > 0 && (ap->state & SC_TOSS) == 0) {
-                       /* stuff the chars in the skb */
-                       skb = ap->rpkt;
-                       if (!skb) {
-                               skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
-                               if (!skb)
-                                       goto nomem;
-                               ap->rpkt = skb;
-                       }
-                       if (skb->len == 0) {
-                               /* Try to get the payload 4-byte aligned.
-                                * This should match the
-                                * PPP_ALLSTATIONS/PPP_UI/compressed tests in
-                                * process_input_packet, but we do not have
-                                * enough chars here to test buf[1] and buf[2].
-                                */
-                               if (buf[0] != PPP_ALLSTATIONS)
-                                       skb_reserve(skb, 2 + (buf[0] & 1));
-                       }
-                       if (n > skb_tailroom(skb)) {
-                               /* packet overflowed MRU */
-                               ap->state |= SC_TOSS;
-                       } else {
-                               sp = skb_put(skb, n);
-                               memcpy(sp, buf, n);
-                               if (ap->state & SC_ESCAPE) {
-                                       sp[0] ^= PPP_TRANS;
-                                       ap->state &= ~SC_ESCAPE;
-                               }
-                       }
-               }
-
-               if (n >= count)
-                       break;
-
-               c = buf[n];
-               if (flags != NULL && flags[n] != 0) {
-                       ap->state |= SC_TOSS;
-               } else if (c == PPP_FLAG) {
-                       process_input_packet(ap);
-               } else if (c == PPP_ESCAPE) {
-                       ap->state |= SC_ESCAPE;
-               } else if (I_IXON(ap->tty)) {
-                       if (c == START_CHAR(ap->tty))
-                               start_tty(ap->tty);
-                       else if (c == STOP_CHAR(ap->tty))
-                               stop_tty(ap->tty);
-               }
-               /* otherwise it's a char in the recv ACCM */
-               ++n;
-
-               buf += n;
-               if (flags)
-                       flags += n;
-               count -= n;
-       }
-       return;
-
- nomem:
-       printk(KERN_ERR "PPPasync: no memory (input pkt)\n");
-       ap->state |= SC_TOSS;
-}
-
-/*
- * We look at LCP frames going past so that we can notice
- * and react to the LCP configure-ack from the peer.
- * In the situation where the peer has been sent a configure-ack
- * already, LCP is up once it has sent its configure-ack
- * so the immediately following packet can be sent with the
- * configured LCP options.  This allows us to process the following
- * packet correctly without pppd needing to respond quickly.
- *
- * We only respond to the received configure-ack if we have just
- * sent a configure-request, and the configure-ack contains the
- * same data (this is checked using a 16-bit crc of the data).
- */
-#define CONFREQ                1       /* LCP code field values */
-#define CONFACK                2
-#define LCP_MRU                1       /* LCP option numbers */
-#define LCP_ASYNCMAP   2
-
-static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
-                          int len, int inbound)
-{
-       int dlen, fcs, i, code;
-       u32 val;
-
-       data += 2;              /* skip protocol bytes */
-       len -= 2;
-       if (len < 4)            /* 4 = code, ID, length */
-               return;
-       code = data[0];
-       if (code != CONFACK && code != CONFREQ)
-               return;
-       dlen = get_unaligned_be16(data + 2);
-       if (len < dlen)
-               return;         /* packet got truncated or length is bogus */
-
-       if (code == (inbound? CONFACK: CONFREQ)) {
-               /*
-                * sent confreq or received confack:
-                * calculate the crc of the data from the ID field on.
-                */
-               fcs = PPP_INITFCS;
-               for (i = 1; i < dlen; ++i)
-                       fcs = PPP_FCS(fcs, data[i]);
-
-               if (!inbound) {
-                       /* outbound confreq - remember the crc for later */
-                       ap->lcp_fcs = fcs;
-                       return;
-               }
-
-               /* received confack, check the crc */
-               fcs ^= ap->lcp_fcs;
-               ap->lcp_fcs = -1;
-               if (fcs != 0)
-                       return;
-       } else if (inbound)
-               return; /* not interested in received confreq */
-
-       /* process the options in the confack */
-       data += 4;
-       dlen -= 4;
-       /* data[0] is code, data[1] is length */
-       while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {
-               switch (data[0]) {
-               case LCP_MRU:
-                       val = get_unaligned_be16(data + 2);
-                       if (inbound)
-                               ap->mru = val;
-                       else
-                               ap->chan.mtu = val;
-                       break;
-               case LCP_ASYNCMAP:
-                       val = get_unaligned_be32(data + 2);
-                       if (inbound)
-                               ap->raccm = val;
-                       else
-                               ap->xaccm[0] = val;
-                       break;
-               }
-               dlen -= data[1];
-               data += data[1];
-       }
-}
-
-static void __exit ppp_async_cleanup(void)
-{
-       if (tty_unregister_ldisc(N_PPP) != 0)
-               printk(KERN_ERR "failed to unregister PPP line discipline\n");
-}
-
-module_init(ppp_async_init);
-module_exit(ppp_async_cleanup);
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
deleted file mode 100644 (file)
index 1dbdf82..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- *  ==FILEVERSION 980319==
- *
- * ppp_deflate.c - interface the zlib procedures for Deflate compression
- * and decompression (as used by gzip) to the PPP code.
- * This version is for use with Linux kernel 1.3.X.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies.  This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <linux/ppp_defs.h>
-#include <linux/ppp-comp.h>
-
-#include <linux/zlib.h>
-#include <asm/unaligned.h>
-
-/*
- * State for a Deflate (de)compressor.
- */
-struct ppp_deflate_state {
-    int                seqno;
-    int                w_size;
-    int                unit;
-    int                mru;
-    int                debug;
-    z_stream   strm;
-    struct compstat stats;
-};
-
-#define DEFLATE_OVHD   2               /* Deflate overhead/packet */
-
-static void    *z_comp_alloc(unsigned char *options, int opt_len);
-static void    *z_decomp_alloc(unsigned char *options, int opt_len);
-static void    z_comp_free(void *state);
-static void    z_decomp_free(void *state);
-static int     z_comp_init(void *state, unsigned char *options,
-                                int opt_len,
-                                int unit, int hdrlen, int debug);
-static int     z_decomp_init(void *state, unsigned char *options,
-                                  int opt_len,
-                                  int unit, int hdrlen, int mru, int debug);
-static int     z_compress(void *state, unsigned char *rptr,
-                               unsigned char *obuf,
-                               int isize, int osize);
-static void    z_incomp(void *state, unsigned char *ibuf, int icnt);
-static int     z_decompress(void *state, unsigned char *ibuf,
-                               int isize, unsigned char *obuf, int osize);
-static void    z_comp_reset(void *state);
-static void    z_decomp_reset(void *state);
-static void    z_comp_stats(void *state, struct compstat *stats);
-
-/**
- *     z_comp_free - free the memory used by a compressor
- *     @arg:   pointer to the private state for the compressor.
- */
-static void z_comp_free(void *arg)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       if (state) {
-               zlib_deflateEnd(&state->strm);
-               vfree(state->strm.workspace);
-               kfree(state);
-       }
-}
-
-/**
- *     z_comp_alloc - allocate space for a compressor.
- *     @options: pointer to CCP option data
- *     @opt_len: length of the CCP option at @options.
- *
- *     The @options pointer points to the a buffer containing the
- *     CCP option data for the compression being negotiated.  It is
- *     formatted according to RFC1979, and describes the window
- *     size that the peer is requesting that we use in compressing
- *     data to be sent to it.
- *
- *     Returns the pointer to the private state for the compressor,
- *     or NULL if we could not allocate enough memory.
- */
-static void *z_comp_alloc(unsigned char *options, int opt_len)
-{
-       struct ppp_deflate_state *state;
-       int w_size;
-
-       if (opt_len != CILEN_DEFLATE ||
-           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
-           options[1] != CILEN_DEFLATE ||
-           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
-           options[3] != DEFLATE_CHK_SEQUENCE)
-               return NULL;
-       w_size = DEFLATE_SIZE(options[2]);
-       if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
-               return NULL;
-
-       state = kzalloc(sizeof(*state),
-                                                    GFP_KERNEL);
-       if (state == NULL)
-               return NULL;
-
-       state->strm.next_in   = NULL;
-       state->w_size         = w_size;
-       state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
-       if (state->strm.workspace == NULL)
-               goto out_free;
-
-       if (zlib_deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
-                        DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
-           != Z_OK)
-               goto out_free;
-       return (void *) state;
-
-out_free:
-       z_comp_free(state);
-       return NULL;
-}
-
-/**
- *     z_comp_init - initialize a previously-allocated compressor.
- *     @arg:   pointer to the private state for the compressor
- *     @options: pointer to the CCP option data describing the
- *             compression that was negotiated with the peer
- *     @opt_len: length of the CCP option data at @options
- *     @unit:  PPP unit number for diagnostic messages
- *     @hdrlen: ignored (present for backwards compatibility)
- *     @debug: debug flag; if non-zero, debug messages are printed.
- *
- *     The CCP options described by @options must match the options
- *     specified when the compressor was allocated.  The compressor
- *     history is reset.  Returns 0 for failure (CCP options don't
- *     match) or 1 for success.
- */
-static int z_comp_init(void *arg, unsigned char *options, int opt_len,
-                      int unit, int hdrlen, int debug)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       if (opt_len < CILEN_DEFLATE ||
-           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
-           options[1] != CILEN_DEFLATE ||
-           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
-           DEFLATE_SIZE(options[2]) != state->w_size ||
-           options[3] != DEFLATE_CHK_SEQUENCE)
-               return 0;
-
-       state->seqno = 0;
-       state->unit  = unit;
-       state->debug = debug;
-
-       zlib_deflateReset(&state->strm);
-
-       return 1;
-}
-
-/**
- *     z_comp_reset - reset a previously-allocated compressor.
- *     @arg:   pointer to private state for the compressor.
- *
- *     This clears the history for the compressor and makes it
- *     ready to start emitting a new compressed stream.
- */
-static void z_comp_reset(void *arg)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       state->seqno = 0;
-       zlib_deflateReset(&state->strm);
-}
-
-/**
- *     z_compress - compress a PPP packet with Deflate compression.
- *     @arg:   pointer to private state for the compressor
- *     @rptr:  uncompressed packet (input)
- *     @obuf:  compressed packet (output)
- *     @isize: size of uncompressed packet
- *     @osize: space available at @obuf
- *
- *     Returns the length of the compressed packet, or 0 if the
- *     packet is incompressible.
- */
-static int z_compress(void *arg, unsigned char *rptr, unsigned char *obuf,
-              int isize, int osize)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-       int r, proto, off, olen, oavail;
-       unsigned char *wptr;
-
-       /*
-        * Check that the protocol is in the range we handle.
-        */
-       proto = PPP_PROTOCOL(rptr);
-       if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
-               return 0;
-
-       /* Don't generate compressed packets which are larger than
-          the uncompressed packet. */
-       if (osize > isize)
-               osize = isize;
-
-       wptr = obuf;
-
-       /*
-        * Copy over the PPP header and store the 2-byte sequence number.
-        */
-       wptr[0] = PPP_ADDRESS(rptr);
-       wptr[1] = PPP_CONTROL(rptr);
-       put_unaligned_be16(PPP_COMP, wptr + 2);
-       wptr += PPP_HDRLEN;
-       put_unaligned_be16(state->seqno, wptr);
-       wptr += DEFLATE_OVHD;
-       olen = PPP_HDRLEN + DEFLATE_OVHD;
-       state->strm.next_out = wptr;
-       state->strm.avail_out = oavail = osize - olen;
-       ++state->seqno;
-
-       off = (proto > 0xff) ? 2 : 3;   /* skip 1st proto byte if 0 */
-       rptr += off;
-       state->strm.next_in = rptr;
-       state->strm.avail_in = (isize - off);
-
-       for (;;) {
-               r = zlib_deflate(&state->strm, Z_PACKET_FLUSH);
-               if (r != Z_OK) {
-                       if (state->debug)
-                               printk(KERN_ERR
-                                      "z_compress: deflate returned %d\n", r);
-                       break;
-               }
-               if (state->strm.avail_out == 0) {
-                       olen += oavail;
-                       state->strm.next_out = NULL;
-                       state->strm.avail_out = oavail = 1000000;
-               } else {
-                       break;          /* all done */
-               }
-       }
-       olen += oavail - state->strm.avail_out;
-
-       /*
-        * See if we managed to reduce the size of the packet.
-        */
-       if (olen < isize) {
-               state->stats.comp_bytes += olen;
-               state->stats.comp_packets++;
-       } else {
-               state->stats.inc_bytes += isize;
-               state->stats.inc_packets++;
-               olen = 0;
-       }
-       state->stats.unc_bytes += isize;
-       state->stats.unc_packets++;
-
-       return olen;
-}
-
-/**
- *     z_comp_stats - return compression statistics for a compressor
- *             or decompressor.
- *     @arg:   pointer to private space for the (de)compressor
- *     @stats: pointer to a struct compstat to receive the result.
- */
-static void z_comp_stats(void *arg, struct compstat *stats)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       *stats = state->stats;
-}
-
-/**
- *     z_decomp_free - Free the memory used by a decompressor.
- *     @arg:   pointer to private space for the decompressor.
- */
-static void z_decomp_free(void *arg)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       if (state) {
-               zlib_inflateEnd(&state->strm);
-               vfree(state->strm.workspace);
-               kfree(state);
-       }
-}
-
-/**
- *     z_decomp_alloc - allocate space for a decompressor.
- *     @options: pointer to CCP option data
- *     @opt_len: length of the CCP option at @options.
- *
- *     The @options pointer points to the a buffer containing the
- *     CCP option data for the compression being negotiated.  It is
- *     formatted according to RFC1979, and describes the window
- *     size that we are requesting the peer to use in compressing
- *     data to be sent to us.
- *
- *     Returns the pointer to the private state for the decompressor,
- *     or NULL if we could not allocate enough memory.
- */
-static void *z_decomp_alloc(unsigned char *options, int opt_len)
-{
-       struct ppp_deflate_state *state;
-       int w_size;
-
-       if (opt_len != CILEN_DEFLATE ||
-           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
-           options[1] != CILEN_DEFLATE ||
-           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
-           options[3] != DEFLATE_CHK_SEQUENCE)
-               return NULL;
-       w_size = DEFLATE_SIZE(options[2]);
-       if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
-               return NULL;
-
-       state = kzalloc(sizeof(*state), GFP_KERNEL);
-       if (state == NULL)
-               return NULL;
-
-       state->w_size         = w_size;
-       state->strm.next_out  = NULL;
-       state->strm.workspace = vmalloc(zlib_inflate_workspacesize());
-       if (state->strm.workspace == NULL)
-               goto out_free;
-
-       if (zlib_inflateInit2(&state->strm, -w_size) != Z_OK)
-               goto out_free;
-       return (void *) state;
-
-out_free:
-       z_decomp_free(state);
-       return NULL;
-}
-
-/**
- *     z_decomp_init - initialize a previously-allocated decompressor.
- *     @arg:   pointer to the private state for the decompressor
- *     @options: pointer to the CCP option data describing the
- *             compression that was negotiated with the peer
- *     @opt_len: length of the CCP option data at @options
- *     @unit:  PPP unit number for diagnostic messages
- *     @hdrlen: ignored (present for backwards compatibility)
- *     @mru:   maximum length of decompressed packets
- *     @debug: debug flag; if non-zero, debug messages are printed.
- *
- *     The CCP options described by @options must match the options
- *     specified when the decompressor was allocated.  The decompressor
- *     history is reset.  Returns 0 for failure (CCP options don't
- *     match) or 1 for success.
- */
-static int z_decomp_init(void *arg, unsigned char *options, int opt_len,
-                        int unit, int hdrlen, int mru, int debug)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       if (opt_len < CILEN_DEFLATE ||
-           (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) ||
-           options[1] != CILEN_DEFLATE ||
-           DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL ||
-           DEFLATE_SIZE(options[2]) != state->w_size ||
-           options[3] != DEFLATE_CHK_SEQUENCE)
-               return 0;
-
-       state->seqno = 0;
-       state->unit  = unit;
-       state->debug = debug;
-       state->mru   = mru;
-
-       zlib_inflateReset(&state->strm);
-
-       return 1;
-}
-
-/**
- *     z_decomp_reset - reset a previously-allocated decompressor.
- *     @arg:   pointer to private state for the decompressor.
- *
- *     This clears the history for the decompressor and makes it
- *     ready to receive a new compressed stream.
- */
-static void z_decomp_reset(void *arg)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-
-       state->seqno = 0;
-       zlib_inflateReset(&state->strm);
-}
-
-/**
- *     z_decompress - decompress a Deflate-compressed packet.
- *     @arg:   pointer to private state for the decompressor
- *     @ibuf:  pointer to input (compressed) packet data
- *     @isize: length of input packet
- *     @obuf:  pointer to space for output (decompressed) packet
- *     @osize: amount of space available at @obuf
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression.  For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-static int z_decompress(void *arg, unsigned char *ibuf, int isize,
-                unsigned char *obuf, int osize)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-       int olen, seq, r;
-       int decode_proto, overflow;
-       unsigned char overflow_buf[1];
-
-       if (isize <= PPP_HDRLEN + DEFLATE_OVHD) {
-               if (state->debug)
-                       printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",
-                              state->unit, isize);
-               return DECOMP_ERROR;
-       }
-
-       /* Check the sequence number. */
-       seq = get_unaligned_be16(ibuf + PPP_HDRLEN);
-       if (seq != (state->seqno & 0xffff)) {
-               if (state->debug)
-                       printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n",
-                              state->unit, seq, state->seqno & 0xffff);
-               return DECOMP_ERROR;
-       }
-       ++state->seqno;
-
-       /*
-        * Fill in the first part of the PPP header.  The protocol field
-        * comes from the decompressed data.
-        */
-       obuf[0] = PPP_ADDRESS(ibuf);
-       obuf[1] = PPP_CONTROL(ibuf);
-       obuf[2] = 0;
-
-       /*
-        * Set up to call inflate.  We set avail_out to 1 initially so we can
-        * look at the first byte of the output and decide whether we have
-        * a 1-byte or 2-byte protocol field.
-        */
-       state->strm.next_in = ibuf + PPP_HDRLEN + DEFLATE_OVHD;
-       state->strm.avail_in = isize - (PPP_HDRLEN + DEFLATE_OVHD);
-       state->strm.next_out = obuf + 3;
-       state->strm.avail_out = 1;
-       decode_proto = 1;
-       overflow = 0;
-
-       /*
-        * Call inflate, supplying more input or output as needed.
-        */
-       for (;;) {
-               r = zlib_inflate(&state->strm, Z_PACKET_FLUSH);
-               if (r != Z_OK) {
-                       if (state->debug)
-                               printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",
-                                      state->unit, r, (state->strm.msg? state->strm.msg: ""));
-                       return DECOMP_FATALERROR;
-               }
-               if (state->strm.avail_out != 0)
-                       break;          /* all done */
-               if (decode_proto) {
-                       state->strm.avail_out = osize - PPP_HDRLEN;
-                       if ((obuf[3] & 1) == 0) {
-                               /* 2-byte protocol field */
-                               obuf[2] = obuf[3];
-                               --state->strm.next_out;
-                               ++state->strm.avail_out;
-                       }
-                       decode_proto = 0;
-               } else if (!overflow) {
-                       /*
-                        * We've filled up the output buffer; the only way to
-                        * find out whether inflate has any more characters
-                        * left is to give it another byte of output space.
-                        */
-                       state->strm.next_out = overflow_buf;
-                       state->strm.avail_out = 1;
-                       overflow = 1;
-               } else {
-                       if (state->debug)
-                               printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",
-                                      state->unit);
-                       return DECOMP_FATALERROR;
-               }
-       }
-
-       if (decode_proto) {
-               if (state->debug)
-                       printk(KERN_DEBUG "z_decompress%d: didn't get proto\n",
-                              state->unit);
-               return DECOMP_ERROR;
-       }
-
-       olen = osize + overflow - state->strm.avail_out;
-       state->stats.unc_bytes += olen;
-       state->stats.unc_packets++;
-       state->stats.comp_bytes += isize;
-       state->stats.comp_packets++;
-
-       return olen;
-}
-
-/**
- *     z_incomp - add incompressible input data to the history.
- *     @arg:   pointer to private state for the decompressor
- *     @ibuf:  pointer to input packet data
- *     @icnt:  length of input data.
- */
-static void z_incomp(void *arg, unsigned char *ibuf, int icnt)
-{
-       struct ppp_deflate_state *state = (struct ppp_deflate_state *) arg;
-       int proto, r;
-
-       /*
-        * Check that the protocol is one we handle.
-        */
-       proto = PPP_PROTOCOL(ibuf);
-       if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
-               return;
-
-       ++state->seqno;
-
-       /*
-        * We start at the either the 1st or 2nd byte of the protocol field,
-        * depending on whether the protocol value is compressible.
-        */
-       state->strm.next_in = ibuf + 3;
-       state->strm.avail_in = icnt - 3;
-       if (proto > 0xff) {
-               --state->strm.next_in;
-               ++state->strm.avail_in;
-       }
-
-       r = zlib_inflateIncomp(&state->strm);
-       if (r != Z_OK) {
-               /* gak! */
-               if (state->debug) {
-                       printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",
-                              state->unit, r, (state->strm.msg? state->strm.msg: ""));
-               }
-               return;
-       }
-
-       /*
-        * Update stats.
-        */
-       state->stats.inc_bytes += icnt;
-       state->stats.inc_packets++;
-       state->stats.unc_bytes += icnt;
-       state->stats.unc_packets++;
-}
-
-/*************************************************************
- * Module interface table
- *************************************************************/
-
-/* These are in ppp_generic.c */
-extern int  ppp_register_compressor   (struct compressor *cp);
-extern void ppp_unregister_compressor (struct compressor *cp);
-
-/*
- * Procedures exported to if_ppp.c.
- */
-static struct compressor ppp_deflate = {
-       .compress_proto =       CI_DEFLATE,
-       .comp_alloc =           z_comp_alloc,
-       .comp_free =            z_comp_free,
-       .comp_init =            z_comp_init,
-       .comp_reset =           z_comp_reset,
-       .compress =             z_compress,
-       .comp_stat =            z_comp_stats,
-       .decomp_alloc =         z_decomp_alloc,
-       .decomp_free =          z_decomp_free,
-       .decomp_init =          z_decomp_init,
-       .decomp_reset =         z_decomp_reset,
-       .decompress =           z_decompress,
-       .incomp =               z_incomp,
-       .decomp_stat =          z_comp_stats,
-       .owner =                THIS_MODULE
-};
-
-static struct compressor ppp_deflate_draft = {
-       .compress_proto =       CI_DEFLATE_DRAFT,
-       .comp_alloc =           z_comp_alloc,
-       .comp_free =            z_comp_free,
-       .comp_init =            z_comp_init,
-       .comp_reset =           z_comp_reset,
-       .compress =             z_compress,
-       .comp_stat =            z_comp_stats,
-       .decomp_alloc =         z_decomp_alloc,
-       .decomp_free =          z_decomp_free,
-       .decomp_init =          z_decomp_init,
-       .decomp_reset =         z_decomp_reset,
-       .decompress =           z_decompress,
-       .incomp =               z_incomp,
-       .decomp_stat =          z_comp_stats,
-       .owner =                THIS_MODULE
-};
-
-static int __init deflate_init(void)
-{
-        int answer = ppp_register_compressor(&ppp_deflate);
-        if (answer == 0)
-                printk(KERN_INFO
-                      "PPP Deflate Compression module registered\n");
-       ppp_register_compressor(&ppp_deflate_draft);
-        return answer;
-}
-
-static void __exit deflate_cleanup(void)
-{
-       ppp_unregister_compressor(&ppp_deflate);
-       ppp_unregister_compressor(&ppp_deflate_draft);
-}
-
-module_init(deflate_init);
-module_exit(deflate_cleanup);
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE));
-MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT));
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
deleted file mode 100644 (file)
index 10e5d98..0000000
+++ /dev/null
@@ -1,2954 +0,0 @@
-/*
- * Generic PPP layer for Linux.
- *
- * Copyright 1999-2002 Paul Mackerras.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- * The generic PPP layer handles the PPP network interfaces, the
- * /dev/ppp device, packet and VJ compression, and multilink.
- * It talks to PPP `channels' via the interface defined in
- * include/linux/ppp_channel.h.  Channels provide the basic means for
- * sending and receiving PPP frames on some kind of communications
- * channel.
- *
- * Part of the code in this driver was inspired by the old async-only
- * PPP driver, written by Michael Callahan and Al Longyear, and
- * subsequently hacked by Paul Mackerras.
- *
- * ==FILEVERSION 20041108==
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/idr.h>
-#include <linux/netdevice.h>
-#include <linux/poll.h>
-#include <linux/ppp_defs.h>
-#include <linux/filter.h>
-#include <linux/if_ppp.h>
-#include <linux/ppp_channel.h>
-#include <linux/ppp-comp.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/if_arp.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/spinlock.h>
-#include <linux/rwsem.h>
-#include <linux/stddef.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-#include <net/slhc_vj.h>
-#include <linux/atomic.h>
-
-#include <linux/nsproxy.h>
-#include <net/net_namespace.h>
-#include <net/netns/generic.h>
-
-#define PPP_VERSION    "2.4.2"
-
-/*
- * Network protocols we support.
- */
-#define NP_IP  0               /* Internet Protocol V4 */
-#define NP_IPV6        1               /* Internet Protocol V6 */
-#define NP_IPX 2               /* IPX protocol */
-#define NP_AT  3               /* Appletalk protocol */
-#define NP_MPLS_UC 4           /* MPLS unicast */
-#define NP_MPLS_MC 5           /* MPLS multicast */
-#define NUM_NP 6               /* Number of NPs. */
-
-#define MPHDRLEN       6       /* multilink protocol header length */
-#define MPHDRLEN_SSN   4       /* ditto with short sequence numbers */
-
-/*
- * An instance of /dev/ppp can be associated with either a ppp
- * interface unit or a ppp channel.  In both cases, file->private_data
- * points to one of these.
- */
-struct ppp_file {
-       enum {
-               INTERFACE=1, CHANNEL
-       }               kind;
-       struct sk_buff_head xq;         /* pppd transmit queue */
-       struct sk_buff_head rq;         /* receive queue for pppd */
-       wait_queue_head_t rwait;        /* for poll on reading /dev/ppp */
-       atomic_t        refcnt;         /* # refs (incl /dev/ppp attached) */
-       int             hdrlen;         /* space to leave for headers */
-       int             index;          /* interface unit / channel number */
-       int             dead;           /* unit/channel has been shut down */
-};
-
-#define PF_TO_X(pf, X)         container_of(pf, X, file)
-
-#define PF_TO_PPP(pf)          PF_TO_X(pf, struct ppp)
-#define PF_TO_CHANNEL(pf)      PF_TO_X(pf, struct channel)
-
-/*
- * Data structure describing one ppp unit.
- * A ppp unit corresponds to a ppp network interface device
- * and represents a multilink bundle.
- * It can have 0 or more ppp channels connected to it.
- */
-struct ppp {
-       struct ppp_file file;           /* stuff for read/write/poll 0 */
-       struct file     *owner;         /* file that owns this unit 48 */
-       struct list_head channels;      /* list of attached channels 4c */
-       int             n_channels;     /* how many channels are attached 54 */
-       spinlock_t      rlock;          /* lock for receive side 58 */
-       spinlock_t      wlock;          /* lock for transmit side 5c */
-       int             mru;            /* max receive unit 60 */
-       unsigned int    flags;          /* control bits 64 */
-       unsigned int    xstate;         /* transmit state bits 68 */
-       unsigned int    rstate;         /* receive state bits 6c */
-       int             debug;          /* debug flags 70 */
-       struct slcompress *vj;          /* state for VJ header compression */
-       enum NPmode     npmode[NUM_NP]; /* what to do with each net proto 78 */
-       struct sk_buff  *xmit_pending;  /* a packet ready to go out 88 */
-       struct compressor *xcomp;       /* transmit packet compressor 8c */
-       void            *xc_state;      /* its internal state 90 */
-       struct compressor *rcomp;       /* receive decompressor 94 */
-       void            *rc_state;      /* its internal state 98 */
-       unsigned long   last_xmit;      /* jiffies when last pkt sent 9c */
-       unsigned long   last_recv;      /* jiffies when last pkt rcvd a0 */
-       struct net_device *dev;         /* network interface device a4 */
-       int             closing;        /* is device closing down? a8 */
-#ifdef CONFIG_PPP_MULTILINK
-       int             nxchan;         /* next channel to send something on */
-       u32             nxseq;          /* next sequence number to send */
-       int             mrru;           /* MP: max reconst. receive unit */
-       u32             nextseq;        /* MP: seq no of next packet */
-       u32             minseq;         /* MP: min of most recent seqnos */
-       struct sk_buff_head mrq;        /* MP: receive reconstruction queue */
-#endif /* CONFIG_PPP_MULTILINK */
-#ifdef CONFIG_PPP_FILTER
-       struct sock_filter *pass_filter;        /* filter for packets to pass */
-       struct sock_filter *active_filter;/* filter for pkts to reset idle */
-       unsigned pass_len, active_len;
-#endif /* CONFIG_PPP_FILTER */
-       struct net      *ppp_net;       /* the net we belong to */
-};
-
-/*
- * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC,
- * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP,
- * SC_MUST_COMP
- * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR.
- * Bits in xstate: SC_COMP_RUN
- */
-#define SC_FLAG_BITS   (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \
-                        |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \
-                        |SC_COMP_TCP|SC_REJ_COMP_TCP|SC_MUST_COMP)
-
-/*
- * Private data structure for each channel.
- * This includes the data structure used for multilink.
- */
-struct channel {
-       struct ppp_file file;           /* stuff for read/write/poll */
-       struct list_head list;          /* link in all/new_channels list */
-       struct ppp_channel *chan;       /* public channel data structure */
-       struct rw_semaphore chan_sem;   /* protects `chan' during chan ioctl */
-       spinlock_t      downl;          /* protects `chan', file.xq dequeue */
-       struct ppp      *ppp;           /* ppp unit we're connected to */
-       struct net      *chan_net;      /* the net channel belongs to */
-       struct list_head clist;         /* link in list of channels per unit */
-       rwlock_t        upl;            /* protects `ppp' */
-#ifdef CONFIG_PPP_MULTILINK
-       u8              avail;          /* flag used in multilink stuff */
-       u8              had_frag;       /* >= 1 fragments have been sent */
-       u32             lastseq;        /* MP: last sequence # received */
-       int             speed;          /* speed of the corresponding ppp channel*/
-#endif /* CONFIG_PPP_MULTILINK */
-};
-
-/*
- * SMP locking issues:
- * Both the ppp.rlock and ppp.wlock locks protect the ppp.channels
- * list and the ppp.n_channels field, you need to take both locks
- * before you modify them.
- * The lock ordering is: channel.upl -> ppp.wlock -> ppp.rlock ->
- * channel.downl.
- */
-
-static DEFINE_MUTEX(ppp_mutex);
-static atomic_t ppp_unit_count = ATOMIC_INIT(0);
-static atomic_t channel_count = ATOMIC_INIT(0);
-
-/* per-net private data for this module */
-static int ppp_net_id __read_mostly;
-struct ppp_net {
-       /* units to ppp mapping */
-       struct idr units_idr;
-
-       /*
-        * all_ppp_mutex protects the units_idr mapping.
-        * It also ensures that finding a ppp unit in the units_idr
-        * map and updating its file.refcnt field is atomic.
-        */
-       struct mutex all_ppp_mutex;
-
-       /* channels */
-       struct list_head all_channels;
-       struct list_head new_channels;
-       int last_channel_index;
-
-       /*
-        * all_channels_lock protects all_channels and
-        * last_channel_index, and the atomicity of find
-        * a channel and updating its file.refcnt field.
-        */
-       spinlock_t all_channels_lock;
-};
-
-/* Get the PPP protocol number from a skb */
-#define PPP_PROTO(skb) get_unaligned_be16((skb)->data)
-
-/* We limit the length of ppp->file.rq to this (arbitrary) value */
-#define PPP_MAX_RQLEN  32
-
-/*
- * Maximum number of multilink fragments queued up.
- * This has to be large enough to cope with the maximum latency of
- * the slowest channel relative to the others.  Strictly it should
- * depend on the number of channels and their characteristics.
- */
-#define PPP_MP_MAX_QLEN        128
-
-/* Multilink header bits. */
-#define B      0x80            /* this fragment begins a packet */
-#define E      0x40            /* this fragment ends a packet */
-
-/* Compare multilink sequence numbers (assumed to be 32 bits wide) */
-#define seq_before(a, b)       ((s32)((a) - (b)) < 0)
-#define seq_after(a, b)                ((s32)((a) - (b)) > 0)
-
-/* Prototypes. */
-static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
-                       struct file *file, unsigned int cmd, unsigned long arg);
-static void ppp_xmit_process(struct ppp *ppp);
-static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
-static void ppp_push(struct ppp *ppp);
-static void ppp_channel_push(struct channel *pch);
-static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb,
-                             struct channel *pch);
-static void ppp_receive_error(struct ppp *ppp);
-static void ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb);
-static struct sk_buff *ppp_decompress_frame(struct ppp *ppp,
-                                           struct sk_buff *skb);
-#ifdef CONFIG_PPP_MULTILINK
-static void ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb,
-                               struct channel *pch);
-static void ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb);
-static struct sk_buff *ppp_mp_reconstruct(struct ppp *ppp);
-static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb);
-#endif /* CONFIG_PPP_MULTILINK */
-static int ppp_set_compress(struct ppp *ppp, unsigned long arg);
-static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound);
-static void ppp_ccp_closed(struct ppp *ppp);
-static struct compressor *find_compressor(int type);
-static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
-static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
-static void init_ppp_file(struct ppp_file *pf, int kind);
-static void ppp_shutdown_interface(struct ppp *ppp);
-static void ppp_destroy_interface(struct ppp *ppp);
-static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
-static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
-static int ppp_connect_channel(struct channel *pch, int unit);
-static int ppp_disconnect_channel(struct channel *pch);
-static void ppp_destroy_channel(struct channel *pch);
-static int unit_get(struct idr *p, void *ptr);
-static int unit_set(struct idr *p, void *ptr, int n);
-static void unit_put(struct idr *p, int n);
-static void *unit_find(struct idr *p, int n);
-
-static struct class *ppp_class;
-
-/* per net-namespace data */
-static inline struct ppp_net *ppp_pernet(struct net *net)
-{
-       BUG_ON(!net);
-
-       return net_generic(net, ppp_net_id);
-}
-
-/* Translates a PPP protocol number to a NP index (NP == network protocol) */
-static inline int proto_to_npindex(int proto)
-{
-       switch (proto) {
-       case PPP_IP:
-               return NP_IP;
-       case PPP_IPV6:
-               return NP_IPV6;
-       case PPP_IPX:
-               return NP_IPX;
-       case PPP_AT:
-               return NP_AT;
-       case PPP_MPLS_UC:
-               return NP_MPLS_UC;
-       case PPP_MPLS_MC:
-               return NP_MPLS_MC;
-       }
-       return -EINVAL;
-}
-
-/* Translates an NP index into a PPP protocol number */
-static const int npindex_to_proto[NUM_NP] = {
-       PPP_IP,
-       PPP_IPV6,
-       PPP_IPX,
-       PPP_AT,
-       PPP_MPLS_UC,
-       PPP_MPLS_MC,
-};
-
-/* Translates an ethertype into an NP index */
-static inline int ethertype_to_npindex(int ethertype)
-{
-       switch (ethertype) {
-       case ETH_P_IP:
-               return NP_IP;
-       case ETH_P_IPV6:
-               return NP_IPV6;
-       case ETH_P_IPX:
-               return NP_IPX;
-       case ETH_P_PPPTALK:
-       case ETH_P_ATALK:
-               return NP_AT;
-       case ETH_P_MPLS_UC:
-               return NP_MPLS_UC;
-       case ETH_P_MPLS_MC:
-               return NP_MPLS_MC;
-       }
-       return -1;
-}
-
-/* Translates an NP index into an ethertype */
-static const int npindex_to_ethertype[NUM_NP] = {
-       ETH_P_IP,
-       ETH_P_IPV6,
-       ETH_P_IPX,
-       ETH_P_PPPTALK,
-       ETH_P_MPLS_UC,
-       ETH_P_MPLS_MC,
-};
-
-/*
- * Locking shorthand.
- */
-#define ppp_xmit_lock(ppp)     spin_lock_bh(&(ppp)->wlock)
-#define ppp_xmit_unlock(ppp)   spin_unlock_bh(&(ppp)->wlock)
-#define ppp_recv_lock(ppp)     spin_lock_bh(&(ppp)->rlock)
-#define ppp_recv_unlock(ppp)   spin_unlock_bh(&(ppp)->rlock)
-#define ppp_lock(ppp)          do { ppp_xmit_lock(ppp); \
-                                    ppp_recv_lock(ppp); } while (0)
-#define ppp_unlock(ppp)                do { ppp_recv_unlock(ppp); \
-                                    ppp_xmit_unlock(ppp); } while (0)
-
-/*
- * /dev/ppp device routines.
- * The /dev/ppp device is used by pppd to control the ppp unit.
- * It supports the read, write, ioctl and poll functions.
- * Open instances of /dev/ppp can be in one of three states:
- * unattached, attached to a ppp unit, or attached to a ppp channel.
- */
-static int ppp_open(struct inode *inode, struct file *file)
-{
-       /*
-        * This could (should?) be enforced by the permissions on /dev/ppp.
-        */
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-       return 0;
-}
-
-static int ppp_release(struct inode *unused, struct file *file)
-{
-       struct ppp_file *pf = file->private_data;
-       struct ppp *ppp;
-
-       if (pf) {
-               file->private_data = NULL;
-               if (pf->kind == INTERFACE) {
-                       ppp = PF_TO_PPP(pf);
-                       if (file == ppp->owner)
-                               ppp_shutdown_interface(ppp);
-               }
-               if (atomic_dec_and_test(&pf->refcnt)) {
-                       switch (pf->kind) {
-                       case INTERFACE:
-                               ppp_destroy_interface(PF_TO_PPP(pf));
-                               break;
-                       case CHANNEL:
-                               ppp_destroy_channel(PF_TO_CHANNEL(pf));
-                               break;
-                       }
-               }
-       }
-       return 0;
-}
-
-static ssize_t ppp_read(struct file *file, char __user *buf,
-                       size_t count, loff_t *ppos)
-{
-       struct ppp_file *pf = file->private_data;
-       DECLARE_WAITQUEUE(wait, current);
-       ssize_t ret;
-       struct sk_buff *skb = NULL;
-       struct iovec iov;
-
-       ret = count;
-
-       if (!pf)
-               return -ENXIO;
-       add_wait_queue(&pf->rwait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               skb = skb_dequeue(&pf->rq);
-               if (skb)
-                       break;
-               ret = 0;
-               if (pf->dead)
-                       break;
-               if (pf->kind == INTERFACE) {
-                       /*
-                        * Return 0 (EOF) on an interface that has no
-                        * channels connected, unless it is looping
-                        * network traffic (demand mode).
-                        */
-                       struct ppp *ppp = PF_TO_PPP(pf);
-                       if (ppp->n_channels == 0 &&
-                           (ppp->flags & SC_LOOP_TRAFFIC) == 0)
-                               break;
-               }
-               ret = -EAGAIN;
-               if (file->f_flags & O_NONBLOCK)
-                       break;
-               ret = -ERESTARTSYS;
-               if (signal_pending(current))
-                       break;
-               schedule();
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&pf->rwait, &wait);
-
-       if (!skb)
-               goto out;
-
-       ret = -EOVERFLOW;
-       if (skb->len > count)
-               goto outf;
-       ret = -EFAULT;
-       iov.iov_base = buf;
-       iov.iov_len = count;
-       if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len))
-               goto outf;
-       ret = skb->len;
-
- outf:
-       kfree_skb(skb);
- out:
-       return ret;
-}
-
-static ssize_t ppp_write(struct file *file, const char __user *buf,
-                        size_t count, loff_t *ppos)
-{
-       struct ppp_file *pf = file->private_data;
-       struct sk_buff *skb;
-       ssize_t ret;
-
-       if (!pf)
-               return -ENXIO;
-       ret = -ENOMEM;
-       skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
-       if (!skb)
-               goto out;
-       skb_reserve(skb, pf->hdrlen);
-       ret = -EFAULT;
-       if (copy_from_user(skb_put(skb, count), buf, count)) {
-               kfree_skb(skb);
-               goto out;
-       }
-
-       skb_queue_tail(&pf->xq, skb);
-
-       switch (pf->kind) {
-       case INTERFACE:
-               ppp_xmit_process(PF_TO_PPP(pf));
-               break;
-       case CHANNEL:
-               ppp_channel_push(PF_TO_CHANNEL(pf));
-               break;
-       }
-
-       ret = count;
-
- out:
-       return ret;
-}
-
-/* No kernel lock - fine */
-static unsigned int ppp_poll(struct file *file, poll_table *wait)
-{
-       struct ppp_file *pf = file->private_data;
-       unsigned int mask;
-
-       if (!pf)
-               return 0;
-       poll_wait(file, &pf->rwait, wait);
-       mask = POLLOUT | POLLWRNORM;
-       if (skb_peek(&pf->rq))
-               mask |= POLLIN | POLLRDNORM;
-       if (pf->dead)
-               mask |= POLLHUP;
-       else if (pf->kind == INTERFACE) {
-               /* see comment in ppp_read */
-               struct ppp *ppp = PF_TO_PPP(pf);
-               if (ppp->n_channels == 0 &&
-                   (ppp->flags & SC_LOOP_TRAFFIC) == 0)
-                       mask |= POLLIN | POLLRDNORM;
-       }
-
-       return mask;
-}
-
-#ifdef CONFIG_PPP_FILTER
-static int get_filter(void __user *arg, struct sock_filter **p)
-{
-       struct sock_fprog uprog;
-       struct sock_filter *code = NULL;
-       int len, err;
-
-       if (copy_from_user(&uprog, arg, sizeof(uprog)))
-               return -EFAULT;
-
-       if (!uprog.len) {
-               *p = NULL;
-               return 0;
-       }
-
-       len = uprog.len * sizeof(struct sock_filter);
-       code = memdup_user(uprog.filter, len);
-       if (IS_ERR(code))
-               return PTR_ERR(code);
-
-       err = sk_chk_filter(code, uprog.len);
-       if (err) {
-               kfree(code);
-               return err;
-       }
-
-       *p = code;
-       return uprog.len;
-}
-#endif /* CONFIG_PPP_FILTER */
-
-static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct ppp_file *pf = file->private_data;
-       struct ppp *ppp;
-       int err = -EFAULT, val, val2, i;
-       struct ppp_idle idle;
-       struct npioctl npi;
-       int unit, cflags;
-       struct slcompress *vj;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-
-       if (!pf)
-               return ppp_unattached_ioctl(current->nsproxy->net_ns,
-                                       pf, file, cmd, arg);
-
-       if (cmd == PPPIOCDETACH) {
-               /*
-                * We have to be careful here... if the file descriptor
-                * has been dup'd, we could have another process in the
-                * middle of a poll using the same file *, so we had
-                * better not free the interface data structures -
-                * instead we fail the ioctl.  Even in this case, we
-                * shut down the interface if we are the owner of it.
-                * Actually, we should get rid of PPPIOCDETACH, userland
-                * (i.e. pppd) could achieve the same effect by closing
-                * this fd and reopening /dev/ppp.
-                */
-               err = -EINVAL;
-               mutex_lock(&ppp_mutex);
-               if (pf->kind == INTERFACE) {
-                       ppp = PF_TO_PPP(pf);
-                       if (file == ppp->owner)
-                               ppp_shutdown_interface(ppp);
-               }
-               if (atomic_long_read(&file->f_count) <= 2) {
-                       ppp_release(NULL, file);
-                       err = 0;
-               } else
-                       pr_warn("PPPIOCDETACH file->f_count=%ld\n",
-                               atomic_long_read(&file->f_count));
-               mutex_unlock(&ppp_mutex);
-               return err;
-       }
-
-       if (pf->kind == CHANNEL) {
-               struct channel *pch;
-               struct ppp_channel *chan;
-
-               mutex_lock(&ppp_mutex);
-               pch = PF_TO_CHANNEL(pf);
-
-               switch (cmd) {
-               case PPPIOCCONNECT:
-                       if (get_user(unit, p))
-                               break;
-                       err = ppp_connect_channel(pch, unit);
-                       break;
-
-               case PPPIOCDISCONN:
-                       err = ppp_disconnect_channel(pch);
-                       break;
-
-               default:
-                       down_read(&pch->chan_sem);
-                       chan = pch->chan;
-                       err = -ENOTTY;
-                       if (chan && chan->ops->ioctl)
-                               err = chan->ops->ioctl(chan, cmd, arg);
-                       up_read(&pch->chan_sem);
-               }
-               mutex_unlock(&ppp_mutex);
-               return err;
-       }
-
-       if (pf->kind != INTERFACE) {
-               /* can't happen */
-               pr_err("PPP: not interface or channel??\n");
-               return -EINVAL;
-       }
-
-       mutex_lock(&ppp_mutex);
-       ppp = PF_TO_PPP(pf);
-       switch (cmd) {
-       case PPPIOCSMRU:
-               if (get_user(val, p))
-                       break;
-               ppp->mru = val;
-               err = 0;
-               break;
-
-       case PPPIOCSFLAGS:
-               if (get_user(val, p))
-                       break;
-               ppp_lock(ppp);
-               cflags = ppp->flags & ~val;
-               ppp->flags = val & SC_FLAG_BITS;
-               ppp_unlock(ppp);
-               if (cflags & SC_CCP_OPEN)
-                       ppp_ccp_closed(ppp);
-               err = 0;
-               break;
-
-       case PPPIOCGFLAGS:
-               val = ppp->flags | ppp->xstate | ppp->rstate;
-               if (put_user(val, p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCSCOMPRESS:
-               err = ppp_set_compress(ppp, arg);
-               break;
-
-       case PPPIOCGUNIT:
-               if (put_user(ppp->file.index, p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCSDEBUG:
-               if (get_user(val, p))
-                       break;
-               ppp->debug = val;
-               err = 0;
-               break;
-
-       case PPPIOCGDEBUG:
-               if (put_user(ppp->debug, p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGIDLE:
-               idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
-               idle.recv_idle = (jiffies - ppp->last_recv) / HZ;
-               if (copy_to_user(argp, &idle, sizeof(idle)))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCSMAXCID:
-               if (get_user(val, p))
-                       break;
-               val2 = 15;
-               if ((val >> 16) != 0) {
-                       val2 = val >> 16;
-                       val &= 0xffff;
-               }
-               vj = slhc_init(val2+1, val+1);
-               if (!vj) {
-                       netdev_err(ppp->dev,
-                                  "PPP: no memory (VJ compressor)\n");
-                       err = -ENOMEM;
-                       break;
-               }
-               ppp_lock(ppp);
-               if (ppp->vj)
-                       slhc_free(ppp->vj);
-               ppp->vj = vj;
-               ppp_unlock(ppp);
-               err = 0;
-               break;
-
-       case PPPIOCGNPMODE:
-       case PPPIOCSNPMODE:
-               if (copy_from_user(&npi, argp, sizeof(npi)))
-                       break;
-               err = proto_to_npindex(npi.protocol);
-               if (err < 0)
-                       break;
-               i = err;
-               if (cmd == PPPIOCGNPMODE) {
-                       err = -EFAULT;
-                       npi.mode = ppp->npmode[i];
-                       if (copy_to_user(argp, &npi, sizeof(npi)))
-                               break;
-               } else {
-                       ppp->npmode[i] = npi.mode;
-                       /* we may be able to transmit more packets now (??) */
-                       netif_wake_queue(ppp->dev);
-               }
-               err = 0;
-               break;
-
-#ifdef CONFIG_PPP_FILTER
-       case PPPIOCSPASS:
-       {
-               struct sock_filter *code;
-               err = get_filter(argp, &code);
-               if (err >= 0) {
-                       ppp_lock(ppp);
-                       kfree(ppp->pass_filter);
-                       ppp->pass_filter = code;
-                       ppp->pass_len = err;
-                       ppp_unlock(ppp);
-                       err = 0;
-               }
-               break;
-       }
-       case PPPIOCSACTIVE:
-       {
-               struct sock_filter *code;
-               err = get_filter(argp, &code);
-               if (err >= 0) {
-                       ppp_lock(ppp);
-                       kfree(ppp->active_filter);
-                       ppp->active_filter = code;
-                       ppp->active_len = err;
-                       ppp_unlock(ppp);
-                       err = 0;
-               }
-               break;
-       }
-#endif /* CONFIG_PPP_FILTER */
-
-#ifdef CONFIG_PPP_MULTILINK
-       case PPPIOCSMRRU:
-               if (get_user(val, p))
-                       break;
-               ppp_recv_lock(ppp);
-               ppp->mrru = val;
-               ppp_recv_unlock(ppp);
-               err = 0;
-               break;
-#endif /* CONFIG_PPP_MULTILINK */
-
-       default:
-               err = -ENOTTY;
-       }
-       mutex_unlock(&ppp_mutex);
-       return err;
-}
-
-static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
-                       struct file *file, unsigned int cmd, unsigned long arg)
-{
-       int unit, err = -EFAULT;
-       struct ppp *ppp;
-       struct channel *chan;
-       struct ppp_net *pn;
-       int __user *p = (int __user *)arg;
-
-       mutex_lock(&ppp_mutex);
-       switch (cmd) {
-       case PPPIOCNEWUNIT:
-               /* Create a new ppp unit */
-               if (get_user(unit, p))
-                       break;
-               ppp = ppp_create_interface(net, unit, &err);
-               if (!ppp)
-                       break;
-               file->private_data = &ppp->file;
-               ppp->owner = file;
-               err = -EFAULT;
-               if (put_user(ppp->file.index, p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCATTACH:
-               /* Attach to an existing ppp unit */
-               if (get_user(unit, p))
-                       break;
-               err = -ENXIO;
-               pn = ppp_pernet(net);
-               mutex_lock(&pn->all_ppp_mutex);
-               ppp = ppp_find_unit(pn, unit);
-               if (ppp) {
-                       atomic_inc(&ppp->file.refcnt);
-                       file->private_data = &ppp->file;
-                       err = 0;
-               }
-               mutex_unlock(&pn->all_ppp_mutex);
-               break;
-
-       case PPPIOCATTCHAN:
-               if (get_user(unit, p))
-                       break;
-               err = -ENXIO;
-               pn = ppp_pernet(net);
-               spin_lock_bh(&pn->all_channels_lock);
-               chan = ppp_find_channel(pn, unit);
-               if (chan) {
-                       atomic_inc(&chan->file.refcnt);
-                       file->private_data = &chan->file;
-                       err = 0;
-               }
-               spin_unlock_bh(&pn->all_channels_lock);
-               break;
-
-       default:
-               err = -ENOTTY;
-       }
-       mutex_unlock(&ppp_mutex);
-       return err;
-}
-
-static const struct file_operations ppp_device_fops = {
-       .owner          = THIS_MODULE,
-       .read           = ppp_read,
-       .write          = ppp_write,
-       .poll           = ppp_poll,
-       .unlocked_ioctl = ppp_ioctl,
-       .open           = ppp_open,
-       .release        = ppp_release,
-       .llseek         = noop_llseek,
-};
-
-static __net_init int ppp_init_net(struct net *net)
-{
-       struct ppp_net *pn = net_generic(net, ppp_net_id);
-
-       idr_init(&pn->units_idr);
-       mutex_init(&pn->all_ppp_mutex);
-
-       INIT_LIST_HEAD(&pn->all_channels);
-       INIT_LIST_HEAD(&pn->new_channels);
-
-       spin_lock_init(&pn->all_channels_lock);
-
-       return 0;
-}
-
-static __net_exit void ppp_exit_net(struct net *net)
-{
-       struct ppp_net *pn = net_generic(net, ppp_net_id);
-
-       idr_destroy(&pn->units_idr);
-}
-
-static struct pernet_operations ppp_net_ops = {
-       .init = ppp_init_net,
-       .exit = ppp_exit_net,
-       .id   = &ppp_net_id,
-       .size = sizeof(struct ppp_net),
-};
-
-#define PPP_MAJOR      108
-
-/* Called at boot time if ppp is compiled into the kernel,
-   or at module load time (from init_module) if compiled as a module. */
-static int __init ppp_init(void)
-{
-       int err;
-
-       pr_info("PPP generic driver version " PPP_VERSION "\n");
-
-       err = register_pernet_device(&ppp_net_ops);
-       if (err) {
-               pr_err("failed to register PPP pernet device (%d)\n", err);
-               goto out;
-       }
-
-       err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
-       if (err) {
-               pr_err("failed to register PPP device (%d)\n", err);
-               goto out_net;
-       }
-
-       ppp_class = class_create(THIS_MODULE, "ppp");
-       if (IS_ERR(ppp_class)) {
-               err = PTR_ERR(ppp_class);
-               goto out_chrdev;
-       }
-
-       /* not a big deal if we fail here :-) */
-       device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
-
-       return 0;
-
-out_chrdev:
-       unregister_chrdev(PPP_MAJOR, "ppp");
-out_net:
-       unregister_pernet_device(&ppp_net_ops);
-out:
-       return err;
-}
-
-/*
- * Network interface unit routines.
- */
-static netdev_tx_t
-ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct ppp *ppp = netdev_priv(dev);
-       int npi, proto;
-       unsigned char *pp;
-
-       npi = ethertype_to_npindex(ntohs(skb->protocol));
-       if (npi < 0)
-               goto outf;
-
-       /* Drop, accept or reject the packet */
-       switch (ppp->npmode[npi]) {
-       case NPMODE_PASS:
-               break;
-       case NPMODE_QUEUE:
-               /* it would be nice to have a way to tell the network
-                  system to queue this one up for later. */
-               goto outf;
-       case NPMODE_DROP:
-       case NPMODE_ERROR:
-               goto outf;
-       }
-
-       /* Put the 2-byte PPP protocol number on the front,
-          making sure there is room for the address and control fields. */
-       if (skb_cow_head(skb, PPP_HDRLEN))
-               goto outf;
-
-       pp = skb_push(skb, 2);
-       proto = npindex_to_proto[npi];
-       put_unaligned_be16(proto, pp);
-
-       netif_stop_queue(dev);
-       skb_queue_tail(&ppp->file.xq, skb);
-       ppp_xmit_process(ppp);
-       return NETDEV_TX_OK;
-
- outf:
-       kfree_skb(skb);
-       ++dev->stats.tx_dropped;
-       return NETDEV_TX_OK;
-}
-
-static int
-ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       struct ppp *ppp = netdev_priv(dev);
-       int err = -EFAULT;
-       void __user *addr = (void __user *) ifr->ifr_ifru.ifru_data;
-       struct ppp_stats stats;
-       struct ppp_comp_stats cstats;
-       char *vers;
-
-       switch (cmd) {
-       case SIOCGPPPSTATS:
-               ppp_get_stats(ppp, &stats);
-               if (copy_to_user(addr, &stats, sizeof(stats)))
-                       break;
-               err = 0;
-               break;
-
-       case SIOCGPPPCSTATS:
-               memset(&cstats, 0, sizeof(cstats));
-               if (ppp->xc_state)
-                       ppp->xcomp->comp_stat(ppp->xc_state, &cstats.c);
-               if (ppp->rc_state)
-                       ppp->rcomp->decomp_stat(ppp->rc_state, &cstats.d);
-               if (copy_to_user(addr, &cstats, sizeof(cstats)))
-                       break;
-               err = 0;
-               break;
-
-       case SIOCGPPPVER:
-               vers = PPP_VERSION;
-               if (copy_to_user(addr, vers, strlen(vers) + 1))
-                       break;
-               err = 0;
-               break;
-
-       default:
-               err = -EINVAL;
-       }
-
-       return err;
-}
-
-static const struct net_device_ops ppp_netdev_ops = {
-       .ndo_start_xmit = ppp_start_xmit,
-       .ndo_do_ioctl   = ppp_net_ioctl,
-};
-
-static void ppp_setup(struct net_device *dev)
-{
-       dev->netdev_ops = &ppp_netdev_ops;
-       dev->hard_header_len = PPP_HDRLEN;
-       dev->mtu = PPP_MTU;
-       dev->addr_len = 0;
-       dev->tx_queue_len = 3;
-       dev->type = ARPHRD_PPP;
-       dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
-       dev->features |= NETIF_F_NETNS_LOCAL;
-       dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
-}
-
-/*
- * Transmit-side routines.
- */
-
-/*
- * Called to do any work queued up on the transmit side
- * that can now be done.
- */
-static void
-ppp_xmit_process(struct ppp *ppp)
-{
-       struct sk_buff *skb;
-
-       ppp_xmit_lock(ppp);
-       if (!ppp->closing) {
-               ppp_push(ppp);
-               while (!ppp->xmit_pending &&
-                      (skb = skb_dequeue(&ppp->file.xq)))
-                       ppp_send_frame(ppp, skb);
-               /* If there's no work left to do, tell the core net
-                  code that we can accept some more. */
-               if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
-                       netif_wake_queue(ppp->dev);
-       }
-       ppp_xmit_unlock(ppp);
-}
-
-static inline struct sk_buff *
-pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
-{
-       struct sk_buff *new_skb;
-       int len;
-       int new_skb_size = ppp->dev->mtu +
-               ppp->xcomp->comp_extra + ppp->dev->hard_header_len;
-       int compressor_skb_size = ppp->dev->mtu +
-               ppp->xcomp->comp_extra + PPP_HDRLEN;
-       new_skb = alloc_skb(new_skb_size, GFP_ATOMIC);
-       if (!new_skb) {
-               if (net_ratelimit())
-                       netdev_err(ppp->dev, "PPP: no memory (comp pkt)\n");
-               return NULL;
-       }
-       if (ppp->dev->hard_header_len > PPP_HDRLEN)
-               skb_reserve(new_skb,
-                           ppp->dev->hard_header_len - PPP_HDRLEN);
-
-       /* compressor still expects A/C bytes in hdr */
-       len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2,
-                                  new_skb->data, skb->len + 2,
-                                  compressor_skb_size);
-       if (len > 0 && (ppp->flags & SC_CCP_UP)) {
-               kfree_skb(skb);
-               skb = new_skb;
-               skb_put(skb, len);
-               skb_pull(skb, 2);       /* pull off A/C bytes */
-       } else if (len == 0) {
-               /* didn't compress, or CCP not up yet */
-               kfree_skb(new_skb);
-               new_skb = skb;
-       } else {
-               /*
-                * (len < 0)
-                * MPPE requires that we do not send unencrypted
-                * frames.  The compressor will return -1 if we
-                * should drop the frame.  We cannot simply test
-                * the compress_proto because MPPE and MPPC share
-                * the same number.
-                */
-               if (net_ratelimit())
-                       netdev_err(ppp->dev, "ppp: compressor dropped pkt\n");
-               kfree_skb(skb);
-               kfree_skb(new_skb);
-               new_skb = NULL;
-       }
-       return new_skb;
-}
-
-/*
- * Compress and send a frame.
- * The caller should have locked the xmit path,
- * and xmit_pending should be 0.
- */
-static void
-ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
-{
-       int proto = PPP_PROTO(skb);
-       struct sk_buff *new_skb;
-       int len;
-       unsigned char *cp;
-
-       if (proto < 0x8000) {
-#ifdef CONFIG_PPP_FILTER
-               /* check if we should pass this packet */
-               /* the filter instructions are constructed assuming
-                  a four-byte PPP header on each packet */
-               *skb_push(skb, 2) = 1;
-               if (ppp->pass_filter &&
-                   sk_run_filter(skb, ppp->pass_filter) == 0) {
-                       if (ppp->debug & 1)
-                               netdev_printk(KERN_DEBUG, ppp->dev,
-                                             "PPP: outbound frame "
-                                             "not passed\n");
-                       kfree_skb(skb);
-                       return;
-               }
-               /* if this packet passes the active filter, record the time */
-               if (!(ppp->active_filter &&
-                     sk_run_filter(skb, ppp->active_filter) == 0))
-                       ppp->last_xmit = jiffies;
-               skb_pull(skb, 2);
-#else
-               /* for data packets, record the time */
-               ppp->last_xmit = jiffies;
-#endif /* CONFIG_PPP_FILTER */
-       }
-
-       ++ppp->dev->stats.tx_packets;
-       ppp->dev->stats.tx_bytes += skb->len - 2;
-
-       switch (proto) {
-       case PPP_IP:
-               if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0)
-                       break;
-               /* try to do VJ TCP header compression */
-               new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
-                                   GFP_ATOMIC);
-               if (!new_skb) {
-                       netdev_err(ppp->dev, "PPP: no memory (VJ comp pkt)\n");
-                       goto drop;
-               }
-               skb_reserve(new_skb, ppp->dev->hard_header_len - 2);
-               cp = skb->data + 2;
-               len = slhc_compress(ppp->vj, cp, skb->len - 2,
-                                   new_skb->data + 2, &cp,
-                                   !(ppp->flags & SC_NO_TCP_CCID));
-               if (cp == skb->data + 2) {
-                       /* didn't compress */
-                       kfree_skb(new_skb);
-               } else {
-                       if (cp[0] & SL_TYPE_COMPRESSED_TCP) {
-                               proto = PPP_VJC_COMP;
-                               cp[0] &= ~SL_TYPE_COMPRESSED_TCP;
-                       } else {
-                               proto = PPP_VJC_UNCOMP;
-                               cp[0] = skb->data[2];
-                       }
-                       kfree_skb(skb);
-                       skb = new_skb;
-                       cp = skb_put(skb, len + 2);
-                       cp[0] = 0;
-                       cp[1] = proto;
-               }
-               break;
-
-       case PPP_CCP:
-               /* peek at outbound CCP frames */
-               ppp_ccp_peek(ppp, skb, 0);
-               break;
-       }
-
-       /* try to do packet compression */
-       if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state &&
-           proto != PPP_LCP && proto != PPP_CCP) {
-               if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
-                       if (net_ratelimit())
-                               netdev_err(ppp->dev,
-                                          "ppp: compression required but "
-                                          "down - pkt dropped.\n");
-                       goto drop;
-               }
-               skb = pad_compress_skb(ppp, skb);
-               if (!skb)
-                       goto drop;
-       }
-
-       /*
-        * If we are waiting for traffic (demand dialling),
-        * queue it up for pppd to receive.
-        */
-       if (ppp->flags & SC_LOOP_TRAFFIC) {
-               if (ppp->file.rq.qlen > PPP_MAX_RQLEN)
-                       goto drop;
-               skb_queue_tail(&ppp->file.rq, skb);
-               wake_up_interruptible(&ppp->file.rwait);
-               return;
-       }
-
-       ppp->xmit_pending = skb;
-       ppp_push(ppp);
-       return;
-
- drop:
-       kfree_skb(skb);
-       ++ppp->dev->stats.tx_errors;
-}
-
-/*
- * Try to send the frame in xmit_pending.
- * The caller should have the xmit path locked.
- */
-static void
-ppp_push(struct ppp *ppp)
-{
-       struct list_head *list;
-       struct channel *pch;
-       struct sk_buff *skb = ppp->xmit_pending;
-
-       if (!skb)
-               return;
-
-       list = &ppp->channels;
-       if (list_empty(list)) {
-               /* nowhere to send the packet, just drop it */
-               ppp->xmit_pending = NULL;
-               kfree_skb(skb);
-               return;
-       }
-
-       if ((ppp->flags & SC_MULTILINK) == 0) {
-               /* not doing multilink: send it down the first channel */
-               list = list->next;
-               pch = list_entry(list, struct channel, clist);
-
-               spin_lock_bh(&pch->downl);
-               if (pch->chan) {
-                       if (pch->chan->ops->start_xmit(pch->chan, skb))
-                               ppp->xmit_pending = NULL;
-               } else {
-                       /* channel got unregistered */
-                       kfree_skb(skb);
-                       ppp->xmit_pending = NULL;
-               }
-               spin_unlock_bh(&pch->downl);
-               return;
-       }
-
-#ifdef CONFIG_PPP_MULTILINK
-       /* Multilink: fragment the packet over as many links
-          as can take the packet at the moment. */
-       if (!ppp_mp_explode(ppp, skb))
-               return;
-#endif /* CONFIG_PPP_MULTILINK */
-
-       ppp->xmit_pending = NULL;
-       kfree_skb(skb);
-}
-
-#ifdef CONFIG_PPP_MULTILINK
-static bool mp_protocol_compress __read_mostly = true;
-module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(mp_protocol_compress,
-                "compress protocol id in multilink fragments");
-
-/*
- * Divide a packet to be transmitted into fragments and
- * send them out the individual links.
- */
-static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
-{
-       int len, totlen;
-       int i, bits, hdrlen, mtu;
-       int flen;
-       int navail, nfree, nzero;
-       int nbigger;
-       int totspeed;
-       int totfree;
-       unsigned char *p, *q;
-       struct list_head *list;
-       struct channel *pch;
-       struct sk_buff *frag;
-       struct ppp_channel *chan;
-
-       totspeed = 0; /*total bitrate of the bundle*/
-       nfree = 0; /* # channels which have no packet already queued */
-       navail = 0; /* total # of usable channels (not deregistered) */
-       nzero = 0; /* number of channels with zero speed associated*/
-       totfree = 0; /*total # of channels available and
-                                 *having no queued packets before
-                                 *starting the fragmentation*/
-
-       hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
-       i = 0;
-       list_for_each_entry(pch, &ppp->channels, clist) {
-               if (pch->chan) {
-                       pch->avail = 1;
-                       navail++;
-                       pch->speed = pch->chan->speed;
-               } else {
-                       pch->avail = 0;
-               }
-               if (pch->avail) {
-                       if (skb_queue_empty(&pch->file.xq) ||
-                               !pch->had_frag) {
-                                       if (pch->speed == 0)
-                                               nzero++;
-                                       else
-                                               totspeed += pch->speed;
-
-                                       pch->avail = 2;
-                                       ++nfree;
-                                       ++totfree;
-                               }
-                       if (!pch->had_frag && i < ppp->nxchan)
-                               ppp->nxchan = i;
-               }
-               ++i;
-       }
-       /*
-        * Don't start sending this packet unless at least half of
-        * the channels are free.  This gives much better TCP
-        * performance if we have a lot of channels.
-        */
-       if (nfree == 0 || nfree < navail / 2)
-               return 0; /* can't take now, leave it in xmit_pending */
-
-       /* Do protocol field compression */
-       p = skb->data;
-       len = skb->len;
-       if (*p == 0 && mp_protocol_compress) {
-               ++p;
-               --len;
-       }
-
-       totlen = len;
-       nbigger = len % nfree;
-
-       /* skip to the channel after the one we last used
-          and start at that one */
-       list = &ppp->channels;
-       for (i = 0; i < ppp->nxchan; ++i) {
-               list = list->next;
-               if (list == &ppp->channels) {
-                       i = 0;
-                       break;
-               }
-       }
-
-       /* create a fragment for each channel */
-       bits = B;
-       while (len > 0) {
-               list = list->next;
-               if (list == &ppp->channels) {
-                       i = 0;
-                       continue;
-               }
-               pch = list_entry(list, struct channel, clist);
-               ++i;
-               if (!pch->avail)
-                       continue;
-
-               /*
-                * Skip this channel if it has a fragment pending already and
-                * we haven't given a fragment to all of the free channels.
-                */
-               if (pch->avail == 1) {
-                       if (nfree > 0)
-                               continue;
-               } else {
-                       pch->avail = 1;
-               }
-
-               /* check the channel's mtu and whether it is still attached. */
-               spin_lock_bh(&pch->downl);
-               if (pch->chan == NULL) {
-                       /* can't use this channel, it's being deregistered */
-                       if (pch->speed == 0)
-                               nzero--;
-                       else
-                               totspeed -= pch->speed;
-
-                       spin_unlock_bh(&pch->downl);
-                       pch->avail = 0;
-                       totlen = len;
-                       totfree--;
-                       nfree--;
-                       if (--navail == 0)
-                               break;
-                       continue;
-               }
-
-               /*
-               *if the channel speed is not set divide
-               *the packet evenly among the free channels;
-               *otherwise divide it according to the speed
-               *of the channel we are going to transmit on
-               */
-               flen = len;
-               if (nfree > 0) {
-                       if (pch->speed == 0) {
-                               flen = len/nfree;
-                               if (nbigger > 0) {
-                                       flen++;
-                                       nbigger--;
-                               }
-                       } else {
-                               flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
-                                       ((totspeed*totfree)/pch->speed)) - hdrlen;
-                               if (nbigger > 0) {
-                                       flen += ((totfree - nzero)*pch->speed)/totspeed;
-                                       nbigger -= ((totfree - nzero)*pch->speed)/
-                                                       totspeed;
-                               }
-                       }
-                       nfree--;
-               }
-
-               /*
-                *check if we are on the last channel or
-                *we exceded the length of the data to
-                *fragment
-                */
-               if ((nfree <= 0) || (flen > len))
-                       flen = len;
-               /*
-                *it is not worth to tx on slow channels:
-                *in that case from the resulting flen according to the
-                *above formula will be equal or less than zero.
-                *Skip the channel in this case
-                */
-               if (flen <= 0) {
-                       pch->avail = 2;
-                       spin_unlock_bh(&pch->downl);
-                       continue;
-               }
-
-               mtu = pch->chan->mtu - hdrlen;
-               if (mtu < 4)
-                       mtu = 4;
-               if (flen > mtu)
-                       flen = mtu;
-               if (flen == len)
-                       bits |= E;
-               frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
-               if (!frag)
-                       goto noskb;
-               q = skb_put(frag, flen + hdrlen);
-
-               /* make the MP header */
-               put_unaligned_be16(PPP_MP, q);
-               if (ppp->flags & SC_MP_XSHORTSEQ) {
-                       q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
-                       q[3] = ppp->nxseq;
-               } else {
-                       q[2] = bits;
-                       q[3] = ppp->nxseq >> 16;
-                       q[4] = ppp->nxseq >> 8;
-                       q[5] = ppp->nxseq;
-               }
-
-               memcpy(q + hdrlen, p, flen);
-
-               /* try to send it down the channel */
-               chan = pch->chan;
-               if (!skb_queue_empty(&pch->file.xq) ||
-                       !chan->ops->start_xmit(chan, frag))
-                       skb_queue_tail(&pch->file.xq, frag);
-               pch->had_frag = 1;
-               p += flen;
-               len -= flen;
-               ++ppp->nxseq;
-               bits = 0;
-               spin_unlock_bh(&pch->downl);
-       }
-       ppp->nxchan = i;
-
-       return 1;
-
- noskb:
-       spin_unlock_bh(&pch->downl);
-       if (ppp->debug & 1)
-               netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
-       ++ppp->dev->stats.tx_errors;
-       ++ppp->nxseq;
-       return 1;       /* abandon the frame */
-}
-#endif /* CONFIG_PPP_MULTILINK */
-
-/*
- * Try to send data out on a channel.
- */
-static void
-ppp_channel_push(struct channel *pch)
-{
-       struct sk_buff *skb;
-       struct ppp *ppp;
-
-       spin_lock_bh(&pch->downl);
-       if (pch->chan) {
-               while (!skb_queue_empty(&pch->file.xq)) {
-                       skb = skb_dequeue(&pch->file.xq);
-                       if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
-                               /* put the packet back and try again later */
-                               skb_queue_head(&pch->file.xq, skb);
-                               break;
-                       }
-               }
-       } else {
-               /* channel got deregistered */
-               skb_queue_purge(&pch->file.xq);
-       }
-       spin_unlock_bh(&pch->downl);
-       /* see if there is anything from the attached unit to be sent */
-       if (skb_queue_empty(&pch->file.xq)) {
-               read_lock_bh(&pch->upl);
-               ppp = pch->ppp;
-               if (ppp)
-                       ppp_xmit_process(ppp);
-               read_unlock_bh(&pch->upl);
-       }
-}
-
-/*
- * Receive-side routines.
- */
-
-struct ppp_mp_skb_parm {
-       u32             sequence;
-       u8              BEbits;
-};
-#define PPP_MP_CB(skb) ((struct ppp_mp_skb_parm *)((skb)->cb))
-
-static inline void
-ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
-{
-       ppp_recv_lock(ppp);
-       if (!ppp->closing)
-               ppp_receive_frame(ppp, skb, pch);
-       else
-               kfree_skb(skb);
-       ppp_recv_unlock(ppp);
-}
-
-void
-ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
-{
-       struct channel *pch = chan->ppp;
-       int proto;
-
-       if (!pch) {
-               kfree_skb(skb);
-               return;
-       }
-
-       read_lock_bh(&pch->upl);
-       if (!pskb_may_pull(skb, 2)) {
-               kfree_skb(skb);
-               if (pch->ppp) {
-                       ++pch->ppp->dev->stats.rx_length_errors;
-                       ppp_receive_error(pch->ppp);
-               }
-               goto done;
-       }
-
-       proto = PPP_PROTO(skb);
-       if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {
-               /* put it on the channel queue */
-               skb_queue_tail(&pch->file.rq, skb);
-               /* drop old frames if queue too long */
-               while (pch->file.rq.qlen > PPP_MAX_RQLEN &&
-                      (skb = skb_dequeue(&pch->file.rq)))
-                       kfree_skb(skb);
-               wake_up_interruptible(&pch->file.rwait);
-       } else {
-               ppp_do_recv(pch->ppp, skb, pch);
-       }
-
-done:
-       read_unlock_bh(&pch->upl);
-}
-
-/* Put a 0-length skb in the receive queue as an error indication */
-void
-ppp_input_error(struct ppp_channel *chan, int code)
-{
-       struct channel *pch = chan->ppp;
-       struct sk_buff *skb;
-
-       if (!pch)
-               return;
-
-       read_lock_bh(&pch->upl);
-       if (pch->ppp) {
-               skb = alloc_skb(0, GFP_ATOMIC);
-               if (skb) {
-                       skb->len = 0;           /* probably unnecessary */
-                       skb->cb[0] = code;
-                       ppp_do_recv(pch->ppp, skb, pch);
-               }
-       }
-       read_unlock_bh(&pch->upl);
-}
-
-/*
- * We come in here to process a received frame.
- * The receive side of the ppp unit is locked.
- */
-static void
-ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
-{
-       /* note: a 0-length skb is used as an error indication */
-       if (skb->len > 0) {
-#ifdef CONFIG_PPP_MULTILINK
-               /* XXX do channel-level decompression here */
-               if (PPP_PROTO(skb) == PPP_MP)
-                       ppp_receive_mp_frame(ppp, skb, pch);
-               else
-#endif /* CONFIG_PPP_MULTILINK */
-                       ppp_receive_nonmp_frame(ppp, skb);
-       } else {
-               kfree_skb(skb);
-               ppp_receive_error(ppp);
-       }
-}
-
-static void
-ppp_receive_error(struct ppp *ppp)
-{
-       ++ppp->dev->stats.rx_errors;
-       if (ppp->vj)
-               slhc_toss(ppp->vj);
-}
-
-static void
-ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
-{
-       struct sk_buff *ns;
-       int proto, len, npi;
-
-       /*
-        * Decompress the frame, if compressed.
-        * Note that some decompressors need to see uncompressed frames
-        * that come in as well as compressed frames.
-        */
-       if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN) &&
-           (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0)
-               skb = ppp_decompress_frame(ppp, skb);
-
-       if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR)
-               goto err;
-
-       proto = PPP_PROTO(skb);
-       switch (proto) {
-       case PPP_VJC_COMP:
-               /* decompress VJ compressed packets */
-               if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
-                       goto err;
-
-               if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
-                       /* copy to a new sk_buff with more tailroom */
-                       ns = dev_alloc_skb(skb->len + 128);
-                       if (!ns) {
-                               netdev_err(ppp->dev, "PPP: no memory "
-                                          "(VJ decomp)\n");
-                               goto err;
-                       }
-                       skb_reserve(ns, 2);
-                       skb_copy_bits(skb, 0, skb_put(ns, skb->len), skb->len);
-                       kfree_skb(skb);
-                       skb = ns;
-               }
-               else
-                       skb->ip_summed = CHECKSUM_NONE;
-
-               len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
-               if (len <= 0) {
-                       netdev_printk(KERN_DEBUG, ppp->dev,
-                                     "PPP: VJ decompression error\n");
-                       goto err;
-               }
-               len += 2;
-               if (len > skb->len)
-                       skb_put(skb, len - skb->len);
-               else if (len < skb->len)
-                       skb_trim(skb, len);
-               proto = PPP_IP;
-               break;
-
-       case PPP_VJC_UNCOMP:
-               if (!ppp->vj || (ppp->flags & SC_REJ_COMP_TCP))
-                       goto err;
-
-               /* Until we fix the decompressor need to make sure
-                * data portion is linear.
-                */
-               if (!pskb_may_pull(skb, skb->len))
-                       goto err;
-
-               if (slhc_remember(ppp->vj, skb->data + 2, skb->len - 2) <= 0) {
-                       netdev_err(ppp->dev, "PPP: VJ uncompressed error\n");
-                       goto err;
-               }
-               proto = PPP_IP;
-               break;
-
-       case PPP_CCP:
-               ppp_ccp_peek(ppp, skb, 1);
-               break;
-       }
-
-       ++ppp->dev->stats.rx_packets;
-       ppp->dev->stats.rx_bytes += skb->len - 2;
-
-       npi = proto_to_npindex(proto);
-       if (npi < 0) {
-               /* control or unknown frame - pass it to pppd */
-               skb_queue_tail(&ppp->file.rq, skb);
-               /* limit queue length by dropping old frames */
-               while (ppp->file.rq.qlen > PPP_MAX_RQLEN &&
-                      (skb = skb_dequeue(&ppp->file.rq)))
-                       kfree_skb(skb);
-               /* wake up any process polling or blocking on read */
-               wake_up_interruptible(&ppp->file.rwait);
-
-       } else {
-               /* network protocol frame - give it to the kernel */
-
-#ifdef CONFIG_PPP_FILTER
-               /* check if the packet passes the pass and active filters */
-               /* the filter instructions are constructed assuming
-                  a four-byte PPP header on each packet */
-               if (ppp->pass_filter || ppp->active_filter) {
-                       if (skb_cloned(skb) &&
-                           pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-                               goto err;
-
-                       *skb_push(skb, 2) = 0;
-                       if (ppp->pass_filter &&
-                           sk_run_filter(skb, ppp->pass_filter) == 0) {
-                               if (ppp->debug & 1)
-                                       netdev_printk(KERN_DEBUG, ppp->dev,
-                                                     "PPP: inbound frame "
-                                                     "not passed\n");
-                               kfree_skb(skb);
-                               return;
-                       }
-                       if (!(ppp->active_filter &&
-                             sk_run_filter(skb, ppp->active_filter) == 0))
-                               ppp->last_recv = jiffies;
-                       __skb_pull(skb, 2);
-               } else
-#endif /* CONFIG_PPP_FILTER */
-                       ppp->last_recv = jiffies;
-
-               if ((ppp->dev->flags & IFF_UP) == 0 ||
-                   ppp->npmode[npi] != NPMODE_PASS) {
-                       kfree_skb(skb);
-               } else {
-                       /* chop off protocol */
-                       skb_pull_rcsum(skb, 2);
-                       skb->dev = ppp->dev;
-                       skb->protocol = htons(npindex_to_ethertype[npi]);
-                       skb_reset_mac_header(skb);
-                       netif_rx(skb);
-               }
-       }
-       return;
-
- err:
-       kfree_skb(skb);
-       ppp_receive_error(ppp);
-}
-
-static struct sk_buff *
-ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
-{
-       int proto = PPP_PROTO(skb);
-       struct sk_buff *ns;
-       int len;
-
-       /* Until we fix all the decompressor's need to make sure
-        * data portion is linear.
-        */
-       if (!pskb_may_pull(skb, skb->len))
-               goto err;
-
-       if (proto == PPP_COMP) {
-               int obuff_size;
-
-               switch(ppp->rcomp->compress_proto) {
-               case CI_MPPE:
-                       obuff_size = ppp->mru + PPP_HDRLEN + 1;
-                       break;
-               default:
-                       obuff_size = ppp->mru + PPP_HDRLEN;
-                       break;
-               }
-
-               ns = dev_alloc_skb(obuff_size);
-               if (!ns) {
-                       netdev_err(ppp->dev, "ppp_decompress_frame: "
-                                  "no memory\n");
-                       goto err;
-               }
-               /* the decompressor still expects the A/C bytes in the hdr */
-               len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2,
-                               skb->len + 2, ns->data, obuff_size);
-               if (len < 0) {
-                       /* Pass the compressed frame to pppd as an
-                          error indication. */
-                       if (len == DECOMP_FATALERROR)
-                               ppp->rstate |= SC_DC_FERROR;
-                       kfree_skb(ns);
-                       goto err;
-               }
-
-               kfree_skb(skb);
-               skb = ns;
-               skb_put(skb, len);
-               skb_pull(skb, 2);       /* pull off the A/C bytes */
-
-       } else {
-               /* Uncompressed frame - pass to decompressor so it
-                  can update its dictionary if necessary. */
-               if (ppp->rcomp->incomp)
-                       ppp->rcomp->incomp(ppp->rc_state, skb->data - 2,
-                                          skb->len + 2);
-       }
-
-       return skb;
-
- err:
-       ppp->rstate |= SC_DC_ERROR;
-       ppp_receive_error(ppp);
-       return skb;
-}
-
-#ifdef CONFIG_PPP_MULTILINK
-/*
- * Receive a multilink frame.
- * We put it on the reconstruction queue and then pull off
- * as many completed frames as we can.
- */
-static void
-ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
-{
-       u32 mask, seq;
-       struct channel *ch;
-       int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
-
-       if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
-               goto err;               /* no good, throw it away */
-
-       /* Decode sequence number and begin/end bits */
-       if (ppp->flags & SC_MP_SHORTSEQ) {
-               seq = ((skb->data[2] & 0x0f) << 8) | skb->data[3];
-               mask = 0xfff;
-       } else {
-               seq = (skb->data[3] << 16) | (skb->data[4] << 8)| skb->data[5];
-               mask = 0xffffff;
-       }
-       PPP_MP_CB(skb)->BEbits = skb->data[2];
-       skb_pull(skb, mphdrlen);        /* pull off PPP and MP headers */
-
-       /*
-        * Do protocol ID decompression on the first fragment of each packet.
-        */
-       if ((PPP_MP_CB(skb)->BEbits & B) && (skb->data[0] & 1))
-               *skb_push(skb, 1) = 0;
-
-       /*
-        * Expand sequence number to 32 bits, making it as close
-        * as possible to ppp->minseq.
-        */
-       seq |= ppp->minseq & ~mask;
-       if ((int)(ppp->minseq - seq) > (int)(mask >> 1))
-               seq += mask + 1;
-       else if ((int)(seq - ppp->minseq) > (int)(mask >> 1))
-               seq -= mask + 1;        /* should never happen */
-       PPP_MP_CB(skb)->sequence = seq;
-       pch->lastseq = seq;
-
-       /*
-        * If this packet comes before the next one we were expecting,
-        * drop it.
-        */
-       if (seq_before(seq, ppp->nextseq)) {
-               kfree_skb(skb);
-               ++ppp->dev->stats.rx_dropped;
-               ppp_receive_error(ppp);
-               return;
-       }
-
-       /*
-        * Reevaluate minseq, the minimum over all channels of the
-        * last sequence number received on each channel.  Because of
-        * the increasing sequence number rule, we know that any fragment
-        * before `minseq' which hasn't arrived is never going to arrive.
-        * The list of channels can't change because we have the receive
-        * side of the ppp unit locked.
-        */
-       list_for_each_entry(ch, &ppp->channels, clist) {
-               if (seq_before(ch->lastseq, seq))
-                       seq = ch->lastseq;
-       }
-       if (seq_before(ppp->minseq, seq))
-               ppp->minseq = seq;
-
-       /* Put the fragment on the reconstruction queue */
-       ppp_mp_insert(ppp, skb);
-
-       /* If the queue is getting long, don't wait any longer for packets
-          before the start of the queue. */
-       if (skb_queue_len(&ppp->mrq) >= PPP_MP_MAX_QLEN) {
-               struct sk_buff *mskb = skb_peek(&ppp->mrq);
-               if (seq_before(ppp->minseq, PPP_MP_CB(mskb)->sequence))
-                       ppp->minseq = PPP_MP_CB(mskb)->sequence;
-       }
-
-       /* Pull completed packets off the queue and receive them. */
-       while ((skb = ppp_mp_reconstruct(ppp))) {
-               if (pskb_may_pull(skb, 2))
-                       ppp_receive_nonmp_frame(ppp, skb);
-               else {
-                       ++ppp->dev->stats.rx_length_errors;
-                       kfree_skb(skb);
-                       ppp_receive_error(ppp);
-               }
-       }
-
-       return;
-
- err:
-       kfree_skb(skb);
-       ppp_receive_error(ppp);
-}
-
-/*
- * Insert a fragment on the MP reconstruction queue.
- * The queue is ordered by increasing sequence number.
- */
-static void
-ppp_mp_insert(struct ppp *ppp, struct sk_buff *skb)
-{
-       struct sk_buff *p;
-       struct sk_buff_head *list = &ppp->mrq;
-       u32 seq = PPP_MP_CB(skb)->sequence;
-
-       /* N.B. we don't need to lock the list lock because we have the
-          ppp unit receive-side lock. */
-       skb_queue_walk(list, p) {
-               if (seq_before(seq, PPP_MP_CB(p)->sequence))
-                       break;
-       }
-       __skb_queue_before(list, p, skb);
-}
-
-/*
- * Reconstruct a packet from the MP fragment queue.
- * We go through increasing sequence numbers until we find a
- * complete packet, or we get to the sequence number for a fragment
- * which hasn't arrived but might still do so.
- */
-static struct sk_buff *
-ppp_mp_reconstruct(struct ppp *ppp)
-{
-       u32 seq = ppp->nextseq;
-       u32 minseq = ppp->minseq;
-       struct sk_buff_head *list = &ppp->mrq;
-       struct sk_buff *p, *tmp;
-       struct sk_buff *head, *tail;
-       struct sk_buff *skb = NULL;
-       int lost = 0, len = 0;
-
-       if (ppp->mrru == 0)     /* do nothing until mrru is set */
-               return NULL;
-       head = list->next;
-       tail = NULL;
-       skb_queue_walk_safe(list, p, tmp) {
-       again:
-               if (seq_before(PPP_MP_CB(p)->sequence, seq)) {
-                       /* this can't happen, anyway ignore the skb */
-                       netdev_err(ppp->dev, "ppp_mp_reconstruct bad "
-                                  "seq %u < %u\n",
-                                  PPP_MP_CB(p)->sequence, seq);
-                       __skb_unlink(p, list);
-                       kfree_skb(p);
-                       continue;
-               }
-               if (PPP_MP_CB(p)->sequence != seq) {
-                       /* Fragment `seq' is missing.  If it is after
-                          minseq, it might arrive later, so stop here. */
-                       if (seq_after(seq, minseq))
-                               break;
-                       /* Fragment `seq' is lost, keep going. */
-                       lost = 1;
-                       seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
-                               minseq + 1: PPP_MP_CB(p)->sequence;
-                       goto again;
-               }
-
-               /*
-                * At this point we know that all the fragments from
-                * ppp->nextseq to seq are either present or lost.
-                * Also, there are no complete packets in the queue
-                * that have no missing fragments and end before this
-                * fragment.
-                */
-
-               /* B bit set indicates this fragment starts a packet */
-               if (PPP_MP_CB(p)->BEbits & B) {
-                       head = p;
-                       lost = 0;
-                       len = 0;
-               }
-
-               len += p->len;
-
-               /* Got a complete packet yet? */
-               if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) &&
-                   (PPP_MP_CB(head)->BEbits & B)) {
-                       if (len > ppp->mrru + 2) {
-                               ++ppp->dev->stats.rx_length_errors;
-                               netdev_printk(KERN_DEBUG, ppp->dev,
-                                             "PPP: reconstructed packet"
-                                             " is too long (%d)\n", len);
-                       } else {
-                               tail = p;
-                               break;
-                       }
-                       ppp->nextseq = seq + 1;
-               }
-
-               /*
-                * If this is the ending fragment of a packet,
-                * and we haven't found a complete valid packet yet,
-                * we can discard up to and including this fragment.
-                */
-               if (PPP_MP_CB(p)->BEbits & E) {
-                       struct sk_buff *tmp2;
-
-                       skb_queue_reverse_walk_from_safe(list, p, tmp2) {
-                               __skb_unlink(p, list);
-                               kfree_skb(p);
-                       }
-                       head = skb_peek(list);
-                       if (!head)
-                               break;
-               }
-               ++seq;
-       }
-
-       /* If we have a complete packet, copy it all into one skb. */
-       if (tail != NULL) {
-               /* If we have discarded any fragments,
-                  signal a receive error. */
-               if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
-                       if (ppp->debug & 1)
-                               netdev_printk(KERN_DEBUG, ppp->dev,
-                                             "  missed pkts %u..%u\n",
-                                             ppp->nextseq,
-                                             PPP_MP_CB(head)->sequence-1);
-                       ++ppp->dev->stats.rx_dropped;
-                       ppp_receive_error(ppp);
-               }
-
-               skb = head;
-               if (head != tail) {
-                       struct sk_buff **fragpp = &skb_shinfo(skb)->frag_list;
-                       p = skb_queue_next(list, head);
-                       __skb_unlink(skb, list);
-                       skb_queue_walk_from_safe(list, p, tmp) {
-                               __skb_unlink(p, list);
-                               *fragpp = p;
-                               p->next = NULL;
-                               fragpp = &p->next;
-
-                               skb->len += p->len;
-                               skb->data_len += p->len;
-                               skb->truesize += p->len;
-
-                               if (p == tail)
-                                       break;
-                       }
-               } else {
-                       __skb_unlink(skb, list);
-               }
-
-               ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
-       }
-
-       return skb;
-}
-#endif /* CONFIG_PPP_MULTILINK */
-
-/*
- * Channel interface.
- */
-
-/* Create a new, unattached ppp channel. */
-int ppp_register_channel(struct ppp_channel *chan)
-{
-       return ppp_register_net_channel(current->nsproxy->net_ns, chan);
-}
-
-/* Create a new, unattached ppp channel for specified net. */
-int ppp_register_net_channel(struct net *net, struct ppp_channel *chan)
-{
-       struct channel *pch;
-       struct ppp_net *pn;
-
-       pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
-       if (!pch)
-               return -ENOMEM;
-
-       pn = ppp_pernet(net);
-
-       pch->ppp = NULL;
-       pch->chan = chan;
-       pch->chan_net = net;
-       chan->ppp = pch;
-       init_ppp_file(&pch->file, CHANNEL);
-       pch->file.hdrlen = chan->hdrlen;
-#ifdef CONFIG_PPP_MULTILINK
-       pch->lastseq = -1;
-#endif /* CONFIG_PPP_MULTILINK */
-       init_rwsem(&pch->chan_sem);
-       spin_lock_init(&pch->downl);
-       rwlock_init(&pch->upl);
-
-       spin_lock_bh(&pn->all_channels_lock);
-       pch->file.index = ++pn->last_channel_index;
-       list_add(&pch->list, &pn->new_channels);
-       atomic_inc(&channel_count);
-       spin_unlock_bh(&pn->all_channels_lock);
-
-       return 0;
-}
-
-/*
- * Return the index of a channel.
- */
-int ppp_channel_index(struct ppp_channel *chan)
-{
-       struct channel *pch = chan->ppp;
-
-       if (pch)
-               return pch->file.index;
-       return -1;
-}
-
-/*
- * Return the PPP unit number to which a channel is connected.
- */
-int ppp_unit_number(struct ppp_channel *chan)
-{
-       struct channel *pch = chan->ppp;
-       int unit = -1;
-
-       if (pch) {
-               read_lock_bh(&pch->upl);
-               if (pch->ppp)
-                       unit = pch->ppp->file.index;
-               read_unlock_bh(&pch->upl);
-       }
-       return unit;
-}
-
-/*
- * Return the PPP device interface name of a channel.
- */
-char *ppp_dev_name(struct ppp_channel *chan)
-{
-       struct channel *pch = chan->ppp;
-       char *name = NULL;
-
-       if (pch) {
-               read_lock_bh(&pch->upl);
-               if (pch->ppp && pch->ppp->dev)
-                       name = pch->ppp->dev->name;
-               read_unlock_bh(&pch->upl);
-       }
-       return name;
-}
-
-
-/*
- * Disconnect a channel from the generic layer.
- * This must be called in process context.
- */
-void
-ppp_unregister_channel(struct ppp_channel *chan)
-{
-       struct channel *pch = chan->ppp;
-       struct ppp_net *pn;
-
-       if (!pch)
-               return;         /* should never happen */
-
-       chan->ppp = NULL;
-
-       /*
-        * This ensures that we have returned from any calls into the
-        * the channel's start_xmit or ioctl routine before we proceed.
-        */
-       down_write(&pch->chan_sem);
-       spin_lock_bh(&pch->downl);
-       pch->chan = NULL;
-       spin_unlock_bh(&pch->downl);
-       up_write(&pch->chan_sem);
-       ppp_disconnect_channel(pch);
-
-       pn = ppp_pernet(pch->chan_net);
-       spin_lock_bh(&pn->all_channels_lock);
-       list_del(&pch->list);
-       spin_unlock_bh(&pn->all_channels_lock);
-
-       pch->file.dead = 1;
-       wake_up_interruptible(&pch->file.rwait);
-       if (atomic_dec_and_test(&pch->file.refcnt))
-               ppp_destroy_channel(pch);
-}
-
-/*
- * Callback from a channel when it can accept more to transmit.
- * This should be called at BH/softirq level, not interrupt level.
- */
-void
-ppp_output_wakeup(struct ppp_channel *chan)
-{
-       struct channel *pch = chan->ppp;
-
-       if (!pch)
-               return;
-       ppp_channel_push(pch);
-}
-
-/*
- * Compression control.
- */
-
-/* Process the PPPIOCSCOMPRESS ioctl. */
-static int
-ppp_set_compress(struct ppp *ppp, unsigned long arg)
-{
-       int err;
-       struct compressor *cp, *ocomp;
-       struct ppp_option_data data;
-       void *state, *ostate;
-       unsigned char ccp_option[CCP_MAX_OPTION_LENGTH];
-
-       err = -EFAULT;
-       if (copy_from_user(&data, (void __user *) arg, sizeof(data)) ||
-           (data.length <= CCP_MAX_OPTION_LENGTH &&
-            copy_from_user(ccp_option, (void __user *) data.ptr, data.length)))
-               goto out;
-       err = -EINVAL;
-       if (data.length > CCP_MAX_OPTION_LENGTH ||
-           ccp_option[1] < 2 || ccp_option[1] > data.length)
-               goto out;
-
-       cp = try_then_request_module(
-               find_compressor(ccp_option[0]),
-               "ppp-compress-%d", ccp_option[0]);
-       if (!cp)
-               goto out;
-
-       err = -ENOBUFS;
-       if (data.transmit) {
-               state = cp->comp_alloc(ccp_option, data.length);
-               if (state) {
-                       ppp_xmit_lock(ppp);
-                       ppp->xstate &= ~SC_COMP_RUN;
-                       ocomp = ppp->xcomp;
-                       ostate = ppp->xc_state;
-                       ppp->xcomp = cp;
-                       ppp->xc_state = state;
-                       ppp_xmit_unlock(ppp);
-                       if (ostate) {
-                               ocomp->comp_free(ostate);
-                               module_put(ocomp->owner);
-                       }
-                       err = 0;
-               } else
-                       module_put(cp->owner);
-
-       } else {
-               state = cp->decomp_alloc(ccp_option, data.length);
-               if (state) {
-                       ppp_recv_lock(ppp);
-                       ppp->rstate &= ~SC_DECOMP_RUN;
-                       ocomp = ppp->rcomp;
-                       ostate = ppp->rc_state;
-                       ppp->rcomp = cp;
-                       ppp->rc_state = state;
-                       ppp_recv_unlock(ppp);
-                       if (ostate) {
-                               ocomp->decomp_free(ostate);
-                               module_put(ocomp->owner);
-                       }
-                       err = 0;
-               } else
-                       module_put(cp->owner);
-       }
-
- out:
-       return err;
-}
-
-/*
- * Look at a CCP packet and update our state accordingly.
- * We assume the caller has the xmit or recv path locked.
- */
-static void
-ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
-{
-       unsigned char *dp;
-       int len;
-
-       if (!pskb_may_pull(skb, CCP_HDRLEN + 2))
-               return; /* no header */
-       dp = skb->data + 2;
-
-       switch (CCP_CODE(dp)) {
-       case CCP_CONFREQ:
-
-               /* A ConfReq starts negotiation of compression
-                * in one direction of transmission,
-                * and hence brings it down...but which way?
-                *
-                * Remember:
-                * A ConfReq indicates what the sender would like to receive
-                */
-               if(inbound)
-                       /* He is proposing what I should send */
-                       ppp->xstate &= ~SC_COMP_RUN;
-               else
-                       /* I am proposing to what he should send */
-                       ppp->rstate &= ~SC_DECOMP_RUN;
-
-               break;
-
-       case CCP_TERMREQ:
-       case CCP_TERMACK:
-               /*
-                * CCP is going down, both directions of transmission
-                */
-               ppp->rstate &= ~SC_DECOMP_RUN;
-               ppp->xstate &= ~SC_COMP_RUN;
-               break;
-
-       case CCP_CONFACK:
-               if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN)
-                       break;
-               len = CCP_LENGTH(dp);
-               if (!pskb_may_pull(skb, len + 2))
-                       return;         /* too short */
-               dp += CCP_HDRLEN;
-               len -= CCP_HDRLEN;
-               if (len < CCP_OPT_MINLEN || len < CCP_OPT_LENGTH(dp))
-                       break;
-               if (inbound) {
-                       /* we will start receiving compressed packets */
-                       if (!ppp->rc_state)
-                               break;
-                       if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
-                                       ppp->file.index, 0, ppp->mru, ppp->debug)) {
-                               ppp->rstate |= SC_DECOMP_RUN;
-                               ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR);
-                       }
-               } else {
-                       /* we will soon start sending compressed packets */
-                       if (!ppp->xc_state)
-                               break;
-                       if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
-                                       ppp->file.index, 0, ppp->debug))
-                               ppp->xstate |= SC_COMP_RUN;
-               }
-               break;
-
-       case CCP_RESETACK:
-               /* reset the [de]compressor */
-               if ((ppp->flags & SC_CCP_UP) == 0)
-                       break;
-               if (inbound) {
-                       if (ppp->rc_state && (ppp->rstate & SC_DECOMP_RUN)) {
-                               ppp->rcomp->decomp_reset(ppp->rc_state);
-                               ppp->rstate &= ~SC_DC_ERROR;
-                       }
-               } else {
-                       if (ppp->xc_state && (ppp->xstate & SC_COMP_RUN))
-                               ppp->xcomp->comp_reset(ppp->xc_state);
-               }
-               break;
-       }
-}
-
-/* Free up compression resources. */
-static void
-ppp_ccp_closed(struct ppp *ppp)
-{
-       void *xstate, *rstate;
-       struct compressor *xcomp, *rcomp;
-
-       ppp_lock(ppp);
-       ppp->flags &= ~(SC_CCP_OPEN | SC_CCP_UP);
-       ppp->xstate = 0;
-       xcomp = ppp->xcomp;
-       xstate = ppp->xc_state;
-       ppp->xc_state = NULL;
-       ppp->rstate = 0;
-       rcomp = ppp->rcomp;
-       rstate = ppp->rc_state;
-       ppp->rc_state = NULL;
-       ppp_unlock(ppp);
-
-       if (xstate) {
-               xcomp->comp_free(xstate);
-               module_put(xcomp->owner);
-       }
-       if (rstate) {
-               rcomp->decomp_free(rstate);
-               module_put(rcomp->owner);
-       }
-}
-
-/* List of compressors. */
-static LIST_HEAD(compressor_list);
-static DEFINE_SPINLOCK(compressor_list_lock);
-
-struct compressor_entry {
-       struct list_head list;
-       struct compressor *comp;
-};
-
-static struct compressor_entry *
-find_comp_entry(int proto)
-{
-       struct compressor_entry *ce;
-
-       list_for_each_entry(ce, &compressor_list, list) {
-               if (ce->comp->compress_proto == proto)
-                       return ce;
-       }
-       return NULL;
-}
-
-/* Register a compressor */
-int
-ppp_register_compressor(struct compressor *cp)
-{
-       struct compressor_entry *ce;
-       int ret;
-       spin_lock(&compressor_list_lock);
-       ret = -EEXIST;
-       if (find_comp_entry(cp->compress_proto))
-               goto out;
-       ret = -ENOMEM;
-       ce = kmalloc(sizeof(struct compressor_entry), GFP_ATOMIC);
-       if (!ce)
-               goto out;
-       ret = 0;
-       ce->comp = cp;
-       list_add(&ce->list, &compressor_list);
- out:
-       spin_unlock(&compressor_list_lock);
-       return ret;
-}
-
-/* Unregister a compressor */
-void
-ppp_unregister_compressor(struct compressor *cp)
-{
-       struct compressor_entry *ce;
-
-       spin_lock(&compressor_list_lock);
-       ce = find_comp_entry(cp->compress_proto);
-       if (ce && ce->comp == cp) {
-               list_del(&ce->list);
-               kfree(ce);
-       }
-       spin_unlock(&compressor_list_lock);
-}
-
-/* Find a compressor. */
-static struct compressor *
-find_compressor(int type)
-{
-       struct compressor_entry *ce;
-       struct compressor *cp = NULL;
-
-       spin_lock(&compressor_list_lock);
-       ce = find_comp_entry(type);
-       if (ce) {
-               cp = ce->comp;
-               if (!try_module_get(cp->owner))
-                       cp = NULL;
-       }
-       spin_unlock(&compressor_list_lock);
-       return cp;
-}
-
-/*
- * Miscelleneous stuff.
- */
-
-static void
-ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
-{
-       struct slcompress *vj = ppp->vj;
-
-       memset(st, 0, sizeof(*st));
-       st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
-       st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
-       st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
-       st->p.ppp_opackets = ppp->dev->stats.tx_packets;
-       st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
-       st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
-       if (!vj)
-               return;
-       st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
-       st->vj.vjs_compressed = vj->sls_o_compressed;
-       st->vj.vjs_searches = vj->sls_o_searches;
-       st->vj.vjs_misses = vj->sls_o_misses;
-       st->vj.vjs_errorin = vj->sls_i_error;
-       st->vj.vjs_tossed = vj->sls_i_tossed;
-       st->vj.vjs_uncompressedin = vj->sls_i_uncompressed;
-       st->vj.vjs_compressedin = vj->sls_i_compressed;
-}
-
-/*
- * Stuff for handling the lists of ppp units and channels
- * and for initialization.
- */
-
-/*
- * Create a new ppp interface unit.  Fails if it can't allocate memory
- * or if there is already a unit with the requested number.
- * unit == -1 means allocate a new number.
- */
-static struct ppp *
-ppp_create_interface(struct net *net, int unit, int *retp)
-{
-       struct ppp *ppp;
-       struct ppp_net *pn;
-       struct net_device *dev = NULL;
-       int ret = -ENOMEM;
-       int i;
-
-       dev = alloc_netdev(sizeof(struct ppp), "", ppp_setup);
-       if (!dev)
-               goto out1;
-
-       pn = ppp_pernet(net);
-
-       ppp = netdev_priv(dev);
-       ppp->dev = dev;
-       ppp->mru = PPP_MRU;
-       init_ppp_file(&ppp->file, INTERFACE);
-       ppp->file.hdrlen = PPP_HDRLEN - 2;      /* don't count proto bytes */
-       for (i = 0; i < NUM_NP; ++i)
-               ppp->npmode[i] = NPMODE_PASS;
-       INIT_LIST_HEAD(&ppp->channels);
-       spin_lock_init(&ppp->rlock);
-       spin_lock_init(&ppp->wlock);
-#ifdef CONFIG_PPP_MULTILINK
-       ppp->minseq = -1;
-       skb_queue_head_init(&ppp->mrq);
-#endif /* CONFIG_PPP_MULTILINK */
-
-       /*
-        * drum roll: don't forget to set
-        * the net device is belong to
-        */
-       dev_net_set(dev, net);
-
-       mutex_lock(&pn->all_ppp_mutex);
-
-       if (unit < 0) {
-               unit = unit_get(&pn->units_idr, ppp);
-               if (unit < 0) {
-                       ret = unit;
-                       goto out2;
-               }
-       } else {
-               ret = -EEXIST;
-               if (unit_find(&pn->units_idr, unit))
-                       goto out2; /* unit already exists */
-               /*
-                * if caller need a specified unit number
-                * lets try to satisfy him, otherwise --
-                * he should better ask us for new unit number
-                *
-                * NOTE: yes I know that returning EEXIST it's not
-                * fair but at least pppd will ask us to allocate
-                * new unit in this case so user is happy :)
-                */
-               unit = unit_set(&pn->units_idr, ppp, unit);
-               if (unit < 0)
-                       goto out2;
-       }
-
-       /* Initialize the new ppp unit */
-       ppp->file.index = unit;
-       sprintf(dev->name, "ppp%d", unit);
-
-       ret = register_netdev(dev);
-       if (ret != 0) {
-               unit_put(&pn->units_idr, unit);
-               netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n",
-                          dev->name, ret);
-               goto out2;
-       }
-
-       ppp->ppp_net = net;
-
-       atomic_inc(&ppp_unit_count);
-       mutex_unlock(&pn->all_ppp_mutex);
-
-       *retp = 0;
-       return ppp;
-
-out2:
-       mutex_unlock(&pn->all_ppp_mutex);
-       free_netdev(dev);
-out1:
-       *retp = ret;
-       return NULL;
-}
-
-/*
- * Initialize a ppp_file structure.
- */
-static void
-init_ppp_file(struct ppp_file *pf, int kind)
-{
-       pf->kind = kind;
-       skb_queue_head_init(&pf->xq);
-       skb_queue_head_init(&pf->rq);
-       atomic_set(&pf->refcnt, 1);
-       init_waitqueue_head(&pf->rwait);
-}
-
-/*
- * Take down a ppp interface unit - called when the owning file
- * (the one that created the unit) is closed or detached.
- */
-static void ppp_shutdown_interface(struct ppp *ppp)
-{
-       struct ppp_net *pn;
-
-       pn = ppp_pernet(ppp->ppp_net);
-       mutex_lock(&pn->all_ppp_mutex);
-
-       /* This will call dev_close() for us. */
-       ppp_lock(ppp);
-       if (!ppp->closing) {
-               ppp->closing = 1;
-               ppp_unlock(ppp);
-               unregister_netdev(ppp->dev);
-               unit_put(&pn->units_idr, ppp->file.index);
-       } else
-               ppp_unlock(ppp);
-
-       ppp->file.dead = 1;
-       ppp->owner = NULL;
-       wake_up_interruptible(&ppp->file.rwait);
-
-       mutex_unlock(&pn->all_ppp_mutex);
-}
-
-/*
- * Free the memory used by a ppp unit.  This is only called once
- * there are no channels connected to the unit and no file structs
- * that reference the unit.
- */
-static void ppp_destroy_interface(struct ppp *ppp)
-{
-       atomic_dec(&ppp_unit_count);
-
-       if (!ppp->file.dead || ppp->n_channels) {
-               /* "can't happen" */
-               netdev_err(ppp->dev, "ppp: destroying ppp struct %p "
-                          "but dead=%d n_channels=%d !\n",
-                          ppp, ppp->file.dead, ppp->n_channels);
-               return;
-       }
-
-       ppp_ccp_closed(ppp);
-       if (ppp->vj) {
-               slhc_free(ppp->vj);
-               ppp->vj = NULL;
-       }
-       skb_queue_purge(&ppp->file.xq);
-       skb_queue_purge(&ppp->file.rq);
-#ifdef CONFIG_PPP_MULTILINK
-       skb_queue_purge(&ppp->mrq);
-#endif /* CONFIG_PPP_MULTILINK */
-#ifdef CONFIG_PPP_FILTER
-       kfree(ppp->pass_filter);
-       ppp->pass_filter = NULL;
-       kfree(ppp->active_filter);
-       ppp->active_filter = NULL;
-#endif /* CONFIG_PPP_FILTER */
-
-       kfree_skb(ppp->xmit_pending);
-
-       free_netdev(ppp->dev);
-}
-
-/*
- * Locate an existing ppp unit.
- * The caller should have locked the all_ppp_mutex.
- */
-static struct ppp *
-ppp_find_unit(struct ppp_net *pn, int unit)
-{
-       return unit_find(&pn->units_idr, unit);
-}
-
-/*
- * Locate an existing ppp channel.
- * The caller should have locked the all_channels_lock.
- * First we look in the new_channels list, then in the
- * all_channels list.  If found in the new_channels list,
- * we move it to the all_channels list.  This is for speed
- * when we have a lot of channels in use.
- */
-static struct channel *
-ppp_find_channel(struct ppp_net *pn, int unit)
-{
-       struct channel *pch;
-
-       list_for_each_entry(pch, &pn->new_channels, list) {
-               if (pch->file.index == unit) {
-                       list_move(&pch->list, &pn->all_channels);
-                       return pch;
-               }
-       }
-
-       list_for_each_entry(pch, &pn->all_channels, list) {
-               if (pch->file.index == unit)
-                       return pch;
-       }
-
-       return NULL;
-}
-
-/*
- * Connect a PPP channel to a PPP interface unit.
- */
-static int
-ppp_connect_channel(struct channel *pch, int unit)
-{
-       struct ppp *ppp;
-       struct ppp_net *pn;
-       int ret = -ENXIO;
-       int hdrlen;
-
-       pn = ppp_pernet(pch->chan_net);
-
-       mutex_lock(&pn->all_ppp_mutex);
-       ppp = ppp_find_unit(pn, unit);
-       if (!ppp)
-               goto out;
-       write_lock_bh(&pch->upl);
-       ret = -EINVAL;
-       if (pch->ppp)
-               goto outl;
-
-       ppp_lock(ppp);
-       if (pch->file.hdrlen > ppp->file.hdrlen)
-               ppp->file.hdrlen = pch->file.hdrlen;
-       hdrlen = pch->file.hdrlen + 2;  /* for protocol bytes */
-       if (hdrlen > ppp->dev->hard_header_len)
-               ppp->dev->hard_header_len = hdrlen;
-       list_add_tail(&pch->clist, &ppp->channels);
-       ++ppp->n_channels;
-       pch->ppp = ppp;
-       atomic_inc(&ppp->file.refcnt);
-       ppp_unlock(ppp);
-       ret = 0;
-
- outl:
-       write_unlock_bh(&pch->upl);
- out:
-       mutex_unlock(&pn->all_ppp_mutex);
-       return ret;
-}
-
-/*
- * Disconnect a channel from its ppp unit.
- */
-static int
-ppp_disconnect_channel(struct channel *pch)
-{
-       struct ppp *ppp;
-       int err = -EINVAL;
-
-       write_lock_bh(&pch->upl);
-       ppp = pch->ppp;
-       pch->ppp = NULL;
-       write_unlock_bh(&pch->upl);
-       if (ppp) {
-               /* remove it from the ppp unit's list */
-               ppp_lock(ppp);
-               list_del(&pch->clist);
-               if (--ppp->n_channels == 0)
-                       wake_up_interruptible(&ppp->file.rwait);
-               ppp_unlock(ppp);
-               if (atomic_dec_and_test(&ppp->file.refcnt))
-                       ppp_destroy_interface(ppp);
-               err = 0;
-       }
-       return err;
-}
-
-/*
- * Free up the resources used by a ppp channel.
- */
-static void ppp_destroy_channel(struct channel *pch)
-{
-       atomic_dec(&channel_count);
-
-       if (!pch->file.dead) {
-               /* "can't happen" */
-               pr_err("ppp: destroying undead channel %p !\n", pch);
-               return;
-       }
-       skb_queue_purge(&pch->file.xq);
-       skb_queue_purge(&pch->file.rq);
-       kfree(pch);
-}
-
-static void __exit ppp_cleanup(void)
-{
-       /* should never happen */
-       if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
-               pr_err("PPP: removing module but units remain!\n");
-       unregister_chrdev(PPP_MAJOR, "ppp");
-       device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
-       class_destroy(ppp_class);
-       unregister_pernet_device(&ppp_net_ops);
-}
-
-/*
- * Units handling. Caller must protect concurrent access
- * by holding all_ppp_mutex
- */
-
-static int __unit_alloc(struct idr *p, void *ptr, int n)
-{
-       int unit, err;
-
-again:
-       if (!idr_pre_get(p, GFP_KERNEL)) {
-               pr_err("PPP: No free memory for idr\n");
-               return -ENOMEM;
-       }
-
-       err = idr_get_new_above(p, ptr, n, &unit);
-       if (err < 0) {
-               if (err == -EAGAIN)
-                       goto again;
-               return err;
-       }
-
-       return unit;
-}
-
-/* associate pointer with specified number */
-static int unit_set(struct idr *p, void *ptr, int n)
-{
-       int unit;
-
-       unit = __unit_alloc(p, ptr, n);
-       if (unit < 0)
-               return unit;
-       else if (unit != n) {
-               idr_remove(p, unit);
-               return -EINVAL;
-       }
-
-       return unit;
-}
-
-/* get new free unit number and associate pointer with it */
-static int unit_get(struct idr *p, void *ptr)
-{
-       return __unit_alloc(p, ptr, 0);
-}
-
-/* put unit number back to a pool */
-static void unit_put(struct idr *p, int n)
-{
-       idr_remove(p, n);
-}
-
-/* get pointer associated with the number */
-static void *unit_find(struct idr *p, int n)
-{
-       return idr_find(p, n);
-}
-
-/* Module/initialization stuff */
-
-module_init(ppp_init);
-module_exit(ppp_cleanup);
-
-EXPORT_SYMBOL(ppp_register_net_channel);
-EXPORT_SYMBOL(ppp_register_channel);
-EXPORT_SYMBOL(ppp_unregister_channel);
-EXPORT_SYMBOL(ppp_channel_index);
-EXPORT_SYMBOL(ppp_unit_number);
-EXPORT_SYMBOL(ppp_dev_name);
-EXPORT_SYMBOL(ppp_input);
-EXPORT_SYMBOL(ppp_input_error);
-EXPORT_SYMBOL(ppp_output_wakeup);
-EXPORT_SYMBOL(ppp_register_compressor);
-EXPORT_SYMBOL(ppp_unregister_compressor);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0);
-MODULE_ALIAS("devname:ppp");
diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c
deleted file mode 100644 (file)
index 9a1849a..0000000
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * ppp_mppe.c - interface MPPE to the PPP code.
- * This version is for use with Linux kernel 2.6.14+
- *
- * By Frank Cusack <fcusack@fcusack.com>.
- * Copyright (c) 2002,2003,2004 Google, Inc.
- * All rights reserved.
- *
- * License:
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies.  This software is provided without any
- * warranty, express or implied.
- *
- * ALTERNATIVELY, provided that this notice is retained in full, this product
- * may be distributed under the terms of the GNU General Public License (GPL),
- * in which case the provisions of the GPL apply INSTEAD OF those given above.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- *
- * Changelog:
- *      08/12/05 - Matt Domsch <Matt_Domsch@dell.com>
- *                 Only need extra skb padding on transmit, not receive.
- *      06/18/04 - Matt Domsch <Matt_Domsch@dell.com>, Oleg Makarenko <mole@quadra.ru>
- *                 Use Linux kernel 2.6 arc4 and sha1 routines rather than
- *                 providing our own.
- *      2/15/04 - TS: added #include <version.h> and testing for Kernel
- *                    version before using
- *                    MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are
- *                    deprecated in 2.6
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/crypto.h>
-#include <linux/mm.h>
-#include <linux/ppp_defs.h>
-#include <linux/ppp-comp.h>
-#include <linux/scatterlist.h>
-#include <asm/unaligned.h>
-
-#include "ppp_mppe.h"
-
-MODULE_AUTHOR("Frank Cusack <fcusack@fcusack.com>");
-MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE));
-MODULE_VERSION("1.0.2");
-
-static unsigned int
-setup_sg(struct scatterlist *sg, const void *address, unsigned int length)
-{
-       sg_set_buf(sg, address, length);
-       return length;
-}
-
-#define SHA1_PAD_SIZE 40
-
-/*
- * kernel crypto API needs its arguments to be in kmalloc'd memory, not in the module
- * static data area.  That means sha_pad needs to be kmalloc'd.
- */
-
-struct sha_pad {
-       unsigned char sha_pad1[SHA1_PAD_SIZE];
-       unsigned char sha_pad2[SHA1_PAD_SIZE];
-};
-static struct sha_pad *sha_pad;
-
-static inline void sha_pad_init(struct sha_pad *shapad)
-{
-       memset(shapad->sha_pad1, 0x00, sizeof(shapad->sha_pad1));
-       memset(shapad->sha_pad2, 0xF2, sizeof(shapad->sha_pad2));
-}
-
-/*
- * State for an MPPE (de)compressor.
- */
-struct ppp_mppe_state {
-       struct crypto_blkcipher *arc4;
-       struct crypto_hash *sha1;
-       unsigned char *sha1_digest;
-       unsigned char master_key[MPPE_MAX_KEY_LEN];
-       unsigned char session_key[MPPE_MAX_KEY_LEN];
-       unsigned keylen;        /* key length in bytes             */
-       /* NB: 128-bit == 16, 40-bit == 8! */
-       /* If we want to support 56-bit,   */
-       /* the unit has to change to bits  */
-       unsigned char bits;     /* MPPE control bits */
-       unsigned ccount;        /* 12-bit coherency count (seqno)  */
-       unsigned stateful;      /* stateful mode flag */
-       int discard;            /* stateful mode packet loss flag */
-       int sanity_errors;      /* take down LCP if too many */
-       int unit;
-       int debug;
-       struct compstat stats;
-};
-
-/* struct ppp_mppe_state.bits definitions */
-#define MPPE_BIT_A     0x80    /* Encryption table were (re)inititalized */
-#define MPPE_BIT_B     0x40    /* MPPC only (not implemented) */
-#define MPPE_BIT_C     0x20    /* MPPC only (not implemented) */
-#define MPPE_BIT_D     0x10    /* This is an encrypted frame */
-
-#define MPPE_BIT_FLUSHED       MPPE_BIT_A
-#define MPPE_BIT_ENCRYPTED     MPPE_BIT_D
-
-#define MPPE_BITS(p) ((p)[4] & 0xf0)
-#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5])
-#define MPPE_CCOUNT_SPACE 0x1000       /* The size of the ccount space */
-
-#define MPPE_OVHD      2       /* MPPE overhead/packet */
-#define SANITY_MAX     1600    /* Max bogon factor we will tolerate */
-
-/*
- * Key Derivation, from RFC 3078, RFC 3079.
- * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
- */
-static void get_new_key_from_sha(struct ppp_mppe_state * state)
-{
-       struct hash_desc desc;
-       struct scatterlist sg[4];
-       unsigned int nbytes;
-
-       sg_init_table(sg, 4);
-
-       nbytes = setup_sg(&sg[0], state->master_key, state->keylen);
-       nbytes += setup_sg(&sg[1], sha_pad->sha_pad1,
-                          sizeof(sha_pad->sha_pad1));
-       nbytes += setup_sg(&sg[2], state->session_key, state->keylen);
-       nbytes += setup_sg(&sg[3], sha_pad->sha_pad2,
-                          sizeof(sha_pad->sha_pad2));
-
-       desc.tfm = state->sha1;
-       desc.flags = 0;
-
-       crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest);
-}
-
-/*
- * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3.
- * Well, not what's written there, but rather what they meant.
- */
-static void mppe_rekey(struct ppp_mppe_state * state, int initial_key)
-{
-       struct scatterlist sg_in[1], sg_out[1];
-       struct blkcipher_desc desc = { .tfm = state->arc4 };
-
-       get_new_key_from_sha(state);
-       if (!initial_key) {
-               crypto_blkcipher_setkey(state->arc4, state->sha1_digest,
-                                       state->keylen);
-               sg_init_table(sg_in, 1);
-               sg_init_table(sg_out, 1);
-               setup_sg(sg_in, state->sha1_digest, state->keylen);
-               setup_sg(sg_out, state->session_key, state->keylen);
-               if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
-                                            state->keylen) != 0) {
-                   printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n");
-               }
-       } else {
-               memcpy(state->session_key, state->sha1_digest, state->keylen);
-       }
-       if (state->keylen == 8) {
-               /* See RFC 3078 */
-               state->session_key[0] = 0xd1;
-               state->session_key[1] = 0x26;
-               state->session_key[2] = 0x9e;
-       }
-       crypto_blkcipher_setkey(state->arc4, state->session_key, state->keylen);
-}
-
-/*
- * Allocate space for a (de)compressor.
- */
-static void *mppe_alloc(unsigned char *options, int optlen)
-{
-       struct ppp_mppe_state *state;
-       unsigned int digestsize;
-
-       if (optlen != CILEN_MPPE + sizeof(state->master_key) ||
-           options[0] != CI_MPPE || options[1] != CILEN_MPPE)
-               goto out;
-
-       state = kzalloc(sizeof(*state), GFP_KERNEL);
-       if (state == NULL)
-               goto out;
-
-
-       state->arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(state->arc4)) {
-               state->arc4 = NULL;
-               goto out_free;
-       }
-
-       state->sha1 = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(state->sha1)) {
-               state->sha1 = NULL;
-               goto out_free;
-       }
-
-       digestsize = crypto_hash_digestsize(state->sha1);
-       if (digestsize < MPPE_MAX_KEY_LEN)
-               goto out_free;
-
-       state->sha1_digest = kmalloc(digestsize, GFP_KERNEL);
-       if (!state->sha1_digest)
-               goto out_free;
-
-       /* Save keys. */
-       memcpy(state->master_key, &options[CILEN_MPPE],
-              sizeof(state->master_key));
-       memcpy(state->session_key, state->master_key,
-              sizeof(state->master_key));
-
-       /*
-        * We defer initial key generation until mppe_init(), as mppe_alloc()
-        * is called frequently during negotiation.
-        */
-
-       return (void *)state;
-
-       out_free:
-           if (state->sha1_digest)
-               kfree(state->sha1_digest);
-           if (state->sha1)
-               crypto_free_hash(state->sha1);
-           if (state->arc4)
-               crypto_free_blkcipher(state->arc4);
-           kfree(state);
-       out:
-       return NULL;
-}
-
-/*
- * Deallocate space for a (de)compressor.
- */
-static void mppe_free(void *arg)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-       if (state) {
-           if (state->sha1_digest)
-               kfree(state->sha1_digest);
-           if (state->sha1)
-               crypto_free_hash(state->sha1);
-           if (state->arc4)
-               crypto_free_blkcipher(state->arc4);
-           kfree(state);
-       }
-}
-
-/*
- * Initialize (de)compressor state.
- */
-static int
-mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug,
-         const char *debugstr)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-       unsigned char mppe_opts;
-
-       if (optlen != CILEN_MPPE ||
-           options[0] != CI_MPPE || options[1] != CILEN_MPPE)
-               return 0;
-
-       MPPE_CI_TO_OPTS(&options[2], mppe_opts);
-       if (mppe_opts & MPPE_OPT_128)
-               state->keylen = 16;
-       else if (mppe_opts & MPPE_OPT_40)
-               state->keylen = 8;
-       else {
-               printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr,
-                      unit);
-               return 0;
-       }
-       if (mppe_opts & MPPE_OPT_STATEFUL)
-               state->stateful = 1;
-
-       /* Generate the initial session key. */
-       mppe_rekey(state, 1);
-
-       if (debug) {
-               int i;
-               char mkey[sizeof(state->master_key) * 2 + 1];
-               char skey[sizeof(state->session_key) * 2 + 1];
-
-               printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n",
-                      debugstr, unit, (state->keylen == 16) ? 128 : 40,
-                      (state->stateful) ? "stateful" : "stateless");
-
-               for (i = 0; i < sizeof(state->master_key); i++)
-                       sprintf(mkey + i * 2, "%02x", state->master_key[i]);
-               for (i = 0; i < sizeof(state->session_key); i++)
-                       sprintf(skey + i * 2, "%02x", state->session_key[i]);
-               printk(KERN_DEBUG
-                      "%s[%d]: keys: master: %s initial session: %s\n",
-                      debugstr, unit, mkey, skey);
-       }
-
-       /*
-        * Initialize the coherency count.  The initial value is not specified
-        * in RFC 3078, but we can make a reasonable assumption that it will
-        * start at 0.  Setting it to the max here makes the comp/decomp code
-        * do the right thing (determined through experiment).
-        */
-       state->ccount = MPPE_CCOUNT_SPACE - 1;
-
-       /*
-        * Note that even though we have initialized the key table, we don't
-        * set the FLUSHED bit.  This is contrary to RFC 3078, sec. 3.1.
-        */
-       state->bits = MPPE_BIT_ENCRYPTED;
-
-       state->unit = unit;
-       state->debug = debug;
-
-       return 1;
-}
-
-static int
-mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit,
-              int hdrlen, int debug)
-{
-       /* ARGSUSED */
-       return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init");
-}
-
-/*
- * We received a CCP Reset-Request (actually, we are sending a Reset-Ack),
- * tell the compressor to rekey.  Note that we MUST NOT rekey for
- * every CCP Reset-Request; we only rekey on the next xmit packet.
- * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost.
- * So, rekeying for every CCP Reset-Request is broken as the peer will not
- * know how many times we've rekeyed.  (If we rekey and THEN get another
- * CCP Reset-Request, we must rekey again.)
- */
-static void mppe_comp_reset(void *arg)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-
-       state->bits |= MPPE_BIT_FLUSHED;
-}
-
-/*
- * Compress (encrypt) a packet.
- * It's strange to call this a compressor, since the output is always
- * MPPE_OVHD + 2 bytes larger than the input.
- */
-static int
-mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf,
-             int isize, int osize)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-       struct blkcipher_desc desc = { .tfm = state->arc4 };
-       int proto;
-       struct scatterlist sg_in[1], sg_out[1];
-
-       /*
-        * Check that the protocol is in the range we handle.
-        */
-       proto = PPP_PROTOCOL(ibuf);
-       if (proto < 0x0021 || proto > 0x00fa)
-               return 0;
-
-       /* Make sure we have enough room to generate an encrypted packet. */
-       if (osize < isize + MPPE_OVHD + 2) {
-               /* Drop the packet if we should encrypt it, but can't. */
-               printk(KERN_DEBUG "mppe_compress[%d]: osize too small! "
-                      "(have: %d need: %d)\n", state->unit,
-                      osize, osize + MPPE_OVHD + 2);
-               return -1;
-       }
-
-       osize = isize + MPPE_OVHD + 2;
-
-       /*
-        * Copy over the PPP header and set control bits.
-        */
-       obuf[0] = PPP_ADDRESS(ibuf);
-       obuf[1] = PPP_CONTROL(ibuf);
-       put_unaligned_be16(PPP_COMP, obuf + 2);
-       obuf += PPP_HDRLEN;
-
-       state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-       if (state->debug >= 7)
-               printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit,
-                      state->ccount);
-       put_unaligned_be16(state->ccount, obuf);
-
-       if (!state->stateful || /* stateless mode     */
-           ((state->ccount & 0xff) == 0xff) || /* "flag" packet      */
-           (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request  */
-               /* We must rekey */
-               if (state->debug && state->stateful)
-                       printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n",
-                              state->unit);
-               mppe_rekey(state, 0);
-               state->bits |= MPPE_BIT_FLUSHED;
-       }
-       obuf[0] |= state->bits;
-       state->bits &= ~MPPE_BIT_FLUSHED;       /* reset for next xmit */
-
-       obuf += MPPE_OVHD;
-       ibuf += 2;              /* skip to proto field */
-       isize -= 2;
-
-       /* Encrypt packet */
-       sg_init_table(sg_in, 1);
-       sg_init_table(sg_out, 1);
-       setup_sg(sg_in, ibuf, isize);
-       setup_sg(sg_out, obuf, osize);
-       if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) {
-               printk(KERN_DEBUG "crypto_cypher_encrypt failed\n");
-               return -1;
-       }
-
-       state->stats.unc_bytes += isize;
-       state->stats.unc_packets++;
-       state->stats.comp_bytes += osize;
-       state->stats.comp_packets++;
-
-       return osize;
-}
-
-/*
- * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going
- * to look bad ... and the longer the link is up the worse it will get.
- */
-static void mppe_comp_stats(void *arg, struct compstat *stats)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-
-       *stats = state->stats;
-}
-
-static int
-mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit,
-                int hdrlen, int mru, int debug)
-{
-       /* ARGSUSED */
-       return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init");
-}
-
-/*
- * We received a CCP Reset-Ack.  Just ignore it.
- */
-static void mppe_decomp_reset(void *arg)
-{
-       /* ARGSUSED */
-       return;
-}
-
-/*
- * Decompress (decrypt) an MPPE packet.
- */
-static int
-mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
-               int osize)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-       struct blkcipher_desc desc = { .tfm = state->arc4 };
-       unsigned ccount;
-       int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
-       int sanity = 0;
-       struct scatterlist sg_in[1], sg_out[1];
-
-       if (isize <= PPP_HDRLEN + MPPE_OVHD) {
-               if (state->debug)
-                       printk(KERN_DEBUG
-                              "mppe_decompress[%d]: short pkt (%d)\n",
-                              state->unit, isize);
-               return DECOMP_ERROR;
-       }
-
-       /*
-        * Make sure we have enough room to decrypt the packet.
-        * Note that for our test we only subtract 1 byte whereas in
-        * mppe_compress() we added 2 bytes (+MPPE_OVHD);
-        * this is to account for possible PFC.
-        */
-       if (osize < isize - MPPE_OVHD - 1) {
-               printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! "
-                      "(have: %d need: %d)\n", state->unit,
-                      osize, isize - MPPE_OVHD - 1);
-               return DECOMP_ERROR;
-       }
-       osize = isize - MPPE_OVHD - 2;  /* assume no PFC */
-
-       ccount = MPPE_CCOUNT(ibuf);
-       if (state->debug >= 7)
-               printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n",
-                      state->unit, ccount);
-
-       /* sanity checks -- terminate with extreme prejudice */
-       if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) {
-               printk(KERN_DEBUG
-                      "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
-                      state->unit);
-               state->sanity_errors += 100;
-               sanity = 1;
-       }
-       if (!state->stateful && !flushed) {
-               printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
-                      "stateless mode!\n", state->unit);
-               state->sanity_errors += 100;
-               sanity = 1;
-       }
-       if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
-               printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
-                      "flag packet!\n", state->unit);
-               state->sanity_errors += 100;
-               sanity = 1;
-       }
-
-       if (sanity) {
-               if (state->sanity_errors < SANITY_MAX)
-                       return DECOMP_ERROR;
-               else
-                       /*
-                        * Take LCP down if the peer is sending too many bogons.
-                        * We don't want to do this for a single or just a few
-                        * instances since it could just be due to packet corruption.
-                        */
-                       return DECOMP_FATALERROR;
-       }
-
-       /*
-        * Check the coherency count.
-        */
-
-       if (!state->stateful) {
-               /* RFC 3078, sec 8.1.  Rekey for every packet. */
-               while (state->ccount != ccount) {
-                       mppe_rekey(state, 0);
-                       state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-               }
-       } else {
-               /* RFC 3078, sec 8.2. */
-               if (!state->discard) {
-                       /* normal state */
-                       state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE;
-                       if (ccount != state->ccount) {
-                               /*
-                                * (ccount > state->ccount)
-                                * Packet loss detected, enter the discard state.
-                                * Signal the peer to rekey (by sending a CCP Reset-Request).
-                                */
-                               state->discard = 1;
-                               return DECOMP_ERROR;
-                       }
-               } else {
-                       /* discard state */
-                       if (!flushed) {
-                               /* ccp.c will be silent (no additional CCP Reset-Requests). */
-                               return DECOMP_ERROR;
-                       } else {
-                               /* Rekey for every missed "flag" packet. */
-                               while ((ccount & ~0xff) !=
-                                      (state->ccount & ~0xff)) {
-                                       mppe_rekey(state, 0);
-                                       state->ccount =
-                                           (state->ccount +
-                                            256) % MPPE_CCOUNT_SPACE;
-                               }
-
-                               /* reset */
-                               state->discard = 0;
-                               state->ccount = ccount;
-                               /*
-                                * Another problem with RFC 3078 here.  It implies that the
-                                * peer need not send a Reset-Ack packet.  But RFC 1962
-                                * requires it.  Hopefully, M$ does send a Reset-Ack; even
-                                * though it isn't required for MPPE synchronization, it is
-                                * required to reset CCP state.
-                                */
-                       }
-               }
-               if (flushed)
-                       mppe_rekey(state, 0);
-       }
-
-       /*
-        * Fill in the first part of the PPP header.  The protocol field
-        * comes from the decrypted data.
-        */
-       obuf[0] = PPP_ADDRESS(ibuf);    /* +1 */
-       obuf[1] = PPP_CONTROL(ibuf);    /* +1 */
-       obuf += 2;
-       ibuf += PPP_HDRLEN + MPPE_OVHD;
-       isize -= PPP_HDRLEN + MPPE_OVHD;        /* -6 */
-       /* net osize: isize-4 */
-
-       /*
-        * Decrypt the first byte in order to check if it is
-        * a compressed or uncompressed protocol field.
-        */
-       sg_init_table(sg_in, 1);
-       sg_init_table(sg_out, 1);
-       setup_sg(sg_in, ibuf, 1);
-       setup_sg(sg_out, obuf, 1);
-       if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) {
-               printk(KERN_DEBUG "crypto_cypher_decrypt failed\n");
-               return DECOMP_ERROR;
-       }
-
-       /*
-        * Do PFC decompression.
-        * This would be nicer if we were given the actual sk_buff
-        * instead of a char *.
-        */
-       if ((obuf[0] & 0x01) != 0) {
-               obuf[1] = obuf[0];
-               obuf[0] = 0;
-               obuf++;
-               osize++;
-       }
-
-       /* And finally, decrypt the rest of the packet. */
-       setup_sg(sg_in, ibuf + 1, isize - 1);
-       setup_sg(sg_out, obuf + 1, osize - 1);
-       if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, isize - 1)) {
-               printk(KERN_DEBUG "crypto_cypher_decrypt failed\n");
-               return DECOMP_ERROR;
-       }
-
-       state->stats.unc_bytes += osize;
-       state->stats.unc_packets++;
-       state->stats.comp_bytes += isize;
-       state->stats.comp_packets++;
-
-       /* good packet credit */
-       state->sanity_errors >>= 1;
-
-       return osize;
-}
-
-/*
- * Incompressible data has arrived (this should never happen!).
- * We should probably drop the link if the protocol is in the range
- * of what should be encrypted.  At the least, we should drop this
- * packet.  (How to do this?)
- */
-static void mppe_incomp(void *arg, unsigned char *ibuf, int icnt)
-{
-       struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg;
-
-       if (state->debug &&
-           (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa))
-               printk(KERN_DEBUG
-                      "mppe_incomp[%d]: incompressible (unencrypted) data! "
-                      "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf));
-
-       state->stats.inc_bytes += icnt;
-       state->stats.inc_packets++;
-       state->stats.unc_bytes += icnt;
-       state->stats.unc_packets++;
-}
-
-/*************************************************************
- * Module interface table
- *************************************************************/
-
-/*
- * Procedures exported to if_ppp.c.
- */
-static struct compressor ppp_mppe = {
-       .compress_proto = CI_MPPE,
-       .comp_alloc     = mppe_alloc,
-       .comp_free      = mppe_free,
-       .comp_init      = mppe_comp_init,
-       .comp_reset     = mppe_comp_reset,
-       .compress       = mppe_compress,
-       .comp_stat      = mppe_comp_stats,
-       .decomp_alloc   = mppe_alloc,
-       .decomp_free    = mppe_free,
-       .decomp_init    = mppe_decomp_init,
-       .decomp_reset   = mppe_decomp_reset,
-       .decompress     = mppe_decompress,
-       .incomp         = mppe_incomp,
-       .decomp_stat    = mppe_comp_stats,
-       .owner          = THIS_MODULE,
-       .comp_extra     = MPPE_PAD,
-};
-
-/*
- * ppp_mppe_init()
- *
- * Prior to allowing load, try to load the arc4 and sha1 crypto
- * libraries.  The actual use will be allocated later, but
- * this way the module will fail to insmod if they aren't available.
- */
-
-static int __init ppp_mppe_init(void)
-{
-       int answer;
-       if (!(crypto_has_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) &&
-             crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC)))
-               return -ENODEV;
-
-       sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL);
-       if (!sha_pad)
-               return -ENOMEM;
-       sha_pad_init(sha_pad);
-
-       answer = ppp_register_compressor(&ppp_mppe);
-
-       if (answer == 0)
-               printk(KERN_INFO "PPP MPPE Compression module registered\n");
-       else
-               kfree(sha_pad);
-
-       return answer;
-}
-
-static void __exit ppp_mppe_cleanup(void)
-{
-       ppp_unregister_compressor(&ppp_mppe);
-       kfree(sha_pad);
-}
-
-module_init(ppp_mppe_init);
-module_exit(ppp_mppe_cleanup);
diff --git a/drivers/net/ppp_mppe.h b/drivers/net/ppp_mppe.h
deleted file mode 100644 (file)
index 7a14e05..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#define MPPE_PAD                4      /* MPPE growth per frame */
-#define MPPE_MAX_KEY_LEN       16      /* largest key length (128-bit) */
-
-/* option bits for ccp_options.mppe */
-#define MPPE_OPT_40            0x01    /* 40 bit */
-#define MPPE_OPT_128           0x02    /* 128 bit */
-#define MPPE_OPT_STATEFUL      0x04    /* stateful mode */
-/* unsupported opts */
-#define MPPE_OPT_56            0x08    /* 56 bit */
-#define MPPE_OPT_MPPC          0x10    /* MPPC compression */
-#define MPPE_OPT_D             0x20    /* Unknown */
-#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D)
-#define MPPE_OPT_UNKNOWN       0x40    /* Bits !defined in RFC 3078 were set */
-
-/*
- * This is not nice ... the alternative is a bitfield struct though.
- * And unfortunately, we cannot share the same bits for the option
- * names above since C and H are the same bit.  We could do a u_int32
- * but then we have to do a htonl() all the time and/or we still need
- * to know which octet is which.
- */
-#define MPPE_C_BIT             0x01    /* MPPC */
-#define MPPE_D_BIT             0x10    /* Obsolete, usage unknown */
-#define MPPE_L_BIT             0x20    /* 40-bit */
-#define MPPE_S_BIT             0x40    /* 128-bit */
-#define MPPE_M_BIT             0x80    /* 56-bit, not supported */
-#define MPPE_H_BIT             0x01    /* Stateless (in a different byte) */
-
-/* Does not include H bit; used for least significant octet only. */
-#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT)
-
-/* Build a CI from mppe opts (see RFC 3078) */
-#define MPPE_OPTS_TO_CI(opts, ci)              \
-    do {                                       \
-       u_char *ptr = ci; /* u_char[4] */       \
-                                               \
-       /* H bit */                             \
-       if (opts & MPPE_OPT_STATEFUL)           \
-           *ptr++ = 0x0;                       \
-       else                                    \
-           *ptr++ = MPPE_H_BIT;                \
-       *ptr++ = 0;                             \
-       *ptr++ = 0;                             \
-                                               \
-       /* S,L bits */                          \
-       *ptr = 0;                               \
-       if (opts & MPPE_OPT_128)                \
-           *ptr |= MPPE_S_BIT;                 \
-       if (opts & MPPE_OPT_40)                 \
-           *ptr |= MPPE_L_BIT;                 \
-       /* M,D,C bits not supported */          \
-    } while (/* CONSTCOND */ 0)
-
-/* The reverse of the above */
-#define MPPE_CI_TO_OPTS(ci, opts)              \
-    do {                                       \
-       u_char *ptr = ci; /* u_char[4] */       \
-                                               \
-       opts = 0;                               \
-                                               \
-       /* H bit */                             \
-       if (!(ptr[0] & MPPE_H_BIT))             \
-           opts |= MPPE_OPT_STATEFUL;          \
-                                               \
-       /* S,L bits */                          \
-       if (ptr[3] & MPPE_S_BIT)                \
-           opts |= MPPE_OPT_128;               \
-       if (ptr[3] & MPPE_L_BIT)                \
-           opts |= MPPE_OPT_40;                \
-                                               \
-       /* M,D,C bits */                        \
-       if (ptr[3] & MPPE_M_BIT)                \
-           opts |= MPPE_OPT_56;                \
-       if (ptr[3] & MPPE_D_BIT)                \
-           opts |= MPPE_OPT_D;                 \
-       if (ptr[3] & MPPE_C_BIT)                \
-           opts |= MPPE_OPT_MPPC;              \
-                                               \
-       /* Other bits */                        \
-       if (ptr[0] & ~MPPE_H_BIT)               \
-           opts |= MPPE_OPT_UNKNOWN;           \
-       if (ptr[1] || ptr[2])                   \
-           opts |= MPPE_OPT_UNKNOWN;           \
-       if (ptr[3] & ~MPPE_ALL_BITS)            \
-           opts |= MPPE_OPT_UNKNOWN;           \
-    } while (/* CONSTCOND */ 0)
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
deleted file mode 100644 (file)
index 736a39e..0000000
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * PPP synchronous tty channel driver for Linux.
- *
- * This is a ppp channel driver that can be used with tty device drivers
- * that are frame oriented, such as synchronous HDLC devices.
- *
- * Complete PPP frames without encoding/decoding are exchanged between
- * the channel driver and the device driver.
- *
- * The async map IOCTL codes are implemented to keep the user mode
- * applications happy if they call them. Synchronous PPP does not use
- * the async maps.
- *
- * Copyright 1999 Paul Mackerras.
- *
- * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.com
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- * This driver provides the encapsulation and framing for sending
- * and receiving PPP frames over sync serial lines.  It relies on
- * the generic PPP layer to give it frames to send and to process
- * received frames.  It implements the PPP line discipline.
- *
- * Part of the code in this driver was inspired by the old async-only
- * PPP driver, written by Michael Callahan and Al Longyear, and
- * subsequently hacked by Paul Mackerras.
- *
- * ==FILEVERSION 20040616==
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/tty.h>
-#include <linux/netdevice.h>
-#include <linux/poll.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/ppp_channel.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-#include <asm/uaccess.h>
-
-#define PPP_VERSION    "2.4.2"
-
-/* Structure for storing local state. */
-struct syncppp {
-       struct tty_struct *tty;
-       unsigned int    flags;
-       unsigned int    rbits;
-       int             mru;
-       spinlock_t      xmit_lock;
-       spinlock_t      recv_lock;
-       unsigned long   xmit_flags;
-       u32             xaccm[8];
-       u32             raccm;
-       unsigned int    bytes_sent;
-       unsigned int    bytes_rcvd;
-
-       struct sk_buff  *tpkt;
-       unsigned long   last_xmit;
-
-       struct sk_buff_head rqueue;
-
-       struct tasklet_struct tsk;
-
-       atomic_t        refcnt;
-       struct completion dead_cmp;
-       struct ppp_channel chan;        /* interface to generic ppp layer */
-};
-
-/* Bit numbers in xmit_flags */
-#define XMIT_WAKEUP    0
-#define XMIT_FULL      1
-
-/* Bits in rbits */
-#define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
-
-#define PPPSYNC_MAX_RQLEN      32      /* arbitrary */
-
-/*
- * Prototypes.
- */
-static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *);
-static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
-static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
-                         unsigned long arg);
-static void ppp_sync_process(unsigned long arg);
-static int ppp_sync_push(struct syncppp *ap);
-static void ppp_sync_flush_output(struct syncppp *ap);
-static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
-                          char *flags, int count);
-
-static const struct ppp_channel_ops sync_ops = {
-       .start_xmit = ppp_sync_send,
-       .ioctl      = ppp_sync_ioctl,
-};
-
-/*
- * Utility procedures to print a buffer in hex/ascii
- */
-static void
-ppp_print_hex (register __u8 * out, const __u8 * in, int count)
-{
-       register __u8 next_ch;
-       static const char hex[] = "0123456789ABCDEF";
-
-       while (count-- > 0) {
-               next_ch = *in++;
-               *out++ = hex[(next_ch >> 4) & 0x0F];
-               *out++ = hex[next_ch & 0x0F];
-               ++out;
-       }
-}
-
-static void
-ppp_print_char (register __u8 * out, const __u8 * in, int count)
-{
-       register __u8 next_ch;
-
-       while (count-- > 0) {
-               next_ch = *in++;
-
-               if (next_ch < 0x20 || next_ch > 0x7e)
-                       *out++ = '.';
-               else {
-                       *out++ = next_ch;
-                       if (next_ch == '%')   /* printk/syslogd has a bug !! */
-                               *out++ = '%';
-               }
-       }
-       *out = '\0';
-}
-
-static void
-ppp_print_buffer (const char *name, const __u8 *buf, int count)
-{
-       __u8 line[44];
-
-       if (name != NULL)
-               printk(KERN_DEBUG "ppp_synctty: %s, count = %d\n", name, count);
-
-       while (count > 8) {
-               memset (line, 32, 44);
-               ppp_print_hex (line, buf, 8);
-               ppp_print_char (&line[8 * 3], buf, 8);
-               printk(KERN_DEBUG "%s\n", line);
-               count -= 8;
-               buf += 8;
-       }
-
-       if (count > 0) {
-               memset (line, 32, 44);
-               ppp_print_hex (line, buf, count);
-               ppp_print_char (&line[8 * 3], buf, count);
-               printk(KERN_DEBUG "%s\n", line);
-       }
-}
-
-
-/*
- * Routines implementing the synchronous PPP line discipline.
- */
-
-/*
- * We have a potential race on dereferencing tty->disc_data,
- * because the tty layer provides no locking at all - thus one
- * cpu could be running ppp_synctty_receive while another
- * calls ppp_synctty_close, which zeroes tty->disc_data and
- * frees the memory that ppp_synctty_receive is using.  The best
- * way to fix this is to use a rwlock in the tty struct, but for now
- * we use a single global rwlock for all ttys in ppp line discipline.
- *
- * FIXME: Fixed in tty_io nowadays.
- */
-static DEFINE_RWLOCK(disc_data_lock);
-
-static struct syncppp *sp_get(struct tty_struct *tty)
-{
-       struct syncppp *ap;
-
-       read_lock(&disc_data_lock);
-       ap = tty->disc_data;
-       if (ap != NULL)
-               atomic_inc(&ap->refcnt);
-       read_unlock(&disc_data_lock);
-       return ap;
-}
-
-static void sp_put(struct syncppp *ap)
-{
-       if (atomic_dec_and_test(&ap->refcnt))
-               complete(&ap->dead_cmp);
-}
-
-/*
- * Called when a tty is put into sync-PPP line discipline.
- */
-static int
-ppp_sync_open(struct tty_struct *tty)
-{
-       struct syncppp *ap;
-       int err;
-       int speed;
-
-       if (tty->ops->write == NULL)
-               return -EOPNOTSUPP;
-
-       ap = kzalloc(sizeof(*ap), GFP_KERNEL);
-       err = -ENOMEM;
-       if (!ap)
-               goto out;
-
-       /* initialize the syncppp structure */
-       ap->tty = tty;
-       ap->mru = PPP_MRU;
-       spin_lock_init(&ap->xmit_lock);
-       spin_lock_init(&ap->recv_lock);
-       ap->xaccm[0] = ~0U;
-       ap->xaccm[3] = 0x60000000U;
-       ap->raccm = ~0U;
-
-       skb_queue_head_init(&ap->rqueue);
-       tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
-
-       atomic_set(&ap->refcnt, 1);
-       init_completion(&ap->dead_cmp);
-
-       ap->chan.private = ap;
-       ap->chan.ops = &sync_ops;
-       ap->chan.mtu = PPP_MRU;
-       ap->chan.hdrlen = 2;    /* for A/C bytes */
-       speed = tty_get_baud_rate(tty);
-       ap->chan.speed = speed;
-       err = ppp_register_channel(&ap->chan);
-       if (err)
-               goto out_free;
-
-       tty->disc_data = ap;
-       tty->receive_room = 65536;
-       return 0;
-
- out_free:
-       kfree(ap);
- out:
-       return err;
-}
-
-/*
- * Called when the tty is put into another line discipline
- * or it hangs up.  We have to wait for any cpu currently
- * executing in any of the other ppp_synctty_* routines to
- * finish before we can call ppp_unregister_channel and free
- * the syncppp struct.  This routine must be called from
- * process context, not interrupt or softirq context.
- */
-static void
-ppp_sync_close(struct tty_struct *tty)
-{
-       struct syncppp *ap;
-
-       write_lock_irq(&disc_data_lock);
-       ap = tty->disc_data;
-       tty->disc_data = NULL;
-       write_unlock_irq(&disc_data_lock);
-       if (!ap)
-               return;
-
-       /*
-        * We have now ensured that nobody can start using ap from now
-        * on, but we have to wait for all existing users to finish.
-        * Note that ppp_unregister_channel ensures that no calls to
-        * our channel ops (i.e. ppp_sync_send/ioctl) are in progress
-        * by the time it returns.
-        */
-       if (!atomic_dec_and_test(&ap->refcnt))
-               wait_for_completion(&ap->dead_cmp);
-       tasklet_kill(&ap->tsk);
-
-       ppp_unregister_channel(&ap->chan);
-       skb_queue_purge(&ap->rqueue);
-       kfree_skb(ap->tpkt);
-       kfree(ap);
-}
-
-/*
- * Called on tty hangup in process context.
- *
- * Wait for I/O to driver to complete and unregister PPP channel.
- * This is already done by the close routine, so just call that.
- */
-static int ppp_sync_hangup(struct tty_struct *tty)
-{
-       ppp_sync_close(tty);
-       return 0;
-}
-
-/*
- * Read does nothing - no data is ever available this way.
- * Pppd reads and writes packets via /dev/ppp instead.
- */
-static ssize_t
-ppp_sync_read(struct tty_struct *tty, struct file *file,
-              unsigned char __user *buf, size_t count)
-{
-       return -EAGAIN;
-}
-
-/*
- * Write on the tty does nothing, the packets all come in
- * from the ppp generic stuff.
- */
-static ssize_t
-ppp_sync_write(struct tty_struct *tty, struct file *file,
-               const unsigned char *buf, size_t count)
-{
-       return -EAGAIN;
-}
-
-static int
-ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
-                 unsigned int cmd, unsigned long arg)
-{
-       struct syncppp *ap = sp_get(tty);
-       int __user *p = (int __user *)arg;
-       int err, val;
-
-       if (!ap)
-               return -ENXIO;
-       err = -EFAULT;
-       switch (cmd) {
-       case PPPIOCGCHAN:
-               err = -EFAULT;
-               if (put_user(ppp_channel_index(&ap->chan), p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGUNIT:
-               err = -EFAULT;
-               if (put_user(ppp_unit_number(&ap->chan), p))
-                       break;
-               err = 0;
-               break;
-
-       case TCFLSH:
-               /* flush our buffers and the serial port's buffer */
-               if (arg == TCIOFLUSH || arg == TCOFLUSH)
-                       ppp_sync_flush_output(ap);
-               err = tty_perform_flush(tty, arg);
-               break;
-
-       case FIONREAD:
-               val = 0;
-               if (put_user(val, p))
-                       break;
-               err = 0;
-               break;
-
-       default:
-               err = tty_mode_ioctl(tty, file, cmd, arg);
-               break;
-       }
-
-       sp_put(ap);
-       return err;
-}
-
-/* No kernel lock - fine */
-static unsigned int
-ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
-{
-       return 0;
-}
-
-/* May sleep, don't call from interrupt level or with interrupts disabled */
-static void
-ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
-                 char *cflags, int count)
-{
-       struct syncppp *ap = sp_get(tty);
-       unsigned long flags;
-
-       if (!ap)
-               return;
-       spin_lock_irqsave(&ap->recv_lock, flags);
-       ppp_sync_input(ap, buf, cflags, count);
-       spin_unlock_irqrestore(&ap->recv_lock, flags);
-       if (!skb_queue_empty(&ap->rqueue))
-               tasklet_schedule(&ap->tsk);
-       sp_put(ap);
-       tty_unthrottle(tty);
-}
-
-static void
-ppp_sync_wakeup(struct tty_struct *tty)
-{
-       struct syncppp *ap = sp_get(tty);
-
-       clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-       if (!ap)
-               return;
-       set_bit(XMIT_WAKEUP, &ap->xmit_flags);
-       tasklet_schedule(&ap->tsk);
-       sp_put(ap);
-}
-
-
-static struct tty_ldisc_ops ppp_sync_ldisc = {
-       .owner  = THIS_MODULE,
-       .magic  = TTY_LDISC_MAGIC,
-       .name   = "pppsync",
-       .open   = ppp_sync_open,
-       .close  = ppp_sync_close,
-       .hangup = ppp_sync_hangup,
-       .read   = ppp_sync_read,
-       .write  = ppp_sync_write,
-       .ioctl  = ppp_synctty_ioctl,
-       .poll   = ppp_sync_poll,
-       .receive_buf = ppp_sync_receive,
-       .write_wakeup = ppp_sync_wakeup,
-};
-
-static int __init
-ppp_sync_init(void)
-{
-       int err;
-
-       err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc);
-       if (err != 0)
-               printk(KERN_ERR "PPP_sync: error %d registering line disc.\n",
-                      err);
-       return err;
-}
-
-/*
- * The following routines provide the PPP channel interface.
- */
-static int
-ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
-{
-       struct syncppp *ap = chan->private;
-       int err, val;
-       u32 accm[8];
-       void __user *argp = (void __user *)arg;
-       u32 __user *p = argp;
-
-       err = -EFAULT;
-       switch (cmd) {
-       case PPPIOCGFLAGS:
-               val = ap->flags | ap->rbits;
-               if (put_user(val, (int __user *) argp))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSFLAGS:
-               if (get_user(val, (int __user *) argp))
-                       break;
-               ap->flags = val & ~SC_RCV_BITS;
-               spin_lock_irq(&ap->recv_lock);
-               ap->rbits = val & SC_RCV_BITS;
-               spin_unlock_irq(&ap->recv_lock);
-               err = 0;
-               break;
-
-       case PPPIOCGASYNCMAP:
-               if (put_user(ap->xaccm[0], p))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSASYNCMAP:
-               if (get_user(ap->xaccm[0], p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGRASYNCMAP:
-               if (put_user(ap->raccm, p))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSRASYNCMAP:
-               if (get_user(ap->raccm, p))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCGXASYNCMAP:
-               if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSXASYNCMAP:
-               if (copy_from_user(accm, argp, sizeof(accm)))
-                       break;
-               accm[2] &= ~0x40000000U;        /* can't escape 0x5e */
-               accm[3] |= 0x60000000U;         /* must escape 0x7d, 0x7e */
-               memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
-               err = 0;
-               break;
-
-       case PPPIOCGMRU:
-               if (put_user(ap->mru, (int __user *) argp))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSMRU:
-               if (get_user(val, (int __user *) argp))
-                       break;
-               if (val < PPP_MRU)
-                       val = PPP_MRU;
-               ap->mru = val;
-               err = 0;
-               break;
-
-       default:
-               err = -ENOTTY;
-       }
-       return err;
-}
-
-/*
- * This is called at softirq level to deliver received packets
- * to the ppp_generic code, and to tell the ppp_generic code
- * if we can accept more output now.
- */
-static void ppp_sync_process(unsigned long arg)
-{
-       struct syncppp *ap = (struct syncppp *) arg;
-       struct sk_buff *skb;
-
-       /* process received packets */
-       while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
-               if (skb->len == 0) {
-                       /* zero length buffers indicate error */
-                       ppp_input_error(&ap->chan, 0);
-                       kfree_skb(skb);
-               }
-               else
-                       ppp_input(&ap->chan, skb);
-       }
-
-       /* try to push more stuff out */
-       if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_sync_push(ap))
-               ppp_output_wakeup(&ap->chan);
-}
-
-/*
- * Procedures for encapsulation and framing.
- */
-
-static struct sk_buff*
-ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
-{
-       int proto;
-       unsigned char *data;
-       int islcp;
-
-       data  = skb->data;
-       proto = get_unaligned_be16(data);
-
-       /* LCP packets with codes between 1 (configure-request)
-        * and 7 (code-reject) must be sent as though no options
-        * have been negotiated.
-        */
-       islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
-
-       /* compress protocol field if option enabled */
-       if (data[0] == 0 && (ap->flags & SC_COMP_PROT) && !islcp)
-               skb_pull(skb,1);
-
-       /* prepend address/control fields if necessary */
-       if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
-               if (skb_headroom(skb) < 2) {
-                       struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
-                       if (npkt == NULL) {
-                               kfree_skb(skb);
-                               return NULL;
-                       }
-                       skb_reserve(npkt,2);
-                       skb_copy_from_linear_data(skb,
-                                     skb_put(npkt, skb->len), skb->len);
-                       kfree_skb(skb);
-                       skb = npkt;
-               }
-               skb_push(skb,2);
-               skb->data[0] = PPP_ALLSTATIONS;
-               skb->data[1] = PPP_UI;
-       }
-
-       ap->last_xmit = jiffies;
-
-       if (skb && ap->flags & SC_LOG_OUTPKT)
-               ppp_print_buffer ("send buffer", skb->data, skb->len);
-
-       return skb;
-}
-
-/*
- * Transmit-side routines.
- */
-
-/*
- * Send a packet to the peer over an sync tty line.
- * Returns 1 iff the packet was accepted.
- * If the packet was not accepted, we will call ppp_output_wakeup
- * at some later time.
- */
-static int
-ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb)
-{
-       struct syncppp *ap = chan->private;
-
-       ppp_sync_push(ap);
-
-       if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
-               return 0;       /* already full */
-       skb = ppp_sync_txmunge(ap, skb);
-       if (skb != NULL)
-               ap->tpkt = skb;
-       else
-               clear_bit(XMIT_FULL, &ap->xmit_flags);
-
-       ppp_sync_push(ap);
-       return 1;
-}
-
-/*
- * Push as much data as possible out to the tty.
- */
-static int
-ppp_sync_push(struct syncppp *ap)
-{
-       int sent, done = 0;
-       struct tty_struct *tty = ap->tty;
-       int tty_stuffed = 0;
-
-       if (!spin_trylock_bh(&ap->xmit_lock))
-               return 0;
-       for (;;) {
-               if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
-                       tty_stuffed = 0;
-               if (!tty_stuffed && ap->tpkt) {
-                       set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-                       sent = tty->ops->write(tty, ap->tpkt->data, ap->tpkt->len);
-                       if (sent < 0)
-                               goto flush;     /* error, e.g. loss of CD */
-                       if (sent < ap->tpkt->len) {
-                               tty_stuffed = 1;
-                       } else {
-                               kfree_skb(ap->tpkt);
-                               ap->tpkt = NULL;
-                               clear_bit(XMIT_FULL, &ap->xmit_flags);
-                               done = 1;
-                       }
-                       continue;
-               }
-               /* haven't made any progress */
-               spin_unlock_bh(&ap->xmit_lock);
-               if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||
-                     (!tty_stuffed && ap->tpkt)))
-                       break;
-               if (!spin_trylock_bh(&ap->xmit_lock))
-                       break;
-       }
-       return done;
-
-flush:
-       if (ap->tpkt) {
-               kfree_skb(ap->tpkt);
-               ap->tpkt = NULL;
-               clear_bit(XMIT_FULL, &ap->xmit_flags);
-               done = 1;
-       }
-       spin_unlock_bh(&ap->xmit_lock);
-       return done;
-}
-
-/*
- * Flush output from our internal buffers.
- * Called for the TCFLSH ioctl.
- */
-static void
-ppp_sync_flush_output(struct syncppp *ap)
-{
-       int done = 0;
-
-       spin_lock_bh(&ap->xmit_lock);
-       if (ap->tpkt != NULL) {
-               kfree_skb(ap->tpkt);
-               ap->tpkt = NULL;
-               clear_bit(XMIT_FULL, &ap->xmit_flags);
-               done = 1;
-       }
-       spin_unlock_bh(&ap->xmit_lock);
-       if (done)
-               ppp_output_wakeup(&ap->chan);
-}
-
-/*
- * Receive-side routines.
- */
-
-/* called when the tty driver has data for us.
- *
- * Data is frame oriented: each call to ppp_sync_input is considered
- * a whole frame. If the 1st flag byte is non-zero then the whole
- * frame is considered to be in error and is tossed.
- */
-static void
-ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
-               char *flags, int count)
-{
-       struct sk_buff *skb;
-       unsigned char *p;
-
-       if (count == 0)
-               return;
-
-       if (ap->flags & SC_LOG_INPKT)
-               ppp_print_buffer ("receive buffer", buf, count);
-
-       /* stuff the chars in the skb */
-       skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
-       if (!skb) {
-               printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
-               goto err;
-       }
-       /* Try to get the payload 4-byte aligned */
-       if (buf[0] != PPP_ALLSTATIONS)
-               skb_reserve(skb, 2 + (buf[0] & 1));
-
-       if (flags && *flags) {
-               /* error flag set, ignore frame */
-               goto err;
-       } else if (count > skb_tailroom(skb)) {
-               /* packet overflowed MRU */
-               goto err;
-       }
-
-       p = skb_put(skb, count);
-       memcpy(p, buf, count);
-
-       /* strip address/control field if present */
-       p = skb->data;
-       if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
-               /* chop off address/control */
-               if (skb->len < 3)
-                       goto err;
-               p = skb_pull(skb, 2);
-       }
-
-       /* decompress protocol field if compressed */
-       if (p[0] & 1) {
-               /* protocol is compressed */
-               skb_push(skb, 1)[0] = 0;
-       } else if (skb->len < 2)
-               goto err;
-
-       /* queue the frame to be processed */
-       skb_queue_tail(&ap->rqueue, skb);
-       return;
-
-err:
-       /* queue zero length packet as error indication */
-       if (skb || (skb = dev_alloc_skb(0))) {
-               skb_trim(skb, 0);
-               skb_queue_tail(&ap->rqueue, skb);
-       }
-}
-
-static void __exit
-ppp_sync_cleanup(void)
-{
-       if (tty_unregister_ldisc(N_SYNC_PPP) != 0)
-               printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
-}
-
-module_init(ppp_sync_init);
-module_exit(ppp_sync_cleanup);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_LDISC(N_SYNC_PPP);
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
deleted file mode 100644 (file)
index bc9a4bb..0000000
+++ /dev/null
@@ -1,1208 +0,0 @@
-/** -*- linux-c -*- ***********************************************************
- * Linux PPP over Ethernet (PPPoX/PPPoE) Sockets
- *
- * PPPoX --- Generic PPP encapsulation socket family
- * PPPoE --- PPP over Ethernet (RFC 2516)
- *
- *
- * Version:    0.7.0
- *
- * 070228 :    Fix to allow multiple sessions with same remote MAC and same
- *             session id by including the local device ifindex in the
- *             tuple identifying a session. This also ensures packets can't
- *             be injected into a session from interfaces other than the one
- *             specified by userspace. Florian Zumbiehl <florz@florz.de>
- *             (Oh, BTW, this one is YYMMDD, in case you were wondering ...)
- * 220102 :    Fix module use count on failure in pppoe_create, pppox_sk -acme
- * 030700 :    Fixed connect logic to allow for disconnect.
- * 270700 :    Fixed potential SMP problems; we must protect against
- *             simultaneous invocation of ppp_input
- *             and ppp_unregister_channel.
- * 040800 :    Respect reference count mechanisms on net-devices.
- * 200800 :    fix kfree(skb) in pppoe_rcv (acme)
- *             Module reference count is decremented in the right spot now,
- *             guards against sock_put not actually freeing the sk
- *             in pppoe_release.
- * 051000 :    Initialization cleanup.
- * 111100 :    Fix recvmsg.
- * 050101 :    Fix PADT procesing.
- * 140501 :    Use pppoe_rcv_core to handle all backlog. (Alexey)
- * 170701 :    Do not lock_sock with rwlock held. (DaveM)
- *             Ignore discovery frames if user has socket
- *             locked. (DaveM)
- *             Ignore return value of dev_queue_xmit in __pppoe_xmit
- *             or else we may kfree an SKB twice. (DaveM)
- * 190701 :    When doing copies of skb's in __pppoe_xmit, always delete
- *             the original skb that was passed in on success, never on
- *             failure.  Delete the copy of the skb on failure to avoid
- *             a memory leak.
- * 081001 :    Misc. cleanup (licence string, non-blocking, prevent
- *             reference of device on close).
- * 121301 :    New ppp channels interface; cannot unregister a channel
- *             from interrupts.  Thus, we mark the socket as a ZOMBIE
- *             and do the unregistration later.
- * 081002 :    seq_file support for proc stuff -acme
- * 111602 :    Merge all 2.4 fixes into 2.5/2.6 tree.  Label 2.5/2.6
- *             as version 0.7.  Spacing cleanup.
- * Author:     Michal Ostrowski <mostrows@speakeasy.net>
- * Contributors:
- *             Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *             David S. Miller (davem@redhat.com)
- *
- * License:
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/if_ether.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_channel.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/notifier.h>
-#include <linux/file.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include <linux/nsproxy.h>
-#include <net/net_namespace.h>
-#include <net/netns/generic.h>
-#include <net/sock.h>
-
-#include <asm/uaccess.h>
-
-#define PPPOE_HASH_BITS 4
-#define PPPOE_HASH_SIZE (1 << PPPOE_HASH_BITS)
-#define PPPOE_HASH_MASK        (PPPOE_HASH_SIZE - 1)
-
-static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
-
-static const struct proto_ops pppoe_ops;
-static const struct ppp_channel_ops pppoe_chan_ops;
-
-/* per-net private data for this module */
-static int pppoe_net_id __read_mostly;
-struct pppoe_net {
-       /*
-        * we could use _single_ hash table for all
-        * nets by injecting net id into the hash but
-        * it would increase hash chains and add
-        * a few additional math comparations messy
-        * as well, moreover in case of SMP less locking
-        * controversy here
-        */
-       struct pppox_sock *hash_table[PPPOE_HASH_SIZE];
-       rwlock_t hash_lock;
-};
-
-/*
- * PPPoE could be in the following stages:
- * 1) Discovery stage (to obtain remote MAC and Session ID)
- * 2) Session stage (MAC and SID are known)
- *
- * Ethernet frames have a special tag for this but
- * we use simpler approach based on session id
- */
-static inline bool stage_session(__be16 sid)
-{
-       return sid != 0;
-}
-
-static inline struct pppoe_net *pppoe_pernet(struct net *net)
-{
-       BUG_ON(!net);
-
-       return net_generic(net, pppoe_net_id);
-}
-
-static inline int cmp_2_addr(struct pppoe_addr *a, struct pppoe_addr *b)
-{
-       return a->sid == b->sid && !memcmp(a->remote, b->remote, ETH_ALEN);
-}
-
-static inline int cmp_addr(struct pppoe_addr *a, __be16 sid, char *addr)
-{
-       return a->sid == sid && !memcmp(a->remote, addr, ETH_ALEN);
-}
-
-#if 8 % PPPOE_HASH_BITS
-#error 8 must be a multiple of PPPOE_HASH_BITS
-#endif
-
-static int hash_item(__be16 sid, unsigned char *addr)
-{
-       unsigned char hash = 0;
-       unsigned int i;
-
-       for (i = 0; i < ETH_ALEN; i++)
-               hash ^= addr[i];
-       for (i = 0; i < sizeof(sid_t) * 8; i += 8)
-               hash ^= (__force __u32)sid >> i;
-       for (i = 8; (i >>= 1) >= PPPOE_HASH_BITS;)
-               hash ^= hash >> i;
-
-       return hash & PPPOE_HASH_MASK;
-}
-
-/**********************************************************************
- *
- *  Set/get/delete/rehash items  (internal versions)
- *
- **********************************************************************/
-static struct pppox_sock *__get_item(struct pppoe_net *pn, __be16 sid,
-                               unsigned char *addr, int ifindex)
-{
-       int hash = hash_item(sid, addr);
-       struct pppox_sock *ret;
-
-       ret = pn->hash_table[hash];
-       while (ret) {
-               if (cmp_addr(&ret->pppoe_pa, sid, addr) &&
-                   ret->pppoe_ifindex == ifindex)
-                       return ret;
-
-               ret = ret->next;
-       }
-
-       return NULL;
-}
-
-static int __set_item(struct pppoe_net *pn, struct pppox_sock *po)
-{
-       int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
-       struct pppox_sock *ret;
-
-       ret = pn->hash_table[hash];
-       while (ret) {
-               if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) &&
-                   ret->pppoe_ifindex == po->pppoe_ifindex)
-                       return -EALREADY;
-
-               ret = ret->next;
-       }
-
-       po->next = pn->hash_table[hash];
-       pn->hash_table[hash] = po;
-
-       return 0;
-}
-
-static struct pppox_sock *__delete_item(struct pppoe_net *pn, __be16 sid,
-                                       char *addr, int ifindex)
-{
-       int hash = hash_item(sid, addr);
-       struct pppox_sock *ret, **src;
-
-       ret = pn->hash_table[hash];
-       src = &pn->hash_table[hash];
-
-       while (ret) {
-               if (cmp_addr(&ret->pppoe_pa, sid, addr) &&
-                   ret->pppoe_ifindex == ifindex) {
-                       *src = ret->next;
-                       break;
-               }
-
-               src = &ret->next;
-               ret = ret->next;
-       }
-
-       return ret;
-}
-
-/**********************************************************************
- *
- *  Set/get/delete/rehash items
- *
- **********************************************************************/
-static inline struct pppox_sock *get_item(struct pppoe_net *pn, __be16 sid,
-                                       unsigned char *addr, int ifindex)
-{
-       struct pppox_sock *po;
-
-       read_lock_bh(&pn->hash_lock);
-       po = __get_item(pn, sid, addr, ifindex);
-       if (po)
-               sock_hold(sk_pppox(po));
-       read_unlock_bh(&pn->hash_lock);
-
-       return po;
-}
-
-static inline struct pppox_sock *get_item_by_addr(struct net *net,
-                                               struct sockaddr_pppox *sp)
-{
-       struct net_device *dev;
-       struct pppoe_net *pn;
-       struct pppox_sock *pppox_sock = NULL;
-
-       int ifindex;
-
-       rcu_read_lock();
-       dev = dev_get_by_name_rcu(net, sp->sa_addr.pppoe.dev);
-       if (dev) {
-               ifindex = dev->ifindex;
-               pn = pppoe_pernet(net);
-               pppox_sock = get_item(pn, sp->sa_addr.pppoe.sid,
-                               sp->sa_addr.pppoe.remote, ifindex);
-       }
-       rcu_read_unlock();
-       return pppox_sock;
-}
-
-static inline struct pppox_sock *delete_item(struct pppoe_net *pn, __be16 sid,
-                                       char *addr, int ifindex)
-{
-       struct pppox_sock *ret;
-
-       write_lock_bh(&pn->hash_lock);
-       ret = __delete_item(pn, sid, addr, ifindex);
-       write_unlock_bh(&pn->hash_lock);
-
-       return ret;
-}
-
-/***************************************************************************
- *
- *  Handler for device events.
- *  Certain device events require that sockets be unconnected.
- *
- **************************************************************************/
-
-static void pppoe_flush_dev(struct net_device *dev)
-{
-       struct pppoe_net *pn;
-       int i;
-
-       pn = pppoe_pernet(dev_net(dev));
-       write_lock_bh(&pn->hash_lock);
-       for (i = 0; i < PPPOE_HASH_SIZE; i++) {
-               struct pppox_sock *po = pn->hash_table[i];
-               struct sock *sk;
-
-               while (po) {
-                       while (po && po->pppoe_dev != dev) {
-                               po = po->next;
-                       }
-
-                       if (!po)
-                               break;
-
-                       sk = sk_pppox(po);
-
-                       /* We always grab the socket lock, followed by the
-                        * hash_lock, in that order.  Since we should hold the
-                        * sock lock while doing any unbinding, we need to
-                        * release the lock we're holding.  Hold a reference to
-                        * the sock so it doesn't disappear as we're jumping
-                        * between locks.
-                        */
-
-                       sock_hold(sk);
-                       write_unlock_bh(&pn->hash_lock);
-                       lock_sock(sk);
-
-                       if (po->pppoe_dev == dev &&
-                           sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
-                               pppox_unbind_sock(sk);
-                               sk->sk_state = PPPOX_ZOMBIE;
-                               sk->sk_state_change(sk);
-                               po->pppoe_dev = NULL;
-                               dev_put(dev);
-                       }
-
-                       release_sock(sk);
-                       sock_put(sk);
-
-                       /* Restart the process from the start of the current
-                        * hash chain. We dropped locks so the world may have
-                        * change from underneath us.
-                        */
-
-                       BUG_ON(pppoe_pernet(dev_net(dev)) == NULL);
-                       write_lock_bh(&pn->hash_lock);
-                       po = pn->hash_table[i];
-               }
-       }
-       write_unlock_bh(&pn->hash_lock);
-}
-
-static int pppoe_device_event(struct notifier_block *this,
-                             unsigned long event, void *ptr)
-{
-       struct net_device *dev = (struct net_device *)ptr;
-
-       /* Only look at sockets that are using this specific device. */
-       switch (event) {
-       case NETDEV_CHANGEADDR:
-       case NETDEV_CHANGEMTU:
-               /* A change in mtu or address is a bad thing, requiring
-                * LCP re-negotiation.
-                */
-
-       case NETDEV_GOING_DOWN:
-       case NETDEV_DOWN:
-               /* Find every socket on this device and kill it. */
-               pppoe_flush_dev(dev);
-               break;
-
-       default:
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block pppoe_notifier = {
-       .notifier_call = pppoe_device_event,
-};
-
-/************************************************************************
- *
- * Do the real work of receiving a PPPoE Session frame.
- *
- ***********************************************************************/
-static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
-{
-       struct pppox_sock *po = pppox_sk(sk);
-       struct pppox_sock *relay_po;
-
-       /* Backlog receive. Semantics of backlog rcv preclude any code from
-        * executing in lock_sock()/release_sock() bounds; meaning sk->sk_state
-        * can't change.
-        */
-
-       if (sk->sk_state & PPPOX_BOUND) {
-               ppp_input(&po->chan, skb);
-       } else if (sk->sk_state & PPPOX_RELAY) {
-               relay_po = get_item_by_addr(sock_net(sk),
-                                           &po->pppoe_relay);
-               if (relay_po == NULL)
-                       goto abort_kfree;
-
-               if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0)
-                       goto abort_put;
-
-               if (!__pppoe_xmit(sk_pppox(relay_po), skb))
-                       goto abort_put;
-       } else {
-               if (sock_queue_rcv_skb(sk, skb))
-                       goto abort_kfree;
-       }
-
-       return NET_RX_SUCCESS;
-
-abort_put:
-       sock_put(sk_pppox(relay_po));
-
-abort_kfree:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-/************************************************************************
- *
- * Receive wrapper called in BH context.
- *
- ***********************************************************************/
-static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
-                    struct packet_type *pt, struct net_device *orig_dev)
-{
-       struct pppoe_hdr *ph;
-       struct pppox_sock *po;
-       struct pppoe_net *pn;
-       int len;
-
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (!skb)
-               goto out;
-
-       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
-               goto drop;
-
-       ph = pppoe_hdr(skb);
-       len = ntohs(ph->length);
-
-       skb_pull_rcsum(skb, sizeof(*ph));
-       if (skb->len < len)
-               goto drop;
-
-       if (pskb_trim_rcsum(skb, len))
-               goto drop;
-
-       pn = pppoe_pernet(dev_net(dev));
-
-       /* Note that get_item does a sock_hold(), so sk_pppox(po)
-        * is known to be safe.
-        */
-       po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
-       if (!po)
-               goto drop;
-
-       return sk_receive_skb(sk_pppox(po), skb, 0);
-
-drop:
-       kfree_skb(skb);
-out:
-       return NET_RX_DROP;
-}
-
-/************************************************************************
- *
- * Receive a PPPoE Discovery frame.
- * This is solely for detection of PADT frames
- *
- ***********************************************************************/
-static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev,
-                         struct packet_type *pt, struct net_device *orig_dev)
-
-{
-       struct pppoe_hdr *ph;
-       struct pppox_sock *po;
-       struct pppoe_net *pn;
-
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (!skb)
-               goto out;
-
-       if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
-               goto abort;
-
-       ph = pppoe_hdr(skb);
-       if (ph->code != PADT_CODE)
-               goto abort;
-
-       pn = pppoe_pernet(dev_net(dev));
-       po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
-       if (po) {
-               struct sock *sk = sk_pppox(po);
-
-               bh_lock_sock(sk);
-
-               /* If the user has locked the socket, just ignore
-                * the packet.  With the way two rcv protocols hook into
-                * one socket family type, we cannot (easily) distinguish
-                * what kind of SKB it is during backlog rcv.
-                */
-               if (sock_owned_by_user(sk) == 0) {
-                       /* We're no longer connect at the PPPOE layer,
-                        * and must wait for ppp channel to disconnect us.
-                        */
-                       sk->sk_state = PPPOX_ZOMBIE;
-               }
-
-               bh_unlock_sock(sk);
-               sock_put(sk);
-       }
-
-abort:
-       kfree_skb(skb);
-out:
-       return NET_RX_SUCCESS; /* Lies... :-) */
-}
-
-static struct packet_type pppoes_ptype __read_mostly = {
-       .type   = cpu_to_be16(ETH_P_PPP_SES),
-       .func   = pppoe_rcv,
-};
-
-static struct packet_type pppoed_ptype __read_mostly = {
-       .type   = cpu_to_be16(ETH_P_PPP_DISC),
-       .func   = pppoe_disc_rcv,
-};
-
-static struct proto pppoe_sk_proto __read_mostly = {
-       .name     = "PPPOE",
-       .owner    = THIS_MODULE,
-       .obj_size = sizeof(struct pppox_sock),
-};
-
-/***********************************************************************
- *
- * Initialize a new struct sock.
- *
- **********************************************************************/
-static int pppoe_create(struct net *net, struct socket *sock)
-{
-       struct sock *sk;
-
-       sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto);
-       if (!sk)
-               return -ENOMEM;
-
-       sock_init_data(sock, sk);
-
-       sock->state     = SS_UNCONNECTED;
-       sock->ops       = &pppoe_ops;
-
-       sk->sk_backlog_rcv      = pppoe_rcv_core;
-       sk->sk_state            = PPPOX_NONE;
-       sk->sk_type             = SOCK_STREAM;
-       sk->sk_family           = PF_PPPOX;
-       sk->sk_protocol         = PX_PROTO_OE;
-
-       return 0;
-}
-
-static int pppoe_release(struct socket *sock)
-{
-       struct sock *sk = sock->sk;
-       struct pppox_sock *po;
-       struct pppoe_net *pn;
-       struct net *net = NULL;
-
-       if (!sk)
-               return 0;
-
-       lock_sock(sk);
-       if (sock_flag(sk, SOCK_DEAD)) {
-               release_sock(sk);
-               return -EBADF;
-       }
-
-       po = pppox_sk(sk);
-
-       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
-               dev_put(po->pppoe_dev);
-               po->pppoe_dev = NULL;
-       }
-
-       pppox_unbind_sock(sk);
-
-       /* Signal the death of the socket. */
-       sk->sk_state = PPPOX_DEAD;
-
-       net = sock_net(sk);
-       pn = pppoe_pernet(net);
-
-       /*
-        * protect "po" from concurrent updates
-        * on pppoe_flush_dev
-        */
-       delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
-                   po->pppoe_ifindex);
-
-       sock_orphan(sk);
-       sock->sk = NULL;
-
-       skb_queue_purge(&sk->sk_receive_queue);
-       release_sock(sk);
-       sock_put(sk);
-
-       return 0;
-}
-
-static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
-                 int sockaddr_len, int flags)
-{
-       struct sock *sk = sock->sk;
-       struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr;
-       struct pppox_sock *po = pppox_sk(sk);
-       struct net_device *dev = NULL;
-       struct pppoe_net *pn;
-       struct net *net = NULL;
-       int error;
-
-       lock_sock(sk);
-
-       error = -EINVAL;
-       if (sp->sa_protocol != PX_PROTO_OE)
-               goto end;
-
-       /* Check for already bound sockets */
-       error = -EBUSY;
-       if ((sk->sk_state & PPPOX_CONNECTED) &&
-            stage_session(sp->sa_addr.pppoe.sid))
-               goto end;
-
-       /* Check for already disconnected sockets, on attempts to disconnect */
-       error = -EALREADY;
-       if ((sk->sk_state & PPPOX_DEAD) &&
-            !stage_session(sp->sa_addr.pppoe.sid))
-               goto end;
-
-       error = 0;
-
-       /* Delete the old binding */
-       if (stage_session(po->pppoe_pa.sid)) {
-               pppox_unbind_sock(sk);
-               pn = pppoe_pernet(sock_net(sk));
-               delete_item(pn, po->pppoe_pa.sid,
-                           po->pppoe_pa.remote, po->pppoe_ifindex);
-               if (po->pppoe_dev) {
-                       dev_put(po->pppoe_dev);
-                       po->pppoe_dev = NULL;
-               }
-
-               memset(sk_pppox(po) + 1, 0,
-                      sizeof(struct pppox_sock) - sizeof(struct sock));
-               sk->sk_state = PPPOX_NONE;
-       }
-
-       /* Re-bind in session stage only */
-       if (stage_session(sp->sa_addr.pppoe.sid)) {
-               error = -ENODEV;
-               net = sock_net(sk);
-               dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev);
-               if (!dev)
-                       goto err_put;
-
-               po->pppoe_dev = dev;
-               po->pppoe_ifindex = dev->ifindex;
-               pn = pppoe_pernet(net);
-               if (!(dev->flags & IFF_UP)) {
-                       goto err_put;
-               }
-
-               memcpy(&po->pppoe_pa,
-                      &sp->sa_addr.pppoe,
-                      sizeof(struct pppoe_addr));
-
-               write_lock_bh(&pn->hash_lock);
-               error = __set_item(pn, po);
-               write_unlock_bh(&pn->hash_lock);
-               if (error < 0)
-                       goto err_put;
-
-               po->chan.hdrlen = (sizeof(struct pppoe_hdr) +
-                                  dev->hard_header_len);
-
-               po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr);
-               po->chan.private = sk;
-               po->chan.ops = &pppoe_chan_ops;
-
-               error = ppp_register_net_channel(dev_net(dev), &po->chan);
-               if (error) {
-                       delete_item(pn, po->pppoe_pa.sid,
-                                   po->pppoe_pa.remote, po->pppoe_ifindex);
-                       goto err_put;
-               }
-
-               sk->sk_state = PPPOX_CONNECTED;
-       }
-
-       po->num = sp->sa_addr.pppoe.sid;
-
-end:
-       release_sock(sk);
-       return error;
-err_put:
-       if (po->pppoe_dev) {
-               dev_put(po->pppoe_dev);
-               po->pppoe_dev = NULL;
-       }
-       goto end;
-}
-
-static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr,
-                 int *usockaddr_len, int peer)
-{
-       int len = sizeof(struct sockaddr_pppox);
-       struct sockaddr_pppox sp;
-
-       sp.sa_family    = AF_PPPOX;
-       sp.sa_protocol  = PX_PROTO_OE;
-       memcpy(&sp.sa_addr.pppoe, &pppox_sk(sock->sk)->pppoe_pa,
-              sizeof(struct pppoe_addr));
-
-       memcpy(uaddr, &sp, len);
-
-       *usockaddr_len = len;
-
-       return 0;
-}
-
-static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
-               unsigned long arg)
-{
-       struct sock *sk = sock->sk;
-       struct pppox_sock *po = pppox_sk(sk);
-       int val;
-       int err;
-
-       switch (cmd) {
-       case PPPIOCGMRU:
-               err = -ENXIO;
-               if (!(sk->sk_state & PPPOX_CONNECTED))
-                       break;
-
-               err = -EFAULT;
-               if (put_user(po->pppoe_dev->mtu -
-                            sizeof(struct pppoe_hdr) -
-                            PPP_HDRLEN,
-                            (int __user *)arg))
-                       break;
-               err = 0;
-               break;
-
-       case PPPIOCSMRU:
-               err = -ENXIO;
-               if (!(sk->sk_state & PPPOX_CONNECTED))
-                       break;
-
-               err = -EFAULT;
-               if (get_user(val, (int __user *)arg))
-                       break;
-
-               if (val < (po->pppoe_dev->mtu
-                          - sizeof(struct pppoe_hdr)
-                          - PPP_HDRLEN))
-                       err = 0;
-               else
-                       err = -EINVAL;
-               break;
-
-       case PPPIOCSFLAGS:
-               err = -EFAULT;
-               if (get_user(val, (int __user *)arg))
-                       break;
-               err = 0;
-               break;
-
-       case PPPOEIOCSFWD:
-       {
-               struct pppox_sock *relay_po;
-
-               err = -EBUSY;
-               if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD))
-                       break;
-
-               err = -ENOTCONN;
-               if (!(sk->sk_state & PPPOX_CONNECTED))
-                       break;
-
-               /* PPPoE address from the user specifies an outbound
-                  PPPoE address which frames are forwarded to */
-               err = -EFAULT;
-               if (copy_from_user(&po->pppoe_relay,
-                                  (void __user *)arg,
-                                  sizeof(struct sockaddr_pppox)))
-                       break;
-
-               err = -EINVAL;
-               if (po->pppoe_relay.sa_family != AF_PPPOX ||
-                   po->pppoe_relay.sa_protocol != PX_PROTO_OE)
-                       break;
-
-               /* Check that the socket referenced by the address
-                  actually exists. */
-               relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay);
-               if (!relay_po)
-                       break;
-
-               sock_put(sk_pppox(relay_po));
-               sk->sk_state |= PPPOX_RELAY;
-               err = 0;
-               break;
-       }
-
-       case PPPOEIOCDFWD:
-               err = -EALREADY;
-               if (!(sk->sk_state & PPPOX_RELAY))
-                       break;
-
-               sk->sk_state &= ~PPPOX_RELAY;
-               err = 0;
-               break;
-
-       default:
-               err = -ENOTTY;
-       }
-
-       return err;
-}
-
-static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
-                 struct msghdr *m, size_t total_len)
-{
-       struct sk_buff *skb;
-       struct sock *sk = sock->sk;
-       struct pppox_sock *po = pppox_sk(sk);
-       int error;
-       struct pppoe_hdr hdr;
-       struct pppoe_hdr *ph;
-       struct net_device *dev;
-       char *start;
-
-       lock_sock(sk);
-       if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) {
-               error = -ENOTCONN;
-               goto end;
-       }
-
-       hdr.ver = 1;
-       hdr.type = 1;
-       hdr.code = 0;
-       hdr.sid = po->num;
-
-       dev = po->pppoe_dev;
-
-       error = -EMSGSIZE;
-       if (total_len > (dev->mtu + dev->hard_header_len))
-               goto end;
-
-
-       skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
-                          0, GFP_KERNEL);
-       if (!skb) {
-               error = -ENOMEM;
-               goto end;
-       }
-
-       /* Reserve space for headers. */
-       skb_reserve(skb, dev->hard_header_len);
-       skb_reset_network_header(skb);
-
-       skb->dev = dev;
-
-       skb->priority = sk->sk_priority;
-       skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
-
-       ph = (struct pppoe_hdr *)skb_put(skb, total_len + sizeof(struct pppoe_hdr));
-       start = (char *)&ph->tag[0];
-
-       error = memcpy_fromiovec(start, m->msg_iov, total_len);
-       if (error < 0) {
-               kfree_skb(skb);
-               goto end;
-       }
-
-       error = total_len;
-       dev_hard_header(skb, dev, ETH_P_PPP_SES,
-                       po->pppoe_pa.remote, NULL, total_len);
-
-       memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
-
-       ph->length = htons(total_len);
-
-       dev_queue_xmit(skb);
-
-end:
-       release_sock(sk);
-       return error;
-}
-
-/************************************************************************
- *
- * xmit function for internal use.
- *
- ***********************************************************************/
-static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
-{
-       struct pppox_sock *po = pppox_sk(sk);
-       struct net_device *dev = po->pppoe_dev;
-       struct pppoe_hdr *ph;
-       int data_len = skb->len;
-
-       /* The higher-level PPP code (ppp_unregister_channel()) ensures the PPP
-        * xmit operations conclude prior to an unregistration call.  Thus
-        * sk->sk_state cannot change, so we don't need to do lock_sock().
-        * But, we also can't do a lock_sock since that introduces a potential
-        * deadlock as we'd reverse the lock ordering used when calling
-        * ppp_unregister_channel().
-        */
-
-       if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
-               goto abort;
-
-       if (!dev)
-               goto abort;
-
-       /* Copy the data if there is no space for the header or if it's
-        * read-only.
-        */
-       if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len))
-               goto abort;
-
-       __skb_push(skb, sizeof(*ph));
-       skb_reset_network_header(skb);
-
-       ph = pppoe_hdr(skb);
-       ph->ver = 1;
-       ph->type = 1;
-       ph->code = 0;
-       ph->sid = po->num;
-       ph->length = htons(data_len);
-
-       skb->protocol = cpu_to_be16(ETH_P_PPP_SES);
-       skb->dev = dev;
-
-       dev_hard_header(skb, dev, ETH_P_PPP_SES,
-                       po->pppoe_pa.remote, NULL, data_len);
-
-       dev_queue_xmit(skb);
-       return 1;
-
-abort:
-       kfree_skb(skb);
-       return 1;
-}
-
-/************************************************************************
- *
- * xmit function called by generic PPP driver
- * sends PPP frame over PPPoE socket
- *
- ***********************************************************************/
-static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
-{
-       struct sock *sk = (struct sock *)chan->private;
-       return __pppoe_xmit(sk, skb);
-}
-
-static const struct ppp_channel_ops pppoe_chan_ops = {
-       .start_xmit = pppoe_xmit,
-};
-
-static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
-                 struct msghdr *m, size_t total_len, int flags)
-{
-       struct sock *sk = sock->sk;
-       struct sk_buff *skb;
-       int error = 0;
-
-       if (sk->sk_state & PPPOX_BOUND) {
-               error = -EIO;
-               goto end;
-       }
-
-       skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
-                               flags & MSG_DONTWAIT, &error);
-       if (error < 0)
-               goto end;
-
-       m->msg_namelen = 0;
-
-       if (skb) {
-               total_len = min_t(size_t, total_len, skb->len);
-               error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
-               if (error == 0)
-                       error = total_len;
-       }
-
-       kfree_skb(skb);
-end:
-       return error;
-}
-
-#ifdef CONFIG_PROC_FS
-static int pppoe_seq_show(struct seq_file *seq, void *v)
-{
-       struct pppox_sock *po;
-       char *dev_name;
-
-       if (v == SEQ_START_TOKEN) {
-               seq_puts(seq, "Id       Address              Device\n");
-               goto out;
-       }
-
-       po = v;
-       dev_name = po->pppoe_pa.dev;
-
-       seq_printf(seq, "%08X %pM %8s\n",
-               po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name);
-out:
-       return 0;
-}
-
-static inline struct pppox_sock *pppoe_get_idx(struct pppoe_net *pn, loff_t pos)
-{
-       struct pppox_sock *po;
-       int i;
-
-       for (i = 0; i < PPPOE_HASH_SIZE; i++) {
-               po = pn->hash_table[i];
-               while (po) {
-                       if (!pos--)
-                               goto out;
-                       po = po->next;
-               }
-       }
-
-out:
-       return po;
-}
-
-static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(pn->hash_lock)
-{
-       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
-       loff_t l = *pos;
-
-       read_lock_bh(&pn->hash_lock);
-       return l ? pppoe_get_idx(pn, --l) : SEQ_START_TOKEN;
-}
-
-static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
-       struct pppox_sock *po;
-
-       ++*pos;
-       if (v == SEQ_START_TOKEN) {
-               po = pppoe_get_idx(pn, 0);
-               goto out;
-       }
-       po = v;
-       if (po->next)
-               po = po->next;
-       else {
-               int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
-
-               po = NULL;
-               while (++hash < PPPOE_HASH_SIZE) {
-                       po = pn->hash_table[hash];
-                       if (po)
-                               break;
-               }
-       }
-
-out:
-       return po;
-}
-
-static void pppoe_seq_stop(struct seq_file *seq, void *v)
-       __releases(pn->hash_lock)
-{
-       struct pppoe_net *pn = pppoe_pernet(seq_file_net(seq));
-       read_unlock_bh(&pn->hash_lock);
-}
-
-static const struct seq_operations pppoe_seq_ops = {
-       .start          = pppoe_seq_start,
-       .next           = pppoe_seq_next,
-       .stop           = pppoe_seq_stop,
-       .show           = pppoe_seq_show,
-};
-
-static int pppoe_seq_open(struct inode *inode, struct file *file)
-{
-       return seq_open_net(inode, file, &pppoe_seq_ops,
-                       sizeof(struct seq_net_private));
-}
-
-static const struct file_operations pppoe_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pppoe_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release_net,
-};
-
-#endif /* CONFIG_PROC_FS */
-
-static const struct proto_ops pppoe_ops = {
-       .family         = AF_PPPOX,
-       .owner          = THIS_MODULE,
-       .release        = pppoe_release,
-       .bind           = sock_no_bind,
-       .connect        = pppoe_connect,
-       .socketpair     = sock_no_socketpair,
-       .accept         = sock_no_accept,
-       .getname        = pppoe_getname,
-       .poll           = datagram_poll,
-       .listen         = sock_no_listen,
-       .shutdown       = sock_no_shutdown,
-       .setsockopt     = sock_no_setsockopt,
-       .getsockopt     = sock_no_getsockopt,
-       .sendmsg        = pppoe_sendmsg,
-       .recvmsg        = pppoe_recvmsg,
-       .mmap           = sock_no_mmap,
-       .ioctl          = pppox_ioctl,
-};
-
-static const struct pppox_proto pppoe_proto = {
-       .create = pppoe_create,
-       .ioctl  = pppoe_ioctl,
-       .owner  = THIS_MODULE,
-};
-
-static __net_init int pppoe_init_net(struct net *net)
-{
-       struct pppoe_net *pn = pppoe_pernet(net);
-       struct proc_dir_entry *pde;
-
-       rwlock_init(&pn->hash_lock);
-
-       pde = proc_net_fops_create(net, "pppoe", S_IRUGO, &pppoe_seq_fops);
-#ifdef CONFIG_PROC_FS
-       if (!pde)
-               return -ENOMEM;
-#endif
-
-       return 0;
-}
-
-static __net_exit void pppoe_exit_net(struct net *net)
-{
-       proc_net_remove(net, "pppoe");
-}
-
-static struct pernet_operations pppoe_net_ops = {
-       .init = pppoe_init_net,
-       .exit = pppoe_exit_net,
-       .id   = &pppoe_net_id,
-       .size = sizeof(struct pppoe_net),
-};
-
-static int __init pppoe_init(void)
-{
-       int err;
-
-       err = register_pernet_device(&pppoe_net_ops);
-       if (err)
-               goto out;
-
-       err = proto_register(&pppoe_sk_proto, 0);
-       if (err)
-               goto out_unregister_net_ops;
-
-       err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
-       if (err)
-               goto out_unregister_pppoe_proto;
-
-       dev_add_pack(&pppoes_ptype);
-       dev_add_pack(&pppoed_ptype);
-       register_netdevice_notifier(&pppoe_notifier);
-
-       return 0;
-
-out_unregister_pppoe_proto:
-       proto_unregister(&pppoe_sk_proto);
-out_unregister_net_ops:
-       unregister_pernet_device(&pppoe_net_ops);
-out:
-       return err;
-}
-
-static void __exit pppoe_exit(void)
-{
-       unregister_netdevice_notifier(&pppoe_notifier);
-       dev_remove_pack(&pppoed_ptype);
-       dev_remove_pack(&pppoes_ptype);
-       unregister_pppox_proto(PX_PROTO_OE);
-       proto_unregister(&pppoe_sk_proto);
-       unregister_pernet_device(&pppoe_net_ops);
-}
-
-module_init(pppoe_init);
-module_exit(pppoe_exit);
-
-MODULE_AUTHOR("Michal Ostrowski <mostrows@speakeasy.net>");
-MODULE_DESCRIPTION("PPP over Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_NETPROTO(PF_PPPOX);
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
deleted file mode 100644 (file)
index 8c0d170..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/** -*- linux-c -*- ***********************************************************
- * Linux PPP over X/Ethernet (PPPoX/PPPoE) Sockets
- *
- * PPPoX --- Generic PPP encapsulation socket family
- * PPPoE --- PPP over Ethernet (RFC 2516)
- *
- *
- * Version:    0.5.2
- *
- * Author:     Michal Ostrowski <mostrows@speakeasy.net>
- *
- * 051000 :    Initialization cleanup
- *
- * License:
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/init.h>
-#include <linux/if_pppox.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_ppp.h>
-#include <linux/ppp_channel.h>
-#include <linux/kmod.h>
-
-#include <net/sock.h>
-
-#include <asm/uaccess.h>
-
-static const struct pppox_proto *pppox_protos[PX_MAX_PROTO + 1];
-
-int register_pppox_proto(int proto_num, const struct pppox_proto *pp)
-{
-       if (proto_num < 0 || proto_num > PX_MAX_PROTO)
-               return -EINVAL;
-       if (pppox_protos[proto_num])
-               return -EALREADY;
-       pppox_protos[proto_num] = pp;
-       return 0;
-}
-
-void unregister_pppox_proto(int proto_num)
-{
-       if (proto_num >= 0 && proto_num <= PX_MAX_PROTO)
-               pppox_protos[proto_num] = NULL;
-}
-
-void pppox_unbind_sock(struct sock *sk)
-{
-       /* Clear connection to ppp device, if attached. */
-
-       if (sk->sk_state & (PPPOX_BOUND | PPPOX_CONNECTED | PPPOX_ZOMBIE)) {
-               ppp_unregister_channel(&pppox_sk(sk)->chan);
-               sk->sk_state = PPPOX_DEAD;
-       }
-}
-
-EXPORT_SYMBOL(register_pppox_proto);
-EXPORT_SYMBOL(unregister_pppox_proto);
-EXPORT_SYMBOL(pppox_unbind_sock);
-
-int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       struct sock *sk = sock->sk;
-       struct pppox_sock *po = pppox_sk(sk);
-       int rc;
-
-       lock_sock(sk);
-
-       switch (cmd) {
-       case PPPIOCGCHAN: {
-               int index;
-               rc = -ENOTCONN;
-               if (!(sk->sk_state & PPPOX_CONNECTED))
-                       break;
-
-               rc = -EINVAL;
-               index = ppp_channel_index(&po->chan);
-               if (put_user(index , (int __user *) arg))
-                       break;
-
-               rc = 0;
-               sk->sk_state |= PPPOX_BOUND;
-               break;
-       }
-       default:
-               rc = pppox_protos[sk->sk_protocol]->ioctl ?
-                       pppox_protos[sk->sk_protocol]->ioctl(sock, cmd, arg) : -ENOTTY;
-       }
-
-       release_sock(sk);
-       return rc;
-}
-
-EXPORT_SYMBOL(pppox_ioctl);
-
-static int pppox_create(struct net *net, struct socket *sock, int protocol,
-                       int kern)
-{
-       int rc = -EPROTOTYPE;
-
-       if (protocol < 0 || protocol > PX_MAX_PROTO)
-               goto out;
-
-       rc = -EPROTONOSUPPORT;
-       if (!pppox_protos[protocol])
-               request_module("pppox-proto-%d", protocol);
-       if (!pppox_protos[protocol] ||
-           !try_module_get(pppox_protos[protocol]->owner))
-               goto out;
-
-       rc = pppox_protos[protocol]->create(net, sock);
-
-       module_put(pppox_protos[protocol]->owner);
-out:
-       return rc;
-}
-
-static const struct net_proto_family pppox_proto_family = {
-       .family = PF_PPPOX,
-       .create = pppox_create,
-       .owner  = THIS_MODULE,
-};
-
-static int __init pppox_init(void)
-{
-       return sock_register(&pppox_proto_family);
-}
-
-static void __exit pppox_exit(void)
-{
-       sock_unregister(PF_PPPOX);
-}
-
-module_init(pppox_init);
-module_exit(pppox_exit);
-
-MODULE_AUTHOR("Michal Ostrowski <mostrows@speakeasy.net>");
-MODULE_DESCRIPTION("PPP over Ethernet driver (generic socket layer)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
deleted file mode 100644 (file)
index eae542a..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- *  Point-to-Point Tunneling Protocol for Linux
- *
- *     Authors: Dmitry Kozlov <xeb@mail.ru>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/net.h>
-#include <linux/skbuff.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/ppp_channel.h>
-#include <linux/ppp_defs.h>
-#include <linux/if_pppox.h>
-#include <linux/if_ppp.h>
-#include <linux/notifier.h>
-#include <linux/file.h>
-#include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter_ipv4.h>
-#include <linux/rcupdate.h>
-#include <linux/spinlock.h>
-
-#include <net/sock.h>
-#include <net/protocol.h>
-#include <net/ip.h>
-#include <net/icmp.h>
-#include <net/route.h>
-#include <net/gre.h>
-
-#include <linux/uaccess.h>
-
-#define PPTP_DRIVER_VERSION "0.8.5"
-
-#define MAX_CALLID 65535
-
-static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
-static struct pppox_sock **callid_sock;
-
-static DEFINE_SPINLOCK(chan_lock);
-
-static struct proto pptp_sk_proto __read_mostly;
-static const struct ppp_channel_ops pptp_chan_ops;
-static const struct proto_ops pptp_ops;
-
-#define PPP_LCP_ECHOREQ 0x09
-#define PPP_LCP_ECHOREP 0x0A
-#define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
-
-#define MISSING_WINDOW 20
-#define WRAPPED(curseq, lastseq)\
-       ((((curseq) & 0xffffff00) == 0) &&\
-       (((lastseq) & 0xffffff00) == 0xffffff00))
-
-#define PPTP_GRE_PROTO  0x880B
-#define PPTP_GRE_VER    0x1
-
-#define PPTP_GRE_FLAG_C        0x80
-#define PPTP_GRE_FLAG_R        0x40
-#define PPTP_GRE_FLAG_K        0x20
-#define PPTP_GRE_FLAG_S        0x10
-#define PPTP_GRE_FLAG_A        0x80
-
-#define PPTP_GRE_IS_C(f) ((f)&PPTP_GRE_FLAG_C)
-#define PPTP_GRE_IS_R(f) ((f)&PPTP_GRE_FLAG_R)
-#define PPTP_GRE_IS_K(f) ((f)&PPTP_GRE_FLAG_K)
-#define PPTP_GRE_IS_S(f) ((f)&PPTP_GRE_FLAG_S)
-#define PPTP_GRE_IS_A(f) ((f)&PPTP_GRE_FLAG_A)
-
-#define PPTP_HEADER_OVERHEAD (2+sizeof(struct pptp_gre_header))
-struct pptp_gre_header {
-       u8  flags;
-       u8  ver;
-       u16 protocol;
-       u16 payload_len;
-       u16 call_id;
-       u32 seq;
-       u32 ack;
-} __packed;
-
-static struct pppox_sock *lookup_chan(u16 call_id, __be32 s_addr)
-{
-       struct pppox_sock *sock;
-       struct pptp_opt *opt;
-
-       rcu_read_lock();
-       sock = rcu_dereference(callid_sock[call_id]);
-       if (sock) {
-               opt = &sock->proto.pptp;
-               if (opt->dst_addr.sin_addr.s_addr != s_addr)
-                       sock = NULL;
-               else
-                       sock_hold(sk_pppox(sock));
-       }
-       rcu_read_unlock();
-
-       return sock;
-}
-
-static int lookup_chan_dst(u16 call_id, __be32 d_addr)
-{
-       struct pppox_sock *sock;
-       struct pptp_opt *opt;
-       int i;
-
-       rcu_read_lock();
-       for (i = find_next_bit(callid_bitmap, MAX_CALLID, 1); i < MAX_CALLID;
-            i = find_next_bit(callid_bitmap, MAX_CALLID, i + 1)) {
-               sock = rcu_dereference(callid_sock[i]);
-               if (!sock)
-                       continue;
-               opt = &sock->proto.pptp;
-               if (opt->dst_addr.call_id == call_id &&
-                         opt->dst_addr.sin_addr.s_addr == d_addr)
-                       break;
-       }
-       rcu_read_unlock();
-
-       return i < MAX_CALLID;
-}
-
-static int add_chan(struct pppox_sock *sock)
-{
-       static int call_id;
-
-       spin_lock(&chan_lock);
-       if (!sock->proto.pptp.src_addr.call_id) {
-               call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
-               if (call_id == MAX_CALLID) {
-                       call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
-                       if (call_id == MAX_CALLID)
-                               goto out_err;
-               }
-               sock->proto.pptp.src_addr.call_id = call_id;
-       } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
-               goto out_err;
-
-       set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
-       rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
-       spin_unlock(&chan_lock);
-
-       return 0;
-
-out_err:
-       spin_unlock(&chan_lock);
-       return -1;
-}
-
-static void del_chan(struct pppox_sock *sock)
-{
-       spin_lock(&chan_lock);
-       clear_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
-       rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], NULL);
-       spin_unlock(&chan_lock);
-       synchronize_rcu();
-}
-
-static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
-{
-       struct sock *sk = (struct sock *) chan->private;
-       struct pppox_sock *po = pppox_sk(sk);
-       struct pptp_opt *opt = &po->proto.pptp;
-       struct pptp_gre_header *hdr;
-       unsigned int header_len = sizeof(*hdr);
-       struct flowi4 fl4;
-       int islcp;
-       int len;
-       unsigned char *data;
-       __u32 seq_recv;
-
-
-       struct rtable *rt;
-       struct net_device *tdev;
-       struct iphdr  *iph;
-       int    max_headroom;
-
-       if (sk_pppox(po)->sk_state & PPPOX_DEAD)
-               goto tx_error;
-
-       rt = ip_route_output_ports(&init_net, &fl4, NULL,
-                                  opt->dst_addr.sin_addr.s_addr,
-                                  opt->src_addr.sin_addr.s_addr,
-                                  0, 0, IPPROTO_GRE,
-                                  RT_TOS(0), 0);
-       if (IS_ERR(rt))
-               goto tx_error;
-
-       tdev = rt->dst.dev;
-
-       max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
-
-       if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
-               struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
-               if (!new_skb) {
-                       ip_rt_put(rt);
-                       goto tx_error;
-               }
-               if (skb->sk)
-                       skb_set_owner_w(new_skb, skb->sk);
-               kfree_skb(skb);
-               skb = new_skb;
-       }
-
-       data = skb->data;
-       islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7;
-
-       /* compress protocol field */
-       if ((opt->ppp_flags & SC_COMP_PROT) && data[0] == 0 && !islcp)
-               skb_pull(skb, 1);
-
-       /* Put in the address/control bytes if necessary */
-       if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) {
-               data = skb_push(skb, 2);
-               data[0] = PPP_ALLSTATIONS;
-               data[1] = PPP_UI;
-       }
-
-       len = skb->len;
-
-       seq_recv = opt->seq_recv;
-
-       if (opt->ack_sent == seq_recv)
-               header_len -= sizeof(hdr->ack);
-
-       /* Push down and install GRE header */
-       skb_push(skb, header_len);
-       hdr = (struct pptp_gre_header *)(skb->data);
-
-       hdr->flags       = PPTP_GRE_FLAG_K;
-       hdr->ver         = PPTP_GRE_VER;
-       hdr->protocol    = htons(PPTP_GRE_PROTO);
-       hdr->call_id     = htons(opt->dst_addr.call_id);
-
-       hdr->flags      |= PPTP_GRE_FLAG_S;
-       hdr->seq         = htonl(++opt->seq_sent);
-       if (opt->ack_sent != seq_recv)  {
-               /* send ack with this message */
-               hdr->ver |= PPTP_GRE_FLAG_A;
-               hdr->ack  = htonl(seq_recv);
-               opt->ack_sent = seq_recv;
-       }
-       hdr->payload_len = htons(len);
-
-       /*      Push down and install the IP header. */
-
-       skb_reset_transport_header(skb);
-       skb_push(skb, sizeof(*iph));
-       skb_reset_network_header(skb);
-       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
-       IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED);
-
-       iph =   ip_hdr(skb);
-       iph->version =  4;
-       iph->ihl =      sizeof(struct iphdr) >> 2;
-       if (ip_dont_fragment(sk, &rt->dst))
-               iph->frag_off   =       htons(IP_DF);
-       else
-               iph->frag_off   =       0;
-       iph->protocol = IPPROTO_GRE;
-       iph->tos      = 0;
-       iph->daddr    = fl4.daddr;
-       iph->saddr    = fl4.saddr;
-       iph->ttl      = ip4_dst_hoplimit(&rt->dst);
-       iph->tot_len  = htons(skb->len);
-
-       skb_dst_drop(skb);
-       skb_dst_set(skb, &rt->dst);
-
-       nf_reset(skb);
-
-       skb->ip_summed = CHECKSUM_NONE;
-       ip_select_ident(iph, &rt->dst, NULL);
-       ip_send_check(iph);
-
-       ip_local_out(skb);
-
-tx_error:
-       return 1;
-}
-
-static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)
-{
-       struct pppox_sock *po = pppox_sk(sk);
-       struct pptp_opt *opt = &po->proto.pptp;
-       int headersize, payload_len, seq;
-       __u8 *payload;
-       struct pptp_gre_header *header;
-
-       if (!(sk->sk_state & PPPOX_CONNECTED)) {
-               if (sock_queue_rcv_skb(sk, skb))
-                       goto drop;
-               return NET_RX_SUCCESS;
-       }
-
-       header = (struct pptp_gre_header *)(skb->data);
-
-       /* test if acknowledgement present */
-       if (PPTP_GRE_IS_A(header->ver)) {
-               __u32 ack = (PPTP_GRE_IS_S(header->flags)) ?
-                               header->ack : header->seq; /* ack in different place if S = 0 */
-
-               ack = ntohl(ack);
-
-               if (ack > opt->ack_recv)
-                       opt->ack_recv = ack;
-               /* also handle sequence number wrap-around  */
-               if (WRAPPED(ack, opt->ack_recv))
-                       opt->ack_recv = ack;
-       }
-
-       /* test if payload present */
-       if (!PPTP_GRE_IS_S(header->flags))
-               goto drop;
-
-       headersize  = sizeof(*header);
-       payload_len = ntohs(header->payload_len);
-       seq         = ntohl(header->seq);
-
-       /* no ack present? */
-       if (!PPTP_GRE_IS_A(header->ver))
-               headersize -= sizeof(header->ack);
-       /* check for incomplete packet (length smaller than expected) */
-       if (skb->len - headersize < payload_len)
-               goto drop;
-
-       payload = skb->data + headersize;
-       /* check for expected sequence number */
-       if (seq < opt->seq_recv + 1 || WRAPPED(opt->seq_recv, seq)) {
-               if ((payload[0] == PPP_ALLSTATIONS) && (payload[1] == PPP_UI) &&
-                               (PPP_PROTOCOL(payload) == PPP_LCP) &&
-                               ((payload[4] == PPP_LCP_ECHOREQ) || (payload[4] == PPP_LCP_ECHOREP)))
-                       goto allow_packet;
-       } else {
-               opt->seq_recv = seq;
-allow_packet:
-               skb_pull(skb, headersize);
-
-               if (payload[0] == PPP_ALLSTATIONS && payload[1] == PPP_UI) {
-                       /* chop off address/control */
-                       if (skb->len < 3)
-                               goto drop;
-                       skb_pull(skb, 2);
-               }
-
-               if ((*skb->data) & 1) {
-                       /* protocol is compressed */
-                       skb_push(skb, 1)[0] = 0;
-               }
-
-               skb->ip_summed = CHECKSUM_NONE;
-               skb_set_network_header(skb, skb->head-skb->data);
-               ppp_input(&po->chan, skb);
-
-               return NET_RX_SUCCESS;
-       }
-drop:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-static int pptp_rcv(struct sk_buff *skb)
-{
-       struct pppox_sock *po;
-       struct pptp_gre_header *header;
-       struct iphdr *iph;
-
-       if (skb->pkt_type != PACKET_HOST)
-               goto drop;
-
-       if (!pskb_may_pull(skb, 12))
-               goto drop;
-
-       iph = ip_hdr(skb);
-
-       header = (struct pptp_gre_header *)skb->data;
-
-       if (ntohs(header->protocol) != PPTP_GRE_PROTO || /* PPTP-GRE protocol for PPTP */
-               PPTP_GRE_IS_C(header->flags) ||                /* flag C should be clear */
-               PPTP_GRE_IS_R(header->flags) ||                /* flag R should be clear */
-               !PPTP_GRE_IS_K(header->flags) ||               /* flag K should be set */
-               (header->flags&0xF) != 0)                      /* routing and recursion ctrl = 0 */
-               /* if invalid, discard this packet */
-               goto drop;
-
-       po = lookup_chan(htons(header->call_id), iph->saddr);
-       if (po) {
-               skb_dst_drop(skb);
-               nf_reset(skb);
-               return sk_receive_skb(sk_pppox(po), skb, 0);
-       }
-drop:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
-       int sockaddr_len)
-{
-       struct sock *sk = sock->sk;
-       struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
-       struct pppox_sock *po = pppox_sk(sk);
-       struct pptp_opt *opt = &po->proto.pptp;
-       int error = 0;
-
-       lock_sock(sk);
-
-       opt->src_addr = sp->sa_addr.pptp;
-       if (add_chan(po)) {
-               release_sock(sk);
-               error = -EBUSY;
-       }
-
-       release_sock(sk);
-       return error;
-}
-
-static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
-       int sockaddr_len, int flags)
-{
-       struct sock *sk = sock->sk;
-       struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
-       struct pppox_sock *po = pppox_sk(sk);
-       struct pptp_opt *opt = &po->proto.pptp;
-       struct rtable *rt;
-       struct flowi4 fl4;
-       int error = 0;
-
-       if (sp->sa_protocol != PX_PROTO_PPTP)
-               return -EINVAL;
-
-       if (lookup_chan_dst(sp->sa_addr.pptp.call_id, sp->sa_addr.pptp.sin_addr.s_addr))
-               return -EALREADY;
-
-       lock_sock(sk);
-       /* Check for already bound sockets */
-       if (sk->sk_state & PPPOX_CONNECTED) {
-               error = -EBUSY;
-               goto end;
-       }
-
-       /* Check for already disconnected sockets, on attempts to disconnect */
-       if (sk->sk_state & PPPOX_DEAD) {
-               error = -EALREADY;
-               goto end;
-       }
-
-       if (!opt->src_addr.sin_addr.s_addr || !sp->sa_addr.pptp.sin_addr.s_addr) {
-               error = -EINVAL;
-               goto end;
-       }
-
-       po->chan.private = sk;
-       po->chan.ops = &pptp_chan_ops;
-
-       rt = ip_route_output_ports(&init_net, &fl4, sk,
-                                  opt->dst_addr.sin_addr.s_addr,
-                                  opt->src_addr.sin_addr.s_addr,
-                                  0, 0,
-                                  IPPROTO_GRE, RT_CONN_FLAGS(sk), 0);
-       if (IS_ERR(rt)) {
-               error = -EHOSTUNREACH;
-               goto end;
-       }
-       sk_setup_caps(sk, &rt->dst);
-
-       po->chan.mtu = dst_mtu(&rt->dst);
-       if (!po->chan.mtu)
-               po->chan.mtu = PPP_MTU;
-       ip_rt_put(rt);
-       po->chan.mtu -= PPTP_HEADER_OVERHEAD;
-
-       po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
-       error = ppp_register_channel(&po->chan);
-       if (error) {
-               pr_err("PPTP: failed to register PPP channel (%d)\n", error);
-               goto end;
-       }
-
-       opt->dst_addr = sp->sa_addr.pptp;
-       sk->sk_state = PPPOX_CONNECTED;
-
- end:
-       release_sock(sk);
-       return error;
-}
-
-static int pptp_getname(struct socket *sock, struct sockaddr *uaddr,
-       int *usockaddr_len, int peer)
-{
-       int len = sizeof(struct sockaddr_pppox);
-       struct sockaddr_pppox sp;
-
-       sp.sa_family      = AF_PPPOX;
-       sp.sa_protocol  = PX_PROTO_PPTP;
-       sp.sa_addr.pptp = pppox_sk(sock->sk)->proto.pptp.src_addr;
-
-       memcpy(uaddr, &sp, len);
-
-       *usockaddr_len = len;
-
-       return 0;
-}
-
-static int pptp_release(struct socket *sock)
-{
-       struct sock *sk = sock->sk;
-       struct pppox_sock *po;
-       struct pptp_opt *opt;
-       int error = 0;
-
-       if (!sk)
-               return 0;
-
-       lock_sock(sk);
-
-       if (sock_flag(sk, SOCK_DEAD)) {
-               release_sock(sk);
-               return -EBADF;
-       }
-
-       po = pppox_sk(sk);
-       opt = &po->proto.pptp;
-       del_chan(po);
-
-       pppox_unbind_sock(sk);
-       sk->sk_state = PPPOX_DEAD;
-
-       sock_orphan(sk);
-       sock->sk = NULL;
-
-       release_sock(sk);
-       sock_put(sk);
-
-       return error;
-}
-
-static void pptp_sock_destruct(struct sock *sk)
-{
-       if (!(sk->sk_state & PPPOX_DEAD)) {
-               del_chan(pppox_sk(sk));
-               pppox_unbind_sock(sk);
-       }
-       skb_queue_purge(&sk->sk_receive_queue);
-}
-
-static int pptp_create(struct net *net, struct socket *sock)
-{
-       int error = -ENOMEM;
-       struct sock *sk;
-       struct pppox_sock *po;
-       struct pptp_opt *opt;
-
-       sk = sk_alloc(net, PF_PPPOX, GFP_KERNEL, &pptp_sk_proto);
-       if (!sk)
-               goto out;
-
-       sock_init_data(sock, sk);
-
-       sock->state = SS_UNCONNECTED;
-       sock->ops   = &pptp_ops;
-
-       sk->sk_backlog_rcv = pptp_rcv_core;
-       sk->sk_state       = PPPOX_NONE;
-       sk->sk_type        = SOCK_STREAM;
-       sk->sk_family      = PF_PPPOX;
-       sk->sk_protocol    = PX_PROTO_PPTP;
-       sk->sk_destruct    = pptp_sock_destruct;
-
-       po = pppox_sk(sk);
-       opt = &po->proto.pptp;
-
-       opt->seq_sent = 0; opt->seq_recv = 0;
-       opt->ack_recv = 0; opt->ack_sent = 0;
-
-       error = 0;
-out:
-       return error;
-}
-
-static int pptp_ppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
-       unsigned long arg)
-{
-       struct sock *sk = (struct sock *) chan->private;
-       struct pppox_sock *po = pppox_sk(sk);
-       struct pptp_opt *opt = &po->proto.pptp;
-       void __user *argp = (void __user *)arg;
-       int __user *p = argp;
-       int err, val;
-
-       err = -EFAULT;
-       switch (cmd) {
-       case PPPIOCGFLAGS:
-               val = opt->ppp_flags;
-               if (put_user(val, p))
-                       break;
-               err = 0;
-               break;
-       case PPPIOCSFLAGS:
-               if (get_user(val, p))
-                       break;
-               opt->ppp_flags = val & ~SC_RCV_BITS;
-               err = 0;
-               break;
-       default:
-               err = -ENOTTY;
-       }
-
-       return err;
-}
-
-static const struct ppp_channel_ops pptp_chan_ops = {
-       .start_xmit = pptp_xmit,
-       .ioctl      = pptp_ppp_ioctl,
-};
-
-static struct proto pptp_sk_proto __read_mostly = {
-       .name     = "PPTP",
-       .owner    = THIS_MODULE,
-       .obj_size = sizeof(struct pppox_sock),
-};
-
-static const struct proto_ops pptp_ops = {
-       .family     = AF_PPPOX,
-       .owner      = THIS_MODULE,
-       .release    = pptp_release,
-       .bind       = pptp_bind,
-       .connect    = pptp_connect,
-       .socketpair = sock_no_socketpair,
-       .accept     = sock_no_accept,
-       .getname    = pptp_getname,
-       .poll       = sock_no_poll,
-       .listen     = sock_no_listen,
-       .shutdown   = sock_no_shutdown,
-       .setsockopt = sock_no_setsockopt,
-       .getsockopt = sock_no_getsockopt,
-       .sendmsg    = sock_no_sendmsg,
-       .recvmsg    = sock_no_recvmsg,
-       .mmap       = sock_no_mmap,
-       .ioctl      = pppox_ioctl,
-};
-
-static const struct pppox_proto pppox_pptp_proto = {
-       .create = pptp_create,
-       .owner  = THIS_MODULE,
-};
-
-static const struct gre_protocol gre_pptp_protocol = {
-       .handler = pptp_rcv,
-};
-
-static int __init pptp_init_module(void)
-{
-       int err = 0;
-       pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
-
-       callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *));
-       if (!callid_sock) {
-               pr_err("PPTP: cann't allocate memory\n");
-               return -ENOMEM;
-       }
-
-       err = gre_add_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
-       if (err) {
-               pr_err("PPTP: can't add gre protocol\n");
-               goto out_mem_free;
-       }
-
-       err = proto_register(&pptp_sk_proto, 0);
-       if (err) {
-               pr_err("PPTP: can't register sk_proto\n");
-               goto out_gre_del_protocol;
-       }
-
-       err = register_pppox_proto(PX_PROTO_PPTP, &pppox_pptp_proto);
-       if (err) {
-               pr_err("PPTP: can't register pppox_proto\n");
-               goto out_unregister_sk_proto;
-       }
-
-       return 0;
-
-out_unregister_sk_proto:
-       proto_unregister(&pptp_sk_proto);
-out_gre_del_protocol:
-       gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
-out_mem_free:
-       vfree(callid_sock);
-
-       return err;
-}
-
-static void __exit pptp_exit_module(void)
-{
-       unregister_pppox_proto(PX_PROTO_PPTP);
-       proto_unregister(&pptp_sk_proto);
-       gre_del_protocol(&gre_pptp_protocol, GREPROTO_PPTP);
-       vfree(callid_sock);
-}
-
-module_init(pptp_init_module);
-module_exit(pptp_exit_module);
-
-MODULE_DESCRIPTION("Point-to-Point Tunneling Protocol");
-MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
deleted file mode 100644 (file)
index e68c941..0000000
+++ /dev/null
@@ -1,1716 +0,0 @@
-/*
- * rrunner.c: Linux driver for the Essential RoadRunner HIPPI board.
- *
- * Copyright (C) 1998-2002 by Jes Sorensen, <jes@wildopensource.com>.
- *
- * Thanks to Essential Communication for providing us with hardware
- * and very comprehensive documentation without which I would not have
- * been able to write this driver. A special thank you to John Gibbon
- * for sorting out the legal issues, with the NDA, allowing the code to
- * be released under the GPL.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Thanks to Jayaram Bhat from ODS/Essential for fixing some of the
- * stupid bugs in my code.
- *
- * Softnet support and various other patches from Val Henson of
- * ODS/Essential.
- *
- * PCI DMA mapping code partly based on work by Francois Romieu.
- */
-
-
-#define DEBUG 1
-#define RX_DMA_SKBUFF 1
-#define PKT_COPY_THRESHOLD 512
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/hippidevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <net/sock.h>
-
-#include <asm/system.h>
-#include <asm/cache.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#define rr_if_busy(dev)     netif_queue_stopped(dev)
-#define rr_if_running(dev)  netif_running(dev)
-
-#include "rrunner.h"
-
-#define RUN_AT(x) (jiffies + (x))
-
-
-MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
-MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
-MODULE_LICENSE("GPL");
-
-static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
-
-
-static const struct net_device_ops rr_netdev_ops = {
-       .ndo_open               = rr_open,
-       .ndo_stop               = rr_close,
-       .ndo_do_ioctl           = rr_ioctl,
-       .ndo_start_xmit         = rr_start_xmit,
-       .ndo_change_mtu         = hippi_change_mtu,
-       .ndo_set_mac_address    = hippi_mac_addr,
-};
-
-/*
- * Implementation notes:
- *
- * The DMA engine only allows for DMA within physical 64KB chunks of
- * memory. The current approach of the driver (and stack) is to use
- * linear blocks of memory for the skbuffs. However, as the data block
- * is always the first part of the skb and skbs are 2^n aligned so we
- * are guarantted to get the whole block within one 64KB align 64KB
- * chunk.
- *
- * On the long term, relying on being able to allocate 64KB linear
- * chunks of memory is not feasible and the skb handling code and the
- * stack will need to know about I/O vectors or something similar.
- */
-
-static int __devinit rr_init_one(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
-{
-       struct net_device *dev;
-       static int version_disp;
-       u8 pci_latency;
-       struct rr_private *rrpriv;
-       void *tmpptr;
-       dma_addr_t ring_dma;
-       int ret = -ENOMEM;
-
-       dev = alloc_hippi_dev(sizeof(struct rr_private));
-       if (!dev)
-               goto out3;
-
-       ret = pci_enable_device(pdev);
-       if (ret) {
-               ret = -ENODEV;
-               goto out2;
-       }
-
-       rrpriv = netdev_priv(dev);
-
-       SET_NETDEV_DEV(dev, &pdev->dev);
-
-       if (pci_request_regions(pdev, "rrunner")) {
-               ret = -EIO;
-               goto out;
-       }
-
-       pci_set_drvdata(pdev, dev);
-
-       rrpriv->pci_dev = pdev;
-
-       spin_lock_init(&rrpriv->lock);
-
-       dev->irq = pdev->irq;
-       dev->netdev_ops = &rr_netdev_ops;
-
-       dev->base_addr = pci_resource_start(pdev, 0);
-
-       /* display version info if adapter is found */
-       if (!version_disp) {
-               /* set display flag to TRUE so that */
-               /* we only display this string ONCE */
-               version_disp = 1;
-               printk(version);
-       }
-
-       pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
-       if (pci_latency <= 0x58){
-               pci_latency = 0x58;
-               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_latency);
-       }
-
-       pci_set_master(pdev);
-
-       printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
-              "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,
-              dev->base_addr, dev->irq, pci_latency);
-
-       /*
-        * Remap the regs into kernel space.
-        */
-
-       rrpriv->regs = ioremap(dev->base_addr, 0x1000);
-
-       if (!rrpriv->regs){
-               printk(KERN_ERR "%s:  Unable to map I/O register, "
-                       "RoadRunner will be disabled.\n", dev->name);
-               ret = -EIO;
-               goto out;
-       }
-
-       tmpptr = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
-       rrpriv->tx_ring = tmpptr;
-       rrpriv->tx_ring_dma = ring_dma;
-
-       if (!tmpptr) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       tmpptr = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
-       rrpriv->rx_ring = tmpptr;
-       rrpriv->rx_ring_dma = ring_dma;
-
-       if (!tmpptr) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       tmpptr = pci_alloc_consistent(pdev, EVT_RING_SIZE, &ring_dma);
-       rrpriv->evt_ring = tmpptr;
-       rrpriv->evt_ring_dma = ring_dma;
-
-       if (!tmpptr) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       /*
-        * Don't access any register before this point!
-        */
-#ifdef __BIG_ENDIAN
-       writel(readl(&rrpriv->regs->HostCtrl) | NO_SWAP,
-               &rrpriv->regs->HostCtrl);
-#endif
-       /*
-        * Need to add a case for little-endian 64-bit hosts here.
-        */
-
-       rr_init(dev);
-
-       dev->base_addr = 0;
-
-       ret = register_netdev(dev);
-       if (ret)
-               goto out;
-       return 0;
-
- out:
-       if (rrpriv->rx_ring)
-               pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring,
-                                   rrpriv->rx_ring_dma);
-       if (rrpriv->tx_ring)
-               pci_free_consistent(pdev, TX_TOTAL_SIZE, rrpriv->tx_ring,
-                                   rrpriv->tx_ring_dma);
-       if (rrpriv->regs)
-               iounmap(rrpriv->regs);
-       if (pdev) {
-               pci_release_regions(pdev);
-               pci_set_drvdata(pdev, NULL);
-       }
- out2:
-       free_netdev(dev);
- out3:
-       return ret;
-}
-
-static void __devexit rr_remove_one (struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-
-       if (dev) {
-               struct rr_private *rr = netdev_priv(dev);
-
-               if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){
-                       printk(KERN_ERR "%s: trying to unload running NIC\n",
-                              dev->name);
-                       writel(HALT_NIC, &rr->regs->HostCtrl);
-               }
-
-               pci_free_consistent(pdev, EVT_RING_SIZE, rr->evt_ring,
-                                   rr->evt_ring_dma);
-               pci_free_consistent(pdev, RX_TOTAL_SIZE, rr->rx_ring,
-                                   rr->rx_ring_dma);
-               pci_free_consistent(pdev, TX_TOTAL_SIZE, rr->tx_ring,
-                                   rr->tx_ring_dma);
-               unregister_netdev(dev);
-               iounmap(rr->regs);
-               free_netdev(dev);
-               pci_release_regions(pdev);
-               pci_disable_device(pdev);
-               pci_set_drvdata(pdev, NULL);
-       }
-}
-
-
-/*
- * Commands are considered to be slow, thus there is no reason to
- * inline this.
- */
-static void rr_issue_cmd(struct rr_private *rrpriv, struct cmd *cmd)
-{
-       struct rr_regs __iomem *regs;
-       u32 idx;
-
-       regs = rrpriv->regs;
-       /*
-        * This is temporary - it will go away in the final version.
-        * We probably also want to make this function inline.
-        */
-       if (readl(&regs->HostCtrl) & NIC_HALTED){
-               printk("issuing command for halted NIC, code 0x%x, "
-                      "HostCtrl %08x\n", cmd->code, readl(&regs->HostCtrl));
-               if (readl(&regs->Mode) & FATAL_ERR)
-                       printk("error codes Fail1 %02x, Fail2 %02x\n",
-                              readl(&regs->Fail1), readl(&regs->Fail2));
-       }
-
-       idx = rrpriv->info->cmd_ctrl.pi;
-
-       writel(*(u32*)(cmd), &regs->CmdRing[idx]);
-       wmb();
-
-       idx = (idx - 1) % CMD_RING_ENTRIES;
-       rrpriv->info->cmd_ctrl.pi = idx;
-       wmb();
-
-       if (readl(&regs->Mode) & FATAL_ERR)
-               printk("error code %02x\n", readl(&regs->Fail1));
-}
-
-
-/*
- * Reset the board in a sensible manner. The NIC is already halted
- * when we get here and a spin-lock is held.
- */
-static int rr_reset(struct net_device *dev)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       u32 start_pc;
-       int i;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       rr_load_firmware(dev);
-
-       writel(0x01000000, &regs->TX_state);
-       writel(0xff800000, &regs->RX_state);
-       writel(0, &regs->AssistState);
-       writel(CLEAR_INTA, &regs->LocalCtrl);
-       writel(0x01, &regs->BrkPt);
-       writel(0, &regs->Timer);
-       writel(0, &regs->TimerRef);
-       writel(RESET_DMA, &regs->DmaReadState);
-       writel(RESET_DMA, &regs->DmaWriteState);
-       writel(0, &regs->DmaWriteHostHi);
-       writel(0, &regs->DmaWriteHostLo);
-       writel(0, &regs->DmaReadHostHi);
-       writel(0, &regs->DmaReadHostLo);
-       writel(0, &regs->DmaReadLen);
-       writel(0, &regs->DmaWriteLen);
-       writel(0, &regs->DmaWriteLcl);
-       writel(0, &regs->DmaWriteIPchecksum);
-       writel(0, &regs->DmaReadLcl);
-       writel(0, &regs->DmaReadIPchecksum);
-       writel(0, &regs->PciState);
-#if (BITS_PER_LONG == 64) && defined __LITTLE_ENDIAN
-       writel(SWAP_DATA | PTR64BIT | PTR_WD_SWAP, &regs->Mode);
-#elif (BITS_PER_LONG == 64)
-       writel(SWAP_DATA | PTR64BIT | PTR_WD_NOSWAP, &regs->Mode);
-#else
-       writel(SWAP_DATA | PTR32BIT | PTR_WD_NOSWAP, &regs->Mode);
-#endif
-
-#if 0
-       /*
-        * Don't worry, this is just black magic.
-        */
-       writel(0xdf000, &regs->RxBase);
-       writel(0xdf000, &regs->RxPrd);
-       writel(0xdf000, &regs->RxCon);
-       writel(0xce000, &regs->TxBase);
-       writel(0xce000, &regs->TxPrd);
-       writel(0xce000, &regs->TxCon);
-       writel(0, &regs->RxIndPro);
-       writel(0, &regs->RxIndCon);
-       writel(0, &regs->RxIndRef);
-       writel(0, &regs->TxIndPro);
-       writel(0, &regs->TxIndCon);
-       writel(0, &regs->TxIndRef);
-       writel(0xcc000, &regs->pad10[0]);
-       writel(0, &regs->DrCmndPro);
-       writel(0, &regs->DrCmndCon);
-       writel(0, &regs->DwCmndPro);
-       writel(0, &regs->DwCmndCon);
-       writel(0, &regs->DwCmndRef);
-       writel(0, &regs->DrDataPro);
-       writel(0, &regs->DrDataCon);
-       writel(0, &regs->DrDataRef);
-       writel(0, &regs->DwDataPro);
-       writel(0, &regs->DwDataCon);
-       writel(0, &regs->DwDataRef);
-#endif
-
-       writel(0xffffffff, &regs->MbEvent);
-       writel(0, &regs->Event);
-
-       writel(0, &regs->TxPi);
-       writel(0, &regs->IpRxPi);
-
-       writel(0, &regs->EvtCon);
-       writel(0, &regs->EvtPrd);
-
-       rrpriv->info->evt_ctrl.pi = 0;
-
-       for (i = 0; i < CMD_RING_ENTRIES; i++)
-               writel(0, &regs->CmdRing[i]);
-
-/*
- * Why 32 ? is this not cache line size dependent?
- */
-       writel(RBURST_64|WBURST_64, &regs->PciState);
-       wmb();
-
-       start_pc = rr_read_eeprom_word(rrpriv,
-                       offsetof(struct eeprom, rncd_info.FwStart));
-
-#if (DEBUG > 1)
-       printk("%s: Executing firmware at address 0x%06x\n",
-              dev->name, start_pc);
-#endif
-
-       writel(start_pc + 0x800, &regs->Pc);
-       wmb();
-       udelay(5);
-
-       writel(start_pc, &regs->Pc);
-       wmb();
-
-       return 0;
-}
-
-
-/*
- * Read a string from the EEPROM.
- */
-static unsigned int rr_read_eeprom(struct rr_private *rrpriv,
-                               unsigned long offset,
-                               unsigned char *buf,
-                               unsigned long length)
-{
-       struct rr_regs __iomem *regs = rrpriv->regs;
-       u32 misc, io, host, i;
-
-       io = readl(&regs->ExtIo);
-       writel(0, &regs->ExtIo);
-       misc = readl(&regs->LocalCtrl);
-       writel(0, &regs->LocalCtrl);
-       host = readl(&regs->HostCtrl);
-       writel(host | HALT_NIC, &regs->HostCtrl);
-       mb();
-
-       for (i = 0; i < length; i++){
-               writel((EEPROM_BASE + ((offset+i) << 3)), &regs->WinBase);
-               mb();
-               buf[i] = (readl(&regs->WinData) >> 24) & 0xff;
-               mb();
-       }
-
-       writel(host, &regs->HostCtrl);
-       writel(misc, &regs->LocalCtrl);
-       writel(io, &regs->ExtIo);
-       mb();
-       return i;
-}
-
-
-/*
- * Shortcut to read one word (4 bytes) out of the EEPROM and convert
- * it to our CPU byte-order.
- */
-static u32 rr_read_eeprom_word(struct rr_private *rrpriv,
-                           size_t offset)
-{
-       __be32 word;
-
-       if ((rr_read_eeprom(rrpriv, offset,
-                           (unsigned char *)&word, 4) == 4))
-               return be32_to_cpu(word);
-       return 0;
-}
-
-
-/*
- * Write a string to the EEPROM.
- *
- * This is only called when the firmware is not running.
- */
-static unsigned int write_eeprom(struct rr_private *rrpriv,
-                                unsigned long offset,
-                                unsigned char *buf,
-                                unsigned long length)
-{
-       struct rr_regs __iomem *regs = rrpriv->regs;
-       u32 misc, io, data, i, j, ready, error = 0;
-
-       io = readl(&regs->ExtIo);
-       writel(0, &regs->ExtIo);
-       misc = readl(&regs->LocalCtrl);
-       writel(ENABLE_EEPROM_WRITE, &regs->LocalCtrl);
-       mb();
-
-       for (i = 0; i < length; i++){
-               writel((EEPROM_BASE + ((offset+i) << 3)), &regs->WinBase);
-               mb();
-               data = buf[i] << 24;
-               /*
-                * Only try to write the data if it is not the same
-                * value already.
-                */
-               if ((readl(&regs->WinData) & 0xff000000) != data){
-                       writel(data, &regs->WinData);
-                       ready = 0;
-                       j = 0;
-                       mb();
-                       while(!ready){
-                               udelay(20);
-                               if ((readl(&regs->WinData) & 0xff000000) ==
-                                   data)
-                                       ready = 1;
-                               mb();
-                               if (j++ > 5000){
-                                       printk("data mismatch: %08x, "
-                                              "WinData %08x\n", data,
-                                              readl(&regs->WinData));
-                                       ready = 1;
-                                       error = 1;
-                               }
-                       }
-               }
-       }
-
-       writel(misc, &regs->LocalCtrl);
-       writel(io, &regs->ExtIo);
-       mb();
-
-       return error;
-}
-
-
-static int __devinit rr_init(struct net_device *dev)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       u32 sram_size, rev;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       rev = readl(&regs->FwRev);
-       rrpriv->fw_rev = rev;
-       if (rev > 0x00020024)
-               printk("  Firmware revision: %i.%i.%i\n", (rev >> 16),
-                      ((rev >> 8) & 0xff), (rev & 0xff));
-       else if (rev >= 0x00020000) {
-               printk("  Firmware revision: %i.%i.%i (2.0.37 or "
-                      "later is recommended)\n", (rev >> 16),
-                      ((rev >> 8) & 0xff), (rev & 0xff));
-       }else{
-               printk("  Firmware revision too old: %i.%i.%i, please "
-                      "upgrade to 2.0.37 or later.\n",
-                      (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff));
-       }
-
-#if (DEBUG > 2)
-       printk("  Maximum receive rings %i\n", readl(&regs->MaxRxRng));
-#endif
-
-       /*
-        * Read the hardware address from the eeprom.  The HW address
-        * is not really necessary for HIPPI but awfully convenient.
-        * The pointer arithmetic to put it in dev_addr is ugly, but
-        * Donald Becker does it this way for the GigE version of this
-        * card and it's shorter and more portable than any
-        * other method I've seen.  -VAL
-        */
-
-       *(__be16 *)(dev->dev_addr) =
-         htons(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA)));
-       *(__be32 *)(dev->dev_addr+2) =
-         htonl(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA[4])));
-
-       printk("  MAC: %pM\n", dev->dev_addr);
-
-       sram_size = rr_read_eeprom_word(rrpriv, 8);
-       printk("  SRAM size 0x%06x\n", sram_size);
-
-       return 0;
-}
-
-
-static int rr_init1(struct net_device *dev)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       unsigned long myjif, flags;
-       struct cmd cmd;
-       u32 hostctrl;
-       int ecode = 0;
-       short i;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       spin_lock_irqsave(&rrpriv->lock, flags);
-
-       hostctrl = readl(&regs->HostCtrl);
-       writel(hostctrl | HALT_NIC | RR_CLEAR_INT, &regs->HostCtrl);
-       wmb();
-
-       if (hostctrl & PARITY_ERR){
-               printk("%s: Parity error halting NIC - this is serious!\n",
-                      dev->name);
-               spin_unlock_irqrestore(&rrpriv->lock, flags);
-               ecode = -EFAULT;
-               goto error;
-       }
-
-       set_rxaddr(regs, rrpriv->rx_ctrl_dma);
-       set_infoaddr(regs, rrpriv->info_dma);
-
-       rrpriv->info->evt_ctrl.entry_size = sizeof(struct event);
-       rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES;
-       rrpriv->info->evt_ctrl.mode = 0;
-       rrpriv->info->evt_ctrl.pi = 0;
-       set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring_dma);
-
-       rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd);
-       rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES;
-       rrpriv->info->cmd_ctrl.mode = 0;
-       rrpriv->info->cmd_ctrl.pi = 15;
-
-       for (i = 0; i < CMD_RING_ENTRIES; i++) {
-               writel(0, &regs->CmdRing[i]);
-       }
-
-       for (i = 0; i < TX_RING_ENTRIES; i++) {
-               rrpriv->tx_ring[i].size = 0;
-               set_rraddr(&rrpriv->tx_ring[i].addr, 0);
-               rrpriv->tx_skbuff[i] = NULL;
-       }
-       rrpriv->info->tx_ctrl.entry_size = sizeof(struct tx_desc);
-       rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES;
-       rrpriv->info->tx_ctrl.mode = 0;
-       rrpriv->info->tx_ctrl.pi = 0;
-       set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring_dma);
-
-       /*
-        * Set dirty_tx before we start receiving interrupts, otherwise
-        * the interrupt handler might think it is supposed to process
-        * tx ints before we are up and running, which may cause a null
-        * pointer access in the int handler.
-        */
-       rrpriv->tx_full = 0;
-       rrpriv->cur_rx = 0;
-       rrpriv->dirty_rx = rrpriv->dirty_tx = 0;
-
-       rr_reset(dev);
-
-       /* Tuning values */
-       writel(0x5000, &regs->ConRetry);
-       writel(0x100, &regs->ConRetryTmr);
-       writel(0x500000, &regs->ConTmout);
-       writel(0x60, &regs->IntrTmr);
-       writel(0x500000, &regs->TxDataMvTimeout);
-       writel(0x200000, &regs->RxDataMvTimeout);
-       writel(0x80, &regs->WriteDmaThresh);
-       writel(0x80, &regs->ReadDmaThresh);
-
-       rrpriv->fw_running = 0;
-       wmb();
-
-       hostctrl &= ~(HALT_NIC | INVALID_INST_B | PARITY_ERR);
-       writel(hostctrl, &regs->HostCtrl);
-       wmb();
-
-       spin_unlock_irqrestore(&rrpriv->lock, flags);
-
-       for (i = 0; i < RX_RING_ENTRIES; i++) {
-               struct sk_buff *skb;
-               dma_addr_t addr;
-
-               rrpriv->rx_ring[i].mode = 0;
-               skb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC);
-               if (!skb) {
-                       printk(KERN_WARNING "%s: Unable to allocate memory "
-                              "for receive ring - halting NIC\n", dev->name);
-                       ecode = -ENOMEM;
-                       goto error;
-               }
-               rrpriv->rx_skbuff[i] = skb;
-               addr = pci_map_single(rrpriv->pci_dev, skb->data,
-                       dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
-               /*
-                * Sanity test to see if we conflict with the DMA
-                * limitations of the Roadrunner.
-                */
-               if ((((unsigned long)skb->data) & 0xfff) > ~65320)
-                       printk("skb alloc error\n");
-
-               set_rraddr(&rrpriv->rx_ring[i].addr, addr);
-               rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN;
-       }
-
-       rrpriv->rx_ctrl[4].entry_size = sizeof(struct rx_desc);
-       rrpriv->rx_ctrl[4].entries = RX_RING_ENTRIES;
-       rrpriv->rx_ctrl[4].mode = 8;
-       rrpriv->rx_ctrl[4].pi = 0;
-       wmb();
-       set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring_dma);
-
-       udelay(1000);
-
-       /*
-        * Now start the FirmWare.
-        */
-       cmd.code = C_START_FW;
-       cmd.ring = 0;
-       cmd.index = 0;
-
-       rr_issue_cmd(rrpriv, &cmd);
-
-       /*
-        * Give the FirmWare time to chew on the `get running' command.
-        */
-       myjif = jiffies + 5 * HZ;
-       while (time_before(jiffies, myjif) && !rrpriv->fw_running)
-               cpu_relax();
-
-       netif_start_queue(dev);
-
-       return ecode;
-
- error:
-       /*
-        * We might have gotten here because we are out of memory,
-        * make sure we release everything we allocated before failing
-        */
-       for (i = 0; i < RX_RING_ENTRIES; i++) {
-               struct sk_buff *skb = rrpriv->rx_skbuff[i];
-
-               if (skb) {
-                       pci_unmap_single(rrpriv->pci_dev,
-                                        rrpriv->rx_ring[i].addr.addrlo,
-                                        dev->mtu + HIPPI_HLEN,
-                                        PCI_DMA_FROMDEVICE);
-                       rrpriv->rx_ring[i].size = 0;
-                       set_rraddr(&rrpriv->rx_ring[i].addr, 0);
-                       dev_kfree_skb(skb);
-                       rrpriv->rx_skbuff[i] = NULL;
-               }
-       }
-       return ecode;
-}
-
-
-/*
- * All events are considered to be slow (RX/TX ints do not generate
- * events) and are handled here, outside the main interrupt handler,
- * to reduce the size of the handler.
- */
-static u32 rr_handle_event(struct net_device *dev, u32 prodidx, u32 eidx)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       u32 tmp;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       while (prodidx != eidx){
-               switch (rrpriv->evt_ring[eidx].code){
-               case E_NIC_UP:
-                       tmp = readl(&regs->FwRev);
-                       printk(KERN_INFO "%s: Firmware revision %i.%i.%i "
-                              "up and running\n", dev->name,
-                              (tmp >> 16), ((tmp >> 8) & 0xff), (tmp & 0xff));
-                       rrpriv->fw_running = 1;
-                       writel(RX_RING_ENTRIES - 1, &regs->IpRxPi);
-                       wmb();
-                       break;
-               case E_LINK_ON:
-                       printk(KERN_INFO "%s: Optical link ON\n", dev->name);
-                       break;
-               case E_LINK_OFF:
-                       printk(KERN_INFO "%s: Optical link OFF\n", dev->name);
-                       break;
-               case E_RX_IDLE:
-                       printk(KERN_WARNING "%s: RX data not moving\n",
-                              dev->name);
-                       goto drop;
-               case E_WATCHDOG:
-                       printk(KERN_INFO "%s: The watchdog is here to see "
-                              "us\n", dev->name);
-                       break;
-               case E_INTERN_ERR:
-                       printk(KERN_ERR "%s: HIPPI Internal NIC error\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_HOST_ERR:
-                       printk(KERN_ERR "%s: Host software error\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               /*
-                * TX events.
-                */
-               case E_CON_REJ:
-                       printk(KERN_WARNING "%s: Connection rejected\n",
-                              dev->name);
-                       dev->stats.tx_aborted_errors++;
-                       break;
-               case E_CON_TMOUT:
-                       printk(KERN_WARNING "%s: Connection timeout\n",
-                              dev->name);
-                       break;
-               case E_DISC_ERR:
-                       printk(KERN_WARNING "%s: HIPPI disconnect error\n",
-                              dev->name);
-                       dev->stats.tx_aborted_errors++;
-                       break;
-               case E_INT_PRTY:
-                       printk(KERN_ERR "%s: HIPPI Internal Parity error\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_TX_IDLE:
-                       printk(KERN_WARNING "%s: Transmitter idle\n",
-                              dev->name);
-                       break;
-               case E_TX_LINK_DROP:
-                       printk(KERN_WARNING "%s: Link lost during transmit\n",
-                              dev->name);
-                       dev->stats.tx_aborted_errors++;
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_TX_INV_RNG:
-                       printk(KERN_ERR "%s: Invalid send ring block\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_TX_INV_BUF:
-                       printk(KERN_ERR "%s: Invalid send buffer address\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_TX_INV_DSC:
-                       printk(KERN_ERR "%s: Invalid descriptor address\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               /*
-                * RX events.
-                */
-               case E_RX_RNG_OUT:
-                       printk(KERN_INFO "%s: Receive ring full\n", dev->name);
-                       break;
-
-               case E_RX_PAR_ERR:
-                       printk(KERN_WARNING "%s: Receive parity error\n",
-                              dev->name);
-                       goto drop;
-               case E_RX_LLRC_ERR:
-                       printk(KERN_WARNING "%s: Receive LLRC error\n",
-                              dev->name);
-                       goto drop;
-               case E_PKT_LN_ERR:
-                       printk(KERN_WARNING "%s: Receive packet length "
-                              "error\n", dev->name);
-                       goto drop;
-               case E_DTA_CKSM_ERR:
-                       printk(KERN_WARNING "%s: Data checksum error\n",
-                              dev->name);
-                       goto drop;
-               case E_SHT_BST:
-                       printk(KERN_WARNING "%s: Unexpected short burst "
-                              "error\n", dev->name);
-                       goto drop;
-               case E_STATE_ERR:
-                       printk(KERN_WARNING "%s: Recv. state transition"
-                              " error\n", dev->name);
-                       goto drop;
-               case E_UNEXP_DATA:
-                       printk(KERN_WARNING "%s: Unexpected data error\n",
-                              dev->name);
-                       goto drop;
-               case E_LST_LNK_ERR:
-                       printk(KERN_WARNING "%s: Link lost error\n",
-                              dev->name);
-                       goto drop;
-               case E_FRM_ERR:
-                       printk(KERN_WARNING "%s: Framming Error\n",
-                              dev->name);
-                       goto drop;
-               case E_FLG_SYN_ERR:
-                       printk(KERN_WARNING "%s: Flag sync. lost during "
-                              "packet\n", dev->name);
-                       goto drop;
-               case E_RX_INV_BUF:
-                       printk(KERN_ERR "%s: Invalid receive buffer "
-                              "address\n", dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_RX_INV_DSC:
-                       printk(KERN_ERR "%s: Invalid receive descriptor "
-                              "address\n", dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               case E_RNG_BLK:
-                       printk(KERN_ERR "%s: Invalid ring block\n",
-                              dev->name);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       wmb();
-                       break;
-               drop:
-                       /* Label packet to be dropped.
-                        * Actual dropping occurs in rx
-                        * handling.
-                        *
-                        * The index of packet we get to drop is
-                        * the index of the packet following
-                        * the bad packet. -kbf
-                        */
-                       {
-                               u16 index = rrpriv->evt_ring[eidx].index;
-                               index = (index + (RX_RING_ENTRIES - 1)) %
-                                       RX_RING_ENTRIES;
-                               rrpriv->rx_ring[index].mode |=
-                                       (PACKET_BAD | PACKET_END);
-                       }
-                       break;
-               default:
-                       printk(KERN_WARNING "%s: Unhandled event 0x%02x\n",
-                              dev->name, rrpriv->evt_ring[eidx].code);
-               }
-               eidx = (eidx + 1) % EVT_RING_ENTRIES;
-       }
-
-       rrpriv->info->evt_ctrl.pi = eidx;
-       wmb();
-       return eidx;
-}
-
-
-static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
-{
-       struct rr_private *rrpriv = netdev_priv(dev);
-       struct rr_regs __iomem *regs = rrpriv->regs;
-
-       do {
-               struct rx_desc *desc;
-               u32 pkt_len;
-
-               desc = &(rrpriv->rx_ring[index]);
-               pkt_len = desc->size;
-#if (DEBUG > 2)
-               printk("index %i, rxlimit %i\n", index, rxlimit);
-               printk("len %x, mode %x\n", pkt_len, desc->mode);
-#endif
-               if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){
-                       dev->stats.rx_dropped++;
-                       goto defer;
-               }
-
-               if (pkt_len > 0){
-                       struct sk_buff *skb, *rx_skb;
-
-                       rx_skb = rrpriv->rx_skbuff[index];
-
-                       if (pkt_len < PKT_COPY_THRESHOLD) {
-                               skb = alloc_skb(pkt_len, GFP_ATOMIC);
-                               if (skb == NULL){
-                                       printk(KERN_WARNING "%s: Unable to allocate skb (%i bytes), deferring packet\n", dev->name, pkt_len);
-                                       dev->stats.rx_dropped++;
-                                       goto defer;
-                               } else {
-                                       pci_dma_sync_single_for_cpu(rrpriv->pci_dev,
-                                                                   desc->addr.addrlo,
-                                                                   pkt_len,
-                                                                   PCI_DMA_FROMDEVICE);
-
-                                       memcpy(skb_put(skb, pkt_len),
-                                              rx_skb->data, pkt_len);
-
-                                       pci_dma_sync_single_for_device(rrpriv->pci_dev,
-                                                                      desc->addr.addrlo,
-                                                                      pkt_len,
-                                                                      PCI_DMA_FROMDEVICE);
-                               }
-                       }else{
-                               struct sk_buff *newskb;
-
-                               newskb = alloc_skb(dev->mtu + HIPPI_HLEN,
-                                       GFP_ATOMIC);
-                               if (newskb){
-                                       dma_addr_t addr;
-
-                                       pci_unmap_single(rrpriv->pci_dev,
-                                               desc->addr.addrlo, dev->mtu +
-                                               HIPPI_HLEN, PCI_DMA_FROMDEVICE);
-                                       skb = rx_skb;
-                                       skb_put(skb, pkt_len);
-                                       rrpriv->rx_skbuff[index] = newskb;
-                                       addr = pci_map_single(rrpriv->pci_dev,
-                                               newskb->data,
-                                               dev->mtu + HIPPI_HLEN,
-                                               PCI_DMA_FROMDEVICE);
-                                       set_rraddr(&desc->addr, addr);
-                               } else {
-                                       printk("%s: Out of memory, deferring "
-                                              "packet\n", dev->name);
-                                       dev->stats.rx_dropped++;
-                                       goto defer;
-                               }
-                       }
-                       skb->protocol = hippi_type_trans(skb, dev);
-
-                       netif_rx(skb);          /* send it up */
-
-                       dev->stats.rx_packets++;
-                       dev->stats.rx_bytes += pkt_len;
-               }
-       defer:
-               desc->mode = 0;
-               desc->size = dev->mtu + HIPPI_HLEN;
-
-               if ((index & 7) == 7)
-                       writel(index, &regs->IpRxPi);
-
-               index = (index + 1) % RX_RING_ENTRIES;
-       } while(index != rxlimit);
-
-       rrpriv->cur_rx = index;
-       wmb();
-}
-
-
-static irqreturn_t rr_interrupt(int irq, void *dev_id)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       struct net_device *dev = (struct net_device *)dev_id;
-       u32 prodidx, rxindex, eidx, txcsmr, rxlimit, txcon;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       if (!(readl(&regs->HostCtrl) & RR_INT))
-               return IRQ_NONE;
-
-       spin_lock(&rrpriv->lock);
-
-       prodidx = readl(&regs->EvtPrd);
-       txcsmr = (prodidx >> 8) & 0xff;
-       rxlimit = (prodidx >> 16) & 0xff;
-       prodidx &= 0xff;
-
-#if (DEBUG > 2)
-       printk("%s: interrupt, prodidx = %i, eidx = %i\n", dev->name,
-              prodidx, rrpriv->info->evt_ctrl.pi);
-#endif
-       /*
-        * Order here is important.  We must handle events
-        * before doing anything else in order to catch
-        * such things as LLRC errors, etc -kbf
-        */
-
-       eidx = rrpriv->info->evt_ctrl.pi;
-       if (prodidx != eidx)
-               eidx = rr_handle_event(dev, prodidx, eidx);
-
-       rxindex = rrpriv->cur_rx;
-       if (rxindex != rxlimit)
-               rx_int(dev, rxlimit, rxindex);
-
-       txcon = rrpriv->dirty_tx;
-       if (txcsmr != txcon) {
-               do {
-                       /* Due to occational firmware TX producer/consumer out
-                        * of sync. error need to check entry in ring -kbf
-                        */
-                       if(rrpriv->tx_skbuff[txcon]){
-                               struct tx_desc *desc;
-                               struct sk_buff *skb;
-
-                               desc = &(rrpriv->tx_ring[txcon]);
-                               skb = rrpriv->tx_skbuff[txcon];
-
-                               dev->stats.tx_packets++;
-                               dev->stats.tx_bytes += skb->len;
-
-                               pci_unmap_single(rrpriv->pci_dev,
-                                                desc->addr.addrlo, skb->len,
-                                                PCI_DMA_TODEVICE);
-                               dev_kfree_skb_irq(skb);
-
-                               rrpriv->tx_skbuff[txcon] = NULL;
-                               desc->size = 0;
-                               set_rraddr(&rrpriv->tx_ring[txcon].addr, 0);
-                               desc->mode = 0;
-                       }
-                       txcon = (txcon + 1) % TX_RING_ENTRIES;
-               } while (txcsmr != txcon);
-               wmb();
-
-               rrpriv->dirty_tx = txcon;
-               if (rrpriv->tx_full && rr_if_busy(dev) &&
-                   (((rrpriv->info->tx_ctrl.pi + 1) % TX_RING_ENTRIES)
-                    != rrpriv->dirty_tx)){
-                       rrpriv->tx_full = 0;
-                       netif_wake_queue(dev);
-               }
-       }
-
-       eidx |= ((txcsmr << 8) | (rxlimit << 16));
-       writel(eidx, &regs->EvtCon);
-       wmb();
-
-       spin_unlock(&rrpriv->lock);
-       return IRQ_HANDLED;
-}
-
-static inline void rr_raz_tx(struct rr_private *rrpriv,
-                            struct net_device *dev)
-{
-       int i;
-
-       for (i = 0; i < TX_RING_ENTRIES; i++) {
-               struct sk_buff *skb = rrpriv->tx_skbuff[i];
-
-               if (skb) {
-                       struct tx_desc *desc = &(rrpriv->tx_ring[i]);
-
-                       pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
-                               skb->len, PCI_DMA_TODEVICE);
-                       desc->size = 0;
-                       set_rraddr(&desc->addr, 0);
-                       dev_kfree_skb(skb);
-                       rrpriv->tx_skbuff[i] = NULL;
-               }
-       }
-}
-
-
-static inline void rr_raz_rx(struct rr_private *rrpriv,
-                            struct net_device *dev)
-{
-       int i;
-
-       for (i = 0; i < RX_RING_ENTRIES; i++) {
-               struct sk_buff *skb = rrpriv->rx_skbuff[i];
-
-               if (skb) {
-                       struct rx_desc *desc = &(rrpriv->rx_ring[i]);
-
-                       pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
-                               dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
-                       desc->size = 0;
-                       set_rraddr(&desc->addr, 0);
-                       dev_kfree_skb(skb);
-                       rrpriv->rx_skbuff[i] = NULL;
-               }
-       }
-}
-
-static void rr_timer(unsigned long data)
-{
-       struct net_device *dev = (struct net_device *)data;
-       struct rr_private *rrpriv = netdev_priv(dev);
-       struct rr_regs __iomem *regs = rrpriv->regs;
-       unsigned long flags;
-
-       if (readl(&regs->HostCtrl) & NIC_HALTED){
-               printk("%s: Restarting nic\n", dev->name);
-               memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl));
-               memset(rrpriv->info, 0, sizeof(struct rr_info));
-               wmb();
-
-               rr_raz_tx(rrpriv, dev);
-               rr_raz_rx(rrpriv, dev);
-
-               if (rr_init1(dev)) {
-                       spin_lock_irqsave(&rrpriv->lock, flags);
-                       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT,
-                              &regs->HostCtrl);
-                       spin_unlock_irqrestore(&rrpriv->lock, flags);
-               }
-       }
-       rrpriv->timer.expires = RUN_AT(5*HZ);
-       add_timer(&rrpriv->timer);
-}
-
-
-static int rr_open(struct net_device *dev)
-{
-       struct rr_private *rrpriv = netdev_priv(dev);
-       struct pci_dev *pdev = rrpriv->pci_dev;
-       struct rr_regs __iomem *regs;
-       int ecode = 0;
-       unsigned long flags;
-       dma_addr_t dma_addr;
-
-       regs = rrpriv->regs;
-
-       if (rrpriv->fw_rev < 0x00020000) {
-               printk(KERN_WARNING "%s: trying to configure device with "
-                      "obsolete firmware\n", dev->name);
-               ecode = -EBUSY;
-               goto error;
-       }
-
-       rrpriv->rx_ctrl = pci_alloc_consistent(pdev,
-                                              256 * sizeof(struct ring_ctrl),
-                                              &dma_addr);
-       if (!rrpriv->rx_ctrl) {
-               ecode = -ENOMEM;
-               goto error;
-       }
-       rrpriv->rx_ctrl_dma = dma_addr;
-       memset(rrpriv->rx_ctrl, 0, 256*sizeof(struct ring_ctrl));
-
-       rrpriv->info = pci_alloc_consistent(pdev, sizeof(struct rr_info),
-                                           &dma_addr);
-       if (!rrpriv->info) {
-               ecode = -ENOMEM;
-               goto error;
-       }
-       rrpriv->info_dma = dma_addr;
-       memset(rrpriv->info, 0, sizeof(struct rr_info));
-       wmb();
-
-       spin_lock_irqsave(&rrpriv->lock, flags);
-       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);
-       readl(&regs->HostCtrl);
-       spin_unlock_irqrestore(&rrpriv->lock, flags);
-
-       if (request_irq(dev->irq, rr_interrupt, IRQF_SHARED, dev->name, dev)) {
-               printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
-                      dev->name, dev->irq);
-               ecode = -EAGAIN;
-               goto error;
-       }
-
-       if ((ecode = rr_init1(dev)))
-               goto error;
-
-       /* Set the timer to switch to check for link beat and perhaps switch
-          to an alternate media type. */
-       init_timer(&rrpriv->timer);
-       rrpriv->timer.expires = RUN_AT(5*HZ);           /* 5 sec. watchdog */
-       rrpriv->timer.data = (unsigned long)dev;
-       rrpriv->timer.function = rr_timer;               /* timer handler */
-       add_timer(&rrpriv->timer);
-
-       netif_start_queue(dev);
-
-       return ecode;
-
- error:
-       spin_lock_irqsave(&rrpriv->lock, flags);
-       writel(readl(&regs->HostCtrl)|HALT_NIC|RR_CLEAR_INT, &regs->HostCtrl);
-       spin_unlock_irqrestore(&rrpriv->lock, flags);
-
-       if (rrpriv->info) {
-               pci_free_consistent(pdev, sizeof(struct rr_info), rrpriv->info,
-                                   rrpriv->info_dma);
-               rrpriv->info = NULL;
-       }
-       if (rrpriv->rx_ctrl) {
-               pci_free_consistent(pdev, sizeof(struct ring_ctrl),
-                                   rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
-               rrpriv->rx_ctrl = NULL;
-       }
-
-       netif_stop_queue(dev);
-
-       return ecode;
-}
-
-
-static void rr_dump(struct net_device *dev)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       u32 index, cons;
-       short i;
-       int len;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       printk("%s: dumping NIC TX rings\n", dev->name);
-
-       printk("RxPrd %08x, TxPrd %02x, EvtPrd %08x, TxPi %02x, TxCtrlPi %02x\n",
-              readl(&regs->RxPrd), readl(&regs->TxPrd),
-              readl(&regs->EvtPrd), readl(&regs->TxPi),
-              rrpriv->info->tx_ctrl.pi);
-
-       printk("Error code 0x%x\n", readl(&regs->Fail1));
-
-       index = (((readl(&regs->EvtPrd) >> 8) & 0xff) - 1) % TX_RING_ENTRIES;
-       cons = rrpriv->dirty_tx;
-       printk("TX ring index %i, TX consumer %i\n",
-              index, cons);
-
-       if (rrpriv->tx_skbuff[index]){
-               len = min_t(int, 0x80, rrpriv->tx_skbuff[index]->len);
-               printk("skbuff for index %i is valid - dumping data (0x%x bytes - DMA len 0x%x)\n", index, len, rrpriv->tx_ring[index].size);
-               for (i = 0; i < len; i++){
-                       if (!(i & 7))
-                               printk("\n");
-                       printk("%02x ", (unsigned char) rrpriv->tx_skbuff[index]->data[i]);
-               }
-               printk("\n");
-       }
-
-       if (rrpriv->tx_skbuff[cons]){
-               len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len);
-               printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len);
-               printk("mode 0x%x, size 0x%x,\n phys %08Lx, skbuff-addr %08lx, truesize 0x%x\n",
-                      rrpriv->tx_ring[cons].mode,
-                      rrpriv->tx_ring[cons].size,
-                      (unsigned long long) rrpriv->tx_ring[cons].addr.addrlo,
-                      (unsigned long)rrpriv->tx_skbuff[cons]->data,
-                      (unsigned int)rrpriv->tx_skbuff[cons]->truesize);
-               for (i = 0; i < len; i++){
-                       if (!(i & 7))
-                               printk("\n");
-                       printk("%02x ", (unsigned char)rrpriv->tx_ring[cons].size);
-               }
-               printk("\n");
-       }
-
-       printk("dumping TX ring info:\n");
-       for (i = 0; i < TX_RING_ENTRIES; i++)
-               printk("mode 0x%x, size 0x%x, phys-addr %08Lx\n",
-                      rrpriv->tx_ring[i].mode,
-                      rrpriv->tx_ring[i].size,
-                      (unsigned long long) rrpriv->tx_ring[i].addr.addrlo);
-
-}
-
-
-static int rr_close(struct net_device *dev)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       unsigned long flags;
-       u32 tmp;
-       short i;
-
-       netif_stop_queue(dev);
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       /*
-        * Lock to make sure we are not cleaning up while another CPU
-        * is handling interrupts.
-        */
-       spin_lock_irqsave(&rrpriv->lock, flags);
-
-       tmp = readl(&regs->HostCtrl);
-       if (tmp & NIC_HALTED){
-               printk("%s: NIC already halted\n", dev->name);
-               rr_dump(dev);
-       }else{
-               tmp |= HALT_NIC | RR_CLEAR_INT;
-               writel(tmp, &regs->HostCtrl);
-               readl(&regs->HostCtrl);
-       }
-
-       rrpriv->fw_running = 0;
-
-       del_timer_sync(&rrpriv->timer);
-
-       writel(0, &regs->TxPi);
-       writel(0, &regs->IpRxPi);
-
-       writel(0, &regs->EvtCon);
-       writel(0, &regs->EvtPrd);
-
-       for (i = 0; i < CMD_RING_ENTRIES; i++)
-               writel(0, &regs->CmdRing[i]);
-
-       rrpriv->info->tx_ctrl.entries = 0;
-       rrpriv->info->cmd_ctrl.pi = 0;
-       rrpriv->info->evt_ctrl.pi = 0;
-       rrpriv->rx_ctrl[4].entries = 0;
-
-       rr_raz_tx(rrpriv, dev);
-       rr_raz_rx(rrpriv, dev);
-
-       pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl),
-                           rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
-       rrpriv->rx_ctrl = NULL;
-
-       pci_free_consistent(rrpriv->pci_dev, sizeof(struct rr_info),
-                           rrpriv->info, rrpriv->info_dma);
-       rrpriv->info = NULL;
-
-       free_irq(dev->irq, dev);
-       spin_unlock_irqrestore(&rrpriv->lock, flags);
-
-       return 0;
-}
-
-
-static netdev_tx_t rr_start_xmit(struct sk_buff *skb,
-                                struct net_device *dev)
-{
-       struct rr_private *rrpriv = netdev_priv(dev);
-       struct rr_regs __iomem *regs = rrpriv->regs;
-       struct hippi_cb *hcb = (struct hippi_cb *) skb->cb;
-       struct ring_ctrl *txctrl;
-       unsigned long flags;
-       u32 index, len = skb->len;
-       u32 *ifield;
-       struct sk_buff *new_skb;
-
-       if (readl(&regs->Mode) & FATAL_ERR)
-               printk("error codes Fail1 %02x, Fail2 %02x\n",
-                      readl(&regs->Fail1), readl(&regs->Fail2));
-
-       /*
-        * We probably need to deal with tbusy here to prevent overruns.
-        */
-
-       if (skb_headroom(skb) < 8){
-               printk("incoming skb too small - reallocating\n");
-               if (!(new_skb = dev_alloc_skb(len + 8))) {
-                       dev_kfree_skb(skb);
-                       netif_wake_queue(dev);
-                       return NETDEV_TX_OK;
-               }
-               skb_reserve(new_skb, 8);
-               skb_put(new_skb, len);
-               skb_copy_from_linear_data(skb, new_skb->data, len);
-               dev_kfree_skb(skb);
-               skb = new_skb;
-       }
-
-       ifield = (u32 *)skb_push(skb, 8);
-
-       ifield[0] = 0;
-       ifield[1] = hcb->ifield;
-
-       /*
-        * We don't need the lock before we are actually going to start
-        * fiddling with the control blocks.
-        */
-       spin_lock_irqsave(&rrpriv->lock, flags);
-
-       txctrl = &rrpriv->info->tx_ctrl;
-
-       index = txctrl->pi;
-
-       rrpriv->tx_skbuff[index] = skb;
-       set_rraddr(&rrpriv->tx_ring[index].addr, pci_map_single(
-               rrpriv->pci_dev, skb->data, len + 8, PCI_DMA_TODEVICE));
-       rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */
-       rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END;
-       txctrl->pi = (index + 1) % TX_RING_ENTRIES;
-       wmb();
-       writel(txctrl->pi, &regs->TxPi);
-
-       if (txctrl->pi == rrpriv->dirty_tx){
-               rrpriv->tx_full = 1;
-               netif_stop_queue(dev);
-       }
-
-       spin_unlock_irqrestore(&rrpriv->lock, flags);
-
-       return NETDEV_TX_OK;
-}
-
-
-/*
- * Read the firmware out of the EEPROM and put it into the SRAM
- * (or from user space - later)
- *
- * This operation requires the NIC to be halted and is performed with
- * interrupts disabled and with the spinlock hold.
- */
-static int rr_load_firmware(struct net_device *dev)
-{
-       struct rr_private *rrpriv;
-       struct rr_regs __iomem *regs;
-       size_t eptr, segptr;
-       int i, j;
-       u32 localctrl, sptr, len, tmp;
-       u32 p2len, p2size, nr_seg, revision, io, sram_size;
-
-       rrpriv = netdev_priv(dev);
-       regs = rrpriv->regs;
-
-       if (dev->flags & IFF_UP)
-               return -EBUSY;
-
-       if (!(readl(&regs->HostCtrl) & NIC_HALTED)){
-               printk("%s: Trying to load firmware to a running NIC.\n",
-                      dev->name);
-               return -EBUSY;
-       }
-
-       localctrl = readl(&regs->LocalCtrl);
-       writel(0, &regs->LocalCtrl);
-
-       writel(0, &regs->EvtPrd);
-       writel(0, &regs->RxPrd);
-       writel(0, &regs->TxPrd);
-
-       /*
-        * First wipe the entire SRAM, otherwise we might run into all
-        * kinds of trouble ... sigh, this took almost all afternoon
-        * to track down ;-(
-        */
-       io = readl(&regs->ExtIo);
-       writel(0, &regs->ExtIo);
-       sram_size = rr_read_eeprom_word(rrpriv, 8);
-
-       for (i = 200; i < sram_size / 4; i++){
-               writel(i * 4, &regs->WinBase);
-               mb();
-               writel(0, &regs->WinData);
-               mb();
-       }
-       writel(io, &regs->ExtIo);
-       mb();
-
-       eptr = rr_read_eeprom_word(rrpriv,
-                      offsetof(struct eeprom, rncd_info.AddrRunCodeSegs));
-       eptr = ((eptr & 0x1fffff) >> 3);
-
-       p2len = rr_read_eeprom_word(rrpriv, 0x83*4);
-       p2len = (p2len << 2);
-       p2size = rr_read_eeprom_word(rrpriv, 0x84*4);
-       p2size = ((p2size & 0x1fffff) >> 3);
-
-       if ((eptr < p2size) || (eptr > (p2size + p2len))){
-               printk("%s: eptr is invalid\n", dev->name);
-               goto out;
-       }
-
-       revision = rr_read_eeprom_word(rrpriv,
-                       offsetof(struct eeprom, manf.HeaderFmt));
-
-       if (revision != 1){
-               printk("%s: invalid firmware format (%i)\n",
-                      dev->name, revision);
-               goto out;
-       }
-
-       nr_seg = rr_read_eeprom_word(rrpriv, eptr);
-       eptr +=4;
-#if (DEBUG > 1)
-       printk("%s: nr_seg %i\n", dev->name, nr_seg);
-#endif
-
-       for (i = 0; i < nr_seg; i++){
-               sptr = rr_read_eeprom_word(rrpriv, eptr);
-               eptr += 4;
-               len = rr_read_eeprom_word(rrpriv, eptr);
-               eptr += 4;
-               segptr = rr_read_eeprom_word(rrpriv, eptr);
-               segptr = ((segptr & 0x1fffff) >> 3);
-               eptr += 4;
-#if (DEBUG > 1)
-               printk("%s: segment %i, sram address %06x, length %04x, segptr %06x\n",
-                      dev->name, i, sptr, len, segptr);
-#endif
-               for (j = 0; j < len; j++){
-                       tmp = rr_read_eeprom_word(rrpriv, segptr);
-                       writel(sptr, &regs->WinBase);
-                       mb();
-                       writel(tmp, &regs->WinData);
-                       mb();
-                       segptr += 4;
-                       sptr += 4;
-               }
-       }
-
-out:
-       writel(localctrl, &regs->LocalCtrl);
-       mb();
-       return 0;
-}
-
-
-static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct rr_private *rrpriv;
-       unsigned char *image, *oldimage;
-       unsigned long flags;
-       unsigned int i;
-       int error = -EOPNOTSUPP;
-
-       rrpriv = netdev_priv(dev);
-
-       switch(cmd){
-       case SIOCRRGFW:
-               if (!capable(CAP_SYS_RAWIO)){
-                       return -EPERM;
-               }
-
-               image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-               if (!image){
-                       printk(KERN_ERR "%s: Unable to allocate memory "
-                              "for EEPROM image\n", dev->name);
-                       return -ENOMEM;
-               }
-
-
-               if (rrpriv->fw_running){
-                       printk("%s: Firmware already running\n", dev->name);
-                       error = -EPERM;
-                       goto gf_out;
-               }
-
-               spin_lock_irqsave(&rrpriv->lock, flags);
-               i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
-               spin_unlock_irqrestore(&rrpriv->lock, flags);
-               if (i != EEPROM_BYTES){
-                       printk(KERN_ERR "%s: Error reading EEPROM\n",
-                              dev->name);
-                       error = -EFAULT;
-                       goto gf_out;
-               }
-               error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
-               if (error)
-                       error = -EFAULT;
-       gf_out:
-               kfree(image);
-               return error;
-
-       case SIOCRRPFW:
-               if (!capable(CAP_SYS_RAWIO)){
-                       return -EPERM;
-               }
-
-               image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-               oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-               if (!image || !oldimage) {
-                       printk(KERN_ERR "%s: Unable to allocate memory "
-                              "for EEPROM image\n", dev->name);
-                       error = -ENOMEM;
-                       goto wf_out;
-               }
-
-               error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
-               if (error) {
-                       error = -EFAULT;
-                       goto wf_out;
-               }
-
-               if (rrpriv->fw_running){
-                       printk("%s: Firmware already running\n", dev->name);
-                       error = -EPERM;
-                       goto wf_out;
-               }
-
-               printk("%s: Updating EEPROM firmware\n", dev->name);
-
-               spin_lock_irqsave(&rrpriv->lock, flags);
-               error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
-               if (error)
-                       printk(KERN_ERR "%s: Error writing EEPROM\n",
-                              dev->name);
-
-               i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);
-               spin_unlock_irqrestore(&rrpriv->lock, flags);
-
-               if (i != EEPROM_BYTES)
-                       printk(KERN_ERR "%s: Error reading back EEPROM "
-                              "image\n", dev->name);
-
-               error = memcmp(image, oldimage, EEPROM_BYTES);
-               if (error){
-                       printk(KERN_ERR "%s: Error verifying EEPROM image\n",
-                              dev->name);
-                       error = -EFAULT;
-               }
-       wf_out:
-               kfree(oldimage);
-               kfree(image);
-               return error;
-
-       case SIOCRRID:
-               return put_user(0x52523032, (int __user *)rq->ifr_data);
-       default:
-               return error;
-       }
-}
-
-static DEFINE_PCI_DEVICE_TABLE(rr_pci_tbl) = {
-       { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       { 0,}
-};
-MODULE_DEVICE_TABLE(pci, rr_pci_tbl);
-
-static struct pci_driver rr_driver = {
-       .name           = "rrunner",
-       .id_table       = rr_pci_tbl,
-       .probe          = rr_init_one,
-       .remove         = __devexit_p(rr_remove_one),
-};
-
-static int __init rr_init_module(void)
-{
-       return pci_register_driver(&rr_driver);
-}
-
-static void __exit rr_cleanup_module(void)
-{
-       pci_unregister_driver(&rr_driver);
-}
-
-module_init(rr_init_module);
-module_exit(rr_cleanup_module);
diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h
deleted file mode 100644 (file)
index 2816904..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-#ifndef _RRUNNER_H_
-#define _RRUNNER_H_
-
-#include <linux/interrupt.h>
-
-#if ((BITS_PER_LONG != 32) && (BITS_PER_LONG != 64))
-#error "BITS_PER_LONG not defined or not valid"
-#endif
-
-
-struct rr_regs {
-
-       u32     pad0[16];
-
-       u32     HostCtrl;
-       u32     LocalCtrl;
-       u32     Pc;
-       u32     BrkPt;
-
-/* Timer increments every 0.97 micro-seconds (unsigned int) */
-       u32     Timer_Hi;
-       u32     Timer;
-       u32     TimerRef;
-       u32     PciState;
-
-       u32     Event;
-       u32     MbEvent;
-
-       u32     WinBase;
-       u32     WinData;
-       u32     RX_state;
-       u32     TX_state;
-
-       u32     Overhead;
-       u32     ExtIo;
-
-       u32     DmaWriteHostHi;
-       u32     DmaWriteHostLo;
-
-       u32     pad1[2];
-
-       u32     DmaReadHostHi;
-       u32     DmaReadHostLo;
-
-       u32     pad2;
-
-       u32     DmaReadLen;
-       u32     DmaWriteState;
-
-       u32     DmaWriteLcl;
-       u32     DmaWriteIPchecksum;
-       u32     DmaWriteLen;
-       u32     DmaReadState;
-       u32     DmaReadLcl;
-       u32     DmaReadIPchecksum;
-       u32     pad3;
-
-       u32     RxBase;
-       u32     RxPrd;
-       u32     RxCon;
-
-       u32     pad4;
-
-       u32     TxBase;
-       u32     TxPrd;
-       u32     TxCon;
-
-       u32     pad5;
-
-       u32     RxIndPro;
-       u32     RxIndCon;
-       u32     RxIndRef;
-
-       u32     pad6;
-
-       u32     TxIndPro;
-       u32     TxIndCon;
-       u32     TxIndRef;
-
-       u32     pad7[17];
-
-       u32     DrCmndPro;
-       u32     DrCmndCon;
-       u32     DrCmndRef;
-
-       u32     pad8;
-
-       u32     DwCmndPro;
-       u32     DwCmndCon;
-       u32     DwCmndRef;
-
-       u32     AssistState;
-
-       u32     DrDataPro;
-       u32     DrDataCon;
-       u32     DrDataRef;
-
-       u32     pad9;
-
-       u32     DwDataPro;
-       u32     DwDataCon;
-       u32     DwDataRef;
-
-       u32     pad10[33];
-
-       u32     EvtCon;
-
-       u32     pad11[5];
-
-       u32     TxPi;
-       u32     IpRxPi;
-
-       u32     pad11a[8];
-
-       u32     CmdRing[16];
-
-/* The ULA is in two registers the high order two bytes of the first
- * word contain the RunCode features.
- * ula0                res     res     byte0   byte1
- * ula1                byte2   byte3   byte4   byte5
- */
-       u32     Ula0;
-       u32     Ula1;
-
-       u32     RxRingHi;
-       u32     RxRingLo;
-
-       u32     InfoPtrHi;
-       u32     InfoPtrLo;
-
-       u32     Mode;
-
-       u32     ConRetry;
-       u32     ConRetryTmr;
-
-       u32     ConTmout;
-       u32     CtatTmr;
-
-       u32     MaxRxRng;
-
-       u32     IntrTmr;
-       u32     TxDataMvTimeout;
-       u32     RxDataMvTimeout;
-
-       u32     EvtPrd;
-       u32     TraceIdx;
-
-       u32     Fail1;
-       u32     Fail2;
-
-       u32     DrvPrm;
-
-       u32     FilterLA;
-
-       u32     FwRev;
-       u32     FwRes1;
-       u32     FwRes2;
-       u32     FwRes3;
-
-       u32     WriteDmaThresh;
-       u32     ReadDmaThresh;
-
-       u32     pad12[325];
-       u32     Window[512];
-};
-
-/*
- * Host control register bits.
- */
-
-#define RR_INT         0x01
-#define RR_CLEAR_INT   0x02
-#define NO_SWAP                0x04000004
-#define NO_SWAP1       0x00000004
-#define PCI_RESET_NIC  0x08
-#define HALT_NIC       0x10
-#define SSTEP_NIC      0x20
-#define MEM_READ_MULTI 0x40
-#define NIC_HALTED     0x100
-#define HALT_INST      0x200
-#define PARITY_ERR     0x400
-#define INVALID_INST_B 0x800
-#define RR_REV_2       0x20000000
-#define RR_REV_MASK    0xf0000000
-
-/*
- * Local control register bits.
- */
-
-#define INTA_STATE             0x01
-#define CLEAR_INTA             0x02
-#define FAST_EEPROM_ACCESS     0x08
-#define ENABLE_EXTRA_SRAM      0x100
-#define ENABLE_EXTRA_DESC      0x200
-#define ENABLE_PARITY          0x400
-#define FORCE_DMA_PARITY_ERROR 0x800
-#define ENABLE_EEPROM_WRITE    0x1000
-#define ENABLE_DATA_CACHE      0x2000
-#define SRAM_LO_PARITY_ERR     0x4000
-#define SRAM_HI_PARITY_ERR     0x8000
-
-/*
- * PCI state bits.
- */
-
-#define FORCE_PCI_RESET                0x01
-#define PROVIDE_LENGTH         0x02
-#define MASK_DMA_READ_MAX      0x1C
-#define RBURST_DISABLE         0x00
-#define RBURST_4               0x04
-#define RBURST_16              0x08
-#define RBURST_32              0x0C
-#define RBURST_64              0x10
-#define RBURST_128             0x14
-#define RBURST_256             0x18
-#define RBURST_1024            0x1C
-#define MASK_DMA_WRITE_MAX     0xE0
-#define WBURST_DISABLE         0x00
-#define WBURST_4               0x20
-#define WBURST_16              0x40
-#define WBURST_32              0x60
-#define WBURST_64              0x80
-#define WBURST_128             0xa0
-#define WBURST_256             0xc0
-#define WBURST_1024            0xe0
-#define MASK_MIN_DMA           0xFF00
-#define FIFO_RETRY_ENABLE      0x10000
-
-/*
- * Event register
- */
-
-#define DMA_WRITE_DONE         0x10000
-#define DMA_READ_DONE          0x20000
-#define DMA_WRITE_ERR          0x40000
-#define DMA_READ_ERR           0x80000
-
-/*
- * Receive state
- *
- * RoadRunner HIPPI Receive State Register controls and monitors the
- * HIPPI receive interface in the NIC. Look at err bits when a HIPPI
- * receive Error Event occurs.
- */
-
-#define ENABLE_NEW_CON         0x01
-#define RESET_RECV             0x02
-#define RECV_ALL               0x00
-#define RECV_1K                        0x20
-#define RECV_2K                        0x40
-#define RECV_4K                        0x60
-#define RECV_8K                        0x80
-#define RECV_16K               0xa0
-#define RECV_32K               0xc0
-#define RECV_64K               0xe0
-
-/*
- * Transmit status.
- */
-
-#define ENA_XMIT               0x01
-#define PERM_CON               0x02
-
-/*
- * DMA write state
- */
-
-#define RESET_DMA              0x01
-#define NO_SWAP_DMA            0x02
-#define DMA_ACTIVE             0x04
-#define THRESH_MASK            0x1F
-#define DMA_ERROR_MASK         0xff000000
-
-/*
- * Gooddies stored in the ULA registers.
- */
-
-#define TRACE_ON_WHAT_BIT      0x00020000    /* Traces on */
-#define ONEM_BUF_WHAT_BIT      0x00040000    /* 1Meg vs 256K */
-#define CHAR_API_WHAT_BIT      0x00080000    /* Char API vs network only */
-#define CMD_EVT_WHAT_BIT       0x00200000    /* Command event */
-#define LONG_TX_WHAT_BIT       0x00400000
-#define LONG_RX_WHAT_BIT       0x00800000
-#define WHAT_BIT_MASK          0xFFFD0000    /* Feature bit mask */
-
-/*
- * Mode status
- */
-
-#define EVENT_OVFL             0x80000000
-#define FATAL_ERR              0x40000000
-#define LOOP_BACK              0x01
-#define MODE_PH                        0x02
-#define MODE_FP                        0x00
-#define PTR64BIT               0x04
-#define PTR32BIT               0x00
-#define PTR_WD_SWAP            0x08
-#define PTR_WD_NOSWAP          0x00
-#define POST_WARN_EVENT                0x10
-#define ERR_TERM               0x20
-#define DIRECT_CONN            0x40
-#define NO_NIC_WATCHDOG                0x80
-#define SWAP_DATA              0x100
-#define SWAP_CONTROL           0x200
-#define NIC_HALT_ON_ERR                0x400
-#define NIC_NO_RESTART         0x800
-#define HALF_DUP_TX            0x1000
-#define HALF_DUP_RX            0x2000
-
-
-/*
- * Error codes
- */
-
-/* Host Error Codes - values of fail1 */
-#define ERR_UNKNOWN_MBOX       0x1001
-#define ERR_UNKNOWN_CMD                0x1002
-#define ERR_MAX_RING           0x1003
-#define ERR_RING_CLOSED                0x1004
-#define ERR_RING_OPEN          0x1005
-/* Firmware internal errors */
-#define ERR_EVENT_RING_FULL    0x01
-#define ERR_DW_PEND_CMND_FULL  0x02
-#define ERR_DR_PEND_CMND_FULL  0x03
-#define ERR_DW_PEND_DATA_FULL  0x04
-#define ERR_DR_PEND_DATA_FULL  0x05
-#define ERR_ILLEGAL_JUMP       0x06
-#define ERR_UNIMPLEMENTED      0x07
-#define ERR_TX_INFO_FULL       0x08
-#define ERR_RX_INFO_FULL       0x09
-#define ERR_ILLEGAL_MODE       0x0A
-#define ERR_MAIN_TIMEOUT       0x0B
-#define ERR_EVENT_BITS         0x0C
-#define ERR_UNPEND_FULL                0x0D
-#define ERR_TIMER_QUEUE_FULL   0x0E
-#define ERR_TIMER_QUEUE_EMPTY  0x0F
-#define ERR_TIMER_NO_FREE      0x10
-#define ERR_INTR_START         0x11
-#define ERR_BAD_STARTUP                0x12
-#define ERR_NO_PKT_END         0x13
-#define ERR_HALTED_ON_ERR      0x14
-/* Hardware NIC Errors */
-#define ERR_WRITE_DMA          0x0101
-#define ERR_READ_DMA           0x0102
-#define ERR_EXT_SERIAL         0x0103
-#define ERR_TX_INT_PARITY      0x0104
-
-
-/*
- * Event definitions
- */
-
-#define EVT_RING_ENTRIES       64
-#define EVT_RING_SIZE          (EVT_RING_ENTRIES * sizeof(struct event))
-
-struct event {
-#ifdef __LITTLE_ENDIAN
-       u16     index;
-       u8      ring;
-       u8      code;
-#else
-       u8      code;
-       u8      ring;
-       u16     index;
-#endif
-       u32     timestamp;
-};
-
-/*
- * General Events
- */
-
-#define E_NIC_UP       0x01
-#define E_WATCHDOG     0x02
-
-#define E_STAT_UPD     0x04
-#define E_INVAL_CMD    0x05
-#define E_SET_CMD_CONS 0x06
-#define E_LINK_ON      0x07
-#define E_LINK_OFF     0x08
-#define E_INTERN_ERR   0x09
-#define E_HOST_ERR     0x0A
-#define E_STATS_UPDATE 0x0B
-#define E_REJECTING    0x0C
-
-/*
- * Send  Events
- */
-#define E_CON_REJ      0x13
-#define E_CON_TMOUT    0x14
-#define E_CON_NC_TMOUT 0x15    /* I  , Connection No Campon Timeout */
-#define E_DISC_ERR     0x16
-#define E_INT_PRTY     0x17
-#define E_TX_IDLE      0x18
-#define E_TX_LINK_DROP 0x19
-#define E_TX_INV_RNG   0x1A
-#define E_TX_INV_BUF   0x1B
-#define E_TX_INV_DSC   0x1C
-
-/*
- * Destination Events
- */
-/*
- * General Receive events
- */
-#define E_VAL_RNG      0x20
-#define E_RX_RNG_ENER  0x21
-#define E_INV_RNG      0x22
-#define E_RX_RNG_SPC   0x23
-#define E_RX_RNG_OUT   0x24
-#define E_PKT_DISCARD  0x25
-#define E_INFO_EVT     0x27
-
-/*
- * Data corrupted events
- */
-#define E_RX_PAR_ERR   0x2B
-#define E_RX_LLRC_ERR  0x2C
-#define E_IP_CKSM_ERR  0x2D
-#define E_DTA_CKSM_ERR 0x2E
-#define E_SHT_BST      0x2F
-
-/*
- * Data lost events
- */
-#define E_LST_LNK_ERR  0x30
-#define E_FLG_SYN_ERR  0x31
-#define E_FRM_ERR      0x32
-#define E_RX_IDLE      0x33
-#define E_PKT_LN_ERR   0x34
-#define E_STATE_ERR    0x35
-#define E_UNEXP_DATA   0x3C
-
-/*
- * Fatal events
- */
-#define E_RX_INV_BUF   0x36
-#define E_RX_INV_DSC   0x37
-#define E_RNG_BLK      0x38
-
-/*
- * Warning events
- */
-#define E_RX_TO                0x39
-#define E_BFR_SPC      0x3A
-#define E_INV_ULP      0x3B
-
-#define E_NOT_IMPLEMENTED 0x40
-
-
-/*
- * Commands
- */
-
-#define CMD_RING_ENTRIES       16
-
-struct cmd {
-#ifdef __LITTLE_ENDIAN
-       u16     index;
-       u8      ring;
-       u8      code;
-#else
-       u8      code;
-       u8      ring;
-       u16     index;
-#endif
-};
-
-#define C_START_FW     0x01
-#define C_UPD_STAT     0x02
-#define C_WATCHDOG     0x05
-#define C_DEL_RNG      0x09
-#define C_NEW_RNG      0x0A
-#define C_CONN         0x0D
-
-
-/*
- * Mode bits
- */
-
-#define  PACKET_BAD            0x01 /* Packet had link-layer error */
-#define  INTERRUPT             0x02
-#define  TX_IP_CKSUM           0x04
-#define  PACKET_END            0x08
-#define  PACKET_START          0x10
-#define  SAME_IFIELD           0x80
-
-
-typedef struct {
-#if (BITS_PER_LONG == 64)
-       u64 addrlo;
-#else
-       u32 addrhi;
-       u32 addrlo;
-#endif
-} rraddr;
-
-
-static inline void set_rraddr(rraddr *ra, dma_addr_t addr)
-{
-       unsigned long baddr = addr;
-#if (BITS_PER_LONG == 64)
-       ra->addrlo = baddr;
-#else
-    /* Don't bother setting zero every time */
-       ra->addrlo = baddr;
-#endif
-       mb();
-}
-
-
-static inline void set_rxaddr(struct rr_regs __iomem *regs, volatile dma_addr_t addr)
-{
-       unsigned long baddr = addr;
-#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
-       writel(baddr & 0xffffffff, &regs->RxRingHi);
-       writel(baddr >> 32, &regs->RxRingLo);
-#elif (BITS_PER_LONG == 64)
-       writel(baddr >> 32, &regs->RxRingHi);
-       writel(baddr & 0xffffffff, &regs->RxRingLo);
-#else
-       writel(0, &regs->RxRingHi);
-       writel(baddr, &regs->RxRingLo);
-#endif
-       mb();
-}
-
-
-static inline void set_infoaddr(struct rr_regs __iomem *regs, volatile dma_addr_t addr)
-{
-       unsigned long baddr = addr;
-#if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN)
-       writel(baddr & 0xffffffff, &regs->InfoPtrHi);
-       writel(baddr >> 32, &regs->InfoPtrLo);
-#elif (BITS_PER_LONG == 64)
-       writel(baddr >> 32, &regs->InfoPtrHi);
-       writel(baddr & 0xffffffff, &regs->InfoPtrLo);
-#else
-       writel(0, &regs->InfoPtrHi);
-       writel(baddr, &regs->InfoPtrLo);
-#endif
-       mb();
-}
-
-
-/*
- * TX ring
- */
-
-#ifdef CONFIG_ROADRUNNER_LARGE_RINGS
-#define TX_RING_ENTRIES        32
-#else
-#define TX_RING_ENTRIES        16
-#endif
-#define TX_TOTAL_SIZE  (TX_RING_ENTRIES * sizeof(struct tx_desc))
-
-struct tx_desc{
-       rraddr  addr;
-       u32     res;
-#ifdef __LITTLE_ENDIAN
-       u16     size;
-       u8      pad;
-       u8      mode;
-#else
-       u8      mode;
-       u8      pad;
-       u16     size;
-#endif
-};
-
-
-#ifdef CONFIG_ROADRUNNER_LARGE_RINGS
-#define RX_RING_ENTRIES        32
-#else
-#define RX_RING_ENTRIES 16
-#endif
-#define RX_TOTAL_SIZE  (RX_RING_ENTRIES * sizeof(struct rx_desc))
-
-struct rx_desc{
-       rraddr  addr;
-       u32     res;
-#ifdef __LITTLE_ENDIAN
-       u16     size;
-       u8      pad;
-       u8      mode;
-#else
-       u8      mode;
-       u8      pad;
-       u16     size;
-#endif
-};
-
-
-/*
- * ioctl's
- */
-
-#define SIOCRRPFW      SIOCDEVPRIVATE          /* put firmware */
-#define SIOCRRGFW      SIOCDEVPRIVATE+1        /* get firmware */
-#define SIOCRRID       SIOCDEVPRIVATE+2        /* identify */
-
-
-struct seg_hdr {
-       u32     seg_start;
-       u32     seg_len;
-       u32     seg_eestart;
-};
-
-
-#define EEPROM_BASE 0x80000000
-#define EEPROM_WORDS 8192
-#define EEPROM_BYTES (EEPROM_WORDS * sizeof(u32))
-
-struct eeprom_boot {
-       u32     key1;
-       u32     key2;
-       u32     sram_size;
-       struct  seg_hdr loader;
-       u32     init_chksum;
-       u32     reserved1;
-};
-
-struct eeprom_manf {
-       u32     HeaderFmt;
-       u32     Firmware;
-       u32     BoardRevision;
-       u32     RoadrunnerRev;
-       char    OpticsPart[8];
-       u32     OpticsRev;
-       u32     pad1;
-       char    SramPart[8];
-       u32     SramRev;
-       u32     pad2;
-       char    EepromPart[8];
-       u32     EepromRev;
-       u32     EepromSize;
-       char    PalPart[8];
-       u32     PalRev;
-       u32     pad3;
-       char    PalCodeFile[12];
-       u32     PalCodeRev;
-       char    BoardULA[8];
-       char    SerialNo[8];
-       char    MfgDate[8];
-       char    MfgTime[8];
-       char    ModifyDate[8];
-       u32     ModCount;
-       u32     pad4[13];
-};
-
-
-struct eeprom_phase_info {
-       char    phase1File[12];
-       u32     phase1Rev;
-       char    phase1Date[8];
-       char    phase2File[12];
-       u32     phase2Rev;
-       char    phase2Date[8];
-       u32     reserved7[4];
-};
-
-struct eeprom_rncd_info {
-       u32     FwStart;
-       u32     FwRev;
-       char    FwDate[8];
-       u32     AddrRunCodeSegs;
-       u32     FileNames;
-       char    File[13][8];
-};
-
-
-/* Phase 1 region (starts are word offset 0x80) */
-struct phase1_hdr{
-       u32     jump;
-       u32     noop;
-       struct seg_hdr phase2Seg;
-};
-
-struct eeprom {
-       struct eeprom_boot      boot;
-       u32                     pad1[8];
-       struct eeprom_manf      manf;
-       struct eeprom_phase_info phase_info;
-       struct eeprom_rncd_info rncd_info;
-       u32                     pad2[15];
-       u32                     hdr_checksum;
-       struct phase1_hdr       phase1;
-};
-
-
-struct rr_stats {
-       u32     NicTimeStamp;
-       u32     RngCreated;
-       u32     RngDeleted;
-       u32     IntrGen;
-       u32     NEvtOvfl;
-       u32     InvCmd;
-       u32     DmaReadErrs;
-       u32     DmaWriteErrs;
-       u32     StatUpdtT;
-       u32     StatUpdtC;
-       u32     WatchDog;
-       u32     Trace;
-
-       /* Serial HIPPI */
-       u32     LnkRdyEst;
-       u32     GLinkErr;
-       u32     AltFlgErr;
-       u32     OvhdBit8Sync;
-       u32     RmtSerPrtyErr;
-       u32     RmtParPrtyErr;
-       u32     RmtLoopBk;
-       u32     pad1;
-
-       /* HIPPI tx */
-       u32     ConEst;
-       u32     ConRejS;
-       u32     ConRetry;
-       u32     ConTmOut;
-       u32     SndConDiscon;
-       u32     SndParErr;
-       u32     PktSnt;
-       u32     pad2[2];
-       u32     ShFBstSnt;
-       u64     BytSent;
-       u32     TxTimeout;
-       u32     pad3[3];
-
-       /* HIPPI rx */
-       u32     ConAcc;
-       u32     ConRejdiPrty;
-       u32     ConRejd64b;
-       u32     ConRejdBuf;
-       u32     RxConDiscon;
-       u32     RxConNoData;
-       u32     PktRx;
-       u32     pad4[2];
-       u32     ShFBstRx;
-       u64     BytRx;
-       u32     RxParErr;
-       u32     RxLLRCerr;
-       u32     RxBstSZerr;
-       u32     RxStateErr;
-       u32     RxRdyErr;
-       u32     RxInvULP;
-       u32     RxSpcBuf;
-       u32     RxSpcDesc;
-       u32     RxRngSpc;
-       u32     RxRngFull;
-       u32     RxPktLenErr;
-       u32     RxCksmErr;
-       u32     RxPktDrp;
-       u32     RngLowSpc;
-       u32     RngDataClose;
-       u32     RxTimeout;
-       u32     RxIdle;
-};
-
-
-/*
- * This struct is shared with the NIC firmware.
- */
-struct ring_ctrl {
-       rraddr  rngptr;
-#ifdef __LITTLE_ENDIAN
-       u16     entries;
-       u8      pad;
-       u8      entry_size;
-       u16     pi;
-       u16     mode;
-#else
-       u8      entry_size;
-       u8      pad;
-       u16     entries;
-       u16     mode;
-       u16     pi;
-#endif
-};
-
-struct rr_info {
-       union {
-               struct rr_stats stats;
-               u32 stati[128];
-       } s;
-       struct ring_ctrl        evt_ctrl;
-       struct ring_ctrl        cmd_ctrl;
-       struct ring_ctrl        tx_ctrl;
-       u8                      pad[464];
-       u8                      trace[3072];
-};
-
-/*
- * The linux structure for the RoadRunner.
- *
- * RX/TX descriptors are put first to make sure they are properly
- * aligned and do not cross cache-line boundaries.
- */
-
-struct rr_private
-{
-       struct rx_desc          *rx_ring;
-       struct tx_desc          *tx_ring;
-       struct event            *evt_ring;
-       dma_addr_t              tx_ring_dma;
-       dma_addr_t              rx_ring_dma;
-       dma_addr_t              evt_ring_dma;
-       /* Alignment ok ? */
-       struct sk_buff          *rx_skbuff[RX_RING_ENTRIES];
-       struct sk_buff          *tx_skbuff[TX_RING_ENTRIES];
-       struct rr_regs          __iomem *regs;          /* Register base */
-       struct ring_ctrl        *rx_ctrl;       /* Receive ring control */
-       struct rr_info          *info;          /* Shared info page */
-       dma_addr_t              rx_ctrl_dma;
-       dma_addr_t              info_dma;
-       spinlock_t              lock;
-       struct timer_list       timer;
-       u32                     cur_rx, cur_cmd, cur_evt;
-       u32                     dirty_rx, dirty_tx;
-       u32                     tx_full;
-       u32                     fw_rev;
-       volatile short          fw_running;
-       struct pci_dev          *pci_dev;
-};
-
-
-/*
- * Prototypes
- */
-static int rr_init(struct net_device *dev);
-static int rr_init1(struct net_device *dev);
-static irqreturn_t rr_interrupt(int irq, void *dev_id);
-
-static int rr_open(struct net_device *dev);
-static netdev_tx_t rr_start_xmit(struct sk_buff *skb,
-                                struct net_device *dev);
-static int rr_close(struct net_device *dev);
-static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static unsigned int rr_read_eeprom(struct rr_private *rrpriv,
-                                  unsigned long offset,
-                                  unsigned char *buf,
-                                  unsigned long length);
-static u32 rr_read_eeprom_word(struct rr_private *rrpriv, size_t offset);
-static int rr_load_firmware(struct net_device *dev);
-static inline void rr_raz_tx(struct rr_private *, struct net_device *);
-static inline void rr_raz_rx(struct rr_private *, struct net_device *);
-#endif /* _RRUNNER_H_ */
diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile
deleted file mode 100644 (file)
index b0be023..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Makefile for the SysKonnect FDDI PCI adapter driver
-#
-
-obj-$(CONFIG_SKFP) += skfp.o
-
-skfp-objs :=  skfddi.o    hwmtm.o    fplustm.o  smt.o      cfm.o     \
-              ecm.o       pcmplc.o   pmf.o      queue.o    rmt.o     \
-             smtdef.o    smtinit.o  smttimer.o srf.o      hwt.o     \
-             drvfbi.o   ess.o
-
-# NOTE:
-#   Compiling this driver produces some warnings (and some more are 
-#   switched off below), but I did not fix this, because the Hardware
-#   Module source (see skfddi.c for details) is used for different
-#   drivers, and fixing it for Linux might bring problems on other
-#   projects. To keep the source common for all those drivers (and
-#   thus simplify fixes to it), please do not clean it up!
-
-ccflags-y := -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes
diff --git a/drivers/net/skfp/cfm.c b/drivers/net/skfp/cfm.c
deleted file mode 100644 (file)
index e395ace..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT CFM
-       Configuration Management
-       DAS with single MAC
-*/
-
-/*
- *     Hardware independent state machine implemantation
- *     The following external SMT functions are referenced :
- *
- *             queue_event()
- *
- *     The following external HW dependent functions are referenced :
- *             config_mux()
- *
- *     The following HW dependent events are required :
- *             NONE 
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)cfm.c       2.18 98/10/06 (C) SK " ;
-#endif
-
-/*
- * FSM Macros
- */
-#define AFLAG  0x10
-#define GO_STATE(x)    (smc->mib.fddiSMTCF_State = (x)|AFLAG)
-#define ACTIONS_DONE() (smc->mib.fddiSMTCF_State &= ~AFLAG)
-#define ACTIONS(x)     (x|AFLAG)
-
-#ifdef DEBUG
-/*
- * symbolic state names
- */
-static const char * const cfm_states[] = {
-       "SC0_ISOLATED","CF1","CF2","CF3","CF4",
-       "SC1_WRAP_A","SC2_WRAP_B","SC5_TRHU_B","SC7_WRAP_S",
-       "SC9_C_WRAP_A","SC10_C_WRAP_B","SC11_C_WRAP_S","SC4_THRU_A"
-} ;
-
-/*
- * symbolic event names
- */
-static const char * const cfm_events[] = {
-       "NONE","CF_LOOP_A","CF_LOOP_B","CF_JOIN_A","CF_JOIN_B"
-} ;
-#endif
-
-/*
- * map from state to downstream port type
- */
-static const unsigned char cf_to_ptype[] = {
-       TNONE,TNONE,TNONE,TNONE,TNONE,
-       TNONE,TB,TB,TS,
-       TA,TB,TS,TB
-} ;
-
-/*
- * CEM port states
- */
-#define        CEM_PST_DOWN    0
-#define        CEM_PST_UP      1
-#define        CEM_PST_HOLD    2
-/* define portstate array only for A and B port */
-/* Do this within the smc structure (use in multiple cards) */
-
-/*
- * all Globals  are defined in smc.h
- * struct s_cfm
- */
-
-/*
- * function declarations
- */
-static void cfm_fsm(struct s_smc *smc, int cmd);
-
-/*
-       init CFM state machine
-       clear all CFM vars and flags
-*/
-void cfm_init(struct s_smc *smc)
-{
-       smc->mib.fddiSMTCF_State = ACTIONS(SC0_ISOLATED) ;
-       smc->r.rm_join = 0 ;
-       smc->r.rm_loop = 0 ;
-       smc->y[PA].scrub = 0 ;
-       smc->y[PB].scrub = 0 ;
-       smc->y[PA].cem_pst = CEM_PST_DOWN ;
-       smc->y[PB].cem_pst = CEM_PST_DOWN ;
-}
-
-/* Some terms conditions used by the selection criteria */
-#define THRU_ENABLED(smc)      (smc->y[PA].pc_mode != PM_TREE && \
-                                smc->y[PB].pc_mode != PM_TREE)
-/* Selection criteria for the ports */
-static void selection_criteria (struct s_smc *smc, struct s_phy *phy)
-{
-
-       switch (phy->mib->fddiPORTMy_Type) {
-       case TA:
-               if ( !THRU_ENABLED(smc) && smc->y[PB].cf_join ) {
-                       phy->wc_flag = TRUE ;
-               } else {
-                       phy->wc_flag = FALSE ;
-               }
-
-               break;
-       case TB:
-               /* take precedence over PA */
-               phy->wc_flag = FALSE ;
-               break;
-       case TS:
-               phy->wc_flag = FALSE ;
-               break;
-       case TM:
-               phy->wc_flag = FALSE ;
-               break;
-       }
-
-}
-
-void all_selection_criteria(struct s_smc *smc)
-{
-       struct s_phy    *phy ;
-       int             p ;
-
-       for ( p = 0,phy = smc->y ; p < NUMPHYS; p++, phy++ ) {
-               /* Do the selection criteria */
-               selection_criteria (smc,phy);
-       }
-}
-
-static void cem_priv_state(struct s_smc *smc, int event)
-/* State machine for private PORT states: used to optimize dual homing */
-{
-       int     np;     /* Number of the port */
-       int     i;
-
-       /* Do this only in a DAS */
-       if (smc->s.sas != SMT_DAS )
-               return ;
-
-       np = event - CF_JOIN;
-
-       if (np != PA && np != PB) {
-               return ;
-       }
-       /* Change the port state according to the event (portnumber) */
-       if (smc->y[np].cf_join) {
-               smc->y[np].cem_pst = CEM_PST_UP ;
-       } else if (!smc->y[np].wc_flag) {
-               /* set the port to done only if it is not withheld */
-               smc->y[np].cem_pst = CEM_PST_DOWN ;
-       }
-
-       /* Don't set an hold port to down */
-
-       /* Check all ports of restart conditions */
-       for (i = 0 ; i < 2 ; i ++ ) {
-               /* Check all port for PORT is on hold and no withhold is done */
-               if ( smc->y[i].cem_pst == CEM_PST_HOLD && !smc->y[i].wc_flag ) {
-                       smc->y[i].cem_pst = CEM_PST_DOWN;
-                       queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
-               }
-               if ( smc->y[i].cem_pst == CEM_PST_UP && smc->y[i].wc_flag ) {
-                       smc->y[i].cem_pst = CEM_PST_HOLD;
-                       queue_event(smc,(int)(EVENT_PCM+i),PC_START) ;
-               }
-               if ( smc->y[i].cem_pst == CEM_PST_DOWN && smc->y[i].wc_flag ) {
-                       /*
-                        * The port must be restarted when the wc_flag
-                        * will be reset. So set the port on hold.
-                        */
-                       smc->y[i].cem_pst = CEM_PST_HOLD;
-               }
-       }
-       return ;
-}
-
-/*
-       CFM state machine
-       called by dispatcher
-
-       do
-               display state change
-               process event
-       until SM is stable
-*/
-void cfm(struct s_smc *smc, int event)
-{
-       int     state ;         /* remember last state */
-       int     cond ;
-       int     oldstate ;
-
-       /* We will do the following: */
-       /*  - compute the variable WC_Flag for every port (This is where */
-       /*    we can extend the requested path checking !!) */
-       /*  - do the old (SMT 6.2 like) state machine */
-       /*  - do the resulting station states */
-
-       all_selection_criteria (smc);
-
-       /* We will check now whether a state transition is allowed or not */
-       /*  - change the portstates */
-       cem_priv_state (smc, event);
-
-       oldstate = smc->mib.fddiSMTCF_State ;
-       do {
-               DB_CFM("CFM : state %s%s",
-                       (smc->mib.fddiSMTCF_State & AFLAG) ? "ACTIONS " : "",
-                       cfm_states[smc->mib.fddiSMTCF_State & ~AFLAG]) ;
-               DB_CFM(" event %s\n",cfm_events[event],0) ;
-               state = smc->mib.fddiSMTCF_State ;
-               cfm_fsm(smc,event) ;
-               event = 0 ;
-       } while (state != smc->mib.fddiSMTCF_State) ;
-
-#ifndef        SLIM_SMT
-       /*
-        * check peer wrap condition
-        */
-       cond = FALSE ;
-       if (    (smc->mib.fddiSMTCF_State == SC9_C_WRAP_A &&
-               smc->y[PA].pc_mode == PM_PEER)  ||
-               (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B &&
-               smc->y[PB].pc_mode == PM_PEER)  ||
-               (smc->mib.fddiSMTCF_State == SC11_C_WRAP_S &&
-               smc->y[PS].pc_mode == PM_PEER &&
-               smc->y[PS].mib->fddiPORTNeighborType != TS ) ) {
-                       cond = TRUE ;
-       }
-       if (cond != smc->mib.fddiSMTPeerWrapFlag)
-               smt_srf_event(smc,SMT_COND_SMT_PEER_WRAP,0,cond) ;
-
-#if    0
-       /*
-        * Don't send ever MAC_PATH_CHANGE events. Our MAC is hard-wired
-        * to the primary path.
-        */
-       /*
-        * path change
-        */
-       if (smc->mib.fddiSMTCF_State != oldstate) {
-               smt_srf_event(smc,SMT_EVENT_MAC_PATH_CHANGE,INDEX_MAC,0) ;
-       }
-#endif
-#endif /* no SLIM_SMT */
-
-       /*
-        * set MAC port type
-        */
-       smc->mib.m[MAC0].fddiMACDownstreamPORTType =
-               cf_to_ptype[smc->mib.fddiSMTCF_State] ;
-       cfm_state_change(smc,(int)smc->mib.fddiSMTCF_State) ;
-}
-
-/*
-       process CFM event
-*/
-/*ARGSUSED1*/
-static void cfm_fsm(struct s_smc *smc, int cmd)
-{
-       switch(smc->mib.fddiSMTCF_State) {
-       case ACTIONS(SC0_ISOLATED) :
-               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
-               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
-               smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
-               smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
-               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;
-               config_mux(smc,MUX_ISOLATE) ;   /* configure PHY Mux */
-               smc->r.rm_loop = FALSE ;
-               smc->r.rm_join = FALSE ;
-               queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
-               /* Don't do the WC-Flag changing here */
-               ACTIONS_DONE() ;
-               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
-               break;
-       case SC0_ISOLATED :
-               /*SC07*/
-               /*SAS port can be PA or PB ! */
-               if (smc->s.sas && (smc->y[PA].cf_join || smc->y[PA].cf_loop ||
-                               smc->y[PB].cf_join || smc->y[PB].cf_loop)) {
-                       GO_STATE(SC11_C_WRAP_S) ;
-                       break ;
-               }
-               /*SC01*/
-               if ((smc->y[PA].cem_pst == CEM_PST_UP && smc->y[PA].cf_join &&
-                    !smc->y[PA].wc_flag) || smc->y[PA].cf_loop) {
-                       GO_STATE(SC9_C_WRAP_A) ;
-                       break ;
-               }
-               /*SC02*/
-               if ((smc->y[PB].cem_pst == CEM_PST_UP && smc->y[PB].cf_join &&
-                    !smc->y[PB].wc_flag) || smc->y[PB].cf_loop) {
-                       GO_STATE(SC10_C_WRAP_B) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(SC9_C_WRAP_A) :
-               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
-               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
-               smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
-               smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
-               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
-               config_mux(smc,MUX_WRAPA) ;             /* configure PHY mux */
-               if (smc->y[PA].cf_loop) {
-                       smc->r.rm_join = FALSE ;
-                       smc->r.rm_loop = TRUE ;
-                       queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
-               }
-               if (smc->y[PA].cf_join) {
-                       smc->r.rm_loop = FALSE ;
-                       smc->r.rm_join = TRUE ;
-                       queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
-               }
-               ACTIONS_DONE() ;
-               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
-               break ;
-       case SC9_C_WRAP_A :
-               /*SC10*/
-               if ( (smc->y[PA].wc_flag || !smc->y[PA].cf_join) &&
-                     !smc->y[PA].cf_loop ) {
-                       GO_STATE(SC0_ISOLATED) ;
-                       break ;
-               }
-               /*SC12*/
-               else if ( (smc->y[PB].cf_loop && smc->y[PA].cf_join &&
-                          smc->y[PA].cem_pst == CEM_PST_UP) ||
-                         ((smc->y[PB].cf_loop ||
-                          (smc->y[PB].cf_join &&
-                           smc->y[PB].cem_pst == CEM_PST_UP)) &&
-                           (smc->y[PA].pc_mode == PM_TREE ||
-                            smc->y[PB].pc_mode == PM_TREE))) {
-                       smc->y[PA].scrub = TRUE ;
-                       GO_STATE(SC10_C_WRAP_B) ;
-                       break ;
-               }
-               /*SC14*/
-               else if (!smc->s.attach_s &&
-                         smc->y[PA].cf_join &&
-                         smc->y[PA].cem_pst == CEM_PST_UP &&
-                         smc->y[PA].pc_mode == PM_PEER && smc->y[PB].cf_join &&
-                         smc->y[PB].cem_pst == CEM_PST_UP &&
-                         smc->y[PB].pc_mode == PM_PEER) {
-                       smc->y[PA].scrub = TRUE ;
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC4_THRU_A) ;
-                       break ;
-               }
-               /*SC15*/
-               else if ( smc->s.attach_s &&
-                         smc->y[PA].cf_join &&
-                         smc->y[PA].cem_pst == CEM_PST_UP &&
-                         smc->y[PA].pc_mode == PM_PEER &&
-                         smc->y[PB].cf_join &&
-                         smc->y[PB].cem_pst == CEM_PST_UP &&
-                         smc->y[PB].pc_mode == PM_PEER) {
-                       smc->y[PA].scrub = TRUE ;
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC5_THRU_B) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(SC10_C_WRAP_B) :
-               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
-               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
-               smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
-               smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
-               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
-               config_mux(smc,MUX_WRAPB) ;             /* configure PHY mux */
-               if (smc->y[PB].cf_loop) {
-                       smc->r.rm_join = FALSE ;
-                       smc->r.rm_loop = TRUE ;
-                       queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
-               }
-               if (smc->y[PB].cf_join) {
-                       smc->r.rm_loop = FALSE ;
-                       smc->r.rm_join = TRUE ;
-                       queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
-               }
-               ACTIONS_DONE() ;
-               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
-               break ;
-       case SC10_C_WRAP_B :
-               /*SC20*/
-               if ( !smc->y[PB].cf_join && !smc->y[PB].cf_loop ) {
-                       GO_STATE(SC0_ISOLATED) ;
-                       break ;
-               }
-               /*SC21*/
-               else if ( smc->y[PA].cf_loop && smc->y[PA].pc_mode == PM_PEER &&
-                         smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC9_C_WRAP_A) ;
-                       break ;
-               }
-               /*SC24*/
-               else if (!smc->s.attach_s &&
-                        smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
-                        smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
-                       smc->y[PA].scrub = TRUE ;
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC4_THRU_A) ;
-                       break ;
-               }
-               /*SC25*/
-               else if ( smc->s.attach_s &&
-                        smc->y[PA].cf_join && smc->y[PA].pc_mode == PM_PEER &&
-                        smc->y[PB].cf_join && smc->y[PB].pc_mode == PM_PEER) {
-                       smc->y[PA].scrub = TRUE ;
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC5_THRU_B) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(SC4_THRU_A) :
-               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
-               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
-               smc->mib.p[PA].fddiPORTMACPlacement = 0 ;
-               smc->mib.p[PB].fddiPORTMACPlacement = INDEX_MAC ;
-               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
-               config_mux(smc,MUX_THRUA) ;             /* configure PHY mux */
-               smc->r.rm_loop = FALSE ;
-               smc->r.rm_join = TRUE ;
-               queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
-               ACTIONS_DONE() ;
-               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
-               break ;
-       case SC4_THRU_A :
-               /*SC41*/
-               if (smc->y[PB].wc_flag || !smc->y[PB].cf_join) {
-                       smc->y[PA].scrub = TRUE ;
-                       GO_STATE(SC9_C_WRAP_A) ;
-                       break ;
-               }
-               /*SC42*/
-               else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC10_C_WRAP_B) ;
-                       break ;
-               }
-               /*SC45*/
-               else if (smc->s.attach_s) {
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC5_THRU_B) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(SC5_THRU_B) :
-               smc->mib.p[PA].fddiPORTCurrentPath = MIB_PATH_THRU ;
-               smc->mib.p[PB].fddiPORTCurrentPath = MIB_PATH_THRU ;
-               smc->mib.p[PA].fddiPORTMACPlacement = INDEX_MAC ;
-               smc->mib.p[PB].fddiPORTMACPlacement = 0 ;
-               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_THRU ;
-               config_mux(smc,MUX_THRUB) ;             /* configure PHY mux */
-               smc->r.rm_loop = FALSE ;
-               smc->r.rm_join = TRUE ;
-               queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
-               ACTIONS_DONE() ;
-               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
-               break ;
-       case SC5_THRU_B :
-               /*SC51*/
-               if (!smc->y[PB].cf_join || smc->y[PB].wc_flag) {
-                       smc->y[PA].scrub = TRUE ;
-                       GO_STATE(SC9_C_WRAP_A) ;
-                       break ;
-               }
-               /*SC52*/
-               else if (!smc->y[PA].cf_join || smc->y[PA].wc_flag) {
-                       smc->y[PB].scrub = TRUE ;
-                       GO_STATE(SC10_C_WRAP_B) ;
-                       break ;
-               }
-               /*SC54*/
-               else if (!smc->s.attach_s) {
-                       smc->y[PA].scrub = TRUE ;
-                       GO_STATE(SC4_THRU_A) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(SC11_C_WRAP_S) :
-               smc->mib.p[PS].fddiPORTCurrentPath = MIB_PATH_CONCATENATED ;
-               smc->mib.p[PS].fddiPORTMACPlacement = INDEX_MAC ;
-               smc->mib.fddiSMTStationStatus = MIB_SMT_STASTA_CON ;
-               config_mux(smc,MUX_WRAPS) ;             /* configure PHY mux */
-               if (smc->y[PA].cf_loop || smc->y[PB].cf_loop) {
-                       smc->r.rm_join = FALSE ;
-                       smc->r.rm_loop = TRUE ;
-                       queue_event(smc,EVENT_RMT,RM_LOOP) ;/* signal RMT */
-               }
-               if (smc->y[PA].cf_join || smc->y[PB].cf_join) {
-                       smc->r.rm_loop = FALSE ;
-                       smc->r.rm_join = TRUE ;
-                       queue_event(smc,EVENT_RMT,RM_JOIN) ;/* signal RMT */
-               }
-               ACTIONS_DONE() ;
-               DB_CFMN(1,"CFM : %s\n",cfm_states[smc->mib.fddiSMTCF_State],0) ;
-               break ;
-       case SC11_C_WRAP_S :
-               /*SC70*/
-               if ( !smc->y[PA].cf_join && !smc->y[PA].cf_loop &&
-                    !smc->y[PB].cf_join && !smc->y[PB].cf_loop) {
-                       GO_STATE(SC0_ISOLATED) ;
-                       break ;
-               }
-               break ;
-       default:
-               SMT_PANIC(smc,SMT_E0106, SMT_E0106_MSG) ;
-               break;
-       }
-}
-
-/*
- * get MAC's input Port
- *     return :
- *             PA or PB
- */
-int cfm_get_mac_input(struct s_smc *smc)
-{
-       return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
-               smc->mib.fddiSMTCF_State == SC5_THRU_B) ? PB : PA;
-}
-
-/*
- * get MAC's output Port
- *     return :
- *             PA or PB
- */
-int cfm_get_mac_output(struct s_smc *smc)
-{
-       return (smc->mib.fddiSMTCF_State == SC10_C_WRAP_B ||
-               smc->mib.fddiSMTCF_State == SC4_THRU_A) ? PB : PA;
-}
-
-static char path_iso[] = {
-       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_ISO,
-       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_ISO,
-       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_ISO
-} ;
-
-static char path_wrap_a[] = {
-       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_PRIM,
-       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
-       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_ISO
-} ;
-
-static char path_wrap_b[] = {
-       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_PRIM,
-       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
-       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_ISO
-} ;
-
-static char path_thru[] = {
-       0,0,    0,RES_PORT,     0,PA + INDEX_PORT,      0,PATH_PRIM,
-       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
-       0,0,    0,RES_PORT,     0,PB + INDEX_PORT,      0,PATH_PRIM
-} ;
-
-static char path_wrap_s[] = {
-       0,0,    0,RES_PORT,     0,PS + INDEX_PORT,      0,PATH_PRIM,
-       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_PRIM,
-} ;
-
-static char path_iso_s[] = {
-       0,0,    0,RES_PORT,     0,PS + INDEX_PORT,      0,PATH_ISO,
-       0,0,    0,RES_MAC,      0,INDEX_MAC,            0,PATH_ISO,
-} ;
-
-int cem_build_path(struct s_smc *smc, char *to, int path_index)
-{
-       char    *path ;
-       int     len ;
-
-       switch (smc->mib.fddiSMTCF_State) {
-       default :
-       case SC0_ISOLATED :
-               path = smc->s.sas ? path_iso_s : path_iso ;
-               len = smc->s.sas ? sizeof(path_iso_s) :  sizeof(path_iso) ;
-               break ;
-       case SC9_C_WRAP_A :
-               path = path_wrap_a ;
-               len = sizeof(path_wrap_a) ;
-               break ;
-       case SC10_C_WRAP_B :
-               path = path_wrap_b ;
-               len = sizeof(path_wrap_b) ;
-               break ;
-       case SC4_THRU_A :
-               path = path_thru ;
-               len = sizeof(path_thru) ;
-               break ;
-       case SC11_C_WRAP_S :
-               path = path_wrap_s ;
-               len = sizeof(path_wrap_s) ;
-               break ;
-       }
-       memcpy(to,path,len) ;
-
-       LINT_USE(path_index);
-
-       return len;
-}
diff --git a/drivers/net/skfp/drvfbi.c b/drivers/net/skfp/drvfbi.c
deleted file mode 100644 (file)
index 07da97c..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * FBI board dependent Driver for SMT and LLC
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/supern_2.h"
-#include "h/skfbiinc.h"
-#include <linux/bitrev.h>
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)drvfbi.c    1.63 99/02/11 (C) SK " ;
-#endif
-
-/*
- * PCM active state
- */
-#define PC8_ACTIVE     8
-
-#define        LED_Y_ON        0x11    /* Used for ring up/down indication */
-#define        LED_Y_OFF       0x10
-
-
-#define MS2BCLK(x)     ((x)*12500L)
-
-/*
- * valid configuration values are:
- */
-
-/*
- *     xPOS_ID:xxxx
- *     |       \  /
- *     |        \/
- *     |         --------------------- the patched POS_ID of the Adapter
- *     |                               xxxx = (Vendor ID low byte,
- *     |                                       Vendor ID high byte,
- *     |                                       Device ID low byte,
- *     |                                       Device ID high byte)
- *     +------------------------------ the patched oem_id must be
- *                                     'S' for SK or 'I' for IBM
- *                                     this is a short id for the driver.
- */
-#ifndef MULT_OEM
-#ifndef        OEM_CONCEPT
-const u_char oem_id[] = "xPOS_ID:xxxx" ;
-#else  /* OEM_CONCEPT */
-const u_char oem_id[] = OEM_ID ;
-#endif /* OEM_CONCEPT */
-#define        ID_BYTE0        8
-#define        OEMID(smc,i)    oem_id[ID_BYTE0 + i]
-#else  /* MULT_OEM */
-const struct s_oem_ids oem_ids[] = {
-#include "oemids.h"
-{0}
-};
-#define        OEMID(smc,i)    smc->hw.oem_id->oi_id[i]
-#endif /* MULT_OEM */
-
-/* Prototypes of external functions */
-#ifdef AIX
-extern int AIX_vpdReadByte() ;
-#endif
-
-
-/* Prototype of a local function. */
-static void smt_stop_watchdog(struct s_smc *smc);
-
-/*
- * FDDI card reset
- */
-static void card_start(struct s_smc *smc)
-{
-       int i ;
-#ifdef PCI
-       u_char  rev_id ;
-       u_short word;
-#endif
-
-       smt_stop_watchdog(smc) ;
-
-#ifdef PCI
-       /*
-        * make sure no transfer activity is pending
-        */
-       outpw(FM_A(FM_MDREG1),FM_MINIT) ;
-       outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
-       hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
-       /*
-        * now reset everything
-        */
-       outp(ADDR(B0_CTRL),CTRL_RST_SET) ;      /* reset for all chips */
-       i = (int) inp(ADDR(B0_CTRL)) ;          /* do dummy read */
-       SK_UNUSED(i) ;                          /* Make LINT happy. */
-       outp(ADDR(B0_CTRL), CTRL_RST_CLR) ;
-
-       /*
-        * Reset all bits in the PCI STATUS register
-        */
-       outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_ON) ;     /* enable for writes */
-       word = inpw(PCI_C(PCI_STATUS)) ;
-       outpw(PCI_C(PCI_STATUS), word | PCI_ERRBITS) ;
-       outp(ADDR(B0_TST_CTRL), TST_CFG_WRITE_OFF) ;    /* disable writes */
-
-       /*
-        * Release the reset of all the State machines
-        * Release Master_Reset
-        * Release HPI_SM_Reset
-        */
-       outp(ADDR(B0_CTRL), CTRL_MRST_CLR|CTRL_HPI_CLR) ;
-
-       /*
-        * determine the adapter type
-        * Note: Do it here, because some drivers may call card_start() once
-        *       at very first before any other initialization functions is
-        *       executed.
-        */
-       rev_id = inp(PCI_C(PCI_REV_ID)) ;
-       if ((rev_id & 0xf0) == SK_ML_ID_1 || (rev_id & 0xf0) == SK_ML_ID_2) {
-               smc->hw.hw_is_64bit = TRUE ;
-       } else {
-               smc->hw.hw_is_64bit = FALSE ;
-       }
-
-       /*
-        * Watermark initialization
-        */
-       if (!smc->hw.hw_is_64bit) {
-               outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
-               outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
-               outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
-       }
-
-       outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;      /* clear the reset chips */
-       outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_ON|LED_GB_OFF) ; /* ye LED on */
-
-       /* init the timer value for the watch dog 2,5 minutes */
-       outpd(ADDR(B2_WDOG_INI),0x6FC23AC0) ;
-
-       /* initialize the ISR mask */
-       smc->hw.is_imask = ISR_MASK ;
-       smc->hw.hw_state = STOPPED ;
-#endif
-       GET_PAGE(0) ;           /* necessary for BOOT */
-}
-
-void card_stop(struct s_smc *smc)
-{
-       smt_stop_watchdog(smc) ;
-       smc->hw.mac_ring_is_up = 0 ;            /* ring down */
-
-#ifdef PCI
-       /*
-        * make sure no transfer activity is pending
-        */
-       outpw(FM_A(FM_MDREG1),FM_MINIT) ;
-       outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
-       hwt_wait_time(smc,hwt_quick_read(smc),MS2BCLK(10)) ;
-       /*
-        * now reset everything
-        */
-       outp(ADDR(B0_CTRL),CTRL_RST_SET) ;      /* reset for all chips */
-       outp(ADDR(B0_CTRL),CTRL_RST_CLR) ;      /* reset for all chips */
-       outp(ADDR(B0_LED),LED_GA_OFF|LED_MY_OFF|LED_GB_OFF) ; /* all LEDs off */
-       smc->hw.hw_state = STOPPED ;
-#endif
-}
-/*--------------------------- ISR handling ----------------------------------*/
-
-void mac1_irq(struct s_smc *smc, u_short stu, u_short stl)
-{
-       int     restart_tx = 0 ;
-again:
-
-       /*
-        * parity error: note encoding error is not possible in tag mode
-        */
-       if (stl & (FM_SPCEPDS  |        /* parity err. syn.q.*/
-                  FM_SPCEPDA0 |        /* parity err. a.q.0 */
-                  FM_SPCEPDA1)) {      /* parity err. a.q.1 */
-               SMT_PANIC(smc,SMT_E0134, SMT_E0134_MSG) ;
-       }
-       /*
-        * buffer underrun: can only occur if a tx threshold is specified
-        */
-       if (stl & (FM_STBURS  |         /* tx buffer underrun syn.q.*/
-                  FM_STBURA0 |         /* tx buffer underrun a.q.0 */
-                  FM_STBURA1)) {       /* tx buffer underrun a.q.2 */
-               SMT_PANIC(smc,SMT_E0133, SMT_E0133_MSG) ;
-       }
-
-       if ( (stu & (FM_SXMTABT |               /* transmit abort */
-                    FM_STXABRS |               /* syn. tx abort */
-                    FM_STXABRA0)) ||           /* asyn. tx abort */
-            (stl & (FM_SQLCKS |                /* lock for syn. q. */
-                    FM_SQLCKA0)) ) {           /* lock for asyn. q. */
-               formac_tx_restart(smc) ;        /* init tx */
-               restart_tx = 1 ;
-               stu = inpw(FM_A(FM_ST1U)) ;
-               stl = inpw(FM_A(FM_ST1L)) ;
-               stu &= ~ (FM_STECFRMA0 | FM_STEFRMA0 | FM_STEFRMS) ;
-               if (stu || stl)
-                       goto again ;
-       }
-
-       if (stu & (FM_STEFRMA0 |        /* end of asyn tx */
-                   FM_STEFRMS)) {      /* end of sync tx */
-               restart_tx = 1 ;
-       }
-
-       if (restart_tx)
-               llc_restart_tx(smc) ;
-}
-
-/*
- * interrupt source= plc1
- * this function is called in nwfbisr.asm
- */
-void plc1_irq(struct s_smc *smc)
-{
-       u_short st = inpw(PLC(PB,PL_INTR_EVENT)) ;
-
-       plc_irq(smc,PB,st) ;
-}
-
-/*
- * interrupt source= plc2
- * this function is called in nwfbisr.asm
- */
-void plc2_irq(struct s_smc *smc)
-{
-       u_short st = inpw(PLC(PA,PL_INTR_EVENT)) ;
-
-       plc_irq(smc,PA,st) ;
-}
-
-
-/*
- * interrupt source= timer
- */
-void timer_irq(struct s_smc *smc)
-{
-       hwt_restart(smc);
-       smc->hw.t_stop = smc->hw.t_start;
-       smt_timer_done(smc) ;
-}
-
-/*
- * return S-port (PA or PB)
- */
-int pcm_get_s_port(struct s_smc *smc)
-{
-       SK_UNUSED(smc) ;
-       return PS;
-}
-
-/*
- * Station Label = "FDDI-XYZ" where
- *
- *     X = connector type
- *     Y = PMD type
- *     Z = port type
- */
-#define STATION_LABEL_CONNECTOR_OFFSET 5
-#define STATION_LABEL_PMD_OFFSET       6
-#define STATION_LABEL_PORT_OFFSET      7
-
-void read_address(struct s_smc *smc, u_char *mac_addr)
-{
-       char ConnectorType ;
-       char PmdType ;
-       int     i ;
-
-#ifdef PCI
-       for (i = 0; i < 6; i++) {       /* read mac address from board */
-               smc->hw.fddi_phys_addr.a[i] =
-                       bitrev8(inp(ADDR(B2_MAC_0+i)));
-       }
-#endif
-
-       ConnectorType = inp(ADDR(B2_CONN_TYP)) ;
-       PmdType = inp(ADDR(B2_PMD_TYP)) ;
-
-       smc->y[PA].pmd_type[PMD_SK_CONN] =
-       smc->y[PB].pmd_type[PMD_SK_CONN] = ConnectorType ;
-       smc->y[PA].pmd_type[PMD_SK_PMD ] =
-       smc->y[PB].pmd_type[PMD_SK_PMD ] = PmdType ;
-
-       if (mac_addr) {
-               for (i = 0; i < 6 ;i++) {
-                       smc->hw.fddi_canon_addr.a[i] = mac_addr[i] ;
-                       smc->hw.fddi_home_addr.a[i] = bitrev8(mac_addr[i]);
-               }
-               return ;
-       }
-       smc->hw.fddi_home_addr = smc->hw.fddi_phys_addr ;
-
-       for (i = 0; i < 6 ;i++) {
-               smc->hw.fddi_canon_addr.a[i] =
-                       bitrev8(smc->hw.fddi_phys_addr.a[i]);
-       }
-}
-
-/*
- * FDDI card soft reset
- */
-void init_board(struct s_smc *smc, u_char *mac_addr)
-{
-       card_start(smc) ;
-       read_address(smc,mac_addr) ;
-
-       if (!(inp(ADDR(B0_DAS)) & DAS_AVAIL))
-               smc->s.sas = SMT_SAS ;  /* Single att. station */
-       else
-               smc->s.sas = SMT_DAS ;  /* Dual att. station */
-
-       if (!(inp(ADDR(B0_DAS)) & DAS_BYP_ST))
-               smc->mib.fddiSMTBypassPresent = 0 ;
-               /* without opt. bypass */
-       else
-               smc->mib.fddiSMTBypassPresent = 1 ;
-               /* with opt. bypass */
-}
-
-/*
- * insert or deinsert optical bypass (called by ECM)
- */
-void sm_pm_bypass_req(struct s_smc *smc, int mode)
-{
-       DB_ECMN(1,"ECM : sm_pm_bypass_req(%s)\n",(mode == BP_INSERT) ?
-                                       "BP_INSERT" : "BP_DEINSERT",0) ;
-
-       if (smc->s.sas != SMT_DAS)
-               return ;
-
-#ifdef PCI
-       switch(mode) {
-       case BP_INSERT :
-               outp(ADDR(B0_DAS),DAS_BYP_INS) ;        /* insert station */
-               break ;
-       case BP_DEINSERT :
-               outp(ADDR(B0_DAS),DAS_BYP_RMV) ;        /* bypass station */
-               break ;
-       }
-#endif
-}
-
-/*
- * check if bypass connected
- */
-int sm_pm_bypass_present(struct s_smc *smc)
-{
-       return (inp(ADDR(B0_DAS)) & DAS_BYP_ST) ? TRUE : FALSE;
-}
-
-void plc_clear_irq(struct s_smc *smc, int p)
-{
-       SK_UNUSED(p) ;
-
-       SK_UNUSED(smc) ;
-}
-
-
-/*
- * led_indication called by rmt_indication() and
- * pcm_state_change()
- *
- * Input:
- *     smc:    SMT context
- *     led_event:
- *     0       Only switch green LEDs according to their respective PCM state
- *     LED_Y_OFF       just switch yellow LED off
- *     LED_Y_ON        just switch yello LED on
- */
-static void led_indication(struct s_smc *smc, int led_event)
-{
-       /* use smc->hw.mac_ring_is_up == TRUE 
-        * as indication for Ring Operational
-        */
-       u_short                 led_state ;
-       struct s_phy            *phy ;
-       struct fddi_mib_p       *mib_a ;
-       struct fddi_mib_p       *mib_b ;
-
-       phy = &smc->y[PA] ;
-       mib_a = phy->mib ;
-       phy = &smc->y[PB] ;
-       mib_b = phy->mib ;
-
-#ifdef PCI
-        led_state = 0 ;
-       
-       /* Ring up = yellow led OFF*/
-       if (led_event == LED_Y_ON) {
-               led_state |= LED_MY_ON ;
-       }
-       else if (led_event == LED_Y_OFF) {
-               led_state |= LED_MY_OFF ;
-       }
-       else {  /* PCM state changed */
-               /* Link at Port A/S = green led A ON */
-               if (mib_a->fddiPORTPCMState == PC8_ACTIVE) {    
-                       led_state |= LED_GA_ON ;
-               }
-               else {
-                       led_state |= LED_GA_OFF ;
-               }
-               
-               /* Link at Port B = green led B ON */
-               if (mib_b->fddiPORTPCMState == PC8_ACTIVE) {
-                       led_state |= LED_GB_ON ;
-               }
-               else {
-                       led_state |= LED_GB_OFF ;
-               }
-       }
-
-        outp(ADDR(B0_LED), led_state) ;
-#endif /* PCI */
-
-}
-
-
-void pcm_state_change(struct s_smc *smc, int plc, int p_state)
-{
-       /*
-        * the current implementation of pcm_state_change() in the driver
-        * parts must be renamed to drv_pcm_state_change() which will be called
-        * now after led_indication.
-        */
-       DRV_PCM_STATE_CHANGE(smc,plc,p_state) ;
-       
-       led_indication(smc,0) ;
-}
-
-
-void rmt_indication(struct s_smc *smc, int i)
-{
-       /* Call a driver special function if defined */
-       DRV_RMT_INDICATION(smc,i) ;
-
-        led_indication(smc, i ? LED_Y_OFF : LED_Y_ON) ;
-}
-
-
-/*
- * llc_recover_tx called by init_tx (fplus.c)
- */
-void llc_recover_tx(struct s_smc *smc)
-{
-#ifdef LOAD_GEN
-       extern  int load_gen_flag ;
-
-       load_gen_flag = 0 ;
-#endif
-#ifndef        SYNC
-       smc->hw.n_a_send= 0 ;
-#else
-       SK_UNUSED(smc) ;
-#endif
-}
-
-#ifdef MULT_OEM
-static int is_equal_num(char comp1[], char comp2[], int num)
-{
-       int i ;
-
-       for (i = 0 ; i < num ; i++) {
-               if (comp1[i] != comp2[i])
-                       return 0;
-       }
-               return 1;
-}      /* is_equal_num */
-
-
-/*
- * set the OEM ID defaults, and test the contents of the OEM data base
- * The default OEM is the first ACTIVE entry in the OEM data base 
- *
- * returns:    0       success
- *             1       error in data base
- *             2       data base empty
- *             3       no active entry 
- */
-int set_oi_id_def(struct s_smc *smc)
-{
-       int sel_id ;
-       int i ;
-       int act_entries ;
-
-       i = 0 ;
-       sel_id = -1 ;
-       act_entries = FALSE ;
-       smc->hw.oem_id = 0 ;
-       smc->hw.oem_min_status = OI_STAT_ACTIVE ;
-       
-       /* check OEM data base */
-       while (oem_ids[i].oi_status) {
-               switch (oem_ids[i].oi_status) {
-               case OI_STAT_ACTIVE:
-                       act_entries = TRUE ;    /* we have active IDs */
-                       if (sel_id == -1)
-                               sel_id = i ;    /* save the first active ID */
-               case OI_STAT_VALID:
-               case OI_STAT_PRESENT:
-                       i++ ;
-                       break ;                 /* entry ok */
-               default:
-                       return 1;               /* invalid oi_status */
-               }
-       }
-
-       if (i == 0)
-               return 2;
-       if (!act_entries)
-               return 3;
-
-       /* ok, we have a valid OEM data base with an active entry */
-       smc->hw.oem_id = (struct s_oem_ids *)  &oem_ids[sel_id] ;
-       return 0;
-}
-#endif /* MULT_OEM */
-
-void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr)
-{
-       int i ;
-
-       for (i = 0 ; i < 6 ; i++)
-               bia_addr->a[i] = bitrev8(smc->hw.fddi_phys_addr.a[i]);
-}
-
-void smt_start_watchdog(struct s_smc *smc)
-{
-       SK_UNUSED(smc) ;        /* Make LINT happy. */
-
-#ifndef        DEBUG
-
-#ifdef PCI
-       if (smc->hw.wdog_used) {
-               outpw(ADDR(B2_WDOG_CRTL),TIM_START) ;   /* Start timer. */
-       }
-#endif
-
-#endif /* DEBUG */
-}
-
-static void smt_stop_watchdog(struct s_smc *smc)
-{
-       SK_UNUSED(smc) ;        /* Make LINT happy. */
-#ifndef        DEBUG
-
-#ifdef PCI
-       if (smc->hw.wdog_used) {
-               outpw(ADDR(B2_WDOG_CRTL),TIM_STOP) ;    /* Stop timer. */
-       }
-#endif
-
-#endif /* DEBUG */
-}
-
-#ifdef PCI
-
-void mac_do_pci_fix(struct s_smc *smc)
-{
-       SK_UNUSED(smc) ;
-}
-#endif /* PCI */
-
diff --git a/drivers/net/skfp/ecm.c b/drivers/net/skfp/ecm.c
deleted file mode 100644 (file)
index 47d922c..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT ECM
-       Entity Coordination Management
-       Hardware independent state machine
-*/
-
-/*
- * Hardware independent state machine implemantation
- * The following external SMT functions are referenced :
- *
- *             queue_event()
- *             smt_timer_start()
- *             smt_timer_stop()
- *
- *     The following external HW dependent functions are referenced :
- *             sm_pm_bypass_req()
- *             sm_pm_ls_latch()
- *             sm_pm_get_ls()
- * 
- *     The following HW dependent events are required :
- *             NONE
- *
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)ecm.c       2.7 99/08/05 (C) SK " ;
-#endif
-
-/*
- * FSM Macros
- */
-#define AFLAG  0x10
-#define GO_STATE(x)    (smc->mib.fddiSMTECMState = (x)|AFLAG)
-#define ACTIONS_DONE() (smc->mib.fddiSMTECMState &= ~AFLAG)
-#define ACTIONS(x)     (x|AFLAG)
-
-#define EC0_OUT                0                       /* not inserted */
-#define EC1_IN         1                       /* inserted */
-#define EC2_TRACE      2                       /* tracing */
-#define EC3_LEAVE      3                       /* leaving the ring */
-#define EC4_PATH_TEST  4                       /* performing path test */
-#define EC5_INSERT     5                       /* bypass being turned on */
-#define EC6_CHECK      6                       /* checking bypass */
-#define EC7_DEINSERT   7                       /* bypass being turnde off */
-
-#ifdef DEBUG
-/*
- * symbolic state names
- */
-static const char * const ecm_states[] = {
-       "EC0_OUT","EC1_IN","EC2_TRACE","EC3_LEAVE","EC4_PATH_TEST",
-       "EC5_INSERT","EC6_CHECK","EC7_DEINSERT"
-} ;
-
-/*
- * symbolic event names
- */
-static const char * const ecm_events[] = {
-       "NONE","EC_CONNECT","EC_DISCONNECT","EC_TRACE_PROP","EC_PATH_TEST",
-       "EC_TIMEOUT_TD","EC_TIMEOUT_TMAX",
-       "EC_TIMEOUT_IMAX","EC_TIMEOUT_INMAX","EC_TEST_DONE"
-} ;
-#endif
-
-/*
- * all Globals  are defined in smc.h
- * struct s_ecm
- */
-
-/*
- * function declarations
- */
-
-static void ecm_fsm(struct s_smc *smc, int cmd);
-static void start_ecm_timer(struct s_smc *smc, u_long value, int event);
-static void stop_ecm_timer(struct s_smc *smc);
-static void prop_actions(struct s_smc *smc);
-
-/*
-       init ECM state machine
-       clear all ECM vars and flags
-*/
-void ecm_init(struct s_smc *smc)
-{
-       smc->e.path_test = PT_PASSED ;
-       smc->e.trace_prop = 0 ;
-       smc->e.sb_flag = 0 ;
-       smc->mib.fddiSMTECMState = ACTIONS(EC0_OUT) ;
-       smc->e.ecm_line_state = FALSE ;
-}
-
-/*
-       ECM state machine
-       called by dispatcher
-
-       do
-               display state change
-               process event
-       until SM is stable
-*/
-void ecm(struct s_smc *smc, int event)
-{
-       int     state ;
-
-       do {
-               DB_ECM("ECM : state %s%s",
-                       (smc->mib.fddiSMTECMState & AFLAG) ? "ACTIONS " : "",
-                       ecm_states[smc->mib.fddiSMTECMState & ~AFLAG]) ;
-               DB_ECM(" event %s\n",ecm_events[event],0) ;
-               state = smc->mib.fddiSMTECMState ;
-               ecm_fsm(smc,event) ;
-               event = 0 ;
-       } while (state != smc->mib.fddiSMTECMState) ;
-       ecm_state_change(smc,(int)smc->mib.fddiSMTECMState) ;
-}
-
-/*
-       process ECM event
-*/
-static void ecm_fsm(struct s_smc *smc, int cmd)
-{
-       int ls_a ;                      /* current line state PHY A */
-       int ls_b ;                      /* current line state PHY B */
-       int     p ;                     /* ports */
-
-
-       smc->mib.fddiSMTBypassPresent = sm_pm_bypass_present(smc) ;
-       if (cmd == EC_CONNECT)
-               smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
-
-       /* For AIX event notification: */
-       /* Is a disconnect  command remotely issued ? */
-       if (cmd == EC_DISCONNECT &&
-               smc->mib.fddiSMTRemoteDisconnectFlag == TRUE)
-               AIX_EVENT (smc, (u_long) CIO_HARD_FAIL, (u_long)
-                       FDDI_REMOTE_DISCONNECT, smt_get_event_word(smc),
-                       smt_get_error_word(smc) );
-
-       /*jd 05-Aug-1999 Bug #10419 "Port Disconnect fails at Dup MAc Cond."*/
-       if (cmd == EC_CONNECT) {
-               smc->e.DisconnectFlag = FALSE ;
-       }
-       else if (cmd == EC_DISCONNECT) {
-               smc->e.DisconnectFlag = TRUE ;
-       }
-       
-       switch(smc->mib.fddiSMTECMState) {
-       case ACTIONS(EC0_OUT) :
-               /*
-                * We do not perform a path test
-                */
-               smc->e.path_test = PT_PASSED ;
-               smc->e.ecm_line_state = FALSE ;
-               stop_ecm_timer(smc) ;
-               ACTIONS_DONE() ;
-               break ;
-       case EC0_OUT:
-               /*EC01*/
-               if (cmd == EC_CONNECT && !smc->mib.fddiSMTBypassPresent
-                       && smc->e.path_test==PT_PASSED) {
-                       GO_STATE(EC1_IN) ;
-                       break ;
-               }
-               /*EC05*/
-               else if (cmd == EC_CONNECT && (smc->e.path_test==PT_PASSED) &&
-                       smc->mib.fddiSMTBypassPresent &&
-                       (smc->s.sas == SMT_DAS)) {
-                       GO_STATE(EC5_INSERT) ;
-                       break ;
-               }
-               break;
-       case ACTIONS(EC1_IN) :
-               stop_ecm_timer(smc) ;
-               smc->e.trace_prop = 0 ;
-               sm_ma_control(smc,MA_TREQ) ;
-               for (p = 0 ; p < NUMPHYS ; p++)
-                       if (smc->mib.p[p].fddiPORTHardwarePresent)
-                               queue_event(smc,EVENT_PCMA+p,PC_START) ;
-               ACTIONS_DONE() ;
-               break ;
-       case EC1_IN:
-               /*EC12*/
-               if (cmd == EC_TRACE_PROP) {
-                       prop_actions(smc) ;
-                       GO_STATE(EC2_TRACE) ;
-                       break ;
-               }
-               /*EC13*/
-               else if (cmd == EC_DISCONNECT) {
-                       GO_STATE(EC3_LEAVE) ;
-                       break ;
-               }
-               break;
-       case ACTIONS(EC2_TRACE) :
-               start_ecm_timer(smc,MIB2US(smc->mib.fddiSMTTrace_MaxExpiration),
-                       EC_TIMEOUT_TMAX) ;
-               ACTIONS_DONE() ;
-               break ;
-       case EC2_TRACE :
-               /*EC22*/
-               if (cmd == EC_TRACE_PROP) {
-                       prop_actions(smc) ;
-                       GO_STATE(EC2_TRACE) ;
-                       break ;
-               }
-               /*EC23a*/
-               else if (cmd == EC_DISCONNECT) {
-                       smc->e.path_test = PT_EXITING ;
-                       GO_STATE(EC3_LEAVE) ;
-                       break ;
-               }
-               /*EC23b*/
-               else if (smc->e.path_test == PT_PENDING) {
-                       GO_STATE(EC3_LEAVE) ;
-                       break ;
-               }
-               /*EC23c*/
-               else if (cmd == EC_TIMEOUT_TMAX) {
-                       /* Trace_Max is expired */
-                       /* -> send AIX_EVENT */
-                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
-                               (u_long) FDDI_SMT_ERROR, (u_long)
-                               FDDI_TRACE_MAX, smt_get_error_word(smc));
-                       smc->e.path_test = PT_PENDING ;
-                       GO_STATE(EC3_LEAVE) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(EC3_LEAVE) :
-               start_ecm_timer(smc,smc->s.ecm_td_min,EC_TIMEOUT_TD) ;
-               for (p = 0 ; p < NUMPHYS ; p++)
-                       queue_event(smc,EVENT_PCMA+p,PC_STOP) ;
-               ACTIONS_DONE() ;
-               break ;
-       case EC3_LEAVE:
-               /*EC30*/
-               if (cmd == EC_TIMEOUT_TD && !smc->mib.fddiSMTBypassPresent &&
-                       (smc->e.path_test != PT_PENDING)) {
-                       GO_STATE(EC0_OUT) ;
-                       break ;
-               }
-               /*EC34*/
-               else if (cmd == EC_TIMEOUT_TD &&
-                       (smc->e.path_test == PT_PENDING)) {
-                       GO_STATE(EC4_PATH_TEST) ;
-                       break ;
-               }
-               /*EC31*/
-               else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
-                       GO_STATE(EC1_IN) ;
-                       break ;
-               }
-               /*EC33*/
-               else if (cmd == EC_DISCONNECT &&
-                       smc->e.path_test == PT_PENDING) {
-                       smc->e.path_test = PT_EXITING ;
-                       /*
-                        * stay in state - state will be left via timeout
-                        */
-               }
-               /*EC37*/
-               else if (cmd == EC_TIMEOUT_TD &&
-                       smc->mib.fddiSMTBypassPresent &&
-                       smc->e.path_test != PT_PENDING) {
-                       GO_STATE(EC7_DEINSERT) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(EC4_PATH_TEST) :
-               stop_ecm_timer(smc) ;
-               smc->e.path_test = PT_TESTING ;
-               start_ecm_timer(smc,smc->s.ecm_test_done,EC_TEST_DONE) ;
-               /* now perform path test ... just a simulation */
-               ACTIONS_DONE() ;
-               break ;
-       case EC4_PATH_TEST :
-               /* path test done delay */
-               if (cmd == EC_TEST_DONE)
-                       smc->e.path_test = PT_PASSED ;
-
-               if (smc->e.path_test == PT_FAILED)
-                       RS_SET(smc,RS_PATHTEST) ;
-
-               /*EC40a*/
-               if (smc->e.path_test == PT_FAILED &&
-                       !smc->mib.fddiSMTBypassPresent) {
-                       GO_STATE(EC0_OUT) ;
-                       break ;
-               }
-               /*EC40b*/
-               else if (cmd == EC_DISCONNECT &&
-                       !smc->mib.fddiSMTBypassPresent) {
-                       GO_STATE(EC0_OUT) ;
-                       break ;
-               }
-               /*EC41*/
-               else if (smc->e.path_test == PT_PASSED) {
-                       GO_STATE(EC1_IN) ;
-                       break ;
-               }
-               /*EC47a*/
-               else if (smc->e.path_test == PT_FAILED &&
-                       smc->mib.fddiSMTBypassPresent) {
-                       GO_STATE(EC7_DEINSERT) ;
-                       break ;
-               }
-               /*EC47b*/
-               else if (cmd == EC_DISCONNECT &&
-                       smc->mib.fddiSMTBypassPresent) {
-                       GO_STATE(EC7_DEINSERT) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(EC5_INSERT) :
-               sm_pm_bypass_req(smc,BP_INSERT);
-               start_ecm_timer(smc,smc->s.ecm_in_max,EC_TIMEOUT_INMAX) ;
-               ACTIONS_DONE() ;
-               break ;
-       case EC5_INSERT :
-               /*EC56*/
-               if (cmd == EC_TIMEOUT_INMAX) {
-                       GO_STATE(EC6_CHECK) ;
-                       break ;
-               }
-               /*EC57*/
-               else if (cmd == EC_DISCONNECT) {
-                       GO_STATE(EC7_DEINSERT) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(EC6_CHECK) :
-               /*
-                * in EC6_CHECK, we *POLL* the line state !
-                * check whether both bypass switches have switched.
-                */
-               start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
-               smc->e.ecm_line_state = TRUE ;  /* flag to pcm: report Q/HLS */
-               (void) sm_pm_ls_latch(smc,PA,1) ; /* enable line state latch */
-               (void) sm_pm_ls_latch(smc,PB,1) ; /* enable line state latch */
-               ACTIONS_DONE() ;
-               break ;
-       case EC6_CHECK :
-               ls_a = sm_pm_get_ls(smc,PA) ;
-               ls_b = sm_pm_get_ls(smc,PB) ;
-
-               /*EC61*/
-               if (((ls_a == PC_QLS) || (ls_a == PC_HLS)) &&
-                   ((ls_b == PC_QLS) || (ls_b == PC_HLS)) ) {
-                       smc->e.sb_flag = FALSE ;
-                       smc->e.ecm_line_state = FALSE ;
-                       GO_STATE(EC1_IN) ;
-                       break ;
-               }
-               /*EC66*/
-               else if (!smc->e.sb_flag &&
-                        (((ls_a == PC_ILS) && (ls_b == PC_QLS)) ||
-                         ((ls_a == PC_QLS) && (ls_b == PC_ILS)))){
-                       smc->e.sb_flag = TRUE ;
-                       DB_ECMN(1,"ECM : EC6_CHECK - stuck bypass\n",0,0) ;
-                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                               FDDI_SMT_ERROR, (u_long) FDDI_BYPASS_STUCK,
-                               smt_get_error_word(smc));
-               }
-               /*EC67*/
-               else if (cmd == EC_DISCONNECT) {
-                       smc->e.ecm_line_state = FALSE ;
-                       GO_STATE(EC7_DEINSERT) ;
-                       break ;
-               }
-               else {
-                       /*
-                        * restart poll
-                        */
-                       start_ecm_timer(smc,smc->s.ecm_check_poll,0) ;
-               }
-               break ;
-       case ACTIONS(EC7_DEINSERT) :
-               sm_pm_bypass_req(smc,BP_DEINSERT);
-               start_ecm_timer(smc,smc->s.ecm_i_max,EC_TIMEOUT_IMAX) ;
-               ACTIONS_DONE() ;
-               break ;
-       case EC7_DEINSERT:
-               /*EC70*/
-               if (cmd == EC_TIMEOUT_IMAX) {
-                       GO_STATE(EC0_OUT) ;
-                       break ;
-               }
-               /*EC75*/
-               else if (cmd == EC_CONNECT && smc->e.path_test == PT_PASSED) {
-                       GO_STATE(EC5_INSERT) ;
-                       break ;
-               }
-               break;
-       default:
-               SMT_PANIC(smc,SMT_E0107, SMT_E0107_MSG) ;
-               break;
-       }
-}
-
-#ifndef        CONCENTRATOR
-/*
- * trace propagation actions for SAS & DAS
- */
-static void prop_actions(struct s_smc *smc)
-{
-       int     port_in = 0 ;
-       int     port_out = 0 ;
-
-       RS_SET(smc,RS_EVENT) ;
-       switch (smc->s.sas) {
-       case SMT_SAS :
-               port_in = port_out = pcm_get_s_port(smc) ;
-               break ;
-       case SMT_DAS :
-               port_in = cfm_get_mac_input(smc) ;      /* PA or PB */
-               port_out = cfm_get_mac_output(smc) ;    /* PA or PB */
-               break ;
-       case SMT_NAC :
-               SMT_PANIC(smc,SMT_E0108, SMT_E0108_MSG) ;
-               return ;
-       }
-
-       DB_ECM("ECM : prop_actions - trace_prop %d\n", smc->e.trace_prop,0) ;
-       DB_ECM("ECM : prop_actions - in %d out %d\n", port_in,port_out) ;
-
-       if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
-               /* trace initiatior */
-               DB_ECM("ECM : initiate TRACE on PHY %c\n",'A'+port_in-PA,0) ;
-               queue_event(smc,EVENT_PCM+port_in,PC_TRACE) ;
-       }
-       else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PA))) &&
-               port_out != PA) {
-               /* trace propagate upstream */
-               DB_ECM("ECM : propagate TRACE on PHY B\n",0,0) ;
-               queue_event(smc,EVENT_PCMB,PC_TRACE) ;
-       }
-       else if ((smc->e.trace_prop & ENTITY_BIT(ENTITY_PHY(PB))) &&
-               port_out != PB) {
-               /* trace propagate upstream */
-               DB_ECM("ECM : propagate TRACE on PHY A\n",0,0) ;
-               queue_event(smc,EVENT_PCMA,PC_TRACE) ;
-       }
-       else {
-               /* signal trace termination */
-               DB_ECM("ECM : TRACE terminated\n",0,0) ;
-               smc->e.path_test = PT_PENDING ;
-       }
-       smc->e.trace_prop = 0 ;
-}
-#else
-/*
- * trace propagation actions for Concentrator
- */
-static void prop_actions(struct s_smc *smc)
-{
-       int     initiator ;
-       int     upstream ;
-       int     p ;
-
-       RS_SET(smc,RS_EVENT) ;
-       while (smc->e.trace_prop) {
-               DB_ECM("ECM : prop_actions - trace_prop %d\n",
-                       smc->e.trace_prop,0) ;
-
-               if (smc->e.trace_prop & ENTITY_BIT(ENTITY_MAC)) {
-                       initiator = ENTITY_MAC ;
-                       smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_MAC) ;
-                       DB_ECM("ECM: MAC initiates trace\n",0,0) ;
-               }
-               else {
-                       for (p = NUMPHYS-1 ; p >= 0 ; p--) {
-                               if (smc->e.trace_prop &
-                                       ENTITY_BIT(ENTITY_PHY(p)))
-                                       break ;
-                       }
-                       initiator = ENTITY_PHY(p) ;
-                       smc->e.trace_prop &= ~ENTITY_BIT(ENTITY_PHY(p)) ;
-               }
-               upstream = cem_get_upstream(smc,initiator) ;
-
-               if (upstream == ENTITY_MAC) {
-                       /* signal trace termination */
-                       DB_ECM("ECM : TRACE terminated\n",0,0) ;
-                       smc->e.path_test = PT_PENDING ;
-               }
-               else {
-                       /* trace propagate upstream */
-                       DB_ECM("ECM : propagate TRACE on PHY %d\n",upstream,0) ;
-                       queue_event(smc,EVENT_PCM+upstream,PC_TRACE) ;
-               }
-       }
-}
-#endif
-
-
-/*
- * SMT timer interface
- *     start ECM timer
- */
-static void start_ecm_timer(struct s_smc *smc, u_long value, int event)
-{
-       smt_timer_start(smc,&smc->e.ecm_timer,value,EV_TOKEN(EVENT_ECM,event));
-}
-
-/*
- * SMT timer interface
- *     stop ECM timer
- */
-static void stop_ecm_timer(struct s_smc *smc)
-{
-       if (smc->e.ecm_timer.tm_active)
-               smt_timer_stop(smc,&smc->e.ecm_timer) ;
-}
diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
deleted file mode 100644 (file)
index 2fc5987..0000000
+++ /dev/null
@@ -1,720 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * *******************************************************************
- * This SBA code implements the Synchronous Bandwidth Allocation
- * functions described in the "FDDI Synchronous Forum Implementer's
- * Agreement" dated December 1th, 1993.
- * *******************************************************************
- *
- *     PURPOSE: The purpose of this function is to control
- *              synchronous allocations on a single FDDI segment.
- *              Allocations are limited to the primary FDDI ring.
- *              The SBM provides recovery mechanisms to recover
- *              unused bandwidth also resolves T_Neg and
- *              reconfiguration changes. Many of the SBM state
- *              machine inputs are sourced by the underlying
- *              FDDI sub-system supporting the SBA application.
- *
- * *******************************************************************
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/smt_p.h"
-
-
-#ifndef        SLIM_SMT
-
-#ifdef ESS
-
-#ifndef lint
-static const char ID_sccs[] = "@(#)ess.c       1.10 96/02/23 (C) SK" ;
-#define LINT_USE(x)
-#else
-#define LINT_USE(x)    (x)=(x)
-#endif
-#define MS2BCLK(x)     ((x)*12500L)
-
-/*
-       -------------------------------------------------------------
-       LOCAL VARIABLES:
-       -------------------------------------------------------------
-*/
-
-static const u_short plist_raf_alc_res[] = { SMT_P0012, SMT_P320B, SMT_P320F,
-                                       SMT_P3210, SMT_P0019, SMT_P001A,
-                                       SMT_P001D, 0 } ;
-
-static const u_short plist_raf_chg_req[] = { SMT_P320B, SMT_P320F, SMT_P3210,
-                                       SMT_P001A, 0 } ;
-
-static const struct fddi_addr smt_sba_da = {{0x80,0x01,0x43,0x00,0x80,0x0C}} ;
-static const struct fddi_addr null_addr = {{0,0,0,0,0,0}} ;
-
-/*
-       -------------------------------------------------------------
-       GLOBAL VARIABLES:
-       -------------------------------------------------------------
-*/
-
-
-/*
-       -------------------------------------------------------------
-       LOCAL FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
-                             int sba_cmd);
-static void ess_config_fifo(struct s_smc *smc);
-static void ess_send_alc_req(struct s_smc *smc);
-static void ess_send_frame(struct s_smc *smc, SMbuf *mb);
-
-/*
-       -------------------------------------------------------------
-       EXTERNAL FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-/*
-       -------------------------------------------------------------
-       PUBLIC FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-void ess_timer_poll(struct s_smc *smc);
-void ess_para_change(struct s_smc *smc);
-int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
-                         int fs);
-static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead);
-
-
-/*
- * --------------------------------------------------------------------------
- *     End Station Support     (ESS)
- * --------------------------------------------------------------------------
- */
-
-/*
- * evaluate the RAF frame
- */
-int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
-                         int fs)
-{
-       void                    *p ;            /* universal pointer */
-       struct smt_p_0016       *cmd ;          /* para: command for the ESS */
-       SMbuf                   *db ;
-       u_long                  msg_res_type ;  /* recource type */
-       u_long                  payload, overhead ;
-       int                     local ;
-       int                     i ;
-
-       /*
-        * Message Processing Code
-        */
-        local = ((fs & L_INDICATOR) != 0) ;
-
-       /*
-        * get the resource type
-        */
-       if (!(p = (void *) sm_to_para(smc,sm,SMT_P0015))) {
-               DB_ESS("ESS: RAF frame error, parameter type not found\n",0,0) ;
-               return fs;
-       }
-       msg_res_type = ((struct smt_p_0015 *)p)->res_type ;
-
-       /*
-        * get the pointer to the ESS command
-        */
-       if (!(cmd = (struct smt_p_0016 *) sm_to_para(smc,sm,SMT_P0016))) {
-               /*
-                * error in frame: para ESS command was not found
-                */
-                DB_ESS("ESS: RAF frame error, parameter command not found\n",0,0);
-                return fs;
-       }
-
-       DB_ESSN(2,"fc %x        ft %x\n",sm->smt_class,sm->smt_type) ;
-       DB_ESSN(2,"ver %x       tran %lx\n",sm->smt_version,sm->smt_tid) ;
-       DB_ESSN(2,"stn_id %s\n",addr_to_string(&sm->smt_source),0) ;
-
-       DB_ESSN(2,"infolen %x   res %x\n",sm->smt_len, msg_res_type) ;
-       DB_ESSN(2,"sbacmd %x\n",cmd->sba_cmd,0) ;
-
-       /*
-        * evaluate the ESS command
-        */
-       switch (cmd->sba_cmd) {
-
-       /*
-        * Process an ESS Allocation Request
-        */
-       case REQUEST_ALLOCATION :
-               /*
-                * check for an RAF Request (Allocation Request)
-                */
-               if (sm->smt_type == SMT_REQUEST) {
-                       /*
-                        * process the Allocation request only if the frame is
-                        * local and no static allocation is used
-                        */
-                       if (!local || smc->mib.fddiESSPayload)
-                               return fs;
-                       
-                       p = (void *) sm_to_para(smc,sm,SMT_P0019)  ;
-                       for (i = 0; i < 5; i++) {
-                               if (((struct smt_p_0019 *)p)->alloc_addr.a[i]) {
-                                       return fs;
-                               }
-                       }
-
-                       /*
-                        * Note: The Application should send a LAN_LOC_FRAME.
-                        *       The ESS do not send the Frame to the network!
-                        */
-                       smc->ess.alloc_trans_id = sm->smt_tid ;
-                       DB_ESS("ESS: save Alloc Req Trans ID %lx\n",sm->smt_tid,0);
-                       p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
-                       ((struct smt_p_320f *)p)->mib_payload =
-                               smc->mib.a[PATH0].fddiPATHSbaPayload ;
-                       p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
-                       ((struct smt_p_3210 *)p)->mib_overhead =
-                               smc->mib.a[PATH0].fddiPATHSbaOverhead ;
-                       sm->smt_dest = smt_sba_da ;
-
-                       if (smc->ess.local_sba_active)
-                               return fs | I_INDICATOR;
-
-                       if (!(db = smt_get_mbuf(smc)))
-                               return fs;
-
-                       db->sm_len = mb->sm_len ;
-                       db->sm_off = mb->sm_off ;
-                       memcpy(((char *)(db->sm_data+db->sm_off)),(char *)sm,
-                               (int)db->sm_len) ;
-                       dump_smt(smc,
-                               (struct smt_header *)(db->sm_data+db->sm_off),
-                               "RAF") ;
-                       smt_send_frame(smc,db,FC_SMT_INFO,0) ;
-                       return fs;
-               }
-
-               /*
-                * The RAF frame is an Allocation Response !
-                * check the parameters
-                */
-               if (smt_check_para(smc,sm,plist_raf_alc_res)) {
-                       DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
-                       return fs;
-               }
-
-               /*
-                * VERIFY THE FRAME IS WELL BUILT:
-                *
-                *      1. path index = primary ring only
-                *      2. resource type = sync bw only
-                *      3. trans action id = alloc_trans_id
-                *      4. reason code = success
-                *
-                * If any are violated, discard the RAF frame
-                */
-               if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
-                       != PRIMARY_RING) ||
-                       (msg_res_type != SYNC_BW) ||
-               (((struct smt_p_reason *)sm_to_para(smc,sm,SMT_P0012))->rdf_reason
-                       != SMT_RDF_SUCCESS) ||
-                       (sm->smt_tid != smc->ess.alloc_trans_id)) {
-
-                       DB_ESS("ESS: Allocation Response not accepted\n",0,0) ;
-                       return fs;
-               }
-
-               /*
-                * Extract message parameters
-                */
-               p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
-                if (!p) {
-                        printk(KERN_ERR "ESS: sm_to_para failed");
-                        return fs;
-                }       
-               payload = ((struct smt_p_320f *)p)->mib_payload ;
-               p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
-                if (!p) {
-                        printk(KERN_ERR "ESS: sm_to_para failed");
-                        return fs;
-                }       
-               overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
-
-               DB_ESSN(2,"payload= %lx overhead= %lx\n",payload,overhead) ;
-
-               /*
-                * process the bandwidth allocation
-                */
-               (void)process_bw_alloc(smc,(long)payload,(long)overhead) ;
-
-               return fs;
-               /* end of Process Allocation Request */
-
-       /*
-        * Process an ESS Change Request
-        */
-       case CHANGE_ALLOCATION :
-               /*
-                * except only replies
-                */
-               if (sm->smt_type != SMT_REQUEST) {
-                       DB_ESS("ESS: Do not process Change Responses\n",0,0) ;
-                       return fs;
-               }
-
-               /*
-                * check the para for the Change Request
-                */
-               if (smt_check_para(smc,sm,plist_raf_chg_req)) {
-                       DB_ESS("ESS: RAF with para problem, ignoring\n",0,0) ;
-                       return fs;
-               }
-
-               /*
-                * Verify the path index and resource
-                * type are correct. If any of
-                * these are false, don't process this
-                * change request frame.
-                */
-               if ((((struct smt_p_320b *)sm_to_para(smc,sm,SMT_P320B))->path_index
-                       != PRIMARY_RING) || (msg_res_type != SYNC_BW)) {
-                       DB_ESS("ESS: RAF frame with para problem, ignoring\n",0,0) ;
-                       return fs;
-               }
-
-               /*
-                * Extract message queue parameters
-                */
-               p = (void *) sm_to_para(smc,sm,SMT_P320F) ;
-               payload = ((struct smt_p_320f *)p)->mib_payload ;
-               p = (void *) sm_to_para(smc,sm,SMT_P3210) ;
-               overhead = ((struct smt_p_3210 *)p)->mib_overhead ;
-
-               DB_ESSN(2,"ESS: Change Request from %s\n",
-                       addr_to_string(&sm->smt_source),0) ;
-               DB_ESSN(2,"payload= %lx overhead= %lx\n",payload,overhead) ;
-
-               /*
-                * process the bandwidth allocation
-                */
-               if(!process_bw_alloc(smc,(long)payload,(long)overhead))
-                       return fs;
-
-               /*
-                * send an RAF Change Reply
-                */
-               ess_send_response(smc,sm,CHANGE_ALLOCATION) ;
-
-               return fs;
-               /* end of Process Change Request */
-
-       /*
-        * Process Report Response
-        */
-       case REPORT_ALLOCATION :
-               /*
-                * except only requests
-                */
-               if (sm->smt_type != SMT_REQUEST) {
-                       DB_ESS("ESS: Do not process a Report Reply\n",0,0) ;
-                       return fs;
-               }
-
-               DB_ESSN(2,"ESS: Report Request from %s\n",
-                       addr_to_string(&(sm->smt_source)),0) ;
-
-               /*
-                * verify that the resource type is sync bw only
-                */
-               if (msg_res_type != SYNC_BW) {
-                       DB_ESS("ESS: ignoring RAF with para problem\n",0,0) ;
-                       return fs;
-               }
-
-               /*
-                * send an RAF Change Reply
-                */
-               ess_send_response(smc,sm,REPORT_ALLOCATION) ;
-
-               return fs;
-               /* end of Process Report Request */
-
-       default:
-               /*
-                * error in frame
-                */
-               DB_ESS("ESS: ignoring RAF with bad sba_cmd\n",0,0) ;
-               break ;
-       }
-
-       return fs;
-}
-
-/*
- * determines the synchronous bandwidth, set the TSYNC register and the
- * mib variables SBAPayload, SBAOverhead and fddiMACT-NEG.
- */
-static int process_bw_alloc(struct s_smc *smc, long int payload, long int overhead)
-{
-       /*
-        * determine the synchronous bandwidth (sync_bw) in bytes per T-NEG,
-        * if the payload is greater than zero.
-        * For the SBAPayload and the SBAOverhead we have the following
-        * unite quations
-        *                    _           _
-        *                   |       bytes |
-        *      SBAPayload = | 8000 ------ |
-        *                   |          s  |
-        *                    -           -
-        *                     _       _
-        *                    |  bytes  |
-        *      SBAOverhead = | ------  |
-        *                    |  T-NEG  |
-        *                     -       -
-        *
-        * T-NEG is described by the equation:
-        *
-        *                   (-) fddiMACT-NEG
-        *      T-NEG =     -------------------
-        *                      12500000 1/s
-        *
-        * The number of bytes we are able to send is the payload
-        * plus the overhead.
-        *
-        *                        bytes    T-NEG SBAPayload 8000 bytes/s
-        * sync_bw =  SBAOverhead ------ + -----------------------------
-        *                        T-NEG         T-NEG
-        *
-        *
-        *                           1
-        * sync_bw =  SBAOverhead + ---- (-)fddiMACT-NEG * SBAPayload
-        *                          1562
-        *
-        */
-
-       /*
-        * set the mib attributes fddiPATHSbaOverhead, fddiPATHSbaPayload
-        */
-/*     if (smt_set_obj(smc,SMT_P320F,payload,S_SET)) {
-               DB_ESS("ESS: SMT does not accept the payload value\n",0,0) ;
-               return FALSE;
-       }
-       if (smt_set_obj(smc,SMT_P3210,overhead,S_SET)) {
-               DB_ESS("ESS: SMT does not accept the overhead value\n",0,0) ;
-               return FALSE;
-       } */
-
-       /* premliminary */
-       if (payload > MAX_PAYLOAD || overhead > 5000) {
-               DB_ESS("ESS: payload / overhead not accepted\n",0,0) ;
-               return FALSE;
-       }
-
-       /*
-        * start the iterative allocation process if the payload or the overhead
-        * are smaller than the parsed values
-        */
-       if (smc->mib.fddiESSPayload &&
-               ((u_long)payload != smc->mib.fddiESSPayload ||
-               (u_long)overhead != smc->mib.fddiESSOverhead)) {
-               smc->ess.raf_act_timer_poll = TRUE ;
-               smc->ess.timer_count = 0 ;
-       }
-
-       /*
-        * evulate the Payload
-        */
-       if (payload) {
-               DB_ESSN(2,"ESS: turn SMT_ST_SYNC_SERVICE bit on\n",0,0) ;
-               smc->ess.sync_bw_available = TRUE ;
-
-               smc->ess.sync_bw = overhead -
-                       (long)smc->mib.m[MAC0].fddiMACT_Neg *
-                       payload / 1562 ;
-       }
-       else {
-               DB_ESSN(2,"ESS: turn SMT_ST_SYNC_SERVICE bit off\n",0,0) ;
-               smc->ess.sync_bw_available = FALSE ;
-               smc->ess.sync_bw = 0 ;
-               overhead = 0 ;
-       }
-
-       smc->mib.a[PATH0].fddiPATHSbaPayload = payload ;
-       smc->mib.a[PATH0].fddiPATHSbaOverhead = overhead ;
-
-
-       DB_ESSN(2,"tsync = %lx\n",smc->ess.sync_bw,0) ;
-
-       ess_config_fifo(smc) ;
-       set_formac_tsync(smc,smc->ess.sync_bw) ;
-       return TRUE;
-}
-
-static void ess_send_response(struct s_smc *smc, struct smt_header *sm,
-                             int sba_cmd)
-{
-       struct smt_sba_chg      *chg ;
-       SMbuf                   *mb ;
-       void                    *p ;
-
-       /*
-        * get and initialize the response frame
-        */
-       if (sba_cmd == CHANGE_ALLOCATION) {
-               if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
-                               sizeof(struct smt_sba_chg))))
-                               return ;
-       }
-       else {
-               if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
-                               sizeof(struct smt_sba_rep_res))))
-                               return ;
-       }
-
-       chg = smtod(mb,struct smt_sba_chg *) ;
-       chg->smt.smt_tid = sm->smt_tid ;
-       chg->smt.smt_dest = sm->smt_source ;
-
-       /* set P15 */
-       chg->s_type.para.p_type = SMT_P0015 ;
-       chg->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
-       chg->s_type.res_type = SYNC_BW ;
-
-       /* set P16 */
-       chg->cmd.para.p_type = SMT_P0016 ;
-       chg->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
-       chg->cmd.sba_cmd = sba_cmd ;
-
-       /* set P320B */
-       chg->path.para.p_type = SMT_P320B ;
-       chg->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
-       chg->path.mib_index = SBAPATHINDEX ;
-       chg->path.path_pad = 0;
-       chg->path.path_index = PRIMARY_RING ;
-
-       /* set P320F */
-       chg->payload.para.p_type = SMT_P320F ;
-       chg->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
-       chg->payload.mib_index = SBAPATHINDEX ;
-       chg->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
-
-       /* set P3210 */
-       chg->overhead.para.p_type = SMT_P3210 ;
-       chg->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
-       chg->overhead.mib_index = SBAPATHINDEX ;
-       chg->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
-
-       if (sba_cmd == CHANGE_ALLOCATION) {
-               /* set P1A */
-               chg->cat.para.p_type = SMT_P001A ;
-               chg->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
-               p = (void *) sm_to_para(smc,sm,SMT_P001A) ;
-               chg->cat.category = ((struct smt_p_001a *)p)->category ;
-       }
-       dump_smt(smc,(struct smt_header *)chg,"RAF") ;
-       ess_send_frame(smc,mb) ;
-}
-
-void ess_timer_poll(struct s_smc *smc)
-{
-       if (!smc->ess.raf_act_timer_poll)
-               return ;
-
-       DB_ESSN(2,"ESS: timer_poll\n",0,0) ;
-
-       smc->ess.timer_count++ ;
-       if (smc->ess.timer_count == 10) {
-               smc->ess.timer_count = 0 ;
-               ess_send_alc_req(smc) ;
-       }
-}
-
-static void ess_send_alc_req(struct s_smc *smc)
-{
-       struct smt_sba_alc_req *req ;
-       SMbuf   *mb ;
-
-       /*
-        * send never allocation request where the requested payload and
-        * overhead is zero or deallocate bandwidth when no bandwidth is
-        * parsed
-        */
-       if (!smc->mib.fddiESSPayload) {
-               smc->mib.fddiESSOverhead = 0 ;
-       }
-       else {
-               if (!smc->mib.fddiESSOverhead)
-                       smc->mib.fddiESSOverhead = DEFAULT_OV ;
-       }
-
-       if (smc->mib.fddiESSOverhead ==
-               smc->mib.a[PATH0].fddiPATHSbaOverhead &&
-               smc->mib.fddiESSPayload ==
-               smc->mib.a[PATH0].fddiPATHSbaPayload){
-               smc->ess.raf_act_timer_poll = FALSE ;
-               smc->ess.timer_count = 7 ;      /* next RAF alc req after 3 s */
-               return ;
-       }
-       
-       /*
-        * get and initialize the response frame
-        */
-       if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST,
-                       sizeof(struct smt_sba_alc_req))))
-                       return ;
-       req = smtod(mb,struct smt_sba_alc_req *) ;
-       req->smt.smt_tid = smc->ess.alloc_trans_id = smt_get_tid(smc) ;
-       req->smt.smt_dest = smt_sba_da ;
-
-       /* set P15 */
-       req->s_type.para.p_type = SMT_P0015 ;
-       req->s_type.para.p_len = sizeof(struct smt_p_0015) - PARA_LEN ;
-       req->s_type.res_type = SYNC_BW ;
-
-       /* set P16 */
-       req->cmd.para.p_type = SMT_P0016 ;
-       req->cmd.para.p_len = sizeof(struct smt_p_0016) - PARA_LEN ;
-       req->cmd.sba_cmd = REQUEST_ALLOCATION ;
-
-       /*
-        * set the parameter type and parameter length of all used
-        * parameters
-        */
-
-       /* set P320B */
-       req->path.para.p_type = SMT_P320B ;
-       req->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ;
-       req->path.mib_index = SBAPATHINDEX ;
-       req->path.path_pad = 0;
-       req->path.path_index = PRIMARY_RING ;
-
-       /* set P0017 */
-       req->pl_req.para.p_type = SMT_P0017 ;
-       req->pl_req.para.p_len = sizeof(struct smt_p_0017) - PARA_LEN ;
-       req->pl_req.sba_pl_req = smc->mib.fddiESSPayload -
-               smc->mib.a[PATH0].fddiPATHSbaPayload ;
-
-       /* set P0018 */
-       req->ov_req.para.p_type = SMT_P0018 ;
-       req->ov_req.para.p_len = sizeof(struct smt_p_0018) - PARA_LEN ;
-       req->ov_req.sba_ov_req = smc->mib.fddiESSOverhead -
-               smc->mib.a[PATH0].fddiPATHSbaOverhead ;
-
-       /* set P320F */
-       req->payload.para.p_type = SMT_P320F ;
-       req->payload.para.p_len = sizeof(struct smt_p_320f) - PARA_LEN ;
-       req->payload.mib_index = SBAPATHINDEX ;
-       req->payload.mib_payload = smc->mib.a[PATH0].fddiPATHSbaPayload ;
-
-       /* set P3210 */
-       req->overhead.para.p_type = SMT_P3210 ;
-       req->overhead.para.p_len = sizeof(struct smt_p_3210) - PARA_LEN ;
-       req->overhead.mib_index = SBAPATHINDEX ;
-       req->overhead.mib_overhead = smc->mib.a[PATH0].fddiPATHSbaOverhead ;
-
-       /* set P19 */
-       req->a_addr.para.p_type = SMT_P0019 ;
-       req->a_addr.para.p_len = sizeof(struct smt_p_0019) - PARA_LEN ;
-       req->a_addr.sba_pad = 0;
-       req->a_addr.alloc_addr = null_addr ;
-
-       /* set P1A */
-       req->cat.para.p_type = SMT_P001A ;
-       req->cat.para.p_len = sizeof(struct smt_p_001a) - PARA_LEN ;
-       req->cat.category = smc->mib.fddiESSCategory ;
-
-       /* set P1B */
-       req->tneg.para.p_type = SMT_P001B ;
-       req->tneg.para.p_len = sizeof(struct smt_p_001b) - PARA_LEN ;
-       req->tneg.max_t_neg = smc->mib.fddiESSMaxTNeg ;
-
-       /* set P1C */
-       req->segm.para.p_type = SMT_P001C ;
-       req->segm.para.p_len = sizeof(struct smt_p_001c) - PARA_LEN ;
-       req->segm.min_seg_siz = smc->mib.fddiESSMinSegmentSize ;
-
-       dump_smt(smc,(struct smt_header *)req,"RAF") ;
-       ess_send_frame(smc,mb) ;
-}
-
-static void ess_send_frame(struct s_smc *smc, SMbuf *mb)
-{
-       /*
-        * check if the frame must be send to the own ESS
-        */
-       if (smc->ess.local_sba_active) {
-               /*
-                * Send the Change Reply to the local SBA
-                */
-               DB_ESS("ESS:Send to the local SBA\n",0,0) ;
-               if (!smc->ess.sba_reply_pend)
-                       smc->ess.sba_reply_pend = mb ;
-               else {
-                       DB_ESS("Frame is lost - another frame was pending\n",0,0);
-                       smt_free_mbuf(smc,mb) ;
-               }
-       }
-       else {
-               /*
-                * Send the SBA RAF Change Reply to the network
-                */
-               DB_ESS("ESS:Send to the network\n",0,0) ;
-               smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
-       }
-}
-
-void ess_para_change(struct s_smc *smc)
-{
-       (void)process_bw_alloc(smc,(long)smc->mib.a[PATH0].fddiPATHSbaPayload,
-               (long)smc->mib.a[PATH0].fddiPATHSbaOverhead) ;
-}
-
-static void ess_config_fifo(struct s_smc *smc)
-{
-       /*
-        * if nothing to do exit 
-        */
-       if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
-               if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON &&
-                       (smc->hw.fp.fifo.fifo_config_mode&SEND_ASYNC_AS_SYNC) ==
-                       smc->mib.fddiESSSynchTxMode) {
-                       return ;
-               }
-       }
-       else {
-               if (!(smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON)) {
-                       return ;
-               }
-       }
-
-       /*
-        * split up the FIFO and reinitialize the queues
-        */
-       formac_reinit_tx(smc) ;
-}
-
-#endif /* ESS */
-
-#endif /* no SLIM_SMT */
-
diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
deleted file mode 100644 (file)
index a20ed1a..0000000
+++ /dev/null
@@ -1,1491 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * FORMAC+ Driver for tag mode
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/supern_2.h"
-#include <linux/bitrev.h>
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)fplustm.c   1.32 99/02/23 (C) SK " ;
-#endif
-
-#ifndef UNUSED
-#ifdef  lint
-#define UNUSED(x)      (x) = (x)
-#else
-#define UNUSED(x)
-#endif
-#endif
-
-#define FM_ADDRX        (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
-#define MS2BCLK(x)     ((x)*12500L)
-#define US2BCLK(x)     ((x)*1250L)
-
-/*
- * prototypes for static function
- */
-static void build_claim_beacon(struct s_smc *smc, u_long t_request);
-static int init_mac(struct s_smc *smc, int all);
-static void rtm_init(struct s_smc *smc);
-static void smt_split_up_fifo(struct s_smc *smc);
-
-#if (!defined(NO_SMT_PANIC) || defined(DEBUG))
-static char write_mdr_warning [] = "E350 write_mdr() FM_SNPPND is set\n";
-static char cam_warning [] = "E_SMT_004: CAM still busy\n";
-#endif
-
-#define        DUMMY_READ()    smc->hw.mc_dummy = (u_short) inp(ADDR(B0_RAP))
-
-#define        CHECK_NPP() {   unsigned k = 10000 ;\
-                       while ((inpw(FM_A(FM_STMCHN)) & FM_SNPPND) && k) k--;\
-                       if (!k) { \
-                               SMT_PANIC(smc,SMT_E0130, SMT_E0130_MSG) ; \
-                       }       \
-               }
-
-#define        CHECK_CAM() {   unsigned k = 10 ;\
-                       while (!(inpw(FM_A(FM_AFSTAT)) & FM_DONE) && k) k--;\
-                       if (!k) { \
-                               SMT_PANIC(smc,SMT_E0131, SMT_E0131_MSG) ; \
-                       }       \
-               }
-
-const struct fddi_addr fddi_broadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
-static const struct fddi_addr null_addr = {{0,0,0,0,0,0}};
-static const struct fddi_addr dbeacon_multi = {{0x01,0x80,0xc2,0x00,0x01,0x00}};
-
-static const u_short my_said = 0xffff ;        /* short address (n.u.) */
-static const u_short my_sagp = 0xffff ;        /* short group address (n.u.) */
-
-/*
- * define my address
- */
-#ifdef USE_CAN_ADDR
-#define MA     smc->hw.fddi_canon_addr
-#else
-#define MA     smc->hw.fddi_home_addr
-#endif
-
-
-/*
- * useful interrupt bits
- */
-static const int mac_imsk1u = FM_STXABRS | FM_STXABRA0 | FM_SXMTABT ;
-static const int mac_imsk1l = FM_SQLCKS | FM_SQLCKA0 | FM_SPCEPDS | FM_SPCEPDA0|
-                       FM_STBURS | FM_STBURA0 ;
-
-       /* delete FM_SRBFL after tests */
-static const int mac_imsk2u = FM_SERRSF | FM_SNFSLD | FM_SRCVOVR | FM_SRBFL |
-                       FM_SMYCLM ;
-static const int mac_imsk2l = FM_STRTEXR | FM_SDUPCLM | FM_SFRMCTR |
-                       FM_SERRCTR | FM_SLSTCTR |
-                       FM_STRTEXP | FM_SMULTDA | FM_SRNGOP ;
-
-static const int mac_imsk3u = FM_SRCVOVR2 | FM_SRBFL2 ;
-static const int mac_imsk3l = FM_SRPERRQ2 | FM_SRPERRQ1 ;
-
-static const int mac_beacon_imsk2u = FM_SOTRBEC | FM_SMYBEC | FM_SBEC |
-                       FM_SLOCLM | FM_SHICLM | FM_SMYCLM | FM_SCLM ;
-
-
-static u_long mac_get_tneg(struct s_smc *smc)
-{
-       u_long  tneg ;
-
-       tneg = (u_long)((long)inpw(FM_A(FM_TNEG))<<5) ;
-       return (u_long)((tneg + ((inpw(FM_A(FM_TMRS))>>10)&0x1f)) |
-               0xffe00000L) ;
-}
-
-void mac_update_counter(struct s_smc *smc)
-{
-       smc->mib.m[MAC0].fddiMACFrame_Ct =
-               (smc->mib.m[MAC0].fddiMACFrame_Ct & 0xffff0000L)
-               + (u_short) inpw(FM_A(FM_FCNTR)) ;
-       smc->mib.m[MAC0].fddiMACLost_Ct =
-               (smc->mib.m[MAC0].fddiMACLost_Ct & 0xffff0000L)
-               + (u_short) inpw(FM_A(FM_LCNTR)) ;
-       smc->mib.m[MAC0].fddiMACError_Ct =
-               (smc->mib.m[MAC0].fddiMACError_Ct & 0xffff0000L)
-               + (u_short) inpw(FM_A(FM_ECNTR)) ;
-       smc->mib.m[MAC0].fddiMACT_Neg = mac_get_tneg(smc) ;
-#ifdef SMT_REAL_TOKEN_CT
-       /*
-        * If the token counter is emulated it is updated in smt_event.
-        */
-       TBD
-#else
-       smt_emulate_token_ct( smc, MAC0 );
-#endif
-}
-
-/*
- * write long value into buffer memory over memory data register (MDR),
- */
-static void write_mdr(struct s_smc *smc, u_long val)
-{
-       CHECK_NPP() ;
-       MDRW(val) ;
-}
-
-#if 0
-/*
- * read long value from buffer memory over memory data register (MDR),
- */
-static u_long read_mdr(struct s_smc *smc, unsigned int addr)
-{
-       long p ;
-       CHECK_NPP() ;
-       MARR(addr) ;
-       outpw(FM_A(FM_CMDREG1),FM_IRMEMWO) ;
-       CHECK_NPP() ;   /* needed for PCI to prevent from timeing violations */
-/*     p = MDRR() ; */ /* bad read values if the workaround */
-                       /* smc->hw.mc_dummy = *((short volatile far *)(addr)))*/
-                       /* is used */
-       p = (u_long)inpw(FM_A(FM_MDRU))<<16 ;
-       p += (u_long)inpw(FM_A(FM_MDRL)) ;
-       return p;
-}
-#endif
-
-/*
- * clear buffer memory
- */
-static void init_ram(struct s_smc *smc)
-{
-       u_short i ;
-
-       smc->hw.fp.fifo.rbc_ram_start = 0 ;
-       smc->hw.fp.fifo.rbc_ram_end =
-               smc->hw.fp.fifo.rbc_ram_start + RBC_MEM_SIZE ;
-       CHECK_NPP() ;
-       MARW(smc->hw.fp.fifo.rbc_ram_start) ;
-       for (i = smc->hw.fp.fifo.rbc_ram_start;
-               i < (u_short) (smc->hw.fp.fifo.rbc_ram_end-1); i++)
-               write_mdr(smc,0L) ;
-       /* Erase the last byte too */
-       write_mdr(smc,0L) ;
-}
-
-/*
- * set receive FIFO pointer
- */
-static void set_recvptr(struct s_smc *smc)
-{
-       /*
-        * initialize the pointer for receive queue 1
-        */
-       outpw(FM_A(FM_RPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* RPR1 */
-       outpw(FM_A(FM_SWPR1),smc->hw.fp.fifo.rx1_fifo_start) ;  /* SWPR1 */
-       outpw(FM_A(FM_WPR1),smc->hw.fp.fifo.rx1_fifo_start) ;   /* WPR1 */
-       outpw(FM_A(FM_EARV1),smc->hw.fp.fifo.tx_s_start-1) ;    /* EARV1 */
-
-       /*
-        * initialize the pointer for receive queue 2
-        */
-       if (smc->hw.fp.fifo.rx2_fifo_size) {
-               outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
-               outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
-               outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rx2_fifo_start) ;
-               outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
-       }
-       else {
-               outpw(FM_A(FM_RPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
-               outpw(FM_A(FM_SWPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
-               outpw(FM_A(FM_WPR2),smc->hw.fp.fifo.rbc_ram_end-1) ;
-               outpw(FM_A(FM_EARV2),smc->hw.fp.fifo.rbc_ram_end-1) ;
-       }
-}
-
-/*
- * set transmit FIFO pointer
- */
-static void set_txptr(struct s_smc *smc)
-{
-       outpw(FM_A(FM_CMDREG2),FM_IRSTQ) ;      /* reset transmit queues */
-
-       /*
-        * initialize the pointer for asynchronous transmit queue
-        */
-       outpw(FM_A(FM_RPXA0),smc->hw.fp.fifo.tx_a0_start) ;     /* RPXA0 */
-       outpw(FM_A(FM_SWPXA0),smc->hw.fp.fifo.tx_a0_start) ;    /* SWPXA0 */
-       outpw(FM_A(FM_WPXA0),smc->hw.fp.fifo.tx_a0_start) ;     /* WPXA0 */
-       outpw(FM_A(FM_EAA0),smc->hw.fp.fifo.rx2_fifo_start-1) ; /* EAA0 */
-
-       /*
-        * initialize the pointer for synchronous transmit queue
-        */
-       if (smc->hw.fp.fifo.tx_s_size) {
-               outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_s_start) ;
-               outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_s_start) ;
-               outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_s_start) ;
-               outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
-       }
-       else {
-               outpw(FM_A(FM_RPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
-               outpw(FM_A(FM_SWPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
-               outpw(FM_A(FM_WPXS),smc->hw.fp.fifo.tx_a0_start-1) ;
-               outpw(FM_A(FM_EAS),smc->hw.fp.fifo.tx_a0_start-1) ;
-       }
-}
-
-/*
- * init memory buffer management registers
- */
-static void init_rbc(struct s_smc *smc)
-{
-       u_short rbc_ram_addr ;
-
-       /*
-        * set unused pointers or permanent pointers
-        */
-       rbc_ram_addr = smc->hw.fp.fifo.rx2_fifo_start - 1 ;
-
-       outpw(FM_A(FM_RPXA1),rbc_ram_addr) ;    /* a1-send pointer */
-       outpw(FM_A(FM_WPXA1),rbc_ram_addr) ;
-       outpw(FM_A(FM_SWPXA1),rbc_ram_addr) ;
-       outpw(FM_A(FM_EAA1),rbc_ram_addr) ;
-
-       set_recvptr(smc) ;
-       set_txptr(smc) ;
-}
-
-/*
- * init rx pointer
- */
-static void init_rx(struct s_smc *smc)
-{
-       struct s_smt_rx_queue   *queue ;
-
-       /*
-        * init all tx data structures for receive queue 1
-        */
-       smc->hw.fp.rx[QUEUE_R1] = queue = &smc->hw.fp.rx_q[QUEUE_R1] ;
-       queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R1_CSR) ;
-       queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R1_DA) ;
-
-       /*
-        * init all tx data structures for receive queue 2
-        */
-       smc->hw.fp.rx[QUEUE_R2] = queue = &smc->hw.fp.rx_q[QUEUE_R2] ;
-       queue->rx_bmu_ctl = (HW_PTR) ADDR(B0_R2_CSR) ;
-       queue->rx_bmu_dsc = (HW_PTR) ADDR(B4_R2_DA) ;
-}
-
-/*
- * set the TSYNC register of the FORMAC to regulate synchronous transmission
- */
-void set_formac_tsync(struct s_smc *smc, long sync_bw)
-{
-       outpw(FM_A(FM_TSYNC),(unsigned int) (((-sync_bw) >> 5) & 0xffff) ) ;
-}
-
-/*
- * init all tx data structures
- */
-static void init_tx(struct s_smc *smc)
-{
-       struct s_smt_tx_queue   *queue ;
-
-       /*
-        * init all tx data structures for the synchronous queue
-        */
-       smc->hw.fp.tx[QUEUE_S] = queue = &smc->hw.fp.tx_q[QUEUE_S] ;
-       queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XS_CSR) ;
-       queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XS_DA) ;
-
-#ifdef ESS
-       set_formac_tsync(smc,smc->ess.sync_bw) ;
-#endif
-
-       /*
-        * init all tx data structures for the asynchronous queue 0
-        */
-       smc->hw.fp.tx[QUEUE_A0] = queue = &smc->hw.fp.tx_q[QUEUE_A0] ;
-       queue->tx_bmu_ctl = (HW_PTR) ADDR(B0_XA_CSR) ;
-       queue->tx_bmu_dsc = (HW_PTR) ADDR(B5_XA_DA) ;
-
-
-       llc_recover_tx(smc) ;
-}
-
-static void mac_counter_init(struct s_smc *smc)
-{
-       int i ;
-       u_long *ec ;
-
-       /*
-        * clear FORMAC+ frame-, lost- and error counter
-        */
-       outpw(FM_A(FM_FCNTR),0) ;
-       outpw(FM_A(FM_LCNTR),0) ;
-       outpw(FM_A(FM_ECNTR),0) ;
-       /*
-        * clear internal error counter structure
-        */
-       ec = (u_long *)&smc->hw.fp.err_stats ;
-       for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
-               *ec++ = 0L ;
-       smc->mib.m[MAC0].fddiMACRingOp_Ct = 0 ;
-}
-
-/*
- * set FORMAC address, and t_request
- */
-static void set_formac_addr(struct s_smc *smc)
-{
-       long    t_requ = smc->mib.m[MAC0].fddiMACT_Req ;
-
-       outpw(FM_A(FM_SAID),my_said) ;  /* set short address */
-       outpw(FM_A(FM_LAIL),(unsigned)((smc->hw.fddi_home_addr.a[4]<<8) +
-                                       smc->hw.fddi_home_addr.a[5])) ;
-       outpw(FM_A(FM_LAIC),(unsigned)((smc->hw.fddi_home_addr.a[2]<<8) +
-                                       smc->hw.fddi_home_addr.a[3])) ;
-       outpw(FM_A(FM_LAIM),(unsigned)((smc->hw.fddi_home_addr.a[0]<<8) +
-                                       smc->hw.fddi_home_addr.a[1])) ;
-
-       outpw(FM_A(FM_SAGP),my_sagp) ;  /* set short group address */
-
-       outpw(FM_A(FM_LAGL),(unsigned)((smc->hw.fp.group_addr.a[4]<<8) +
-                                       smc->hw.fp.group_addr.a[5])) ;
-       outpw(FM_A(FM_LAGC),(unsigned)((smc->hw.fp.group_addr.a[2]<<8) +
-                                       smc->hw.fp.group_addr.a[3])) ;
-       outpw(FM_A(FM_LAGM),(unsigned)((smc->hw.fp.group_addr.a[0]<<8) +
-                                       smc->hw.fp.group_addr.a[1])) ;
-
-       /* set r_request regs. (MSW & LSW of TRT ) */
-       outpw(FM_A(FM_TREQ1),(unsigned)(t_requ>>16)) ;
-       outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ;
-}
-
-static void set_int(char *p, int l)
-{
-       p[0] = (char)(l >> 24) ;
-       p[1] = (char)(l >> 16) ;
-       p[2] = (char)(l >> 8) ;
-       p[3] = (char)(l >> 0) ;
-}
-
-/*
- * copy TX descriptor to buffer mem
- * append FC field and MAC frame
- * if more bit is set in descr
- *     append pointer to descriptor (endless loop)
- * else
- *     append 'end of chain' pointer
- */
-static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
-                       unsigned off, int len)
-/* u_long td;           transmit descriptor */
-/* struct fddi_mac *mac; mac frame pointer */
-/* unsigned off;        start address within buffer memory */
-/* int len ;            length of the frame including the FC */
-{
-       int     i ;
-       __le32  *p ;
-
-       CHECK_NPP() ;
-       MARW(off) ;             /* set memory address reg for writes */
-
-       p = (__le32 *) mac ;
-       for (i = (len + 3)/4 ; i ; i--) {
-               if (i == 1) {
-                       /* last word, set the tag bit */
-                       outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;
-               }
-               write_mdr(smc,le32_to_cpu(*p)) ;
-               p++ ;
-       }
-
-       outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;      /* set the tag bit */
-       write_mdr(smc,td) ;     /* write over memory data reg to buffer */
-}
-
-/*
-       BEGIN_MANUAL_ENTRY(module;tests;3)
-       How to test directed beacon frames
-       ----------------------------------------------------------------
-
-       o Insert a break point in the function build_claim_beacon()
-         before calling copy_tx_mac() for building the claim frame.
-       o Modify the RM3_DETECT case so that the RM6_DETECT state
-         will always entered from the RM3_DETECT state (function rmt_fsm(),
-         rmt.c)
-       o Compile the driver.
-       o Set the parameter TREQ in the protocol.ini or net.cfg to a
-         small value to make sure your station will win the claim
-         process.
-       o Start the driver.
-       o When you reach the break point, modify the SA and DA address
-         of the claim frame (e.g. SA = DA = 10005affffff).
-       o When you see RM3_DETECT and RM6_DETECT, observe the direct
-         beacon frames on the UPPSLANA.
-
-       END_MANUAL_ENTRY
- */
-static void directed_beacon(struct s_smc *smc)
-{
-       SK_LOC_DECL(__le32,a[2]) ;
-
-       /*
-        * set UNA in frame
-        * enable FORMAC to send endless queue of directed beacon
-        * important: the UNA starts at byte 1 (not at byte 0)
-        */
-       * (char *) a = (char) ((long)DBEACON_INFO<<24L) ;
-       a[1] = 0 ;
-       memcpy((char *)a+1,(char *) &smc->mib.m[MAC0].fddiMACUpstreamNbr,6) ;
-
-       CHECK_NPP() ;
-        /* set memory address reg for writes */
-       MARW(smc->hw.fp.fifo.rbc_ram_start+DBEACON_FRAME_OFF+4) ;
-       write_mdr(smc,le32_to_cpu(a[0])) ;
-       outpw(FM_A(FM_CMDREG2),FM_ISTTB) ;      /* set the tag bit */
-       write_mdr(smc,le32_to_cpu(a[1])) ;
-
-       outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF) ;
-}
-
-/*
-       setup claim & beacon pointer
-       NOTE :
-               special frame packets end with a pointer to their own
-               descriptor, and the MORE bit is set in the descriptor
-*/
-static void build_claim_beacon(struct s_smc *smc, u_long t_request)
-{
-       u_int   td ;
-       int     len ;
-       struct fddi_mac_sf *mac ;
-
-       /*
-        * build claim packet
-        */
-       len = 17 ;
-       td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
-       mac = &smc->hw.fp.mac_sfb ;
-       mac->mac_fc = FC_CLAIM ;
-       /* DA == SA in claim frame */
-       mac->mac_source = mac->mac_dest = MA ;
-       /* 2's complement */
-       set_int((char *)mac->mac_info,(int)t_request) ;
-
-       copy_tx_mac(smc,td,(struct fddi_mac *)mac,
-               smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ;
-       /* set CLAIM start pointer */
-       outpw(FM_A(FM_SACL),smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF) ;
-
-       /*
-        * build beacon packet
-        */
-       len = 17 ;
-       td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
-       mac->mac_fc = FC_BEACON ;
-       mac->mac_source = MA ;
-       mac->mac_dest = null_addr ;             /* DA == 0 in beacon frame */
-       set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ;
-
-       copy_tx_mac(smc,td,(struct fddi_mac *)mac,
-               smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ;
-       /* set beacon start pointer */
-       outpw(FM_A(FM_SABC),smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF) ;
-
-       /*
-        * build directed beacon packet
-        * contains optional UNA
-        */
-       len = 23 ;
-       td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ;
-       mac->mac_fc = FC_BEACON ;
-       mac->mac_source = MA ;
-       mac->mac_dest = dbeacon_multi ;         /* multicast */
-       set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ;
-       set_int((char *) mac->mac_info+4,0) ;
-       set_int((char *) mac->mac_info+8,0) ;
-
-       copy_tx_mac(smc,td,(struct fddi_mac *)mac,
-               smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ;
-
-       /* end of claim/beacon queue */
-       outpw(FM_A(FM_EACB),smc->hw.fp.fifo.rx1_fifo_start-1) ;
-
-       outpw(FM_A(FM_WPXSF),0) ;
-       outpw(FM_A(FM_RPXSF),0) ;
-}
-
-static void formac_rcv_restart(struct s_smc *smc)
-{
-       /* enable receive function */
-       SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
-
-       outpw(FM_A(FM_CMDREG1),FM_ICLLR) ;      /* clear receive lock */
-}
-
-void formac_tx_restart(struct s_smc *smc)
-{
-       outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;      /* clear s-frame lock */
-       outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;     /* clear a-frame lock */
-}
-
-static void enable_formac(struct s_smc *smc)
-{
-       /* set formac IMSK : 0 enables irq */
-       outpw(FM_A(FM_IMSK1U),(unsigned short)~mac_imsk1u);
-       outpw(FM_A(FM_IMSK1L),(unsigned short)~mac_imsk1l);
-       outpw(FM_A(FM_IMSK2U),(unsigned short)~mac_imsk2u);
-       outpw(FM_A(FM_IMSK2L),(unsigned short)~mac_imsk2l);
-       outpw(FM_A(FM_IMSK3U),(unsigned short)~mac_imsk3u);
-       outpw(FM_A(FM_IMSK3L),(unsigned short)~mac_imsk3l);
-}
-
-#if 0  /* Removed because the driver should use the ASICs TX complete IRQ. */
-       /* The FORMACs tx complete IRQ should be used any longer */
-
-/*
-       BEGIN_MANUAL_ENTRY(if,func;others;4)
-
-       void enable_tx_irq(smc, queue)
-       struct s_smc *smc ;
-       u_short queue ;
-
-Function       DOWNCALL        (SMT, fplustm.c)
-               enable_tx_irq() enables the FORMACs transmit complete
-               interrupt of the queue.
-
-Para   queue   = QUEUE_S:      synchronous queue
-               = QUEUE_A0:     asynchronous queue
-
-Note   After any ring operational change the transmit complete
-       interrupts are disabled.
-       The operating system dependent module must enable
-       the transmit complete interrupt of a queue,
-               - when it queues the first frame,
-                 because of no transmit resources are beeing
-                 available and
-               - when it escapes from the function llc_restart_tx
-                 while some frames are still queued.
-
-       END_MANUAL_ENTRY
- */
-void enable_tx_irq(struct s_smc *smc, u_short queue)
-/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
-{
-       u_short imask ;
-
-       imask = ~(inpw(FM_A(FM_IMSK1U))) ;
-
-       if (queue == 0) {
-               outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMS)) ;
-       }
-       if (queue == 1) {
-               outpw(FM_A(FM_IMSK1U),~(imask|FM_STEFRMA0)) ;
-       }
-}
-
-/*
-       BEGIN_MANUAL_ENTRY(if,func;others;4)
-
-       void disable_tx_irq(smc, queue)
-       struct s_smc *smc ;
-       u_short queue ;
-
-Function       DOWNCALL        (SMT, fplustm.c)
-               disable_tx_irq disables the FORMACs transmit complete
-               interrupt of the queue
-
-Para   queue   = QUEUE_S:      synchronous queue
-               = QUEUE_A0:     asynchronous queue
-
-Note   The operating system dependent module should disable
-       the transmit complete interrupts if it escapes from the
-       function llc_restart_tx and no frames are queued.
-
-       END_MANUAL_ENTRY
- */
-void disable_tx_irq(struct s_smc *smc, u_short queue)
-/* u_short queue; 0 = synchronous queue, 1 = asynchronous queue 0 */
-{
-       u_short imask ;
-
-       imask = ~(inpw(FM_A(FM_IMSK1U))) ;
-
-       if (queue == 0) {
-               outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMS)) ;
-       }
-       if (queue == 1) {
-               outpw(FM_A(FM_IMSK1U),~(imask&~FM_STEFRMA0)) ;
-       }
-}
-#endif
-
-static void disable_formac(struct s_smc *smc)
-{
-       /* clear formac IMSK : 1 disables irq */
-       outpw(FM_A(FM_IMSK1U),MW) ;
-       outpw(FM_A(FM_IMSK1L),MW) ;
-       outpw(FM_A(FM_IMSK2U),MW) ;
-       outpw(FM_A(FM_IMSK2L),MW) ;
-       outpw(FM_A(FM_IMSK3U),MW) ;
-       outpw(FM_A(FM_IMSK3L),MW) ;
-}
-
-
-static void mac_ring_up(struct s_smc *smc, int up)
-{
-       if (up) {
-               formac_rcv_restart(smc) ;       /* enable receive function */
-               smc->hw.mac_ring_is_up = TRUE ;
-               llc_restart_tx(smc) ;           /* TX queue */
-       }
-       else {
-               /* disable receive function */
-               SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
-
-               /* abort current transmit activity */
-               outpw(FM_A(FM_CMDREG2),FM_IACTR) ;
-
-               smc->hw.mac_ring_is_up = FALSE ;
-       }
-}
-
-/*--------------------------- ISR handling ----------------------------------*/
-/*
- * mac1_irq is in drvfbi.c
- */
-
-/*
- * mac2_irq:   status bits for the receive queue 1, and ring status
- *             ring status indication bits
- */
-void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l)
-{
-       u_short change_s2l ;
-       u_short change_s2u ;
-
-       /* (jd) 22-Feb-1999
-        * Restart 2_DMax Timer after end of claiming or beaconing
-        */
-       if (code_s2u & (FM_SCLM|FM_SHICLM|FM_SBEC|FM_SOTRBEC)) {
-               queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
-       }
-       else if (code_s2l & (FM_STKISS)) {
-               queue_event(smc,EVENT_RMT,RM_TX_STATE_CHANGE) ;
-       }
-
-       /*
-        * XOR current st bits with the last to avoid useless RMT event queuing
-        */
-       change_s2l = smc->hw.fp.s2l ^ code_s2l ;
-       change_s2u = smc->hw.fp.s2u ^ code_s2u ;
-
-       if ((change_s2l & FM_SRNGOP) ||
-               (!smc->hw.mac_ring_is_up && ((code_s2l & FM_SRNGOP)))) {
-               if (code_s2l & FM_SRNGOP) {
-                       mac_ring_up(smc,1) ;
-                       queue_event(smc,EVENT_RMT,RM_RING_OP) ;
-                       smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
-               }
-               else {
-                       mac_ring_up(smc,0) ;
-                       queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
-               }
-               goto mac2_end ;
-       }
-       if (code_s2l & FM_SMISFRM) {    /* missed frame */
-               smc->mib.m[MAC0].fddiMACNotCopied_Ct++ ;
-       }
-       if (code_s2u & (FM_SRCVOVR |    /* recv. FIFO overflow */
-                       FM_SRBFL)) {    /* recv. buffer full */
-               smc->hw.mac_ct.mac_r_restart_counter++ ;
-/*             formac_rcv_restart(smc) ;       */
-               smt_stat_counter(smc,1) ;
-/*             goto mac2_end ;                 */
-       }
-       if (code_s2u & FM_SOTRBEC)
-               queue_event(smc,EVENT_RMT,RM_OTHER_BEACON) ;
-       if (code_s2u & FM_SMYBEC)
-               queue_event(smc,EVENT_RMT,RM_MY_BEACON) ;
-       if (change_s2u & code_s2u & FM_SLOCLM) {
-               DB_RMTN(2,"RMT : lower claim received\n",0,0) ;
-       }
-       if ((code_s2u & FM_SMYCLM) && !(code_s2l & FM_SDUPCLM)) {
-               /*
-                * This is my claim and that claim is not detected as a
-                * duplicate one.
-                */
-               queue_event(smc,EVENT_RMT,RM_MY_CLAIM) ;
-       }
-       if (code_s2l & FM_SDUPCLM) {
-               /*
-                * If a duplicate claim frame (same SA but T_Bid != T_Req)
-                * this flag will be set.
-                * In the RMT state machine we need a RM_VALID_CLAIM event
-                * to do the appropriate state change.
-                * RM(34c)
-                */
-               queue_event(smc,EVENT_RMT,RM_VALID_CLAIM) ;
-       }
-       if (change_s2u & code_s2u & FM_SHICLM) {
-               DB_RMTN(2,"RMT : higher claim received\n",0,0) ;
-       }
-       if ( (code_s2l & FM_STRTEXP) ||
-            (code_s2l & FM_STRTEXR) )
-               queue_event(smc,EVENT_RMT,RM_TRT_EXP) ;
-       if (code_s2l & FM_SMULTDA) {
-               /*
-                * The MAC has found a 2. MAC with the same address.
-                * Signal dup_addr_test = failed to RMT state machine.
-                * RM(25)
-                */
-               smc->r.dup_addr_test = DA_FAILED ;
-               queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
-       }
-       if (code_s2u & FM_SBEC)
-               smc->hw.fp.err_stats.err_bec_stat++ ;
-       if (code_s2u & FM_SCLM)
-               smc->hw.fp.err_stats.err_clm_stat++ ;
-       if (code_s2l & FM_STVXEXP)
-               smc->mib.m[MAC0].fddiMACTvxExpired_Ct++ ;
-       if ((code_s2u & (FM_SBEC|FM_SCLM))) {
-               if (!(change_s2l & FM_SRNGOP) && (smc->hw.fp.s2l & FM_SRNGOP)) {
-                       mac_ring_up(smc,0) ;
-                       queue_event(smc,EVENT_RMT,RM_RING_NON_OP) ;
-
-                       mac_ring_up(smc,1) ;
-                       queue_event(smc,EVENT_RMT,RM_RING_OP) ;
-                       smc->mib.m[MAC0].fddiMACRingOp_Ct++ ;
-               }
-       }
-       if (code_s2l & FM_SPHINV)
-               smc->hw.fp.err_stats.err_phinv++ ;
-       if (code_s2l & FM_SSIFG)
-               smc->hw.fp.err_stats.err_sifg_det++ ;
-       if (code_s2l & FM_STKISS)
-               smc->hw.fp.err_stats.err_tkiss++ ;
-       if (code_s2l & FM_STKERR)
-               smc->hw.fp.err_stats.err_tkerr++ ;
-       if (code_s2l & FM_SFRMCTR)
-               smc->mib.m[MAC0].fddiMACFrame_Ct += 0x10000L ;
-       if (code_s2l & FM_SERRCTR)
-               smc->mib.m[MAC0].fddiMACError_Ct += 0x10000L ;
-       if (code_s2l & FM_SLSTCTR)
-               smc->mib.m[MAC0].fddiMACLost_Ct  += 0x10000L ;
-       if (code_s2u & FM_SERRSF) {
-               SMT_PANIC(smc,SMT_E0114, SMT_E0114_MSG) ;
-       }
-mac2_end:
-       /* notice old status */
-       smc->hw.fp.s2l = code_s2l ;
-       smc->hw.fp.s2u = code_s2u ;
-       outpw(FM_A(FM_IMSK2U),~mac_imsk2u) ;
-}
-
-/*
- * mac3_irq:   receive queue 2 bits and address detection bits
- */
-void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l)
-{
-       UNUSED(code_s3l) ;
-
-       if (code_s3u & (FM_SRCVOVR2 |   /* recv. FIFO overflow */
-                       FM_SRBFL2)) {   /* recv. buffer full */
-               smc->hw.mac_ct.mac_r_restart_counter++ ;
-               smt_stat_counter(smc,1);
-       }
-
-
-       if (code_s3u & FM_SRPERRQ2) {   /* parity error receive queue 2 */
-               SMT_PANIC(smc,SMT_E0115, SMT_E0115_MSG) ;
-       }
-       if (code_s3u & FM_SRPERRQ1) {   /* parity error receive queue 2 */
-               SMT_PANIC(smc,SMT_E0116, SMT_E0116_MSG) ;
-       }
-}
-
-
-/*
- * take formac offline
- */
-static void formac_offline(struct s_smc *smc)
-{
-       outpw(FM_A(FM_CMDREG2),FM_IACTR) ;/* abort current transmit activity */
-
-       /* disable receive function */
-       SETMASK(FM_A(FM_MDREG1),FM_MDISRCV,FM_ADDET) ;
-
-       /* FORMAC+ 'Initialize Mode' */
-       SETMASK(FM_A(FM_MDREG1),FM_MINIT,FM_MMODE) ;
-
-       disable_formac(smc) ;
-       smc->hw.mac_ring_is_up = FALSE ;
-       smc->hw.hw_state = STOPPED ;
-}
-
-/*
- * bring formac online
- */
-static void formac_online(struct s_smc *smc)
-{
-       enable_formac(smc) ;
-       SETMASK(FM_A(FM_MDREG1),FM_MONLINE | FM_SELRA | MDR1INIT |
-               smc->hw.fp.rx_mode, FM_MMODE | FM_SELRA | FM_ADDRX) ;
-}
-
-/*
- * FORMAC+ full init. (tx, rx, timer, counter, claim & beacon)
- */
-int init_fplus(struct s_smc *smc)
-{
-       smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
-       smc->hw.fp.rx_mode = FM_MDAMA ;
-       smc->hw.fp.group_addr = fddi_broadcast ;
-       smc->hw.fp.func_addr = 0 ;
-       smc->hw.fp.frselreg_init = 0 ;
-
-       init_driver_fplus(smc) ;
-       if (smc->s.sas == SMT_DAS)
-               smc->hw.fp.mdr3init |= FM_MENDAS ;
-
-       smc->hw.mac_ct.mac_nobuf_counter = 0 ;
-       smc->hw.mac_ct.mac_r_restart_counter = 0 ;
-
-       smc->hw.fp.fm_st1u = (HW_PTR) ADDR(B0_ST1U) ;
-       smc->hw.fp.fm_st1l = (HW_PTR) ADDR(B0_ST1L) ;
-       smc->hw.fp.fm_st2u = (HW_PTR) ADDR(B0_ST2U) ;
-       smc->hw.fp.fm_st2l = (HW_PTR) ADDR(B0_ST2L) ;
-       smc->hw.fp.fm_st3u = (HW_PTR) ADDR(B0_ST3U) ;
-       smc->hw.fp.fm_st3l = (HW_PTR) ADDR(B0_ST3L) ;
-
-       smc->hw.fp.s2l = smc->hw.fp.s2u = 0 ;
-       smc->hw.mac_ring_is_up = 0 ;
-
-       mac_counter_init(smc) ;
-
-       /* convert BCKL units to symbol time */
-       smc->hw.mac_pa.t_neg = (u_long)0 ;
-       smc->hw.mac_pa.t_pri = (u_long)0 ;
-
-       /* make sure all PCI settings are correct */
-       mac_do_pci_fix(smc) ;
-
-       return init_mac(smc, 1);
-       /* enable_formac(smc) ; */
-}
-
-static int init_mac(struct s_smc *smc, int all)
-{
-       u_short t_max,x ;
-       u_long  time=0 ;
-
-       /*
-        * clear memory
-        */
-       outpw(FM_A(FM_MDREG1),FM_MINIT) ;       /* FORMAC+ init mode */
-       set_formac_addr(smc) ;
-       outpw(FM_A(FM_MDREG1),FM_MMEMACT) ;     /* FORMAC+ memory activ mode */
-       /* Note: Mode register 2 is set here, incase parity is enabled. */
-       outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
-
-       if (all) {
-               init_ram(smc) ;
-       }
-       else {
-               /*
-                * reset the HPI, the Master and the BMUs
-                */
-               outp(ADDR(B0_CTRL), CTRL_HPI_SET) ;
-               time = hwt_quick_read(smc) ;
-       }
-
-       /*
-        * set all pointers, frames etc
-        */
-       smt_split_up_fifo(smc) ;
-
-       init_tx(smc) ;
-       init_rx(smc) ;
-       init_rbc(smc) ;
-
-       build_claim_beacon(smc,smc->mib.m[MAC0].fddiMACT_Req) ;
-
-       /* set RX threshold */
-       /* see Errata #SN2 Phantom receive overflow */
-       outpw(FM_A(FM_FRMTHR),14<<12) ;         /* switch on */
-
-       /* set formac work mode */
-       outpw(FM_A(FM_MDREG1),MDR1INIT | FM_SELRA | smc->hw.fp.rx_mode) ;
-       outpw(FM_A(FM_MDREG2),smc->hw.fp.mdr2init) ;
-       outpw(FM_A(FM_MDREG3),smc->hw.fp.mdr3init) ;
-       outpw(FM_A(FM_FRSELREG),smc->hw.fp.frselreg_init) ;
-
-       /* set timer */
-       /*
-        * errata #22 fplus:
-        * T_MAX must not be FFFE
-        * or one of FFDF, FFB8, FF91 (-0x27 etc..)
-        */
-       t_max = (u_short)(smc->mib.m[MAC0].fddiMACT_Max/32) ;
-       x = t_max/0x27 ;
-       x *= 0x27 ;
-       if ((t_max == 0xfffe) || (t_max - x == 0x16))
-               t_max-- ;
-       outpw(FM_A(FM_TMAX),(u_short)t_max) ;
-
-       /* BugFix for report #10204 */
-       if (smc->mib.m[MAC0].fddiMACTvxValue < (u_long) (- US2BCLK(52))) {
-               outpw(FM_A(FM_TVX), (u_short) (- US2BCLK(52))/255 & MB) ;
-       } else {
-               outpw(FM_A(FM_TVX),
-                       (u_short)((smc->mib.m[MAC0].fddiMACTvxValue/255) & MB)) ;
-       }
-
-       outpw(FM_A(FM_CMDREG1),FM_ICLLS) ;      /* clear s-frame lock */
-       outpw(FM_A(FM_CMDREG1),FM_ICLLA0) ;     /* clear a-frame lock */
-       outpw(FM_A(FM_CMDREG1),FM_ICLLR);       /* clear receive lock */
-
-       /* Auto unlock receice threshold for receive queue 1 and 2 */
-       outpw(FM_A(FM_UNLCKDLY),(0xff|(0xff<<8))) ;
-
-       rtm_init(smc) ;                         /* RT-Monitor */
-
-       if (!all) {
-               /*
-                * after 10ms, reset the BMUs and repair the rings
-                */
-               hwt_wait_time(smc,time,MS2BCLK(10)) ;
-               outpd(ADDR(B0_R1_CSR),CSR_SET_RESET) ;
-               outpd(ADDR(B0_XA_CSR),CSR_SET_RESET) ;
-               outpd(ADDR(B0_XS_CSR),CSR_SET_RESET) ;
-               outp(ADDR(B0_CTRL), CTRL_HPI_CLR) ;
-               outpd(ADDR(B0_R1_CSR),CSR_CLR_RESET) ;
-               outpd(ADDR(B0_XA_CSR),CSR_CLR_RESET) ;
-               outpd(ADDR(B0_XS_CSR),CSR_CLR_RESET) ;
-               if (!smc->hw.hw_is_64bit) {
-                       outpd(ADDR(B4_R1_F), RX_WATERMARK) ;
-                       outpd(ADDR(B5_XA_F), TX_WATERMARK) ;
-                       outpd(ADDR(B5_XS_F), TX_WATERMARK) ;
-               }
-               smc->hw.hw_state = STOPPED ;
-               mac_drv_repair_descr(smc) ;
-       }
-       smc->hw.hw_state = STARTED ;
-
-       return 0;
-}
-
-
-/*
- * called by CFM
- */
-void config_mux(struct s_smc *smc, int mux)
-{
-       plc_config_mux(smc,mux) ;
-
-       SETMASK(FM_A(FM_MDREG1),FM_SELRA,FM_SELRA) ;
-}
-
-/*
- * called by RMT
- * enable CLAIM/BEACON interrupts
- * (only called if these events are of interest, e.g. in DETECT state
- * the interrupt must not be permanently enabled
- * RMT calls this function periodically (timer driven polling)
- */
-void sm_mac_check_beacon_claim(struct s_smc *smc)
-{
-       /* set formac IMSK : 0 enables irq */
-       outpw(FM_A(FM_IMSK2U),~(mac_imsk2u | mac_beacon_imsk2u)) ;
-       /* the driver must receive the directed beacons */
-       formac_rcv_restart(smc) ;
-       process_receive(smc) ;
-}
-
-/*-------------------------- interface functions ----------------------------*/
-/*
- * control MAC layer   (called by RMT)
- */
-void sm_ma_control(struct s_smc *smc, int mode)
-{
-       switch(mode) {
-       case MA_OFFLINE :
-               /* Add to make the MAC offline in RM0_ISOLATED state */
-               formac_offline(smc) ;
-               break ;
-       case MA_RESET :
-               (void)init_mac(smc,0) ;
-               break ;
-       case MA_BEACON :
-               formac_online(smc) ;
-               break ;
-       case MA_DIRECTED :
-               directed_beacon(smc) ;
-               break ;
-       case MA_TREQ :
-               /*
-                * no actions necessary, TREQ is already set
-                */
-               break ;
-       }
-}
-
-int sm_mac_get_tx_state(struct s_smc *smc)
-{
-       return (inpw(FM_A(FM_STMCHN))>>4) & 7;
-}
-
-/*
- * multicast functions
- */
-
-static struct s_fpmc* mac_get_mc_table(struct s_smc *smc,
-                                      struct fddi_addr *user,
-                                      struct fddi_addr *own,
-                                      int del, int can)
-{
-       struct s_fpmc   *tb ;
-       struct s_fpmc   *slot ;
-       u_char  *p ;
-       int i ;
-
-       /*
-        * set own = can(user)
-        */
-       *own = *user ;
-       if (can) {
-               p = own->a ;
-               for (i = 0 ; i < 6 ; i++, p++)
-                       *p = bitrev8(*p);
-       }
-       slot = NULL;
-       for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
-               if (!tb->n) {           /* not used */
-                       if (!del && !slot)      /* if !del save first free */
-                               slot = tb ;
-                       continue ;
-               }
-               if (memcmp((char *)&tb->a,(char *)own,6))
-                       continue ;
-               return tb;
-       }
-       return slot;                    /* return first free or NULL */
-}
-
-/*
-       BEGIN_MANUAL_ENTRY(if,func;others;2)
-
-       void mac_clear_multicast(smc)
-       struct s_smc *smc ;
-
-Function       DOWNCALL        (SMT, fplustm.c)
-               Clear all multicast entries
-
-       END_MANUAL_ENTRY()
- */
-void mac_clear_multicast(struct s_smc *smc)
-{
-       struct s_fpmc   *tb ;
-       int i ;
-
-       smc->hw.fp.os_slots_used = 0 ;  /* note the SMT addresses */
-                                       /* will not be deleted */
-       for (i = 0, tb = smc->hw.fp.mc.table ; i < FPMAX_MULTICAST ; i++, tb++){
-               if (!tb->perm) {
-                       tb->n = 0 ;
-               }
-       }
-}
-
-/*
-       BEGIN_MANUAL_ENTRY(if,func;others;2)
-
-       int mac_add_multicast(smc,addr,can)
-       struct s_smc *smc ;
-       struct fddi_addr *addr ;
-       int can ;
-
-Function       DOWNCALL        (SMC, fplustm.c)
-               Add an entry to the multicast table
-
-Para   addr    pointer to a multicast address
-       can     = 0:    the multicast address has the physical format
-               = 1:    the multicast address has the canonical format
-               | 0x80  permanent
-
-Returns        0: success
-       1: address table full
-
-Note   After a 'driver reset' or a 'station set address' all
-       entries of the multicast table are cleared.
-       In this case the driver has to fill the multicast table again.
-       After the operating system dependent module filled
-       the multicast table it must call mac_update_multicast
-       to activate the new multicast addresses!
-
-       END_MANUAL_ENTRY()
- */
-int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can)
-{
-       SK_LOC_DECL(struct fddi_addr,own) ;
-       struct s_fpmc   *tb ;
-
-       /*
-        * check if there are free table entries
-        */
-       if (can & 0x80) {
-               if (smc->hw.fp.smt_slots_used >= SMT_MAX_MULTI) {
-                       return 1;
-               }
-       }
-       else {
-               if (smc->hw.fp.os_slots_used >= FPMAX_MULTICAST-SMT_MAX_MULTI) {
-                       return 1;
-               }
-       }
-
-       /*
-        * find empty slot
-        */
-       if (!(tb = mac_get_mc_table(smc,addr,&own,0,can & ~0x80)))
-               return 1;
-       tb->n++ ;
-       tb->a = own ;
-       tb->perm = (can & 0x80) ? 1 : 0 ;
-
-       if (can & 0x80)
-               smc->hw.fp.smt_slots_used++ ;
-       else
-               smc->hw.fp.os_slots_used++ ;
-
-       return 0;
-}
-
-/*
- * mode
- */
-
-#define RX_MODE_PROM           0x1
-#define RX_MODE_ALL_MULTI      0x2
-
-/*
-       BEGIN_MANUAL_ENTRY(if,func;others;2)
-
-       void mac_update_multicast(smc)
-       struct s_smc *smc ;
-
-Function       DOWNCALL        (SMT, fplustm.c)
-               Update FORMAC multicast registers
-
-       END_MANUAL_ENTRY()
- */
-void mac_update_multicast(struct s_smc *smc)
-{
-       struct s_fpmc   *tb ;
-       u_char  *fu ;
-       int     i ;
-
-       /*
-        * invalidate the CAM
-        */
-       outpw(FM_A(FM_AFCMD),FM_IINV_CAM) ;
-
-       /*
-        * set the functional address
-        */
-       if (smc->hw.fp.func_addr) {
-               fu = (u_char *) &smc->hw.fp.func_addr ;
-               outpw(FM_A(FM_AFMASK2),0xffff) ;
-               outpw(FM_A(FM_AFMASK1),(u_short) ~((fu[0] << 8) + fu[1])) ;
-               outpw(FM_A(FM_AFMASK0),(u_short) ~((fu[2] << 8) + fu[3])) ;
-               outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
-               outpw(FM_A(FM_AFCOMP2), 0xc000) ;
-               outpw(FM_A(FM_AFCOMP1), 0x0000) ;
-               outpw(FM_A(FM_AFCOMP0), 0x0000) ;
-               outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
-       }
-
-       /*
-        * set the mask and the personality register(s)
-        */
-       outpw(FM_A(FM_AFMASK0),0xffff) ;
-       outpw(FM_A(FM_AFMASK1),0xffff) ;
-       outpw(FM_A(FM_AFMASK2),0xffff) ;
-       outpw(FM_A(FM_AFPERS),FM_VALID|FM_DA) ;
-
-       for (i = 0, tb = smc->hw.fp.mc.table; i < FPMAX_MULTICAST; i++, tb++) {
-               if (tb->n) {
-                       CHECK_CAM() ;
-
-                       /*
-                        * write the multicast address into the CAM
-                        */
-                       outpw(FM_A(FM_AFCOMP2),
-                               (u_short)((tb->a.a[0]<<8)+tb->a.a[1])) ;
-                       outpw(FM_A(FM_AFCOMP1),
-                               (u_short)((tb->a.a[2]<<8)+tb->a.a[3])) ;
-                       outpw(FM_A(FM_AFCOMP0),
-                               (u_short)((tb->a.a[4]<<8)+tb->a.a[5])) ;
-                       outpw(FM_A(FM_AFCMD),FM_IWRITE_CAM) ;
-               }
-       }
-}
-
-/*
-       BEGIN_MANUAL_ENTRY(if,func;others;3)
-
-       void mac_set_rx_mode(smc,mode)
-       struct s_smc *smc ;
-       int mode ;
-
-Function       DOWNCALL/INTERN (SMT, fplustm.c)
-               This function enables / disables the selected receive.
-               Don't call this function if the hardware module is
-               used -- use mac_drv_rx_mode() instead of.
-
-Para   mode =  1       RX_ENABLE_ALLMULTI      enable all multicasts
-               2       RX_DISABLE_ALLMULTI     disable "enable all multicasts"
-               3       RX_ENABLE_PROMISC       enable promiscuous
-               4       RX_DISABLE_PROMISC      disable promiscuous
-               5       RX_ENABLE_NSA           enable reception of NSA frames
-               6       RX_DISABLE_NSA          disable reception of NSA frames
-
-Note   The selected receive modes will be lost after 'driver reset'
-       or 'set station address'
-
-       END_MANUAL_ENTRY
- */
-void mac_set_rx_mode(struct s_smc *smc, int mode)
-{
-       switch (mode) {
-       case RX_ENABLE_ALLMULTI :
-               smc->hw.fp.rx_prom |= RX_MODE_ALL_MULTI ;
-               break ;
-       case RX_DISABLE_ALLMULTI :
-               smc->hw.fp.rx_prom &= ~RX_MODE_ALL_MULTI ;
-               break ;
-       case RX_ENABLE_PROMISC :
-               smc->hw.fp.rx_prom |= RX_MODE_PROM ;
-               break ;
-       case RX_DISABLE_PROMISC :
-               smc->hw.fp.rx_prom &= ~RX_MODE_PROM ;
-               break ;
-       case RX_ENABLE_NSA :
-               smc->hw.fp.nsa_mode = FM_MDAMA ;
-               smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
-                       smc->hw.fp.nsa_mode ;
-               break ;
-       case RX_DISABLE_NSA :
-               smc->hw.fp.nsa_mode = FM_MRNNSAFNMA ;
-               smc->hw.fp.rx_mode = (smc->hw.fp.rx_mode & ~FM_ADDET) |
-                       smc->hw.fp.nsa_mode ;
-               break ;
-       }
-       if (smc->hw.fp.rx_prom & RX_MODE_PROM) {
-               smc->hw.fp.rx_mode = FM_MLIMPROM ;
-       }
-       else if (smc->hw.fp.rx_prom & RX_MODE_ALL_MULTI) {
-               smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode | FM_EXGPA0 ;
-       }
-       else
-               smc->hw.fp.rx_mode = smc->hw.fp.nsa_mode ;
-       SETMASK(FM_A(FM_MDREG1),smc->hw.fp.rx_mode,FM_ADDRX) ;
-       mac_update_multicast(smc) ;
-}
-
-/*
-       BEGIN_MANUAL_ENTRY(module;tests;3)
-       How to test the Restricted Token Monitor
-       ----------------------------------------------------------------
-
-       o Insert a break point in the function rtm_irq()
-       o Remove all stations with a restricted token monitor from the
-         network.
-       o Connect a UPPS ISA or EISA station to the network.
-       o Give the FORMAC of UPPS station the command to send
-         restricted tokens until the ring becomes instable.
-       o Now connect your test test client.
-       o The restricted token monitor should detect the restricted token,
-         and your break point will be reached.
-       o You can ovserve how the station will clean the ring.
-
-       END_MANUAL_ENTRY
- */
-void rtm_irq(struct s_smc *smc)
-{
-       outpw(ADDR(B2_RTM_CRTL),TIM_CL_IRQ) ;           /* clear IRQ */
-       if (inpw(ADDR(B2_RTM_CRTL)) & TIM_RES_TOK) {
-               outpw(FM_A(FM_CMDREG1),FM_ICL) ;        /* force claim */
-               DB_RMT("RMT: fddiPATHT_Rmode expired\n",0,0) ;
-               AIX_EVENT(smc, (u_long) FDDI_RING_STATUS,
-                               (u_long) FDDI_SMT_EVENT,
-                               (u_long) FDDI_RTT, smt_get_event_word(smc));
-       }
-       outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable RTM monitoring */
-}
-
-static void rtm_init(struct s_smc *smc)
-{
-       outpd(ADDR(B2_RTM_INI),0) ;             /* timer = 0 */
-       outpw(ADDR(B2_RTM_CRTL),TIM_START) ;    /* enable IRQ */
-}
-
-void rtm_set_timer(struct s_smc *smc)
-{
-       /*
-        * MIB timer and hardware timer have the same resolution of 80nS
-        */
-       DB_RMT("RMT: setting new fddiPATHT_Rmode, t = %d ns\n",
-               (int) smc->mib.a[PATH0].fddiPATHT_Rmode,0) ;
-       outpd(ADDR(B2_RTM_INI),smc->mib.a[PATH0].fddiPATHT_Rmode) ;
-}
-
-static void smt_split_up_fifo(struct s_smc *smc)
-{
-
-/*
-       BEGIN_MANUAL_ENTRY(module;mem;1)
-       -------------------------------------------------------------
-       RECEIVE BUFFER MEMORY DIVERSION
-       -------------------------------------------------------------
-
-       R1_RxD == SMT_R1_RXD_COUNT
-       R2_RxD == SMT_R2_RXD_COUNT
-
-       SMT_R1_RXD_COUNT must be unequal zero
-
-                  | R1_RxD R2_RxD |R1_RxD R2_RxD | R1_RxD R2_RxD
-                  |   x      0    |  x     1-3   |   x     < 3
-       ----------------------------------------------------------------------
-                  |   63,75 kB    |    54,75     |     R1_RxD
-       rx queue 1 | RX_FIFO_SPACE | RX_LARGE_FIFO| ------------- * 63,75 kB
-                  |               |              | R1_RxD+R2_RxD
-       ----------------------------------------------------------------------
-                  |               |    9 kB      |     R2_RxD
-       rx queue 2 |    0 kB       | RX_SMALL_FIFO| ------------- * 63,75 kB
-                  |  (not used)   |              | R1_RxD+R2_RxD
-
-       END_MANUAL_ENTRY
-*/
-
-       if (SMT_R1_RXD_COUNT == 0) {
-               SMT_PANIC(smc,SMT_E0117, SMT_E0117_MSG) ;
-       }
-
-       switch(SMT_R2_RXD_COUNT) {
-       case 0:
-               smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE ;
-               smc->hw.fp.fifo.rx2_fifo_size = 0 ;
-               break ;
-       case 1:
-       case 2:
-       case 3:
-               smc->hw.fp.fifo.rx1_fifo_size = RX_LARGE_FIFO ;
-               smc->hw.fp.fifo.rx2_fifo_size = RX_SMALL_FIFO ;
-               break ;
-       default:        /* this is not the real defaule */
-               smc->hw.fp.fifo.rx1_fifo_size = RX_FIFO_SPACE *
-               SMT_R1_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
-               smc->hw.fp.fifo.rx2_fifo_size = RX_FIFO_SPACE *
-               SMT_R2_RXD_COUNT/(SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT) ;
-               break ;
-       }
-
-/*
-       BEGIN_MANUAL_ENTRY(module;mem;1)
-       -------------------------------------------------------------
-       TRANSMIT BUFFER MEMORY DIVERSION
-       -------------------------------------------------------------
-
-
-                | no sync bw   | sync bw available and | sync bw available and
-                | available    | SynchTxMode = SPLIT   | SynchTxMode = ALL
-       -----------------------------------------------------------------------
-       sync tx  |     0 kB     |       32 kB           |       55 kB
-       queue    |              |   TX_MEDIUM_FIFO      |   TX_LARGE_FIFO
-       -----------------------------------------------------------------------
-       async tx |    64 kB     |       32 kB           |        9 k
-       queue    | TX_FIFO_SPACE|   TX_MEDIUM_FIFO      |   TX_SMALL_FIFO
-
-       END_MANUAL_ENTRY
-*/
-
-       /*
-        * set the tx mode bits
-        */
-       if (smc->mib.a[PATH0].fddiPATHSbaPayload) {
-#ifdef ESS
-               smc->hw.fp.fifo.fifo_config_mode |=
-                       smc->mib.fddiESSSynchTxMode | SYNC_TRAFFIC_ON ;
-#endif
-       }
-       else {
-               smc->hw.fp.fifo.fifo_config_mode &=
-                       ~(SEND_ASYNC_AS_SYNC|SYNC_TRAFFIC_ON) ;
-       }
-
-       /*
-        * split up the FIFO
-        */
-       if (smc->hw.fp.fifo.fifo_config_mode & SYNC_TRAFFIC_ON) {
-               if (smc->hw.fp.fifo.fifo_config_mode & SEND_ASYNC_AS_SYNC) {
-                       smc->hw.fp.fifo.tx_s_size = TX_LARGE_FIFO ;
-                       smc->hw.fp.fifo.tx_a0_size = TX_SMALL_FIFO ;
-               }
-               else {
-                       smc->hw.fp.fifo.tx_s_size = TX_MEDIUM_FIFO ;
-                       smc->hw.fp.fifo.tx_a0_size = TX_MEDIUM_FIFO ;
-               }
-       }
-       else {
-                       smc->hw.fp.fifo.tx_s_size = 0 ;
-                       smc->hw.fp.fifo.tx_a0_size = TX_FIFO_SPACE ;
-       }
-
-       smc->hw.fp.fifo.rx1_fifo_start = smc->hw.fp.fifo.rbc_ram_start +
-               RX_FIFO_OFF ;
-       smc->hw.fp.fifo.tx_s_start = smc->hw.fp.fifo.rx1_fifo_start +
-               smc->hw.fp.fifo.rx1_fifo_size ;
-       smc->hw.fp.fifo.tx_a0_start = smc->hw.fp.fifo.tx_s_start +
-               smc->hw.fp.fifo.tx_s_size ;
-       smc->hw.fp.fifo.rx2_fifo_start = smc->hw.fp.fifo.tx_a0_start +
-               smc->hw.fp.fifo.tx_a0_size ;
-
-       DB_SMT("FIFO split: mode = %x\n",smc->hw.fp.fifo.fifo_config_mode,0) ;
-       DB_SMT("rbc_ram_start = %x       rbc_ram_end =  %x\n",
-               smc->hw.fp.fifo.rbc_ram_start, smc->hw.fp.fifo.rbc_ram_end) ;
-       DB_SMT("rx1_fifo_start = %x      tx_s_start =   %x\n",
-               smc->hw.fp.fifo.rx1_fifo_start, smc->hw.fp.fifo.tx_s_start) ;
-       DB_SMT("tx_a0_start =   %x       rx2_fifo_start =       %x\n",
-               smc->hw.fp.fifo.tx_a0_start, smc->hw.fp.fifo.rx2_fifo_start) ;
-}
-
-void formac_reinit_tx(struct s_smc *smc)
-{
-       /*
-        * Split up the FIFO and reinitialize the MAC if synchronous
-        * bandwidth becomes available but no synchronous queue is
-        * configured.
-        */
-       if (!smc->hw.fp.fifo.tx_s_size && smc->mib.a[PATH0].fddiPATHSbaPayload){
-               (void)init_mac(smc,0) ;
-       }
-}
-
diff --git a/drivers/net/skfp/h/cmtdef.h b/drivers/net/skfp/h/cmtdef.h
deleted file mode 100644 (file)
index 5a6c612..0000000
+++ /dev/null
@@ -1,756 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _CMTDEF_
-#define _CMTDEF_
-
-/* **************************************************************** */
-
-/*
- * implementation specific constants
- * MODIIFY THE FOLLOWING THREE DEFINES
- */
-#define AMDPLC                 /* if Amd PLC chip used */
-#ifdef CONC
-#define NUMPHYS                12      /* 2 for SAS or DAS, more for Concentrator */
-#else
-#ifdef CONC_II
-#define NUMPHYS                24      /* 2 for SAS or DAS, more for Concentrator */
-#else
-#define NUMPHYS                2       /* 2 for SAS or DAS, more for Concentrator */
-#endif
-#endif
-#define NUMMACS                1       /* only 1 supported at the moment */
-#define NUMPATHS       2       /* primary and secondary path supported */
-
-/*
- * DO NOT MODIFY BEYOND THIS POINT
- */
-
-/* **************************************************************** */
-
-#if    NUMPHYS > 2
-#define CONCENTRATOR
-#endif
-
-/*
- * Definitions for comfortable LINT usage
- */
-#ifdef lint
-#define LINT_USE(x)    (x)=(x)
-#else
-#define LINT_USE(x)
-#endif
-
-#ifdef DEBUG
-#define        DB_PR(flag,a,b,c)       { if (flag) printf(a,b,c) ; }
-#else
-#define        DB_PR(flag,a,b,c)
-#endif
-
-#ifdef DEBUG_BRD
-#define DB_ECM(a,b,c)          DB_PR((smc->debug.d_smt&1),a,b,c)
-#define DB_ECMN(n,a,b,c)       DB_PR((smc->debug.d_ecm >=(n)),a,b,c)
-#define DB_RMT(a,b,c)          DB_PR((smc->debug.d_smt&2),a,b,c)
-#define DB_RMTN(n,a,b,c)       DB_PR((smc->debug.d_rmt >=(n)),a,b,c)
-#define DB_CFM(a,b,c)          DB_PR((smc->debug.d_smt&4),a,b,c)
-#define DB_CFMN(n,a,b,c)       DB_PR((smc->debug.d_cfm >=(n)),a,b,c)
-#define DB_PCM(a,b,c)          DB_PR((smc->debug.d_smt&8),a,b,c)
-#define DB_PCMN(n,a,b,c)       DB_PR((smc->debug.d_pcm >=(n)),a,b,c)
-#define DB_SMT(a,b,c)          DB_PR((smc->debug.d_smtf),a,b,c)
-#define DB_SMTN(n,a,b,c)       DB_PR((smc->debug.d_smtf >=(n)),a,b,c)
-#define DB_SBA(a,b,c)          DB_PR((smc->debug.d_sba),a,b,c)
-#define DB_SBAN(n,a,b,c)       DB_PR((smc->debug.d_sba >=(n)),a,b,c)
-#define DB_ESS(a,b,c)          DB_PR((smc->debug.d_ess),a,b,c)
-#define DB_ESSN(n,a,b,c)       DB_PR((smc->debug.d_ess >=(n)),a,b,c)
-#else
-#define DB_ECM(a,b,c)          DB_PR((debug.d_smt&1),a,b,c)
-#define DB_ECMN(n,a,b,c)       DB_PR((debug.d_ecm >=(n)),a,b,c)
-#define DB_RMT(a,b,c)          DB_PR((debug.d_smt&2),a,b,c)
-#define DB_RMTN(n,a,b,c)       DB_PR((debug.d_rmt >=(n)),a,b,c)
-#define DB_CFM(a,b,c)          DB_PR((debug.d_smt&4),a,b,c)
-#define DB_CFMN(n,a,b,c)       DB_PR((debug.d_cfm >=(n)),a,b,c)
-#define DB_PCM(a,b,c)          DB_PR((debug.d_smt&8),a,b,c)
-#define DB_PCMN(n,a,b,c)       DB_PR((debug.d_pcm >=(n)),a,b,c)
-#define DB_SMT(a,b,c)          DB_PR((debug.d_smtf),a,b,c)
-#define DB_SMTN(n,a,b,c)       DB_PR((debug.d_smtf >=(n)),a,b,c)
-#define DB_SBA(a,b,c)          DB_PR((debug.d_sba),a,b,c)
-#define DB_SBAN(n,a,b,c)       DB_PR((debug.d_sba >=(n)),a,b,c)
-#define DB_ESS(a,b,c)          DB_PR((debug.d_ess),a,b,c)
-#define DB_ESSN(n,a,b,c)       DB_PR((debug.d_ess >=(n)),a,b,c)
-#endif
-
-#ifndef        SS_NOT_DS
-#define        SK_LOC_DECL(type,var)   type var
-#else
-#define        SK_LOC_DECL(type,var)   static type var
-#endif
-/*
- * PHYs and PORTS
- * Note: Don't touch the definition of PA and PB. Those might be used
- *     by some "for" loops.
- */
-#define PA             0
-#define PB             1
-#if    defined(SUPERNET_3) || defined(CONC_II)
-/*
- * The port indices have to be different,
- * because the MAC output goes through the 2. PLC
- * Conc II: It has to be the first port in the row.
- */
-#define PS             0       /* Internal PLC which is the same as PA */
-#else
-#define PS             1
-#endif
-#define PM             2               /* PM .. PA+NUM_PHYS-1 */
-
-/*
- * PHY types - as in path descriptor 'fddiPHYType'
- */
-#define TA                     0       /* A port */
-#define TB                     1       /* B port */
-#define TS                     2       /* S port */
-#define TM                     3       /* M port */
-#define TNONE                  4
-
-
-/*
- * indexes in MIB
- */
-#define INDEX_MAC      1
-#define INDEX_PATH     1
-#define INDEX_PORT     1
-
-
-/*
- * policies
- */
-#define POLICY_AA      (1<<0)          /* reject AA */
-#define POLICY_AB      (1<<1)          /* reject AB */
-#define POLICY_AS      (1<<2)          /* reject AS */
-#define POLICY_AM      (1<<3)          /* reject AM */
-#define POLICY_BA      (1<<4)          /* reject BA */
-#define POLICY_BB      (1<<5)          /* reject BB */
-#define POLICY_BS      (1<<6)          /* reject BS */
-#define POLICY_BM      (1<<7)          /* reject BM */
-#define POLICY_SA      (1<<8)          /* reject SA */
-#define POLICY_SB      (1<<9)          /* reject SB */
-#define POLICY_SS      (1<<10)         /* reject SS */
-#define POLICY_SM      (1<<11)         /* reject SM */
-#define POLICY_MA      (1<<12)         /* reject MA */
-#define POLICY_MB      (1<<13)         /* reject MB */
-#define POLICY_MS      (1<<14)         /* reject MS */
-#define POLICY_MM      (1<<15)         /* reject MM */
-
-/*
- * commands
- */
-
-/*
- * EVENTS
- * event classes
- */
-#define EVENT_ECM      1               /* event class ECM */
-#define EVENT_CFM      2               /* event class CFM */
-#define EVENT_RMT      3               /* event class RMT */
-#define EVENT_SMT      4               /* event class SMT */
-#define EVENT_PCM      5               /* event class PCM */
-#define EVENT_PCMA     5               /* event class PCMA */
-#define EVENT_PCMB     6               /* event class PCMB */
-
-/* WARNING :
- * EVENT_PCM* must be last in the above list
- * if more than two ports are used, EVENT_PCM .. EVENT_PCMA+NUM_PHYS-1
- * are used !
- */
-
-#define EV_TOKEN(class,event)  (((u_long)(class)<<16L)|((u_long)(event)))
-#define EV_T_CLASS(token)      ((int)((token)>>16)&0xffff)
-#define EV_T_EVENT(token)      ((int)(token)&0xffff)
-
-/*
- * ECM events
- */
-#define EC_CONNECT     1               /* connect request */
-#define EC_DISCONNECT  2               /* disconnect request */
-#define EC_TRACE_PROP  3               /* trace propagation */
-#define EC_PATH_TEST   4               /* path test */
-#define EC_TIMEOUT_TD  5               /* timer TD_min */
-#define EC_TIMEOUT_TMAX        6               /* timer trace_max */
-#define EC_TIMEOUT_IMAX        7               /* timer I_max */
-#define EC_TIMEOUT_INMAX 8             /* timer IN_max */
-#define EC_TEST_DONE   9               /* path test done */
-
-/*
- * CFM events
- */
-#define CF_LOOP                1               /* cf_loop flag from PCM */
-#define CF_LOOP_A      1               /* cf_loop flag from PCM */
-#define CF_LOOP_B      2               /* cf_loop flag from PCM */
-#define CF_JOIN                3               /* cf_join flag from PCM */
-#define CF_JOIN_A      3               /* cf_join flag from PCM */
-#define CF_JOIN_B      4               /* cf_join flag from PCM */
-
-/*
- * PCM events
- */
-#define PC_START               1
-#define PC_STOP                        2
-#define PC_LOOP                        3
-#define PC_JOIN                        4
-#define PC_SIGNAL              5
-#define PC_REJECT              6
-#define PC_MAINT               7
-#define PC_TRACE               8
-#define PC_PDR                 9
-#define PC_ENABLE              10
-#define PC_DISABLE             11
-
-/*
- * must be ordered as in LineStateType
- */
-#define PC_QLS                 12
-#define PC_ILS                 13
-#define PC_MLS                 14
-#define PC_HLS                 15
-#define PC_LS_PDR              16
-#define PC_LS_NONE             17
-#define LS2MIB(x)      ((x)-PC_QLS)
-#define MIB2LS(x)      ((x)+PC_QLS)
-
-#define PC_TIMEOUT_TB_MAX      18      /* timer TB_max */
-#define PC_TIMEOUT_TB_MIN      19      /* timer TB_min */
-#define PC_TIMEOUT_C_MIN       20      /* timer C_Min */
-#define PC_TIMEOUT_T_OUT       21      /* timer T_Out */
-#define PC_TIMEOUT_TL_MIN      22      /* timer TL_Min */
-#define PC_TIMEOUT_T_NEXT      23      /* timer t_next[] */
-#define PC_TIMEOUT_LCT         24
-#define PC_NSE                 25      /* NOISE hardware timer */
-#define PC_LEM                 26      /* LEM done */
-
-/*
- * RMT events                            meaning               from
- */
-#define RM_RING_OP     1               /* ring operational     MAC     */
-#define RM_RING_NON_OP 2               /* ring not operational MAC     */
-#define RM_MY_BEACON   3               /* recvd my beacon      MAC     */
-#define RM_OTHER_BEACON        4               /* recvd other beacon   MAC     */
-#define RM_MY_CLAIM    5               /* recvd my claim       MAC     */
-#define RM_TRT_EXP     6               /* TRT exp              MAC     */
-#define RM_VALID_CLAIM 7               /* claim from dup addr  MAC     */
-#define RM_JOIN                8               /* signal rm_join       CFM     */
-#define RM_LOOP                9               /* signal rm_loop       CFM     */
-#define RM_DUP_ADDR    10              /* dup_addr_test hange  SMT-NIF */
-#define RM_ENABLE_FLAG 11              /* enable flag */
-
-#define RM_TIMEOUT_NON_OP      12      /* timeout T_Non_OP     */
-#define RM_TIMEOUT_T_STUCK     13      /* timeout T_Stuck      */
-#define RM_TIMEOUT_ANNOUNCE    14      /* timeout T_Announce   */
-#define RM_TIMEOUT_T_DIRECT    15      /* timeout T_Direct     */
-#define RM_TIMEOUT_D_MAX       16      /* timeout D_Max        */
-#define RM_TIMEOUT_POLL                17      /* claim/beacon poller  */
-#define RM_TX_STATE_CHANGE     18      /* To restart timer for D_Max */
-
-/*
- * SMT events
- */
-#define SM_TIMER       1               /* timer */
-#define SM_FAST                2               /* smt_force_irq */
-
-/* PC modes */
-#define PM_NONE                0
-#define PM_PEER                1
-#define PM_TREE                2
-
-/*
- * PCM withhold codes
- * MIB PC-WithholdType ENUM
- */
-#define PC_WH_NONE     0               /* ok */
-#define PC_WH_M_M      1               /* M to M */
-#define PC_WH_OTHER    2               /* other incompatible phys */
-#define PC_WH_PATH     3               /* path not available */
-/*
- * LCT duration
- */
-#define LC_SHORT       1               /* short LCT */
-#define LC_MEDIUM      2               /* medium LCT */
-#define LC_LONG                3               /* long LCT */
-#define LC_EXTENDED    4               /* extended LCT */
-
-/*
- * path_test values
- */
-#define PT_NONE                0
-#define PT_TESTING     1               /* test is running */
-#define PT_PASSED      2               /* test passed */
-#define PT_FAILED      3               /* test failed */
-#define PT_PENDING     4               /* path test follows */
-#define PT_EXITING     5               /* disconnected while in trace/leave */
-
-/*
- * duplicate address test
- * MIB DupAddressTest ENUM
- */
-#define DA_NONE                0               /*              */
-#define DA_PASSED      1               /* test passed */
-#define DA_FAILED      2               /* test failed */
-
-
-/*
- * optical bypass
- */
-#define BP_DEINSERT    0               /* disable bypass */
-#define BP_INSERT      1               /* enable bypass */
-
-/*
- * ODL enable/disable
- */
-#define PM_TRANSMIT_DISABLE    0       /* disable xmit */
-#define PM_TRANSMIT_ENABLE     1       /* enable xmit */
-
-/*
- * parameter for config_mux
- * note : number is index in config_endec table !
- */
-#define MUX_THRUA      0               /* through A */
-#define MUX_THRUB      1               /* through B */
-#define MUX_WRAPA      2               /* wrap A */
-#define MUX_WRAPB      3               /* wrap B */
-#define MUX_ISOLATE    4               /* isolated */
-#define MUX_WRAPS      5               /* SAS */
-
-/*
- * MAC control
- */
-#define MA_RESET       0
-#define MA_BEACON      1
-#define MA_CLAIM       2
-#define MA_DIRECTED    3               /* directed beacon */
-#define MA_TREQ                4               /* change T_Req */
-#define MA_OFFLINE     5               /* switch MAC to offline */
-
-
-/*
- * trace prop
- * bit map for trace propagation
- */
-#define ENTITY_MAC     (NUMPHYS)
-#define ENTITY_PHY(p)  (p)
-#define ENTITY_BIT(m)  (1<<(m))
-
-/*
- * Resource Tag Types
- */
-#define PATH_ISO       0       /* isolated */
-#define PATH_PRIM      3       /* primary path */
-#define PATH_THRU      5       /* through path */
-
-#define RES_MAC                2       /* resource type MAC */
-#define RES_PORT       4       /* resource type PORT */
-
-
-/*
- * CFM state
- * oops: MUST MATCH CF-StateType in SMT7.2 !
- */
-#define SC0_ISOLATED   0               /* isolated */
-#define SC1_WRAP_A     5               /* wrap A (not used) */
-#define SC2_WRAP_B     6               /* wrap B (not used) */
-#define SC4_THRU_A     12              /* through A */
-#define SC5_THRU_B     7               /* through B (used in SMT 6.2) */
-#define SC7_WRAP_S     8               /* SAS (not used) */
-#define SC9_C_WRAP_A   9               /* c wrap A */
-#define SC10_C_WRAP_B  10              /* c wrap B */
-#define SC11_C_WRAP_S  11              /* c wrap S */
-
-/*
- * convert MIB time in units of 80nS to uS
- */
-#define MIB2US(t)              ((t)/12)
-#define SEC2MIB(s)     ((s)*12500000L)
-/*
- * SMT timer
- */
-struct smt_timer {
-       struct smt_timer        *tm_next ;      /* linked list */
-       struct s_smc            *tm_smc ;       /* pointer to context */
-       u_long                  tm_delta ;      /* delta time */
-       u_long                  tm_token ;      /* token value */
-       u_short                 tm_active ;     /* flag : active/inactive */
-       u_short                 tm_pad ;        /* pad field */
-} ;
-
-/*
- * communication structures
- */
-struct mac_parameter {
-       u_long  t_neg ;         /* T_Neg parameter */
-       u_long  t_pri ;         /* T_Pri register in MAC */
-} ;
-
-/*
- * MAC counters
- */
-struct mac_counter {
-       u_long  mac_nobuf_counter ;     /* MAC SW counter: no buffer */
-       u_long  mac_r_restart_counter ; /* MAC SW counter: rx restarted */
-} ;
-
-/*
- * para struct context for SMT parameters
- */
-struct s_pcon {
-       int     pc_len ;
-       int     pc_err ;
-       int     pc_badset ;
-       void    *pc_p ;
-} ;
-
-/*
- * link error monitor
- */
-#define LEM_AVG        5
-struct lem_counter {
-#ifdef AM29K
-       int     lem_on  ;
-       u_long  lem_errors ;
-       u_long  lem_symbols ;
-       u_long  lem_tsymbols ;
-       int     lem_s_count ;
-       int     lem_n_s ;
-       int     lem_values ;
-       int     lem_index ;
-       int     lem_avg_ber[LEM_AVG] ;
-       int     lem_sum ;
-#else
-       u_short lem_float_ber ;         /* 10E-nn bit error rate */
-       u_long  lem_errors ;            /* accumulated error count */
-       u_short lem_on  ;
-#endif
-} ;
-
-#define NUMBITS        10
-
-#ifdef AMDPLC
-
-/*
- * PLC state table
- */
-struct s_plc {
-       u_short p_state ;               /* current state */
-       u_short p_bits ;                /* number of bits to send */
-       u_short p_start ;               /* first bit pos */
-       u_short p_pad ;                 /* padding for alignment */
-       u_long soft_err ;               /* error counter */
-       u_long parity_err ;             /* error counter */
-       u_long ebuf_err ;               /* error counter */
-       u_long ebuf_cont ;              /* continuous error counter */
-       u_long phyinv ;                 /* error counter */
-       u_long vsym_ctr ;               /* error counter */
-       u_long mini_ctr ;               /* error counter */
-       u_long tpc_exp ;                /* error counter */
-       u_long np_err ;                 /* error counter */
-       u_long b_pcs ;                  /* error counter */
-       u_long b_tpc ;                  /* error counter */
-       u_long b_tne ;                  /* error counter */
-       u_long b_qls ;                  /* error counter */
-       u_long b_ils ;                  /* error counter */
-       u_long b_hls ;                  /* error counter */
-} ;
-#endif
-
-#ifdef PROTOTYP_INC
-#include "fddi/driver.pro"
-#else  /* PROTOTYP_INC */
-/*
- * function prototypes
- */
-#include "h/mbuf.h"    /* Type definitions for MBUFs */
-#include "h/smtstate.h"        /* struct smt_state */
-
-void hwt_restart(struct s_smc *smc);   /* hwt.c */
-SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
-                      int length);     /* smt.c */
-SMbuf *smt_get_mbuf(struct s_smc *smc);        /* drvsr.c */
-void *sm_to_para(struct s_smc *smc, struct smt_header *sm,
-                int para);             /* smt.c */
-
-#ifndef SK_UNUSED
-#define SK_UNUSED(var)         (void)(var)
-#endif
-
-void queue_event(struct s_smc *smc, int class, int event);
-void ecm(struct s_smc *smc, int event);
-void ecm_init(struct s_smc *smc);
-void rmt(struct s_smc *smc, int event);
-void rmt_init(struct s_smc *smc);
-void pcm(struct s_smc *smc, const int np, int event);
-void pcm_init(struct s_smc *smc);
-void cfm(struct s_smc *smc, int event);
-void cfm_init(struct s_smc *smc);
-void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
-                    u_long token);
-void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer);
-void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
-                     int *remote, int *mac);
-void plc_config_mux(struct s_smc *smc, int mux);
-void sm_lem_evaluate(struct s_smc *smc);
-void mac_update_counter(struct s_smc *smc);
-void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off);
-void sm_ma_control(struct s_smc *smc, int mode);
-void sm_mac_check_beacon_claim(struct s_smc *smc);
-void config_mux(struct s_smc *smc, int mux);
-void smt_agent_init(struct s_smc *smc);
-void smt_timer_init(struct s_smc *smc);
-void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs);
-void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
-                 int index, int local);
-void smt_swap_para(struct smt_header *sm, int len, int direction);
-void ev_init(struct s_smc *smc);
-void hwt_init(struct s_smc *smc);
-u_long hwt_read(struct s_smc *smc);
-void hwt_stop(struct s_smc *smc);
-void hwt_start(struct s_smc *smc, u_long time);
-void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc);
-void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
-void sm_pm_bypass_req(struct s_smc *smc, int mode);
-void rmt_indication(struct s_smc *smc, int i);
-void cfm_state_change(struct s_smc *smc, int c_state);
-
-#if defined(DEBUG) || !defined(NO_SMT_PANIC)
-void smt_panic(struct s_smc *smc, char *text);
-#else
-#define        smt_panic(smc,text)
-#endif /* DEBUG || !NO_SMT_PANIC */
-
-void smt_stat_counter(struct s_smc *smc, int stat);
-void smt_timer_poll(struct s_smc *smc);
-u_long smt_get_time(void);
-u_long smt_get_tid(struct s_smc *smc);
-void smt_timer_done(struct s_smc *smc);
-void smt_fixup_mib(struct s_smc *smc);
-void smt_reset_defaults(struct s_smc *smc, int level);
-void smt_agent_task(struct s_smc *smc);
-int smt_check_para(struct s_smc *smc, struct smt_header *sm,
-                  const u_short list[]);
-void driver_get_bia(struct s_smc *smc, struct fddi_addr *bia_addr);
-
-#ifdef SUPERNET_3
-void drv_reset_indication(struct s_smc *smc);
-#endif /* SUPERNET_3 */
-
-void smt_start_watchdog(struct s_smc *smc);
-void smt_event(struct s_smc *smc, int event);
-void timer_event(struct s_smc *smc, u_long token);
-void ev_dispatcher(struct s_smc *smc);
-void pcm_get_state(struct s_smc *smc, struct smt_state *state);
-void ecm_state_change(struct s_smc *smc, int e_state);
-int sm_pm_bypass_present(struct s_smc *smc);
-void pcm_state_change(struct s_smc *smc, int plc, int p_state);
-void rmt_state_change(struct s_smc *smc, int r_state);
-int sm_pm_get_ls(struct s_smc *smc, int phy);
-int pcm_get_s_port(struct s_smc *smc);
-int pcm_rooted_station(struct s_smc *smc);
-int cfm_get_mac_input(struct s_smc *smc);
-int cfm_get_mac_output(struct s_smc *smc);
-int cem_build_path(struct s_smc *smc, char *to, int path_index);
-int sm_mac_get_tx_state(struct s_smc *smc);
-char *get_pcmstate(struct s_smc *smc, int np);
-int smt_action(struct s_smc *smc, int class, int code, int index);
-u_short smt_online(struct s_smc *smc, int on);
-void smt_force_irq(struct s_smc *smc);
-void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local);
-void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local);
-void smt_set_timestamp(struct s_smc *smc, u_char *p);
-void mac_set_rx_mode(struct s_smc *smc,        int mode);
-int mac_add_multicast(struct s_smc *smc, struct fddi_addr *addr, int can);
-void mac_update_multicast(struct s_smc *smc);
-void mac_clear_multicast(struct s_smc *smc);
-void set_formac_tsync(struct s_smc *smc, long sync_bw);
-void formac_reinit_tx(struct s_smc *smc);
-void formac_tx_restart(struct s_smc *smc);
-void process_receive(struct s_smc *smc);
-void init_driver_fplus(struct s_smc *smc);
-void rtm_irq(struct s_smc *smc);
-void rtm_set_timer(struct s_smc *smc);
-void ring_status_indication(struct s_smc *smc, u_long status);
-void llc_recover_tx(struct s_smc *smc);
-void llc_restart_tx(struct s_smc *smc);
-void plc_clear_irq(struct s_smc *smc, int p);
-void plc_irq(struct s_smc *smc,        int np, unsigned int cmd);
-int smt_set_mac_opvalues(struct s_smc *smc);
-
-#ifdef TAG_MODE
-void mac_do_pci_fix(struct s_smc *smc);
-void mac_drv_clear_tx_queue(struct s_smc *smc);
-void mac_drv_repair_descr(struct s_smc *smc);
-u_long hwt_quick_read(struct s_smc *smc);
-void hwt_wait_time(struct s_smc *smc, u_long start, long duration);
-#endif
-
-#ifdef SMT_PNMI
-int pnmi_init(struct s_smc* smc);
-int pnmi_process_ndis_id(struct s_smc *smc, u_long ndis_oid, void *buf, int len,
-                        int *BytesAccessed, int *BytesNeeded, u_char action);
-#endif
-
-#ifdef SBA
-#ifndef _H2INC
-void sba();
-#endif
-void sba_raf_received_pack();
-void sba_timer_poll();
-void smt_init_sba();
-#endif
-
-#ifdef ESS
-int ess_raf_received_pack(struct s_smc *smc, SMbuf *mb, struct smt_header *sm,
-                         int fs);
-void ess_timer_poll(struct s_smc *smc);
-void ess_para_change(struct s_smc *smc);
-#endif
-
-#ifndef        BOOT
-void smt_init_evc(struct s_smc *smc);
-void smt_srf_event(struct s_smc *smc, int code, int index, int cond);
-#else
-#define smt_init_evc(smc)
-#define smt_srf_event(smc,code,index,cond)
-#endif
-
-#ifndef SMT_REAL_TOKEN_CT
-void smt_emulate_token_ct(struct s_smc *smc, int mac_index);
-#endif
-
-#if defined(DEBUG) && !defined(BOOT)
-void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text);
-#else
-#define        dump_smt(smc,sm,text)
-#endif
-
-#ifdef DEBUG
-char* addr_to_string(struct fddi_addr *addr);
-void dump_hex(char *p, int len);
-#endif
-
-#endif /* PROTOTYP_INC */
-
-/* PNMI default defines */
-#ifndef PNMI_INIT
-#define        PNMI_INIT(smc)  /* Nothing */
-#endif
-#ifndef PNMI_GET_ID
-#define PNMI_GET_ID( smc, ndis_oid, buf, len, BytesWritten, BytesNeeded ) \
-               ( 1 ? (-1) : (-1) )
-#endif
-#ifndef PNMI_SET_ID
-#define PNMI_SET_ID( smc, ndis_oid, buf, len, BytesRead, BytesNeeded, \
-               set_type) ( 1 ? (-1) : (-1) )
-#endif
-
-/*
- * SMT_PANIC defines
- */
-#ifndef        SMT_PANIC
-#define        SMT_PANIC(smc,nr,msg)   smt_panic (smc, msg)
-#endif
-
-#ifndef        SMT_ERR_LOG
-#define        SMT_ERR_LOG(smc,nr,msg) SMT_PANIC (smc, nr, msg)
-#endif
-
-#ifndef        SMT_EBASE
-#define        SMT_EBASE       100
-#endif
-
-#define        SMT_E0100       SMT_EBASE + 0
-#define        SMT_E0100_MSG   "cfm FSM: invalid ce_type"
-#define        SMT_E0101       SMT_EBASE + 1
-#define        SMT_E0101_MSG   "CEM: case ???"
-#define        SMT_E0102       SMT_EBASE + 2
-#define        SMT_E0102_MSG   "CEM A: invalid state"
-#define        SMT_E0103       SMT_EBASE + 3
-#define        SMT_E0103_MSG   "CEM B: invalid state"
-#define        SMT_E0104       SMT_EBASE + 4
-#define        SMT_E0104_MSG   "CEM M: invalid state"
-#define        SMT_E0105       SMT_EBASE + 5
-#define        SMT_E0105_MSG   "CEM S: invalid state"
-#define        SMT_E0106       SMT_EBASE + 6
-#define        SMT_E0106_MSG   "CFM : invalid state"
-#define        SMT_E0107       SMT_EBASE + 7
-#define        SMT_E0107_MSG   "ECM : invalid state"
-#define        SMT_E0108       SMT_EBASE + 8
-#define        SMT_E0108_MSG   "prop_actions : NAC in DAS CFM"
-#define        SMT_E0109       SMT_EBASE + 9
-#define        SMT_E0109_MSG   "ST2U.FM_SERRSF error in special frame"
-#define        SMT_E0110       SMT_EBASE + 10
-#define        SMT_E0110_MSG   "ST2U.FM_SRFRCTOV recv. count. overflow"
-#define        SMT_E0111       SMT_EBASE + 11
-#define        SMT_E0111_MSG   "ST2U.FM_SNFSLD NP & FORMAC simult. load"
-#define        SMT_E0112       SMT_EBASE + 12
-#define        SMT_E0112_MSG   "ST2U.FM_SRCVFRM single-frame recv.-mode"
-#define        SMT_E0113       SMT_EBASE + 13
-#define        SMT_E0113_MSG   "FPLUS: Buffer Memory Error"
-#define        SMT_E0114       SMT_EBASE + 14
-#define        SMT_E0114_MSG   "ST2U.FM_SERRSF error in special frame"
-#define        SMT_E0115       SMT_EBASE + 15
-#define        SMT_E0115_MSG   "ST3L: parity error in receive queue 2"
-#define        SMT_E0116       SMT_EBASE + 16
-#define        SMT_E0116_MSG   "ST3L: parity error in receive queue 1"
-#define        SMT_E0117       SMT_EBASE + 17
-#define        SMT_E0117_MSG   "E_SMT_001: RxD count for receive queue 1 = 0"
-#define        SMT_E0118       SMT_EBASE + 18
-#define        SMT_E0118_MSG   "PCM : invalid state"
-#define        SMT_E0119       SMT_EBASE + 19
-#define        SMT_E0119_MSG   "smt_add_para"
-#define        SMT_E0120       SMT_EBASE + 20
-#define        SMT_E0120_MSG   "smt_set_para"
-#define        SMT_E0121       SMT_EBASE + 21
-#define        SMT_E0121_MSG   "invalid event in dispatcher"
-#define        SMT_E0122       SMT_EBASE + 22
-#define        SMT_E0122_MSG   "RMT : invalid state"
-#define        SMT_E0123       SMT_EBASE + 23
-#define        SMT_E0123_MSG   "SBA: state machine has invalid state"
-#define        SMT_E0124       SMT_EBASE + 24
-#define        SMT_E0124_MSG   "sba_free_session() called with NULL pointer"
-#define        SMT_E0125       SMT_EBASE + 25
-#define        SMT_E0125_MSG   "SBA : invalid session pointer"
-#define        SMT_E0126       SMT_EBASE + 26
-#define        SMT_E0126_MSG   "smt_free_mbuf() called with NULL pointer\n"
-#define        SMT_E0127       SMT_EBASE + 27
-#define        SMT_E0127_MSG   "sizeof evcs"
-#define        SMT_E0128       SMT_EBASE + 28
-#define        SMT_E0128_MSG   "evc->evc_cond_state = 0"
-#define        SMT_E0129       SMT_EBASE + 29
-#define        SMT_E0129_MSG   "evc->evc_multiple = 0"
-#define        SMT_E0130       SMT_EBASE + 30
-#define        SMT_E0130_MSG   write_mdr_warning
-#define        SMT_E0131       SMT_EBASE + 31
-#define        SMT_E0131_MSG   cam_warning
-#define SMT_E0132      SMT_EBASE + 32
-#define SMT_E0132_MSG  "ST1L.FM_SPCEPDx parity/coding error"
-#define SMT_E0133      SMT_EBASE + 33
-#define SMT_E0133_MSG  "ST1L.FM_STBURx tx buffer underrun"
-#define SMT_E0134      SMT_EBASE + 34
-#define SMT_E0134_MSG  "ST1L.FM_SPCEPDx parity error"
-#define SMT_E0135      SMT_EBASE + 35
-#define SMT_E0135_MSG  "RMT: duplicate MAC address detected. Ring left!"
-#define SMT_E0136      SMT_EBASE + 36
-#define SMT_E0136_MSG  "Elasticity Buffer hang-up"
-#define SMT_E0137      SMT_EBASE + 37
-#define SMT_E0137_MSG  "SMT: queue overrun"
-#define SMT_E0138      SMT_EBASE + 38
-#define SMT_E0138_MSG  "RMT: duplicate MAC address detected. Ring NOT left!"
-#endif /* _CMTDEF_ */
diff --git a/drivers/net/skfp/h/fddi.h b/drivers/net/skfp/h/fddi.h
deleted file mode 100644 (file)
index c9a28a8..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _FDDI_
-#define _FDDI_
-
-struct fddi_addr {
-       u_char  a[6] ;
-} ;
-
-#define GROUP_ADDR     0x80            /* MSB in a[0] */
-
-struct fddi_mac {
-       struct fddi_addr        mac_dest ;
-       struct fddi_addr        mac_source ;
-       u_char                  mac_info[4478] ;
-} ;
-
-#define FDDI_MAC_SIZE  (12)
-#define FDDI_RAW_MTU   (4500-5)        /* exl. Pr,SD, ED/FS */
-#define FDDI_RAW       (4500)
-
-/*
- * FC values
- */
-#define FC_VOID                0x40            /* void frame */
-#define FC_TOKEN       0x80            /* token */
-#define FC_RES_TOKEN   0xc0            /* restricted token */
-#define FC_SMT_INFO    0x41            /* SMT Info frame */
-/*
- * FC_SMT_LAN_LOC && FC_SMT_LOC are SK specific !
- */
-#define FC_SMT_LAN_LOC 0x42            /* local SMT Info frame */
-#define FC_SMT_LOC     0x43            /* local SMT Info frame */
-#define FC_SMT_NSA     0x4f            /* SMT NSA frame */
-#define FC_MAC         0xc0            /* MAC frame */
-#define FC_BEACON      0xc2            /* MAC beacon frame */
-#define FC_CLAIM       0xc3            /* MAC claim frame */
-#define FC_SYNC_LLC    0xd0            /* sync. LLC frame */
-#define FC_ASYNC_LLC   0x50            /* async. LLC frame */
-#define FC_SYNC_BIT    0x80            /* sync. bit in FC */
-
-#define FC_LLC_PRIOR   0x07            /* priority bits */
-
-#define BEACON_INFO    0               /* beacon type */
-#define DBEACON_INFO   1               /* beacon type DIRECTED */
-
-
-/*
- * indicator bits
- */
-#define C_INDICATOR    (1<<0)
-#define A_INDICATOR    (1<<1)
-#define E_INDICATOR    (1<<2)
-#define I_INDICATOR    (1<<6)          /* SK specific */ 
-#define L_INDICATOR    (1<<7)          /* SK specific */
-
-#endif /* _FDDI_ */
diff --git a/drivers/net/skfp/h/fddimib.h b/drivers/net/skfp/h/fddimib.h
deleted file mode 100644 (file)
index d1acdc7..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * FDDI MIB
- */
-
-/*
- * typedefs
- */
-
-typedef        u_long  Counter ;
-typedef u_char TimeStamp[8] ;
-typedef struct fddi_addr LongAddr ;
-typedef        u_long  Timer_2 ;
-typedef        u_long  Timer ;
-typedef        u_short ResId ;
-typedef u_short        SMTEnum ;
-typedef        u_char  SMTFlag ;
-
-typedef struct {
-       Counter         count ;
-       TimeStamp       timestamp ;
-} SetCountType ;
-
-/*
- * bits for bit string "available_path"
- */
-#define MIB_PATH_P     (1<<0)
-#define MIB_PATH_S     (1<<1)
-#define MIB_PATH_L     (1<<2)
-
-/*
- * bits for bit string PermittedPaths & RequestedPaths (SIZE(8))
- */
-#define MIB_P_PATH_LOCAL       (1<<0)
-#define MIB_P_PATH_SEC_ALTER   (1<<1)
-#define MIB_P_PATH_PRIM_ALTER  (1<<2)
-#define MIB_P_PATH_CON_ALTER   (1<<3)
-#define MIB_P_PATH_SEC_PREFER  (1<<4)
-#define MIB_P_PATH_PRIM_PREFER (1<<5)
-#define MIB_P_PATH_CON_PREFER  (1<<6)
-#define MIB_P_PATH_THRU                (1<<7)
-
-/*
- * enum current path
- */
-#define MIB_PATH_ISOLATED      0
-#define MIB_PATH_LOCAL         1
-#define MIB_PATH_SECONDARY     2
-#define MIB_PATH_PRIMARY       3
-#define MIB_PATH_CONCATENATED  4
-#define MIB_PATH_THRU          5
-
-/*
- * enum PMDClass
- */
-#define MIB_PMDCLASS_MULTI     0
-#define MIB_PMDCLASS_SINGLE1   1
-#define MIB_PMDCLASS_SINGLE2   2
-#define MIB_PMDCLASS_SONET     3
-#define MIB_PMDCLASS_LCF       4
-#define MIB_PMDCLASS_TP                5
-#define MIB_PMDCLASS_UNKNOWN   6
-#define MIB_PMDCLASS_UNSPEC    7
-
-/*
- * enum SMTStationStatus
- */
-#define MIB_SMT_STASTA_CON     0
-#define MIB_SMT_STASTA_SEPA    1
-#define MIB_SMT_STASTA_THRU    2
-
-
-struct fddi_mib {
-       /*
-        * private
-        */
-       u_char                  fddiPRPMFPasswd[8] ;
-       struct smt_sid          fddiPRPMFStation ;
-
-#ifdef ESS
-       /*
-        * private variables for static allocation of the
-        * End Station Support
-        */
-       u_long  fddiESSPayload ;        /* payload for static alloc */
-       u_long  fddiESSOverhead ;       /* frame ov for static alloc */
-       u_long  fddiESSMaxTNeg ;        /* maximum of T-NEG */
-       u_long  fddiESSMinSegmentSize ; /* min size of the sync frames */
-       u_long  fddiESSCategory ;       /* category for the Alloc req */
-       short   fddiESSSynchTxMode ;    /* send all LLC frames as sync */
-#endif /* ESS */
-#ifdef SBA
-       /*
-        * private variables for the Synchronous Bandwidth Allocator
-        */
-       char    fddiSBACommand ;        /* holds the parsed SBA cmd */
-       u_char  fddiSBAAvailable ;      /* SBA allocatable value */
-#endif /* SBA */
-
-       /*
-        * SMT standard mib
-        */
-       struct smt_sid          fddiSMTStationId ;
-       u_short                 fddiSMTOpVersionId ;
-       u_short                 fddiSMTHiVersionId ;
-       u_short                 fddiSMTLoVersionId ;
-       u_char                  fddiSMTManufacturerData[32] ;
-       u_char                  fddiSMTUserData[32] ;
-       u_short                 fddiSMTMIBVersionId ;
-
-       /*
-        * ConfigGrp
-        */
-       u_char                  fddiSMTMac_Ct ;
-       u_char                  fddiSMTNonMaster_Ct ;
-       u_char                  fddiSMTMaster_Ct ;
-       u_char                  fddiSMTAvailablePaths ;
-       u_short                 fddiSMTConfigCapabilities ;
-       u_short                 fddiSMTConfigPolicy ;
-       u_short                 fddiSMTConnectionPolicy ;
-       u_short                 fddiSMTTT_Notify ;
-       u_char                  fddiSMTStatRptPolicy ;
-       u_long                  fddiSMTTrace_MaxExpiration ;
-       u_short                 fddiSMTPORTIndexes[NUMPHYS] ;
-       u_short                 fddiSMTMACIndexes ;
-       u_char                  fddiSMTBypassPresent ;
-
-       /*
-        * StatusGrp
-        */
-       SMTEnum                 fddiSMTECMState ;
-       SMTEnum                 fddiSMTCF_State ;
-       SMTEnum                 fddiSMTStationStatus ;
-       u_char                  fddiSMTRemoteDisconnectFlag ;
-       u_char                  fddiSMTPeerWrapFlag ;
-
-       /*
-        * MIBOperationGrp
-        */
-       TimeStamp               fddiSMTTimeStamp ;
-       TimeStamp               fddiSMTTransitionTimeStamp ;
-       SetCountType            fddiSMTSetCount ;
-       struct smt_sid          fddiSMTLastSetStationId ;
-
-       struct fddi_mib_m {
-               u_short         fddiMACFrameStatusFunctions ;
-               Timer_2         fddiMACT_MaxCapabilitiy ;
-               Timer_2         fddiMACTVXCapabilitiy ;
-
-               /* ConfigGrp */
-               u_char          fddiMACMultiple_N ;     /* private */
-               u_char          fddiMACMultiple_P ;     /* private */
-               u_char          fddiMACDuplicateAddressCond ;/* private */
-               u_char          fddiMACAvailablePaths ;
-               u_short         fddiMACCurrentPath ;
-               LongAddr        fddiMACUpstreamNbr ;
-               LongAddr        fddiMACDownstreamNbr ;
-               LongAddr        fddiMACOldUpstreamNbr ;
-               LongAddr        fddiMACOldDownstreamNbr ;
-               SMTEnum         fddiMACDupAddressTest ;
-               u_short         fddiMACRequestedPaths ;
-               SMTEnum         fddiMACDownstreamPORTType ;
-               ResId           fddiMACIndex ;
-
-               /* AddressGrp */
-               LongAddr        fddiMACSMTAddress ;
-
-               /* OperationGrp */
-               Timer_2         fddiMACT_Min ;  /* private */
-               Timer_2         fddiMACT_ReqMIB ;
-               Timer_2         fddiMACT_Req ;  /* private */
-               Timer_2         fddiMACT_Neg ;
-               Timer_2         fddiMACT_MaxMIB ;
-               Timer_2         fddiMACT_Max ;  /* private */
-               Timer_2         fddiMACTvxValueMIB ;
-               Timer_2         fddiMACTvxValue ; /* private */
-               Timer_2         fddiMACT_Pri0 ;
-               Timer_2         fddiMACT_Pri1 ;
-               Timer_2         fddiMACT_Pri2 ;
-               Timer_2         fddiMACT_Pri3 ;
-               Timer_2         fddiMACT_Pri4 ;
-               Timer_2         fddiMACT_Pri5 ;
-               Timer_2         fddiMACT_Pri6 ;
-
-               /* CountersGrp */
-               Counter         fddiMACFrame_Ct ;
-               Counter         fddiMACCopied_Ct ;
-               Counter         fddiMACTransmit_Ct ;
-               Counter         fddiMACToken_Ct ;
-               Counter         fddiMACError_Ct ;
-               Counter         fddiMACLost_Ct ;
-               Counter         fddiMACTvxExpired_Ct ;
-               Counter         fddiMACNotCopied_Ct ;
-               Counter         fddiMACRingOp_Ct ;
-
-               Counter         fddiMACSMTCopied_Ct ;           /* private */
-               Counter         fddiMACSMTTransmit_Ct ;         /* private */
-
-               /* private for delta ratio */
-               Counter         fddiMACOld_Frame_Ct ;
-               Counter         fddiMACOld_Copied_Ct ;
-               Counter         fddiMACOld_Error_Ct ;
-               Counter         fddiMACOld_Lost_Ct ;
-               Counter         fddiMACOld_NotCopied_Ct ;
-
-               /* FrameErrorConditionGrp */
-               u_short         fddiMACFrameErrorThreshold ;
-               u_short         fddiMACFrameErrorRatio ;
-
-               /* NotCopiedConditionGrp */
-               u_short         fddiMACNotCopiedThreshold ;
-               u_short         fddiMACNotCopiedRatio ;
-
-               /* StatusGrp */
-               SMTEnum         fddiMACRMTState ;
-               SMTFlag         fddiMACDA_Flag ;
-               SMTFlag         fddiMACUNDA_Flag ;
-               SMTFlag         fddiMACFrameErrorFlag ;
-               SMTFlag         fddiMACNotCopiedFlag ;
-               SMTFlag         fddiMACMA_UnitdataAvailable ;
-               SMTFlag         fddiMACHardwarePresent ;
-               SMTFlag         fddiMACMA_UnitdataEnable ;
-
-       } m[NUMMACS] ;
-#define MAC0   0
-
-       struct fddi_mib_a {
-               ResId           fddiPATHIndex ;
-               u_long          fddiPATHSbaPayload ;
-               u_long          fddiPATHSbaOverhead ;
-               /* fddiPATHConfiguration is built on demand */
-               /* u_long               fddiPATHConfiguration ; */
-               Timer           fddiPATHT_Rmode ;
-               u_long          fddiPATHSbaAvailable ;
-               Timer_2         fddiPATHTVXLowerBound ;
-               Timer_2         fddiPATHT_MaxLowerBound ;
-               Timer_2         fddiPATHMaxT_Req ;
-       } a[NUMPATHS] ;
-#define PATH0  0
-
-       struct fddi_mib_p {
-               /* ConfigGrp */
-               SMTEnum         fddiPORTMy_Type ;
-               SMTEnum         fddiPORTNeighborType ;
-               u_char          fddiPORTConnectionPolicies ;
-               struct {
-                       u_char  T_val ;
-                       u_char  R_val ;
-               } fddiPORTMacIndicated ;
-               SMTEnum         fddiPORTCurrentPath ;
-               /* must be 4: is 32 bit in SMT format
-                * indices :
-                *      1       none
-                *      2       tree
-                *      3       peer
-                */
-               u_char          fddiPORTRequestedPaths[4] ;
-               u_short         fddiPORTMACPlacement ;
-               u_char          fddiPORTAvailablePaths ;
-               u_char          fddiPORTConnectionCapabilities ;
-               SMTEnum         fddiPORTPMDClass ;
-               ResId           fddiPORTIndex ;
-
-               /* OperationGrp */
-               SMTEnum         fddiPORTMaint_LS ;
-               SMTEnum         fddiPORTPC_LS ;
-               u_char          fddiPORTBS_Flag ;
-
-               /* ErrorCtrsGrp */
-               Counter         fddiPORTLCTFail_Ct ;
-               Counter         fddiPORTEBError_Ct ;
-               Counter         fddiPORTOldEBError_Ct ;
-
-               /* LerGrp */
-               Counter         fddiPORTLem_Reject_Ct ;
-               Counter         fddiPORTLem_Ct ;
-               u_char          fddiPORTLer_Estimate ;
-               u_char          fddiPORTLer_Cutoff ;
-               u_char          fddiPORTLer_Alarm ;
-
-               /* StatusGrp */
-               SMTEnum         fddiPORTConnectState ;
-               SMTEnum         fddiPORTPCMState ;      /* real value */
-               SMTEnum         fddiPORTPCMStateX ;     /* value for MIB */
-               SMTEnum         fddiPORTPC_Withhold ;
-               SMTFlag         fddiPORTHardwarePresent ;
-               u_char          fddiPORTLerFlag ;
-
-               u_char          fddiPORTMultiple_U ;    /* private */
-               u_char          fddiPORTMultiple_P ;    /* private */
-               u_char          fddiPORTEB_Condition ;  /* private */
-       } p[NUMPHYS] ;
-       struct {
-               Counter         fddiPRIVECF_Req_Rx ;    /* ECF req received */
-               Counter         fddiPRIVECF_Reply_Rx ;  /* ECF repl received */
-               Counter         fddiPRIVECF_Req_Tx ;    /* ECF req transm */
-               Counter         fddiPRIVECF_Reply_Tx ;  /* ECF repl transm */
-               Counter         fddiPRIVPMF_Get_Rx ;    /* PMF Get rec */
-               Counter         fddiPRIVPMF_Set_Rx ;    /* PMF Set rec */
-               Counter         fddiPRIVRDF_Rx ;        /* RDF received */
-               Counter         fddiPRIVRDF_Tx ;        /* RDF transmitted */
-       } priv ;
-} ;
-
-/*
- * OIDs for statistics
- */
-#define        SMT_OID_CF_STATE        1       /* fddiSMTCF_State */
-#define        SMT_OID_PCM_STATE_A     2       /* fddiPORTPCMState port A */
-#define        SMT_OID_PCM_STATE_B     17      /* fddiPORTPCMState port B */
-#define        SMT_OID_RMT_STATE       3       /* fddiMACRMTState */
-#define        SMT_OID_UNA             4       /* fddiMACUpstreamNbr */
-#define        SMT_OID_DNA             5       /* fddiMACOldDownstreamNbr */
-#define        SMT_OID_ERROR_CT        6       /* fddiMACError_Ct */
-#define        SMT_OID_LOST_CT         7       /* fddiMACLost_Ct */
-#define        SMT_OID_LEM_CT          8       /* fddiPORTLem_Ct */
-#define        SMT_OID_LEM_CT_A        11      /* fddiPORTLem_Ct port A */
-#define        SMT_OID_LEM_CT_B        12      /* fddiPORTLem_Ct port B */
-#define        SMT_OID_LCT_FAIL_CT     9       /* fddiPORTLCTFail_Ct */
-#define        SMT_OID_LCT_FAIL_CT_A   13      /* fddiPORTLCTFail_Ct port A */
-#define        SMT_OID_LCT_FAIL_CT_B   14      /* fddiPORTLCTFail_Ct port B */
-#define        SMT_OID_LEM_REJECT_CT   10      /* fddiPORTLem_Reject_Ct */
-#define        SMT_OID_LEM_REJECT_CT_A 15      /* fddiPORTLem_Reject_Ct port A */
-#define        SMT_OID_LEM_REJECT_CT_B 16      /* fddiPORTLem_Reject_Ct port B */
-
-/*
- * SK MIB
- */
-#define SMT_OID_ECF_REQ_RX     20      /* ECF requests received */
-#define SMT_OID_ECF_REPLY_RX   21      /* ECF replies received */
-#define SMT_OID_ECF_REQ_TX     22      /* ECF requests transmitted */
-#define SMT_OID_ECF_REPLY_TX   23      /* ECF replies transmitted */
-#define SMT_OID_PMF_GET_RX     24      /* PMF get requests received */
-#define SMT_OID_PMF_SET_RX     25      /* PMF set requests received */
-#define SMT_OID_RDF_RX         26      /* RDF received */
-#define SMT_OID_RDF_TX         27      /* RDF transmitted */
diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/skfp/h/fplustm.h
deleted file mode 100644 (file)
index d43191e..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *     AMD Fplus in tag mode data structs
- *     defs for fplustm.c
- */
-
-#ifndef        _FPLUS_
-#define _FPLUS_
-
-#ifndef        HW_PTR
-#define        HW_PTR  void __iomem *
-#endif
-
-/*
- * fplus error statistic structure
- */
-struct err_st {
-       u_long err_valid ;              /* memory status valid */
-       u_long err_abort ;              /* memory status receive abort */
-       u_long err_e_indicator ;        /* error indicator */
-       u_long err_crc ;                /* error detected (CRC or length) */
-       u_long err_llc_frame ;          /* LLC frame */
-       u_long err_mac_frame ;          /* MAC frame */
-       u_long err_smt_frame ;          /* SMT frame */
-       u_long err_imp_frame ;          /* implementer frame */
-       u_long err_no_buf ;             /* no buffer available */
-       u_long err_too_long ;           /* longer than max. buffer */
-       u_long err_bec_stat ;           /* beacon state entered */
-       u_long err_clm_stat ;           /* claim state entered */
-       u_long err_sifg_det ;           /* short interframe gap detect */
-       u_long err_phinv ;              /* PHY invalid */
-       u_long err_tkiss ;              /* token issued */
-       u_long err_tkerr ;              /* token error */
-} ;
-
-/*
- *     Transmit Descriptor struct
- */
-struct s_smt_fp_txd {
-       __le32 txd_tbctrl ;             /* transmit buffer control */
-       __le32 txd_txdscr ;             /* transmit frame status word */
-       __le32 txd_tbadr ;              /* physical tx buffer address */
-       __le32 txd_ntdadr ;             /* physical pointer to the next TxD */
-#ifdef ENA_64BIT_SUP
-       __le32 txd_tbadr_hi ;           /* physical tx buffer addr (high dword)*/
-#endif
-       char far *txd_virt ;            /* virtual pointer to the data frag */
-                                       /* virt pointer to the next TxD */
-       struct s_smt_fp_txd volatile far *txd_next ;
-       struct s_txd_os txd_os ;        /* OS - specific struct */
-} ;
-
-/*
- *     Receive Descriptor struct
- */
-struct s_smt_fp_rxd {
-       __le32 rxd_rbctrl ;             /* receive buffer control */
-       __le32 rxd_rfsw ;               /* receive frame status word */
-       __le32 rxd_rbadr ;              /* physical rx buffer address */
-       __le32 rxd_nrdadr ;             /* physical pointer to the next RxD */
-#ifdef ENA_64BIT_SUP
-       __le32 rxd_rbadr_hi ;           /* physical tx buffer addr (high dword)*/
-#endif
-       char far *rxd_virt ;            /* virtual pointer to the data frag */
-                                       /* virt pointer to the next RxD */
-       struct s_smt_fp_rxd volatile far *rxd_next ;
-       struct s_rxd_os rxd_os ;        /* OS - specific struct */
-} ;
-
-/*
- *     Descriptor Union Definition
- */
-union s_fp_descr {
-       struct  s_smt_fp_txd t ;                /* pointer to the TxD */
-       struct  s_smt_fp_rxd r ;                /* pointer to the RxD */
-} ;
-
-/*
- *     TxD Ring Control struct
- */
-struct s_smt_tx_queue {
-       struct s_smt_fp_txd volatile *tx_curr_put ; /* next free TxD */
-       struct s_smt_fp_txd volatile *tx_prev_put ; /* shadow put pointer */
-       struct s_smt_fp_txd volatile *tx_curr_get ; /* next TxD to release*/
-       u_short tx_free ;                       /* count of free TxD's */
-       u_short tx_used ;                       /* count of used TxD's */
-       HW_PTR tx_bmu_ctl ;                     /* BMU addr for tx start */
-       HW_PTR tx_bmu_dsc ;                     /* BMU addr for curr dsc. */
-} ;
-
-/*
- *     RxD Ring Control struct
- */
-struct s_smt_rx_queue {
-       struct s_smt_fp_rxd volatile *rx_curr_put ; /* next RxD to queue into */
-       struct s_smt_fp_rxd volatile *rx_prev_put ; /* shadow put pointer */
-       struct s_smt_fp_rxd volatile *rx_curr_get ; /* next RxD to fill */
-       u_short rx_free ;                       /* count of free RxD's */
-       u_short rx_used ;                       /* count of used RxD's */
-       HW_PTR rx_bmu_ctl ;                     /* BMU addr for rx start */
-       HW_PTR rx_bmu_dsc ;                     /* BMU addr for curr dsc. */
-} ;
-
-#define VOID_FRAME_OFF         0x00
-#define CLAIM_FRAME_OFF                0x08
-#define BEACON_FRAME_OFF       0x10
-#define DBEACON_FRAME_OFF      0x18
-#define RX_FIFO_OFF            0x21            /* to get a prime number for */
-                                               /* the RX_FIFO_SPACE */
-
-#define RBC_MEM_SIZE           0x8000
-#define SEND_ASYNC_AS_SYNC     0x1
-#define        SYNC_TRAFFIC_ON         0x2
-
-/* big FIFO memory */
-#define        RX_FIFO_SPACE           0x4000 - RX_FIFO_OFF
-#define        TX_FIFO_SPACE           0x4000
-
-#define        TX_SMALL_FIFO           0x0900
-#define        TX_MEDIUM_FIFO          TX_FIFO_SPACE / 2       
-#define        TX_LARGE_FIFO           TX_FIFO_SPACE - TX_SMALL_FIFO   
-
-#define        RX_SMALL_FIFO           0x0900
-#define        RX_LARGE_FIFO           RX_FIFO_SPACE - RX_SMALL_FIFO   
-
-struct s_smt_fifo_conf {
-       u_short rbc_ram_start ;         /* FIFO start address */
-       u_short rbc_ram_end ;           /* FIFO size */
-       u_short rx1_fifo_start ;        /* rx queue start address */
-       u_short rx1_fifo_size ;         /* rx queue size */
-       u_short rx2_fifo_start ;        /* rx queue start address */
-       u_short rx2_fifo_size ;         /* rx queue size */
-       u_short tx_s_start ;            /* sync queue start address */
-       u_short tx_s_size ;             /* sync queue size */
-       u_short tx_a0_start ;           /* async queue A0 start address */
-       u_short tx_a0_size ;            /* async queue A0 size */
-       u_short fifo_config_mode ;      /* FIFO configuration mode */
-} ;
-
-#define FM_ADDRX       (FM_ADDET|FM_EXGPA0|FM_EXGPA1)
-
-struct s_smt_fp {
-       u_short mdr2init ;              /* mode register 2 init value */
-       u_short mdr3init ;              /* mode register 3 init value */
-       u_short frselreg_init ;         /* frame selection register init val */
-       u_short rx_mode ;               /* address mode broad/multi/promisc */
-       u_short nsa_mode ;
-       u_short rx_prom ;
-       u_short exgpa ;
-
-       struct err_st err_stats ;       /* error statistics */
-
-       /*
-        * MAC buffers
-        */
-       struct fddi_mac_sf {            /* special frame build buffer */
-               u_char                  mac_fc ;
-               struct fddi_addr        mac_dest ;
-               struct fddi_addr        mac_source ;
-               u_char                  mac_info[0x20] ;
-       } mac_sfb ;
-
-
-       /*
-        * queues
-        */
-#define QUEUE_S                        0
-#define QUEUE_A0               1
-#define QUEUE_R1               0
-#define QUEUE_R2               1
-#define USED_QUEUES            2
-
-       /*
-        * queue pointers; points to the queue dependent variables
-        */
-       struct s_smt_tx_queue *tx[USED_QUEUES] ;
-       struct s_smt_rx_queue *rx[USED_QUEUES] ;
-
-       /*
-        * queue dependent variables
-        */
-       struct s_smt_tx_queue tx_q[USED_QUEUES] ;
-       struct s_smt_rx_queue rx_q[USED_QUEUES] ;
-
-       /*
-        * FIFO configuration struct
-        */
-       struct  s_smt_fifo_conf fifo ;
-
-       /* last formac status */
-       u_short  s2u ;
-       u_short  s2l ;
-
-       /* calculated FORMAC+ reg.addr. */
-       HW_PTR  fm_st1u ;
-       HW_PTR  fm_st1l ;
-       HW_PTR  fm_st2u ;
-       HW_PTR  fm_st2l ;
-       HW_PTR  fm_st3u ;
-       HW_PTR  fm_st3l ;
-
-
-       /*
-        * multicast table
-        */
-#define FPMAX_MULTICAST 32 
-#define        SMT_MAX_MULTI   4
-       struct {
-               struct s_fpmc {
-                       struct fddi_addr        a ;     /* mc address */
-                       u_char                  n ;     /* usage counter */
-                       u_char                  perm ;  /* flag: permanent */
-               } table[FPMAX_MULTICAST] ;
-       } mc ;
-       struct fddi_addr        group_addr ;
-       u_long  func_addr ;             /* functional address */
-       int     smt_slots_used ;        /* count of table entries for the SMT */
-       int     os_slots_used ;         /* count of table entries */ 
-                                       /* used by the os-specific module */
-} ;
-
-/*
- * modes for mac_set_rx_mode()
- */
-#define RX_ENABLE_ALLMULTI     1       /* enable all multicasts */
-#define RX_DISABLE_ALLMULTI    2       /* disable "enable all multicasts" */
-#define RX_ENABLE_PROMISC      3       /* enable promiscuous */
-#define RX_DISABLE_PROMISC     4       /* disable promiscuous */
-#define RX_ENABLE_NSA          5       /* enable reception of NSA frames */
-#define RX_DISABLE_NSA         6       /* disable reception of NSA frames */
-
-
-/*
- * support for byte reversal in AIX
- * (descriptors and pointers must be byte reversed in memory
- *  CPU is big endian; M-Channel is little endian)
- */
-#ifdef AIX
-#define MDR_REV
-#define        AIX_REVERSE(x)          ((((x)<<24L)&0xff000000L)       +       \
-                                (((x)<< 8L)&0x00ff0000L)       +       \
-                                (((x)>> 8L)&0x0000ff00L)       +       \
-                                (((x)>>24L)&0x000000ffL))
-#else
-#ifndef AIX_REVERSE
-#define        AIX_REVERSE(x)  (x)
-#endif
-#endif
-
-#ifdef MDR_REV 
-#define        MDR_REVERSE(x)          ((((x)<<24L)&0xff000000L)       +       \
-                                (((x)<< 8L)&0x00ff0000L)       +       \
-                                (((x)>> 8L)&0x0000ff00L)       +       \
-                                (((x)>>24L)&0x000000ffL))
-#else
-#ifndef MDR_REVERSE
-#define        MDR_REVERSE(x)  (x)
-#endif
-#endif
-
-#endif
diff --git a/drivers/net/skfp/h/hwmtm.h b/drivers/net/skfp/h/hwmtm.h
deleted file mode 100644 (file)
index e1a7e5f..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _HWM_
-#define        _HWM_
-
-#include "h/mbuf.h"
-
-/*
- * MACRO for DMA synchronization:
- *     The descriptor 'desc' is flushed for the device 'flag'.
- *     Devices are the CPU (DDI_DMA_SYNC_FORCPU) and the
- *     adapter (DDI_DMA_SYNC_FORDEV).
- *
- *     'desc'  Pointer to a Rx or Tx descriptor.
- *     'flag'  Flag for direction (view for CPU or DEVICE) that
- *             should be synchronized.
- *
- *     Empty macros and defines are specified here. The real macro
- *     is os-specific and should be defined in osdef1st.h.
- */
-#ifndef DRV_BUF_FLUSH
-#define DRV_BUF_FLUSH(desc,flag)
-#define DDI_DMA_SYNC_FORCPU
-#define DDI_DMA_SYNC_FORDEV
-#endif
-
-       /*
-        * hardware modul dependent receive modes
-        */
-#define        RX_ENABLE_PASS_SMT      21
-#define        RX_DISABLE_PASS_SMT     22
-#define        RX_ENABLE_PASS_NSA      23
-#define        RX_DISABLE_PASS_NSA     24
-#define        RX_ENABLE_PASS_DB       25
-#define        RX_DISABLE_PASS_DB      26
-#define        RX_DISABLE_PASS_ALL     27
-#define        RX_DISABLE_LLC_PROMISC  28
-#define        RX_ENABLE_LLC_PROMISC   29
-
-
-#ifndef        DMA_RD
-#define DMA_RD         1       /* memory -> hw */
-#endif
-#ifndef DMA_WR
-#define DMA_WR         2       /* hw -> memory */
-#endif
-#define SMT_BUF                0x80
-
-       /*
-        * bits of the frame status byte
-        */
-#define EN_IRQ_EOF     0x02    /* get IRQ after end of frame transmission */
-#define        LOC_TX          0x04    /* send frame to the local SMT */
-#define LAST_FRAG      0x08    /* last TxD of the frame */
-#define        FIRST_FRAG      0x10    /* first TxD of the frame */
-#define        LAN_TX          0x20    /* send frame to network if set */
-#define RING_DOWN      0x40    /* error: unable to send, ring down */
-#define OUT_OF_TXD     0x80    /* error: not enough TxDs available */
-
-
-#ifndef NULL
-#define NULL           0
-#endif
-
-#ifdef LITTLE_ENDIAN
-#define HWM_REVERSE(x) (x)
-#else
-#define        HWM_REVERSE(x)          ((((x)<<24L)&0xff000000L)       +       \
-                                (((x)<< 8L)&0x00ff0000L)       +       \
-                                (((x)>> 8L)&0x0000ff00L)       +       \
-                                (((x)>>24L)&0x000000ffL))
-#endif
-
-#define C_INDIC                (1L<<25)
-#define A_INDIC                (1L<<26)
-#define        RD_FS_LOCAL     0x80
-
-       /*
-        * DEBUG FLAGS
-        */
-#define        DEBUG_SMTF      1
-#define        DEBUG_SMT       2
-#define        DEBUG_ECM       3
-#define        DEBUG_RMT       4
-#define        DEBUG_CFM       5
-#define        DEBUG_PCM       6
-#define        DEBUG_SBA       7
-#define        DEBUG_ESS       8
-
-#define        DB_HWM_RX       10
-#define        DB_HWM_TX       11
-#define DB_HWM_GEN     12
-
-struct s_mbuf_pool {
-#ifndef        MB_OUTSIDE_SMC
-       SMbuf           mb[MAX_MBUF] ;          /* mbuf pool */
-#endif
-       SMbuf           *mb_start ;             /* points to the first mb */
-       SMbuf           *mb_free ;              /* free queue */
-} ;
-
-struct hwm_r {
-       /*
-        * hardware modul specific receive variables
-        */
-       u_int                   len ;           /* length of the whole frame */
-       char                    *mb_pos ;       /* SMbuf receive position */
-} ;
-
-struct hw_modul {
-       /*
-        * All hardware modul specific variables
-        */
-       struct  s_mbuf_pool     mbuf_pool ;
-       struct  hwm_r   r ;
-
-       union s_fp_descr volatile *descr_p ; /* points to the desriptor area */
-
-       u_short pass_SMT ;              /* pass SMT frames */
-       u_short pass_NSA ;              /* pass all NSA frames */
-       u_short pass_DB ;               /* pass Direct Beacon Frames */
-       u_short pass_llc_promisc ;      /* pass all llc frames (default ON) */
-
-       SMbuf   *llc_rx_pipe ;          /* points to the first queued llc fr */
-       SMbuf   *llc_rx_tail ;          /* points to the last queued llc fr */
-       int     queued_rx_frames ;      /* number of queued frames */
-
-       SMbuf   *txd_tx_pipe ;          /* points to first mb in the txd ring */
-       SMbuf   *txd_tx_tail ;          /* points to last mb in the txd ring */
-       int     queued_txd_mb ;         /* number of SMT MBufs in txd ring */
-
-       int     rx_break ;              /* rev. was breaked because ind. off */
-       int     leave_isr ;             /* leave fddi_isr immedeately if set */
-       int     isr_flag ;              /* set, when HWM is entered from isr */
-       /*
-        * variables for the current transmit frame
-        */
-       struct s_smt_tx_queue *tx_p ;   /* pointer to the transmit queue */
-       u_long  tx_descr ;              /* tx descriptor for FORMAC+ */
-       int     tx_len ;                /* tx frame length */
-       SMbuf   *tx_mb ;                /* SMT tx MBuf pointer */
-       char    *tx_data ;              /* data pointer to the SMT tx Mbuf */
-
-       int     detec_count ;           /* counter for out of RxD condition */
-       u_long  rx_len_error ;          /* rx len FORMAC != sum of fragments */
-} ;
-
-
-/*
- * DEBUG structs and macros
- */
-
-#ifdef DEBUG
-struct os_debug {
-       int     hwm_rx ;
-       int     hwm_tx ;
-       int     hwm_gen ;
-} ;
-#endif
-
-#ifdef DEBUG
-#ifdef DEBUG_BRD
-#define        DB_P    smc->debug
-#else
-#define DB_P   debug
-#endif
-
-#define DB_RX(a,b,c,lev) if (DB_P.d_os.hwm_rx >= (lev))        printf(a,b,c)
-#define DB_TX(a,b,c,lev) if (DB_P.d_os.hwm_tx >= (lev))        printf(a,b,c)
-#define DB_GEN(a,b,c,lev) if (DB_P.d_os.hwm_gen >= (lev)) printf(a,b,c)
-#else  /* DEBUG */
-#define DB_RX(a,b,c,lev)
-#define DB_TX(a,b,c,lev)
-#define DB_GEN(a,b,c,lev)
-#endif /* DEBUG */
-
-#ifndef        SK_BREAK
-#define        SK_BREAK()
-#endif
-
-
-/*
- * HWM Macros
- */
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_TX_PHYS)
- *     u_long HWM_GET_TX_PHYS(txd)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to read
- *             the physical address of the specified TxD.
- *
- * para        txd     pointer to the TxD
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_TX_PHYS(txd)            (u_long)AIX_REVERSE((txd)->txd_tbadr)
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_TX_LEN)
- *     int HWM_GET_TX_LEN(txd)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to read
- *             the fragment length of the specified TxD
- *
- * para        rxd     pointer to the TxD
- *
- * return      the length of the fragment in bytes
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_TX_LEN(txd)     ((int)AIX_REVERSE((txd)->txd_tbctrl)& RD_LENGTH)
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_TX_USED)
- *     txd *HWM_GET_TX_USED(smc,queue)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to get the
- *             number of used TxDs for the queue, specified by the index.
- *
- * para        queue   the number of the send queue: Can be specified by
- *             QUEUE_A0, QUEUE_S or (frame_status & QUEUE_A0)
- *
- * return      number of used TxDs for this send queue
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_TX_USED(smc,queue)      (int) (smc)->hw.fp.tx_q[queue].tx_used
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_CURR_TXD)
- *     txd *HWM_GET_CURR_TXD(smc,queue)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to get the
- *             pointer to the TxD which points to the current queue put
- *             position.
- *
- * para        queue   the number of the send queue: Can be specified by
- *             QUEUE_A0, QUEUE_S or (frame_status & QUEUE_A0)
- *
- * return      pointer to the current TxD
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_CURR_TXD(smc,queue)     (struct s_smt_fp_txd volatile *)\
-                                       (smc)->hw.fp.tx_q[queue].tx_curr_put
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_FRAG_LEN)
- *     int HWM_GET_RX_FRAG_LEN(rxd)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to read
- *             the fragment length of the specified RxD
- *
- * para        rxd     pointer to the RxD
- *
- * return      the length of the fragment in bytes
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_RX_FRAG_LEN(rxd)        ((int)AIX_REVERSE((rxd)->rxd_rbctrl)& \
-                               RD_LENGTH)
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_PHYS)
- *     u_long HWM_GET_RX_PHYS(rxd)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to read
- *             the physical address of the specified RxD.
- *
- * para        rxd     pointer to the RxD
- *
- * return      the RxD's physical pointer to the data fragment
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_RX_PHYS(rxd)    (u_long)AIX_REVERSE((rxd)->rxd_rbadr)
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_USED)
- *     int HWM_GET_RX_USED(smc)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to get
- *             the count of used RXDs in receive queue 1.
- *
- * return      the used RXD count of receive queue 1
- *
- * NOTE: Remember, because of an ASIC bug at least one RXD should be unused
- *      in the descriptor ring !
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_RX_USED(smc)    ((int)(smc)->hw.fp.rx_q[QUEUE_R1].rx_used)
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_RX_FREE)
- *     int HWM_GET_RX_FREE(smc)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to get
- *             the rxd_free count of receive queue 1.
- *
- * return      the rxd_free count of receive queue 1
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_RX_FREE(smc)    ((int)(smc)->hw.fp.rx_q[QUEUE_R1].rx_free-1)
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_GET_CURR_RXD)
- *     rxd *HWM_GET_CURR_RXD(smc)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro may be invoked by the OS-specific module to get the
- *             pointer to the RxD which points to the current queue put
- *             position.
- *
- * return      pointer to the current RxD
- *
- *     END_MANUAL_ENTRY
- */
-#define        HWM_GET_CURR_RXD(smc)   (struct s_smt_fp_rxd volatile *)\
-                               (smc)->hw.fp.rx_q[QUEUE_R1].rx_curr_put
-
-/*
- *     BEGIN_MANUAL_ENTRY(HWM_RX_CHECK)
- *     void HWM_RX_CHECK(smc,low_water)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This macro is invoked by the OS-specific before it left the
- *             function mac_drv_rx_complete. This macro calls mac_drv_fill_rxd
- *             if the number of used RxDs is equal or lower than the
- *             the given low water mark.
- *
- * para        low_water       low water mark of used RxD's
- *
- *     END_MANUAL_ENTRY
- */
-#ifndef HWM_NO_FLOW_CTL
-#define        HWM_RX_CHECK(smc,low_water) {\
-       if ((low_water) >= (smc)->hw.fp.rx_q[QUEUE_R1].rx_used) {\
-               mac_drv_fill_rxd(smc) ;\
-       }\
-}
-#else
-#define        HWM_RX_CHECK(smc,low_water)             mac_drv_fill_rxd(smc)
-#endif
-
-#ifndef        HWM_EBASE
-#define        HWM_EBASE       500
-#endif
-
-#define        HWM_E0001       HWM_EBASE + 1
-#define        HWM_E0001_MSG   "HWM: Wrong size of s_rxd_os struct"
-#define        HWM_E0002       HWM_EBASE + 2
-#define        HWM_E0002_MSG   "HWM: Wrong size of s_txd_os struct"
-#define        HWM_E0003       HWM_EBASE + 3
-#define        HWM_E0003_MSG   "HWM: smt_free_mbuf() called with NULL pointer"
-#define        HWM_E0004       HWM_EBASE + 4
-#define        HWM_E0004_MSG   "HWM: Parity error rx queue 1"
-#define        HWM_E0005       HWM_EBASE + 5
-#define        HWM_E0005_MSG   "HWM: Encoding error rx queue 1"
-#define        HWM_E0006       HWM_EBASE + 6
-#define        HWM_E0006_MSG   "HWM: Encoding error async tx queue"
-#define        HWM_E0007       HWM_EBASE + 7
-#define        HWM_E0007_MSG   "HWM: Encoding error sync tx queue"
-#define        HWM_E0008       HWM_EBASE + 8
-#define        HWM_E0008_MSG   ""
-#define        HWM_E0009       HWM_EBASE + 9
-#define        HWM_E0009_MSG   "HWM: Out of RxD condition detected"
-#define        HWM_E0010       HWM_EBASE + 10
-#define        HWM_E0010_MSG   "HWM: A protocol layer has tried to send a frame with an invalid frame control"
-#define HWM_E0011      HWM_EBASE + 11
-#define HWM_E0011_MSG  "HWM: mac_drv_clear_tx_queue was called although the hardware wasn't stopped"
-#define HWM_E0012      HWM_EBASE + 12
-#define HWM_E0012_MSG  "HWM: mac_drv_clear_rx_queue was called although the hardware wasn't stopped"
-#define HWM_E0013      HWM_EBASE + 13
-#define HWM_E0013_MSG  "HWM: mac_drv_repair_descr was called although the hardware wasn't stopped"
-
-#endif
diff --git a/drivers/net/skfp/h/mbuf.h b/drivers/net/skfp/h/mbuf.h
deleted file mode 100644 (file)
index f2aadcd..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _MBUF_
-#define _MBUF_
-
-#define M_SIZE 4504
-
-#ifndef MAX_MBUF
-#define MAX_MBUF       4
-#endif
-
-#ifndef NO_STD_MBUF
-#define sm_next         m_next
-#define sm_off          m_off
-#define sm_len          m_len
-#define sm_data         m_data
-#define SMbuf           Mbuf
-#define mtod           smtod
-#define mtodoff                smtodoff
-#endif
-
-struct s_mbuf {
-       struct s_mbuf   *sm_next ;              /* low level linked list */
-       short           sm_off ;                        /* offset in m_data */
-       u_int           sm_len ;                        /* len of data */
-#ifdef PCI
-       int             sm_use_count ;
-#endif
-       char            sm_data[M_SIZE] ;
-} ;
-
-typedef struct s_mbuf SMbuf ;
-
-/* mbuf head, to typed data */
-#define        smtod(x,t)      ((t)((x)->sm_data + (x)->sm_off))
-#define        smtodoff(x,t,o) ((t)((x)->sm_data + (o)))
-
-#endif /* _MBUF_ */
diff --git a/drivers/net/skfp/h/osdef1st.h b/drivers/net/skfp/h/osdef1st.h
deleted file mode 100644 (file)
index 763ca18..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/* 
- * Operating system-dependent definitions that have to be defined
- * before any other header files are included.
- */
-
-// HWM (HardWare Module) Definitions
-// -----------------------
-
-#include <asm/byteorder.h>
-
-#ifdef __LITTLE_ENDIAN
-#define LITTLE_ENDIAN
-#else
-#define BIG_ENDIAN
-#endif
-
-// this is set in the makefile
-// #define PCI                 /* only PCI adapters supported by this driver */
-// #define MEM_MAPPED_IO       /* use memory mapped I/O */
-
-
-#define USE_CAN_ADDR           /* DA and SA in MAC header are canonical. */
-
-#define MB_OUTSIDE_SMC         /* SMT Mbufs outside of smc struct. */
-
-// -----------------------
-
-
-// SMT Definitions 
-// -----------------------
-#define SYNC                   /* allow synchronous frames */
-
-// #define SBA                 /* Synchronous Bandwidth Allocator support */
-                               /* not available as free source */
-
-#define ESS                    /* SBA End Station Support */
-
-#define        SMT_PANIC(smc, nr, msg) printk(KERN_INFO "SMT PANIC: code: %d, msg: %s\n",nr,msg)
-
-
-#ifdef DEBUG
-#define printf(s,args...) printk(KERN_INFO s, ## args)
-#endif
-
-// #define HW_PTR      u_long
-// -----------------------
-
-
-
-// HWM and OS-specific buffer definitions
-// -----------------------
-
-// default number of receive buffers.
-#define NUM_RECEIVE_BUFFERS            10
-
-// default number of transmit buffers.
-#define NUM_TRANSMIT_BUFFERS           10
-
-// Number of SMT buffers (Mbufs).
-#define NUM_SMT_BUF    4
-
-// Number of TXDs for asynchronous transmit queue.
-#define HWM_ASYNC_TXD_COUNT    (NUM_TRANSMIT_BUFFERS + NUM_SMT_BUF)
-
-// Number of TXDs for synchronous transmit queue.
-#define HWM_SYNC_TXD_COUNT     HWM_ASYNC_TXD_COUNT
-
-
-// Number of RXDs for receive queue #1.
-// Note: Workaround for ASIC Errata #7: One extra RXD is required.
-#if (NUM_RECEIVE_BUFFERS > 100)
-#define SMT_R1_RXD_COUNT       (1 + 100)
-#else
-#define SMT_R1_RXD_COUNT       (1 + NUM_RECEIVE_BUFFERS)
-#endif
-
-// Number of RXDs for receive queue #2.
-#define SMT_R2_RXD_COUNT       0       // Not used.
-// -----------------------
-
-
-
-/*
- * OS-specific part of the transmit/receive descriptor structure (TXD/RXD).
- *
- * Note: The size of these structures must follow this rule:
- *
- *     sizeof(struct) + 2*sizeof(void*) == n * 16, n >= 1
- *
- * We use the dma_addr fields under Linux to keep track of the
- * DMA address of the packet data, for later pci_unmap_single. -DaveM
- */
-
-struct s_txd_os {      // os-specific part of transmit descriptor
-       struct sk_buff *skb;
-       dma_addr_t dma_addr;
-} ;
-
-struct s_rxd_os {      // os-specific part of receive descriptor
-       struct sk_buff *skb;
-       dma_addr_t dma_addr;
-} ;
-
-
-/*
- * So we do not need to make too many modifications to the generic driver
- * parts, we take advantage of the AIX byte swapping macro interface.
- */
-
-#define AIX_REVERSE(x)         ((u32)le32_to_cpu((u32)(x)))
-#define MDR_REVERSE(x)         ((u32)le32_to_cpu((u32)(x)))
diff --git a/drivers/net/skfp/h/sba.h b/drivers/net/skfp/h/sba.h
deleted file mode 100644 (file)
index 638cf02..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * Synchronous Bandwidth Allocation (SBA) structs
- */
-#ifndef _SBA_
-#define _SBA_
-
-#include "h/mbuf.h"
-#include "h/sba_def.h"
-
-#ifdef SBA
-
-/* Timer Cell Template */
-struct timer_cell {
-       struct timer_cell       *next_ptr ;
-       struct timer_cell       *prev_ptr ;
-       u_long                  start_time ;
-       struct s_sba_node_vars  *node_var ;
-} ;
-
-/*
- * Node variables
- */
-struct s_sba_node_vars {
-       u_char                  change_resp_flag ;
-       u_char                  report_resp_flag ;
-       u_char                  change_req_flag ;
-       u_char                  report_req_flag ;
-       long                    change_amount ;
-       long                    node_overhead ;
-       long                    node_payload ;
-       u_long                  node_status ;
-       u_char                  deallocate_status ;
-       u_char                  timer_state ;
-       u_short                 report_cnt ;
-       long                    lastrep_req_tranid ;
-       struct fddi_addr        mac_address ;
-       struct s_sba_sessions   *node_sessions ;
-       struct timer_cell       timer ;
-} ;
-
-/*
- * Session variables
- */
-struct s_sba_sessions {
-       u_long                  deallocate_status ;
-       long                    session_overhead ;
-       u_long                  min_segment_size ;
-       long                    session_payload ;
-       u_long                  session_status ;
-       u_long                  sba_category ;
-       long                    lastchg_req_tranid ;
-       u_short                 session_id ;
-       u_char                  class ;
-       u_char                  fddi2 ;
-       u_long                  max_t_neg ;
-       struct s_sba_sessions   *next_session ;
-} ;
-
-struct s_sba {
-
-       struct s_sba_node_vars  node[MAX_NODES] ;
-       struct s_sba_sessions   session[MAX_SESSIONS] ;
-
-       struct s_sba_sessions   *free_session ; /* points to the first */
-                                               /* free session */
-
-       struct timer_cell       *tail_timer ;   /* points to the last timer cell */
-
-       /*
-        * variables for allocation actions
-        */
-       long    total_payload ;         /* Total Payload */
-       long    total_overhead ;        /* Total Overhead */
-       long    sba_allocatable ;       /* allocatable sync bandwidth */
-
-       /*
-        * RAF message receive parameters
-        */
-       long            msg_path_index ;        /* Path Type */
-       long            msg_sba_pl_req ;        /* Payload Request */
-       long            msg_sba_ov_req ;        /* Overhead Request */
-       long            msg_mib_pl ;            /* Current Payload for this Path */
-       long            msg_mib_ov ;            /* Current Overhead for this Path*/
-       long            msg_category ;          /* Category of the Allocation */
-       u_long          msg_max_t_neg ;         /* longest T_Neg acceptable */
-       u_long          msg_min_seg_siz ;       /* minimum segement size */
-       struct smt_header       *sm ;           /* points to the rec message */
-       struct fddi_addr        *msg_alloc_addr ;       /* Allocation Address */
-
-       /*
-        * SBA variables
-        */
-       u_long  sba_t_neg ;             /* holds the last T_NEG */
-       long    sba_max_alloc ;         /* the parsed value of SBAAvailable */  
-
-       /*
-        * SBA state machine variables
-        */
-       short   sba_next_state ;        /* the next state of the SBA */
-       char    sba_command ;           /* holds the execuded SBA cmd */
-       u_char  sba_available ;         /* parsed value after possible check */
-} ;
-
-#endif /* SBA */
-
-       /*
-        * variables for the End Station Support
-        */
-struct s_ess {
-
-       /*
-        * flags and counters
-        */
-       u_char  sync_bw_available ;     /* is set if sync bw is allocated */
-       u_char  local_sba_active ;      /* set when a local sba is available */
-       char    raf_act_timer_poll ;    /* activate the timer to send allc req */
-       char    timer_count ;           /* counts every timer function call */
-
-       SMbuf   *sba_reply_pend ;       /* local reply for the sba is pending */
-       
-       /*
-        * variables for the ess bandwidth control
-        */
-       long    sync_bw ;               /* holds the allocaed sync bw */
-       u_long  alloc_trans_id ;        /* trans id of the last alloc req */
-} ;
-#endif
diff --git a/drivers/net/skfp/h/sba_def.h b/drivers/net/skfp/h/sba_def.h
deleted file mode 100644 (file)
index 0459a09..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#define PHYS                   0               /* physical addr */
-#define PERM_ADDR              0x80            /* permanet address */
-#define SB_STATIC              0x00000001
-#define MAX_PAYLOAD            1562
-#define PRIMARY_RING           0x00000001
-#ifndef NULL
-#define NULL                   0x00
-#endif
-
-/*********************** SB_Input Variable Values ***********************/
-/*      may be needed when ever the SBA state machine is called        */
-
-#define UNKNOWN_SYNC_SOURCE    0x0001
-#define REQ_ALLOCATION         0x0002
-#define REPORT_RESP            0x0003
-#define CHANGE_RESP            0x0004
-#define TNEG                   0x0005
-#define NIF                    0x0006
-#define SB_STOP                        0x0007
-#define SB_START               0x0008
-#define REPORT_TIMER           0x0009
-#define CHANGE_REQUIRED                0x000A
-
-#define DEFAULT_OV             50
-
-#ifdef SBA
-/**************************** SBA STATES *****************************/
-
-#define SBA_STANDBY            0x00000000
-#define SBA_ACTIVE             0x00000001
-#define SBA_RECOVERY           0x00000002
-#define SBA_REPORT             0x00000003
-#define SBA_CHANGE             0x00000004
-
-/**************************** OTHERS *********************************/
-
-#define FIFTY_PERCENT          50              /* bytes per second */
-#define MAX_SESSIONS           150     
-#define TWO_MINUTES            13079           /* 9.175 ms/tick */
-#define FIFTY_BYTES            50
-#define SBA_DENIED             0x0000000D
-#define I_NEED_ONE             0x00000000
-#define MAX_NODES              50
-/*#define T_REPORT             0x59682F00L*/   /* 120s/80ns in Hex */
-#define        TWO_MIN                 120             /* seconds */
-#define SBA_ST_UNKNOWN         0x00000002
-#define SBA_ST_ACTIVE          0x00000001
-#define S_CLEAR                        0x00000000L
-#define ZERO                   0x00000000
-#define FULL                   0x00000000      /* old: 0xFFFFFFFFF */
-#define S_SET                  0x00000001L
-#define LOW_PRIO               0x02            /* ??????? */
-#define OK                     0x01            /* ??????? */
-#define NOT_OK                 0x00            /* ??????? */
-
-/****************************************/
-/* deallocate_status[ni][si] values    */
-/****************************************/
-#define TX_CHANGE              0X00000001L
-#define PENDING                        0x00000002L
-#define NONE                   0X00000000L
-#endif
diff --git a/drivers/net/skfp/h/skfbi.h b/drivers/net/skfp/h/skfbi.h
deleted file mode 100644 (file)
index c1ba26c..0000000
+++ /dev/null
@@ -1,1133 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _SKFBI_H_
-#define        _SKFBI_H_
-
-/*
- * FDDI-Fx (x := {I(SA), P(CI)})
- *     address calculation & function defines
- */
-
-/*--------------------------------------------------------------------------*/
-#ifdef PCI
-
-/*
- *     (DV)    = only defined for Da Vinci
- *     (ML)    = only defined for Monalisa
- */
-
-/*
- * Configuration Space header
- */
-#define        PCI_VENDOR_ID   0x00    /* 16 bit       Vendor ID */
-#define        PCI_DEVICE_ID   0x02    /* 16 bit       Device ID */
-#define        PCI_COMMAND     0x04    /* 16 bit       Command */
-#define        PCI_STATUS      0x06    /* 16 bit       Status */
-#define        PCI_REV_ID      0x08    /*  8 bit       Revision ID */
-#define        PCI_CLASS_CODE  0x09    /* 24 bit       Class Code */
-#define        PCI_CACHE_LSZ   0x0c    /*  8 bit       Cache Line Size */
-#define        PCI_LAT_TIM     0x0d    /*  8 bit       Latency Timer */
-#define        PCI_HEADER_T    0x0e    /*  8 bit       Header Type */
-#define        PCI_BIST        0x0f    /*  8 bit       Built-in selftest */
-#define        PCI_BASE_1ST    0x10    /* 32 bit       1st Base address */
-#define        PCI_BASE_2ND    0x14    /* 32 bit       2nd Base address */
-/* Byte 18..2b:        Reserved */
-#define        PCI_SUB_VID     0x2c    /* 16 bit       Subsystem Vendor ID */
-#define        PCI_SUB_ID      0x2e    /* 16 bit       Subsystem ID */
-#define        PCI_BASE_ROM    0x30    /* 32 bit       Expansion ROM Base Address */
-/* Byte 34..33:        Reserved */
-#define PCI_CAP_PTR    0x34    /*  8 bit (ML)  Capabilities Ptr */
-/* Byte 35..3b:        Reserved */
-#define        PCI_IRQ_LINE    0x3c    /*  8 bit       Interrupt Line */
-#define        PCI_IRQ_PIN     0x3d    /*  8 bit       Interrupt Pin */
-#define        PCI_MIN_GNT     0x3e    /*  8 bit       Min_Gnt */
-#define        PCI_MAX_LAT     0x3f    /*  8 bit       Max_Lat */
-/* Device Dependent Region */
-#define        PCI_OUR_REG     0x40    /* 32 bit (DV)  Our Register */
-#define        PCI_OUR_REG_1   0x40    /* 32 bit (ML)  Our Register 1 */
-#define        PCI_OUR_REG_2   0x44    /* 32 bit (ML)  Our Register 2 */
-/* Power Management Region */
-#define PCI_PM_CAP_ID  0x48    /*  8 bit (ML)  Power Management Cap. ID */
-#define PCI_PM_NITEM   0x49    /*  8 bit (ML)  Next Item Ptr */
-#define PCI_PM_CAP_REG 0x4a    /* 16 bit (ML)  Power Management Capabilities */
-#define PCI_PM_CTL_STS 0x4c    /* 16 bit (ML)  Power Manag. Control/Status */
-/* Byte 0x4e:  Reserved */
-#define PCI_PM_DAT_REG 0x4f    /*  8 bit (ML)  Power Manag. Data Register */
-/* VPD Region */
-#define        PCI_VPD_CAP_ID  0x50    /*  8 bit (ML)  VPD Cap. ID */
-#define PCI_VPD_NITEM  0x51    /*  8 bit (ML)  Next Item Ptr */
-#define PCI_VPD_ADR_REG        0x52    /* 16 bit (ML)  VPD Address Register */
-#define PCI_VPD_DAT_REG        0x54    /* 32 bit (ML)  VPD Data Register */
-/* Byte 58..ff:        Reserved */
-
-/*
- * I2C Address (PCI Config)
- *
- * Note: The temperature and voltage sensors are relocated on a different
- *      I2C bus.
- */
-#define I2C_ADDR_VPD   0xA0    /* I2C address for the VPD EEPROM */ 
-
-/*
- * Define Bits and Values of the registers
- */
-/*     PCI_VENDOR_ID   16 bit  Vendor ID */
-/*     PCI_DEVICE_ID   16 bit  Device ID */
-/* Values for Vendor ID and Device ID shall be patched into the code */
-/*     PCI_COMMAND     16 bit  Command */
-#define        PCI_FBTEN       0x0200  /* Bit 9:       Fast Back-To-Back enable */
-#define        PCI_SERREN      0x0100  /* Bit 8:       SERR enable */
-#define        PCI_ADSTEP      0x0080  /* Bit 7:       Address Stepping */
-#define        PCI_PERREN      0x0040  /* Bit 6:       Parity Report Response enable */
-#define        PCI_VGA_SNOOP   0x0020  /* Bit 5:       VGA palette snoop */
-#define        PCI_MWIEN       0x0010  /* Bit 4:       Memory write an inv cycl ena */
-#define        PCI_SCYCEN      0x0008  /* Bit 3:       Special Cycle enable */
-#define        PCI_BMEN        0x0004  /* Bit 2:       Bus Master enable */
-#define        PCI_MEMEN       0x0002  /* Bit 1:       Memory Space Access enable */
-#define        PCI_IOEN        0x0001  /* Bit 0:       IO Space Access enable */
-
-/*     PCI_STATUS      16 bit  Status */
-#define        PCI_PERR        0x8000  /* Bit 15:      Parity Error */
-#define        PCI_SERR        0x4000  /* Bit 14:      Signaled SERR */
-#define        PCI_RMABORT     0x2000  /* Bit 13:      Received Master Abort */
-#define        PCI_RTABORT     0x1000  /* Bit 12:      Received Target Abort */
-#define        PCI_STABORT     0x0800  /* Bit 11:      Sent Target Abort */
-#define        PCI_DEVSEL      0x0600  /* Bit 10..9:   DEVSEL Timing */
-#define        PCI_DEV_FAST    (0<<9)  /*              fast */
-#define        PCI_DEV_MEDIUM  (1<<9)  /*              medium */
-#define        PCI_DEV_SLOW    (2<<9)  /*              slow */
-#define        PCI_DATAPERR    0x0100  /* Bit 8:       DATA Parity error detected */
-#define        PCI_FB2BCAP     0x0080  /* Bit 7:       Fast Back-to-Back Capability */
-#define        PCI_UDF         0x0040  /* Bit 6:       User Defined Features */
-#define PCI_66MHZCAP   0x0020  /* Bit 5:       66 MHz PCI bus clock capable */
-#define PCI_NEWCAP     0x0010  /* Bit 4:       New cap. list implemented */
-
-#define PCI_ERRBITS    (PCI_PERR|PCI_SERR|PCI_RMABORT|PCI_STABORT|PCI_DATAPERR)
-
-/*     PCI_REV_ID      8 bit   Revision ID */
-/*     PCI_CLASS_CODE  24 bit  Class Code */
-/*     Byte 2:         Base Class              (02) */
-/*     Byte 1:         SubClass                (02) */
-/*     Byte 0:         Programming Interface   (00) */
-
-/*     PCI_CACHE_LSZ   8 bit   Cache Line Size */
-/*     Possible values: 0,2,4,8,16     */
-
-/*     PCI_LAT_TIM     8 bit   Latency Timer */
-
-/*     PCI_HEADER_T    8 bit   Header Type */
-#define        PCI_HD_MF_DEV   0x80    /* Bit 7:       0= single, 1= multi-func dev */
-#define        PCI_HD_TYPE     0x7f    /* Bit 6..0:    Header Layout 0= normal */
-
-/*     PCI_BIST        8 bit   Built-in selftest */
-#define        PCI_BIST_CAP    0x80    /* Bit 7:       BIST Capable */
-#define        PCI_BIST_ST     0x40    /* Bit 6:       Start BIST */
-#define        PCI_BIST_RET    0x0f    /* Bit 3..0:    Completion Code */
-
-/*     PCI_BASE_1ST    32 bit  1st Base address */
-#define        PCI_MEMSIZE     0x800L       /* use 2 kB Memory Base */
-#define        PCI_MEMBASE_BITS 0xfffff800L /* Bit 31..11:     Memory Base Address */
-#define        PCI_MEMSIZE_BIIS 0x000007f0L /* Bit 10..4:      Memory Size Req. */
-#define        PCI_PREFEN      0x00000008L  /* Bit 3:          Prefetchable */
-#define        PCI_MEM_TYP     0x00000006L  /* Bit 2..1:       Memory Type */
-#define        PCI_MEM32BIT    (0<<1)       /* Base addr anywhere in 32 Bit range */
-#define        PCI_MEM1M       (1<<1)       /* Base addr below 1 MegaByte */
-#define        PCI_MEM64BIT    (2<<1)       /* Base addr anywhere in 64 Bit range */
-#define        PCI_MEMSPACE    0x00000001L  /* Bit 0:  Memory Space Indic. */
-
-/*     PCI_BASE_2ND    32 bit  2nd Base address */
-#define        PCI_IOBASE      0xffffff00L  /* Bit 31..8:  I/O Base address */
-#define        PCI_IOSIZE      0x000000fcL  /* Bit 7..2:   I/O Size Requirements */
-#define        PCI_IOSPACE     0x00000001L  /* Bit 0:      I/O Space Indicator */
-
-/*     PCI_SUB_VID     16 bit  Subsystem Vendor ID */
-/*     PCI_SUB_ID      16 bit  Subsystem ID */
-
-/*     PCI_BASE_ROM    32 bit  Expansion ROM Base Address */
-#define        PCI_ROMBASE     0xfffe0000L  /* Bit 31..17: ROM BASE address (1st) */
-#define        PCI_ROMBASZ     0x0001c000L  /* Bit 16..14: Treat as BASE or SIZE */
-#define        PCI_ROMSIZE     0x00003800L  /* Bit 13..11: ROM Size Requirements */
-#define        PCI_ROMEN       0x00000001L  /* Bit 0:      Address Decode enable */
-
-/*     PCI_CAP_PTR     8 bit   New Capabilities Pointers */
-/*     PCI_IRQ_LINE    8 bit   Interrupt Line */
-/*     PCI_IRQ_PIN     8 bit   Interrupt Pin */
-/*     PCI_MIN_GNT     8 bit   Min_Gnt */
-/*     PCI_MAX_LAT     8 bit   Max_Lat */
-/* Device Dependent Region */
-/*     PCI_OUR_REG     (DV)    32 bit  Our Register */
-/*     PCI_OUR_REG_1   (ML)    32 bit  Our Register 1 */
-                                 /*     Bit 31..29:    reserved */
-#define        PCI_PATCH_DIR   (3L<<27)  /*(DV) Bit 28..27:    Ext Patchs direction */
-#define PCI_PATCH_DIR_0        (1L<<27)  /*(DV) Type of the pins EXT_PATCHS<1..0>   */
-#define PCI_PATCH_DIR_1 (1L<<28)  /*      0 = input                         */
-                                 /*       1 = output                        */
-#define        PCI_EXT_PATCHS  (3L<<25)  /*(DV) Bit 26..25:    Extended Patches     */
-#define PCI_EXT_PATCH_0 (1L<<25)  /*(DV)                                    */
-#define PCI_EXT_PATCH_1 (1L<<26)  /*    CLK for MicroWire (ML)              */
-#define PCI_VIO                (1L<<25)  /*(ML)                                     */
-#define        PCI_EN_BOOT     (1L<<24)  /*     Bit 24:        Enable BOOT via ROM  */
-                                 /*       1 = Don't boot with ROM           */
-                                 /*       0 = Boot with ROM                 */
-#define        PCI_EN_IO       (1L<<23)  /*     Bit 23:        Mapping to IO space  */
-#define        PCI_EN_FPROM    (1L<<22)  /*     Bit 22:        FLASH mapped to mem? */
-                                 /*       1 = Map Flash to Memory           */
-                                 /*       0 = Disable all addr. decoding    */
-#define        PCI_PAGESIZE    (3L<<20)  /*     Bit 21..20:    FLASH Page Size      */
-#define        PCI_PAGE_16     (0L<<20)  /*            16 k pages                   */
-#define        PCI_PAGE_32K    (1L<<20)  /*            32 k pages                   */
-#define        PCI_PAGE_64K    (2L<<20)  /*            64 k pages                   */
-#define        PCI_PAGE_128K   (3L<<20)  /*            128 k pages                  */
-                                 /*     Bit 19: reserved (ML) and (DV)      */
-#define        PCI_PAGEREG     (7L<<16)  /*     Bit 18..16:    Page Register        */
-                                 /*     Bit 15:        reserved             */
-#define        PCI_FORCE_BE    (1L<<14)  /*     Bit 14:        Assert all BEs on MR */
-#define        PCI_DIS_MRL     (1L<<13)  /*     Bit 13:        Disable Mem R Line   */
-#define        PCI_DIS_MRM     (1L<<12)  /*     Bit 12:        Disable Mem R multip */
-#define        PCI_DIS_MWI     (1L<<11)  /*     Bit 11:        Disable Mem W & inv  */
-#define        PCI_DISC_CLS    (1L<<10)  /*     Bit 10:        Disc: cacheLsz bound */
-#define        PCI_BURST_DIS   (1L<<9)   /*     Bit  9:        Burst Disable        */
-#define        PCI_BYTE_SWAP   (1L<<8)   /*(DV) Bit  8:        Byte Swap in DATA    */
-#define        PCI_SKEW_DAS    (0xfL<<4) /*     Bit 7..4:      Skew Ctrl, DAS Ext   */
-#define        PCI_SKEW_BASE   (0xfL<<0) /*     Bit 3..0:      Skew Ctrl, Base      */
-
-/*     PCI_OUR_REG_2   (ML)    32 bit  Our Register 2 (Monalisa only) */
-#define PCI_VPD_WR_TH  (0xffL<<24)     /* Bit 24..31   VPD Write Threshold  */
-#define        PCI_DEV_SEL     (0x7fL<<17)     /* Bit 17..23   EEPROM Device Select */
-#define        PCI_VPD_ROM_SZ  (7L<<14)        /* Bit 14..16   VPD ROM Size         */
-                                       /* Bit 12..13   reserved             */
-#define        PCI_PATCH_DIR2  (0xfL<<8)       /* Bit  8..11   Ext Patchs dir 2..5  */
-#define        PCI_PATCH_DIR_2 (1L<<8)         /* Bit  8       CS for MicroWire     */
-#define        PCI_PATCH_DIR_3 (1L<<9)
-#define        PCI_PATCH_DIR_4 (1L<<10)
-#define        PCI_PATCH_DIR_5 (1L<<11)
-#define PCI_EXT_PATCHS2 (0xfL<<4)      /* Bit  4..7    Extended Patches     */
-#define        PCI_EXT_PATCH_2 (1L<<4)         /* Bit  4       CS for MicroWire     */
-#define        PCI_EXT_PATCH_3 (1L<<5)
-#define        PCI_EXT_PATCH_4 (1L<<6)
-#define        PCI_EXT_PATCH_5 (1L<<7)
-#define        PCI_EN_DUMMY_RD (1L<<3)         /* Bit  3       Enable Dummy Read    */
-#define PCI_REV_DESC   (1L<<2)         /* Bit  2       Reverse Desc. Bytes  */
-#define PCI_USEADDR64  (1L<<1)         /* Bit  1       Use 64 Bit Addresse  */
-#define PCI_USEDATA64  (1L<<0)         /* Bit  0       Use 64 Bit Data bus ext*/
-
-/* Power Management Region */
-/*     PCI_PM_CAP_ID            8 bit (ML)     Power Management Cap. ID */
-/*     PCI_PM_NITEM             8 bit (ML)     Next Item Ptr */
-/*     PCI_PM_CAP_REG          16 bit (ML)     Power Management Capabilities*/
-#define        PCI_PME_SUP     (0x1f<<11)      /* Bit 11..15   PM Manag. Event Support*/
-#define PCI_PM_D2_SUB  (1<<10)         /* Bit 10       D2 Support Bit       */
-#define PCI_PM_D1_SUB  (1<<9)          /* Bit 9        D1 Support Bit       */
-                                       /* Bit 6..8 reserved                 */
-#define PCI_PM_DSI     (1<<5)          /* Bit 5        Device Specific Init.*/
-#define PCI_PM_APS     (1<<4)          /* Bit 4        Auxialiary Power Src */
-#define PCI_PME_CLOCK  (1<<3)          /* Bit 3        PM Event Clock       */
-#define PCI_PM_VER     (7<<0)          /* Bit 0..2     PM PCI Spec. version */
-
-/*     PCI_PM_CTL_STS          16 bit (ML)     Power Manag. Control/Status  */
-#define        PCI_PME_STATUS  (1<<15)         /* Bit 15       PFA doesn't sup. PME#*/
-#define PCI_PM_DAT_SCL (3<<13)         /* Bit 13..14   dat reg Scaling factor */
-#define PCI_PM_DAT_SEL (0xf<<9)        /* Bit  9..12   PM data selector field */
-                                       /* Bit  7.. 2   reserved             */
-#define PCI_PM_STATE   (3<<0)          /* Bit  0.. 1   Power Management State */
-#define PCI_PM_STATE_D0        (0<<0)          /* D0:  Operational (default) */
-#define        PCI_PM_STATE_D1 (1<<0)          /* D1:  not supported */
-#define PCI_PM_STATE_D2        (2<<0)          /* D2:  not supported */
-#define PCI_PM_STATE_D3 (3<<0)         /* D3:  HOT, Power Down and Reset */
-
-/*     PCI_PM_DAT_REG           8 bit (ML)     Power Manag. Data Register */
-/* VPD Region */
-/*     PCI_VPD_CAP_ID           8 bit (ML)     VPD Cap. ID */
-/*     PCI_VPD_NITEM            8 bit (ML)     Next Item Ptr */
-/*     PCI_VPD_ADR_REG         16 bit (ML)     VPD Address Register */
-#define        PCI_VPD_FLAG    (1<<15)         /* Bit 15       starts VPD rd/wd cycle*/
-
-/*     PCI_VPD_DAT_REG         32 bit (ML)     VPD Data Register */
-
-/*
- *     Control Register File:
- *     Bank 0
- */
-#define        B0_RAP          0x0000  /*  8 bit register address port */
-       /* 0x0001 - 0x0003:     reserved */
-#define        B0_CTRL         0x0004  /*  8 bit control register */
-#define        B0_DAS          0x0005  /*  8 Bit control register (DAS) */
-#define        B0_LED          0x0006  /*  8 Bit LED register */
-#define        B0_TST_CTRL     0x0007  /*  8 bit test control register */
-#define        B0_ISRC         0x0008  /* 32 bit Interrupt source register */
-#define        B0_IMSK         0x000c  /* 32 bit Interrupt mask register */
-
-/* 0x0010 - 0x006b:    formac+ (supernet_3) fequently used registers */
-#define B0_CMDREG1     0x0010  /* write command reg 1 instruction */
-#define B0_CMDREG2     0x0014  /* write command reg 2 instruction */
-#define B0_ST1U                0x0010  /* read upper 16-bit of status reg 1 */
-#define B0_ST1L                0x0014  /* read lower 16-bit of status reg 1 */
-#define B0_ST2U                0x0018  /* read upper 16-bit of status reg 2 */
-#define B0_ST2L                0x001c  /* read lower 16-bit of status reg 2 */
-
-#define B0_MARR                0x0020  /* r/w the memory read addr register */
-#define B0_MARW                0x0024  /* r/w the memory write addr register*/
-#define B0_MDRU                0x0028  /* r/w upper 16-bit of mem. data reg */
-#define B0_MDRL                0x002c  /* r/w lower 16-bit of mem. data reg */
-
-#define        B0_MDREG3       0x0030  /* r/w Mode Register 3 */
-#define        B0_ST3U         0x0034  /* read upper 16-bit of status reg 3 */
-#define        B0_ST3L         0x0038  /* read lower 16-bit of status reg 3 */
-#define        B0_IMSK3U       0x003c  /* r/w upper 16-bit of IMSK reg 3 */
-#define        B0_IMSK3L       0x0040  /* r/w lower 16-bit of IMSK reg 3 */
-#define        B0_IVR          0x0044  /* read Interrupt Vector register */
-#define        B0_IMR          0x0048  /* r/w Interrupt mask register */
-/* 0x4c        Hidden */
-
-#define B0_CNTRL_A     0x0050  /* control register A (r/w) */
-#define B0_CNTRL_B     0x0054  /* control register B (r/w) */
-#define B0_INTR_MASK   0x0058  /* interrupt mask (r/w) */
-#define B0_XMIT_VECTOR 0x005c  /* transmit vector register (r/w) */
-
-#define B0_STATUS_A    0x0060  /* status register A (read only) */
-#define B0_STATUS_B    0x0064  /* status register B (read only) */
-#define B0_CNTRL_C     0x0068  /* control register C (r/w) */
-#define        B0_MDREG1       0x006c  /* r/w Mode Register 1 */
-
-#define        B0_R1_CSR       0x0070  /* 32 bit BMU control/status reg (rec q 1) */
-#define        B0_R2_CSR       0x0074  /* 32 bit BMU control/status reg (rec q 2)(DV)*/
-#define        B0_XA_CSR       0x0078  /* 32 bit BMU control/status reg (a xmit q) */
-#define        B0_XS_CSR       0x007c  /* 32 bit BMU control/status reg (s xmit q) */
-
-/*
- *     Bank 1
- *     - completely empty (this is the RAP Block window)
- *     Note: if RAP = 1 this page is reserved
- */
-
-/*
- *     Bank 2
- */
-#define        B2_MAC_0        0x0100  /*  8 bit MAC address Byte 0 */
-#define        B2_MAC_1        0x0101  /*  8 bit MAC address Byte 1 */
-#define        B2_MAC_2        0x0102  /*  8 bit MAC address Byte 2 */
-#define        B2_MAC_3        0x0103  /*  8 bit MAC address Byte 3 */
-#define        B2_MAC_4        0x0104  /*  8 bit MAC address Byte 4 */
-#define        B2_MAC_5        0x0105  /*  8 bit MAC address Byte 5 */
-#define        B2_MAC_6        0x0106  /*  8 bit MAC address Byte 6 (== 0) (DV) */
-#define        B2_MAC_7        0x0107  /*  8 bit MAC address Byte 7 (== 0) (DV) */
-
-#define B2_CONN_TYP    0x0108  /*  8 bit Connector type */
-#define B2_PMD_TYP     0x0109  /*  8 bit PMD type */
-                               /* 0x010a - 0x010b:     reserved */
-       /* Eprom registers are currently of no use */
-#define B2_E_0         0x010c  /*  8 bit EPROM Byte 0 */
-#define B2_E_1         0x010d  /*  8 bit EPROM Byte 1 */
-#define B2_E_2         0x010e  /*  8 bit EPROM Byte 2 */
-#define B2_E_3         0x010f  /*  8 bit EPROM Byte 3 */
-#define B2_FAR         0x0110  /* 32 bit Flash-Prom Address Register/Counter */
-#define B2_FDP         0x0114  /*  8 bit Flash-Prom Data Port */
-                               /* 0x0115 - 0x0117:     reserved */
-#define B2_LD_CRTL     0x0118  /*  8 bit loader control */
-#define B2_LD_TEST     0x0119  /*  8 bit loader test */
-                               /* 0x011a - 0x011f:     reserved */
-#define B2_TI_INI      0x0120  /* 32 bit Timer init value */
-#define B2_TI_VAL      0x0124  /* 32 bit Timer value */
-#define B2_TI_CRTL     0x0128  /*  8 bit Timer control */
-#define B2_TI_TEST     0x0129  /*  8 Bit Timer Test */
-                               /* 0x012a - 0x012f:     reserved */
-#define B2_WDOG_INI    0x0130  /* 32 bit Watchdog init value */
-#define B2_WDOG_VAL    0x0134  /* 32 bit Watchdog value */
-#define B2_WDOG_CRTL   0x0138  /*  8 bit Watchdog control */
-#define B2_WDOG_TEST   0x0139  /*  8 Bit Watchdog Test */
-                               /* 0x013a - 0x013f:     reserved */
-#define B2_RTM_INI     0x0140  /* 32 bit RTM init value */
-#define B2_RTM_VAL     0x0144  /* 32 bit RTM value */
-#define B2_RTM_CRTL    0x0148  /*  8 bit RTM control */
-#define B2_RTM_TEST    0x0149  /*  8 Bit RTM Test */
-
-#define B2_TOK_COUNT   0x014c  /* (ML) 32 bit  Token Counter */
-#define B2_DESC_ADDR_H 0x0150  /* (ML) 32 bit  Desciptor Base Addr Reg High */
-#define B2_CTRL_2      0x0154  /* (ML)  8 bit  Control Register 2 */
-#define B2_IFACE_REG   0x0155  /* (ML)  8 bit  Interface Register */
-                               /* 0x0156:              reserved */
-#define B2_TST_CTRL_2  0x0157  /* (ML)  8 bit  Test Control Register 2 */
-#define B2_I2C_CTRL    0x0158  /* (ML) 32 bit  I2C Control Register */
-#define B2_I2C_DATA    0x015c  /* (ML) 32 bit  I2C Data Register */
-
-#define B2_IRQ_MOD_INI 0x0160  /* (ML) 32 bit  IRQ Moderation Timer Init Reg. */
-#define B2_IRQ_MOD_VAL 0x0164  /* (ML) 32 bit  IRQ Moderation Timer Value */
-#define B2_IRQ_MOD_CTRL        0x0168  /* (ML)  8 bit  IRQ Moderation Timer Control */
-#define B2_IRQ_MOD_TEST        0x0169  /* (ML)  8 bit  IRQ Moderation Timer Test */
-                               /* 0x016a - 0x017f:     reserved */
-
-/*
- *     Bank 3
- */
-/*
- * This is a copy of the Configuration register file (lower half)
- */
-#define B3_CFG_SPC     0x180
-
-/*
- *     Bank 4
- */
-#define B4_R1_D                0x0200  /*      4*32 bit current receive Descriptor  */
-#define B4_R1_DA       0x0210  /*      32 bit current rec desc address      */
-#define B4_R1_AC       0x0214  /*      32 bit current receive Address Count */
-#define B4_R1_BC       0x0218  /*      32 bit current receive Byte Counter  */
-#define B4_R1_CSR      0x021c  /*      32 bit BMU Control/Status Register   */
-#define B4_R1_F                0x0220  /*      32 bit flag register                 */
-#define B4_R1_T1       0x0224  /*      32 bit Test Register 1               */
-#define B4_R1_T1_TR    0x0224  /*      8 bit Test Register 1 TR             */
-#define B4_R1_T1_WR    0x0225  /*      8 bit Test Register 1 WR             */
-#define B4_R1_T1_RD    0x0226  /*      8 bit Test Register 1 RD             */
-#define B4_R1_T1_SV    0x0227  /*      8 bit Test Register 1 SV             */
-#define B4_R1_T2       0x0228  /*      32 bit Test Register 2               */
-#define B4_R1_T3       0x022c  /*      32 bit Test Register 3               */
-#define B4_R1_DA_H     0x0230  /* (ML) 32 bit Curr Rx Desc Address High     */
-#define B4_R1_AC_H     0x0234  /* (ML) 32 bit Curr Addr Counter High dword  */
-                               /* 0x0238 - 0x023f:     reserved          */
-                               /* Receive queue 2 is removed on Monalisa */
-#define B4_R2_D                0x0240  /* 4*32 bit current receive Descriptor  (q2) */
-#define B4_R2_DA       0x0250  /* 32 bit current rec desc address      (q2) */
-#define B4_R2_AC       0x0254  /* 32 bit current receive Address Count (q2) */
-#define B4_R2_BC       0x0258  /* 32 bit current receive Byte Counter  (q2) */
-#define B4_R2_CSR      0x025c  /* 32 bit BMU Control/Status Register   (q2) */
-#define B4_R2_F                0x0260  /* 32 bit flag register                 (q2) */
-#define B4_R2_T1       0x0264  /* 32 bit Test Register 1               (q2) */
-#define B4_R2_T1_TR    0x0264  /* 8 bit Test Register 1 TR             (q2) */
-#define B4_R2_T1_WR    0x0265  /* 8 bit Test Register 1 WR             (q2) */
-#define B4_R2_T1_RD    0x0266  /* 8 bit Test Register 1 RD             (q2) */
-#define B4_R2_T1_SV    0x0267  /* 8 bit Test Register 1 SV             (q2) */
-#define B4_R2_T2       0x0268  /* 32 bit Test Register 2               (q2) */
-#define B4_R2_T3       0x026c  /* 32 bit Test Register 3               (q2) */
-                               /* 0x0270 - 0x027c:     reserved */
-
-/*
- *     Bank 5
- */
-#define B5_XA_D                0x0280  /* 4*32 bit current transmit Descriptor (xa) */
-#define B5_XA_DA       0x0290  /* 32 bit current tx desc address       (xa) */
-#define B5_XA_AC       0x0294  /* 32 bit current tx Address Count      (xa) */
-#define B5_XA_BC       0x0298  /* 32 bit current tx Byte Counter       (xa) */
-#define B5_XA_CSR      0x029c  /* 32 bit BMU Control/Status Register   (xa) */
-#define B5_XA_F                0x02a0  /* 32 bit flag register                 (xa) */
-#define B5_XA_T1       0x02a4  /* 32 bit Test Register 1               (xa) */
-#define B5_XA_T1_TR    0x02a4  /* 8 bit Test Register 1 TR             (xa) */
-#define B5_XA_T1_WR    0x02a5  /* 8 bit Test Register 1 WR             (xa) */
-#define B5_XA_T1_RD    0x02a6  /* 8 bit Test Register 1 RD             (xa) */
-#define B5_XA_T1_SV    0x02a7  /* 8 bit Test Register 1 SV             (xa) */
-#define B5_XA_T2       0x02a8  /* 32 bit Test Register 2               (xa) */
-#define B5_XA_T3       0x02ac  /* 32 bit Test Register 3               (xa) */
-#define B5_XA_DA_H     0x02b0  /* (ML) 32 bit Curr Tx Desc Address High     */
-#define B5_XA_AC_H     0x02b4  /* (ML) 32 bit Curr Addr Counter High dword  */
-                               /* 0x02b8 - 0x02bc:     reserved */
-#define B5_XS_D                0x02c0  /* 4*32 bit current transmit Descriptor (xs) */
-#define B5_XS_DA       0x02d0  /* 32 bit current tx desc address       (xs) */
-#define B5_XS_AC       0x02d4  /* 32 bit current transmit Address Count(xs) */
-#define B5_XS_BC       0x02d8  /* 32 bit current transmit Byte Counter (xs) */
-#define B5_XS_CSR      0x02dc  /* 32 bit BMU Control/Status Register   (xs) */
-#define B5_XS_F                0x02e0  /* 32 bit flag register                 (xs) */
-#define B5_XS_T1       0x02e4  /* 32 bit Test Register 1               (xs) */
-#define B5_XS_T1_TR    0x02e4  /* 8 bit Test Register 1 TR             (xs) */
-#define B5_XS_T1_WR    0x02e5  /* 8 bit Test Register 1 WR             (xs) */
-#define B5_XS_T1_RD    0x02e6  /* 8 bit Test Register 1 RD             (xs) */
-#define B5_XS_T1_SV    0x02e7  /* 8 bit Test Register 1 SV             (xs) */
-#define B5_XS_T2       0x02e8  /* 32 bit Test Register 2               (xs) */
-#define B5_XS_T3       0x02ec  /* 32 bit Test Register 3               (xs) */
-#define B5_XS_DA_H     0x02f0  /* (ML) 32 bit Curr Tx Desc Address High     */
-#define B5_XS_AC_H     0x02f4  /* (ML) 32 bit Curr Addr Counter High dword  */
-                               /* 0x02f8 - 0x02fc:     reserved */
-
-/*
- *     Bank 6
- */
-/* External PLC-S registers (SN2 compatibility for DV) */
-/* External registers (ML) */
-#define B6_EXT_REG     0x300
-
-/*
- *     Bank 7
- */
-/* DAS PLC-S Registers */
-
-/*
- *     Bank 8 - 15
- */
-/* IFCP registers */
-
-/*---------------------------------------------------------------------------*/
-/* Definitions of the Bits in the registers */
-
-/*     B0_RAP          16 bit register address port */
-#define        RAP_RAP         0x0f    /* Bit 3..0:    0 = block0, .., f = block15 */
-
-/*     B0_CTRL         8 bit control register */
-#define CTRL_FDDI_CLR  (1<<7)  /* Bit 7: (ML)  Clear FDDI Reset */
-#define CTRL_FDDI_SET  (1<<6)  /* Bit 6: (ML)  Set FDDI Reset */
-#define        CTRL_HPI_CLR    (1<<5)  /* Bit 5:       Clear HPI SM reset */
-#define        CTRL_HPI_SET    (1<<4)  /* Bit 4:       Set HPI SM reset */
-#define        CTRL_MRST_CLR   (1<<3)  /* Bit 3:       Clear Master reset */
-#define        CTRL_MRST_SET   (1<<2)  /* Bit 2:       Set Master reset */
-#define        CTRL_RST_CLR    (1<<1)  /* Bit 1:       Clear Software reset */
-#define        CTRL_RST_SET    (1<<0)  /* Bit 0:       Set Software reset */
-
-/*     B0_DAS          8 Bit control register (DAS) */
-#define BUS_CLOCK      (1<<7)  /* Bit 7: (ML)  Bus Clock 0/1 = 33/66MHz */
-#define BUS_SLOT_SZ    (1<<6)  /* Bit 6: (ML)  Slot Size 0/1 = 32/64 bit slot*/
-                               /* Bit 5..4:    reserved */
-#define        DAS_AVAIL       (1<<3)  /* Bit 3:       1 = DAS, 0 = SAS */
-#define DAS_BYP_ST     (1<<2)  /* Bit 2:       1 = avail,SAS, 0 = not avail */
-#define DAS_BYP_INS    (1<<1)  /* Bit 1:       1 = insert Bypass */
-#define DAS_BYP_RMV    (1<<0)  /* Bit 0:       1 = remove Bypass */
-
-/*     B0_LED          8 Bit LED register */
-                               /* Bit 7..6:    reserved */
-#define LED_2_ON       (1<<5)  /* Bit 5:       1 = switch LED_2 on (left,gn)*/
-#define LED_2_OFF      (1<<4)  /* Bit 4:       1 = switch LED_2 off */
-#define LED_1_ON       (1<<3)  /* Bit 3:       1 = switch LED_1 on (mid,yel)*/
-#define LED_1_OFF      (1<<2)  /* Bit 2:       1 = switch LED_1 off */
-#define LED_0_ON       (1<<1)  /* Bit 1:       1 = switch LED_0 on (rght,gn)*/
-#define LED_0_OFF      (1<<0)  /* Bit 0:       1 = switch LED_0 off */
-/* This hardware defines are very ugly therefore we define some others */
-
-#define LED_GA_ON      LED_2_ON        /* S port = A port */
-#define LED_GA_OFF     LED_2_OFF       /* S port = A port */
-#define LED_MY_ON      LED_1_ON
-#define LED_MY_OFF     LED_1_OFF
-#define LED_GB_ON      LED_0_ON
-#define LED_GB_OFF     LED_0_OFF
-
-/*     B0_TST_CTRL     8 bit test control register */
-#define        TST_FRC_DPERR_MR        (1<<7)  /* Bit 7:  force DATAPERR on MST RE. */
-#define        TST_FRC_DPERR_MW        (1<<6)  /* Bit 6:  force DATAPERR on MST WR. */
-#define        TST_FRC_DPERR_TR        (1<<5)  /* Bit 5:  force DATAPERR on TRG RE. */
-#define        TST_FRC_DPERR_TW        (1<<4)  /* Bit 4:  force DATAPERR on TRG WR. */
-#define        TST_FRC_APERR_M         (1<<3)  /* Bit 3:  force ADDRPERR on MST     */
-#define        TST_FRC_APERR_T         (1<<2)  /* Bit 2:  force ADDRPERR on TRG     */
-#define        TST_CFG_WRITE_ON        (1<<1)  /* Bit 1:  ena configuration reg. WR */
-#define        TST_CFG_WRITE_OFF       (1<<0)  /* Bit 0:  dis configuration reg. WR */
-
-/*     B0_ISRC         32 bit Interrupt source register */
-                                       /* Bit 31..28:  reserved             */
-#define IS_I2C_READY   (1L<<27)        /* Bit 27: (ML) IRQ on end of I2C tx */
-#define IS_IRQ_SW      (1L<<26)        /* Bit 26: (ML) SW forced IRQ        */
-#define IS_EXT_REG     (1L<<25)        /* Bit 25: (ML) IRQ from external reg*/
-#define        IS_IRQ_STAT     (1L<<24)        /* Bit 24:      IRQ status exception */
-                                       /*   PERR, RMABORT, RTABORT DATAPERR */
-#define        IS_IRQ_MST_ERR  (1L<<23)        /* Bit 23:      IRQ master error     */
-                                       /*   RMABORT, RTABORT, DATAPERR      */
-#define        IS_TIMINT       (1L<<22)        /* Bit 22:      IRQ_TIMER       */
-#define        IS_TOKEN        (1L<<21)        /* Bit 21:      IRQ_RTM         */
-/*
- * Note: The DAS is our First Port (!=PA)
- */
-#define        IS_PLINT1       (1L<<20)        /* Bit 20:      IRQ_PHY_DAS     */
-#define        IS_PLINT2       (1L<<19)        /* Bit 19:      IRQ_IFCP_4      */
-#define        IS_MINTR3       (1L<<18)        /* Bit 18:      IRQ_IFCP_3/IRQ_PHY */
-#define        IS_MINTR2       (1L<<17)        /* Bit 17:      IRQ_IFCP_2/IRQ_MAC_2 */
-#define        IS_MINTR1       (1L<<16)        /* Bit 16:      IRQ_IFCP_1/IRQ_MAC_1 */
-/* Receive Queue 1 */
-#define        IS_R1_P         (1L<<15)        /* Bit 15:      Parity Error (q1) */
-#define        IS_R1_B         (1L<<14)        /* Bit 14:      End of Buffer (q1) */
-#define        IS_R1_F         (1L<<13)        /* Bit 13:      End of Frame (q1) */
-#define        IS_R1_C         (1L<<12)        /* Bit 12:      Encoding Error (q1) */
-/* Receive Queue 2 */
-#define        IS_R2_P         (1L<<11)        /* Bit 11: (DV) Parity Error (q2) */
-#define        IS_R2_B         (1L<<10)        /* Bit 10: (DV) End of Buffer (q2) */
-#define        IS_R2_F         (1L<<9)         /* Bit  9: (DV) End of Frame (q2) */
-#define        IS_R2_C         (1L<<8)         /* Bit  8: (DV) Encoding Error (q2) */
-/* Asynchronous Transmit queue */
-                                       /* Bit  7:      reserved */
-#define        IS_XA_B         (1L<<6)         /* Bit  6:      End of Buffer (xa) */
-#define        IS_XA_F         (1L<<5)         /* Bit  5:      End of Frame (xa) */
-#define        IS_XA_C         (1L<<4)         /* Bit  4:      Encoding Error (xa) */
-/* Synchronous Transmit queue */
-                                       /* Bit  3:      reserved */
-#define        IS_XS_B         (1L<<2)         /* Bit  2:      End of Buffer (xs) */
-#define        IS_XS_F         (1L<<1)         /* Bit  1:      End of Frame (xs) */
-#define        IS_XS_C         (1L<<0)         /* Bit  0:      Encoding Error (xs) */
-
-/*
- * Define all valid interrupt source Bits from GET_ISR ()
- */
-#define        ALL_IRSR        0x01ffff77L     /* (DV) */
-#define        ALL_IRSR_ML     0x0ffff077L     /* (ML) */
-
-
-/*     B0_IMSK         32 bit Interrupt mask register */
-/*
- * The Bit definnition of this register are the same as of the interrupt
- * source register. These definition are directly derived from the Hardware
- * spec.
- */
-                                       /* Bit 31..28:  reserved             */
-#define IRQ_I2C_READY  (1L<<27)        /* Bit 27: (ML) IRQ on end of I2C tx */
-#define IRQ_SW         (1L<<26)        /* Bit 26: (ML) SW forced IRQ        */
-#define IRQ_EXT_REG    (1L<<25)        /* Bit 25: (ML) IRQ from external reg*/
-#define        IRQ_STAT        (1L<<24)        /* Bit 24:      IRQ status exception */
-                                       /*   PERR, RMABORT, RTABORT DATAPERR */
-#define        IRQ_MST_ERR     (1L<<23)        /* Bit 23:      IRQ master error     */
-                                       /*   RMABORT, RTABORT, DATAPERR      */
-#define        IRQ_TIMER       (1L<<22)        /* Bit 22:      IRQ_TIMER       */
-#define        IRQ_RTM         (1L<<21)        /* Bit 21:      IRQ_RTM         */
-#define        IRQ_DAS         (1L<<20)        /* Bit 20:      IRQ_PHY_DAS     */
-#define        IRQ_IFCP_4      (1L<<19)        /* Bit 19:      IRQ_IFCP_4      */
-#define        IRQ_IFCP_3      (1L<<18)        /* Bit 18:      IRQ_IFCP_3/IRQ_PHY */
-#define        IRQ_IFCP_2      (1L<<17)        /* Bit 17:      IRQ_IFCP_2/IRQ_MAC_2 */
-#define        IRQ_IFCP_1      (1L<<16)        /* Bit 16:      IRQ_IFCP_1/IRQ_MAC_1 */
-/* Receive Queue 1 */
-#define        IRQ_R1_P        (1L<<15)        /* Bit 15:      Parity Error (q1) */
-#define        IRQ_R1_B        (1L<<14)        /* Bit 14:      End of Buffer (q1) */
-#define        IRQ_R1_F        (1L<<13)        /* Bit 13:      End of Frame (q1) */
-#define        IRQ_R1_C        (1L<<12)        /* Bit 12:      Encoding Error (q1) */
-/* Receive Queue 2 */
-#define        IRQ_R2_P        (1L<<11)        /* Bit 11: (DV) Parity Error (q2) */
-#define        IRQ_R2_B        (1L<<10)        /* Bit 10: (DV) End of Buffer (q2) */
-#define        IRQ_R2_F        (1L<<9)         /* Bit  9: (DV) End of Frame (q2) */
-#define        IRQ_R2_C        (1L<<8)         /* Bit  8: (DV) Encoding Error (q2) */
-/* Asynchronous Transmit queue */
-                                       /* Bit  7:      reserved */
-#define        IRQ_XA_B        (1L<<6)         /* Bit  6:      End of Buffer (xa) */
-#define        IRQ_XA_F        (1L<<5)         /* Bit  5:      End of Frame (xa) */
-#define        IRQ_XA_C        (1L<<4)         /* Bit  4:      Encoding Error (xa) */
-/* Synchronous Transmit queue */
-                                       /* Bit  3:      reserved */
-#define        IRQ_XS_B        (1L<<2)         /* Bit  2:      End of Buffer (xs) */
-#define        IRQ_XS_F        (1L<<1)         /* Bit  1:      End of Frame (xs) */
-#define        IRQ_XS_C        (1L<<0)         /* Bit  0:      Encoding Error (xs) */
-
-/* 0x0010 - 0x006b:    formac+ (supernet_3) fequently used registers */
-/*     B0_R1_CSR       32 bit BMU control/status reg (rec q 1 ) */
-/*     B0_R2_CSR       32 bit BMU control/status reg (rec q 2 ) */
-/*     B0_XA_CSR       32 bit BMU control/status reg (a xmit q ) */
-/*     B0_XS_CSR       32 bit BMU control/status reg (s xmit q ) */
-/* The registers are the same as B4_R1_CSR, B4_R2_CSR, B5_Xa_CSR, B5_XS_CSR */
-
-/*     B2_MAC_0        8 bit MAC address Byte 0 */
-/*     B2_MAC_1        8 bit MAC address Byte 1 */
-/*     B2_MAC_2        8 bit MAC address Byte 2 */
-/*     B2_MAC_3        8 bit MAC address Byte 3 */
-/*     B2_MAC_4        8 bit MAC address Byte 4 */
-/*     B2_MAC_5        8 bit MAC address Byte 5 */
-/*     B2_MAC_6        8 bit MAC address Byte 6 (== 0) (DV) */
-/*     B2_MAC_7        8 bit MAC address Byte 7 (== 0) (DV) */
-
-/*     B2_CONN_TYP     8 bit Connector type */
-/*     B2_PMD_TYP      8 bit PMD type */
-/*     Values of connector and PMD type comply to SysKonnect internal std */
-
-/*     The EPROM register are currently of no use */
-/*     B2_E_0          8 bit EPROM Byte 0 */
-/*     B2_E_1          8 bit EPROM Byte 1 */
-/*     B2_E_2          8 bit EPROM Byte 2 */
-/*     B2_E_3          8 bit EPROM Byte 3 */
-
-/*     B2_FAR          32 bit Flash-Prom Address Register/Counter */
-#define        FAR_ADDR        0x1ffffL        /* Bit 16..0:   FPROM Address mask */
-
-/*     B2_FDP          8 bit Flash-Prom Data Port */
-
-/*     B2_LD_CRTL      8 bit loader control */
-/*     Bits are currently reserved */
-
-/*     B2_LD_TEST      8 bit loader test */
-#define        LD_T_ON         (1<<3)  /* Bit 3:    Loader Testmode on */
-#define        LD_T_OFF        (1<<2)  /* Bit 2:    Loader Testmode off */
-#define        LD_T_STEP       (1<<1)  /* Bit 1:    Decrement FPROM addr. Counter */
-#define        LD_START        (1<<0)  /* Bit 0:    Start loading FPROM */
-
-/*     B2_TI_INI       32 bit Timer init value */
-/*     B2_TI_VAL       32 bit Timer value */
-/*     B2_TI_CRTL      8 bit Timer control */
-/*     B2_TI_TEST      8 Bit Timer Test */
-/*     B2_WDOG_INI     32 bit Watchdog init value */
-/*     B2_WDOG_VAL     32 bit Watchdog value */
-/*     B2_WDOG_CRTL    8 bit Watchdog control */
-/*     B2_WDOG_TEST    8 Bit Watchdog Test */
-/*     B2_RTM_INI      32 bit RTM init value */
-/*     B2_RTM_VAL      32 bit RTM value */
-/*     B2_RTM_CRTL     8 bit RTM control */
-/*     B2_RTM_TEST     8 Bit RTM Test */
-/*     B2_<TIM>_CRTL   8 bit <TIM> control */
-/*     B2_IRQ_MOD_INI  32 bit IRQ Moderation Timer Init Reg.   (ML) */
-/*     B2_IRQ_MOD_VAL  32 bit IRQ Moderation Timer Value       (ML) */
-/*     B2_IRQ_MOD_CTRL 8 bit IRQ Moderation Timer Control      (ML) */
-/*     B2_IRQ_MOD_TEST 8 bit IRQ Moderation Timer Test         (ML) */
-#define GET_TOK_CT     (1<<4)  /* Bit 4: Get the Token Counter (RTM) */
-#define TIM_RES_TOK    (1<<3)  /* Bit 3: RTM Status: 1 == restricted */
-#define TIM_ALARM      (1<<3)  /* Bit 3: Timer Alarm (WDOG) */
-#define TIM_START      (1<<2)  /* Bit 2: Start Timer (TI,WDOG,RTM,IRQ_MOD)*/
-#define TIM_STOP       (1<<1)  /* Bit 1: Stop Timer (TI,WDOG,RTM,IRQ_MOD) */
-#define TIM_CL_IRQ     (1<<0)  /* Bit 0: Clear Timer IRQ (TI,WDOG,RTM) */
-/*     B2_<TIM>_TEST   8 Bit <TIM> Test */
-#define        TIM_T_ON        (1<<2)  /* Bit 2: Test mode on (TI,WDOG,RTM,IRQ_MOD) */
-#define        TIM_T_OFF       (1<<1)  /* Bit 1: Test mode off (TI,WDOG,RTM,IRQ_MOD) */
-#define        TIM_T_STEP      (1<<0)  /* Bit 0: Test step (TI,WDOG,RTM,IRQ_MOD) */
-
-/*     B2_TOK_COUNT    0x014c  (ML)    32 bit  Token Counter */
-/*     B2_DESC_ADDR_H  0x0150  (ML)    32 bit  Desciptor Base Addr Reg High */
-/*     B2_CTRL_2       0x0154  (ML)     8 bit  Control Register 2 */
-                               /* Bit 7..5:    reserved                */
-#define CTRL_CL_I2C_IRQ (1<<4) /* Bit 4:       Clear I2C IRQ           */
-#define CTRL_ST_SW_IRQ (1<<3)  /* Bit 3:       Set IRQ SW Request      */
-#define CTRL_CL_SW_IRQ (1<<2)  /* Bit 2:       Clear IRQ SW Request    */
-#define CTRL_STOP_DONE (1<<1)  /* Bit 1:       Stop Master is finished */
-#define        CTRL_STOP_MAST  (1<<0)  /* Bit 0:       Command Bit to stop the master*/
-
-/*     B2_IFACE_REG    0x0155  (ML)     8 bit  Interface Register */
-                               /* Bit 7..3:    reserved                */
-#define        IF_I2C_DATA_DIR (1<<2)  /* Bit 2:       direction of IF_I2C_DATA*/
-#define IF_I2C_DATA    (1<<1)  /* Bit 1:       I2C Data Port           */
-#define        IF_I2C_CLK      (1<<0)  /* Bit 0:       I2C Clock Port          */
-
-                               /* 0x0156:              reserved */
-/*     B2_TST_CTRL_2   0x0157  (ML)     8 bit  Test Control Register 2 */
-                                       /* Bit 7..4:    reserved */
-                                       /* force the following error on */
-                                       /* the next master read/write   */
-#define TST_FRC_DPERR_MR64     (1<<3)  /* Bit 3:       DataPERR RD 64  */
-#define TST_FRC_DPERR_MW64     (1<<2)  /* Bit 2:       DataPERR WR 64  */
-#define TST_FRC_APERR_1M64     (1<<1)  /* Bit 1:       AddrPERR on 1. phase */
-#define TST_FRC_APERR_2M64     (1<<0)  /* Bit 0:       AddrPERR on 2. phase */
-
-/*     B2_I2C_CTRL     0x0158  (ML)    32 bit  I2C Control Register           */
-#define        I2C_FLAG        (1L<<31)        /* Bit 31:      Start read/write if WR */
-#define I2C_ADDR       (0x7fffL<<16)   /* Bit 30..16:  Addr to be read/written*/
-#define        I2C_DEV_SEL     (0x7fL<<9)      /* Bit  9..15:  I2C Device Select      */
-                                       /* Bit  5.. 8:  reserved               */
-#define I2C_BURST_LEN  (1L<<4)         /* Bit  4       Burst Len, 1/4 bytes   */
-#define I2C_DEV_SIZE   (7L<<1)         /* Bit  1.. 3:  I2C Device Size        */
-#define I2C_025K_DEV   (0L<<1)         /*              0: 256 Bytes or smaller*/
-#define I2C_05K_DEV    (1L<<1)         /*              1: 512  Bytes          */
-#define        I2C_1K_DEV      (2L<<1)         /*              2: 1024 Bytes          */
-#define I2C_2K_DEV     (3L<<1)         /*              3: 2048 Bytes          */
-#define        I2C_4K_DEV      (4L<<1)         /*              4: 4096 Bytes          */
-#define        I2C_8K_DEV      (5L<<1)         /*              5: 8192 Bytes          */
-#define        I2C_16K_DEV     (6L<<1)         /*              6: 16384 Bytes         */
-#define        I2C_32K_DEV     (7L<<1)         /*              7: 32768 Bytes         */
-#define I2C_STOP_BIT   (1<<0)          /* Bit  0:      Interrupt I2C transfer */
-
-/*
- * I2C Addresses
- *
- * The temperature sensor and the voltage sensor are on the same I2C bus.
- * Note: The voltage sensor (Micorwire) will be selected by PCI_EXT_PATCH_1
- *      in PCI_OUR_REG 1.
- */
-#define        I2C_ADDR_TEMP   0x90    /* I2C Address Temperature Sensor */
-
-/*     B2_I2C_DATA     0x015c  (ML)    32 bit  I2C Data Register */
-
-/*     B4_R1_D         4*32 bit current receive Descriptor     (q1) */
-/*     B4_R1_DA        32 bit current rec desc address         (q1) */
-/*     B4_R1_AC        32 bit current receive Address Count    (q1) */
-/*     B4_R1_BC        32 bit current receive Byte Counter     (q1) */
-/*     B4_R1_CSR       32 bit BMU Control/Status Register      (q1) */
-/*     B4_R1_F         32 bit flag register                    (q1) */
-/*     B4_R1_T1        32 bit Test Register 1                  (q1) */
-/*     B4_R1_T2        32 bit Test Register 2                  (q1) */
-/*     B4_R1_T3        32 bit Test Register 3                  (q1) */
-/*     B4_R2_D         4*32 bit current receive Descriptor     (q2) */
-/*     B4_R2_DA        32 bit current rec desc address         (q2) */
-/*     B4_R2_AC        32 bit current receive Address Count    (q2) */
-/*     B4_R2_BC        32 bit current receive Byte Counter     (q2) */
-/*     B4_R2_CSR       32 bit BMU Control/Status Register      (q2) */
-/*     B4_R2_F         32 bit flag register                    (q2) */
-/*     B4_R2_T1        32 bit Test Register 1                  (q2) */
-/*     B4_R2_T2        32 bit Test Register 2                  (q2) */
-/*     B4_R2_T3        32 bit Test Register 3                  (q2) */
-/*     B5_XA_D         4*32 bit current receive Descriptor     (xa) */
-/*     B5_XA_DA        32 bit current rec desc address         (xa) */
-/*     B5_XA_AC        32 bit current receive Address Count    (xa) */
-/*     B5_XA_BC        32 bit current receive Byte Counter     (xa) */
-/*     B5_XA_CSR       32 bit BMU Control/Status Register      (xa) */
-/*     B5_XA_F         32 bit flag register                    (xa) */
-/*     B5_XA_T1        32 bit Test Register 1                  (xa) */
-/*     B5_XA_T2        32 bit Test Register 2                  (xa) */
-/*     B5_XA_T3        32 bit Test Register 3                  (xa) */
-/*     B5_XS_D         4*32 bit current receive Descriptor     (xs) */
-/*     B5_XS_DA        32 bit current rec desc address         (xs) */
-/*     B5_XS_AC        32 bit current receive Address Count    (xs) */
-/*     B5_XS_BC        32 bit current receive Byte Counter     (xs) */
-/*     B5_XS_CSR       32 bit BMU Control/Status Register      (xs) */
-/*     B5_XS_F         32 bit flag register                    (xs) */
-/*     B5_XS_T1        32 bit Test Register 1                  (xs) */
-/*     B5_XS_T2        32 bit Test Register 2                  (xs) */
-/*     B5_XS_T3        32 bit Test Register 3                  (xs) */
-/*     B5_<xx>_CSR     32 bit BMU Control/Status Register      (xx) */
-#define        CSR_DESC_CLEAR  (1L<<21)    /* Bit 21:  Clear Reset for Descr */
-#define        CSR_DESC_SET    (1L<<20)    /* Bit 20:  Set Reset for Descr */
-#define        CSR_FIFO_CLEAR  (1L<<19)    /* Bit 19:  Clear Reset for FIFO */
-#define        CSR_FIFO_SET    (1L<<18)    /* Bit 18:  Set Reset for FIFO */
-#define        CSR_HPI_RUN     (1L<<17)    /* Bit 17:  Release HPI SM */
-#define        CSR_HPI_RST     (1L<<16)    /* Bit 16:  Reset HPI SM to Idle */
-#define        CSR_SV_RUN      (1L<<15)    /* Bit 15:  Release Supervisor SM */
-#define        CSR_SV_RST      (1L<<14)    /* Bit 14:  Reset Supervisor SM */
-#define        CSR_DREAD_RUN   (1L<<13)    /* Bit 13:  Release Descr Read SM */
-#define        CSR_DREAD_RST   (1L<<12)    /* Bit 12:  Reset Descr Read SM */
-#define        CSR_DWRITE_RUN  (1L<<11)    /* Bit 11:  Rel. Descr Write SM */
-#define        CSR_DWRITE_RST  (1L<<10)    /* Bit 10:  Reset Descr Write SM */
-#define        CSR_TRANS_RUN   (1L<<9)     /* Bit 9:   Release Transfer SM */
-#define        CSR_TRANS_RST   (1L<<8)     /* Bit 8:   Reset Transfer SM */
-                                   /* Bit 7..5: reserved */
-#define        CSR_START       (1L<<4)     /* Bit 4:   Start Rec/Xmit Queue */
-#define        CSR_IRQ_CL_P    (1L<<3)     /* Bit 3:   Clear Parity IRQ, Rcv */
-#define        CSR_IRQ_CL_B    (1L<<2)     /* Bit 2:   Clear EOB IRQ */
-#define        CSR_IRQ_CL_F    (1L<<1)     /* Bit 1:   Clear EOF IRQ */
-#define        CSR_IRQ_CL_C    (1L<<0)     /* Bit 0:   Clear ERR IRQ */
-
-#define CSR_SET_RESET  (CSR_DESC_SET|CSR_FIFO_SET|CSR_HPI_RST|CSR_SV_RST|\
-                       CSR_DREAD_RST|CSR_DWRITE_RST|CSR_TRANS_RST)
-#define CSR_CLR_RESET  (CSR_DESC_CLEAR|CSR_FIFO_CLEAR|CSR_HPI_RUN|CSR_SV_RUN|\
-                       CSR_DREAD_RUN|CSR_DWRITE_RUN|CSR_TRANS_RUN)
-
-
-/*     B5_<xx>_F       32 bit flag register             (xx) */
-                                       /* Bit 28..31:  reserved              */
-#define F_ALM_FULL     (1L<<27)        /* Bit 27: (ML) FIFO almost full      */
-#define F_FIFO_EOF     (1L<<26)        /* Bit 26: (ML) Fag bit in FIFO       */
-#define F_WM_REACHED   (1L<<25)        /* Bit 25: (ML) Watermark reached     */
-#define F_UP_DW_USED   (1L<<24)        /* Bit 24: (ML) Upper Dword used (bug)*/
-                                       /* Bit 23:      reserved              */
-#define F_FIFO_LEVEL   (0x1fL<<16)     /* Bit 16..22:(ML) # of Qwords in FIFO*/
-                                       /* Bit  8..15:  reserved              */
-#define F_ML_WATER_M   0x0000ffL       /* Bit  0.. 7:(ML) Watermark          */
-#define        FLAG_WATER      0x00001fL       /* Bit 4..0:(DV) Level of req data tr.*/
-
-/*     B5_<xx>_T1      32 bit Test Register 1           (xx) */
-/*             Holds four State Machine control Bytes */
-#define        SM_CRTL_SV      (0xffL<<24) /* Bit 31..24:  Control Supervisor SM */
-#define        SM_CRTL_RD      (0xffL<<16) /* Bit 23..16:  Control Read Desc SM */
-#define        SM_CRTL_WR      (0xffL<<8)  /* Bit 15..8:   Control Write Desc SM */
-#define        SM_CRTL_TR      (0xffL<<0)  /* Bit 7..0:    Control Transfer SM */
-
-/*     B4_<xx>_T1_TR   8 bit Test Register 1 TR                (xx) */
-/*     B4_<xx>_T1_WR   8 bit Test Register 1 WR                (xx) */
-/*     B4_<xx>_T1_RD   8 bit Test Register 1 RD                (xx) */
-/*     B4_<xx>_T1_SV   8 bit Test Register 1 SV                (xx) */
-/* The control status byte of each machine looks like ... */
-#define        SM_STATE        0xf0    /* Bit 7..4:    State which shall be loaded */
-#define        SM_LOAD         0x08    /* Bit 3:       Load the SM with SM_STATE */
-#define        SM_TEST_ON      0x04    /* Bit 2:       Switch on SM Test Mode */
-#define        SM_TEST_OFF     0x02    /* Bit 1:       Go off the Test Mode */
-#define        SM_STEP         0x01    /* Bit 0:       Step the State Machine */
-
-/* The coding of the states */
-#define        SM_SV_IDLE      0x0     /* Supervisor   Idle            Tr/Re        */
-#define        SM_SV_RES_START 0x1     /* Supervisor   Res_Start       Tr/Re        */
-#define        SM_SV_GET_DESC  0x3     /* Supervisor   Get_Desc        Tr/Re        */
-#define        SM_SV_CHECK     0x2     /* Supervisor   Check           Tr/Re        */
-#define        SM_SV_MOV_DATA  0x6     /* Supervisor   Move_Data       Tr/Re        */
-#define        SM_SV_PUT_DESC  0x7     /* Supervisor   Put_Desc        Tr/Re        */
-#define        SM_SV_SET_IRQ   0x5     /* Supervisor   Set_Irq         Tr/Re        */
-
-#define        SM_RD_IDLE      0x0     /* Read Desc.   Idle            Tr/Re        */
-#define        SM_RD_LOAD      0x1     /* Read Desc.   Load            Tr/Re        */
-#define        SM_RD_WAIT_TC   0x3     /* Read Desc.   Wait_TC         Tr/Re        */
-#define        SM_RD_RST_EOF   0x6     /* Read Desc.   Reset_EOF          Re        */
-#define        SM_RD_WDONE_R   0x2     /* Read Desc.   Wait_Done          Re        */
-#define        SM_RD_WDONE_T   0x4     /* Read Desc.   Wait_Done       Tr           */
-
-#define        SM_TR_IDLE      0x0     /* Trans. Data  Idle            Tr/Re        */
-#define        SM_TR_LOAD      0x3     /* Trans. Data  Load            Tr/Re        */
-#define        SM_TR_LOAD_R_ML 0x1     /* Trans. Data  Load              /Re   (ML) */
-#define        SM_TR_WAIT_TC   0x2     /* Trans. Data  Wait_TC         Tr/Re        */
-#define        SM_TR_WDONE     0x4     /* Trans. Data  Wait_Done       Tr/Re        */
-
-#define        SM_WR_IDLE      0x0     /* Write Desc.  Idle            Tr/Re        */
-#define        SM_WR_ABLEN     0x1     /* Write Desc.  Act_Buf_Length  Tr/Re        */
-#define        SM_WR_LD_A4     0x2     /* Write Desc.  Load_A4            Re        */
-#define        SM_WR_RES_OWN   0x2     /* Write Desc.  Res_OWN         Tr           */
-#define        SM_WR_WAIT_EOF  0x3     /* Write Desc.  Wait_EOF           Re        */
-#define        SM_WR_LD_N2C_R  0x4     /* Write Desc.  Load_N2C           Re        */
-#define        SM_WR_WAIT_TC_R 0x5     /* Write Desc.  Wait_TC            Re        */
-#define        SM_WR_WAIT_TC4  0x6     /* Write Desc.  Wait_TC4           Re        */
-#define        SM_WR_LD_A_T    0x6     /* Write Desc.  Load_A          Tr           */
-#define        SM_WR_LD_A_R    0x7     /* Write Desc.  Load_A             Re        */
-#define        SM_WR_WAIT_TC_T 0x7     /* Write Desc.  Wait_TC         Tr           */
-#define        SM_WR_LD_N2C_T  0xc     /* Write Desc.  Load_N2C        Tr           */
-#define        SM_WR_WDONE_T   0x9     /* Write Desc.  Wait_Done       Tr           */
-#define        SM_WR_WDONE_R   0xc     /* Write Desc.  Wait_Done          Re        */
-#define SM_WR_LD_D_AD  0xe     /* Write Desc.  Load_Dumr_A        Re   (ML) */
-#define SM_WR_WAIT_D_TC        0xf     /* Write Desc.  Wait_Dumr_TC       Re   (ML) */
-
-/*     B5_<xx>_T2      32 bit Test Register 2           (xx) */
-/* Note: This register is only defined for the transmit queues */
-                               /* Bit 31..8:   reserved */
-#define        AC_TEST_ON      (1<<7)  /* Bit 7:       Address Counter Test Mode on */
-#define        AC_TEST_OFF     (1<<6)  /* Bit 6:       Address Counter Test Mode off*/
-#define        BC_TEST_ON      (1<<5)  /* Bit 5:       Byte Counter Test Mode on */
-#define        BC_TEST_OFF     (1<<4)  /* Bit 4:       Byte Counter Test Mode off */
-#define        TEST_STEP04     (1<<3)  /* Bit 3:       Inc AC/Dec BC by 4 */
-#define        TEST_STEP03     (1<<2)  /* Bit 2:       Inc AC/Dec BC by 3 */
-#define        TEST_STEP02     (1<<1)  /* Bit 1:       Inc AC/Dec BC by 2 */
-#define        TEST_STEP01     (1<<0)  /* Bit 0:       Inc AC/Dec BC by 1 */
-
-/*     B5_<xx>_T3      32 bit Test Register 3           (xx) */
-/* Note: This register is only defined for the transmit queues */
-                               /* Bit 31..8:   reserved */
-#define T3_MUX_2       (1<<7)  /* Bit 7: (ML)  Mux position MSB */
-#define T3_VRAM_2      (1<<6)  /* Bit 6: (ML)  Virtual RAM buffer addr MSB */
-#define        T3_LOOP         (1<<5)  /* Bit 5:       Set Loopback (Xmit) */
-#define        T3_UNLOOP       (1<<4)  /* Bit 4:       Unset Loopback (Xmit) */
-#define        T3_MUX          (3<<2)  /* Bit 3..2:    Mux position */
-#define        T3_VRAM         (3<<0)  /* Bit 1..0:    Virtual RAM buffer Address */
-
-/* PCI card IDs */
-/*
- * Note: The following 4 byte definitions shall not be used! Use OEM Concept!
- */
-#define        PCI_VEND_ID0    0x48            /* PCI vendor ID (SysKonnect) */
-#define        PCI_VEND_ID1    0x11            /* PCI vendor ID (SysKonnect) */
-                                       /*               (High byte) */
-#define        PCI_DEV_ID0     0x00            /* PCI device ID */
-#define        PCI_DEV_ID1     0x40            /* PCI device ID (High byte) */
-
-/*#define PCI_CLASS    0x02*/          /* PCI class code: network device */
-#define PCI_NW_CLASS   0x02            /* PCI class code: network device */
-#define PCI_SUB_CLASS  0x02            /* PCI subclass ID: FDDI device */
-#define PCI_PROG_INTFC 0x00            /* PCI programming Interface (=0) */
-
-/*
- * address transmission from logical to physical offset address on board
- */
-#define        FMA(a)  (0x0400|((a)<<2))       /* FORMAC+ (r/w) (SN3) */
-#define        P1(a)   (0x0380|((a)<<2))       /* PLC1 (r/w) (DAS) */
-#define        P2(a)   (0x0600|((a)<<2))       /* PLC2 (r/w) (covered by the SN3) */
-#define PRA(a) (B2_MAC_0 + (a))        /* configuration PROM (MAC address) */
-
-/*
- * FlashProm specification
- */
-#define        MAX_PAGES       0x20000L        /* Every byte has a single page */
-#define        MAX_FADDR       1               /* 1 byte per page */
-
-/*
- * Receive / Transmit Buffer Control word
- */
-#define        BMU_OWN         (1UL<<31)       /* OWN bit: 0 == host, 1 == adapter */
-#define        BMU_STF         (1L<<30)        /* Start of Frame ?             */
-#define        BMU_EOF         (1L<<29)        /* End of Frame ?               */
-#define        BMU_EN_IRQ_EOB  (1L<<28)        /* Enable "End of Buffer" IRQ   */
-#define        BMU_EN_IRQ_EOF  (1L<<27)        /* Enable "End of Frame" IRQ    */
-#define        BMU_DEV_0       (1L<<26)        /* RX: don't transfer to system mem */
-#define BMU_SMT_TX     (1L<<25)        /* TX: if set, buffer type SMT_MBuf */
-#define BMU_ST_BUF     (1L<<25)        /* RX: copy of start of frame */
-#define BMU_UNUSED     (1L<<24)        /* Set if the Descr is curr unused */
-#define BMU_SW         (3L<<24)        /* 2 Bits reserved for SW usage */
-#define        BMU_CHECK       0x00550000L     /* To identify the control word */
-#define        BMU_BBC         0x0000FFFFL     /* R/T Buffer Byte Count        */
-
-/*
- * physical address offset + IO-Port base address
- */
-#ifdef MEM_MAPPED_IO
-#define        ADDR(a)         (char far *) smc->hw.iop+(a)
-#define        ADDRS(smc,a)    (char far *) (smc)->hw.iop+(a)
-#else
-#define        ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), \
-       (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0)))) : \
-       (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
-#define        ADDRS(smc,a) (((a)>>7) ? (outp((smc)->hw.iop+B0_RAP,(a)>>7), \
-       ((smc)->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0)))) : \
-       ((smc)->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
-#endif
-
-/*
- * Define a macro to access the configuration space
- */
-#define PCI_C(a)       ADDR(B3_CFG_SPC + (a))  /* PCI Config Space */
-
-#define EXT_R(a)       ADDR(B6_EXT_REG + (a))  /* External Registers */
-
-/*
- * Define some values needed for the MAC address (PROM)
- */
-#define        SA_MAC          (0)     /* start addr. MAC_AD within the PROM */
-#define        PRA_OFF         (0)     /* offset correction when 4th byte reading */
-
-#define        SKFDDI_PSZ      8       /* address PROM size */
-
-#define        FM_A(a) ADDR(FMA(a))    /* FORMAC Plus physical addr */
-#define        P1_A(a) ADDR(P1(a))     /* PLC1 (r/w) */
-#define        P2_A(a) ADDR(P2(a))     /* PLC2 (r/w) (DAS) */
-#define PR_A(a)        ADDR(PRA(a))    /* config. PROM (MAC address) */
-
-/*
- * Macro to read the PROM
- */
-#define        READ_PROM(a)    ((u_char)inp(a))
-
-#define        GET_PAGE(bank)  outpd(ADDR(B2_FAR),bank)
-#define        VPP_ON()
-#define        VPP_OFF()
-
-/*
- * Note: Values of the Interrupt Source Register are defined above
- */
-#define ISR_A          ADDR(B0_ISRC)
-#define        GET_ISR()               inpd(ISR_A)
-#define GET_ISR_SMP(iop)       inpd((iop)+B0_ISRC)
-#define        CHECK_ISR()             (inpd(ISR_A) & inpd(ADDR(B0_IMSK)))
-#define CHECK_ISR_SMP(iop)     (inpd((iop)+B0_ISRC) & inpd((iop)+B0_IMSK))
-
-#define        BUS_CHECK()
-
-/*
- * CLI_FBI:    Disable Board Interrupts
- * STI_FBI:    Enable Board Interrupts
- */
-#ifndef UNIX
-#define        CLI_FBI()       outpd(ADDR(B0_IMSK),0)
-#else
-#define        CLI_FBI(smc)    outpd(ADDRS((smc),B0_IMSK),0)
-#endif
-
-#ifndef UNIX
-#define        STI_FBI()       outpd(ADDR(B0_IMSK),smc->hw.is_imask)
-#else
-#define        STI_FBI(smc)    outpd(ADDRS((smc),B0_IMSK),(smc)->hw.is_imask)
-#endif
-
-#define CLI_FBI_SMP(iop)       outpd((iop)+B0_IMSK,0)
-#define        STI_FBI_SMP(smc,iop)    outpd((iop)+B0_IMSK,(smc)->hw.is_imask)
-
-#endif /* PCI */
-/*--------------------------------------------------------------------------*/
-
-/*
- * 12 bit transfer (dword) counter:
- *     (ISA:   2*trc = number of byte)
- *     (EISA:  4*trc = number of byte)
- *     (MCA:   4*trc = number of byte)
- */
-#define        MAX_TRANS       (0x0fff)
-
-/*
- * PC PIC
- */
-#define        MST_8259 (0x20)
-#define        SLV_8259 (0xA0)
-
-#define TPS            (18)            /* ticks per second */
-
-/*
- * error timer defs
- */
-#define        TN              (4)     /* number of supported timer = TN+1 */
-#define        SNPPND_TIME     (5)     /* buffer memory access over mem. data reg. */
-
-#define        MAC_AD  0x405a0000
-
-#define MODR1  FM_A(FM_MDREG1) /* mode register 1 */
-#define MODR2  FM_A(FM_MDREG2) /* mode register 2 */
-
-#define CMDR1  FM_A(FM_CMDREG1)        /* command register 1 */
-#define CMDR2  FM_A(FM_CMDREG2)        /* command register 2 */
-
-
-/*
- * function defines
- */
-#define        CLEAR(io,mask)          outpw((io),inpw(io)&(~(mask)))
-#define        SET(io,mask)            outpw((io),inpw(io)|(mask))
-#define        GET(io,mask)            (inpw(io)&(mask))
-#define        SETMASK(io,val,mask)    outpw((io),(inpw(io) & ~(mask)) | (val))
-
-/*
- * PHY Port A (PA) = PLC 1
- * With SuperNet 3 PHY-A and PHY S are identical.
- */
-#define        PLC(np,reg)     (((np) == PA) ? P2_A(reg) : P1_A(reg))
-
-/*
- * set memory address register for write and read
- */
-#define        MARW(ma)        outpw(FM_A(FM_MARW),(unsigned int)(ma))
-#define        MARR(ma)        outpw(FM_A(FM_MARR),(unsigned int)(ma))
-
-/*
- * read/write from/to memory data register
- */
-/* write double word */
-#define        MDRW(dd)        outpw(FM_A(FM_MDRU),(unsigned int)((dd)>>16)) ;\
-                       outpw(FM_A(FM_MDRL),(unsigned int)(dd))
-
-#ifndef WINNT
-/* read double word */
-#define        MDRR()          (((long)inpw(FM_A(FM_MDRU))<<16) + inpw(FM_A(FM_MDRL)))
-
-/* read FORMAC+ 32-bit status register */
-#define        GET_ST1()       (((long)inpw(FM_A(FM_ST1U))<<16) + inpw(FM_A(FM_ST1L)))
-#define        GET_ST2()       (((long)inpw(FM_A(FM_ST2U))<<16) + inpw(FM_A(FM_ST2L)))
-#ifdef SUPERNET_3
-#define        GET_ST3()       (((long)inpw(FM_A(FM_ST3U))<<16) + inpw(FM_A(FM_ST3L)))
-#endif
-#else
-/* read double word */
-#define MDRR()         inp2w((FM_A(FM_MDRU)),(FM_A(FM_MDRL)))
-
-/* read FORMAC+ 32-bit status register */
-#define GET_ST1()      inp2w((FM_A(FM_ST1U)),(FM_A(FM_ST1L)))
-#define GET_ST2()      inp2w((FM_A(FM_ST2U)),(FM_A(FM_ST2L)))
-#ifdef SUPERNET_3
-#define GET_ST3()      inp2w((FM_A(FM_ST3U)),(FM_A(FM_ST3L)))
-#endif
-#endif
-
-/* Special timer macro for 82c54 */
-                               /* timer access over data bus bit 8..15 */
-#define        OUT_82c54_TIMER(port,val)       outpw(TI_A(port),(val)<<8)
-#define        IN_82c54_TIMER(port)            ((inpw(TI_A(port))>>8) & 0xff)
-
-
-#ifdef DEBUG
-#define        DB_MAC(mac,st) {if (debug_mac & 0x1)\
-                               printf("M") ;\
-                       if (debug_mac & 0x2)\
-                               printf("\tMAC %d status 0x%08lx\n",mac,st) ;\
-                       if (debug_mac & 0x4)\
-                               dp_mac(mac,st) ;\
-}
-
-#define        DB_PLC(p,iev) { if (debug_plc & 0x1)\
-                               printf("P") ;\
-                       if (debug_plc & 0x2)\
-                               printf("\tPLC %s Int 0x%04x\n", \
-                                       (p == PA) ? "A" : "B", iev) ;\
-                       if (debug_plc & 0x4)\
-                               dp_plc(p,iev) ;\
-}
-
-#define        DB_TIMER() {    if (debug_timer & 0x1)\
-                               printf("T") ;\
-                       if (debug_timer & 0x2)\
-                               printf("\tTimer ISR\n") ;\
-}
-
-#else  /* no DEBUG */
-
-#define        DB_MAC(mac,st)
-#define        DB_PLC(p,iev)
-#define        DB_TIMER()
-
-#endif /* no DEBUG */
-
-#define        INC_PTR(sp,cp,ep)       if (++cp == ep) cp = sp
-/*
- * timer defs
- */
-#define        COUNT(t)        ((t)<<6)        /* counter */
-#define        RW_OP(o)        ((o)<<4)        /* read/write operation */
-#define        TMODE(m)        ((m)<<1)        /* timer mode */
-
-#endif
diff --git a/drivers/net/skfp/h/skfbiinc.h b/drivers/net/skfp/h/skfbiinc.h
deleted file mode 100644 (file)
index ac2d719..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _SKFBIINC_
-#define _SKFBIINC_
-
-#include "h/supern_2.h"
-
-/*
- * special defines for use into .asm files
- */
-#define ERR_FLAGS (FS_MSRABT | FS_SEAC2 | FS_SFRMERR | FS_SFRMTY1)
-
-#ifdef PCI
-#define        IMASK_FAST      (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
-                        IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
-                        IS_R1_C | IS_XA_C | IS_XS_C)
-#endif
-
-#ifdef PCI
-#define        ISR_MASK        (IS_MINTR1 | IS_R1_F | IS_XS_F| IS_XA_F | IMASK_FAST)
-#else
-#define        ISR_MASK        (IS_MINTR1 | IS_MINTR2 | IMASK_FAST)
-#endif
-
-#define        FMA_FM_CMDREG1  FMA(FM_CMDREG1)
-#define        FMA_FM_CMDREG2  FMA(FM_CMDREG2)
-#define        FMA_FM_STMCHN   FMA(FM_STMCHN)
-#define        FMA_FM_RPR      FMA(FM_RPR)
-#define        FMA_FM_WPXA0    FMA(FM_WPXA0)
-#define        FMA_FM_WPXA2    FMA(FM_WPXA2)
-#define        FMA_FM_MARR     FMA(FM_MARR)
-#define        FMA_FM_MARW     FMA(FM_MARW)
-#define        FMA_FM_MDRU     FMA(FM_MDRU)
-#define        FMA_FM_MDRL     FMA(FM_MDRL)
-#define        FMA_ST1L        FMA(FM_ST1L)
-#define        FMA_ST1U        FMA(FM_ST1U)
-#define        FMA_ST2L        FMA(FM_ST2L)
-#define        FMA_ST2U        FMA(FM_ST2U)
-#ifdef SUPERNET_3
-#define FMA_ST3L       FMA(FM_ST3L)
-#define FMA_ST3U       FMA(FM_ST3U)
-#endif
-
-#define TMODE_RRQ      RQ_RRQ
-#define TMODE_WAQ2     RQ_WA2
-#define        HSRA            HSR(0)
-
-
-#define FMA_FM_ST1L    FMA_ST1L
-#define FMA_FM_ST1U    FMA_ST1U
-#define FMA_FM_ST2L    FMA_ST2L
-#define FMA_FM_ST2U    FMA_ST2U
-#ifdef SUPERNET_3
-#define FMA_FM_ST3L    FMA_ST3L
-#define FMA_FM_ST3U    FMA_ST3U
-#endif
-
-#define FMA_FM_SWPR    FMA(FM_SWPR)
-
-#define FMA_FM_RPXA0   FMA(FM_RPXA0)
-
-#define        FMA_FM_RPXS     FMA(FM_RPXS)
-#define        FMA_FM_WPXS     FMA(FM_WPXS)
-
-#define        FMA_FM_IMSK1U   FMA(FM_IMSK1U)
-#define        FMA_FM_IMSK1L   FMA(FM_IMSK1L)
-
-#define        FMA_FM_EAS      FMA(FM_EAS)
-#define        FMA_FM_EAA0     FMA(FM_EAA0)
-
-#define        TMODE_WAQ0      RQ_WA0
-#define TMODE_WSQ      RQ_WSQ
-
-/* Define default for DRV_PCM_STATE_CHANGE */
-#ifndef        DRV_PCM_STATE_CHANGE
-#define        DRV_PCM_STATE_CHANGE(smc,plc,p_state)   /* nothing */
-#endif
-
-/* Define default for DRV_RMT_INDICATION */
-#ifndef        DRV_RMT_INDICATION
-#define        DRV_RMT_INDICATION(smc,i)       /* nothing */
-#endif
-
-#endif /* n_SKFBIINC_ */
-
diff --git a/drivers/net/skfp/h/smc.h b/drivers/net/skfp/h/smc.h
deleted file mode 100644 (file)
index c774a95..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _SCMECM_
-#define _SCMECM_
-
-#if    defined(PCI) && !defined(OSDEF)
-/*
- * In the case of the PCI bus the file osdef1st.h must be present
- */
-#define        OSDEF
-#endif
-
-#ifdef PCI
-#ifndef        SUPERNET_3
-#define        SUPERNET_3
-#endif
-#ifndef        TAG_MODE
-#define        TAG_MODE
-#endif
-#endif
-
-/*
- * include all other files in required order
- * the following files must have been included before:
- *     types.h
- *     fddi.h
- */
-#ifdef OSDEF
-#include "h/osdef1st.h"
-#endif /* OSDEF */
-#ifdef OEM_CONCEPT
-#include "oemdef.h"
-#endif /* OEM_CONCEPT */
-#include "h/smt.h"
-#include "h/cmtdef.h"
-#include "h/fddimib.h"
-#include "h/targethw.h"                /* all target hw dependencies */
-#include "h/targetos.h"                /* all target os dependencies */
-#ifdef ESS
-#include "h/sba.h"
-#endif
-
-/*
- * Event Queue
- *     queue.c
- * events are class/value pairs
- *     class   is addressee, e.g. RMT, PCM etc.
- *     value   is command, e.g. line state change, ring op change etc.
- */
-struct event_queue {
-       u_short class ;                 /* event class */
-       u_short event ;                 /* event value */
-} ;
-
-/*
- * define event queue as circular buffer
- */
-#ifdef CONCENTRATOR
-#define MAX_EVENT      128
-#else  /* nCONCENTRATOR */
-#define MAX_EVENT      64
-#endif /* nCONCENTRATOR */
-
-struct s_queue {
-
-       struct event_queue ev_queue[MAX_EVENT];
-       struct event_queue *ev_put ;
-       struct event_queue *ev_get ;
-} ;
-
-/*
- * ECM - Entity Coordination Management
- * ecm.c
- */
-struct s_ecm {
-       u_char path_test ;              /* ECM path test variable */
-       u_char sb_flag ;                /* ECM stuck bypass */
-       u_char DisconnectFlag ;         /* jd 05-Aug-1999 Bug #10419 
-                                        * ECM disconnected */
-       u_char ecm_line_state ;         /* flag to dispatcher : line states */
-       u_long trace_prop ;             /* ECM Trace_Prop flag >= 16 bits !! */
-       /* NUMPHYS note:
-        * this variable must have enough bits to hold all entiies in
-        * the station. So NUMPHYS may not be greater than 31.
-        */
-       char    ec_pad[2] ;
-       struct smt_timer ecm_timer ;    /* timer */
-} ;
-
-
-/*
- * RMT - Ring Management
- * rmt.c
- */
-struct s_rmt {
-       u_char dup_addr_test ;          /* state of dupl. addr. test */
-       u_char da_flag ;                /* flag : duplicate address det. */
-       u_char loop_avail ;             /* flag : MAC available for loopback */
-       u_char sm_ma_avail ;            /* flag : MAC available for SMT */
-       u_char no_flag ;                /* flag : ring not operational */
-       u_char bn_flag ;                /* flag : MAC reached beacon state */
-       u_char jm_flag ;                /* flag : jamming in NON_OP_DUP */
-       u_char rm_join ;                /* CFM flag RM_Join */
-       u_char rm_loop ;                /* CFM flag RM_Loop */
-
-       long fast_rm_join ;             /* bit mask of active ports */
-       /*
-        * timer and flags
-        */
-       struct smt_timer rmt_timer0 ;   /* timer 0 */
-       struct smt_timer rmt_timer1 ;   /* timer 1 */
-       struct smt_timer rmt_timer2 ;   /* timer 2 */
-       u_char timer0_exp ;             /* flag : timer 0 expired */
-       u_char timer1_exp ;             /* flag : timer 1 expired */
-       u_char timer2_exp ;             /* flag : timer 2 expired */
-
-       u_char rm_pad1[1] ;
-} ;
-
-/*
- * CFM - Configuration Management
- * cfm.c
- * used for SAS and DAS
- */
-struct s_cfm {
-       u_char cf_state;                /* CFM state machine current state */
-       u_char cf_pad[3] ;
-} ;
-
-/*
- * CEM - Configuration Element Management
- * cem.c
- * used for Concentrator
- */
-#ifdef CONCENTRATOR
-struct s_cem {
-       int     ce_state ;      /* CEM state */
-       int     ce_port ;       /* PA PB PM PM+1 .. */
-       int     ce_type ;       /* TA TB TS TM */
-} ;
-
-/*
- * linked list of CCEs in current token path
- */
-struct s_c_ring {
-       struct s_c_ring *c_next ;
-       char            c_entity ;
-} ;
-
-struct mib_path_config {
-       u_long  fddimibPATHConfigSMTIndex;
-       u_long  fddimibPATHConfigPATHIndex;
-       u_long  fddimibPATHConfigTokenOrder;
-       u_long  fddimibPATHConfigResourceType;
-#define SNMP_RES_TYPE_MAC      2       /* Resource is a MAC */
-#define SNMP_RES_TYPE_PORT     4       /* Resource is a PORT */
-       u_long  fddimibPATHConfigResourceIndex;
-       u_long  fddimibPATHConfigCurrentPath;
-#define SNMP_PATH_ISOLATED     1       /* Current path is isolated */
-#define SNMP_PATH_LOCAL                2       /* Current path is local */
-#define SNMP_PATH_SECONDARY    3       /* Current path is secondary */
-#define SNMP_PATH_PRIMARY      4       /* Current path is primary */
-#define SNMP_PATH_CONCATENATED 5       /* Current path is concatenated */
-#define SNMP_PATH_THRU         6       /* Current path is thru */
-};
-
-
-#endif
-
-/*
- * PCM connect states
- */
-#define PCM_DISABLED   0
-#define PCM_CONNECTING 1
-#define PCM_STANDBY    2
-#define PCM_ACTIVE     3
-
-struct s_pcm {
-       u_char  pcm_pad[3] ;
-} ;
-
-/*
- * PHY struct
- * one per physical port
- */
-struct s_phy {
-       /* Inter Module Globals */
-       struct fddi_mib_p       *mib ;
-
-       u_char np ;             /* index 0 .. NUMPHYS */
-       u_char cf_join ;
-       u_char cf_loop ;
-       u_char wc_flag ;        /* withhold connection flag */
-       u_char pc_mode ;        /* Holds the negotiated mode of the PCM */
-       u_char pc_lem_fail ;    /* flag : LCT failed */
-       u_char lc_test ;
-       u_char scrub ;          /* CFM flag Scrub -> PCM */
-       char phy_name ;
-       u_char pmd_type[2] ;    /* SK connector/transceiver type codes */
-#define PMD_SK_CONN    0       /* pmd_type[PMD_SK_CONN] = Connector */
-#define PMD_SK_PMD     1       /* pmd_type[PMD_SK_PMD] = Xver */
-       u_char pmd_scramble ;   /* scrambler on/off */
-
-       /* inner Module Globals */
-       u_char curr_ls ;        /* current line state */
-       u_char ls_flag ;
-       u_char rc_flag ;
-       u_char tc_flag ;
-       u_char td_flag ;
-       u_char bitn ;
-       u_char tr_flag ;        /* trace recvd while in active */
-       u_char twisted ;        /* flag to indicate an A-A or B-B connection */
-       u_char t_val[NUMBITS] ; /* transmit bits for signaling */
-       u_char r_val[NUMBITS] ; /* receive bits for signaling */
-       u_long t_next[NUMBITS] ;
-       struct smt_timer pcm_timer0 ;
-       struct smt_timer pcm_timer1 ;
-       struct smt_timer pcm_timer2 ;
-       u_char timer0_exp ;
-       u_char timer1_exp ;
-       u_char timer2_exp ;
-       u_char pcm_pad1[1] ;
-       int     cem_pst ;       /* CEM privae state; used for dual homing */
-       struct lem_counter lem ;
-#ifdef AMDPLC
-       struct s_plc    plc ;
-#endif
-} ;
-
-/*
- * timer package
- * smttimer.c
- */
-struct s_timer {
-       struct smt_timer        *st_queue ;
-       struct smt_timer        st_fast ;
-} ;
-
-/*
- * SRF types and data
- */
-#define SMT_EVENT_BASE                 1
-#define SMT_EVENT_MAC_PATH_CHANGE      (SMT_EVENT_BASE+0)
-#define SMT_EVENT_MAC_NEIGHBOR_CHANGE  (SMT_EVENT_BASE+1)
-#define SMT_EVENT_PORT_PATH_CHANGE     (SMT_EVENT_BASE+2)
-#define SMT_EVENT_PORT_CONNECTION      (SMT_EVENT_BASE+3)
-
-#define SMT_IS_CONDITION(x)                    ((x)>=SMT_COND_BASE)
-
-#define SMT_COND_BASE          (SMT_EVENT_PORT_CONNECTION+1)
-#define SMT_COND_SMT_PEER_WRAP         (SMT_COND_BASE+0)
-#define SMT_COND_SMT_HOLD              (SMT_COND_BASE+1)
-#define SMT_COND_MAC_FRAME_ERROR       (SMT_COND_BASE+2)
-#define SMT_COND_MAC_DUP_ADDR          (SMT_COND_BASE+3)
-#define SMT_COND_MAC_NOT_COPIED                (SMT_COND_BASE+4)
-#define SMT_COND_PORT_EB_ERROR         (SMT_COND_BASE+5)
-#define SMT_COND_PORT_LER              (SMT_COND_BASE+6)
-
-#define SR0_WAIT       0
-#define SR1_HOLDOFF    1
-#define SR2_DISABLED   2
-
-struct s_srf {
-       u_long  SRThreshold ;                   /* threshold value */
-       u_char  RT_Flag ;                       /* report transmitted flag */
-       u_char  sr_state ;                      /* state-machine */
-       u_char  any_report ;                    /* any report required */
-       u_long  TSR ;                           /* timer */
-       u_short ring_status ;                   /* IBM ring status */
-} ;
-
-/*
- * IBM token ring status
- */
-#define RS_RES15       (1<<15)                 /* reserved */
-#define RS_HARDERROR   (1<<14)                 /* ring down */
-#define RS_SOFTERROR   (1<<13)                 /* sent SRF */
-#define RS_BEACON      (1<<12)                 /* transmitted beacon */
-#define RS_PATHTEST    (1<<11)                 /* path test failed */
-#define RS_SELFTEST    (1<<10)                 /* selftest required */
-#define RS_RES9                (1<< 9)                 /* reserved */
-#define RS_DISCONNECT  (1<< 8)                 /* remote disconnect */
-#define RS_RES7                (1<< 7)                 /* reserved */
-#define RS_DUPADDR     (1<< 6)                 /* duplicate address */
-#define RS_NORINGOP    (1<< 5)                 /* no ring op */
-#define RS_VERSION     (1<< 4)                 /* SMT version mismatch */
-#define RS_STUCKBYPASSS        (1<< 3)                 /* stuck bypass */
-#define RS_EVENT       (1<< 2)                 /* FDDI event occurred */
-#define RS_RINGOPCHANGE        (1<< 1)                 /* ring op changed */
-#define RS_RES0                (1<< 0)                 /* reserved */
-
-#define RS_SET(smc,bit) \
-       ring_status_indication(smc,smc->srf.ring_status |= bit)
-#define RS_CLEAR(smc,bit)      \
-       ring_status_indication(smc,smc->srf.ring_status &= ~bit)
-
-#define RS_CLEAR_EVENT (0xffff & ~(RS_NORINGOP))
-
-/* Define the AIX-event-Notification as null function if it isn't defined */
-/* in the targetos.h file */
-#ifndef AIX_EVENT
-#define AIX_EVENT(smc,opt0,opt1,opt2,opt3)     /* nothing */
-#endif
-
-struct s_srf_evc {
-       u_char  evc_code ;                      /* event code type */
-       u_char  evc_index ;                     /* index for mult. instances */
-       u_char  evc_rep_required ;              /* report required */
-       u_short evc_para ;                      /* SMT Para Number */
-       u_char  *evc_cond_state ;               /* condition state */
-       u_char  *evc_multiple ;                 /* multiple occurrence */
-} ;
-
-/*
- * Values used by frame based services
- * smt.c
- */
-#define SMT_MAX_TEST           5
-#define SMT_TID_NIF            0               /* pending NIF request */
-#define SMT_TID_NIF_TEST       1               /* pending NIF test */
-#define SMT_TID_ECF_UNA                2               /* pending ECF UNA test */
-#define SMT_TID_ECF_DNA                3               /* pending ECF DNA test */
-#define SMT_TID_ECF            4               /* pending ECF test */
-
-struct smt_values {
-       u_long          smt_tvu ;               /* timer valid una */
-       u_long          smt_tvd ;               /* timer valid dna */
-       u_long          smt_tid ;               /* transaction id */
-       u_long          pend[SMT_MAX_TEST] ;    /* TID of requests */
-       u_long          uniq_time ;             /* unique time stamp */
-       u_short         uniq_ticks  ;           /* unique time stamp */
-       u_short         please_reconnect ;      /* flag : reconnect */
-       u_long          smt_last_lem ;
-       u_long          smt_last_notify ;
-       struct smt_timer        smt_timer ;     /* SMT NIF timer */
-       u_long          last_tok_time[NUMMACS]; /* token cnt emulation */
-} ;
-
-/*
- * SMT/CMT configurable parameters
- */
-#define SMT_DAS        0                       /* dual attach */
-#define SMT_SAS        1                       /* single attach */
-#define SMT_NAC        2                       /* null attach concentrator */
-
-struct smt_config {
-       u_char  attach_s ;              /* CFM attach to secondary path */
-       u_char  sas ;                   /* SMT_DAS/SAS/NAC */
-       u_char  build_ring_map ;        /* build ringmap if TRUE */
-       u_char  numphys ;               /* number of active phys */
-       u_char  sc_pad[1] ;
-
-       u_long  pcm_tb_min ;            /* PCM : TB_Min timer value */
-       u_long  pcm_tb_max ;            /* PCM : TB_Max timer value */
-       u_long  pcm_c_min ;             /* PCM : C_Min timer value */
-       u_long  pcm_t_out ;             /* PCM : T_Out timer value */
-       u_long  pcm_tl_min ;            /* PCM : TL_min timer value */
-       u_long  pcm_lc_short ;          /* PCM : LC_Short timer value */
-       u_long  pcm_lc_medium ;         /* PCM : LC_Medium timer value */
-       u_long  pcm_lc_long ;           /* PCM : LC_Long timer value */
-       u_long  pcm_lc_extended ;       /* PCM : LC_Extended timer value */
-       u_long  pcm_t_next_9 ;          /* PCM : T_Next[9] timer value */
-       u_long  pcm_ns_max ;            /* PCM : NS_Max timer value */
-
-       u_long  ecm_i_max ;             /* ECM : I_Max timer value */
-       u_long  ecm_in_max ;            /* ECM : IN_Max timer value */
-       u_long  ecm_td_min ;            /* ECM : TD_Min timer */
-       u_long  ecm_test_done ;         /* ECM : path test done timer */
-       u_long  ecm_check_poll ;        /* ECM : check bypass poller */
-
-       u_long  rmt_t_non_op ;          /* RMT : T_Non_OP timer value */
-       u_long  rmt_t_stuck ;           /* RMT : T_Stuck timer value */
-       u_long  rmt_t_direct ;          /* RMT : T_Direct timer value */
-       u_long  rmt_t_jam ;             /* RMT : T_Jam timer value */
-       u_long  rmt_t_announce ;        /* RMT : T_Announce timer value */
-       u_long  rmt_t_poll ;            /* RMT : claim/beacon poller */
-       u_long  rmt_dup_mac_behavior ;  /* Flag for the beavior of SMT if
-                                        * a Duplicate MAC Address was detected.
-                                        * FALSE: SMT will leave finally the ring
-                                        * TRUE:  SMT will reinstert into the ring
-                                        */
-       u_long  mac_d_max ;             /* MAC : D_Max timer value */
-
-       u_long lct_short ;              /* LCT : error threshold */
-       u_long lct_medium ;             /* LCT : error threshold */
-       u_long lct_long ;               /* LCT : error threshold */
-       u_long lct_extended ;           /* LCT : error threshold */
-} ;
-
-#ifdef DEBUG
-/*
- * Debugging struct sometimes used in smc
- */
-struct smt_debug {
-       int     d_smtf ;
-       int     d_smt ;
-       int     d_ecm ;
-       int     d_rmt ;
-       int     d_cfm ;
-       int     d_pcm ;
-       int     d_plc ;
-#ifdef ESS
-       int     d_ess ;
-#endif
-#ifdef SBA
-       int     d_sba ;
-#endif
-       struct  os_debug        d_os;   /* Include specific OS DEBUG struct */
-} ;
-
-#ifndef        DEBUG_BRD
-/* all boards shall be debugged with one debug struct */
-extern struct  smt_debug       debug;  /* Declaration of debug struct */
-#endif /* DEBUG_BRD */
-
-#endif /* DEBUG */
-
-/*
- * the SMT Context Struct SMC
- * this struct contains ALL global variables of SMT
- */
-struct s_smc {
-       struct s_smt_os os ;            /* os specific */
-       struct s_smt_hw hw ;            /* hardware */
-
-/*
- * NOTE: os and hw MUST BE the first two structs
- * anything beyond hw WILL BE SET TO ZERO in smt_set_defaults()
- */
-       struct smt_config s ;           /* smt constants */
-       struct smt_values sm ;          /* smt variables */
-       struct s_ecm    e ;             /* ecm */
-       struct s_rmt    r ;             /* rmt */
-       struct s_cfm    cf ;            /* cfm/cem */
-#ifdef CONCENTRATOR
-       struct s_cem    ce[NUMPHYS] ;   /* cem */
-       struct s_c_ring cr[NUMPHYS+NUMMACS] ;
-#endif
-       struct s_pcm    p ;             /* pcm */
-       struct s_phy    y[NUMPHYS] ;    /* phy */
-       struct s_queue  q ;             /* queue */
-       struct s_timer  t ;             /* timer */
-       struct s_srf srf ;              /* SRF */
-       struct s_srf_evc evcs[6+NUMPHYS*4] ;
-       struct fddi_mib mib ;           /* __THE_MIB__ */
-#ifdef SBA
-       struct s_sba    sba ;           /* SBA variables */
-#endif
-#ifdef ESS
-       struct s_ess    ess ;           /* Ess variables */
-#endif
-#if    defined(DEBUG) && defined(DEBUG_BRD)
-       /* If you want all single board to be debugged separately */
-       struct smt_debug        debug;  /* Declaration of debug struct */
-#endif /* DEBUG_BRD && DEBUG */
-} ;
-
-extern const struct fddi_addr fddi_broadcast;
-
-extern void all_selection_criteria(struct s_smc *smc);
-extern void card_stop(struct s_smc *smc);
-extern void init_board(struct s_smc *smc, u_char *mac_addr);
-extern int init_fplus(struct s_smc *smc);
-extern void init_plc(struct s_smc *smc);
-extern int init_smt(struct s_smc *smc, u_char * mac_addr);
-extern void mac1_irq(struct s_smc *smc, u_short stu, u_short stl);
-extern void mac2_irq(struct s_smc *smc, u_short code_s2u, u_short code_s2l);
-extern void mac3_irq(struct s_smc *smc, u_short code_s3u, u_short code_s3l);
-extern int pcm_status_twisted(struct s_smc *smc);
-extern void plc1_irq(struct s_smc *smc);
-extern void plc2_irq(struct s_smc *smc);
-extern void read_address(struct s_smc *smc, u_char * mac_addr);
-extern void timer_irq(struct s_smc *smc);
-
-#endif /* _SCMECM_ */
-
diff --git a/drivers/net/skfp/h/smt.h b/drivers/net/skfp/h/smt.h
deleted file mode 100644 (file)
index 2030f9c..0000000
+++ /dev/null
@@ -1,882 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *     SMT 7.2 frame definitions
- */
-
-#ifndef        _SMT_
-#define _SMT_
-
-/* #define SMT5_10 */
-#define SMT6_10
-#define SMT7_20
-
-#define        OPT_PMF         /* if parameter management is supported */
-#define        OPT_SRF         /* if status report is supported */
-
-/*
- * SMT frame version 5.1
- */
-
-#define SMT_VID        0x0001                  /* V 5.1 .. 6.1 */
-#define SMT_VID_2 0x0002               /* V 7.2 */
-
-struct smt_sid {
-       u_char  sid_oem[2] ;                    /* implementation spec. */
-       struct fddi_addr sid_node ;             /* node address */
-} ;
-
-typedef u_char t_station_id[8] ;
-
-/*
- * note on alignment :
- * sizeof(struct smt_header) = 32
- * all parameters are long aligned
- * if struct smt_header starts at offset 0, all longs are aligned correctly
- * (FC starts at offset 3)
- */
-_packed struct smt_header {
-       struct fddi_addr        smt_dest ;      /* destination address */
-       struct fddi_addr        smt_source ;    /* source address */
-       u_char                  smt_class ;     /* NIF, SIF ... */
-       u_char                  smt_type ;      /* req., response .. */
-       u_short                 smt_version ;   /* version id */
-       u_int                   smt_tid ;       /* transaction ID */
-       struct smt_sid          smt_sid ;       /* station ID */
-       u_short                 smt_pad ;       /* pad with 0 */
-       u_short                 smt_len ;       /* length of info field */
-} ;
-#define SWAP_SMTHEADER "662sl8ss"
-
-#if    0
-/*
- * MAC FC values
- */
-#define FC_SMT_INFO    0x41            /* SMT info */
-#define FC_SMT_NSA     0x4f            /* SMT Next Station Addressing */
-#endif
-
-
-/*
- * type codes
- */
-#define SMT_ANNOUNCE   0x01            /* announcement */
-#define SMT_REQUEST    0x02            /* request */
-#define SMT_REPLY      0x03            /* reply */
-
-/*
- * class codes
- */
-#define SMT_NIF                0x01            /* neighbor information frames */
-#define SMT_SIF_CONFIG 0x02            /* station information configuration */
-#define SMT_SIF_OPER   0x03            /* station information operation */
-#define SMT_ECF                0x04            /* echo frames */
-#define SMT_RAF                0x05            /* resource allocation */
-#define SMT_RDF                0x06            /* request denied */
-#define SMT_SRF                0x07            /* status report */
-#define SMT_PMF_GET    0x08            /* parameter management get */
-#define SMT_PMF_SET    0x09            /* parameter management set */
-#define SMT_ESF                0xff            /* extended service */
-
-#define SMT_MAX_ECHO_LEN       4458    /* max length of SMT Echo */
-#if    defined(CONC) || defined(CONC_II)
-#define SMT_TEST_ECHO_LEN      50      /* test length of SMT Echo */
-#else
-#define SMT_TEST_ECHO_LEN      SMT_MAX_ECHO_LEN        /* test length */
-#endif
-
-#define SMT_MAX_INFO_LEN       (4352-20)       /* max length for SMT info */
-
-
-/*
- * parameter types
- */
-
-struct smt_para {
-       u_short p_type ;                /* type */
-       u_short p_len ;                 /* length of parameter */
-} ;
-
-#define PARA_LEN       (sizeof(struct smt_para))
-
-#define SMTSETPARA(p,t)                (p)->para.p_type = (t),\
-                               (p)->para.p_len = sizeof(*(p)) - PARA_LEN
-
-/*
- * P01 : Upstream Neighbor Address, UNA
- */
-#define SMT_P_UNA      0x0001          /* upstream neighbor address */
-#define SWAP_SMT_P_UNA "s6"
-
-struct smt_p_una {
-       struct smt_para para ;          /* generic parameter header */
-       u_short una_pad ;
-       struct fddi_addr una_node ;     /* node address, zero if unknown */
-} ;
-
-/*
- * P02 : Station Descriptor
- */
-#define SMT_P_SDE      0x0002          /* station descriptor */
-#define SWAP_SMT_P_SDE "1111"
-
-#define SMT_SDE_STATION                0       /* end node */
-#define SMT_SDE_CONCENTRATOR   1       /* concentrator */
-
-struct smt_p_sde {
-       struct smt_para para ;          /* generic parameter header */
-       u_char  sde_type ;              /* station type */
-       u_char  sde_mac_count ;         /* number of MACs */
-       u_char  sde_non_master ;        /* number of A,B or S ports */
-       u_char  sde_master ;            /* number of S ports on conc. */
-} ;
-
-/*
- * P03 : Station State
- */
-#define SMT_P_STATE    0x0003          /* station state */
-#define SWAP_SMT_P_STATE       "scc"
-
-struct smt_p_state {
-       struct smt_para para ;          /* generic parameter header */
-       u_short st_pad ;
-       u_char  st_topology ;           /* topology */
-       u_char  st_dupl_addr ;          /* duplicate address detected */
-} ;
-#define SMT_ST_WRAPPED         (1<<0)  /* station wrapped */
-#define SMT_ST_UNATTACHED      (1<<1)  /* unattached concentrator */
-#define SMT_ST_TWISTED_A       (1<<2)  /* A-A connection, twisted ring */
-#define SMT_ST_TWISTED_B       (1<<3)  /* B-B connection, twisted ring */
-#define SMT_ST_ROOTED_S                (1<<4)  /* rooted station */
-#define SMT_ST_SRF             (1<<5)  /* SRF protocol supported */
-#define SMT_ST_SYNC_SERVICE    (1<<6)  /* use synchronous bandwidth */
-
-#define SMT_ST_MY_DUPA         (1<<0)  /* my station detected dupl. */
-#define SMT_ST_UNA_DUPA                (1<<1)  /* my UNA detected duplicate */
-
-/*
- * P04 : timestamp
- */
-#define SMT_P_TIMESTAMP        0x0004          /* time stamp */
-#define SWAP_SMT_P_TIMESTAMP   "8"
-struct smt_p_timestamp {
-       struct smt_para para ;          /* generic parameter header */
-       u_char  ts_time[8] ;            /* time, resolution 80nS, unique */
-} ;
-
-/*
- * P05 : station policies
- */
-#define SMT_P_POLICY   0x0005          /* station policies */
-#define SWAP_SMT_P_POLICY      "ss"
-
-struct smt_p_policy {
-       struct smt_para para ;          /* generic parameter header */
-       u_short pl_config ;
-       u_short pl_connect ;            /* bit string POLICY_AA ... */
-} ;
-#define SMT_PL_HOLD            1       /* hold policy supported (Dual MAC) */
-
-/*
- * P06 : latency equivalent
- */
-#define SMT_P_LATENCY  0x0006          /* latency */
-#define SWAP_SMT_P_LATENCY     "ssss"
-
-/*
- * note: latency has two phy entries by definition
- * for a SAS, the 2nd one is null
- */
-struct smt_p_latency {
-       struct smt_para para ;          /* generic parameter header */
-       u_short lt_phyout_idx1 ;        /* index */
-       u_short lt_latency1 ;           /* latency , unit : byte clock */
-       u_short lt_phyout_idx2 ;        /* 0 if SAS */
-       u_short lt_latency2 ;           /* 0 if SAS */
-} ;
-
-/*
- * P07 : MAC neighbors
- */
-#define SMT_P_NEIGHBORS        0x0007          /* MAC neighbor description */
-#define SWAP_SMT_P_NEIGHBORS   "ss66"
-
-struct smt_p_neighbor {
-       struct smt_para para ;          /* generic parameter header */
-       u_short nb_mib_index ;          /* MIB index */
-       u_short nb_mac_index ;          /* n+1 .. n+m, m = #MACs, n = #PHYs */
-       struct fddi_addr nb_una ;       /* UNA , 0 for unknown */
-       struct fddi_addr nb_dna ;       /* DNA , 0 for unknown */
-} ;
-
-/*
- * PHY record
- */
-#define SMT_PHY_A      0               /* A port */
-#define SMT_PHY_B      1               /* B port */
-#define SMT_PHY_S      2               /* slave port */
-#define SMT_PHY_M      3               /* master port */
-
-#define SMT_CS_DISABLED        0               /* connect state : disabled */
-#define SMT_CS_CONNECTING      1       /* connect state : connecting */
-#define SMT_CS_STANDBY 2               /* connect state : stand by */
-#define SMT_CS_ACTIVE  3               /* connect state : active */
-
-#define SMT_RM_NONE    0
-#define SMT_RM_MAC     1
-
-struct smt_phy_rec {
-       u_short phy_mib_index ;         /* MIB index */
-       u_char  phy_type ;              /* A/B/S/M */
-       u_char  phy_connect_state ;     /* disabled/connecting/active */
-       u_char  phy_remote_type ;       /* A/B/S/M */
-       u_char  phy_remote_mac ;        /* none/remote */
-       u_short phy_resource_idx ;      /* 1 .. n */
-} ;
-
-/*
- * MAC record
- */
-struct smt_mac_rec {
-       struct fddi_addr mac_addr ;             /* MAC address */
-       u_short         mac_resource_idx ;      /* n+1 .. n+m */
-} ;
-
-/*
- * P08 : path descriptors
- * should be really an array ; however our environment has a fixed number of
- * PHYs and MACs
- */
-#define SMT_P_PATH     0x0008                  /* path descriptor */
-#define SWAP_SMT_P_PATH        "[6s]"
-
-struct smt_p_path {
-       struct smt_para para ;          /* generic parameter header */
-       struct smt_phy_rec      pd_phy[2] ;     /* PHY A */
-       struct smt_mac_rec      pd_mac ;        /* MAC record */
-} ;
-
-/*
- * P09 : MAC status
- */
-#define SMT_P_MAC_STATUS       0x0009          /* MAC status */
-#define SWAP_SMT_P_MAC_STATUS  "sslllllllll"
-
-struct smt_p_mac_status {
-       struct smt_para para ;          /* generic parameter header */
-       u_short st_mib_index ;          /* MIB index */
-       u_short st_mac_index ;          /* n+1 .. n+m */
-       u_int   st_t_req ;              /* T_Req */
-       u_int   st_t_neg ;              /* T_Neg */
-       u_int   st_t_max ;              /* T_Max */
-       u_int   st_tvx_value ;          /* TVX_Value */
-       u_int   st_t_min ;              /* T_Min */
-       u_int   st_sba ;                /* synchr. bandwidth alloc */
-       u_int   st_frame_ct ;           /* frame counter */
-       u_int   st_error_ct ;           /* error counter */
-       u_int   st_lost_ct ;            /* lost frames counter */
-} ;
-
-/*
- * P0A : PHY link error rate monitoring
- */
-#define SMT_P_LEM      0x000a          /* link error monitor */
-#define SWAP_SMT_P_LEM "ssccccll"
-/*
- * units of lem_cutoff,lem_alarm,lem_estimate : 10**-x
- */
-struct smt_p_lem {
-       struct smt_para para ;          /* generic parameter header */
-       u_short lem_mib_index ;         /* MIB index */
-       u_short lem_phy_index ;         /* 1 .. n */
-       u_char  lem_pad2 ;              /* be nice and make it even . */
-       u_char  lem_cutoff ;            /* 0x4 .. 0xf, default 0x7 */
-       u_char  lem_alarm ;             /* 0x4 .. 0xf, default 0x8 */
-       u_char  lem_estimate ;          /* 0x0 .. 0xff */
-       u_int   lem_reject_ct ;         /* 0x00000000 .. 0xffffffff */
-       u_int   lem_ct ;                /* 0x00000000 .. 0xffffffff */
-} ;
-
-/*
- * P0B : MAC frame counters
- */
-#define SMT_P_MAC_COUNTER 0x000b       /* MAC frame counters */
-#define SWAP_SMT_P_MAC_COUNTER "ssll"
-
-struct smt_p_mac_counter {
-       struct smt_para para ;          /* generic parameter header */
-       u_short mc_mib_index ;          /* MIB index */
-       u_short mc_index ;              /* mac index */
-       u_int   mc_receive_ct ;         /* receive counter */
-       u_int   mc_transmit_ct ;        /* transmit counter */
-} ;
-
-/*
- * P0C : MAC frame not copied counter
- */
-#define SMT_P_MAC_FNC  0x000c          /* MAC frame not copied counter */
-#define SWAP_SMT_P_MAC_FNC     "ssl"
-
-struct smt_p_mac_fnc {
-       struct smt_para para ;          /* generic parameter header */
-       u_short nc_mib_index ;          /* MIB index */
-       u_short nc_index ;              /* mac index */
-       u_int   nc_counter ;            /* not copied counter */
-} ;
-
-
-/*
- * P0D : MAC priority values
- */
-#define SMT_P_PRIORITY 0x000d          /* MAC priority values */
-#define SWAP_SMT_P_PRIORITY    "ssl"
-
-struct smt_p_priority {
-       struct smt_para para ;          /* generic parameter header */
-       u_short pr_mib_index ;          /* MIB index */
-       u_short pr_index ;              /* mac index */
-       u_int   pr_priority[7] ;        /* priority values */
-} ;
-
-/*
- * P0E : PHY elasticity buffer status
- */
-#define SMT_P_EB       0x000e          /* PHY EB status */
-#define SWAP_SMT_P_EB  "ssl"
-
-struct smt_p_eb {
-       struct smt_para para ;          /* generic parameter header */
-       u_short eb_mib_index ;          /* MIB index */
-       u_short eb_index ;              /* phy index */
-       u_int   eb_error_ct ;           /* # of eb overflows */
-} ;
-
-/*
- * P0F : manufacturer field
- */
-#define SMT_P_MANUFACTURER     0x000f  /* manufacturer field */
-#define SWAP_SMT_P_MANUFACTURER        ""
-
-struct smp_p_manufacturer {
-       struct smt_para para ;          /* generic parameter header */
-       u_char mf_data[32] ;            /* OUI + arbitrary data */
-} ;
-
-/*
- * P10 : user field
- */
-#define SMT_P_USER             0x0010  /* manufacturer field */
-#define SWAP_SMT_P_USER        ""
-
-struct smp_p_user {
-       struct smt_para para ;          /* generic parameter header */
-       u_char us_data[32] ;            /* arbitrary data */
-} ;
-
-
-
-/*
- * P11 : echo data
- */
-#define SMT_P_ECHODATA 0x0011          /* echo data */
-#define SWAP_SMT_P_ECHODATA    ""
-
-struct smt_p_echo {
-       struct smt_para para ;          /* generic parameter header */
-       u_char  ec_data[SMT_MAX_ECHO_LEN-4] ;   /* echo data */
-} ;
-
-/*
- * P12 : reason code
- */
-#define SMT_P_REASON   0x0012          /* reason code */
-#define SWAP_SMT_P_REASON      "l"
-
-struct smt_p_reason {
-       struct smt_para para ;          /* generic parameter header */
-       u_int   rdf_reason ;            /* CLASS/VERSION */
-} ;
-#define SMT_RDF_CLASS  0x00000001      /* class not supported */
-#define SMT_RDF_VERSION        0x00000002      /* version not supported */
-#define SMT_RDF_SUCCESS        0x00000003      /* success (PMF) */
-#define SMT_RDF_BADSET 0x00000004      /* bad set count (PMF) */
-#define SMT_RDF_ILLEGAL 0x00000005     /* read only (PMF) */
-#define SMT_RDF_NOPARAM        0x6             /* parameter not supported (PMF) */
-#define SMT_RDF_RANGE  0x8             /* out of range */
-#define SMT_RDF_AUTHOR 0x9             /* not autohorized */
-#define SMT_RDF_LENGTH 0x0a            /* length error */
-#define SMT_RDF_TOOLONG        0x0b            /* length error */
-#define SMT_RDF_SBA    0x0d            /* SBA denied */
-
-/*
- * P13 : refused frame beginning
- */
-#define SMT_P_REFUSED  0x0013          /* refused frame beginning */
-#define SWAP_SMT_P_REFUSED     "l"
-
-struct smt_p_refused {
-       struct smt_para para ;          /* generic parameter header */
-       u_int   ref_fc ;                /* 3 bytes 0 + FC */
-       struct smt_header       ref_header ;    /* refused header */
-} ;
-
-/*
- * P14 : supported SMT versions
- */
-#define SMT_P_VERSION  0x0014          /* SMT supported versions */
-#define SWAP_SMT_P_VERSION     "sccss"
-
-struct smt_p_version {
-       struct smt_para para ;          /* generic parameter header */
-       u_short v_pad ;
-       u_char  v_n ;                   /* 1 .. 0xff, #versions */
-       u_char  v_index ;               /* 1 .. 0xff, index of op. v. */
-       u_short v_version[1] ;          /* list of min. 1 version */
-       u_short v_pad2 ;                /* pad if necessary */
-} ;
-
-/*
- * P15 : Resource Type
- */
-#define        SWAP_SMT_P0015          "l"
-
-struct smt_p_0015 {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           res_type ;      /* recsource type */
-} ;
-
-#define        SYNC_BW         0x00000001L     /* Synchronous Bandwidth */
-
-/*
- * P16 : SBA Command
- */
-#define        SWAP_SMT_P0016          "l"
-
-struct smt_p_0016 {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           sba_cmd ;       /* command for the SBA */
-} ;
-
-#define        REQUEST_ALLOCATION      0x1     /* req allocation of sync bandwidth */
-#define        REPORT_ALLOCATION       0x2     /* rep of sync bandwidth allocation */
-#define        CHANGE_ALLOCATION       0x3     /* forces a station using sync band-*/
-                                       /* width to change its current allo-*/
-                                       /* cation */
-
-/*
- * P17 : SBA Payload Request
- */
-#define        SWAP_SMT_P0017          "l"
-
-struct smt_p_0017 {
-       struct smt_para para ;          /* generic parameter header */
-       int             sba_pl_req ;    /* total sync bandwidth measured in */
-} ;                                    /* bytes per 125 us */
-
-/*
- * P18 : SBA Overhead Request
- */
-#define        SWAP_SMT_P0018          "l"
-
-struct smt_p_0018 {
-       struct smt_para para ;          /* generic parameter header */
-       int             sba_ov_req ;    /* total sync bandwidth req for overhead*/
-} ;                                    /* measuered in bytes per T_Neg */
-
-/*
- * P19 : SBA Allocation Address
- */
-#define        SWAP_SMT_P0019          "s6"
-
-struct smt_p_0019 {
-       struct smt_para para ;          /* generic parameter header */
-       u_short         sba_pad ;
-       struct fddi_addr alloc_addr ;   /* Allocation Address */
-} ;
-
-/*
- * P1A : SBA Category
- */
-#define        SWAP_SMT_P001A          "l"
-
-struct smt_p_001a {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           category ;      /* Allocator defined classification */
-} ;
-
-/*
- * P1B : Maximum T_Neg
- */
-#define        SWAP_SMT_P001B          "l"
-
-struct smt_p_001b {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           max_t_neg ;     /* longest T_NEG for the sync service*/
-} ;
-
-/*
- * P1C : Minimum SBA Segment Size
- */
-#define        SWAP_SMT_P001C          "l"
-
-struct smt_p_001c {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           min_seg_siz ;   /* smallest number of bytes per frame*/
-} ;
-
-/*
- * P1D : SBA Allocatable
- */
-#define        SWAP_SMT_P001D          "l"
-
-struct smt_p_001d {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           allocatable ;   /* total sync bw available for alloc */
-} ;
-
-/*
- * P20 0B : frame status capabilities
- * NOTE: not in swap table, is used by smt.c AND PMF table
- */
-#define SMT_P_FSC      0x200b
-/* #define SWAP_SMT_P_FSC      "ssss" */
-
-struct smt_p_fsc {
-       struct smt_para para ;          /* generic parameter header */
-       u_short fsc_pad0 ;
-       u_short fsc_mac_index ;         /* mac index 1 .. ff */
-       u_short fsc_pad1 ;
-       u_short fsc_value ;             /* FSC_TYPE[0-2] */
-} ;
-
-#define FSC_TYPE0      0               /* "normal" node (A/C handling) */
-#define FSC_TYPE1      1               /* Special A/C indicator forwarding */
-#define FSC_TYPE2      2               /* Special A/C indicator forwarding */
-
-/*
- * P00 21 : user defined authoriziation (see pmf.c)
- */
-#define SMT_P_AUTHOR   0x0021
-
-/*
- * notification parameters
- */
-#define SWAP_SMT_P1048 "ll"
-struct smt_p_1048 {
-       u_int p1048_flag ;
-       u_int p1048_cf_state ;
-} ;
-
-/*
- * NOTE: all 2xxx 3xxx and 4xxx must include the INDEX in the swap string,
- *     even so the INDEX is NOT part of the struct.
- *     INDEX is already swapped in pmf.c, format in string is '4'
- */
-#define SWAP_SMT_P208C "4lss66"
-struct smt_p_208c {
-       u_int                   p208c_flag ;
-       u_short                 p208c_pad ;
-       u_short                 p208c_dupcondition ;
-       struct  fddi_addr       p208c_fddilong ;
-       struct  fddi_addr       p208c_fddiunalong ;
-} ;
-
-#define SWAP_SMT_P208D "4lllll"
-struct smt_p_208d {
-       u_int                   p208d_flag ;
-       u_int                   p208d_frame_ct ;
-       u_int                   p208d_error_ct ;
-       u_int                   p208d_lost_ct ;
-       u_int                   p208d_ratio ;
-} ;
-
-#define SWAP_SMT_P208E "4llll"
-struct smt_p_208e {
-       u_int                   p208e_flag ;
-       u_int                   p208e_not_copied ;
-       u_int                   p208e_copied ;
-       u_int                   p208e_not_copied_ratio ;
-} ;
-
-#define SWAP_SMT_P208F "4ll6666s6"
-
-struct smt_p_208f {
-       u_int                   p208f_multiple ;
-       u_int                   p208f_nacondition ;
-       struct fddi_addr        p208f_old_una ;
-       struct fddi_addr        p208f_new_una ;
-       struct fddi_addr        p208f_old_dna ;
-       struct fddi_addr        p208f_new_dna ;
-       u_short                 p208f_curren_path ;
-       struct fddi_addr        p208f_smt_address ;
-} ;
-
-#define SWAP_SMT_P2090 "4lssl"
-
-struct smt_p_2090 {
-       u_int                   p2090_multiple ;
-       u_short                 p2090_availablepaths ;
-       u_short                 p2090_currentpath ;
-       u_int                   p2090_requestedpaths ;
-} ;
-
-/*
- * NOTE:
- * special kludge for parameters 320b,320f,3210
- * these parameters are part of RAF frames
- * RAF frames are parsed in SBA.C and must be swapped
- * PMF.C has special code to avoid double swapping
- */
-#ifdef LITTLE_ENDIAN
-#define SBAPATHINDEX   (0x01000000L)
-#else
-#define SBAPATHINDEX   (0x01L)
-#endif
-
-#define        SWAP_SMT_P320B  "42s"
-
-struct smt_p_320b {
-       struct smt_para para ;  /* generic parameter header */
-       u_int   mib_index ;
-       u_short path_pad ;
-       u_short path_index ;
-} ;
-
-#define        SWAP_SMT_P320F  "4l"
-
-struct smt_p_320f {
-       struct smt_para para ;  /* generic parameter header */
-       u_int   mib_index ;
-       u_int   mib_payload ;
-} ;
-
-#define        SWAP_SMT_P3210  "4l"
-
-struct smt_p_3210 {
-       struct smt_para para ;  /* generic parameter header */
-       u_int   mib_index ;
-       u_int   mib_overhead ;
-} ;
-
-#define SWAP_SMT_P4050 "4l1111ll"
-
-struct smt_p_4050 {
-       u_int                   p4050_flag ;
-       u_char                  p4050_pad ;
-       u_char                  p4050_cutoff ;
-       u_char                  p4050_alarm ;
-       u_char                  p4050_estimate ;
-       u_int                   p4050_reject_ct ;
-       u_int                   p4050_ct ;
-} ;
-
-#define SWAP_SMT_P4051 "4lssss"
-struct smt_p_4051 {
-       u_int                   p4051_multiple ;
-       u_short                 p4051_porttype ;
-       u_short                 p4051_connectstate ;
-       u_short                 p4051_pc_neighbor ;
-       u_short                 p4051_pc_withhold ;
-} ;
-
-#define SWAP_SMT_P4052 "4ll"
-struct smt_p_4052 {
-       u_int                   p4052_flag ;
-       u_int                   p4052_eberrorcount ;
-} ;
-
-#define SWAP_SMT_P4053 "4lsslss"
-
-struct smt_p_4053 {
-       u_int                   p4053_multiple ;
-       u_short                 p4053_availablepaths ;
-       u_short                 p4053_currentpath ;
-       u_int                   p4053_requestedpaths ;
-       u_short                 p4053_mytype ;
-       u_short                 p4053_neighbortype ;
-} ;
-
-
-#define SMT_P_SETCOUNT 0x1035
-#define SWAP_SMT_P_SETCOUNT    "l8"
-
-struct smt_p_setcount {
-       struct smt_para para ;          /* generic parameter header */
-       u_int           count ;
-       u_char          timestamp[8] ;
-} ;
-
-/*
- * SMT FRAMES
- */
-
-/*
- * NIF : neighbor information frames
- */
-struct smt_nif {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_una        una ;           /* UNA */
-       struct smt_p_sde        sde ;           /* station descriptor */
-       struct smt_p_state      state ;         /* station state */
-#ifdef SMT6_10
-       struct smt_p_fsc        fsc ;           /* frame status cap. */
-#endif
-} ;
-
-/*
- * SIF : station information frames
- */
-struct smt_sif_config {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_timestamp  ts ;            /* time stamp */
-       struct smt_p_sde        sde ;           /* station descriptor */
-       struct smt_p_version    version ;       /* supported versions */
-       struct smt_p_state      state ;         /* station state */
-       struct smt_p_policy     policy ;        /* station policy */
-       struct smt_p_latency    latency ;       /* path latency */
-       struct smt_p_neighbor   neighbor ;      /* neighbors, we have only one*/
-#ifdef OPT_PMF
-       struct smt_p_setcount   setcount ;       /* Set Count mandatory */
-#endif
-       /* WARNING : path MUST BE LAST FIELD !!! (see smt.c:smt_fill_path) */
-       struct smt_p_path       path ;          /* path descriptor */
-} ;
-#define SIZEOF_SMT_SIF_CONFIG  (sizeof(struct smt_sif_config)- \
-                                sizeof(struct smt_p_path))
-
-struct smt_sif_operation {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_timestamp  ts ;            /* time stamp */
-       struct smt_p_mac_status status ;        /* mac status */
-       struct smt_p_mac_counter mc ;           /* MAC counter */
-       struct smt_p_mac_fnc    fnc ;           /* MAC frame not copied */
-       struct smp_p_manufacturer man ;         /* manufacturer field */
-       struct smp_p_user       user ;          /* user field */
-#ifdef OPT_PMF
-       struct smt_p_setcount   setcount ;       /* Set Count mandatory */
-#endif
-       /* must be last */
-       struct smt_p_lem        lem[1] ;        /* phy lem status */
-} ;
-#define SIZEOF_SMT_SIF_OPERATION       (sizeof(struct smt_sif_operation)- \
-                                        sizeof(struct smt_p_lem))
-
-/*
- * ECF : echo frame
- */
-struct smt_ecf {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_echo       ec_echo ;       /* echo parameter */
-} ;
-#define SMT_ECF_LEN    (sizeof(struct smt_header)+sizeof(struct smt_para))
-
-/*
- * RDF : request denied frame
- */
-struct smt_rdf {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_reason     reason ;        /* reason code */
-       struct smt_p_version    version ;       /* supported versions */
-       struct smt_p_refused    refused ;       /* refused frame fragment */
-} ;
-
-/*
- * SBA Request Allocation Response Frame
- */
-struct smt_sba_alc_res {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_0015       s_type ;        /* resource type */
-       struct smt_p_0016       cmd ;           /* SBA command */
-       struct smt_p_reason     reason ;        /* reason code */
-       struct smt_p_320b       path ;          /* path type */
-       struct smt_p_320f       payload ;       /* current SBA payload */
-       struct smt_p_3210       overhead ;      /* current SBA overhead */
-       struct smt_p_0019       a_addr ;        /* Allocation Address */
-       struct smt_p_001a       cat ;           /* Category - from the request */
-       struct smt_p_001d       alloc ;         /* SBA Allocatable */
-} ;
-
-/*
- * SBA Request Allocation Request Frame
- */
-struct smt_sba_alc_req {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_0015       s_type ;        /* resource type */
-       struct smt_p_0016       cmd ;           /* SBA command */
-       struct smt_p_320b       path ;          /* path type */
-       struct smt_p_0017       pl_req ;        /* requested payload */
-       struct smt_p_0018       ov_req ;        /* requested SBA overhead */
-       struct smt_p_320f       payload ;       /* current SBA payload */
-       struct smt_p_3210       overhead ;      /* current SBA overhead */
-       struct smt_p_0019       a_addr ;        /* Allocation Address */
-       struct smt_p_001a       cat ;           /* Category - from the request */
-       struct smt_p_001b       tneg ;          /* max T-NEG */
-       struct smt_p_001c       segm ;          /* minimum segment size */
-} ;
-
-/*
- * SBA Change Allocation Request Frame
- */
-struct smt_sba_chg {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_0015       s_type ;        /* resource type */
-       struct smt_p_0016       cmd ;           /* SBA command */
-       struct smt_p_320b       path ;          /* path type */
-       struct smt_p_320f       payload ;       /* current SBA payload */
-       struct smt_p_3210       overhead ;      /* current SBA overhead */
-       struct smt_p_001a       cat ;           /* Category - from the request */
-} ;
-
-/*
- * SBA Report Allocation Request Frame
- */
-struct smt_sba_rep_req {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_0015       s_type ;        /* resource type */
-       struct smt_p_0016       cmd ;           /* SBA command */
-} ;
-
-/*
- * SBA Report Allocation Response Frame
- */
-struct smt_sba_rep_res {
-       struct smt_header       smt ;           /* generic header */
-       struct smt_p_0015       s_type ;        /* resource type */
-       struct smt_p_0016       cmd ;           /* SBA command */
-       struct smt_p_320b       path ;          /* path type */
-       struct smt_p_320f       payload ;       /* current SBA payload */
-       struct smt_p_3210       overhead ;      /* current SBA overhead */
-} ;
-
-/*
- * actions
- */
-#define SMT_STATION_ACTION     1
-#define SMT_STATION_ACTION_CONNECT     0
-#define SMT_STATION_ACTION_DISCONNECT  1
-#define SMT_STATION_ACTION_PATHTEST    2
-#define SMT_STATION_ACTION_SELFTEST    3
-#define SMT_STATION_ACTION_DISABLE_A   4
-#define SMT_STATION_ACTION_DISABLE_B   5
-#define SMT_STATION_ACTION_DISABLE_M   6
-
-#define SMT_PORT_ACTION                2
-#define SMT_PORT_ACTION_MAINT  0
-#define SMT_PORT_ACTION_ENABLE 1
-#define SMT_PORT_ACTION_DISABLE        2
-#define SMT_PORT_ACTION_START  3
-#define SMT_PORT_ACTION_STOP   4
-
-#endif /* _SMT_ */
diff --git a/drivers/net/skfp/h/smt_p.h b/drivers/net/skfp/h/smt_p.h
deleted file mode 100644 (file)
index 99f9be9..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * defines for all SMT attributes
- */
-
-/*
- * this boring file was produced by perl
- * thanks Larry !
- */
-#define        SMT_P0012       0x0012
-
-#define        SMT_P0015       0x0015
-#define        SMT_P0016       0x0016
-#define        SMT_P0017       0x0017
-#define        SMT_P0018       0x0018
-#define        SMT_P0019       0x0019
-
-#define        SMT_P001A       0x001a
-#define        SMT_P001B       0x001b
-#define        SMT_P001C       0x001c
-#define        SMT_P001D       0x001d
-
-#define        SMT_P100A       0x100a
-#define        SMT_P100B       0x100b
-#define        SMT_P100C       0x100c
-#define        SMT_P100D       0x100d
-#define        SMT_P100E       0x100e
-#define        SMT_P100F       0x100f
-#define        SMT_P1010       0x1010
-#define        SMT_P1011       0x1011
-#define        SMT_P1012       0x1012
-#define        SMT_P1013       0x1013
-#define        SMT_P1014       0x1014
-#define        SMT_P1015       0x1015
-#define        SMT_P1016       0x1016
-#define        SMT_P1017       0x1017
-#define        SMT_P1018       0x1018
-#define        SMT_P1019       0x1019
-#define        SMT_P101A       0x101a
-#define        SMT_P101B       0x101b
-#define        SMT_P101C       0x101c
-#define        SMT_P101D       0x101d
-#define        SMT_P101E       0x101e
-#define        SMT_P101F       0x101f
-#define        SMT_P1020       0x1020
-#define        SMT_P1021       0x1021
-#define        SMT_P1022       0x1022
-#define        SMT_P1023       0x1023
-#define        SMT_P1024       0x1024
-#define        SMT_P1025       0x1025
-#define        SMT_P1026       0x1026
-#define        SMT_P1027       0x1027
-#define        SMT_P1028       0x1028
-#define        SMT_P1029       0x1029
-#define        SMT_P102A       0x102a
-#define        SMT_P102B       0x102b
-#define        SMT_P102C       0x102c
-#define        SMT_P102D       0x102d
-#define        SMT_P102E       0x102e
-#define        SMT_P102F       0x102f
-#define        SMT_P1030       0x1030
-#define        SMT_P1031       0x1031
-#define        SMT_P1032       0x1032
-#define        SMT_P1033       0x1033
-#define        SMT_P1034       0x1034
-#define        SMT_P1035       0x1035
-#define        SMT_P1036       0x1036
-#define        SMT_P1037       0x1037
-#define        SMT_P1038       0x1038
-#define        SMT_P1039       0x1039
-#define        SMT_P103A       0x103a
-#define        SMT_P103B       0x103b
-#define        SMT_P103C       0x103c
-#define        SMT_P103D       0x103d
-#define        SMT_P103E       0x103e
-#define        SMT_P103F       0x103f
-#define        SMT_P1040       0x1040
-#define        SMT_P1041       0x1041
-#define        SMT_P1042       0x1042
-#define        SMT_P1043       0x1043
-#define        SMT_P1044       0x1044
-#define        SMT_P1045       0x1045
-#define        SMT_P1046       0x1046
-#define        SMT_P1047       0x1047
-#define        SMT_P1048       0x1048
-#define        SMT_P1049       0x1049
-#define        SMT_P104A       0x104a
-#define        SMT_P104B       0x104b
-#define        SMT_P104C       0x104c
-#define        SMT_P104D       0x104d
-#define        SMT_P104E       0x104e
-#define        SMT_P104F       0x104f
-#define        SMT_P1050       0x1050
-#define        SMT_P1051       0x1051
-#define        SMT_P1052       0x1052
-#define        SMT_P1053       0x1053
-#define        SMT_P1054       0x1054
-
-#define        SMT_P10F0       0x10f0
-#define        SMT_P10F1       0x10f1
-#ifdef ESS
-#define        SMT_P10F2       0x10f2
-#define        SMT_P10F3       0x10f3
-#define        SMT_P10F4       0x10f4
-#define        SMT_P10F5       0x10f5
-#define        SMT_P10F6       0x10f6
-#define        SMT_P10F7       0x10f7
-#endif
-#ifdef SBA
-#define        SMT_P10F8       0x10f8
-#define        SMT_P10F9       0x10f9
-#endif
-
-#define        SMT_P200A       0x200a
-#define        SMT_P200B       0x200b
-#define        SMT_P200C       0x200c
-#define        SMT_P200D       0x200d
-#define        SMT_P200E       0x200e
-#define        SMT_P200F       0x200f
-#define        SMT_P2010       0x2010
-#define        SMT_P2011       0x2011
-#define        SMT_P2012       0x2012
-#define        SMT_P2013       0x2013
-#define        SMT_P2014       0x2014
-#define        SMT_P2015       0x2015
-#define        SMT_P2016       0x2016
-#define        SMT_P2017       0x2017
-#define        SMT_P2018       0x2018
-#define        SMT_P2019       0x2019
-#define        SMT_P201A       0x201a
-#define        SMT_P201B       0x201b
-#define        SMT_P201C       0x201c
-#define        SMT_P201D       0x201d
-#define        SMT_P201E       0x201e
-#define        SMT_P201F       0x201f
-#define        SMT_P2020       0x2020
-#define        SMT_P2021       0x2021
-#define        SMT_P2022       0x2022
-#define        SMT_P2023       0x2023
-#define        SMT_P2024       0x2024
-#define        SMT_P2025       0x2025
-#define        SMT_P2026       0x2026
-#define        SMT_P2027       0x2027
-#define        SMT_P2028       0x2028
-#define        SMT_P2029       0x2029
-#define        SMT_P202A       0x202a
-#define        SMT_P202B       0x202b
-#define        SMT_P202C       0x202c
-#define        SMT_P202D       0x202d
-#define        SMT_P202E       0x202e
-#define        SMT_P202F       0x202f
-#define        SMT_P2030       0x2030
-#define        SMT_P2031       0x2031
-#define        SMT_P2032       0x2032
-#define        SMT_P2033       0x2033
-#define        SMT_P2034       0x2034
-#define        SMT_P2035       0x2035
-#define        SMT_P2036       0x2036
-#define        SMT_P2037       0x2037
-#define        SMT_P2038       0x2038
-#define        SMT_P2039       0x2039
-#define        SMT_P203A       0x203a
-#define        SMT_P203B       0x203b
-#define        SMT_P203C       0x203c
-#define        SMT_P203D       0x203d
-#define        SMT_P203E       0x203e
-#define        SMT_P203F       0x203f
-#define        SMT_P2040       0x2040
-#define        SMT_P2041       0x2041
-#define        SMT_P2042       0x2042
-#define        SMT_P2043       0x2043
-#define        SMT_P2044       0x2044
-#define        SMT_P2045       0x2045
-#define        SMT_P2046       0x2046
-#define        SMT_P2047       0x2047
-#define        SMT_P2048       0x2048
-#define        SMT_P2049       0x2049
-#define        SMT_P204A       0x204a
-#define        SMT_P204B       0x204b
-#define        SMT_P204C       0x204c
-#define        SMT_P204D       0x204d
-#define        SMT_P204E       0x204e
-#define        SMT_P204F       0x204f
-#define        SMT_P2050       0x2050
-#define        SMT_P2051       0x2051
-#define        SMT_P2052       0x2052
-#define        SMT_P2053       0x2053
-#define        SMT_P2054       0x2054
-#define        SMT_P2055       0x2055
-#define        SMT_P2056       0x2056
-#define        SMT_P2057       0x2057
-#define        SMT_P2058       0x2058
-#define        SMT_P2059       0x2059
-#define        SMT_P205A       0x205a
-#define        SMT_P205B       0x205b
-#define        SMT_P205C       0x205c
-#define        SMT_P205D       0x205d
-#define        SMT_P205E       0x205e
-#define        SMT_P205F       0x205f
-#define        SMT_P2060       0x2060
-#define        SMT_P2061       0x2061
-#define        SMT_P2062       0x2062
-#define        SMT_P2063       0x2063
-#define        SMT_P2064       0x2064
-#define        SMT_P2065       0x2065
-#define        SMT_P2066       0x2066
-#define        SMT_P2067       0x2067
-#define        SMT_P2068       0x2068
-#define        SMT_P2069       0x2069
-#define        SMT_P206A       0x206a
-#define        SMT_P206B       0x206b
-#define        SMT_P206C       0x206c
-#define        SMT_P206D       0x206d
-#define        SMT_P206E       0x206e
-#define        SMT_P206F       0x206f
-#define        SMT_P2070       0x2070
-#define        SMT_P2071       0x2071
-#define        SMT_P2072       0x2072
-#define        SMT_P2073       0x2073
-#define        SMT_P2074       0x2074
-#define        SMT_P2075       0x2075
-#define        SMT_P2076       0x2076
-
-#define        SMT_P208C       0x208c
-#define        SMT_P208D       0x208d
-#define        SMT_P208E       0x208e
-#define        SMT_P208F       0x208f
-#define        SMT_P2090       0x2090
-
-#define        SMT_P20F0       0x20F0
-#define        SMT_P20F1       0x20F1
-
-#define        SMT_P320A       0x320a
-#define        SMT_P320B       0x320b
-#define        SMT_P320C       0x320c
-#define        SMT_P320D       0x320d
-#define        SMT_P320E       0x320e
-#define        SMT_P320F       0x320f
-#define        SMT_P3210       0x3210
-#define        SMT_P3211       0x3211
-#define        SMT_P3212       0x3212
-#define        SMT_P3213       0x3213
-#define        SMT_P3214       0x3214
-#define        SMT_P3215       0x3215
-#define        SMT_P3216       0x3216
-#define        SMT_P3217       0x3217
-
-#define        SMT_P400A       0x400a
-#define        SMT_P400B       0x400b
-#define        SMT_P400C       0x400c
-#define        SMT_P400D       0x400d
-#define        SMT_P400E       0x400e
-#define        SMT_P400F       0x400f
-#define        SMT_P4010       0x4010
-#define        SMT_P4011       0x4011
-#define        SMT_P4012       0x4012
-#define        SMT_P4013       0x4013
-#define        SMT_P4014       0x4014
-#define        SMT_P4015       0x4015
-#define        SMT_P4016       0x4016
-#define        SMT_P4017       0x4017
-#define        SMT_P4018       0x4018
-#define        SMT_P4019       0x4019
-#define        SMT_P401A       0x401a
-#define        SMT_P401B       0x401b
-#define        SMT_P401C       0x401c
-#define        SMT_P401D       0x401d
-#define        SMT_P401E       0x401e
-#define        SMT_P401F       0x401f
-#define        SMT_P4020       0x4020
-#define        SMT_P4021       0x4021
-#define        SMT_P4022       0x4022
-#define        SMT_P4023       0x4023
-#define        SMT_P4024       0x4024
-#define        SMT_P4025       0x4025
-#define        SMT_P4026       0x4026
-#define        SMT_P4027       0x4027
-#define        SMT_P4028       0x4028
-#define        SMT_P4029       0x4029
-#define        SMT_P402A       0x402a
-#define        SMT_P402B       0x402b
-#define        SMT_P402C       0x402c
-#define        SMT_P402D       0x402d
-#define        SMT_P402E       0x402e
-#define        SMT_P402F       0x402f
-#define        SMT_P4030       0x4030
-#define        SMT_P4031       0x4031
-#define        SMT_P4032       0x4032
-#define        SMT_P4033       0x4033
-#define        SMT_P4034       0x4034
-#define        SMT_P4035       0x4035
-#define        SMT_P4036       0x4036
-#define        SMT_P4037       0x4037
-#define        SMT_P4038       0x4038
-#define        SMT_P4039       0x4039
-#define        SMT_P403A       0x403a
-#define        SMT_P403B       0x403b
-#define        SMT_P403C       0x403c
-#define        SMT_P403D       0x403d
-#define        SMT_P403E       0x403e
-#define        SMT_P403F       0x403f
-#define        SMT_P4040       0x4040
-#define        SMT_P4041       0x4041
-#define        SMT_P4042       0x4042
-#define        SMT_P4043       0x4043
-#define        SMT_P4044       0x4044
-#define        SMT_P4045       0x4045
-#define        SMT_P4046       0x4046
-
-#define        SMT_P4050       0x4050
-#define        SMT_P4051       0x4051
-#define        SMT_P4052       0x4052
-#define        SMT_P4053       0x4053
diff --git a/drivers/net/skfp/h/smtstate.h b/drivers/net/skfp/h/smtstate.h
deleted file mode 100644 (file)
index 62fe695..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKFP_H_SMTSTATE_H_
-#define _SKFP_H_SMTSTATE_H_
-
-/*
- *     SMT state definitions
- */
-
-#ifndef        KERNEL
-/*
- * PCM states
- */
-#define PC0_OFF                        0
-#define PC1_BREAK              1
-#define PC2_TRACE              2
-#define PC3_CONNECT            3
-#define PC4_NEXT               4
-#define PC5_SIGNAL             5
-#define PC6_JOIN               6
-#define PC7_VERIFY             7
-#define PC8_ACTIVE             8
-#define PC9_MAINT              9
-
-/*
- * PCM modes
- */
-#define PM_NONE                        0
-#define PM_PEER                        1
-#define PM_TREE                        2
-
-/*
- * PCM type
- */
-#define TA                     0
-#define TB                     1
-#define TS                     2
-#define TM                     3
-#define TNONE                  4
-
-/*
- * CFM states
- */
-#define SC0_ISOLATED   0               /* isolated */
-#define SC1_WRAP_A     5               /* wrap A */
-#define SC2_WRAP_B     6               /* wrap B */
-#define SC4_THRU_A     12              /* through A */
-#define SC5_THRU_B     7               /* through B (SMt 6.2) */
-#define SC7_WRAP_S     8               /* SAS */
-
-/*
- * ECM states
- */
-#define EC0_OUT                0
-#define EC1_IN         1
-#define EC2_TRACE      2
-#define EC3_LEAVE      3
-#define EC4_PATH_TEST  4
-#define EC5_INSERT     5
-#define EC6_CHECK      6
-#define EC7_DEINSERT   7
-
-/*
- * RMT states
- */
-#define RM0_ISOLATED   0
-#define RM1_NON_OP     1               /* not operational */
-#define RM2_RING_OP    2               /* ring operational */
-#define RM3_DETECT     3               /* detect dupl addresses */
-#define RM4_NON_OP_DUP 4               /* dupl. addr detected */
-#define RM5_RING_OP_DUP        5               /* ring oper. with dupl. addr */
-#define RM6_DIRECTED   6               /* sending directed beacons */
-#define RM7_TRACE      7               /* trace initiated */
-#endif
-
-struct pcm_state {
-       unsigned char   pcm_type ;              /* TA TB TS TM */
-       unsigned char   pcm_state ;             /* state PC[0-9]_* */
-       unsigned char   pcm_mode ;              /* PM_{NONE,PEER,TREE} */
-       unsigned char   pcm_neighbor ;          /* TA TB TS TM */
-       unsigned char   pcm_bsf ;               /* flag bs : TRUE/FALSE */
-       unsigned char   pcm_lsf ;               /* flag ls : TRUE/FALSE */
-       unsigned char   pcm_lct_fail ;          /* counter lct_fail */
-       unsigned char   pcm_ls_rx ;             /* rx line state */
-       short           pcm_r_val ;             /* signaling bits */
-       short           pcm_t_val ;             /* signaling bits */
-} ;
-
-struct smt_state {
-       struct pcm_state pcm_state[NUMPHYS] ;   /* port A & port B */
-} ;
-
-#endif
-
diff --git a/drivers/net/skfp/h/supern_2.h b/drivers/net/skfp/h/supern_2.h
deleted file mode 100644 (file)
index 0b73690..0000000
+++ /dev/null
@@ -1,1059 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       defines for AMD Supernet II chip set
-       the chips are referred to as
-               FPLUS   Formac Plus
-               PLC     Physical Layer
-
-       added defines for AMD Supernet III chip set
-       added comments on differences between Supernet II and Supernet III
-       added defines for the Motorola ELM (MOT_ELM)
-*/
-
-#ifndef        _SUPERNET_
-#define _SUPERNET_
-
-/*
- * Define Supernet 3 when used
- */
-#ifdef PCI
-#ifndef        SUPERNET_3
-#define        SUPERNET_3
-#endif
-#define TAG
-#endif
-
-#define        MB      0xff
-#define        MW      0xffff
-#define        MD      0xffffffff
-
-/*
- * FORMAC frame status (rx_msext)
- */
-#define        FS_EI           (1<<2)
-#define        FS_AI           (1<<1)
-#define        FS_CI           (1<<0)
-
-#define FS_MSVALID     (1<<15)         /* end of queue */
-#define FS_MSRABT      (1<<14)         /* frame was aborted during reception*/
-#define FS_SSRCRTG     (1<<12)         /* if SA has set MSB (source-routing)*/
-#define FS_SEAC2       (FS_EI<<9)      /* error indicator */
-#define FS_SEAC1       (FS_AI<<9)      /* address indicator */
-#define FS_SEAC0       (FS_CI<<9)      /* copy indicator */
-#define FS_SFRMERR     (1<<8)          /* error detected (CRC or length) */
-#define FS_SADRRG      (1<<7)          /* address recognized */
-#define FS_SFRMTY2     (1<<6)          /* frame-class bit */
-#define FS_SFRMTY1     (1<<5)          /* frame-type bit (impementor) */
-#define FS_SFRMTY0     (1<<4)          /* frame-type bit (LLC) */
-#define FS_ERFBB1      (1<<1)          /* byte offset (depends on LSB bit) */
-#define FS_ERFBB0      (1<<0)          /*  - " - */
-
-/*
- * status frame type
- */
-#define        FRM_SMT         (0)     /* asynchr. frames */
-#define        FRM_LLCA        (1)
-#define        FRM_IMPA        (2)     
-#define        FRM_MAC         (4)     /* synchr. frames */
-#define        FRM_LLCS        (5)
-#define        FRM_IMPS        (6)
-
-/*
- * bits in rx_descr.i  (receive frame status word)
- */
-#define RX_MSVALID     ((long)1<<31)   /* memory status valid */
-#define RX_MSRABT      ((long)1<<30)   /* memory status receive abort */
-#define RX_FS_E                ((long)FS_SEAC2<<16)    /* error indicator */
-#define RX_FS_A                ((long)FS_SEAC1<<16)    /* address indicator */
-#define RX_FS_C                ((long)FS_SEAC0<<16)    /* copy indicator */
-#define RX_FS_CRC      ((long)FS_SFRMERR<<16)/* error detected */
-#define RX_FS_ADDRESS  ((long)FS_SADRRG<<16)   /* address recognized */
-#define RX_FS_MAC      ((long)FS_SFRMTY2<<16)/* MAC frame */
-#define RX_FS_SMT      ((long)0<<16)           /* SMT frame */
-#define RX_FS_IMPL     ((long)FS_SFRMTY1<<16)/* implementer frame */
-#define RX_FS_LLC      ((long)FS_SFRMTY0<<16)/* LLC frame */
-
-/*
- * receive frame descriptor
- */
-union rx_descr {
-       struct {
-#ifdef LITTLE_ENDIAN
-       unsigned        rx_length :16 ; /* frame length lower/upper byte */
-       unsigned        rx_erfbb  :2 ;  /* received frame byte boundary */
-       unsigned        rx_reserv2:2 ;  /* reserved */  
-       unsigned        rx_sfrmty :3 ;  /* frame type bits */
-       unsigned        rx_sadrrg :1 ;  /* DA == MA or broad-/multicast */
-       unsigned        rx_sfrmerr:1 ;  /* received frame not valid */
-       unsigned        rx_seac0  :1 ;  /* frame-copied  C-indicator */
-       unsigned        rx_seac1  :1 ;  /* address-match A-indicator */
-       unsigned        rx_seac2  :1 ;  /* frame-error   E-indicator */
-       unsigned        rx_ssrcrtg:1 ;  /* == 1 SA has MSB set */
-       unsigned        rx_reserv1:1 ;  /* reserved */  
-       unsigned        rx_msrabt :1 ;  /* memory status receive abort */
-       unsigned        rx_msvalid:1 ;  /* memory status valid */
-#else
-       unsigned        rx_msvalid:1 ;  /* memory status valid */
-       unsigned        rx_msrabt :1 ;  /* memory status receive abort */
-       unsigned        rx_reserv1:1 ;  /* reserved */  
-       unsigned        rx_ssrcrtg:1 ;  /* == 1 SA has MSB set */
-       unsigned        rx_seac2  :1 ;  /* frame-error   E-indicator */
-       unsigned        rx_seac1  :1 ;  /* address-match A-indicator */
-       unsigned        rx_seac0  :1 ;  /* frame-copied  C-indicator */
-       unsigned        rx_sfrmerr:1 ;  /* received frame not valid */
-       unsigned        rx_sadrrg :1 ;  /* DA == MA or broad-/multicast */
-       unsigned        rx_sfrmty :3 ;  /* frame type bits */
-       unsigned        rx_erfbb  :2 ;  /* received frame byte boundary */
-       unsigned        rx_reserv2:2 ;  /* reserved */  
-       unsigned        rx_length :16 ; /* frame length lower/upper byte */
-#endif
-       } r ;
-       long    i ;
-} ;
-
-/* defines for Receive Frame Descriptor access */
-#define RD_S_ERFBB     0x00030000L     /* received frame byte boundary */
-#define RD_S_RES2      0x000c0000L     /* reserved */
-#define RD_S_SFRMTY    0x00700000L     /* frame type bits */
-#define RD_S_SADRRG    0x00800000L     /* DA == MA or broad-/multicast */
-#define RD_S_SFRMERR   0x01000000L     /* received frame not valid */
-#define        RD_S_SEAC       0x0e000000L     /* frame status indicators */
-#define RD_S_SEAC0     0x02000000L     /* frame-copied  case-indicator */
-#define RD_S_SEAC1     0x04000000L     /* address-match A-indicator */
-#define RD_S_SEAC2     0x08000000L     /* frame-error   E-indicator */
-#define RD_S_SSRCRTG   0x10000000L     /* == 1 SA has MSB set */
-#define RD_S_RES1      0x20000000L     /* reserved */
-#define RD_S_MSRABT    0x40000000L     /* memory status receive abort */
-#define RD_S_MSVALID   0x80000000L     /* memory status valid */
-
-#define        RD_STATUS       0xffff0000L
-#define        RD_LENGTH       0x0000ffffL
-
-/* defines for Receive Frames Status Word values */
-/*RD_S_SFRMTY*/
-#define RD_FRM_SMT     (unsigned long)(0<<20)     /* asynchr. frames */
-#define RD_FRM_LLCA    (unsigned long)(1<<20)
-#define RD_FRM_IMPA    (unsigned long)(2<<20)
-#define RD_FRM_MAC     (unsigned long)(4<<20)     /* synchr. frames */
-#define RD_FRM_LLCS    (unsigned long)(5<<20)
-#define RD_FRM_IMPS    (unsigned long)(6<<20)
-
-#define TX_DESCRIPTOR  0x40000000L
-#define TX_OFFSET_3    0x18000000L
-
-#define TXP1   2
-
-/*
- * transmit frame descriptor
- */
-union tx_descr {
-       struct {
-#ifdef LITTLE_ENDIAN
-       unsigned        tx_length:16 ;  /* frame length lower/upper byte */
-       unsigned        tx_res   :8 ;   /* reserved      (bit 16..23) */
-       unsigned        tx_xmtabt:1 ;   /* transmit abort */
-       unsigned        tx_nfcs  :1 ;   /* no frame check sequence */
-       unsigned        tx_xdone :1 ;   /* give up token */
-       unsigned        tx_rpxm  :2 ;   /* byte offset */
-       unsigned        tx_pat1  :2 ;   /* must be TXP1 */
-       unsigned        tx_more  :1 ;   /* more frame in chain */
-#else
-       unsigned        tx_more  :1 ;   /* more frame in chain */
-       unsigned        tx_pat1  :2 ;   /* must be TXP1 */
-       unsigned        tx_rpxm  :2 ;   /* byte offset */
-       unsigned        tx_xdone :1 ;   /* give up token */
-       unsigned        tx_nfcs  :1 ;   /* no frame check sequence */
-       unsigned        tx_xmtabt:1 ;   /* transmit abort */
-       unsigned        tx_res   :8 ;   /* reserved      (bit 16..23) */
-       unsigned        tx_length:16 ;  /* frame length lower/upper byte */
-#endif
-       } t ;
-       long    i ;
-} ;
-
-/* defines for Transmit Descriptor access */
-#define        TD_C_MORE       0x80000000L     /* more frame in chain */
-#define        TD_C_DESCR      0x60000000L     /* must be TXP1 */
-#define        TD_C_TXFBB      0x18000000L     /* byte offset */
-#define        TD_C_XDONE      0x04000000L     /* give up token */
-#define TD_C_NFCS      0x02000000L     /* no frame check sequence */
-#define TD_C_XMTABT    0x01000000L     /* transmit abort */
-
-#define        TD_C_LNCNU      0x0000ff00L     
-#define TD_C_LNCNL     0x000000ffL
-#define TD_C_LNCN      0x0000ffffL     /* frame length lower/upper byte */
-/*
- * transmit pointer
- */
-union tx_pointer {
-       struct t {
-#ifdef LITTLE_ENDIAN
-       unsigned        tp_pointer:16 ; /* pointer to tx_descr (low/high) */
-       unsigned        tp_res    :8 ;  /* reserved      (bit 16..23) */
-       unsigned        tp_pattern:8 ;  /* fixed pattern (bit 24..31) */
-#else
-       unsigned        tp_pattern:8 ;  /* fixed pattern (bit 24..31) */
-       unsigned        tp_res    :8 ;  /* reserved      (bit 16..23) */
-       unsigned        tp_pointer:16 ; /* pointer to tx_descr (low/high) */
-#endif
-       } t ;
-       long    i ;
-} ;
-
-/* defines for Nontag Mode Pointer access */
-#define        TD_P_CNTRL      0xff000000L
-#define TD_P_RPXU      0x0000ff00L
-#define TD_P_RPXL      0x000000ffL
-#define TD_P_RPX       0x0000ffffL
-
-
-#define TX_PATTERN     0xa0
-#define TX_POINTER_END 0xa0000000L
-#define TX_INT_PATTERN 0xa0000000L
-
-struct tx_queue {
-       struct tx_queue *tq_next ;
-       u_short tq_pack_offset ;        /* offset buffer memory */
-       u_char  tq_pad[2] ;
-} ;
-
-/*
-       defines for FORMAC Plus (Am79C830)
-*/
-
-/*
- *  FORMAC+ read/write (r/w) registers
- */
-#define FM_CMDREG1     0x00            /* write command reg 1 instruction */
-#define FM_CMDREG2     0x01            /* write command reg 2 instruction */
-#define FM_ST1U                0x00            /* read upper 16-bit of status reg 1 */
-#define FM_ST1L                0x01            /* read lower 16-bit of status reg 1 */
-#define FM_ST2U                0x02            /* read upper 16-bit of status reg 2 */
-#define FM_ST2L                0x03            /* read lower 16-bit of status reg 2 */
-#define FM_IMSK1U      0x04            /* r/w upper 16-bit of IMSK 1 */
-#define FM_IMSK1L      0x05            /* r/w lower 16-bit of IMSK 1 */
-#define FM_IMSK2U      0x06            /* r/w upper 16-bit of IMSK 2 */
-#define FM_IMSK2L      0x07            /* r/w lower 16-bit of IMSK 2 */
-#define FM_SAID                0x08            /* r/w short addr.-individual */
-#define FM_LAIM                0x09            /* r/w long addr.-ind. (MSW of LAID) */
-#define FM_LAIC                0x0a            /* r/w long addr.-ind. (middle)*/
-#define FM_LAIL                0x0b            /* r/w long addr.-ind. (LSW) */
-#define FM_SAGP                0x0c            /* r/w short address-group */
-#define FM_LAGM                0x0d            /* r/w long addr.-gr. (MSW of LAGP) */
-#define FM_LAGC                0x0e            /* r/w long addr.-gr. (middle) */
-#define FM_LAGL                0x0f            /* r/w long addr.-gr. (LSW) */
-#define FM_MDREG1      0x10            /* r/w 16-bit mode reg 1 */
-#define FM_STMCHN      0x11            /* read state-machine reg */
-#define FM_MIR1                0x12            /* read upper 16-bit of MAC Info Reg */
-#define FM_MIR0                0x13            /* read lower 16-bit of MAC Info Reg */
-#define FM_TMAX                0x14            /* r/w 16-bit TMAX reg */
-#define FM_TVX         0x15            /* write 8-bit TVX reg with NP7-0
-                                          read TVX on NP7-0, timer on NP15-8*/
-#define FM_TRT         0x16            /* r/w upper 16-bit of TRT timer */
-#define FM_THT         0x17            /* r/w upper 16-bit of THT timer */
-#define FM_TNEG                0x18            /* read upper 16-bit of TNEG (TTRT) */
-#define FM_TMRS                0x19            /* read lower 5-bit of TNEG,TRT,THT */
-                       /* F E D C  B A 9 8  7 6 5 4  3 2 1 0
-                          x |-TNEG4-0| |-TRT4-0-| |-THT4-0-| (x-late count) */
-#define FM_TREQ0       0x1a            /* r/w 16-bit TREQ0 reg (LSW of TRT) */
-#define FM_TREQ1       0x1b            /* r/w 16-bit TREQ1 reg (MSW of TRT) */
-#define FM_PRI0                0x1c            /* r/w priority r. for asyn.-queue 0 */
-#define FM_PRI1                0x1d            /* r/w priority r. for asyn.-queue 1 */
-#define FM_PRI2                0x1e            /* r/w priority r. for asyn.-queue 2 */
-#define FM_TSYNC       0x1f            /* r/w 16-bit of the TSYNC register */
-#define FM_MDREG2      0x20            /* r/w 16-bit mode reg 2 */
-#define FM_FRMTHR      0x21            /* r/w the frame threshold register */
-#define FM_EACB                0x22            /* r/w end addr of claim/beacon area */
-#define FM_EARV                0x23            /* r/w end addr of receive queue */
-/* Supernet 3 */
-#define        FM_EARV1        FM_EARV
-
-#define FM_EAS         0x24            /* r/w end addr of synchr. queue */
-#define FM_EAA0                0x25            /* r/w end addr of asyn. queue 0 */
-#define FM_EAA1                0x26            /* r/w end addr of asyn. queue 1 */
-#define FM_EAA2                0x27            /* r/w end addr of asyn. queue 2 */
-#define FM_SACL                0x28            /* r/w start addr of claim frame */
-#define FM_SABC                0x29            /* r/w start addr of beacon frame */
-#define FM_WPXSF       0x2a            /* r/w the write ptr. for special fr.*/
-#define FM_RPXSF       0x2b            /* r/w the read ptr. for special fr. */
-#define FM_RPR         0x2d            /* r/w the read ptr. for receive qu. */
-#define FM_WPR         0x2e            /* r/w the write ptr. for receive qu.*/
-#define FM_SWPR                0x2f            /* r/w the shadow wr.-ptr. for rec.q.*/
-/* Supernet 3 */ 
-#define FM_RPR1         FM_RPR   
-#define FM_WPR1         FM_WPR 
-#define FM_SWPR1        FM_SWPR
-
-#define FM_WPXS                0x30            /* r/w the write ptr. for synchr. qu.*/
-#define FM_WPXA0       0x31            /* r/w the write ptr. for asyn. qu.0 */
-#define FM_WPXA1       0x32            /* r/w the write ptr. for asyn. qu.1 */
-#define FM_WPXA2       0x33            /* r/w the write ptr. for asyn. qu.2 */
-#define FM_SWPXS       0x34            /* r/w the shadow wr.-ptr. for syn.q.*/
-#define FM_SWPXA0      0x35            /* r/w the shad. wr.-ptr. for asyn.q0*/
-#define FM_SWPXA1      0x36            /* r/w the shad. wr.-ptr. for asyn.q1*/
-#define FM_SWPXA2      0x37            /* r/w the shad. wr.-ptr. for asyn.q2*/
-#define FM_RPXS                0x38            /* r/w the read ptr. for synchr. qu. */
-#define FM_RPXA0       0x39            /* r/w the read ptr. for asyn. qu. 0 */
-#define FM_RPXA1       0x3a            /* r/w the read ptr. for asyn. qu. 1 */
-#define FM_RPXA2       0x3b            /* r/w the read ptr. for asyn. qu. 2 */
-#define FM_MARR                0x3c            /* r/w the memory read addr register */
-#define FM_MARW                0x3d            /* r/w the memory write addr register*/
-#define FM_MDRU                0x3e            /* r/w upper 16-bit of mem. data reg */
-#define FM_MDRL                0x3f            /* r/w lower 16-bit of mem. data reg */
-
-/* following instructions relate to MAC counters and timer */
-#define FM_TMSYNC      0x40            /* r/w upper 16 bits of TMSYNC timer */
-#define FM_FCNTR       0x41            /* r/w the 16-bit frame counter */
-#define FM_LCNTR       0x42            /* r/w the 16-bit lost counter */
-#define FM_ECNTR       0x43            /* r/w the 16-bit error counter */
-
-/* Supernet 3: extensions to old register block */
-#define        FM_FSCNTR       0x44            /* r/? Frame Strip Counter */
-#define        FM_FRSELREG     0x45            /* r/w Frame Selection Register */
-
-/* Supernet 3: extensions for 2. receive queue etc. */
-#define        FM_MDREG3       0x60            /* r/w Mode Register 3 */
-#define        FM_ST3U         0x61            /* read upper 16-bit of status reg 3 */
-#define        FM_ST3L         0x62            /* read lower 16-bit of status reg 3 */
-#define        FM_IMSK3U       0x63            /* r/w upper 16-bit of IMSK reg 3 */
-#define        FM_IMSK3L       0x64            /* r/w lower 16-bit of IMSK reg 3 */
-#define        FM_IVR          0x65            /* read Interrupt Vector register */
-#define        FM_IMR          0x66            /* r/w Interrupt mask register */
-/* 0x67        Hidden */
-#define        FM_RPR2         0x68            /* r/w the read ptr. for rec. qu. 2 */
-#define        FM_WPR2         0x69            /* r/w the write ptr. for rec. qu. 2 */
-#define        FM_SWPR2        0x6a            /* r/w the shadow wptr. for rec. q. 2 */
-#define        FM_EARV2        0x6b            /* r/w end addr of rec. qu. 2 */
-#define        FM_UNLCKDLY     0x6c            /* r/w Auto Unlock Delay register */
-                                       /* Bit 15-8: RECV2 unlock threshold */
-                                       /* Bit  7-0: RECV1 unlock threshold */
-/* 0x6f-0x73   Hidden */
-#define        FM_LTDPA1       0x79            /* r/w Last Trans desc ptr for A1 qu. */
-/* 0x80-0x9a   PLCS registers of built-in PLCS  (Supernet 3 only) */
-
-/* Supernet 3: Adderss Filter Registers */
-#define        FM_AFCMD        0xb0            /* r/w Address Filter Command Reg */
-#define        FM_AFSTAT       0xb2            /* r/w Address Filter Status Reg */
-#define        FM_AFBIST       0xb4            /* r/w Address Filter BIST signature */
-#define        FM_AFCOMP2      0xb6            /* r/w Address Filter Comparand 2 */
-#define        FM_AFCOMP1      0xb8            /* r/w Address Filter Comparand 1 */
-#define        FM_AFCOMP0      0xba            /* r/w Address Filter Comparand 0 */
-#define        FM_AFMASK2      0xbc            /* r/w Address Filter Mask 2 */
-#define        FM_AFMASK1      0xbe            /* r/w Address Filter Mask 1 */
-#define        FM_AFMASK0      0xc0            /* r/w Address Filter Mask 0 */
-#define        FM_AFPERS       0xc2            /* r/w Address Filter Personality Reg */
-
-/* Supernet 3: Orion (PDX?) Registers */
-#define        FM_ORBIST       0xd0            /* r/w Orion BIST signature */
-#define        FM_ORSTAT       0xd2            /* r/w Orion Status Register */
-
-
-/*
- * Mode Register 1 (MDREG1)
- */
-#define FM_RES0                0x0001          /* reserved */
-                                       /* SN3: other definition */
-#define        FM_XMTINH_HOLD  0x0002          /* transmit-inhibit/hold bit */
-                                       /* SN3: other definition */
-#define        FM_HOFLXI       0x0003          /* SN3: Hold / Flush / Inhibit */
-#define        FM_FULL_HALF    0x0004          /* full-duplex/half-duplex bit */
-#define        FM_LOCKTX       0x0008          /* lock-transmit-asynchr.-queues bit */
-#define FM_EXGPA0      0x0010          /* extended-group-addressing bit 0 */
-#define FM_EXGPA1      0x0020          /* extended-group-addressing bit 1 */
-#define FM_DISCRY      0x0040          /* disable-carry bit */
-                                       /* SN3: reserved */
-#define FM_SELRA       0x0080          /* select input from PHY (1=RA,0=RB) */
-
-#define FM_ADDET       0x0700          /* address detection */
-#define FM_MDAMA       (0<<8)          /* address detection : DA = MA */
-#define FM_MDASAMA     (1<<8)          /* address detection : DA=MA||SA=MA */
-#define        FM_MRNNSAFNMA   (2<<8)          /* rec. non-NSA frames DA=MA&&SA!=MA */
-#define        FM_MRNNSAF      (3<<8)          /* rec. non-NSA frames DA = MA */
-#define        FM_MDISRCV      (4<<8)          /* disable receive function */
-#define        FM_MRES0        (5<<8)          /* reserve */
-#define        FM_MLIMPROM     (6<<8)          /* limited-promiscuous mode */
-#define FM_MPROMISCOUS (7<<8)          /* address detection : promiscuous */
-
-#define FM_SELSA       0x0800          /* select-short-address bit */
-
-#define FM_MMODE       0x7000          /* mode select */
-#define FM_MINIT       (0<<12)         /* initialize */
-#define FM_MMEMACT     (1<<12)         /* memory activate */
-#define FM_MONLINESP   (2<<12)         /* on-line special */
-#define FM_MONLINE     (3<<12)         /* on-line (FDDI operational mode) */
-#define FM_MILOOP      (4<<12)         /* internal loopback */
-#define FM_MRES1       (5<<12)         /* reserved */
-#define FM_MRES2       (6<<12)         /* reserved */
-#define FM_MELOOP      (7<<12)         /* external loopback */
-
-#define        FM_SNGLFRM      0x8000          /* single-frame-receive mode */
-                                       /* SN3: reserved */
-
-#define        MDR1INIT        (FM_MINIT | FM_MDAMA)
-
-/*
- * Mode Register 2 (MDREG2)
- */
-#define        FM_AFULL        0x000f          /* 4-bit value (empty loc.in txqueue)*/
-#define        FM_RCVERR       0x0010          /* rec.-errored-frames bit */
-#define        FM_SYMCTL       0x0020          /* sysmbol-control bit */
-                                       /* SN3: reserved */
-#define        FM_SYNPRQ       0x0040          /* synchron.-NP-DMA-request bit */
-#define        FM_ENNPRQ       0x0080          /* enable-NP-DMA-request bit */
-#define        FM_ENHSRQ       0x0100          /* enable-host-request bit */
-#define        FM_RXFBB01      0x0600          /* rec. frame byte boundary bit0 & 1 */
-#define        FM_LSB          0x0800          /* determ. ordering of bytes in buffer*/
-#define        FM_PARITY       0x1000          /* 1 = even, 0 = odd */
-#define        FM_CHKPAR       0x2000          /* 1 = parity of 32-bit buffer BD-bus*/
-#define        FM_STRPFCS      0x4000          /* 1 = strips FCS field of rec.frame */
-#define        FM_BMMODE       0x8000          /* Buffer-Memory-Mode (1 = tag mode) */
-                                       /* SN3: 1 = tag, 0 = modified tag */
-
-/*
- * Status Register 1, Upper 16 Bits (ST1U)
- */
-#define FM_STEFRMS     0x0001          /* transmit end of frame: synchr. qu.*/
-#define FM_STEFRMA0    0x0002          /* transmit end of frame: asyn. qu.0 */
-#define FM_STEFRMA1    0x0004          /* transmit end of frame: asyn. qu.1 */
-#define FM_STEFRMA2    0x0008          /* transmit end of frame: asyn. qu.2 */
-                                       /* SN3: reserved */
-#define FM_STECFRMS    0x0010          /* transmit end of chain of syn. qu. */
-                                       /* SN3: reserved */
-#define FM_STECFRMA0   0x0020          /* transmit end of chain of asyn. q0 */
-                                       /* SN3: reserved */
-#define FM_STECFRMA1   0x0040          /* transmit end of chain of asyn. q1 */
-                                       /* SN3: STECMDA1 */
-#define FM_STECMDA1    0x0040          /* SN3: 'no description' */
-#define FM_STECFRMA2   0x0080          /* transmit end of chain of asyn. q2 */
-                                       /* SN3: reserved */
-#define        FM_STEXDONS     0x0100          /* transmit until XDONE in syn. qu. */
-#define        FM_STBFLA       0x0200          /* asynchr.-queue trans. buffer full */
-#define        FM_STBFLS       0x0400          /* synchr.-queue transm. buffer full */
-#define        FM_STXABRS      0x0800          /* synchr. queue transmit-abort */
-#define        FM_STXABRA0     0x1000          /* asynchr. queue 0 transmit-abort */
-#define        FM_STXABRA1     0x2000          /* asynchr. queue 1 transmit-abort */
-#define        FM_STXABRA2     0x4000          /* asynchr. queue 2 transmit-abort */
-                                       /* SN3: reserved */
-#define        FM_SXMTABT      0x8000          /* transmit abort */
-
-/*
- * Status Register 1, Lower 16 Bits (ST1L)
- */
-#define FM_SQLCKS      0x0001          /* queue lock for synchr. queue */
-#define FM_SQLCKA0     0x0002          /* queue lock for asynchr. queue 0 */
-#define FM_SQLCKA1     0x0004          /* queue lock for asynchr. queue 1 */
-#define FM_SQLCKA2     0x0008          /* queue lock for asynchr. queue 2 */
-                                       /* SN3: reserved */
-#define FM_STXINFLS    0x0010          /* transmit instruction full: syn. */
-                                       /* SN3: reserved */
-#define FM_STXINFLA0   0x0020          /* transmit instruction full: asyn.0 */
-                                       /* SN3: reserved */
-#define FM_STXINFLA1   0x0040          /* transmit instruction full: asyn.1 */
-                                       /* SN3: reserved */
-#define FM_STXINFLA2   0x0080          /* transmit instruction full: asyn.2 */
-                                       /* SN3: reserved */
-#define FM_SPCEPDS     0x0100          /* parity/coding error: syn. queue */
-#define FM_SPCEPDA0    0x0200          /* parity/coding error: asyn. queue0 */
-#define FM_SPCEPDA1    0x0400          /* parity/coding error: asyn. queue1 */
-#define FM_SPCEPDA2    0x0800          /* parity/coding error: asyn. queue2 */
-                                       /* SN3: reserved */
-#define FM_STBURS      0x1000          /* transmit buffer underrun: syn. q. */
-#define FM_STBURA0     0x2000          /* transmit buffer underrun: asyn.0 */
-#define FM_STBURA1     0x4000          /* transmit buffer underrun: asyn.1 */
-#define FM_STBURA2     0x8000          /* transmit buffer underrun: asyn.2 */
-                                       /* SN3: reserved */
-
-/*
- * Status Register 2, Upper 16 Bits (ST2U)
- */
-#define FM_SOTRBEC     0x0001          /* other beacon received */
-#define FM_SMYBEC      0x0002          /* my beacon received */
-#define FM_SBEC                0x0004          /* beacon state entered */
-#define FM_SLOCLM      0x0008          /* low claim received */
-#define FM_SHICLM      0x0010          /* high claim received */
-#define FM_SMYCLM      0x0020          /* my claim received */
-#define FM_SCLM                0x0040          /* claim state entered */
-#define FM_SERRSF      0x0080          /* error in special frame */
-#define FM_SNFSLD      0x0100          /* NP and FORMAC+ simultaneous load */
-#define FM_SRFRCTOV    0x0200          /* receive frame counter overflow */
-                                       /* SN3: reserved */
-#define FM_SRCVFRM     0x0400          /* receive frame */
-                                       /* SN3: reserved */
-#define FM_SRCVOVR     0x0800          /* receive FIFO overflow */
-#define FM_SRBFL       0x1000          /* receive buffer full */
-#define FM_SRABT       0x2000          /* receive abort */
-#define FM_SRBMT       0x4000          /* receive buffer empty */
-#define FM_SRCOMP      0x8000          /* receive complete. Nontag mode */
-
-/*
- * Status Register 2, Lower 16 Bits (ST2L)
- * Attention: SN3 docu shows these bits the other way around
- */
-#define FM_SRES0       0x0001          /* reserved */
-#define FM_SESTRIPTK   0x0001          /* SN3: 'no description' */
-#define FM_STRTEXR     0x0002          /* TRT expired in claim | beacon st. */
-#define FM_SDUPCLM     0x0004          /* duplicate claim received */
-#define FM_SSIFG       0x0008          /* short interframe gap */
-#define FM_SFRMCTR     0x0010          /* frame counter overflow */
-#define FM_SERRCTR     0x0020          /* error counter overflow */
-#define FM_SLSTCTR     0x0040          /* lost counter overflow */
-#define FM_SPHINV      0x0080          /* PHY invalid */
-#define FM_SADET       0x0100          /* address detect */
-#define FM_SMISFRM     0x0200          /* missed frame */
-#define FM_STRTEXP     0x0400          /* TRT expired and late count > 0 */
-#define FM_STVXEXP     0x0800          /* TVX expired */
-#define FM_STKISS      0x1000          /* token issued */
-#define FM_STKERR      0x2000          /* token error */
-#define FM_SMULTDA     0x4000          /* multiple destination address */
-#define FM_SRNGOP      0x8000          /* ring operational */
-
-/*
- * Supernet 3:
- * Status Register 3, Upper 16 Bits (ST3U)
- */
-#define        FM_SRQUNLCK1    0x0001          /* receive queue unlocked queue 1 */
-#define        FM_SRQUNLCK2    0x0002          /* receive queue unlocked queue 2 */
-#define        FM_SRPERRQ1     0x0004          /* receive parity error rx queue 1 */
-#define        FM_SRPERRQ2     0x0008          /* receive parity error rx queue 2 */
-                                       /* Bit 4-10: reserved */
-#define        FM_SRCVOVR2     0x0800          /* receive FIFO overfull rx queue 2 */
-#define        FM_SRBFL2       0x1000          /* receive buffer full rx queue 2 */
-#define        FM_SRABT2       0x2000          /* receive abort rx queue 2 */
-#define        FM_SRBMT2       0x4000          /* receive buf empty rx queue 2 */
-#define        FM_SRCOMP2      0x8000          /* receive comp rx queue 2 */
-
-/*
- * Supernet 3:
- * Status Register 3, Lower 16 Bits (ST3L)
- */
-#define        FM_AF_BIST_DONE         0x0001  /* Address Filter BIST is done */
-#define        FM_PLC_BIST_DONE        0x0002  /* internal PLC Bist is done */
-#define        FM_PDX_BIST_DONE        0x0004  /* PDX BIST is done */
-                                       /* Bit  3: reserved */
-#define        FM_SICAMDAMAT           0x0010  /* Status internal CAM DA match */
-#define        FM_SICAMDAXACT          0x0020  /* Status internal CAM DA exact match */
-#define        FM_SICAMSAMAT           0x0040  /* Status internal CAM SA match */
-#define        FM_SICAMSAXACT          0x0080  /* Status internal CAM SA exact match */
-
-/*
- * MAC State-Machine Register FM_STMCHN
- */
-#define        FM_MDRTAG       0x0004          /* tag bit of long word read */
-#define        FM_SNPPND       0x0008          /* r/w from buffer mem. is pending */
-#define        FM_TXSTAT       0x0070          /* transmitter state machine state */
-#define        FM_RCSTAT       0x0380          /* receiver state machine state */
-#define        FM_TM01         0x0c00          /* indicate token mode */
-#define        FM_SIM          0x1000          /* indicate send immediate-mode */
-#define        FM_REV          0xe000          /* FORMAC Plus revision number */
-
-/*
- * Supernet 3
- * Mode Register 3
- */
-#define        FM_MENRS        0x0001          /* Ena enhanced rec status encoding */
-#define        FM_MENXS        0x0002          /* Ena enhanced xmit status encoding */
-#define        FM_MENXCT       0x0004          /* Ena EXACT/INEXACT matching */
-#define        FM_MENAFULL     0x0008          /* Ena enh QCTRL encoding for AFULL */
-#define        FM_MEIND        0x0030          /* Ena enh A,C indicator settings */
-#define        FM_MENQCTRL     0x0040          /* Ena enh QCTRL encoding */
-#define        FM_MENRQAUNLCK  0x0080          /* Ena rec q auto unlock */
-#define        FM_MENDAS       0x0100          /* Ena DAS connections by cntr MUX */
-#define        FM_MENPLCCST    0x0200          /* Ena Counter Segm test in PLC blck */
-#define        FM_MENSGLINT    0x0400          /* Ena Vectored Interrupt reading */
-#define        FM_MENDRCV      0x0800          /* Ena dual receive queue operation */
-#define        FM_MENFCLOC     0x3000          /* Ena FC location within frm data */
-#define        FM_MENTRCMD     0x4000          /* Ena ASYNC1 xmit only after command */
-#define        FM_MENTDLPBK    0x8000          /* Ena TDAT to RDAT lkoopback */
-
-/*
- * Supernet 3
- * Frame Selection Register
- */
-#define        FM_RECV1        0x000f          /* options for receive queue 1 */
-#define        FM_RCV1_ALL     (0<<0)          /* receive all frames */
-#define        FM_RCV1_LLC     (1<<0)          /* rec all LLC frames */
-#define        FM_RCV1_SMT     (2<<0)          /* rec all SMT frames */
-#define        FM_RCV1_NSMT    (3<<0)          /* rec non-SMT frames */
-#define        FM_RCV1_IMP     (4<<0)          /* rec Implementor frames */
-#define        FM_RCV1_MAC     (5<<0)          /* rec all MAC frames */
-#define        FM_RCV1_SLLC    (6<<0)          /* rec all sync LLC frames */
-#define        FM_RCV1_ALLC    (7<<0)          /* rec all async LLC frames */
-#define        FM_RCV1_VOID    (8<<0)          /* rec all void frames */
-#define        FM_RCV1_ALSMT   (9<<0)          /* rec all async LLC & SMT frames */
-#define        FM_RECV2        0x00f0          /* options for receive queue 2 */
-#define        FM_RCV2_ALL     (0<<4)          /* receive all other frames */
-#define        FM_RCV2_LLC     (1<<4)          /* rec all LLC frames */
-#define        FM_RCV2_SMT     (2<<4)          /* rec all SMT frames */
-#define        FM_RCV2_NSMT    (3<<4)          /* rec non-SMT frames */
-#define        FM_RCV2_IMP     (4<<4)          /* rec Implementor frames */
-#define        FM_RCV2_MAC     (5<<4)          /* rec all MAC frames */
-#define        FM_RCV2_SLLC    (6<<4)          /* rec all sync LLC frames */
-#define        FM_RCV2_ALLC    (7<<4)          /* rec all async LLC frames */
-#define        FM_RCV2_VOID    (8<<4)          /* rec all void frames */
-#define        FM_RCV2_ALSMT   (9<<4)          /* rec all async LLC & SMT frames */
-#define        FM_ENXMTADSWAP  0x4000          /* enh rec addr swap (phys -> can) */
-#define        FM_ENRCVADSWAP  0x8000          /* enh tx addr swap (can -> phys) */
-
-/*
- * Supernet 3:
- * Address Filter Command Register (AFCMD)
- */
-#define        FM_INST         0x0007          /* Address Filter Operation */
-#define FM_IINV_CAM    (0<<0)          /* Invalidate CAM */
-#define FM_IWRITE_CAM  (1<<0)          /* Write CAM */
-#define FM_IREAD_CAM   (2<<0)          /* Read CAM */
-#define FM_IRUN_BIST   (3<<0)          /* Run BIST */
-#define FM_IFIND       (4<<0)          /* Find */
-#define FM_IINV                (5<<0)          /* Invalidate */
-#define FM_ISKIP       (6<<0)          /* Skip */
-#define FM_ICL_SKIP    (7<<0)          /* Clear all SKIP bits */
-
-/*
- * Supernet 3:
- * Address Filter Status Register (AFSTAT)
- */
-                                       /* Bit  0-4: reserved */
-#define        FM_REV_NO       0x00e0          /* Revision Number of Address Filter */
-#define        FM_BIST_DONE    0x0100          /* BIST complete */
-#define        FM_EMPTY        0x0200          /* CAM empty */
-#define        FM_ERROR        0x0400          /* Error (improper operation) */
-#define        FM_MULT         0x0800          /* Multiple Match */
-#define        FM_EXACT        0x1000          /* Exact Match */
-#define        FM_FOUND        0x2000          /* Comparand found in CAM */
-#define        FM_FULL         0x4000          /* CAM full */
-#define        FM_DONE         0x8000          /* DONE indicator */
-
-/*
- * Supernet 3:
- * BIST Signature Register (AFBIST)
- */
-#define        AF_BIST_SIGNAT  0x0553          /* Address Filter BIST Signature */
-
-/*
- * Supernet 3:
- * Personality Register (AFPERS)
- */
-#define        FM_VALID        0x0001          /* CAM Entry Valid */
-#define        FM_DA           0x0002          /* Destination Address */
-#define        FM_DAX          0x0004          /* Destination Address Exact */
-#define        FM_SA           0x0008          /* Source Address */
-#define        FM_SAX          0x0010          /* Source Address Exact */
-#define        FM_SKIP         0x0020          /* Skip this entry */
-
-/*
- * instruction set for command register 1 (NPADDR6-0 = 0x00)
- */
-#define FM_IRESET      0x01            /* software reset */
-#define FM_IRMEMWI     0x02            /* load Memory Data Reg., inc MARR */
-#define FM_IRMEMWO     0x03            /* load MDR from buffer memory, n.i. */
-#define FM_IIL         0x04            /* idle/listen */
-#define FM_ICL         0x05            /* claim/listen */
-#define FM_IBL         0x06            /* beacon/listen */
-#define FM_ILTVX       0x07            /* load TVX timer from TVX reg */
-#define FM_INRTM       0x08            /* nonrestricted token mode */
-#define FM_IENTM       0x09            /* enter nonrestricted token mode */
-#define FM_IERTM       0x0a            /* enter restricted token mode */
-#define FM_IRTM                0x0b            /* restricted token mode */
-#define FM_ISURT       0x0c            /* send unrestricted token */
-#define FM_ISRT                0x0d            /* send restricted token */
-#define FM_ISIM                0x0e            /* enter send-immediate mode */
-#define FM_IESIM       0x0f            /* exit send-immediate mode */
-#define FM_ICLLS       0x11            /* clear synchronous queue lock */
-#define FM_ICLLA0      0x12            /* clear asynchronous queue 0 lock */
-#define FM_ICLLA1      0x14            /* clear asynchronous queue 1 lock */
-#define FM_ICLLA2      0x18            /* clear asynchronous queue 2 lock */
-                                       /* SN3: reserved */
-#define FM_ICLLR       0x20            /* clear receive queue (SN3:1) lock */
-#define FM_ICLLR2      0x21            /* SN3: clear receive queue 2 lock */
-#define FM_ITRXBUS     0x22            /* SN3: Tristate X-Bus (SAS only) */
-#define FM_IDRXBUS     0x23            /* SN3: drive X-Bus */
-#define FM_ICLLAL      0x3f            /* clear all queue locks */
-
-/*
- * instruction set for command register 2 (NPADDR6-0 = 0x01)
- */
-#define FM_ITRS                0x01            /* transmit synchronous queue */
-                                       /* SN3: reserved */
-#define FM_ITRA0       0x02            /* transmit asynchronous queue 0 */
-                                       /* SN3: reserved */
-#define FM_ITRA1       0x04            /* transmit asynchronous queue 1 */
-                                       /* SN3: reserved */
-#define FM_ITRA2       0x08            /* transmit asynchronous queue 2 */
-                                       /* SN3: reserved */
-#define FM_IACTR       0x10            /* abort current transmit activity */
-#define FM_IRSTQ       0x20            /* reset transmit queues */
-#define FM_ISTTB       0x30            /* set tag bit */
-#define FM_IERSF       0x40            /* enable receive single frame */
-                                       /* SN3: reserved */
-#define        FM_ITR          0x50            /* SN3: Transmit Command */
-
-
-/*
- *     defines for PLC (Am79C864)
- */
-
-/*
- *  PLC read/write (r/w) registers
- */
-#define PL_CNTRL_A     0x00            /* control register A (r/w) */
-#define PL_CNTRL_B     0x01            /* control register B (r/w) */
-#define PL_INTR_MASK   0x02            /* interrupt mask (r/w) */
-#define PL_XMIT_VECTOR 0x03            /* transmit vector register (r/w) */
-#define PL_VECTOR_LEN  0x04            /* transmit vector length (r/w) */
-#define PL_LE_THRESHOLD        0x05            /* link error event threshold (r/w) */
-#define PL_C_MIN       0x06            /* minimum connect state time (r/w) */
-#define PL_TL_MIN      0x07            /* min. line state transmit t. (r/w) */
-#define PL_TB_MIN      0x08            /* minimum break time (r/w) */
-#define PL_T_OUT       0x09            /* signal timeout (r/w) */
-#define PL_CNTRL_C     0x0a            /* control register C (r/w) */
-#define PL_LC_LENGTH   0x0b            /* link confidence test time (r/w) */
-#define PL_T_SCRUB     0x0c            /* scrub time = MAC TVX (r/w) */
-#define PL_NS_MAX      0x0d            /* max. noise time before break (r/w)*/
-#define PL_TPC_LOAD_V  0x0e            /* TPC timer load value (write only) */
-#define PL_TNE_LOAD_V  0x0f            /* TNE timer load value (write only) */
-#define PL_STATUS_A    0x10            /* status register A (read only) */
-#define PL_STATUS_B    0x11            /* status register B (read only) */
-#define PL_TPC         0x12            /* timer for PCM (ro) [20.48 us] */
-#define PL_TNE         0x13            /* time of noise event [0.32 us] */
-#define PL_CLK_DIV     0x14            /* TNE clock divider (read only) */
-#define PL_BIST_SIGNAT 0x15            /* built in self test signature (ro)*/
-#define PL_RCV_VECTOR  0x16            /* receive vector reg. (read only) */
-#define PL_INTR_EVENT  0x17            /* interrupt event reg. (read only) */
-#define PL_VIOL_SYM_CTR        0x18            /* violation symbol count. (read o) */
-#define PL_MIN_IDLE_CTR        0x19            /* minimum idle counter (read only) */
-#define PL_LINK_ERR_CTR        0x1a            /* link error event ctr.(read only) */
-#ifdef MOT_ELM
-#define        PL_T_FOT_ASS    0x1e            /* FOTOFF Assert Timer */
-#define        PL_T_FOT_DEASS  0x1f            /* FOTOFF Deassert Timer */
-#endif /* MOT_ELM */
-
-#ifdef MOT_ELM
-/*
- * Special Quad-Elm Registers.
- * A Quad-ELM consists of for ELMs and these additional registers.
- */
-#define        QELM_XBAR_W     0x80            /* Crossbar Control ELM W */
-#define        QELM_XBAR_X     0x81            /* Crossbar Control ELM X */
-#define        QELM_XBAR_Y     0x82            /* Crossbar Control ELM Y */
-#define        QELM_XBAR_Z     0x83            /* Crossbar Control ELM Z */
-#define        QELM_XBAR_P     0x84            /* Crossbar Control Bus P */
-#define        QELM_XBAR_S     0x85            /* Crossbar Control Bus S */
-#define        QELM_XBAR_R     0x86            /* Crossbar Control Bus R */
-#define        QELM_WR_XBAR    0x87            /* Write the Crossbar now (write) */
-#define        QELM_CTR_W      0x88            /* Counter W */
-#define        QELM_CTR_X      0x89            /* Counter X */
-#define        QELM_CTR_Y      0x8a            /* Counter Y */
-#define        QELM_CTR_Z      0x8b            /* Counter Z */
-#define        QELM_INT_MASK   0x8c            /* Interrupt mask register */
-#define        QELM_INT_DATA   0x8d            /* Interrupt data (event) register */
-#define        QELM_ELMB       0x00            /* Elm base */
-#define        QELM_ELM_SIZE   0x20            /* ELM size */
-#endif /* MOT_ELM */
-/*
- * PLC control register A (PL_CNTRL_A: log. addr. 0x00)
- * It is used for timer configuration, specification of PCM MAINT state option,
- * counter interrupt frequency, PLC data path config. and Built In Self Test.
- */
-#define        PL_RUN_BIST     0x0001          /* begin running its Built In Self T.*/
-#define        PL_RF_DISABLE   0x0002          /* disable the Repeat Filter state m.*/
-#define        PL_SC_REM_LOOP  0x0004          /* remote loopback path */
-#define        PL_SC_BYPASS    0x0008          /* by providing a physical bypass */
-#define        PL_LM_LOC_LOOP  0x0010          /* loop path just after elastic buff.*/
-#define        PL_EB_LOC_LOOP  0x0020          /* loop path just prior to PDT/PDR IF*/
-#define        PL_FOT_OFF      0x0040          /* assertion of /FOTOFF pin of PLC */
-#define        PL_LOOPBACK     0x0080          /* it cause the /LPBCK pin ass. low */
-#define        PL_MINI_CTR_INT 0x0100          /* partially contr. when bit is ass. */
-#define        PL_VSYM_CTR_INT 0x0200          /* controls when int bit is asserted */
-#define        PL_ENA_PAR_CHK  0x0400          /* enable parity check */
-#define        PL_REQ_SCRUB    0x0800          /* limited access to scrub capability*/
-#define        PL_TPC_16BIT    0x1000          /* causes the TPC as a 16 bit timer */
-#define        PL_TNE_16BIT    0x2000          /* causes the TNE as a 16 bit timer */
-#define        PL_NOISE_TIMER  0x4000          /* allows the noise timing function */
-
-/*
- * PLC control register B (PL_CNTRL_B: log. addr. 0x01)
- * It contains signals and requeste to direct the process of PCM and it is also
- * used to control the Line State Match interrupt.
- */
-#define        PL_PCM_CNTRL    0x0003          /* control PCM state machine */
-#define        PL_PCM_NAF      (0)             /* state is not affected */
-#define        PL_PCM_START    (1)             /* goes to the BREAK state */
-#define        PL_PCM_TRACE    (2)             /* goes to the TRACE state */
-#define        PL_PCM_STOP     (3)             /* goes to the OFF state */
-
-#define        PL_MAINT        0x0004          /* if OFF state --> MAINT state */
-#define        PL_LONG         0x0008          /* perf. a long Link Confid.Test(LCT)*/
-#define        PL_PC_JOIN      0x0010          /* if NEXT state --> JOIN state */
-
-#define        PL_PC_LOOP      0x0060          /* loopback used in the LCT */
-#define        PL_NOLCT        (0<<5)          /* no LCT is performed */
-#define        PL_TPDR         (1<<5)          /* PCM asserts transmit PDR */
-#define        PL_TIDLE        (2<<5)          /* PCM asserts transmit idle */
-#define        PL_RLBP         (3<<5)          /* trans. PDR & remote loopb. path */
-
-#define        PL_CLASS_S      0x0080          /* signif. that single att. station */
-
-#define        PL_MAINT_LS     0x0700          /* line state while in the MAINT st. */
-#define        PL_M_QUI0       (0<<8)          /* transmit QUIET line state */
-#define        PL_M_IDLE       (1<<8)          /* transmit IDLE line state */
-#define        PL_M_HALT       (2<<8)          /* transmit HALT line state */
-#define        PL_M_MASTR      (3<<8)          /* transmit MASTER line state */
-#define        PL_M_QUI1       (4<<8)          /* transmit QUIET line state */
-#define        PL_M_QUI2       (5<<8)          /* transmit QUIET line state */
-#define        PL_M_TPDR       (6<<8)          /* tr. PHY_DATA requ.-symbol is tr.ed*/
-#define        PL_M_QUI3       (7<<8)          /* transmit QUIET line state */
-
-#define        PL_MATCH_LS     0x7800          /* line state to be comp. with curr.*/
-#define        PL_I_ANY        (0<<11)         /* Int. on any change in *_LINE_ST */
-#define        PL_I_IDLE       (1<<11)         /* Interrupt on IDLE line state */
-#define        PL_I_HALT       (2<<11)         /* Interrupt on HALT line state */
-#define        PL_I_MASTR      (4<<11)         /* Interrupt on MASTER line state */
-#define        PL_I_QUIET      (8<<11)         /* Interrupt on QUIET line state */
-
-#define        PL_CONFIG_CNTRL 0x8000          /* control over scrub, byp. & loopb.*/
-
-/*
- * PLC control register C (PL_CNTRL_C: log. addr. 0x0a)
- * It contains the scrambling control registers (PLC-S only)
- */
-#define PL_C_CIPHER_ENABLE     (1<<0)  /* enable scrambler */
-#define PL_C_CIPHER_LPBCK      (1<<1)  /* loopback scrambler */
-#define PL_C_SDOFF_ENABLE      (1<<6)  /* enable SDOFF timer */
-#define PL_C_SDON_ENABLE       (1<<7)  /* enable SDON timer */
-#ifdef MOT_ELM
-#define PL_C_FOTOFF_CTRL       (3<<2)  /* FOTOFF timer control */
-#define PL_C_FOTOFF_TIM                (0<<2)  /* FOTOFF use timer for (de)-assert */
-#define PL_C_FOTOFF_INA                (2<<2)  /* FOTOFF forced inactive */
-#define PL_C_FOTOFF_ACT                (3<<2)  /* FOTOFF forced active */
-#define PL_C_FOTOFF_SRCE       (1<<4)  /* FOTOFF source is PCM state != OFF */
-#define        PL_C_RXDATA_EN          (1<<5)  /* Rec scr data forced to 0 */
-#define        PL_C_SDNRZEN            (1<<8)  /* Monitor rec descr. data for act */
-#else  /* nMOT_ELM */
-#define PL_C_FOTOFF_CTRL       (3<<8)  /* FOTOFF timer control */
-#define PL_C_FOTOFF_0          (0<<8)  /* timer off */
-#define PL_C_FOTOFF_30         (1<<8)  /* 30uS */
-#define PL_C_FOTOFF_50         (2<<8)  /* 50uS */
-#define PL_C_FOTOFF_NEVER      (3<<8)  /* never */
-#define PL_C_SDON_TIMER                (3<<10) /* SDON timer control */
-#define PL_C_SDON_084          (0<<10) /* 0.84 uS */
-#define PL_C_SDON_132          (1<<10) /* 1.32 uS */
-#define PL_C_SDON_252          (2<<10) /* 2.52 uS */
-#define PL_C_SDON_512          (3<<10) /* 5.12 uS */
-#define PL_C_SOFF_TIMER                (3<<12) /* SDOFF timer control */
-#define PL_C_SOFF_076          (0<<12) /* 0.76 uS */
-#define PL_C_SOFF_132          (1<<12) /* 1.32 uS */
-#define PL_C_SOFF_252          (2<<12) /* 2.52 uS */
-#define PL_C_SOFF_512          (3<<12) /* 5.12 uS */
-#define PL_C_TSEL              (3<<14) /* scrambler path select */
-#endif /* nMOT_ELM */
-
-/*
- * PLC status register A (PL_STATUS_A: log. addr. 0x10)
- * It is used to report status information to the Node Processor about the 
- * Line State Machine (LSM).
- */
-#ifdef MOT_ELM
-#define PLC_INT_MASK   0xc000          /* ELM integration bits in status A */
-#define PLC_INT_C      0x0000          /* ELM Revision Band C */
-#define PLC_INT_CAMEL  0x4000          /* ELM integrated into CAMEL */
-#define PLC_INT_QE     0x8000          /* ELM integrated into Quad ELM */
-#define PLC_REV_MASK   0x3800          /* revision bits in status A */
-#define PLC_REVISION_B 0x0000          /* rev bits for ELM Rev B */
-#define PLC_REVISION_QA        0x0800          /* rev bits for ELM core in QELM-A */
-#else  /* nMOT_ELM */
-#define PLC_REV_MASK   0xf800          /* revision bits in status A */
-#define PLC_REVISION_A 0x0000          /* revision bits for PLC */
-#define PLC_REVISION_S 0xf800          /* revision bits for PLC-S */
-#define PLC_REV_SN3    0x7800          /* revision bits for PLC-S in IFCP */
-#endif /* nMOT_ELM */
-#define        PL_SYM_PR_CTR   0x0007          /* contains the LSM symbol pair Ctr. */
-#define        PL_UNKN_LINE_ST 0x0008          /* unknown line state bit from LSM */
-#define        PL_LSM_STATE    0x0010          /* state bit of LSM */
-
-#define        PL_LINE_ST      0x00e0          /* contains recogn. line state of LSM*/
-#define        PL_L_NLS        (0<<5)          /* noise line state */
-#define        PL_L_ALS        (1<<5)          /* activ line state */
-#define        PL_L_UND        (2<<5)          /* undefined */
-#define        PL_L_ILS4       (3<<5)          /* idle l. s. (after 4 idle symbols) */
-#define        PL_L_QLS        (4<<5)          /* quiet line state */
-#define        PL_L_MLS        (5<<5)          /* master line state */
-#define        PL_L_HLS        (6<<5)          /* halt line state */
-#define        PL_L_ILS16      (7<<5)          /* idle line state (after 16 idle s.)*/
-
-#define        PL_PREV_LINE_ST 0x0300          /* value of previous line state */
-#define        PL_P_QLS        (0<<8)          /* quiet line state */
-#define        PL_P_MLS        (1<<8)          /* master line state */
-#define        PL_P_HLS        (2<<8)          /* halt line state */
-#define        PL_P_ILS16      (3<<8)          /* idle line state (after 16 idle s.)*/
-
-#define        PL_SIGNAL_DET   0x0400          /* 1=that signal detect is deasserted*/
-
-
-/*
- * PLC status register B (PL_STATUS_B: log. addr. 0x11)
- * It contains signals and status from the repeat filter and PCM state machine.
- */
-#define        PL_BREAK_REASON 0x0007          /* reason for PCM state mach.s to br.*/
-#define        PL_B_NOT        (0)             /* PCM SM has not gone to BREAK state*/
-#define        PL_B_PCS        (1)             /* PC_Start issued */
-#define        PL_B_TPC        (2)             /* TPC timer expired after T_OUT */
-#define        PL_B_TNE        (3)             /* TNE timer expired after NS_MAX */
-#define        PL_B_QLS        (4)             /* quit line state detected */
-#define        PL_B_ILS        (5)             /* idle line state detected */
-#define        PL_B_HLS        (6)             /* halt line state detected */
-
-#define        PL_TCF          0x0008          /* transmit code flag (start exec.) */
-#define        PL_RCF          0x0010          /* receive code flag (start exec.) */
-#define        PL_LSF          0x0020          /* line state flag (l.s. has been r.)*/
-#define        PL_PCM_SIGNAL   0x0040          /* indic. that XMIT_VECTOR hb.written*/
-
-#define        PL_PCM_STATE    0x0780          /* state bits of PCM state machine */
-#define        PL_PC0          (0<<7)          /* OFF     - when /RST or PCM_CNTRL */
-#define        PL_PC1          (1<<7)          /* BREAK   - entry point in start PCM*/
-#define        PL_PC2          (2<<7)          /* TRACE   - to localize stuck Beacon*/
-#define        PL_PC3          (3<<7)          /* CONNECT - synchronize ends of conn*/
-#define        PL_PC4          (4<<7)          /* NEXT    - to separate the signalng*/
-#define        PL_PC5          (5<<7)          /* SIGNAL  - PCM trans/rec. bit infos*/
-#define        PL_PC6          (6<<7)          /* JOIN    - 1. state to activ conn. */
-#define        PL_PC7          (7<<7)          /* VERIFY  - 2. - " - (3. ACTIVE) */
-#define        PL_PC8          (8<<7)          /* ACTIVE  - PHY has been incorporated*/
-#define        PL_PC9          (9<<7)          /* MAINT   - for test purposes or so 
-                                          that PCM op. completely in softw. */
-
-#define        PL_PCI_SCRUB    0x0800          /* scrubbing function is being exec. */
-
-#define        PL_PCI_STATE    0x3000          /* Physical Connect. Insertion SM */
-#define        PL_CI_REMV      (0<<12)         /* REMOVED */
-#define        PL_CI_ISCR      (1<<12)         /* INSERT_SCRUB */
-#define        PL_CI_RSCR      (2<<12)         /* REMOVE_SCRUB */
-#define        PL_CI_INS       (3<<12)         /* INSERTED */
-
-#define        PL_RF_STATE     0xc000          /* state bit of repeate filter SM */
-#define        PL_RF_REPT      (0<<14)         /* REPEAT */
-#define        PL_RF_IDLE      (1<<14)         /* IDLE */
-#define        PL_RF_HALT1     (2<<14)         /* HALT1 */
-#define        PL_RF_HALT2     (3<<14)         /* HALT2 */
-
-
-/*
- * PLC interrupt event register (PL_INTR_EVENT: log. addr. 0x17)
- * It is read only and is clearde whenever it is read!
- * It is used by the PLC to report events to the node processor.
- */
-#define        PL_PARITY_ERR   0x0001          /* p. error h.b.detected on TX9-0 inp*/
-#define        PL_LS_MATCH     0x0002          /* l.s.== l.s. PLC_CNTRL_B's MATCH_LS*/
-#define        PL_PCM_CODE     0x0004          /* transmit&receive | LCT complete */
-#define        PL_TRACE_PROP   0x0008          /* master l.s. while PCM ACTIV|TRACE */
-#define        PL_SELF_TEST    0x0010          /* QUIET|HALT while PCM in TRACE st. */
-#define        PL_PCM_BREAK    0x0020          /* PCM has entered the BREAK state */
-#define        PL_PCM_ENABLED  0x0040          /* asserted SC_JOIN, scrub. & ACTIV */
-#define        PL_TPC_EXPIRED  0x0080          /* TPC timer reached zero */
-#define        PL_TNE_EXPIRED  0x0100          /* TNE timer reached zero */
-#define        PL_EBUF_ERR     0x0200          /* elastic buff. det. over-|underflow*/
-#define        PL_PHYINV       0x0400          /* physical layer invalid signal */
-#define        PL_VSYM_CTR     0x0800          /* violation symbol counter has incr.*/
-#define        PL_MINI_CTR     0x1000          /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
-#define        PL_LE_CTR       0x2000          /* link error event counter */
-#define        PL_LSDO         0x4000          /* SDO input pin changed to a 1 */
-#define        PL_NP_ERR       0x8000          /* NP has requested to r/w an inv. r.*/
-
-/*
- * The PLC interrupt mask register (PL_INTR_MASK: log. addr. 0x02) constr. is
- * equal PL_INTR_EVENT register.
- * For each set bit, the setting of corresponding bit generate an int to NP. 
- */
-
-#ifdef MOT_ELM
-/*
- * Quad ELM Crosbar Control register values (QELM_XBAR_?)
- */
-#define        QELM_XOUT_IDLE  0x0000          /* Idles/Passthrough */
-#define        QELM_XOUT_P     0x0001          /* Output to: Bus P */
-#define        QELM_XOUT_S     0x0002          /* Output to: Bus S */
-#define        QELM_XOUT_R     0x0003          /* Output to: Bus R */
-#define        QELM_XOUT_W     0x0004          /* Output to: ELM W */
-#define        QELM_XOUT_X     0x0005          /* Output to: ELM X */
-#define        QELM_XOUT_Y     0x0006          /* Output to: ELM Y */
-#define        QELM_XOUT_Z     0x0007          /* Output to: ELM Z */
-
-/*
- * Quad ELM Interrupt data and event registers.
- */
-#define        QELM_NP_ERR     (1<<15)         /* Node Processor Error */
-#define        QELM_COUNT_Z    (1<<7)          /* Counter Z Interrupt */
-#define        QELM_COUNT_Y    (1<<6)          /* Counter Y Interrupt */
-#define        QELM_COUNT_X    (1<<5)          /* Counter X Interrupt */
-#define        QELM_COUNT_W    (1<<4)          /* Counter W Interrupt */
-#define        QELM_ELM_Z      (1<<3)          /* ELM Z Interrupt */
-#define        QELM_ELM_Y      (1<<2)          /* ELM Y Interrupt */
-#define        QELM_ELM_X      (1<<1)          /* ELM X Interrupt */
-#define        QELM_ELM_W      (1<<0)          /* ELM W Interrupt */
-#endif /* MOT_ELM */
-/*
- * PLC Timing Parameters
- */
-#define        TP_C_MIN        0xff9c  /*   2    ms */
-#define        TP_TL_MIN       0xfff0  /*   0.3  ms */
-#define        TP_TB_MIN       0xff10  /*   5    ms */
-#define        TP_T_OUT        0xd9db  /* 200    ms */
-#define        TP_LC_LENGTH    0xf676  /*  50    ms */
-#define        TP_LC_LONGLN    0xa0a2  /* 500    ms */
-#define        TP_T_SCRUB      0xff6d  /*   3.5  ms */
-#define        TP_NS_MAX       0xf021  /*   1.3   ms */
-
-/*
- * BIST values
- */
-#define PLC_BIST       0x6ecd          /* BIST signature for PLC */
-#define PLCS_BIST      0x5b6b          /* BIST signature for PLC-S */
-#define        PLC_ELM_B_BIST  0x6ecd          /* BIST signature of ELM Rev. B */
-#define        PLC_ELM_D_BIST  0x5b6b          /* BIST signature of ELM Rev. D */
-#define        PLC_CAM_A_BIST  0x9e75          /* BIST signature of CAMEL Rev. A */
-#define        PLC_CAM_B_BIST  0x5b6b          /* BIST signature of CAMEL Rev. B */
-#define        PLC_IFD_A_BIST  0x9e75          /* BIST signature of IFDDI Rev. A */
-#define        PLC_IFD_B_BIST  0x5b6b          /* BIST signature of IFDDI Rev. B */
-#define        PLC_QELM_A_BIST 0x5b6b          /* BIST signature of QELM Rev. A */
-
-/*
-       FDDI board recources    
- */
-
-/*
- * request register array (log. addr: RQA_A + a<<1 {a=0..7}) write only.
- * It specifies to FORMAC+ the type of buffer memory access the host requires.
- */
-#define        RQ_NOT          0               /* not request */
-#define        RQ_RES          1               /* reserved */
-#define        RQ_SFW          2               /* special frame write */
-#define        RQ_RRQ          3               /* read request: receive queue */
-#define        RQ_WSQ          4               /* write request: synchronous queue */
-#define        RQ_WA0          5               /* write requ.: asynchronous queue 0 */
-#define        RQ_WA1          6               /* write requ.: asynchronous queue 1 */
-#define        RQ_WA2          7               /* write requ.: asynchronous queue 2 */
-
-#define        SZ_LONG         (sizeof(long))
-
-/*
- * FDDI defaults
- * NOTE : In the ANSI docs, times are specified in units of "symbol time".
- *       AMD chips use BCLK as unit. 1 BCKL == 2 symbols
- */
-#define        COMPLREF        ((u_long)32*256*256)    /* two's complement 21 bit */
-#define MSTOBCLK(x)    ((u_long)(x)*12500L)
-#define MSTOTVX(x)     (((u_long)(x)*1000L)/80/255)
-
-#endif /* _SUPERNET_ */
diff --git a/drivers/net/skfp/h/targethw.h b/drivers/net/skfp/h/targethw.h
deleted file mode 100644 (file)
index 626dc72..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        _TARGETHW_
-#define _TARGETHW_
-
-       /*
-        *  PCI Watermark definition
-        */
-#ifdef PCI
-#define        RX_WATERMARK    24
-#define TX_WATERMARK   24
-#define SK_ML_ID_1     0x20
-#define SK_ML_ID_2     0x30
-#endif
-
-#include       "h/skfbi.h"
-#ifndef TAG_MODE       
-#include       "h/fplus.h"
-#else
-#include       "h/fplustm.h"
-#endif
-
-#ifndef        HW_PTR
-#define HW_PTR  void __iomem *
-#endif
-
-#ifdef MULT_OEM
-#define        OI_STAT_LAST            0       /* end of OEM data base */
-#define        OI_STAT_PRESENT         1       /* entry present but not empty */
-#define        OI_STAT_VALID           2       /* holds valid ID, but is not active */ 
-#define        OI_STAT_ACTIVE          3       /* holds valid ID, entry is active */
-                                       /* active = adapter is supported */
-
-/* Memory representation of IDs must match representation in adapter. */
-struct s_oem_ids {
-       u_char  oi_status ;             /* Stat: last, present, valid, active */
-       u_char  oi_mark[5] ;            /* "PID00" .. "PID07" ..        */
-       u_char  oi_id[4] ;              /* id bytes, representation as  */
-                                       /* defined by hardware,         */      
-#ifdef PCI
-       u_char  oi_sub_id[4] ;          /* sub id bytes, representation as */
-                                       /* defined by hardware,         */
-#endif
-} ;
-#endif /* MULT_OEM */
-
-
-struct s_smt_hw {
-       /*
-        * global
-        */
-       HW_PTR  iop ;                   /* IO base address */
-       short   dma ;                   /* DMA channel */
-       short   irq ;                   /* IRQ level */
-       short   eprom ;                 /* FLASH prom */
-
-#ifndef SYNC
-       u_short n_a_send ;              /* pending send requests */
-#endif
-
-#if    defined(PCI)
-       short   slot ;                  /* slot number */
-       short   max_slots ;             /* maximum number of slots */
-       short   wdog_used ;             /* TRUE if the watch dog is used */
-#endif
-
-#ifdef PCI
-       u_short pci_handle ;            /* handle to access the BIOS func */
-       u_long  is_imask ;              /* int maske for the int source reg */
-       u_long  phys_mem_addr ;         /* physical memory address */
-       u_short mc_dummy ;              /* work around for MC compiler bug */   
-       /*
-        * state of the hardware
-        */
-       u_short hw_state ;              /* started or stopped */
-
-#define        STARTED         1
-#define        STOPPED         0
-
-       int     hw_is_64bit ;           /* does we have a 64 bit adapter */
-#endif
-
-#ifdef TAG_MODE
-       u_long  pci_fix_value ;         /* value parsed by PCIFIX */
-#endif
-
-       /*
-        * hwt.c
-        */
-       u_long  t_start ;               /* HWT start */
-       u_long  t_stop ;                /* HWT stop */
-       u_short timer_activ ;           /* HWT timer active */
-
-       /*
-        * PIC
-        */
-       u_char  pic_a1 ;
-       u_char  pic_21 ;
-
-       /*
-        * GENERIC ; do not modify beyond this line
-        */
-
-       /*
-        * physical and canonical address
-        */
-       struct fddi_addr fddi_home_addr ;
-       struct fddi_addr fddi_canon_addr ;
-       struct fddi_addr fddi_phys_addr ;
-
-       /*
-        * mac variables
-        */
-       struct mac_parameter mac_pa ;   /* tmin, tmax, tvx, treq .. */
-       struct mac_counter mac_ct ;     /* recv., lost, error  */
-       u_short mac_ring_is_up ;        /* ring is up flag */
-
-       struct s_smt_fp fp ;            /* formac+ */
-
-#ifdef MULT_OEM
-       struct s_oem_ids *oem_id ;      /* pointer to selected id */
-       int oem_min_status ;            /* IDs to take care of */
-#endif /* MULT_OEM */
-
-} ;
-#endif
diff --git a/drivers/net/skfp/h/targetos.h b/drivers/net/skfp/h/targetos.h
deleted file mode 100644 (file)
index 5d940e7..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- *     Operating system specific definitions for driver and
- *     hardware module.
- */
-
-#ifndef        TARGETOS_H
-#define TARGETOS_H
-
-
-//-------- those should go into include/linux/pci.h
-#define PCI_VENDOR_ID_SK               0x1148
-#define PCI_DEVICE_ID_SK_FP            0x4000
-//--------
-
-
-
-//-------- those should go into include/linux/if_fddi.h
-#define FDDI_MAC_HDR_LEN 13
-
-#define FDDI_RII       0x01 /* routing information bit */
-#define FDDI_RCF_DIR_BIT 0x80
-#define FDDI_RCF_LEN_MASK 0x1f
-#define FDDI_RCF_BROADCAST 0x8000
-#define FDDI_RCF_LIMITED_BROADCAST 0xA000
-#define FDDI_RCF_FRAME2K 0x20
-#define FDDI_RCF_FRAME4K 0x30
-//--------
-
-
-#undef ADDR
-
-#include <asm/io.h>
-#include <linux/netdevice.h>
-#include <linux/fddidevice.h>
-#include <linux/skbuff.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-// is redefined by linux, but we need our definition
-#undef ADDR
-#ifdef MEM_MAPPED_IO
-#define        ADDR(a) (smc->hw.iop+(a))
-#else
-#define        ADDR(a) (((a)>>7) ? (outp(smc->hw.iop+B0_RAP,(a)>>7), (smc->hw.iop+( ((a)&0x7F) | ((a)>>7 ? 0x80:0)) )) : (smc->hw.iop+(((a)&0x7F)|((a)>>7 ? 0x80:0))))
-#endif
-
-#include "h/hwmtm.h"
-
-#define TRUE  1
-#define FALSE 0
-
-// HWM Definitions
-// -----------------------
-#define FDDI_TRACE(string, arg1, arg2, arg3)   // Performance analysis.
-#ifdef PCI
-#define NDD_TRACE(string, arg1, arg2, arg3)    // Performance analysis.
-#endif // PCI
-#define SMT_PAGESIZE   PAGE_SIZE       // Size of a memory page (power of 2).
-// -----------------------
-
-
-// SMT Definitions
-// -----------------------
-#define        TICKS_PER_SECOND        HZ
-#define SMC_VERSION                    1
-// -----------------------
-
-
-// OS-Driver Definitions
-// -----------------------
-#define NO_ADDRESS 0xffe0      /* No Device (I/O) Address */
-#define SKFP_MAX_NUM_BOARDS 8  /* maximum number of PCI boards */
-
-#define SK_BUS_TYPE_PCI                0
-#define SK_BUS_TYPE_EISA       1
-
-#define FP_IO_LEN              256     /* length of IO area used */
-
-#define u8     unsigned char
-#define u16    unsigned short
-#define u32    unsigned int
-
-#define MAX_TX_QUEUE_LEN       20 // number of packets queued by driver
-#define MAX_FRAME_SIZE         4550
-
-#define        RX_LOW_WATERMARK        NUM_RECEIVE_BUFFERS  / 2
-#define TX_LOW_WATERMARK       NUM_TRANSMIT_BUFFERS - 2
-
-/*
-** Include the IOCTL stuff
-*/
-#include <linux/sockios.h>
-
-#define        SKFPIOCTL       SIOCDEVPRIVATE
-
-struct s_skfp_ioctl {
-       unsigned short cmd;                /* Command to run */
-       unsigned short len;                /* Length of the data buffer */
-       unsigned char __user *data;        /* Pointer to the data buffer */
-};
-
-/* 
-** Recognised ioctl commands for the driver 
-*/
-#define SKFP_GET_STATS         0x05 /* Get the driver statistics */
-#define SKFP_CLR_STATS         0x06 /* Zero out the driver statistics */
-
-// The per-adapter driver structure
-struct s_smt_os {
-       struct net_device *dev;
-       struct net_device *next_module;
-       u32     bus_type;               /* bus type (0 == PCI, 1 == EISA) */
-       struct pci_dev  pdev;           /* PCI device structure */
-       
-       unsigned long base_addr;
-       unsigned char factory_mac_addr[8];
-       ulong   SharedMemSize;
-       ulong   SharedMemHeap;
-       void*   SharedMemAddr;
-       dma_addr_t SharedMemDMA;
-
-       ulong   QueueSkb;
-       struct  sk_buff_head SendSkbQueue;
-
-       ulong   MaxFrameSize;
-       u8      ResetRequested;
-
-       // MAC statistics structure
-       struct fddi_statistics MacStat;
-
-       // receive into this local buffer if no skb available
-       // data will be not valid, because multiple RxDs can
-       // point here at the same time, it must be at least
-       // MAX_FRAME_SIZE bytes in size
-       unsigned char *LocalRxBuffer;
-       dma_addr_t LocalRxBufferDMA;
-       
-       // Version (required by SMT module).
-       u_long smc_version ;
-
-       // Required by Hardware Module (HWM).
-       struct hw_modul hwm ;
-       
-       // For SMP-savety
-       spinlock_t DriverLock;
-       
-};
-
-typedef struct s_smt_os skfddi_priv;
-
-#endif  // _TARGETOS_
diff --git a/drivers/net/skfp/h/types.h b/drivers/net/skfp/h/types.h
deleted file mode 100644 (file)
index 5a3bf83..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include       <linux/types.h>
-/*
-       ----------------------
-       Basic SMT system types
-       ----------------------
-*/
-#ifndef _TYPES_
-#define        _TYPES_
-
-#define _packed
-#ifndef far
-#define far
-#endif
-#ifndef _far
-#define _far
-#endif
-
-#define inp(p)  ioread8(p)
-#define inpw(p)        ioread16(p)
-#define inpd(p) ioread32(p)
-#define outp(p,c)  iowrite8(c,p)
-#define outpw(p,s) iowrite16(s,p)
-#define outpd(p,l) iowrite32(l,p)
-
-#endif /* _TYPES_ */
diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
deleted file mode 100644 (file)
index e26398b..0000000
+++ /dev/null
@@ -1,2178 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef        lint
-static char const ID_sccs[] = "@(#)hwmtm.c     1.40 99/05/31 (C) SK" ;
-#endif
-
-#define        HWMTM
-
-#ifndef FDDI
-#define        FDDI
-#endif
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/supern_2.h"
-#include "h/skfbiinc.h"
-
-/*
-       -------------------------------------------------------------
-       DOCUMENTATION
-       -------------------------------------------------------------
-       BEGIN_MANUAL_ENTRY(DOCUMENTATION)
-
-                       T B D
-
-       END_MANUAL_ENTRY
-*/
-/*
-       -------------------------------------------------------------
-       LOCAL VARIABLES:
-       -------------------------------------------------------------
-*/
-#ifdef COMMON_MB_POOL
-static SMbuf *mb_start = 0 ;
-static SMbuf *mb_free = 0 ;
-static int mb_init = FALSE ;
-static int call_count = 0 ;
-#endif
-
-/*
-       -------------------------------------------------------------
-       EXTERNE VARIABLES:
-       -------------------------------------------------------------
-*/
-
-#ifdef DEBUG
-#ifndef        DEBUG_BRD
-extern struct smt_debug        debug ;
-#endif
-#endif
-
-#ifdef NDIS_OS2
-extern u_char  offDepth ;
-extern u_char  force_irq_pending ;
-#endif
-
-/*
-       -------------------------------------------------------------
-       LOCAL FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-static void queue_llc_rx(struct s_smc *smc, SMbuf *mb);
-static void smt_to_llc(struct s_smc *smc, SMbuf *mb);
-static void init_txd_ring(struct s_smc *smc);
-static void init_rxd_ring(struct s_smc *smc);
-static void queue_txd_mb(struct s_smc *smc, SMbuf *mb);
-static u_long init_descr_ring(struct s_smc *smc, union s_fp_descr volatile *start,
-                             int count);
-static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue);
-static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue);
-static SMbuf* get_llc_rx(struct s_smc *smc);
-static SMbuf* get_txd_mb(struct s_smc *smc);
-static void mac_drv_clear_txd(struct s_smc *smc);
-
-/*
-       -------------------------------------------------------------
-       EXTERNAL FUNCTIONS:
-       -------------------------------------------------------------
-*/
-/*     The external SMT functions are listed in cmtdef.h */
-
-extern void* mac_drv_get_space(struct s_smc *smc, unsigned int size);
-extern void* mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size);
-extern void mac_drv_fill_rxd(struct s_smc *smc);
-extern void mac_drv_tx_complete(struct s_smc *smc,
-                               volatile struct s_smt_fp_txd *txd);
-extern void mac_drv_rx_complete(struct s_smc *smc,
-                               volatile struct s_smt_fp_rxd *rxd,
-                               int frag_count, int len);
-extern void mac_drv_requeue_rxd(struct s_smc *smc, 
-                               volatile struct s_smt_fp_rxd *rxd,
-                               int frag_count);
-extern void mac_drv_clear_rxd(struct s_smc *smc,
-                             volatile struct s_smt_fp_rxd *rxd, int frag_count);
-
-#ifdef USE_OS_CPY
-extern void hwm_cpy_rxd2mb(void);
-extern void hwm_cpy_txd2mb(void);
-#endif
-
-#ifdef ALL_RX_COMPLETE
-extern void mac_drv_all_receives_complete(void);
-#endif
-
-extern u_long mac_drv_virt2phys(struct s_smc *smc, void *virt);
-extern u_long dma_master(struct s_smc *smc, void *virt, int len, int flag);
-
-#ifdef NDIS_OS2
-extern void post_proc(void);
-#else
-extern void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
-                        int flag);
-#endif
-
-extern int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
-                          int la_len);
-
-/*
-       -------------------------------------------------------------
-       PUBLIC FUNCTIONS:
-       -------------------------------------------------------------
-*/
-void process_receive(struct s_smc *smc);
-void fddi_isr(struct s_smc *smc);
-void smt_free_mbuf(struct s_smc *smc, SMbuf *mb);
-void init_driver_fplus(struct s_smc *smc);
-void mac_drv_rx_mode(struct s_smc *smc, int mode);
-void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
-void mac_drv_clear_tx_queue(struct s_smc *smc);
-void mac_drv_clear_rx_queue(struct s_smc *smc);
-void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
-                int frame_status);
-void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
-                int frame_status);
-
-int mac_drv_init(struct s_smc *smc);
-int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
-               int frame_status);
-
-u_int mac_drv_check_space(void);
-
-SMbuf* smt_get_mbuf(struct s_smc *smc);
-
-#ifdef DEBUG
-       void mac_drv_debug_lev(void);
-#endif
-
-/*
-       -------------------------------------------------------------
-       MACROS:
-       -------------------------------------------------------------
-*/
-#ifndef        UNUSED
-#ifdef lint
-#define UNUSED(x)      (x) = (x)
-#else
-#define UNUSED(x)
-#endif
-#endif
-
-#ifdef USE_CAN_ADDR
-#define MA             smc->hw.fddi_canon_addr.a
-#define        GROUP_ADDR_BIT  0x01
-#else
-#define        MA              smc->hw.fddi_home_addr.a
-#define        GROUP_ADDR_BIT  0x80
-#endif
-
-#define RXD_TXD_COUNT  (HWM_ASYNC_TXD_COUNT+HWM_SYNC_TXD_COUNT+\
-                       SMT_R1_RXD_COUNT+SMT_R2_RXD_COUNT)
-
-#ifdef MB_OUTSIDE_SMC
-#define        EXT_VIRT_MEM    ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd) +\
-                       MAX_MBUF*sizeof(SMbuf))
-#define        EXT_VIRT_MEM_2  ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
-#else
-#define        EXT_VIRT_MEM    ((RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd))
-#endif
-
-       /*
-        * define critical read for 16 Bit drivers
-        */
-#if    defined(NDIS_OS2) || defined(ODI2)
-#define CR_READ(var)   ((var) & 0xffff0000 | ((var) & 0xffff))
-#else
-#define CR_READ(var)   (__le32)(var)
-#endif
-
-#define IMASK_SLOW     (IS_PLINT1 | IS_PLINT2 | IS_TIMINT | IS_TOKEN | \
-                        IS_MINTR1 | IS_MINTR2 | IS_MINTR3 | IS_R1_P | \
-                        IS_R1_C | IS_XA_C | IS_XS_C)
-
-/*
-       -------------------------------------------------------------
-       INIT- AND SMT FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-
-/*
- *     BEGIN_MANUAL_ENTRY(mac_drv_check_space)
- *     u_int mac_drv_check_space()
- *
- *     function        DOWNCALL        (drvsr.c)
- *                     This function calculates the needed non virtual
- *                     memory for MBufs, RxD and TxD descriptors etc.
- *                     needed by the driver.
- *
- *     return          u_int   memory in bytes
- *
- *     END_MANUAL_ENTRY
- */
-u_int mac_drv_check_space(void)
-{
-#ifdef MB_OUTSIDE_SMC
-#ifdef COMMON_MB_POOL
-       call_count++ ;
-       if (call_count == 1) {
-               return EXT_VIRT_MEM;
-       }
-       else {
-               return EXT_VIRT_MEM_2;
-       }
-#else
-       return EXT_VIRT_MEM;
-#endif
-#else
-       return 0;
-#endif
-}
-
-/*
- *     BEGIN_MANUAL_ENTRY(mac_drv_init)
- *     void mac_drv_init(smc)
- *
- *     function        DOWNCALL        (drvsr.c)
- *                     In this function the hardware module allocates it's
- *                     memory.
- *                     The operating system dependent module should call
- *                     mac_drv_init once, after the adatper is detected.
- *     END_MANUAL_ENTRY
- */
-int mac_drv_init(struct s_smc *smc)
-{
-       if (sizeof(struct s_smt_fp_rxd) % 16) {
-               SMT_PANIC(smc,HWM_E0001,HWM_E0001_MSG) ;
-       }
-       if (sizeof(struct s_smt_fp_txd) % 16) {
-               SMT_PANIC(smc,HWM_E0002,HWM_E0002_MSG) ;
-       }
-
-       /*
-        * get the required memory for the RxDs and TxDs
-        */
-       if (!(smc->os.hwm.descr_p = (union s_fp_descr volatile *)
-               mac_drv_get_desc_mem(smc,(u_int)
-               (RXD_TXD_COUNT+1)*sizeof(struct s_smt_fp_txd)))) {
-               return 1;       /* no space the hwm modul can't work */
-       }
-
-       /*
-        * get the memory for the SMT MBufs
-        */
-#ifndef        MB_OUTSIDE_SMC
-       smc->os.hwm.mbuf_pool.mb_start=(SMbuf *)(&smc->os.hwm.mbuf_pool.mb[0]) ;
-#else
-#ifndef        COMMON_MB_POOL
-       if (!(smc->os.hwm.mbuf_pool.mb_start = (SMbuf *) mac_drv_get_space(smc,
-               MAX_MBUF*sizeof(SMbuf)))) {
-               return 1;       /* no space the hwm modul can't work */
-       }
-#else
-       if (!mb_start) {
-               if (!(mb_start = (SMbuf *) mac_drv_get_space(smc,
-                       MAX_MBUF*sizeof(SMbuf)))) {
-                       return 1;       /* no space the hwm modul can't work */
-               }
-       }
-#endif
-#endif
-       return 0;
-}
-
-/*
- *     BEGIN_MANUAL_ENTRY(init_driver_fplus)
- *     init_driver_fplus(smc)
- *
- * Sets hardware modul specific values for the mode register 2
- * (e.g. the byte alignment for the received frames, the position of the
- *      least significant byte etc.)
- *     END_MANUAL_ENTRY
- */
-void init_driver_fplus(struct s_smc *smc)
-{
-       smc->hw.fp.mdr2init = FM_LSB | FM_BMMODE | FM_ENNPRQ | FM_ENHSRQ | 3 ;
-
-#ifdef PCI
-       smc->hw.fp.mdr2init |= FM_CHKPAR | FM_PARITY ;
-#endif
-       smc->hw.fp.mdr3init = FM_MENRQAUNLCK | FM_MENRS ;
-
-#ifdef USE_CAN_ADDR
-       /* enable address bit swapping */
-       smc->hw.fp.frselreg_init = FM_ENXMTADSWAP | FM_ENRCVADSWAP ;
-#endif
-}
-
-static u_long init_descr_ring(struct s_smc *smc,
-                             union s_fp_descr volatile *start,
-                             int count)
-{
-       int i ;
-       union s_fp_descr volatile *d1 ;
-       union s_fp_descr volatile *d2 ;
-       u_long  phys ;
-
-       DB_GEN("descr ring starts at = %x ",(void *)start,0,3) ;
-       for (i=count-1, d1=start; i ; i--) {
-               d2 = d1 ;
-               d1++ ;          /* descr is owned by the host */
-               d2->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
-               d2->r.rxd_next = &d1->r ;
-               phys = mac_drv_virt2phys(smc,(void *)d1) ;
-               d2->r.rxd_nrdadr = cpu_to_le32(phys) ;
-       }
-       DB_GEN("descr ring ends at = %x ",(void *)d1,0,3) ;
-       d1->r.rxd_rbctrl = cpu_to_le32(BMU_CHECK) ;
-       d1->r.rxd_next = &start->r ;
-       phys = mac_drv_virt2phys(smc,(void *)start) ;
-       d1->r.rxd_nrdadr = cpu_to_le32(phys) ;
-
-       for (i=count, d1=start; i ; i--) {
-               DRV_BUF_FLUSH(&d1->r,DDI_DMA_SYNC_FORDEV) ;
-               d1++;
-       }
-       return phys;
-}
-
-static void init_txd_ring(struct s_smc *smc)
-{
-       struct s_smt_fp_txd volatile *ds ;
-       struct s_smt_tx_queue *queue ;
-       u_long  phys ;
-
-       /*
-        * initialize the transmit descriptors
-        */
-       ds = (struct s_smt_fp_txd volatile *) ((char *)smc->os.hwm.descr_p +
-               SMT_R1_RXD_COUNT*sizeof(struct s_smt_fp_rxd)) ;
-       queue = smc->hw.fp.tx[QUEUE_A0] ;
-       DB_GEN("Init async TxD ring, %d TxDs ",HWM_ASYNC_TXD_COUNT,0,3) ;
-       (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
-               HWM_ASYNC_TXD_COUNT) ;
-       phys = le32_to_cpu(ds->txd_ntdadr) ;
-       ds++ ;
-       queue->tx_curr_put = queue->tx_curr_get = ds ;
-       ds-- ;
-       queue->tx_free = HWM_ASYNC_TXD_COUNT ;
-       queue->tx_used = 0 ;
-       outpd(ADDR(B5_XA_DA),phys) ;
-
-       ds = (struct s_smt_fp_txd volatile *) ((char *)ds +
-               HWM_ASYNC_TXD_COUNT*sizeof(struct s_smt_fp_txd)) ;
-       queue = smc->hw.fp.tx[QUEUE_S] ;
-       DB_GEN("Init sync TxD ring, %d TxDs ",HWM_SYNC_TXD_COUNT,0,3) ;
-       (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
-               HWM_SYNC_TXD_COUNT) ;
-       phys = le32_to_cpu(ds->txd_ntdadr) ;
-       ds++ ;
-       queue->tx_curr_put = queue->tx_curr_get = ds ;
-       queue->tx_free = HWM_SYNC_TXD_COUNT ;
-       queue->tx_used = 0 ;
-       outpd(ADDR(B5_XS_DA),phys) ;
-}
-
-static void init_rxd_ring(struct s_smc *smc)
-{
-       struct s_smt_fp_rxd volatile *ds ;
-       struct s_smt_rx_queue *queue ;
-       u_long  phys ;
-
-       /*
-        * initialize the receive descriptors
-        */
-       ds = (struct s_smt_fp_rxd volatile *) smc->os.hwm.descr_p ;
-       queue = smc->hw.fp.rx[QUEUE_R1] ;
-       DB_GEN("Init RxD ring, %d RxDs ",SMT_R1_RXD_COUNT,0,3) ;
-       (void)init_descr_ring(smc,(union s_fp_descr volatile *)ds,
-               SMT_R1_RXD_COUNT) ;
-       phys = le32_to_cpu(ds->rxd_nrdadr) ;
-       ds++ ;
-       queue->rx_curr_put = queue->rx_curr_get = ds ;
-       queue->rx_free = SMT_R1_RXD_COUNT ;
-       queue->rx_used = 0 ;
-       outpd(ADDR(B4_R1_DA),phys) ;
-}
-
-/*
- *     BEGIN_MANUAL_ENTRY(init_fddi_driver)
- *     void init_fddi_driver(smc,mac_addr)
- *
- * initializes the driver and it's variables
- *
- *     END_MANUAL_ENTRY
- */
-void init_fddi_driver(struct s_smc *smc, u_char *mac_addr)
-{
-       SMbuf   *mb ;
-       int     i ;
-
-       init_board(smc,mac_addr) ;
-       (void)init_fplus(smc) ;
-
-       /*
-        * initialize the SMbufs for the SMT
-        */
-#ifndef        COMMON_MB_POOL
-       mb = smc->os.hwm.mbuf_pool.mb_start ;
-       smc->os.hwm.mbuf_pool.mb_free = (SMbuf *)NULL ;
-       for (i = 0; i < MAX_MBUF; i++) {
-               mb->sm_use_count = 1 ;
-               smt_free_mbuf(smc,mb)   ;
-               mb++ ;
-       }
-#else
-       mb = mb_start ;
-       if (!mb_init) {
-               mb_free = 0 ;
-               for (i = 0; i < MAX_MBUF; i++) {
-                       mb->sm_use_count = 1 ;
-                       smt_free_mbuf(smc,mb)   ;
-                       mb++ ;
-               }
-               mb_init = TRUE ;
-       }
-#endif
-
-       /*
-        * initialize the other variables
-        */
-       smc->os.hwm.llc_rx_pipe = smc->os.hwm.llc_rx_tail = (SMbuf *)NULL ;
-       smc->os.hwm.txd_tx_pipe = smc->os.hwm.txd_tx_tail = NULL ;
-       smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = smc->os.hwm.pass_DB = 0 ;
-       smc->os.hwm.pass_llc_promisc = TRUE ;
-       smc->os.hwm.queued_rx_frames = smc->os.hwm.queued_txd_mb = 0 ;
-       smc->os.hwm.detec_count = 0 ;
-       smc->os.hwm.rx_break = 0 ;
-       smc->os.hwm.rx_len_error = 0 ;
-       smc->os.hwm.isr_flag = FALSE ;
-
-       /*
-        * make sure that the start pointer is 16 byte aligned
-        */
-       i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ;
-       if (i != 16) {
-               DB_GEN("i = %d",i,0,3) ;
-               smc->os.hwm.descr_p = (union s_fp_descr volatile *)
-                       ((char *)smc->os.hwm.descr_p+i) ;
-       }
-       DB_GEN("pt to descr area = %x",(void *)smc->os.hwm.descr_p,0,3) ;
-
-       init_txd_ring(smc) ;
-       init_rxd_ring(smc) ;
-       mac_drv_fill_rxd(smc) ;
-
-       init_plc(smc) ;
-}
-
-
-SMbuf *smt_get_mbuf(struct s_smc *smc)
-{
-       register SMbuf  *mb ;
-
-#ifndef        COMMON_MB_POOL
-       mb = smc->os.hwm.mbuf_pool.mb_free ;
-#else
-       mb = mb_free ;
-#endif
-       if (mb) {
-#ifndef        COMMON_MB_POOL
-               smc->os.hwm.mbuf_pool.mb_free = mb->sm_next ;
-#else
-               mb_free = mb->sm_next ;
-#endif
-               mb->sm_off = 8 ;
-               mb->sm_use_count = 1 ;
-       }
-       DB_GEN("get SMbuf: mb = %x",(void *)mb,0,3) ;
-       return mb;      /* May be NULL */
-}
-
-void smt_free_mbuf(struct s_smc *smc, SMbuf *mb)
-{
-
-       if (mb) {
-               mb->sm_use_count-- ;
-               DB_GEN("free_mbuf: sm_use_count = %d",mb->sm_use_count,0,3) ;
-               /*
-                * If the use_count is != zero the MBuf is queued
-                * more than once and must not queued into the
-                * free MBuf queue
-                */
-               if (!mb->sm_use_count) {
-                       DB_GEN("free SMbuf: mb = %x",(void *)mb,0,3) ;
-#ifndef        COMMON_MB_POOL
-                       mb->sm_next = smc->os.hwm.mbuf_pool.mb_free ;
-                       smc->os.hwm.mbuf_pool.mb_free = mb ;
-#else
-                       mb->sm_next = mb_free ;
-                       mb_free = mb ;
-#endif
-               }
-       }
-       else
-               SMT_PANIC(smc,HWM_E0003,HWM_E0003_MSG) ;
-}
-
-
-/*
- *     BEGIN_MANUAL_ENTRY(mac_drv_repair_descr)
- *     void mac_drv_repair_descr(smc)
- *
- * function    called from SMT (HWM / hwmtm.c)
- *             The BMU is idle when this function is called.
- *             Mac_drv_repair_descr sets up the physical address
- *             for all receive and transmit queues where the BMU
- *             should continue.
- *             It may be that the BMU was reseted during a fragmented
- *             transfer. In this case there are some fragments which will
- *             never completed by the BMU. The OWN bit of this fragments
- *             must be switched to be owned by the host.
- *
- *             Give a start command to the receive BMU.
- *             Start the transmit BMUs if transmit frames pending.
- *
- *     END_MANUAL_ENTRY
- */
-void mac_drv_repair_descr(struct s_smc *smc)
-{
-       u_long  phys ;
-
-       if (smc->hw.hw_state != STOPPED) {
-               SK_BREAK() ;
-               SMT_PANIC(smc,HWM_E0013,HWM_E0013_MSG) ;
-               return ;
-       }
-
-       /*
-        * repair tx queues: don't start
-        */
-       phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_A0]) ;
-       outpd(ADDR(B5_XA_DA),phys) ;
-       if (smc->hw.fp.tx_q[QUEUE_A0].tx_used) {
-               outpd(ADDR(B0_XA_CSR),CSR_START) ;
-       }
-       phys = repair_txd_ring(smc,smc->hw.fp.tx[QUEUE_S]) ;
-       outpd(ADDR(B5_XS_DA),phys) ;
-       if (smc->hw.fp.tx_q[QUEUE_S].tx_used) {
-               outpd(ADDR(B0_XS_CSR),CSR_START) ;
-       }
-
-       /*
-        * repair rx queues
-        */
-       phys = repair_rxd_ring(smc,smc->hw.fp.rx[QUEUE_R1]) ;
-       outpd(ADDR(B4_R1_DA),phys) ;
-       outpd(ADDR(B0_R1_CSR),CSR_START) ;
-}
-
-static u_long repair_txd_ring(struct s_smc *smc, struct s_smt_tx_queue *queue)
-{
-       int i ;
-       int tx_used ;
-       u_long phys ;
-       u_long tbctrl ;
-       struct s_smt_fp_txd volatile *t ;
-
-       SK_UNUSED(smc) ;
-
-       t = queue->tx_curr_get ;
-       tx_used = queue->tx_used ;
-       for (i = tx_used+queue->tx_free-1 ; i ; i-- ) {
-               t = t->txd_next ;
-       }
-       phys = le32_to_cpu(t->txd_ntdadr) ;
-
-       t = queue->tx_curr_get ;
-       while (tx_used) {
-               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
-               tbctrl = le32_to_cpu(t->txd_tbctrl) ;
-
-               if (tbctrl & BMU_OWN) {
-                       if (tbctrl & BMU_STF) {
-                               break ;         /* exit the loop */
-                       }
-                       else {
-                               /*
-                                * repair the descriptor
-                                */
-                               t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
-                       }
-               }
-               phys = le32_to_cpu(t->txd_ntdadr) ;
-               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
-               t = t->txd_next ;
-               tx_used-- ;
-       }
-       return phys;
-}
-
-/*
- * Repairs the receive descriptor ring and returns the physical address
- * where the BMU should continue working.
- *
- *     o The physical address where the BMU was stopped has to be
- *       determined. This is the next RxD after rx_curr_get with an OWN
- *       bit set.
- *     o The BMU should start working at beginning of the next frame.
- *       RxDs with an OWN bit set but with a reset STF bit should be
- *       skipped and owned by the driver (OWN = 0). 
- */
-static u_long repair_rxd_ring(struct s_smc *smc, struct s_smt_rx_queue *queue)
-{
-       int i ;
-       int rx_used ;
-       u_long phys ;
-       u_long rbctrl ;
-       struct s_smt_fp_rxd volatile *r ;
-
-       SK_UNUSED(smc) ;
-
-       r = queue->rx_curr_get ;
-       rx_used = queue->rx_used ;
-       for (i = SMT_R1_RXD_COUNT-1 ; i ; i-- ) {
-               r = r->rxd_next ;
-       }
-       phys = le32_to_cpu(r->rxd_nrdadr) ;
-
-       r = queue->rx_curr_get ;
-       while (rx_used) {
-               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-               rbctrl = le32_to_cpu(r->rxd_rbctrl) ;
-
-               if (rbctrl & BMU_OWN) {
-                       if (rbctrl & BMU_STF) {
-                               break ;         /* exit the loop */
-                       }
-                       else {
-                               /*
-                                * repair the descriptor
-                                */
-                               r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
-                       }
-               }
-               phys = le32_to_cpu(r->rxd_nrdadr) ;
-               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
-               r = r->rxd_next ;
-               rx_used-- ;
-       }
-       return phys;
-}
-
-
-/*
-       -------------------------------------------------------------
-       INTERRUPT SERVICE ROUTINE:
-       -------------------------------------------------------------
-*/
-
-/*
- *     BEGIN_MANUAL_ENTRY(fddi_isr)
- *     void fddi_isr(smc)
- *
- * function    DOWNCALL        (drvsr.c)
- *             interrupt service routine, handles the interrupt requests
- *             generated by the FDDI adapter.
- *
- * NOTE:       The operating system dependent module must guarantee that the
- *             interrupts of the adapter are disabled when it calls fddi_isr.
- *
- *     About the USE_BREAK_ISR mechanismn:
- *
- *     The main requirement of this mechanismn is to force an timer IRQ when
- *     leaving process_receive() with leave_isr set. process_receive() may
- *     be called at any time from anywhere!
- *     To be sure we don't miss such event we set 'force_irq' per default.
- *     We have to force and Timer IRQ if 'smc->os.hwm.leave_isr' AND
- *     'force_irq' are set. 'force_irq' may be reset if a receive complete
- *     IRQ is pending.
- *
- *     END_MANUAL_ENTRY
- */
-void fddi_isr(struct s_smc *smc)
-{
-       u_long          is ;            /* ISR source */
-       u_short         stu, stl ;
-       SMbuf           *mb ;
-
-#ifdef USE_BREAK_ISR
-       int     force_irq ;
-#endif
-
-#ifdef ODI2
-       if (smc->os.hwm.rx_break) {
-               mac_drv_fill_rxd(smc) ;
-               if (smc->hw.fp.rx_q[QUEUE_R1].rx_used > 0) {
-                       smc->os.hwm.rx_break = 0 ;
-                       process_receive(smc) ;
-               }
-               else {
-                       smc->os.hwm.detec_count = 0 ;
-                       smt_force_irq(smc) ;
-               }
-       }
-#endif
-       smc->os.hwm.isr_flag = TRUE ;
-
-#ifdef USE_BREAK_ISR
-       force_irq = TRUE ;
-       if (smc->os.hwm.leave_isr) {
-               smc->os.hwm.leave_isr = FALSE ;
-               process_receive(smc) ;
-       }
-#endif
-
-       while ((is = GET_ISR() & ISR_MASK)) {
-               NDD_TRACE("CH0B",is,0,0) ;
-               DB_GEN("ISA = 0x%x",is,0,7) ;
-
-               if (is & IMASK_SLOW) {
-                       NDD_TRACE("CH1b",is,0,0) ;
-                       if (is & IS_PLINT1) {   /* PLC1 */
-                               plc1_irq(smc) ;
-                       }
-                       if (is & IS_PLINT2) {   /* PLC2 */
-                               plc2_irq(smc) ;
-                       }
-                       if (is & IS_MINTR1) {   /* FORMAC+ STU1(U/L) */
-                               stu = inpw(FM_A(FM_ST1U)) ;
-                               stl = inpw(FM_A(FM_ST1L)) ;
-                               DB_GEN("Slow transmit complete",0,0,6) ;
-                               mac1_irq(smc,stu,stl) ;
-                       }
-                       if (is & IS_MINTR2) {   /* FORMAC+ STU2(U/L) */
-                               stu= inpw(FM_A(FM_ST2U)) ;
-                               stl= inpw(FM_A(FM_ST2L)) ;
-                               DB_GEN("Slow receive complete",0,0,6) ;
-                               DB_GEN("stl = %x : stu = %x",stl,stu,7) ;
-                               mac2_irq(smc,stu,stl) ;
-                       }
-                       if (is & IS_MINTR3) {   /* FORMAC+ STU3(U/L) */
-                               stu= inpw(FM_A(FM_ST3U)) ;
-                               stl= inpw(FM_A(FM_ST3L)) ;
-                               DB_GEN("FORMAC Mode Register 3",0,0,6) ;
-                               mac3_irq(smc,stu,stl) ;
-                       }
-                       if (is & IS_TIMINT) {   /* Timer 82C54-2 */
-                               timer_irq(smc) ;
-#ifdef NDIS_OS2
-                               force_irq_pending = 0 ;
-#endif
-                               /*
-                                * out of RxD detection
-                                */
-                               if (++smc->os.hwm.detec_count > 4) {
-                                       /*
-                                        * check out of RxD condition
-                                        */
-                                        process_receive(smc) ;
-                               }
-                       }
-                       if (is & IS_TOKEN) {    /* Restricted Token Monitor */
-                               rtm_irq(smc) ;
-                       }
-                       if (is & IS_R1_P) {     /* Parity error rx queue 1 */
-                               /* clear IRQ */
-                               outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_P) ;
-                               SMT_PANIC(smc,HWM_E0004,HWM_E0004_MSG) ;
-                       }
-                       if (is & IS_R1_C) {     /* Encoding error rx queue 1 */
-                               /* clear IRQ */
-                               outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_C) ;
-                               SMT_PANIC(smc,HWM_E0005,HWM_E0005_MSG) ;
-                       }
-                       if (is & IS_XA_C) {     /* Encoding error async tx q */
-                               /* clear IRQ */
-                               outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_C) ;
-                               SMT_PANIC(smc,HWM_E0006,HWM_E0006_MSG) ;
-                       }
-                       if (is & IS_XS_C) {     /* Encoding error sync tx q */
-                               /* clear IRQ */
-                               outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_C) ;
-                               SMT_PANIC(smc,HWM_E0007,HWM_E0007_MSG) ;
-                       }
-               }
-
-               /*
-                *      Fast Tx complete Async/Sync Queue (BMU service)
-                */
-               if (is & (IS_XS_F|IS_XA_F)) {
-                       DB_GEN("Fast tx complete queue",0,0,6) ;
-                       /*
-                        * clear IRQ, Note: no IRQ is lost, because
-                        *      we always service both queues
-                        */
-                       outpd(ADDR(B5_XS_CSR),CSR_IRQ_CL_F) ;
-                       outpd(ADDR(B5_XA_CSR),CSR_IRQ_CL_F) ;
-                       mac_drv_clear_txd(smc) ;
-                       llc_restart_tx(smc) ;
-               }
-
-               /*
-                *      Fast Rx Complete (BMU service)
-                */
-               if (is & IS_R1_F) {
-                       DB_GEN("Fast receive complete",0,0,6) ;
-                       /* clear IRQ */
-#ifndef USE_BREAK_ISR
-                       outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
-                       process_receive(smc) ;
-#else
-                       process_receive(smc) ;
-                       if (smc->os.hwm.leave_isr) {
-                               force_irq = FALSE ;
-                       } else {
-                               outpd(ADDR(B4_R1_CSR),CSR_IRQ_CL_F) ;
-                               process_receive(smc) ;
-                       }
-#endif
-               }
-
-#ifndef        NDIS_OS2
-               while ((mb = get_llc_rx(smc))) {
-                       smt_to_llc(smc,mb) ;
-               }
-#else
-               if (offDepth)
-                       post_proc() ;
-
-               while (!offDepth && (mb = get_llc_rx(smc))) {
-                       smt_to_llc(smc,mb) ;
-               }
-
-               if (!offDepth && smc->os.hwm.rx_break) {
-                       process_receive(smc) ;
-               }
-#endif
-               if (smc->q.ev_get != smc->q.ev_put) {
-                       NDD_TRACE("CH2a",0,0,0) ;
-                       ev_dispatcher(smc) ;
-               }
-#ifdef NDIS_OS2
-               post_proc() ;
-               if (offDepth) {         /* leave fddi_isr because */
-                       break ;         /* indications not allowed */
-               }
-#endif
-#ifdef USE_BREAK_ISR
-               if (smc->os.hwm.leave_isr) {
-                       break ;         /* leave fddi_isr */
-               }
-#endif
-
-               /* NOTE: when the isr is left, no rx is pending */
-       }       /* end of interrupt source polling loop */
-
-#ifdef USE_BREAK_ISR
-       if (smc->os.hwm.leave_isr && force_irq) {
-               smt_force_irq(smc) ;
-       }
-#endif
-       smc->os.hwm.isr_flag = FALSE ;
-       NDD_TRACE("CH0E",0,0,0) ;
-}
-
-
-/*
-       -------------------------------------------------------------
-       RECEIVE FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-#ifndef        NDIS_OS2
-/*
- *     BEGIN_MANUAL_ENTRY(mac_drv_rx_mode)
- *     void mac_drv_rx_mode(smc,mode)
- *
- * function    DOWNCALL        (fplus.c)
- *             Corresponding to the parameter mode, the operating system
- *             dependent module can activate several receive modes.
- *
- * para        mode    = 1:    RX_ENABLE_ALLMULTI      enable all multicasts
- *             = 2:    RX_DISABLE_ALLMULTI     disable "enable all multicasts"
- *             = 3:    RX_ENABLE_PROMISC       enable promiscuous
- *             = 4:    RX_DISABLE_PROMISC      disable promiscuous
- *             = 5:    RX_ENABLE_NSA           enable rec. of all NSA frames
- *                     (disabled after 'driver reset' & 'set station address')
- *             = 6:    RX_DISABLE_NSA          disable rec. of all NSA frames
- *
- *             = 21:   RX_ENABLE_PASS_SMT      ( see description )
- *             = 22:   RX_DISABLE_PASS_SMT     (  "       "      )
- *             = 23:   RX_ENABLE_PASS_NSA      (  "       "      )
- *             = 24:   RX_DISABLE_PASS_NSA     (  "       "      )
- *             = 25:   RX_ENABLE_PASS_DB       (  "       "      )
- *             = 26:   RX_DISABLE_PASS_DB      (  "       "      )
- *             = 27:   RX_DISABLE_PASS_ALL     (  "       "      )
- *             = 28:   RX_DISABLE_LLC_PROMISC  (  "       "      )
- *             = 29:   RX_ENABLE_LLC_PROMISC   (  "       "      )
- *
- *
- *             RX_ENABLE_PASS_SMT / RX_DISABLE_PASS_SMT
- *
- *             If the operating system dependent module activates the
- *             mode RX_ENABLE_PASS_SMT, the hardware module
- *             duplicates all SMT frames with the frame control
- *             FC_SMT_INFO and passes them to the LLC receive channel
- *             by calling mac_drv_rx_init.
- *             The SMT Frames which are sent by the local SMT and the NSA
- *             frames whose A- and C-Indicator is not set are also duplicated
- *             and passed.
- *             The receive mode RX_DISABLE_PASS_SMT disables the passing
- *             of SMT frames.
- *
- *             RX_ENABLE_PASS_NSA / RX_DISABLE_PASS_NSA
- *
- *             If the operating system dependent module activates the
- *             mode RX_ENABLE_PASS_NSA, the hardware module
- *             duplicates all NSA frames with frame control FC_SMT_NSA
- *             and a set A-Indicator and passed them to the LLC
- *             receive channel by calling mac_drv_rx_init.
- *             All NSA Frames which are sent by the local SMT
- *             are also duplicated and passed.
- *             The receive mode RX_DISABLE_PASS_NSA disables the passing
- *             of NSA frames with the A- or C-Indicator set.
- *
- * NOTE:       For fear that the hardware module receives NSA frames with
- *             a reset A-Indicator, the operating system dependent module
- *             has to call mac_drv_rx_mode with the mode RX_ENABLE_NSA
- *             before activate the RX_ENABLE_PASS_NSA mode and after every
- *             'driver reset' and 'set station address'.
- *
- *             RX_ENABLE_PASS_DB / RX_DISABLE_PASS_DB
- *
- *             If the operating system dependent module activates the
- *             mode RX_ENABLE_PASS_DB, direct BEACON frames
- *             (FC_BEACON frame control) are passed to the LLC receive
- *             channel by mac_drv_rx_init.
- *             The receive mode RX_DISABLE_PASS_DB disables the passing
- *             of direct BEACON frames.
- *
- *             RX_DISABLE_PASS_ALL
- *
- *             Disables all special receives modes. It is equal to
- *             call mac_drv_set_rx_mode successively with the
- *             parameters RX_DISABLE_NSA, RX_DISABLE_PASS_SMT,
- *             RX_DISABLE_PASS_NSA and RX_DISABLE_PASS_DB.
- *
- *             RX_ENABLE_LLC_PROMISC
- *
- *             (default) all received LLC frames and all SMT/NSA/DBEACON
- *             frames depending on the attitude of the flags
- *             PASS_SMT/PASS_NSA/PASS_DBEACON will be delivered to the
- *             LLC layer
- *
- *             RX_DISABLE_LLC_PROMISC
- *
- *             all received SMT/NSA/DBEACON frames depending on the
- *             attitude of the flags PASS_SMT/PASS_NSA/PASS_DBEACON
- *             will be delivered to the LLC layer.
- *             all received LLC frames with a directed address, Multicast
- *             or Broadcast address will be delivered to the LLC
- *             layer too.
- *
- *     END_MANUAL_ENTRY
- */
-void mac_drv_rx_mode(struct s_smc *smc, int mode)
-{
-       switch(mode) {
-       case RX_ENABLE_PASS_SMT:
-               smc->os.hwm.pass_SMT = TRUE ;
-               break ;
-       case RX_DISABLE_PASS_SMT:
-               smc->os.hwm.pass_SMT = FALSE ;
-               break ;
-       case RX_ENABLE_PASS_NSA:
-               smc->os.hwm.pass_NSA = TRUE ;
-               break ;
-       case RX_DISABLE_PASS_NSA:
-               smc->os.hwm.pass_NSA = FALSE ;
-               break ;
-       case RX_ENABLE_PASS_DB:
-               smc->os.hwm.pass_DB = TRUE ;
-               break ;
-       case RX_DISABLE_PASS_DB:
-               smc->os.hwm.pass_DB = FALSE ;
-               break ;
-       case RX_DISABLE_PASS_ALL:
-               smc->os.hwm.pass_SMT = smc->os.hwm.pass_NSA = FALSE ;
-               smc->os.hwm.pass_DB = FALSE ;
-               smc->os.hwm.pass_llc_promisc = TRUE ;
-               mac_set_rx_mode(smc,RX_DISABLE_NSA) ;
-               break ;
-       case RX_DISABLE_LLC_PROMISC:
-               smc->os.hwm.pass_llc_promisc = FALSE ;
-               break ;
-       case RX_ENABLE_LLC_PROMISC:
-               smc->os.hwm.pass_llc_promisc = TRUE ;
-               break ;
-       case RX_ENABLE_ALLMULTI:
-       case RX_DISABLE_ALLMULTI:
-       case RX_ENABLE_PROMISC:
-       case RX_DISABLE_PROMISC:
-       case RX_ENABLE_NSA:
-       case RX_DISABLE_NSA:
-       default:
-               mac_set_rx_mode(smc,mode) ;
-               break ;
-       }
-}
-#endif /* ifndef NDIS_OS2 */
-
-/*
- * process receive queue
- */
-void process_receive(struct s_smc *smc)
-{
-       int i ;
-       int n ;
-       int frag_count ;                /* number of RxDs of the curr rx buf */
-       int used_frags ;                /* number of RxDs of the curr frame */
-       struct s_smt_rx_queue *queue ;  /* points to the queue ctl struct */
-       struct s_smt_fp_rxd volatile *r ;       /* rxd pointer */
-       struct s_smt_fp_rxd volatile *rxd ;     /* first rxd of rx frame */
-       u_long rbctrl ;                 /* receive buffer control word */
-       u_long rfsw ;                   /* receive frame status word */
-       u_short rx_used ;
-       u_char far *virt ;
-       char far *data ;
-       SMbuf *mb ;
-       u_char fc ;                     /* Frame control */
-       int len ;                       /* Frame length */
-
-       smc->os.hwm.detec_count = 0 ;
-       queue = smc->hw.fp.rx[QUEUE_R1] ;
-       NDD_TRACE("RHxB",0,0,0) ;
-       for ( ; ; ) {
-               r = queue->rx_curr_get ;
-               rx_used = queue->rx_used ;
-               frag_count = 0 ;
-
-#ifdef USE_BREAK_ISR
-               if (smc->os.hwm.leave_isr) {
-                       goto rx_end ;
-               }
-#endif
-#ifdef NDIS_OS2
-               if (offDepth) {
-                       smc->os.hwm.rx_break = 1 ;
-                       goto rx_end ;
-               }
-               smc->os.hwm.rx_break = 0 ;
-#endif
-#ifdef ODI2
-               if (smc->os.hwm.rx_break) {
-                       goto rx_end ;
-               }
-#endif
-               n = 0 ;
-               do {
-                       DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ;
-                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-                       rbctrl = le32_to_cpu(CR_READ(r->rxd_rbctrl));
-
-                       if (rbctrl & BMU_OWN) {
-                               NDD_TRACE("RHxE",r,rfsw,rbctrl) ;
-                               DB_RX("End of RxDs",0,0,4) ;
-                               goto rx_end ;
-                       }
-                       /*
-                        * out of RxD detection
-                        */
-                       if (!rx_used) {
-                               SK_BREAK() ;
-                               SMT_PANIC(smc,HWM_E0009,HWM_E0009_MSG) ;
-                               /* Either we don't have an RxD or all
-                                * RxDs are filled. Therefore it's allowed
-                                * for to set the STOPPED flag */
-                               smc->hw.hw_state = STOPPED ;
-                               mac_drv_clear_rx_queue(smc) ;
-                               smc->hw.hw_state = STARTED ;
-                               mac_drv_fill_rxd(smc) ;
-                               smc->os.hwm.detec_count = 0 ;
-                               goto rx_end ;
-                       }
-                       rfsw = le32_to_cpu(r->rxd_rfsw) ;
-                       if ((rbctrl & BMU_STF) != ((rbctrl & BMU_ST_BUF) <<5)) {
-                               /*
-                                * The BMU_STF bit is deleted, 1 frame is
-                                * placed into more than 1 rx buffer
-                                *
-                                * skip frame by setting the rx len to 0
-                                *
-                                * if fragment count == 0
-                                *      The missing STF bit belongs to the
-                                *      current frame, search for the
-                                *      EOF bit to complete the frame
-                                * else
-                                *      the fragment belongs to the next frame,
-                                *      exit the loop and process the frame
-                                */
-                               SK_BREAK() ;
-                               rfsw = 0 ;
-                               if (frag_count) {
-                                       break ;
-                               }
-                       }
-                       n += rbctrl & 0xffff ;
-                       r = r->rxd_next ;
-                       frag_count++ ;
-                       rx_used-- ;
-               } while (!(rbctrl & BMU_EOF)) ;
-               used_frags = frag_count ;
-               DB_RX("EOF set in RxD, used_frags = %d ",used_frags,0,5) ;
-
-               /* may be next 2 DRV_BUF_FLUSH() can be skipped, because */
-               /* BMU_ST_BUF will not be changed by the ASIC */
-               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-               while (rx_used && !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
-                       DB_RX("Check STF bit in %x",(void *)r,0,5) ;
-                       r = r->rxd_next ;
-                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-                       frag_count++ ;
-                       rx_used-- ;
-               }
-               DB_RX("STF bit found",0,0,5) ;
-
-               /*
-                * The received frame is finished for the process receive
-                */
-               rxd = queue->rx_curr_get ;
-               queue->rx_curr_get = r ;
-               queue->rx_free += frag_count ;
-               queue->rx_used = rx_used ;
-
-               /*
-                * ASIC Errata no. 7 (STF - Bit Bug)
-                */
-               rxd->rxd_rbctrl &= cpu_to_le32(~BMU_STF) ;
-
-               for (r=rxd, i=frag_count ; i ; r=r->rxd_next, i--){
-                       DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
-                       dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
-               }
-               smc->hw.fp.err_stats.err_valid++ ;
-               smc->mib.m[MAC0].fddiMACCopied_Ct++ ;
-
-               /* the length of the data including the FC */
-               len = (rfsw & RD_LENGTH) - 4 ;
-
-               DB_RX("frame length = %d",len,0,4) ;
-               /*
-                * check the frame_length and all error flags
-                */
-               if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
-                       if (rfsw & RD_S_MSRABT) {
-                               DB_RX("Frame aborted by the FORMAC",0,0,2) ;
-                               smc->hw.fp.err_stats.err_abort++ ;
-                       }
-                       /*
-                        * check frame status
-                        */
-                       if (rfsw & RD_S_SEAC2) {
-                               DB_RX("E-Indicator set",0,0,2) ;
-                               smc->hw.fp.err_stats.err_e_indicator++ ;
-                       }
-                       if (rfsw & RD_S_SFRMERR) {
-                               DB_RX("CRC error",0,0,2) ;
-                               smc->hw.fp.err_stats.err_crc++ ;
-                       }
-                       if (rfsw & RX_FS_IMPL) {
-                               DB_RX("Implementer frame",0,0,2) ;
-                               smc->hw.fp.err_stats.err_imp_frame++ ;
-                       }
-                       goto abort_frame ;
-               }
-               if (len > FDDI_RAW_MTU-4) {
-                       DB_RX("Frame too long error",0,0,2) ;
-                       smc->hw.fp.err_stats.err_too_long++ ;
-                       goto abort_frame ;
-               }
-               /*
-                * SUPERNET 3 Bug: FORMAC delivers status words
-                * of aborded frames to the BMU
-                */
-               if (len <= 4) {
-                       DB_RX("Frame length = 0",0,0,2) ;
-                       goto abort_frame ;
-               }
-
-               if (len != (n-4)) {
-                       DB_RX("BMU: rx len differs: [%d:%d]",len,n,4);
-                       smc->os.hwm.rx_len_error++ ;
-                       goto abort_frame ;
-               }
-
-               /*
-                * Check SA == MA
-                */
-               virt = (u_char far *) rxd->rxd_virt ;
-               DB_RX("FC = %x",*virt,0,2) ;
-               if (virt[12] == MA[5] &&
-                   virt[11] == MA[4] &&
-                   virt[10] == MA[3] &&
-                   virt[9] == MA[2] &&
-                   virt[8] == MA[1] &&
-                   (virt[7] & ~GROUP_ADDR_BIT) == MA[0]) {
-                       goto abort_frame ;
-               }
-
-               /*
-                * test if LLC frame
-                */
-               if (rfsw & RX_FS_LLC) {
-                       /*
-                        * if pass_llc_promisc is disable
-                        *      if DA != Multicast or Broadcast or DA!=MA
-                        *              abort the frame
-                        */
-                       if (!smc->os.hwm.pass_llc_promisc) {
-                               if(!(virt[1] & GROUP_ADDR_BIT)) {
-                                       if (virt[6] != MA[5] ||
-                                           virt[5] != MA[4] ||
-                                           virt[4] != MA[3] ||
-                                           virt[3] != MA[2] ||
-                                           virt[2] != MA[1] ||
-                                           virt[1] != MA[0]) {
-                                               DB_RX("DA != MA and not multi- or broadcast",0,0,2) ;
-                                               goto abort_frame ;
-                                       }
-                               }
-                       }
-
-                       /*
-                        * LLC frame received
-                        */
-                       DB_RX("LLC - receive",0,0,4) ;
-                       mac_drv_rx_complete(smc,rxd,frag_count,len) ;
-               }
-               else {
-                       if (!(mb = smt_get_mbuf(smc))) {
-                               smc->hw.fp.err_stats.err_no_buf++ ;
-                               DB_RX("No SMbuf; receive terminated",0,0,4) ;
-                               goto abort_frame ;
-                       }
-                       data = smtod(mb,char *) - 1 ;
-
-                       /*
-                        * copy the frame into a SMT_MBuf
-                        */
-#ifdef USE_OS_CPY
-                       hwm_cpy_rxd2mb(rxd,data,len) ;
-#else
-                       for (r=rxd, i=used_frags ; i ; r=r->rxd_next, i--){
-                               n = le32_to_cpu(r->rxd_rbctrl) & RD_LENGTH ;
-                               DB_RX("cp SMT frame to mb: len = %d",n,0,6) ;
-                               memcpy(data,r->rxd_virt,n) ;
-                               data += n ;
-                       }
-                       data = smtod(mb,char *) - 1 ;
-#endif
-                       fc = *(char *)mb->sm_data = *data ;
-                       mb->sm_len = len - 1 ;          /* len - fc */
-                       data++ ;
-
-                       /*
-                        * SMT frame received
-                        */
-                       switch(fc) {
-                       case FC_SMT_INFO :
-                               smc->hw.fp.err_stats.err_smt_frame++ ;
-                               DB_RX("SMT frame received ",0,0,5) ;
-
-                               if (smc->os.hwm.pass_SMT) {
-                                       DB_RX("pass SMT frame ",0,0,5) ;
-                                       mac_drv_rx_complete(smc, rxd,
-                                               frag_count,len) ;
-                               }
-                               else {
-                                       DB_RX("requeue RxD",0,0,5) ;
-                                       mac_drv_requeue_rxd(smc,rxd,frag_count);
-                               }
-
-                               smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
-                               break ;
-                       case FC_SMT_NSA :
-                               smc->hw.fp.err_stats.err_smt_frame++ ;
-                               DB_RX("SMT frame received ",0,0,5) ;
-
-                               /* if pass_NSA set pass the NSA frame or */
-                               /* pass_SMT set and the A-Indicator */
-                               /* is not set, pass the NSA frame */
-                               if (smc->os.hwm.pass_NSA ||
-                                       (smc->os.hwm.pass_SMT &&
-                                       !(rfsw & A_INDIC))) {
-                                       DB_RX("pass SMT frame ",0,0,5) ;
-                                       mac_drv_rx_complete(smc, rxd,
-                                               frag_count,len) ;
-                               }
-                               else {
-                                       DB_RX("requeue RxD",0,0,5) ;
-                                       mac_drv_requeue_rxd(smc,rxd,frag_count);
-                               }
-
-                               smt_received_pack(smc,mb,(int)(rfsw>>25)) ;
-                               break ;
-                       case FC_BEACON :
-                               if (smc->os.hwm.pass_DB) {
-                                       DB_RX("pass DB frame ",0,0,5) ;
-                                       mac_drv_rx_complete(smc, rxd,
-                                               frag_count,len) ;
-                               }
-                               else {
-                                       DB_RX("requeue RxD",0,0,5) ;
-                                       mac_drv_requeue_rxd(smc,rxd,frag_count);
-                               }
-                               smt_free_mbuf(smc,mb) ;
-                               break ;
-                       default :
-                               /*
-                                * unknown FC abord the frame
-                                */
-                               DB_RX("unknown FC error",0,0,2) ;
-                               smt_free_mbuf(smc,mb) ;
-                               DB_RX("requeue RxD",0,0,5) ;
-                               mac_drv_requeue_rxd(smc,rxd,frag_count) ;
-                               if ((fc & 0xf0) == FC_MAC)
-                                       smc->hw.fp.err_stats.err_mac_frame++ ;
-                               else
-                                       smc->hw.fp.err_stats.err_imp_frame++ ;
-
-                               break ;
-                       }
-               }
-
-               DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
-               NDD_TRACE("RHx1",queue->rx_curr_get,0,0) ;
-
-               continue ;
-       /*--------------------------------------------------------------------*/
-abort_frame:
-               DB_RX("requeue RxD",0,0,5) ;
-               mac_drv_requeue_rxd(smc,rxd,frag_count) ;
-
-               DB_RX("next RxD is %x ",queue->rx_curr_get,0,3) ;
-               NDD_TRACE("RHx2",queue->rx_curr_get,0,0) ;
-       }
-rx_end:
-#ifdef ALL_RX_COMPLETE
-       mac_drv_all_receives_complete(smc) ;
-#endif
-       return ;        /* lint bug: needs return detect end of function */
-}
-
-static void smt_to_llc(struct s_smc *smc, SMbuf *mb)
-{
-       u_char  fc ;
-
-       DB_RX("send a queued frame to the llc layer",0,0,4) ;
-       smc->os.hwm.r.len = mb->sm_len ;
-       smc->os.hwm.r.mb_pos = smtod(mb,char *) ;
-       fc = *smc->os.hwm.r.mb_pos ;
-       (void)mac_drv_rx_init(smc,(int)mb->sm_len,(int)fc,
-               smc->os.hwm.r.mb_pos,(int)mb->sm_len) ;
-       smt_free_mbuf(smc,mb) ;
-}
-
-/*
- *     BEGIN_MANUAL_ENTRY(hwm_rx_frag)
- *     void hwm_rx_frag(smc,virt,phys,len,frame_status)
- *
- * function    MACRO           (hardware module, hwmtm.h)
- *             This function calls dma_master for preparing the
- *             system hardware for the DMA transfer and initializes
- *             the current RxD with the length and the physical and
- *             virtual address of the fragment. Furthermore, it sets the
- *             STF and EOF bits depending on the frame status byte,
- *             switches the OWN flag of the RxD, so that it is owned by the
- *             adapter and issues an rx_start.
- *
- * para        virt    virtual pointer to the fragment
- *     len     the length of the fragment
- *     frame_status    status of the frame, see design description
- *
- * NOTE:       It is possible to call this function with a fragment length
- *             of zero.
- *
- *     END_MANUAL_ENTRY
- */
-void hwm_rx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
-                int frame_status)
-{
-       struct s_smt_fp_rxd volatile *r ;
-       __le32  rbctrl;
-
-       NDD_TRACE("RHfB",virt,len,frame_status) ;
-       DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ;
-       r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ;
-       r->rxd_virt = virt ;
-       r->rxd_rbadr = cpu_to_le32(phys) ;
-       rbctrl = cpu_to_le32( (((__u32)frame_status &
-               (FIRST_FRAG|LAST_FRAG))<<26) |
-               (((u_long) frame_status & FIRST_FRAG) << 21) |
-               BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ;
-       r->rxd_rbctrl = rbctrl ;
-
-       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
-       outpd(ADDR(B0_R1_CSR),CSR_START) ;
-       smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ;
-       smc->hw.fp.rx_q[QUEUE_R1].rx_used++ ;
-       smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put = r->rxd_next ;
-       NDD_TRACE("RHfE",r,le32_to_cpu(r->rxd_rbadr),0) ;
-}
-
-/*
- *     BEGINN_MANUAL_ENTRY(mac_drv_clear_rx_queue)
- *
- * void mac_drv_clear_rx_queue(smc)
- * struct s_smc *smc ;
- *
- * function    DOWNCALL        (hardware module, hwmtm.c)
- *             mac_drv_clear_rx_queue is called by the OS-specific module
- *             after it has issued a card_stop.
- *             In this case, the frames in the receive queue are obsolete and
- *             should be removed. For removing mac_drv_clear_rx_queue
- *             calls dma_master for each RxD and mac_drv_clear_rxd for each
- *             receive buffer.
- *
- * NOTE:       calling sequence card_stop:
- *             CLI_FBI(), card_stop(),
- *             mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
- *
- * NOTE:       The caller is responsible that the BMUs are idle
- *             when this function is called.
- *
- *     END_MANUAL_ENTRY
- */
-void mac_drv_clear_rx_queue(struct s_smc *smc)
-{
-       struct s_smt_fp_rxd volatile *r ;
-       struct s_smt_fp_rxd volatile *next_rxd ;
-       struct s_smt_rx_queue *queue ;
-       int frag_count ;
-       int i ;
-
-       if (smc->hw.hw_state != STOPPED) {
-               SK_BREAK() ;
-               SMT_PANIC(smc,HWM_E0012,HWM_E0012_MSG) ;
-               return ;
-       }
-
-       queue = smc->hw.fp.rx[QUEUE_R1] ;
-       DB_RX("clear_rx_queue",0,0,5) ;
-
-       /*
-        * dma_complete and mac_drv_clear_rxd for all RxDs / receive buffers
-        */
-       r = queue->rx_curr_get ;
-       while (queue->rx_used) {
-               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-               DB_RX("switch OWN bit of RxD 0x%x ",r,0,5) ;
-               r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
-               frag_count = 1 ;
-               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
-               r = r->rxd_next ;
-               DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-               while (r != queue->rx_curr_put &&
-                       !(r->rxd_rbctrl & cpu_to_le32(BMU_ST_BUF))) {
-                       DB_RX("Check STF bit in %x",(void *)r,0,5) ;
-                       r->rxd_rbctrl &= ~cpu_to_le32(BMU_OWN) ;
-                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ;
-                       r = r->rxd_next ;
-                       DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ;
-                       frag_count++ ;
-               }
-               DB_RX("STF bit found",0,0,5) ;
-               next_rxd = r ;
-
-               for (r=queue->rx_curr_get,i=frag_count; i ; r=r->rxd_next,i--){
-                       DB_RX("dma_complete for RxD %x",(void *)r,0,5) ;
-                       dma_complete(smc,(union s_fp_descr volatile *)r,DMA_WR);
-               }
-
-               DB_RX("mac_drv_clear_rxd: RxD %x frag_count %d ",
-                       (void *)queue->rx_curr_get,frag_count,5) ;
-               mac_drv_clear_rxd(smc,queue->rx_curr_get,frag_count) ;
-
-               queue->rx_curr_get = next_rxd ;
-               queue->rx_used -= frag_count ;
-               queue->rx_free += frag_count ;
-       }
-}
-
-
-/*
-       -------------------------------------------------------------
-       SEND FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-/*
- *     BEGIN_MANUAL_ENTRY(hwm_tx_init)
- *     int hwm_tx_init(smc,fc,frag_count,frame_len,frame_status)
- *
- * function    DOWN_CALL       (hardware module, hwmtm.c)
- *             hwm_tx_init checks if the frame can be sent through the
- *             corresponding send queue.
- *
- * para        fc      the frame control. To determine through which
- *             send queue the frame should be transmitted.
- *             0x50 - 0x57:    asynchronous LLC frame
- *             0xD0 - 0xD7:    synchronous LLC frame
- *             0x41, 0x4F:     SMT frame to the network
- *             0x42:           SMT frame to the network and to the local SMT
- *             0x43:           SMT frame to the local SMT
- *     frag_count      count of the fragments for this frame
- *     frame_len       length of the frame
- *     frame_status    status of the frame, the send queue bit is already
- *                     specified
- *
- * return              frame_status
- *
- *     END_MANUAL_ENTRY
- */
-int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count, int frame_len,
-               int frame_status)
-{
-       NDD_TRACE("THiB",fc,frag_count,frame_len) ;
-       smc->os.hwm.tx_p = smc->hw.fp.tx[frame_status & QUEUE_A0] ;
-       smc->os.hwm.tx_descr = TX_DESCRIPTOR | (((u_long)(frame_len-1)&3)<<27) ;
-       smc->os.hwm.tx_len = frame_len ;
-       DB_TX("hwm_tx_init: fc = %x, len = %d",fc,frame_len,3) ;
-       if ((fc & ~(FC_SYNC_BIT|FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
-               frame_status |= LAN_TX ;
-       }
-       else {
-               switch (fc) {
-               case FC_SMT_INFO :
-               case FC_SMT_NSA :
-                       frame_status |= LAN_TX ;
-                       break ;
-               case FC_SMT_LOC :
-                       frame_status |= LOC_TX ;
-                       break ;
-               case FC_SMT_LAN_LOC :
-                       frame_status |= LAN_TX | LOC_TX ;
-                       break ;
-               default :
-                       SMT_PANIC(smc,HWM_E0010,HWM_E0010_MSG) ;
-               }
-       }
-       if (!smc->hw.mac_ring_is_up) {
-               frame_status &= ~LAN_TX ;
-               frame_status |= RING_DOWN ;
-               DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
-       }
-       if (frag_count > smc->os.hwm.tx_p->tx_free) {
-#ifndef        NDIS_OS2
-               mac_drv_clear_txd(smc) ;
-               if (frag_count > smc->os.hwm.tx_p->tx_free) {
-                       DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
-                       frame_status &= ~LAN_TX ;
-                       frame_status |= OUT_OF_TXD ;
-               }
-#else
-               DB_TX("Out of TxDs, terminate LAN_TX",0,0,2) ;
-               frame_status &= ~LAN_TX ;
-               frame_status |= OUT_OF_TXD ;
-#endif
-       }
-       DB_TX("frame_status = %x",frame_status,0,3) ;
-       NDD_TRACE("THiE",frame_status,smc->os.hwm.tx_p->tx_free,0) ;
-       return frame_status;
-}
-
-/*
- *     BEGIN_MANUAL_ENTRY(hwm_tx_frag)
- *     void hwm_tx_frag(smc,virt,phys,len,frame_status)
- *
- * function    DOWNCALL        (hardware module, hwmtm.c)
- *             If the frame should be sent to the LAN, this function calls
- *             dma_master, fills the current TxD with the virtual and the
- *             physical address, sets the STF and EOF bits dependent on
- *             the frame status, and requests the BMU to start the
- *             transmit.
- *             If the frame should be sent to the local SMT, an SMT_MBuf
- *             is allocated if the FIRST_FRAG bit is set in the frame_status.
- *             The fragment of the frame is copied into the SMT MBuf.
- *             The function smt_received_pack is called if the LAST_FRAG
- *             bit is set in the frame_status word.
- *
- * para        virt    virtual pointer to the fragment
- *     len     the length of the fragment
- *     frame_status    status of the frame, see design description
- *
- * return      nothing returned, no parameter is modified
- *
- * NOTE:       It is possible to invoke this macro with a fragment length
- *             of zero.
- *
- *     END_MANUAL_ENTRY
- */
-void hwm_tx_frag(struct s_smc *smc, char far *virt, u_long phys, int len,
-                int frame_status)
-{
-       struct s_smt_fp_txd volatile *t ;
-       struct s_smt_tx_queue *queue ;
-       __le32  tbctrl ;
-
-       queue = smc->os.hwm.tx_p ;
-
-       NDD_TRACE("THfB",virt,len,frame_status) ;
-       /* Bug fix: AF / May 31 1999 (#missing)
-        * snmpinfo problem reported by IBM is caused by invalid
-        * t-pointer (txd) if LAN_TX is not set but LOC_TX only.
-        * Set: t = queue->tx_curr_put  here !
-        */
-       t = queue->tx_curr_put ;
-
-       DB_TX("hwm_tx_frag: len = %d, frame_status = %x ",len,frame_status,2) ;
-       if (frame_status & LAN_TX) {
-               /* '*t' is already defined */
-               DB_TX("LAN_TX: TxD = %x, virt = %x ",t,virt,3) ;
-               t->txd_virt = virt ;
-               t->txd_txdscr = cpu_to_le32(smc->os.hwm.tx_descr) ;
-               t->txd_tbadr = cpu_to_le32(phys) ;
-               tbctrl = cpu_to_le32((((__u32)frame_status &
-                       (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) |
-                       BMU_OWN|BMU_CHECK |len) ;
-               t->txd_tbctrl = tbctrl ;
-
-#ifndef        AIX
-               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
-               outpd(queue->tx_bmu_ctl,CSR_START) ;
-#else  /* ifndef AIX */
-               DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
-               if (frame_status & QUEUE_A0) {
-                       outpd(ADDR(B0_XA_CSR),CSR_START) ;
-               }
-               else {
-                       outpd(ADDR(B0_XS_CSR),CSR_START) ;
-               }
-#endif
-               queue->tx_free-- ;
-               queue->tx_used++ ;
-               queue->tx_curr_put = t->txd_next ;
-               if (frame_status & LAST_FRAG) {
-                       smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
-               }
-       }
-       if (frame_status & LOC_TX) {
-               DB_TX("LOC_TX: ",0,0,3) ;
-               if (frame_status & FIRST_FRAG) {
-                       if(!(smc->os.hwm.tx_mb = smt_get_mbuf(smc))) {
-                               smc->hw.fp.err_stats.err_no_buf++ ;
-                               DB_TX("No SMbuf; transmit terminated",0,0,4) ;
-                       }
-                       else {
-                               smc->os.hwm.tx_data =
-                                       smtod(smc->os.hwm.tx_mb,char *) - 1 ;
-#ifdef USE_OS_CPY
-#ifdef PASS_1ST_TXD_2_TX_COMP
-                               hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
-                                       smc->os.hwm.tx_len) ;
-#endif
-#endif
-                       }
-               }
-               if (smc->os.hwm.tx_mb) {
-#ifndef        USE_OS_CPY
-                       DB_TX("copy fragment into MBuf ",0,0,3) ;
-                       memcpy(smc->os.hwm.tx_data,virt,len) ;
-                       smc->os.hwm.tx_data += len ;
-#endif
-                       if (frame_status & LAST_FRAG) {
-#ifdef USE_OS_CPY
-#ifndef PASS_1ST_TXD_2_TX_COMP
-                               /*
-                                * hwm_cpy_txd2mb(txd,data,len) copies 'len' 
-                                * bytes from the virtual pointer in 'rxd'
-                                * to 'data'. The virtual pointer of the 
-                                * os-specific tx-buffer should be written
-                                * in the LAST txd.
-                                */ 
-                               hwm_cpy_txd2mb(t,smc->os.hwm.tx_data,
-                                       smc->os.hwm.tx_len) ;
-#endif /* nPASS_1ST_TXD_2_TX_COMP */
-#endif /* USE_OS_CPY */
-                               smc->os.hwm.tx_data =
-                                       smtod(smc->os.hwm.tx_mb,char *) - 1 ;
-                               *(char *)smc->os.hwm.tx_mb->sm_data =
-                                       *smc->os.hwm.tx_data ;
-                               smc->os.hwm.tx_data++ ;
-                               smc->os.hwm.tx_mb->sm_len =
-                                       smc->os.hwm.tx_len - 1 ;
-                               DB_TX("pass LLC frame to SMT ",0,0,3) ;
-                               smt_received_pack(smc,smc->os.hwm.tx_mb,
-                                               RD_FS_LOCAL) ;
-                       }
-               }
-       }
-       NDD_TRACE("THfE",t,queue->tx_free,0) ;
-}
-
-
-/*
- * queues a receive for later send
- */
-static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
-{
-       DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
-       smc->os.hwm.queued_rx_frames++ ;
-       mb->sm_next = (SMbuf *)NULL ;
-       if (smc->os.hwm.llc_rx_pipe == NULL) {
-               smc->os.hwm.llc_rx_pipe = mb ;
-       }
-       else {
-               smc->os.hwm.llc_rx_tail->sm_next = mb ;
-       }
-       smc->os.hwm.llc_rx_tail = mb ;
-
-       /*
-        * force an timer IRQ to receive the data
-        */
-       if (!smc->os.hwm.isr_flag) {
-               smt_force_irq(smc) ;
-       }
-}
-
-/*
- * get a SMbuf from the llc_rx_queue
- */
-static SMbuf *get_llc_rx(struct s_smc *smc)
-{
-       SMbuf   *mb ;
-
-       if ((mb = smc->os.hwm.llc_rx_pipe)) {
-               smc->os.hwm.queued_rx_frames-- ;
-               smc->os.hwm.llc_rx_pipe = mb->sm_next ;
-       }
-       DB_GEN("get_llc_rx: mb = 0x%x",(void *)mb,0,4) ;
-       return mb;
-}
-
-/*
- * queues a transmit SMT MBuf during the time were the MBuf is
- * queued the TxD ring
- */
-static void queue_txd_mb(struct s_smc *smc, SMbuf *mb)
-{
-       DB_GEN("_rx: queue_txd_mb = %x",(void *)mb,0,4) ;
-       smc->os.hwm.queued_txd_mb++ ;
-       mb->sm_next = (SMbuf *)NULL ;
-       if (smc->os.hwm.txd_tx_pipe == NULL) {
-               smc->os.hwm.txd_tx_pipe = mb ;
-       }
-       else {
-               smc->os.hwm.txd_tx_tail->sm_next = mb ;
-       }
-       smc->os.hwm.txd_tx_tail = mb ;
-}
-
-/*
- * get a SMbuf from the txd_tx_queue
- */
-static SMbuf *get_txd_mb(struct s_smc *smc)
-{
-       SMbuf *mb ;
-
-       if ((mb = smc->os.hwm.txd_tx_pipe)) {
-               smc->os.hwm.queued_txd_mb-- ;
-               smc->os.hwm.txd_tx_pipe = mb->sm_next ;
-       }
-       DB_GEN("get_txd_mb: mb = 0x%x",(void *)mb,0,4) ;
-       return mb;
-}
-
-/*
- *     SMT Send function
- */
-void smt_send_mbuf(struct s_smc *smc, SMbuf *mb, int fc)
-{
-       char far *data ;
-       int     len ;
-       int     n ;
-       int     i ;
-       int     frag_count ;
-       int     frame_status ;
-       SK_LOC_DECL(char far,*virt[3]) ;
-       int     frag_len[3] ;
-       struct s_smt_tx_queue *queue ;
-       struct s_smt_fp_txd volatile *t ;
-       u_long  phys ;
-       __le32  tbctrl;
-
-       NDD_TRACE("THSB",mb,fc,0) ;
-       DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ;
-
-       mb->sm_off-- ;  /* set to fc */
-       mb->sm_len++ ;  /* + fc */
-       data = smtod(mb,char *) ;
-       *data = fc ;
-       if (fc == FC_SMT_LOC)
-               *data = FC_SMT_INFO ;
-
-       /*
-        * determine the frag count and the virt addresses of the frags
-        */
-       frag_count = 0 ;
-       len = mb->sm_len ;
-       while (len) {
-               n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ;
-               if (n >= len) {
-                       n = len ;
-               }
-               DB_TX("frag: virt/len = 0x%x/%d ",(void *)data,n,5) ;
-               virt[frag_count] = data ;
-               frag_len[frag_count] = n ;
-               frag_count++ ;
-               len -= n ;
-               data += n ;
-       }
-
-       /*
-        * determine the frame status
-        */
-       queue = smc->hw.fp.tx[QUEUE_A0] ;
-       if (fc == FC_BEACON || fc == FC_SMT_LOC) {
-               frame_status = LOC_TX ;
-       }
-       else {
-               frame_status = LAN_TX ;
-               if ((smc->os.hwm.pass_NSA &&(fc == FC_SMT_NSA)) ||
-                  (smc->os.hwm.pass_SMT &&(fc == FC_SMT_INFO)))
-                       frame_status |= LOC_TX ;
-       }
-
-       if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
-               frame_status &= ~LAN_TX;
-               if (frame_status) {
-                       DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
-               }
-               else {
-                       DB_TX("Ring is down: terminate transmission",0,0,2) ;
-                       smt_free_mbuf(smc,mb) ;
-                       return ;
-               }
-       }
-       DB_TX("frame_status = 0x%x ",frame_status,0,5) ;
-
-       if ((frame_status & LAN_TX) && (frame_status & LOC_TX)) {
-               mb->sm_use_count = 2 ;
-       }
-
-       if (frame_status & LAN_TX) {
-               t = queue->tx_curr_put ;
-               frame_status |= FIRST_FRAG ;
-               for (i = 0; i < frag_count; i++) {
-                       DB_TX("init TxD = 0x%x",(void *)t,0,5) ;
-                       if (i == frag_count-1) {
-                               frame_status |= LAST_FRAG ;
-                               t->txd_txdscr = cpu_to_le32(TX_DESCRIPTOR |
-                                       (((__u32)(mb->sm_len-1)&3) << 27)) ;
-                       }
-                       t->txd_virt = virt[i] ;
-                       phys = dma_master(smc, (void far *)virt[i],
-                               frag_len[i], DMA_RD|SMT_BUF) ;
-                       t->txd_tbadr = cpu_to_le32(phys) ;
-                       tbctrl = cpu_to_le32((((__u32)frame_status &
-                               (FIRST_FRAG|LAST_FRAG)) << 26) |
-                               BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ;
-                       t->txd_tbctrl = tbctrl ;
-#ifndef        AIX
-                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
-                       outpd(queue->tx_bmu_ctl,CSR_START) ;
-#else
-                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
-                       outpd(ADDR(B0_XA_CSR),CSR_START) ;
-#endif
-                       frame_status &= ~FIRST_FRAG ;
-                       queue->tx_curr_put = t = t->txd_next ;
-                       queue->tx_free-- ;
-                       queue->tx_used++ ;
-               }
-               smc->mib.m[MAC0].fddiMACTransmit_Ct++ ;
-               queue_txd_mb(smc,mb) ;
-       }
-
-       if (frame_status & LOC_TX) {
-               DB_TX("pass Mbuf to LLC queue",0,0,5) ;
-               queue_llc_rx(smc,mb) ;
-       }
-
-       /*
-        * We need to unqueue the free SMT_MBUFs here, because it may
-        * be that the SMT want's to send more than 1 frame for one down call
-        */
-       mac_drv_clear_txd(smc) ;
-       NDD_TRACE("THSE",t,queue->tx_free,frag_count) ;
-}
-
-/*     BEGIN_MANUAL_ENTRY(mac_drv_clear_txd)
- *     void mac_drv_clear_txd(smc)
- *
- * function    DOWNCALL        (hardware module, hwmtm.c)
- *             mac_drv_clear_txd searches in both send queues for TxD's
- *             which were finished by the adapter. It calls dma_complete
- *             for each TxD. If the last fragment of an LLC frame is
- *             reached, it calls mac_drv_tx_complete to release the
- *             send buffer.
- *
- * return      nothing
- *
- *     END_MANUAL_ENTRY
- */
-static void mac_drv_clear_txd(struct s_smc *smc)
-{
-       struct s_smt_tx_queue *queue ;
-       struct s_smt_fp_txd volatile *t1 ;
-       struct s_smt_fp_txd volatile *t2 = NULL ;
-       SMbuf *mb ;
-       u_long  tbctrl ;
-       int i ;
-       int frag_count ;
-       int n ;
-
-       NDD_TRACE("THcB",0,0,0) ;
-       for (i = QUEUE_S; i <= QUEUE_A0; i++) {
-               queue = smc->hw.fp.tx[i] ;
-               t1 = queue->tx_curr_get ;
-               DB_TX("clear_txd: QUEUE = %d (0=sync/1=async)",i,0,5) ;
-
-               for ( ; ; ) {
-                       frag_count = 0 ;
-
-                       do {
-                               DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ;
-                               DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ;
-                               tbctrl = le32_to_cpu(CR_READ(t1->txd_tbctrl));
-
-                               if (tbctrl & BMU_OWN || !queue->tx_used){
-                                       DB_TX("End of TxDs queue %d",i,0,4) ;
-                                       goto free_next_queue ;  /* next queue */
-                               }
-                               t1 = t1->txd_next ;
-                               frag_count++ ;
-                       } while (!(tbctrl & BMU_EOF)) ;
-
-                       t1 = queue->tx_curr_get ;
-                       for (n = frag_count; n; n--) {
-                               tbctrl = le32_to_cpu(t1->txd_tbctrl) ;
-                               dma_complete(smc,
-                                       (union s_fp_descr volatile *) t1,
-                                       (int) (DMA_RD |
-                                       ((tbctrl & BMU_SMT_TX) >> 18))) ;
-                               t2 = t1 ;
-                               t1 = t1->txd_next ;
-                       }
-
-                       if (tbctrl & BMU_SMT_TX) {
-                               mb = get_txd_mb(smc) ;
-                               smt_free_mbuf(smc,mb) ;
-                       }
-                       else {
-#ifndef PASS_1ST_TXD_2_TX_COMP
-                               DB_TX("mac_drv_tx_comp for TxD 0x%x",t2,0,4) ;
-                               mac_drv_tx_complete(smc,t2) ;
-#else
-                               DB_TX("mac_drv_tx_comp for TxD 0x%x",
-                                       queue->tx_curr_get,0,4) ;
-                               mac_drv_tx_complete(smc,queue->tx_curr_get) ;
-#endif
-                       }
-                       queue->tx_curr_get = t1 ;
-                       queue->tx_free += frag_count ;
-                       queue->tx_used -= frag_count ;
-               }
-free_next_queue: ;
-       }
-       NDD_TRACE("THcE",0,0,0) ;
-}
-
-/*
- *     BEGINN_MANUAL_ENTRY(mac_drv_clear_tx_queue)
- *
- * void mac_drv_clear_tx_queue(smc)
- * struct s_smc *smc ;
- *
- * function    DOWNCALL        (hardware module, hwmtm.c)
- *             mac_drv_clear_tx_queue is called from the SMT when
- *             the RMT state machine has entered the ISOLATE state.
- *             This function is also called by the os-specific module
- *             after it has called the function card_stop().
- *             In this case, the frames in the send queues are obsolete and
- *             should be removed.
- *
- * note                calling sequence:
- *             CLI_FBI(), card_stop(),
- *             mac_drv_clear_tx_queue(), mac_drv_clear_rx_queue(),
- *
- * NOTE:       The caller is responsible that the BMUs are idle
- *             when this function is called.
- *
- *     END_MANUAL_ENTRY
- */
-void mac_drv_clear_tx_queue(struct s_smc *smc)
-{
-       struct s_smt_fp_txd volatile *t ;
-       struct s_smt_tx_queue *queue ;
-       int tx_used ;
-       int i ;
-
-       if (smc->hw.hw_state != STOPPED) {
-               SK_BREAK() ;
-               SMT_PANIC(smc,HWM_E0011,HWM_E0011_MSG) ;
-               return ;
-       }
-
-       for (i = QUEUE_S; i <= QUEUE_A0; i++) {
-               queue = smc->hw.fp.tx[i] ;
-               DB_TX("clear_tx_queue: QUEUE = %d (0=sync/1=async)",i,0,5) ;
-
-               /*
-                * switch the OWN bit of all pending frames to the host
-                */
-               t = queue->tx_curr_get ;
-               tx_used = queue->tx_used ;
-               while (tx_used) {
-                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORCPU) ;
-                       DB_TX("switch OWN bit of TxD 0x%x ",t,0,5) ;
-                       t->txd_tbctrl &= ~cpu_to_le32(BMU_OWN) ;
-                       DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ;
-                       t = t->txd_next ;
-                       tx_used-- ;
-               }
-       }
-
-       /*
-        * release all TxD's for both send queues
-        */
-       mac_drv_clear_txd(smc) ;
-
-       for (i = QUEUE_S; i <= QUEUE_A0; i++) {
-               queue = smc->hw.fp.tx[i] ;
-               t = queue->tx_curr_get ;
-
-               /*
-                * write the phys pointer of the NEXT descriptor into the
-                * BMU's current address descriptor pointer and set
-                * tx_curr_get and tx_curr_put to this position
-                */
-               if (i == QUEUE_S) {
-                       outpd(ADDR(B5_XS_DA),le32_to_cpu(t->txd_ntdadr)) ;
-               }
-               else {
-                       outpd(ADDR(B5_XA_DA),le32_to_cpu(t->txd_ntdadr)) ;
-               }
-
-               queue->tx_curr_put = queue->tx_curr_get->txd_next ;
-               queue->tx_curr_get = queue->tx_curr_put ;
-       }
-}
-
-
-/*
-       -------------------------------------------------------------
-       TEST FUNCTIONS:
-       -------------------------------------------------------------
-*/
-
-#ifdef DEBUG
-/*
- *     BEGIN_MANUAL_ENTRY(mac_drv_debug_lev)
- *     void mac_drv_debug_lev(smc,flag,lev)
- *
- * function    DOWNCALL        (drvsr.c)
- *             To get a special debug info the user can assign a debug level
- *             to any debug flag.
- *
- * para        flag    debug flag, possible values are:
- *                     = 0:    reset all debug flags (the defined level is
- *                             ignored)
- *                     = 1:    debug.d_smtf
- *                     = 2:    debug.d_smt
- *                     = 3:    debug.d_ecm
- *                     = 4:    debug.d_rmt
- *                     = 5:    debug.d_cfm
- *                     = 6:    debug.d_pcm
- *
- *                     = 10:   debug.d_os.hwm_rx (hardware module receive path)
- *                     = 11:   debug.d_os.hwm_tx(hardware module transmit path)
- *                     = 12:   debug.d_os.hwm_gen(hardware module general flag)
- *
- *     lev     debug level
- *
- *     END_MANUAL_ENTRY
- */
-void mac_drv_debug_lev(struct s_smc *smc, int flag, int lev)
-{
-       switch(flag) {
-       case (int)NULL:
-               DB_P.d_smtf = DB_P.d_smt = DB_P.d_ecm = DB_P.d_rmt = 0 ;
-               DB_P.d_cfm = 0 ;
-               DB_P.d_os.hwm_rx = DB_P.d_os.hwm_tx = DB_P.d_os.hwm_gen = 0 ;
-#ifdef SBA
-               DB_P.d_sba = 0 ;
-#endif
-#ifdef ESS
-               DB_P.d_ess = 0 ;
-#endif
-               break ;
-       case DEBUG_SMTF:
-               DB_P.d_smtf = lev ;
-               break ;
-       case DEBUG_SMT:
-               DB_P.d_smt = lev ;
-               break ;
-       case DEBUG_ECM:
-               DB_P.d_ecm = lev ;
-               break ;
-       case DEBUG_RMT:
-               DB_P.d_rmt = lev ;
-               break ;
-       case DEBUG_CFM:
-               DB_P.d_cfm = lev ;
-               break ;
-       case DEBUG_PCM:
-               DB_P.d_pcm = lev ;
-               break ;
-       case DEBUG_SBA:
-#ifdef SBA
-               DB_P.d_sba = lev ;
-#endif
-               break ;
-       case DEBUG_ESS:
-#ifdef ESS
-               DB_P.d_ess = lev ;
-#endif
-               break ;
-       case DB_HWM_RX:
-               DB_P.d_os.hwm_rx = lev ;
-               break ;
-       case DB_HWM_TX:
-               DB_P.d_os.hwm_tx = lev ;
-               break ;
-       case DB_HWM_GEN:
-               DB_P.d_os.hwm_gen = lev ;
-               break ;
-       default:
-               break ;
-       }
-}
-#endif
diff --git a/drivers/net/skfp/hwt.c b/drivers/net/skfp/hwt.c
deleted file mode 100644 (file)
index c0798fd..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * Timer Driver for FBI board (timer chip 82C54)
- */
-
-/*
- * Modifications:
- *
- *     28-Jun-1994 sw  Edit v1.6.
- *                     MCA: Added support for the SK-NET FDDI-FM2 adapter. The
- *                      following functions have been added(+) or modified(*):
- *                      hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*)
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)hwt.c       1.13 97/04/23 (C) SK " ;
-#endif
-
-/*
- * Prototypes of local functions.
- */
-/* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
-/*static void hwt_restart() ; */
-
-/************************
- *
- *     hwt_start
- *
- *     Start hardware timer (clock ticks are 16us).
- *
- *     void hwt_start(
- *             struct s_smc *smc,
- *             u_long time) ;
- * In
- *     smc - A pointer to the SMT Context structure.
- *
- *     time - The time in units of 16us to load the timer with.
- * Out
- *     Nothing.
- *
- ************************/
-#define        HWT_MAX (65000)
-
-void hwt_start(struct s_smc *smc, u_long time)
-{
-       u_short cnt ;
-
-       if (time > HWT_MAX)
-               time = HWT_MAX ;
-
-       smc->hw.t_start = time ;
-       smc->hw.t_stop = 0L ;
-
-       cnt = (u_short)time ;
-       /*
-        * if time < 16 us
-        *      time = 16 us
-        */
-       if (!cnt)
-               cnt++ ;
-
-       outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ;    /* Load timer value. */
-       outpw(ADDR(B2_TI_CRTL), TIM_START) ;            /* Start timer. */
-
-       smc->hw.timer_activ = TRUE ;
-}
-
-/************************
- *
- *     hwt_stop
- *
- *     Stop hardware timer.
- *
- *     void hwt_stop(
- *             struct s_smc *smc) ;
- * In
- *     smc - A pointer to the SMT Context structure.
- * Out
- *     Nothing.
- *
- ************************/
-void hwt_stop(struct s_smc *smc)
-{
-       outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
-       outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;
-
-       smc->hw.timer_activ = FALSE ;
-}
-
-/************************
- *
- *     hwt_init
- *
- *     Initialize hardware timer.
- *
- *     void hwt_init(
- *             struct s_smc *smc) ;
- * In
- *     smc - A pointer to the SMT Context structure.
- * Out
- *     Nothing.
- *
- ************************/
-void hwt_init(struct s_smc *smc)
-{
-       smc->hw.t_start = 0 ;
-       smc->hw.t_stop  = 0 ;
-       smc->hw.timer_activ = FALSE ;
-
-       hwt_restart(smc) ;
-}
-
-/************************
- *
- *     hwt_restart
- *
- *     Clear timer interrupt.
- *
- *     void hwt_restart(
- *             struct s_smc *smc) ;
- * In
- *     smc - A pointer to the SMT Context structure.
- * Out
- *     Nothing.
- *
- ************************/
-void hwt_restart(struct s_smc *smc)
-{
-       hwt_stop(smc) ;
-}
-
-/************************
- *
- *     hwt_read
- *
- *     Stop hardware timer and read time elapsed since last start.
- *
- *     u_long hwt_read(smc) ;
- * In
- *     smc - A pointer to the SMT Context structure.
- * Out
- *     The elapsed time since last start in units of 16us.
- *
- ************************/
-u_long hwt_read(struct s_smc *smc)
-{
-       u_short tr ;
-       u_long  is ;
-
-       if (smc->hw.timer_activ) {
-               hwt_stop(smc) ;
-               tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;
-
-               is = GET_ISR() ;
-               /* Check if timer expired (or wraparound). */
-               if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {
-                       hwt_restart(smc) ;
-                       smc->hw.t_stop = smc->hw.t_start ;
-               }
-               else
-                       smc->hw.t_stop = smc->hw.t_start - tr ;
-       }
-       return smc->hw.t_stop;
-}
-
-#ifdef PCI
-/************************
- *
- *     hwt_quick_read
- *
- *     Stop hardware timer and read timer value and start the timer again.
- *
- *     u_long hwt_read(smc) ;
- * In
- *     smc - A pointer to the SMT Context structure.
- * Out
- *     current timer value in units of 80ns.
- *
- ************************/
-u_long hwt_quick_read(struct s_smc *smc)
-{
-       u_long interval ;
-       u_long time ;
-
-       interval = inpd(ADDR(B2_TI_INI)) ;
-       outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
-       time = inpd(ADDR(B2_TI_VAL)) ;
-       outpd(ADDR(B2_TI_INI),time) ;
-       outpw(ADDR(B2_TI_CRTL), TIM_START) ;
-       outpd(ADDR(B2_TI_INI),interval) ;
-
-       return time;
-}
-
-/************************
- *
- *     hwt_wait_time(smc,start,duration)
- *
- *     This function returnes after the amount of time is elapsed
- *     since the start time.
- * 
- * para        start           start time
- *     duration        time to wait
- *
- * NOTE: The function will return immediately, if the timer is not
- *      started
- ************************/
-void hwt_wait_time(struct s_smc *smc, u_long start, long int duration)
-{
-       long    diff ;
-       long    interval ;
-       int     wrapped ;
-
-       /*
-        * check if timer is running
-        */
-       if (smc->hw.timer_activ == FALSE ||
-               hwt_quick_read(smc) == hwt_quick_read(smc)) {
-               return ;
-       }
-
-       interval = inpd(ADDR(B2_TI_INI)) ;
-       if (interval > duration) {
-               do {
-                       diff = (long)(start - hwt_quick_read(smc)) ;
-                       if (diff < 0) {
-                               diff += interval ;
-                       }
-               } while (diff <= duration) ;
-       }
-       else {
-               diff = interval ;
-               wrapped = 0 ;
-               do {
-                       if (!wrapped) {
-                               if (hwt_quick_read(smc) >= start) {
-                                       diff += interval ;
-                                       wrapped = 1 ;
-                               }
-                       }
-                       else {
-                               if (hwt_quick_read(smc) < start) {
-                                       wrapped = 0 ;
-                               }
-                       }
-               } while (diff <= duration) ;
-       }
-}
-#endif
-
diff --git a/drivers/net/skfp/pcmplc.c b/drivers/net/skfp/pcmplc.c
deleted file mode 100644 (file)
index 88d02d0..0000000
+++ /dev/null
@@ -1,2014 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       PCM
-       Physical Connection Management
-*/
-
-/*
- * Hardware independent state machine implemantation
- * The following external SMT functions are referenced :
- *
- *             queue_event()
- *             smt_timer_start()
- *             smt_timer_stop()
- *
- *     The following external HW dependent functions are referenced :
- *             sm_pm_control()
- *             sm_ph_linestate()
- *             sm_pm_ls_latch()
- *
- *     The following HW dependent events are required :
- *             PC_QLS
- *             PC_ILS
- *             PC_HLS
- *             PC_MLS
- *             PC_NSE
- *             PC_LEM
- *
- */
-
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/supern_2.h"
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)pcmplc.c    2.55 99/08/05 (C) SK " ;
-#endif
-
-#ifdef FDDI_MIB
-extern int snmp_fddi_trap(
-#ifdef ANSIC
-struct s_smc   * smc, int  type, int  index
-#endif
-);
-#endif
-#ifdef CONCENTRATOR
-extern int plc_is_installed(
-#ifdef ANSIC
-struct s_smc *smc ,
-int p
-#endif
-) ;
-#endif
-/*
- * FSM Macros
- */
-#define AFLAG          (0x20)
-#define GO_STATE(x)    (mib->fddiPORTPCMState = (x)|AFLAG)
-#define ACTIONS_DONE() (mib->fddiPORTPCMState &= ~AFLAG)
-#define ACTIONS(x)     (x|AFLAG)
-
-/*
- * PCM states
- */
-#define PC0_OFF                        0
-#define PC1_BREAK              1
-#define PC2_TRACE              2
-#define PC3_CONNECT            3
-#define PC4_NEXT               4
-#define PC5_SIGNAL             5
-#define PC6_JOIN               6
-#define PC7_VERIFY             7
-#define PC8_ACTIVE             8
-#define PC9_MAINT              9
-
-#ifdef DEBUG
-/*
- * symbolic state names
- */
-static const char * const pcm_states[] =  {
-       "PC0_OFF","PC1_BREAK","PC2_TRACE","PC3_CONNECT","PC4_NEXT",
-       "PC5_SIGNAL","PC6_JOIN","PC7_VERIFY","PC8_ACTIVE","PC9_MAINT"
-} ;
-
-/*
- * symbolic event names
- */
-static const char * const pcm_events[] = {
-       "NONE","PC_START","PC_STOP","PC_LOOP","PC_JOIN","PC_SIGNAL",
-       "PC_REJECT","PC_MAINT","PC_TRACE","PC_PDR",
-       "PC_ENABLE","PC_DISABLE",
-       "PC_QLS","PC_ILS","PC_MLS","PC_HLS","PC_LS_PDR","PC_LS_NONE",
-       "PC_TIMEOUT_TB_MAX","PC_TIMEOUT_TB_MIN",
-       "PC_TIMEOUT_C_MIN","PC_TIMEOUT_T_OUT",
-       "PC_TIMEOUT_TL_MIN","PC_TIMEOUT_T_NEXT","PC_TIMEOUT_LCT",
-       "PC_NSE","PC_LEM"
-} ;
-#endif
-
-#ifdef MOT_ELM
-/*
- * PCL-S control register
- * this register in the PLC-S controls the scrambling parameters
- */
-#define PLCS_CONTROL_C_U       0
-#define PLCS_CONTROL_C_S       (PL_C_SDOFF_ENABLE | PL_C_SDON_ENABLE | \
-                                PL_C_CIPHER_ENABLE)
-#define        PLCS_FASSERT_U          0
-#define        PLCS_FASSERT_S          0xFd76  /* 52.0 us */
-#define        PLCS_FDEASSERT_U        0
-#define        PLCS_FDEASSERT_S        0
-#else  /* nMOT_ELM */
-/*
- * PCL-S control register
- * this register in the PLC-S controls the scrambling parameters
- * can be patched for ANSI compliance if standard changes
- */
-static const u_char plcs_control_c_u[17] = "PLC_CNTRL_C_U=\0\0" ;
-static const u_char plcs_control_c_s[17] = "PLC_CNTRL_C_S=\01\02" ;
-
-#define PLCS_CONTROL_C_U (plcs_control_c_u[14] | (plcs_control_c_u[15]<<8))
-#define PLCS_CONTROL_C_S (plcs_control_c_s[14] | (plcs_control_c_s[15]<<8))
-#endif /* nMOT_ELM */
-
-/*
- * external vars
- */
-/* struct definition see 'cmtdef.h' (also used by CFM) */
-
-#define PS_OFF         0
-#define PS_BIT3                1
-#define PS_BIT4                2
-#define PS_BIT7                3
-#define PS_LCT         4
-#define PS_BIT8                5
-#define PS_JOIN                6
-#define PS_ACTIVE      7
-
-#define LCT_LEM_MAX    255
-
-/*
- * PLC timing parameter
- */
-
-#define PLC_MS(m)      ((int)((0x10000L-(m*100000L/2048))))
-#define SLOW_TL_MIN    PLC_MS(6)
-#define SLOW_C_MIN     PLC_MS(10)
-
-static const struct plt {
-       int     timer ;                 /* relative plc timer address */
-       int     para ;                  /* default timing parameters */
-} pltm[] = {
-       { PL_C_MIN, SLOW_C_MIN },       /* min t. to remain Connect State */
-       { PL_TL_MIN, SLOW_TL_MIN },     /* min t. to transmit a Line State */
-       { PL_TB_MIN, TP_TB_MIN },       /* min break time */
-       { PL_T_OUT, TP_T_OUT },         /* Signaling timeout */
-       { PL_LC_LENGTH, TP_LC_LENGTH }, /* Link Confidence Test Time */
-       { PL_T_SCRUB, TP_T_SCRUB },     /* Scrub Time == MAC TVX time ! */
-       { PL_NS_MAX, TP_NS_MAX },       /* max t. that noise is tolerated */
-       { 0,0 }
-} ;
-
-/*
- * interrupt mask
- */
-#ifdef SUPERNET_3
-/*
- * Do we need the EBUF error during signaling, too, to detect SUPERNET_3
- * PLL bug?
- */
-static const int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
-                       PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
-#else  /* SUPERNET_3 */
-/*
- * We do NOT need the elasticity buffer error during signaling.
- */
-static int plc_imsk_na = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
-                       PL_PCM_ENABLED | PL_SELF_TEST ;
-#endif /* SUPERNET_3 */
-static const int plc_imsk_act = PL_PCM_CODE | PL_TRACE_PROP | PL_PCM_BREAK |
-                       PL_PCM_ENABLED | PL_SELF_TEST | PL_EBUF_ERR;
-
-/* internal functions */
-static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd);
-static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy);
-static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy);
-static void reset_lem_struct(struct s_phy *phy);
-static void plc_init(struct s_smc *smc, int p);
-static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold);
-static void sm_ph_lem_stop(struct s_smc *smc, int np);
-static void sm_ph_linestate(struct s_smc *smc, int phy, int ls);
-static void real_init_plc(struct s_smc *smc);
-
-/*
- * SMT timer interface
- *      start PCM timer 0
- */
-static void start_pcm_timer0(struct s_smc *smc, u_long value, int event,
-                            struct s_phy *phy)
-{
-       phy->timer0_exp = FALSE ;       /* clear timer event flag */
-       smt_timer_start(smc,&phy->pcm_timer0,value,
-               EV_TOKEN(EVENT_PCM+phy->np,event)) ;
-}
-/*
- * SMT timer interface
- *      stop PCM timer 0
- */
-static void stop_pcm_timer0(struct s_smc *smc, struct s_phy *phy)
-{
-       if (phy->pcm_timer0.tm_active)
-               smt_timer_stop(smc,&phy->pcm_timer0) ;
-}
-
-/*
-       init PCM state machine (called by driver)
-       clear all PCM vars and flags
-*/
-void pcm_init(struct s_smc *smc)
-{
-       int             i ;
-       int             np ;
-       struct s_phy    *phy ;
-       struct fddi_mib_p       *mib ;
-
-       for (np = 0,phy = smc->y ; np < NUMPHYS ; np++,phy++) {
-               /* Indicates the type of PHY being used */
-               mib = phy->mib ;
-               mib->fddiPORTPCMState = ACTIONS(PC0_OFF) ;
-               phy->np = np ;
-               switch (smc->s.sas) {
-#ifdef CONCENTRATOR
-               case SMT_SAS :
-                       mib->fddiPORTMy_Type = (np == PS) ? TS : TM ;
-                       break ;
-               case SMT_DAS :
-                       mib->fddiPORTMy_Type = (np == PA) ? TA :
-                                       (np == PB) ? TB : TM ;
-                       break ;
-               case SMT_NAC :
-                       mib->fddiPORTMy_Type = TM ;
-                       break;
-#else
-               case SMT_SAS :
-                       mib->fddiPORTMy_Type = (np == PS) ? TS : TNONE ;
-                       mib->fddiPORTHardwarePresent = (np == PS) ? TRUE :
-                                       FALSE ;
-#ifndef        SUPERNET_3
-                       smc->y[PA].mib->fddiPORTPCMState = PC0_OFF ;
-#else
-                       smc->y[PB].mib->fddiPORTPCMState = PC0_OFF ;
-#endif
-                       break ;
-               case SMT_DAS :
-                       mib->fddiPORTMy_Type = (np == PB) ? TB : TA ;
-                       break ;
-#endif
-               }
-               /*
-                * set PMD-type
-                */
-               phy->pmd_scramble = 0 ;
-               switch (phy->pmd_type[PMD_SK_PMD]) {
-               case 'P' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
-                       break ;
-               case 'L' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_LCF ;
-                       break ;
-               case 'D' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
-                       break ;
-               case 'S' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
-                       phy->pmd_scramble = TRUE ;
-                       break ;
-               case 'U' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
-                       phy->pmd_scramble = TRUE ;
-                       break ;
-               case '1' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
-                       break ;
-               case '2' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
-                       break ;
-               case '3' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE2 ;
-                       break ;
-               case '4' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_SINGLE1 ;
-                       break ;
-               case 'H' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
-                       break ;
-               case 'I' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
-                       break ;
-               case 'G' :
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_TP ;
-                       break ;
-               default:
-                       mib->fddiPORTPMDClass = MIB_PMDCLASS_UNKNOWN ;
-                       break ;
-               }
-               /*
-                * A and B port can be on primary and secondary path
-                */
-               switch (mib->fddiPORTMy_Type) {
-               case TA :
-                       mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
-                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
-                       mib->fddiPORTRequestedPaths[2] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_CON_ALTER |
-                               MIB_P_PATH_SEC_PREFER ;
-                       mib->fddiPORTRequestedPaths[3] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_CON_ALTER |
-                               MIB_P_PATH_SEC_PREFER |
-                               MIB_P_PATH_THRU ;
-                       break ;
-               case TB :
-                       mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
-                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
-                       mib->fddiPORTRequestedPaths[2] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_PRIM_PREFER ;
-                       mib->fddiPORTRequestedPaths[3] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_PRIM_PREFER |
-                               MIB_P_PATH_CON_PREFER |
-                               MIB_P_PATH_THRU ;
-                       break ;
-               case TS :
-                       mib->fddiPORTAvailablePaths |= MIB_PATH_S ;
-                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
-                       mib->fddiPORTRequestedPaths[2] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_CON_ALTER |
-                               MIB_P_PATH_PRIM_PREFER ;
-                       mib->fddiPORTRequestedPaths[3] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_CON_ALTER |
-                               MIB_P_PATH_PRIM_PREFER ;
-                       break ;
-               case TM :
-                       mib->fddiPORTRequestedPaths[1] = MIB_P_PATH_LOCAL ;
-                       mib->fddiPORTRequestedPaths[2] =
-                               MIB_P_PATH_LOCAL |
-                               MIB_P_PATH_SEC_ALTER |
-                               MIB_P_PATH_PRIM_ALTER ;
-                       mib->fddiPORTRequestedPaths[3] = 0 ;
-                       break ;
-               }
-
-               phy->pc_lem_fail = FALSE ;
-               mib->fddiPORTPCMStateX = mib->fddiPORTPCMState ;
-               mib->fddiPORTLCTFail_Ct = 0 ;
-               mib->fddiPORTBS_Flag = 0 ;
-               mib->fddiPORTCurrentPath = MIB_PATH_ISOLATED ;
-               mib->fddiPORTNeighborType = TNONE ;
-               phy->ls_flag = 0 ;
-               phy->rc_flag = 0 ;
-               phy->tc_flag = 0 ;
-               phy->td_flag = 0 ;
-               if (np >= PM)
-                       phy->phy_name = '0' + np - PM ;
-               else
-                       phy->phy_name = 'A' + np ;
-               phy->wc_flag = FALSE ;          /* set by SMT */
-               memset((char *)&phy->lem,0,sizeof(struct lem_counter)) ;
-               reset_lem_struct(phy) ;
-               memset((char *)&phy->plc,0,sizeof(struct s_plc)) ;
-               phy->plc.p_state = PS_OFF ;
-               for (i = 0 ; i < NUMBITS ; i++) {
-                       phy->t_next[i] = 0 ;
-               }
-       }
-       real_init_plc(smc) ;
-}
-
-void init_plc(struct s_smc *smc)
-{
-       SK_UNUSED(smc) ;
-
-       /*
-        * dummy
-        * this is an obsolete public entry point that has to remain
-        * for compat. It is used by various drivers.
-        * the work is now done in real_init_plc()
-        * which is called from pcm_init() ;
-        */
-}
-
-static void real_init_plc(struct s_smc *smc)
-{
-       int     p ;
-
-       for (p = 0 ; p < NUMPHYS ; p++)
-               plc_init(smc,p) ;
-}
-
-static void plc_init(struct s_smc *smc, int p)
-{
-       int     i ;
-#ifndef        MOT_ELM
-       int     rev ;   /* Revision of PLC-x */
-#endif /* MOT_ELM */
-
-       /* transit PCM state machine to MAINT state */
-       outpw(PLC(p,PL_CNTRL_B),0) ;
-       outpw(PLC(p,PL_CNTRL_B),PL_PCM_STOP) ;
-       outpw(PLC(p,PL_CNTRL_A),0) ;
-
-       /*
-        * if PLC-S then set control register C
-        */
-#ifndef        MOT_ELM
-       rev = inpw(PLC(p,PL_STATUS_A)) & PLC_REV_MASK ;
-       if (rev != PLC_REVISION_A)
-#endif /* MOT_ELM */
-       {
-               if (smc->y[p].pmd_scramble) {
-                       outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_S) ;
-#ifdef MOT_ELM
-                       outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_S) ;
-                       outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_S) ;
-#endif /* MOT_ELM */
-               }
-               else {
-                       outpw(PLC(p,PL_CNTRL_C),PLCS_CONTROL_C_U) ;
-#ifdef MOT_ELM
-                       outpw(PLC(p,PL_T_FOT_ASS),PLCS_FASSERT_U) ;
-                       outpw(PLC(p,PL_T_FOT_DEASS),PLCS_FDEASSERT_U) ;
-#endif /* MOT_ELM */
-               }
-       }
-
-       /*
-        * set timer register
-        */
-       for ( i = 0 ; pltm[i].timer; i++)       /* set timer parameter reg */
-               outpw(PLC(p,pltm[i].timer),pltm[i].para) ;
-
-       (void)inpw(PLC(p,PL_INTR_EVENT)) ;      /* clear interrupt event reg */
-       plc_clear_irq(smc,p) ;
-       outpw(PLC(p,PL_INTR_MASK),plc_imsk_na); /* enable non active irq's */
-
-       /*
-        * if PCM is configured for class s, it will NOT go to the
-        * REMOVE state if offline (page 3-36;)
-        * in the concentrator, all inactive PHYS always must be in
-        * the remove state
-        * there's no real need to use this feature at all ..
-        */
-#ifndef        CONCENTRATOR
-       if ((smc->s.sas == SMT_SAS) && (p == PS)) {
-               outpw(PLC(p,PL_CNTRL_B),PL_CLASS_S) ;
-       }
-#endif
-}
-
-/*
- * control PCM state machine
- */
-static void plc_go_state(struct s_smc *smc, int p, int state)
-{
-       HW_PTR port ;
-       int val ;
-
-       SK_UNUSED(smc) ;
-
-       port = (HW_PTR) (PLC(p,PL_CNTRL_B)) ;
-       val = inpw(port) & ~(PL_PCM_CNTRL | PL_MAINT) ;
-       outpw(port,val) ;
-       outpw(port,val | state) ;
-}
-
-/*
- * read current line state (called by ECM & PCM)
- */
-int sm_pm_get_ls(struct s_smc *smc, int phy)
-{
-       int     state ;
-
-#ifdef CONCENTRATOR
-       if (!plc_is_installed(smc,phy))
-               return PC_QLS;
-#endif
-
-       state = inpw(PLC(phy,PL_STATUS_A)) & PL_LINE_ST ;
-       switch(state) {
-       case PL_L_QLS:
-               state = PC_QLS ;
-               break ;
-       case PL_L_MLS:
-               state = PC_MLS ;
-               break ;
-       case PL_L_HLS:
-               state = PC_HLS ;
-               break ;
-       case PL_L_ILS4:
-       case PL_L_ILS16:
-               state = PC_ILS ;
-               break ;
-       case PL_L_ALS:
-               state = PC_LS_PDR ;
-               break ;
-       default :
-               state = PC_LS_NONE ;
-       }
-       return state;
-}
-
-static int plc_send_bits(struct s_smc *smc, struct s_phy *phy, int len)
-{
-       int np = phy->np ;              /* PHY index */
-       int     n ;
-       int     i ;
-
-       SK_UNUSED(smc) ;
-
-       /* create bit vector */
-       for (i = len-1,n = 0 ; i >= 0 ; i--) {
-               n = (n<<1) | phy->t_val[phy->bitn+i] ;
-       }
-       if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
-#if    0
-               printf("PL_PCM_SIGNAL is set\n") ;
-#endif
-               return 1;
-       }
-       /* write bit[n] & length = 1 to regs */
-       outpw(PLC(np,PL_VECTOR_LEN),len-1) ;    /* len=nr-1 */
-       outpw(PLC(np,PL_XMIT_VECTOR),n) ;
-#ifdef DEBUG
-#if 1
-#ifdef DEBUG_BRD
-       if (smc->debug.d_plc & 0x80)
-#else
-       if (debug.d_plc & 0x80)
-#endif
-               printf("SIGNALING bit %d .. %d\n",phy->bitn,phy->bitn+len-1) ;
-#endif
-#endif
-       return 0;
-}
-
-/*
- * config plc muxes
- */
-void plc_config_mux(struct s_smc *smc, int mux)
-{
-       if (smc->s.sas != SMT_DAS)
-               return ;
-       if (mux == MUX_WRAPB) {
-               SETMASK(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
-               SETMASK(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
-       }
-       else {
-               CLEAR(PLC(PA,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
-               CLEAR(PLC(PA,PL_CNTRL_A),PL_SC_REM_LOOP) ;
-       }
-       CLEAR(PLC(PB,PL_CNTRL_B),PL_CONFIG_CNTRL) ;
-       CLEAR(PLC(PB,PL_CNTRL_A),PL_SC_REM_LOOP) ;
-}
-
-/*
-       PCM state machine
-       called by dispatcher  & fddi_init() (driver)
-       do
-               display state change
-               process event
-       until SM is stable
-*/
-void pcm(struct s_smc *smc, const int np, int event)
-{
-       int     state ;
-       int     oldstate ;
-       struct s_phy    *phy ;
-       struct fddi_mib_p       *mib ;
-
-#ifndef        CONCENTRATOR
-       /*
-        * ignore 2nd PHY if SAS
-        */
-       if ((np != PS) && (smc->s.sas == SMT_SAS))
-               return ;
-#endif
-       phy = &smc->y[np] ;
-       mib = phy->mib ;
-       oldstate = mib->fddiPORTPCMState ;
-       do {
-               DB_PCM("PCM %c: state %s",
-                       phy->phy_name,
-                       (mib->fddiPORTPCMState & AFLAG) ? "ACTIONS " : "") ;
-               DB_PCM("%s, event %s\n",
-                       pcm_states[mib->fddiPORTPCMState & ~AFLAG],
-                       pcm_events[event]) ;
-               state = mib->fddiPORTPCMState ;
-               pcm_fsm(smc,phy,event) ;
-               event = 0 ;
-       } while (state != mib->fddiPORTPCMState) ;
-       /*
-        * because the PLC does the bit signaling for us,
-        * we're always in SIGNAL state
-        * the MIB want's to see CONNECT
-        * we therefore fake an entry in the MIB
-        */
-       if (state == PC5_SIGNAL)
-               mib->fddiPORTPCMStateX = PC3_CONNECT ;
-       else
-               mib->fddiPORTPCMStateX = state ;
-
-#ifndef        SLIM_SMT
-       /*
-        * path change
-        */
-       if (    mib->fddiPORTPCMState != oldstate &&
-               ((oldstate == PC8_ACTIVE) || (mib->fddiPORTPCMState == PC8_ACTIVE))) {
-               smt_srf_event(smc,SMT_EVENT_PORT_PATH_CHANGE,
-                       (int) (INDEX_PORT+ phy->np),0) ;
-       }
-#endif
-
-#ifdef FDDI_MIB
-       /* check whether a snmp-trap has to be sent */
-
-       if ( mib->fddiPORTPCMState != oldstate ) {
-               /* a real state change took place */
-               DB_SNMP ("PCM from %d to %d\n", oldstate, mib->fddiPORTPCMState);
-               if ( mib->fddiPORTPCMState == PC0_OFF ) {
-                       /* send first trap */
-                       snmp_fddi_trap (smc, 1, (int) mib->fddiPORTIndex );
-               } else if ( oldstate == PC0_OFF ) {
-                       /* send second trap */
-                       snmp_fddi_trap (smc, 2, (int) mib->fddiPORTIndex );
-               } else if ( mib->fddiPORTPCMState != PC2_TRACE &&
-                       oldstate == PC8_ACTIVE ) {
-                       /* send third trap */
-                       snmp_fddi_trap (smc, 3, (int) mib->fddiPORTIndex );
-               } else if ( mib->fddiPORTPCMState == PC8_ACTIVE ) {
-                       /* send fourth trap */
-                       snmp_fddi_trap (smc, 4, (int) mib->fddiPORTIndex );
-               }
-       }
-#endif
-
-       pcm_state_change(smc,np,state) ;
-}
-
-/*
- * PCM state machine
- */
-static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd)
-{
-       int     i ;
-       int     np = phy->np ;          /* PHY index */
-       struct s_plc    *plc ;
-       struct fddi_mib_p       *mib ;
-#ifndef        MOT_ELM
-       u_short plc_rev ;               /* Revision of the plc */
-#endif /* nMOT_ELM */
-
-       plc = &phy->plc ;
-       mib = phy->mib ;
-
-       /*
-        * general transitions independent of state
-        */
-       switch (cmd) {
-       case PC_STOP :
-               /*PC00-PC80*/
-               if (mib->fddiPORTPCMState != PC9_MAINT) {
-                       GO_STATE(PC0_OFF) ;
-                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                               FDDI_PORT_EVENT, (u_long) FDDI_PORT_STOP,
-                               smt_get_port_event_word(smc));
-               }
-               return ;
-       case PC_START :
-               /*PC01-PC81*/
-               if (mib->fddiPORTPCMState != PC9_MAINT)
-                       GO_STATE(PC1_BREAK) ;
-               return ;
-       case PC_DISABLE :
-               /* PC09-PC99 */
-               GO_STATE(PC9_MAINT) ;
-               AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                       FDDI_PORT_EVENT, (u_long) FDDI_PORT_DISABLED,
-                       smt_get_port_event_word(smc));
-               return ;
-       case PC_TIMEOUT_LCT :
-               /* if long or extended LCT */
-               stop_pcm_timer0(smc,phy) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
-               /* end of LCT is indicate by PCM_CODE (initiate PCM event) */
-               return ;
-       }
-
-       switch(mib->fddiPORTPCMState) {
-       case ACTIONS(PC0_OFF) :
-               stop_pcm_timer0(smc,phy) ;
-               outpw(PLC(np,PL_CNTRL_A),0) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
-               sm_ph_lem_stop(smc,np) ;                /* disable LEM */
-               phy->cf_loop = FALSE ;
-               phy->cf_join = FALSE ;
-               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
-               plc_go_state(smc,np,PL_PCM_STOP) ;
-               mib->fddiPORTConnectState = PCM_DISABLED ;
-               ACTIONS_DONE() ;
-               break ;
-       case PC0_OFF:
-               /*PC09*/
-               if (cmd == PC_MAINT) {
-                       GO_STATE(PC9_MAINT) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(PC1_BREAK) :
-               /* Stop the LCT timer if we came from Signal state */
-               stop_pcm_timer0(smc,phy) ;
-               ACTIONS_DONE() ;
-               plc_go_state(smc,np,0) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
-               sm_ph_lem_stop(smc,np) ;                /* disable LEM */
-               /*
-                * if vector is already loaded, go to OFF to clear PCM_SIGNAL
-                */
-#if    0
-               if (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL) {
-                       plc_go_state(smc,np,PL_PCM_STOP) ;
-                       /* TB_MIN ? */
-               }
-#endif
-               /*
-                * Go to OFF state in any case.
-                */
-               plc_go_state(smc,np,PL_PCM_STOP) ;
-
-               if (mib->fddiPORTPC_Withhold == PC_WH_NONE)
-                       mib->fddiPORTConnectState = PCM_CONNECTING ;
-               phy->cf_loop = FALSE ;
-               phy->cf_join = FALSE ;
-               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
-               phy->ls_flag = FALSE ;
-               phy->pc_mode = PM_NONE ;        /* needed by CFM */
-               phy->bitn = 0 ;                 /* bit signaling start bit */
-               for (i = 0 ; i < 3 ; i++)
-                       pc_tcode_actions(smc,i,phy) ;
-
-               /* Set the non-active interrupt mask register */
-               outpw(PLC(np,PL_INTR_MASK),plc_imsk_na) ;
-
-               /*
-                * If the LCT was stopped. There might be a
-                * PCM_CODE interrupt event present.
-                * This must be cleared.
-                */
-               (void)inpw(PLC(np,PL_INTR_EVENT)) ;
-#ifndef        MOT_ELM
-               /* Get the plc revision for revision dependent code */
-               plc_rev = inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK ;
-
-               if (plc_rev != PLC_REV_SN3)
-#endif /* MOT_ELM */
-               {
-                       /*
-                        * No supernet III PLC, so set Xmit verctor and
-                        * length BEFORE starting the state machine.
-                        */
-                       if (plc_send_bits(smc,phy,3)) {
-                               return ;
-                       }
-               }
-
-               /*
-                * Now give the Start command.
-                * - The start command shall be done before setting the bits
-                *   to be signaled. (In PLC-S description and PLCS in SN3.
-                * - The start command shall be issued AFTER setting the
-                *   XMIT vector and the XMIT length register.
-                *
-                * We do it exactly according this specs for the old PLC and
-                * the new PLCS inside the SN3.
-                * For the usual PLCS we try it the way it is done for the
-                * old PLC and set the XMIT registers again, if the PLC is
-                * not in SIGNAL state. This is done according to an PLCS
-                * errata workaround.
-                */
-
-               plc_go_state(smc,np,PL_PCM_START) ;
-
-               /*
-                * workaround for PLC-S eng. sample errata
-                */
-#ifdef MOT_ELM
-               if (!(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
-#else  /* nMOT_ELM */
-               if (((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) !=
-                       PLC_REVISION_A) &&
-                       !(inpw(PLC(np,PL_STATUS_B)) & PL_PCM_SIGNAL))
-#endif /* nMOT_ELM */
-               {
-                       /*
-                        * Set register again (PLCS errata) or the first time
-                        * (new SN3 PLCS).
-                        */
-                       (void) plc_send_bits(smc,phy,3) ;
-               }
-               /*
-                * end of workaround
-                */
-
-               GO_STATE(PC5_SIGNAL) ;
-               plc->p_state = PS_BIT3 ;
-               plc->p_bits = 3 ;
-               plc->p_start = 0 ;
-
-               break ;
-       case PC1_BREAK :
-               break ;
-       case ACTIONS(PC2_TRACE) :
-               plc_go_state(smc,np,PL_PCM_TRACE) ;
-               ACTIONS_DONE() ;
-               break ;
-       case PC2_TRACE :
-               break ;
-
-       case PC3_CONNECT :      /* these states are done by hardware */
-       case PC4_NEXT :
-               break ;
-
-       case ACTIONS(PC5_SIGNAL) :
-               ACTIONS_DONE() ;
-       case PC5_SIGNAL :
-               if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT))
-                       break ;
-               switch (plc->p_state) {
-               case PS_BIT3 :
-                       for (i = 0 ; i <= 2 ; i++)
-                               pc_rcode_actions(smc,i,phy) ;
-                       pc_tcode_actions(smc,3,phy) ;
-                       plc->p_state = PS_BIT4 ;
-                       plc->p_bits = 1 ;
-                       plc->p_start = 3 ;
-                       phy->bitn = 3 ;
-                       if (plc_send_bits(smc,phy,1)) {
-                               return ;
-                       }
-                       break ;
-               case PS_BIT4 :
-                       pc_rcode_actions(smc,3,phy) ;
-                       for (i = 4 ; i <= 6 ; i++)
-                               pc_tcode_actions(smc,i,phy) ;
-                       plc->p_state = PS_BIT7 ;
-                       plc->p_bits = 3 ;
-                       plc->p_start = 4 ;
-                       phy->bitn = 4 ;
-                       if (plc_send_bits(smc,phy,3)) {
-                               return ;
-                       }
-                       break ;
-               case PS_BIT7 :
-                       for (i = 3 ; i <= 6 ; i++)
-                               pc_rcode_actions(smc,i,phy) ;
-                       plc->p_state = PS_LCT ;
-                       plc->p_bits = 0 ;
-                       plc->p_start = 7 ;
-                       phy->bitn = 7 ;
-               sm_ph_lem_start(smc,np,(int)smc->s.lct_short) ; /* enable LEM */
-                       /* start LCT */
-                       i = inpw(PLC(np,PL_CNTRL_B)) & ~PL_PC_LOOP ;
-                       outpw(PLC(np,PL_CNTRL_B),i) ;   /* must be cleared */
-                       outpw(PLC(np,PL_CNTRL_B),i | PL_RLBP) ;
-                       break ;
-               case PS_LCT :
-                       /* check for local LCT failure */
-                       pc_tcode_actions(smc,7,phy) ;
-                       /*
-                        * set tval[7]
-                        */
-                       plc->p_state = PS_BIT8 ;
-                       plc->p_bits = 1 ;
-                       plc->p_start = 7 ;
-                       phy->bitn = 7 ;
-                       if (plc_send_bits(smc,phy,1)) {
-                               return ;
-                       }
-                       break ;
-               case PS_BIT8 :
-                       /* check for remote LCT failure */
-                       pc_rcode_actions(smc,7,phy) ;
-                       if (phy->t_val[7] || phy->r_val[7]) {
-                               plc_go_state(smc,np,PL_PCM_STOP) ;
-                               GO_STATE(PC1_BREAK) ;
-                               break ;
-                       }
-                       for (i = 8 ; i <= 9 ; i++)
-                               pc_tcode_actions(smc,i,phy) ;
-                       plc->p_state = PS_JOIN ;
-                       plc->p_bits = 2 ;
-                       plc->p_start = 8 ;
-                       phy->bitn = 8 ;
-                       if (plc_send_bits(smc,phy,2)) {
-                               return ;
-                       }
-                       break ;
-               case PS_JOIN :
-                       for (i = 8 ; i <= 9 ; i++)
-                               pc_rcode_actions(smc,i,phy) ;
-                       plc->p_state = PS_ACTIVE ;
-                       GO_STATE(PC6_JOIN) ;
-                       break ;
-               }
-               break ;
-
-       case ACTIONS(PC6_JOIN) :
-               /*
-                * prevent mux error when going from WRAP_A to WRAP_B
-                */
-               if (smc->s.sas == SMT_DAS && np == PB &&
-                       (smc->y[PA].pc_mode == PM_TREE ||
-                        smc->y[PB].pc_mode == PM_TREE)) {
-                       SETMASK(PLC(np,PL_CNTRL_A),
-                               PL_SC_REM_LOOP,PL_SC_REM_LOOP) ;
-                       SETMASK(PLC(np,PL_CNTRL_B),
-                               PL_CONFIG_CNTRL,PL_CONFIG_CNTRL) ;
-               }
-               SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
-               SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ;
-               ACTIONS_DONE() ;
-               cmd = 0 ;
-               /* fall thru */
-       case PC6_JOIN :
-               switch (plc->p_state) {
-               case PS_ACTIVE:
-                       /*PC88b*/
-                       if (!phy->cf_join) {
-                               phy->cf_join = TRUE ;
-                               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
-                       }
-                       if (cmd == PC_JOIN)
-                               GO_STATE(PC8_ACTIVE) ;
-                       /*PC82*/
-                       if (cmd == PC_TRACE) {
-                               GO_STATE(PC2_TRACE) ;
-                               break ;
-                       }
-                       break ;
-               }
-               break ;
-
-       case PC7_VERIFY :
-               break ;
-
-       case ACTIONS(PC8_ACTIVE) :
-               /*
-                * start LEM for SMT
-                */
-               sm_ph_lem_start(smc,(int)phy->np,LCT_LEM_MAX) ;
-
-               phy->tr_flag = FALSE ;
-               mib->fddiPORTConnectState = PCM_ACTIVE ;
-
-               /* Set the active interrupt mask register */
-               outpw(PLC(np,PL_INTR_MASK),plc_imsk_act) ;
-
-               ACTIONS_DONE() ;
-               break ;
-       case PC8_ACTIVE :
-               /*PC81 is done by PL_TNE_EXPIRED irq */
-               /*PC82*/
-               if (cmd == PC_TRACE) {
-                       GO_STATE(PC2_TRACE) ;
-                       break ;
-               }
-               /*PC88c: is done by TRACE_PROP irq */
-
-               break ;
-       case ACTIONS(PC9_MAINT) :
-               stop_pcm_timer0(smc,phy) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_PC_JOIN) ;
-               CLEAR(PLC(np,PL_CNTRL_B),PL_LONG) ;
-               CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ; /* disable LEM int. */
-               sm_ph_lem_stop(smc,np) ;                /* disable LEM */
-               phy->cf_loop = FALSE ;
-               phy->cf_join = FALSE ;
-               queue_event(smc,EVENT_CFM,CF_JOIN+np) ;
-               plc_go_state(smc,np,PL_PCM_STOP) ;
-               mib->fddiPORTConnectState = PCM_DISABLED ;
-               SETMASK(PLC(np,PL_CNTRL_B),PL_MAINT,PL_MAINT) ;
-               sm_ph_linestate(smc,np,(int) MIB2LS(mib->fddiPORTMaint_LS)) ;
-               outpw(PLC(np,PL_CNTRL_A),PL_SC_BYPASS) ;
-               ACTIONS_DONE() ;
-               break ;
-       case PC9_MAINT :
-               DB_PCMN(1,"PCM %c : MAINT\n",phy->phy_name,0) ;
-               /*PC90*/
-               if (cmd == PC_ENABLE) {
-                       GO_STATE(PC0_OFF) ;
-                       break ;
-               }
-               break ;
-
-       default:
-               SMT_PANIC(smc,SMT_E0118, SMT_E0118_MSG) ;
-               break ;
-       }
-}
-
-/*
- * force line state on a PHY output    (only in MAINT state)
- */
-static void sm_ph_linestate(struct s_smc *smc, int phy, int ls)
-{
-       int     cntrl ;
-
-       SK_UNUSED(smc) ;
-
-       cntrl = (inpw(PLC(phy,PL_CNTRL_B)) & ~PL_MAINT_LS) |
-                                               PL_PCM_STOP | PL_MAINT ;
-       switch(ls) {
-       case PC_QLS:            /* Force Quiet */
-               cntrl |= PL_M_QUI0 ;
-               break ;
-       case PC_MLS:            /* Force Master */
-               cntrl |= PL_M_MASTR ;
-               break ;
-       case PC_HLS:            /* Force Halt */
-               cntrl |= PL_M_HALT ;
-               break ;
-       default :
-       case PC_ILS:            /* Force Idle */
-               cntrl |= PL_M_IDLE ;
-               break ;
-       case PC_LS_PDR:         /* Enable repeat filter */
-               cntrl |= PL_M_TPDR ;
-               break ;
-       }
-       outpw(PLC(phy,PL_CNTRL_B),cntrl) ;
-}
-
-static void reset_lem_struct(struct s_phy *phy)
-{
-       struct lem_counter *lem = &phy->lem ;
-
-       phy->mib->fddiPORTLer_Estimate = 15 ;
-       lem->lem_float_ber = 15 * 100 ;
-}
-
-/*
- * link error monitor
- */
-static void lem_evaluate(struct s_smc *smc, struct s_phy *phy)
-{
-       int ber ;
-       u_long errors ;
-       struct lem_counter *lem = &phy->lem ;
-       struct fddi_mib_p       *mib ;
-       int                     cond ;
-
-       mib = phy->mib ;
-
-       if (!lem->lem_on)
-               return ;
-
-       errors = inpw(PLC(((int) phy->np),PL_LINK_ERR_CTR)) ;
-       lem->lem_errors += errors ;
-       mib->fddiPORTLem_Ct += errors ;
-
-       errors = lem->lem_errors ;
-       /*
-        * calculation is called on a intervall of 8 seconds
-        *      -> this means, that one error in 8 sec. is one of 8*125*10E6
-        *      the same as BER = 10E-9
-        * Please note:
-        *      -> 9 errors in 8 seconds mean:
-        *         BER = 9 * 10E-9  and this is
-        *          < 10E-8, so the limit of 10E-8 is not reached!
-        */
-
-               if (!errors)            ber = 15 ;
-       else    if (errors <= 9)        ber = 9 ;
-       else    if (errors <= 99)       ber = 8 ;
-       else    if (errors <= 999)      ber = 7 ;
-       else    if (errors <= 9999)     ber = 6 ;
-       else    if (errors <= 99999)    ber = 5 ;
-       else    if (errors <= 999999)   ber = 4 ;
-       else    if (errors <= 9999999)  ber = 3 ;
-       else    if (errors <= 99999999) ber = 2 ;
-       else    if (errors <= 999999999) ber = 1 ;
-       else                            ber = 0 ;
-
-       /*
-        * weighted average
-        */
-       ber *= 100 ;
-       lem->lem_float_ber = lem->lem_float_ber * 7 + ber * 3 ;
-       lem->lem_float_ber /= 10 ;
-       mib->fddiPORTLer_Estimate = lem->lem_float_ber / 100 ;
-       if (mib->fddiPORTLer_Estimate < 4) {
-               mib->fddiPORTLer_Estimate = 4 ;
-       }
-
-       if (lem->lem_errors) {
-               DB_PCMN(1,"LEM %c :\n",phy->np == PB? 'B' : 'A',0) ;
-               DB_PCMN(1,"errors      : %ld\n",lem->lem_errors,0) ;
-               DB_PCMN(1,"sum_errors  : %ld\n",mib->fddiPORTLem_Ct,0) ;
-               DB_PCMN(1,"current BER : 10E-%d\n",ber/100,0) ;
-               DB_PCMN(1,"float BER   : 10E-(%d/100)\n",lem->lem_float_ber,0) ;
-               DB_PCMN(1,"avg. BER    : 10E-%d\n",
-                       mib->fddiPORTLer_Estimate,0) ;
-       }
-
-       lem->lem_errors = 0L ;
-
-#ifndef        SLIM_SMT
-       cond = (mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Alarm) ?
-               TRUE : FALSE ;
-#ifdef SMT_EXT_CUTOFF
-       smt_ler_alarm_check(smc,phy,cond) ;
-#endif /* nSMT_EXT_CUTOFF */
-       if (cond != mib->fddiPORTLerFlag) {
-               smt_srf_event(smc,SMT_COND_PORT_LER,
-                       (int) (INDEX_PORT+ phy->np) ,cond) ;
-       }
-#endif
-
-       if (    mib->fddiPORTLer_Estimate <= mib->fddiPORTLer_Cutoff) {
-               phy->pc_lem_fail = TRUE ;               /* flag */
-               mib->fddiPORTLem_Reject_Ct++ ;
-               /*
-                * "forgive 10e-2" if we cutoff so we can come
-                * up again ..
-                */
-               lem->lem_float_ber += 2*100 ;
-
-               /*PC81b*/
-#ifdef CONCENTRATOR
-               DB_PCMN(1,"PCM: LER cutoff on port %d cutoff %d\n",
-                       phy->np, mib->fddiPORTLer_Cutoff) ;
-#endif
-#ifdef SMT_EXT_CUTOFF
-               smt_port_off_event(smc,phy->np);
-#else  /* nSMT_EXT_CUTOFF */
-               queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
-#endif /* nSMT_EXT_CUTOFF */
-       }
-}
-
-/*
- * called by SMT to calculate LEM bit error rate
- */
-void sm_lem_evaluate(struct s_smc *smc)
-{
-       int np ;
-
-       for (np = 0 ; np < NUMPHYS ; np++)
-               lem_evaluate(smc,&smc->y[np]) ;
-}
-
-static void lem_check_lct(struct s_smc *smc, struct s_phy *phy)
-{
-       struct lem_counter      *lem = &phy->lem ;
-       struct fddi_mib_p       *mib ;
-       int errors ;
-
-       mib = phy->mib ;
-
-       phy->pc_lem_fail = FALSE ;              /* flag */
-       errors = inpw(PLC(((int)phy->np),PL_LINK_ERR_CTR)) ;
-       lem->lem_errors += errors ;
-       mib->fddiPORTLem_Ct += errors ;
-       if (lem->lem_errors) {
-               switch(phy->lc_test) {
-               case LC_SHORT:
-                       if (lem->lem_errors >= smc->s.lct_short)
-                               phy->pc_lem_fail = TRUE ;
-                       break ;
-               case LC_MEDIUM:
-                       if (lem->lem_errors >= smc->s.lct_medium)
-                               phy->pc_lem_fail = TRUE ;
-                       break ;
-               case LC_LONG:
-                       if (lem->lem_errors >= smc->s.lct_long)
-                               phy->pc_lem_fail = TRUE ;
-                       break ;
-               case LC_EXTENDED:
-                       if (lem->lem_errors >= smc->s.lct_extended)
-                               phy->pc_lem_fail = TRUE ;
-                       break ;
-               }
-               DB_PCMN(1," >>errors : %d\n",lem->lem_errors,0) ;
-       }
-       if (phy->pc_lem_fail) {
-               mib->fddiPORTLCTFail_Ct++ ;
-               mib->fddiPORTLem_Reject_Ct++ ;
-       }
-       else
-               mib->fddiPORTLCTFail_Ct = 0 ;
-}
-
-/*
- * LEM functions
- */
-static void sm_ph_lem_start(struct s_smc *smc, int np, int threshold)
-{
-       struct lem_counter *lem = &smc->y[np].lem ;
-
-       lem->lem_on = 1 ;
-       lem->lem_errors = 0L ;
-
-       /* Do NOT reset mib->fddiPORTLer_Estimate here. It is called too
-        * often.
-        */
-
-       outpw(PLC(np,PL_LE_THRESHOLD),threshold) ;
-       (void)inpw(PLC(np,PL_LINK_ERR_CTR)) ;   /* clear error counter */
-
-       /* enable LE INT */
-       SETMASK(PLC(np,PL_INTR_MASK),PL_LE_CTR,PL_LE_CTR) ;
-}
-
-static void sm_ph_lem_stop(struct s_smc *smc, int np)
-{
-       struct lem_counter *lem = &smc->y[np].lem ;
-
-       lem->lem_on = 0 ;
-       CLEAR(PLC(np,PL_INTR_MASK),PL_LE_CTR) ;
-}
-
-/* ARGSUSED */
-void sm_pm_ls_latch(struct s_smc *smc, int phy, int on_off)
-/* int on_off; en- or disable ident. ls */
-{
-       SK_UNUSED(smc) ;
-
-       phy = phy ; on_off = on_off ;
-}
-
-
-/*
- * PCM pseudo code
- * receive actions are called AFTER the bit n is received,
- * i.e. if pc_rcode_actions(5) is called, bit 6 is the next bit to be received
- */
-
-/*
- * PCM pseudo code 5.1 .. 6.1
- */
-static void pc_rcode_actions(struct s_smc *smc, int bit, struct s_phy *phy)
-{
-       struct fddi_mib_p       *mib ;
-
-       mib = phy->mib ;
-
-       DB_PCMN(1,"SIG rec %x %x:\n", bit,phy->r_val[bit] ) ;
-       bit++ ;
-
-       switch(bit) {
-       case 0:
-       case 1:
-       case 2:
-               break ;
-       case 3 :
-               if (phy->r_val[1] == 0 && phy->r_val[2] == 0)
-                       mib->fddiPORTNeighborType = TA ;
-               else if (phy->r_val[1] == 0 && phy->r_val[2] == 1)
-                       mib->fddiPORTNeighborType = TB ;
-               else if (phy->r_val[1] == 1 && phy->r_val[2] == 0)
-                       mib->fddiPORTNeighborType = TS ;
-               else if (phy->r_val[1] == 1 && phy->r_val[2] == 1)
-                       mib->fddiPORTNeighborType = TM ;
-               break ;
-       case 4:
-               if (mib->fddiPORTMy_Type == TM &&
-                       mib->fddiPORTNeighborType == TM) {
-                       DB_PCMN(1,"PCM %c : E100 withhold M-M\n",
-                               phy->phy_name,0) ;
-                       mib->fddiPORTPC_Withhold = PC_WH_M_M ;
-                       RS_SET(smc,RS_EVENT) ;
-               }
-               else if (phy->t_val[3] || phy->r_val[3]) {
-                       mib->fddiPORTPC_Withhold = PC_WH_NONE ;
-                       if (mib->fddiPORTMy_Type == TM ||
-                           mib->fddiPORTNeighborType == TM)
-                               phy->pc_mode = PM_TREE ;
-                       else
-                               phy->pc_mode = PM_PEER ;
-
-                       /* reevaluate the selection criteria (wc_flag) */
-                       all_selection_criteria (smc);
-
-                       if (phy->wc_flag) {
-                               mib->fddiPORTPC_Withhold = PC_WH_PATH ;
-                       }
-               }
-               else {
-                       mib->fddiPORTPC_Withhold = PC_WH_OTHER ;
-                       RS_SET(smc,RS_EVENT) ;
-                       DB_PCMN(1,"PCM %c : E101 withhold other\n",
-                               phy->phy_name,0) ;
-               }
-               phy->twisted = ((mib->fddiPORTMy_Type != TS) &&
-                               (mib->fddiPORTMy_Type != TM) &&
-                               (mib->fddiPORTNeighborType ==
-                               mib->fddiPORTMy_Type)) ;
-               if (phy->twisted) {
-                       DB_PCMN(1,"PCM %c : E102 !!! TWISTED !!!\n",
-                               phy->phy_name,0) ;
-               }
-               break ;
-       case 5 :
-               break ;
-       case 6:
-               if (phy->t_val[4] || phy->r_val[4]) {
-                       if ((phy->t_val[4] && phy->t_val[5]) ||
-                           (phy->r_val[4] && phy->r_val[5]) )
-                               phy->lc_test = LC_EXTENDED ;
-                       else
-                               phy->lc_test = LC_LONG ;
-               }
-               else if (phy->t_val[5] || phy->r_val[5])
-                       phy->lc_test = LC_MEDIUM ;
-               else
-                       phy->lc_test = LC_SHORT ;
-               switch (phy->lc_test) {
-               case LC_SHORT :                         /* 50ms */
-                       outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LENGTH ) ;
-                       phy->t_next[7] = smc->s.pcm_lc_short ;
-                       break ;
-               case LC_MEDIUM :                        /* 500ms */
-                       outpw(PLC((int)phy->np,PL_LC_LENGTH), TP_LC_LONGLN ) ;
-                       phy->t_next[7] = smc->s.pcm_lc_medium ;
-                       break ;
-               case LC_LONG :
-                       SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
-                       phy->t_next[7] = smc->s.pcm_lc_long ;
-                       break ;
-               case LC_EXTENDED :
-                       SETMASK(PLC((int)phy->np,PL_CNTRL_B),PL_LONG,PL_LONG) ;
-                       phy->t_next[7] = smc->s.pcm_lc_extended ;
-                       break ;
-               }
-               if (phy->t_next[7] > smc->s.pcm_lc_medium) {
-                       start_pcm_timer0(smc,phy->t_next[7],PC_TIMEOUT_LCT,phy);
-               }
-               DB_PCMN(1,"LCT timer = %ld us\n", phy->t_next[7], 0) ;
-               phy->t_next[9] = smc->s.pcm_t_next_9 ;
-               break ;
-       case 7:
-               if (phy->t_val[6]) {
-                       phy->cf_loop = TRUE ;
-               }
-               phy->td_flag = TRUE ;
-               break ;
-       case 8:
-               if (phy->t_val[7] || phy->r_val[7]) {
-                       DB_PCMN(1,"PCM %c : E103 LCT fail %s\n",
-                               phy->phy_name,phy->t_val[7]? "local":"remote") ;
-                       queue_event(smc,(int)(EVENT_PCM+phy->np),PC_START) ;
-               }
-               break ;
-       case 9:
-               if (phy->t_val[8] || phy->r_val[8]) {
-                       if (phy->t_val[8])
-                               phy->cf_loop = TRUE ;
-                       phy->td_flag = TRUE ;
-               }
-               break ;
-       case 10:
-               if (phy->r_val[9]) {
-                       /* neighbor intends to have MAC on output */ ;
-                       mib->fddiPORTMacIndicated.R_val = TRUE ;
-               }
-               else {
-                       /* neighbor does not intend to have MAC on output */ ;
-                       mib->fddiPORTMacIndicated.R_val = FALSE ;
-               }
-               break ;
-       }
-}
-
-/*
- * PCM pseudo code 5.1 .. 6.1
- */
-static void pc_tcode_actions(struct s_smc *smc, const int bit, struct s_phy *phy)
-{
-       int     np = phy->np ;
-       struct fddi_mib_p       *mib ;
-
-       mib = phy->mib ;
-
-       switch(bit) {
-       case 0:
-               phy->t_val[0] = 0 ;             /* no escape used */
-               break ;
-       case 1:
-               if (mib->fddiPORTMy_Type == TS || mib->fddiPORTMy_Type == TM)
-                       phy->t_val[1] = 1 ;
-               else
-                       phy->t_val[1] = 0 ;
-               break ;
-       case 2 :
-               if (mib->fddiPORTMy_Type == TB || mib->fddiPORTMy_Type == TM)
-                       phy->t_val[2] = 1 ;
-               else
-                       phy->t_val[2] = 0 ;
-               break ;
-       case 3:
-               {
-               int     type,ne ;
-               int     policy ;
-
-               type = mib->fddiPORTMy_Type ;
-               ne = mib->fddiPORTNeighborType ;
-               policy = smc->mib.fddiSMTConnectionPolicy ;
-
-               phy->t_val[3] = 1 ;     /* Accept connection */
-               switch (type) {
-               case TA :
-                       if (
-                               ((policy & POLICY_AA) && ne == TA) ||
-                               ((policy & POLICY_AB) && ne == TB) ||
-                               ((policy & POLICY_AS) && ne == TS) ||
-                               ((policy & POLICY_AM) && ne == TM) )
-                               phy->t_val[3] = 0 ;     /* Reject */
-                       break ;
-               case TB :
-                       if (
-                               ((policy & POLICY_BA) && ne == TA) ||
-                               ((policy & POLICY_BB) && ne == TB) ||
-                               ((policy & POLICY_BS) && ne == TS) ||
-                               ((policy & POLICY_BM) && ne == TM) )
-                               phy->t_val[3] = 0 ;     /* Reject */
-                       break ;
-               case TS :
-                       if (
-                               ((policy & POLICY_SA) && ne == TA) ||
-                               ((policy & POLICY_SB) && ne == TB) ||
-                               ((policy & POLICY_SS) && ne == TS) ||
-                               ((policy & POLICY_SM) && ne == TM) )
-                               phy->t_val[3] = 0 ;     /* Reject */
-                       break ;
-               case TM :
-                       if (    ne == TM ||
-                               ((policy & POLICY_MA) && ne == TA) ||
-                               ((policy & POLICY_MB) && ne == TB) ||
-                               ((policy & POLICY_MS) && ne == TS) ||
-                               ((policy & POLICY_MM) && ne == TM) )
-                               phy->t_val[3] = 0 ;     /* Reject */
-                       break ;
-               }
-#ifndef        SLIM_SMT
-               /*
-                * detect undesirable connection attempt event
-                */
-               if (    (type == TA && ne == TA ) ||
-                       (type == TA && ne == TS ) ||
-                       (type == TB && ne == TB ) ||
-                       (type == TB && ne == TS ) ||
-                       (type == TS && ne == TA ) ||
-                       (type == TS && ne == TB ) ) {
-                       smt_srf_event(smc,SMT_EVENT_PORT_CONNECTION,
-                               (int) (INDEX_PORT+ phy->np) ,0) ;
-               }
-#endif
-               }
-               break ;
-       case 4:
-               if (mib->fddiPORTPC_Withhold == PC_WH_NONE) {
-                       if (phy->pc_lem_fail) {
-                               phy->t_val[4] = 1 ;     /* long */
-                               phy->t_val[5] = 0 ;
-                       }
-                       else {
-                               phy->t_val[4] = 0 ;
-                               if (mib->fddiPORTLCTFail_Ct > 0)
-                                       phy->t_val[5] = 1 ;     /* medium */
-                               else
-                                       phy->t_val[5] = 0 ;     /* short */
-
-                               /*
-                                * Implementers choice: use medium
-                                * instead of short when undesired
-                                * connection attempt is made.
-                                */
-                               if (phy->wc_flag)
-                                       phy->t_val[5] = 1 ;     /* medium */
-                       }
-                       mib->fddiPORTConnectState = PCM_CONNECTING ;
-               }
-               else {
-                       mib->fddiPORTConnectState = PCM_STANDBY ;
-                       phy->t_val[4] = 1 ;     /* extended */
-                       phy->t_val[5] = 1 ;
-               }
-               break ;
-       case 5:
-               break ;
-       case 6:
-               /* we do NOT have a MAC for LCT */
-               phy->t_val[6] = 0 ;
-               break ;
-       case 7:
-               phy->cf_loop = FALSE ;
-               lem_check_lct(smc,phy) ;
-               if (phy->pc_lem_fail) {
-                       DB_PCMN(1,"PCM %c : E104 LCT failed\n",
-                               phy->phy_name,0) ;
-                       phy->t_val[7] = 1 ;
-               }
-               else
-                       phy->t_val[7] = 0 ;
-               break ;
-       case 8:
-               phy->t_val[8] = 0 ;     /* Don't request MAC loopback */
-               break ;
-       case 9:
-               phy->cf_loop = 0 ;
-               if ((mib->fddiPORTPC_Withhold != PC_WH_NONE) ||
-                    ((smc->s.sas == SMT_DAS) && (phy->wc_flag))) {
-                       queue_event(smc,EVENT_PCM+np,PC_START) ;
-                       break ;
-               }
-               phy->t_val[9] = FALSE ;
-               switch (smc->s.sas) {
-               case SMT_DAS :
-                       /*
-                        * MAC intended on output
-                        */
-                       if (phy->pc_mode == PM_TREE) {
-                               if ((np == PB) || ((np == PA) &&
-                               (smc->y[PB].mib->fddiPORTConnectState !=
-                                       PCM_ACTIVE)))
-                                       phy->t_val[9] = TRUE ;
-                       }
-                       else {
-                               if (np == PB)
-                                       phy->t_val[9] = TRUE ;
-                       }
-                       break ;
-               case SMT_SAS :
-                       if (np == PS)
-                               phy->t_val[9] = TRUE ;
-                       break ;
-#ifdef CONCENTRATOR
-               case SMT_NAC :
-                       /*
-                        * MAC intended on output
-                        */
-                       if (np == PB)
-                               phy->t_val[9] = TRUE ;
-                       break ;
-#endif
-               }
-               mib->fddiPORTMacIndicated.T_val = phy->t_val[9] ;
-               break ;
-       }
-       DB_PCMN(1,"SIG snd %x %x:\n", bit,phy->t_val[bit] ) ;
-}
-
-/*
- * return status twisted (called by SMT)
- */
-int pcm_status_twisted(struct s_smc *smc)
-{
-       int     twist = 0 ;
-       if (smc->s.sas != SMT_DAS)
-               return 0;
-       if (smc->y[PA].twisted && (smc->y[PA].mib->fddiPORTPCMState == PC8_ACTIVE))
-               twist |= 1 ;
-       if (smc->y[PB].twisted && (smc->y[PB].mib->fddiPORTPCMState == PC8_ACTIVE))
-               twist |= 2 ;
-       return twist;
-}
-
-/*
- * return status       (called by SMT)
- *     type
- *     state
- *     remote phy type
- *     remote mac yes/no
- */
-void pcm_status_state(struct s_smc *smc, int np, int *type, int *state,
-                     int *remote, int *mac)
-{
-       struct s_phy    *phy = &smc->y[np] ;
-       struct fddi_mib_p       *mib ;
-
-       mib = phy->mib ;
-
-       /* remote PHY type and MAC - set only if active */
-       *mac = 0 ;
-       *type = mib->fddiPORTMy_Type ;          /* our PHY type */
-       *state = mib->fddiPORTConnectState ;
-       *remote = mib->fddiPORTNeighborType ;
-
-       switch(mib->fddiPORTPCMState) {
-       case PC8_ACTIVE :
-               *mac = mib->fddiPORTMacIndicated.R_val ;
-               break ;
-       }
-}
-
-/*
- * return rooted station status (called by SMT)
- */
-int pcm_rooted_station(struct s_smc *smc)
-{
-       int     n ;
-
-       for (n = 0 ; n < NUMPHYS ; n++) {
-               if (smc->y[n].mib->fddiPORTPCMState == PC8_ACTIVE &&
-                   smc->y[n].mib->fddiPORTNeighborType == TM)
-                       return 0;
-       }
-       return 1;
-}
-
-/*
- * Interrupt actions for PLC & PCM events
- */
-void plc_irq(struct s_smc *smc, int np, unsigned int cmd)
-/* int np;     PHY index */
-{
-       struct s_phy *phy = &smc->y[np] ;
-       struct s_plc *plc = &phy->plc ;
-       int             n ;
-#ifdef SUPERNET_3
-       int             corr_mask ;
-#endif /* SUPERNET_3 */
-       int             i ;
-
-       if (np >= smc->s.numphys) {
-               plc->soft_err++ ;
-               return ;
-       }
-       if (cmd & PL_EBUF_ERR) {        /* elastic buff. det. over-|underflow*/
-               /*
-                * Check whether the SRF Condition occurred.
-                */
-               if (!plc->ebuf_cont && phy->mib->fddiPORTPCMState == PC8_ACTIVE){
-                       /*
-                        * This is the real Elasticity Error.
-                        * More than one in a row are treated as a
-                        * single one.
-                        * Only count this in the active state.
-                        */
-                       phy->mib->fddiPORTEBError_Ct ++ ;
-
-               }
-
-               plc->ebuf_err++ ;
-               if (plc->ebuf_cont <= 1000) {
-                       /*
-                        * Prevent counter from being wrapped after
-                        * hanging years in that interrupt.
-                        */
-                       plc->ebuf_cont++ ;      /* Ebuf continuous error */
-               }
-
-#ifdef SUPERNET_3
-               if (plc->ebuf_cont == 1000 &&
-                       ((inpw(PLC(np,PL_STATUS_A)) & PLC_REV_MASK) ==
-                       PLC_REV_SN3)) {
-                       /*
-                        * This interrupt remeained high for at least
-                        * 1000 consecutive interrupt calls.
-                        *
-                        * This is caused by a hardware error of the
-                        * ORION part of the Supernet III chipset.
-                        *
-                        * Disable this bit from the mask.
-                        */
-                       corr_mask = (plc_imsk_na & ~PL_EBUF_ERR) ;
-                       outpw(PLC(np,PL_INTR_MASK),corr_mask);
-
-                       /*
-                        * Disconnect from the ring.
-                        * Call the driver with the reset indication.
-                        */
-                       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
-
-                       /*
-                        * Make an error log entry.
-                        */
-                       SMT_ERR_LOG(smc,SMT_E0136, SMT_E0136_MSG) ;
-
-                       /*
-                        * Indicate the Reset.
-                        */
-                       drv_reset_indication(smc) ;
-               }
-#endif /* SUPERNET_3 */
-       } else {
-               /* Reset the continuous error variable */
-               plc->ebuf_cont = 0 ;    /* reset Ebuf continuous error */
-       }
-       if (cmd & PL_PHYINV) {          /* physical layer invalid signal */
-               plc->phyinv++ ;
-       }
-       if (cmd & PL_VSYM_CTR) {        /* violation symbol counter has incr.*/
-               plc->vsym_ctr++ ;
-       }
-       if (cmd & PL_MINI_CTR) {        /* dep. on PLC_CNTRL_A's MINI_CTR_INT*/
-               plc->mini_ctr++ ;
-       }
-       if (cmd & PL_LE_CTR) {          /* link error event counter */
-               int     j ;
-
-               /*
-                * note: PL_LINK_ERR_CTR MUST be read to clear it
-                */
-               j = inpw(PLC(np,PL_LE_THRESHOLD)) ;
-               i = inpw(PLC(np,PL_LINK_ERR_CTR)) ;
-
-               if (i < j) {
-                       /* wrapped around */
-                       i += 256 ;
-               }
-
-               if (phy->lem.lem_on) {
-                       /* Note: Lem errors shall only be counted when
-                        * link is ACTIVE or LCT is active.
-                        */
-                       phy->lem.lem_errors += i ;
-                       phy->mib->fddiPORTLem_Ct += i ;
-               }
-       }
-       if (cmd & PL_TPC_EXPIRED) {     /* TPC timer reached zero */
-               if (plc->p_state == PS_LCT) {
-                       /*
-                        * end of LCT
-                        */
-                       ;
-               }
-               plc->tpc_exp++ ;
-       }
-       if (cmd & PL_LS_MATCH) {        /* LS == LS in PLC_CNTRL_B's MATCH_LS*/
-               switch (inpw(PLC(np,PL_CNTRL_B)) & PL_MATCH_LS) {
-               case PL_I_IDLE :        phy->curr_ls = PC_ILS ;         break ;
-               case PL_I_HALT :        phy->curr_ls = PC_HLS ;         break ;
-               case PL_I_MASTR :       phy->curr_ls = PC_MLS ;         break ;
-               case PL_I_QUIET :       phy->curr_ls = PC_QLS ;         break ;
-               }
-       }
-       if (cmd & PL_PCM_BREAK) {       /* PCM has entered the BREAK state */
-               int     reason;
-
-               reason = inpw(PLC(np,PL_STATUS_B)) & PL_BREAK_REASON ;
-
-               switch (reason) {
-               case PL_B_PCS :         plc->b_pcs++ ;  break ;
-               case PL_B_TPC :         plc->b_tpc++ ;  break ;
-               case PL_B_TNE :         plc->b_tne++ ;  break ;
-               case PL_B_QLS :         plc->b_qls++ ;  break ;
-               case PL_B_ILS :         plc->b_ils++ ;  break ;
-               case PL_B_HLS :         plc->b_hls++ ;  break ;
-               }
-
-               /*jd 05-Aug-1999 changed: Bug #10419 */
-               DB_PCMN(1,"PLC %d: MDcF = %x\n", np, smc->e.DisconnectFlag);
-               if (smc->e.DisconnectFlag == FALSE) {
-                       DB_PCMN(1,"PLC %d: restart (reason %x)\n", np, reason);
-                       queue_event(smc,EVENT_PCM+np,PC_START) ;
-               }
-               else {
-                       DB_PCMN(1,"PLC %d: NO!! restart (reason %x)\n", np, reason);
-               }
-               return ;
-       }
-       /*
-        * If both CODE & ENABLE are set ignore enable
-        */
-       if (cmd & PL_PCM_CODE) { /* receive last sign.-bit | LCT complete */
-               queue_event(smc,EVENT_PCM+np,PC_SIGNAL) ;
-               n = inpw(PLC(np,PL_RCV_VECTOR)) ;
-               for (i = 0 ; i < plc->p_bits ; i++) {
-                       phy->r_val[plc->p_start+i] = n & 1 ;
-                       n >>= 1 ;
-               }
-       }
-       else if (cmd & PL_PCM_ENABLED) { /* asserted SC_JOIN, scrub.completed*/
-               queue_event(smc,EVENT_PCM+np,PC_JOIN) ;
-       }
-       if (cmd & PL_TRACE_PROP) {      /* MLS while PC8_ACTIV || PC2_TRACE */
-               /*PC22b*/
-               if (!phy->tr_flag) {
-                       DB_PCMN(1,"PCM : irq TRACE_PROP %d %d\n",
-                               np,smc->mib.fddiSMTECMState) ;
-                       phy->tr_flag = TRUE ;
-                       smc->e.trace_prop |= ENTITY_BIT(ENTITY_PHY(np)) ;
-                       queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
-               }
-       }
-       /*
-        * filter PLC glitch ???
-        * QLS || HLS only while in PC2_TRACE state
-        */
-       if ((cmd & PL_SELF_TEST) && (phy->mib->fddiPORTPCMState == PC2_TRACE)) {
-               /*PC22a*/
-               if (smc->e.path_test == PT_PASSED) {
-                       DB_PCMN(1,"PCM : state = %s %d\n", get_pcmstate(smc,np),
-                               phy->mib->fddiPORTPCMState) ;
-
-                       smc->e.path_test = PT_PENDING ;
-                       queue_event(smc,EVENT_ECM,EC_PATH_TEST) ;
-               }
-       }
-       if (cmd & PL_TNE_EXPIRED) {     /* TNE: length of noise events */
-               /* break_required (TNE > NS_Max) */
-               if (phy->mib->fddiPORTPCMState == PC8_ACTIVE) {
-                       if (!phy->tr_flag) {
-                          DB_PCMN(1,"PCM %c : PC81 %s\n",phy->phy_name,"NSE");
-                          queue_event(smc,EVENT_PCM+np,PC_START) ;
-                          return ;
-                       }
-               }
-       }
-#if    0
-       if (cmd & PL_NP_ERR) {          /* NP has requested to r/w an inv reg*/
-               /*
-                * It's a bug by AMD
-                */
-               plc->np_err++ ;
-       }
-       /* pin inactiv (GND) */
-       if (cmd & PL_PARITY_ERR) {      /* p. error dedected on TX9-0 inp */
-               plc->parity_err++ ;
-       }
-       if (cmd & PL_LSDO) {            /* carrier detected */
-               ;
-       }
-#endif
-}
-
-#ifdef DEBUG
-/*
- * fill state struct
- */
-void pcm_get_state(struct s_smc *smc, struct smt_state *state)
-{
-       struct s_phy    *phy ;
-       struct pcm_state *pcs ;
-       int     i ;
-       int     ii ;
-       short   rbits ;
-       short   tbits ;
-       struct fddi_mib_p       *mib ;
-
-       for (i = 0, phy = smc->y, pcs = state->pcm_state ; i < NUMPHYS ;
-               i++ , phy++, pcs++ ) {
-               mib = phy->mib ;
-               pcs->pcm_type = (u_char) mib->fddiPORTMy_Type ;
-               pcs->pcm_state = (u_char) mib->fddiPORTPCMState ;
-               pcs->pcm_mode = phy->pc_mode ;
-               pcs->pcm_neighbor = (u_char) mib->fddiPORTNeighborType ;
-               pcs->pcm_bsf = mib->fddiPORTBS_Flag ;
-               pcs->pcm_lsf = phy->ls_flag ;
-               pcs->pcm_lct_fail = (u_char) mib->fddiPORTLCTFail_Ct ;
-               pcs->pcm_ls_rx = LS2MIB(sm_pm_get_ls(smc,i)) ;
-               for (ii = 0, rbits = tbits = 0 ; ii < NUMBITS ; ii++) {
-                       rbits <<= 1 ;
-                       tbits <<= 1 ;
-                       if (phy->r_val[NUMBITS-1-ii])
-                               rbits |= 1 ;
-                       if (phy->t_val[NUMBITS-1-ii])
-                               tbits |= 1 ;
-               }
-               pcs->pcm_r_val = rbits ;
-               pcs->pcm_t_val = tbits ;
-       }
-}
-
-int get_pcm_state(struct s_smc *smc, int np)
-{
-       int pcs ;
-
-       SK_UNUSED(smc) ;
-
-       switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
-               case PL_PC0 :   pcs = PC_STOP ;         break ;
-               case PL_PC1 :   pcs = PC_START ;        break ;
-               case PL_PC2 :   pcs = PC_TRACE ;        break ;
-               case PL_PC3 :   pcs = PC_SIGNAL ;       break ;
-               case PL_PC4 :   pcs = PC_SIGNAL ;       break ;
-               case PL_PC5 :   pcs = PC_SIGNAL ;       break ;
-               case PL_PC6 :   pcs = PC_JOIN ;         break ;
-               case PL_PC7 :   pcs = PC_JOIN ;         break ;
-               case PL_PC8 :   pcs = PC_ENABLE ;       break ;
-               case PL_PC9 :   pcs = PC_MAINT ;        break ;
-               default :       pcs = PC_DISABLE ;      break ;
-       }
-       return pcs;
-}
-
-char *get_linestate(struct s_smc *smc, int np)
-{
-       char *ls = "" ;
-
-       SK_UNUSED(smc) ;
-
-       switch (inpw(PLC(np,PL_STATUS_A)) & PL_LINE_ST) {
-               case PL_L_NLS : ls = "NOISE" ;  break ;
-               case PL_L_ALS : ls = "ACTIV" ;  break ;
-               case PL_L_UND : ls = "UNDEF" ;  break ;
-               case PL_L_ILS4: ls = "ILS 4" ;  break ;
-               case PL_L_QLS : ls = "QLS" ;    break ;
-               case PL_L_MLS : ls = "MLS" ;    break ;
-               case PL_L_HLS : ls = "HLS" ;    break ;
-               case PL_L_ILS16:ls = "ILS16" ;  break ;
-#ifdef lint
-               default:        ls = "unknown" ; break ;
-#endif
-       }
-       return ls;
-}
-
-char *get_pcmstate(struct s_smc *smc, int np)
-{
-       char *pcs ;
-       
-       SK_UNUSED(smc) ;
-
-       switch (inpw(PLC(np,PL_STATUS_B)) & PL_PCM_STATE) {
-               case PL_PC0 :   pcs = "OFF" ;           break ;
-               case PL_PC1 :   pcs = "BREAK" ;         break ;
-               case PL_PC2 :   pcs = "TRACE" ;         break ;
-               case PL_PC3 :   pcs = "CONNECT";        break ;
-               case PL_PC4 :   pcs = "NEXT" ;          break ;
-               case PL_PC5 :   pcs = "SIGNAL" ;        break ;
-               case PL_PC6 :   pcs = "JOIN" ;          break ;
-               case PL_PC7 :   pcs = "VERIFY" ;        break ;
-               case PL_PC8 :   pcs = "ACTIV" ;         break ;
-               case PL_PC9 :   pcs = "MAINT" ;         break ;
-               default :       pcs = "UNKNOWN" ;       break ;
-       }
-       return pcs;
-}
-
-void list_phy(struct s_smc *smc)
-{
-       struct s_plc *plc ;
-       int np ;
-
-       for (np = 0 ; np < NUMPHYS ; np++) {
-               plc  = &smc->y[np].plc ;
-               printf("PHY %d:\tERRORS\t\t\tBREAK_REASONS\t\tSTATES:\n",np) ;
-               printf("\tsoft_error: %ld \t\tPC_Start : %ld\n",
-                                               plc->soft_err,plc->b_pcs);
-               printf("\tparity_err: %ld \t\tTPC exp. : %ld\t\tLine: %s\n",
-                       plc->parity_err,plc->b_tpc,get_linestate(smc,np)) ;
-               printf("\tebuf_error: %ld \t\tTNE exp. : %ld\n",
-                                               plc->ebuf_err,plc->b_tne) ;
-               printf("\tphyinvalid: %ld \t\tQLS det. : %ld\t\tPCM : %s\n",
-                       plc->phyinv,plc->b_qls,get_pcmstate(smc,np)) ;
-               printf("\tviosym_ctr: %ld \t\tILS det. : %ld\n",
-                                               plc->vsym_ctr,plc->b_ils)  ;
-               printf("\tmingap_ctr: %ld \t\tHLS det. : %ld\n",
-                                               plc->mini_ctr,plc->b_hls) ;
-               printf("\tnodepr_err: %ld\n",plc->np_err) ;
-               printf("\tTPC_exp : %ld\n",plc->tpc_exp) ;
-               printf("\tLEM_err : %ld\n",smc->y[np].lem.lem_errors) ;
-       }
-}
-
-
-#ifdef CONCENTRATOR
-void pcm_lem_dump(struct s_smc *smc)
-{
-       int             i ;
-       struct s_phy    *phy ;
-       struct fddi_mib_p       *mib ;
-
-       char            *entostring() ;
-
-       printf("PHY     errors  BER\n") ;
-       printf("----------------------\n") ;
-       for (i = 0,phy = smc->y ; i < NUMPHYS ; i++,phy++) {
-               if (!plc_is_installed(smc,i))
-                       continue ;
-               mib = phy->mib ;
-               printf("%s\t%ld\t10E-%d\n",
-                       entostring(smc,ENTITY_PHY(i)),
-                       mib->fddiPORTLem_Ct,
-                       mib->fddiPORTLer_Estimate) ;
-       }
-}
-#endif
-#endif
diff --git a/drivers/net/skfp/pmf.c b/drivers/net/skfp/pmf.c
deleted file mode 100644 (file)
index 9ac4665..0000000
+++ /dev/null
@@ -1,1663 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       Parameter Management Frame processing for SMT 7.2
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/smt_p.h"
-
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        SLIM_SMT
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)pmf.c       1.37 97/08/04 (C) SK " ;
-#endif
-
-static int smt_authorize(struct s_smc *smc, struct smt_header *sm);
-static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm);
-static const struct s_p_tab* smt_get_ptab(u_short para);
-static int smt_mib_phys(struct s_smc *smc);
-static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
-                       int local, int set);
-void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
-                 int index, int local);
-static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
-                                    int set, int local);
-static int port_to_mib(struct s_smc *smc, int p);
-
-#define MOFFSS(e)      offsetof(struct fddi_mib, e)
-#define MOFFMS(e)      offsetof(struct fddi_mib_m, e)
-#define MOFFAS(e)      offsetof(struct fddi_mib_a, e)
-#define MOFFPS(e)      offsetof(struct fddi_mib_p, e)
-
-
-#define AC_G   0x01            /* Get */
-#define AC_GR  0x02            /* Get/Set */
-#define AC_S   0x04            /* Set */
-#define AC_NA  0x08
-#define AC_GROUP       0x10            /* Group */
-#define MS2BCLK(x)     ((x)*12500L)
-/*
-       F       LFag (byte)
-       B       byte
-       S       u_short 16 bit
-       C       Counter 32 bit
-       L       Long 32 bit
-       T       Timer_2 32 bit
-       P       TimeStamp ;
-       A       LongAddress (6 byte)
-       E       Enum 16 bit
-       R       ResId 16 Bit
-*/
-static const struct s_p_tab {
-       u_short p_num ;         /* parameter code */
-       u_char  p_access ;      /* access rights */
-       u_short p_offset ;      /* offset in mib */
-       char    p_swap[3] ;     /* format string */
-} p_tab[] = {
-       /* StationIdGrp */
-       { SMT_P100A,AC_GROUP    } ,
-       { SMT_P100B,AC_G,       MOFFSS(fddiSMTStationId),       "8"     } ,
-       { SMT_P100D,AC_G,       MOFFSS(fddiSMTOpVersionId),     "S"     } ,
-       { SMT_P100E,AC_G,       MOFFSS(fddiSMTHiVersionId),     "S"     } ,
-       { SMT_P100F,AC_G,       MOFFSS(fddiSMTLoVersionId),     "S"     } ,
-       { SMT_P1010,AC_G,       MOFFSS(fddiSMTManufacturerData), "D" } ,
-       { SMT_P1011,AC_GR,      MOFFSS(fddiSMTUserData),        "D"     } ,
-       { SMT_P1012,AC_G,       MOFFSS(fddiSMTMIBVersionId),    "S"     } ,
-
-       /* StationConfigGrp */
-       { SMT_P1014,AC_GROUP    } ,
-       { SMT_P1015,AC_G,       MOFFSS(fddiSMTMac_Ct),          "B"     } ,
-       { SMT_P1016,AC_G,       MOFFSS(fddiSMTNonMaster_Ct),    "B"     } ,
-       { SMT_P1017,AC_G,       MOFFSS(fddiSMTMaster_Ct),       "B"     } ,
-       { SMT_P1018,AC_G,       MOFFSS(fddiSMTAvailablePaths),  "B"     } ,
-       { SMT_P1019,AC_G,       MOFFSS(fddiSMTConfigCapabilities),"S"   } ,
-       { SMT_P101A,AC_GR,      MOFFSS(fddiSMTConfigPolicy),    "wS"    } ,
-       { SMT_P101B,AC_GR,      MOFFSS(fddiSMTConnectionPolicy),"wS"    } ,
-       { SMT_P101D,AC_GR,      MOFFSS(fddiSMTTT_Notify),       "wS"    } ,
-       { SMT_P101E,AC_GR,      MOFFSS(fddiSMTStatRptPolicy),   "bB"    } ,
-       { SMT_P101F,AC_GR,      MOFFSS(fddiSMTTrace_MaxExpiration),"lL" } ,
-       { SMT_P1020,AC_G,       MOFFSS(fddiSMTPORTIndexes),     "II"    } ,
-       { SMT_P1021,AC_G,       MOFFSS(fddiSMTMACIndexes),      "I"     } ,
-       { SMT_P1022,AC_G,       MOFFSS(fddiSMTBypassPresent),   "F"     } ,
-
-       /* StatusGrp */
-       { SMT_P1028,AC_GROUP    } ,
-       { SMT_P1029,AC_G,       MOFFSS(fddiSMTECMState),        "E"     } ,
-       { SMT_P102A,AC_G,       MOFFSS(fddiSMTCF_State),        "E"     } ,
-       { SMT_P102C,AC_G,       MOFFSS(fddiSMTRemoteDisconnectFlag),"F" } ,
-       { SMT_P102D,AC_G,       MOFFSS(fddiSMTStationStatus),   "E"     } ,
-       { SMT_P102E,AC_G,       MOFFSS(fddiSMTPeerWrapFlag),    "F"     } ,
-
-       /* MIBOperationGrp */
-       { SMT_P1032,AC_GROUP    } ,
-       { SMT_P1033,AC_G,       MOFFSS(fddiSMTTimeStamp),"P"            } ,
-       { SMT_P1034,AC_G,       MOFFSS(fddiSMTTransitionTimeStamp),"P"  } ,
-       /* NOTE : SMT_P1035 is already swapped ! SMT_P_SETCOUNT */
-       { SMT_P1035,AC_G,       MOFFSS(fddiSMTSetCount),"4P"            } ,
-       { SMT_P1036,AC_G,       MOFFSS(fddiSMTLastSetStationId),"8"     } ,
-
-       { SMT_P103C,AC_S,       0,                              "wS"    } ,
-
-       /*
-        * PRIVATE EXTENSIONS
-        * only accessible locally to get/set passwd
-        */
-       { SMT_P10F0,AC_GR,      MOFFSS(fddiPRPMFPasswd),        "8"     } ,
-       { SMT_P10F1,AC_GR,      MOFFSS(fddiPRPMFStation),       "8"     } ,
-#ifdef ESS
-       { SMT_P10F2,AC_GR,      MOFFSS(fddiESSPayload),         "lL"    } ,
-       { SMT_P10F3,AC_GR,      MOFFSS(fddiESSOverhead),        "lL"    } ,
-       { SMT_P10F4,AC_GR,      MOFFSS(fddiESSMaxTNeg),         "lL"    } ,
-       { SMT_P10F5,AC_GR,      MOFFSS(fddiESSMinSegmentSize),  "lL"    } ,
-       { SMT_P10F6,AC_GR,      MOFFSS(fddiESSCategory),        "lL"    } ,
-       { SMT_P10F7,AC_GR,      MOFFSS(fddiESSSynchTxMode),     "wS"    } ,
-#endif
-#ifdef SBA
-       { SMT_P10F8,AC_GR,      MOFFSS(fddiSBACommand),         "bF"    } ,
-       { SMT_P10F9,AC_GR,      MOFFSS(fddiSBAAvailable),       "bF"    } ,
-#endif
-       /* MAC Attributes */
-       { SMT_P200A,AC_GROUP    } ,
-       { SMT_P200B,AC_G,       MOFFMS(fddiMACFrameStatusFunctions),"S" } ,
-       { SMT_P200D,AC_G,       MOFFMS(fddiMACT_MaxCapabilitiy),"T"     } ,
-       { SMT_P200E,AC_G,       MOFFMS(fddiMACTVXCapabilitiy),"T"       } ,
-
-       /* ConfigGrp */
-       { SMT_P2014,AC_GROUP    } ,
-       { SMT_P2016,AC_G,       MOFFMS(fddiMACAvailablePaths),  "B"     } ,
-       { SMT_P2017,AC_G,       MOFFMS(fddiMACCurrentPath),     "S"     } ,
-       { SMT_P2018,AC_G,       MOFFMS(fddiMACUpstreamNbr),     "A"     } ,
-       { SMT_P2019,AC_G,       MOFFMS(fddiMACDownstreamNbr),   "A"     } ,
-       { SMT_P201A,AC_G,       MOFFMS(fddiMACOldUpstreamNbr),  "A"     } ,
-       { SMT_P201B,AC_G,       MOFFMS(fddiMACOldDownstreamNbr),"A"     } ,
-       { SMT_P201D,AC_G,       MOFFMS(fddiMACDupAddressTest),  "E"     } ,
-       { SMT_P2020,AC_GR,      MOFFMS(fddiMACRequestedPaths),  "wS"    } ,
-       { SMT_P2021,AC_G,       MOFFMS(fddiMACDownstreamPORTType),"E"   } ,
-       { SMT_P2022,AC_G,       MOFFMS(fddiMACIndex),           "S"     } ,
-
-       /* AddressGrp */
-       { SMT_P2028,AC_GROUP    } ,
-       { SMT_P2029,AC_G,       MOFFMS(fddiMACSMTAddress),      "A"     } ,
-
-       /* OperationGrp */
-       { SMT_P2032,AC_GROUP    } ,
-       { SMT_P2033,AC_G,       MOFFMS(fddiMACT_Req),           "T"     } ,
-       { SMT_P2034,AC_G,       MOFFMS(fddiMACT_Neg),           "T"     } ,
-       { SMT_P2035,AC_G,       MOFFMS(fddiMACT_Max),           "T"     } ,
-       { SMT_P2036,AC_G,       MOFFMS(fddiMACTvxValue),        "T"     } ,
-       { SMT_P2038,AC_G,       MOFFMS(fddiMACT_Pri0),          "T"     } ,
-       { SMT_P2039,AC_G,       MOFFMS(fddiMACT_Pri1),          "T"     } ,
-       { SMT_P203A,AC_G,       MOFFMS(fddiMACT_Pri2),          "T"     } ,
-       { SMT_P203B,AC_G,       MOFFMS(fddiMACT_Pri3),          "T"     } ,
-       { SMT_P203C,AC_G,       MOFFMS(fddiMACT_Pri4),          "T"     } ,
-       { SMT_P203D,AC_G,       MOFFMS(fddiMACT_Pri5),          "T"     } ,
-       { SMT_P203E,AC_G,       MOFFMS(fddiMACT_Pri6),          "T"     } ,
-
-
-       /* CountersGrp */
-       { SMT_P2046,AC_GROUP    } ,
-       { SMT_P2047,AC_G,       MOFFMS(fddiMACFrame_Ct),        "C"     } ,
-       { SMT_P2048,AC_G,       MOFFMS(fddiMACCopied_Ct),       "C"     } ,
-       { SMT_P2049,AC_G,       MOFFMS(fddiMACTransmit_Ct),     "C"     } ,
-       { SMT_P204A,AC_G,       MOFFMS(fddiMACToken_Ct),        "C"     } ,
-       { SMT_P2051,AC_G,       MOFFMS(fddiMACError_Ct),        "C"     } ,
-       { SMT_P2052,AC_G,       MOFFMS(fddiMACLost_Ct),         "C"     } ,
-       { SMT_P2053,AC_G,       MOFFMS(fddiMACTvxExpired_Ct),   "C"     } ,
-       { SMT_P2054,AC_G,       MOFFMS(fddiMACNotCopied_Ct),    "C"     } ,
-       { SMT_P2056,AC_G,       MOFFMS(fddiMACRingOp_Ct),       "C"     } ,
-
-       /* FrameErrorConditionGrp */
-       { SMT_P205A,AC_GROUP    } ,
-       { SMT_P205F,AC_GR,      MOFFMS(fddiMACFrameErrorThreshold),"wS" } ,
-       { SMT_P2060,AC_G,       MOFFMS(fddiMACFrameErrorRatio), "S"     } ,
-
-       /* NotCopiedConditionGrp */
-       { SMT_P2064,AC_GROUP    } ,
-       { SMT_P2067,AC_GR,      MOFFMS(fddiMACNotCopiedThreshold),"wS"  } ,
-       { SMT_P2069,AC_G,       MOFFMS(fddiMACNotCopiedRatio),  "S"     } ,
-
-       /* StatusGrp */
-       { SMT_P206E,AC_GROUP    } ,
-       { SMT_P206F,AC_G,       MOFFMS(fddiMACRMTState),        "S"     } ,
-       { SMT_P2070,AC_G,       MOFFMS(fddiMACDA_Flag), "F"     } ,
-       { SMT_P2071,AC_G,       MOFFMS(fddiMACUNDA_Flag),       "F"     } ,
-       { SMT_P2072,AC_G,       MOFFMS(fddiMACFrameErrorFlag),  "F"     } ,
-       { SMT_P2073,AC_G,       MOFFMS(fddiMACNotCopiedFlag),   "F"     } ,
-       { SMT_P2074,AC_G,       MOFFMS(fddiMACMA_UnitdataAvailable),"F" } ,
-       { SMT_P2075,AC_G,       MOFFMS(fddiMACHardwarePresent), "F"     } ,
-       { SMT_P2076,AC_GR,      MOFFMS(fddiMACMA_UnitdataEnable),"bF"   } ,
-
-       /*
-        * PRIVATE EXTENSIONS
-        * only accessible locally to get/set TMIN
-        */
-       { SMT_P20F0,AC_NA                                               } ,
-       { SMT_P20F1,AC_GR,      MOFFMS(fddiMACT_Min),           "lT"    } ,
-
-       /* Path Attributes */
-       /*
-        * DON't swap 320B,320F,3210: they are already swapped in swap_para()
-        */
-       { SMT_P320A,AC_GROUP    } ,
-       { SMT_P320B,AC_G,       MOFFAS(fddiPATHIndex),          "r"     } ,
-       { SMT_P320F,AC_GR,      MOFFAS(fddiPATHSbaPayload),     "l4"    } ,
-       { SMT_P3210,AC_GR,      MOFFAS(fddiPATHSbaOverhead),    "l4"    } ,
-       /* fddiPATHConfiguration */
-       { SMT_P3212,AC_G,       0,                              ""      } ,
-       { SMT_P3213,AC_GR,      MOFFAS(fddiPATHT_Rmode),        "lT"    } ,
-       { SMT_P3214,AC_GR,      MOFFAS(fddiPATHSbaAvailable),   "lL"    } ,
-       { SMT_P3215,AC_GR,      MOFFAS(fddiPATHTVXLowerBound),  "lT"    } ,
-       { SMT_P3216,AC_GR,      MOFFAS(fddiPATHT_MaxLowerBound),"lT"    } ,
-       { SMT_P3217,AC_GR,      MOFFAS(fddiPATHMaxT_Req),       "lT"    } ,
-
-       /* Port Attributes */
-       /* ConfigGrp */
-       { SMT_P400A,AC_GROUP    } ,
-       { SMT_P400C,AC_G,       MOFFPS(fddiPORTMy_Type),        "E"     } ,
-       { SMT_P400D,AC_G,       MOFFPS(fddiPORTNeighborType),   "E"     } ,
-       { SMT_P400E,AC_GR,      MOFFPS(fddiPORTConnectionPolicies),"bB" } ,
-       { SMT_P400F,AC_G,       MOFFPS(fddiPORTMacIndicated),   "2"     } ,
-       { SMT_P4010,AC_G,       MOFFPS(fddiPORTCurrentPath),    "E"     } ,
-       { SMT_P4011,AC_GR,      MOFFPS(fddiPORTRequestedPaths), "l4"    } ,
-       { SMT_P4012,AC_G,       MOFFPS(fddiPORTMACPlacement),   "S"     } ,
-       { SMT_P4013,AC_G,       MOFFPS(fddiPORTAvailablePaths), "B"     } ,
-       { SMT_P4016,AC_G,       MOFFPS(fddiPORTPMDClass),       "E"     } ,
-       { SMT_P4017,AC_G,       MOFFPS(fddiPORTConnectionCapabilities), "B"} ,
-       { SMT_P401D,AC_G,       MOFFPS(fddiPORTIndex),          "R"     } ,
-
-       /* OperationGrp */
-       { SMT_P401E,AC_GROUP    } ,
-       { SMT_P401F,AC_GR,      MOFFPS(fddiPORTMaint_LS),       "wE"    } ,
-       { SMT_P4021,AC_G,       MOFFPS(fddiPORTBS_Flag),        "F"     } ,
-       { SMT_P4022,AC_G,       MOFFPS(fddiPORTPC_LS),          "E"     } ,
-
-       /* ErrorCtrsGrp */
-       { SMT_P4028,AC_GROUP    } ,
-       { SMT_P4029,AC_G,       MOFFPS(fddiPORTEBError_Ct),     "C"     } ,
-       { SMT_P402A,AC_G,       MOFFPS(fddiPORTLCTFail_Ct),     "C"     } ,
-
-       /* LerGrp */
-       { SMT_P4032,AC_GROUP    } ,
-       { SMT_P4033,AC_G,       MOFFPS(fddiPORTLer_Estimate),   "F"     } ,
-       { SMT_P4034,AC_G,       MOFFPS(fddiPORTLem_Reject_Ct),  "C"     } ,
-       { SMT_P4035,AC_G,       MOFFPS(fddiPORTLem_Ct),         "C"     } ,
-       { SMT_P403A,AC_GR,      MOFFPS(fddiPORTLer_Cutoff),     "bB"    } ,
-       { SMT_P403B,AC_GR,      MOFFPS(fddiPORTLer_Alarm),      "bB"    } ,
-
-       /* StatusGrp */
-       { SMT_P403C,AC_GROUP    } ,
-       { SMT_P403D,AC_G,       MOFFPS(fddiPORTConnectState),   "E"     } ,
-       { SMT_P403E,AC_G,       MOFFPS(fddiPORTPCMStateX),      "E"     } ,
-       { SMT_P403F,AC_G,       MOFFPS(fddiPORTPC_Withhold),    "E"     } ,
-       { SMT_P4040,AC_G,       MOFFPS(fddiPORTLerFlag),        "F"     } ,
-       { SMT_P4041,AC_G,       MOFFPS(fddiPORTHardwarePresent),"F"     } ,
-
-       { SMT_P4046,AC_S,       0,                              "wS"    } ,
-
-       { 0,    AC_GROUP        } ,
-       { 0 }
-} ;
-
-void smt_pmf_received_pack(struct s_smc *smc, SMbuf *mb, int local)
-{
-       struct smt_header       *sm ;
-       SMbuf           *reply ;
-
-       sm = smtod(mb,struct smt_header *) ;
-       DB_SMT("SMT: processing PMF frame at %x len %d\n",sm,mb->sm_len) ;
-#ifdef DEBUG
-       dump_smt(smc,sm,"PMF Received") ;
-#endif
-       /*
-        * Start the watchdog: It may be a long, long packet and
-        * maybe the watchdog occurs ...
-        */
-       smt_start_watchdog(smc) ;
-
-       if (sm->smt_class == SMT_PMF_GET ||
-           sm->smt_class == SMT_PMF_SET) {
-               reply = smt_build_pmf_response(smc,sm,
-                       sm->smt_class == SMT_PMF_SET,local) ;
-               if (reply) {
-                       sm = smtod(reply,struct smt_header *) ;
-#ifdef DEBUG
-                       dump_smt(smc,sm,"PMF Reply") ;
-#endif
-                       smt_send_frame(smc,reply,FC_SMT_INFO,local) ;
-               }
-       }
-}
-
-static SMbuf *smt_build_pmf_response(struct s_smc *smc, struct smt_header *req,
-                                    int set, int local)
-{
-       SMbuf                   *mb ;
-       struct smt_header       *smt ;
-       struct smt_para         *pa ;
-       struct smt_p_reason     *res ;
-       const struct s_p_tab    *pt ;
-       int                     len ;
-       int                     index ;
-       int                     idx_end ;
-       int                     error ;
-       int                     range ;
-       SK_LOC_DECL(struct s_pcon,pcon) ;
-       SK_LOC_DECL(struct s_pcon,set_pcon) ;
-
-       /*
-        * build SMT header
-        */
-       if (!(mb = smt_get_mbuf(smc)))
-               return mb;
-
-       smt = smtod(mb, struct smt_header *) ;
-       smt->smt_dest = req->smt_source ;       /* DA == source of request */
-       smt->smt_class = req->smt_class ;       /* same class (GET/SET) */
-       smt->smt_type = SMT_REPLY ;
-       smt->smt_version = SMT_VID_2 ;
-       smt->smt_tid = req->smt_tid ;           /* same TID */
-       smt->smt_pad = 0 ;
-       smt->smt_len = 0 ;
-
-       /*
-        * setup parameter status
-        */
-       pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
-       pcon.pc_err = 0 ;                       /* no error */
-       pcon.pc_badset = 0 ;                    /* no bad set count */
-       pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
-
-       /*
-        * check authoriziation and set count
-        */
-       error = 0 ;
-       if (set) {
-               if (!local && smt_authorize(smc,req))
-                       error = SMT_RDF_AUTHOR ;
-               else if (smt_check_set_count(smc,req))
-                       pcon.pc_badset = SMT_RDF_BADSET ;
-       }
-       /*
-        * add reason code and all mandatory parameters
-        */
-       res = (struct smt_p_reason *) pcon.pc_p ;
-       smt_add_para(smc,&pcon,(u_short) SMT_P_REASON,0,0) ;
-       smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
-       /* update 1035 and 1036 later if set */
-       set_pcon = pcon ;
-       smt_add_para(smc,&pcon,(u_short) SMT_P1035,0,0) ;
-       smt_add_para(smc,&pcon,(u_short) SMT_P1036,0,0) ;
-
-       pcon.pc_err = error ;
-       len = req->smt_len ;
-       pa = (struct smt_para *) (req + 1) ;
-       /*
-        * process list of paras
-        */
-       while (!pcon.pc_err && len > 0 ) {
-               if (((u_short)len < pa->p_len + PARA_LEN) || (pa->p_len & 3)) {
-                       pcon.pc_err = SMT_RDF_LENGTH ;
-                       break ;
-               }
-
-               if (((range = (pa->p_type & 0xf000)) == 0x2000) ||
-                       range == 0x3000 || range == 0x4000) {
-                       /*
-                        * get index for PART,MAC ad PATH group
-                        */
-                       index = *((u_char *)pa + PARA_LEN + 3) ;/* index */
-                       idx_end = index ;
-                       if (!set && (pa->p_len != 4)) {
-                               pcon.pc_err = SMT_RDF_LENGTH ;
-                               break ;
-                       }
-                       if (!index && !set) {
-                               switch (range) {
-                               case 0x2000 :
-                                       index = INDEX_MAC ;
-                                       idx_end = index - 1 + NUMMACS ;
-                                       break ;
-                               case 0x3000 :
-                                       index = INDEX_PATH ;
-                                       idx_end = index - 1 + NUMPATHS ;
-                                       break ;
-                               case 0x4000 :
-                                       index = INDEX_PORT ;
-                                       idx_end = index - 1 + NUMPHYS ;
-#ifndef        CONCENTRATOR
-                                       if (smc->s.sas == SMT_SAS)
-                                               idx_end = INDEX_PORT ;
-#endif
-                                       break ;
-                               }
-                       }
-               }
-               else {
-                       /*
-                        * smt group has no index
-                        */
-                       if (!set && (pa->p_len != 0)) {
-                               pcon.pc_err = SMT_RDF_LENGTH ;
-                               break ;
-                       }
-                       index = 0 ;
-                       idx_end = 0 ;
-               }
-               while (index <= idx_end) {
-                       /*
-                        * if group
-                        *      add all paras of group
-                        */
-                       pt = smt_get_ptab(pa->p_type) ;
-                       if (pt && pt->p_access == AC_GROUP && !set) {
-                               pt++ ;
-                               while (pt->p_access == AC_G ||
-                                       pt->p_access == AC_GR) {
-                                       smt_add_para(smc,&pcon,pt->p_num,
-                                               index,local);
-                                       pt++ ;
-                               }
-                       }
-                       /*
-                        * ignore
-                        *      AUTHORIZATION in get/set
-                        *      SET COUNT in set
-                        */
-                       else if (pa->p_type != SMT_P_AUTHOR &&
-                                (!set || (pa->p_type != SMT_P1035))) {
-                               int     st ;
-                               if (pcon.pc_badset) {
-                                       smt_add_para(smc,&pcon,pa->p_type,
-                                               index,local) ;
-                               }
-                               else if (set) {
-                                       st = smt_set_para(smc,pa,index,local,1);
-                                       /*
-                                        * return para even if error
-                                        */
-                                       smt_add_para(smc,&pcon,pa->p_type,
-                                               index,local) ;
-                                       pcon.pc_err = st ;
-                               }
-                               else {
-                                       if (pt && pt->p_access == AC_S) {
-                                               pcon.pc_err =
-                                                       SMT_RDF_ILLEGAL ;
-                                       }
-                                       smt_add_para(smc,&pcon,pa->p_type,
-                                               index,local) ;
-                               }
-                       }
-                       if (pcon.pc_err)
-                               break ;
-                       index++ ;
-               }
-               len -= pa->p_len + PARA_LEN ;
-               pa = (struct smt_para *) ((char *)pa + pa->p_len + PARA_LEN) ;
-       }
-       smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
-       mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
-
-       /* update reason code */
-       res->rdf_reason = pcon.pc_badset ? pcon.pc_badset :
-                       pcon.pc_err ? pcon.pc_err : SMT_RDF_SUCCESS ;
-       if (set && (res->rdf_reason == SMT_RDF_SUCCESS)) {
-               /*
-                * increment set count
-                * set time stamp
-                * store station id of last set
-                */
-               smc->mib.fddiSMTSetCount.count++ ;
-               smt_set_timestamp(smc,smc->mib.fddiSMTSetCount.timestamp) ;
-               smc->mib.fddiSMTLastSetStationId = req->smt_sid ;
-               smt_add_para(smc,&set_pcon,(u_short) SMT_P1035,0,0) ;
-               smt_add_para(smc,&set_pcon,(u_short) SMT_P1036,0,0) ;
-       }
-       return mb;
-}
-
-static int smt_authorize(struct s_smc *smc, struct smt_header *sm)
-{
-       struct smt_para *pa ;
-       int             i ;
-       char            *p ;
-
-       /*
-        * check source station id if not zero
-        */
-       p = (char *) &smc->mib.fddiPRPMFStation ;
-       for (i = 0 ; i < 8 && !p[i] ; i++)
-               ;
-       if (i != 8) {
-               if (memcmp((char *) &sm->smt_sid,
-                       (char *) &smc->mib.fddiPRPMFStation,8))
-                       return 1;
-       }
-       /*
-        * check authoriziation parameter if passwd not zero
-        */
-       p = (char *) smc->mib.fddiPRPMFPasswd ;
-       for (i = 0 ; i < 8 && !p[i] ; i++)
-               ;
-       if (i != 8) {
-               pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P_AUTHOR) ;
-               if (!pa)
-                       return 1;
-               if (pa->p_len != 8)
-                       return 1;
-               if (memcmp((char *)(pa+1),(char *)smc->mib.fddiPRPMFPasswd,8))
-                       return 1;
-       }
-       return 0;
-}
-
-static int smt_check_set_count(struct s_smc *smc, struct smt_header *sm)
-{
-       struct smt_para *pa ;
-       struct smt_p_setcount   *sc ;
-
-       pa = (struct smt_para *) sm_to_para(smc,sm,SMT_P1035) ;
-       if (pa) {
-               sc = (struct smt_p_setcount *) pa ;
-               if ((smc->mib.fddiSMTSetCount.count != sc->count) ||
-                       memcmp((char *) smc->mib.fddiSMTSetCount.timestamp,
-                       (char *)sc->timestamp,8))
-                       return 1;
-       }
-       return 0;
-}
-
-void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
-                 int index, int local)
-{
-       struct smt_para *pa ;
-       const struct s_p_tab    *pt ;
-       struct fddi_mib_m *mib_m = NULL;
-       struct fddi_mib_p *mib_p = NULL;
-       int             len ;
-       int             plen ;
-       char            *from ;
-       char            *to ;
-       const char      *swap ;
-       char            c ;
-       int             range ;
-       char            *mib_addr ;
-       int             mac ;
-       int             path ;
-       int             port ;
-       int             sp_len ;
-
-       /*
-        * skip if error
-        */
-       if (pcon->pc_err)
-               return ;
-
-       /*
-        * actions don't have a value
-        */
-       pt = smt_get_ptab(para) ;
-       if (pt && pt->p_access == AC_S)
-               return ;
-
-       to = (char *) (pcon->pc_p) ;    /* destination pointer */
-       len = pcon->pc_len ;            /* free space */
-       plen = len ;                    /* remember start length */
-       pa = (struct smt_para *) to ;   /* type/length pointer */
-       to += PARA_LEN ;                /* skip smt_para */
-       len -= PARA_LEN ;
-       /*
-        * set index if required
-        */
-       if (((range = (para & 0xf000)) == 0x2000) ||
-               range == 0x3000 || range == 0x4000) {
-               if (len < 4)
-                       goto wrong_error ;
-               to[0] = 0 ;
-               to[1] = 0 ;
-               to[2] = 0 ;
-               to[3] = index ;
-               len -= 4 ;
-               to += 4 ;
-       }
-       mac = index - INDEX_MAC ;
-       path = index - INDEX_PATH ;
-       port = index - INDEX_PORT ;
-       /*
-        * get pointer to mib
-        */
-       switch (range) {
-       case 0x1000 :
-       default :
-               mib_addr = (char *) (&smc->mib) ;
-               break ;
-       case 0x2000 :
-               if (mac < 0 || mac >= NUMMACS) {
-                       pcon->pc_err = SMT_RDF_NOPARAM ;
-                       return ;
-               }
-               mib_addr = (char *) (&smc->mib.m[mac]) ;
-               mib_m = (struct fddi_mib_m *) mib_addr ;
-               break ;
-       case 0x3000 :
-               if (path < 0 || path >= NUMPATHS) {
-                       pcon->pc_err = SMT_RDF_NOPARAM ;
-                       return ;
-               }
-               mib_addr = (char *) (&smc->mib.a[path]) ;
-               break ;
-       case 0x4000 :
-               if (port < 0 || port >= smt_mib_phys(smc)) {
-                       pcon->pc_err = SMT_RDF_NOPARAM ;
-                       return ;
-               }
-               mib_addr = (char *) (&smc->mib.p[port_to_mib(smc,port)]) ;
-               mib_p = (struct fddi_mib_p *) mib_addr ;
-               break ;
-       }
-       /*
-        * check special paras
-        */
-       swap = NULL;
-       switch (para) {
-       case SMT_P10F0 :
-       case SMT_P10F1 :
-#ifdef ESS
-       case SMT_P10F2 :
-       case SMT_P10F3 :
-       case SMT_P10F4 :
-       case SMT_P10F5 :
-       case SMT_P10F6 :
-       case SMT_P10F7 :
-#endif
-#ifdef SBA
-       case SMT_P10F8 :
-       case SMT_P10F9 :
-#endif
-       case SMT_P20F1 :
-               if (!local) {
-                       pcon->pc_err = SMT_RDF_NOPARAM ;
-                       return ;
-               }
-               break ;
-       case SMT_P2034 :
-       case SMT_P2046 :
-       case SMT_P2047 :
-       case SMT_P204A :
-       case SMT_P2051 :
-       case SMT_P2052 :
-               mac_update_counter(smc) ;
-               break ;
-       case SMT_P4022:
-               mib_p->fddiPORTPC_LS = LS2MIB(
-                       sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
-               break ;
-       case SMT_P_REASON :
-               * (u_long *) to = 0 ;
-               sp_len = 4 ;
-               goto sp_done ;
-       case SMT_P1033 :                        /* time stamp */
-               smt_set_timestamp(smc,smc->mib.fddiSMTTimeStamp) ;
-               break ;
-
-       case SMT_P1020:                         /* port indexes */
-#if    NUMPHYS == 12
-               swap = "IIIIIIIIIIII" ;
-#else
-#if    NUMPHYS == 2
-               if (smc->s.sas == SMT_SAS)
-                       swap = "I" ;
-               else
-                       swap = "II" ;
-#else
-#if    NUMPHYS == 24
-               swap = "IIIIIIIIIIIIIIIIIIIIIIII" ;
-#else
-       ????
-#endif
-#endif
-#endif
-               break ;
-       case SMT_P3212 :
-               {
-                       sp_len = cem_build_path(smc,to,path) ;
-                       goto sp_done ;
-               }
-       case SMT_P1048 :                /* peer wrap condition */
-               {
-                       struct smt_p_1048       *sp ;
-                       sp = (struct smt_p_1048 *) to ;
-                       sp->p1048_flag = smc->mib.fddiSMTPeerWrapFlag ;
-                       sp->p1048_cf_state = smc->mib.fddiSMTCF_State ;
-                       sp_len = sizeof(struct smt_p_1048) ;
-                       goto sp_done ;
-               }
-       case SMT_P208C :
-               {
-                       struct smt_p_208c       *sp ;
-                       sp = (struct smt_p_208c *) to ;
-                       sp->p208c_flag =
-                               smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
-                       sp->p208c_dupcondition =
-                               (mib_m->fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0) |
-                               (mib_m->fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0);
-                       sp->p208c_fddilong =
-                               mib_m->fddiMACSMTAddress ;
-                       sp->p208c_fddiunalong =
-                               mib_m->fddiMACUpstreamNbr ;
-                       sp->p208c_pad = 0 ;
-                       sp_len = sizeof(struct smt_p_208c) ;
-                       goto sp_done ;
-               }
-       case SMT_P208D :                /* frame error condition */
-               {
-                       struct smt_p_208d       *sp ;
-                       sp = (struct smt_p_208d *) to ;
-                       sp->p208d_flag =
-                               mib_m->fddiMACFrameErrorFlag ;
-                       sp->p208d_frame_ct =
-                               mib_m->fddiMACFrame_Ct ;
-                       sp->p208d_error_ct =
-                               mib_m->fddiMACError_Ct ;
-                       sp->p208d_lost_ct =
-                               mib_m->fddiMACLost_Ct ;
-                       sp->p208d_ratio =
-                               mib_m->fddiMACFrameErrorRatio ;
-                       sp_len = sizeof(struct smt_p_208d) ;
-                       goto sp_done ;
-               }
-       case SMT_P208E :                /* not copied condition */
-               {
-                       struct smt_p_208e       *sp ;
-                       sp = (struct smt_p_208e *) to ;
-                       sp->p208e_flag =
-                               mib_m->fddiMACNotCopiedFlag ;
-                       sp->p208e_not_copied =
-                               mib_m->fddiMACNotCopied_Ct ;
-                       sp->p208e_copied =
-                               mib_m->fddiMACCopied_Ct ;
-                       sp->p208e_not_copied_ratio =
-                               mib_m->fddiMACNotCopiedRatio ;
-                       sp_len = sizeof(struct smt_p_208e) ;
-                       goto sp_done ;
-               }
-       case SMT_P208F :        /* neighbor change event */
-               {
-                       struct smt_p_208f       *sp ;
-                       sp = (struct smt_p_208f *) to ;
-                       sp->p208f_multiple =
-                               mib_m->fddiMACMultiple_N ;
-                       sp->p208f_nacondition =
-                               mib_m->fddiMACDuplicateAddressCond ;
-                       sp->p208f_old_una =
-                               mib_m->fddiMACOldUpstreamNbr ;
-                       sp->p208f_new_una =
-                               mib_m->fddiMACUpstreamNbr ;
-                       sp->p208f_old_dna =
-                               mib_m->fddiMACOldDownstreamNbr ;
-                       sp->p208f_new_dna =
-                               mib_m->fddiMACDownstreamNbr ;
-                       sp->p208f_curren_path =
-                               mib_m->fddiMACCurrentPath ;
-                       sp->p208f_smt_address =
-                               mib_m->fddiMACSMTAddress ;
-                       sp_len = sizeof(struct smt_p_208f) ;
-                       goto sp_done ;
-               }
-       case SMT_P2090 :
-               {
-                       struct smt_p_2090       *sp ;
-                       sp = (struct smt_p_2090 *) to ;
-                       sp->p2090_multiple =
-                               mib_m->fddiMACMultiple_P ;
-                       sp->p2090_availablepaths =
-                               mib_m->fddiMACAvailablePaths ;
-                       sp->p2090_currentpath =
-                               mib_m->fddiMACCurrentPath ;
-                       sp->p2090_requestedpaths =
-                               mib_m->fddiMACRequestedPaths ;
-                       sp_len = sizeof(struct smt_p_2090) ;
-                       goto sp_done ;
-               }
-       case SMT_P4050 :
-               {
-                       struct smt_p_4050       *sp ;
-                       sp = (struct smt_p_4050 *) to ;
-                       sp->p4050_flag =
-                               mib_p->fddiPORTLerFlag ;
-                       sp->p4050_pad = 0 ;
-                       sp->p4050_cutoff =
-                               mib_p->fddiPORTLer_Cutoff ;
-                       sp->p4050_alarm =
-                               mib_p->fddiPORTLer_Alarm ;
-                       sp->p4050_estimate =
-                               mib_p->fddiPORTLer_Estimate ;
-                       sp->p4050_reject_ct =
-                               mib_p->fddiPORTLem_Reject_Ct ;
-                       sp->p4050_ct =
-                               mib_p->fddiPORTLem_Ct ;
-                       sp_len = sizeof(struct smt_p_4050) ;
-                       goto sp_done ;
-               }
-
-       case SMT_P4051 :
-               {
-                       struct smt_p_4051       *sp ;
-                       sp = (struct smt_p_4051 *) to ;
-                       sp->p4051_multiple =
-                               mib_p->fddiPORTMultiple_U ;
-                       sp->p4051_porttype =
-                               mib_p->fddiPORTMy_Type ;
-                       sp->p4051_connectstate =
-                               mib_p->fddiPORTConnectState ;
-                       sp->p4051_pc_neighbor =
-                               mib_p->fddiPORTNeighborType ;
-                       sp->p4051_pc_withhold =
-                               mib_p->fddiPORTPC_Withhold ;
-                       sp_len = sizeof(struct smt_p_4051) ;
-                       goto sp_done ;
-               }
-       case SMT_P4052 :
-               {
-                       struct smt_p_4052       *sp ;
-                       sp = (struct smt_p_4052 *) to ;
-                       sp->p4052_flag =
-                               mib_p->fddiPORTEB_Condition ;
-                       sp->p4052_eberrorcount =
-                               mib_p->fddiPORTEBError_Ct ;
-                       sp_len = sizeof(struct smt_p_4052) ;
-                       goto sp_done ;
-               }
-       case SMT_P4053 :
-               {
-                       struct smt_p_4053       *sp ;
-                       sp = (struct smt_p_4053 *) to ;
-                       sp->p4053_multiple =
-                               mib_p->fddiPORTMultiple_P ;
-                       sp->p4053_availablepaths =
-                               mib_p->fddiPORTAvailablePaths ;
-                       sp->p4053_currentpath =
-                               mib_p->fddiPORTCurrentPath ;
-                       memcpy( (char *) &sp->p4053_requestedpaths,
-                               (char *) mib_p->fddiPORTRequestedPaths,4) ;
-                       sp->p4053_mytype =
-                               mib_p->fddiPORTMy_Type ;
-                       sp->p4053_neighbortype =
-                               mib_p->fddiPORTNeighborType ;
-                       sp_len = sizeof(struct smt_p_4053) ;
-                       goto sp_done ;
-               }
-       default :
-               break ;
-       }
-       /*
-        * in table ?
-        */
-       if (!pt) {
-               pcon->pc_err = (para & 0xff00) ? SMT_RDF_NOPARAM :
-                                               SMT_RDF_ILLEGAL ;
-               return ;
-       }
-       /*
-        * check access rights
-        */
-       switch (pt->p_access) {
-       case AC_G :
-       case AC_GR :
-               break ;
-       default :
-               pcon->pc_err = SMT_RDF_ILLEGAL ;
-               return ;
-       }
-       from = mib_addr + pt->p_offset ;
-       if (!swap)
-               swap = pt->p_swap ;             /* pointer to swap string */
-
-       /*
-        * copy values
-        */
-       while ((c = *swap++)) {
-               switch(c) {
-               case 'b' :
-               case 'w' :
-               case 'l' :
-                       break ;
-               case 'S' :
-               case 'E' :
-               case 'R' :
-               case 'r' :
-                       if (len < 4)
-                               goto len_error ;
-                       to[0] = 0 ;
-                       to[1] = 0 ;
-#ifdef LITTLE_ENDIAN
-                       if (c == 'r') {
-                               to[2] = *from++ ;
-                               to[3] = *from++ ;
-                       }
-                       else {
-                               to[3] = *from++ ;
-                               to[2] = *from++ ;
-                       }
-#else
-                       to[2] = *from++ ;
-                       to[3] = *from++ ;
-#endif
-                       to += 4 ;
-                       len -= 4 ;
-                       break ;
-               case 'I' :              /* for SET of port indexes */
-                       if (len < 2)
-                               goto len_error ;
-#ifdef LITTLE_ENDIAN
-                       to[1] = *from++ ;
-                       to[0] = *from++ ;
-#else
-                       to[0] = *from++ ;
-                       to[1] = *from++ ;
-#endif
-                       to += 2 ;
-                       len -= 2 ;
-                       break ;
-               case 'F' :
-               case 'B' :
-                       if (len < 4)
-                               goto len_error ;
-                       len -= 4 ;
-                       to[0] = 0 ;
-                       to[1] = 0 ;
-                       to[2] = 0 ;
-                       to[3] = *from++ ;
-                       to += 4 ;
-                       break ;
-               case 'C' :
-               case 'T' :
-               case 'L' :
-                       if (len < 4)
-                               goto len_error ;
-#ifdef LITTLE_ENDIAN
-                       to[3] = *from++ ;
-                       to[2] = *from++ ;
-                       to[1] = *from++ ;
-                       to[0] = *from++ ;
-#else
-                       to[0] = *from++ ;
-                       to[1] = *from++ ;
-                       to[2] = *from++ ;
-                       to[3] = *from++ ;
-#endif
-                       len -= 4 ;
-                       to += 4 ;
-                       break ;
-               case '2' :              /* PortMacIndicated */
-                       if (len < 4)
-                               goto len_error ;
-                       to[0] = 0 ;
-                       to[1] = 0 ;
-                       to[2] = *from++ ;
-                       to[3] = *from++ ;
-                       len -= 4 ;
-                       to += 4 ;
-                       break ;
-               case '4' :
-                       if (len < 4)
-                               goto len_error ;
-                       to[0] = *from++ ;
-                       to[1] = *from++ ;
-                       to[2] = *from++ ;
-                       to[3] = *from++ ;
-                       len -= 4 ;
-                       to += 4 ;
-                       break ;
-               case 'A' :
-                       if (len < 8)
-                               goto len_error ;
-                       to[0] = 0 ;
-                       to[1] = 0 ;
-                       memcpy((char *) to+2,(char *) from,6) ;
-                       to += 8 ;
-                       from += 8 ;
-                       len -= 8 ;
-                       break ;
-               case '8' :
-                       if (len < 8)
-                               goto len_error ;
-                       memcpy((char *) to,(char *) from,8) ;
-                       to += 8 ;
-                       from += 8 ;
-                       len -= 8 ;
-                       break ;
-               case 'D' :
-                       if (len < 32)
-                               goto len_error ;
-                       memcpy((char *) to,(char *) from,32) ;
-                       to += 32 ;
-                       from += 32 ;
-                       len -= 32 ;
-                       break ;
-               case 'P' :              /* timestamp is NOT swapped */
-                       if (len < 8)
-                               goto len_error ;
-                       to[0] = *from++ ;
-                       to[1] = *from++ ;
-                       to[2] = *from++ ;
-                       to[3] = *from++ ;
-                       to[4] = *from++ ;
-                       to[5] = *from++ ;
-                       to[6] = *from++ ;
-                       to[7] = *from++ ;
-                       to += 8 ;
-                       len -= 8 ;
-                       break ;
-               default :
-                       SMT_PANIC(smc,SMT_E0119, SMT_E0119_MSG) ;
-                       break ;
-               }
-       }
-
-done:
-       /*
-        * make it even (in case of 'I' encoding)
-        * note: len is DECREMENTED
-        */
-       if (len & 3) {
-               to[0] = 0 ;
-               to[1] = 0 ;
-               to += 4 - (len & 3 ) ;
-               len = len & ~ 3 ;
-       }
-
-       /* set type and length */
-       pa->p_type = para ;
-       pa->p_len = plen - len - PARA_LEN ;
-       /* return values */
-       pcon->pc_p = (void *) to ;
-       pcon->pc_len = len ;
-       return ;
-
-sp_done:
-       len -= sp_len ;
-       to += sp_len ;
-       goto done ;
-
-len_error:
-       /* parameter does not fit in frame */
-       pcon->pc_err = SMT_RDF_TOOLONG ;
-       return ;
-
-wrong_error:
-       pcon->pc_err = SMT_RDF_LENGTH ;
-}
-
-/*
- * set parameter
- */
-static int smt_set_para(struct s_smc *smc, struct smt_para *pa, int index,
-                       int local, int set)
-{
-#define IFSET(x)       if (set) (x)
-
-       const struct s_p_tab    *pt ;
-       int             len ;
-       char            *from ;
-       char            *to ;
-       const char      *swap ;
-       char            c ;
-       char            *mib_addr ;
-       struct fddi_mib *mib ;
-       struct fddi_mib_m       *mib_m = NULL;
-       struct fddi_mib_a       *mib_a = NULL;
-       struct fddi_mib_p       *mib_p = NULL;
-       int             mac ;
-       int             path ;
-       int             port ;
-       SK_LOC_DECL(u_char,byte_val) ;
-       SK_LOC_DECL(u_short,word_val) ;
-       SK_LOC_DECL(u_long,long_val) ;
-
-       mac = index - INDEX_MAC ;
-       path = index - INDEX_PATH ;
-       port = index - INDEX_PORT ;
-       len = pa->p_len ;
-       from = (char *) (pa + 1 ) ;
-
-       mib = &smc->mib ;
-       switch (pa->p_type & 0xf000) {
-       case 0x1000 :
-       default :
-               mib_addr = (char *) mib ;
-               break ;
-       case 0x2000 :
-               if (mac < 0 || mac >= NUMMACS) {
-                       return SMT_RDF_NOPARAM;
-               }
-               mib_m = &smc->mib.m[mac] ;
-               mib_addr = (char *) mib_m ;
-               from += 4 ;             /* skip index */
-               len -= 4 ;
-               break ;
-       case 0x3000 :
-               if (path < 0 || path >= NUMPATHS) {
-                       return SMT_RDF_NOPARAM;
-               }
-               mib_a = &smc->mib.a[path] ;
-               mib_addr = (char *) mib_a ;
-               from += 4 ;             /* skip index */
-               len -= 4 ;
-               break ;
-       case 0x4000 :
-               if (port < 0 || port >= smt_mib_phys(smc)) {
-                       return SMT_RDF_NOPARAM;
-               }
-               mib_p = &smc->mib.p[port_to_mib(smc,port)] ;
-               mib_addr = (char *) mib_p ;
-               from += 4 ;             /* skip index */
-               len -= 4 ;
-               break ;
-       }
-       switch (pa->p_type) {
-       case SMT_P10F0 :
-       case SMT_P10F1 :
-#ifdef ESS
-       case SMT_P10F2 :
-       case SMT_P10F3 :
-       case SMT_P10F4 :
-       case SMT_P10F5 :
-       case SMT_P10F6 :
-       case SMT_P10F7 :
-#endif
-#ifdef SBA
-       case SMT_P10F8 :
-       case SMT_P10F9 :
-#endif
-       case SMT_P20F1 :
-               if (!local)
-                       return SMT_RDF_NOPARAM;
-               break ;
-       }
-       pt = smt_get_ptab(pa->p_type) ;
-       if (!pt)
-               return (pa->p_type & 0xff00) ? SMT_RDF_NOPARAM :
-                                              SMT_RDF_ILLEGAL;
-       switch (pt->p_access) {
-       case AC_GR :
-       case AC_S :
-               break ;
-       default :
-               return SMT_RDF_ILLEGAL;
-       }
-       to = mib_addr + pt->p_offset ;
-       swap = pt->p_swap ;             /* pointer to swap string */
-
-       while (swap && (c = *swap++)) {
-               switch(c) {
-               case 'b' :
-                       to = (char *) &byte_val ;
-                       break ;
-               case 'w' :
-                       to = (char *) &word_val ;
-                       break ;
-               case 'l' :
-                       to = (char *) &long_val ;
-                       break ;
-               case 'S' :
-               case 'E' :
-               case 'R' :
-               case 'r' :
-                       if (len < 4) {
-                               goto len_error ;
-                       }
-                       if (from[0] | from[1])
-                               goto val_error ;
-#ifdef LITTLE_ENDIAN
-                       if (c == 'r') {
-                               to[0] = from[2] ;
-                               to[1] = from[3] ;
-                       }
-                       else {
-                               to[1] = from[2] ;
-                               to[0] = from[3] ;
-                       }
-#else
-                       to[0] = from[2] ;
-                       to[1] = from[3] ;
-#endif
-                       from += 4 ;
-                       to += 2 ;
-                       len -= 4 ;
-                       break ;
-               case 'F' :
-               case 'B' :
-                       if (len < 4) {
-                               goto len_error ;
-                       }
-                       if (from[0] | from[1] | from[2])
-                               goto val_error ;
-                       to[0] = from[3] ;
-                       len -= 4 ;
-                       from += 4 ;
-                       to += 4 ;
-                       break ;
-               case 'C' :
-               case 'T' :
-               case 'L' :
-                       if (len < 4) {
-                               goto len_error ;
-                       }
-#ifdef LITTLE_ENDIAN
-                       to[3] = *from++ ;
-                       to[2] = *from++ ;
-                       to[1] = *from++ ;
-                       to[0] = *from++ ;
-#else
-                       to[0] = *from++ ;
-                       to[1] = *from++ ;
-                       to[2] = *from++ ;
-                       to[3] = *from++ ;
-#endif
-                       len -= 4 ;
-                       to += 4 ;
-                       break ;
-               case 'A' :
-                       if (len < 8)
-                               goto len_error ;
-                       if (set)
-                               memcpy((char *) to,(char *) from+2,6) ;
-                       to += 8 ;
-                       from += 8 ;
-                       len -= 8 ;
-                       break ;
-               case '4' :
-                       if (len < 4)
-                               goto len_error ;
-                       if (set)
-                               memcpy((char *) to,(char *) from,4) ;
-                       to += 4 ;
-                       from += 4 ;
-                       len -= 4 ;
-                       break ;
-               case '8' :
-                       if (len < 8)
-                               goto len_error ;
-                       if (set)
-                               memcpy((char *) to,(char *) from,8) ;
-                       to += 8 ;
-                       from += 8 ;
-                       len -= 8 ;
-                       break ;
-               case 'D' :
-                       if (len < 32)
-                               goto len_error ;
-                       if (set)
-                               memcpy((char *) to,(char *) from,32) ;
-                       to += 32 ;
-                       from += 32 ;
-                       len -= 32 ;
-                       break ;
-               case 'P' :              /* timestamp is NOT swapped */
-                       if (set) {
-                               to[0] = *from++ ;
-                               to[1] = *from++ ;
-                               to[2] = *from++ ;
-                               to[3] = *from++ ;
-                               to[4] = *from++ ;
-                               to[5] = *from++ ;
-                               to[6] = *from++ ;
-                               to[7] = *from++ ;
-                       }
-                       to += 8 ;
-                       len -= 8 ;
-                       break ;
-               default :
-                       SMT_PANIC(smc,SMT_E0120, SMT_E0120_MSG) ;
-                       return SMT_RDF_ILLEGAL;
-               }
-       }
-       /*
-        * actions and internal updates
-        */
-       switch (pa->p_type) {
-       case SMT_P101A:                 /* fddiSMTConfigPolicy */
-               if (word_val & ~1)
-                       goto val_error ;
-               IFSET(mib->fddiSMTConfigPolicy = word_val) ;
-               break ;
-       case SMT_P101B :                /* fddiSMTConnectionPolicy */
-               if (!(word_val & POLICY_MM))
-                       goto val_error ;
-               IFSET(mib->fddiSMTConnectionPolicy = word_val) ;
-               break ;
-       case SMT_P101D :                /* fddiSMTTT_Notify */
-               if (word_val < 2 || word_val > 30)
-                       goto val_error ;
-               IFSET(mib->fddiSMTTT_Notify = word_val) ;
-               break ;
-       case SMT_P101E :                /* fddiSMTStatRptPolicy */
-               if (byte_val & ~1)
-                       goto val_error ;
-               IFSET(mib->fddiSMTStatRptPolicy = byte_val) ;
-               break ;
-       case SMT_P101F :                /* fddiSMTTrace_MaxExpiration */
-               /*
-                * note: lower limit trace_max = 6.001773... s
-                * NO upper limit
-                */
-               if (long_val < (long)0x478bf51L)
-                       goto val_error ;
-               IFSET(mib->fddiSMTTrace_MaxExpiration = long_val) ;
-               break ;
-#ifdef ESS
-       case SMT_P10F2 :                /* fddiESSPayload */
-               if (long_val > 1562)
-                       goto val_error ;
-               if (set && smc->mib.fddiESSPayload != long_val) {
-                       smc->ess.raf_act_timer_poll = TRUE ;
-                       smc->mib.fddiESSPayload = long_val ;
-               }
-               break ;
-       case SMT_P10F3 :                /* fddiESSOverhead */
-               if (long_val < 50 || long_val > 5000)
-                       goto val_error ;
-               if (set && smc->mib.fddiESSPayload &&
-                       smc->mib.fddiESSOverhead != long_val) {
-                       smc->ess.raf_act_timer_poll = TRUE ;
-                       smc->mib.fddiESSOverhead = long_val ;
-               }
-               break ;
-       case SMT_P10F4 :                /* fddiESSMaxTNeg */
-               if (long_val > -MS2BCLK(5) || long_val < -MS2BCLK(165))
-                       goto val_error ;
-               IFSET(mib->fddiESSMaxTNeg = long_val) ;
-               break ;
-       case SMT_P10F5 :                /* fddiESSMinSegmentSize */
-               if (long_val < 1 || long_val > 4478)
-                       goto val_error ;
-               IFSET(mib->fddiESSMinSegmentSize = long_val) ;
-               break ;
-       case SMT_P10F6 :                /* fddiESSCategory */
-               if ((long_val & 0xffff) != 1)
-                       goto val_error ;
-               IFSET(mib->fddiESSCategory = long_val) ;
-               break ;
-       case SMT_P10F7 :                /* fddiESSSyncTxMode */
-               if (word_val > 1)
-                       goto val_error ;
-               IFSET(mib->fddiESSSynchTxMode = word_val) ;
-               break ;
-#endif
-#ifdef SBA
-       case SMT_P10F8 :                /* fddiSBACommand */
-               if (byte_val != SB_STOP && byte_val != SB_START)
-                       goto val_error ;
-               IFSET(mib->fddiSBACommand = byte_val) ;
-               break ;
-       case SMT_P10F9 :                /* fddiSBAAvailable */
-               if (byte_val > 100)
-                       goto val_error ;
-               IFSET(mib->fddiSBAAvailable = byte_val) ;
-               break ;
-#endif
-       case SMT_P2020 :                /* fddiMACRequestedPaths */
-               if ((word_val & (MIB_P_PATH_PRIM_PREFER |
-                       MIB_P_PATH_PRIM_ALTER)) == 0 )
-                       goto val_error ;
-               IFSET(mib_m->fddiMACRequestedPaths = word_val) ;
-               break ;
-       case SMT_P205F :                /* fddiMACFrameErrorThreshold */
-               /* 0 .. ffff acceptable */
-               IFSET(mib_m->fddiMACFrameErrorThreshold = word_val) ;
-               break ;
-       case SMT_P2067 :                /* fddiMACNotCopiedThreshold */
-               /* 0 .. ffff acceptable */
-               IFSET(mib_m->fddiMACNotCopiedThreshold = word_val) ;
-               break ;
-       case SMT_P2076:                 /* fddiMACMA_UnitdataEnable */
-               if (byte_val & ~1)
-                       goto val_error ;
-               if (set) {
-                       mib_m->fddiMACMA_UnitdataEnable = byte_val ;
-                       queue_event(smc,EVENT_RMT,RM_ENABLE_FLAG) ;
-               }
-               break ;
-       case SMT_P20F1 :                /* fddiMACT_Min */
-               IFSET(mib_m->fddiMACT_Min = long_val) ;
-               break ;
-       case SMT_P320F :
-               if (long_val > 1562)
-                       goto val_error ;
-               IFSET(mib_a->fddiPATHSbaPayload = long_val) ;
-#ifdef ESS
-               if (set)
-                       ess_para_change(smc) ;
-#endif
-               break ;
-       case SMT_P3210 :
-               if (long_val > 5000)
-                       goto val_error ;
-               
-               if (long_val != 0 && mib_a->fddiPATHSbaPayload == 0)
-                       goto val_error ;
-
-               IFSET(mib_a->fddiPATHSbaOverhead = long_val) ;
-#ifdef ESS
-               if (set)
-                       ess_para_change(smc) ;
-#endif
-               break ;
-       case SMT_P3213:                 /* fddiPATHT_Rmode */
-               /* no limit :
-                * 0 .. 343.597 => 0 .. 2e32 * 80nS
-                */
-               if (set) {
-                       mib_a->fddiPATHT_Rmode = long_val ;
-                       rtm_set_timer(smc) ;
-               }
-               break ;
-       case SMT_P3214 :                /* fddiPATHSbaAvailable */
-               if (long_val > 0x00BEBC20L)
-                       goto val_error ;
-#ifdef SBA 
-               if (set && mib->fddiSBACommand == SB_STOP)
-                       goto val_error ;
-#endif
-               IFSET(mib_a->fddiPATHSbaAvailable = long_val) ;
-               break ;
-       case SMT_P3215 :                /* fddiPATHTVXLowerBound */
-               IFSET(mib_a->fddiPATHTVXLowerBound = long_val) ;
-               goto change_mac_para ;
-       case SMT_P3216 :                /* fddiPATHT_MaxLowerBound */
-               IFSET(mib_a->fddiPATHT_MaxLowerBound = long_val) ;
-               goto change_mac_para ;
-       case SMT_P3217 :                /* fddiPATHMaxT_Req */
-               IFSET(mib_a->fddiPATHMaxT_Req = long_val) ;
-
-change_mac_para:
-               if (set && smt_set_mac_opvalues(smc)) {
-                       RS_SET(smc,RS_EVENT) ;
-                       smc->sm.please_reconnect = 1 ;
-                       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
-               }
-               break ;
-       case SMT_P400E :                /* fddiPORTConnectionPolicies */
-               if (byte_val > 1)
-                       goto val_error ;
-               IFSET(mib_p->fddiPORTConnectionPolicies = byte_val) ;
-               break ;
-       case SMT_P4011 :                /* fddiPORTRequestedPaths */
-               /* all 3*8 bits allowed */
-               IFSET(memcpy((char *)mib_p->fddiPORTRequestedPaths,
-                       (char *)&long_val,4)) ;
-               break ;
-       case SMT_P401F:                 /* fddiPORTMaint_LS */
-               if (word_val > 4)
-                       goto val_error ;
-               IFSET(mib_p->fddiPORTMaint_LS = word_val) ;
-               break ;
-       case SMT_P403A :                /* fddiPORTLer_Cutoff */
-               if (byte_val < 4 || byte_val > 15)
-                       goto val_error ;
-               IFSET(mib_p->fddiPORTLer_Cutoff = byte_val) ;
-               break ;
-       case SMT_P403B :                /* fddiPORTLer_Alarm */
-               if (byte_val < 4 || byte_val > 15)
-                       goto val_error ;
-               IFSET(mib_p->fddiPORTLer_Alarm = byte_val) ;
-               break ;
-
-       /*
-        * Actions
-        */
-       case SMT_P103C :                /* fddiSMTStationAction */
-               if (smt_action(smc,SMT_STATION_ACTION, (int) word_val, 0))
-                       goto val_error ;
-               break ;
-       case SMT_P4046:                 /* fddiPORTAction */
-               if (smt_action(smc,SMT_PORT_ACTION, (int) word_val,
-                       port_to_mib(smc,port)))
-                       goto val_error ;
-               break ;
-       default :
-               break ;
-       }
-       return 0;
-
-val_error:
-       /* parameter value in frame is out of range */
-       return SMT_RDF_RANGE;
-
-len_error:
-       /* parameter value in frame is too short */
-       return SMT_RDF_LENGTH;
-
-#if    0
-no_author_error:
-       /* parameter not setable, because the SBA is not active
-        * Please note: we give the return code 'not authorizeed
-        *  because SBA denied is not a valid return code in the
-        * PMF protocol.
-        */
-       return SMT_RDF_AUTHOR;
-#endif
-}
-
-static const struct s_p_tab *smt_get_ptab(u_short para)
-{
-       const struct s_p_tab    *pt ;
-       for (pt = p_tab ; pt->p_num && pt->p_num != para ; pt++)
-               ;
-       return pt->p_num ? pt : NULL;
-}
-
-static int smt_mib_phys(struct s_smc *smc)
-{
-#ifdef CONCENTRATOR
-       SK_UNUSED(smc) ;
-
-       return NUMPHYS;
-#else
-       if (smc->s.sas == SMT_SAS)
-               return 1;
-       return NUMPHYS;
-#endif
-}
-
-static int port_to_mib(struct s_smc *smc, int p)
-{
-#ifdef CONCENTRATOR
-       SK_UNUSED(smc) ;
-
-       return p;
-#else
-       if (smc->s.sas == SMT_SAS)
-               return PS;
-       return p;
-#endif
-}
-
-
-#ifdef DEBUG
-#ifndef        BOOT
-void dump_smt(struct s_smc *smc, struct smt_header *sm, char *text)
-{
-       int     len ;
-       struct smt_para *pa ;
-       char    *c ;
-       int     n ;
-       int     nn ;
-#ifdef LITTLE_ENDIAN
-       int     smtlen ;
-#endif
-
-       SK_UNUSED(smc) ;
-
-#ifdef DEBUG_BRD
-       if (smc->debug.d_smtf < 2)
-#else
-       if (debug.d_smtf < 2)
-#endif
-               return ;
-#ifdef LITTLE_ENDIAN
-       smtlen = sm->smt_len + sizeof(struct smt_header) ;
-#endif
-       printf("SMT Frame [%s]:\nDA  ",text) ;
-       dump_hex((char *) &sm->smt_dest,6) ;
-       printf("\tSA ") ;
-       dump_hex((char *) &sm->smt_source,6) ;
-       printf(" Class %x Type %x Version %x\n",
-               sm->smt_class,sm->smt_type,sm->smt_version)  ;
-       printf("TID %lx\t\tSID ",sm->smt_tid) ;
-       dump_hex((char *) &sm->smt_sid,8) ;
-       printf(" LEN %x\n",sm->smt_len) ;
-
-       len = sm->smt_len ;
-       pa = (struct smt_para *) (sm + 1) ;
-       while (len > 0 ) {
-               int     plen ;
-#ifdef UNIX
-               printf("TYPE %x LEN %x VALUE\t",pa->p_type,pa->p_len) ;
-#else
-               printf("TYPE %04x LEN %2x VALUE\t",pa->p_type,pa->p_len) ;
-#endif
-               n = pa->p_len ;
-               if ( (n < 0 ) || (n > (int)(len - PARA_LEN))) {
-                       n = len - PARA_LEN ;
-                       printf(" BAD LENGTH\n") ;
-                       break ;
-               }
-#ifdef LITTLE_ENDIAN
-               smt_swap_para(sm,smtlen,0) ;
-#endif
-               if (n < 24) {
-                       dump_hex((char *)(pa+1),(int) n) ;
-                       printf("\n") ;
-               }
-               else {
-                       int     first = 0 ;
-                       c = (char *)(pa+1) ;
-                       dump_hex(c,16) ;
-                       printf("\n") ;
-                       n -= 16 ;
-                       c += 16 ;
-                       while (n > 0) {
-                               nn = (n > 16) ? 16 : n ;
-                               if (n > 64) {
-                                       if (first == 0)
-                                               printf("\t\t\t...\n") ;
-                                       first = 1 ;
-                               }
-                               else {
-                                       printf("\t\t\t") ;
-                                       dump_hex(c,nn) ;
-                                       printf("\n") ;
-                               }
-                               n -= nn ;
-                               c += 16 ;
-                       }
-               }
-#ifdef LITTLE_ENDIAN
-               smt_swap_para(sm,smtlen,1) ;
-#endif
-               plen = (pa->p_len + PARA_LEN + 3) & ~3 ;
-               len -= plen ;
-               pa = (struct smt_para *)((char *)pa + plen) ;
-       }
-       printf("-------------------------------------------------\n\n") ;
-}
-
-void dump_hex(char *p, int len)
-{
-       int     n = 0 ;
-       while (len--) {
-               n++ ;
-#ifdef UNIX
-               printf("%x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
-#else
-               printf("%02x%s",*p++ & 0xff,len ? ( (n & 7) ? " " : "-") : "") ;
-#endif
-       }
-}
-#endif /* no BOOT */
-#endif /* DEBUG */
-
-
-#endif /* no SLIM_SMT */
diff --git a/drivers/net/skfp/queue.c b/drivers/net/skfp/queue.c
deleted file mode 100644 (file)
index c1a0df4..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT Event Queue Management
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)queue.c     2.9 97/08/04 (C) SK " ;
-#endif
-
-#define PRINTF(a,b,c)
-
-/*
- * init event queue management
- */
-void ev_init(struct s_smc *smc)
-{
-       smc->q.ev_put = smc->q.ev_get = smc->q.ev_queue ;
-}
-
-/*
- * add event to queue
- */
-void queue_event(struct s_smc *smc, int class, int event)
-{
-       PRINTF("queue class %d event %d\n",class,event) ;
-       smc->q.ev_put->class = class ;
-       smc->q.ev_put->event = event ;
-       if (++smc->q.ev_put == &smc->q.ev_queue[MAX_EVENT])
-               smc->q.ev_put = smc->q.ev_queue ;
-
-       if (smc->q.ev_put == smc->q.ev_get) {
-               SMT_ERR_LOG(smc,SMT_E0137, SMT_E0137_MSG) ;
-       }
-}
-
-/*
- * timer_event is called from HW timer package.
- */
-void timer_event(struct s_smc *smc, u_long token)
-{
-       PRINTF("timer event class %d token %d\n",
-               EV_T_CLASS(token),
-               EV_T_EVENT(token)) ;
-       queue_event(smc,EV_T_CLASS(token),EV_T_EVENT(token));
-}
-
-/*
- * event dispatcher
- *     while event queue is not empty
- *             get event from queue
- *             send command to state machine
- *     end
- */
-void ev_dispatcher(struct s_smc *smc)
-{
-       struct event_queue *ev ;        /* pointer into queue */
-       int             class ;
-
-       ev = smc->q.ev_get ;
-       PRINTF("dispatch get %x put %x\n",ev,smc->q.ev_put) ;
-       while (ev != smc->q.ev_put) {
-               PRINTF("dispatch class %d event %d\n",ev->class,ev->event) ;
-               switch(class = ev->class) {
-               case EVENT_ECM :                /* Entity Corordination  Man. */
-                       ecm(smc,(int)ev->event) ;
-                       break ;
-               case EVENT_CFM :                /* Configuration Man. */
-                       cfm(smc,(int)ev->event) ;
-                       break ;
-               case EVENT_RMT :                /* Ring Man. */
-                       rmt(smc,(int)ev->event) ;
-                       break ;
-               case EVENT_SMT :
-                       smt_event(smc,(int)ev->event) ;
-                       break ;
-#ifdef CONCENTRATOR
-               case 99 :
-                       timer_test_event(smc,(int)ev->event) ;
-                       break ;
-#endif
-               case EVENT_PCMA :               /* PHY A */
-               case EVENT_PCMB :               /* PHY B */
-               default :
-                       if (class >= EVENT_PCMA &&
-                           class < EVENT_PCMA + NUMPHYS) {
-                               pcm(smc,class - EVENT_PCMA,(int)ev->event) ;
-                               break ;
-                       }
-                       SMT_PANIC(smc,SMT_E0121, SMT_E0121_MSG) ;
-                       return ;
-               }
-
-               if (++ev == &smc->q.ev_queue[MAX_EVENT])
-                       ev = smc->q.ev_queue ;
-
-               /* Renew get: it is used in queue_events to detect overruns */
-               smc->q.ev_get = ev;
-       }
-}
-
-/*
- * smt_online connects to or disconnects from the ring
- * MUST be called to initiate connection establishment
- *
- *     on      0       disconnect
- *     on      1       connect
- */
-u_short smt_online(struct s_smc *smc, int on)
-{
-       queue_event(smc,EVENT_ECM,on ? EC_CONNECT : EC_DISCONNECT) ;
-       ev_dispatcher(smc) ;
-       return smc->mib.fddiSMTCF_State;
-}
-
-/*
- * set SMT flag to value
- *     flag            flag name
- *     value           flag value
- * dump current flag setting
- */
-#ifdef CONCENTRATOR
-void do_smt_flag(struct s_smc *smc, char *flag, int value)
-{
-#ifdef DEBUG
-       struct smt_debug        *deb;
-
-       SK_UNUSED(smc) ;
-
-#ifdef DEBUG_BRD
-       deb = &smc->debug;
-#else
-       deb = &debug;
-#endif
-       if (!strcmp(flag,"smt"))
-               deb->d_smt = value ;
-       else if (!strcmp(flag,"smtf"))
-               deb->d_smtf = value ;
-       else if (!strcmp(flag,"pcm"))
-               deb->d_pcm = value ;
-       else if (!strcmp(flag,"rmt"))
-               deb->d_rmt = value ;
-       else if (!strcmp(flag,"cfm"))
-               deb->d_cfm = value ;
-       else if (!strcmp(flag,"ecm"))
-               deb->d_ecm = value ;
-       printf("smt     %d\n",deb->d_smt) ;
-       printf("smtf    %d\n",deb->d_smtf) ;
-       printf("pcm     %d\n",deb->d_pcm) ;
-       printf("rmt     %d\n",deb->d_rmt) ;
-       printf("cfm     %d\n",deb->d_cfm) ;
-       printf("ecm     %d\n",deb->d_ecm) ;
-#endif /* DEBUG */
-}
-#endif
diff --git a/drivers/net/skfp/rmt.c b/drivers/net/skfp/rmt.c
deleted file mode 100644 (file)
index ef8d567..0000000
+++ /dev/null
@@ -1,654 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT RMT
-       Ring Management
-*/
-
-/*
- * Hardware independent state machine implemantation
- * The following external SMT functions are referenced :
- *
- *             queue_event()
- *             smt_timer_start()
- *             smt_timer_stop()
- *
- *     The following external HW dependent functions are referenced :
- *             sm_ma_control()
- *             sm_mac_check_beacon_claim()
- *
- *     The following HW dependent events are required :
- *             RM_RING_OP
- *             RM_RING_NON_OP
- *             RM_MY_BEACON
- *             RM_OTHER_BEACON
- *             RM_MY_CLAIM
- *             RM_TRT_EXP
- *             RM_VALID_CLAIM
- *
- */
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)rmt.c       2.13 99/07/02 (C) SK " ;
-#endif
-
-/*
- * FSM Macros
- */
-#define AFLAG  0x10
-#define GO_STATE(x)    (smc->mib.m[MAC0].fddiMACRMTState = (x)|AFLAG)
-#define ACTIONS_DONE() (smc->mib.m[MAC0].fddiMACRMTState &= ~AFLAG)
-#define ACTIONS(x)     (x|AFLAG)
-
-#define RM0_ISOLATED   0
-#define RM1_NON_OP     1               /* not operational */
-#define RM2_RING_OP    2               /* ring operational */
-#define RM3_DETECT     3               /* detect dupl addresses */
-#define RM4_NON_OP_DUP 4               /* dupl. addr detected */
-#define RM5_RING_OP_DUP        5               /* ring oper. with dupl. addr */
-#define RM6_DIRECTED   6               /* sending directed beacons */
-#define RM7_TRACE      7               /* trace initiated */
-
-#ifdef DEBUG
-/*
- * symbolic state names
- */
-static const char * const rmt_states[] = {
-       "RM0_ISOLATED","RM1_NON_OP","RM2_RING_OP","RM3_DETECT",
-       "RM4_NON_OP_DUP","RM5_RING_OP_DUP","RM6_DIRECTED",
-       "RM7_TRACE"
-} ;
-
-/*
- * symbolic event names
- */
-static const char * const rmt_events[] = {
-       "NONE","RM_RING_OP","RM_RING_NON_OP","RM_MY_BEACON",
-       "RM_OTHER_BEACON","RM_MY_CLAIM","RM_TRT_EXP","RM_VALID_CLAIM",
-       "RM_JOIN","RM_LOOP","RM_DUP_ADDR","RM_ENABLE_FLAG",
-       "RM_TIMEOUT_NON_OP","RM_TIMEOUT_T_STUCK",
-       "RM_TIMEOUT_ANNOUNCE","RM_TIMEOUT_T_DIRECT",
-       "RM_TIMEOUT_D_MAX","RM_TIMEOUT_POLL","RM_TX_STATE_CHANGE"
-} ;
-#endif
-
-/*
- * Globals
- * in struct s_rmt
- */
-
-
-/*
- * function declarations
- */
-static void rmt_fsm(struct s_smc *smc, int cmd);
-static void start_rmt_timer0(struct s_smc *smc, u_long value, int event);
-static void start_rmt_timer1(struct s_smc *smc, u_long value, int event);
-static void start_rmt_timer2(struct s_smc *smc, u_long value, int event);
-static void stop_rmt_timer0(struct s_smc *smc);
-static void stop_rmt_timer1(struct s_smc *smc);
-static void stop_rmt_timer2(struct s_smc *smc);
-static void rmt_dup_actions(struct s_smc *smc);
-static void rmt_reinsert_actions(struct s_smc *smc);
-static void rmt_leave_actions(struct s_smc *smc);
-static void rmt_new_dup_actions(struct s_smc *smc);
-
-#ifndef SUPERNET_3
-extern void restart_trt_for_dbcn() ;
-#endif /*SUPERNET_3*/
-
-/*
-       init RMT state machine
-       clear all RMT vars and flags
-*/
-void rmt_init(struct s_smc *smc)
-{
-       smc->mib.m[MAC0].fddiMACRMTState = ACTIONS(RM0_ISOLATED) ;
-       smc->r.dup_addr_test = DA_NONE ;
-       smc->r.da_flag = 0 ;
-       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
-       smc->r.sm_ma_avail = FALSE ;
-       smc->r.loop_avail = 0 ;
-       smc->r.bn_flag = 0 ;
-       smc->r.jm_flag = 0 ;
-       smc->r.no_flag = TRUE ;
-}
-
-/*
-       RMT state machine
-       called by dispatcher
-
-       do
-               display state change
-               process event
-       until SM is stable
-*/
-void rmt(struct s_smc *smc, int event)
-{
-       int     state ;
-
-       do {
-               DB_RMT("RMT : state %s%s",
-                       (smc->mib.m[MAC0].fddiMACRMTState & AFLAG) ? "ACTIONS " : "",
-                       rmt_states[smc->mib.m[MAC0].fddiMACRMTState & ~AFLAG]) ;
-               DB_RMT(" event %s\n",rmt_events[event],0) ;
-               state = smc->mib.m[MAC0].fddiMACRMTState ;
-               rmt_fsm(smc,event) ;
-               event = 0 ;
-       } while (state != smc->mib.m[MAC0].fddiMACRMTState) ;
-       rmt_state_change(smc,(int)smc->mib.m[MAC0].fddiMACRMTState) ;
-}
-
-/*
-       process RMT event
-*/
-static void rmt_fsm(struct s_smc *smc, int cmd)
-{
-       /*
-        * RM00-RM70 : from all states
-        */
-       if (!smc->r.rm_join && !smc->r.rm_loop &&
-               smc->mib.m[MAC0].fddiMACRMTState != ACTIONS(RM0_ISOLATED) &&
-               smc->mib.m[MAC0].fddiMACRMTState != RM0_ISOLATED) {
-               RS_SET(smc,RS_NORINGOP) ;
-               rmt_indication(smc,0) ;
-               GO_STATE(RM0_ISOLATED) ;
-               return ;
-       }
-
-       switch(smc->mib.m[MAC0].fddiMACRMTState) {
-       case ACTIONS(RM0_ISOLATED) :
-               stop_rmt_timer0(smc) ;
-               stop_rmt_timer1(smc) ;
-               stop_rmt_timer2(smc) ;
-
-               /*
-                * Disable MAC.
-                */
-               sm_ma_control(smc,MA_OFFLINE) ;
-               smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
-               smc->r.loop_avail = FALSE ;
-               smc->r.sm_ma_avail = FALSE ;
-               smc->r.no_flag = TRUE ;
-               DB_RMTN(1,"RMT : ISOLATED\n",0,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM0_ISOLATED :
-               /*RM01*/
-               if (smc->r.rm_join || smc->r.rm_loop) {
-                       /*
-                        * According to the standard the MAC must be reset
-                        * here. The FORMAC will be initialized and Claim
-                        * and Beacon Frames will be uploaded to the MAC.
-                        * So any change of Treq will take effect NOW.
-                        */
-                       sm_ma_control(smc,MA_RESET) ;
-                       GO_STATE(RM1_NON_OP) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM1_NON_OP) :
-               start_rmt_timer0(smc,smc->s.rmt_t_non_op,RM_TIMEOUT_NON_OP) ;
-               stop_rmt_timer1(smc) ;
-               stop_rmt_timer2(smc) ;
-               sm_ma_control(smc,MA_BEACON) ;
-               DB_RMTN(1,"RMT : RING DOWN\n",0,0) ;
-               RS_SET(smc,RS_NORINGOP) ;
-               smc->r.sm_ma_avail = FALSE ;
-               rmt_indication(smc,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM1_NON_OP :
-               /*RM12*/
-               if (cmd == RM_RING_OP) {
-                       RS_SET(smc,RS_RINGOPCHANGE) ;
-                       GO_STATE(RM2_RING_OP) ;
-                       break ;
-               }
-               /*RM13*/
-               else if (cmd == RM_TIMEOUT_NON_OP) {
-                       smc->r.bn_flag = FALSE ;
-                       smc->r.no_flag = TRUE ;
-                       GO_STATE(RM3_DETECT) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM2_RING_OP) :
-               stop_rmt_timer0(smc) ;
-               stop_rmt_timer1(smc) ;
-               stop_rmt_timer2(smc) ;
-               smc->r.no_flag = FALSE ;
-               if (smc->r.rm_loop)
-                       smc->r.loop_avail = TRUE ;
-               if (smc->r.rm_join) {
-                       smc->r.sm_ma_avail = TRUE ;
-                       if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
-                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
-                               else
-                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
-               }
-               DB_RMTN(1,"RMT : RING UP\n",0,0) ;
-               RS_CLEAR(smc,RS_NORINGOP) ;
-               RS_SET(smc,RS_RINGOPCHANGE) ;
-               rmt_indication(smc,1) ;
-               smt_stat_counter(smc,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM2_RING_OP :
-               /*RM21*/
-               if (cmd == RM_RING_NON_OP) {
-                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
-                       smc->r.loop_avail = FALSE ;
-                       RS_SET(smc,RS_RINGOPCHANGE) ;
-                       GO_STATE(RM1_NON_OP) ;
-                       break ;
-               }
-               /*RM22a*/
-               else if (cmd == RM_ENABLE_FLAG) {
-                       if (smc->mib.m[MAC0].fddiMACMA_UnitdataEnable)
-                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = TRUE ;
-                               else
-                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
-               }
-               /*RM25*/
-               else if (smc->r.dup_addr_test == DA_FAILED) {
-                       smc->mib.m[MAC0].fddiMACMA_UnitdataAvailable = FALSE ;
-                       smc->r.loop_avail = FALSE ;
-                       smc->r.da_flag = TRUE ;
-                       GO_STATE(RM5_RING_OP_DUP) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM3_DETECT) :
-               start_rmt_timer0(smc,smc->s.mac_d_max*2,RM_TIMEOUT_D_MAX) ;
-               start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
-               start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
-               sm_mac_check_beacon_claim(smc) ;
-               DB_RMTN(1,"RMT : RM3_DETECT\n",0,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM3_DETECT :
-               if (cmd == RM_TIMEOUT_POLL) {
-                       start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
-                       sm_mac_check_beacon_claim(smc) ;
-                       break ;
-               }
-               if (cmd == RM_TIMEOUT_D_MAX) {
-                       smc->r.timer0_exp = TRUE ;
-               }
-               /*
-                *jd(22-Feb-1999)
-                * We need a time ">= 2*mac_d_max" since we had finished
-                * Claim or Beacon state. So we will restart timer0 at
-                * every state change.
-                */
-               if (cmd == RM_TX_STATE_CHANGE) {
-                       start_rmt_timer0(smc,
-                                        smc->s.mac_d_max*2,
-                                        RM_TIMEOUT_D_MAX) ;
-               }
-               /*RM32*/
-               if (cmd == RM_RING_OP) {
-                       GO_STATE(RM2_RING_OP) ;
-                       break ;
-               }
-               /*RM33a*/
-               else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON)
-                       && smc->r.bn_flag) {
-                       smc->r.bn_flag = FALSE ;
-               }
-               /*RM33b*/
-               else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
-                       int     tx ;
-                       /*
-                        * set bn_flag only if in state T4 or T5:
-                        * only if we're the beaconer should we start the
-                        * trace !
-                        */
-                       if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
-                       DB_RMTN(2,"RMT : DETECT && TRT_EXPIRED && T4/T5\n",0,0);
-                               smc->r.bn_flag = TRUE ;
-                               /*
-                                * If one of the upstream stations beaconed
-                                * and the link to the upstream neighbor is
-                                * lost we need to restart the stuck timer to
-                                * check the "stuck beacon" condition.
-                                */
-                               start_rmt_timer1(smc,smc->s.rmt_t_stuck,
-                                       RM_TIMEOUT_T_STUCK) ;
-                       }
-                       /*
-                        * We do NOT need to clear smc->r.bn_flag in case of
-                        * not being in state T4 or T5, because the flag
-                        * must be cleared in order to get in this condition.
-                        */
-
-                       DB_RMTN(2,
-                       "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
-                       tx,smc->r.bn_flag) ;
-               }
-               /*RM34a*/
-               else if (cmd == RM_MY_CLAIM && smc->r.timer0_exp) {
-                       rmt_new_dup_actions(smc) ;
-                       GO_STATE(RM4_NON_OP_DUP) ;
-                       break ;
-               }
-               /*RM34b*/
-               else if (cmd == RM_MY_BEACON && smc->r.timer0_exp) {
-                       rmt_new_dup_actions(smc) ;
-                       GO_STATE(RM4_NON_OP_DUP) ;
-                       break ;
-               }
-               /*RM34c*/
-               else if (cmd == RM_VALID_CLAIM) {
-                       rmt_new_dup_actions(smc) ;
-                       GO_STATE(RM4_NON_OP_DUP) ;
-                       break ;
-               }
-               /*RM36*/
-               else if (cmd == RM_TIMEOUT_T_STUCK &&
-                       smc->r.rm_join && smc->r.bn_flag) {
-                       GO_STATE(RM6_DIRECTED) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM4_NON_OP_DUP) :
-               start_rmt_timer0(smc,smc->s.rmt_t_announce,RM_TIMEOUT_ANNOUNCE);
-               start_rmt_timer1(smc,smc->s.rmt_t_stuck,RM_TIMEOUT_T_STUCK) ;
-               start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
-               sm_mac_check_beacon_claim(smc) ;
-               DB_RMTN(1,"RMT : RM4_NON_OP_DUP\n",0,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM4_NON_OP_DUP :
-               if (cmd == RM_TIMEOUT_POLL) {
-                       start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
-                       sm_mac_check_beacon_claim(smc) ;
-                       break ;
-               }
-               /*RM41*/
-               if (!smc->r.da_flag) {
-                       GO_STATE(RM1_NON_OP) ;
-                       break ;
-               }
-               /*RM44a*/
-               else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
-                       smc->r.bn_flag) {
-                       smc->r.bn_flag = FALSE ;
-               }
-               /*RM44b*/
-               else if (cmd == RM_TRT_EXP && !smc->r.bn_flag) {
-                       int     tx ;
-                       /*
-                        * set bn_flag only if in state T4 or T5:
-                        * only if we're the beaconer should we start the
-                        * trace !
-                        */
-                       if ((tx =  sm_mac_get_tx_state(smc)) == 4 || tx == 5) {
-                       DB_RMTN(2,"RMT : NOPDUP && TRT_EXPIRED && T4/T5\n",0,0);
-                               smc->r.bn_flag = TRUE ;
-                               /*
-                                * If one of the upstream stations beaconed
-                                * and the link to the upstream neighbor is
-                                * lost we need to restart the stuck timer to
-                                * check the "stuck beacon" condition.
-                                */
-                               start_rmt_timer1(smc,smc->s.rmt_t_stuck,
-                                       RM_TIMEOUT_T_STUCK) ;
-                       }
-                       /*
-                        * We do NOT need to clear smc->r.bn_flag in case of
-                        * not being in state T4 or T5, because the flag
-                        * must be cleared in order to get in this condition.
-                        */
-
-                       DB_RMTN(2,
-                       "RMT : sm_mac_get_tx_state() = %d (bn_flag = %d)\n",
-                       tx,smc->r.bn_flag) ;
-               }
-               /*RM44c*/
-               else if (cmd == RM_TIMEOUT_ANNOUNCE && !smc->r.bn_flag) {
-                       rmt_dup_actions(smc) ;
-               }
-               /*RM45*/
-               else if (cmd == RM_RING_OP) {
-                       smc->r.no_flag = FALSE ;
-                       GO_STATE(RM5_RING_OP_DUP) ;
-                       break ;
-               }
-               /*RM46*/
-               else if (cmd == RM_TIMEOUT_T_STUCK &&
-                       smc->r.rm_join && smc->r.bn_flag) {
-                       GO_STATE(RM6_DIRECTED) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM5_RING_OP_DUP) :
-               stop_rmt_timer0(smc) ;
-               stop_rmt_timer1(smc) ;
-               stop_rmt_timer2(smc) ;
-               DB_RMTN(1,"RMT : RM5_RING_OP_DUP\n",0,0) ;
-               ACTIONS_DONE() ;
-               break;
-       case RM5_RING_OP_DUP :
-               /*RM52*/
-               if (smc->r.dup_addr_test == DA_PASSED) {
-                       smc->r.da_flag = FALSE ;
-                       GO_STATE(RM2_RING_OP) ;
-                       break ;
-               }
-               /*RM54*/
-               else if (cmd == RM_RING_NON_OP) {
-                       smc->r.jm_flag = FALSE ;
-                       smc->r.bn_flag = FALSE ;
-                       GO_STATE(RM4_NON_OP_DUP) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM6_DIRECTED) :
-               start_rmt_timer0(smc,smc->s.rmt_t_direct,RM_TIMEOUT_T_DIRECT) ;
-               stop_rmt_timer1(smc) ;
-               start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL) ;
-               sm_ma_control(smc,MA_DIRECTED) ;
-               RS_SET(smc,RS_BEACON) ;
-               DB_RMTN(1,"RMT : RM6_DIRECTED\n",0,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM6_DIRECTED :
-               /*RM63*/
-               if (cmd == RM_TIMEOUT_POLL) {
-                       start_rmt_timer2(smc,smc->s.rmt_t_poll,RM_TIMEOUT_POLL);
-                       sm_mac_check_beacon_claim(smc) ;
-#ifndef SUPERNET_3
-                       /* Because of problems with the Supernet II chip set
-                        * sending of Directed Beacon will stop after 165ms
-                        * therefore restart_trt_for_dbcn(smc) will be called
-                        * to prevent this.
-                        */
-                       restart_trt_for_dbcn(smc) ;
-#endif /*SUPERNET_3*/
-                       break ;
-               }
-               if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
-                       !smc->r.da_flag) {
-                       smc->r.bn_flag = FALSE ;
-                       GO_STATE(RM3_DETECT) ;
-                       break ;
-               }
-               /*RM64*/
-               else if ((cmd == RM_MY_BEACON || cmd == RM_OTHER_BEACON) &&
-                       smc->r.da_flag) {
-                       smc->r.bn_flag = FALSE ;
-                       GO_STATE(RM4_NON_OP_DUP) ;
-                       break ;
-               }
-               /*RM67*/
-               else if (cmd == RM_TIMEOUT_T_DIRECT) {
-                       GO_STATE(RM7_TRACE) ;
-                       break ;
-               }
-               break ;
-       case ACTIONS(RM7_TRACE) :
-               stop_rmt_timer0(smc) ;
-               stop_rmt_timer1(smc) ;
-               stop_rmt_timer2(smc) ;
-               smc->e.trace_prop |= ENTITY_BIT(ENTITY_MAC) ;
-               queue_event(smc,EVENT_ECM,EC_TRACE_PROP) ;
-               DB_RMTN(1,"RMT : RM7_TRACE\n",0,0) ;
-               ACTIONS_DONE() ;
-               break ;
-       case RM7_TRACE :
-               break ;
-       default:
-               SMT_PANIC(smc,SMT_E0122, SMT_E0122_MSG) ;
-               break;
-       }
-}
-
-/*
- * (jd) RMT duplicate address actions
- * leave the ring or reinsert just as configured
- */
-static void rmt_dup_actions(struct s_smc *smc)
-{
-       if (smc->r.jm_flag) {
-       }
-       else {
-               if (smc->s.rmt_dup_mac_behavior) {
-                       SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
-                        rmt_reinsert_actions(smc) ;
-               }
-               else {
-                       SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
-                       rmt_leave_actions(smc) ;
-               }
-       }
-}
-
-/*
- * Reconnect to the Ring
- */
-static void rmt_reinsert_actions(struct s_smc *smc)
-{
-       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
-       queue_event(smc,EVENT_ECM,EC_CONNECT) ;
-}
-
-/*
- * duplicate address detected
- */
-static void rmt_new_dup_actions(struct s_smc *smc)
-{
-       smc->r.da_flag = TRUE ;
-       smc->r.bn_flag = FALSE ;
-       smc->r.jm_flag = FALSE ;
-       /*
-        * we have three options : change address, jam or leave
-        * we leave the ring as default 
-        * Optionally it's possible to reinsert after leaving the Ring
-        * but this will not conform with SMT Spec.
-        */
-       if (smc->s.rmt_dup_mac_behavior) {
-               SMT_ERR_LOG(smc,SMT_E0138, SMT_E0138_MSG) ;
-               rmt_reinsert_actions(smc) ;
-       }
-       else {
-               SMT_ERR_LOG(smc,SMT_E0135, SMT_E0135_MSG) ;
-               rmt_leave_actions(smc) ;
-       }
-}
-
-
-/*
- * leave the ring
- */
-static void rmt_leave_actions(struct s_smc *smc)
-{
-       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
-       /*
-        * Note: Do NOT try again later. (with please reconnect)
-        * The station must be left from the ring!
-        */
-}
-
-/*
- * SMT timer interface
- *     start RMT timer 0
- */
-static void start_rmt_timer0(struct s_smc *smc, u_long value, int event)
-{
-       smc->r.timer0_exp = FALSE ;             /* clear timer event flag */
-       smt_timer_start(smc,&smc->r.rmt_timer0,value,EV_TOKEN(EVENT_RMT,event));
-}
-
-/*
- * SMT timer interface
- *     start RMT timer 1
- */
-static void start_rmt_timer1(struct s_smc *smc, u_long value, int event)
-{
-       smc->r.timer1_exp = FALSE ;     /* clear timer event flag */
-       smt_timer_start(smc,&smc->r.rmt_timer1,value,EV_TOKEN(EVENT_RMT,event));
-}
-
-/*
- * SMT timer interface
- *     start RMT timer 2
- */
-static void start_rmt_timer2(struct s_smc *smc, u_long value, int event)
-{
-       smc->r.timer2_exp = FALSE ;             /* clear timer event flag */
-       smt_timer_start(smc,&smc->r.rmt_timer2,value,EV_TOKEN(EVENT_RMT,event));
-}
-
-/*
- * SMT timer interface
- *     stop RMT timer 0
- */
-static void stop_rmt_timer0(struct s_smc *smc)
-{
-       if (smc->r.rmt_timer0.tm_active)
-               smt_timer_stop(smc,&smc->r.rmt_timer0) ;
-}
-
-/*
- * SMT timer interface
- *     stop RMT timer 1
- */
-static void stop_rmt_timer1(struct s_smc *smc)
-{
-       if (smc->r.rmt_timer1.tm_active)
-               smt_timer_stop(smc,&smc->r.rmt_timer1) ;
-}
-
-/*
- * SMT timer interface
- *     stop RMT timer 2
- */
-static void stop_rmt_timer2(struct s_smc *smc)
-{
-       if (smc->r.rmt_timer2.tm_active)
-               smt_timer_stop(smc,&smc->r.rmt_timer2) ;
-}
-
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
deleted file mode 100644 (file)
index 3d9a459..0000000
+++ /dev/null
@@ -1,2260 +0,0 @@
-/*
- * File Name:
- *   skfddi.c
- *
- * Copyright Information:
- *   Copyright SysKonnect 1998,1999.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- * Abstract:
- *   A Linux device driver supporting the SysKonnect FDDI PCI controller
- *   familie.
- *
- * Maintainers:
- *   CG    Christoph Goos (cgoos@syskonnect.de)
- *
- * Contributors:
- *   DM    David S. Miller
- *
- * Address all question to:
- *   linux@syskonnect.de
- *
- * The technical manual for the adapters is available from SysKonnect's
- * web pages: www.syskonnect.com
- * Goto "Support" and search Knowledge Base for "manual".
- *
- * Driver Architecture:
- *   The driver architecture is based on the DEC FDDI driver by
- *   Lawrence V. Stefani and several ethernet drivers.
- *   I also used an existing Windows NT miniport driver.
- *   All hardware dependent functions are handled by the SysKonnect
- *   Hardware Module.
- *   The only headerfiles that are directly related to this source
- *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h.
- *   The others belong to the SysKonnect FDDI Hardware Module and
- *   should better not be changed.
- *
- * Modification History:
- *              Date            Name    Description
- *              02-Mar-98       CG     Created.
- *
- *             10-Mar-99       CG      Support for 2.2.x added.
- *             25-Mar-99       CG      Corrected IRQ routing for SMP (APIC)
- *             26-Oct-99       CG      Fixed compilation error on 2.2.13
- *             12-Nov-99       CG      Source code release
- *             22-Nov-99       CG      Included in kernel source.
- *             07-May-00       DM      64 bit fixes, new dma interface
- *             31-Jul-03       DB      Audit copy_*_user in skfp_ioctl
- *                                       Daniele Bellucci <bellucda@tiscali.it>
- *             03-Dec-03       SH      Convert to PCI device model
- *
- * Compilation options (-Dxxx):
- *              DRIVERDEBUG     print lots of messages to log file
- *              DUMPPACKETS     print received/transmitted packets to logfile
- * 
- * Tested cpu architectures:
- *     - i386
- *     - sparc64
- */
-
-/* Version information string - should be updated prior to */
-/* each new release!!! */
-#define VERSION                "2.07"
-
-static const char * const boot_msg = 
-       "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
-       "  SK-55xx/SK-58xx adapters (SK-NET FDDI-FP/UP/LP)";
-
-/* Include files */
-
-#include <linux/capability.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/fddidevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/gfp.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include       "h/types.h"
-#undef ADDR                    // undo Linux definition
-#include       "h/skfbi.h"
-#include       "h/fddi.h"
-#include       "h/smc.h"
-#include       "h/smtstate.h"
-
-
-// Define module-wide (static) routines
-static int skfp_driver_init(struct net_device *dev);
-static int skfp_open(struct net_device *dev);
-static int skfp_close(struct net_device *dev);
-static irqreturn_t skfp_interrupt(int irq, void *dev_id);
-static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev);
-static void skfp_ctl_set_multicast_list(struct net_device *dev);
-static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev);
-static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr);
-static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
-                                      struct net_device *dev);
-static void send_queued_packets(struct s_smc *smc);
-static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr);
-static void ResetAdapter(struct s_smc *smc);
-
-
-// Functions needed by the hardware module
-void *mac_drv_get_space(struct s_smc *smc, u_int size);
-void *mac_drv_get_desc_mem(struct s_smc *smc, u_int size);
-unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt);
-unsigned long dma_master(struct s_smc *smc, void *virt, int len, int flag);
-void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr,
-                 int flag);
-void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd);
-void llc_restart_tx(struct s_smc *smc);
-void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
-                        int frag_count, int len);
-void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
-                        int frag_count);
-void mac_drv_fill_rxd(struct s_smc *smc);
-void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
-                      int frag_count);
-int mac_drv_rx_init(struct s_smc *smc, int len, int fc, char *look_ahead,
-                   int la_len);
-void dump_data(unsigned char *Data, int length);
-
-// External functions from the hardware module
-extern u_int mac_drv_check_space(void);
-extern int mac_drv_init(struct s_smc *smc);
-extern void hwm_tx_frag(struct s_smc *smc, char far * virt, u_long phys,
-                       int len, int frame_status);
-extern int hwm_tx_init(struct s_smc *smc, u_char fc, int frag_count,
-                      int frame_len, int frame_status);
-extern void fddi_isr(struct s_smc *smc);
-extern void hwm_rx_frag(struct s_smc *smc, char far * virt, u_long phys,
-                       int len, int frame_status);
-extern void mac_drv_rx_mode(struct s_smc *smc, int mode);
-extern void mac_drv_clear_rx_queue(struct s_smc *smc);
-extern void enable_tx_irq(struct s_smc *smc, u_short queue);
-
-static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = {
-       { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, },
-       { }                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, skfddi_pci_tbl);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
-
-// Define module-wide (static) variables
-
-static int num_boards; /* total number of adapters configured */
-
-static const struct net_device_ops skfp_netdev_ops = {
-       .ndo_open               = skfp_open,
-       .ndo_stop               = skfp_close,
-       .ndo_start_xmit         = skfp_send_pkt,
-       .ndo_get_stats          = skfp_ctl_get_stats,
-       .ndo_change_mtu         = fddi_change_mtu,
-       .ndo_set_rx_mode        = skfp_ctl_set_multicast_list,
-       .ndo_set_mac_address    = skfp_ctl_set_mac_address,
-       .ndo_do_ioctl           = skfp_ioctl,
-};
-
-/*
- * =================
- * = skfp_init_one =
- * =================
- *   
- * Overview:
- *   Probes for supported FDDI PCI controllers
- *  
- * Returns:
- *   Condition code
- *       
- * Arguments:
- *   pdev - pointer to PCI device information
- *
- * Functional Description:
- *   This is now called by PCI driver registration process
- *   for each board found.
- *   
- * Return Codes:
- *   0           - This device (fddi0, fddi1, etc) configured successfully
- *   -ENODEV - No devices present, or no SysKonnect FDDI PCI device
- *                         present for this device name
- *
- *
- * Side Effects:
- *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
- *   initialized and the board resources are read and stored in
- *   the device structure.
- */
-static int skfp_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
-{
-       struct net_device *dev;
-       struct s_smc *smc;      /* board pointer */
-       void __iomem *mem;
-       int err;
-
-       pr_debug("entering skfp_init_one\n");
-
-       if (num_boards == 0) 
-               printk("%s\n", boot_msg);
-
-       err = pci_enable_device(pdev);
-       if (err)
-               return err;
-
-       err = pci_request_regions(pdev, "skfddi");
-       if (err)
-               goto err_out1;
-
-       pci_set_master(pdev);
-
-#ifdef MEM_MAPPED_IO
-       if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-               printk(KERN_ERR "skfp: region is not an MMIO resource\n");
-               err = -EIO;
-               goto err_out2;
-       }
-
-       mem = ioremap(pci_resource_start(pdev, 0), 0x4000);
-#else
-       if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) {
-               printk(KERN_ERR "skfp: region is not PIO resource\n");
-               err = -EIO;
-               goto err_out2;
-       }
-
-       mem = ioport_map(pci_resource_start(pdev, 1), FP_IO_LEN);
-#endif
-       if (!mem) {
-               printk(KERN_ERR "skfp:  Unable to map register, "
-                               "FDDI adapter will be disabled.\n");
-               err = -EIO;
-               goto err_out2;
-       }
-
-       dev = alloc_fddidev(sizeof(struct s_smc));
-       if (!dev) {
-               printk(KERN_ERR "skfp: Unable to allocate fddi device, "
-                               "FDDI adapter will be disabled.\n");
-               err = -ENOMEM;
-               goto err_out3;
-       }
-
-       dev->irq = pdev->irq;
-       dev->netdev_ops = &skfp_netdev_ops;
-
-       SET_NETDEV_DEV(dev, &pdev->dev);
-
-       /* Initialize board structure with bus-specific info */
-       smc = netdev_priv(dev);
-       smc->os.dev = dev;
-       smc->os.bus_type = SK_BUS_TYPE_PCI;
-       smc->os.pdev = *pdev;
-       smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
-       smc->os.MaxFrameSize = MAX_FRAME_SIZE;
-       smc->os.dev = dev;
-       smc->hw.slot = -1;
-       smc->hw.iop = mem;
-       smc->os.ResetRequested = FALSE;
-       skb_queue_head_init(&smc->os.SendSkbQueue);
-
-       dev->base_addr = (unsigned long)mem;
-
-       err = skfp_driver_init(dev);
-       if (err)
-               goto err_out4;
-
-       err = register_netdev(dev);
-       if (err)
-               goto err_out5;
-
-       ++num_boards;
-       pci_set_drvdata(pdev, dev);
-
-       if ((pdev->subsystem_device & 0xff00) == 0x5500 ||
-           (pdev->subsystem_device & 0xff00) == 0x5800) 
-               printk("%s: SysKonnect FDDI PCI adapter"
-                      " found (SK-%04X)\n", dev->name, 
-                      pdev->subsystem_device);
-       else
-               printk("%s: FDDI PCI adapter found\n", dev->name);
-
-       return 0;
-err_out5:
-       if (smc->os.SharedMemAddr) 
-               pci_free_consistent(pdev, smc->os.SharedMemSize,
-                                   smc->os.SharedMemAddr, 
-                                   smc->os.SharedMemDMA);
-       pci_free_consistent(pdev, MAX_FRAME_SIZE,
-                           smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
-err_out4:
-       free_netdev(dev);
-err_out3:
-#ifdef MEM_MAPPED_IO
-       iounmap(mem);
-#else
-       ioport_unmap(mem);
-#endif
-err_out2:
-       pci_release_regions(pdev);
-err_out1:
-       pci_disable_device(pdev);
-       return err;
-}
-
-/*
- * Called for each adapter board from pci_unregister_driver
- */
-static void __devexit skfp_remove_one(struct pci_dev *pdev)
-{
-       struct net_device *p = pci_get_drvdata(pdev);
-       struct s_smc *lp = netdev_priv(p);
-
-       unregister_netdev(p);
-
-       if (lp->os.SharedMemAddr) {
-               pci_free_consistent(&lp->os.pdev,
-                                   lp->os.SharedMemSize,
-                                   lp->os.SharedMemAddr,
-                                   lp->os.SharedMemDMA);
-               lp->os.SharedMemAddr = NULL;
-       }
-       if (lp->os.LocalRxBuffer) {
-               pci_free_consistent(&lp->os.pdev,
-                                   MAX_FRAME_SIZE,
-                                   lp->os.LocalRxBuffer,
-                                   lp->os.LocalRxBufferDMA);
-               lp->os.LocalRxBuffer = NULL;
-       }
-#ifdef MEM_MAPPED_IO
-       iounmap(lp->hw.iop);
-#else
-       ioport_unmap(lp->hw.iop);
-#endif
-       pci_release_regions(pdev);
-       free_netdev(p);
-
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
-}
-
-/*
- * ====================
- * = skfp_driver_init =
- * ====================
- *   
- * Overview:
- *   Initializes remaining adapter board structure information
- *   and makes sure adapter is in a safe state prior to skfp_open().
- *  
- * Returns:
- *   Condition code
- *       
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This function allocates additional resources such as the host memory
- *   blocks needed by the adapter.
- *   The adapter is also reset. The OS must call skfp_open() to open 
- *   the adapter and bring it on-line.
- *
- * Return Codes:
- *    0 - initialization succeeded
- *   -1 - initialization failed
- */
-static  int skfp_driver_init(struct net_device *dev)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       skfddi_priv *bp = &smc->os;
-       int err = -EIO;
-
-       pr_debug("entering skfp_driver_init\n");
-
-       // set the io address in private structures
-       bp->base_addr = dev->base_addr;
-
-       // Get the interrupt level from the PCI Configuration Table
-       smc->hw.irq = dev->irq;
-
-       spin_lock_init(&bp->DriverLock);
-       
-       // Allocate invalid frame
-       bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA);
-       if (!bp->LocalRxBuffer) {
-               printk("could not allocate mem for ");
-               printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE);
-               goto fail;
-       }
-
-       // Determine the required size of the 'shared' memory area.
-       bp->SharedMemSize = mac_drv_check_space();
-       pr_debug("Memory for HWM: %ld\n", bp->SharedMemSize);
-       if (bp->SharedMemSize > 0) {
-               bp->SharedMemSize += 16;        // for descriptor alignment
-
-               bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
-                                                        bp->SharedMemSize,
-                                                        &bp->SharedMemDMA);
-               if (!bp->SharedMemAddr) {
-                       printk("could not allocate mem for ");
-                       printk("hardware module: %ld byte\n",
-                              bp->SharedMemSize);
-                       goto fail;
-               }
-               bp->SharedMemHeap = 0;  // Nothing used yet.
-
-       } else {
-               bp->SharedMemAddr = NULL;
-               bp->SharedMemHeap = 0;
-       }                       // SharedMemSize > 0
-
-       memset(bp->SharedMemAddr, 0, bp->SharedMemSize);
-
-       card_stop(smc);         // Reset adapter.
-
-       pr_debug("mac_drv_init()..\n");
-       if (mac_drv_init(smc) != 0) {
-               pr_debug("mac_drv_init() failed\n");
-               goto fail;
-       }
-       read_address(smc, NULL);
-       pr_debug("HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a);
-       memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
-
-       smt_reset_defaults(smc, 0);
-
-       return 0;
-
-fail:
-       if (bp->SharedMemAddr) {
-               pci_free_consistent(&bp->pdev,
-                                   bp->SharedMemSize,
-                                   bp->SharedMemAddr,
-                                   bp->SharedMemDMA);
-               bp->SharedMemAddr = NULL;
-       }
-       if (bp->LocalRxBuffer) {
-               pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE,
-                                   bp->LocalRxBuffer, bp->LocalRxBufferDMA);
-               bp->LocalRxBuffer = NULL;
-       }
-       return err;
-}                              // skfp_driver_init
-
-
-/*
- * =============
- * = skfp_open =
- * =============
- *   
- * Overview:
- *   Opens the adapter
- *  
- * Returns:
- *   Condition code
- *       
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This function brings the adapter to an operational state.
- *
- * Return Codes:
- *   0           - Adapter was successfully opened
- *   -EAGAIN - Could not register IRQ
- */
-static int skfp_open(struct net_device *dev)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       int err;
-
-       pr_debug("entering skfp_open\n");
-       /* Register IRQ - support shared interrupts by passing device ptr */
-       err = request_irq(dev->irq, skfp_interrupt, IRQF_SHARED,
-                         dev->name, dev);
-       if (err)
-               return err;
-
-       /*
-        * Set current address to factory MAC address
-        *
-        * Note: We've already done this step in skfp_driver_init.
-        *       However, it's possible that a user has set a node
-        *               address override, then closed and reopened the
-        *               adapter.  Unless we reset the device address field
-        *               now, we'll continue to use the existing modified
-        *               address.
-        */
-       read_address(smc, NULL);
-       memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6);
-
-       init_smt(smc, NULL);
-       smt_online(smc, 1);
-       STI_FBI();
-
-       /* Clear local multicast address tables */
-       mac_clear_multicast(smc);
-
-       /* Disable promiscuous filter settings */
-       mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
-
-       netif_start_queue(dev);
-       return 0;
-}                              // skfp_open
-
-
-/*
- * ==============
- * = skfp_close =
- * ==============
- *   
- * Overview:
- *   Closes the device/module.
- *  
- * Returns:
- *   Condition code
- *       
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This routine closes the adapter and brings it to a safe state.
- *   The interrupt service routine is deregistered with the OS.
- *   The adapter can be opened again with another call to skfp_open().
- *
- * Return Codes:
- *   Always return 0.
- *
- * Assumptions:
- *   No further requests for this adapter are made after this routine is
- *   called.  skfp_open() can be called to reset and reinitialize the
- *   adapter.
- */
-static int skfp_close(struct net_device *dev)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       skfddi_priv *bp = &smc->os;
-
-       CLI_FBI();
-       smt_reset_defaults(smc, 1);
-       card_stop(smc);
-       mac_drv_clear_tx_queue(smc);
-       mac_drv_clear_rx_queue(smc);
-
-       netif_stop_queue(dev);
-       /* Deregister (free) IRQ */
-       free_irq(dev->irq, dev);
-
-       skb_queue_purge(&bp->SendSkbQueue);
-       bp->QueueSkb = MAX_TX_QUEUE_LEN;
-
-       return 0;
-}                              // skfp_close
-
-
-/*
- * ==================
- * = skfp_interrupt =
- * ==================
- *   
- * Overview:
- *   Interrupt processing routine
- *  
- * Returns:
- *   None
- *       
- * Arguments:
- *   irq        - interrupt vector
- *   dev_id     - pointer to device information
- *
- * Functional Description:
- *   This routine calls the interrupt processing routine for this adapter.  It
- *   disables and reenables adapter interrupts, as appropriate.  We can support
- *   shared interrupts since the incoming dev_id pointer provides our device
- *   structure context. All the real work is done in the hardware module.
- *
- * Return Codes:
- *   None
- *
- * Assumptions:
- *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
- *   on Intel-based systems) is done by the operating system outside this
- *   routine.
- *
- *       System interrupts are enabled through this call.
- *
- * Side Effects:
- *   Interrupts are disabled, then reenabled at the adapter.
- */
-
-static irqreturn_t skfp_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       struct s_smc *smc;      /* private board structure pointer */
-       skfddi_priv *bp;
-
-       smc = netdev_priv(dev);
-       bp = &smc->os;
-
-       // IRQs enabled or disabled ?
-       if (inpd(ADDR(B0_IMSK)) == 0) {
-               // IRQs are disabled: must be shared interrupt
-               return IRQ_NONE;
-       }
-       // Note: At this point, IRQs are enabled.
-       if ((inpd(ISR_A) & smc->hw.is_imask) == 0) {    // IRQ?
-               // Adapter did not issue an IRQ: must be shared interrupt
-               return IRQ_NONE;
-       }
-       CLI_FBI();              // Disable IRQs from our adapter.
-       spin_lock(&bp->DriverLock);
-
-       // Call interrupt handler in hardware module (HWM).
-       fddi_isr(smc);
-
-       if (smc->os.ResetRequested) {
-               ResetAdapter(smc);
-               smc->os.ResetRequested = FALSE;
-       }
-       spin_unlock(&bp->DriverLock);
-       STI_FBI();              // Enable IRQs from our adapter.
-
-       return IRQ_HANDLED;
-}                              // skfp_interrupt
-
-
-/*
- * ======================
- * = skfp_ctl_get_stats =
- * ======================
- *   
- * Overview:
- *   Get statistics for FDDI adapter
- *  
- * Returns:
- *   Pointer to FDDI statistics structure
- *       
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Gets current MIB objects from adapter, then
- *   returns FDDI statistics structure as defined
- *   in if_fddi.h.
- *
- *   Note: Since the FDDI statistics structure is
- *   still new and the device structure doesn't
- *   have an FDDI-specific get statistics handler,
- *   we'll return the FDDI statistics structure as
- *   a pointer to an Ethernet statistics structure.
- *   That way, at least the first part of the statistics
- *   structure can be decoded properly.
- *   We'll have to pay attention to this routine as the
- *   device structure becomes more mature and LAN media
- *   independent.
- *
- */
-static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev)
-{
-       struct s_smc *bp = netdev_priv(dev);
-
-       /* Fill the bp->stats structure with driver-maintained counters */
-
-       bp->os.MacStat.port_bs_flag[0] = 0x1234;
-       bp->os.MacStat.port_bs_flag[1] = 0x5678;
-// goos: need to fill out fddi statistic
-#if 0
-       /* Get FDDI SMT MIB objects */
-
-/* Fill the bp->stats structure with the SMT MIB object values */
-
-       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));
-       bp->stats.smt_op_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
-       bp->stats.smt_hi_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
-       bp->stats.smt_lo_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
-       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));
-       bp->stats.smt_mib_version_id = bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
-       bp->stats.smt_mac_cts = bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
-       bp->stats.smt_non_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
-       bp->stats.smt_master_cts = bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
-       bp->stats.smt_available_paths = bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
-       bp->stats.smt_config_capabilities = bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
-       bp->stats.smt_config_policy = bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
-       bp->stats.smt_connection_policy = bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
-       bp->stats.smt_t_notify = bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
-       bp->stats.smt_stat_rpt_policy = bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
-       bp->stats.smt_trace_max_expiration = bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
-       bp->stats.smt_bypass_present = bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
-       bp->stats.smt_ecm_state = bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
-       bp->stats.smt_cf_state = bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
-       bp->stats.smt_remote_disconnect_flag = bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
-       bp->stats.smt_station_status = bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
-       bp->stats.smt_peer_wrap_flag = bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
-       bp->stats.smt_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
-       bp->stats.smt_transition_time_stamp = bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
-       bp->stats.mac_frame_status_functions = bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
-       bp->stats.mac_t_max_capability = bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
-       bp->stats.mac_tvx_capability = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
-       bp->stats.mac_available_paths = bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
-       bp->stats.mac_current_path = bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
-       memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
-       memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
-       memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
-       memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
-       bp->stats.mac_dup_address_test = bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
-       bp->stats.mac_requested_paths = bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
-       bp->stats.mac_downstream_port_type = bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
-       memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
-       bp->stats.mac_t_req = bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
-       bp->stats.mac_t_neg = bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
-       bp->stats.mac_t_max = bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
-       bp->stats.mac_tvx_value = bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
-       bp->stats.mac_frame_error_threshold = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
-       bp->stats.mac_frame_error_ratio = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
-       bp->stats.mac_rmt_state = bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
-       bp->stats.mac_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
-       bp->stats.mac_una_da_flag = bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
-       bp->stats.mac_frame_error_flag = bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
-       bp->stats.mac_ma_unitdata_available = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
-       bp->stats.mac_hardware_present = bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
-       bp->stats.mac_ma_unitdata_enable = bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
-       bp->stats.path_tvx_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
-       bp->stats.path_t_max_lower_bound = bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
-       bp->stats.path_max_t_req = bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
-       memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
-       bp->stats.port_my_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
-       bp->stats.port_my_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
-       bp->stats.port_neighbor_type[0] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
-       bp->stats.port_neighbor_type[1] = bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
-       bp->stats.port_connection_policies[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
-       bp->stats.port_connection_policies[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
-       bp->stats.port_mac_indicated[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
-       bp->stats.port_mac_indicated[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
-       bp->stats.port_current_path[0] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
-       bp->stats.port_current_path[1] = bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
-       memcpy(&bp->stats.port_requested_paths[0 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
-       memcpy(&bp->stats.port_requested_paths[1 * 3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
-       bp->stats.port_mac_placement[0] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
-       bp->stats.port_mac_placement[1] = bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
-       bp->stats.port_available_paths[0] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
-       bp->stats.port_available_paths[1] = bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
-       bp->stats.port_pmd_class[0] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
-       bp->stats.port_pmd_class[1] = bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
-       bp->stats.port_connection_capabilities[0] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
-       bp->stats.port_connection_capabilities[1] = bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
-       bp->stats.port_bs_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
-       bp->stats.port_bs_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
-       bp->stats.port_ler_estimate[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
-       bp->stats.port_ler_estimate[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
-       bp->stats.port_ler_cutoff[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
-       bp->stats.port_ler_cutoff[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
-       bp->stats.port_ler_alarm[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
-       bp->stats.port_ler_alarm[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
-       bp->stats.port_connect_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
-       bp->stats.port_connect_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
-       bp->stats.port_pcm_state[0] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
-       bp->stats.port_pcm_state[1] = bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
-       bp->stats.port_pc_withhold[0] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
-       bp->stats.port_pc_withhold[1] = bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
-       bp->stats.port_ler_flag[0] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
-       bp->stats.port_ler_flag[1] = bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
-       bp->stats.port_hardware_present[0] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
-       bp->stats.port_hardware_present[1] = bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
-
-
-       /* Fill the bp->stats structure with the FDDI counter values */
-
-       bp->stats.mac_frame_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
-       bp->stats.mac_copied_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
-       bp->stats.mac_transmit_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
-       bp->stats.mac_error_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
-       bp->stats.mac_lost_cts = bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
-       bp->stats.port_lct_fail_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
-       bp->stats.port_lct_fail_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
-       bp->stats.port_lem_reject_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
-       bp->stats.port_lem_reject_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
-       bp->stats.port_lem_cts[0] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
-       bp->stats.port_lem_cts[1] = bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
-
-#endif
-       return (struct net_device_stats *)&bp->os.MacStat;
-}                              // ctl_get_stat
-
-
-/*
- * ==============================
- * = skfp_ctl_set_multicast_list =
- * ==============================
- *   
- * Overview:
- *   Enable/Disable LLC frame promiscuous mode reception
- *   on the adapter and/or update multicast address table.
- *  
- * Returns:
- *   None
- *       
- * Arguments:
- *   dev - pointer to device information
- *
- * Functional Description:
- *   This function acquires the driver lock and only calls
- *   skfp_ctl_set_multicast_list_wo_lock then.
- *   This routine follows a fairly simple algorithm for setting the
- *   adapter filters and CAM:
- *
- *      if IFF_PROMISC flag is set
- *              enable promiscuous mode
- *      else
- *              disable promiscuous mode
- *              if number of multicast addresses <= max. multicast number
- *                      add mc addresses to adapter table
- *              else
- *                      enable promiscuous mode
- *              update adapter filters
- *
- * Assumptions:
- *   Multicast addresses are presented in canonical (LSB) format.
- *
- * Side Effects:
- *   On-board adapter filters are updated.
- */
-static void skfp_ctl_set_multicast_list(struct net_device *dev)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       skfddi_priv *bp = &smc->os;
-       unsigned long Flags;
-
-       spin_lock_irqsave(&bp->DriverLock, Flags);
-       skfp_ctl_set_multicast_list_wo_lock(dev);
-       spin_unlock_irqrestore(&bp->DriverLock, Flags);
-}                              // skfp_ctl_set_multicast_list
-
-
-
-static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       struct netdev_hw_addr *ha;
-
-       /* Enable promiscuous mode, if necessary */
-       if (dev->flags & IFF_PROMISC) {
-               mac_drv_rx_mode(smc, RX_ENABLE_PROMISC);
-               pr_debug("PROMISCUOUS MODE ENABLED\n");
-       }
-       /* Else, update multicast address table */
-       else {
-               mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
-               pr_debug("PROMISCUOUS MODE DISABLED\n");
-
-               // Reset all MC addresses
-               mac_clear_multicast(smc);
-               mac_drv_rx_mode(smc, RX_DISABLE_ALLMULTI);
-
-               if (dev->flags & IFF_ALLMULTI) {
-                       mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
-                       pr_debug("ENABLE ALL MC ADDRESSES\n");
-               } else if (!netdev_mc_empty(dev)) {
-                       if (netdev_mc_count(dev) <= FPMAX_MULTICAST) {
-                               /* use exact filtering */
-
-                               // point to first multicast addr
-                               netdev_for_each_mc_addr(ha, dev) {
-                                       mac_add_multicast(smc,
-                                               (struct fddi_addr *)ha->addr,
-                                               1);
-
-                                       pr_debug("ENABLE MC ADDRESS: %pMF\n",
-                                                ha->addr);
-                               }
-
-                       } else {        // more MC addresses than HW supports
-
-                               mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI);
-                               pr_debug("ENABLE ALL MC ADDRESSES\n");
-                       }
-               } else {        // no MC addresses
-
-                       pr_debug("DISABLE ALL MC ADDRESSES\n");
-               }
-
-               /* Update adapter filters */
-               mac_update_multicast(smc);
-       }
-}                              // skfp_ctl_set_multicast_list_wo_lock
-
-
-/*
- * ===========================
- * = skfp_ctl_set_mac_address =
- * ===========================
- *   
- * Overview:
- *   set new mac address on adapter and update dev_addr field in device table.
- *  
- * Returns:
- *   None
- *       
- * Arguments:
- *   dev  - pointer to device information
- *   addr - pointer to sockaddr structure containing unicast address to set
- *
- * Assumptions:
- *   The address pointed to by addr->sa_data is a valid unicast
- *   address and is presented in canonical (LSB) format.
- */
-static int skfp_ctl_set_mac_address(struct net_device *dev, void *addr)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       struct sockaddr *p_sockaddr = (struct sockaddr *) addr;
-       skfddi_priv *bp = &smc->os;
-       unsigned long Flags;
-
-
-       memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);
-       spin_lock_irqsave(&bp->DriverLock, Flags);
-       ResetAdapter(smc);
-       spin_unlock_irqrestore(&bp->DriverLock, Flags);
-
-       return 0;               /* always return zero */
-}                              // skfp_ctl_set_mac_address
-
-
-/*
- * ==============
- * = skfp_ioctl =
- * ==============
- *   
- * Overview:
- *
- * Perform IOCTL call functions here. Some are privileged operations and the
- * effective uid is checked in those cases.
- *  
- * Returns:
- *   status value
- *   0 - success
- *   other - failure
- *       
- * Arguments:
- *   dev  - pointer to device information
- *   rq - pointer to ioctl request structure
- *   cmd - ?
- *
- */
-
-
-static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       skfddi_priv *lp = &smc->os;
-       struct s_skfp_ioctl ioc;
-       int status = 0;
-
-       if (copy_from_user(&ioc, rq->ifr_data, sizeof(struct s_skfp_ioctl)))
-               return -EFAULT;
-
-       switch (ioc.cmd) {
-       case SKFP_GET_STATS:    /* Get the driver statistics */
-               ioc.len = sizeof(lp->MacStat);
-               status = copy_to_user(ioc.data, skfp_ctl_get_stats(dev), ioc.len)
-                               ? -EFAULT : 0;
-               break;
-       case SKFP_CLR_STATS:    /* Zero out the driver statistics */
-               if (!capable(CAP_NET_ADMIN)) {
-                       status = -EPERM;
-               } else {
-                       memset(&lp->MacStat, 0, sizeof(lp->MacStat));
-               }
-               break;
-       default:
-               printk("ioctl for %s: unknown cmd: %04x\n", dev->name, ioc.cmd);
-               status = -EOPNOTSUPP;
-
-       }                       // switch
-
-       return status;
-}                              // skfp_ioctl
-
-
-/*
- * =====================
- * = skfp_send_pkt     =
- * =====================
- *   
- * Overview:
- *   Queues a packet for transmission and try to transmit it.
- *  
- * Returns:
- *   Condition code
- *       
- * Arguments:
- *   skb - pointer to sk_buff to queue for transmission
- *   dev - pointer to device information
- *
- * Functional Description:
- *   Here we assume that an incoming skb transmit request
- *   is contained in a single physically contiguous buffer
- *   in which the virtual address of the start of packet
- *   (skb->data) can be converted to a physical address
- *   by using pci_map_single().
- *
- *   We have an internal queue for packets we can not send 
- *   immediately. Packets in this queue can be given to the 
- *   adapter if transmit buffers are freed.
- *
- *   We can't free the skb until after it's been DMA'd
- *   out by the adapter, so we'll keep it in the driver and
- *   return it in mac_drv_tx_complete.
- *
- * Return Codes:
- *   0 - driver has queued and/or sent packet
- *       1 - caller should requeue the sk_buff for later transmission
- *
- * Assumptions:
- *   The entire packet is stored in one physically
- *   contiguous buffer which is not cached and whose
- *   32-bit physical address can be determined.
- *
- *   It's vital that this routine is NOT reentered for the
- *   same board and that the OS is not in another section of
- *   code (eg. skfp_interrupt) for the same board on a
- *   different thread.
- *
- * Side Effects:
- *   None
- */
-static netdev_tx_t skfp_send_pkt(struct sk_buff *skb,
-                                      struct net_device *dev)
-{
-       struct s_smc *smc = netdev_priv(dev);
-       skfddi_priv *bp = &smc->os;
-
-       pr_debug("skfp_send_pkt\n");
-
-       /*
-        * Verify that incoming transmit request is OK
-        *
-        * Note: The packet size check is consistent with other
-        *               Linux device drivers, although the correct packet
-        *               size should be verified before calling the
-        *               transmit routine.
-        */
-
-       if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {
-               bp->MacStat.gen.tx_errors++;    /* bump error counter */
-               // dequeue packets from xmt queue and send them
-               netif_start_queue(dev);
-               dev_kfree_skb(skb);
-               return NETDEV_TX_OK;    /* return "success" */
-       }
-       if (bp->QueueSkb == 0) {        // return with tbusy set: queue full
-
-               netif_stop_queue(dev);
-               return NETDEV_TX_BUSY;
-       }
-       bp->QueueSkb--;
-       skb_queue_tail(&bp->SendSkbQueue, skb);
-       send_queued_packets(netdev_priv(dev));
-       if (bp->QueueSkb == 0) {
-               netif_stop_queue(dev);
-       }
-       return NETDEV_TX_OK;
-
-}                              // skfp_send_pkt
-
-
-/*
- * =======================
- * = send_queued_packets =
- * =======================
- *   
- * Overview:
- *   Send packets from the driver queue as long as there are some and
- *   transmit resources are available.
- *  
- * Returns:
- *   None
- *       
- * Arguments:
- *   smc - pointer to smc (adapter) structure
- *
- * Functional Description:
- *   Take a packet from queue if there is any. If not, then we are done.
- *   Check if there are resources to send the packet. If not, requeue it
- *   and exit. 
- *   Set packet descriptor flags and give packet to adapter.
- *   Check if any send resources can be freed (we do not use the
- *   transmit complete interrupt).
- */
-static void send_queued_packets(struct s_smc *smc)
-{
-       skfddi_priv *bp = &smc->os;
-       struct sk_buff *skb;
-       unsigned char fc;
-       int queue;
-       struct s_smt_fp_txd *txd;       // Current TxD.
-       dma_addr_t dma_address;
-       unsigned long Flags;
-
-       int frame_status;       // HWM tx frame status.
-
-       pr_debug("send queued packets\n");
-       for (;;) {
-               // send first buffer from queue
-               skb = skb_dequeue(&bp->SendSkbQueue);
-
-               if (!skb) {
-                       pr_debug("queue empty\n");
-                       return;
-               }               // queue empty !
-
-               spin_lock_irqsave(&bp->DriverLock, Flags);
-               fc = skb->data[0];
-               queue = (fc & FC_SYNC_BIT) ? QUEUE_S : QUEUE_A0;
-#ifdef ESS
-               // Check if the frame may/must be sent as a synchronous frame.
-
-               if ((fc & ~(FC_SYNC_BIT | FC_LLC_PRIOR)) == FC_ASYNC_LLC) {
-                       // It's an LLC frame.
-                       if (!smc->ess.sync_bw_available)
-                               fc &= ~FC_SYNC_BIT; // No bandwidth available.
-
-                       else {  // Bandwidth is available.
-
-                               if (smc->mib.fddiESSSynchTxMode) {
-                                       // Send as sync. frame.
-                                       fc |= FC_SYNC_BIT;
-                               }
-                       }
-               }
-#endif                         // ESS
-               frame_status = hwm_tx_init(smc, fc, 1, skb->len, queue);
-
-               if ((frame_status & (LOC_TX | LAN_TX)) == 0) {
-                       // Unable to send the frame.
-
-                       if ((frame_status & RING_DOWN) != 0) {
-                               // Ring is down.
-                               pr_debug("Tx attempt while ring down.\n");
-                       } else if ((frame_status & OUT_OF_TXD) != 0) {
-                               pr_debug("%s: out of TXDs.\n", bp->dev->name);
-                       } else {
-                               pr_debug("%s: out of transmit resources",
-                                       bp->dev->name);
-                       }
-
-                       // Note: We will retry the operation as soon as
-                       // transmit resources become available.
-                       skb_queue_head(&bp->SendSkbQueue, skb);
-                       spin_unlock_irqrestore(&bp->DriverLock, Flags);
-                       return; // Packet has been queued.
-
-               }               // if (unable to send frame)
-
-               bp->QueueSkb++; // one packet less in local queue
-
-               // source address in packet ?
-               CheckSourceAddress(skb->data, smc->hw.fddi_canon_addr.a);
-
-               txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue);
-
-               dma_address = pci_map_single(&bp->pdev, skb->data,
-                                            skb->len, PCI_DMA_TODEVICE);
-               if (frame_status & LAN_TX) {
-                       txd->txd_os.skb = skb;                  // save skb
-                       txd->txd_os.dma_addr = dma_address;     // save dma mapping
-               }
-               hwm_tx_frag(smc, skb->data, dma_address, skb->len,
-                      frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF);
-
-               if (!(frame_status & LAN_TX)) {         // local only frame
-                       pci_unmap_single(&bp->pdev, dma_address,
-                                        skb->len, PCI_DMA_TODEVICE);
-                       dev_kfree_skb_irq(skb);
-               }
-               spin_unlock_irqrestore(&bp->DriverLock, Flags);
-       }                       // for
-
-       return;                 // never reached
-
-}                              // send_queued_packets
-
-
-/************************
- * 
- * CheckSourceAddress
- *
- * Verify if the source address is set. Insert it if necessary.
- *
- ************************/
-static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
-{
-       unsigned char SRBit;
-
-       if ((((unsigned long) frame[1 + 6]) & ~0x01) != 0) // source routing bit
-
-               return;
-       if ((unsigned short) frame[1 + 10] != 0)
-               return;
-       SRBit = frame[1 + 6] & 0x01;
-       memcpy(&frame[1 + 6], hw_addr, 6);
-       frame[8] |= SRBit;
-}                              // CheckSourceAddress
-
-
-/************************
- *
- *     ResetAdapter
- *
- *     Reset the adapter and bring it back to operational mode.
- * Args
- *     smc - A pointer to the SMT context struct.
- * Out
- *     Nothing.
- *
- ************************/
-static void ResetAdapter(struct s_smc *smc)
-{
-
-       pr_debug("[fddi: ResetAdapter]\n");
-
-       // Stop the adapter.
-
-       card_stop(smc);         // Stop all activity.
-
-       // Clear the transmit and receive descriptor queues.
-       mac_drv_clear_tx_queue(smc);
-       mac_drv_clear_rx_queue(smc);
-
-       // Restart the adapter.
-
-       smt_reset_defaults(smc, 1);     // Initialize the SMT module.
-
-       init_smt(smc, (smc->os.dev)->dev_addr); // Initialize the hardware.
-
-       smt_online(smc, 1);     // Insert into the ring again.
-       STI_FBI();
-
-       // Restore original receive mode (multicasts, promiscuous, etc.).
-       skfp_ctl_set_multicast_list_wo_lock(smc->os.dev);
-}                              // ResetAdapter
-
-
-//--------------- functions called by hardware module ----------------
-
-/************************
- *
- *     llc_restart_tx
- *
- *     The hardware driver calls this routine when the transmit complete
- *     interrupt bits (end of frame) for the synchronous or asynchronous
- *     queue is set.
- *
- * NOTE The hardware driver calls this function also if no packets are queued.
- *     The routine must be able to handle this case.
- * Args
- *     smc - A pointer to the SMT context struct.
- * Out
- *     Nothing.
- *
- ************************/
-void llc_restart_tx(struct s_smc *smc)
-{
-       skfddi_priv *bp = &smc->os;
-
-       pr_debug("[llc_restart_tx]\n");
-
-       // Try to send queued packets
-       spin_unlock(&bp->DriverLock);
-       send_queued_packets(smc);
-       spin_lock(&bp->DriverLock);
-       netif_start_queue(bp->dev);// system may send again if it was blocked
-
-}                              // llc_restart_tx
-
-
-/************************
- *
- *     mac_drv_get_space
- *
- *     The hardware module calls this function to allocate the memory
- *     for the SMT MBufs if the define MB_OUTSIDE_SMC is specified.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     size - Size of memory in bytes to allocate.
- * Out
- *     != 0    A pointer to the virtual address of the allocated memory.
- *     == 0    Allocation error.
- *
- ************************/
-void *mac_drv_get_space(struct s_smc *smc, unsigned int size)
-{
-       void *virt;
-
-       pr_debug("mac_drv_get_space (%d bytes), ", size);
-       virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap);
-
-       if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) {
-               printk("Unexpected SMT memory size requested: %d\n", size);
-               return NULL;
-       }
-       smc->os.SharedMemHeap += size;  // Move heap pointer.
-
-       pr_debug("mac_drv_get_space end\n");
-       pr_debug("virt addr: %lx\n", (ulong) virt);
-       pr_debug("bus  addr: %lx\n", (ulong)
-              (smc->os.SharedMemDMA +
-               ((char *) virt - (char *)smc->os.SharedMemAddr)));
-       return virt;
-}                              // mac_drv_get_space
-
-
-/************************
- *
- *     mac_drv_get_desc_mem
- *
- *     This function is called by the hardware dependent module.
- *     It allocates the memory for the RxD and TxD descriptors.
- *
- *     This memory must be non-cached, non-movable and non-swappable.
- *     This memory should start at a physical page boundary.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     size - Size of memory in bytes to allocate.
- * Out
- *     != 0    A pointer to the virtual address of the allocated memory.
- *     == 0    Allocation error.
- *
- ************************/
-void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size)
-{
-
-       char *virt;
-
-       pr_debug("mac_drv_get_desc_mem\n");
-
-       // Descriptor memory must be aligned on 16-byte boundary.
-
-       virt = mac_drv_get_space(smc, size);
-
-       size = (u_int) (16 - (((unsigned long) virt) & 15UL));
-       size = size % 16;
-
-       pr_debug("Allocate %u bytes alignment gap ", size);
-       pr_debug("for descriptor memory.\n");
-
-       if (!mac_drv_get_space(smc, size)) {
-               printk("fddi: Unable to align descriptor memory.\n");
-               return NULL;
-       }
-       return virt + size;
-}                              // mac_drv_get_desc_mem
-
-
-/************************
- *
- *     mac_drv_virt2phys
- *
- *     Get the physical address of a given virtual address.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     virt - A (virtual) pointer into our 'shared' memory area.
- * Out
- *     Physical address of the given virtual address.
- *
- ************************/
-unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt)
-{
-       return smc->os.SharedMemDMA +
-               ((char *) virt - (char *)smc->os.SharedMemAddr);
-}                              // mac_drv_virt2phys
-
-
-/************************
- *
- *     dma_master
- *
- *     The HWM calls this function, when the driver leads through a DMA
- *     transfer. If the OS-specific module must prepare the system hardware
- *     for the DMA transfer, it should do it in this function.
- *
- *     The hardware module calls this dma_master if it wants to send an SMT
- *     frame.  This means that the virt address passed in here is part of
- *      the 'shared' memory area.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     virt - The virtual address of the data.
- *
- *     len - The length in bytes of the data.
- *
- *     flag - Indicates the transmit direction and the buffer type:
- *             DMA_RD  (0x01)  system RAM ==> adapter buffer memory
- *             DMA_WR  (0x02)  adapter buffer memory ==> system RAM
- *             SMT_BUF (0x80)  SMT buffer
- *
- *     >> NOTE: SMT_BUF and DMA_RD are always set for PCI. <<
- * Out
- *     Returns the pyhsical address for the DMA transfer.
- *
- ************************/
-u_long dma_master(struct s_smc * smc, void *virt, int len, int flag)
-{
-       return smc->os.SharedMemDMA +
-               ((char *) virt - (char *)smc->os.SharedMemAddr);
-}                              // dma_master
-
-
-/************************
- *
- *     dma_complete
- *
- *     The hardware module calls this routine when it has completed a DMA
- *     transfer. If the operating system dependent module has set up the DMA
- *     channel via dma_master() (e.g. Windows NT or AIX) it should clean up
- *     the DMA channel.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     descr - A pointer to a TxD or RxD, respectively.
- *
- *     flag - Indicates the DMA transfer direction / SMT buffer:
- *             DMA_RD  (0x01)  system RAM ==> adapter buffer memory
- *             DMA_WR  (0x02)  adapter buffer memory ==> system RAM
- *             SMT_BUF (0x80)  SMT buffer (managed by HWM)
- * Out
- *     Nothing.
- *
- ************************/
-void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag)
-{
-       /* For TX buffers, there are two cases.  If it is an SMT transmit
-        * buffer, there is nothing to do since we use consistent memory
-        * for the 'shared' memory area.  The other case is for normal
-        * transmit packets given to us by the networking stack, and in
-        * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete
-        * below.
-        *
-        * For RX buffers, we have to unmap dynamic PCI DMA mappings here
-        * because the hardware module is about to potentially look at
-        * the contents of the buffer.  If we did not call the PCI DMA
-        * unmap first, the hardware module could read inconsistent data.
-        */
-       if (flag & DMA_WR) {
-               skfddi_priv *bp = &smc->os;
-               volatile struct s_smt_fp_rxd *r = &descr->r;
-
-               /* If SKB is NULL, we used the local buffer. */
-               if (r->rxd_os.skb && r->rxd_os.dma_addr) {
-                       int MaxFrameSize = bp->MaxFrameSize;
-
-                       pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr,
-                                        MaxFrameSize, PCI_DMA_FROMDEVICE);
-                       r->rxd_os.dma_addr = 0;
-               }
-       }
-}                              // dma_complete
-
-
-/************************
- *
- *     mac_drv_tx_complete
- *
- *     Transmit of a packet is complete. Release the tx staging buffer.
- *
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     txd - A pointer to the last TxD which is used by the frame.
- * Out
- *     Returns nothing.
- *
- ************************/
-void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
-{
-       struct sk_buff *skb;
-
-       pr_debug("entering mac_drv_tx_complete\n");
-       // Check if this TxD points to a skb
-
-       if (!(skb = txd->txd_os.skb)) {
-               pr_debug("TXD with no skb assigned.\n");
-               return;
-       }
-       txd->txd_os.skb = NULL;
-
-       // release the DMA mapping
-       pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr,
-                        skb->len, PCI_DMA_TODEVICE);
-       txd->txd_os.dma_addr = 0;
-
-       smc->os.MacStat.gen.tx_packets++;       // Count transmitted packets.
-       smc->os.MacStat.gen.tx_bytes+=skb->len; // Count bytes
-
-       // free the skb
-       dev_kfree_skb_irq(skb);
-
-       pr_debug("leaving mac_drv_tx_complete\n");
-}                              // mac_drv_tx_complete
-
-
-/************************
- *
- * dump packets to logfile
- *
- ************************/
-#ifdef DUMPPACKETS
-void dump_data(unsigned char *Data, int length)
-{
-       int i, j;
-       unsigned char s[255], sh[10];
-       if (length > 64) {
-               length = 64;
-       }
-       printk(KERN_INFO "---Packet start---\n");
-       for (i = 0, j = 0; i < length / 8; i++, j += 8)
-               printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-                      Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3],
-                      Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]);
-       strcpy(s, "");
-       for (i = 0; i < length % 8; i++) {
-               sprintf(sh, "%02x ", Data[j + i]);
-               strcat(s, sh);
-       }
-       printk(KERN_INFO "%s\n", s);
-       printk(KERN_INFO "------------------\n");
-}                              // dump_data
-#else
-#define dump_data(data,len)
-#endif                         // DUMPPACKETS
-
-/************************
- *
- *     mac_drv_rx_complete
- *
- *     The hardware module calls this function if an LLC frame is received
- *     in a receive buffer. Also the SMT, NSA, and directed beacon frames
- *     from the network will be passed to the LLC layer by this function
- *     if passing is enabled.
- *
- *     mac_drv_rx_complete forwards the frame to the LLC layer if it should
- *     be received. It also fills the RxD ring with new receive buffers if
- *     some can be queued.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     rxd - A pointer to the first RxD which is used by the receive frame.
- *
- *     frag_count - Count of RxDs used by the received frame.
- *
- *     len - Frame length.
- * Out
- *     Nothing.
- *
- ************************/
-void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
-                        int frag_count, int len)
-{
-       skfddi_priv *bp = &smc->os;
-       struct sk_buff *skb;
-       unsigned char *virt, *cp;
-       unsigned short ri;
-       u_int RifLength;
-
-       pr_debug("entering mac_drv_rx_complete (len=%d)\n", len);
-       if (frag_count != 1) {  // This is not allowed to happen.
-
-               printk("fddi: Multi-fragment receive!\n");
-               goto RequeueRxd;        // Re-use the given RXD(s).
-
-       }
-       skb = rxd->rxd_os.skb;
-       if (!skb) {
-               pr_debug("No skb in rxd\n");
-               smc->os.MacStat.gen.rx_errors++;
-               goto RequeueRxd;
-       }
-       virt = skb->data;
-
-       // The DMA mapping was released in dma_complete above.
-
-       dump_data(skb->data, len);
-
-       /*
-        * FDDI Frame format:
-        * +-------+-------+-------+------------+--------+------------+
-        * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] |
-        * +-------+-------+-------+------------+--------+------------+
-        *
-        * FC = Frame Control
-        * DA = Destination Address
-        * SA = Source Address
-        * RIF = Routing Information Field
-        * LLC = Logical Link Control
-        */
-
-       // Remove Routing Information Field (RIF), if present.
-
-       if ((virt[1 + 6] & FDDI_RII) == 0)
-               RifLength = 0;
-       else {
-               int n;
-// goos: RIF removal has still to be tested
-               pr_debug("RIF found\n");
-               // Get RIF length from Routing Control (RC) field.
-               cp = virt + FDDI_MAC_HDR_LEN;   // Point behind MAC header.
-
-               ri = ntohs(*((__be16 *) cp));
-               RifLength = ri & FDDI_RCF_LEN_MASK;
-               if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {
-                       printk("fddi: Invalid RIF.\n");
-                       goto RequeueRxd;        // Discard the frame.
-
-               }
-               virt[1 + 6] &= ~FDDI_RII;       // Clear RII bit.
-               // regions overlap
-
-               virt = cp + RifLength;
-               for (n = FDDI_MAC_HDR_LEN; n; n--)
-                       *--virt = *--cp;
-               // adjust sbd->data pointer
-               skb_pull(skb, RifLength);
-               len -= RifLength;
-               RifLength = 0;
-       }
-
-       // Count statistics.
-       smc->os.MacStat.gen.rx_packets++;       // Count indicated receive
-                                               // packets.
-       smc->os.MacStat.gen.rx_bytes+=len;      // Count bytes.
-
-       // virt points to header again
-       if (virt[1] & 0x01) {   // Check group (multicast) bit.
-
-               smc->os.MacStat.gen.multicast++;
-       }
-
-       // deliver frame to system
-       rxd->rxd_os.skb = NULL;
-       skb_trim(skb, len);
-       skb->protocol = fddi_type_trans(skb, bp->dev);
-
-       netif_rx(skb);
-
-       HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
-       return;
-
-      RequeueRxd:
-       pr_debug("Rx: re-queue RXD.\n");
-       mac_drv_requeue_rxd(smc, rxd, frag_count);
-       smc->os.MacStat.gen.rx_errors++;        // Count receive packets
-                                               // not indicated.
-
-}                              // mac_drv_rx_complete
-
-
-/************************
- *
- *     mac_drv_requeue_rxd
- *
- *     The hardware module calls this function to request the OS-specific
- *     module to queue the receive buffer(s) represented by the pointer
- *     to the RxD and the frag_count into the receive queue again. This
- *     buffer was filled with an invalid frame or an SMT frame.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     rxd - A pointer to the first RxD which is used by the receive frame.
- *
- *     frag_count - Count of RxDs used by the received frame.
- * Out
- *     Nothing.
- *
- ************************/
-void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
-                        int frag_count)
-{
-       volatile struct s_smt_fp_rxd *next_rxd;
-       volatile struct s_smt_fp_rxd *src_rxd;
-       struct sk_buff *skb;
-       int MaxFrameSize;
-       unsigned char *v_addr;
-       dma_addr_t b_addr;
-
-       if (frag_count != 1)    // This is not allowed to happen.
-
-               printk("fddi: Multi-fragment requeue!\n");
-
-       MaxFrameSize = smc->os.MaxFrameSize;
-       src_rxd = rxd;
-       for (; frag_count > 0; frag_count--) {
-               next_rxd = src_rxd->rxd_next;
-               rxd = HWM_GET_CURR_RXD(smc);
-
-               skb = src_rxd->rxd_os.skb;
-               if (skb == NULL) {      // this should not happen
-
-                       pr_debug("Requeue with no skb in rxd!\n");
-                       skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
-                       if (skb) {
-                               // we got a skb
-                               rxd->rxd_os.skb = skb;
-                               skb_reserve(skb, 3);
-                               skb_put(skb, MaxFrameSize);
-                               v_addr = skb->data;
-                               b_addr = pci_map_single(&smc->os.pdev,
-                                                       v_addr,
-                                                       MaxFrameSize,
-                                                       PCI_DMA_FROMDEVICE);
-                               rxd->rxd_os.dma_addr = b_addr;
-                       } else {
-                               // no skb available, use local buffer
-                               pr_debug("Queueing invalid buffer!\n");
-                               rxd->rxd_os.skb = NULL;
-                               v_addr = smc->os.LocalRxBuffer;
-                               b_addr = smc->os.LocalRxBufferDMA;
-                       }
-               } else {
-                       // we use skb from old rxd
-                       rxd->rxd_os.skb = skb;
-                       v_addr = skb->data;
-                       b_addr = pci_map_single(&smc->os.pdev,
-                                               v_addr,
-                                               MaxFrameSize,
-                                               PCI_DMA_FROMDEVICE);
-                       rxd->rxd_os.dma_addr = b_addr;
-               }
-               hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
-                           FIRST_FRAG | LAST_FRAG);
-
-               src_rxd = next_rxd;
-       }
-}                              // mac_drv_requeue_rxd
-
-
-/************************
- *
- *     mac_drv_fill_rxd
- *
- *     The hardware module calls this function at initialization time
- *     to fill the RxD ring with receive buffers. It is also called by
- *     mac_drv_rx_complete if rx_free is large enough to queue some new
- *     receive buffers into the RxD ring. mac_drv_fill_rxd queues new
- *     receive buffers as long as enough RxDs and receive buffers are
- *     available.
- * Args
- *     smc - A pointer to the SMT context struct.
- * Out
- *     Nothing.
- *
- ************************/
-void mac_drv_fill_rxd(struct s_smc *smc)
-{
-       int MaxFrameSize;
-       unsigned char *v_addr;
-       unsigned long b_addr;
-       struct sk_buff *skb;
-       volatile struct s_smt_fp_rxd *rxd;
-
-       pr_debug("entering mac_drv_fill_rxd\n");
-
-       // Walk through the list of free receive buffers, passing receive
-       // buffers to the HWM as long as RXDs are available.
-
-       MaxFrameSize = smc->os.MaxFrameSize;
-       // Check if there is any RXD left.
-       while (HWM_GET_RX_FREE(smc) > 0) {
-               pr_debug(".\n");
-
-               rxd = HWM_GET_CURR_RXD(smc);
-               skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);
-               if (skb) {
-                       // we got a skb
-                       skb_reserve(skb, 3);
-                       skb_put(skb, MaxFrameSize);
-                       v_addr = skb->data;
-                       b_addr = pci_map_single(&smc->os.pdev,
-                                               v_addr,
-                                               MaxFrameSize,
-                                               PCI_DMA_FROMDEVICE);
-                       rxd->rxd_os.dma_addr = b_addr;
-               } else {
-                       // no skb available, use local buffer
-                       // System has run out of buffer memory, but we want to
-                       // keep the receiver running in hope of better times.
-                       // Multiple descriptors may point to this local buffer,
-                       // so data in it must be considered invalid.
-                       pr_debug("Queueing invalid buffer!\n");
-                       v_addr = smc->os.LocalRxBuffer;
-                       b_addr = smc->os.LocalRxBufferDMA;
-               }
-
-               rxd->rxd_os.skb = skb;
-
-               // Pass receive buffer to HWM.
-               hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,
-                           FIRST_FRAG | LAST_FRAG);
-       }
-       pr_debug("leaving mac_drv_fill_rxd\n");
-}                              // mac_drv_fill_rxd
-
-
-/************************
- *
- *     mac_drv_clear_rxd
- *
- *     The hardware module calls this function to release unused
- *     receive buffers.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     rxd - A pointer to the first RxD which is used by the receive buffer.
- *
- *     frag_count - Count of RxDs used by the receive buffer.
- * Out
- *     Nothing.
- *
- ************************/
-void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
-                      int frag_count)
-{
-
-       struct sk_buff *skb;
-
-       pr_debug("entering mac_drv_clear_rxd\n");
-
-       if (frag_count != 1)    // This is not allowed to happen.
-
-               printk("fddi: Multi-fragment clear!\n");
-
-       for (; frag_count > 0; frag_count--) {
-               skb = rxd->rxd_os.skb;
-               if (skb != NULL) {
-                       skfddi_priv *bp = &smc->os;
-                       int MaxFrameSize = bp->MaxFrameSize;
-
-                       pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr,
-                                        MaxFrameSize, PCI_DMA_FROMDEVICE);
-
-                       dev_kfree_skb(skb);
-                       rxd->rxd_os.skb = NULL;
-               }
-               rxd = rxd->rxd_next;    // Next RXD.
-
-       }
-}                              // mac_drv_clear_rxd
-
-
-/************************
- *
- *     mac_drv_rx_init
- *
- *     The hardware module calls this routine when an SMT or NSA frame of the
- *     local SMT should be delivered to the LLC layer.
- *
- *     It is necessary to have this function, because there is no other way to
- *     copy the contents of SMT MBufs into receive buffers.
- *
- *     mac_drv_rx_init allocates the required target memory for this frame,
- *     and receives the frame fragment by fragment by calling mac_drv_rx_frag.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     len - The length (in bytes) of the received frame (FC, DA, SA, Data).
- *
- *     fc - The Frame Control field of the received frame.
- *
- *     look_ahead - A pointer to the lookahead data buffer (may be NULL).
- *
- *     la_len - The length of the lookahead data stored in the lookahead
- *     buffer (may be zero).
- * Out
- *     Always returns zero (0).
- *
- ************************/
-int mac_drv_rx_init(struct s_smc *smc, int len, int fc,
-                   char *look_ahead, int la_len)
-{
-       struct sk_buff *skb;
-
-       pr_debug("entering mac_drv_rx_init(len=%d)\n", len);
-
-       // "Received" a SMT or NSA frame of the local SMT.
-
-       if (len != la_len || len < FDDI_MAC_HDR_LEN || !look_ahead) {
-               pr_debug("fddi: Discard invalid local SMT frame\n");
-               pr_debug("  len=%d, la_len=%d, (ULONG) look_ahead=%08lXh.\n",
-                      len, la_len, (unsigned long) look_ahead);
-               return 0;
-       }
-       skb = alloc_skb(len + 3, GFP_ATOMIC);
-       if (!skb) {
-               pr_debug("fddi: Local SMT: skb memory exhausted.\n");
-               return 0;
-       }
-       skb_reserve(skb, 3);
-       skb_put(skb, len);
-       skb_copy_to_linear_data(skb, look_ahead, len);
-
-       // deliver frame to system
-       skb->protocol = fddi_type_trans(skb, smc->os.dev);
-       netif_rx(skb);
-
-       return 0;
-}                              // mac_drv_rx_init
-
-
-/************************
- *
- *     smt_timer_poll
- *
- *     This routine is called periodically by the SMT module to clean up the
- *     driver.
- *
- *     Return any queued frames back to the upper protocol layers if the ring
- *     is down.
- * Args
- *     smc - A pointer to the SMT context struct.
- * Out
- *     Nothing.
- *
- ************************/
-void smt_timer_poll(struct s_smc *smc)
-{
-}                              // smt_timer_poll
-
-
-/************************
- *
- *     ring_status_indication
- *
- *     This function indicates a change of the ring state.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     status - The current ring status.
- * Out
- *     Nothing.
- *
- ************************/
-void ring_status_indication(struct s_smc *smc, u_long status)
-{
-       pr_debug("ring_status_indication( ");
-       if (status & RS_RES15)
-               pr_debug("RS_RES15 ");
-       if (status & RS_HARDERROR)
-               pr_debug("RS_HARDERROR ");
-       if (status & RS_SOFTERROR)
-               pr_debug("RS_SOFTERROR ");
-       if (status & RS_BEACON)
-               pr_debug("RS_BEACON ");
-       if (status & RS_PATHTEST)
-               pr_debug("RS_PATHTEST ");
-       if (status & RS_SELFTEST)
-               pr_debug("RS_SELFTEST ");
-       if (status & RS_RES9)
-               pr_debug("RS_RES9 ");
-       if (status & RS_DISCONNECT)
-               pr_debug("RS_DISCONNECT ");
-       if (status & RS_RES7)
-               pr_debug("RS_RES7 ");
-       if (status & RS_DUPADDR)
-               pr_debug("RS_DUPADDR ");
-       if (status & RS_NORINGOP)
-               pr_debug("RS_NORINGOP ");
-       if (status & RS_VERSION)
-               pr_debug("RS_VERSION ");
-       if (status & RS_STUCKBYPASSS)
-               pr_debug("RS_STUCKBYPASSS ");
-       if (status & RS_EVENT)
-               pr_debug("RS_EVENT ");
-       if (status & RS_RINGOPCHANGE)
-               pr_debug("RS_RINGOPCHANGE ");
-       if (status & RS_RES0)
-               pr_debug("RS_RES0 ");
-       pr_debug("]\n");
-}                              // ring_status_indication
-
-
-/************************
- *
- *     smt_get_time
- *
- *     Gets the current time from the system.
- * Args
- *     None.
- * Out
- *     The current time in TICKS_PER_SECOND.
- *
- *     TICKS_PER_SECOND has the unit 'count of timer ticks per second'. It is
- *     defined in "targetos.h". The definition of TICKS_PER_SECOND must comply
- *     to the time returned by smt_get_time().
- *
- ************************/
-unsigned long smt_get_time(void)
-{
-       return jiffies;
-}                              // smt_get_time
-
-
-/************************
- *
- *     smt_stat_counter
- *
- *     Status counter update (ring_op, fifo full).
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     stat -  = 0: A ring operational change occurred.
- *             = 1: The FORMAC FIFO buffer is full / FIFO overflow.
- * Out
- *     Nothing.
- *
- ************************/
-void smt_stat_counter(struct s_smc *smc, int stat)
-{
-//      BOOLEAN RingIsUp ;
-
-       pr_debug("smt_stat_counter\n");
-       switch (stat) {
-       case 0:
-               pr_debug("Ring operational change.\n");
-               break;
-       case 1:
-               pr_debug("Receive fifo overflow.\n");
-               smc->os.MacStat.gen.rx_errors++;
-               break;
-       default:
-               pr_debug("Unknown status (%d).\n", stat);
-               break;
-       }
-}                              // smt_stat_counter
-
-
-/************************
- *
- *     cfm_state_change
- *
- *     Sets CFM state in custom statistics.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     c_state - Possible values are:
- *
- *             EC0_OUT, EC1_IN, EC2_TRACE, EC3_LEAVE, EC4_PATH_TEST,
- *             EC5_INSERT, EC6_CHECK, EC7_DEINSERT
- * Out
- *     Nothing.
- *
- ************************/
-void cfm_state_change(struct s_smc *smc, int c_state)
-{
-#ifdef DRIVERDEBUG
-       char *s;
-
-       switch (c_state) {
-       case SC0_ISOLATED:
-               s = "SC0_ISOLATED";
-               break;
-       case SC1_WRAP_A:
-               s = "SC1_WRAP_A";
-               break;
-       case SC2_WRAP_B:
-               s = "SC2_WRAP_B";
-               break;
-       case SC4_THRU_A:
-               s = "SC4_THRU_A";
-               break;
-       case SC5_THRU_B:
-               s = "SC5_THRU_B";
-               break;
-       case SC7_WRAP_S:
-               s = "SC7_WRAP_S";
-               break;
-       case SC9_C_WRAP_A:
-               s = "SC9_C_WRAP_A";
-               break;
-       case SC10_C_WRAP_B:
-               s = "SC10_C_WRAP_B";
-               break;
-       case SC11_C_WRAP_S:
-               s = "SC11_C_WRAP_S";
-               break;
-       default:
-               pr_debug("cfm_state_change: unknown %d\n", c_state);
-               return;
-       }
-       pr_debug("cfm_state_change: %s\n", s);
-#endif                         // DRIVERDEBUG
-}                              // cfm_state_change
-
-
-/************************
- *
- *     ecm_state_change
- *
- *     Sets ECM state in custom statistics.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     e_state - Possible values are:
- *
- *             SC0_ISOLATED, SC1_WRAP_A (5), SC2_WRAP_B (6), SC4_THRU_A (12),
- *             SC5_THRU_B (7), SC7_WRAP_S (8)
- * Out
- *     Nothing.
- *
- ************************/
-void ecm_state_change(struct s_smc *smc, int e_state)
-{
-#ifdef DRIVERDEBUG
-       char *s;
-
-       switch (e_state) {
-       case EC0_OUT:
-               s = "EC0_OUT";
-               break;
-       case EC1_IN:
-               s = "EC1_IN";
-               break;
-       case EC2_TRACE:
-               s = "EC2_TRACE";
-               break;
-       case EC3_LEAVE:
-               s = "EC3_LEAVE";
-               break;
-       case EC4_PATH_TEST:
-               s = "EC4_PATH_TEST";
-               break;
-       case EC5_INSERT:
-               s = "EC5_INSERT";
-               break;
-       case EC6_CHECK:
-               s = "EC6_CHECK";
-               break;
-       case EC7_DEINSERT:
-               s = "EC7_DEINSERT";
-               break;
-       default:
-               s = "unknown";
-               break;
-       }
-       pr_debug("ecm_state_change: %s\n", s);
-#endif                         //DRIVERDEBUG
-}                              // ecm_state_change
-
-
-/************************
- *
- *     rmt_state_change
- *
- *     Sets RMT state in custom statistics.
- * Args
- *     smc - A pointer to the SMT context struct.
- *
- *     r_state - Possible values are:
- *
- *             RM0_ISOLATED, RM1_NON_OP, RM2_RING_OP, RM3_DETECT,
- *             RM4_NON_OP_DUP, RM5_RING_OP_DUP, RM6_DIRECTED, RM7_TRACE
- * Out
- *     Nothing.
- *
- ************************/
-void rmt_state_change(struct s_smc *smc, int r_state)
-{
-#ifdef DRIVERDEBUG
-       char *s;
-
-       switch (r_state) {
-       case RM0_ISOLATED:
-               s = "RM0_ISOLATED";
-               break;
-       case RM1_NON_OP:
-               s = "RM1_NON_OP - not operational";
-               break;
-       case RM2_RING_OP:
-               s = "RM2_RING_OP - ring operational";
-               break;
-       case RM3_DETECT:
-               s = "RM3_DETECT - detect dupl addresses";
-               break;
-       case RM4_NON_OP_DUP:
-               s = "RM4_NON_OP_DUP - dupl. addr detected";
-               break;
-       case RM5_RING_OP_DUP:
-               s = "RM5_RING_OP_DUP - ring oper. with dupl. addr";
-               break;
-       case RM6_DIRECTED:
-               s = "RM6_DIRECTED - sending directed beacons";
-               break;
-       case RM7_TRACE:
-               s = "RM7_TRACE - trace initiated";
-               break;
-       default:
-               s = "unknown";
-               break;
-       }
-       pr_debug("[rmt_state_change: %s]\n", s);
-#endif                         // DRIVERDEBUG
-}                              // rmt_state_change
-
-
-/************************
- *
- *     drv_reset_indication
- *
- *     This function is called by the SMT when it has detected a severe
- *     hardware problem. The driver should perform a reset on the adapter
- *     as soon as possible, but not from within this function.
- * Args
- *     smc - A pointer to the SMT context struct.
- * Out
- *     Nothing.
- *
- ************************/
-void drv_reset_indication(struct s_smc *smc)
-{
-       pr_debug("entering drv_reset_indication\n");
-
-       smc->os.ResetRequested = TRUE;  // Set flag.
-
-}                              // drv_reset_indication
-
-static struct pci_driver skfddi_pci_driver = {
-       .name           = "skfddi",
-       .id_table       = skfddi_pci_tbl,
-       .probe          = skfp_init_one,
-       .remove         = __devexit_p(skfp_remove_one),
-};
-
-static int __init skfd_init(void)
-{
-       return pci_register_driver(&skfddi_pci_driver);
-}
-
-static void __exit skfd_exit(void)
-{
-       pci_unregister_driver(&skfddi_pci_driver);
-}
-
-module_init(skfd_init);
-module_exit(skfd_exit);
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
deleted file mode 100644 (file)
index 08d9432..0000000
+++ /dev/null
@@ -1,2046 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/smt_p.h"
-#include <linux/bitrev.h>
-#include <linux/kernel.h>
-
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)smt.c       2.43 98/11/23 (C) SK " ;
-#endif
-
-/*
- * FC in SMbuf
- */
-#define m_fc(mb)       ((mb)->sm_data[0])
-
-#define SMT_TID_MAGIC  0x1f0a7b3c
-
-#ifdef DEBUG
-static const char *const smt_type_name[] = {
-       "SMT_00??", "SMT_INFO", "SMT_02??", "SMT_03??",
-       "SMT_04??", "SMT_05??", "SMT_06??", "SMT_07??",
-       "SMT_08??", "SMT_09??", "SMT_0A??", "SMT_0B??",
-       "SMT_0C??", "SMT_0D??", "SMT_0E??", "SMT_NSA"
-} ;
-
-static const char *const smt_class_name[] = {
-       "UNKNOWN","NIF","SIF_CONFIG","SIF_OPER","ECF","RAF","RDF",
-       "SRF","PMF_GET","PMF_SET","ESF"
-} ;
-#endif
-#define LAST_CLASS     (SMT_PMF_SET)
-
-static const struct fddi_addr SMT_Unknown = {
-       { 0,0,0x1f,0,0,0 }
-} ;
-
-/*
- * function prototypes
- */
-#ifdef LITTLE_ENDIAN
-static int smt_swap_short(u_short s);
-#endif
-static int mac_index(struct s_smc *smc, int mac);
-static int phy_index(struct s_smc *smc, int phy);
-static int mac_con_resource_index(struct s_smc *smc, int mac);
-static int phy_con_resource_index(struct s_smc *smc, int phy);
-static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
-                        int local);
-static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 
-                        int fc, u_long tid, int type, int local);
-static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
-                         u_long tid, int type, int len);
-static void smt_echo_test(struct s_smc *smc, int dna);
-static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
-                               u_long tid, int local);
-static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
-                                  u_long tid, int local);
-#ifdef LITTLE_ENDIAN
-static void smt_string_swap(char *data, const char *format, int len);
-#endif
-static void smt_add_frame_len(SMbuf *mb, int len);
-static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);
-static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde);
-static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state);
-static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts);
-static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy);
-static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency);
-static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor);
-static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path);
-static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st);
-static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy);
-static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers);
-static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc);
-static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc);
-static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc);
-static void smt_fill_manufacturer(struct s_smc *smc, 
-                                 struct smp_p_manufacturer *man);
-static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user);
-static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount);
-static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
-                         int len);
-
-static void smt_clear_una_dna(struct s_smc *smc);
-static void smt_clear_old_una_dna(struct s_smc *smc);
-#ifdef CONCENTRATOR
-static int entity_to_index(void);
-#endif
-static void update_dac(struct s_smc *smc, int report);
-static int div_ratio(u_long upper, u_long lower);
-#ifdef  USE_CAN_ADDR
-static void    hwm_conv_can(struct s_smc *smc, char *data, int len);
-#else
-#define                hwm_conv_can(smc,data,len)
-#endif
-
-
-static inline int is_my_addr(const struct s_smc *smc, 
-                            const struct fddi_addr *addr)
-{
-       return(*(short *)(&addr->a[0]) ==
-               *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[0])
-         && *(short *)(&addr->a[2]) ==
-               *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[2])
-         && *(short *)(&addr->a[4]) ==
-               *(short *)(&smc->mib.m[MAC0].fddiMACSMTAddress.a[4])) ;
-}
-
-static inline int is_broadcast(const struct fddi_addr *addr)
-{
-       return *(u_short *)(&addr->a[0]) == 0xffff &&
-              *(u_short *)(&addr->a[2]) == 0xffff &&
-              *(u_short *)(&addr->a[4]) == 0xffff;
-}
-
-static inline int is_individual(const struct fddi_addr *addr)
-{
-       return !(addr->a[0] & GROUP_ADDR);
-}
-
-static inline int is_equal(const struct fddi_addr *addr1, 
-                          const struct fddi_addr *addr2)
-{
-       return *(u_short *)(&addr1->a[0]) == *(u_short *)(&addr2->a[0]) &&
-              *(u_short *)(&addr1->a[2]) == *(u_short *)(&addr2->a[2]) &&
-              *(u_short *)(&addr1->a[4]) == *(u_short *)(&addr2->a[4]);
-}
-
-/*
- * list of mandatory paras in frames
- */
-static const u_short plist_nif[] = { SMT_P_UNA,SMT_P_SDE,SMT_P_STATE,0 } ;
-
-/*
- * init SMT agent
- */
-void smt_agent_init(struct s_smc *smc)
-{
-       int             i ;
-
-       /*
-        * get MAC address
-        */
-       smc->mib.m[MAC0].fddiMACSMTAddress = smc->hw.fddi_home_addr ;
-
-       /*
-        * get OUI address from driver (bia == built-in-address)
-        */
-       smc->mib.fddiSMTStationId.sid_oem[0] = 0 ;
-       smc->mib.fddiSMTStationId.sid_oem[1] = 0 ;
-       driver_get_bia(smc,&smc->mib.fddiSMTStationId.sid_node) ;
-       for (i = 0 ; i < 6 ; i ++) {
-               smc->mib.fddiSMTStationId.sid_node.a[i] =
-                       bitrev8(smc->mib.fddiSMTStationId.sid_node.a[i]);
-       }
-       smc->mib.fddiSMTManufacturerData[0] =
-               smc->mib.fddiSMTStationId.sid_node.a[0] ;
-       smc->mib.fddiSMTManufacturerData[1] =
-               smc->mib.fddiSMTStationId.sid_node.a[1] ;
-       smc->mib.fddiSMTManufacturerData[2] =
-               smc->mib.fddiSMTStationId.sid_node.a[2] ;
-       smc->sm.smt_tid = 0 ;
-       smc->mib.m[MAC0].fddiMACDupAddressTest = DA_NONE ;
-       smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
-#ifndef        SLIM_SMT
-       smt_clear_una_dna(smc) ;
-       smt_clear_old_una_dna(smc) ;
-#endif
-       for (i = 0 ; i < SMT_MAX_TEST ; i++)
-               smc->sm.pend[i] = 0 ;
-       smc->sm.please_reconnect = 0 ;
-       smc->sm.uniq_ticks = 0 ;
-}
-
-/*
- * SMT task
- * forever
- *     delay 30 seconds
- *     send NIF
- *     check tvu & tvd
- * end
- */
-void smt_agent_task(struct s_smc *smc)
-{
-       smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
-               EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
-       DB_SMT("SMT agent task\n",0,0) ;
-}
-
-#ifndef SMT_REAL_TOKEN_CT
-void smt_emulate_token_ct(struct s_smc *smc, int mac_index)
-{
-       u_long  count;
-       u_long  time;
-
-
-       time = smt_get_time();
-       count = ((time - smc->sm.last_tok_time[mac_index]) *
-                                       100)/TICKS_PER_SECOND;
-
-       /*
-        * Only when ring is up we will have a token count. The
-        * flag is unfortunately a single instance value. This
-        * doesn't matter now, because we currently have only
-        * one MAC instance.
-        */
-       if (smc->hw.mac_ring_is_up){
-               smc->mib.m[mac_index].fddiMACToken_Ct += count;
-       }
-
-       /* Remember current time */
-       smc->sm.last_tok_time[mac_index] = time;
-
-}
-#endif
-
-/*ARGSUSED1*/
-void smt_event(struct s_smc *smc, int event)
-{
-       u_long          time ;
-#ifndef SMT_REAL_TOKEN_CT
-       int             i ;
-#endif
-
-
-       if (smc->sm.please_reconnect) {
-               smc->sm.please_reconnect -- ;
-               if (smc->sm.please_reconnect == 0) {
-                       /* Counted down */
-                       queue_event(smc,EVENT_ECM,EC_CONNECT) ;
-               }
-       }
-
-       if (event == SM_FAST)
-               return ;
-
-       /*
-        * timer for periodic cleanup in driver
-        * reset and start the watchdog (FM2)
-        * ESS timer
-        * SBA timer
-        */
-       smt_timer_poll(smc) ;
-       smt_start_watchdog(smc) ;
-#ifndef        SLIM_SMT
-#ifndef BOOT
-#ifdef ESS
-       ess_timer_poll(smc) ;
-#endif
-#endif
-#ifdef SBA
-       sba_timer_poll(smc) ;
-#endif
-
-       smt_srf_event(smc,0,0,0) ;
-
-#endif /* no SLIM_SMT */
-
-       time = smt_get_time() ;
-
-       if (time - smc->sm.smt_last_lem >= TICKS_PER_SECOND*8) {
-               /*
-                * Use 8 sec. for the time intervall, it simplifies the
-                * LER estimation.
-                */
-               struct fddi_mib_m       *mib ;
-               u_long                  upper ;
-               u_long                  lower ;
-               int                     cond ;
-               int                     port;
-               struct s_phy            *phy ;
-               /*
-                * calculate LEM bit error rate
-                */
-               sm_lem_evaluate(smc) ;
-               smc->sm.smt_last_lem = time ;
-
-               /*
-                * check conditions
-                */
-#ifndef        SLIM_SMT
-               mac_update_counter(smc) ;
-               mib = smc->mib.m ;
-               upper =
-               (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) +
-               (mib->fddiMACError_Ct - mib->fddiMACOld_Error_Ct) ;
-               lower =
-               (mib->fddiMACFrame_Ct - mib->fddiMACOld_Frame_Ct) +
-               (mib->fddiMACLost_Ct - mib->fddiMACOld_Lost_Ct) ;
-               mib->fddiMACFrameErrorRatio = div_ratio(upper,lower) ;
-
-               cond =
-                       ((!mib->fddiMACFrameErrorThreshold &&
-                       mib->fddiMACError_Ct != mib->fddiMACOld_Error_Ct) ||
-                       (mib->fddiMACFrameErrorRatio >
-                       mib->fddiMACFrameErrorThreshold)) ;
-
-               if (cond != mib->fddiMACFrameErrorFlag)
-                       smt_srf_event(smc,SMT_COND_MAC_FRAME_ERROR,
-                               INDEX_MAC,cond) ;
-
-               upper =
-               (mib->fddiMACNotCopied_Ct - mib->fddiMACOld_NotCopied_Ct) ;
-               lower =
-               upper +
-               (mib->fddiMACCopied_Ct - mib->fddiMACOld_Copied_Ct) ;
-               mib->fddiMACNotCopiedRatio = div_ratio(upper,lower) ;
-
-               cond =
-                       ((!mib->fddiMACNotCopiedThreshold &&
-                       mib->fddiMACNotCopied_Ct !=
-                               mib->fddiMACOld_NotCopied_Ct)||
-                       (mib->fddiMACNotCopiedRatio >
-                       mib->fddiMACNotCopiedThreshold)) ;
-
-               if (cond != mib->fddiMACNotCopiedFlag)
-                       smt_srf_event(smc,SMT_COND_MAC_NOT_COPIED,
-                               INDEX_MAC,cond) ;
-
-               /*
-                * set old values
-                */
-               mib->fddiMACOld_Frame_Ct = mib->fddiMACFrame_Ct ;
-               mib->fddiMACOld_Copied_Ct = mib->fddiMACCopied_Ct ;
-               mib->fddiMACOld_Error_Ct = mib->fddiMACError_Ct ;
-               mib->fddiMACOld_Lost_Ct = mib->fddiMACLost_Ct ;
-               mib->fddiMACOld_NotCopied_Ct = mib->fddiMACNotCopied_Ct ;
-
-               /*
-                * Check port EBError Condition
-                */
-               for (port = 0; port < NUMPHYS; port ++) {
-                       phy = &smc->y[port] ;
-
-                       if (!phy->mib->fddiPORTHardwarePresent) {
-                               continue;
-                       }
-
-                       cond = (phy->mib->fddiPORTEBError_Ct -
-                               phy->mib->fddiPORTOldEBError_Ct > 5) ;
-
-                       /* If ratio is more than 5 in 8 seconds
-                        * Set the condition.
-                        */
-                       smt_srf_event(smc,SMT_COND_PORT_EB_ERROR,
-                               (int) (INDEX_PORT+ phy->np) ,cond) ;
-
-                       /*
-                        * set old values
-                        */
-                       phy->mib->fddiPORTOldEBError_Ct =
-                               phy->mib->fddiPORTEBError_Ct ;
-               }
-
-#endif /* no SLIM_SMT */
-       }
-
-#ifndef        SLIM_SMT
-
-       if (time - smc->sm.smt_last_notify >= (u_long)
-               (smc->mib.fddiSMTTT_Notify * TICKS_PER_SECOND) ) {
-               /*
-                * we can either send an announcement or a request
-                * a request will trigger a reply so that we can update
-                * our dna
-                * note: same tid must be used until reply is received
-                */
-               if (!smc->sm.pend[SMT_TID_NIF])
-                       smc->sm.pend[SMT_TID_NIF] = smt_get_tid(smc) ;
-               smt_send_nif(smc,&fddi_broadcast, FC_SMT_NSA,
-                       smc->sm.pend[SMT_TID_NIF], SMT_REQUEST,0) ;
-               smc->sm.smt_last_notify = time ;
-       }
-
-       /*
-        * check timer
-        */
-       if (smc->sm.smt_tvu &&
-           time - smc->sm.smt_tvu > 228*TICKS_PER_SECOND) {
-               DB_SMT("SMT : UNA expired\n",0,0) ;
-               smc->sm.smt_tvu = 0 ;
-
-               if (!is_equal(&smc->mib.m[MAC0].fddiMACUpstreamNbr,
-                       &SMT_Unknown)){
-                       /* Do not update unknown address */
-                       smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
-                               smc->mib.m[MAC0].fddiMACUpstreamNbr ;
-               }
-               smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
-               smc->mib.m[MAC0].fddiMACUNDA_Flag = FALSE ;
-               /*
-                * Make sure the fddiMACUNDA_Flag = FALSE is
-                * included in the SRF so we don't generate
-                * a separate SRF for the deassertion of this
-                * condition
-                */
-               update_dac(smc,0) ;
-               smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
-                       INDEX_MAC,0) ;
-       }
-       if (smc->sm.smt_tvd &&
-           time - smc->sm.smt_tvd > 228*TICKS_PER_SECOND) {
-               DB_SMT("SMT : DNA expired\n",0,0) ;
-               smc->sm.smt_tvd = 0 ;
-               if (!is_equal(&smc->mib.m[MAC0].fddiMACDownstreamNbr,
-                       &SMT_Unknown)){
-                       /* Do not update unknown address */
-                       smc->mib.m[MAC0].fddiMACOldDownstreamNbr=
-                               smc->mib.m[MAC0].fddiMACDownstreamNbr ;
-               }
-               smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
-               smt_srf_event(smc, SMT_EVENT_MAC_NEIGHBOR_CHANGE,
-                       INDEX_MAC,0) ;
-       }
-
-#endif /* no SLIM_SMT */
-
-#ifndef SMT_REAL_TOKEN_CT
-       /*
-        * Token counter emulation section. If hardware supports the token
-        * count, the token counter will be updated in mac_update_counter.
-        */
-       for (i = MAC0; i < NUMMACS; i++ ){
-               if (time - smc->sm.last_tok_time[i] > 2*TICKS_PER_SECOND ){
-                       smt_emulate_token_ct( smc, i );
-               }
-       }
-#endif
-
-       smt_timer_start(smc,&smc->sm.smt_timer, (u_long)1000000L,
-               EV_TOKEN(EVENT_SMT,SM_TIMER)) ;
-}
-
-static int div_ratio(u_long upper, u_long lower)
-{
-       if ((upper<<16L) < upper)
-               upper = 0xffff0000L ;
-       else
-               upper <<= 16L ;
-       if (!lower)
-               return 0;
-       return (int)(upper/lower) ;
-}
-
-#ifndef        SLIM_SMT
-
-/*
- * receive packet handler
- */
-void smt_received_pack(struct s_smc *smc, SMbuf *mb, int fs)
-/* int fs;  frame status */
-{
-       struct smt_header       *sm ;
-       int                     local ;
-
-       int                     illegal = 0 ;
-
-       switch (m_fc(mb)) {
-       case FC_SMT_INFO :
-       case FC_SMT_LAN_LOC :
-       case FC_SMT_LOC :
-       case FC_SMT_NSA :
-               break ;
-       default :
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-
-       smc->mib.m[MAC0].fddiMACSMTCopied_Ct++ ;
-       sm = smtod(mb,struct smt_header *) ;
-       local = ((fs & L_INDICATOR) != 0) ;
-       hwm_conv_can(smc,(char *)sm,12) ;
-
-       /* check destination address */
-       if (is_individual(&sm->smt_dest) && !is_my_addr(smc,&sm->smt_dest)) {
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-#if    0               /* for DUP recognition, do NOT filter them */
-       /* ignore loop back packets */
-       if (is_my_addr(smc,&sm->smt_source) && !local) {
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-#endif
-
-       smt_swap_para(sm,(int) mb->sm_len,1) ;
-       DB_SMT("SMT : received packet [%s] at 0x%x\n",
-               smt_type_name[m_fc(mb) & 0xf],sm) ;
-       DB_SMT("SMT : version %d, class %s\n",sm->smt_version,
-               smt_class_name[(sm->smt_class>LAST_CLASS)?0 : sm->smt_class]) ;
-
-#ifdef SBA
-       /*
-        * check if NSA frame
-        */
-       if (m_fc(mb) == FC_SMT_NSA && sm->smt_class == SMT_NIF &&
-               (sm->smt_type == SMT_ANNOUNCE || sm->smt_type == SMT_REQUEST)) {
-                       smc->sba.sm = sm ;
-                       sba(smc,NIF) ;
-       }
-#endif
-
-       /*
-        * ignore any packet with NSA and A-indicator set
-        */
-       if ( (fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) {
-               DB_SMT("SMT : ignoring NSA with A-indicator set from %s\n",
-                       addr_to_string(&sm->smt_source),0) ;
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-
-       /*
-        * ignore frames with illegal length
-        */
-       if (((sm->smt_class == SMT_ECF) && (sm->smt_len > SMT_MAX_ECHO_LEN)) ||
-           ((sm->smt_class != SMT_ECF) && (sm->smt_len > SMT_MAX_INFO_LEN))) {
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-
-       /*
-        * check SMT version
-        */
-       switch (sm->smt_class) {
-       case SMT_NIF :
-       case SMT_SIF_CONFIG :
-       case SMT_SIF_OPER :
-       case SMT_ECF :
-               if (sm->smt_version != SMT_VID)
-                       illegal = 1;
-               break ;
-       default :
-               if (sm->smt_version != SMT_VID_2)
-                       illegal = 1;
-               break ;
-       }
-       if (illegal) {
-               DB_SMT("SMT : version = %d, dest = %s\n",
-                       sm->smt_version,addr_to_string(&sm->smt_source)) ;
-               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_VERSION,local) ;
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-       if ((sm->smt_len > mb->sm_len - sizeof(struct smt_header)) ||
-           ((sm->smt_len & 3) && (sm->smt_class != SMT_ECF))) {
-               DB_SMT("SMT: info length error, len = %d\n",sm->smt_len,0) ;
-               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,local) ;
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-       switch (sm->smt_class) {
-       case SMT_NIF :
-               if (smt_check_para(smc,sm,plist_nif)) {
-                       DB_SMT("SMT: NIF with para problem, ignoring\n",0,0) ;
-                       break ;
-               }
-               switch (sm->smt_type) {
-               case SMT_ANNOUNCE :
-               case SMT_REQUEST :
-                       if (!(fs & C_INDICATOR) && m_fc(mb) == FC_SMT_NSA
-                               && is_broadcast(&sm->smt_dest)) {
-                               struct smt_p_state      *st ;
-
-                               /* set my UNA */
-                               if (!is_equal(
-                                       &smc->mib.m[MAC0].fddiMACUpstreamNbr,
-                                       &sm->smt_source)) {
-                                       DB_SMT("SMT : updated my UNA = %s\n",
-                                       addr_to_string(&sm->smt_source),0) ;
-                                       if (!is_equal(&smc->mib.m[MAC0].
-                                           fddiMACUpstreamNbr,&SMT_Unknown)){
-                                        /* Do not update unknown address */
-                                        smc->mib.m[MAC0].fddiMACOldUpstreamNbr=
-                                        smc->mib.m[MAC0].fddiMACUpstreamNbr ;
-                                       }
-
-                                       smc->mib.m[MAC0].fddiMACUpstreamNbr =
-                                               sm->smt_source ;
-                                       smt_srf_event(smc,
-                                               SMT_EVENT_MAC_NEIGHBOR_CHANGE,
-                                               INDEX_MAC,0) ;
-                                       smt_echo_test(smc,0) ;
-                               }
-                               smc->sm.smt_tvu = smt_get_time() ;
-                               st = (struct smt_p_state *)
-                                       sm_to_para(smc,sm,SMT_P_STATE) ;
-                               if (st) {
-                                       smc->mib.m[MAC0].fddiMACUNDA_Flag =
-                                       (st->st_dupl_addr & SMT_ST_MY_DUPA) ?
-                                       TRUE : FALSE ;
-                                       update_dac(smc,1) ;
-                               }
-                       }
-                       if ((sm->smt_type == SMT_REQUEST) &&
-                           is_individual(&sm->smt_source) &&
-                           ((!(fs & A_INDICATOR) && m_fc(mb) == FC_SMT_NSA) ||
-                            (m_fc(mb) != FC_SMT_NSA))) {
-                               DB_SMT("SMT : replying to NIF request %s\n",
-                                       addr_to_string(&sm->smt_source),0) ;
-                               smt_send_nif(smc,&sm->smt_source,
-                                       FC_SMT_INFO,
-                                       sm->smt_tid,
-                                       SMT_REPLY,local) ;
-                       }
-                       break ;
-               case SMT_REPLY :
-                       DB_SMT("SMT : received NIF response from %s\n",
-                               addr_to_string(&sm->smt_source),0) ;
-                       if (fs & A_INDICATOR) {
-                               smc->sm.pend[SMT_TID_NIF] = 0 ;
-                               DB_SMT("SMT : duplicate address\n",0,0) ;
-                               smc->mib.m[MAC0].fddiMACDupAddressTest =
-                                       DA_FAILED ;
-                               smc->r.dup_addr_test = DA_FAILED ;
-                               queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
-                               smc->mib.m[MAC0].fddiMACDA_Flag = TRUE ;
-                               update_dac(smc,1) ;
-                               break ;
-                       }
-                       if (sm->smt_tid == smc->sm.pend[SMT_TID_NIF]) {
-                               smc->sm.pend[SMT_TID_NIF] = 0 ;
-                               /* set my DNA */
-                               if (!is_equal(
-                                       &smc->mib.m[MAC0].fddiMACDownstreamNbr,
-                                       &sm->smt_source)) {
-                                       DB_SMT("SMT : updated my DNA\n",0,0) ;
-                                       if (!is_equal(&smc->mib.m[MAC0].
-                                        fddiMACDownstreamNbr, &SMT_Unknown)){
-                                        /* Do not update unknown address */
-                               smc->mib.m[MAC0].fddiMACOldDownstreamNbr =
-                                        smc->mib.m[MAC0].fddiMACDownstreamNbr ;
-                                       }
-
-                                       smc->mib.m[MAC0].fddiMACDownstreamNbr =
-                                               sm->smt_source ;
-                                       smt_srf_event(smc,
-                                               SMT_EVENT_MAC_NEIGHBOR_CHANGE,
-                                               INDEX_MAC,0) ;
-                                       smt_echo_test(smc,1) ;
-                               }
-                               smc->mib.m[MAC0].fddiMACDA_Flag = FALSE ;
-                               update_dac(smc,1) ;
-                               smc->sm.smt_tvd = smt_get_time() ;
-                               smc->mib.m[MAC0].fddiMACDupAddressTest =
-                                       DA_PASSED ;
-                               if (smc->r.dup_addr_test != DA_PASSED) {
-                                       smc->r.dup_addr_test = DA_PASSED ;
-                                       queue_event(smc,EVENT_RMT,RM_DUP_ADDR) ;
-                               }
-                       }
-                       else if (sm->smt_tid ==
-                               smc->sm.pend[SMT_TID_NIF_TEST]) {
-                               DB_SMT("SMT : NIF test TID ok\n",0,0) ;
-                       }
-                       else {
-                               DB_SMT("SMT : expected TID %lx, got %lx\n",
-                               smc->sm.pend[SMT_TID_NIF],sm->smt_tid) ;
-                       }
-                       break ;
-               default :
-                       illegal = 2 ;
-                       break ;
-               }
-               break ;
-       case SMT_SIF_CONFIG :   /* station information */
-               if (sm->smt_type != SMT_REQUEST)
-                       break ;
-               DB_SMT("SMT : replying to SIF Config request from %s\n",
-                       addr_to_string(&sm->smt_source),0) ;
-               smt_send_sif_config(smc,&sm->smt_source,sm->smt_tid,local) ;
-               break ;
-       case SMT_SIF_OPER :     /* station information */
-               if (sm->smt_type != SMT_REQUEST)
-                       break ;
-               DB_SMT("SMT : replying to SIF Operation request from %s\n",
-                       addr_to_string(&sm->smt_source),0) ;
-               smt_send_sif_operation(smc,&sm->smt_source,sm->smt_tid,local) ;
-               break ;
-       case SMT_ECF :          /* echo frame */
-               switch (sm->smt_type) {
-               case SMT_REPLY :
-                       smc->mib.priv.fddiPRIVECF_Reply_Rx++ ;
-                       DB_SMT("SMT: received ECF reply from %s\n",
-                               addr_to_string(&sm->smt_source),0) ;
-                       if (sm_to_para(smc,sm,SMT_P_ECHODATA) == NULL) {
-                               DB_SMT("SMT: ECHODATA missing\n",0,0) ;
-                               break ;
-                       }
-                       if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF]) {
-                               DB_SMT("SMT : ECF test TID ok\n",0,0) ;
-                       }
-                       else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_UNA]) {
-                               DB_SMT("SMT : ECF test UNA ok\n",0,0) ;
-                       }
-                       else if (sm->smt_tid == smc->sm.pend[SMT_TID_ECF_DNA]) {
-                               DB_SMT("SMT : ECF test DNA ok\n",0,0) ;
-                       }
-                       else {
-                               DB_SMT("SMT : expected TID %lx, got %lx\n",
-                                       smc->sm.pend[SMT_TID_ECF],
-                                       sm->smt_tid) ;
-                       }
-                       break ;
-               case SMT_REQUEST :
-                       smc->mib.priv.fddiPRIVECF_Req_Rx++ ;
-                       {
-                       if (sm->smt_len && !sm_to_para(smc,sm,SMT_P_ECHODATA)) {
-                       DB_SMT("SMT: ECF with para problem,sending RDF\n",0,0) ;
-                               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_LENGTH,
-                                       local) ;
-                               break ;
-                       }
-                       DB_SMT("SMT - sending ECF reply to %s\n",
-                               addr_to_string(&sm->smt_source),0) ;
-
-                       /* set destination addr.  & reply */
-                       sm->smt_dest = sm->smt_source ;
-                       sm->smt_type = SMT_REPLY ;
-                       dump_smt(smc,sm,"ECF REPLY") ;
-                       smc->mib.priv.fddiPRIVECF_Reply_Tx++ ;
-                       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
-                       return ;                /* DON'T free mbuf */
-                       }
-               default :
-                       illegal = 1 ;
-                       break ;
-               }
-               break ;
-#ifndef        BOOT
-       case SMT_RAF :          /* resource allocation */
-#ifdef ESS
-               DB_ESSN(2,"ESS: RAF frame received\n",0,0) ;
-               fs = ess_raf_received_pack(smc,mb,sm,fs) ;
-#endif
-
-#ifdef SBA
-               DB_SBAN(2,"SBA: RAF frame received\n",0,0) ;
-               sba_raf_received_pack(smc,sm,fs) ;
-#endif
-               break ;
-       case SMT_RDF :          /* request denied */
-               smc->mib.priv.fddiPRIVRDF_Rx++ ;
-               break ;
-       case SMT_ESF :          /* extended service - not supported */
-               if (sm->smt_type == SMT_REQUEST) {
-                       DB_SMT("SMT - received ESF, sending RDF\n",0,0) ;
-                       smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
-               }
-               break ;
-       case SMT_PMF_GET :
-       case SMT_PMF_SET :
-               if (sm->smt_type != SMT_REQUEST)
-                       break ;
-               /* update statistics */
-               if (sm->smt_class == SMT_PMF_GET)
-                       smc->mib.priv.fddiPRIVPMF_Get_Rx++ ;
-               else
-                       smc->mib.priv.fddiPRIVPMF_Set_Rx++ ;
-               /*
-                * ignore PMF SET with I/G set
-                */
-               if ((sm->smt_class == SMT_PMF_SET) &&
-                       !is_individual(&sm->smt_dest)) {
-                       DB_SMT("SMT: ignoring PMF-SET with I/G set\n",0,0) ;
-                       break ;
-               }
-               smt_pmf_received_pack(smc,mb, local) ;
-               break ;
-       case SMT_SRF :
-               dump_smt(smc,sm,"SRF received") ;
-               break ;
-       default :
-               if (sm->smt_type != SMT_REQUEST)
-                       break ;
-               /*
-                * For frames with unknown class:
-                * we need to send a RDF frame according to 8.1.3.1.1,
-                * only if it is a REQUEST.
-                */
-               DB_SMT("SMT : class = %d, send RDF to %s\n",
-                       sm->smt_class, addr_to_string(&sm->smt_source)) ;
-
-               smt_send_rdf(smc,mb,m_fc(mb),SMT_RDF_CLASS,local) ;
-               break ;
-#endif
-       }
-       if (illegal) {
-               DB_SMT("SMT: discarding invalid frame, reason = %d\n",
-                       illegal,0) ;
-       }
-       smt_free_mbuf(smc,mb) ;
-}
-
-static void update_dac(struct s_smc *smc, int report)
-{
-       int     cond ;
-
-       cond = ( smc->mib.m[MAC0].fddiMACUNDA_Flag |
-               smc->mib.m[MAC0].fddiMACDA_Flag) != 0 ;
-       if (report && (cond != smc->mib.m[MAC0].fddiMACDuplicateAddressCond))
-               smt_srf_event(smc, SMT_COND_MAC_DUP_ADDR,INDEX_MAC,cond) ;
-       else
-               smc->mib.m[MAC0].fddiMACDuplicateAddressCond = cond ;
-}
-
-/*
- * send SMT frame
- *     set source address
- *     set station ID
- *     send frame
- */
-void smt_send_frame(struct s_smc *smc, SMbuf *mb, int fc, int local)
-/* SMbuf *mb;  buffer to send */
-/* int fc;     FC value */
-{
-       struct smt_header       *sm ;
-
-       if (!smc->r.sm_ma_avail && !local) {
-               smt_free_mbuf(smc,mb) ;
-               return ;
-       }
-       sm = smtod(mb,struct smt_header *) ;
-       sm->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
-       sm->smt_sid = smc->mib.fddiSMTStationId ;
-
-       smt_swap_para(sm,(int) mb->sm_len,0) ;          /* swap para & header */
-       hwm_conv_can(smc,(char *)sm,12) ;               /* convert SA and DA */
-       smc->mib.m[MAC0].fddiMACSMTTransmit_Ct++ ;
-       smt_send_mbuf(smc,mb,local ? FC_SMT_LOC : fc) ;
-}
-
-/*
- * generate and send RDF
- */
-static void smt_send_rdf(struct s_smc *smc, SMbuf *rej, int fc, int reason,
-                        int local)
-/* SMbuf *rej; mbuf of offending frame */
-/* int fc;     FC of denied frame */
-/* int reason; reason code */
-{
-       SMbuf   *mb ;
-       struct smt_header       *sm ;   /* header of offending frame */
-       struct smt_rdf  *rdf ;
-       int             len ;
-       int             frame_len ;
-
-       sm = smtod(rej,struct smt_header *) ;
-       if (sm->smt_type != SMT_REQUEST)
-               return ;
-
-       DB_SMT("SMT: sending RDF to %s,reason = 0x%x\n",
-               addr_to_string(&sm->smt_source),reason) ;
-
-
-       /*
-        * note: get framelength from MAC length, NOT from SMT header
-        * smt header length is included in sm_len
-        */
-       frame_len = rej->sm_len ;
-
-       if (!(mb=smt_build_frame(smc,SMT_RDF,SMT_REPLY,sizeof(struct smt_rdf))))
-               return ;
-       rdf = smtod(mb,struct smt_rdf *) ;
-       rdf->smt.smt_tid = sm->smt_tid ;                /* use TID from sm */
-       rdf->smt.smt_dest = sm->smt_source ;            /* set dest = source */
-
-       /* set P12 */
-       rdf->reason.para.p_type = SMT_P_REASON ;
-       rdf->reason.para.p_len = sizeof(struct smt_p_reason) - PARA_LEN ;
-       rdf->reason.rdf_reason = reason ;
-
-       /* set P14 */
-       rdf->version.para.p_type = SMT_P_VERSION ;
-       rdf->version.para.p_len = sizeof(struct smt_p_version) - PARA_LEN ;
-       rdf->version.v_pad = 0 ;
-       rdf->version.v_n = 1 ;
-       rdf->version.v_index = 1 ;
-       rdf->version.v_version[0] = SMT_VID_2 ;
-       rdf->version.v_pad2 = 0 ;
-
-       /* set P13 */
-       if ((unsigned) frame_len <= SMT_MAX_INFO_LEN - sizeof(*rdf) +
-               2*sizeof(struct smt_header))
-               len = frame_len ;
-       else
-               len = SMT_MAX_INFO_LEN - sizeof(*rdf) +
-                       2*sizeof(struct smt_header) ;
-       /* make length multiple of 4 */
-       len &= ~3 ;
-       rdf->refused.para.p_type = SMT_P_REFUSED ;
-       /* length of para is smt_frame + ref_fc */
-       rdf->refused.para.p_len = len + 4 ;
-       rdf->refused.ref_fc = fc ;
-
-       /* swap it back */
-       smt_swap_para(sm,frame_len,0) ;
-
-       memcpy((char *) &rdf->refused.ref_header,(char *) sm,len) ;
-
-       len -= sizeof(struct smt_header) ;
-       mb->sm_len += len ;
-       rdf->smt.smt_len += len ;
-
-       dump_smt(smc,(struct smt_header *)rdf,"RDF") ;
-       smc->mib.priv.fddiPRIVRDF_Tx++ ;
-       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
-}
-
-/*
- * generate and send NIF
- */
-static void smt_send_nif(struct s_smc *smc, const struct fddi_addr *dest, 
-                        int fc, u_long tid, int type, int local)
-/* struct fddi_addr *dest;     dest address */
-/* int fc;                     frame control */
-/* u_long tid;                 transaction id */
-/* int type;                   frame type */
-{
-       struct smt_nif  *nif ;
-       SMbuf           *mb ;
-
-       if (!(mb = smt_build_frame(smc,SMT_NIF,type,sizeof(struct smt_nif))))
-               return ;
-       nif = smtod(mb, struct smt_nif *) ;
-       smt_fill_una(smc,&nif->una) ;   /* set UNA */
-       smt_fill_sde(smc,&nif->sde) ;   /* set station descriptor */
-       smt_fill_state(smc,&nif->state) ;       /* set state information */
-#ifdef SMT6_10
-       smt_fill_fsc(smc,&nif->fsc) ;   /* set frame status cap. */
-#endif
-       nif->smt.smt_dest = *dest ;     /* destination address */
-       nif->smt.smt_tid = tid ;        /* transaction ID */
-       dump_smt(smc,(struct smt_header *)nif,"NIF") ;
-       smt_send_frame(smc,mb,fc,local) ;
-}
-
-#ifdef DEBUG
-/*
- * send NIF request (test purpose)
- */
-static void smt_send_nif_request(struct s_smc *smc, struct fddi_addr *dest)
-{
-       smc->sm.pend[SMT_TID_NIF_TEST] = smt_get_tid(smc) ;
-       smt_send_nif(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_NIF_TEST],
-               SMT_REQUEST,0) ;
-}
-
-/*
- * send ECF request (test purpose)
- */
-static void smt_send_ecf_request(struct s_smc *smc, struct fddi_addr *dest,
-                                int len)
-{
-       smc->sm.pend[SMT_TID_ECF] = smt_get_tid(smc) ;
-       smt_send_ecf(smc,dest, FC_SMT_INFO, smc->sm.pend[SMT_TID_ECF],
-               SMT_REQUEST,len) ;
-}
-#endif
-
-/*
- * echo test
- */
-static void smt_echo_test(struct s_smc *smc, int dna)
-{
-       u_long  tid ;
-
-       smc->sm.pend[dna ? SMT_TID_ECF_DNA : SMT_TID_ECF_UNA] =
-               tid = smt_get_tid(smc) ;
-       smt_send_ecf(smc, dna ?
-               &smc->mib.m[MAC0].fddiMACDownstreamNbr :
-               &smc->mib.m[MAC0].fddiMACUpstreamNbr,
-               FC_SMT_INFO,tid, SMT_REQUEST, (SMT_TEST_ECHO_LEN & ~3)-8) ;
-}
-
-/*
- * generate and send ECF
- */
-static void smt_send_ecf(struct s_smc *smc, struct fddi_addr *dest, int fc,
-                        u_long tid, int type, int len)
-/* struct fddi_addr *dest;     dest address */
-/* int fc;                     frame control */
-/* u_long tid;                 transaction id */
-/* int type;                   frame type */
-/* int len;                    frame length */
-{
-       struct smt_ecf  *ecf ;
-       SMbuf           *mb ;
-
-       if (!(mb = smt_build_frame(smc,SMT_ECF,type,SMT_ECF_LEN + len)))
-               return ;
-       ecf = smtod(mb, struct smt_ecf *) ;
-
-       smt_fill_echo(smc,&ecf->ec_echo,tid,len) ;      /* set ECHO */
-       ecf->smt.smt_dest = *dest ;     /* destination address */
-       ecf->smt.smt_tid = tid ;        /* transaction ID */
-       smc->mib.priv.fddiPRIVECF_Req_Tx++ ;
-       smt_send_frame(smc,mb,fc,0) ;
-}
-
-/*
- * generate and send SIF config response
- */
-
-static void smt_send_sif_config(struct s_smc *smc, struct fddi_addr *dest,
-                               u_long tid, int local)
-/* struct fddi_addr *dest;     dest address */
-/* u_long tid;                 transaction id */
-{
-       struct smt_sif_config   *sif ;
-       SMbuf                   *mb ;
-       int                     len ;
-       if (!(mb = smt_build_frame(smc,SMT_SIF_CONFIG,SMT_REPLY,
-               SIZEOF_SMT_SIF_CONFIG)))
-               return ;
-
-       sif = smtod(mb, struct smt_sif_config *) ;
-       smt_fill_timestamp(smc,&sif->ts) ;      /* set time stamp */
-       smt_fill_sde(smc,&sif->sde) ;           /* set station descriptor */
-       smt_fill_version(smc,&sif->version) ;   /* set version information */
-       smt_fill_state(smc,&sif->state) ;       /* set state information */
-       smt_fill_policy(smc,&sif->policy) ;     /* set station policy */
-       smt_fill_latency(smc,&sif->latency);    /* set station latency */
-       smt_fill_neighbor(smc,&sif->neighbor);  /* set station neighbor */
-       smt_fill_setcount(smc,&sif->setcount) ; /* set count */
-       len = smt_fill_path(smc,&sif->path);    /* set station path descriptor*/
-       sif->smt.smt_dest = *dest ;             /* destination address */
-       sif->smt.smt_tid = tid ;                /* transaction ID */
-       smt_add_frame_len(mb,len) ;             /* adjust length fields */
-       dump_smt(smc,(struct smt_header *)sif,"SIF Configuration Reply") ;
-       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
-}
-
-/*
- * generate and send SIF operation response
- */
-
-static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
-                                  u_long tid, int local)
-/* struct fddi_addr *dest;     dest address */
-/* u_long tid;                 transaction id */
-{
-       struct smt_sif_operation *sif ;
-       SMbuf                   *mb ;
-       int                     ports ;
-       int                     i ;
-
-       ports = NUMPHYS ;
-#ifndef        CONCENTRATOR
-       if (smc->s.sas == SMT_SAS)
-               ports = 1 ;
-#endif
-
-       if (!(mb = smt_build_frame(smc,SMT_SIF_OPER,SMT_REPLY,
-               SIZEOF_SMT_SIF_OPERATION+ports*sizeof(struct smt_p_lem))))
-               return ;
-       sif = smtod(mb, struct smt_sif_operation *) ;
-       smt_fill_timestamp(smc,&sif->ts) ;      /* set time stamp */
-       smt_fill_mac_status(smc,&sif->status) ; /* set mac status */
-       smt_fill_mac_counter(smc,&sif->mc) ; /* set mac counter field */
-       smt_fill_mac_fnc(smc,&sif->fnc) ; /* set frame not copied counter */
-       smt_fill_manufacturer(smc,&sif->man) ; /* set manufacturer field */
-       smt_fill_user(smc,&sif->user) ;         /* set user field */
-       smt_fill_setcount(smc,&sif->setcount) ; /* set count */
-       /*
-        * set link error mon information
-        */
-       if (ports == 1) {
-               smt_fill_lem(smc,sif->lem,PS) ;
-       }
-       else {
-               for (i = 0 ; i < ports ; i++) {
-                       smt_fill_lem(smc,&sif->lem[i],i) ;
-               }
-       }
-
-       sif->smt.smt_dest = *dest ;     /* destination address */
-       sif->smt.smt_tid = tid ;        /* transaction ID */
-       dump_smt(smc,(struct smt_header *)sif,"SIF Operation Reply") ;
-       smt_send_frame(smc,mb,FC_SMT_INFO,local) ;
-}
-
-/*
- * get and initialize SMT frame
- */
-SMbuf *smt_build_frame(struct s_smc *smc, int class, int type,
-                                 int length)
-{
-       SMbuf                   *mb ;
-       struct smt_header       *smt ;
-
-#if    0
-       if (!smc->r.sm_ma_avail) {
-               return 0;
-       }
-#endif
-       if (!(mb = smt_get_mbuf(smc)))
-               return mb;
-
-       mb->sm_len = length ;
-       smt = smtod(mb, struct smt_header *) ;
-       smt->smt_dest = fddi_broadcast ; /* set dest = broadcast */
-       smt->smt_class = class ;
-       smt->smt_type = type ;
-       switch (class) {
-       case SMT_NIF :
-       case SMT_SIF_CONFIG :
-       case SMT_SIF_OPER :
-       case SMT_ECF :
-               smt->smt_version = SMT_VID ;
-               break ;
-       default :
-               smt->smt_version = SMT_VID_2 ;
-               break ;
-       }
-       smt->smt_tid = smt_get_tid(smc) ;       /* set transaction ID */
-       smt->smt_pad = 0 ;
-       smt->smt_len = length - sizeof(struct smt_header) ;
-       return mb;
-}
-
-static void smt_add_frame_len(SMbuf *mb, int len)
-{
-       struct smt_header       *smt ;
-
-       smt = smtod(mb, struct smt_header *) ;
-       smt->smt_len += len ;
-       mb->sm_len += len ;
-}
-
-
-
-/*
- * fill values in UNA parameter
- */
-static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una)
-{
-       SMTSETPARA(una,SMT_P_UNA) ;
-       una->una_pad = 0 ;
-       una->una_node = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
-}
-
-/*
- * fill values in SDE parameter
- */
-static void smt_fill_sde(struct s_smc *smc, struct smt_p_sde *sde)
-{
-       SMTSETPARA(sde,SMT_P_SDE) ;
-       sde->sde_non_master = smc->mib.fddiSMTNonMaster_Ct ;
-       sde->sde_master = smc->mib.fddiSMTMaster_Ct ;
-       sde->sde_mac_count = NUMMACS ;          /* only 1 MAC */
-#ifdef CONCENTRATOR
-       sde->sde_type = SMT_SDE_CONCENTRATOR ;
-#else
-       sde->sde_type = SMT_SDE_STATION ;
-#endif
-}
-
-/*
- * fill in values in station state parameter
- */
-static void smt_fill_state(struct s_smc *smc, struct smt_p_state *state)
-{
-       int     top ;
-       int     twist ;
-
-       SMTSETPARA(state,SMT_P_STATE) ;
-       state->st_pad = 0 ;
-
-       /* determine topology */
-       top = 0 ;
-       if (smc->mib.fddiSMTPeerWrapFlag) {
-               top |= SMT_ST_WRAPPED ;         /* state wrapped */
-       }
-#ifdef CONCENTRATOR
-       if (cfm_status_unattached(smc)) {
-               top |= SMT_ST_UNATTACHED ;      /* unattached concentrator */
-       }
-#endif
-       if ((twist = pcm_status_twisted(smc)) & 1) {
-               top |= SMT_ST_TWISTED_A ;       /* twisted cable */
-       }
-       if (twist & 2) {
-               top |= SMT_ST_TWISTED_B ;       /* twisted cable */
-       }
-#ifdef OPT_SRF
-       top |= SMT_ST_SRF ;
-#endif
-       if (pcm_rooted_station(smc))
-               top |= SMT_ST_ROOTED_S ;
-       if (smc->mib.a[0].fddiPATHSbaPayload != 0)
-               top |= SMT_ST_SYNC_SERVICE ;
-       state->st_topology = top ;
-       state->st_dupl_addr =
-               ((smc->mib.m[MAC0].fddiMACDA_Flag ? SMT_ST_MY_DUPA : 0 ) |
-                (smc->mib.m[MAC0].fddiMACUNDA_Flag ? SMT_ST_UNA_DUPA : 0)) ;
-}
-
-/*
- * fill values in timestamp parameter
- */
-static void smt_fill_timestamp(struct s_smc *smc, struct smt_p_timestamp *ts)
-{
-
-       SMTSETPARA(ts,SMT_P_TIMESTAMP) ;
-       smt_set_timestamp(smc,ts->ts_time) ;
-}
-
-void smt_set_timestamp(struct s_smc *smc, u_char *p)
-{
-       u_long  time ;
-       u_long  utime ;
-
-       /*
-        * timestamp is 64 bits long ; resolution is 80 nS
-        * our clock resolution is 10mS
-        * 10mS/80ns = 125000 ~ 2^17 = 131072
-        */
-       utime = smt_get_time() ;
-       time = utime * 100 ;
-       time /= TICKS_PER_SECOND ;
-       p[0] = 0 ;
-       p[1] = (u_char)((time>>(8+8+8+8-1)) & 1) ;
-       p[2] = (u_char)(time>>(8+8+8-1)) ;
-       p[3] = (u_char)(time>>(8+8-1)) ;
-       p[4] = (u_char)(time>>(8-1)) ;
-       p[5] = (u_char)(time<<1) ;
-       p[6] = (u_char)(smc->sm.uniq_ticks>>8) ;
-       p[7] = (u_char)smc->sm.uniq_ticks ;
-       /*
-        * make sure we don't wrap: restart whenever the upper digits change
-        */
-       if (utime != smc->sm.uniq_time) {
-               smc->sm.uniq_ticks = 0 ;
-       }
-       smc->sm.uniq_ticks++ ;
-       smc->sm.uniq_time = utime ;
-}
-
-/*
- * fill values in station policy parameter
- */
-static void smt_fill_policy(struct s_smc *smc, struct smt_p_policy *policy)
-{
-       int     i ;
-       const u_char *map ;
-       u_short in ;
-       u_short out ;
-
-       /*
-        * MIB para 101b (fddiSMTConnectionPolicy) coding
-        * is different from 0005 coding
-        */
-       static const u_char ansi_weirdness[16] = {
-               0,7,5,3,8,1,6,4,9,10,2,11,12,13,14,15
-       } ;
-       SMTSETPARA(policy,SMT_P_POLICY) ;
-
-       out = 0 ;
-       in = smc->mib.fddiSMTConnectionPolicy ;
-       for (i = 0, map = ansi_weirdness ; i < 16 ; i++) {
-               if (in & 1)
-                       out |= (1<<*map) ;
-               in >>= 1 ;
-               map++ ;
-       }
-       policy->pl_config = smc->mib.fddiSMTConfigPolicy ;
-       policy->pl_connect = out ;
-}
-
-/*
- * fill values in latency equivalent parameter
- */
-static void smt_fill_latency(struct s_smc *smc, struct smt_p_latency *latency)
-{
-       SMTSETPARA(latency,SMT_P_LATENCY) ;
-
-       latency->lt_phyout_idx1 = phy_index(smc,0) ;
-       latency->lt_latency1 = 10 ;     /* in octets (byte clock) */
-       /*
-        * note: latency has two phy entries by definition
-        * for a SAS, the 2nd one is null
-        */
-       if (smc->s.sas == SMT_DAS) {
-               latency->lt_phyout_idx2 = phy_index(smc,1) ;
-               latency->lt_latency2 = 10 ;     /* in octets (byte clock) */
-       }
-       else {
-               latency->lt_phyout_idx2 = 0 ;
-               latency->lt_latency2 = 0 ;
-       }
-}
-
-/*
- * fill values in MAC neighbors parameter
- */
-static void smt_fill_neighbor(struct s_smc *smc, struct smt_p_neighbor *neighbor)
-{
-       SMTSETPARA(neighbor,SMT_P_NEIGHBORS) ;
-
-       neighbor->nb_mib_index = INDEX_MAC ;
-       neighbor->nb_mac_index = mac_index(smc,1) ;
-       neighbor->nb_una = smc->mib.m[MAC0].fddiMACUpstreamNbr ;
-       neighbor->nb_dna = smc->mib.m[MAC0].fddiMACDownstreamNbr ;
-}
-
-/*
- * fill values in path descriptor
- */
-#ifdef CONCENTRATOR
-#define ALLPHYS        NUMPHYS
-#else
-#define ALLPHYS        ((smc->s.sas == SMT_SAS) ? 1 : 2)
-#endif
-
-static int smt_fill_path(struct s_smc *smc, struct smt_p_path *path)
-{
-       SK_LOC_DECL(int,type) ;
-       SK_LOC_DECL(int,state) ;
-       SK_LOC_DECL(int,remote) ;
-       SK_LOC_DECL(int,mac) ;
-       int     len ;
-       int     p ;
-       int     physp ;
-       struct smt_phy_rec      *phy ;
-       struct smt_mac_rec      *pd_mac ;
-
-       len =   PARA_LEN +
-               sizeof(struct smt_mac_rec) * NUMMACS +
-               sizeof(struct smt_phy_rec) * ALLPHYS ;
-       path->para.p_type = SMT_P_PATH ;
-       path->para.p_len = len - PARA_LEN ;
-
-       /* PHYs */
-       for (p = 0,phy = path->pd_phy ; p < ALLPHYS ; p++, phy++) {
-               physp = p ;
-#ifndef        CONCENTRATOR
-               if (smc->s.sas == SMT_SAS)
-                       physp = PS ;
-#endif
-               pcm_status_state(smc,physp,&type,&state,&remote,&mac) ;
-#ifdef LITTLE_ENDIAN
-               phy->phy_mib_index = smt_swap_short((u_short)p+INDEX_PORT) ;
-#else
-               phy->phy_mib_index = p+INDEX_PORT ;
-#endif
-               phy->phy_type = type ;
-               phy->phy_connect_state = state ;
-               phy->phy_remote_type = remote ;
-               phy->phy_remote_mac = mac ;
-               phy->phy_resource_idx = phy_con_resource_index(smc,p) ;
-       }
-
-       /* MAC */
-       pd_mac = (struct smt_mac_rec *) phy ;
-       pd_mac->mac_addr = smc->mib.m[MAC0].fddiMACSMTAddress ;
-       pd_mac->mac_resource_idx = mac_con_resource_index(smc,1) ;
-       return len;
-}
-
-/*
- * fill values in mac status
- */
-static void smt_fill_mac_status(struct s_smc *smc, struct smt_p_mac_status *st)
-{
-       SMTSETPARA(st,SMT_P_MAC_STATUS) ;
-
-       st->st_mib_index = INDEX_MAC ;
-       st->st_mac_index = mac_index(smc,1) ;
-
-       mac_update_counter(smc) ;
-       /*
-        * timer values are represented in SMT as 2's complement numbers
-        * units :      internal :  2's complement BCLK
-        */
-       st->st_t_req = smc->mib.m[MAC0].fddiMACT_Req ;
-       st->st_t_neg = smc->mib.m[MAC0].fddiMACT_Neg ;
-       st->st_t_max = smc->mib.m[MAC0].fddiMACT_Max ;
-       st->st_tvx_value = smc->mib.m[MAC0].fddiMACTvxValue ;
-       st->st_t_min = smc->mib.m[MAC0].fddiMACT_Min ;
-
-       st->st_sba = smc->mib.a[PATH0].fddiPATHSbaPayload ;
-       st->st_frame_ct = smc->mib.m[MAC0].fddiMACFrame_Ct ;
-       st->st_error_ct = smc->mib.m[MAC0].fddiMACError_Ct ;
-       st->st_lost_ct = smc->mib.m[MAC0].fddiMACLost_Ct ;
-}
-
-/*
- * fill values in LEM status
- */
-static void smt_fill_lem(struct s_smc *smc, struct smt_p_lem *lem, int phy)
-{
-       struct fddi_mib_p       *mib ;
-
-       mib = smc->y[phy].mib ;
-
-       SMTSETPARA(lem,SMT_P_LEM) ;
-       lem->lem_mib_index = phy+INDEX_PORT ;
-       lem->lem_phy_index = phy_index(smc,phy) ;
-       lem->lem_pad2 = 0 ;
-       lem->lem_cutoff = mib->fddiPORTLer_Cutoff ;
-       lem->lem_alarm = mib->fddiPORTLer_Alarm ;
-       /* long term bit error rate */
-       lem->lem_estimate = mib->fddiPORTLer_Estimate ;
-       /* # of rejected connections */
-       lem->lem_reject_ct = mib->fddiPORTLem_Reject_Ct ;
-       lem->lem_ct = mib->fddiPORTLem_Ct ;     /* total number of errors */
-}
-
-/*
- * fill version parameter
- */
-static void smt_fill_version(struct s_smc *smc, struct smt_p_version *vers)
-{
-       SK_UNUSED(smc) ;
-       SMTSETPARA(vers,SMT_P_VERSION) ;
-       vers->v_pad = 0 ;
-       vers->v_n = 1 ;                         /* one version is enough .. */
-       vers->v_index = 1 ;
-       vers->v_version[0] = SMT_VID_2 ;
-       vers->v_pad2 = 0 ;
-}
-
-#ifdef SMT6_10
-/*
- * fill frame status capabilities
- */
-/*
- * note: this para 200B is NOT in swap table, because it's also set in
- * PMF add_para
- */
-static void smt_fill_fsc(struct s_smc *smc, struct smt_p_fsc *fsc)
-{
-       SK_UNUSED(smc) ;
-       SMTSETPARA(fsc,SMT_P_FSC) ;
-       fsc->fsc_pad0 = 0 ;
-       fsc->fsc_mac_index = INDEX_MAC ;        /* this is MIB ; MIB is NOT
-                                                * mac_index ()i !
-                                                */
-       fsc->fsc_pad1 = 0 ;
-       fsc->fsc_value = FSC_TYPE0 ;            /* "normal" node */
-#ifdef LITTLE_ENDIAN
-       fsc->fsc_mac_index = smt_swap_short(INDEX_MAC) ;
-       fsc->fsc_value = smt_swap_short(FSC_TYPE0) ;
-#endif
-}
-#endif
-
-/*
- * fill mac counter field
- */
-static void smt_fill_mac_counter(struct s_smc *smc, struct smt_p_mac_counter *mc)
-{
-       SMTSETPARA(mc,SMT_P_MAC_COUNTER) ;
-       mc->mc_mib_index = INDEX_MAC ;
-       mc->mc_index = mac_index(smc,1) ;
-       mc->mc_receive_ct = smc->mib.m[MAC0].fddiMACCopied_Ct ;
-       mc->mc_transmit_ct =  smc->mib.m[MAC0].fddiMACTransmit_Ct ;
-}
-
-/*
- * fill mac frame not copied counter
- */
-static void smt_fill_mac_fnc(struct s_smc *smc, struct smt_p_mac_fnc *fnc)
-{
-       SMTSETPARA(fnc,SMT_P_MAC_FNC) ;
-       fnc->nc_mib_index = INDEX_MAC ;
-       fnc->nc_index = mac_index(smc,1) ;
-       fnc->nc_counter = smc->mib.m[MAC0].fddiMACNotCopied_Ct ;
-}
-
-
-/*
- * fill manufacturer field
- */
-static void smt_fill_manufacturer(struct s_smc *smc, 
-                                 struct smp_p_manufacturer *man)
-{
-       SMTSETPARA(man,SMT_P_MANUFACTURER) ;
-       memcpy((char *) man->mf_data,
-               (char *) smc->mib.fddiSMTManufacturerData,
-               sizeof(man->mf_data)) ;
-}
-
-/*
- * fill user field
- */
-static void smt_fill_user(struct s_smc *smc, struct smp_p_user *user)
-{
-       SMTSETPARA(user,SMT_P_USER) ;
-       memcpy((char *) user->us_data,
-               (char *) smc->mib.fddiSMTUserData,
-               sizeof(user->us_data)) ;
-}
-
-/*
- * fill set count
- */
-static void smt_fill_setcount(struct s_smc *smc, struct smt_p_setcount *setcount)
-{
-       SK_UNUSED(smc) ;
-       SMTSETPARA(setcount,SMT_P_SETCOUNT) ;
-       setcount->count = smc->mib.fddiSMTSetCount.count ;
-       memcpy((char *)setcount->timestamp,
-               (char *)smc->mib.fddiSMTSetCount.timestamp,8) ;
-}
-
-/*
- * fill echo data
- */
-static void smt_fill_echo(struct s_smc *smc, struct smt_p_echo *echo, u_long seed,
-                         int len)
-{
-       u_char  *p ;
-
-       SK_UNUSED(smc) ;
-       SMTSETPARA(echo,SMT_P_ECHODATA) ;
-       echo->para.p_len = len ;
-       for (p = echo->ec_data ; len ; len--) {
-               *p++ = (u_char) seed ;
-               seed += 13 ;
-       }
-}
-
-/*
- * clear DNA and UNA
- * called from CFM if configuration changes
- */
-static void smt_clear_una_dna(struct s_smc *smc)
-{
-       smc->mib.m[MAC0].fddiMACUpstreamNbr = SMT_Unknown ;
-       smc->mib.m[MAC0].fddiMACDownstreamNbr = SMT_Unknown ;
-}
-
-static void smt_clear_old_una_dna(struct s_smc *smc)
-{
-       smc->mib.m[MAC0].fddiMACOldUpstreamNbr = SMT_Unknown ;
-       smc->mib.m[MAC0].fddiMACOldDownstreamNbr = SMT_Unknown ;
-}
-
-u_long smt_get_tid(struct s_smc *smc)
-{
-       u_long  tid ;
-       while ((tid = ++(smc->sm.smt_tid) ^ SMT_TID_MAGIC) == 0)
-               ;
-       return tid & 0x3fffffffL;
-}
-
-
-/*
- * table of parameter lengths
- */
-static const struct smt_pdef {
-       int     ptype ;
-       int     plen ;
-       const char      *pswap ;
-} smt_pdef[] = {
-       { SMT_P_UNA,    sizeof(struct smt_p_una) ,
-               SWAP_SMT_P_UNA                                  } ,
-       { SMT_P_SDE,    sizeof(struct smt_p_sde) ,
-               SWAP_SMT_P_SDE                                  } ,
-       { SMT_P_STATE,  sizeof(struct smt_p_state) ,
-               SWAP_SMT_P_STATE                                } ,
-       { SMT_P_TIMESTAMP,sizeof(struct smt_p_timestamp) ,
-               SWAP_SMT_P_TIMESTAMP                            } ,
-       { SMT_P_POLICY, sizeof(struct smt_p_policy) ,
-               SWAP_SMT_P_POLICY                               } ,
-       { SMT_P_LATENCY,        sizeof(struct smt_p_latency) ,
-               SWAP_SMT_P_LATENCY                              } ,
-       { SMT_P_NEIGHBORS,sizeof(struct smt_p_neighbor) ,
-               SWAP_SMT_P_NEIGHBORS                            } ,
-       { SMT_P_PATH,   sizeof(struct smt_p_path) ,
-               SWAP_SMT_P_PATH                                 } ,
-       { SMT_P_MAC_STATUS,sizeof(struct smt_p_mac_status) ,
-               SWAP_SMT_P_MAC_STATUS                           } ,
-       { SMT_P_LEM,    sizeof(struct smt_p_lem) ,
-               SWAP_SMT_P_LEM                                  } ,
-       { SMT_P_MAC_COUNTER,sizeof(struct smt_p_mac_counter) ,
-               SWAP_SMT_P_MAC_COUNTER                          } ,
-       { SMT_P_MAC_FNC,sizeof(struct smt_p_mac_fnc) ,
-               SWAP_SMT_P_MAC_FNC                              } ,
-       { SMT_P_PRIORITY,sizeof(struct smt_p_priority) ,
-               SWAP_SMT_P_PRIORITY                             } ,
-       { SMT_P_EB,sizeof(struct smt_p_eb) ,
-               SWAP_SMT_P_EB                                   } ,
-       { SMT_P_MANUFACTURER,sizeof(struct smp_p_manufacturer) ,
-               SWAP_SMT_P_MANUFACTURER                         } ,
-       { SMT_P_REASON, sizeof(struct smt_p_reason) ,
-               SWAP_SMT_P_REASON                               } ,
-       { SMT_P_REFUSED, sizeof(struct smt_p_refused) ,
-               SWAP_SMT_P_REFUSED                              } ,
-       { SMT_P_VERSION, sizeof(struct smt_p_version) ,
-               SWAP_SMT_P_VERSION                              } ,
-#ifdef ESS
-       { SMT_P0015, sizeof(struct smt_p_0015) , SWAP_SMT_P0015 } ,
-       { SMT_P0016, sizeof(struct smt_p_0016) , SWAP_SMT_P0016 } ,
-       { SMT_P0017, sizeof(struct smt_p_0017) , SWAP_SMT_P0017 } ,
-       { SMT_P0018, sizeof(struct smt_p_0018) , SWAP_SMT_P0018 } ,
-       { SMT_P0019, sizeof(struct smt_p_0019) , SWAP_SMT_P0019 } ,
-       { SMT_P001A, sizeof(struct smt_p_001a) , SWAP_SMT_P001A } ,
-       { SMT_P001B, sizeof(struct smt_p_001b) , SWAP_SMT_P001B } ,
-       { SMT_P001C, sizeof(struct smt_p_001c) , SWAP_SMT_P001C } ,
-       { SMT_P001D, sizeof(struct smt_p_001d) , SWAP_SMT_P001D } ,
-#endif
-#if    0
-       { SMT_P_FSC,    sizeof(struct smt_p_fsc) ,
-               SWAP_SMT_P_FSC                                  } ,
-#endif
-
-       { SMT_P_SETCOUNT,0,     SWAP_SMT_P_SETCOUNT             } ,
-       { SMT_P1048,    0,      SWAP_SMT_P1048                  } ,
-       { SMT_P208C,    0,      SWAP_SMT_P208C                  } ,
-       { SMT_P208D,    0,      SWAP_SMT_P208D                  } ,
-       { SMT_P208E,    0,      SWAP_SMT_P208E                  } ,
-       { SMT_P208F,    0,      SWAP_SMT_P208F                  } ,
-       { SMT_P2090,    0,      SWAP_SMT_P2090                  } ,
-#ifdef ESS
-       { SMT_P320B, sizeof(struct smt_p_320b) , SWAP_SMT_P320B } ,
-       { SMT_P320F, sizeof(struct smt_p_320f) , SWAP_SMT_P320F } ,
-       { SMT_P3210, sizeof(struct smt_p_3210) , SWAP_SMT_P3210 } ,
-#endif
-       { SMT_P4050,    0,      SWAP_SMT_P4050                  } ,
-       { SMT_P4051,    0,      SWAP_SMT_P4051                  } ,
-       { SMT_P4052,    0,      SWAP_SMT_P4052                  } ,
-       { SMT_P4053,    0,      SWAP_SMT_P4053                  } ,
-} ;
-
-#define N_SMT_PLEN     ARRAY_SIZE(smt_pdef)
-
-int smt_check_para(struct s_smc *smc, struct smt_header        *sm,
-                  const u_short list[])
-{
-       const u_short           *p = list ;
-       while (*p) {
-               if (!sm_to_para(smc,sm,(int) *p)) {
-                       DB_SMT("SMT: smt_check_para - missing para %x\n",*p,0);
-                       return -1;
-               }
-               p++ ;
-       }
-       return 0;
-}
-
-void *sm_to_para(struct s_smc *smc, struct smt_header *sm, int para)
-{
-       char    *p ;
-       int     len ;
-       int     plen ;
-       void    *found = NULL;
-
-       SK_UNUSED(smc) ;
-
-       len = sm->smt_len ;
-       p = (char *)(sm+1) ;            /* pointer to info */
-       while (len > 0 ) {
-               if (((struct smt_para *)p)->p_type == para)
-                       found = (void *) p ;
-               plen = ((struct smt_para *)p)->p_len + PARA_LEN ;
-               p += plen ;
-               len -= plen ;
-               if (len < 0) {
-                       DB_SMT("SMT : sm_to_para - length error %d\n",plen,0) ;
-                       return NULL;
-               }
-               if ((plen & 3) && (para != SMT_P_ECHODATA)) {
-                       DB_SMT("SMT : sm_to_para - odd length %d\n",plen,0) ;
-                       return NULL;
-               }
-               if (found)
-                       return found;
-       }
-       return NULL;
-}
-
-#if    0
-/*
- * send ANTC data test frame
- */
-void fddi_send_antc(struct s_smc *smc, struct fddi_addr *dest)
-{
-       SK_UNUSED(smc) ;
-       SK_UNUSED(dest) ;
-#if    0
-       SMbuf                   *mb ;
-       struct smt_header       *smt ;
-       int                     i ;
-       char                    *p ;
-
-       mb = smt_get_mbuf() ;
-       mb->sm_len = 3000+12 ;
-       p = smtod(mb, char *) + 12 ;
-       for (i = 0 ; i < 3000 ; i++)
-               *p++ = 1 << (i&7) ;
-
-       smt = smtod(mb, struct smt_header *) ;
-       smt->smt_dest = *dest ;
-       smt->smt_source = smc->mib.m[MAC0].fddiMACSMTAddress ;
-       smt_send_mbuf(smc,mb,FC_ASYNC_LLC) ;
-#endif
-}
-#endif
-
-#ifdef DEBUG
-char *addr_to_string(struct fddi_addr *addr)
-{
-       int     i ;
-       static char     string[6*3] = "****" ;
-
-       for (i = 0 ; i < 6 ; i++) {
-               string[i * 3] = hex_asc_hi(addr->a[i]);
-               string[i * 3 + 1] = hex_asc_lo(addr->a[i]);
-               string[i * 3 + 2] = ':';
-       }
-       string[5 * 3 + 2] = 0;
-       return string;
-}
-#endif
-
-#ifdef AM29K
-int smt_ifconfig(int argc, char *argv[])
-{
-       if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
-           !strcmp(argv[1],"yes")) {
-               smc->mib.fddiSMTBypassPresent = 1 ;
-               return 0;
-       }
-       return amdfddi_config(0, argc, argv);
-}
-#endif
-
-/*
- * return static mac index
- */
-static int mac_index(struct s_smc *smc, int mac)
-{
-       SK_UNUSED(mac) ;
-#ifdef CONCENTRATOR
-       SK_UNUSED(smc) ;
-       return NUMPHYS + 1;
-#else
-       return (smc->s.sas == SMT_SAS) ? 2 : 3;
-#endif
-}
-
-/*
- * return static phy index
- */
-static int phy_index(struct s_smc *smc, int phy)
-{
-       SK_UNUSED(smc) ;
-       return phy + 1;
-}
-
-/*
- * return dynamic mac connection resource index
- */
-static int mac_con_resource_index(struct s_smc *smc, int mac)
-{
-#ifdef CONCENTRATOR
-       SK_UNUSED(smc) ;
-       SK_UNUSED(mac) ;
-       return entity_to_index(smc, cem_get_downstream(smc, ENTITY_MAC));
-#else
-       SK_UNUSED(mac) ;
-       switch (smc->mib.fddiSMTCF_State) {
-       case SC9_C_WRAP_A :
-       case SC5_THRU_B :
-       case SC11_C_WRAP_S :
-               return 1;
-       case SC10_C_WRAP_B :
-       case SC4_THRU_A :
-               return 2;
-       }
-       return smc->s.sas == SMT_SAS ? 2 : 3;
-#endif
-}
-
-/*
- * return dynamic phy connection resource index
- */
-static int phy_con_resource_index(struct s_smc *smc, int phy)
-{
-#ifdef CONCENTRATOR
-       return entity_to_index(smc, cem_get_downstream(smc, ENTITY_PHY(phy))) ;
-#else
-       switch (smc->mib.fddiSMTCF_State) {
-       case SC9_C_WRAP_A :
-               return phy == PA ? 3 : 2;
-       case SC10_C_WRAP_B :
-               return phy == PA ? 1 : 3;
-       case SC4_THRU_A :
-               return phy == PA ? 3 : 1;
-       case SC5_THRU_B :
-               return phy == PA ? 2 : 3;
-       case SC11_C_WRAP_S :
-               return 2;
-       }
-       return phy;
-#endif
-}
-
-#ifdef CONCENTRATOR
-static int entity_to_index(struct s_smc *smc, int e)
-{
-       if (e == ENTITY_MAC)
-               return mac_index(smc, 1);
-       else
-               return phy_index(smc, e - ENTITY_PHY(0));
-}
-#endif
-
-#ifdef LITTLE_ENDIAN
-static int smt_swap_short(u_short s)
-{
-       return ((s>>8)&0xff) | ((s&0xff)<<8);
-}
-
-void smt_swap_para(struct smt_header *sm, int len, int direction)
-/* int direction;      0 encode 1 decode */
-{
-       struct smt_para *pa ;
-       const  struct smt_pdef  *pd ;
-       char    *p ;
-       int     plen ;
-       int     type ;
-       int     i ;
-
-/*     printf("smt_swap_para sm %x len %d dir %d\n",
-               sm,len,direction) ;
- */
-       smt_string_swap((char *)sm,SWAP_SMTHEADER,len) ;
-
-       /* swap args */
-       len -= sizeof(struct smt_header) ;
-
-       p = (char *) (sm + 1) ;
-       while (len > 0) {
-               pa = (struct smt_para *) p ;
-               plen = pa->p_len ;
-               type = pa->p_type ;
-               pa->p_type = smt_swap_short(pa->p_type) ;
-               pa->p_len = smt_swap_short(pa->p_len) ;
-               if (direction) {
-                       plen = pa->p_len ;
-                       type = pa->p_type ;
-               }
-               /*
-                * note: paras can have 0 length !
-                */
-               if (plen < 0)
-                       break ;
-               plen += PARA_LEN ;
-               for (i = N_SMT_PLEN, pd = smt_pdef; i ; i--,pd++) {
-                       if (pd->ptype == type)
-                               break ;
-               }
-               if (i && pd->pswap) {
-                       smt_string_swap(p+PARA_LEN,pd->pswap,len) ;
-               }
-               len -= plen ;
-               p += plen ;
-       }
-}
-
-static void smt_string_swap(char *data, const char *format, int len)
-{
-       const char      *open_paren = NULL ;
-       int     x ;
-
-       while (len > 0  && *format) {
-               switch (*format) {
-               case '[' :
-                       open_paren = format ;
-                       break ;
-               case ']' :
-                       format = open_paren ;
-                       break ;
-               case '1' :
-               case '2' :
-               case '3' :
-               case '4' :
-               case '5' :
-               case '6' :
-               case '7' :
-               case '8' :
-               case '9' :
-                       data  += *format - '0' ;
-                       len   -= *format - '0' ;
-                       break ;
-               case 'c':
-                       data++ ;
-                       len-- ;
-                       break ;
-               case 's' :
-                       x = data[0] ;
-                       data[0] = data[1] ;
-                       data[1] = x ;
-                       data += 2 ;
-                       len -= 2 ;
-                       break ;
-               case 'l' :
-                       x = data[0] ;
-                       data[0] = data[3] ;
-                       data[3] = x ;
-                       x = data[1] ;
-                       data[1] = data[2] ;
-                       data[2] = x ;
-                       data += 4 ;
-                       len -= 4 ;
-                       break ;
-               }
-               format++ ;
-       }
-}
-#else
-void smt_swap_para(struct smt_header *sm, int len, int direction)
-/* int direction;      0 encode 1 decode */
-{
-       SK_UNUSED(sm) ;
-       SK_UNUSED(len) ;
-       SK_UNUSED(direction) ;
-}
-#endif
-
-/*
- * PMF actions
- */
-int smt_action(struct s_smc *smc, int class, int code, int index)
-{
-       int     event ;
-       int     port ;
-       DB_SMT("SMT: action %d code %d\n",class,code) ;
-       switch(class) {
-       case SMT_STATION_ACTION :
-               switch(code) {
-               case SMT_STATION_ACTION_CONNECT :
-                       smc->mib.fddiSMTRemoteDisconnectFlag = FALSE ;
-                       queue_event(smc,EVENT_ECM,EC_CONNECT) ;
-                       break ;
-               case SMT_STATION_ACTION_DISCONNECT :
-                       queue_event(smc,EVENT_ECM,EC_DISCONNECT) ;
-                       smc->mib.fddiSMTRemoteDisconnectFlag = TRUE ;
-                       RS_SET(smc,RS_DISCONNECT) ;
-                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                               FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_DISCONNECT,
-                               smt_get_event_word(smc));
-                       break ;
-               case SMT_STATION_ACTION_PATHTEST :
-                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                               FDDI_SMT_EVENT, (u_long) FDDI_PATH_TEST,
-                               smt_get_event_word(smc));
-                       break ;
-               case SMT_STATION_ACTION_SELFTEST :
-                       AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                               FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_SELF_TEST,
-                               smt_get_event_word(smc));
-                       break ;
-               case SMT_STATION_ACTION_DISABLE_A :
-                       if (smc->y[PA].pc_mode == PM_PEER) {
-                               RS_SET(smc,RS_EVENT) ;
-                               queue_event(smc,EVENT_PCM+PA,PC_DISABLE) ;
-                       }
-                       break ;
-               case SMT_STATION_ACTION_DISABLE_B :
-                       if (smc->y[PB].pc_mode == PM_PEER) {
-                               RS_SET(smc,RS_EVENT) ;
-                               queue_event(smc,EVENT_PCM+PB,PC_DISABLE) ;
-                       }
-                       break ;
-               case SMT_STATION_ACTION_DISABLE_M :
-                       for (port = 0 ; port <  NUMPHYS ; port++) {
-                               if (smc->mib.p[port].fddiPORTMy_Type != TM)
-                                       continue ;
-                               RS_SET(smc,RS_EVENT) ;
-                               queue_event(smc,EVENT_PCM+port,PC_DISABLE) ;
-                       }
-                       break ;
-               default :
-                       return 1;
-               }
-               break ;
-       case SMT_PORT_ACTION :
-               switch(code) {
-               case SMT_PORT_ACTION_ENABLE :
-                       event = PC_ENABLE ;
-                       break ;
-               case SMT_PORT_ACTION_DISABLE :
-                       event = PC_DISABLE ;
-                       break ;
-               case SMT_PORT_ACTION_MAINT :
-                       event = PC_MAINT ;
-                       break ;
-               case SMT_PORT_ACTION_START :
-                       event = PC_START ;
-                       break ;
-               case SMT_PORT_ACTION_STOP :
-                       event = PC_STOP ;
-                       break ;
-               default :
-                       return 1;
-               }
-               queue_event(smc,EVENT_PCM+index,event) ;
-               break ;
-       default :
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * canonical conversion of <len> bytes beginning form *data
- */
-#ifdef  USE_CAN_ADDR
-static void hwm_conv_can(struct s_smc *smc, char *data, int len)
-{
-       int i ;
-
-       SK_UNUSED(smc) ;
-
-       for (i = len; i ; i--, data++)
-               *data = bitrev8(*data);
-}
-#endif
-
-#endif /* no SLIM_SMT */
-
diff --git a/drivers/net/skfp/smtdef.c b/drivers/net/skfp/smtdef.c
deleted file mode 100644 (file)
index 1acab0b..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT/CMT defaults
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#ifndef OEM_USER_DATA
-#define OEM_USER_DATA  "SK-NET FDDI V2.0 Userdata"
-#endif
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)smtdef.c    2.53 99/08/11 (C) SK " ;
-#endif
-
-/*
- * defaults
- */
-#define TTMS(x)        ((u_long)(x)*1000L)
-#define TTS(x) ((u_long)(x)*1000000L)
-#define TTUS(x)        ((u_long)(x))
-
-#define DEFAULT_TB_MIN         TTMS(5)
-#define DEFAULT_TB_MAX         TTMS(50)
-#define DEFAULT_C_MIN          TTUS(1600)
-#define DEFAULT_T_OUT          TTMS(100+5)
-#define DEFAULT_TL_MIN         TTUS(30)
-#define DEFAULT_LC_SHORT       TTMS(50+5)
-#define DEFAULT_LC_MEDIUM      TTMS(500+20)
-#define DEFAULT_LC_LONG                TTS(5)+TTMS(50)
-#define DEFAULT_LC_EXTENDED    TTS(50)+TTMS(50)
-#define DEFAULT_T_NEXT_9       TTMS(200+10)
-#define DEFAULT_NS_MAX         TTUS(1310)
-#define DEFAULT_I_MAX          TTMS(25)
-#define DEFAULT_IN_MAX         TTMS(40)
-#define DEFAULT_TD_MIN         TTMS(5)
-#define DEFAULT_T_NON_OP       TTS(1)
-#define DEFAULT_T_STUCK                TTS(8)
-#define DEFAULT_T_DIRECT       TTMS(370)
-#define DEFAULT_T_JAM          TTMS(370)
-#define DEFAULT_T_ANNOUNCE     TTMS(2500)
-#define DEFAULT_D_MAX          TTUS(1617)
-#define DEFAULT_LEM_ALARM      (8)
-#define DEFAULT_LEM_CUTOFF     (7)
-#define DEFAULT_TEST_DONE      TTS(1)
-#define DEFAULT_CHECK_POLL     TTS(1)
-#define DEFAULT_POLL           TTMS(50)
-
-/*
- * LCT errors threshold
- */
-#define DEFAULT_LCT_SHORT      1
-#define DEFAULT_LCT_MEDIUM     3
-#define DEFAULT_LCT_LONG       5
-#define DEFAULT_LCT_EXTEND     50
-
-/* Forward declarations */
-void smt_reset_defaults(struct s_smc *smc, int level);
-static void smt_init_mib(struct s_smc *smc, int level);
-static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper);
-
-#define MS2BCLK(x)     ((x)*12500L)
-#define US2BCLK(x)     ((x)*1250L)
-
-void smt_reset_defaults(struct s_smc *smc, int level)
-{
-       struct smt_config       *smt ;
-       int                     i ;
-       u_long                  smt_boot_time;
-
-
-       smt_init_mib(smc,level) ;
-
-       smc->os.smc_version = SMC_VERSION ;
-       smt_boot_time = smt_get_time();
-       for( i = 0; i < NUMMACS; i++ )
-               smc->sm.last_tok_time[i] = smt_boot_time ;
-       smt = &smc->s ;
-       smt->attach_s = 0 ;
-       smt->build_ring_map = 1 ;
-       smt->sas = SMT_DAS ;
-       smt->numphys = NUMPHYS ;
-       smt->pcm_tb_min = DEFAULT_TB_MIN ;
-       smt->pcm_tb_max = DEFAULT_TB_MAX ;
-       smt->pcm_c_min = DEFAULT_C_MIN ;
-       smt->pcm_t_out = DEFAULT_T_OUT ;
-       smt->pcm_tl_min = DEFAULT_TL_MIN ;
-       smt->pcm_lc_short = DEFAULT_LC_SHORT ;
-       smt->pcm_lc_medium = DEFAULT_LC_MEDIUM ;
-       smt->pcm_lc_long = DEFAULT_LC_LONG ;
-       smt->pcm_lc_extended = DEFAULT_LC_EXTENDED ;
-       smt->pcm_t_next_9 = DEFAULT_T_NEXT_9 ;
-       smt->pcm_ns_max = DEFAULT_NS_MAX ;
-       smt->ecm_i_max = DEFAULT_I_MAX ;
-       smt->ecm_in_max = DEFAULT_IN_MAX ;
-       smt->ecm_td_min = DEFAULT_TD_MIN ;
-       smt->ecm_test_done = DEFAULT_TEST_DONE ;
-       smt->ecm_check_poll = DEFAULT_CHECK_POLL ;
-       smt->rmt_t_non_op = DEFAULT_T_NON_OP ;
-       smt->rmt_t_stuck = DEFAULT_T_STUCK ;
-       smt->rmt_t_direct = DEFAULT_T_DIRECT ;
-       smt->rmt_t_jam = DEFAULT_T_JAM ;
-       smt->rmt_t_announce = DEFAULT_T_ANNOUNCE ;
-       smt->rmt_t_poll = DEFAULT_POLL ;
-        smt->rmt_dup_mac_behavior = FALSE ;  /* See Struct smt_config */
-       smt->mac_d_max = DEFAULT_D_MAX ;
-
-       smt->lct_short = DEFAULT_LCT_SHORT ;
-       smt->lct_medium = DEFAULT_LCT_MEDIUM ;
-       smt->lct_long = DEFAULT_LCT_LONG ;
-       smt->lct_extended = DEFAULT_LCT_EXTEND ;
-
-#ifndef        SLIM_SMT
-#ifdef ESS
-       if (level == 0) {
-               smc->ess.sync_bw_available = FALSE ;
-               smc->mib.fddiESSPayload = 0 ;
-               smc->mib.fddiESSOverhead = 0 ;
-               smc->mib.fddiESSMaxTNeg = (u_long)(- MS2BCLK(25)) ;
-               smc->mib.fddiESSMinSegmentSize = 1 ;
-               smc->mib.fddiESSCategory = SB_STATIC ;
-               smc->mib.fddiESSSynchTxMode = FALSE ;
-               smc->ess.raf_act_timer_poll = FALSE ;
-               smc->ess.timer_count = 7 ;      /* first RAF alc req after 3s */
-       }
-       smc->ess.local_sba_active = FALSE ;
-       smc->ess.sba_reply_pend = NULL ;
-#endif
-#ifdef SBA
-       smt_init_sba(smc,level) ;
-#endif
-#endif /* no SLIM_SMT */
-#ifdef TAG_MODE
-       if (level == 0) {
-               smc->hw.pci_fix_value = 0 ;
-       }
-#endif
-}
-
-/*
- * manufacturer data
- */
-static const char man_data[32] =
-/*      01234567890123456789012345678901       */
-       "xxxSK-NET FDDI SMT 7.3 - V2.8.8" ;
-
-static void smt_init_mib(struct s_smc *smc, int level)
-{
-       struct fddi_mib         *mib ;
-       struct fddi_mib_p       *pm ;
-       int                     port ;
-       int                     path ;
-
-       mib = &smc->mib ;
-       if (level == 0) {
-               /*
-                * set EVERYTHING to ZERO
-                * EXCEPT hw and os
-                */
-               memset(((char *)smc)+
-                       sizeof(struct s_smt_os)+sizeof(struct s_smt_hw), 0,
-                       sizeof(struct s_smc) -
-                       sizeof(struct s_smt_os) - sizeof(struct s_smt_hw)) ;
-       }
-       else {
-               mib->fddiSMTRemoteDisconnectFlag = 0 ;
-               mib->fddiSMTPeerWrapFlag = 0 ;
-       }
-
-       mib->fddiSMTOpVersionId = 2 ;
-       mib->fddiSMTHiVersionId = 2 ;
-       mib->fddiSMTLoVersionId = 2 ;
-       memcpy((char *) mib->fddiSMTManufacturerData,man_data,32) ;
-       if (level == 0) {
-               strcpy(mib->fddiSMTUserData,OEM_USER_DATA) ;
-       }
-       mib->fddiSMTMIBVersionId = 1 ;
-       mib->fddiSMTMac_Ct = NUMMACS ;
-       mib->fddiSMTConnectionPolicy = POLICY_MM | POLICY_AA | POLICY_BB ;
-
-       /*
-        * fddiSMTNonMaster_Ct and fddiSMTMaster_Ct are set in smt_fixup_mib
-        * s.sas is not set yet (is set in init driver)
-        */
-       mib->fddiSMTAvailablePaths = MIB_PATH_P | MIB_PATH_S ;
-
-       mib->fddiSMTConfigCapabilities = 0 ;    /* no hold,no wrap_ab*/
-       mib->fddiSMTTT_Notify = 10 ;
-       mib->fddiSMTStatRptPolicy = TRUE ;
-       mib->fddiSMTTrace_MaxExpiration = SEC2MIB(7) ;
-       mib->fddiSMTMACIndexes = INDEX_MAC ;
-       mib->fddiSMTStationStatus = MIB_SMT_STASTA_SEPA ;       /* separated */
-
-       mib->m[MAC0].fddiMACIndex = INDEX_MAC ;
-       mib->m[MAC0].fddiMACFrameStatusFunctions = FSC_TYPE0 ;
-       mib->m[MAC0].fddiMACRequestedPaths =
-               MIB_P_PATH_LOCAL |
-               MIB_P_PATH_SEC_ALTER |
-               MIB_P_PATH_PRIM_ALTER ;
-       mib->m[MAC0].fddiMACAvailablePaths = MIB_PATH_P ;
-       mib->m[MAC0].fddiMACCurrentPath = MIB_PATH_PRIMARY ;
-       mib->m[MAC0].fddiMACT_MaxCapabilitiy = (u_long)(- MS2BCLK(165)) ;
-       mib->m[MAC0].fddiMACTVXCapabilitiy = (u_long)(- US2BCLK(52)) ;
-       if (level == 0) {
-               mib->m[MAC0].fddiMACTvxValue = (u_long)(- US2BCLK(27)) ;
-               mib->m[MAC0].fddiMACTvxValueMIB = (u_long)(- US2BCLK(27)) ;
-               mib->m[MAC0].fddiMACT_Req = (u_long)(- MS2BCLK(165)) ;
-               mib->m[MAC0].fddiMACT_ReqMIB = (u_long)(- MS2BCLK(165)) ;
-               mib->m[MAC0].fddiMACT_Max = (u_long)(- MS2BCLK(165)) ;
-               mib->m[MAC0].fddiMACT_MaxMIB = (u_long)(- MS2BCLK(165)) ;
-               mib->m[MAC0].fddiMACT_Min = (u_long)(- MS2BCLK(4)) ;
-       }
-       mib->m[MAC0].fddiMACHardwarePresent = TRUE ;
-       mib->m[MAC0].fddiMACMA_UnitdataEnable = TRUE ;
-       mib->m[MAC0].fddiMACFrameErrorThreshold = 1 ;
-       mib->m[MAC0].fddiMACNotCopiedThreshold = 1 ;
-       /*
-        * Path attributes
-        */
-       for (path = 0 ; path < NUMPATHS ; path++) {
-               mib->a[path].fddiPATHIndex = INDEX_PATH + path ;
-               if (level == 0) {
-                       mib->a[path].fddiPATHTVXLowerBound =
-                               (u_long)(- US2BCLK(27)) ;
-                       mib->a[path].fddiPATHT_MaxLowerBound =
-                               (u_long)(- MS2BCLK(165)) ;
-                       mib->a[path].fddiPATHMaxT_Req =
-                               (u_long)(- MS2BCLK(165)) ;
-               }
-       }
-
-
-       /*
-        * Port attributes
-        */
-       pm = mib->p ;
-       for (port = 0 ; port <  NUMPHYS ; port++) {
-               /*
-                * set MIB pointer in phy
-                */
-               /* Attention: don't initialize mib pointer here! */
-               /*  It must be initialized during phase 2 */
-               smc->y[port].mib = NULL;
-               mib->fddiSMTPORTIndexes[port] = port+INDEX_PORT ;
-
-               pm->fddiPORTIndex = port+INDEX_PORT ;
-               pm->fddiPORTHardwarePresent = TRUE ;
-               if (level == 0) {
-                       pm->fddiPORTLer_Alarm = DEFAULT_LEM_ALARM ;
-                       pm->fddiPORTLer_Cutoff = DEFAULT_LEM_CUTOFF ;
-               }
-               /*
-                * fddiPORTRequestedPaths are set in pcmplc.c
-                * we don't know the port type yet !
-                */
-               pm->fddiPORTRequestedPaths[1] = 0 ;
-               pm->fddiPORTRequestedPaths[2] = 0 ;
-               pm->fddiPORTRequestedPaths[3] = 0 ;
-               pm->fddiPORTAvailablePaths = MIB_PATH_P ;
-               pm->fddiPORTPMDClass = MIB_PMDCLASS_MULTI ;
-               pm++ ;
-       }
-
-       (void) smt_set_mac_opvalues(smc) ;
-}
-
-int smt_set_mac_opvalues(struct s_smc *smc)
-{
-       int     st ;
-       int     st2 ;
-
-       st = set_min_max(1,smc->mib.m[MAC0].fddiMACTvxValueMIB,
-               smc->mib.a[PATH0].fddiPATHTVXLowerBound,
-               &smc->mib.m[MAC0].fddiMACTvxValue) ;
-       st |= set_min_max(0,smc->mib.m[MAC0].fddiMACT_MaxMIB,
-               smc->mib.a[PATH0].fddiPATHT_MaxLowerBound,
-               &smc->mib.m[MAC0].fddiMACT_Max) ;
-       st |= (st2 = set_min_max(0,smc->mib.m[MAC0].fddiMACT_ReqMIB,
-               smc->mib.a[PATH0].fddiPATHMaxT_Req,
-               &smc->mib.m[MAC0].fddiMACT_Req)) ;
-       if (st2) {
-               /* Treq attribute changed remotely. So send an AIX_EVENT to the
-                * user
-                */
-               AIX_EVENT(smc, (u_long) FDDI_RING_STATUS, (u_long)
-                       FDDI_SMT_EVENT, (u_long) FDDI_REMOTE_T_REQ,
-                       smt_get_event_word(smc));
-       }
-       return st;
-}
-
-void smt_fixup_mib(struct s_smc *smc)
-{
-#ifdef CONCENTRATOR
-       switch (smc->s.sas) {
-       case SMT_SAS :
-               smc->mib.fddiSMTNonMaster_Ct = 1 ;
-               break ;
-       case SMT_DAS :
-               smc->mib.fddiSMTNonMaster_Ct = 2 ;
-               break ;
-       case SMT_NAC :
-               smc->mib.fddiSMTNonMaster_Ct = 0 ;
-               break ;
-       }
-       smc->mib.fddiSMTMaster_Ct = NUMPHYS - smc->mib.fddiSMTNonMaster_Ct ;
-#else
-       switch (smc->s.sas) {
-       case SMT_SAS :
-               smc->mib.fddiSMTNonMaster_Ct = 1 ;
-               break ;
-       case SMT_DAS :
-               smc->mib.fddiSMTNonMaster_Ct = 2 ;
-               break ;
-       }
-       smc->mib.fddiSMTMaster_Ct = 0 ;
-#endif
-}
-
-/*
- * determine new setting for operational value
- * if limit is lower than mib
- *     use limit
- * else
- *     use mib
- * NOTE : numbers are negative, negate comparison !
- */
-static int set_min_max(int maxflag, u_long mib, u_long limit, u_long *oper)
-{
-       u_long  old ;
-       old = *oper ;
-       if ((limit > mib) ^ maxflag)
-               *oper = limit ;
-       else
-               *oper = mib ;
-       return old != *oper;
-}
-
diff --git a/drivers/net/skfp/smtinit.c b/drivers/net/skfp/smtinit.c
deleted file mode 100644 (file)
index e3a0c0b..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       Init SMT
-       call all module level initialization routines
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)smtinit.c   1.15 97/05/06 (C) SK " ;
-#endif
-
-void init_fddi_driver(struct s_smc *smc, u_char *mac_addr);
-
-/* define global debug variable */
-#if defined(DEBUG) && !defined(DEBUG_BRD)
-struct smt_debug debug;
-#endif
-
-#ifndef MULT_OEM
-#define OEMID(smc,i)   oem_id[i]
-       extern u_char   oem_id[] ;
-#else  /* MULT_OEM */
-#define OEMID(smc,i)   smc->hw.oem_id->oi_mark[i]
-       extern struct s_oem_ids oem_ids[] ;
-#endif /* MULT_OEM */
-
-/*
- * Set OEM specific values
- *
- * Can not be called in smt_reset_defaults, because it is not sure that
- * the OEM ID is already defined.
- */
-static void set_oem_spec_val(struct s_smc *smc)
-{
-       struct fddi_mib *mib ;
-
-       mib = &smc->mib ;
-
-       /*
-        * set IBM specific values
-        */
-       if (OEMID(smc,0) == 'I') {
-               mib->fddiSMTConnectionPolicy = POLICY_MM ;
-       }
-}
-
-/*
- * Init SMT
- */
-int init_smt(struct s_smc *smc, u_char *mac_addr)
-/* u_char *mac_addr;   canonical address or NULL */
-{
-       int     p ;
-
-#if defined(DEBUG) && !defined(DEBUG_BRD)
-       debug.d_smt = 0 ;
-       debug.d_smtf = 0 ;
-       debug.d_rmt = 0 ;
-       debug.d_ecm = 0 ;
-       debug.d_pcm = 0 ;
-       debug.d_cfm = 0 ;
-
-       debug.d_plc = 0 ;
-#ifdef ESS
-       debug.d_ess = 0 ;
-#endif
-#ifdef SBA
-       debug.d_sba = 0 ;
-#endif
-#endif /* DEBUG && !DEBUG_BRD */
-
-       /* First initialize the ports mib->pointers */
-       for ( p = 0; p < NUMPHYS; p ++ ) {
-               smc->y[p].mib = & smc->mib.p[p] ;
-       }
-
-       set_oem_spec_val(smc) ; 
-       (void) smt_set_mac_opvalues(smc) ;
-       init_fddi_driver(smc,mac_addr) ;        /* HW driver */
-       smt_fixup_mib(smc) ;            /* update values that depend on s.sas */
-
-       ev_init(smc) ;                  /* event queue */
-#ifndef        SLIM_SMT
-       smt_init_evc(smc) ;             /* evcs in MIB */
-#endif /* no SLIM_SMT */
-       smt_timer_init(smc) ;           /* timer package */
-       smt_agent_init(smc) ;           /* SMT frame manager */
-
-       pcm_init(smc) ;                 /* PCM state machine */
-       ecm_init(smc) ;                 /* ECM state machine */
-       cfm_init(smc) ;                 /* CFM state machine */
-       rmt_init(smc) ;                 /* RMT state machine */
-
-       for (p = 0 ; p < NUMPHYS ; p++) {
-               pcm(smc,p,0) ;          /* PCM A state machine */
-       }
-       ecm(smc,0) ;                    /* ECM state machine */
-       cfm(smc,0) ;                    /* CFM state machine */
-       rmt(smc,0) ;                    /* RMT state machine */
-
-       smt_agent_task(smc) ;           /* NIF FSM etc */
-
-        PNMI_INIT(smc) ;                /* PNMI initialization */
-
-       return 0;
-}
-
diff --git a/drivers/net/skfp/smttimer.c b/drivers/net/skfp/smttimer.c
deleted file mode 100644 (file)
index 531795e..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT timer
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)smttimer.c  2.4 97/08/04 (C) SK " ;
-#endif
-
-static void timer_done(struct s_smc *smc, int restart);
-
-void smt_timer_init(struct s_smc *smc)
-{
-       smc->t.st_queue = NULL;
-       smc->t.st_fast.tm_active = FALSE ;
-       smc->t.st_fast.tm_next = NULL;
-       hwt_init(smc) ;
-}
-
-void smt_timer_stop(struct s_smc *smc, struct smt_timer *timer)
-{
-       struct smt_timer        **prev ;
-       struct smt_timer        *tm ;
-
-       /*
-        * remove timer from queue
-        */
-       timer->tm_active = FALSE ;
-       if (smc->t.st_queue == timer && !timer->tm_next) {
-               hwt_stop(smc) ;
-       }
-       for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
-               if (tm == timer) {
-                       *prev = tm->tm_next ;
-                       if (tm->tm_next) {
-                               tm->tm_next->tm_delta += tm->tm_delta ;
-                       }
-                       return ;
-               }
-       }
-}
-
-void smt_timer_start(struct s_smc *smc, struct smt_timer *timer, u_long time,
-                    u_long token)
-{
-       struct smt_timer        **prev ;
-       struct smt_timer        *tm ;
-       u_long                  delta = 0 ;
-
-       time /= 16 ;            /* input is uS, clock ticks are 16uS */
-       if (!time)
-               time = 1 ;
-       smt_timer_stop(smc,timer) ;
-       timer->tm_smc = smc ;
-       timer->tm_token = token ;
-       timer->tm_active = TRUE ;
-       if (!smc->t.st_queue) {
-               smc->t.st_queue = timer ;
-               timer->tm_next = NULL;
-               timer->tm_delta = time ;
-               hwt_start(smc,time) ;
-               return ;
-       }
-       /*
-        * timer correction
-        */
-       timer_done(smc,0) ;
-
-       /*
-        * find position in queue
-        */
-       delta = 0 ;
-       for (prev = &smc->t.st_queue ; (tm = *prev) ; prev = &tm->tm_next ) {
-               if (delta + tm->tm_delta > time) {
-                       break ;
-               }
-               delta += tm->tm_delta ;
-       }
-       /* insert in queue */
-       *prev = timer ;
-       timer->tm_next = tm ;
-       timer->tm_delta = time - delta ;
-       if (tm)
-               tm->tm_delta -= timer->tm_delta ;
-       /*
-        * start new with first
-        */
-       hwt_start(smc,smc->t.st_queue->tm_delta) ;
-}
-
-void smt_force_irq(struct s_smc *smc)
-{
-       smt_timer_start(smc,&smc->t.st_fast,32L, EV_TOKEN(EVENT_SMT,SM_FAST)); 
-}
-
-void smt_timer_done(struct s_smc *smc)
-{
-       timer_done(smc,1) ;
-}
-
-static void timer_done(struct s_smc *smc, int restart)
-{
-       u_long                  delta ;
-       struct smt_timer        *tm ;
-       struct smt_timer        *next ;
-       struct smt_timer        **last ;
-       int                     done = 0 ;
-
-       delta = hwt_read(smc) ;
-       last = &smc->t.st_queue ;
-       tm = smc->t.st_queue ;
-       while (tm && !done) {
-               if (delta >= tm->tm_delta) {
-                       tm->tm_active = FALSE ;
-                       delta -= tm->tm_delta ;
-                       last = &tm->tm_next ;
-                       tm = tm->tm_next ;
-               }
-               else {
-                       tm->tm_delta -= delta ;
-                       delta = 0 ;
-                       done = 1 ;
-               }
-       }
-       *last = NULL;
-       next = smc->t.st_queue ;
-       smc->t.st_queue = tm ;
-
-       for ( tm = next ; tm ; tm = next) {
-               next = tm->tm_next ;
-               timer_event(smc,tm->tm_token) ;
-       }
-
-       if (restart && smc->t.st_queue)
-               hwt_start(smc,smc->t.st_queue->tm_delta) ;
-}
-
diff --git a/drivers/net/skfp/srf.c b/drivers/net/skfp/srf.c
deleted file mode 100644 (file)
index f6f7baf..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-/******************************************************************************
- *
- *     (C)Copyright 1998,1999 SysKonnect,
- *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *     See the file "skfddi.c" for further information.
- *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-       SMT 7.2 Status Response Frame Implementation
-       SRF state machine and frame generation
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/smt_p.h"
-
-#define KERNEL
-#include "h/smtstate.h"
-
-#ifndef        SLIM_SMT
-#ifndef        BOOT
-
-#ifndef        lint
-static const char ID_sccs[] = "@(#)srf.c       1.18 97/08/04 (C) SK " ;
-#endif
-
-
-/*
- * function declarations
- */
-static void clear_all_rep(struct s_smc *smc);
-static void clear_reported(struct s_smc *smc);
-static void smt_send_srf(struct s_smc *smc);
-static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
-
-#define MAX_EVCS       ARRAY_SIZE(smc->evcs)
-
-struct evc_init {
-       u_char code ;
-       u_char index ;
-       u_char n ;
-       u_short para ;
-}  ;
-
-static const struct evc_init evc_inits[] = {
-       { SMT_COND_SMT_PEER_WRAP,               0,1,SMT_P1048   } ,
-
-       { SMT_COND_MAC_DUP_ADDR,                INDEX_MAC, NUMMACS,SMT_P208C } ,
-       { SMT_COND_MAC_FRAME_ERROR,             INDEX_MAC, NUMMACS,SMT_P208D } ,
-       { SMT_COND_MAC_NOT_COPIED,              INDEX_MAC, NUMMACS,SMT_P208E } ,
-       { SMT_EVENT_MAC_NEIGHBOR_CHANGE,        INDEX_MAC, NUMMACS,SMT_P208F } ,
-       { SMT_EVENT_MAC_PATH_CHANGE,            INDEX_MAC, NUMMACS,SMT_P2090 } ,
-
-       { SMT_COND_PORT_LER,                    INDEX_PORT,NUMPHYS,SMT_P4050 } ,
-       { SMT_COND_PORT_EB_ERROR,               INDEX_PORT,NUMPHYS,SMT_P4052 } ,
-       { SMT_EVENT_PORT_CONNECTION,            INDEX_PORT,NUMPHYS,SMT_P4051 } ,
-       { SMT_EVENT_PORT_PATH_CHANGE,           INDEX_PORT,NUMPHYS,SMT_P4053 } ,
-} ;
-
-#define MAX_INIT_EVC   ARRAY_SIZE(evc_inits)
-
-void smt_init_evc(struct s_smc *smc)
-{
-       struct s_srf_evc        *evc ;
-       const struct evc_init   *init ;
-       int                     i ;
-       int                     index ;
-       int                     offset ;
-
-       static u_char           fail_safe = FALSE ;
-
-       memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
-
-       evc = smc->evcs ;
-       init = evc_inits ;
-
-       for (i = 0 ; (unsigned) i < MAX_INIT_EVC ; i++) {
-               for (index = 0 ; index < init->n ; index++) {
-                       evc->evc_code = init->code ;
-                       evc->evc_para = init->para ;
-                       evc->evc_index = init->index + index ;
-#ifndef        DEBUG
-                       evc->evc_multiple = &fail_safe ;
-                       evc->evc_cond_state = &fail_safe ;
-#endif
-                       evc++ ;
-               }
-               init++ ;
-       }
-
-       if ((unsigned) (evc - smc->evcs) > MAX_EVCS) {
-               SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
-       }
-
-       /*
-        * conditions
-        */
-       smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
-       smc->evcs[1].evc_cond_state =
-               &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
-       smc->evcs[2].evc_cond_state =
-               &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
-       smc->evcs[3].evc_cond_state =
-               &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
-
-       /*
-        * events
-        */
-       smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
-       smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
-
-       offset = 6 ;
-       for (i = 0 ; i < NUMPHYS ; i++) {
-               /*
-                * conditions
-                */
-               smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
-                       &smc->mib.p[i].fddiPORTLerFlag ;
-               smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
-                       &smc->mib.p[i].fddiPORTEB_Condition ;
-
-               /*
-                * events
-                */
-               smc->evcs[offset + 2*NUMPHYS].evc_multiple =
-                       &smc->mib.p[i].fddiPORTMultiple_U ;
-               smc->evcs[offset + 3*NUMPHYS].evc_multiple =
-                       &smc->mib.p[i].fddiPORTMultiple_P ;
-               offset++ ;
-       }
-#ifdef DEBUG
-       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
-               if (SMT_IS_CONDITION(evc->evc_code)) {
-                       if (!evc->evc_cond_state) {
-                               SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
-                       }
-                       evc->evc_multiple = &fail_safe ;
-               }
-               else {
-                       if (!evc->evc_multiple) {
-                               SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
-                       }
-                       evc->evc_cond_state = &fail_safe ;
-               }
-       }
-#endif
-       smc->srf.TSR = smt_get_time() ;
-       smc->srf.sr_state = SR0_WAIT ;
-}
-
-static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
-{
-       int                     i ;
-       struct s_srf_evc        *evc ;
-
-       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
-               if (evc->evc_code == code && evc->evc_index == index)
-                       return evc;
-       }
-       return NULL;
-}
-
-#define THRESHOLD_2    (2*TICKS_PER_SECOND)
-#define THRESHOLD_32   (32*TICKS_PER_SECOND)
-
-#ifdef DEBUG
-static const char * const srf_names[] = {
-       "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
-       "PORTPathChangeEvent",          "PORTUndesiredConnectionAttemptEvent",
-       "SMTPeerWrapCondition",         "SMTHoldCondition",
-       "MACFrameErrorCondition",       "MACDuplicateAddressCondition",
-       "MACNotCopiedCondition",        "PORTEBErrorCondition",
-       "PORTLerCondition"
-} ;
-#endif
-
-void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
-{
-       struct s_srf_evc        *evc ;
-       int                     cond_asserted = 0 ;
-       int                     cond_deasserted = 0 ;
-       int                     event_occurred = 0 ;
-       int                     tsr ;
-       int                     T_Limit = 2*TICKS_PER_SECOND ;
-
-       if (code == SMT_COND_MAC_DUP_ADDR && cond) {
-               RS_SET(smc,RS_DUPADDR) ;
-       }
-
-       if (code) {
-               DB_SMT("SRF: %s index %d\n",srf_names[code],index) ;
-
-               if (!(evc = smt_get_evc(smc,code,index))) {
-                       DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
-                       return ;
-               }
-               /*
-                * ignore condition if no change
-                */
-               if (SMT_IS_CONDITION(code)) {
-                       if (*evc->evc_cond_state == cond)
-                               return ;
-               }
-
-               /*
-                * set transition time stamp
-                */
-               smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
-               if (SMT_IS_CONDITION(code)) {
-                       DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ;
-                       if (cond) {
-                               *evc->evc_cond_state = TRUE ;
-                               evc->evc_rep_required = TRUE ;
-                               smc->srf.any_report = TRUE ;
-                               cond_asserted = TRUE ;
-                       }
-                       else {
-                               *evc->evc_cond_state = FALSE ;
-                               cond_deasserted = TRUE ;
-                       }
-               }
-               else {
-                       if (evc->evc_rep_required) {
-                               *evc->evc_multiple  = TRUE ;
-                       }
-                       else {
-                               evc->evc_rep_required = TRUE ;
-                               *evc->evc_multiple  = FALSE ;
-                       }
-                       smc->srf.any_report = TRUE ;
-                       event_occurred = TRUE ;
-               }
-#ifdef FDDI_MIB
-               snmp_srf_event(smc,evc) ;
-#endif /* FDDI_MIB */
-       }
-       tsr = smt_get_time() - smc->srf.TSR ;
-
-       switch (smc->srf.sr_state) {
-       case SR0_WAIT :
-               /* SR01a */
-               if (cond_asserted && tsr < T_Limit) {
-                       smc->srf.SRThreshold = THRESHOLD_2 ;
-                       smc->srf.sr_state = SR1_HOLDOFF ;
-                       break ;
-               }
-               /* SR01b */
-               if (cond_deasserted && tsr < T_Limit) {
-                       smc->srf.sr_state = SR1_HOLDOFF ;
-                       break ;
-               }
-               /* SR01c */
-               if (event_occurred && tsr < T_Limit) {
-                       smc->srf.sr_state = SR1_HOLDOFF ;
-                       break ;
-               }
-               /* SR00b */
-               if (cond_asserted && tsr >= T_Limit) {
-                       smc->srf.SRThreshold = THRESHOLD_2 ;
-                       smc->srf.TSR = smt_get_time() ;
-                       smt_send_srf(smc) ;
-                       break ;
-               }
-               /* SR00c */
-               if (cond_deasserted && tsr >= T_Limit) {
-                       smc->srf.TSR = smt_get_time() ;
-                       smt_send_srf(smc) ;
-                       break ;
-               }
-               /* SR00d */
-               if (event_occurred && tsr >= T_Limit) {
-                       smc->srf.TSR = smt_get_time() ;
-                       smt_send_srf(smc) ;
-                       break ;
-               }
-               /* SR00e */
-               if (smc->srf.any_report && (u_long) tsr >=
-                       smc->srf.SRThreshold) {
-                       smc->srf.SRThreshold *= 2 ;
-                       if (smc->srf.SRThreshold > THRESHOLD_32)
-                               smc->srf.SRThreshold = THRESHOLD_32 ;
-                       smc->srf.TSR = smt_get_time() ;
-                       smt_send_srf(smc) ;
-                       break ;
-               }
-               /* SR02 */
-               if (!smc->mib.fddiSMTStatRptPolicy) {
-                       smc->srf.sr_state = SR2_DISABLED ;
-                       break ;
-               }
-               break ;
-       case SR1_HOLDOFF :
-               /* SR10b */
-               if (tsr >= T_Limit) {
-                       smc->srf.sr_state = SR0_WAIT ;
-                       smc->srf.TSR = smt_get_time() ;
-                       smt_send_srf(smc) ;
-                       break ;
-               }
-               /* SR11a */
-               if (cond_asserted) {
-                       smc->srf.SRThreshold = THRESHOLD_2 ;
-               }
-               /* SR11b */
-               /* SR11c */
-               /* handled above */
-               /* SR12 */
-               if (!smc->mib.fddiSMTStatRptPolicy) {
-                       smc->srf.sr_state = SR2_DISABLED ;
-                       break ;
-               }
-               break ;
-       case SR2_DISABLED :
-               if (smc->mib.fddiSMTStatRptPolicy) {
-                       smc->srf.sr_state = SR0_WAIT ;
-                       smc->srf.TSR = smt_get_time() ;
-                       smc->srf.SRThreshold = THRESHOLD_2 ;
-                       clear_all_rep(smc) ;
-                       break ;
-               }
-               break ;
-       }
-}
-
-static void clear_all_rep(struct s_smc *smc)
-{
-       struct s_srf_evc        *evc ;
-       int                     i ;
-
-       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
-               evc->evc_rep_required = FALSE ;
-               if (SMT_IS_CONDITION(evc->evc_code))
-                       *evc->evc_cond_state = FALSE ;
-       }
-       smc->srf.any_report = FALSE ;
-}
-
-static void clear_reported(struct s_smc *smc)
-{
-       struct s_srf_evc        *evc ;
-       int                     i ;
-
-       smc->srf.any_report = FALSE ;
-       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
-               if (SMT_IS_CONDITION(evc->evc_code)) {
-                       if (*evc->evc_cond_state == FALSE)
-                               evc->evc_rep_required = FALSE ;
-                       else
-                               smc->srf.any_report = TRUE ;
-               }
-               else {
-                       evc->evc_rep_required = FALSE ;
-                       *evc->evc_multiple = FALSE ;
-               }
-       }
-}
-
-/*
- * build and send SMT SRF frame
- */
-static void smt_send_srf(struct s_smc *smc)
-{
-
-       struct smt_header       *smt ;
-       struct s_srf_evc        *evc ;
-       SK_LOC_DECL(struct s_pcon,pcon) ;
-       SMbuf                   *mb ;
-       int                     i ;
-
-       static const struct fddi_addr SMT_SRF_DA = {
-               { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
-       } ;
-
-       /*
-        * build SMT header
-        */
-       if (!smc->r.sm_ma_avail)
-               return ;
-       if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
-               return ;
-
-       RS_SET(smc,RS_SOFTERROR) ;
-
-       smt = smtod(mb, struct smt_header *) ;
-       smt->smt_dest = SMT_SRF_DA ;            /* DA == SRF multicast */
-
-       /*
-        * setup parameter status
-        */
-       pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
-       pcon.pc_err = 0 ;                       /* no error */
-       pcon.pc_badset = 0 ;                    /* no bad set count */
-       pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
-
-       smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
-       smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
-
-       for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
-               if (evc->evc_rep_required) {
-                       smt_add_para(smc,&pcon,evc->evc_para,
-                               (int)evc->evc_index,0) ;
-               }
-       }
-       smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
-       mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
-
-       DB_SMT("SRF: sending SRF at %x, len %d\n",smt,mb->sm_len) ;
-       DB_SMT("SRF: state SR%d Threshold %d\n",
-               smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ;
-#ifdef DEBUG
-       dump_smt(smc,smt,"SRF Send") ;
-#endif
-       smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
-       clear_reported(smc) ;
-}
-
-#endif /* no BOOT */
-#endif /* no SLIM_SMT */
-
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
deleted file mode 100644 (file)
index 0a0a664..0000000
+++ /dev/null
@@ -1,742 +0,0 @@
-/*
- * Routines to compress and uncompress tcp packets (for transmission
- * over low speed serial lines).
- *
- * Copyright (c) 1989 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- *     Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
- *     - Initial distribution.
- *
- *
- * modified for KA9Q Internet Software Package by
- * Katie Stevens (dkstevens@ucdavis.edu)
- * University of California, Davis
- * Computing Services
- *     - 01-31-90      initial adaptation (from 1.19)
- *     PPP.05  02-15-90 [ks]
- *     PPP.08  05-02-90 [ks]   use PPP protocol field to signal compression
- *     PPP.15  09-90    [ks]   improve mbuf handling
- *     PPP.16  11-02    [karn] substantially rewritten to use NOS facilities
- *
- *     - Feb 1991      Bill_Simpson@um.cc.umich.edu
- *                     variable number of conversation slots
- *                     allow zero or one slots
- *                     separate routines
- *                     status display
- *     - Jul 1994      Dmitry Gorodchanin
- *                     Fixes for memory leaks.
- *      - Oct 1994      Dmitry Gorodchanin
- *                      Modularization.
- *     - Jan 1995      Bjorn Ekwall
- *                     Use ip_fast_csum from ip.h
- *     - July 1995     Christos A. Polyzols
- *                     Spotted bug in tcp option checking
- *
- *
- *     This module is a difficult issue. It's clearly inet code but it's also clearly
- *     driver code belonging close to PPP and SLIP
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <net/slhc_vj.h>
-
-#ifdef CONFIG_INET
-/* Entire module is for IP only */
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/termios.h>
-#include <linux/in.h>
-#include <linux/fcntl.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <net/icmp.h>
-#include <net/tcp.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <linux/timer.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-#include <asm/unaligned.h>
-
-static unsigned char *encode(unsigned char *cp, unsigned short n);
-static long decode(unsigned char **cpp);
-static unsigned char * put16(unsigned char *cp, unsigned short x);
-static unsigned short pull16(unsigned char **cpp);
-
-/* Initialize compression data structure
- *     slots must be in range 0 to 255 (zero meaning no compression)
- */
-struct slcompress *
-slhc_init(int rslots, int tslots)
-{
-       register short i;
-       register struct cstate *ts;
-       struct slcompress *comp;
-
-       comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
-       if (! comp)
-               goto out_fail;
-
-       if ( rslots > 0  &&  rslots < 256 ) {
-               size_t rsize = rslots * sizeof(struct cstate);
-               comp->rstate = kzalloc(rsize, GFP_KERNEL);
-               if (! comp->rstate)
-                       goto out_free;
-               comp->rslot_limit = rslots - 1;
-       }
-
-       if ( tslots > 0  &&  tslots < 256 ) {
-               size_t tsize = tslots * sizeof(struct cstate);
-               comp->tstate = kzalloc(tsize, GFP_KERNEL);
-               if (! comp->tstate)
-                       goto out_free2;
-               comp->tslot_limit = tslots - 1;
-       }
-
-       comp->xmit_oldest = 0;
-       comp->xmit_current = 255;
-       comp->recv_current = 255;
-       /*
-        * don't accept any packets with implicit index until we get
-        * one with an explicit index.  Otherwise the uncompress code
-        * will try to use connection 255, which is almost certainly
-        * out of range
-        */
-       comp->flags |= SLF_TOSS;
-
-       if ( tslots > 0 ) {
-               ts = comp->tstate;
-               for(i = comp->tslot_limit; i > 0; --i){
-                       ts[i].cs_this = i;
-                       ts[i].next = &(ts[i - 1]);
-               }
-               ts[0].next = &(ts[comp->tslot_limit]);
-               ts[0].cs_this = 0;
-       }
-       return comp;
-
-out_free2:
-       kfree(comp->rstate);
-out_free:
-       kfree(comp);
-out_fail:
-       return NULL;
-}
-
-
-/* Free a compression data structure */
-void
-slhc_free(struct slcompress *comp)
-{
-       if ( comp == NULLSLCOMPR )
-               return;
-
-       if ( comp->tstate != NULLSLSTATE )
-               kfree( comp->tstate );
-
-       if ( comp->rstate != NULLSLSTATE )
-               kfree( comp->rstate );
-
-       kfree( comp );
-}
-
-
-/* Put a short in host order into a char array in network order */
-static inline unsigned char *
-put16(unsigned char *cp, unsigned short x)
-{
-       *cp++ = x >> 8;
-       *cp++ = x;
-
-       return cp;
-}
-
-
-/* Encode a number */
-static unsigned char *
-encode(unsigned char *cp, unsigned short n)
-{
-       if(n >= 256 || n == 0){
-               *cp++ = 0;
-               cp = put16(cp,n);
-       } else {
-               *cp++ = n;
-       }
-       return cp;
-}
-
-/* Pull a 16-bit integer in host order from buffer in network byte order */
-static unsigned short
-pull16(unsigned char **cpp)
-{
-       short rval;
-
-       rval = *(*cpp)++;
-       rval <<= 8;
-       rval |= *(*cpp)++;
-       return rval;
-}
-
-/* Decode a number */
-static long
-decode(unsigned char **cpp)
-{
-       register int x;
-
-       x = *(*cpp)++;
-       if(x == 0){
-               return pull16(cpp) & 0xffff;    /* pull16 returns -1 on error */
-       } else {
-               return x & 0xff;                /* -1 if PULLCHAR returned error */
-       }
-}
-
-/*
- * icp and isize are the original packet.
- * ocp is a place to put a copy if necessary.
- * cpp is initially a pointer to icp.  If the copy is used,
- *    change it to ocp.
- */
-
-int
-slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
-       unsigned char *ocp, unsigned char **cpp, int compress_cid)
-{
-       register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
-       register struct cstate *lcs = ocs;
-       register struct cstate *cs = lcs->next;
-       register unsigned long deltaS, deltaA;
-       register short changes = 0;
-       int hlen;
-       unsigned char new_seq[16];
-       register unsigned char *cp = new_seq;
-       struct iphdr *ip;
-       struct tcphdr *th, *oth;
-       __sum16 csum;
-
-
-       /*
-        *      Don't play with runt packets.
-        */
-
-       if(isize<sizeof(struct iphdr))
-               return isize;
-
-       ip = (struct iphdr *) icp;
-
-       /* Bail if this packet isn't TCP, or is an IP fragment */
-       if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
-               /* Send as regular IP */
-               if(ip->protocol != IPPROTO_TCP)
-                       comp->sls_o_nontcp++;
-               else
-                       comp->sls_o_tcp++;
-               return isize;
-       }
-       /* Extract TCP header */
-
-       th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
-       hlen = ip->ihl*4 + th->doff*4;
-
-       /*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
-        *  some other control bit is set). Also uncompressible if
-        *  it's a runt.
-        */
-       if(hlen > isize || th->syn || th->fin || th->rst ||
-           ! (th->ack)){
-               /* TCP connection stuff; send as regular IP */
-               comp->sls_o_tcp++;
-               return isize;
-       }
-       /*
-        * Packet is compressible -- we're going to send either a
-        * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way,
-        * we need to locate (or create) the connection state.
-        *
-        * States are kept in a circularly linked list with
-        * xmit_oldest pointing to the end of the list.  The
-        * list is kept in lru order by moving a state to the
-        * head of the list whenever it is referenced.  Since
-        * the list is short and, empirically, the connection
-        * we want is almost always near the front, we locate
-        * states via linear search.  If we don't find a state
-        * for the datagram, the oldest state is (re-)used.
-        */
-       for ( ; ; ) {
-               if( ip->saddr == cs->cs_ip.saddr
-                && ip->daddr == cs->cs_ip.daddr
-                && th->source == cs->cs_tcp.source
-                && th->dest == cs->cs_tcp.dest)
-                       goto found;
-
-               /* if current equal oldest, at end of list */
-               if ( cs == ocs )
-                       break;
-               lcs = cs;
-               cs = cs->next;
-               comp->sls_o_searches++;
-       }
-       /*
-        * Didn't find it -- re-use oldest cstate.  Send an
-        * uncompressed packet that tells the other side what
-        * connection number we're using for this conversation.
-        *
-        * Note that since the state list is circular, the oldest
-        * state points to the newest and we only need to set
-        * xmit_oldest to update the lru linkage.
-        */
-       comp->sls_o_misses++;
-       comp->xmit_oldest = lcs->cs_this;
-       goto uncompressed;
-
-found:
-       /*
-        * Found it -- move to the front on the connection list.
-        */
-       if(lcs == ocs) {
-               /* found at most recently used */
-       } else if (cs == ocs) {
-               /* found at least recently used */
-               comp->xmit_oldest = lcs->cs_this;
-       } else {
-               /* more than 2 elements */
-               lcs->next = cs->next;
-               cs->next = ocs->next;
-               ocs->next = cs;
-       }
-
-       /*
-        * Make sure that only what we expect to change changed.
-        * Check the following:
-        * IP protocol version, header length & type of service.
-        * The "Don't fragment" bit.
-        * The time-to-live field.
-        * The TCP header length.
-        * IP options, if any.
-        * TCP options, if any.
-        * If any of these things are different between the previous &
-        * current datagram, we send the current datagram `uncompressed'.
-        */
-       oth = &cs->cs_tcp;
-
-       if(ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
-        || ip->tos != cs->cs_ip.tos
-        || (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000))
-        || ip->ttl != cs->cs_ip.ttl
-        || th->doff != cs->cs_tcp.doff
-        || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
-        || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
-               goto uncompressed;
-       }
-
-       /*
-        * Figure out which of the changing fields changed.  The
-        * receiver expects changes in the order: urgent, window,
-        * ack, seq (the order minimizes the number of temporaries
-        * needed in this section of code).
-        */
-       if(th->urg){
-               deltaS = ntohs(th->urg_ptr);
-               cp = encode(cp,deltaS);
-               changes |= NEW_U;
-       } else if(th->urg_ptr != oth->urg_ptr){
-               /* argh! URG not set but urp changed -- a sensible
-                * implementation should never do this but RFC793
-                * doesn't prohibit the change so we have to deal
-                * with it. */
-               goto uncompressed;
-       }
-       if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
-               cp = encode(cp,deltaS);
-               changes |= NEW_W;
-       }
-       if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
-               if(deltaA > 0x0000ffff)
-                       goto uncompressed;
-               cp = encode(cp,deltaA);
-               changes |= NEW_A;
-       }
-       if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
-               if(deltaS > 0x0000ffff)
-                       goto uncompressed;
-               cp = encode(cp,deltaS);
-               changes |= NEW_S;
-       }
-
-       switch(changes){
-       case 0: /* Nothing changed. If this packet contains data and the
-                * last one didn't, this is probably a data packet following
-                * an ack (normal on an interactive connection) and we send
-                * it compressed.  Otherwise it's probably a retransmit,
-                * retransmitted ack or window probe.  Send it uncompressed
-                * in case the other side missed the compressed version.
-                */
-               if(ip->tot_len != cs->cs_ip.tot_len &&
-                  ntohs(cs->cs_ip.tot_len) == hlen)
-                       break;
-               goto uncompressed;
-               break;
-       case SPECIAL_I:
-       case SPECIAL_D:
-               /* actual changes match one of our special case encodings --
-                * send packet uncompressed.
-                */
-               goto uncompressed;
-       case NEW_S|NEW_A:
-               if(deltaS == deltaA &&
-                   deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
-                       /* special case for echoed terminal traffic */
-                       changes = SPECIAL_I;
-                       cp = new_seq;
-               }
-               break;
-       case NEW_S:
-               if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
-                       /* special case for data xfer */
-                       changes = SPECIAL_D;
-                       cp = new_seq;
-               }
-               break;
-       }
-       deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
-       if(deltaS != 1){
-               cp = encode(cp,deltaS);
-               changes |= NEW_I;
-       }
-       if(th->psh)
-               changes |= TCP_PUSH_BIT;
-       /* Grab the cksum before we overwrite it below.  Then update our
-        * state with this packet's header.
-        */
-       csum = th->check;
-       memcpy(&cs->cs_ip,ip,20);
-       memcpy(&cs->cs_tcp,th,20);
-       /* We want to use the original packet as our compressed packet.
-        * (cp - new_seq) is the number of bytes we need for compressed
-        * sequence numbers.  In addition we need one byte for the change
-        * mask, one for the connection id and two for the tcp checksum.
-        * So, (cp - new_seq) + 4 bytes of header are needed.
-        */
-       deltaS = cp - new_seq;
-       if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
-               cp = ocp;
-               *cpp = ocp;
-               *cp++ = changes | NEW_C;
-               *cp++ = cs->cs_this;
-               comp->xmit_current = cs->cs_this;
-       } else {
-               cp = ocp;
-               *cpp = ocp;
-               *cp++ = changes;
-       }
-       *(__sum16 *)cp = csum;
-       cp += 2;
-/* deltaS is now the size of the change section of the compressed header */
-       memcpy(cp,new_seq,deltaS);      /* Write list of deltas */
-       memcpy(cp+deltaS,icp+hlen,isize-hlen);
-       comp->sls_o_compressed++;
-       ocp[0] |= SL_TYPE_COMPRESSED_TCP;
-       return isize - hlen + deltaS + (cp - ocp);
-
-       /* Update connection state cs & send uncompressed packet (i.e.,
-        * a regular ip/tcp packet but with the 'conversation id' we hope
-        * to use on future compressed packets in the protocol field).
-        */
-uncompressed:
-       memcpy(&cs->cs_ip,ip,20);
-       memcpy(&cs->cs_tcp,th,20);
-       if (ip->ihl > 5)
-         memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
-       if (th->doff > 5)
-         memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
-       comp->xmit_current = cs->cs_this;
-       comp->sls_o_uncompressed++;
-       memcpy(ocp, icp, isize);
-       *cpp = ocp;
-       ocp[9] = cs->cs_this;
-       ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
-       return isize;
-}
-
-
-int
-slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
-{
-       register int changes;
-       long x;
-       register struct tcphdr *thp;
-       register struct iphdr *ip;
-       register struct cstate *cs;
-       int len, hdrlen;
-       unsigned char *cp = icp;
-
-       /* We've got a compressed packet; read the change byte */
-       comp->sls_i_compressed++;
-       if(isize < 3){
-               comp->sls_i_error++;
-               return 0;
-       }
-       changes = *cp++;
-       if(changes & NEW_C){
-               /* Make sure the state index is in range, then grab the state.
-                * If we have a good state index, clear the 'discard' flag.
-                */
-               x = *cp++;      /* Read conn index */
-               if(x < 0 || x > comp->rslot_limit)
-                       goto bad;
-
-               comp->flags &=~ SLF_TOSS;
-               comp->recv_current = x;
-       } else {
-               /* this packet has an implicit state index.  If we've
-                * had a line error since the last time we got an
-                * explicit state index, we have to toss the packet. */
-               if(comp->flags & SLF_TOSS){
-                       comp->sls_i_tossed++;
-                       return 0;
-               }
-       }
-       cs = &comp->rstate[comp->recv_current];
-       thp = &cs->cs_tcp;
-       ip = &cs->cs_ip;
-
-       thp->check = *(__sum16 *)cp;
-       cp += 2;
-
-       thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
-/*
- * we can use the same number for the length of the saved header and
- * the current one, because the packet wouldn't have been sent
- * as compressed unless the options were the same as the previous one
- */
-
-       hdrlen = ip->ihl * 4 + thp->doff * 4;
-
-       switch(changes & SPECIALS_MASK){
-       case SPECIAL_I:         /* Echoed terminal traffic */
-               {
-               register short i;
-               i = ntohs(ip->tot_len) - hdrlen;
-               thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
-               thp->seq = htonl( ntohl(thp->seq) + i);
-               }
-               break;
-
-       case SPECIAL_D:                 /* Unidirectional data */
-               thp->seq = htonl( ntohl(thp->seq) +
-                                 ntohs(ip->tot_len) - hdrlen);
-               break;
-
-       default:
-               if(changes & NEW_U){
-                       thp->urg = 1;
-                       if((x = decode(&cp)) == -1) {
-                               goto bad;
-                       }
-                       thp->urg_ptr = htons(x);
-               } else
-                       thp->urg = 0;
-               if(changes & NEW_W){
-                       if((x = decode(&cp)) == -1) {
-                               goto bad;
-                       }
-                       thp->window = htons( ntohs(thp->window) + x);
-               }
-               if(changes & NEW_A){
-                       if((x = decode(&cp)) == -1) {
-                               goto bad;
-                       }
-                       thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
-               }
-               if(changes & NEW_S){
-                       if((x = decode(&cp)) == -1) {
-                               goto bad;
-                       }
-                       thp->seq = htonl( ntohl(thp->seq) + x);
-               }
-               break;
-       }
-       if(changes & NEW_I){
-               if((x = decode(&cp)) == -1) {
-                       goto bad;
-               }
-               ip->id = htons (ntohs (ip->id) + x);
-       } else
-               ip->id = htons (ntohs (ip->id) + 1);
-
-       /*
-        * At this point, cp points to the first byte of data in the
-        * packet.  Put the reconstructed TCP and IP headers back on the
-        * packet.  Recalculate IP checksum (but not TCP checksum).
-        */
-
-       len = isize - (cp - icp);
-       if (len < 0)
-               goto bad;
-       len += hdrlen;
-       ip->tot_len = htons(len);
-       ip->check = 0;
-
-       memmove(icp + hdrlen, cp, len - hdrlen);
-
-       cp = icp;
-       memcpy(cp, ip, 20);
-       cp += 20;
-
-       if (ip->ihl > 5) {
-         memcpy(cp, cs->cs_ipopt, (ip->ihl - 5) * 4);
-         cp += (ip->ihl - 5) * 4;
-       }
-
-       put_unaligned(ip_fast_csum(icp, ip->ihl),
-                     &((struct iphdr *)icp)->check);
-
-       memcpy(cp, thp, 20);
-       cp += 20;
-
-       if (thp->doff > 5) {
-         memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
-         cp += ((thp->doff) - 5) * 4;
-       }
-
-       return len;
-bad:
-       comp->sls_i_error++;
-       return slhc_toss( comp );
-}
-
-
-int
-slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
-{
-       register struct cstate *cs;
-       unsigned ihl;
-
-       unsigned char index;
-
-       if(isize < 20) {
-               /* The packet is shorter than a legal IP header */
-               comp->sls_i_runt++;
-               return slhc_toss( comp );
-       }
-       /* Peek at the IP header's IHL field to find its length */
-       ihl = icp[0] & 0xf;
-       if(ihl < 20 / 4){
-               /* The IP header length field is too small */
-               comp->sls_i_runt++;
-               return slhc_toss( comp );
-       }
-       index = icp[9];
-       icp[9] = IPPROTO_TCP;
-
-       if (ip_fast_csum(icp, ihl)) {
-               /* Bad IP header checksum; discard */
-               comp->sls_i_badcheck++;
-               return slhc_toss( comp );
-       }
-       if(index > comp->rslot_limit) {
-               comp->sls_i_error++;
-               return slhc_toss(comp);
-       }
-
-       /* Update local state */
-       cs = &comp->rstate[comp->recv_current = index];
-       comp->flags &=~ SLF_TOSS;
-       memcpy(&cs->cs_ip,icp,20);
-       memcpy(&cs->cs_tcp,icp + ihl*4,20);
-       if (ihl > 5)
-         memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
-       if (cs->cs_tcp.doff > 5)
-         memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
-       cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
-       /* Put headers back on packet
-        * Neither header checksum is recalculated
-        */
-       comp->sls_i_uncompressed++;
-       return isize;
-}
-
-int
-slhc_toss(struct slcompress *comp)
-{
-       if ( comp == NULLSLCOMPR )
-               return 0;
-
-       comp->flags |= SLF_TOSS;
-       return 0;
-}
-
-#else /* CONFIG_INET */
-
-int
-slhc_toss(struct slcompress *comp)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
-  return -EINVAL;
-}
-int
-slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
-  return -EINVAL;
-}
-int
-slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
-       unsigned char *ocp, unsigned char **cpp, int compress_cid)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
-  return -EINVAL;
-}
-
-int
-slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
-  return -EINVAL;
-}
-
-void
-slhc_free(struct slcompress *comp)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
-}
-struct slcompress *
-slhc_init(int rslots, int tslots)
-{
-  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
-  return NULL;
-}
-
-#endif /* CONFIG_INET */
-
-/* VJ header compression */
-EXPORT_SYMBOL(slhc_init);
-EXPORT_SYMBOL(slhc_free);
-EXPORT_SYMBOL(slhc_remember);
-EXPORT_SYMBOL(slhc_compress);
-EXPORT_SYMBOL(slhc_uncompress);
-EXPORT_SYMBOL(slhc_toss);
-
-MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
deleted file mode 100644 (file)
index ba08341..0000000
+++ /dev/null
@@ -1,1444 +0,0 @@
-/*
- * slip.c      This module implements the SLIP protocol for kernel-based
- *             devices like TTY.  It interfaces between a raw TTY, and the
- *             kernel's INET protocol layers.
- *
- * Version:    @(#)slip.c      0.8.3   12/24/94
- *
- * Authors:    Laurence Culhane, <loz@holmes.demon.co.uk>
- *             Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- *
- * Fixes:
- *             Alan Cox        :       Sanity checks and avoid tx overruns.
- *                                     Has a new sl->mtu field.
- *             Alan Cox        :       Found cause of overrun. ifconfig sl0
- *                                     mtu upwards. Driver now spots this
- *                                     and grows/shrinks its buffers(hack!).
- *                                     Memory leak if you run out of memory
- *                                     setting up a slip driver fixed.
- *             Matt Dillon     :       Printable slip (borrowed from NET2E)
- *     Pauline Middelink       :       Slip driver fixes.
- *             Alan Cox        :       Honours the old SL_COMPRESSED flag
- *             Alan Cox        :       KISS AX.25 and AXUI IP support
- *             Michael Riepe   :       Automatic CSLIP recognition added
- *             Charles Hedrick :       CSLIP header length problem fix.
- *             Alan Cox        :       Corrected non-IP cases of the above.
- *             Alan Cox        :       Now uses hardware type as per FvK.
- *             Alan Cox        :       Default to 192.168.0.0 (RFC 1597)
- *             A.N.Kuznetsov   :       dev_tint() recursion fix.
- *     Dmitry Gorodchanin      :       SLIP memory leaks
- *      Dmitry Gorodchanin      :       Code cleanup. Reduce tty driver
- *                                      buffering from 4096 to 256 bytes.
- *                                      Improving SLIP response time.
- *                                      CONFIG_SLIP_MODE_SLIP6.
- *                                      ifconfig sl? up & down now works
- *                                     correctly.
- *                                     Modularization.
- *              Alan Cox        :       Oops - fix AX.25 buffer lengths
- *      Dmitry Gorodchanin      :       Even more cleanups. Preserve CSLIP
- *                                      statistics. Include CSLIP code only
- *                                      if it really needed.
- *             Alan Cox        :       Free slhc buffers in the right place.
- *             Alan Cox        :       Allow for digipeated IP over AX.25
- *             Matti Aarnio    :       Dynamic SLIP devices, with ideas taken
- *                                     from Jim Freeman's <jfree@caldera.com>
- *                                     dynamic PPP devices.  We do NOT kfree()
- *                                     device entries, just reg./unreg. them
- *                                     as they are needed.  We kfree() them
- *                                     at module cleanup.
- *                                     With MODULE-loading ``insmod'', user
- *                                     can issue parameter:  slip_maxdev=1024
- *                                     (Or how much he/she wants.. Default
- *                                     is 256)
- *     Stanislav Voronyi       :       Slip line checking, with ideas taken
- *                                     from multislip BSDI driver which was
- *                                     written by Igor Chechik, RELCOM Corp.
- *                                     Only algorithms have been ported to
- *                                     Linux SLIP driver.
- *     Vitaly E. Lavrov        :       Sane behaviour on tty hangup.
- *     Alexey Kuznetsov        :       Cleanup interfaces to tty & netdevice
- *                                     modules.
- */
-
-#define SL_CHECK_TRANSMIT
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/bitops.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/tty.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/if_arp.h>
-#include <linux/if_slip.h>
-#include <linux/compat.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include "slip.h"
-#ifdef CONFIG_INET
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <net/slhc_vj.h>
-#endif
-
-#define SLIP_VERSION   "0.8.4-NET3.019-NEWTTY"
-
-static struct net_device **slip_devs;
-
-static int slip_maxdev = SL_NRUNIT;
-module_param(slip_maxdev, int, 0);
-MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices");
-
-static int slip_esc(unsigned char *p, unsigned char *d, int len);
-static void slip_unesc(struct slip *sl, unsigned char c);
-#ifdef CONFIG_SLIP_MODE_SLIP6
-static int slip_esc6(unsigned char *p, unsigned char *d, int len);
-static void slip_unesc6(struct slip *sl, unsigned char c);
-#endif
-#ifdef CONFIG_SLIP_SMART
-static void sl_keepalive(unsigned long sls);
-static void sl_outfill(unsigned long sls);
-static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#endif
-
-/********************************
-*  Buffer administration routines:
-*      sl_alloc_bufs()
-*      sl_free_bufs()
-*      sl_realloc_bufs()
-*
-* NOTE: sl_realloc_bufs != sl_free_bufs + sl_alloc_bufs, because
-*      sl_realloc_bufs provides strong atomicity and reallocation
-*      on actively running device.
-*********************************/
-
-/*
-   Allocate channel buffers.
- */
-
-static int sl_alloc_bufs(struct slip *sl, int mtu)
-{
-       int err = -ENOBUFS;
-       unsigned long len;
-       char *rbuff = NULL;
-       char *xbuff = NULL;
-#ifdef SL_INCLUDE_CSLIP
-       char *cbuff = NULL;
-       struct slcompress *slcomp = NULL;
-#endif
-
-       /*
-        * Allocate the SLIP frame buffers:
-        *
-        * rbuff        Receive buffer.
-        * xbuff        Transmit buffer.
-        * cbuff        Temporary compression buffer.
-        */
-       len = mtu * 2;
-
-       /*
-        * allow for arrival of larger UDP packets, even if we say not to
-        * also fixes a bug in which SunOS sends 512-byte packets even with
-        * an MSS of 128
-        */
-       if (len < 576 * 2)
-               len = 576 * 2;
-       rbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (rbuff == NULL)
-               goto err_exit;
-       xbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (xbuff == NULL)
-               goto err_exit;
-#ifdef SL_INCLUDE_CSLIP
-       cbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (cbuff == NULL)
-               goto err_exit;
-       slcomp = slhc_init(16, 16);
-       if (slcomp == NULL)
-               goto err_exit;
-#endif
-       spin_lock_bh(&sl->lock);
-       if (sl->tty == NULL) {
-               spin_unlock_bh(&sl->lock);
-               err = -ENODEV;
-               goto err_exit;
-       }
-       sl->mtu      = mtu;
-       sl->buffsize = len;
-       sl->rcount   = 0;
-       sl->xleft    = 0;
-       rbuff = xchg(&sl->rbuff, rbuff);
-       xbuff = xchg(&sl->xbuff, xbuff);
-#ifdef SL_INCLUDE_CSLIP
-       cbuff = xchg(&sl->cbuff, cbuff);
-       slcomp = xchg(&sl->slcomp, slcomp);
-#endif
-#ifdef CONFIG_SLIP_MODE_SLIP6
-       sl->xdata    = 0;
-       sl->xbits    = 0;
-#endif
-       spin_unlock_bh(&sl->lock);
-       err = 0;
-
-       /* Cleanup */
-err_exit:
-#ifdef SL_INCLUDE_CSLIP
-       kfree(cbuff);
-       slhc_free(slcomp);
-#endif
-       kfree(xbuff);
-       kfree(rbuff);
-       return err;
-}
-
-/* Free a SLIP channel buffers. */
-static void sl_free_bufs(struct slip *sl)
-{
-       /* Free all SLIP frame buffers. */
-       kfree(xchg(&sl->rbuff, NULL));
-       kfree(xchg(&sl->xbuff, NULL));
-#ifdef SL_INCLUDE_CSLIP
-       kfree(xchg(&sl->cbuff, NULL));
-       slhc_free(xchg(&sl->slcomp, NULL));
-#endif
-}
-
-/*
-   Reallocate slip channel buffers.
- */
-
-static int sl_realloc_bufs(struct slip *sl, int mtu)
-{
-       int err = 0;
-       struct net_device *dev = sl->dev;
-       unsigned char *xbuff, *rbuff;
-#ifdef SL_INCLUDE_CSLIP
-       unsigned char *cbuff;
-#endif
-       int len = mtu * 2;
-
-/*
- * allow for arrival of larger UDP packets, even if we say not to
- * also fixes a bug in which SunOS sends 512-byte packets even with
- * an MSS of 128
- */
-       if (len < 576 * 2)
-               len = 576 * 2;
-
-       xbuff = kmalloc(len + 4, GFP_ATOMIC);
-       rbuff = kmalloc(len + 4, GFP_ATOMIC);
-#ifdef SL_INCLUDE_CSLIP
-       cbuff = kmalloc(len + 4, GFP_ATOMIC);
-#endif
-
-
-#ifdef SL_INCLUDE_CSLIP
-       if (xbuff == NULL || rbuff == NULL || cbuff == NULL)  {
-#else
-       if (xbuff == NULL || rbuff == NULL)  {
-#endif
-               if (mtu > sl->mtu) {
-                       printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n",
-                              dev->name);
-                       err = -ENOBUFS;
-               }
-               goto done;
-       }
-       spin_lock_bh(&sl->lock);
-
-       err = -ENODEV;
-       if (sl->tty == NULL)
-               goto done_on_bh;
-
-       xbuff    = xchg(&sl->xbuff, xbuff);
-       rbuff    = xchg(&sl->rbuff, rbuff);
-#ifdef SL_INCLUDE_CSLIP
-       cbuff    = xchg(&sl->cbuff, cbuff);
-#endif
-       if (sl->xleft)  {
-               if (sl->xleft <= len)  {
-                       memcpy(sl->xbuff, sl->xhead, sl->xleft);
-               } else  {
-                       sl->xleft = 0;
-                       dev->stats.tx_dropped++;
-               }
-       }
-       sl->xhead = sl->xbuff;
-
-       if (sl->rcount)  {
-               if (sl->rcount <= len) {
-                       memcpy(sl->rbuff, rbuff, sl->rcount);
-               } else  {
-                       sl->rcount = 0;
-                       dev->stats.rx_over_errors++;
-                       set_bit(SLF_ERROR, &sl->flags);
-               }
-       }
-       sl->mtu      = mtu;
-       dev->mtu      = mtu;
-       sl->buffsize = len;
-       err = 0;
-
-done_on_bh:
-       spin_unlock_bh(&sl->lock);
-
-done:
-       kfree(xbuff);
-       kfree(rbuff);
-#ifdef SL_INCLUDE_CSLIP
-       kfree(cbuff);
-#endif
-       return err;
-}
-
-
-/* Set the "sending" flag.  This must be atomic hence the set_bit. */
-static inline void sl_lock(struct slip *sl)
-{
-       netif_stop_queue(sl->dev);
-}
-
-
-/* Clear the "sending" flag.  This must be atomic, hence the ASM. */
-static inline void sl_unlock(struct slip *sl)
-{
-       netif_wake_queue(sl->dev);
-}
-
-/* Send one completely decapsulated IP datagram to the IP layer. */
-static void sl_bump(struct slip *sl)
-{
-       struct net_device *dev = sl->dev;
-       struct sk_buff *skb;
-       int count;
-
-       count = sl->rcount;
-#ifdef SL_INCLUDE_CSLIP
-       if (sl->mode & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) {
-               unsigned char c = sl->rbuff[0];
-               if (c & SL_TYPE_COMPRESSED_TCP) {
-                       /* ignore compressed packets when CSLIP is off */
-                       if (!(sl->mode & SL_MODE_CSLIP)) {
-                               printk(KERN_WARNING "%s: compressed packet ignored\n", dev->name);
-                               return;
-                       }
-                       /* make sure we've reserved enough space for uncompress
-                          to use */
-                       if (count + 80 > sl->buffsize) {
-                               dev->stats.rx_over_errors++;
-                               return;
-                       }
-                       count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
-                       if (count <= 0)
-                               return;
-               } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
-                       if (!(sl->mode & SL_MODE_CSLIP)) {
-                               /* turn on header compression */
-                               sl->mode |= SL_MODE_CSLIP;
-                               sl->mode &= ~SL_MODE_ADAPTIVE;
-                               printk(KERN_INFO "%s: header compression turned on\n", dev->name);
-                       }
-                       sl->rbuff[0] &= 0x4f;
-                       if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0)
-                               return;
-               }
-       }
-#endif  /* SL_INCLUDE_CSLIP */
-
-       dev->stats.rx_bytes += count;
-
-       skb = dev_alloc_skb(count);
-       if (skb == NULL) {
-               printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
-               dev->stats.rx_dropped++;
-               return;
-       }
-       skb->dev = dev;
-       memcpy(skb_put(skb, count), sl->rbuff, count);
-       skb_reset_mac_header(skb);
-       skb->protocol = htons(ETH_P_IP);
-       netif_rx_ni(skb);
-       dev->stats.rx_packets++;
-}
-
-/* Encapsulate one IP datagram and stuff into a TTY queue. */
-static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
-{
-       unsigned char *p;
-       int actual, count;
-
-       if (len > sl->mtu) {            /* Sigh, shouldn't occur BUT ... */
-               printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name);
-               sl->dev->stats.tx_dropped++;
-               sl_unlock(sl);
-               return;
-       }
-
-       p = icp;
-#ifdef SL_INCLUDE_CSLIP
-       if (sl->mode & SL_MODE_CSLIP)
-               len = slhc_compress(sl->slcomp, p, len, sl->cbuff, &p, 1);
-#endif
-#ifdef CONFIG_SLIP_MODE_SLIP6
-       if (sl->mode & SL_MODE_SLIP6)
-               count = slip_esc6(p, (unsigned char *) sl->xbuff, len);
-       else
-#endif
-               count = slip_esc(p, (unsigned char *) sl->xbuff, len);
-
-       /* Order of next two lines is *very* important.
-        * When we are sending a little amount of data,
-        * the transfer may be completed inside the ops->write()
-        * routine, because it's running with interrupts enabled.
-        * In this case we *never* got WRITE_WAKEUP event,
-        * if we did not request it before write operation.
-        *       14 Oct 1994  Dmitry Gorodchanin.
-        */
-       set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
-       actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
-#ifdef SL_CHECK_TRANSMIT
-       sl->dev->trans_start = jiffies;
-#endif
-       sl->xleft = count - actual;
-       sl->xhead = sl->xbuff + actual;
-#ifdef CONFIG_SLIP_SMART
-       /* VSV */
-       clear_bit(SLF_OUTWAIT, &sl->flags);     /* reset outfill flag */
-#endif
-}
-
-/*
- * Called by the driver when there's room for more data.  If we have
- * more packets to send, we send them here.
- */
-static void slip_write_wakeup(struct tty_struct *tty)
-{
-       int actual;
-       struct slip *sl = tty->disc_data;
-
-       /* First make sure we're connected. */
-       if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
-               return;
-
-       if (sl->xleft <= 0)  {
-               /* Now serial buffer is almost free & we can start
-                * transmission of another packet */
-               sl->dev->stats.tx_packets++;
-               clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-               sl_unlock(sl);
-               return;
-       }
-
-       actual = tty->ops->write(tty, sl->xhead, sl->xleft);
-       sl->xleft -= actual;
-       sl->xhead += actual;
-}
-
-static void sl_tx_timeout(struct net_device *dev)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       spin_lock(&sl->lock);
-
-       if (netif_queue_stopped(dev)) {
-               if (!netif_running(dev))
-                       goto out;
-
-               /* May be we must check transmitter timeout here ?
-                *      14 Oct 1994 Dmitry Gorodchanin.
-                */
-#ifdef SL_CHECK_TRANSMIT
-               if (time_before(jiffies, dev_trans_start(dev) + 20 * HZ))  {
-                       /* 20 sec timeout not reached */
-                       goto out;
-               }
-               printk(KERN_WARNING "%s: transmit timed out, %s?\n",
-                       dev->name,
-                       (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
-                               "bad line quality" : "driver error");
-               sl->xleft = 0;
-               clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
-               sl_unlock(sl);
-#endif
-       }
-out:
-       spin_unlock(&sl->lock);
-}
-
-
-/* Encapsulate an IP datagram and kick it into a TTY queue. */
-static netdev_tx_t
-sl_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       spin_lock(&sl->lock);
-       if (!netif_running(dev)) {
-               spin_unlock(&sl->lock);
-               printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
-               dev_kfree_skb(skb);
-               return NETDEV_TX_OK;
-       }
-       if (sl->tty == NULL) {
-               spin_unlock(&sl->lock);
-               dev_kfree_skb(skb);
-               return NETDEV_TX_OK;
-       }
-
-       sl_lock(sl);
-       dev->stats.tx_bytes += skb->len;
-       sl_encaps(sl, skb->data, skb->len);
-       spin_unlock(&sl->lock);
-
-       dev_kfree_skb(skb);
-       return NETDEV_TX_OK;
-}
-
-
-/******************************************
- *   Routines looking at netdevice side.
- ******************************************/
-
-/* Netdevice UP -> DOWN routine */
-
-static int
-sl_close(struct net_device *dev)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       spin_lock_bh(&sl->lock);
-       if (sl->tty)
-               /* TTY discipline is running. */
-               clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
-       netif_stop_queue(dev);
-       sl->rcount   = 0;
-       sl->xleft    = 0;
-       spin_unlock_bh(&sl->lock);
-
-       return 0;
-}
-
-/* Netdevice DOWN -> UP routine */
-
-static int sl_open(struct net_device *dev)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       if (sl->tty == NULL)
-               return -ENODEV;
-
-       sl->flags &= (1 << SLF_INUSE);
-       netif_start_queue(dev);
-       return 0;
-}
-
-/* Netdevice change MTU request */
-
-static int sl_change_mtu(struct net_device *dev, int new_mtu)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       if (new_mtu < 68 || new_mtu > 65534)
-               return -EINVAL;
-
-       if (new_mtu != dev->mtu)
-               return sl_realloc_bufs(sl, new_mtu);
-       return 0;
-}
-
-/* Netdevice get statistics request */
-
-static struct rtnl_link_stats64 *
-sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
-{
-       struct net_device_stats *devstats = &dev->stats;
-#ifdef SL_INCLUDE_CSLIP
-       struct slip *sl = netdev_priv(dev);
-       struct slcompress *comp = sl->slcomp;
-#endif
-       stats->rx_packets     = devstats->rx_packets;
-       stats->tx_packets     = devstats->tx_packets;
-       stats->rx_bytes       = devstats->rx_bytes;
-       stats->tx_bytes       = devstats->tx_bytes;
-       stats->rx_dropped     = devstats->rx_dropped;
-       stats->tx_dropped     = devstats->tx_dropped;
-       stats->tx_errors      = devstats->tx_errors;
-       stats->rx_errors      = devstats->rx_errors;
-       stats->rx_over_errors = devstats->rx_over_errors;
-
-#ifdef SL_INCLUDE_CSLIP
-       if (comp) {
-               /* Generic compressed statistics */
-               stats->rx_compressed   = comp->sls_i_compressed;
-               stats->tx_compressed   = comp->sls_o_compressed;
-
-               /* Are we really still needs this? */
-               stats->rx_fifo_errors += comp->sls_i_compressed;
-               stats->rx_dropped     += comp->sls_i_tossed;
-               stats->tx_fifo_errors += comp->sls_o_compressed;
-               stats->collisions     += comp->sls_o_misses;
-       }
-#endif
-       return stats;
-}
-
-/* Netdevice register callback */
-
-static int sl_init(struct net_device *dev)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       /*
-        *      Finish setting up the DEVICE info.
-        */
-
-       dev->mtu                = sl->mtu;
-       dev->type               = ARPHRD_SLIP + sl->mode;
-#ifdef SL_CHECK_TRANSMIT
-       dev->watchdog_timeo     = 20*HZ;
-#endif
-       return 0;
-}
-
-
-static void sl_uninit(struct net_device *dev)
-{
-       struct slip *sl = netdev_priv(dev);
-
-       sl_free_bufs(sl);
-}
-
-/* Hook the destructor so we can free slip devices at the right point in time */
-static void sl_free_netdev(struct net_device *dev)
-{
-       int i = dev->base_addr;
-       free_netdev(dev);
-       slip_devs[i] = NULL;
-}
-
-static const struct net_device_ops sl_netdev_ops = {
-       .ndo_init               = sl_init,
-       .ndo_uninit             = sl_uninit,
-       .ndo_open               = sl_open,
-       .ndo_stop               = sl_close,
-       .ndo_start_xmit         = sl_xmit,
-       .ndo_get_stats64        = sl_get_stats64,
-       .ndo_change_mtu         = sl_change_mtu,
-       .ndo_tx_timeout         = sl_tx_timeout,
-#ifdef CONFIG_SLIP_SMART
-       .ndo_do_ioctl           = sl_ioctl,
-#endif
-};
-
-
-static void sl_setup(struct net_device *dev)
-{
-       dev->netdev_ops         = &sl_netdev_ops;
-       dev->destructor         = sl_free_netdev;
-
-       dev->hard_header_len    = 0;
-       dev->addr_len           = 0;
-       dev->tx_queue_len       = 10;
-
-       /* New-style flags. */
-       dev->flags              = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
-}
-
-/******************************************
-  Routines looking at TTY side.
- ******************************************/
-
-
-/*
- * Handle the 'receiver data ready' interrupt.
- * This function is called by the 'tty_io' module in the kernel when
- * a block of SLIP data has been received, which can now be decapsulated
- * and sent on to some IP layer for further processing. This will not
- * be re-entered while running but other ldisc functions may be called
- * in parallel
- */
-
-static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
-                                                       char *fp, int count)
-{
-       struct slip *sl = tty->disc_data;
-
-       if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
-               return;
-
-       /* Read the characters out of the buffer */
-       while (count--) {
-               if (fp && *fp++) {
-                       if (!test_and_set_bit(SLF_ERROR, &sl->flags))
-                               sl->dev->stats.rx_errors++;
-                       cp++;
-                       continue;
-               }
-#ifdef CONFIG_SLIP_MODE_SLIP6
-               if (sl->mode & SL_MODE_SLIP6)
-                       slip_unesc6(sl, *cp++);
-               else
-#endif
-                       slip_unesc(sl, *cp++);
-       }
-}
-
-/************************************
- *  slip_open helper routines.
- ************************************/
-
-/* Collect hanged up channels */
-static void sl_sync(void)
-{
-       int i;
-       struct net_device *dev;
-       struct slip       *sl;
-
-       for (i = 0; i < slip_maxdev; i++) {
-               dev = slip_devs[i];
-               if (dev == NULL)
-                       break;
-
-               sl = netdev_priv(dev);
-               if (sl->tty || sl->leased)
-                       continue;
-               if (dev->flags & IFF_UP)
-                       dev_close(dev);
-       }
-}
-
-
-/* Find a free SLIP channel, and link in this `tty' line. */
-static struct slip *sl_alloc(dev_t line)
-{
-       int i;
-       char name[IFNAMSIZ];
-       struct net_device *dev = NULL;
-       struct slip       *sl;
-
-       for (i = 0; i < slip_maxdev; i++) {
-               dev = slip_devs[i];
-               if (dev == NULL)
-                       break;
-       }
-       /* Sorry, too many, all slots in use */
-       if (i >= slip_maxdev)
-               return NULL;
-
-       sprintf(name, "sl%d", i);
-       dev = alloc_netdev(sizeof(*sl), name, sl_setup);
-       if (!dev)
-               return NULL;
-
-       dev->base_addr  = i;
-       sl = netdev_priv(dev);
-
-       /* Initialize channel control data */
-       sl->magic       = SLIP_MAGIC;
-       sl->dev         = dev;
-       spin_lock_init(&sl->lock);
-       sl->mode        = SL_MODE_DEFAULT;
-#ifdef CONFIG_SLIP_SMART
-       /* initialize timer_list struct */
-       init_timer(&sl->keepalive_timer);
-       sl->keepalive_timer.data = (unsigned long)sl;
-       sl->keepalive_timer.function = sl_keepalive;
-       init_timer(&sl->outfill_timer);
-       sl->outfill_timer.data = (unsigned long)sl;
-       sl->outfill_timer.function = sl_outfill;
-#endif
-       slip_devs[i] = dev;
-       return sl;
-}
-
-/*
- * Open the high-level part of the SLIP channel.
- * This function is called by the TTY module when the
- * SLIP line discipline is called for.  Because we are
- * sure the tty line exists, we only have to link it to
- * a free SLIP channel...
- *
- * Called in process context serialized from other ldisc calls.
- */
-
-static int slip_open(struct tty_struct *tty)
-{
-       struct slip *sl;
-       int err;
-
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-
-       if (tty->ops->write == NULL)
-               return -EOPNOTSUPP;
-
-       /* RTnetlink lock is misused here to serialize concurrent
-          opens of slip channels. There are better ways, but it is
-          the simplest one.
-        */
-       rtnl_lock();
-
-       /* Collect hanged up channels. */
-       sl_sync();
-
-       sl = tty->disc_data;
-
-       err = -EEXIST;
-       /* First make sure we're not already connected. */
-       if (sl && sl->magic == SLIP_MAGIC)
-               goto err_exit;
-
-       /* OK.  Find a free SLIP channel to use. */
-       err = -ENFILE;
-       sl = sl_alloc(tty_devnum(tty));
-       if (sl == NULL)
-               goto err_exit;
-
-       sl->tty = tty;
-       tty->disc_data = sl;
-       sl->pid = current->pid;
-
-       if (!test_bit(SLF_INUSE, &sl->flags)) {
-               /* Perform the low-level SLIP initialization. */
-               err = sl_alloc_bufs(sl, SL_MTU);
-               if (err)
-                       goto err_free_chan;
-
-               set_bit(SLF_INUSE, &sl->flags);
-
-               err = register_netdevice(sl->dev);
-               if (err)
-                       goto err_free_bufs;
-       }
-
-#ifdef CONFIG_SLIP_SMART
-       if (sl->keepalive) {
-               sl->keepalive_timer.expires = jiffies + sl->keepalive * HZ;
-               add_timer(&sl->keepalive_timer);
-       }
-       if (sl->outfill) {
-               sl->outfill_timer.expires = jiffies + sl->outfill * HZ;
-               add_timer(&sl->outfill_timer);
-       }
-#endif
-
-       /* Done.  We have linked the TTY line to a channel. */
-       rtnl_unlock();
-       tty->receive_room = 65536;      /* We don't flow control */
-
-       /* TTY layer expects 0 on success */
-       return 0;
-
-err_free_bufs:
-       sl_free_bufs(sl);
-
-err_free_chan:
-       sl->tty = NULL;
-       tty->disc_data = NULL;
-       clear_bit(SLF_INUSE, &sl->flags);
-
-err_exit:
-       rtnl_unlock();
-
-       /* Count references from TTY module */
-       return err;
-}
-
-/*
- * Close down a SLIP channel.
- * This means flushing out any pending queues, and then returning. This
- * call is serialized against other ldisc functions.
- *
- * We also use this method fo a hangup event
- */
-
-static void slip_close(struct tty_struct *tty)
-{
-       struct slip *sl = tty->disc_data;
-
-       /* First make sure we're connected. */
-       if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty)
-               return;
-
-       tty->disc_data = NULL;
-       sl->tty = NULL;
-
-       /* VSV = very important to remove timers */
-#ifdef CONFIG_SLIP_SMART
-       del_timer_sync(&sl->keepalive_timer);
-       del_timer_sync(&sl->outfill_timer);
-#endif
-       /* Flush network side */
-       unregister_netdev(sl->dev);
-       /* This will complete via sl_free_netdev */
-}
-
-static int slip_hangup(struct tty_struct *tty)
-{
-       slip_close(tty);
-       return 0;
-}
- /************************************************************************
-  *                    STANDARD SLIP ENCAPSULATION                      *
-  ************************************************************************/
-
-static int slip_esc(unsigned char *s, unsigned char *d, int len)
-{
-       unsigned char *ptr = d;
-       unsigned char c;
-
-       /*
-        * Send an initial END character to flush out any
-        * data that may have accumulated in the receiver
-        * due to line noise.
-        */
-
-       *ptr++ = END;
-
-       /*
-        * For each byte in the packet, send the appropriate
-        * character sequence, according to the SLIP protocol.
-        */
-
-       while (len-- > 0) {
-               switch (c = *s++) {
-               case END:
-                       *ptr++ = ESC;
-                       *ptr++ = ESC_END;
-                       break;
-               case ESC:
-                       *ptr++ = ESC;
-                       *ptr++ = ESC_ESC;
-                       break;
-               default:
-                       *ptr++ = c;
-                       break;
-               }
-       }
-       *ptr++ = END;
-       return ptr - d;
-}
-
-static void slip_unesc(struct slip *sl, unsigned char s)
-{
-
-       switch (s) {
-       case END:
-#ifdef CONFIG_SLIP_SMART
-               /* drop keeptest bit = VSV */
-               if (test_bit(SLF_KEEPTEST, &sl->flags))
-                       clear_bit(SLF_KEEPTEST, &sl->flags);
-#endif
-
-               if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
-                   (sl->rcount > 2))
-                       sl_bump(sl);
-               clear_bit(SLF_ESCAPE, &sl->flags);
-               sl->rcount = 0;
-               return;
-
-       case ESC:
-               set_bit(SLF_ESCAPE, &sl->flags);
-               return;
-       case ESC_ESC:
-               if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
-                       s = ESC;
-               break;
-       case ESC_END:
-               if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
-                       s = END;
-               break;
-       }
-       if (!test_bit(SLF_ERROR, &sl->flags))  {
-               if (sl->rcount < sl->buffsize)  {
-                       sl->rbuff[sl->rcount++] = s;
-                       return;
-               }
-               sl->dev->stats.rx_over_errors++;
-               set_bit(SLF_ERROR, &sl->flags);
-       }
-}
-
-
-#ifdef CONFIG_SLIP_MODE_SLIP6
-/************************************************************************
- *                      6 BIT SLIP ENCAPSULATION                       *
- ************************************************************************/
-
-static int slip_esc6(unsigned char *s, unsigned char *d, int len)
-{
-       unsigned char *ptr = d;
-       unsigned char c;
-       int i;
-       unsigned short v = 0;
-       short bits = 0;
-
-       /*
-        * Send an initial END character to flush out any
-        * data that may have accumulated in the receiver
-        * due to line noise.
-        */
-
-       *ptr++ = 0x70;
-
-       /*
-        * Encode the packet into printable ascii characters
-        */
-
-       for (i = 0; i < len; ++i) {
-               v = (v << 8) | s[i];
-               bits += 8;
-               while (bits >= 6) {
-                       bits -= 6;
-                       c = 0x30 + ((v >> bits) & 0x3F);
-                       *ptr++ = c;
-               }
-       }
-       if (bits) {
-               c = 0x30 + ((v << (6 - bits)) & 0x3F);
-               *ptr++ = c;
-       }
-       *ptr++ = 0x70;
-       return ptr - d;
-}
-
-static void slip_unesc6(struct slip *sl, unsigned char s)
-{
-       unsigned char c;
-
-       if (s == 0x70) {
-#ifdef CONFIG_SLIP_SMART
-               /* drop keeptest bit = VSV */
-               if (test_bit(SLF_KEEPTEST, &sl->flags))
-                       clear_bit(SLF_KEEPTEST, &sl->flags);
-#endif
-
-               if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
-                   (sl->rcount > 2))
-                       sl_bump(sl);
-               sl->rcount = 0;
-               sl->xbits = 0;
-               sl->xdata = 0;
-       } else if (s >= 0x30 && s < 0x70) {
-               sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);
-               sl->xbits += 6;
-               if (sl->xbits >= 8) {
-                       sl->xbits -= 8;
-                       c = (unsigned char)(sl->xdata >> sl->xbits);
-                       if (!test_bit(SLF_ERROR, &sl->flags))  {
-                               if (sl->rcount < sl->buffsize)  {
-                                       sl->rbuff[sl->rcount++] = c;
-                                       return;
-                               }
-                               sl->dev->stats.rx_over_errors++;
-                               set_bit(SLF_ERROR, &sl->flags);
-                       }
-               }
-       }
-}
-#endif /* CONFIG_SLIP_MODE_SLIP6 */
-
-/* Perform I/O control on an active SLIP channel. */
-static int slip_ioctl(struct tty_struct *tty, struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       struct slip *sl = tty->disc_data;
-       unsigned int tmp;
-       int __user *p = (int __user *)arg;
-
-       /* First make sure we're connected. */
-       if (!sl || sl->magic != SLIP_MAGIC)
-               return -EINVAL;
-
-       switch (cmd) {
-       case SIOCGIFNAME:
-               tmp = strlen(sl->dev->name) + 1;
-               if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
-                       return -EFAULT;
-               return 0;
-
-       case SIOCGIFENCAP:
-               if (put_user(sl->mode, p))
-                       return -EFAULT;
-               return 0;
-
-       case SIOCSIFENCAP:
-               if (get_user(tmp, p))
-                       return -EFAULT;
-#ifndef SL_INCLUDE_CSLIP
-               if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))
-                       return -EINVAL;
-#else
-               if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==
-                   (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))
-                       /* return -EINVAL; */
-                       tmp &= ~SL_MODE_ADAPTIVE;
-#endif
-#ifndef CONFIG_SLIP_MODE_SLIP6
-               if (tmp & SL_MODE_SLIP6)
-                       return -EINVAL;
-#endif
-               sl->mode = tmp;
-               sl->dev->type = ARPHRD_SLIP + sl->mode;
-               return 0;
-
-       case SIOCSIFHWADDR:
-               return -EINVAL;
-
-#ifdef CONFIG_SLIP_SMART
-       /* VSV changes start here */
-       case SIOCSKEEPALIVE:
-               if (get_user(tmp, p))
-                       return -EFAULT;
-               if (tmp > 255) /* max for unchar */
-                       return -EINVAL;
-
-               spin_lock_bh(&sl->lock);
-               if (!sl->tty) {
-                       spin_unlock_bh(&sl->lock);
-                       return -ENODEV;
-               }
-               sl->keepalive = (u8)tmp;
-               if (sl->keepalive != 0) {
-                       mod_timer(&sl->keepalive_timer,
-                                       jiffies + sl->keepalive * HZ);
-                       set_bit(SLF_KEEPTEST, &sl->flags);
-               } else
-                       del_timer(&sl->keepalive_timer);
-               spin_unlock_bh(&sl->lock);
-               return 0;
-
-       case SIOCGKEEPALIVE:
-               if (put_user(sl->keepalive, p))
-                       return -EFAULT;
-               return 0;
-
-       case SIOCSOUTFILL:
-               if (get_user(tmp, p))
-                       return -EFAULT;
-               if (tmp > 255) /* max for unchar */
-                       return -EINVAL;
-               spin_lock_bh(&sl->lock);
-               if (!sl->tty) {
-                       spin_unlock_bh(&sl->lock);
-                       return -ENODEV;
-               }
-               sl->outfill = (u8)tmp;
-               if (sl->outfill != 0) {
-                       mod_timer(&sl->outfill_timer,
-                                               jiffies + sl->outfill * HZ);
-                       set_bit(SLF_OUTWAIT, &sl->flags);
-               } else
-                       del_timer(&sl->outfill_timer);
-               spin_unlock_bh(&sl->lock);
-               return 0;
-
-       case SIOCGOUTFILL:
-               if (put_user(sl->outfill, p))
-                       return -EFAULT;
-               return 0;
-       /* VSV changes end */
-#endif
-       default:
-               return tty_mode_ioctl(tty, file, cmd, arg);
-       }
-}
-
-#ifdef CONFIG_COMPAT
-static long slip_compat_ioctl(struct tty_struct *tty, struct file *file,
-                                       unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case SIOCGIFNAME:
-       case SIOCGIFENCAP:
-       case SIOCSIFENCAP:
-       case SIOCSIFHWADDR:
-       case SIOCSKEEPALIVE:
-       case SIOCGKEEPALIVE:
-       case SIOCSOUTFILL:
-       case SIOCGOUTFILL:
-               return slip_ioctl(tty, file, cmd,
-                                 (unsigned long)compat_ptr(arg));
-       }
-
-       return -ENOIOCTLCMD;
-}
-#endif
-
-/* VSV changes start here */
-#ifdef CONFIG_SLIP_SMART
-/* function do_ioctl called from net/core/dev.c
-   to allow get/set outfill/keepalive parameter
-   by ifconfig                                 */
-
-static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct slip *sl = netdev_priv(dev);
-       unsigned long *p = (unsigned long *)&rq->ifr_ifru;
-
-       if (sl == NULL)         /* Allocation failed ?? */
-               return -ENODEV;
-
-       spin_lock_bh(&sl->lock);
-
-       if (!sl->tty) {
-               spin_unlock_bh(&sl->lock);
-               return -ENODEV;
-       }
-
-       switch (cmd) {
-       case SIOCSKEEPALIVE:
-               /* max for unchar */
-               if ((unsigned)*p > 255) {
-                       spin_unlock_bh(&sl->lock);
-                       return -EINVAL;
-               }
-               sl->keepalive = (u8)*p;
-               if (sl->keepalive != 0) {
-                       sl->keepalive_timer.expires =
-                                               jiffies + sl->keepalive * HZ;
-                       mod_timer(&sl->keepalive_timer,
-                                               jiffies + sl->keepalive * HZ);
-                       set_bit(SLF_KEEPTEST, &sl->flags);
-               } else
-                       del_timer(&sl->keepalive_timer);
-               break;
-
-       case SIOCGKEEPALIVE:
-               *p = sl->keepalive;
-               break;
-
-       case SIOCSOUTFILL:
-               if ((unsigned)*p > 255) { /* max for unchar */
-                       spin_unlock_bh(&sl->lock);
-                       return -EINVAL;
-               }
-               sl->outfill = (u8)*p;
-               if (sl->outfill != 0) {
-                       mod_timer(&sl->outfill_timer,
-                                               jiffies + sl->outfill * HZ);
-                       set_bit(SLF_OUTWAIT, &sl->flags);
-               } else
-                       del_timer(&sl->outfill_timer);
-               break;
-
-       case SIOCGOUTFILL:
-               *p = sl->outfill;
-               break;
-
-       case SIOCSLEASE:
-               /* Resolve race condition, when ioctl'ing hanged up
-                  and opened by another process device.
-                */
-               if (sl->tty != current->signal->tty &&
-                                               sl->pid != current->pid) {
-                       spin_unlock_bh(&sl->lock);
-                       return -EPERM;
-               }
-               sl->leased = 0;
-               if (*p)
-                       sl->leased = 1;
-               break;
-
-       case SIOCGLEASE:
-               *p = sl->leased;
-       }
-       spin_unlock_bh(&sl->lock);
-       return 0;
-}
-#endif
-/* VSV changes end */
-
-static struct tty_ldisc_ops sl_ldisc = {
-       .owner          = THIS_MODULE,
-       .magic          = TTY_LDISC_MAGIC,
-       .name           = "slip",
-       .open           = slip_open,
-       .close          = slip_close,
-       .hangup         = slip_hangup,
-       .ioctl          = slip_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = slip_compat_ioctl,
-#endif
-       .receive_buf    = slip_receive_buf,
-       .write_wakeup   = slip_write_wakeup,
-};
-
-static int __init slip_init(void)
-{
-       int status;
-
-       if (slip_maxdev < 4)
-               slip_maxdev = 4; /* Sanity */
-
-       printk(KERN_INFO "SLIP: version %s (dynamic channels, max=%d)"
-#ifdef CONFIG_SLIP_MODE_SLIP6
-              " (6 bit encapsulation enabled)"
-#endif
-              ".\n",
-              SLIP_VERSION, slip_maxdev);
-#if defined(SL_INCLUDE_CSLIP)
-       printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n");
-#endif
-#ifdef CONFIG_SLIP_SMART
-       printk(KERN_INFO "SLIP linefill/keepalive option.\n");
-#endif
-
-       slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev,
-                                                               GFP_KERNEL);
-       if (!slip_devs) {
-               printk(KERN_ERR "SLIP: Can't allocate slip devices array.\n");
-               return -ENOMEM;
-       }
-
-       /* Fill in our line protocol discipline, and register it */
-       status = tty_register_ldisc(N_SLIP, &sl_ldisc);
-       if (status != 0) {
-               printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
-               kfree(slip_devs);
-       }
-       return status;
-}
-
-static void __exit slip_exit(void)
-{
-       int i;
-       struct net_device *dev;
-       struct slip *sl;
-       unsigned long timeout = jiffies + HZ;
-       int busy = 0;
-
-       if (slip_devs == NULL)
-               return;
-
-       /* First of all: check for active disciplines and hangup them.
-        */
-       do {
-               if (busy)
-                       msleep_interruptible(100);
-
-               busy = 0;
-               for (i = 0; i < slip_maxdev; i++) {
-                       dev = slip_devs[i];
-                       if (!dev)
-                               continue;
-                       sl = netdev_priv(dev);
-                       spin_lock_bh(&sl->lock);
-                       if (sl->tty) {
-                               busy++;
-                               tty_hangup(sl->tty);
-                       }
-                       spin_unlock_bh(&sl->lock);
-               }
-       } while (busy && time_before(jiffies, timeout));
-
-       /* FIXME: hangup is async so we should wait when doing this second
-          phase */
-
-       for (i = 0; i < slip_maxdev; i++) {
-               dev = slip_devs[i];
-               if (!dev)
-                       continue;
-               slip_devs[i] = NULL;
-
-               sl = netdev_priv(dev);
-               if (sl->tty) {
-                       printk(KERN_ERR "%s: tty discipline still running\n",
-                              dev->name);
-                       /* Intentionally leak the control block. */
-                       dev->destructor = NULL;
-               }
-
-               unregister_netdev(dev);
-       }
-
-       kfree(slip_devs);
-       slip_devs = NULL;
-
-       i = tty_unregister_ldisc(N_SLIP);
-       if (i != 0)
-               printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
-}
-
-module_init(slip_init);
-module_exit(slip_exit);
-
-#ifdef CONFIG_SLIP_SMART
-/*
- * This is start of the code for multislip style line checking
- * added by Stanislav Voronyi. All changes before marked VSV
- */
-
-static void sl_outfill(unsigned long sls)
-{
-       struct slip *sl = (struct slip *)sls;
-
-       spin_lock(&sl->lock);
-
-       if (sl->tty == NULL)
-               goto out;
-
-       if (sl->outfill) {
-               if (test_bit(SLF_OUTWAIT, &sl->flags)) {
-                       /* no packets were transmitted, do outfill */
-#ifdef CONFIG_SLIP_MODE_SLIP6
-                       unsigned char s = (sl->mode & SL_MODE_SLIP6)?0x70:END;
-#else
-                       unsigned char s = END;
-#endif
-                       /* put END into tty queue. Is it right ??? */
-                       if (!netif_queue_stopped(sl->dev)) {
-                               /* if device busy no outfill */
-                               sl->tty->ops->write(sl->tty, &s, 1);
-                       }
-               } else
-                       set_bit(SLF_OUTWAIT, &sl->flags);
-
-               mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
-       }
-out:
-       spin_unlock(&sl->lock);
-}
-
-static void sl_keepalive(unsigned long sls)
-{
-       struct slip *sl = (struct slip *)sls;
-
-       spin_lock(&sl->lock);
-
-       if (sl->tty == NULL)
-               goto out;
-
-       if (sl->keepalive) {
-               if (test_bit(SLF_KEEPTEST, &sl->flags)) {
-                       /* keepalive still high :(, we must hangup */
-                       if (sl->outfill)
-                               /* outfill timer must be deleted too */
-                               (void)del_timer(&sl->outfill_timer);
-                       printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
-                       /* this must hangup tty & close slip */
-                       tty_hangup(sl->tty);
-                       /* I think we need not something else */
-                       goto out;
-               } else
-                       set_bit(SLF_KEEPTEST, &sl->flags);
-
-               mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
-       }
-out:
-       spin_unlock(&sl->lock);
-}
-
-#endif
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_LDISC(N_SLIP);
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
deleted file mode 100644 (file)
index 67673cf..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * slip.h      Define the SLIP device driver interface and constants.
- *
- * NOTE:       THIS FILE WILL BE MOVED TO THE LINUX INCLUDE DIRECTORY
- *             AS SOON AS POSSIBLE!
- *
- * Version:    @(#)slip.h      1.2.0   03/28/93
- *
- * Fixes:
- *             Alan Cox        :       Added slip mtu field.
- *             Matt Dillon     :       Printable slip (borrowed from net2e)
- *             Alan Cox        :       Added SL_SLIP_LOTS
- *     Dmitry Gorodchanin      :       A lot of changes in the 'struct slip'
- *     Dmitry Gorodchanin      :       Added CSLIP statistics.
- *     Stanislav Voronyi       :       Make line checking as created by
- *                                     Igor Chechik, RELCOM Corp.
- *     Craig Schlenter         :       Fixed #define bug that caused
- *                                     CSLIP telnets to hang in 1.3.61-6
- *
- * Author:     Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- */
-#ifndef _LINUX_SLIP_H
-#define _LINUX_SLIP_H
-
-
-#if defined(CONFIG_INET) && defined(CONFIG_SLIP_COMPRESSED)
-# define SL_INCLUDE_CSLIP
-#endif
-
-#ifdef SL_INCLUDE_CSLIP
-# define SL_MODE_DEFAULT SL_MODE_ADAPTIVE
-#else
-# define SL_MODE_DEFAULT SL_MODE_SLIP
-#endif
-
-/* SLIP configuration. */
-#define SL_NRUNIT      256             /* MAX number of SLIP channels;
-                                          This can be overridden with
-                                          insmod -oslip_maxdev=nnn     */
-#define SL_MTU         296             /* 296; I am used to 600- FvK   */
-
-/* SLIP protocol characters. */
-#define END             0300           /* indicates end of frame       */
-#define ESC             0333           /* indicates byte stuffing      */
-#define ESC_END         0334           /* ESC ESC_END means END 'data' */
-#define ESC_ESC         0335           /* ESC ESC_ESC means ESC 'data' */
-
-
-struct slip {
-  int                  magic;
-
-  /* Various fields. */
-  struct tty_struct    *tty;           /* ptr to TTY structure         */
-  struct net_device    *dev;           /* easy for intr handling       */
-  spinlock_t           lock;
-
-#ifdef SL_INCLUDE_CSLIP
-  struct slcompress    *slcomp;        /* for header compression       */
-  unsigned char                *cbuff;         /* compression buffer           */
-#endif
-
-  /* These are pointers to the malloc()ed frame buffers. */
-  unsigned char                *rbuff;         /* receiver buffer              */
-  int                   rcount;         /* received chars counter       */
-  unsigned char                *xbuff;         /* transmitter buffer           */
-  unsigned char         *xhead;         /* pointer to next byte to XMIT */
-  int                   xleft;          /* bytes left in XMIT queue     */
-  int                  mtu;            /* Our mtu (to spot changes!)   */
-  int                   buffsize;       /* Max buffers sizes            */
-
-#ifdef CONFIG_SLIP_MODE_SLIP6
-  int                  xdata, xbits;   /* 6 bit slip controls          */
-#endif
-
-  unsigned long                flags;          /* Flag values/ mode etc        */
-#define SLF_INUSE      0               /* Channel in use               */
-#define SLF_ESCAPE     1               /* ESC received                 */
-#define SLF_ERROR      2               /* Parity, etc. error           */
-#define SLF_KEEPTEST   3               /* Keepalive test flag          */
-#define SLF_OUTWAIT    4               /* is outpacket was flag        */
-
-  unsigned char                mode;           /* SLIP mode                    */
-  unsigned char                leased;
-  pid_t                        pid;
-#define SL_MODE_SLIP   0
-#define SL_MODE_CSLIP  1
-#define SL_MODE_SLIP6  2               /* Matt Dillon's printable slip */
-#define SL_MODE_CSLIP6 (SL_MODE_SLIP6|SL_MODE_CSLIP)
-#define SL_MODE_AX25   4
-#define SL_MODE_ADAPTIVE 8
-#ifdef CONFIG_SLIP_SMART
-  unsigned char                outfill;        /* # of sec between outfill packet */
-  unsigned char                keepalive;      /* keepalive seconds            */
-  struct timer_list    outfill_timer;
-  struct timer_list    keepalive_timer;
-#endif
-};
-
-#define SLIP_MAGIC 0x5302
-
-#endif /* _LINUX_SLIP.H */
diff --git a/drivers/net/slip/Kconfig b/drivers/net/slip/Kconfig
new file mode 100644 (file)
index 0000000..211b160
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# SLIP network device configuration
+#
+
+config SLIP
+       tristate "SLIP (serial line) support"
+       ---help---
+         Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
+         connect to your Internet service provider or to connect to some
+         other local Unix box or if you want to configure your Linux box as a
+         Slip/CSlip server for other people to dial in. SLIP (Serial Line
+         Internet Protocol) is a protocol used to send Internet traffic over
+         serial connections such as telephone lines or null modem cables;
+         nowadays, the protocol PPP is more commonly used for this same
+         purpose.
+
+         Normally, your access provider has to support SLIP in order for you
+         to be able to use it, but there is now a SLIP emulator called SLiRP
+         around (available from
+         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+         allows you to use SLIP over a regular dial up shell connection. If
+         you plan to use SLiRP, make sure to say Y to CSLIP, below. The
+         NET-3-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, explains how to
+         configure SLIP. Note that you don't need this option if you just
+         want to run term (term is a program which gives you almost full
+         Internet connectivity if you have a regular dial up shell account on
+         some Internet connected Unix computer. Read
+         <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
+         support will enlarge your kernel by about 4 KB. If unsure, say N.
+
+         To compile this driver as a module, choose M here. The module
+         will be called slip.
+
+config SLHC
+       tristate
+       ---help---
+         This option enables Van Jacobsen serial line header compression
+         routines.
+
+if SLIP
+
+config SLIP_COMPRESSED
+       bool "CSLIP compressed headers"
+       depends on SLIP
+       select SLHC
+       ---help---
+         This protocol is faster than SLIP because it uses compression on the
+         TCP/IP headers (not on the data itself), but it has to be supported
+         on both ends. Ask your access provider if you are not sure and
+         answer Y, just in case. You will still be able to use plain SLIP. If
+         you plan to use SLiRP, the SLIP emulator (available from
+         <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
+         allows you to use SLIP over a regular dial up shell connection, you
+         definitely want to say Y here. The NET-3-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>, explains how to configure
+         CSLIP. This won't enlarge your kernel.
+
+config SLIP_SMART
+       bool "Keepalive and linefill"
+       depends on SLIP
+       ---help---
+         Adds additional capabilities to the SLIP driver to support the
+         RELCOM line fill and keepalive monitoring. Ideal on poor quality
+         analogue lines.
+
+config SLIP_MODE_SLIP6
+       bool "Six bit SLIP encapsulation"
+       depends on SLIP
+       ---help---
+         Just occasionally you may need to run IP over hostile serial
+         networks that don't pass all control characters or are only seven
+         bit. Saying Y here adds an extra mode you can use with SLIP:
+         "slip6". In this mode, SLIP will only send normal ASCII symbols over
+         the serial device. Naturally, this has to be supported at the other
+         end of the link as well. It's good enough, for example, to run IP
+         over the async ports of a Camtec JNT Pad. If unsure, say N.
+
+endif # SLIP
diff --git a/drivers/net/slip/Makefile b/drivers/net/slip/Makefile
new file mode 100644 (file)
index 0000000..e3ebc59
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the SLIP network device drivers.
+#
+
+obj-$(CONFIG_SLIP) += slip.o
+obj-$(CONFIG_SLHC) += slhc.o
diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
new file mode 100644 (file)
index 0000000..0a0a664
--- /dev/null
@@ -0,0 +1,742 @@
+/*
+ * Routines to compress and uncompress tcp packets (for transmission
+ * over low speed serial lines).
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ *     - Initial distribution.
+ *
+ *
+ * modified for KA9Q Internet Software Package by
+ * Katie Stevens (dkstevens@ucdavis.edu)
+ * University of California, Davis
+ * Computing Services
+ *     - 01-31-90      initial adaptation (from 1.19)
+ *     PPP.05  02-15-90 [ks]
+ *     PPP.08  05-02-90 [ks]   use PPP protocol field to signal compression
+ *     PPP.15  09-90    [ks]   improve mbuf handling
+ *     PPP.16  11-02    [karn] substantially rewritten to use NOS facilities
+ *
+ *     - Feb 1991      Bill_Simpson@um.cc.umich.edu
+ *                     variable number of conversation slots
+ *                     allow zero or one slots
+ *                     separate routines
+ *                     status display
+ *     - Jul 1994      Dmitry Gorodchanin
+ *                     Fixes for memory leaks.
+ *      - Oct 1994      Dmitry Gorodchanin
+ *                      Modularization.
+ *     - Jan 1995      Bjorn Ekwall
+ *                     Use ip_fast_csum from ip.h
+ *     - July 1995     Christos A. Polyzols
+ *                     Spotted bug in tcp option checking
+ *
+ *
+ *     This module is a difficult issue. It's clearly inet code but it's also clearly
+ *     driver code belonging close to PPP and SLIP
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <net/slhc_vj.h>
+
+#ifdef CONFIG_INET
+/* Entire module is for IP only */
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/termios.h>
+#include <linux/in.h>
+#include <linux/fcntl.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/timer.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <net/checksum.h>
+#include <asm/unaligned.h>
+
+static unsigned char *encode(unsigned char *cp, unsigned short n);
+static long decode(unsigned char **cpp);
+static unsigned char * put16(unsigned char *cp, unsigned short x);
+static unsigned short pull16(unsigned char **cpp);
+
+/* Initialize compression data structure
+ *     slots must be in range 0 to 255 (zero meaning no compression)
+ */
+struct slcompress *
+slhc_init(int rslots, int tslots)
+{
+       register short i;
+       register struct cstate *ts;
+       struct slcompress *comp;
+
+       comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
+       if (! comp)
+               goto out_fail;
+
+       if ( rslots > 0  &&  rslots < 256 ) {
+               size_t rsize = rslots * sizeof(struct cstate);
+               comp->rstate = kzalloc(rsize, GFP_KERNEL);
+               if (! comp->rstate)
+                       goto out_free;
+               comp->rslot_limit = rslots - 1;
+       }
+
+       if ( tslots > 0  &&  tslots < 256 ) {
+               size_t tsize = tslots * sizeof(struct cstate);
+               comp->tstate = kzalloc(tsize, GFP_KERNEL);
+               if (! comp->tstate)
+                       goto out_free2;
+               comp->tslot_limit = tslots - 1;
+       }
+
+       comp->xmit_oldest = 0;
+       comp->xmit_current = 255;
+       comp->recv_current = 255;
+       /*
+        * don't accept any packets with implicit index until we get
+        * one with an explicit index.  Otherwise the uncompress code
+        * will try to use connection 255, which is almost certainly
+        * out of range
+        */
+       comp->flags |= SLF_TOSS;
+
+       if ( tslots > 0 ) {
+               ts = comp->tstate;
+               for(i = comp->tslot_limit; i > 0; --i){
+                       ts[i].cs_this = i;
+                       ts[i].next = &(ts[i - 1]);
+               }
+               ts[0].next = &(ts[comp->tslot_limit]);
+               ts[0].cs_this = 0;
+       }
+       return comp;
+
+out_free2:
+       kfree(comp->rstate);
+out_free:
+       kfree(comp);
+out_fail:
+       return NULL;
+}
+
+
+/* Free a compression data structure */
+void
+slhc_free(struct slcompress *comp)
+{
+       if ( comp == NULLSLCOMPR )
+               return;
+
+       if ( comp->tstate != NULLSLSTATE )
+               kfree( comp->tstate );
+
+       if ( comp->rstate != NULLSLSTATE )
+               kfree( comp->rstate );
+
+       kfree( comp );
+}
+
+
+/* Put a short in host order into a char array in network order */
+static inline unsigned char *
+put16(unsigned char *cp, unsigned short x)
+{
+       *cp++ = x >> 8;
+       *cp++ = x;
+
+       return cp;
+}
+
+
+/* Encode a number */
+static unsigned char *
+encode(unsigned char *cp, unsigned short n)
+{
+       if(n >= 256 || n == 0){
+               *cp++ = 0;
+               cp = put16(cp,n);
+       } else {
+               *cp++ = n;
+       }
+       return cp;
+}
+
+/* Pull a 16-bit integer in host order from buffer in network byte order */
+static unsigned short
+pull16(unsigned char **cpp)
+{
+       short rval;
+
+       rval = *(*cpp)++;
+       rval <<= 8;
+       rval |= *(*cpp)++;
+       return rval;
+}
+
+/* Decode a number */
+static long
+decode(unsigned char **cpp)
+{
+       register int x;
+
+       x = *(*cpp)++;
+       if(x == 0){
+               return pull16(cpp) & 0xffff;    /* pull16 returns -1 on error */
+       } else {
+               return x & 0xff;                /* -1 if PULLCHAR returned error */
+       }
+}
+
+/*
+ * icp and isize are the original packet.
+ * ocp is a place to put a copy if necessary.
+ * cpp is initially a pointer to icp.  If the copy is used,
+ *    change it to ocp.
+ */
+
+int
+slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
+       unsigned char *ocp, unsigned char **cpp, int compress_cid)
+{
+       register struct cstate *ocs = &(comp->tstate[comp->xmit_oldest]);
+       register struct cstate *lcs = ocs;
+       register struct cstate *cs = lcs->next;
+       register unsigned long deltaS, deltaA;
+       register short changes = 0;
+       int hlen;
+       unsigned char new_seq[16];
+       register unsigned char *cp = new_seq;
+       struct iphdr *ip;
+       struct tcphdr *th, *oth;
+       __sum16 csum;
+
+
+       /*
+        *      Don't play with runt packets.
+        */
+
+       if(isize<sizeof(struct iphdr))
+               return isize;
+
+       ip = (struct iphdr *) icp;
+
+       /* Bail if this packet isn't TCP, or is an IP fragment */
+       if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
+               /* Send as regular IP */
+               if(ip->protocol != IPPROTO_TCP)
+                       comp->sls_o_nontcp++;
+               else
+                       comp->sls_o_tcp++;
+               return isize;
+       }
+       /* Extract TCP header */
+
+       th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
+       hlen = ip->ihl*4 + th->doff*4;
+
+       /*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
+        *  some other control bit is set). Also uncompressible if
+        *  it's a runt.
+        */
+       if(hlen > isize || th->syn || th->fin || th->rst ||
+           ! (th->ack)){
+               /* TCP connection stuff; send as regular IP */
+               comp->sls_o_tcp++;
+               return isize;
+       }
+       /*
+        * Packet is compressible -- we're going to send either a
+        * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way,
+        * we need to locate (or create) the connection state.
+        *
+        * States are kept in a circularly linked list with
+        * xmit_oldest pointing to the end of the list.  The
+        * list is kept in lru order by moving a state to the
+        * head of the list whenever it is referenced.  Since
+        * the list is short and, empirically, the connection
+        * we want is almost always near the front, we locate
+        * states via linear search.  If we don't find a state
+        * for the datagram, the oldest state is (re-)used.
+        */
+       for ( ; ; ) {
+               if( ip->saddr == cs->cs_ip.saddr
+                && ip->daddr == cs->cs_ip.daddr
+                && th->source == cs->cs_tcp.source
+                && th->dest == cs->cs_tcp.dest)
+                       goto found;
+
+               /* if current equal oldest, at end of list */
+               if ( cs == ocs )
+                       break;
+               lcs = cs;
+               cs = cs->next;
+               comp->sls_o_searches++;
+       }
+       /*
+        * Didn't find it -- re-use oldest cstate.  Send an
+        * uncompressed packet that tells the other side what
+        * connection number we're using for this conversation.
+        *
+        * Note that since the state list is circular, the oldest
+        * state points to the newest and we only need to set
+        * xmit_oldest to update the lru linkage.
+        */
+       comp->sls_o_misses++;
+       comp->xmit_oldest = lcs->cs_this;
+       goto uncompressed;
+
+found:
+       /*
+        * Found it -- move to the front on the connection list.
+        */
+       if(lcs == ocs) {
+               /* found at most recently used */
+       } else if (cs == ocs) {
+               /* found at least recently used */
+               comp->xmit_oldest = lcs->cs_this;
+       } else {
+               /* more than 2 elements */
+               lcs->next = cs->next;
+               cs->next = ocs->next;
+               ocs->next = cs;
+       }
+
+       /*
+        * Make sure that only what we expect to change changed.
+        * Check the following:
+        * IP protocol version, header length & type of service.
+        * The "Don't fragment" bit.
+        * The time-to-live field.
+        * The TCP header length.
+        * IP options, if any.
+        * TCP options, if any.
+        * If any of these things are different between the previous &
+        * current datagram, we send the current datagram `uncompressed'.
+        */
+       oth = &cs->cs_tcp;
+
+       if(ip->version != cs->cs_ip.version || ip->ihl != cs->cs_ip.ihl
+        || ip->tos != cs->cs_ip.tos
+        || (ip->frag_off & htons(0x4000)) != (cs->cs_ip.frag_off & htons(0x4000))
+        || ip->ttl != cs->cs_ip.ttl
+        || th->doff != cs->cs_tcp.doff
+        || (ip->ihl > 5 && memcmp(ip+1,cs->cs_ipopt,((ip->ihl)-5)*4) != 0)
+        || (th->doff > 5 && memcmp(th+1,cs->cs_tcpopt,((th->doff)-5)*4) != 0)){
+               goto uncompressed;
+       }
+
+       /*
+        * Figure out which of the changing fields changed.  The
+        * receiver expects changes in the order: urgent, window,
+        * ack, seq (the order minimizes the number of temporaries
+        * needed in this section of code).
+        */
+       if(th->urg){
+               deltaS = ntohs(th->urg_ptr);
+               cp = encode(cp,deltaS);
+               changes |= NEW_U;
+       } else if(th->urg_ptr != oth->urg_ptr){
+               /* argh! URG not set but urp changed -- a sensible
+                * implementation should never do this but RFC793
+                * doesn't prohibit the change so we have to deal
+                * with it. */
+               goto uncompressed;
+       }
+       if((deltaS = ntohs(th->window) - ntohs(oth->window)) != 0){
+               cp = encode(cp,deltaS);
+               changes |= NEW_W;
+       }
+       if((deltaA = ntohl(th->ack_seq) - ntohl(oth->ack_seq)) != 0L){
+               if(deltaA > 0x0000ffff)
+                       goto uncompressed;
+               cp = encode(cp,deltaA);
+               changes |= NEW_A;
+       }
+       if((deltaS = ntohl(th->seq) - ntohl(oth->seq)) != 0L){
+               if(deltaS > 0x0000ffff)
+                       goto uncompressed;
+               cp = encode(cp,deltaS);
+               changes |= NEW_S;
+       }
+
+       switch(changes){
+       case 0: /* Nothing changed. If this packet contains data and the
+                * last one didn't, this is probably a data packet following
+                * an ack (normal on an interactive connection) and we send
+                * it compressed.  Otherwise it's probably a retransmit,
+                * retransmitted ack or window probe.  Send it uncompressed
+                * in case the other side missed the compressed version.
+                */
+               if(ip->tot_len != cs->cs_ip.tot_len &&
+                  ntohs(cs->cs_ip.tot_len) == hlen)
+                       break;
+               goto uncompressed;
+               break;
+       case SPECIAL_I:
+       case SPECIAL_D:
+               /* actual changes match one of our special case encodings --
+                * send packet uncompressed.
+                */
+               goto uncompressed;
+       case NEW_S|NEW_A:
+               if(deltaS == deltaA &&
+                   deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
+                       /* special case for echoed terminal traffic */
+                       changes = SPECIAL_I;
+                       cp = new_seq;
+               }
+               break;
+       case NEW_S:
+               if(deltaS == ntohs(cs->cs_ip.tot_len) - hlen){
+                       /* special case for data xfer */
+                       changes = SPECIAL_D;
+                       cp = new_seq;
+               }
+               break;
+       }
+       deltaS = ntohs(ip->id) - ntohs(cs->cs_ip.id);
+       if(deltaS != 1){
+               cp = encode(cp,deltaS);
+               changes |= NEW_I;
+       }
+       if(th->psh)
+               changes |= TCP_PUSH_BIT;
+       /* Grab the cksum before we overwrite it below.  Then update our
+        * state with this packet's header.
+        */
+       csum = th->check;
+       memcpy(&cs->cs_ip,ip,20);
+       memcpy(&cs->cs_tcp,th,20);
+       /* We want to use the original packet as our compressed packet.
+        * (cp - new_seq) is the number of bytes we need for compressed
+        * sequence numbers.  In addition we need one byte for the change
+        * mask, one for the connection id and two for the tcp checksum.
+        * So, (cp - new_seq) + 4 bytes of header are needed.
+        */
+       deltaS = cp - new_seq;
+       if(compress_cid == 0 || comp->xmit_current != cs->cs_this){
+               cp = ocp;
+               *cpp = ocp;
+               *cp++ = changes | NEW_C;
+               *cp++ = cs->cs_this;
+               comp->xmit_current = cs->cs_this;
+       } else {
+               cp = ocp;
+               *cpp = ocp;
+               *cp++ = changes;
+       }
+       *(__sum16 *)cp = csum;
+       cp += 2;
+/* deltaS is now the size of the change section of the compressed header */
+       memcpy(cp,new_seq,deltaS);      /* Write list of deltas */
+       memcpy(cp+deltaS,icp+hlen,isize-hlen);
+       comp->sls_o_compressed++;
+       ocp[0] |= SL_TYPE_COMPRESSED_TCP;
+       return isize - hlen + deltaS + (cp - ocp);
+
+       /* Update connection state cs & send uncompressed packet (i.e.,
+        * a regular ip/tcp packet but with the 'conversation id' we hope
+        * to use on future compressed packets in the protocol field).
+        */
+uncompressed:
+       memcpy(&cs->cs_ip,ip,20);
+       memcpy(&cs->cs_tcp,th,20);
+       if (ip->ihl > 5)
+         memcpy(cs->cs_ipopt, ip+1, ((ip->ihl) - 5) * 4);
+       if (th->doff > 5)
+         memcpy(cs->cs_tcpopt, th+1, ((th->doff) - 5) * 4);
+       comp->xmit_current = cs->cs_this;
+       comp->sls_o_uncompressed++;
+       memcpy(ocp, icp, isize);
+       *cpp = ocp;
+       ocp[9] = cs->cs_this;
+       ocp[0] |= SL_TYPE_UNCOMPRESSED_TCP;
+       return isize;
+}
+
+
+int
+slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
+{
+       register int changes;
+       long x;
+       register struct tcphdr *thp;
+       register struct iphdr *ip;
+       register struct cstate *cs;
+       int len, hdrlen;
+       unsigned char *cp = icp;
+
+       /* We've got a compressed packet; read the change byte */
+       comp->sls_i_compressed++;
+       if(isize < 3){
+               comp->sls_i_error++;
+               return 0;
+       }
+       changes = *cp++;
+       if(changes & NEW_C){
+               /* Make sure the state index is in range, then grab the state.
+                * If we have a good state index, clear the 'discard' flag.
+                */
+               x = *cp++;      /* Read conn index */
+               if(x < 0 || x > comp->rslot_limit)
+                       goto bad;
+
+               comp->flags &=~ SLF_TOSS;
+               comp->recv_current = x;
+       } else {
+               /* this packet has an implicit state index.  If we've
+                * had a line error since the last time we got an
+                * explicit state index, we have to toss the packet. */
+               if(comp->flags & SLF_TOSS){
+                       comp->sls_i_tossed++;
+                       return 0;
+               }
+       }
+       cs = &comp->rstate[comp->recv_current];
+       thp = &cs->cs_tcp;
+       ip = &cs->cs_ip;
+
+       thp->check = *(__sum16 *)cp;
+       cp += 2;
+
+       thp->psh = (changes & TCP_PUSH_BIT) ? 1 : 0;
+/*
+ * we can use the same number for the length of the saved header and
+ * the current one, because the packet wouldn't have been sent
+ * as compressed unless the options were the same as the previous one
+ */
+
+       hdrlen = ip->ihl * 4 + thp->doff * 4;
+
+       switch(changes & SPECIALS_MASK){
+       case SPECIAL_I:         /* Echoed terminal traffic */
+               {
+               register short i;
+               i = ntohs(ip->tot_len) - hdrlen;
+               thp->ack_seq = htonl( ntohl(thp->ack_seq) + i);
+               thp->seq = htonl( ntohl(thp->seq) + i);
+               }
+               break;
+
+       case SPECIAL_D:                 /* Unidirectional data */
+               thp->seq = htonl( ntohl(thp->seq) +
+                                 ntohs(ip->tot_len) - hdrlen);
+               break;
+
+       default:
+               if(changes & NEW_U){
+                       thp->urg = 1;
+                       if((x = decode(&cp)) == -1) {
+                               goto bad;
+                       }
+                       thp->urg_ptr = htons(x);
+               } else
+                       thp->urg = 0;
+               if(changes & NEW_W){
+                       if((x = decode(&cp)) == -1) {
+                               goto bad;
+                       }
+                       thp->window = htons( ntohs(thp->window) + x);
+               }
+               if(changes & NEW_A){
+                       if((x = decode(&cp)) == -1) {
+                               goto bad;
+                       }
+                       thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
+               }
+               if(changes & NEW_S){
+                       if((x = decode(&cp)) == -1) {
+                               goto bad;
+                       }
+                       thp->seq = htonl( ntohl(thp->seq) + x);
+               }
+               break;
+       }
+       if(changes & NEW_I){
+               if((x = decode(&cp)) == -1) {
+                       goto bad;
+               }
+               ip->id = htons (ntohs (ip->id) + x);
+       } else
+               ip->id = htons (ntohs (ip->id) + 1);
+
+       /*
+        * At this point, cp points to the first byte of data in the
+        * packet.  Put the reconstructed TCP and IP headers back on the
+        * packet.  Recalculate IP checksum (but not TCP checksum).
+        */
+
+       len = isize - (cp - icp);
+       if (len < 0)
+               goto bad;
+       len += hdrlen;
+       ip->tot_len = htons(len);
+       ip->check = 0;
+
+       memmove(icp + hdrlen, cp, len - hdrlen);
+
+       cp = icp;
+       memcpy(cp, ip, 20);
+       cp += 20;
+
+       if (ip->ihl > 5) {
+         memcpy(cp, cs->cs_ipopt, (ip->ihl - 5) * 4);
+         cp += (ip->ihl - 5) * 4;
+       }
+
+       put_unaligned(ip_fast_csum(icp, ip->ihl),
+                     &((struct iphdr *)icp)->check);
+
+       memcpy(cp, thp, 20);
+       cp += 20;
+
+       if (thp->doff > 5) {
+         memcpy(cp, cs->cs_tcpopt, ((thp->doff) - 5) * 4);
+         cp += ((thp->doff) - 5) * 4;
+       }
+
+       return len;
+bad:
+       comp->sls_i_error++;
+       return slhc_toss( comp );
+}
+
+
+int
+slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
+{
+       register struct cstate *cs;
+       unsigned ihl;
+
+       unsigned char index;
+
+       if(isize < 20) {
+               /* The packet is shorter than a legal IP header */
+               comp->sls_i_runt++;
+               return slhc_toss( comp );
+       }
+       /* Peek at the IP header's IHL field to find its length */
+       ihl = icp[0] & 0xf;
+       if(ihl < 20 / 4){
+               /* The IP header length field is too small */
+               comp->sls_i_runt++;
+               return slhc_toss( comp );
+       }
+       index = icp[9];
+       icp[9] = IPPROTO_TCP;
+
+       if (ip_fast_csum(icp, ihl)) {
+               /* Bad IP header checksum; discard */
+               comp->sls_i_badcheck++;
+               return slhc_toss( comp );
+       }
+       if(index > comp->rslot_limit) {
+               comp->sls_i_error++;
+               return slhc_toss(comp);
+       }
+
+       /* Update local state */
+       cs = &comp->rstate[comp->recv_current = index];
+       comp->flags &=~ SLF_TOSS;
+       memcpy(&cs->cs_ip,icp,20);
+       memcpy(&cs->cs_tcp,icp + ihl*4,20);
+       if (ihl > 5)
+         memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
+       if (cs->cs_tcp.doff > 5)
+         memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
+       cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
+       /* Put headers back on packet
+        * Neither header checksum is recalculated
+        */
+       comp->sls_i_uncompressed++;
+       return isize;
+}
+
+int
+slhc_toss(struct slcompress *comp)
+{
+       if ( comp == NULLSLCOMPR )
+               return 0;
+
+       comp->flags |= SLF_TOSS;
+       return 0;
+}
+
+#else /* CONFIG_INET */
+
+int
+slhc_toss(struct slcompress *comp)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
+  return -EINVAL;
+}
+int
+slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
+  return -EINVAL;
+}
+int
+slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
+       unsigned char *ocp, unsigned char **cpp, int compress_cid)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
+  return -EINVAL;
+}
+
+int
+slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
+  return -EINVAL;
+}
+
+void
+slhc_free(struct slcompress *comp)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
+}
+struct slcompress *
+slhc_init(int rslots, int tslots)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
+  return NULL;
+}
+
+#endif /* CONFIG_INET */
+
+/* VJ header compression */
+EXPORT_SYMBOL(slhc_init);
+EXPORT_SYMBOL(slhc_free);
+EXPORT_SYMBOL(slhc_remember);
+EXPORT_SYMBOL(slhc_compress);
+EXPORT_SYMBOL(slhc_uncompress);
+EXPORT_SYMBOL(slhc_toss);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
new file mode 100644 (file)
index 0000000..ba08341
--- /dev/null
@@ -0,0 +1,1444 @@
+/*
+ * slip.c      This module implements the SLIP protocol for kernel-based
+ *             devices like TTY.  It interfaces between a raw TTY, and the
+ *             kernel's INET protocol layers.
+ *
+ * Version:    @(#)slip.c      0.8.3   12/24/94
+ *
+ * Authors:    Laurence Culhane, <loz@holmes.demon.co.uk>
+ *             Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ * Fixes:
+ *             Alan Cox        :       Sanity checks and avoid tx overruns.
+ *                                     Has a new sl->mtu field.
+ *             Alan Cox        :       Found cause of overrun. ifconfig sl0
+ *                                     mtu upwards. Driver now spots this
+ *                                     and grows/shrinks its buffers(hack!).
+ *                                     Memory leak if you run out of memory
+ *                                     setting up a slip driver fixed.
+ *             Matt Dillon     :       Printable slip (borrowed from NET2E)
+ *     Pauline Middelink       :       Slip driver fixes.
+ *             Alan Cox        :       Honours the old SL_COMPRESSED flag
+ *             Alan Cox        :       KISS AX.25 and AXUI IP support
+ *             Michael Riepe   :       Automatic CSLIP recognition added
+ *             Charles Hedrick :       CSLIP header length problem fix.
+ *             Alan Cox        :       Corrected non-IP cases of the above.
+ *             Alan Cox        :       Now uses hardware type as per FvK.
+ *             Alan Cox        :       Default to 192.168.0.0 (RFC 1597)
+ *             A.N.Kuznetsov   :       dev_tint() recursion fix.
+ *     Dmitry Gorodchanin      :       SLIP memory leaks
+ *      Dmitry Gorodchanin      :       Code cleanup. Reduce tty driver
+ *                                      buffering from 4096 to 256 bytes.
+ *                                      Improving SLIP response time.
+ *                                      CONFIG_SLIP_MODE_SLIP6.
+ *                                      ifconfig sl? up & down now works
+ *                                     correctly.
+ *                                     Modularization.
+ *              Alan Cox        :       Oops - fix AX.25 buffer lengths
+ *      Dmitry Gorodchanin      :       Even more cleanups. Preserve CSLIP
+ *                                      statistics. Include CSLIP code only
+ *                                      if it really needed.
+ *             Alan Cox        :       Free slhc buffers in the right place.
+ *             Alan Cox        :       Allow for digipeated IP over AX.25
+ *             Matti Aarnio    :       Dynamic SLIP devices, with ideas taken
+ *                                     from Jim Freeman's <jfree@caldera.com>
+ *                                     dynamic PPP devices.  We do NOT kfree()
+ *                                     device entries, just reg./unreg. them
+ *                                     as they are needed.  We kfree() them
+ *                                     at module cleanup.
+ *                                     With MODULE-loading ``insmod'', user
+ *                                     can issue parameter:  slip_maxdev=1024
+ *                                     (Or how much he/she wants.. Default
+ *                                     is 256)
+ *     Stanislav Voronyi       :       Slip line checking, with ideas taken
+ *                                     from multislip BSDI driver which was
+ *                                     written by Igor Chechik, RELCOM Corp.
+ *                                     Only algorithms have been ported to
+ *                                     Linux SLIP driver.
+ *     Vitaly E. Lavrov        :       Sane behaviour on tty hangup.
+ *     Alexey Kuznetsov        :       Cleanup interfaces to tty & netdevice
+ *                                     modules.
+ */
+
+#define SL_CHECK_TRANSMIT
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/bitops.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/if_slip.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include "slip.h"
+#ifdef CONFIG_INET
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/slhc_vj.h>
+#endif
+
+#define SLIP_VERSION   "0.8.4-NET3.019-NEWTTY"
+
+static struct net_device **slip_devs;
+
+static int slip_maxdev = SL_NRUNIT;
+module_param(slip_maxdev, int, 0);
+MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices");
+
+static int slip_esc(unsigned char *p, unsigned char *d, int len);
+static void slip_unesc(struct slip *sl, unsigned char c);
+#ifdef CONFIG_SLIP_MODE_SLIP6
+static int slip_esc6(unsigned char *p, unsigned char *d, int len);
+static void slip_unesc6(struct slip *sl, unsigned char c);
+#endif
+#ifdef CONFIG_SLIP_SMART
+static void sl_keepalive(unsigned long sls);
+static void sl_outfill(unsigned long sls);
+static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif
+
+/********************************
+*  Buffer administration routines:
+*      sl_alloc_bufs()
+*      sl_free_bufs()
+*      sl_realloc_bufs()
+*
+* NOTE: sl_realloc_bufs != sl_free_bufs + sl_alloc_bufs, because
+*      sl_realloc_bufs provides strong atomicity and reallocation
+*      on actively running device.
+*********************************/
+
+/*
+   Allocate channel buffers.
+ */
+
+static int sl_alloc_bufs(struct slip *sl, int mtu)
+{
+       int err = -ENOBUFS;
+       unsigned long len;
+       char *rbuff = NULL;
+       char *xbuff = NULL;
+#ifdef SL_INCLUDE_CSLIP
+       char *cbuff = NULL;
+       struct slcompress *slcomp = NULL;
+#endif
+
+       /*
+        * Allocate the SLIP frame buffers:
+        *
+        * rbuff        Receive buffer.
+        * xbuff        Transmit buffer.
+        * cbuff        Temporary compression buffer.
+        */
+       len = mtu * 2;
+
+       /*
+        * allow for arrival of larger UDP packets, even if we say not to
+        * also fixes a bug in which SunOS sends 512-byte packets even with
+        * an MSS of 128
+        */
+       if (len < 576 * 2)
+               len = 576 * 2;
+       rbuff = kmalloc(len + 4, GFP_KERNEL);
+       if (rbuff == NULL)
+               goto err_exit;
+       xbuff = kmalloc(len + 4, GFP_KERNEL);
+       if (xbuff == NULL)
+               goto err_exit;
+#ifdef SL_INCLUDE_CSLIP
+       cbuff = kmalloc(len + 4, GFP_KERNEL);
+       if (cbuff == NULL)
+               goto err_exit;
+       slcomp = slhc_init(16, 16);
+       if (slcomp == NULL)
+               goto err_exit;
+#endif
+       spin_lock_bh(&sl->lock);
+       if (sl->tty == NULL) {
+               spin_unlock_bh(&sl->lock);
+               err = -ENODEV;
+               goto err_exit;
+       }
+       sl->mtu      = mtu;
+       sl->buffsize = len;
+       sl->rcount   = 0;
+       sl->xleft    = 0;
+       rbuff = xchg(&sl->rbuff, rbuff);
+       xbuff = xchg(&sl->xbuff, xbuff);
+#ifdef SL_INCLUDE_CSLIP
+       cbuff = xchg(&sl->cbuff, cbuff);
+       slcomp = xchg(&sl->slcomp, slcomp);
+#endif
+#ifdef CONFIG_SLIP_MODE_SLIP6
+       sl->xdata    = 0;
+       sl->xbits    = 0;
+#endif
+       spin_unlock_bh(&sl->lock);
+       err = 0;
+
+       /* Cleanup */
+err_exit:
+#ifdef SL_INCLUDE_CSLIP
+       kfree(cbuff);
+       slhc_free(slcomp);
+#endif
+       kfree(xbuff);
+       kfree(rbuff);
+       return err;
+}
+
+/* Free a SLIP channel buffers. */
+static void sl_free_bufs(struct slip *sl)
+{
+       /* Free all SLIP frame buffers. */
+       kfree(xchg(&sl->rbuff, NULL));
+       kfree(xchg(&sl->xbuff, NULL));
+#ifdef SL_INCLUDE_CSLIP
+       kfree(xchg(&sl->cbuff, NULL));
+       slhc_free(xchg(&sl->slcomp, NULL));
+#endif
+}
+
+/*
+   Reallocate slip channel buffers.
+ */
+
+static int sl_realloc_bufs(struct slip *sl, int mtu)
+{
+       int err = 0;
+       struct net_device *dev = sl->dev;
+       unsigned char *xbuff, *rbuff;
+#ifdef SL_INCLUDE_CSLIP
+       unsigned char *cbuff;
+#endif
+       int len = mtu * 2;
+
+/*
+ * allow for arrival of larger UDP packets, even if we say not to
+ * also fixes a bug in which SunOS sends 512-byte packets even with
+ * an MSS of 128
+ */
+       if (len < 576 * 2)
+               len = 576 * 2;
+
+       xbuff = kmalloc(len + 4, GFP_ATOMIC);
+       rbuff = kmalloc(len + 4, GFP_ATOMIC);
+#ifdef SL_INCLUDE_CSLIP
+       cbuff = kmalloc(len + 4, GFP_ATOMIC);
+#endif
+
+
+#ifdef SL_INCLUDE_CSLIP
+       if (xbuff == NULL || rbuff == NULL || cbuff == NULL)  {
+#else
+       if (xbuff == NULL || rbuff == NULL)  {
+#endif
+               if (mtu > sl->mtu) {
+                       printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n",
+                              dev->name);
+                       err = -ENOBUFS;
+               }
+               goto done;
+       }
+       spin_lock_bh(&sl->lock);
+
+       err = -ENODEV;
+       if (sl->tty == NULL)
+               goto done_on_bh;
+
+       xbuff    = xchg(&sl->xbuff, xbuff);
+       rbuff    = xchg(&sl->rbuff, rbuff);
+#ifdef SL_INCLUDE_CSLIP
+       cbuff    = xchg(&sl->cbuff, cbuff);
+#endif
+       if (sl->xleft)  {
+               if (sl->xleft <= len)  {
+                       memcpy(sl->xbuff, sl->xhead, sl->xleft);
+               } else  {
+                       sl->xleft = 0;
+                       dev->stats.tx_dropped++;
+               }
+       }
+       sl->xhead = sl->xbuff;
+
+       if (sl->rcount)  {
+               if (sl->rcount <= len) {
+                       memcpy(sl->rbuff, rbuff, sl->rcount);
+               } else  {
+                       sl->rcount = 0;
+                       dev->stats.rx_over_errors++;
+                       set_bit(SLF_ERROR, &sl->flags);
+               }
+       }
+       sl->mtu      = mtu;
+       dev->mtu      = mtu;
+       sl->buffsize = len;
+       err = 0;
+
+done_on_bh:
+       spin_unlock_bh(&sl->lock);
+
+done:
+       kfree(xbuff);
+       kfree(rbuff);
+#ifdef SL_INCLUDE_CSLIP
+       kfree(cbuff);
+#endif
+       return err;
+}
+
+
+/* Set the "sending" flag.  This must be atomic hence the set_bit. */
+static inline void sl_lock(struct slip *sl)
+{
+       netif_stop_queue(sl->dev);
+}
+
+
+/* Clear the "sending" flag.  This must be atomic, hence the ASM. */
+static inline void sl_unlock(struct slip *sl)
+{
+       netif_wake_queue(sl->dev);
+}
+
+/* Send one completely decapsulated IP datagram to the IP layer. */
+static void sl_bump(struct slip *sl)
+{
+       struct net_device *dev = sl->dev;
+       struct sk_buff *skb;
+       int count;
+
+       count = sl->rcount;
+#ifdef SL_INCLUDE_CSLIP
+       if (sl->mode & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) {
+               unsigned char c = sl->rbuff[0];
+               if (c & SL_TYPE_COMPRESSED_TCP) {
+                       /* ignore compressed packets when CSLIP is off */
+                       if (!(sl->mode & SL_MODE_CSLIP)) {
+                               printk(KERN_WARNING "%s: compressed packet ignored\n", dev->name);
+                               return;
+                       }
+                       /* make sure we've reserved enough space for uncompress
+                          to use */
+                       if (count + 80 > sl->buffsize) {
+                               dev->stats.rx_over_errors++;
+                               return;
+                       }
+                       count = slhc_uncompress(sl->slcomp, sl->rbuff, count);
+                       if (count <= 0)
+                               return;
+               } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
+                       if (!(sl->mode & SL_MODE_CSLIP)) {
+                               /* turn on header compression */
+                               sl->mode |= SL_MODE_CSLIP;
+                               sl->mode &= ~SL_MODE_ADAPTIVE;
+                               printk(KERN_INFO "%s: header compression turned on\n", dev->name);
+                       }
+                       sl->rbuff[0] &= 0x4f;
+                       if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0)
+                               return;
+               }
+       }
+#endif  /* SL_INCLUDE_CSLIP */
+
+       dev->stats.rx_bytes += count;
+
+       skb = dev_alloc_skb(count);
+       if (skb == NULL) {
+               printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", dev->name);
+               dev->stats.rx_dropped++;
+               return;
+       }
+       skb->dev = dev;
+       memcpy(skb_put(skb, count), sl->rbuff, count);
+       skb_reset_mac_header(skb);
+       skb->protocol = htons(ETH_P_IP);
+       netif_rx_ni(skb);
+       dev->stats.rx_packets++;
+}
+
+/* Encapsulate one IP datagram and stuff into a TTY queue. */
+static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
+{
+       unsigned char *p;
+       int actual, count;
+
+       if (len > sl->mtu) {            /* Sigh, shouldn't occur BUT ... */
+               printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name);
+               sl->dev->stats.tx_dropped++;
+               sl_unlock(sl);
+               return;
+       }
+
+       p = icp;
+#ifdef SL_INCLUDE_CSLIP
+       if (sl->mode & SL_MODE_CSLIP)
+               len = slhc_compress(sl->slcomp, p, len, sl->cbuff, &p, 1);
+#endif
+#ifdef CONFIG_SLIP_MODE_SLIP6
+       if (sl->mode & SL_MODE_SLIP6)
+               count = slip_esc6(p, (unsigned char *) sl->xbuff, len);
+       else
+#endif
+               count = slip_esc(p, (unsigned char *) sl->xbuff, len);
+
+       /* Order of next two lines is *very* important.
+        * When we are sending a little amount of data,
+        * the transfer may be completed inside the ops->write()
+        * routine, because it's running with interrupts enabled.
+        * In this case we *never* got WRITE_WAKEUP event,
+        * if we did not request it before write operation.
+        *       14 Oct 1994  Dmitry Gorodchanin.
+        */
+       set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+       actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
+#ifdef SL_CHECK_TRANSMIT
+       sl->dev->trans_start = jiffies;
+#endif
+       sl->xleft = count - actual;
+       sl->xhead = sl->xbuff + actual;
+#ifdef CONFIG_SLIP_SMART
+       /* VSV */
+       clear_bit(SLF_OUTWAIT, &sl->flags);     /* reset outfill flag */
+#endif
+}
+
+/*
+ * Called by the driver when there's room for more data.  If we have
+ * more packets to send, we send them here.
+ */
+static void slip_write_wakeup(struct tty_struct *tty)
+{
+       int actual;
+       struct slip *sl = tty->disc_data;
+
+       /* First make sure we're connected. */
+       if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
+               return;
+
+       if (sl->xleft <= 0)  {
+               /* Now serial buffer is almost free & we can start
+                * transmission of another packet */
+               sl->dev->stats.tx_packets++;
+               clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+               sl_unlock(sl);
+               return;
+       }
+
+       actual = tty->ops->write(tty, sl->xhead, sl->xleft);
+       sl->xleft -= actual;
+       sl->xhead += actual;
+}
+
+static void sl_tx_timeout(struct net_device *dev)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       spin_lock(&sl->lock);
+
+       if (netif_queue_stopped(dev)) {
+               if (!netif_running(dev))
+                       goto out;
+
+               /* May be we must check transmitter timeout here ?
+                *      14 Oct 1994 Dmitry Gorodchanin.
+                */
+#ifdef SL_CHECK_TRANSMIT
+               if (time_before(jiffies, dev_trans_start(dev) + 20 * HZ))  {
+                       /* 20 sec timeout not reached */
+                       goto out;
+               }
+               printk(KERN_WARNING "%s: transmit timed out, %s?\n",
+                       dev->name,
+                       (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
+                               "bad line quality" : "driver error");
+               sl->xleft = 0;
+               clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+               sl_unlock(sl);
+#endif
+       }
+out:
+       spin_unlock(&sl->lock);
+}
+
+
+/* Encapsulate an IP datagram and kick it into a TTY queue. */
+static netdev_tx_t
+sl_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       spin_lock(&sl->lock);
+       if (!netif_running(dev)) {
+               spin_unlock(&sl->lock);
+               printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+       if (sl->tty == NULL) {
+               spin_unlock(&sl->lock);
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
+       sl_lock(sl);
+       dev->stats.tx_bytes += skb->len;
+       sl_encaps(sl, skb->data, skb->len);
+       spin_unlock(&sl->lock);
+
+       dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
+}
+
+
+/******************************************
+ *   Routines looking at netdevice side.
+ ******************************************/
+
+/* Netdevice UP -> DOWN routine */
+
+static int
+sl_close(struct net_device *dev)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       spin_lock_bh(&sl->lock);
+       if (sl->tty)
+               /* TTY discipline is running. */
+               clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+       netif_stop_queue(dev);
+       sl->rcount   = 0;
+       sl->xleft    = 0;
+       spin_unlock_bh(&sl->lock);
+
+       return 0;
+}
+
+/* Netdevice DOWN -> UP routine */
+
+static int sl_open(struct net_device *dev)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       if (sl->tty == NULL)
+               return -ENODEV;
+
+       sl->flags &= (1 << SLF_INUSE);
+       netif_start_queue(dev);
+       return 0;
+}
+
+/* Netdevice change MTU request */
+
+static int sl_change_mtu(struct net_device *dev, int new_mtu)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       if (new_mtu < 68 || new_mtu > 65534)
+               return -EINVAL;
+
+       if (new_mtu != dev->mtu)
+               return sl_realloc_bufs(sl, new_mtu);
+       return 0;
+}
+
+/* Netdevice get statistics request */
+
+static struct rtnl_link_stats64 *
+sl_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+       struct net_device_stats *devstats = &dev->stats;
+#ifdef SL_INCLUDE_CSLIP
+       struct slip *sl = netdev_priv(dev);
+       struct slcompress *comp = sl->slcomp;
+#endif
+       stats->rx_packets     = devstats->rx_packets;
+       stats->tx_packets     = devstats->tx_packets;
+       stats->rx_bytes       = devstats->rx_bytes;
+       stats->tx_bytes       = devstats->tx_bytes;
+       stats->rx_dropped     = devstats->rx_dropped;
+       stats->tx_dropped     = devstats->tx_dropped;
+       stats->tx_errors      = devstats->tx_errors;
+       stats->rx_errors      = devstats->rx_errors;
+       stats->rx_over_errors = devstats->rx_over_errors;
+
+#ifdef SL_INCLUDE_CSLIP
+       if (comp) {
+               /* Generic compressed statistics */
+               stats->rx_compressed   = comp->sls_i_compressed;
+               stats->tx_compressed   = comp->sls_o_compressed;
+
+               /* Are we really still needs this? */
+               stats->rx_fifo_errors += comp->sls_i_compressed;
+               stats->rx_dropped     += comp->sls_i_tossed;
+               stats->tx_fifo_errors += comp->sls_o_compressed;
+               stats->collisions     += comp->sls_o_misses;
+       }
+#endif
+       return stats;
+}
+
+/* Netdevice register callback */
+
+static int sl_init(struct net_device *dev)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       /*
+        *      Finish setting up the DEVICE info.
+        */
+
+       dev->mtu                = sl->mtu;
+       dev->type               = ARPHRD_SLIP + sl->mode;
+#ifdef SL_CHECK_TRANSMIT
+       dev->watchdog_timeo     = 20*HZ;
+#endif
+       return 0;
+}
+
+
+static void sl_uninit(struct net_device *dev)
+{
+       struct slip *sl = netdev_priv(dev);
+
+       sl_free_bufs(sl);
+}
+
+/* Hook the destructor so we can free slip devices at the right point in time */
+static void sl_free_netdev(struct net_device *dev)
+{
+       int i = dev->base_addr;
+       free_netdev(dev);
+       slip_devs[i] = NULL;
+}
+
+static const struct net_device_ops sl_netdev_ops = {
+       .ndo_init               = sl_init,
+       .ndo_uninit             = sl_uninit,
+       .ndo_open               = sl_open,
+       .ndo_stop               = sl_close,
+       .ndo_start_xmit         = sl_xmit,
+       .ndo_get_stats64        = sl_get_stats64,
+       .ndo_change_mtu         = sl_change_mtu,
+       .ndo_tx_timeout         = sl_tx_timeout,
+#ifdef CONFIG_SLIP_SMART
+       .ndo_do_ioctl           = sl_ioctl,
+#endif
+};
+
+
+static void sl_setup(struct net_device *dev)
+{
+       dev->netdev_ops         = &sl_netdev_ops;
+       dev->destructor         = sl_free_netdev;
+
+       dev->hard_header_len    = 0;
+       dev->addr_len           = 0;
+       dev->tx_queue_len       = 10;
+
+       /* New-style flags. */
+       dev->flags              = IFF_NOARP|IFF_POINTOPOINT|IFF_MULTICAST;
+}
+
+/******************************************
+  Routines looking at TTY side.
+ ******************************************/
+
+
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of SLIP data has been received, which can now be decapsulated
+ * and sent on to some IP layer for further processing. This will not
+ * be re-entered while running but other ldisc functions may be called
+ * in parallel
+ */
+
+static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+                                                       char *fp, int count)
+{
+       struct slip *sl = tty->disc_data;
+
+       if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
+               return;
+
+       /* Read the characters out of the buffer */
+       while (count--) {
+               if (fp && *fp++) {
+                       if (!test_and_set_bit(SLF_ERROR, &sl->flags))
+                               sl->dev->stats.rx_errors++;
+                       cp++;
+                       continue;
+               }
+#ifdef CONFIG_SLIP_MODE_SLIP6
+               if (sl->mode & SL_MODE_SLIP6)
+                       slip_unesc6(sl, *cp++);
+               else
+#endif
+                       slip_unesc(sl, *cp++);
+       }
+}
+
+/************************************
+ *  slip_open helper routines.
+ ************************************/
+
+/* Collect hanged up channels */
+static void sl_sync(void)
+{
+       int i;
+       struct net_device *dev;
+       struct slip       *sl;
+
+       for (i = 0; i < slip_maxdev; i++) {
+               dev = slip_devs[i];
+               if (dev == NULL)
+                       break;
+
+               sl = netdev_priv(dev);
+               if (sl->tty || sl->leased)
+                       continue;
+               if (dev->flags & IFF_UP)
+                       dev_close(dev);
+       }
+}
+
+
+/* Find a free SLIP channel, and link in this `tty' line. */
+static struct slip *sl_alloc(dev_t line)
+{
+       int i;
+       char name[IFNAMSIZ];
+       struct net_device *dev = NULL;
+       struct slip       *sl;
+
+       for (i = 0; i < slip_maxdev; i++) {
+               dev = slip_devs[i];
+               if (dev == NULL)
+                       break;
+       }
+       /* Sorry, too many, all slots in use */
+       if (i >= slip_maxdev)
+               return NULL;
+
+       sprintf(name, "sl%d", i);
+       dev = alloc_netdev(sizeof(*sl), name, sl_setup);
+       if (!dev)
+               return NULL;
+
+       dev->base_addr  = i;
+       sl = netdev_priv(dev);
+
+       /* Initialize channel control data */
+       sl->magic       = SLIP_MAGIC;
+       sl->dev         = dev;
+       spin_lock_init(&sl->lock);
+       sl->mode        = SL_MODE_DEFAULT;
+#ifdef CONFIG_SLIP_SMART
+       /* initialize timer_list struct */
+       init_timer(&sl->keepalive_timer);
+       sl->keepalive_timer.data = (unsigned long)sl;
+       sl->keepalive_timer.function = sl_keepalive;
+       init_timer(&sl->outfill_timer);
+       sl->outfill_timer.data = (unsigned long)sl;
+       sl->outfill_timer.function = sl_outfill;
+#endif
+       slip_devs[i] = dev;
+       return sl;
+}
+
+/*
+ * Open the high-level part of the SLIP channel.
+ * This function is called by the TTY module when the
+ * SLIP line discipline is called for.  Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free SLIP channel...
+ *
+ * Called in process context serialized from other ldisc calls.
+ */
+
+static int slip_open(struct tty_struct *tty)
+{
+       struct slip *sl;
+       int err;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
+       /* RTnetlink lock is misused here to serialize concurrent
+          opens of slip channels. There are better ways, but it is
+          the simplest one.
+        */
+       rtnl_lock();
+
+       /* Collect hanged up channels. */
+       sl_sync();
+
+       sl = tty->disc_data;
+
+       err = -EEXIST;
+       /* First make sure we're not already connected. */
+       if (sl && sl->magic == SLIP_MAGIC)
+               goto err_exit;
+
+       /* OK.  Find a free SLIP channel to use. */
+       err = -ENFILE;
+       sl = sl_alloc(tty_devnum(tty));
+       if (sl == NULL)
+               goto err_exit;
+
+       sl->tty = tty;
+       tty->disc_data = sl;
+       sl->pid = current->pid;
+
+       if (!test_bit(SLF_INUSE, &sl->flags)) {
+               /* Perform the low-level SLIP initialization. */
+               err = sl_alloc_bufs(sl, SL_MTU);
+               if (err)
+                       goto err_free_chan;
+
+               set_bit(SLF_INUSE, &sl->flags);
+
+               err = register_netdevice(sl->dev);
+               if (err)
+                       goto err_free_bufs;
+       }
+
+#ifdef CONFIG_SLIP_SMART
+       if (sl->keepalive) {
+               sl->keepalive_timer.expires = jiffies + sl->keepalive * HZ;
+               add_timer(&sl->keepalive_timer);
+       }
+       if (sl->outfill) {
+               sl->outfill_timer.expires = jiffies + sl->outfill * HZ;
+               add_timer(&sl->outfill_timer);
+       }
+#endif
+
+       /* Done.  We have linked the TTY line to a channel. */
+       rtnl_unlock();
+       tty->receive_room = 65536;      /* We don't flow control */
+
+       /* TTY layer expects 0 on success */
+       return 0;
+
+err_free_bufs:
+       sl_free_bufs(sl);
+
+err_free_chan:
+       sl->tty = NULL;
+       tty->disc_data = NULL;
+       clear_bit(SLF_INUSE, &sl->flags);
+
+err_exit:
+       rtnl_unlock();
+
+       /* Count references from TTY module */
+       return err;
+}
+
+/*
+ * Close down a SLIP channel.
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
+ *
+ * We also use this method fo a hangup event
+ */
+
+static void slip_close(struct tty_struct *tty)
+{
+       struct slip *sl = tty->disc_data;
+
+       /* First make sure we're connected. */
+       if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty)
+               return;
+
+       tty->disc_data = NULL;
+       sl->tty = NULL;
+
+       /* VSV = very important to remove timers */
+#ifdef CONFIG_SLIP_SMART
+       del_timer_sync(&sl->keepalive_timer);
+       del_timer_sync(&sl->outfill_timer);
+#endif
+       /* Flush network side */
+       unregister_netdev(sl->dev);
+       /* This will complete via sl_free_netdev */
+}
+
+static int slip_hangup(struct tty_struct *tty)
+{
+       slip_close(tty);
+       return 0;
+}
+ /************************************************************************
+  *                    STANDARD SLIP ENCAPSULATION                      *
+  ************************************************************************/
+
+static int slip_esc(unsigned char *s, unsigned char *d, int len)
+{
+       unsigned char *ptr = d;
+       unsigned char c;
+
+       /*
+        * Send an initial END character to flush out any
+        * data that may have accumulated in the receiver
+        * due to line noise.
+        */
+
+       *ptr++ = END;
+
+       /*
+        * For each byte in the packet, send the appropriate
+        * character sequence, according to the SLIP protocol.
+        */
+
+       while (len-- > 0) {
+               switch (c = *s++) {
+               case END:
+                       *ptr++ = ESC;
+                       *ptr++ = ESC_END;
+                       break;
+               case ESC:
+                       *ptr++ = ESC;
+                       *ptr++ = ESC_ESC;
+                       break;
+               default:
+                       *ptr++ = c;
+                       break;
+               }
+       }
+       *ptr++ = END;
+       return ptr - d;
+}
+
+static void slip_unesc(struct slip *sl, unsigned char s)
+{
+
+       switch (s) {
+       case END:
+#ifdef CONFIG_SLIP_SMART
+               /* drop keeptest bit = VSV */
+               if (test_bit(SLF_KEEPTEST, &sl->flags))
+                       clear_bit(SLF_KEEPTEST, &sl->flags);
+#endif
+
+               if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
+                   (sl->rcount > 2))
+                       sl_bump(sl);
+               clear_bit(SLF_ESCAPE, &sl->flags);
+               sl->rcount = 0;
+               return;
+
+       case ESC:
+               set_bit(SLF_ESCAPE, &sl->flags);
+               return;
+       case ESC_ESC:
+               if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
+                       s = ESC;
+               break;
+       case ESC_END:
+               if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
+                       s = END;
+               break;
+       }
+       if (!test_bit(SLF_ERROR, &sl->flags))  {
+               if (sl->rcount < sl->buffsize)  {
+                       sl->rbuff[sl->rcount++] = s;
+                       return;
+               }
+               sl->dev->stats.rx_over_errors++;
+               set_bit(SLF_ERROR, &sl->flags);
+       }
+}
+
+
+#ifdef CONFIG_SLIP_MODE_SLIP6
+/************************************************************************
+ *                      6 BIT SLIP ENCAPSULATION                       *
+ ************************************************************************/
+
+static int slip_esc6(unsigned char *s, unsigned char *d, int len)
+{
+       unsigned char *ptr = d;
+       unsigned char c;
+       int i;
+       unsigned short v = 0;
+       short bits = 0;
+
+       /*
+        * Send an initial END character to flush out any
+        * data that may have accumulated in the receiver
+        * due to line noise.
+        */
+
+       *ptr++ = 0x70;
+
+       /*
+        * Encode the packet into printable ascii characters
+        */
+
+       for (i = 0; i < len; ++i) {
+               v = (v << 8) | s[i];
+               bits += 8;
+               while (bits >= 6) {
+                       bits -= 6;
+                       c = 0x30 + ((v >> bits) & 0x3F);
+                       *ptr++ = c;
+               }
+       }
+       if (bits) {
+               c = 0x30 + ((v << (6 - bits)) & 0x3F);
+               *ptr++ = c;
+       }
+       *ptr++ = 0x70;
+       return ptr - d;
+}
+
+static void slip_unesc6(struct slip *sl, unsigned char s)
+{
+       unsigned char c;
+
+       if (s == 0x70) {
+#ifdef CONFIG_SLIP_SMART
+               /* drop keeptest bit = VSV */
+               if (test_bit(SLF_KEEPTEST, &sl->flags))
+                       clear_bit(SLF_KEEPTEST, &sl->flags);
+#endif
+
+               if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
+                   (sl->rcount > 2))
+                       sl_bump(sl);
+               sl->rcount = 0;
+               sl->xbits = 0;
+               sl->xdata = 0;
+       } else if (s >= 0x30 && s < 0x70) {
+               sl->xdata = (sl->xdata << 6) | ((s - 0x30) & 0x3F);
+               sl->xbits += 6;
+               if (sl->xbits >= 8) {
+                       sl->xbits -= 8;
+                       c = (unsigned char)(sl->xdata >> sl->xbits);
+                       if (!test_bit(SLF_ERROR, &sl->flags))  {
+                               if (sl->rcount < sl->buffsize)  {
+                                       sl->rbuff[sl->rcount++] = c;
+                                       return;
+                               }
+                               sl->dev->stats.rx_over_errors++;
+                               set_bit(SLF_ERROR, &sl->flags);
+                       }
+               }
+       }
+}
+#endif /* CONFIG_SLIP_MODE_SLIP6 */
+
+/* Perform I/O control on an active SLIP channel. */
+static int slip_ioctl(struct tty_struct *tty, struct file *file,
+                                       unsigned int cmd, unsigned long arg)
+{
+       struct slip *sl = tty->disc_data;
+       unsigned int tmp;
+       int __user *p = (int __user *)arg;
+
+       /* First make sure we're connected. */
+       if (!sl || sl->magic != SLIP_MAGIC)
+               return -EINVAL;
+
+       switch (cmd) {
+       case SIOCGIFNAME:
+               tmp = strlen(sl->dev->name) + 1;
+               if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
+                       return -EFAULT;
+               return 0;
+
+       case SIOCGIFENCAP:
+               if (put_user(sl->mode, p))
+                       return -EFAULT;
+               return 0;
+
+       case SIOCSIFENCAP:
+               if (get_user(tmp, p))
+                       return -EFAULT;
+#ifndef SL_INCLUDE_CSLIP
+               if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))
+                       return -EINVAL;
+#else
+               if ((tmp & (SL_MODE_ADAPTIVE | SL_MODE_CSLIP)) ==
+                   (SL_MODE_ADAPTIVE | SL_MODE_CSLIP))
+                       /* return -EINVAL; */
+                       tmp &= ~SL_MODE_ADAPTIVE;
+#endif
+#ifndef CONFIG_SLIP_MODE_SLIP6
+               if (tmp & SL_MODE_SLIP6)
+                       return -EINVAL;
+#endif
+               sl->mode = tmp;
+               sl->dev->type = ARPHRD_SLIP + sl->mode;
+               return 0;
+
+       case SIOCSIFHWADDR:
+               return -EINVAL;
+
+#ifdef CONFIG_SLIP_SMART
+       /* VSV changes start here */
+       case SIOCSKEEPALIVE:
+               if (get_user(tmp, p))
+                       return -EFAULT;
+               if (tmp > 255) /* max for unchar */
+                       return -EINVAL;
+
+               spin_lock_bh(&sl->lock);
+               if (!sl->tty) {
+                       spin_unlock_bh(&sl->lock);
+                       return -ENODEV;
+               }
+               sl->keepalive = (u8)tmp;
+               if (sl->keepalive != 0) {
+                       mod_timer(&sl->keepalive_timer,
+                                       jiffies + sl->keepalive * HZ);
+                       set_bit(SLF_KEEPTEST, &sl->flags);
+               } else
+                       del_timer(&sl->keepalive_timer);
+               spin_unlock_bh(&sl->lock);
+               return 0;
+
+       case SIOCGKEEPALIVE:
+               if (put_user(sl->keepalive, p))
+                       return -EFAULT;
+               return 0;
+
+       case SIOCSOUTFILL:
+               if (get_user(tmp, p))
+                       return -EFAULT;
+               if (tmp > 255) /* max for unchar */
+                       return -EINVAL;
+               spin_lock_bh(&sl->lock);
+               if (!sl->tty) {
+                       spin_unlock_bh(&sl->lock);
+                       return -ENODEV;
+               }
+               sl->outfill = (u8)tmp;
+               if (sl->outfill != 0) {
+                       mod_timer(&sl->outfill_timer,
+                                               jiffies + sl->outfill * HZ);
+                       set_bit(SLF_OUTWAIT, &sl->flags);
+               } else
+                       del_timer(&sl->outfill_timer);
+               spin_unlock_bh(&sl->lock);
+               return 0;
+
+       case SIOCGOUTFILL:
+               if (put_user(sl->outfill, p))
+                       return -EFAULT;
+               return 0;
+       /* VSV changes end */
+#endif
+       default:
+               return tty_mode_ioctl(tty, file, cmd, arg);
+       }
+}
+
+#ifdef CONFIG_COMPAT
+static long slip_compat_ioctl(struct tty_struct *tty, struct file *file,
+                                       unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case SIOCGIFNAME:
+       case SIOCGIFENCAP:
+       case SIOCSIFENCAP:
+       case SIOCSIFHWADDR:
+       case SIOCSKEEPALIVE:
+       case SIOCGKEEPALIVE:
+       case SIOCSOUTFILL:
+       case SIOCGOUTFILL:
+               return slip_ioctl(tty, file, cmd,
+                                 (unsigned long)compat_ptr(arg));
+       }
+
+       return -ENOIOCTLCMD;
+}
+#endif
+
+/* VSV changes start here */
+#ifdef CONFIG_SLIP_SMART
+/* function do_ioctl called from net/core/dev.c
+   to allow get/set outfill/keepalive parameter
+   by ifconfig                                 */
+
+static int sl_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+       struct slip *sl = netdev_priv(dev);
+       unsigned long *p = (unsigned long *)&rq->ifr_ifru;
+
+       if (sl == NULL)         /* Allocation failed ?? */
+               return -ENODEV;
+
+       spin_lock_bh(&sl->lock);
+
+       if (!sl->tty) {
+               spin_unlock_bh(&sl->lock);
+               return -ENODEV;
+       }
+
+       switch (cmd) {
+       case SIOCSKEEPALIVE:
+               /* max for unchar */
+               if ((unsigned)*p > 255) {
+                       spin_unlock_bh(&sl->lock);
+                       return -EINVAL;
+               }
+               sl->keepalive = (u8)*p;
+               if (sl->keepalive != 0) {
+                       sl->keepalive_timer.expires =
+                                               jiffies + sl->keepalive * HZ;
+                       mod_timer(&sl->keepalive_timer,
+                                               jiffies + sl->keepalive * HZ);
+                       set_bit(SLF_KEEPTEST, &sl->flags);
+               } else
+                       del_timer(&sl->keepalive_timer);
+               break;
+
+       case SIOCGKEEPALIVE:
+               *p = sl->keepalive;
+               break;
+
+       case SIOCSOUTFILL:
+               if ((unsigned)*p > 255) { /* max for unchar */
+                       spin_unlock_bh(&sl->lock);
+                       return -EINVAL;
+               }
+               sl->outfill = (u8)*p;
+               if (sl->outfill != 0) {
+                       mod_timer(&sl->outfill_timer,
+                                               jiffies + sl->outfill * HZ);
+                       set_bit(SLF_OUTWAIT, &sl->flags);
+               } else
+                       del_timer(&sl->outfill_timer);
+               break;
+
+       case SIOCGOUTFILL:
+               *p = sl->outfill;
+               break;
+
+       case SIOCSLEASE:
+               /* Resolve race condition, when ioctl'ing hanged up
+                  and opened by another process device.
+                */
+               if (sl->tty != current->signal->tty &&
+                                               sl->pid != current->pid) {
+                       spin_unlock_bh(&sl->lock);
+                       return -EPERM;
+               }
+               sl->leased = 0;
+               if (*p)
+                       sl->leased = 1;
+               break;
+
+       case SIOCGLEASE:
+               *p = sl->leased;
+       }
+       spin_unlock_bh(&sl->lock);
+       return 0;
+}
+#endif
+/* VSV changes end */
+
+static struct tty_ldisc_ops sl_ldisc = {
+       .owner          = THIS_MODULE,
+       .magic          = TTY_LDISC_MAGIC,
+       .name           = "slip",
+       .open           = slip_open,
+       .close          = slip_close,
+       .hangup         = slip_hangup,
+       .ioctl          = slip_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = slip_compat_ioctl,
+#endif
+       .receive_buf    = slip_receive_buf,
+       .write_wakeup   = slip_write_wakeup,
+};
+
+static int __init slip_init(void)
+{
+       int status;
+
+       if (slip_maxdev < 4)
+               slip_maxdev = 4; /* Sanity */
+
+       printk(KERN_INFO "SLIP: version %s (dynamic channels, max=%d)"
+#ifdef CONFIG_SLIP_MODE_SLIP6
+              " (6 bit encapsulation enabled)"
+#endif
+              ".\n",
+              SLIP_VERSION, slip_maxdev);
+#if defined(SL_INCLUDE_CSLIP)
+       printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n");
+#endif
+#ifdef CONFIG_SLIP_SMART
+       printk(KERN_INFO "SLIP linefill/keepalive option.\n");
+#endif
+
+       slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev,
+                                                               GFP_KERNEL);
+       if (!slip_devs) {
+               printk(KERN_ERR "SLIP: Can't allocate slip devices array.\n");
+               return -ENOMEM;
+       }
+
+       /* Fill in our line protocol discipline, and register it */
+       status = tty_register_ldisc(N_SLIP, &sl_ldisc);
+       if (status != 0) {
+               printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
+               kfree(slip_devs);
+       }
+       return status;
+}
+
+static void __exit slip_exit(void)
+{
+       int i;
+       struct net_device *dev;
+       struct slip *sl;
+       unsigned long timeout = jiffies + HZ;
+       int busy = 0;
+
+       if (slip_devs == NULL)
+               return;
+
+       /* First of all: check for active disciplines and hangup them.
+        */
+       do {
+               if (busy)
+                       msleep_interruptible(100);
+
+               busy = 0;
+               for (i = 0; i < slip_maxdev; i++) {
+                       dev = slip_devs[i];
+                       if (!dev)
+                               continue;
+                       sl = netdev_priv(dev);
+                       spin_lock_bh(&sl->lock);
+                       if (sl->tty) {
+                               busy++;
+                               tty_hangup(sl->tty);
+                       }
+                       spin_unlock_bh(&sl->lock);
+               }
+       } while (busy && time_before(jiffies, timeout));
+
+       /* FIXME: hangup is async so we should wait when doing this second
+          phase */
+
+       for (i = 0; i < slip_maxdev; i++) {
+               dev = slip_devs[i];
+               if (!dev)
+                       continue;
+               slip_devs[i] = NULL;
+
+               sl = netdev_priv(dev);
+               if (sl->tty) {
+                       printk(KERN_ERR "%s: tty discipline still running\n",
+                              dev->name);
+                       /* Intentionally leak the control block. */
+                       dev->destructor = NULL;
+               }
+
+               unregister_netdev(dev);
+       }
+
+       kfree(slip_devs);
+       slip_devs = NULL;
+
+       i = tty_unregister_ldisc(N_SLIP);
+       if (i != 0)
+               printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
+}
+
+module_init(slip_init);
+module_exit(slip_exit);
+
+#ifdef CONFIG_SLIP_SMART
+/*
+ * This is start of the code for multislip style line checking
+ * added by Stanislav Voronyi. All changes before marked VSV
+ */
+
+static void sl_outfill(unsigned long sls)
+{
+       struct slip *sl = (struct slip *)sls;
+
+       spin_lock(&sl->lock);
+
+       if (sl->tty == NULL)
+               goto out;
+
+       if (sl->outfill) {
+               if (test_bit(SLF_OUTWAIT, &sl->flags)) {
+                       /* no packets were transmitted, do outfill */
+#ifdef CONFIG_SLIP_MODE_SLIP6
+                       unsigned char s = (sl->mode & SL_MODE_SLIP6)?0x70:END;
+#else
+                       unsigned char s = END;
+#endif
+                       /* put END into tty queue. Is it right ??? */
+                       if (!netif_queue_stopped(sl->dev)) {
+                               /* if device busy no outfill */
+                               sl->tty->ops->write(sl->tty, &s, 1);
+                       }
+               } else
+                       set_bit(SLF_OUTWAIT, &sl->flags);
+
+               mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
+       }
+out:
+       spin_unlock(&sl->lock);
+}
+
+static void sl_keepalive(unsigned long sls)
+{
+       struct slip *sl = (struct slip *)sls;
+
+       spin_lock(&sl->lock);
+
+       if (sl->tty == NULL)
+               goto out;
+
+       if (sl->keepalive) {
+               if (test_bit(SLF_KEEPTEST, &sl->flags)) {
+                       /* keepalive still high :(, we must hangup */
+                       if (sl->outfill)
+                               /* outfill timer must be deleted too */
+                               (void)del_timer(&sl->outfill_timer);
+                       printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
+                       /* this must hangup tty & close slip */
+                       tty_hangup(sl->tty);
+                       /* I think we need not something else */
+                       goto out;
+               } else
+                       set_bit(SLF_KEEPTEST, &sl->flags);
+
+               mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
+       }
+out:
+       spin_unlock(&sl->lock);
+}
+
+#endif
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_LDISC(N_SLIP);
diff --git a/drivers/net/slip/slip.h b/drivers/net/slip/slip.h
new file mode 100644 (file)
index 0000000..67673cf
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * slip.h      Define the SLIP device driver interface and constants.
+ *
+ * NOTE:       THIS FILE WILL BE MOVED TO THE LINUX INCLUDE DIRECTORY
+ *             AS SOON AS POSSIBLE!
+ *
+ * Version:    @(#)slip.h      1.2.0   03/28/93
+ *
+ * Fixes:
+ *             Alan Cox        :       Added slip mtu field.
+ *             Matt Dillon     :       Printable slip (borrowed from net2e)
+ *             Alan Cox        :       Added SL_SLIP_LOTS
+ *     Dmitry Gorodchanin      :       A lot of changes in the 'struct slip'
+ *     Dmitry Gorodchanin      :       Added CSLIP statistics.
+ *     Stanislav Voronyi       :       Make line checking as created by
+ *                                     Igor Chechik, RELCOM Corp.
+ *     Craig Schlenter         :       Fixed #define bug that caused
+ *                                     CSLIP telnets to hang in 1.3.61-6
+ *
+ * Author:     Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ */
+#ifndef _LINUX_SLIP_H
+#define _LINUX_SLIP_H
+
+
+#if defined(CONFIG_INET) && defined(CONFIG_SLIP_COMPRESSED)
+# define SL_INCLUDE_CSLIP
+#endif
+
+#ifdef SL_INCLUDE_CSLIP
+# define SL_MODE_DEFAULT SL_MODE_ADAPTIVE
+#else
+# define SL_MODE_DEFAULT SL_MODE_SLIP
+#endif
+
+/* SLIP configuration. */
+#define SL_NRUNIT      256             /* MAX number of SLIP channels;
+                                          This can be overridden with
+                                          insmod -oslip_maxdev=nnn     */
+#define SL_MTU         296             /* 296; I am used to 600- FvK   */
+
+/* SLIP protocol characters. */
+#define END             0300           /* indicates end of frame       */
+#define ESC             0333           /* indicates byte stuffing      */
+#define ESC_END         0334           /* ESC ESC_END means END 'data' */
+#define ESC_ESC         0335           /* ESC ESC_ESC means ESC 'data' */
+
+
+struct slip {
+  int                  magic;
+
+  /* Various fields. */
+  struct tty_struct    *tty;           /* ptr to TTY structure         */
+  struct net_device    *dev;           /* easy for intr handling       */
+  spinlock_t           lock;
+
+#ifdef SL_INCLUDE_CSLIP
+  struct slcompress    *slcomp;        /* for header compression       */
+  unsigned char                *cbuff;         /* compression buffer           */
+#endif
+
+  /* These are pointers to the malloc()ed frame buffers. */
+  unsigned char                *rbuff;         /* receiver buffer              */
+  int                   rcount;         /* received chars counter       */
+  unsigned char                *xbuff;         /* transmitter buffer           */
+  unsigned char         *xhead;         /* pointer to next byte to XMIT */
+  int                   xleft;          /* bytes left in XMIT queue     */
+  int                  mtu;            /* Our mtu (to spot changes!)   */
+  int                   buffsize;       /* Max buffers sizes            */
+
+#ifdef CONFIG_SLIP_MODE_SLIP6
+  int                  xdata, xbits;   /* 6 bit slip controls          */
+#endif
+
+  unsigned long                flags;          /* Flag values/ mode etc        */
+#define SLF_INUSE      0               /* Channel in use               */
+#define SLF_ESCAPE     1               /* ESC received                 */
+#define SLF_ERROR      2               /* Parity, etc. error           */
+#define SLF_KEEPTEST   3               /* Keepalive test flag          */
+#define SLF_OUTWAIT    4               /* is outpacket was flag        */
+
+  unsigned char                mode;           /* SLIP mode                    */
+  unsigned char                leased;
+  pid_t                        pid;
+#define SL_MODE_SLIP   0
+#define SL_MODE_CSLIP  1
+#define SL_MODE_SLIP6  2               /* Matt Dillon's printable slip */
+#define SL_MODE_CSLIP6 (SL_MODE_SLIP6|SL_MODE_CSLIP)
+#define SL_MODE_AX25   4
+#define SL_MODE_ADAPTIVE 8
+#ifdef CONFIG_SLIP_SMART
+  unsigned char                outfill;        /* # of sec between outfill packet */
+  unsigned char                keepalive;      /* keepalive seconds            */
+  struct timer_list    outfill_timer;
+  struct timer_list    keepalive_timer;
+#endif
+};
+
+#define SLIP_MAGIC 0x5302
+
+#endif /* _LINUX_SLIP.H */
index c4137b0f808e6bd443967f4f3f49c8d44d823daa..c7e0149d151462206eb86fd829e69a6b92218b25 100644 (file)
@@ -4,9 +4,9 @@
 
 # So far, we only have PCI, ISA, and MCA token ring devices
 menuconfig TR
-       tristate "Token Ring driver support"
+       bool "Token Ring driver support"
        depends on NETDEVICES && !UML
-       depends on (PCI || ISA || MCA || CCW)
+       depends on (PCI || ISA || MCA || CCW || PCMCIA)
        select LLC
        help
          Token Ring is IBM's way of communication on a local network; the
@@ -20,6 +20,17 @@ menuconfig TR
 
 if TR
 
+config PCMCIA_IBMTR
+       tristate "IBM PCMCIA tokenring adapter support"
+       depends on IBMTR!=y && PCMCIA
+       ---help---
+         Say Y here if you intend to attach this type of Token Ring PCMCIA
+         card to your computer. You then also need to say Y to "Token Ring
+         driver support".
+
+         To compile this driver as a module, choose M here: the module will be
+         called ibmtr_cs.
+
 config IBMTR
        tristate "IBM Tropic chipset based adapter support"
        depends on ISA || MCA
index c88b0a5e53808f666ce86db86580c2769f04754d..f1be8d97b7a8a2f55f1654f0f29db2013c12fe45 100644 (file)
@@ -2,14 +2,15 @@
 # Makefile for drivers/net/tokenring
 #
 
-obj-$(CONFIG_IBMTR)    += ibmtr.o
-obj-$(CONFIG_IBMOL)    += olympic.o
-obj-$(CONFIG_IBMLS)    += lanstreamer.o
-obj-$(CONFIG_TMS380TR)         += tms380tr.o
-obj-$(CONFIG_ABYSS)    += abyss.o
-obj-$(CONFIG_MADGEMC)  += madgemc.o
-obj-$(CONFIG_PROTEON)  += proteon.o
-obj-$(CONFIG_TMSPCI)   += tmspci.o
-obj-$(CONFIG_SKISA)    += skisa.o
-obj-$(CONFIG_SMCTR)    += smctr.o
+obj-$(CONFIG_PCMCIA_IBMTR)     += ibmtr_cs.o
+obj-$(CONFIG_IBMTR)    += ibmtr.o
+obj-$(CONFIG_IBMOL)    += olympic.o
+obj-$(CONFIG_IBMLS)    += lanstreamer.o
+obj-$(CONFIG_TMS380TR) += tms380tr.o
+obj-$(CONFIG_ABYSS)    += abyss.o
+obj-$(CONFIG_MADGEMC)  += madgemc.o
+obj-$(CONFIG_PROTEON)  += proteon.o
+obj-$(CONFIG_TMSPCI)   += tmspci.o
+obj-$(CONFIG_SKISA)    += skisa.o
+obj-$(CONFIG_SMCTR)    += smctr.o
 obj-$(CONFIG_3C359)    += 3c359.o
diff --git a/drivers/net/tokenring/ibmtr_cs.c b/drivers/net/tokenring/ibmtr_cs.c
new file mode 100644 (file)
index 0000000..91b6846
--- /dev/null
@@ -0,0 +1,371 @@
+/*======================================================================
+
+    A PCMCIA token-ring driver for IBM-based cards
+
+    This driver supports the IBM PCMCIA Token-Ring Card.
+    Written by Steve Kipisz, kipisz@vnet.ibm.com or
+                             bungy@ibm.net
+
+    Written 1995,1996.
+
+    This code is based on pcnet_cs.c from David Hinds.
+    
+    V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com
+
+    Linux V2.2.x presented significant changes to the underlying
+    ibmtr.c code.  Mainly the code became a lot more organized and
+    modular.
+
+    This caused the old PCMCIA Token Ring driver to give up and go 
+    home early. Instead of just patching the old code to make it 
+    work, the PCMCIA code has been streamlined, updated and possibly
+    improved.
+
+    This code now only contains code required for the Card Services.
+    All we do here is set the card up enough so that the real ibmtr.c
+    driver can find it and work with it properly.
+
+    i.e. We set up the io port, irq, mmio memory and shared ram
+    memory.  This enables ibmtr_probe in ibmtr.c to find the card and
+    configure it as though it was a normal ISA and/or PnP card.
+
+    CHANGES
+
+    v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com)
+    Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c
+    
+    v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com)
+    Updated to version 2.2.7 to match the first version of the kernel
+    that the modification to ibmtr.c were incorporated into.
+    
+    v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com)
+    Address translation feature of PCMCIA controller is usable so
+    memory windows can be placed in High memory (meaning above
+    0xFFFFF.)
+
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/ibmtr.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#define PCMCIA
+#include "ibmtr.c"
+
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* MMIO base address */
+static u_long mmiobase = 0xce000;
+
+/* SRAM base address */
+static u_long srambase = 0xd0000;
+
+/* SRAM size 8,16,32,64 */
+static u_long sramsize = 64;
+
+/* Ringspeed 4,16 */
+static int ringspeed = 16;
+
+module_param(mmiobase, ulong, 0);
+module_param(srambase, ulong, 0);
+module_param(sramsize, ulong, 0);
+module_param(ringspeed, int, 0);
+MODULE_LICENSE("GPL");
+
+/*====================================================================*/
+
+static int ibmtr_config(struct pcmcia_device *link);
+static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
+static void ibmtr_release(struct pcmcia_device *link);
+static void ibmtr_detach(struct pcmcia_device *p_dev);
+
+/*====================================================================*/
+
+typedef struct ibmtr_dev_t {
+       struct pcmcia_device    *p_dev;
+       struct net_device       *dev;
+       struct tok_info         *ti;
+} ibmtr_dev_t;
+
+static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) {
+       ibmtr_dev_t *info = dev_id;
+       struct net_device *dev = info->dev;
+       return tok_interrupt(irq, dev);
+};
+
+static int __devinit ibmtr_attach(struct pcmcia_device *link)
+{
+    ibmtr_dev_t *info;
+    struct net_device *dev;
+
+    dev_dbg(&link->dev, "ibmtr_attach()\n");
+
+    /* Create new token-ring device */
+    info = kzalloc(sizeof(*info), GFP_KERNEL);
+    if (!info) return -ENOMEM;
+    dev = alloc_trdev(sizeof(struct tok_info));
+    if (!dev) {
+       kfree(info);
+       return -ENOMEM;
+    }
+
+    info->p_dev = link;
+    link->priv = info;
+    info->ti = netdev_priv(dev);
+
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    link->resource[0]->end = 4;
+    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_regs = PRESENT_OPTION;
+
+    info->dev = dev;
+
+    return ibmtr_config(link);
+} /* ibmtr_attach */
+
+static void ibmtr_detach(struct pcmcia_device *link)
+{
+    struct ibmtr_dev_t *info = link->priv;
+    struct net_device *dev = info->dev;
+     struct tok_info *ti = netdev_priv(dev);
+
+    dev_dbg(&link->dev, "ibmtr_detach\n");
+    
+    /* 
+     * When the card removal interrupt hits tok_interrupt(), 
+     * bail out early, so we don't crash the machine 
+     */
+    ti->sram_phys |= 1;
+
+    unregister_netdev(dev);
+    
+    del_timer_sync(&(ti->tr_timer));
+
+    ibmtr_release(link);
+
+    free_netdev(dev);
+    kfree(info);
+} /* ibmtr_detach */
+
+static int __devinit ibmtr_config(struct pcmcia_device *link)
+{
+    ibmtr_dev_t *info = link->priv;
+    struct net_device *dev = info->dev;
+    struct tok_info *ti = netdev_priv(dev);
+    int i, ret;
+
+    dev_dbg(&link->dev, "ibmtr_config\n");
+
+    link->io_lines = 16;
+    link->config_index = 0x61;
+
+    /* Determine if this is PRIMARY or ALTERNATE. */
+
+    /* Try PRIMARY card at 0xA20-0xA23 */
+    link->resource[0]->start = 0xA20;
+    i = pcmcia_request_io(link);
+    if (i != 0) {
+       /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
+       link->resource[0]->start = 0xA24;
+       ret = pcmcia_request_io(link);
+       if (ret)
+               goto failed;
+    }
+    dev->base_addr = link->resource[0]->start;
+
+    ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt);
+    if (ret)
+           goto failed;
+    dev->irq = link->irq;
+    ti->irq = link->irq;
+    ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
+
+    /* Allocate the MMIO memory window */
+    link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[2]->flags |= WIN_USE_WAIT;
+    link->resource[2]->start = 0;
+    link->resource[2]->end = 0x2000;
+    ret = pcmcia_request_window(link, link->resource[2], 250);
+    if (ret)
+           goto failed;
+
+    ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
+    if (ret)
+           goto failed;
+    ti->mmio = ioremap(link->resource[2]->start,
+                   resource_size(link->resource[2]));
+
+    /* Allocate the SRAM memory window */
+    link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0;
+    link->resource[3]->end = sramsize * 1024;
+    ret = pcmcia_request_window(link, link->resource[3], 250);
+    if (ret)
+           goto failed;
+
+    ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
+    if (ret)
+           goto failed;
+
+    ti->sram_base = srambase >> 12;
+    ti->sram_virt = ioremap(link->resource[3]->start,
+                   resource_size(link->resource[3]));
+    ti->sram_phys = link->resource[3]->start;
+
+    ret = pcmcia_enable_device(link);
+    if (ret)
+           goto failed;
+
+    /*  Set up the Token-Ring Controller Configuration Register and
+        turn on the card.  Check the "Local Area Network Credit Card
+        Adapters Technical Reference"  SC30-3585 for this info.  */
+    ibmtr_hw_setup(dev, mmiobase);
+
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    i = ibmtr_probe_card(dev);
+    if (i != 0) {
+       pr_notice("register_netdev() failed\n");
+       goto failed;
+    }
+
+    netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
+               dev->base_addr, dev->irq,
+               (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
+               dev->dev_addr);
+    return 0;
+
+failed:
+    ibmtr_release(link);
+    return -ENODEV;
+} /* ibmtr_config */
+
+static void ibmtr_release(struct pcmcia_device *link)
+{
+       ibmtr_dev_t *info = link->priv;
+       struct net_device *dev = info->dev;
+
+       dev_dbg(&link->dev, "ibmtr_release\n");
+
+       if (link->resource[2]->end) {
+               struct tok_info *ti = netdev_priv(dev);
+               iounmap(ti->mmio);
+       }
+       pcmcia_disable_device(link);
+}
+
+static int ibmtr_suspend(struct pcmcia_device *link)
+{
+       ibmtr_dev_t *info = link->priv;
+       struct net_device *dev = info->dev;
+
+       if (link->open)
+               netif_device_detach(dev);
+
+       return 0;
+}
+
+static int __devinit ibmtr_resume(struct pcmcia_device *link)
+{
+       ibmtr_dev_t *info = link->priv;
+       struct net_device *dev = info->dev;
+
+       if (link->open) {
+               ibmtr_probe(dev);       /* really? */
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+
+
+/*====================================================================*/
+
+static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
+{
+    int i;
+
+    /* Bizarre IBM behavior, there are 16 bits of information we
+       need to set, but the card only allows us to send 4 bits at a 
+       time.  For each byte sent to base_addr, bits 7-4 tell the
+       card which part of the 16 bits we are setting, bits 3-0 contain 
+       the actual information */
+
+    /* First nibble provides 4 bits of mmio */
+    i = (mmiobase >> 16) & 0x0F;
+    outb(i, dev->base_addr);
+
+    /* Second nibble provides 3 bits of mmio */
+    i = 0x10 | ((mmiobase >> 12) & 0x0E);
+    outb(i, dev->base_addr);
+
+    /* Third nibble, hard-coded values */
+    i = 0x26;
+    outb(i, dev->base_addr);
+
+    /* Fourth nibble sets shared ram page size */
+
+    /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */          
+    i = (sramsize >> 4) & 0x07;
+    i = ((i == 4) ? 3 : i) << 2;
+    i |= 0x30;
+
+    if (ringspeed == 16)
+       i |= 2;
+    if (dev->base_addr == 0xA24)
+       i |= 1;
+    outb(i, dev->base_addr);
+
+    /* 0x40 will release the card for use */
+    outb(0x40, dev->base_addr);
+}
+
+static const struct pcmcia_device_id ibmtr_ids[] = {
+       PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e),
+       PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47),
+       PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids);
+
+static struct pcmcia_driver ibmtr_cs_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "ibmtr_cs",
+       .probe          = ibmtr_attach,
+       .remove         = ibmtr_detach,
+       .id_table       = ibmtr_ids,
+       .suspend        = ibmtr_suspend,
+       .resume         = ibmtr_resume,
+};
+
+static int __init init_ibmtr_cs(void)
+{
+       return pcmcia_register_driver(&ibmtr_cs_driver);
+}
+
+static void __exit exit_ibmtr_cs(void)
+{
+       pcmcia_unregister_driver(&ibmtr_cs_driver);
+}
+
+module_init(init_ibmtr_cs);
+module_exit(exit_ibmtr_cs);