]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.54 2.1.54
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:50 +0000 (15:13 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:13:50 +0000 (15:13 -0500)
90 files changed:
Documentation/Configure.help
Documentation/devices.tex
Documentation/devices.txt
Makefile
arch/alpha/kernel/bios32.c
arch/i386/config.in
arch/i386/defconfig
arch/i386/kernel/bios32.c
arch/i386/kernel/irq.c
arch/i386/kernel/traps.c
arch/i386/mm/init.c
arch/sparc64/defconfig
arch/sparc64/kernel/ebus.c
arch/sparc64/kernel/ioctl32.c
drivers/block/floppy.c
drivers/block/hd.c
drivers/block/raid0.c
drivers/block/rd.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/acquirewdt.c [new file with mode: 0644]
drivers/char/h8.c [new file with mode: 0644]
drivers/char/h8.h [new file with mode: 0644]
drivers/char/mem.c
drivers/char/misc.c
drivers/misc/parport_share.c
drivers/net/arc-rimi.c
drivers/net/arcnet.c
drivers/net/com20020.c
drivers/net/com90io.c
drivers/net/com90xx.c
drivers/net/eepro100.c
drivers/net/ppp.c
drivers/pci/pci.c
drivers/sbus/char/pcikbd.c
drivers/scsi/esp.c
drivers/scsi/g_NCR5380.c
drivers/scsi/mesh.c
drivers/scsi/qlogicpti.c
drivers/scsi/scsi.h
drivers/scsi/scsi_syms.c
fs/autofs/autofs_i.h
fs/autofs/init.c
fs/autofs/root.c
fs/autofs/waitq.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/dcache.c
fs/inode.c
fs/nfs/inode.c
fs/proc/openpromfs.c
fs/proc/root.c
fs/super.c
include/asm-alpha/elf.h
include/asm-alpha/floppy.h
include/asm-alpha/pgtable.h
include/asm-alpha/uaccess.h
include/asm-i386/bugs.h
include/asm-i386/elf.h
include/asm-i386/floppy.h
include/asm-i386/pgtable.h
include/asm-i386/uaccess.h
include/asm-mips/floppy.h
include/asm-mips/namei.h
include/asm-ppc/floppy.h
include/asm-sparc/namei.h
include/asm-sparc64/ebus.h
include/asm-sparc64/floppy.h
include/asm-sparc64/namei.h
include/linux/arcdevice.h
include/linux/fd.h
include/linux/if_arcnet.h
include/linux/kernel.h
include/linux/openpic.h [new file with mode: 0644]
include/linux/pci.h
include/linux/tty.h
include/net/inet_common.h
include/net/snmp.h
init/main.c
ipc/shm.c
kernel/exit.c
kernel/module.c
kernel/sys.c
kernel/time.c
lib/vsprintf.c
mm/filemap.c
net/ipv4/ip_fragment.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/netsyms.c

index 9017926c094f6f1208e326c0e94609a69d9187bb..098c95277164dbfeeadb8df017ed4060bcd7970b 100644 (file)
@@ -680,21 +680,38 @@ CONFIG_TGA_CONSOLE
   VGA driver is used.  Note that, at this time, there is no X server
   for these systems. If unsure, try N.
 
-PCI bios support
+PCI support
 CONFIG_PCI
   Find out whether you have a PCI motherboard. PCI is the name of a
   bus system, i.e. the way the CPU talks to the other stuff inside
   your box. Other bus systems are ISA, EISA, Microchannel (MCA) or
-  VESA. If you have PCI, say Y, otherwise N. Note: some old PCI
-  motherboards have BIOS bugs and may crash if "PCI bios support" is
-  enabled (but they run fine without this option). The PCI-HOWTO,
-  available via ftp (user: anonymous) in
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO, contains valuable information
-  about which PCI hardware does work under Linux and which doesn't.
+  VESA. If you have PCI, say Y, otherwise N. The PCI-HOWTO, available
+  via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO,
+  contains valuable information about which PCI hardware does work
+  under Linux and which doesn't.
   If some of your PCI devices don't work and you get a warning during
   boot time ("man dmesg"), please follow the instructions at the top
   of include/linux/pci.h.
 
+PCI BIOS support
+CONFIG_PCI_BIOS
+  If you have enabled PCI bus support above, you probably want to allow
+  Linux to use your PCI BIOS to detect the PCI devices and determine
+  their configuration. Note: some old PCI motherboards have BIOS bugs
+  and may crash if this switch is enabled -- for such motherboards,
+  you should disable PCI BIOS support and use direct PCI access instead.
+  Except for some special cases (embedded systems with no BIOS), you
+  probably should say Y here.
+
+PCI direct access support
+CONFIG_PCI_DIRECT
+  If you don't want to use the PCI BIOS (e.g., because you run some
+  embedded system with no BIOS at all) or Linux says it cannot use
+  your PCI BIOS, you can enable direct PCI hardware here. It might fail
+  if your machine is based on some unusual chipset, but it usually
+  works. If both PCI BIOS and direct PCI access are enabled, the use
+  of BIOS is preferred. If unsure, say Y.
+
 PCI bridge optimization (experimental)
 CONFIG_PCI_OPTIMIZE
   This can improve access times for some hardware devices under
@@ -2653,6 +2670,26 @@ CONFIG_SOUNDMODEM_FSK9600
   can only use one protocol at a time, depending on what the other end
   can understand).
 
+Shortwave radio modem driver
+CONFIG_HFMODEM
+  This experimental driver is used by a package (to be released)
+  that implements the shortwave radio protocols RTTY, Sitor (Amtor),
+  Pactor 1 and GTOR using a standard PC soundcard. If unsure,
+  say N.
+
+Shortwave radio modem driver support for SoundBlaster and compatible cards
+CONFIG_HFMODEM_SBC
+  This option enables the hfmodem driver to use SoundBlaster and
+  compatible cards. It requires a 16bit capable card, i.e.
+  SB16 or better, or ESS1688 or newer.
+
+Shortwave radio modem driver support for WSS and Crystal cards
+CONFIG_HFMODEM_WSS
+  This option enables the hfmodem driver to use WindowsSoundSystem
+  compatible cards. These cards feature a codec chip from either
+  Analog Devices (such as AD1848, AD1845, AD1812) or Crystal
+  Semiconductors (such as CS4248, CS423x).
+
 Serial port KISS driver for AX.25
 CONFIG_MKISS
   KISS is the protocol used to send IP traffic over AX.25 radio
@@ -3056,10 +3093,14 @@ CONFIG_NET_ISA
   linux, read the Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
 
-ARCnet support
+Generic ARCnet support
 CONFIG_ARCNET
   If you have a network card of this type, say Y and check out the
   (arguably) beautiful poetry in Documentation/networking/arcnet.txt.
+  You need both this driver, and the driver for the particular ARCnet
+  chipset of your card. If you don't know, then it's probably a 
+  COM90xx type card, so say Y (or M) to ARCnet COM90xx chipset support
+  below.
   You might also want to have a look at the Ethernet-HOWTO, available
   via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO
   (even though ARCnet is not really ethernet). This driver is also
@@ -3097,6 +3138,31 @@ CONFIG_ARCNET_1051
   documentation in Documentation/networking/arcnet.txt for more
   information about using arc0e and arc0s.
 
+ARCnet COM90xx chipset support
+CONFIG_ARCNET_COM90xx
+  This is the chipset driver for the standard COM90xx cards. If you always
+  used the old arcnet driver without knowing what type of card you had, 
+  this is probably the one for you.
+
+ARCnet COM90xx IO mapped mode chipset support
+CONFIG_ARCNET_COM90xxIO
+  This is the chipset driver for the COM90xx cards, using them in IO-mapped
+  mode instead of memory-mapped mode. This is slower than the normal driver.
+  Only use it if your card doesn't support shared memory.
+
+ARCnet RIM I chipset support
+CONFIG_ARCNET_RIM_I
+  This is yet another chipset driver for the COM90xx cards, but this time
+  only using memory-mapped mode, and no IO ports at all. This driver is
+  completely untested, so if you have one of these cards, please mail 
+  dwmw2@cam.ac.uk, especially if it works!
+
+ARCnet COM20020 chipset support
+CONFIG_ARCNET_COM20020
+  This is the driver for the new COM20020 chipset. It supports such things
+  as promiscuous mode, so packet sniffing is possible, and extra diagnostic
+  information.
+
 Cabletron E21xx support
 CONFIG_E2100
   If you have a network (ethernet) card of this type, say Y and read
@@ -3222,6 +3288,16 @@ CONFIG_EEXPRESS
   linux, read the Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
 
+NI5010 support
+CONFIG_NI5010
+  If you have a network (ethernet) card of this type, say Y and read
+  the Ethernet-HOWTO, available via ftp (user: anonymous) in
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than
+  one network card under linux, read the Multiple-Ethernet-mini-HOWTO,
+  available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+  Note that this is still experimental code. If you use this driver,
+  please contact the authors to join the development team.
+
 NI5210 support
 CONFIG_NI52
   If you have a network (ethernet) card of this type, say Y and read
@@ -4445,6 +4521,12 @@ CONFIG_VT_CONSOLE
   other console device, in which case you probably want to say Y to
   "Console on serial port", below. If unsure, say N.
 
+Software generated cursor
+CONFIG_SOFTCURSOR
+  If you enable this option, you'll be able to do lots of nice things
+  with your cursor -- for example to turn it into a non-blinking one.
+  See Documentation/VGA-softcursor.txt for more information.
+
 Standard/generic serial support
 CONFIG_SERIAL
   This selects whether you want to include the driver for the standard
@@ -4938,6 +5020,18 @@ CONFIG_PCWATCHDOG
   module is called pcwd.o. If you want to compile it as a module, say
   M here and read Documentation/modules.txt.  Most people will say N.
 
+Acquire SBC Watchdog Timer
+CONFIG_ACQUIRE_WDT
+  This is the driver for the hardware watchdog on the PSC-6x86 Single
+  Board Computer produced by Acquire Inc (and others). This watchdog
+  simply watches your kernel to make sure it doesn't freeze, and if
+  it does, it resets your computer after a certain amount of time.
+  This driver is like the WDT501 driver but for different hardware.
+  This driver is also available as a module ( = code which can be 
+  inserted in and removed from the running kernel whenever you want).
+  The module is called pscwdt.o. If you want to compile it as a module,
+  say M here and read Documentation/modules.txt.  Most people will say N.
+  
 Enhanced Real Time Clock Support
 CONFIG_RTC
   If you say Y here and create a character special file /dev/rtc with
@@ -5854,6 +5948,76 @@ CONFIG_MSDOS_PARTITION
   Say Y if you need this feature; users who are only using their
   system-native partitioning scheme can say N here.
 
+Build PowerMac Kernel (not PReP)
+CONFIG_PMAC
+  There are currently two different kinds of PowerPC-based machines
+  available: Apple Power Macintoshes and clones (such as the Motorola
+  Starmax series, and PReP (PowerPC Reference Platform) machines such
+  as the Motorola PowerStack range.  Currently, a single kernel binary
+  only supports one type or the other.  Say Y here to compile a kernel
+  which will run on Power Macintoshes and clones.
+
+Build PReP Kernel (not PowerMac)
+CONFIG_PREP
+  Say Y here to compile a kernel which will run on PReP (PowerPC
+  Reference Platform) machines such as the Motorola PowerStack range.
+  For Power Macintosh clones, including the Motorola Starmaxes, you
+  should say N (and Y to the previous question).
+
+Processor type
+CONFIG_MCOMMON
+  If you are compiling a kernel to run on a specific machine, you can
+  indicate which type of PowerPC processor it has.  Currently this
+  option does very little.
+
+Support for Open Firmware device tree in /proc
+CONFIG_PROC_DEVICETREE
+  This option adds a device-tree directory under /proc which contains
+  an image of the device tree that the kernel copies from Open
+  Firmware.  If unsure, say Y here.
+
+Support for ATI Mach64 display cards
+CONFIG_ATY_VIDEO
+  Several of the newer Power Macintoshes and clones have a video
+  display interface based on the ATI Mach64 chipset.  Say N here if
+  you are sure you don't need this functionality, otherwise Y.
+
+Support for IMS Twin Turbo display card
+CONFIG_IMSTT_VIDEO
+  Some Power Macintosh clones have an IMS Twin Turbo video display
+  interface.  Say Y to include support for this.
+
+MESH (Power Mac internal SCSI) support
+CONFIG_SCSI_MESH
+  Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
+  SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the
+  other Power Macintoshes do).  Say Y to include support for this SCSI
+  adaptor.
+
+Maximum synchronous transfer rate
+CONFIG_SCSI_MESH_SYNC_RATE
+  On Power Macintoshes (and clones) where the MESH SCSI bus adaptor
+  drives a bus which is entirely internal to the machine (such as the
+  7500, 7600, 8500, etc.), the MESH is capable of synchronous
+  operation at up to 10MB/s.  On machines where the SCSI bus
+  controlled by the MESH can have external devices connected, it is
+  usually rated at 5MB/s.  5 is a safe value here unless you know the
+  MESH SCSI bus is internal only; in that case you can say 10.  Say 0
+  to disable synchronous operation.
+
+53C94 (Power Mac external SCSI) support
+CONFIG_SCSI_MAC53C94
+  On Power Macintoshes (and clones) with two SCSI buses, the external
+  SCSI bus is usually controlled by a 53C94 SCSI bus adaptor.  Older
+  machines which only have one SCSI bus, such as the 7200, also use
+  the 53C94.  Say Y to include support for the 53C94.
+
+MACE (Power Mac ethernet) support
+CONFIG_MACE
+  Power Macintoshes and clones with ethernet built-in on the
+  motherboard will usually use a MACE (Medium Access Control for
+  Ethernet) interface.  Say Y to include support for the MACE chip.
+
 # need an empty line after last entry, for sed script in Configure.
 
 #
index 22acdd3f3e28f297a6e884f187fa2d97c3ffe2e2..f9aa0294d87a98aa5a54d5c2b6506feec3f5155d 100644 (file)
@@ -47,7 +47,7 @@ foo \kill}%
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
-\date{Last revised: July 28, 1997}
+\date{Last revised: September 5, 1997}
 \maketitle
 %
 \noindent
@@ -216,7 +216,9 @@ reply.
 \major{85}{}{char }{Linux/SGI shared memory input queue}
 \major{86}{}{char }{SCSI media changer}
 \major{87}{}{char }{Sony Control-A1 stereo control bus}
-\major{88}{--119}{}{Unallocated}
+\major{88}{}{char }{COMX synchronous serial card}
+\major{89}{}{char }{I$^2$C bus interface}
+\major{90}{--119}{}{Unallocated}
 \major{120}{--127}{}{Local/experimental use}
 \major{128}{--239}{}{Unallocated}
 \major{240}{--254}{}{Local/experimental use}
@@ -525,6 +527,7 @@ physical disks.
        \minor{148}{/dev/gfx}{Linux/SGI graphics effects device}
        \minor{149}{/dev/input/mouse}{Linux/SGI Irix emulation mouse}
        \minor{150}{/dev/input/keyboard}{Linux/SGI Irix emulation keyboard}
+       \minor{151}{/dev/led}{Front panel LEDs}
 \end{devicelist}
 
 \begin{devicelist}
@@ -1417,8 +1420,8 @@ Currently for Dolphin Interconnect Solutions' PCI-SCI bridge.
 
 \begin{devicelist}
 \major{82}{}{char }{WiNRADiO communications receiver card}
-       \major{0}{/dev/winradio0}{First WiNRADiO card}
-       \major{1}{/dev/winradio1}{Second WiNRADiO card}
+       \minor{0}{/dev/winradio0}{First WiNRADiO card}
+       \minor{1}{/dev/winradio1}{Second WiNRADiO card}
        \minordots
 \end{devicelist}
 
@@ -1465,7 +1468,21 @@ on {\url http://home.pages.de/~videotext/\/}.
 \end{devicelist}
 
 \begin{devicelist}
-\major{88}{--119}{}{Unallocated}
+\major{88}{}{char }{COMX synchronous serial card}
+       \minor{0}{/dev/comx0}{Channel 0}
+       \minor{1}{/dev/comx1}{Channel 1}
+       \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{89}{}{char }{I$^2$C bus interface}
+       \minor{0}{/dev/i2c0}{First I$^2$C adapter}
+       \minor{1}{/dev/i2c1}{Second I$^2$C adapter}
+       \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{90}{--119}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
index 14bae22fa77a27cad2d9b2c11c6b89f22fea0e23..c9697e262343c7e2a3d39a4c6040367df8c97f1c 100644 (file)
@@ -1,7 +1,7 @@
                       LINUX ALLOCATED DEVICES
             Maintained by H. Peter Anvin <hpa@zytor.com>
 
-                    Last revised: July 28, 1997
+                  Last revised: September 5, 1997
 
 This list is the successor to Rick Miller's Linux Device List, which
 he stopped maintaining when he got busy with other things in 1993.  It
@@ -301,6 +301,7 @@ reply.
                148 = /dev/gfx          Linux/SGI graphics effects device
                149 = /dev/input/mouse  Linux/SGI Irix emulation mouse
                150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
+               151 = /dev/led          Front panel LEDs
 
  11 char       Raw keyboard device
                  0 = /dev/kbd          Raw keyboard device
@@ -1031,7 +1032,17 @@ reply.
                  1 = /dev/controla1    Second device on chain
                    ...
 
- 88-119                UNALLOCATED
+ 88 char       COMX synchronous serial card
+                 0 = /dev/comx0        COMX channel 0
+                 1 = /dev/comx1        COMX channel 1
+                   ...
+
+ 89 char       I2C bus interface
+                 0 = /dev/i2c0         First I2C adapter
+                 1 = /dev/i2c1         Second I2C adapter
+                   ...
+
+ 90-119                UNALLOCATED
 
 120-127                LOCAL/EXPERIMENTAL USE
 
index b71aa165752f999d85850b05ec8b735d10509684..13a1b0b50b9a8477e069ebf9e6a1bf0cd3e10891 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 53
+SUBLEVEL = 54
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
index 16d7474d1f64e869f08d827298fbf1844b2ca3aa..385fc9494ac1ddd678565d5624832a1c8b7168ca 100644 (file)
@@ -186,6 +186,7 @@ static void layout_dev(struct pci_dev *dev)
                pcibios_read_config_dword(bus->number, dev->devfn, reg, &base);
                if (!base) {
                        /* this base-address register is unused */
+                       dev->base_address[(reg - PCI_BASE_ADDRESS_0)>>2] = 0;
                        continue;
                }
 
index 41435c84cc6afa838ccb9e275f27bd0975f19688..50d9de2a7ea604aca5b9eaf9c64601d5dd9f96cc 100644 (file)
@@ -23,8 +23,10 @@ comment 'General setup'
 
 bool 'Kernel math emulation' CONFIG_MATH_EMULATION
 bool 'Networking support' CONFIG_NET
-bool 'PCI bios support' CONFIG_PCI
+bool 'PCI support' CONFIG_PCI
 if [ "$CONFIG_PCI" = "y" ]; then
+  bool '   PCI BIOS support' CONFIG_PCI_BIOS
+  bool '   PCI direct access support' CONFIG_PCI_DIRECT
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
   fi
index 953fecf23d2c1774c30df6acc174094fcfe98eff..9bdb2efa201c7edcf5818be76e0a39f3a54947cf 100644 (file)
@@ -20,6 +20,8 @@ CONFIG_MODULES=y
 # CONFIG_MATH_EMULATION is not set
 CONFIG_NET=y
 CONFIG_PCI=y
+CONFIG_PCI_BIOS=y
+# CONFIG_PCI_DIRECT is not set
 # CONFIG_MCA is not set
 CONFIG_SYSVIPC=y
 CONFIG_SYSCTL=y
@@ -139,7 +141,6 @@ CONFIG_SCSI_OMIT_FLASHPOINT=y
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
@@ -162,6 +163,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 # CONFIG_PCNET32 is not set
@@ -174,7 +176,6 @@ CONFIG_EEXPRESS_PRO100=y
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_DLCI is not set
-# CONFIG_PLIP is not set
 # CONFIG_PPP is not set
 # CONFIG_NET_RADIO is not set
 # CONFIG_SLIP is not set
@@ -239,6 +240,7 @@ CONFIG_82C710_MOUSE=y
 # CONFIG_APM is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_H8 is not set
 # CONFIG_NVRAM is not set
 # CONFIG_JOYSTICK is not set
 
index 474666f59279a710bae7e80cf55dac7ab74cf2c4..e98819258766958d2b865e182cb0ef736591709f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * bios32.c - BIOS32, PCI BIOS functions.
  *
- * $Id: bios32.c,v 1.12 1997/06/26 13:33:46 mj Exp $
+ * $Id: bios32.c,v 1.14 1997/08/02 22:20:57 mj Exp $
  *
  * Sponsored by
  *     iX Multiuser Multitasking Magazine
@@ -61,6 +61,9 @@
  * 
  * Jun 20, 1997 : Corrected problems in "conf1" type accesses.
  *      (paubert@iram.es)
+ *
+ * Aug 2,  1997 : Split to PCI BIOS handling and direct PCI access parts
+ *     and cleaned it up...     Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/config.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
-#define PCIBIOS_PCI_FUNCTION_ID        0xb1XX
-#define PCIBIOS_PCI_BIOS_PRESENT       0xb101
-#define PCIBIOS_FIND_PCI_DEVICE                0xb102
-#define PCIBIOS_FIND_PCI_CLASS_CODE    0xb103
-#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
-#define PCIBIOS_READ_CONFIG_BYTE       0xb108
-#define PCIBIOS_READ_CONFIG_WORD       0xb109
-#define PCIBIOS_READ_CONFIG_DWORD      0xb10a
-#define PCIBIOS_WRITE_CONFIG_BYTE      0xb10b
-#define PCIBIOS_WRITE_CONFIG_WORD      0xb10c
-#define PCIBIOS_WRITE_CONFIG_DWORD     0xb10d
-
-
-/* BIOS32 signature: "_32_" */
-#define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
-
-/* PCI signature: "PCI " */
-#define PCI_SIGNATURE          (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
-
-/* PCI service signature: "$PCI" */
-#define PCI_SERVICE            (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
-
 /*
- * This is the standard structure used to identify the entry point
- * to the BIOS32 Service Directory, as documented in
- *     Standard BIOS 32-bit Service Directory Proposal
- *     Revision 0.4 May 24, 1993
- *     Phoenix Technologies Ltd.
- *     Norwood, MA
- * and the PCI BIOS specification.
+ * Generic PCI access -- indirect calls according to detected HW.
  */
 
-union bios32 {
-       struct {
-               unsigned long signature;        /* _32_ */
-               unsigned long entry;            /* 32 bit physical address */
-               unsigned char revision;         /* Revision level, 0 */
-               unsigned char length;           /* Length in paragraphs should be 01 */
-               unsigned char checksum;         /* All bytes must add up to zero */
-               unsigned char reserved[5];      /* Must be zero */
-       } fields;
-       char chars[16];
-};
-
-#ifdef CONFIG_PCI
-/*
- * Physical address of the service directory.  I don't know if we're
- * allowed to have more than one of these or not, so just in case
- * we'll make pcibios_present() take a memory start parameter and store
- * the array there.
- */
-
-static unsigned long bios32_entry = 0;
-static struct {
-       unsigned long address;
-       unsigned short segment;
-} bios32_indirect = { 0, KERNEL_CS };
-
-
-/*
- * function table for accessing PCI configuration space
- */
 struct pci_access {
+    int pci_present;
     int (*find_device)(unsigned short, unsigned short, unsigned short, unsigned char *, unsigned char *);
     int (*find_class)(unsigned int, unsigned short, unsigned char *, unsigned char *);
     int (*read_config_byte)(unsigned char, unsigned char, unsigned char, unsigned char *);
@@ -148,363 +94,137 @@ struct pci_access {
     int (*write_config_dword)(unsigned char, unsigned char, unsigned char, unsigned int);
 };
 
-/*
- * pointer to selected PCI access function table
- */
-static struct pci_access *access_pci = NULL;
-
-
-
-/*
- * Returns the entry point for the given service, NULL on error
- */
-
-static unsigned long bios32_service(unsigned long service)
+static int pci_stub(void)
 {
-       unsigned char return_code;      /* %al */
-       unsigned long address;          /* %ebx */
-       unsigned long length;           /* %ecx */
-       unsigned long entry;            /* %edx */
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%edi)"
-               : "=a" (return_code),
-                 "=b" (address),
-                 "=c" (length),
-                 "=d" (entry)
-               : "0" (service),
-                 "1" (0),
-                 "D" (&bios32_indirect));
-       restore_flags(flags);
-
-       switch (return_code) {
-               case 0:
-                       return address + entry;
-               case 0x80:      /* Not present */
-                       printk("bios32_service(0x%lx) : not present\n", service);
-                       return 0;
-               default: /* Shouldn't happen */
-                       printk("bios32_service(0x%lx) : returned 0x%x, mail drew@colorado.edu\n",
-                               service, return_code);
-                       return 0;
-       }
+       return PCIBIOS_FUNC_NOT_SUPPORTED;
 }
 
-static long pcibios_entry = 0;
-static struct {
-       unsigned long address;
-       unsigned short segment;
-} pci_indirect = { 0, KERNEL_CS };
+static struct pci_access pci_access_none = {
+       0,                              /* No PCI present */
+       (void *) pci_stub,              /* No functions implemented */
+       (void *) pci_stub,
+       (void *) pci_stub,
+       (void *) pci_stub,
+       (void *) pci_stub,
+       (void *) pci_stub,
+       (void *) pci_stub,
+       (void *) pci_stub
+};
 
+static struct pci_access *access_pci = &pci_access_none;
 
-__initfunc(static int check_pcibios(void))
+int pcibios_present(void)
 {
-       unsigned long signature;
-       unsigned char present_status;
-       unsigned char major_revision;
-       unsigned char minor_revision;
-       unsigned long flags;
-       int pack;
-
-       if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
-               pci_indirect.address = pcibios_entry | PAGE_OFFSET;
-
-               save_flags(flags); cli();
-               __asm__("lcall (%%edi)\n\t"
-                       "jc 1f\n\t"
-                       "xor %%ah, %%ah\n"
-                       "1:\tshl $8, %%eax\n\t"
-                       "movw %%bx, %%ax"
-                       : "=d" (signature),
-                         "=a" (pack)
-                       : "1" (PCIBIOS_PCI_BIOS_PRESENT),
-                         "D" (&pci_indirect)
-                       : "bx", "cx");
-               restore_flags(flags);
-
-               present_status = (pack >> 16) & 0xff;
-               major_revision = (pack >> 8) & 0xff;
-               minor_revision = pack & 0xff;
-               if (present_status || (signature != PCI_SIGNATURE)) {
-                       printk ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
-                               "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
-                               "       and signature of 0x%08lx (%c%c%c%c).  mail drew@Colorado.EDU\n",
-                               (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
-                               present_status, signature,
-                               (char) (signature >>  0), (char) (signature >>  8),
-                               (char) (signature >> 16), (char) (signature >> 24));
-
-                       if (signature != PCI_SIGNATURE)
-                               pcibios_entry = 0;
-               }
-               if (pcibios_entry) {
-                       printk ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%lx\n",
-                               major_revision, minor_revision, pcibios_entry);
-                       return 1;
-               }
-       }
-       return 0;
+       return access_pci->pci_present;
 }
 
-
-static int pci_bios_find_class (unsigned int class_code, unsigned short index,
+int pcibios_find_class (unsigned int class_code, unsigned short index,
        unsigned char *bus, unsigned char *device_fn)
 {
-       unsigned long bx;
-       unsigned long ret;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__ ("lcall (%%edi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=b" (bx),
-                 "=a" (ret)
-               : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
-                 "c" (class_code),
-                 "S" ((int) index),
-                 "D" (&pci_indirect));
-       restore_flags(flags);
-       *bus = (bx >> 8) & 0xff;
-       *device_fn = bx & 0xff;
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->find_class(class_code, index, bus, device_fn);
 }
 
-
-static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
 {
-       unsigned short bx;
-       unsigned short ret;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%edi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=b" (bx),
-                 "=a" (ret)
-               : "1" (PCIBIOS_FIND_PCI_DEVICE),
-                 "c" (device_id),
-                 "d" (vendor),
-                 "S" ((int) index),
-                 "D" (&pci_indirect));
-       restore_flags(flags);
-       *bus = (bx >> 8) & 0xff;
-       *device_fn = bx & 0xff;
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->find_device(vendor, device_id, index, bus, device_fn);
 }
 
-static int pci_bios_read_config_byte(unsigned char bus,
+int pcibios_read_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
 {
-       unsigned long ret;
-       unsigned long bx = (bus << 8) | device_fn;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%esi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=c" (*value),
-                 "=a" (ret)
-               : "1" (PCIBIOS_READ_CONFIG_BYTE),
-                 "b" (bx),
-                 "D" ((long) where),
-                 "S" (&pci_indirect));
-       restore_flags(flags);
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->read_config_byte(bus, device_fn, where, value);
 }
 
-static int pci_bios_read_config_word (unsigned char bus,
+int pcibios_read_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short *value)
 {
-       unsigned long ret;
-       unsigned long bx = (bus << 8) | device_fn;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%esi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=c" (*value),
-                 "=a" (ret)
-               : "1" (PCIBIOS_READ_CONFIG_WORD),
-                 "b" (bx),
-                 "D" ((long) where),
-                 "S" (&pci_indirect));
-       restore_flags(flags);
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->read_config_word(bus, device_fn, where, value);
 }
 
-static int pci_bios_read_config_dword (unsigned char bus,
+int pcibios_read_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int *value)
 {
-       unsigned long ret;
-       unsigned long bx = (bus << 8) | device_fn;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%esi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=c" (*value),
-                 "=a" (ret)
-               : "1" (PCIBIOS_READ_CONFIG_DWORD),
-                 "b" (bx),
-                 "D" ((long) where),
-                 "S" (&pci_indirect));
-       restore_flags(flags);
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->read_config_dword(bus, device_fn, where, value);
 }
 
-static int pci_bios_write_config_byte (unsigned char bus,
+int pcibios_write_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char value)
 {
-       unsigned long ret;
-       unsigned long bx = (bus << 8) | device_fn;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%esi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=a" (ret)
-               : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
-                 "c" (value),
-                 "b" (bx),
-                 "D" ((long) where),
-                 "S" (&pci_indirect));
-       restore_flags(flags);
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->write_config_byte(bus, device_fn, where, value);
 }
 
-static int pci_bios_write_config_word (unsigned char bus,
+int pcibios_write_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short value)
 {
-       unsigned long ret;
-       unsigned long bx = (bus << 8) | device_fn;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%esi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=a" (ret)
-               : "0" (PCIBIOS_WRITE_CONFIG_WORD),
-                 "c" (value),
-                 "b" (bx),
-                 "D" ((long) where),
-                 "S" (&pci_indirect));
-       restore_flags(flags);
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->write_config_word(bus, device_fn, where, value);
 }
 
-static int pci_bios_write_config_dword (unsigned char bus,
+int pcibios_write_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int value)
 {
-       unsigned long ret;
-       unsigned long bx = (bus << 8) | device_fn;
-       unsigned long flags;
-
-       save_flags(flags); cli();
-       __asm__("lcall (%%esi)\n\t"
-               "jc 1f\n\t"
-               "xor %%ah, %%ah\n"
-               "1:"
-               : "=a" (ret)
-               : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
-                 "c" (value),
-                 "b" (bx),
-                 "D" ((long) where),
-                 "S" (&pci_indirect));
-       restore_flags(flags);
-       return (int) (ret & 0xff00) >> 8;
+       return access_pci->write_config_dword(bus, device_fn, where, value);
 }
 
 /*
- * function table for BIOS32 access
+ * Direct access to PCI hardware...
  */
-static struct pci_access pci_bios_access = {
-      pci_bios_find_device,
-      pci_bios_find_class,
-      pci_bios_read_config_byte,
-      pci_bios_read_config_word,
-      pci_bios_read_config_dword,
-      pci_bios_write_config_byte,
-      pci_bios_write_config_word,
-      pci_bios_write_config_dword
-};
-
-
 
 /*
  * Given the vendor and device ids, find the n'th instance of that device
  * in the system.  
  */
+
+#ifdef CONFIG_PCI_DIRECT
+
 static int pci_direct_find_device (unsigned short vendor, unsigned short device_id,
                           unsigned short index, unsigned char *bus,
                           unsigned char *devfn)
 {
     unsigned int curr = 0;
     struct pci_dev *dev;
-    unsigned long flags;
 
-    save_flags(flags);
     for (dev = pci_devices; dev; dev = dev->next) {
        if (dev->vendor == vendor && dev->device == device_id) {
            if (curr == index) {
                *devfn = dev->devfn;
                *bus = dev->bus->number;
-               restore_flags(flags);
                return PCIBIOS_SUCCESSFUL;
            }
            ++curr;
        }
     }
-    restore_flags(flags);
     return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-
 /*
  * Given the class, find the n'th instance of that device
  * in the system.
  */
+
 static int pci_direct_find_class (unsigned int class_code, unsigned short index,
                          unsigned char *bus, unsigned char *devfn)
 {
     unsigned int curr = 0;
     struct pci_dev *dev;
-    unsigned long flags;
 
-    save_flags(flags); cli();
     for (dev = pci_devices; dev; dev = dev->next) {
        if (dev->class == class_code) {
            if (curr == index) {
                *devfn = dev->devfn;
                *bus = dev->bus->number;
-               restore_flags(flags);
                return PCIBIOS_SUCCESSFUL;
            }
            ++curr;
        }
     }
-    restore_flags(flags);
     return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
  */
+
 #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
 
 static int pci_conf1_read_config_byte(unsigned char bus, unsigned char device_fn,
@@ -585,10 +305,8 @@ static int pci_conf1_write_config_dword (unsigned char bus, unsigned char device
 
 #undef CONFIG_CMD
 
-/*
- * functiontable for type 1
- */
 static struct pci_access pci_direct_conf1 = {
+      1,
       pci_direct_find_device,
       pci_direct_find_class,
       pci_conf1_read_config_byte,
@@ -602,6 +320,7 @@ static struct pci_access pci_direct_conf1 = {
 /*
  * Functions for accessing PCI configuration space with type 2 accesses
  */
+
 #define IOADDR(devfn, where)   ((0xC000 | ((devfn & 0x78) << 5)) + where)
 #define FUNC(devfn)            (((devfn & 7) << 1) | 0xf0)
 
@@ -698,10 +417,8 @@ static int pci_conf2_write_config_dword (unsigned char bus, unsigned char device
 #undef IOADDR
 #undef FUNC
 
-/*
- * functiontable for type 2
- */
 static struct pci_access pci_direct_conf2 = {
+      1,
       pci_direct_find_device,
       pci_direct_find_class,
       pci_conf2_read_config_byte,
@@ -712,8 +429,7 @@ static struct pci_access pci_direct_conf2 = {
       pci_conf2_write_config_dword
 };
 
-
-__initfunc(static struct pci_access *check_direct_pci(void))
+__initfunc(static struct pci_access *pci_check_direct(void))
 {
     unsigned int tmp;
     unsigned long flags;
@@ -721,7 +437,7 @@ __initfunc(static struct pci_access *check_direct_pci(void))
     save_flags(flags); cli();
 
     /*
-     * check if configuration type 1 works
+     * Check if configuration type 1 works.
      */
     outb (0x01, 0xCFB);
     tmp = inl (0xCF8);
@@ -729,153 +445,385 @@ __initfunc(static struct pci_access *check_direct_pci(void))
     if (inl (0xCF8) == 0x80000000) {
        outl (tmp, 0xCF8);
        restore_flags(flags);
-       printk("pcibios_init: Using configuration type 1\n");
+       printk("PCI: Using configuration type 1\n");
        return &pci_direct_conf1;
     }
     outl (tmp, 0xCF8);
 
     /*
-     * check if configuration type 2 works
+     * Check if configuration type 2 works.
      */
     outb (0x00, 0xCFB);
     outb (0x00, 0xCF8);
     outb (0x00, 0xCFA);
     if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) {
        restore_flags(flags);
-       printk("pcibios_init: Using configuration type 2\n");
+       printk("PCI: Using configuration type 2\n");
        return &pci_direct_conf2;
     }
     restore_flags(flags);
-    printk("pcibios_init: Not supported chipset for direct PCI access !\n");
+    printk("PCI: PCI hardware not found (i.e., not present or not supported).\n");
     return NULL;
 }
 
+#endif
+
+/*
+ * BIOS32 and PCI BIOS handling.
+ */
+
+#ifdef CONFIG_PCI_BIOS
+
+#define PCIBIOS_PCI_FUNCTION_ID        0xb1XX
+#define PCIBIOS_PCI_BIOS_PRESENT       0xb101
+#define PCIBIOS_FIND_PCI_DEVICE                0xb102
+#define PCIBIOS_FIND_PCI_CLASS_CODE    0xb103
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
+#define PCIBIOS_READ_CONFIG_BYTE       0xb108
+#define PCIBIOS_READ_CONFIG_WORD       0xb109
+#define PCIBIOS_READ_CONFIG_DWORD      0xb10a
+#define PCIBIOS_WRITE_CONFIG_BYTE      0xb10b
+#define PCIBIOS_WRITE_CONFIG_WORD      0xb10c
+#define PCIBIOS_WRITE_CONFIG_DWORD     0xb10d
+
+/* BIOS32 signature: "_32_" */
+#define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
+
+/* PCI signature: "PCI " */
+#define PCI_SIGNATURE          (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
+
+/* PCI service signature: "$PCI" */
+#define PCI_SERVICE            (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
+
+/*
+ * This is the standard structure used to identify the entry point
+ * to the BIOS32 Service Directory, as documented in
+ *     Standard BIOS 32-bit Service Directory Proposal
+ *     Revision 0.4 May 24, 1993
+ *     Phoenix Technologies Ltd.
+ *     Norwood, MA
+ * and the PCI BIOS specification.
+ */
+
+union bios32 {
+       struct {
+               unsigned long signature;        /* _32_ */
+               unsigned long entry;            /* 32 bit physical address */
+               unsigned char revision;         /* Revision level, 0 */
+               unsigned char length;           /* Length in paragraphs should be 01 */
+               unsigned char checksum;         /* All bytes must add up to zero */
+               unsigned char reserved[5];      /* Must be zero */
+       } fields;
+       char chars[16];
+};
+
+/*
+ * Physical address of the service directory.  I don't know if we're
+ * allowed to have more than one of these or not, so just in case
+ * we'll make pcibios_present() take a memory start parameter and store
+ * the array there.
+ */
+
+static unsigned long bios32_entry = 0;
+static struct {
+       unsigned long address;
+       unsigned short segment;
+} bios32_indirect = { 0, KERNEL_CS };
+
+/*
+ * Returns the entry point for the given service, NULL on error
+ */
+
+static unsigned long bios32_service(unsigned long service)
+{
+       unsigned char return_code;      /* %al */
+       unsigned long address;          /* %ebx */
+       unsigned long length;           /* %ecx */
+       unsigned long entry;            /* %edx */
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__("lcall (%%edi)"
+               : "=a" (return_code),
+                 "=b" (address),
+                 "=c" (length),
+                 "=d" (entry)
+               : "0" (service),
+                 "1" (0),
+                 "D" (&bios32_indirect));
+       restore_flags(flags);
+
+       switch (return_code) {
+               case 0:
+                       return address + entry;
+               case 0x80:      /* Not present */
+                       printk("bios32_service(0x%lx): not present\n", service);
+                       return 0;
+               default: /* Shouldn't happen */
+                       printk("bios32_service(0x%lx): returned 0x%x, mail drew@colorado.edu\n",
+                               service, return_code);
+                       return 0;
+       }
+}
+
+static long pcibios_entry = 0;
+static struct {
+       unsigned long address;
+       unsigned short segment;
+} pci_indirect = { 0, KERNEL_CS };
+
+__initfunc(static int check_pcibios(void))
+{
+       unsigned long signature;
+       unsigned char present_status;
+       unsigned char major_revision;
+       unsigned char minor_revision;
+       unsigned long flags;
+       int pack;
 
-/*
- * access defined pcibios functions via
- * the function table
- */
+       if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
+               pci_indirect.address = pcibios_entry | PAGE_OFFSET;
 
-int pcibios_present(void)
-{
-       return access_pci ? 1 : 0;
+               save_flags(flags); cli();
+               __asm__("lcall (%%edi)\n\t"
+                       "jc 1f\n\t"
+                       "xor %%ah, %%ah\n"
+                       "1:\tshl $8, %%eax\n\t"
+                       "movw %%bx, %%ax"
+                       : "=d" (signature),
+                         "=a" (pack)
+                       : "1" (PCIBIOS_PCI_BIOS_PRESENT),
+                         "D" (&pci_indirect)
+                       : "bx", "cx");
+               restore_flags(flags);
+
+               present_status = (pack >> 16) & 0xff;
+               major_revision = (pack >> 8) & 0xff;
+               minor_revision = pack & 0xff;
+               if (present_status || (signature != PCI_SIGNATURE)) {
+                       printk ("PCI: %s: BIOS32 Service Directory says PCI BIOS is present,\n"
+                               "       but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
+                               "       and signature of 0x%08lx (%c%c%c%c).  Mail drew@Colorado.EDU\n",
+                               (signature == PCI_SIGNATURE) ?  "WARNING" : "ERROR",
+                               present_status, signature,
+                               (char) (signature >>  0), (char) (signature >>  8),
+                               (char) (signature >> 16), (char) (signature >> 24));
+
+                       if (signature != PCI_SIGNATURE)
+                               pcibios_entry = 0;
+               }
+               if (pcibios_entry) {
+                       printk ("PCI: PCI BIOS revision %x.%02x entry at 0x%lx\n",
+                               major_revision, minor_revision, pcibios_entry);
+                       return 1;
+               }
+       }
+       return 0;
 }
 
-int pcibios_find_class (unsigned int class_code, unsigned short index,
+static int pci_bios_find_class (unsigned int class_code, unsigned short index,
        unsigned char *bus, unsigned char *device_fn)
 {
-   if (access_pci && access_pci->find_class)
-      return access_pci->find_class(class_code, index, bus, device_fn);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       unsigned long bx;
+       unsigned long ret;
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__ ("lcall (%%edi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=b" (bx),
+                 "=a" (ret)
+               : "1" (PCIBIOS_FIND_PCI_CLASS_CODE),
+                 "c" (class_code),
+                 "S" ((int) index),
+                 "D" (&pci_indirect));
+       restore_flags(flags);
+       *bus = (bx >> 8) & 0xff;
+       *device_fn = bx & 0xff;
+       return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+static int pci_bios_find_device (unsigned short vendor, unsigned short device_id,
        unsigned short index, unsigned char *bus, unsigned char *device_fn)
 {
-    if (access_pci && access_pci->find_device)
-      return access_pci->find_device(vendor, device_id, index, bus, device_fn);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       unsigned short bx;
+       unsigned short ret;
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__("lcall (%%edi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=b" (bx),
+                 "=a" (ret)
+               : "1" (PCIBIOS_FIND_PCI_DEVICE),
+                 "c" (device_id),
+                 "d" (vendor),
+                 "S" ((int) index),
+                 "D" (&pci_indirect));
+       restore_flags(flags);
+       *bus = (bx >> 8) & 0xff;
+       *device_fn = bx & 0xff;
+       return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_read_config_byte (unsigned char bus,
+static int pci_bios_read_config_byte(unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
 {
-    if (access_pci && access_pci->read_config_byte)
-      return access_pci->read_config_byte(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       unsigned long ret;
+       unsigned long bx = (bus << 8) | device_fn;
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__("lcall (%%esi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=c" (*value),
+                 "=a" (ret)
+               : "1" (PCIBIOS_READ_CONFIG_BYTE),
+                 "b" (bx),
+                 "D" ((long) where),
+                 "S" (&pci_indirect));
+       restore_flags(flags);
+       return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_read_config_word (unsigned char bus,
+static int pci_bios_read_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short *value)
 {
-    if (access_pci && access_pci->read_config_word)
-      return access_pci->read_config_word(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       unsigned long ret;
+       unsigned long bx = (bus << 8) | device_fn;
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__("lcall (%%esi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=c" (*value),
+                 "=a" (ret)
+               : "1" (PCIBIOS_READ_CONFIG_WORD),
+                 "b" (bx),
+                 "D" ((long) where),
+                 "S" (&pci_indirect));
+       restore_flags(flags);
+       return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_read_config_dword (unsigned char bus,
+static int pci_bios_read_config_dword (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned int *value)
 {
-    if (access_pci && access_pci->read_config_dword)
-      return access_pci->read_config_dword(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       unsigned long ret;
+       unsigned long bx = (bus << 8) | device_fn;
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__("lcall (%%esi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=c" (*value),
+                 "=a" (ret)
+               : "1" (PCIBIOS_READ_CONFIG_DWORD),
+                 "b" (bx),
+                 "D" ((long) where),
+                 "S" (&pci_indirect));
+       restore_flags(flags);
+       return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_write_config_byte (unsigned char bus,
+static int pci_bios_write_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char value)
 {
-    if (access_pci && access_pci->write_config_byte)
-      return access_pci->write_config_byte(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       unsigned long ret;
+       unsigned long bx = (bus << 8) | device_fn;
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       __asm__("lcall (%%esi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=a" (ret)
+               : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+                 "c" (value),
+                 "b" (bx),
+                 "D" ((long) where),
+                 "S" (&pci_indirect));
+       restore_flags(flags);
+       return (int) (ret & 0xff00) >> 8;
 }
 
-int pcibios_write_config_word (unsigned char bus,
+static int pci_bios_write_config_word (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned short value)
 {
-    if (access_pci && access_pci->write_config_word)
-      return access_pci->write_config_word(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;    
-}
+       unsigned long ret;
+       unsigned long bx = (bus << 8) | device_fn;
+       unsigned long flags;
 
-int pcibios_write_config_dword (unsigned char bus,
-       unsigned char device_fn, unsigned char where, unsigned int value)
-{
-    if (access_pci && access_pci->write_config_dword)
-      return access_pci->write_config_dword(bus, device_fn, where, value);
-    
-    return PCIBIOS_FUNC_NOT_SUPPORTED;
+       save_flags(flags); cli();
+       __asm__("lcall (%%esi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=a" (ret)
+               : "0" (PCIBIOS_WRITE_CONFIG_WORD),
+                 "c" (value),
+                 "b" (bx),
+                 "D" ((long) where),
+                 "S" (&pci_indirect));
+       restore_flags(flags);
+       return (int) (ret & 0xff00) >> 8;
 }
 
-const char *pcibios_strerror (int error)
+static int pci_bios_write_config_dword (unsigned char bus,
+       unsigned char device_fn, unsigned char where, unsigned int value)
 {
-       static char buf[80];
-
-       switch (error) {
-               case PCIBIOS_SUCCESSFUL:
-                       return "SUCCESSFUL";
-
-               case PCIBIOS_FUNC_NOT_SUPPORTED:
-                       return "FUNC_NOT_SUPPORTED";
-
-               case PCIBIOS_BAD_VENDOR_ID:
-                       return "SUCCESSFUL";
-
-               case PCIBIOS_DEVICE_NOT_FOUND:
-                       return "DEVICE_NOT_FOUND";
-
-               case PCIBIOS_BAD_REGISTER_NUMBER:
-                       return "BAD_REGISTER_NUMBER";
-
-                case PCIBIOS_SET_FAILED:          
-                       return "SET_FAILED";
-
-                case PCIBIOS_BUFFER_TOO_SMALL:    
-                       return "BUFFER_TOO_SMALL";
+       unsigned long ret;
+       unsigned long bx = (bus << 8) | device_fn;
+       unsigned long flags;
 
-               default:
-                       sprintf (buf, "UNKNOWN RETURN 0x%x", error);
-                       return buf;
-       }
+       save_flags(flags); cli();
+       __asm__("lcall (%%esi)\n\t"
+               "jc 1f\n\t"
+               "xor %%ah, %%ah\n"
+               "1:"
+               : "=a" (ret)
+               : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+                 "c" (value),
+                 "b" (bx),
+                 "D" ((long) where),
+                 "S" (&pci_indirect));
+       restore_flags(flags);
+       return (int) (ret & 0xff00) >> 8;
 }
 
+/*
+ * Function table for BIOS32 access
+ */
 
-__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
-{
-    return mem_start;
-}
+static struct pci_access pci_bios_access = {
+      1,
+      pci_bios_find_device,
+      pci_bios_find_class,
+      pci_bios_read_config_byte,
+      pci_bios_read_config_word,
+      pci_bios_read_config_dword,
+      pci_bios_write_config_byte,
+      pci_bios_write_config_word,
+      pci_bios_write_config_dword
+};
 
-#endif
+/*
+ * Try to find PCI BIOS.
+ */
 
-__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(static struct pci_access *pci_find_bios(void))
 {
-#ifdef CONFIG_PCI
        union bios32 *check;
        unsigned char sum;
        int i, length;
@@ -884,7 +832,6 @@ __initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long
         * Follow the standard procedure for locating the BIOS32 Service
         * directory by scanning the permissible address range from
         * 0xe0000 through 0xfffff for a valid BIOS32 structure.
-        *
         */
 
        for (check = (union bios32 *) __va(0xe0000);
@@ -901,24 +848,59 @@ __initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long
                if (sum != 0)
                        continue;
                if (check->fields.revision != 0) {
-                       printk("pcibios_init : unsupported revision %d at 0x%p, mail drew@colorado.edu\n",
+                       printk("PCI: unsupported BIOS32 revision %d at 0x%p, mail drew@colorado.edu\n",
                                check->fields.revision, check);
                        continue;
                }
-               printk ("pcibios_init : BIOS32 Service Directory structure at 0x%p\n", check);
-               if (!bios32_entry) {
-                       if (check->fields.entry >= 0x100000) {
-                               printk("pcibios_init: entry in high memory, trying direct PCI access\n");
-                               access_pci = check_direct_pci();
-                       } else {
-                               bios32_entry = check->fields.entry;
-                               printk ("pcibios_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
-                               bios32_indirect.address = bios32_entry + PAGE_OFFSET;
-                       }
+               printk ("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
+               if (check->fields.entry >= 0x100000) {
+#ifdef CONFIG_PCI_DIRECT
+                       printk("PCI: BIOS32 entry in high memory, trying direct PCI access.\n");
+                       return pci_check_direct();
+#else
+                       printk("PCI: BIOS32 entry in high memory, cannot use.\n");
+#endif
+               } else {
+                       bios32_entry = check->fields.entry;
+                       printk ("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
+                       bios32_indirect.address = bios32_entry + PAGE_OFFSET;
+                       if (check_pcibios())
+                               return &pci_bios_access;
                }
+               break;  /* Hopefully more than one BIOS32 cannot happen... */
        }
-       if (bios32_entry && check_pcibios())
-               access_pci = &pci_bios_access;
+
+       return NULL;
+}
+
+#endif
+
+/*
+ * No fixup function used.
+ */
+
+__initfunc(unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
+{
+    return mem_start;
+}
+
+/*
+ * Initialization. Try all known PCI access methods.
+ */
+
+__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+{
+       struct pci_access *a = NULL;
+
+#ifdef CONFIG_PCI_BIOS
+       a = pci_find_bios();
+#else
+#ifdef CONFIG_PCI_DIRECT
+       a = pci_check_direct();
 #endif
+#endif
+       if (a)
+               access_pci = a;
+
        return memory_start;
 }
index 2e0f3e0843e19c5e4dffc6346543dae232582324..62d07450845679e3711c84394a9df97080f308ba 100644 (file)
@@ -42,8 +42,6 @@
 extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
 #endif
 
-#define CR0_NE 32
-
 unsigned int local_irq_count[NR_CPUS];
 #ifdef __SMP__
 atomic_t __intel_bh_counter;
@@ -55,6 +53,8 @@ int __intel_bh_counter;
 static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
 #endif
 
+atomic_t nmi_counter;
+
 /*
  * This contains the irq mask for both irq controllers
  */
@@ -199,7 +199,6 @@ static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
  * be shot.
  */
  
-
 static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
 {
        outb(0,0xF0);
@@ -224,28 +223,26 @@ static struct irqaction *irq_action[16] = {
 
 int get_irq_list(char *buf)
 {
-       int i, len = 0;
+       int i;
        struct irqaction * action;
+       char *p = buf;
 
        for (i = 0 ; i < NR_IRQS ; i++) {
                action = irq_action[i];
                if (!action) 
                        continue;
-               len += sprintf(buf+len, "%2d: %10u   %s",
+               p += sprintf(p, "%3d: %10u   %s",
                        i, kstat.interrupts[i], action->name);
                for (action=action->next; action; action = action->next) {
-                       len += sprintf(buf+len, ", %s", action->name);
+                       p += sprintf(p, ", %s", action->name);
                }
-               len += sprintf(buf+len, "\n");
+               *p++ = '\n';
        }
-/*
- *     Linus - should you add NMI counts here ?????
- */
+       p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter));
 #ifdef __SMP_PROF__
-       len+=sprintf(buf+len, "IPI: %8lu received\n",
-               ipi_count);
+       p += sprintf(p, "IPI: %10lu\n", ipi_count);
 #endif         
-       return len;
+       return p - buf;
 }
 
 #ifdef __SMP_PROF__
index b397fc76d047401720f8012c5ce53fe8ca5b8f1f..6fb18dc35e473af895cbf3eefdc4dd0a1472053f 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/spinlock.h>
+#include <asm/atomic.h>
 
 asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
@@ -271,7 +272,9 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
 {
        unsigned char reason = inb(0x61);
+       extern atomic_t nmi_counter;
 
+       atomic_inc(&nmi_counter);
        if (reason & 0x80)
                mem_parity_error(reason, regs);
        if (reason & 0x40)
@@ -348,7 +351,10 @@ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
                                          long error_code)
 {
+#if 0
+       /* No need to warn about this any longer. */
        printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+#endif
 }
 
 /*
index 8f2852a48fef599e73eb7bb9b510a89eb676598f..6ed47e2ef85f44e4dce0748db36ac7f6ed7dac77 100644 (file)
@@ -261,6 +261,43 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
        return free_area_init(start_mem, end_mem);
 }
 
+/*
+ * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+ * and also on some strange 486's (NexGen etc.). All 586+'s are OK. The jumps
+ * before and after the test are here to work-around some nasty CPU bugs.
+ */
+
+__initfunc(void test_wp_bit(void))
+{
+       unsigned char tmp_reg;
+       unsigned long old = pg0[0];
+
+       printk("Checking if this processor honours the WP bit even in supervisor mode... ");
+       pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
+       local_flush_tlb();
+       current->mm->mmap->vm_start += PAGE_SIZE;
+       __asm__ __volatile__(
+               "jmp 1f; 1:\n"
+               "movb %0,%1\n"
+               "movb %1,%0\n"
+               "jmp 1f; 1:\n"
+               :"=m" (*(char *) __va(0)),
+                "=q" (tmp_reg)
+               :/* no inputs */
+               :"memory");
+       pg0[0] = old;
+       local_flush_tlb();
+       current->mm->mmap->vm_start -= PAGE_SIZE;
+       if (wp_works_ok < 0) {
+               wp_works_ok = 0;
+               printk("No.\n");
+#ifndef CONFIG_M386
+               panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
+#endif
+       } else
+               printk("Ok.\n");
+}
+
 __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 {
        unsigned long start_low_mem = PAGE_SIZE;
@@ -339,30 +376,9 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
                reservedpages << (PAGE_SHIFT-10),
                datapages << (PAGE_SHIFT-10),
                initpages << (PAGE_SHIFT-10));
-/* test if the WP bit is honoured in supervisor mode */
-       if (wp_works_ok < 0) {
-               unsigned char tmp_reg;
-               unsigned long old = pg0[0];
-               printk("Checking if this processor honours the WP bit even in supervisor mode... ");
-               pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
-               local_flush_tlb();
-               current->mm->mmap->vm_start += PAGE_SIZE;
-               __asm__ __volatile__(
-                       "movb %0,%1 ; movb %1,%0"
-                       :"=m" (*(char *) __va(0)),
-                        "=q" (tmp_reg)
-                       :/* no inputs */
-                       :"memory");
-               pg0[0] = old;
-               local_flush_tlb();
-               current->mm->mmap->vm_start -= PAGE_SIZE;
-               if (wp_works_ok < 0) {
-                       wp_works_ok = 0;
-                       printk("No.\n");
-               } else
-                       printk("Ok.\n");
-       }
-       return;
+
+       if (wp_works_ok < 0)
+               test_wp_bit();
 }
 
 void free_initmem(void)
index a3b1b52def88042c6ad954990e53fe4c5865974b..85958cd6e5f76c2183ab483e6150f9a088910b98 100644 (file)
@@ -68,7 +68,7 @@ CONFIG_SOLARIS_EMUL=m
 #
 # Floppy, IDE, and other block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_STRIPED=m
index 54244513f12933b0a75db26916b65802471269f8..f484cfef825bbcffb1a6f3108cb59ea145d2c83c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.7 1997/08/28 02:23:17 ecd Exp $
+/* $Id: ebus.c,v 1.8 1997/09/05 22:59:39 ecd Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -39,16 +39,72 @@ extern void auxio_probe(void);
 
 extern unsigned int psycho_irq_build(unsigned int full_ino);
 
-__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
+static inline unsigned long
+ebus_alloc(unsigned long *memory_start, size_t size)
+{
+       unsigned long mem;
+
+       *memory_start = (*memory_start + 7) & ~(7);
+       mem = *memory_start;
+       *memory_start += size;
+       return mem;
+}
+
+__initfunc(void fill_ebus_child(int node, struct linux_ebus_child *dev))
+{
+       int regs[PROMREG_MAX];
+       int irqs[PROMREG_MAX];
+       char lbuf[128];
+       int i, len;
+
+       dev->prom_node = node;
+       prom_getstring(node, "name", lbuf, sizeof(lbuf));
+       strcpy(dev->prom_name, lbuf);
+
+       len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+       dev->num_addrs = len / sizeof(regs[0]);
+
+       for (i = 0; i < dev->num_addrs; i++) {
+               if (regs[i] >= dev->parent->num_addrs) {
+                       prom_printf("UGH: property for %s was %d, need < %d\n",
+                                   dev->prom_name, len, dev->parent->num_addrs);
+                       panic(__FUNCTION__);
+               }
+               dev->base_address[i] = dev->parent->base_address[regs[i]];
+       }
+
+       len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
+       if ((len == -1) || (len == 0)) {
+               dev->num_irqs = 0;
+       } else {
+               dev->num_irqs = len / sizeof(irqs[0]);
+               for (i = 0; i < dev->num_irqs; i++)
+                       dev->irqs[i] = psycho_irq_build(irqs[i]);
+       }
+
+#ifdef DEBUG_FILL_EBUS_DEV
+       printk("child '%s': address%s\n", dev->prom_name,
+              dev->num_addrs > 1 ? "es" : "");
+       for (i = 0; i < dev->num_addrs; i++)
+               printk("        %016lx\n", dev->base_address[i]);
+       if (dev->num_irqs) {
+               printk("        IRQ%s", dev->num_irqs > 1 ? "s" : "");
+               for (i = 0; i < dev->num_irqs; i++)
+                       printk(" %08x", dev->irqs[i]);
+               printk("\n");
+       }
+#endif
+}
+
+__initfunc(unsigned long fill_ebus_device(int node, struct linux_ebus_device *dev,
+                                         unsigned long memory_start))
 {
        struct linux_prom_registers regs[PROMREG_MAX];
+       struct linux_ebus_child *child;
        int irqs[PROMINTR_MAX];
        char lbuf[128];
        int i, n, len;
 
-#ifndef CONFIG_PCI
-       return;
-#endif
        dev->prom_node = node;
        prom_getstring(node, "name", lbuf, sizeof(lbuf));
        strcpy(dev->prom_name, lbuf);
@@ -90,6 +146,27 @@ __initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
                printk("\n");
        }
 #endif
+       if ((node = prom_getchild(node))) {
+               dev->children = (struct linux_ebus_child *)
+                       ebus_alloc(&memory_start, sizeof(struct linux_ebus_child));
+
+               child = dev->children;
+               child->next = 0;
+               child->parent = dev;
+               fill_ebus_child(node, child);
+
+               while ((node = prom_getsibling(node))) {
+                       child->next = (struct linux_ebus_child *)
+                               ebus_alloc(&memory_start, sizeof(struct linux_ebus_child));
+
+                       child = child->next;
+                       child->next = 0;
+                       child->parent = dev;
+                       fill_ebus_child(node, child);
+               }
+       }
+
+       return memory_start;
 }
 
 __initfunc(unsigned long ebus_init(unsigned long memory_start,
@@ -100,31 +177,32 @@ __initfunc(unsigned long ebus_init(unsigned long memory_start,
        struct linux_ebus_device *dev;
        struct linux_ebus *ebus;
        struct pci_dev *pdev;
+       struct pcidev_cookie *cookie;
        char lbuf[128];
        unsigned long addr, *base;
-       int nd, len, ebusnd, topnd;
+       unsigned short pci_command;
+       int nd, len, ebusnd;
        int reg, rng, nreg;
-       int devfn;
        int num_ebus = 0;
 
-#ifndef CONFIG_PCI
-       return memory_start;
-#endif
-
-       memory_start = ((memory_start + 7) & (~7));
-
-       topnd = psycho_root->pbm_B.prom_node;
-       if (!topnd)
+       if (!pcibios_present())
                return memory_start;
 
-       ebusnd = prom_searchsiblings(prom_getchild(topnd), "ebus");
-       if (ebusnd == 0) {
-               printk("EBUS: No EBUS's found.\n");
+       for (pdev = pci_devices; pdev; pdev = pdev->next) {
+               if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
+                   (pdev->device == PCI_DEVICE_ID_SUN_EBUS))
+                       break;
+       }
+       if (!pdev) {
+               printk("ebus: No EBus's found.\n");
                return memory_start;
        }
 
-       ebus_chain = ebus = (struct linux_ebus *)memory_start;
-       memory_start += sizeof(struct linux_ebus);
+       cookie = pdev->sysdata;
+       ebusnd = cookie->prom_node;
+
+       ebus_chain = ebus = (struct linux_ebus *)
+                       ebus_alloc(&memory_start, sizeof(struct linux_ebus));
        ebus->next = 0;
 
        while (ebusnd) {
@@ -133,7 +211,16 @@ __initfunc(unsigned long ebus_init(unsigned long memory_start,
                prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
                ebus->prom_node = ebusnd;
                strcpy(ebus->prom_name, lbuf);
-               ebus->parent = pbm = &psycho_root->pbm_B;
+
+               ebus->self = pdev;
+               ebus->parent = pbm = cookie->pbm;
+
+               /* Enable BUS Master. */
+               pcibios_read_config_word(pdev->bus->number, pdev->devfn,
+                                        PCI_COMMAND, &pci_command);
+               pci_command |= PCI_COMMAND_MASTER;
+               pcibios_write_config_word(pdev->bus->number, pdev->devfn,
+                                         PCI_COMMAND, pci_command);
 
                len = prom_getproperty(ebusnd, "reg", (void *)regs,
                                       sizeof(regs));
@@ -144,17 +231,6 @@ __initfunc(unsigned long ebus_init(unsigned long memory_start,
                }
                nreg = len / sizeof(struct linux_prom_pci_registers);
 
-               devfn = (regs[0].phys_hi >> 8) & 0xff;
-               for (pdev = pbm->pci_bus.devices; pdev; pdev = pdev->sibling)
-                       if (pdev->devfn == devfn)
-                               break;
-               if (!pdev) {
-                       prom_printf("%s: can't find PCI device\n",
-                                   __FUNCTION__);
-                       prom_halt();
-               }
-               ebus->self = pdev;
-
                base = &ebus->self->base_address[0];
                for (reg = 0; reg < nreg; reg++) {
                        if (!(regs[reg].phys_hi & 0x03000000))
@@ -181,25 +257,41 @@ __initfunc(unsigned long ebus_init(unsigned long memory_start,
                prom_ebus_ranges_init(ebus);
 
                nd = prom_getchild(ebusnd);
-               ebus->devices = (struct linux_ebus_device *)memory_start;
-               memory_start += sizeof(struct linux_ebus_device);
+               ebus->devices = (struct linux_ebus_device *)
+                       ebus_alloc(&memory_start, sizeof(struct linux_ebus_device));
 
                dev = ebus->devices;
                dev->next = 0;
+               dev->children = 0;
                dev->parent = ebus;
-               fill_ebus_device(nd, dev);
+               memory_start = fill_ebus_device(nd, dev, memory_start);
 
                while ((nd = prom_getsibling(nd))) {
-                       dev->next = (struct linux_ebus_device *)memory_start;
-                       memory_start += sizeof(struct linux_ebus_device);
+                       dev->next = (struct linux_ebus_device *)
+                               ebus_alloc(&memory_start, sizeof(struct linux_ebus_device));
 
                        dev = dev->next;
                        dev->next = 0;
+                       dev->children = 0;
                        dev->parent = ebus;
-                       fill_ebus_device(nd, dev);
+                       memory_start = fill_ebus_device(nd, dev, memory_start);
                }
 
-               ebusnd = prom_searchsiblings(prom_getsibling(ebusnd), "ebus");
+               for (pdev = pdev->next; pdev; pdev = pdev->next) {
+                       if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
+                           (pdev->device == PCI_DEVICE_ID_SUN_EBUS))
+                               break;
+               }
+               if (!pdev)
+                       break;
+
+               cookie = pdev->sysdata;
+               ebusnd = cookie->prom_node;
+
+               ebus->next = (struct linux_ebus *)
+                       ebus_alloc(&memory_start, sizeof(struct linux_ebus));
+               ebus = ebus->next;
+               ebus->next = 0;
                ++num_ebus;
        }
 
index 1964061be4550b65b3fb2ed666594d94c413b3fc..af88ca4b679506db0982645940443c47d3162ced 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.17 1997/09/03 11:54:49 ecd Exp $
+/* $Id: ioctl32.c,v 1.18 1997/09/06 02:25:13 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
 #include <asm/rtc.h>
 #include <asm/openpromio.h>
 
-/*
- * XXX: for DaveM:
- * This is the kludge to know what size of buffer to
- * copy back to the user... (ecd)
- */
-int ifr_data_len;
-
 /* As gcc will warn about casting u32 to some ptr, we have to cast it to
  * unsigned long first, and that's what is A() for.
  * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x)
@@ -203,13 +196,17 @@ static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, u32 arg)
                case SIOCGPPPVER:
                {
                        u32 data;
+                       int len;
+
                        __get_user(data, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_data));
-                       /*
-                        * XXX: for DaveM:
-                        * Here we use 'ifr_data_len' to know what size of buffer to
-                        * copy back to the user... (ecd)
-                        */
-                       if (copy_to_user((char *)A(data), ifr.ifr_data, ifr_data_len))
+                       if(cmd == SIOCGPPPVER)
+                               len = strlen(PPP_VERSION) + 1;
+                       else if(cmd == SIOCGPPPCSTATS)
+                               len = sizeof(struct ppp_comp_stats);
+                       else
+                               len = sizeof(struct ppp_stats);
+
+                       if (copy_to_user((char *)A(data), ifr.ifr_data, len))
                                return -EFAULT;
                        break;
                }
index 490fee987381cb2e3b406be561ea0961e30b3637..ce9d1c7eae5fc67fa522b032275c1db7020d6896 100644 (file)
@@ -161,11 +161,6 @@ static inline int __get_order(unsigned long size);
 #include <linux/blk.h>
 #include <linux/cdrom.h> /* for the compatibility eject ioctl */
 
-
-#ifndef FLOPPY_MOTOR_MASK
-#define FLOPPY_MOTOR_MASK 0xf0
-#endif
-
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
 #endif
index 62e2f8da3c8f3a6d679384a99706bf68ab57c345..558a1b2d2613a6150c86b6977fa3ee1f58aea0df 100644 (file)
@@ -584,7 +584,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
        unsigned int cmd, unsigned long arg)
 {
        struct hd_geometry *loc = (struct hd_geometry *) arg;
-       int dev, err;
+       int dev;
 
        if ((!inode) || !(inode->i_rdev))
                return -EINVAL;
@@ -593,19 +593,15 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                return -EINVAL;
        switch (cmd) {
                case HDIO_GETGEO:
+               {
+                       struct hd_geometry g; 
                        if (!loc)  return -EINVAL;
-                       err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
-                       if (err)
-                               return err;
-                       put_user(hd_info[dev].head,
-                               (char *) &loc->heads);
-                       put_user(hd_info[dev].sect,
-                               (char *) &loc->sectors);
-                       put_user(hd_info[dev].cyl,
-                               (short *) &loc->cylinders);
-                       put_user(hd[MINOR(inode->i_rdev)].start_sect,
-                               (long *) &loc->start);
-                       return 0;
+                       g.heads = hd_info[dev].head;
+                       g.sectors = hd_info[dev].sect;
+                       g.cylinders = hd_info[dev].cyl;
+                       g.start = hd[MINOR(inode->i_rdev)].start_sect;
+                       return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+               }
                case BLKRASET:
                        if(!suser())  return -EACCES;
                        if(arg > 0xff) return -EINVAL;
@@ -613,18 +609,12 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                        return 0;
                case BLKRAGET:
                        if (!arg)  return -EINVAL;
-                       err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-                       if (err)
-                               return err;
-                       put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
-                       return 0;
+                       return put_user(read_ahead[MAJOR(inode->i_rdev)],
+                                       (long *) arg); 
                case BLKGETSIZE:   /* Return device size */
                        if (!arg)  return -EINVAL;
-                       err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-                       if (err)
-                               return err;
-                       put_user(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
-                       return 0;
+                       return put_user(hd[MINOR(inode->i_rdev)].nr_sects, 
+                                       (long *) arg);
                case BLKFLSBUF:
                        if(!suser())  return -EACCES;
                        fsync_dev(inode->i_rdev);
@@ -817,7 +807,7 @@ __initfunc(int hd_init(void))
 
 /*
  * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
+ * for a changed disk, and then re-read the new partition table.
  * If we are revalidating a disk because of a media change, then we
  * enter with usage == 0.  If we are using an ioctl, we automatically have
  * usage == 1 (we need an open channel to use an ioctl :-), so this
@@ -850,8 +840,11 @@ static int revalidate_hddisk(kdev_t dev, int maxusage)
        for (i=max_p - 1; i >=0 ; i--) {
                int minor = start + i;
                kdev_t devi = MKDEV(MAJOR_NR, minor);
+               struct super_block *sb = get_super(devi); 
+
                sync_dev(devi);
-               invalidate_inodes(devi);
+               if (sb)
+                       invalidate_inodes(sb);
                invalidate_buffers(devi);
                gdev->part[minor].start_sect = 0;
                gdev->part[minor].nr_sects = 0;
index dddf5dd8d72df25435910162332a30f59fa1e2d4..6d269745b72c562399c82da3986d80355bd7ab84 100644 (file)
 #include <linux/module.h>
 #include <linux/md.h>
 #include <linux/raid0.h>
-#include <linux/malloc.h>
+#include <linux/vmalloc.h>
 
 #define MAJOR_NR MD_MAJOR
 #define MD_DRIVER
 #define MD_PERSONALITY
 
-static void create_strip_zones (int minor, struct md_dev *mddev)
+static int create_strip_zones (int minor, struct md_dev *mddev)
 {
   int i, j, c=0;
   int current_offset=0;
@@ -50,8 +50,8 @@ static void create_strip_zones (int minor, struct md_dev *mddev)
     c=0;
   }
 
-  data->strip_zone=kmalloc (sizeof(struct strip_zone)*data->nr_strip_zones,
-                             GFP_KERNEL);
+  if ((data->strip_zone=vmalloc(sizeof(struct strip_zone)*data->nr_strip_zones)) == NULL)
+    return 1;
 
   data->smallest=NULL;
   
@@ -81,6 +81,7 @@ static void create_strip_zones (int minor, struct md_dev *mddev)
                                           data->strip_zone[i-1].size) : 0;
     current_offset=smallest_by_zone->size;
   }
+  return 0;
 }
 
 static int raid0_run (int minor, struct md_dev *mddev)
@@ -90,17 +91,26 @@ static int raid0_run (int minor, struct md_dev *mddev)
 
   MOD_INC_USE_COUNT;
 
-  mddev->private=kmalloc (sizeof (struct raid0_data), GFP_KERNEL);
+  if ((mddev->private=vmalloc (sizeof (struct raid0_data))) == NULL) return 1;
   data=(struct raid0_data *) mddev->private;
   
-  create_strip_zones (minor, mddev);
+  if (create_strip_zones (minor, mddev)) 
+  {
+       vfree(data);
+       return 1;
+  }
 
   nb_zone=data->nr_zones=
     md_size[minor]/data->smallest->size +
     (md_size[minor]%data->smallest->size ? 1 : 0);
-  
-  data->hash_table=kmalloc (sizeof (struct raid0_hash)*nb_zone, GFP_KERNEL);
 
+  printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone);
+  if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL)
+  {
+    vfree(data->strip_zone);
+    vfree(data);
+    return 1;
+  }
   size=data->strip_zone[cur].size;
 
   i=0;
@@ -142,9 +152,9 @@ static int raid0_stop (int minor, struct md_dev *mddev)
 {
   struct raid0_data *data=(struct raid0_data *) mddev->private;
 
-  kfree (data->hash_table);
-  kfree (data->strip_zone);
-  kfree (data);
+  vfree (data->hash_table);
+  vfree (data->strip_zone);
+  vfree (data);
 
   MOD_DEC_USE_COUNT;
   return 0;
index 7d7a3931ca8b85c0583fda20c98e25335cdf7df6..b8239df9b1fe619d1d52dc3aa41ff0d0d87d942b 100644 (file)
@@ -447,7 +447,7 @@ __initfunc(static void rd_load_image(kdev_t device,int offset))
        struct inode inode, out_inode;
        struct file infile, outfile;
        struct dentry in_dentry, out_dentry;
-       unsigned short fs;
+       unsigned long fs;
        kdev_t ram_device;
        int nblocks, i;
        char *buf;
index bfaf9b774b76a8cc3e025a6d3ad68caa533dd36e..05e99482fe11394eb30b897745a994a2c09fba2c 100644 (file)
@@ -101,8 +101,10 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
   fi
   tristate '   Software Watchdog' CONFIG_SOFT_WATCHDOG
   tristate '   Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
+  tristate '   Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
 fi
 bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+bool 'Tadpole ANA H8 Support'  CONFIG_H8
 tristate '/dev/nvram support' CONFIG_NVRAM
 tristate 'PC joystick support' CONFIG_JOYSTICK
 endmenu
index ed7f15bbefda71d086ed83706dfcc1a554936f97..9150a37f688859411f2f7fba2169429308dd52e4 100644 (file)
@@ -204,6 +204,16 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_ACQUIRE_WDT),y)
+M = y
+L_OBJS += acquirewdt.o
+else
+  ifeq ($(CONFIG_ACQUIRE_WDT),m)
+  M_OBJS += acquirewdt.o
+  MM = m
+  endif
+endif
+
 ifeq ($(CONFIG_AMIGAMOUSE),y)
 M = y
 L_OBJS += amigamouse.o
@@ -293,6 +303,11 @@ LX_OBJS += apm_bios.o
 M = y
 endif
 
+ifdef CONFIG_H8
+LX_OBJS += h8.o
+M = y
+endif
+
 ifdef M
 LX_OBJS += misc.o
 else
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
new file mode 100644 (file)
index 0000000..aeb7b72
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *     Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x
+ *
+ *      Based on wdt.c. Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@cymru.net>, All Rights Reserved.
+ *                             http://www.cymru.net
+ *
+ *     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.
+ *     
+ *     Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 
+ *     warranty for any of this software. This material is provided 
+ *     "AS-IS" and at no charge.       
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+static int acq_is_open=0;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ */
+#define WDT_STOP 0x43
+#define WDT_START 0x443
+#define WATCHDOG_MINOR 130
+
+#define WD_TIMO (100*60)               /* 1 minute */
+
+
+/*
+ *     Kernel methods.
+ */
+
+static void acq_ping(void)
+{
+       /* Write a watchdog value */
+       inb_p(WDT_START);
+}
+
+static long acq_write(struct inode *inode, struct file *file, const char *buf, unsigned long count)
+{
+       if(count)
+       {
+               acq_ping();
+               return 1;
+       }
+       return 0;
+}
+
+static long acq_read(struct inode *inode, struct file *file, char *buf, unsigned long count)
+{
+       return -EINVAL;
+}
+
+
+
+static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       static struct watchdog_info ident=
+       {
+               WDIOF_KEEPALIVEPING, 1, "Acquire WDT"
+       };
+       
+       switch(cmd)
+       {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+         
+       case WDIOC_GETSTATUS:
+         if (copy_to_user((int *)arg, &acq_is_open,  sizeof(int)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_KEEPALIVE:
+         acq_ping();
+         break;
+
+       default:
+         return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static int acq_open(struct inode *inode, struct file *file)
+{
+       switch(MINOR(inode->i_rdev))
+       {
+               case WATCHDOG_MINOR:
+                       if(acq_is_open)
+                               return -EBUSY;
+                       MOD_INC_USE_COUNT;
+                       /*
+                        *      Activate 
+                        */
+        
+                       acq_is_open=1;
+                       inb_p(WDT_START);      
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int acq_close(struct inode *inode, struct file *file)
+{
+       if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
+       {
+#ifndef CONFIG_WATCHDOG_NOWAYOUT       
+               inb_p(WDT_STOP);
+#endif         
+               acq_is_open=0;
+       }
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int acq_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+       {
+               /* Turn the card off */
+               inb_p(WDT_STOP);
+       }
+       return NOTIFY_DONE;
+}
+/*
+ *     Kernel Interfaces
+ */
+static struct file_operations acq_fops = {
+       NULL,
+       acq_read,
+       acq_write,
+       NULL,           /* No Readdir */
+       NULL,           /* No Select */
+       acq_ioctl,
+       NULL,           /* No mmap */
+       acq_open,
+       acq_close
+};
+
+static struct miscdevice acq_miscdev=
+{
+       WATCHDOG_MINOR,
+       "Acquire WDT",
+       &acq_fops
+};
+
+
+/*
+ *     The WDT card needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block acq_notifier=
+{
+       acq_notify_sys,
+       NULL,
+       0
+};
+
+#ifdef MODULE
+
+#define acq_init init_module
+
+void cleanup_module(void)
+{
+       misc_deregister(&acq_miscdev);
+       unregister_reboot_notifier(&acq_notifier);
+       release_region(WDT_STOP,1);
+       release_region(WDT_START,1);
+}
+
+#endif
+
+__initfunc(int acq_init(void))
+{
+       printk("WDT driver for Acquire single board computer initialising.\n");
+
+       misc_register(&acq_miscdev);
+       request_region(WDT_STOP, 1, "Acquire WDT");
+       request_region(WDT_START, 1, "Acquire WDT");
+       unregister_reboot_notifier(&acq_notifier);
+       return 0;
+}
+
diff --git a/drivers/char/h8.c b/drivers/char/h8.c
new file mode 100644 (file)
index 0000000..73941a0
--- /dev/null
@@ -0,0 +1,1272 @@
+/*
+ */
+/*
+ * Hitachi H8/337 Microcontroller driver
+ *
+ * The H8 is used to deal with the power and thermal environment
+ * of a system.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/timer.h>
+#include <linux/fcntl.h>
+#include <linux/malloc.h>
+#include <linux/linkage.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#endif
+#include <linux/miscdevice.h>
+#include <linux/lists.h>
+#include <linux/ioport.h>
+
+#define __KERNEL_SYSCALLS__
+#include <asm/unistd.h>
+
+#include "h8.h"
+
+#define DEBUG_H8
+
+#ifdef DEBUG_H8
+#define Dprintk                printk
+#else
+#define Dprintk
+#endif
+
+#define XDprintk if(h8_debug==-1)printk
+
+/*
+ * The h8 device is one of the misc char devices.
+ */
+#define H8_MINOR_DEV   140
+
+/*
+ * Forward declarations.
+ */
+int          h8_init(void);
+int          h8_display_blank(void);
+int          h8_display_unblank(void);
+
+static int   h8_open(struct inode *, struct file *);
+static void  h8_release(struct inode *, struct file *);
+static long  h8_read(struct inode *, struct file *, char *, u_long);
+static int   h8_select(struct inode *, struct file *, int, select_table *);
+static int   h8_ioctl(struct inode *, struct file *, u_int, u_long);
+
+static void  h8_intr(int irq, void *dev_id, struct pt_regs *regs);
+
+#ifdef CONFIG_PROC_FS
+static int   h8_get_info(char *, char **, off_t, int, int);
+#endif
+
+/*
+ * Support Routines.
+ */
+static void h8_hw_init(void);
+static void h8_start_new_cmd(void);
+static void h8_send_next_cmd_byte(void);
+static void h8_read_event_status(void);
+static void h8_sync(void);
+static void h8_q_cmd(u_char *, int, int);
+static void h8_cmd_done(h8_cmd_q_t *qp);
+static int  h8_alloc_queues(void);
+
+static u_long h8_get_cpu_speed(void);
+static int h8_get_curr_temp(u_char curr_temp[]);
+static void h8_get_max_temp(void);
+static void h8_get_upper_therm_thold(void);
+static void h8_set_upper_therm_thold(int);
+static int h8_get_ext_status(u_char stat_word[]);
+
+static int h8_monitor_thread(void *);
+
+static int h8_manage_therm(void);
+static void h8_set_cpu_speed(int speed_divisor);
+
+static void h8_start_monitor_timer(unsigned long secs);
+static void h8_activate_monitor(unsigned long unused);
+
+/* in arch/alpha/kernel/lca.c */
+extern void lca_clock_print(void);
+extern int  lca_get_clock(void);
+extern void lca_clock_fiddle(int);
+
+static void h8_set_event_mask(int);
+static void h8_clear_event_mask(int);
+
+/*
+ * Driver structures
+ */
+
+static struct timer_list h8_monitor_timer;
+static int h8_monitor_timer_active = 0;
+
+static char  driver_version[] = "X0.0";/* no spaces */
+
+static struct file_operations h8_fops = {
+        NULL,           /* lseek */
+        h8_read,
+        NULL,           /* write */
+        NULL,           /* readdir */
+        h8_select,
+        h8_ioctl,
+        NULL,           /* mmap */
+        h8_open,
+        h8_release,
+        NULL,           /* fsync */
+        NULL            /* fasync */
+};
+
+static struct miscdevice h8_device = {
+        H8_MINOR_DEV,
+        "h8",
+        &h8_fops
+};
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry    h8_proc_entry = {
+        0, 3, "h8", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, h8_get_info
+};
+#endif
+
+union  intr_buf intrbuf;
+int    intr_buf_ptr;
+union   intr_buf xx;   
+u_char  last_temp;
+
+/*
+ * I/O Macros for register reads and writes.
+ */
+#define H8_READ(a)     inb((a))
+#define H8_WRITE(d,a)  outb((d),(a))
+
+#define        H8_GET_STATUS   H8_READ((h8_base) + H8_STATUS_REG_OFF)
+#define H8_READ_DATA   H8_READ((h8_base) + H8_DATA_REG_OFF)
+#define WRITE_DATA(d)  H8_WRITE((d), h8_base + H8_DATA_REG_OFF)
+#define WRITE_CMD(d)   H8_WRITE((d), h8_base + H8_CMD_REG_OFF)
+
+unsigned int h8_base = H8_BASE_ADDR;
+unsigned int h8_irq = H8_IRQ;
+unsigned int h8_state = H8_IDLE;
+unsigned int h8_index = -1;
+unsigned int h8_enabled = 0;
+
+queue_head_t h8_actq, h8_cmdq, h8_freeq;
+
+/* 
+ * Globals used in thermal control of Alphabook1.
+ */
+int cpu_speed_divisor = -1;                    
+int h8_event_mask = 0;                 
+struct wait_queue *h8_monitor_wait = NULL;
+unsigned int h8_command_mask = 0;
+int h8_uthermal_threshold = DEFAULT_UTHERMAL_THRESHOLD;
+int h8_uthermal_window = UTH_HYSTERESIS;                     
+int h8_debug = 0xfffffdfc;
+int h8_ldamp = MHZ_115;
+int h8_udamp = MHZ_57;
+u_char h8_current_temp = 0;
+u_char h8_system_temp = 0;
+int h8_sync_channel = 0;
+struct wait_queue *h8_sync_wait = NULL;
+int h8_init_performed;
+
+/* CPU speeds and clock divisor values */
+int speed_tab[6] = {230, 153, 115, 57, 28, 14};
+  
+/*
+ * H8 interrupt handler
+ */
+static void h8_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+       u_char  stat_reg, data_reg;
+       h8_cmd_q_t *qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_actq, link);
+
+       stat_reg = H8_GET_STATUS;
+       data_reg = H8_READ_DATA;
+
+       XDprintk("h8_intr: state %d status 0x%x data 0x%x\n", h8_state, stat_reg, data_reg);
+
+       switch (h8_state) {
+         /* Response to an asynchronous event. */
+       case H8_IDLE: { /* H8_IDLE */
+           if (stat_reg & H8_OFULL) {
+               if (data_reg == H8_INTR) {
+                   h8_state = H8_INTR_MODE;
+                   /* Executing a command to determine what happened. */
+                   WRITE_CMD(H8_RD_EVENT_STATUS);
+                   intr_buf_ptr = 1;
+                   WRITE_CMD(H8_RD_EVENT_STATUS);
+               } else {
+                   Dprintk("h8_intr: idle stat 0x%x data 0x%x\n",
+                           stat_reg, data_reg);
+               }
+           } else {
+               Dprintk("h8_intr: bogus interrupt\n");
+           }
+           break;
+       }
+       case H8_INTR_MODE: { /* H8_INTR_MODE */
+           XDprintk("H8 intr/intr_mode\n");
+           if (data_reg == H8_BYTE_LEVEL_ACK) {
+               return;
+           } else if (data_reg == H8_CMD_ACK) {
+               return;
+           } else {
+               intrbuf.byte[intr_buf_ptr] = data_reg;
+               if(!intr_buf_ptr) {
+                   h8_state = H8_IDLE;
+                   h8_read_event_status();
+               }
+               intr_buf_ptr--;
+           }
+           break;
+       }
+       /* Placed in this state by h8_start_new_cmd(). */
+       case H8_XMIT: { /* H8_XMIT */
+           XDprintk("H8 intr/xmit\n");
+           /* If a byte level acknowledgement has been received */
+           if (data_reg == H8_BYTE_LEVEL_ACK) {
+               XDprintk("H8 intr/xmit BYTE ACK\n");
+               qp->nacks++;
+               if (qp->nacks > qp->ncmd)
+                   if(h8_debug & 0x1)
+                       Dprintk("h8intr: bogus # of acks!\n");
+               /* 
+                * If the number of bytes sent is less than the total 
+                * number of bytes in the command.
+                */ 
+               if (qp->cnt < qp->ncmd) {
+                   h8_send_next_cmd_byte();
+               }
+               return;
+               /* If the complete command has produced an acknowledgement. */
+           } else if (data_reg == H8_CMD_ACK) {
+               XDprintk("H8 intr/xmit CMD ACK\n");
+               /* If there are response bytes */
+               if (qp->nrsp)
+                   h8_state = H8_RCV;
+               else
+                   h8_state = H8_IDLE;
+               qp->cnt = 0;
+               return;
+               /* Error, need to start over with a clean slate. */
+           } else if (data_reg == H8_NACK) {
+               XDprintk("h8_intr: NACK received restarting command\n");
+               qp->nacks = 0;
+               qp->cnt = 0;
+               h8_state = H8_IDLE;
+               WRITE_CMD(H8_SYNC);
+               return;
+           } else {
+               Dprintk ("h8intr: xmit unknown data 0x%x \n", data_reg);
+               return;
+           }
+           break;
+       }
+       case H8_RESYNC: { /* H8_RESYNC */
+           XDprintk("H8 intr/resync\n");
+           if (data_reg == H8_BYTE_LEVEL_ACK) {
+               return;
+           } else if (data_reg == H8_SYNC_BYTE) {
+               h8_state = H8_IDLE;
+               if (!QUEUE_EMPTY(&h8_actq, link))
+                   h8_send_next_cmd_byte();
+           } else {
+               Dprintk ("h8_intr: resync unknown data 0x%x \n", data_reg);
+               return;
+           }
+           break;
+       } 
+       case H8_RCV: { /* H8_RCV */
+           XDprintk("H8 intr/rcv\n");
+           if (qp->cnt < qp->nrsp) {
+               qp->rcvbuf[qp->cnt] = data_reg;
+               qp->cnt++;
+               /* If command reception finished. */
+               if (qp->cnt == qp->nrsp) {
+                   h8_state = H8_IDLE;
+                   QUEUE_REMOVE(&h8_actq, qp, link);
+                   h8_cmd_done (qp);
+                   /* More commands to send over? */
+                   if (!QUEUE_EMPTY(&h8_cmdq, link))
+                       h8_start_new_cmd();
+               }
+               return;
+           } else {
+               Dprintk ("h8intr: rcv overflow cmd 0x%x\n", qp->cmdbuf[0]);
+           }
+           break;
+       }
+       default: /* default */
+           Dprintk("H8 intr/unknown\n");
+           break;
+       }
+       return;
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+        printk("H8 module at %X(Interrupt %d)\n", h8_base, h8_irq);
+        if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL))
+        {
+                printk("H8: error: IRQ %d is not free.\n", h8_irq);
+                return -EIO;
+        }
+
+        misc_register(&h8_device);
+        request_region(h8_base, 8, "h8");
+
+#ifdef CONFIG_PROC_FS
+        proc_register_dynamic(&proc_root, &h8_proc_entry);
+#endif
+
+       QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
+       QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *);
+       QUEUE_INIT(&h8_freeq, link, h8_cmd_q_t *);
+       h8_alloc_queues();
+
+       h8_hw_init();
+
+       kernel_thread(h8_monitor_thread, NULL, 0);
+
+        return 0;
+}
+
+void cleanup_module(void)
+{
+        misc_deregister(&h8_device);
+        release_region(h8_base, 8);
+        free_irq(h8_irq, NULL);
+}
+
+#else /* MODULE */
+
+int h8_init(void)
+{
+        if(request_irq(h8_irq, h8_intr, SA_INTERRUPT, "h8", NULL))
+        {
+                printk("H8: error: IRQ %d is not free\n", h8_irq);
+                return -EIO;
+        }
+        printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq);
+
+#ifdef CONFIG_PROC_FS
+        proc_register_dynamic(&proc_root, &h8_proc_entry);
+#endif
+
+        misc_register(&h8_device);
+        request_region(h8_base, 8, "h8");
+
+       QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
+       QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *);
+       QUEUE_INIT(&h8_freeq, link, h8_cmd_q_t *);
+       h8_alloc_queues();
+
+       h8_hw_init();
+
+       kernel_thread(h8_monitor_thread, NULL, 0);
+
+        return 0;
+}
+#endif /* MODULE */
+
+void h8_hw_init(void)
+{
+       u_char  buf[H8_MAX_CMD_SIZE];
+
+       /* set CPU speed to max for booting */
+       h8_set_cpu_speed(MHZ_230);
+
+       /*
+        * Initialize the H8
+        */
+       h8_sync();  /* activate interrupts */
+
+       /* To clear conditions left by console */
+       h8_read_event_status(); 
+
+       /* Perform a conditioning read */
+       buf[0] = H8_DEVICE_CONTROL;
+       buf[1] = 0xff;
+       buf[2] = 0x0;
+       h8_q_cmd(buf, 3, 1);
+
+       /* Turn on built-in and external mice, capture power switch */
+       buf[0] = H8_DEVICE_CONTROL;
+       buf[1] = 0x0;
+       buf[2] = H8_ENAB_INT_PTR | H8_ENAB_EXT_PTR |
+              /*H8_DISAB_PWR_OFF_SW |*/ H8_ENAB_LOW_SPD_IND;
+       h8_q_cmd(buf, 3, 1);
+
+        h8_enabled = 1;
+       return;
+}
+
+#ifdef CONFIG_PROC_FS
+int h8_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
+{
+        char *p;
+
+        if (!h8_enabled)
+                return 0;
+        p = buf;
+
+
+        /*
+           0) Linux driver version (this will change if format changes)
+           1) 
+           2) 
+           3)
+           4)
+       */
+            
+        p += sprintf(p, "%s \n",
+                     driver_version
+                    );
+
+        return p - buf;
+}
+#endif
+
+static long h8_read(struct inode *inode, struct file *fp, char *buf,
+                   u_long count)
+{
+       printk("h8_read: IMPDEL\n");
+       return 0;
+}
+
+static int h8_select(struct inode *inode, struct file *fp, int sel_type,
+                     select_table * wait)
+{
+       printk("h8_select: IMPDEL\n");
+       return 0;
+}
+
+static int h8_ioctl(struct inode * inode, struct file *filp,
+                    u_int cmd, u_long arg)
+{
+       printk("h8_ioctl: IMPDEL\n");
+       return 0;
+}
+
+static void h8_release(struct inode * inode, struct file * filp)
+{
+       printk("h8_release: IMPDEL\n");
+}
+
+static int h8_open(struct inode * inode, struct file * filp)
+{
+       printk("h8_open: IMPDEL\n");
+       return 0;
+}
+
+/* Called from console driver -- must make sure h8_enabled. */
+int h8_display_blank(void)
+{
+#ifdef CONFIG_H8_DISPLAY_BLANK
+        int     error;
+
+        if (!h8_enabled)
+                return 0;
+        error = h8_set_display_power_state(H8_STATE_STANDBY);
+        if (error == H8_SUCCESS)
+                return 1;
+        h8_error("set display standby", error);
+#endif
+        return 0;
+}
+
+/* Called from console driver -- must make sure h8_enabled. */
+int h8_display_unblank(void)
+{
+#ifdef CONFIG_H8_DISPLAY_BLANK
+        int error;
+
+        if (!h8_enabled)
+                return 0;
+        error = h8_set_display_power_state(H8_STATE_READY);
+        if (error == H8_SUCCESS)
+                return 1;
+        h8_error("set display ready", error);
+#endif
+        return 0;
+}
+
+int
+h8_alloc_queues(void)
+{
+        h8_cmd_q_t *qp;
+       unsigned long flags;
+        int i;
+
+        qp = (h8_cmd_q_t *)kmalloc((sizeof (h8_cmd_q_t) * H8_Q_ALLOC_AMOUNT),
+                                  GFP_KERNEL);
+
+        if (!qp) {
+                printk("H8: could not allocate memory for command queue\n");
+                return(0);
+        }
+        /* add to the free queue */
+        save_flags(flags); cli();
+        for (i = 0; i < H8_Q_ALLOC_AMOUNT; i++) {
+                /* place each at front of freeq */
+                QUEUE_ENTER(&h8_freeq, &qp[i], link, h8_cmd_q_t *);
+        }
+        restore_flags(flags);
+        return (1);
+}
+
+/* 
+ * Basic means by which commands are sent to the H8.
+ */
+void
+h8_q_cmd(u_char *cmd, int cmd_size, int resp_size)
+{
+        h8_cmd_q_t      *qp;
+       unsigned long flags;
+        int             i;
+
+        /* get cmd buf */
+       save_flags(flags); cli();
+        while (QUEUE_EMPTY(&h8_freeq, link)) {
+                Dprintk("H8: need to allocate more cmd buffers\n");
+                restore_flags(flags);
+                h8_alloc_queues();
+                save_flags(flags); cli();
+        }
+        /* get first element from queue */
+        qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_freeq, link);
+        QUEUE_REMOVE(&h8_freeq, qp, link);
+
+        restore_flags(flags);
+
+        /* fill it in */
+        for (i = 0; i < cmd_size; i++)
+            qp->cmdbuf[i] = cmd[i];
+        qp->ncmd = cmd_size;
+        qp->nrsp = resp_size;
+
+        /* queue it at the end of the cmd queue */
+        save_flags(flags); cli();
+
+        QUEUE_ENTER(&h8_cmdq, qp, link, h8_cmd_q_t *);
+
+        restore_flags(flags);
+
+        h8_start_new_cmd();
+}
+
+void
+h8_start_new_cmd(void)
+{
+        unsigned long flags;
+        h8_cmd_q_t *qp;
+
+       save_flags(flags); cli();
+        if (h8_state != H8_IDLE) {
+                if (h8_debug & 0x1)
+                        Dprintk("h8_start_new_cmd: not idle\n");
+                restore_flags(flags);
+                return;
+        }
+
+        if (!QUEUE_EMPTY(&h8_actq, link)) {
+                Dprintk("h8_start_new_cmd: inconsistency: IDLE with non-empty active queue!\n");
+                restore_flags(flags);
+                return;
+        }
+
+        if (QUEUE_EMPTY(&h8_cmdq, link)) {
+                Dprintk("h8_start_new_cmd: no command to dequeue\n");
+                restore_flags(flags);
+                return;
+        }
+        /*
+         * Take first command off of the command queue and put
+         * it on the active queue.
+         */
+        qp = (h8_cmd_q_t *) QUEUE_FIRST(&h8_cmdq, link);
+        QUEUE_REMOVE(&h8_cmdq, qp, link);
+        QUEUE_ENTER(&h8_actq, qp, link, h8_cmd_q_t *);
+        h8_state = H8_XMIT;
+        if (h8_debug & 0x1)
+                Dprintk("h8_start_new_cmd: Starting a command\n");
+
+        qp->cnt = 1;
+        WRITE_CMD(qp->cmdbuf[0]);               /* Kick it off */
+
+        restore_flags(flags);
+        return;
+}
+
+void
+h8_send_next_cmd_byte(void)
+{
+        h8_cmd_q_t      *qp = (h8_cmd_q_t *)QUEUE_FIRST(&h8_actq, link);
+        int cnt;
+
+        cnt = qp->cnt;
+        qp->cnt++;
+
+        if (h8_debug & 0x1)
+                Dprintk("h8 sending next cmd byte 0x%x (0x%x)\n",
+                       cnt, qp->cmdbuf[cnt]);
+
+        if (cnt) {
+                WRITE_DATA(qp->cmdbuf[cnt]);
+        } else {
+                WRITE_CMD(qp->cmdbuf[cnt]);
+        }
+        return;
+}
+
+/*
+ * Synchronize H8 communications channel for command transmission.
+ */
+void
+h8_sync(void)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        buf[0] = H8_SYNC;
+        buf[1] = H8_SYNC_BYTE;
+        h8_q_cmd(buf, 2, 1);
+}
+
+/*
+ * Responds to external interrupt. Reads event status word and 
+ * decodes type of interrupt. 
+ */
+void
+h8_read_event_status(void)
+{
+
+        if(h8_debug & 0x200)
+                printk("h8_read_event_status: value 0x%x\n", intrbuf.word);
+
+        /*
+         * Power related items
+         */
+        if (intrbuf.word & H8_DC_CHANGE) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: DC_CHANGE\n");
+                /* see if dc added or removed, set batt/dc flag, send event */
+
+                h8_set_event_mask(H8_MANAGE_BATTERY);
+                wake_up(&h8_monitor_wait);
+        }
+
+        if (intrbuf.word & H8_POWER_BUTTON) {
+                printk("Power switch pressed - please wait - preparing to power 
+off\n");
+                h8_set_event_mask(H8_POWER_BUTTON);
+                wake_up(&h8_monitor_wait);
+        }
+
+        /*
+         * Thermal related items
+         */
+        if (intrbuf.word & H8_THERMAL_THRESHOLD) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: THERMAL_THRESHOLD\n");
+                h8_set_event_mask(H8_MANAGE_UTHERM);
+                wake_up(&h8_monitor_wait);
+        }
+
+        /*
+         * nops -for now
+         */
+        if (intrbuf.word & H8_DOCKING_STATION_STATUS) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: DOCKING_STATION_STATUS\n");
+                /* read_ext_status */
+        }
+        if (intrbuf.word & H8_EXT_BATT_STATUS) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: EXT_BATT_STATUS\n");
+
+        }
+        if (intrbuf.word & H8_EXT_BATT_CHARGE_STATE) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: EXT_BATT_CHARGE_STATE\n");
+
+        }
+        if (intrbuf.word & H8_BATT_CHANGE_OVER) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: BATT_CHANGE_OVER\n");
+
+        }
+        if (intrbuf.word & H8_WATCHDOG) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: WATCHDOG\n");
+                /* nop */
+        }
+        if (intrbuf.word & H8_SHUTDOWN) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: SHUTDOWN\n");
+                /* nop */
+        }
+        if (intrbuf.word & H8_KEYBOARD) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: KEYBOARD\n");
+                /* nop */
+        }
+        if (intrbuf.word & H8_EXT_MOUSE_OR_CASE_SWITCH) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: EXT_MOUSE_OR_CASE_SWITCH\n");
+                /* read_ext_status*/
+        }
+        if (intrbuf.word & H8_INT_BATT_LOW) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: INT_BATT_LOW\n");
+                /* post event, warn user */
+        }
+        if (intrbuf.word & H8_INT_BATT_CHARGE_STATE) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: INT_BATT_CHARGE_STATE\n");
+                /* nop - happens often */
+        }
+        if (intrbuf.word & H8_INT_BATT_STATUS) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: INT_BATT_STATUS\n");
+
+        }
+        if (intrbuf.word & H8_INT_BATT_CHARGE_THRESHOLD) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: INT_BATT_CHARGE_THRESHOLD\n");
+                /* nop - happens often */
+        }
+        if (intrbuf.word & H8_EXT_BATT_LOW) {
+               if(h8_debug & 0x4)
+                   printk("h8_read_event_status: EXT_BATT_LOW\n");
+                /*if no internal, post event, warn user */
+                /* else nop */
+        }
+
+        return;
+}
+
+/*
+ * Function called when H8 has performed requested command.
+ */
+void
+h8_cmd_done(h8_cmd_q_t *qp)
+{
+
+        /* what to do */
+        switch (qp->cmdbuf[0]) {
+       case H8_SYNC:
+           if (h8_debug & 0x40000) 
+               printk("H8: Sync command done - byte returned was 0x%x\n", 
+                      qp->rcvbuf[0]);
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_RD_SN:
+       case H8_RD_ENET_ADDR:
+           printk("H8: Read ethernet addr - command done - address: %x - %x - %x - %x - %x - %x \n", 
+                  qp->rcvbuf[0], qp->rcvbuf[1], qp->rcvbuf[2],
+                  qp->rcvbuf[3], qp->rcvbuf[4], qp->rcvbuf[5]);
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_RD_HW_VER:
+       case H8_RD_MIC_VER:
+       case H8_RD_MAX_TEMP:
+           printk("H8: Max recorded CPU temp %d, Sys temp %d\n",
+                  qp->rcvbuf[0], qp->rcvbuf[1]);
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_RD_MIN_TEMP:
+           printk("H8: Min recorded CPU temp %d, Sys temp %d\n",
+                  qp->rcvbuf[0], qp->rcvbuf[1]);
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_RD_CURR_TEMP:
+           h8_sync_channel |= H8_RD_CURR_TEMP;
+           xx.byte[0] = qp->rcvbuf[0];
+           xx.byte[1] = qp->rcvbuf[1];
+           wake_up(&h8_sync_wait); 
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); 
+           break;
+
+       case H8_RD_SYS_VARIENT:
+       case H8_RD_PWR_ON_CYCLES:
+           printk(" H8: RD_PWR_ON_CYCLES command done\n");
+           break;
+
+       case H8_RD_PWR_ON_SECS:
+           printk("H8: RD_PWR_ON_SECS command done\n");
+           break;
+
+       case H8_RD_RESET_STATUS:
+       case H8_RD_PWR_DN_STATUS:
+       case H8_RD_EVENT_STATUS:
+       case H8_RD_ROM_CKSM:
+       case H8_RD_EXT_STATUS:
+           xx.byte[1] = qp->rcvbuf[0];
+           xx.byte[0] = qp->rcvbuf[1];
+           h8_sync_channel |= H8_GET_EXT_STATUS;
+           wake_up(&h8_sync_wait); 
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *); 
+           break;
+
+       case H8_RD_USER_CFG:
+       case H8_RD_INT_BATT_VOLT:
+       case H8_RD_DC_INPUT_VOLT:
+       case H8_RD_HORIZ_PTR_VOLT:
+       case H8_RD_VERT_PTR_VOLT:
+       case H8_RD_EEPROM_STATUS:
+       case H8_RD_ERR_STATUS:
+       case H8_RD_NEW_BUSY_SPEED:
+       case H8_RD_CONFIG_INTERFACE:
+       case H8_RD_INT_BATT_STATUS:
+           printk("H8: Read int batt status cmd done - returned was %x %x %x\n",
+                  qp->rcvbuf[0], qp->rcvbuf[1], qp->rcvbuf[2]);
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_RD_EXT_BATT_STATUS:
+       case H8_RD_PWR_UP_STATUS:
+       case H8_RD_EVENT_STATUS_MASK:
+       case H8_CTL_EMU_BITPORT:
+       case H8_DEVICE_CONTROL:
+           if(h8_debug & 0x20000) {
+               printk("H8: Device control cmd done - byte returned was 0x%x\n",
+                      qp->rcvbuf[0]);
+           }
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_CTL_TFT_BRT_DC:
+       case H8_CTL_WATCHDOG:
+       case H8_CTL_MIC_PROT:
+       case H8_CTL_INT_BATT_CHG:
+       case H8_CTL_EXT_BATT_CHG:
+       case H8_CTL_MARK_SPACE:
+       case H8_CTL_MOUSE_SENSITIVITY:
+       case H8_CTL_DIAG_MODE:
+       case H8_CTL_IDLE_AND_BUSY_SPDS:
+           printk("H8: Idle and busy speed command done\n");
+           break;
+
+       case H8_CTL_TFT_BRT_BATT:
+       case H8_CTL_UPPER_TEMP:
+           if(h8_debug & 0x10) {
+               XDprintk("H8: ctl upper thermal thresh cmd done - returned was %d\n",
+                      qp->rcvbuf[0]);
+           }
+           QUEUE_ENTER(&h8_freeq, qp, link, h8_cmd_q_t *);
+           break;
+
+       case H8_CTL_LOWER_TEMP:
+       case H8_CTL_TEMP_CUTOUT:
+       case H8_CTL_WAKEUP:
+       case H8_CTL_CHG_THRESHOLD:
+       case H8_CTL_TURBO_MODE:
+       case H8_SET_DIAG_STATUS:
+       case H8_SOFTWARE_RESET:
+       case H8_RECAL_PTR:
+       case H8_SET_INT_BATT_PERCENT:
+       case H8_WRT_CFG_INTERFACE_REG:
+       case H8_WRT_EVENT_STATUS_MASK:
+       case H8_ENTER_POST_MODE:
+       case H8_EXIT_POST_MODE:
+       case H8_RD_EEPROM:
+       case H8_WRT_EEPROM:
+       case H8_WRT_TO_STATUS_DISP:
+           printk("H8: Write IO status display command done\n");
+           break;
+
+       case H8_DEFINE_SPC_CHAR:
+       case H8_DEFINE_TABLE_STRING_ENTRY:
+       case H8_PERFORM_EMU_CMD:
+       case H8_EMU_RD_REG:
+       case H8_EMU_WRT_REG:
+       case H8_EMU_RD_RAM:
+       case H8_EMU_WRT_RAM:
+       case H8_BQ_RD_REG:
+       case H8_BQ_WRT_REG:
+       case H8_PWR_OFF:
+           printk ("H8: misc command completed\n");
+           break;
+        }
+        return;
+}
+
+/*
+ * Retrieve the current cpu temperature and case temperature.  Provides
+ * the feedback for the thermal control algorithm.  Synchcronized via 
+ * sleep() for priority so that no other actions in the process will take
+ * place before the data becomes available.
+ */
+int
+h8_get_curr_temp(u_char curr_temp[])
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+        unsigned long flags;
+
+        memset(buf, 0, H8_MAX_CMD_SIZE); 
+        buf[0] = H8_RD_CURR_TEMP;
+
+        h8_q_cmd(buf, 1, 2);
+
+       save_flags(flags); cli();
+
+        while((h8_sync_channel & H8_RD_CURR_TEMP) == 0)
+                sleep_on(&h8_sync_wait); 
+
+        restore_flags(flags);
+
+        h8_sync_channel &= ~H8_RD_CURR_TEMP;
+        curr_temp[0] = xx.byte[0];
+        curr_temp[1] = xx.byte[1];
+        xx.word = 0;
+
+        if(h8_debug & 0x8) 
+                printk("H8: curr CPU temp %d, Sys temp %d\n",
+                      curr_temp[0], curr_temp[1]);
+        return 0;
+}
+
+static void
+h8_get_max_temp(void)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        buf[0] = H8_RD_MAX_TEMP;
+        h8_q_cmd(buf, 1, 2);
+}
+
+/*
+ * Assigns an upper limit to the value of the H8 thermal interrupt.
+ * As an example setting a value of 115 F here will cause the 
+ * interrupt to trigger when the cpu temperature reaches 115 F.
+ */
+static void
+h8_set_upper_therm_thold(int thold)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        /* write 0 to reinitialize interrupt */
+        buf[0] = H8_CTL_UPPER_TEMP;
+        buf[1] = 0x0;
+        buf[2] = 0x0;
+        h8_q_cmd(buf, 3, 1); 
+
+        /* Do it for real */
+        buf[0] = H8_CTL_UPPER_TEMP;
+        buf[1] = 0x0;
+        buf[2] = thold;
+        h8_q_cmd(buf, 3, 1); 
+}
+
+static void
+h8_get_upper_therm_thold(void)
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+
+        buf[0] = H8_CTL_UPPER_TEMP;
+        buf[1] = 0xff;
+        buf[2] = 0;
+        h8_q_cmd(buf, 3, 1); 
+}
+
+/*
+ * The external status word contains information on keyboard controller,
+ * power button, changes in external batt status, change in DC state,
+ * docking station, etc. General purpose querying use.
+ */
+int
+h8_get_ext_status(u_char stat_word[])
+{
+        u_char  buf[H8_MAX_CMD_SIZE];
+       unsigned long flags;
+
+        memset(buf, 0, H8_MAX_CMD_SIZE); 
+        buf[0] = H8_RD_EXT_STATUS;
+
+        h8_q_cmd(buf, 1, 2);
+
+       save_flags(flags); cli();
+
+        while((h8_sync_channel & H8_GET_EXT_STATUS) == 0)
+                sleep_on(&h8_sync_wait); 
+
+        restore_flags(flags);
+
+        h8_sync_channel &= ~H8_GET_EXT_STATUS;
+        stat_word[0] = xx.byte[0];
+        stat_word[1] = xx.byte[1];
+        xx.word = 0;
+
+        if(h8_debug & 0x8) 
+                printk("H8: curr ext status %x,  %x\n",
+                      stat_word[0], stat_word[1]);
+
+        return 0;
+}
+
+/*
+ * Thread attached to task 0 manages thermal/physcial state of Alphabook. 
+ * When a condition is detected by the interrupt service routine, the
+ * isr does a wakeup() on h8_monitor_wait.  The mask value is then
+ * screened for the appropriate action.
+ */
+
+int
+h8_monitor_thread(void * unused)
+{
+        u_char curr_temp[2];
+
+        /*
+         * Need a logic based safety valve here. During boot when this thread is
+         * started and the thermal interrupt is not yet initialized this logic 
+         * checks the temperature and acts accordingly.  When this path is acted
+         * upon system boot is painfully slow, however, the priority associated 
+         * with overheating is high enough to warrant this action.
+         */
+        h8_get_curr_temp(curr_temp);
+
+        printk("H8: Initial CPU temp: %d\n", curr_temp[0]);
+
+        if(curr_temp[0] >= h8_uthermal_threshold) {
+                h8_set_event_mask(H8_MANAGE_UTHERM);
+                h8_manage_therm();
+        } else {
+                /*
+                 * Arm the upper thermal limit of the H8 so that any temp in
+                 * excess will trigger the thermal control mechanism.
+                 */
+                h8_set_upper_therm_thold(h8_uthermal_threshold);
+        }
+
+        for(;;) {
+               sleep_on(&h8_monitor_wait);
+
+                if(h8_debug & 0x2)
+                        printk("h8_monitor_thread awakened, mask:%x\n",
+                                h8_event_mask);
+
+                if (h8_event_mask & (H8_MANAGE_UTHERM|H8_MANAGE_LTHERM)) {
+                        h8_manage_therm();
+                }
+
+#if 0
+                if (h8_event_mask & H8_POWER_BUTTON) {
+                        h8_system_down();
+                }
+
+               /*
+                * If an external DC supply is removed or added make 
+                * appropriate cpu speed adjustments.
+                */
+                if (h8_event_mask & H8_MANAGE_BATTERY) {
+                          h8_run_level_3_manage(H8_RUN); 
+                          h8_clear_event_mask(H8_MANAGE_BATTERY);
+                }
+#endif
+        }
+}
+
+/* 
+ * Function implements the following policy. When the machine is booted
+ * the system is set to run at full clock speed. When the upper thermal
+ * threshold is reached as a result of full clock a damping factor is 
+ * applied to cool off the cpu.  The default value is one quarter clock
+ * (57 Mhz).  When as a result of this cooling a temperature lower by
+ * hmc_uthermal_window is reached, the machine is reset to a higher 
+ * speed, one half clock (115 Mhz).  One half clock is maintained until
+ * the upper thermal threshold is again reached restarting the cycle.
+ */
+
+int
+h8_manage_therm(void)
+{
+        u_char curr_temp[2];
+
+        if(h8_event_mask & H8_MANAGE_UTHERM) {
+               /* Upper thermal interrupt received, need to cool down. */
+               if(h8_debug & 0x10)
+                        printk("H8: Thermal threshold %d F reached\n",
+                              h8_uthermal_threshold);
+               h8_set_cpu_speed(h8_udamp); 
+                h8_clear_event_mask(H8_MANAGE_UTHERM);
+                h8_set_event_mask(H8_MANAGE_LTHERM);
+                /* Check again in 30 seconds for cpu temperature */
+                h8_start_monitor_timer(H8_TIMEOUT_INTERVAL); 
+        } else if (h8_event_mask & H8_MANAGE_LTHERM) {
+               /* See how cool the system has become as a result
+                  of the reduction in speed. */
+                h8_get_curr_temp(curr_temp);
+                last_temp = curr_temp[0];
+                if (curr_temp[0] < (h8_uthermal_threshold - h8_uthermal_window))
+               {
+                       /* System cooling has progressed to a point
+                          that the cpu may be speeded up. */
+                        h8_set_upper_therm_thold(h8_uthermal_threshold);
+                        h8_set_cpu_speed(h8_ldamp); /* adjustable */ 
+                        if(h8_debug & 0x10)
+                            printk("H8: CPU cool, applying cpu_divisor: %d \n",
+                                  h8_ldamp);
+                        h8_clear_event_mask(H8_MANAGE_LTHERM);
+                }
+               else /* Not cool enough yet, check again in 30 seconds. */
+                        h8_start_monitor_timer(H8_TIMEOUT_INTERVAL);
+        } else {
+                
+        }
+       return 0;
+}
+
+/* 
+ * Function conditions the value of global_rpb_counter before
+ * calling the primitive which causes the actual speed change.
+ */
+void
+h8_set_cpu_speed(int speed_divisor)
+{
+
+#ifdef NOT_YET
+/*
+ * global_rpb_counter is consumed by alpha_delay() in determining just
+ * how much time to delay.  It is necessary that the number of microseconds
+ * in DELAY(n) be kept consistent over a variety of cpu clock speeds.
+ * To that end global_rpb_counter is here adjusted.
+ */ 
+        
+        switch (speed_divisor) {
+                case 0:
+                        global_rpb_counter = rpb->rpb_counter * 2L;
+                        break;
+                case 1:
+                        global_rpb_counter = rpb->rpb_counter * 4L / 3L ;
+                        break;
+                case 3:
+                        global_rpb_counter = rpb->rpb_counter / 2L;
+                        break;
+                case 4:
+                        global_rpb_counter = rpb->rpb_counter / 4L;
+                        break;
+                case 5:
+                        global_rpb_counter = rpb->rpb_counter / 8L;
+                        break;
+                /* 
+                 * This case most commonly needed for cpu_speed_divisor 
+                 * of 2 which is the value assigned by the firmware. 
+                 */
+                default:
+                        global_rpb_counter = rpb->rpb_counter;
+                break;
+        }
+#endif /* NOT_YET */
+
+        if(h8_debug & 0x8)
+                printk("H8: Setting CPU speed to %d MHz\n",
+                      speed_tab[speed_divisor]); 
+
+         /* Make the actual speed change */
+        lca_clock_fiddle(speed_divisor);
+}
+
+/*
+ * Gets value stored in rpb representing cpu clock speed and adjusts this
+ * value based on the current clock speed divisor.
+ */
+u_long
+h8_get_cpu_speed(void)
+{
+        u_long speed = 0;
+        u_long counter;
+
+#ifdef NOT_YET
+        counter = rpb->rpb_counter / 1000000L;
+
+        switch (alphabook_get_clock()) {
+                case 0:
+                        speed = counter * 2L;
+                        break;
+                case 1:
+                        speed = counter * 4L / 3L ;
+                        break;
+                case 2:
+                        speed = counter;
+                        break;
+                case 3:
+                        speed = counter / 2L;
+                        break;
+                case 4:
+                        speed = counter / 4L;
+                        break;
+                case 5:
+                        speed = counter / 8L;
+                        break;
+                default:
+                break;
+        }
+        if(h8_debug & 0x8)
+                printk("H8: CPU speed current setting: %d MHz\n", speed); 
+#endif  /* NOT_YET */
+       return speed;
+}
+
+static void
+h8_activate_monitor(unsigned long unused)
+{
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       h8_monitor_timer_active = 0;
+       restore_flags(flags);
+
+       wake_up(&h8_monitor_wait);
+}
+
+static void
+h8_start_monitor_timer(unsigned long secs)
+{
+       unsigned long flags;
+
+       if (h8_monitor_timer_active)
+           return;
+
+       save_flags(flags); cli();
+       h8_monitor_timer_active = 1;
+       restore_flags(flags);
+
+        init_timer(&h8_monitor_timer);
+        h8_monitor_timer.function = h8_activate_monitor;
+        h8_monitor_timer.expires = secs * HZ + jiffies;
+        add_timer(&h8_monitor_timer);
+}
+
+static void h8_set_event_mask(int mask)
+{
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       h8_event_mask |= mask;
+       restore_flags(flags);
+}
+
+static void h8_clear_event_mask(int mask)
+{
+       unsigned long flags;
+
+       save_flags(flags); cli();
+       h8_event_mask &= (~mask);
+       restore_flags(flags);
+}
diff --git a/drivers/char/h8.h b/drivers/char/h8.h
new file mode 100644 (file)
index 0000000..533c4ec
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ */
+
+#ifndef __H8_H__
+#define __H8_H__
+
+/*
+ * Register address and offsets
+ */
+#define H8_BASE_ADDR                   0x170            /* default */
+#define H8_IRQ                        9                /* default */
+#define H8_STATUS_REG_OFF              0x4              
+#define H8_CMD_REG_OFF                 0x4
+#define H8_DATA_REG_OFF                0x0
+
+
+/* H8 register bit definitions */
+/* status register */
+#define H8_OFULL                       0x1              /* output data register full */
+#define H8_IFULL                       0x2              /* input data register full */
+#define H8_CMD                         0x8              /* command / not data */
+
+#define H8_INTR                        0xfa
+#define H8_NACK                        0xfc
+#define H8_BYTE_LEVEL_ACK              0xfd
+#define H8_CMD_ACK                     0xfe
+#define H8_SYNC_BYTE                   0x99
+
+/*
+ * H8 command definitions
+ */
+/* System info commands */
+#define H8_SYNC                         0x0
+#define H8_RD_SN                        0x1
+#define H8_RD_ENET_ADDR                 0x2
+#define H8_RD_HW_VER                    0x3
+#define H8_RD_MIC_VER                   0x4
+#define H8_RD_MAX_TEMP                  0x5
+#define H8_RD_MIN_TEMP                  0x6
+#define H8_RD_CURR_TEMP                 0x7
+#define H8_RD_SYS_VARIENT               0x8
+#define H8_RD_PWR_ON_CYCLES             0x9
+#define H8_RD_PWR_ON_SECS               0xa
+#define H8_RD_RESET_STATUS              0xb
+#define H8_RD_PWR_DN_STATUS             0xc
+#define H8_RD_EVENT_STATUS              0xd
+#define H8_RD_ROM_CKSM                  0xe
+#define H8_RD_EXT_STATUS                0xf
+#define H8_RD_USER_CFG                  0x10
+#define H8_RD_INT_BATT_VOLT             0x11
+#define H8_RD_DC_INPUT_VOLT             0x12
+#define H8_RD_HORIZ_PTR_VOLT            0x13
+#define H8_RD_VERT_PTR_VOLT             0x14
+#define H8_RD_EEPROM_STATUS             0x15
+#define H8_RD_ERR_STATUS                0x16
+#define H8_RD_NEW_BUSY_SPEED            0x17
+#define H8_RD_CONFIG_INTERFACE          0x18
+#define H8_RD_INT_BATT_STATUS           0x19
+#define H8_RD_EXT_BATT_STATUS           0x1a
+#define H8_RD_PWR_UP_STATUS             0x1b
+#define H8_RD_EVENT_STATUS_MASK         0x56
+
+/* Read/write/modify commands */
+#define H8_CTL_EMU_BITPORT              0x32
+#define H8_DEVICE_CONTROL               0x21
+#define H8_CTL_TFT_BRT_DC               0x22
+#define H8_CTL_WATCHDOG                 0x23
+#define H8_CTL_MIC_PROT                 0x24
+#define H8_CTL_INT_BATT_CHG             0x25
+#define H8_CTL_EXT_BATT_CHG             0x26
+#define H8_CTL_MARK_SPACE               0x27
+#define H8_CTL_MOUSE_SENSITIVITY        0x28
+#define H8_CTL_DIAG_MODE                0x29
+#define H8_CTL_IDLE_AND_BUSY_SPDS       0x2a
+#define H8_CTL_TFT_BRT_BATT             0x2b
+#define H8_CTL_UPPER_TEMP               0x2c
+#define H8_CTL_LOWER_TEMP               0x2d
+#define H8_CTL_TEMP_CUTOUT              0x2e
+#define H8_CTL_WAKEUP                   0x2f
+#define H8_CTL_CHG_THRESHOLD            0x30
+#define H8_CTL_TURBO_MODE               0x31
+#define H8_SET_DIAG_STATUS              0x40
+#define H8_SOFTWARE_RESET               0x41
+#define H8_RECAL_PTR                    0x42
+#define H8_SET_INT_BATT_PERCENT         0x43
+#define H8_WRT_CFG_INTERFACE_REG        0x45
+#define H8_WRT_EVENT_STATUS_MASK        0x57
+#define H8_ENTER_POST_MODE              0x46
+#define H8_EXIT_POST_MODE               0x47
+
+/* Block transfer commands */
+#define H8_RD_EEPROM                    0x50
+#define H8_WRT_EEPROM                   0x51
+#define H8_WRT_TO_STATUS_DISP           0x52
+#define H8_DEFINE_SPC_CHAR              0x53
+/* Generic commands */
+#define H8_DEFINE_TABLE_STRING_ENTRY    0x60
+
+/* Battery control commands */
+#define H8_PERFORM_EMU_CMD              0x70
+#define H8_EMU_RD_REG                   0x71
+#define H8_EMU_WRT_REG                  0x72
+#define H8_EMU_RD_RAM                   0x73
+#define H8_EMU_WRT_RAM                  0x74
+#define H8_BQ_RD_REG                    0x75
+#define H8_BQ_WRT_REG                   0x76
+
+/* System admin commands */
+#define H8_PWR_OFF                      0x80
+
+/*
+ * H8 command related definitions
+ */
+
+/* device control argument bits */
+#define H8_ENAB_EXTSMI                  0x1
+#define H8_DISAB_IRQ                    0x2
+#define H8_ENAB_FLASH_WRT               0x4
+#define H8_ENAB_THERM                   0x8
+#define H8_ENAB_INT_PTR                 0x10
+#define H8_ENAB_LOW_SPD_IND             0x20
+#define H8_ENAB_EXT_PTR                 0x40
+#define H8_DISAB_PWR_OFF_SW             0x80
+#define H8_POWER_OFF                   0x80
+
+/* H8 read event status bits */
+#define H8_DC_CHANGE                    0x1
+#define H8_INT_BATT_LOW                 0x2
+#define H8_INT_BATT_CHARGE_THRESHOLD    0x4
+#define H8_INT_BATT_CHARGE_STATE        0x8
+#define H8_INT_BATT_STATUS              0x10
+#define H8_EXT_BATT_CHARGE_STATE        0x20
+#define H8_EXT_BATT_LOW                 0x40
+#define H8_EXT_BATT_STATUS              0x80
+#define H8_THERMAL_THRESHOLD            0x100
+#define H8_WATCHDOG                     0x200
+#define H8_DOCKING_STATION_STATUS       0x400
+#define H8_EXT_MOUSE_OR_CASE_SWITCH     0x800
+#define H8_KEYBOARD                     0x1000
+#define H8_BATT_CHANGE_OVER             0x2000
+#define H8_POWER_BUTTON                 0x4000
+#define H8_SHUTDOWN                     0x8000
+
+/* H8 control idle and busy speeds */
+#define H8_SPEED_LOW                    0x1
+#define H8_SPEED_MED                    0x2
+#define H8_SPEED_HI                     0x3
+#define H8_SPEED_LOCKED                 0x80
+
+#define H8_MAX_CMD_SIZE                 18      
+#define H8_Q_ALLOC_AMOUNT               10      
+
+/* H8 state field values */
+#define H8_IDLE                         1
+#define H8_XMIT                         2
+#define H8_RCV                          3
+#define H8_RESYNC                       4
+#define H8_INTR_MODE                    5
+
+/* Mask values for control functions */
+#define UTH_HYSTERESIS                  5
+#define DEFAULT_UTHERMAL_THRESHOLD      115
+#define H8_TIMEOUT_INTERVAL            30
+#define H8_RUN                          4
+
+#define H8_GET_MAX_TEMP                 0x1
+#define H8_GET_CURR_TEMP                0x2
+#define H8_GET_UPPR_THRMAL_THOLD        0x4
+#define H8_GET_ETHERNET_ADDR            0x8
+#define H8_SYNC_OP                      0x10 
+#define H8_SET_UPPR_THRMAL_THOLD        0x20
+#define H8_GET_INT_BATT_STAT            0x40
+#define H8_GET_CPU_SPD                  0x80
+#define H8_MANAGE_UTHERM                0x100 
+#define H8_MANAGE_LTHERM                0x200 
+#define H8_HALT                         0x400 
+#define H8_CRASH                        0x800 
+#define H8_GET_EXT_STATUS               0x10000
+#define H8_MANAGE_QUIET                 0x20000
+#define H8_MANAGE_SPEEDUP               0x40000
+#define H8_MANAGE_BATTERY               0x80000
+#define H8_SYSTEM_DELAY_TEST            0x100000
+#define H8_POWER_SWITCH_TEST            0x200000
+
+/* cpu speeds and clock divisor values */
+#define MHZ_14                           5
+#define MHZ_28                           4
+#define MHZ_57                           3
+#define MHZ_115                          2
+#define MHZ_230                          0 
+
+/*
+ * H8 data
+ */
+struct h8_data {
+        u_int           ser_num;
+        u_char          ether_add[6];
+        u_short         hw_ver;
+        u_short         mic_ver;
+        u_short         max_tmp;
+        u_short         min_tmp;
+        u_short         cur_tmp;
+        u_int           sys_var;
+        u_int           pow_on;
+        u_int           pow_on_secs;
+        u_char          reset_status;
+        u_char          pwr_dn_status;
+        u_short         event_status;
+        u_short         rom_cksm;
+        u_short         ext_status;
+        u_short         u_cfg;
+        u_char          ibatt_volt;
+        u_char          dc_volt;
+        u_char          ptr_horiz;
+        u_char          ptr_vert;
+        u_char          eeprom_status;
+        u_char          error_status;
+        u_char          new_busy_speed;
+        u_char          cfg_interface;
+        u_short         int_batt_status;
+        u_short         ext_batt_status;
+        u_char          pow_up_status;
+        u_char          event_status_mask;
+};
+
+
+/*
+ * H8 command buffers
+ */
+typedef struct h8_cmd_q {
+        DLNODE(struct h8_cmd_q) link; /* double linked list */
+        int             ncmd;           /* number of bytes in command */
+        int             nrsp;           /* number of bytes in response */
+        int             cnt;            /* number of bytes sent/received */
+        int             nacks;          /* number of byte level acks */
+        u_char          cmdbuf[H8_MAX_CMD_SIZE]; /* buffer to store command */
+        u_char          rcvbuf[H8_MAX_CMD_SIZE]; /* buffer to store response */
+} h8_cmd_q_t;
+
+typedef struct __queue_head {
+       DLNODE(struct h8_cmd_q) link;
+} queue_head_t;
+
+union   intr_buf {
+        u_char  byte[2];
+        u_int   word;
+};
+
+#endif /* __H8_H_ */
index 9dd9918a4c3c35756ec358265eb23493573b6298..78df2e3be88e86288307aa5cd021961b6a77570c 100644 (file)
@@ -339,13 +339,6 @@ static int mmap_zero(struct inode * inode, struct file * file, struct vm_area_st
        return 0;
 }
 
-static long read_full(struct inode * node, struct file * file,
-       char * buf, unsigned long count)
-{
-       file->f_pos += count;
-       return count;
-}
-
 static long write_full(struct inode * inode, struct file * file,
        const char * buf, unsigned long count)
 {
@@ -390,7 +383,9 @@ static long long memory_lseek(struct inode * inode, struct file * file,
 
 #define mmap_kmem      mmap_mem
 #define zero_lseek     null_lseek
+#define full_lseek      null_lseek
 #define write_zero     write_null
+#define read_full       read_zero
 
 static struct file_operations mem_fops = {
        memory_lseek,
@@ -457,7 +452,7 @@ static struct file_operations zero_fops = {
 };
 
 static struct file_operations full_fops = {
-       memory_lseek,
+       full_lseek,
        read_full,
        write_full,
        NULL,           /* full_readdir */
index 7ad5fce9f44c40b84e0950cb99dbe6d38d4b5698..5699ab1795cb2323797f16d12089b679c5b6ae19 100644 (file)
@@ -71,10 +71,12 @@ extern int atari_mouse_init(void);
 extern int sun_mouse_init(void);
 extern void watchdog_init(void);
 extern void wdt_init(void);
+extern void acq_init(void);
 extern void pcwatchdog_init(void);
 extern int rtc_init(void);
 extern int dsp56k_init(void);
 extern int nvram_init(void);
+extern void hfmodem_init(void);
 
 #ifdef CONFIG_PROC_FS
 static int misc_read_proc(char *buf, char **start, off_t offset,
@@ -231,18 +233,27 @@ __initfunc(int misc_init(void))
 #ifdef CONFIG_WDT
        wdt_init();
 #endif
+#ifdef CONFIG_ACQUIRE_WDT
+       acq_init();
+#endif
 #ifdef CONFIG_SOFT_WATCHDOG
        watchdog_init();
 #endif
 #ifdef CONFIG_APM
        apm_bios_init();
 #endif
+#ifdef CONFIG_H8
+       h8_init();
+#endif
 #ifdef CONFIG_RTC
        rtc_init();
 #endif
 #ifdef CONFIG_ATARI_DSP56K
        dsp56k_init();
 #endif
+#ifdef CONFIG_HFMODEM
+       hfmodem_init();
+#endif
 #ifdef CONFIG_NVRAM
        nvram_init();
 #endif
index 5eb82c78013a248ba7c7141dc25c7277feab465c..e4c58370fa536f5090a507aaff85ed69fac56917 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 
+#include <linux/config.h>
+
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #endif
index 2b79716c03f15d973759c48ea9f62dafa3d9e816..c5ab225846fd5dbd59543f98f22322ee2d782954 100644 (file)
@@ -1,4 +1,5 @@
-/* arc-rimi.c:
+/*     $Id: arc-rimi.c,v 1.2 1997/09/05 08:57:51 mj Exp $
+
         Derived from the original arcnet.c,
         Written 1994-1996 by Avery Pennarun,
        which was in turn derived from skeleton.c by Donald Becker.
 #undef SLOW_XMIT_COPY
 
 
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-                           char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-                              char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
-
 /* Internal function declarations */
+
 static int arcrimi_probe(struct device *dev);
 static void arcrimi_rx(struct device *dev,int recbuf);
-static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem); 
+static int arcrimi_found(struct device *dev,int ioaddr,int airq,u_long shmem);
 static void arcrimi_inthandler (struct device *dev);
 static int arcrimi_reset (struct device *dev, int reset_delay);
 static void arcrimi_setmask (struct device *dev, u_char mask);
@@ -122,7 +93,6 @@ static  void arcrimi_openclose(int open);
 
 /* Module parameters */
 
-
 #ifdef MODULE
 static int shmem=0x0;  /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
 static int irq=0;      /* or use the insmod io= irq= shmem= options */
@@ -142,7 +112,6 @@ extern int arcnet_num_devs;
 
 /* Handy defines for ARCnet specific stuff */
 
-
 /* COM 9026 controller chip --> ARCnet register addresses */
 #define _INTMASK (ioaddr+0)    /* writable */
 #define _STATUS  (ioaddr+0)    /* readable */
@@ -155,20 +124,14 @@ extern int arcnet_num_devs;
 
 #define RDDATAflag      0x00     /* Next access is a read/~write */
 
-
-
-
 #define ARCSTATUS      readb(_STATUS)
 #define ACOMMAND(cmd) writeb((cmd),_COMMAND)
 #define ARCRESET       writeb(TESTvalue,ioaddr-0x800)  /* fake reset */
 #define AINTMASK(msk)  writeb((msk),_INTMASK)
 #define SETCONF        writeb(lp->config,_CONFIG)
 
-
 static const char *version =
-"arc-rimi.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
-
-
+"arc-rimi.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 /****************************************************************************
  *                                                                          *
@@ -186,26 +149,25 @@ __initfunc(int arcrimi_probe(struct device *dev))
   BUGLVL(D_NORMAL) printk(version);
   BUGMSG(D_NORMAL,"Given: node %02Xh, shmem %lXh, irq %d\n",
         dev->dev_addr[0],dev->mem_start,dev->irq);
-  
+
   if (dev->mem_start<=0 || dev->irq<=0)
     {
       BUGMSG(D_NORMAL,"No autoprobe for RIM I; you "
             "must specify the shmem and irq!\n");
       return -ENODEV;
     }
-  
+
   if (dev->dev_addr[0]==0)
     {
       BUGMSG(D_NORMAL,"You need to specify your card's station "
             "ID!\n");
       return -ENODEV;
     }
-  
+
   return arcrimi_found(dev,dev->dev_addr[0],dev->irq,dev->mem_start);
 }
 
 
-
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
@@ -214,7 +176,7 @@ __initfunc(int arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
   struct arcnet_local *lp;
   u_long first_mirror,last_mirror;
   int mirror_size;
-  
+
   /* reserve the irq */
   if (request_irq(airq,&arcnet_interrupt,0,"arcnet (RIM I)",NULL))
     {
@@ -223,15 +185,15 @@ __initfunc(int arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
     }
   irq2dev_map[airq]=dev;
   dev->irq=airq;
-  
+
   dev->base_addr=0;
   writeb(TESTvalue,shmem);
   writeb(node,shmem+1);        /* actually the node ID */
-  
+
   /* find the real shared memory start/end points, including mirrors */
 #define BUFFER_SIZE (512)
 #define MIRROR_SIZE (BUFFER_SIZE*4)
-  
+
   /* guess the actual size of one "memory mirror" - the number of
    * bytes between copies of the shared memory.  On most cards, it's
    * 2k (or there are no mirrors at all) but on some, it's 4k.
@@ -241,21 +203,21 @@ __initfunc(int arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
       && readb(shmem-mirror_size)!=TESTvalue
       && readb(shmem-2*mirror_size)==TESTvalue)
     mirror_size*=2;
-  
+
   first_mirror=last_mirror=shmem;
   while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size;
   first_mirror+=mirror_size;
-  
+
   while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size;
   last_mirror-=mirror_size;
-  
+
   dev->mem_start=first_mirror;
   dev->mem_end=last_mirror+MIRROR_SIZE-1;
   dev->rmem_start=dev->mem_start+BUFFER_SIZE*0;
   dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1;
-  
+
   /* Initialize the rest of the device structure. */
-  
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -274,26 +236,26 @@ __initfunc(int arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
   lp->openclose_device=arcrimi_openclose;
   lp->prepare_tx=arcrimi_prepare_tx;
   lp->inthandler=arcrimi_inthandler;
-  
+
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
         sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
         sizeof(struct archdr));
-  
+
   /* get and check the station ID from offset 1 in shmem */
   lp->stationid = readb(first_mirror+1);
-  
+
   if (lp->stationid==0)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
           "for broadcasts!\n");
@@ -301,13 +263,13 @@ __initfunc(int arcrimi_found(struct device *dev,int node,int airq, u_long shmem)
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
           "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet RIM I: station %02Xh found at IRQ %d, "
         "ShMem %lXh (%ld*%d bytes).\n",
         lp->stationid,
         dev->irq, dev->mem_start,
         (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size);
-  
+
   return 0;
 }
 
@@ -324,46 +286,46 @@ int arcrimi_reset(struct device *dev,int reset_delay)
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->mem_start + 0x800;
   int recbuf=lp->recbuf;
-  
+
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
+
   /* no IRQ's, please! */
   lp->intmask=0;
   SETMASK;
-  
+
   BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
         dev->name,ARCSTATUS);
-  
+
   ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
   ACOMMAND(CFLAGScmd|CONFIGclear);
-  
+
   /* clear out status variables */
   recbuf=lp->recbuf=0;
   lp->txbuf=2;
-  
+
   /* enable extended (512-byte) packets */
   ACOMMAND(CONFIGcmd|EXTconf);
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out all the memory to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset_io(dev->mem_start,0x42,2048);
 #endif
-  
+
   /* and enable receive of our first packet to the first buffer */
   EnableReceiver();
-  
+
   /* re-enable interrupts */
   lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
   lp->intmask|=RECONflag;
 #endif
   SETMASK;
-  
+
   /* done!  return success. */
   return 0;
 }
@@ -380,28 +342,25 @@ static void arcrimi_openclose(int open)
 static void arcrimi_setmask(struct device *dev, u_char mask)
 {
   int ioaddr=dev->mem_start+0x800;
-  
+
   AINTMASK(mask);
 }
 
 static u_char arcrimi_status(struct device *dev)
 {
   int ioaddr=dev->mem_start+0x800;
-  
+
   return ARCSTATUS;
 }
 
 static void arcrimi_command(struct device *dev, u_char cmd)
 {
   int ioaddr=dev->mem_start+0x800;
-  
+
   ACOMMAND(cmd);
 }
 
 
-
-
-
 /* The actual interrupt handler routine - handle various IRQ's generated
  * by the card.
  */
@@ -410,18 +369,17 @@ arcrimi_inthandler(struct device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->mem_start+0x800, status, boguscount = 3, didsomething;
-  
+
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arcrimi_inthandler (status=%Xh, intmask=%Xh)\n",
         ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
       didsomething=0;
-      
-      
+
       /* RESET flag was enabled - card is resetting and if RX
        * is disabled, it's NOT because we just got a packet.
        */
@@ -430,44 +388,43 @@ arcrimi_inthandler(struct device *dev)
          BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
                 status);
          arcrimi_reset(dev,0);
-         
+
          /* all other flag values are just garbage */
          break;
        }
-      
-      
+
       /* RX is inhibited - we must have received something. */
       if (status & lp->intmask & NORXflag)
        {
          int recbuf=lp->recbuf=!lp->recbuf;
-         
+
          BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
                 status);
-         
+
          /* enable receive of our next packet */
          EnableReceiver();
-         
+
          /* Got a packet. */
          arcrimi_rx(dev,!recbuf);
-         
+
          didsomething++;
        }
-      
+
       /* it can only be an xmit-done irq if we're xmitting :) */
       /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
       if (status & lp->intmask & TXFREEflag)
        {
          struct Outgoing *out=&(lp->outgoing);
          int was_sending=lp->sending;
-         
+
          lp->intmask &= ~TXFREEflag;
-         
+
          lp->in_txhandler++;
          if (was_sending) lp->sending--;
-         
+
          BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
                 status,out->numsegs,out->segnum,out->skb);
-         
+
          if (was_sending && !(status&TXACKflag))
            {
              if (lp->lasttrans_dest != 0)
@@ -484,11 +441,11 @@ arcrimi_inthandler(struct device *dev)
                         lp->lasttrans_dest);
                }
            }
-         
+
          /* send packet if there is one */
          arcnet_go_tx(dev,0);
          didsomething++;
-         
+
          if (lp->intx)
            {
              BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
@@ -496,24 +453,24 @@ arcrimi_inthandler(struct device *dev)
              lp->in_txhandler--;
              continue;
            }
-         
+
          if (!lp->outgoing.skb)
            {
              BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-             
+
              /* inform upper layers */
              if (!lp->txready) arcnet_tx_done(dev, lp);
              lp->in_txhandler--;
              continue;
            }
-         
+
          /* if more than one segment, and not all segments
           * are done, then continue xmit.
           */
          if (out->segnum<out->numsegs)
            arcnetA_continue_tx(dev);
          arcnet_go_tx(dev,0);
-         
+
          /* if segnum==numsegs, the transmission is finished;
           * free the skb.
           */
@@ -527,12 +484,12 @@ arcrimi_inthandler(struct device *dev)
                  dev_kfree_skb(out->skb,FREE_WRITE);
                }
              out->skb=NULL;
-             
+
              /* inform upper layers */
              if (!lp->txready) arcnet_tx_done(dev, lp);
            }
          didsomething++;
-         
+
          lp->in_txhandler--;
        }
       else if (lp->txready && !lp->sending && !lp->intx)
@@ -542,20 +499,18 @@ arcrimi_inthandler(struct device *dev)
          arcnet_go_tx(dev,0);
          didsomething++;
        }
-      
+
 #ifdef DETECT_RECONFIGS
       if (status & (lp->intmask) & RECONflag)
        {
          ACOMMAND(CFLAGScmd|CONFIGclear);
          lp->stats.tx_carrier_errors++;
-         
+
 #ifdef SHOW_RECONFIGS
          BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
                 status);
-         
-         
 #endif /* SHOW_RECONFIGS */
-         
+
 #ifdef RECON_THRESHOLD
          /* is the RECON info empty or old? */
          if (!lp->first_recon || !lp->last_recon ||
@@ -565,19 +520,19 @@ arcrimi_inthandler(struct device *dev)
                BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
              lp->first_recon=lp->last_recon=jiffies;
              lp->num_recons=lp->network_down=0;
-             
+
              BUGMSG(D_DURING,"recon: clearing counters.\n");
            }
          else /* add to current RECON counter */
            {
              lp->last_recon=jiffies;
              lp->num_recons++;
-             
+
              BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
                     lp->num_recons,
                     (lp->last_recon-lp->first_recon)/HZ,
                     lp->network_down);
-             
+
              /* if network is marked up;
               * and first_recon and last_recon are 60+ sec
               *   apart;
@@ -609,26 +564,24 @@ arcrimi_inthandler(struct device *dev)
            BUGMSG(D_NORMAL,"cabling restored?\n");
          lp->first_recon=lp->last_recon=0;
          lp->num_recons=lp->network_down=0;
-         
+
          BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
        }
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
         ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;     /* put back interrupt mask */
-  
 }
 
 
-
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arcrimi_rx(struct device *dev,int recbuf)
@@ -640,11 +593,11 @@ arcrimi_rx(struct device *dev,int recbuf)
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -654,11 +607,11 @@ arcrimi_rx(struct device *dev,int recbuf)
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -669,26 +622,22 @@ arcrimi_rx(struct device *dev,int recbuf)
     {
       offset=arcpacket->hardheader.offset2;
       arcsoft=&arcpacket->raw[offset];
-      
+
       length=512-offset;
     }
-  
-  
+
   arcnet_rx(lp, arcsoft, length, saddr, daddr);
-  
-  
+
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset((void *)arcpacket->raw,0x42,512);
 #endif
-  
 }
 
 
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -699,45 +648,45 @@ arcrimi_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   union ArcPacket *arcpacket =
     (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
-  
+
 #ifdef SLOW_XMIT_COPY
   char *iptr,*iend,*optr;
 #endif
-  
+
   lp->txbuf=lp->txbuf^1;       /* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
         hdr,length,data);
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
 #endif
-  
+
   arcpacket->hardheader.destination=daddr;
-  
+
   /* load packet into shared memory */
   if (length<=MTU)     /* Normal (256-byte) Packet */
     arcpacket->hardheader.offset1=offset=offset?offset:256-length;
-  
+
   else if (length>=MinTU || offset)    /* Extended (512-byte) Packet */
     {
       arcpacket->hardheader.offset1=0;
-      arcpacket->hardheader.offset2=offset=offset?offset:512-length;   
+      arcpacket->hardheader.offset2=offset=offset?offset:512-length;
     }
   else if (exceptA)            /* RFC1201 Exception Packet */
     {
       arcpacket->hardheader.offset1=0;
       arcpacket->hardheader.offset2=offset=512-length-4;
-      
+
       /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-      
+
       arcpacket->raw[offset+0]=hdr[0];
       arcpacket->raw[offset+1]=0xFF; /* FF flag */
       arcpacket->raw[offset+2]=0xFF; /* FF padding */
@@ -748,17 +697,17 @@ arcrimi_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
       memset(&arcpacket->raw[508],0,4);
-      
+
       /* now round up to MinTU */
       arcpacket->hardheader.offset1=0;
       arcpacket->hardheader.offset2=offset=512-MinTU;
     }
-  
-  
+
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
-  
+
   memcpy((u_char*)arcpacket+offset, (u_char*)hdr,hdrlen);
 #ifdef SLOW_XMIT_COPY
   for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcpacket+offset+hdrlen;
@@ -770,18 +719,17 @@ arcrimi_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
 #else
   memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen);
 #endif
-  
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
         daddr,length);
-  
+
   BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx");
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;       /* packet is ready for sending */
 }
 
 
-
 /****************************************************************************
  *                                                                          *
  * Kernel Loadable Module Support                                           *
@@ -806,13 +754,13 @@ int init_module(void)
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
-  
+
   if (node && node != 0xff)
     dev->dev_addr[0]=node;
-  
+
   dev->irq=irq;
   if (dev->irq==2) dev->irq=9;
-  
+
   if (shmem)
     {
       dev->mem_start=shmem;
@@ -820,7 +768,7 @@ int init_module(void)
       dev->rmem_start=thiscard.mem_start+512*0;
       dev->rmem_end=thiscard.mem_start+512*2-1;
     }
-  
+
   if (register_netdev(dev) != 0)
     return -EIO;
   arcnet_use_count(1);
@@ -831,9 +779,9 @@ void cleanup_module(void)
 {
   struct device *dev=&thiscard;
   int ioaddr=dev->mem_start;
-  
+
   if (dev->start) (*dev->stop)(dev);
-  
+
   /* Flush TX and disable RX */
   if (ioaddr)
     {
@@ -841,13 +789,13 @@ void cleanup_module(void)
       ACOMMAND(NOTXcmd);       /* stop transmit */
       ACOMMAND(NORXcmd);       /* disable receive */
     }
-  
+
   if (dev->irq)
     {
       irq2dev_map[dev->irq] = NULL;
       free_irq(dev->irq,NULL);
     }
-  
+
   unregister_netdev(dev);
   kfree(dev->priv);
   dev->priv = NULL;
@@ -856,7 +804,6 @@ void cleanup_module(void)
 
 #else
 
-
 __initfunc(void arcrimi_setup (char *str, int *ints))
 {
   struct device *dev;
@@ -867,9 +814,9 @@ __initfunc(void arcrimi_setup (char *str, int *ints))
             MAX_ARCNET_DEVS);
       return;
     }
-  
+
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   if (ints[0] < 3)
     {
       printk("ARCnet RIM I: You must give address, IRQ and node ID.\n");
@@ -888,20 +835,17 @@ __initfunc(void arcrimi_setup (char *str, int *ints))
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* Mem address */
       dev->mem_start=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
-  
+
   arcnet_num_devs++;
 }
 
 #endif /* MODULE */
-
-
-
index 09807f8bba5f542fe410842d67b436756e0c3eec..7669b59a8d420410f8af2d89b119728bb10453ff 100644 (file)
@@ -1,8 +1,9 @@
-/* arcnet.c:
+/*     $Id: arcnet.c,v 1.30 1997/09/05 08:57:46 mj Exp $
+
        Written 1994-1996 by Avery Pennarun,
        derived from skeleton.c by Donald Becker.
 
-       Contact Avery at: apenwarr@foxnet.net or
+       Contact Avery at: apenwarr@bond.net or
        RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
        **********************
 
        **********************
 
+       v2.92 ALPHA (97/02/09)
+         - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
+         - Better probing for the COM90xx chipset, although only as
+           a temporary solution until we implement adding of all found
+           devices at once. [mj]
+
        v2.91 ALPHA (97/19/08)
          - Add counting of octets in/out.
 
          - Smarter recovery from RECON-during-transmit conditions. (ie.
            retransmit immediately)
          - Add support for the new 1.3.x IP header cache, and other features.
-         - Debug level should be changed with a system call, not a hack to
-           the "metric" flag.
+         - Replace setting of debug level with the "metric" flag hack by
+          something better. SIOCDEVPRIVATE is a good candidate, but it would
+          require an extra user-level utility.
 
          - What about cards with shared memory that can be "turned off?"
            (or that have none at all, like the SMC PC500longboard)
-     Does this work now, with IO_MAPPED_BUFFERS?
+           Does this work now, with IO_MAPPED_BUFFERS?
 
          - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
            with temporarily.)  Update: yes, the Pure Data config program
 */
 
 static const char *version =
- "arcnet.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
-
-
+ "arcnet.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -200,16 +206,14 @@ static const char *version =
 
 /**************************************************************************/
 
-/* These are now provided by the chipset driver. There's a performance 
+/* These are now provided by the chipset driver. There's a performance
  * overhead in using them.
  */
 
-
 #define AINTMASK(x) ((*lp->asetmask)(dev, x))
 #define ARCSTATUS ((*lp->astatus)(dev))
 #define ACOMMAND(x) ((*lp->acommand)(dev, x))
 
-
 int arcnet_debug=ARCNET_DEBUG;
 
 /* Exported function prototypes */
@@ -235,7 +239,6 @@ int arcnet_go_tx(struct device *dev,int enable_irq);
 void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
 void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
 
-
 EXPORT_SYMBOL(arcnet_debug);
 EXPORT_SYMBOL(arcnet_tx_done);
 EXPORT_SYMBOL(arcnet_use_count);
@@ -302,10 +305,6 @@ static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
 #endif
 
 
-
-
-
-
 /****************************************************************************
  *                                                                          *
  * Packet dumps for debugging                                               *
@@ -334,6 +333,7 @@ void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,char *desc)
 }
 #endif
 
+
 /* Dump the contents of an ARCnet buffer
  */
 #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
@@ -357,8 +357,6 @@ void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,char *desc)
 #endif
 
 
-
-
 /* Setup a struct device for ARCnet.  This should really be in net_init.c
  * but since there are three different ARCnet devices ANYWAY... <gargle>
  *
@@ -385,8 +383,7 @@ void arcnet_setup(struct device *dev)
        dev->pa_mask            = 0;
        dev->pa_alen            = 4;
 
-
-       /* Put in this stuff here, so we don't have to export the symbols 
+       /* Put in this stuff here, so we don't have to export the symbols
         * to the chipset drivers.
         */
 
@@ -405,7 +402,6 @@ void arcnet_setup(struct device *dev)
  *                                                                          *
  ****************************************************************************/
 
-
 /* Open/initialize the board.  This is called sometime after booting when
  * the 'ifconfig' program is run.
  *
@@ -417,39 +413,33 @@ static int
 arcnet_open(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+
   if (dev->metric>=1000)
     {
       arcnet_debug=dev->metric-1000;
       printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
       dev->metric=1;
     }
-  
+
   BUGMSG(D_INIT,"arcnet_open: resetting card.\n");
-  
+
   /* try to put the card in a defined state - if it fails the first
    * time, actually reset it.
    */
   if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1))
     return -ENODEV;
-#if 0
-  /* reset the card twice in case something goes wrong the first time.
-   */
-  if ((*(lp->arcnet_reset))(dev,1) && (*(lp->arcnet_reset))(dev,1))
-    return -ENODEV;
-#endif
-  
+
   dev->tbusy=0;
   dev->interrupt=0;
   lp->intx=0;
   lp->in_txhandler=0;
-  
+
   /* The RFC1201 driver is the default - just store */
   lp->adev=dev;
 
   /* we're started */
   dev->start=1;
-  
+
 #ifdef CONFIG_ARCNET_ETH
   /* Initialize the ethernet-encap protocol driver */
   lp->edev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
@@ -467,7 +457,7 @@ arcnet_open(struct device *dev)
   lp->edev->init=arcnetE_init;
   register_netdev(lp->edev);
 #endif
-  
+
 #ifdef CONFIG_ARCNET_1051
   /* Initialize the RFC1051-encap protocol driver */
   lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
@@ -477,27 +467,27 @@ arcnet_open(struct device *dev)
   lp->sdev->init=arcnetS_init;
   register_netdev(lp->sdev);
 #endif
-    
+
   /* Enable TX if we need to */
   if (lp->en_dis_able_TX)
     (*lp->en_dis_able_TX)(dev, 1);
-  
+
   /* make sure we're ready to receive IRQ's.
    * arcnet_reset sets this for us, but if we receive one before
    * START is set to 1, it could be ignored.  So, we turn IRQ's
    * off, then on again to clean out the IRQ controller.
    */
-  
+
   AINTMASK(0);
   udelay(1);   /* give it time to set the mask before
                 * we reset it again. (may not even be
                 * necessary)
                 */
   SETMASK;
-  
+
   /* Let it increase its use count */
   (*lp->openclose_device)(1);
-  
+
   return 0;
 }
 
@@ -508,7 +498,7 @@ static int
 arcnet_close(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   if (test_and_set_bit(0, (int *)&dev->tbusy))
     BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
 
@@ -522,36 +512,32 @@ arcnet_close(struct device *dev)
   lp->edev->start=0;
 #endif
 
-  
   /* Shut down the card */
-  
+
   /* Disable TX if we need to */
   if (lp->en_dis_able_TX)
     (*lp->en_dis_able_TX)(dev, 0);
-  
+
   (*lp->arcnet_reset)(dev, 3); /* reset IRQ won't run if START=0 */
 #if 0
   lp->intmask=0;
-  SETMASK;     /* no IRQ's (except RESET, of course) */
+  SETMASK;             /* no IRQ's (except RESET, of course) */
   ACOMMAND(NOTXcmd);   /* stop transmit */
   ACOMMAND(NORXcmd);   /* disable receive */
 #endif
-  
+
   /* reset more flags */
-       dev->interrupt=0;
+  dev->interrupt=0;
 #ifdef CONFIG_ARCNET_ETH
-       lp->edev->interrupt=0;
+  lp->edev->interrupt=0;
 #endif
 #ifdef CONFIG_ARCNET_1051
-       lp->sdev->interrupt=0;
+  lp->sdev->interrupt=0;
 #endif
 
-
-
-  
   /* do NOT free lp->adev!!  It's static! */
   lp->adev=NULL;
-  
+
 #ifdef CONFIG_ARCNET_ETH
   /* free the ethernet-encap protocol device */
   lp->edev->priv=NULL;
@@ -561,7 +547,7 @@ arcnet_close(struct device *dev)
   kfree(lp->edev);
   lp->edev=NULL;
 #endif
-  
+
 #ifdef CONFIG_ARCNET_1051
   /* free the RFC1051-encap protocol device */
   lp->sdev->priv=NULL;
@@ -571,17 +557,16 @@ arcnet_close(struct device *dev)
   kfree(lp->sdev);
   lp->sdev=NULL;
 #endif
-  
+
   /* Update the statistics here. (not necessary in ARCnet) */
-  
+
   /* Decrease the use count */
   (*lp->openclose_device)(0);
-  
+
   return 0;
 }
 
 
-
 /****************************************************************************
  *                                                                          *
  * Transmitter routines                                                     *
@@ -594,24 +579,24 @@ static int
 arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
         ARCSTATUS,lp->intx);
-  
+
   if (lp->in_txhandler)
     {
       BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n");
       lp->stats.tx_dropped++;
       return 1;
     }
-  
+
   if (lp->intx>1)
     {
       BUGMSG(D_NORMAL,"send_packet called while intx!\n");
       lp->stats.tx_dropped++;
       return 1;
     }
-  
+
   if (test_bit(0, (int *)&dev->tbusy))
     {
       /* If we get here, some higher level has decided we are broken.
@@ -619,7 +604,7 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
       int tickssofar = jiffies - dev->trans_start;
 
       int status=ARCSTATUS;
-      
+
       if (tickssofar < TX_TIMEOUT)
        {
          BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
@@ -628,10 +613,10 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
                 lp->outgoing.segnum);
          return 1;
        }
-      
+
       lp->intmask &= ~TXFREEflag;
       SETMASK;
-      
+
       if (status&TXFREEflag)   /* transmit _DID_ finish */
        {
          BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
@@ -644,17 +629,17 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
                 status,tickssofar,lp->intmask,lp->lasttrans_dest);
          lp->stats.tx_errors++;
          lp->stats.tx_aborted_errors++;
-         
+
          ACOMMAND(NOTXcmd);
        }
-      
+
       if (lp->outgoing.skb)
        {
          dev_kfree_skb(lp->outgoing.skb,FREE_WRITE);
          lp->stats.tx_dropped++;
        }
       lp->outgoing.skb=NULL;
-      
+
 #ifdef CONFIG_ARCNET_ETH
       lp->edev->tbusy=0;
 #endif
@@ -666,10 +651,10 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
 
       lp->txready=0;
       lp->sending=0;
-      
+
       return 1;
     }
-  
+
   if (lp->txready)     /* transmit already in progress! */
     {
       BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
@@ -681,10 +666,10 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
       lp->stats.tx_errors++;
       lp->stats.tx_fifo_errors++;
       lp->txready=0;   /* we definitely need this line! */
-      
+
       return 1;
     }
-  
+
   /* Block a timer-based transmit from overlapping.  This could better be
      done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
   if (test_and_set_bit(0, (int *)&lp->adev->tbusy))
@@ -701,7 +686,7 @@ arcnet_send_packet_bad(struct sk_buff *skb, struct device *dev)
 #ifdef CONFIG_ARCNET_ETH
   lp->edev->tbusy=1;
 #endif
-  
+
   return 0;
 }
 
@@ -714,13 +699,13 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,oldmask=0;
   struct Outgoing *out=&(lp->outgoing);
-  
+
   lp->intx++;
-  
+
   oldmask |= lp->intmask;
   lp->intmask=0;
   SETMASK;
-  
+
   bad=arcnet_send_packet_bad(skb,dev);
   if (bad)
     {
@@ -729,20 +714,20 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
       SETMASK;
       return bad;
     }
-  
+
   /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-  
+
   lp->intmask = oldmask & ~TXFREEflag;
   SETMASK;
-  
+
   out->length = 1 < skb->len ? skb->len : 1;
   out->hdr=(struct ClientData*)skb->data;
   out->skb=skb;
-  
+
   BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-  
+
   out->hdr->sequence=(lp->sequence++);
-  
+
   /* fits in one packet? */
   if (out->length-EXTRA_CLIENTDATA<=XMTU)
     {
@@ -759,12 +744,12 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
                        ((char *)skb->data)+sizeof(struct ClientData),
                        out->length-sizeof(struct ClientData),
                        out->hdr->daddr,1,0);
-      
+
       /* done right away */
       lp->stats.tx_bytes += out->skb->len;
       dev_kfree_skb(out->skb,FREE_WRITE);
       out->skb=NULL;
-      
+
       if (arcnet_go_tx(dev,1))
        {
          /* inform upper layers */
@@ -774,19 +759,19 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
   else                 /* too big for one - split it */
     {
       int maxsegsize=XMTU-4;
-      
+
       out->data=(u_char *)skb->data
        + sizeof(struct ClientData);
       out->dataleft=out->length-sizeof(struct ClientData);
       out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
       out->segnum=0;
-      
+
       BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
             out->length,out->numsegs);
-      
+
       /* if a packet waiting, launch it */
       arcnet_go_tx(dev,1);
-      
+
       if (!lp->txready)
        {
          /* prepare a packet, launch it and prepare
@@ -799,7 +784,7 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
              arcnet_go_tx(dev,1);
            }
        }
-      
+
       /* if segnum==numsegs, the transmission is finished;
        * free the skb right away.
        */
@@ -816,14 +801,14 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
          out->skb=NULL;
        }
     }
-  
+
   dev->trans_start=jiffies;
   lp->intx--;
+
   /* make sure we didn't ignore a TX IRQ while we were in here */
   lp->intmask |= TXFREEflag;
   SETMASK;
-  
+
   return 0;
 }
 
@@ -837,38 +822,38 @@ void arcnetA_continue_tx(struct device *dev)
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int maxsegsize=XMTU-4;
   struct Outgoing *out=&(lp->outgoing);
-  
+
   BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
         ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);
-  
+
   if (lp->txready)
     {
       BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
       return;
     }
-  
+
   if (out->segnum>=out->numsegs)
     {
       BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n",
             out->segnum+1,out->numsegs);
     }
-  
+
   if (!out->segnum)    /* first packet */
     out->hdr->split_flag=((out->numsegs-2)<<1)+1;
   else
     out->hdr->split_flag=out->segnum<<1;
-  
+
   out->seglen=maxsegsize;
   if (out->seglen>out->dataleft) out->seglen=out->dataleft;
-  
+
   BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
         out->segnum+1,out->seglen,out->numsegs,
         out->length,out->hdr->split_flag);
-  
+
   (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
                    sizeof(struct ClientData)-EXTRA_CLIENTDATA,
                    out->data,out->seglen,out->hdr->daddr,1,0);
-  
+
   out->dataleft-=out->seglen;
   out->data+=out->seglen;
   out->segnum++;
@@ -936,30 +921,29 @@ arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
 {
        struct device *dev = (struct device *)(irq2dev_map[irq]);
        struct arcnet_local *lp;
-       
+
        if (dev==NULL)
          {
            BUGLVL(D_DURING)
              printk(KERN_DEBUG "arcnet: irq %d for unknown device.\n", irq);
            return;
          }
-       
+
        BUGMSG(D_DURING,"in arcnet_interrupt\n");
-       
-       
+
        lp=(struct arcnet_local *)dev->priv;
-       
+
        /* RESET flag was enabled - if !dev->start, we must clear it right
         * away (but nothing else) since inthandler() is never called.
         */
-       
+
        if (!dev->start)
-         {         
+         {
            if (ARCSTATUS & RESETflag)
              ACOMMAND(CFLAGScmd|RESETclear);
            return;
          }
-       
+
 
        if (test_and_set_bit(0, (int *)&dev->interrupt))
          {
@@ -1000,7 +984,7 @@ void arcnet_tx_done(struct device *dev, struct arcnet_local *lp)
       if (!test_and_clear_bit(0, (int *)&dev->tbusy))
        BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
               " flag!\n");
-      
+
       mark_bh(NET_BH);
     }
 }
@@ -1012,7 +996,7 @@ void arcnet_tx_done(struct device *dev, struct arcnet_local *lp)
  *                                                                          *
  ****************************************************************************/
 
-/* 
+/*
  * This is a generic packet receiver that calls arcnet??_rx depending on the
  * protocol ID found.
  */
@@ -1020,10 +1004,10 @@ void arcnet_tx_done(struct device *dev, struct arcnet_local *lp)
 void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr)
 {
   struct device *dev=lp->adev;
-  
+
   BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
         saddr,daddr,length);
-  
+
   /* call the right receiver for the protocol */
   switch (arcsoft[0])
     {
@@ -1059,13 +1043,13 @@ void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr
       lp->stats.rx_crc_errors++;
       break;
     }
-  
+
   /* If any worth-while packets have been received, a mark_bh(NET_BH)
    * has been done by netif_rx and Linux will handle them after we
    * return.
    */
-  
-  
+
+
 }
 
 
@@ -1079,33 +1063,33 @@ arcnetA_rx(struct device *dev,u_char *buf,
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   struct sk_buff *skb;
   struct ClientData *arcsoft,*soft;
-  
+
   BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
         length);
-  
+
   /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
    * packet)
    */
   arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA);
   length+=EXTRA_CLIENTDATA;
-  
+
   if (arcsoft->split_flag==0xFF)  /* Exception Packet */
     {
       BUGMSG(D_DURING,"compensating for exception packet\n");
-      
+
       /* skip over 4-byte junkola */
       arcsoft=(struct ClientData *)
        ((u_char *)arcsoft + 4);
       length-=4;
     }
-  
+
   if (!arcsoft->split_flag)            /* not split */
     {
       struct Incoming *in=&lp->incoming[saddr];
-      
+
       BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
             arcsoft->split_flag);
-      
+
       if (in->skb)     /* already assembling one! */
        {
          BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
@@ -1117,9 +1101,9 @@ arcnetA_rx(struct device *dev,u_char *buf,
          lp->stats.rx_missed_errors++;
          in->skb=NULL;
        }
-      
+
       in->sequence=arcsoft->sequence;
-      
+
       skb = alloc_skb(length, GFP_ATOMIC);
       if (skb == NULL) {
        BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
@@ -1127,16 +1111,16 @@ arcnetA_rx(struct device *dev,u_char *buf,
        return;
       }
       soft=(struct ClientData *)skb->data;
-      
+
       skb_put(skb,length);
       skb->dev = dev;
-      
+
       memcpy((u_char *)soft+EXTRA_CLIENTDATA,
             (u_char *)arcsoft+EXTRA_CLIENTDATA,
             length-EXTRA_CLIENTDATA);
       soft->daddr=daddr;
       soft->saddr=saddr;
-      
+
       /* ARP packets have problems when sent from DOS.
        * source address is always 0 on some systems!  So we take
        * the hardware source addr (which is impossible to fumble)
@@ -1146,12 +1130,12 @@ arcnetA_rx(struct device *dev,u_char *buf,
        {
          struct arphdr *arp=(struct arphdr *)
            ((char *)soft+sizeof(struct ClientData));
-         
+
          /* make sure addresses are the right length */
          if (arp->ar_hln==1 && arp->ar_pln==4)
            {
              char *cptr=(char *)(arp)+sizeof(struct arphdr);
-             
+
              if (!*cptr)       /* is saddr = 00? */
                {
                  BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
@@ -1173,9 +1157,9 @@ arcnetA_rx(struct device *dev,u_char *buf,
              lp->stats.rx_crc_errors++;
            }
        }
-      
+
       BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-      
+
       lp->stats.rx_bytes += skb->len;
       skb->protocol=arcnetA_type_trans(skb,dev);
       netif_rx(skb);
@@ -1198,12 +1182,12 @@ arcnetA_rx(struct device *dev,u_char *buf,
        * ARCnet card possible on the network.  Seems rather like
        * a waste of memory.  Necessary?
        */
-      
+
       struct Incoming *in=&lp->incoming[saddr];
-      
+
       BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
             arcsoft->split_flag,in->sequence);
-      
+
       if (in->skb && in->sequence!=arcsoft->sequence)
        {
          BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
@@ -1215,7 +1199,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
          lp->stats.rx_missed_errors++;
          in->lastpacket=in->numpackets=0;
        }
-      
+
       if (arcsoft->split_flag & 1)     /* first packet in split */
        {
          BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
@@ -1229,11 +1213,11 @@ arcnetA_rx(struct device *dev,u_char *buf,
              lp->stats.rx_missed_errors++;
              kfree_skb(in->skb,FREE_WRITE);
            }
-         
+
          in->sequence=arcsoft->sequence;
          in->numpackets=((unsigned)arcsoft->split_flag>>1)+2;
          in->lastpacket=1;
-         
+
          if (in->numpackets>16)
            {
              BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
@@ -1242,7 +1226,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
              lp->stats.rx_length_errors++;
              return;
            }
-         
+
          in->skb=skb=alloc_skb(508*in->numpackets
                                + sizeof(struct ClientData),
                                GFP_ATOMIC);
@@ -1251,12 +1235,12 @@ arcnetA_rx(struct device *dev,u_char *buf,
            lp->stats.rx_dropped++;
            return;
          }
-         
+
          soft=(struct ClientData *)skb->data;
-         
+
          skb_put(skb,sizeof(struct ClientData));
          skb->dev=dev;
-         
+
          memcpy((u_char *)soft+EXTRA_CLIENTDATA,
                 (u_char *)arcsoft+EXTRA_CLIENTDATA,
                 sizeof(struct ClientData)-EXTRA_CLIENTDATA);
@@ -1265,7 +1249,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
       else                     /* not first packet */
        {
          int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
-         
+
          /* if we're not assembling, there's no point
           * trying to continue.
           */
@@ -1280,7 +1264,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                }
              return;
            }
-         
+
          in->lastpacket++;
          if (packetnum!=in->lastpacket) /* not the right flag! */
            {
@@ -1293,7 +1277,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
                  lp->stats.rx_frame_errors++;
                  return;
                }
-             
+
              /* "bad" duplicate, kill reassembly */
              BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
                     in->sequence,arcsoft->split_flag,
@@ -1306,20 +1290,20 @@ arcnetA_rx(struct device *dev,u_char *buf,
              in->lastpacket=in->numpackets=0;
              return;
            }
-         
+
          soft=(struct ClientData *)in->skb->data;
        }
-      
+
       skb=in->skb;
-      
+
       memcpy(skb->data+skb->len,
             (u_char *)arcsoft+sizeof(struct ClientData),
             length-sizeof(struct ClientData));
       skb_put(skb,length-sizeof(struct ClientData));
-      
+
       soft->daddr=daddr;
       soft->saddr=saddr;
-      
+
       /* are we done? */
       if (in->lastpacket == in->numpackets)
        {
@@ -1332,9 +1316,9 @@ arcnetA_rx(struct device *dev,u_char *buf,
            {
              in->skb=NULL;
              in->lastpacket=in->numpackets=0;
-             
+
              BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-             
+
              lp->stats.rx_bytes += skb->len;
              skb->protocol=arcnetA_type_trans(skb,dev);
              netif_rx(skb);
@@ -1344,15 +1328,12 @@ arcnetA_rx(struct device *dev,u_char *buf,
 }
 
 
-
-
 /****************************************************************************
  *                                                                          *
  * Miscellaneous routines                                                   *
  *                                                                          *
  ****************************************************************************/
 
-
 /* Get the current statistics. This may be called with the card open or
  * closed.
  */
@@ -1360,7 +1341,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
 static struct net_device_stats *arcnet_get_stats(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   return &lp->stats;
 }
 
@@ -1376,12 +1357,12 @@ static int arcnetA_header(struct sk_buff *skb,struct device *dev,
   struct ClientData *head = (struct ClientData *)
     skb_push(skb,dev->hard_header_len);
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-  
+
   BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n",
         saddr ? *(u_char*)saddr : -1,
         daddr ? *(u_char*)daddr : -1,
         type,type,len);
-  
+
   /* set the protocol ID according to RFC1201 */
   switch(type)
     {
@@ -1409,7 +1390,7 @@ static int arcnetA_header(struct sk_buff *skb,struct device *dev,
       lp->stats.tx_aborted_errors++;
       return 0;
     }
-  
+
   /*
    * Set the source hardware address.
    *
@@ -1422,10 +1403,10 @@ static int arcnetA_header(struct sk_buff *skb,struct device *dev,
     head->saddr=((u_char*)saddr)[0];
   else
     head->saddr=((u_char*)(dev->dev_addr))[0];
-  
+
   head->split_flag=0;  /* split packets are done elsewhere */
   head->sequence=0;    /* so are sequence numbers */
-  
+
   /* supposedly if daddr is NULL, we should ignore it... */
   if(daddr)
     {
@@ -1434,12 +1415,11 @@ static int arcnetA_header(struct sk_buff *skb,struct device *dev,
     }
   else
     head->daddr=0;     /* better fill one in anyway */
-  
+
   return -dev->hard_header_len;
 }
 
 
-
 /* Rebuild the ARCnet ClientData header. This is called after an ARP
  * (or in future other address resolution) has completed on this
  * sk_buff. We now let ARP fill in the other fields.
@@ -1450,13 +1430,13 @@ static int arcnetA_rebuild_header(struct sk_buff *skb)
   struct device *dev=skb->dev;
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
   int status;
-  
+
   /*
    * Only ARP and IP are currently supported
    *
    * FIXME: Anyone want to spec IPv6 over ARCnet ?
    */
-  
+
   if(head->protocol_id != ARC_P_IP)
     {
       BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
@@ -1467,7 +1447,7 @@ static int arcnetA_rebuild_header(struct sk_buff *skb)
       /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
       return 0;
     }
-  
+
   /*
    * Try to get ARP to resolve the header.
    */
@@ -1492,12 +1472,12 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
 {
   struct ClientData *head;
   struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-  
+
   /* Pull off the arcnet header. */
   skb->mac.raw=skb->data;
   skb_pull(skb,dev->hard_header_len);
   head=(struct ClientData *)skb->mac.raw;
-  
+
   if (head->daddr==0)
     skb->pkt_type=PACKET_BROADCAST;
   else if (dev->flags&IFF_PROMISC)
@@ -1506,14 +1486,14 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
       if (head->daddr != dev->dev_addr[0])
        skb->pkt_type=PACKET_OTHERHOST;
     }
-  
+
   /* now return the protocol number */
   switch (head->protocol_id)
     {
     case ARC_P_IP:             return htons(ETH_P_IP);
     case ARC_P_ARP:            return htons(ETH_P_ARP);
     case ARC_P_RARP:   return htons(ETH_P_RARP);
-      
+
     case ARC_P_IPX:
     case ARC_P_NOVELL_EC:
       return htons(ETH_P_802_3);
@@ -1522,7 +1502,7 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
       lp->stats.rx_crc_errors++;
       return 0;
     }
-  
+
   return htons(ETH_P_IP);
 }
 
@@ -1539,7 +1519,7 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
 static int arcnetE_init(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   ether_setup(dev); /* we're emulating ether here, not ARCnet */
   dev->dev_addr[0]=0;
   dev->dev_addr[5]=lp->stationid;
@@ -1547,7 +1527,7 @@ static int arcnetE_init(struct device *dev)
   dev->open=arcnetE_open_close;
   dev->stop=arcnetE_open_close;
   dev->hard_start_xmit=arcnetE_send_packet;
-  
+
   return 0;
 }
 
@@ -1571,13 +1551,13 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
   u_char daddr;
   short offset,length=skb->len+1;
   u_char proto=ARC_P_ETHER;
-  
+
   lp->intx++;
-  
+
   oldmask |= lp->intmask;
   lp->intmask=0;
   SETMASK;
-  
+
   bad=arcnet_send_packet_bad(skb,dev);
   if (bad)
     {
@@ -1586,31 +1566,31 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
       SETMASK;
       return bad;
     }
-  
+
   /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
 
   lp->intmask=oldmask;
   SETMASK;
-  
+
   if (length>XMTU)
     {
       BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
             length);
       BUGMSG(D_NORMAL,"transmit aborted.\n");
-      
+
       dev_kfree_skb(skb,FREE_WRITE);
       lp->intx--;
       return 0;
     }
-  
+
   BUGMSG(D_DURING,"starting tx sequence...\n");
-  
+
   /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
   if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
     daddr=0;
   else
     daddr=((struct ethhdr*)(skb->data))->h_dest[5];
-  
+
   /* load packet into shared memory */
   offset=512-length;
   if (length>MTU)              /* long/exception packet */
@@ -1621,17 +1601,13 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
     {
       offset-=256;
     }
-  
+
   BUGMSG(D_DURING," length=%Xh, offset=%Xh\n",
         length,offset);
-  
 
-
-  (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0, 
+  (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0,
                           offset);
-  
-  
-  
+
   dev_kfree_skb(skb,FREE_WRITE);
 
   if (arcnet_go_tx(dev,1))
@@ -1639,7 +1615,7 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
       /* inform upper layers */
       arcnet_tx_done(lp->adev, lp);
     }
-  
+
        dev->trans_start=jiffies;
        lp->intx--;
 
@@ -1697,9 +1673,9 @@ arcnetE_rx(struct device *dev,u_char *arcsoft,
 static int arcnetS_init(struct device *dev)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->dev_addr[0]=lp->stationid;
   dev->hard_header_len=sizeof(struct S_ClientData);
@@ -1710,7 +1686,7 @@ static int arcnetS_init(struct device *dev)
   dev->hard_start_xmit=arcnetS_send_packet;
   dev->hard_header=arcnetS_header;
   dev->rebuild_header=arcnetS_rebuild_header;
-  
+
   return 0;
 }
 
@@ -1732,9 +1708,9 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   int bad,length;
   struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
-  
+
   lp->intx++;
-  
+
   bad=arcnet_send_packet_bad(skb,dev);
   if (bad)
     {
@@ -1743,11 +1719,11 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
     }
 
   /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-  
+
   length = 1 < skb->len ? skb->len : 1;
-  
+
   BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-  
+
   /* fits in one packet? */
   if (length-S_EXTRA_CLIENTDATA<=XMTU)
     {
@@ -1757,10 +1733,10 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
                        skb->data+sizeof(struct S_ClientData),
                        length-sizeof(struct S_ClientData),
                        hdr->daddr,0,0);
-      
+
       /* done right away */
       dev_kfree_skb(skb,FREE_WRITE);
-      
+
       if (arcnet_go_tx(dev,1))
        {
          /* inform upper layers */
@@ -1775,14 +1751,14 @@ arcnetS_send_packet(struct sk_buff *skb, struct device *dev)
       lp->stats.tx_dropped++;
       arcnet_tx_done(lp->adev, lp);
     }
-  
+
   dev->trans_start=jiffies;
   lp->intx--;
-  
+
   /* make sure we didn't ignore a TX IRQ while we were in here */
   lp->intmask |= TXFREEflag;
   SETMASK;
-  
+
   return 0;
 }
 
@@ -1796,17 +1772,15 @@ arcnetS_rx(struct device *dev,u_char *buf,
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   struct sk_buff *skb;
   struct S_ClientData *arcsoft,*soft;
-  
+
   arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
   length+=S_EXTRA_CLIENTDATA;
-  
+
   BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
         length);
-  
-  
-  
+
   {    /* was "if not split" in A protocol, S is never split */
-    
+
     skb = alloc_skb(length, GFP_ATOMIC);
     if (skb == NULL) {
       BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
@@ -1823,9 +1797,9 @@ arcnetS_rx(struct device *dev,u_char *buf,
     soft->daddr=daddr;
     soft->saddr=saddr;
     skb->dev = dev;  /* is already lp->sdev */
-    
+
     BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-    
+
     lp->stats.rx_bytes += skb->len;
     skb->protocol=arcnetS_type_trans(skb,dev);
     netif_rx(skb);
@@ -1844,7 +1818,7 @@ static int arcnetS_header(struct sk_buff *skb,struct device *dev,
   struct S_ClientData *head = (struct S_ClientData *)
     skb_push(skb,dev->hard_header_len);
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-  
+
   /* set the protocol ID according to RFC1051 */
   switch(type)
     {
@@ -1863,7 +1837,7 @@ static int arcnetS_header(struct sk_buff *skb,struct device *dev,
       lp->stats.tx_aborted_errors++;
       return 0;
     }
-  
+
   /*
    * Set the source hardware address.
    *
@@ -1876,7 +1850,7 @@ static int arcnetS_header(struct sk_buff *skb,struct device *dev,
     head->saddr=((u_char*)saddr)[0];
   else
     head->saddr=((u_char*)(dev->dev_addr))[0];
-  
+
   /* supposedly if daddr is NULL, we should ignore it... */
   if(daddr)
     {
@@ -1885,7 +1859,7 @@ static int arcnetS_header(struct sk_buff *skb,struct device *dev,
     }
   else
     head->daddr=0;     /* better fill one in anyway */
-  
+
   return -dev->hard_header_len;
 }
 
@@ -1899,11 +1873,11 @@ static int arcnetS_rebuild_header(struct sk_buff *skb)
   struct device *dev=skb->dev;
   struct S_ClientData *head = (struct S_ClientData *)skb->data;
   struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-  
+
   /*
    * Only ARP and IP are currently supported
    */
-  
+
   if(head->protocol_id != ARC_P_IP_RFC1051)
     {
       BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
@@ -1914,7 +1888,7 @@ static int arcnetS_rebuild_header(struct sk_buff *skb)
       /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
       return 0;
     }
-  
+
   /*
    * Try to get ARP to resolve the header.
    */
@@ -1934,12 +1908,12 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
 {
   struct S_ClientData *head;
   struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-  
+
   /* Pull off the arcnet header. */
   skb->mac.raw=skb->data;
   skb_pull(skb,dev->hard_header_len);
   head=(struct S_ClientData *)skb->mac.raw;
-  
+
   if (head->daddr==0)
     skb->pkt_type=PACKET_BROADCAST;
   else if (dev->flags&IFF_PROMISC)
@@ -1948,7 +1922,7 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
       if (head->daddr != dev->dev_addr[0])
        skb->pkt_type=PACKET_OTHERHOST;
     }
-  
+
   /* now return the protocol number */
   switch (head->protocol_id)
     {
@@ -1960,20 +1934,19 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
       lp->stats.rx_crc_errors++;
       return 0;
     }
-  
+
   return htons(ETH_P_IP);
 }
 
 #endif /* CONFIG_ARCNET_1051 */
 
+
 /****************************************************************************
  *                                                                          *
  * Kernel Loadable Module Support                                           *
  *                                                                          *
  ****************************************************************************/
 
-
-
 #ifdef MODULE
 
 void cleanup_module(void)
@@ -1982,7 +1955,7 @@ void cleanup_module(void)
 }
 
 void arcnet_use_count(int open)
-{ 
+{
   if (open)
     MOD_INC_USE_COUNT;
   else
@@ -1999,14 +1972,14 @@ struct device arcnet_devs[MAX_ARCNET_DEVS];
 int arcnet_num_devs=0;
 char arcnet_dev_names[MAX_ARCNET_DEVS][10];
 
-void arcnet_init(void)
+__initfunc(void arcnet_init(void))
 {
   int c;
-  
-  (void) init_module();
+
+  init_module();
 
   /* Don't register_netdev here. The chain hasn't been initialised. */
-  
+
 #ifdef CONFIG_ARCNET_COM90xx
   if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS)
     {
@@ -2020,7 +1993,7 @@ void arcnet_init(void)
   if (!arcnet_num_devs)
     {
       printk("Don't forget to load the chipset driver.\n");
-      return;  
+      return;
     }
 
   /* Link into the device chain */
@@ -2033,20 +2006,24 @@ void arcnet_init(void)
 
   arcnet_devs[c].next=dev_base;
   dev_base=&arcnet_devs[0];
-  
+
   /* Give names to those without them */
-  
+
   for (c=0; c< arcnet_num_devs; c++)
     if (!arcnet_dev_names[c][0])
       arcnet_makename((char *)&arcnet_dev_names[c]);
-
 }
-static
+
 #endif /* MODULE */
-int init_module()
+
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(static int init_module(void))
+#endif
 {
-#if 1
+#ifdef ALPHA_WARNING
   BUGLVL(D_EXTRA)
     {
       printk("arcnet: ***\n");
@@ -2058,8 +2035,7 @@ int init_module()
     }
 #endif
 
-  printk("%sGeneric arcnet support for Linux kernel.\n"
-        "Available protocols: ARCnet RFC1201"
+  printk("%sAvailable protocols: ARCnet RFC1201"
 #ifdef CONFIG_ARCNET_ETH
         ", Ethernet-Encap"
 #endif
@@ -2074,50 +2050,20 @@ int init_module()
 }
 
 
-
-
-
 void arcnet_makename(char *device)
 {
-  __u32 arcmask=0;
   struct device *dev;
-  char *c;
   int arcnum;
 
-  for (dev = dev_base; dev; dev=dev->next)
-    {
-      arcnum=0;
-
-      if (!strncmp(dev->name, "arc", 3))
-       {
-         c = &dev->name[3];
-         while ((*c)>='0' && (*c)<='9')
-           {
-             arcnum *= 10;
-             arcnum += (*(c++)-'0');
-           }
-         
-         if (arcnum<32)              
-           arcmask |= ((__u32)1 << arcnum);
-       }
-      
-      
-    }
-  
-  /* arcmask now holds a mask of the first 32 arcnet names available */
-  
-  if ((__u32)~arcmask)
-    {
-      for (arcnum=0; arcmask&1; arcnum++, arcmask >>=1)
-       ;
-      
-      sprintf (device, "arc%d",arcnum);
-    } 
-  else
+  arcnum = 0;
+  for (;;)
     {
-      printk (KERN_INFO "arcnet: Can't find name for device\n");
-      sprintf (device, "arc???");
+      sprintf(device, "arc%d", arcnum);
+      for (dev = dev_base; dev; dev=dev->next)
+       if (dev->name != device && !strcmp(dev->name, device))
+         break;
+      if (!dev)
+       return;
+      arcnum++;
     }
 }
-
-
index e1306a60ea38290d876741341584d4d0647bb3d0..1fb3a08364652442f645f7e543892500556cfb41 100644 (file)
@@ -1,4 +1,5 @@
-/* com20020.c:
+/*     $Id: com20020.c,v 1.2 1997/09/05 08:57:50 mj Exp $
+
         Written 1997 by David Woodhouse <dwmw2@cam.ac.uk>
 
        Derived from the original arcnet.c,
 #include <net/arp.h>
 
 
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-                           char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-                              char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
 /* Internal function declarations */
 
 static int arc20020_probe(struct device *dev);
@@ -136,7 +107,6 @@ extern int arcnet_num_devs;
 #endif
 
 
-
 /* Handy defines for ARCnet specific stuff */
 
 static char *clockrates[]={"2.5 Mb/s","1.25Mb/s","625 Kb/s","312.5 Kb/s",
@@ -144,7 +114,7 @@ static char *clockrates[]={"2.5 Mb/s","1.25Mb/s","625 Kb/s","312.5 Kb/s",
                    "Reserved"};
 
 
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE 9
 
 #define _INTMASK (ioaddr+0)    /* writable */
@@ -156,7 +126,6 @@ static char *clockrates[]={"2.5 Mb/s","1.25Mb/s","625 Kb/s","312.5 Kb/s",
 #define _ADDR_HI  (ioaddr+2)     /* Control registers for said */
 #define _ADDR_LO  (ioaddr+3)
 
-
 #define RDDATAflag      0x80     /* Next access is a read/~write */
 #define NEWNXTIDflag    0x02     /* ID to which token is passed has changed */
 
@@ -178,7 +147,6 @@ static char *clockrates[]={"2.5 Mb/s","1.25Mb/s","625 Kb/s","312.5 Kb/s",
                    outb(0x18 , _CONFIG);            \
                   }
 
-
 #define ARCSTATUS      inb(_STATUS)
 #define ACOMMAND(cmd) outb((cmd),_COMMAND)
 #define AINTMASK(msk)  outb((msk),_INTMASK)
@@ -247,7 +215,7 @@ void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, cha
 
 
 static const char *version =
- "com20020.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
+ "com20020.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 /****************************************************************************
  *                                                                          *
@@ -256,7 +224,6 @@ static const char *version =
  ****************************************************************************/
 
 
-
 /* We cannot probe for an IO mapped card either, although we can check that
  * it's where we were told it was, and even autoirq
  */
@@ -300,15 +267,12 @@ __initfunc(int arc20020_probe(struct device *dev))
       return -ENODEV;
     }
   
-  
   BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status);
   
-  
   /* Enable TX */
   outb(0x39,_CONFIG);
   outb(inb(ioaddr+8),ioaddr+7);
   
-  
   ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
   
   BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status);
@@ -364,7 +328,6 @@ __initfunc(int arc20020_probe(struct device *dev))
 }
 
 
-
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
@@ -385,12 +348,10 @@ __initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
   request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM20020)");
   dev->base_addr=ioaddr;
   
-  
   dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL;
-  
-  
+
   /* Initialize the rest of the device structure. */
-  
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -404,7 +365,7 @@ __initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
   lp=(struct arcnet_local *)(dev->priv);
   lp->card_type = ARC_20020;
   lp->card_type_str = "COM 20020";
-  
+
   lp->arcnet_reset=arc20020_reset;
   lp->asetmask=arc20020_setmask;
   lp->astatus=arc20020_status;
@@ -413,31 +374,30 @@ __initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
   lp->openclose_device=arc20020_openclose;
   lp->prepare_tx=arc20020_prepare_tx;
   lp->inthandler=arc20020_inthandler;
-  
-  
+
   dev->set_multicast_list = arc20020_set_mc_list;
-  
+
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
         sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
         sizeof(struct archdr));
-  
+
   /* get and check the station ID from offset 1 in shmem */
   lp->timeout = dev->dev_addr[3] & 3; dev->dev_addr[3]=0;
   lp->backplane =dev->dev_addr[1] & 1; dev->dev_addr[1]=0;
   lp->setup = (dev->dev_addr[2] & 7) << 1; dev->dev_addr[2]=0;
-  
+
   if (dev->dev_addr[0])
     lp->stationid=dev->dev_addr[0];
   else
@@ -447,11 +407,11 @@ __initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
   /* Default 0x38 + register: Node ID */
   SETCONF;
   outb(lp->stationid, ioaddr+7);
-  
+
   REGSETUP;
   SETCONF;
   outb(lp->setup, ioaddr+7);
-  
+
   if (!lp->stationid)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
           "for broadcasts!\n");
@@ -459,19 +419,19 @@ __initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
           "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet COM20020: station %02Xh found at %03lXh, IRQ %d.\n",
         lp->stationid, dev->base_addr,dev->irq);
-  
+
   if (lp->backplane)
     BUGMSG (D_NORMAL, "Using backplane mode.\n");
-  
+
   if (lp->timeout != 3)
     BUGMSG (D_NORMAL, "Using Extended Timeout value of %d.\n",lp->timeout);
   if (lp->setup)
     {
       BUGMSG (D_NORMAL, "Using CKP %d - Data rate %s.\n",
-             lp->setup >>1,clockrates[lp->setup >> 1] );       
+             lp->setup >>1,clockrates[lp->setup >> 1] );
     }
   return 0;
 }
@@ -479,7 +439,7 @@ __initfunc(int arc20020_found(struct device *dev,int ioaddr,int airq))
 
 /****************************************************************************
  *                                                                          *
- * Utility routines for arcnet.c                                            *
+ * Utility routines                                                         *
  *                                                                          *
  ****************************************************************************/
 
@@ -495,59 +455,59 @@ int arc20020_reset(struct device *dev,int reset_delay)
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->base_addr;
   int delayval,recbuf=lp->recbuf;
-  
+
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
+
   /* no IRQ's, please! */
   lp->intmask=0;
   SETMASK;
-  
+
   BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
         dev->name,ARCSTATUS);
-  
-  lp->config = 0x20 | (lp->timeout<<3) | (lp->backplane<<2); 
+
+  lp->config = 0x20 | (lp->timeout<<3) | (lp->backplane<<2);
   /* power-up defaults */
   SETCONF;
-  
+
   if (reset_delay)
     {
       /* reset the card */
       ARCRESET;
       JIFFER(RESETtime);
     }
-  
+
   ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
   ACOMMAND(CFLAGScmd|CONFIGclear);
-  
+
   /* verify that the ARCnet signature byte is present */
-  
+
   if (get_buffer_byte(dev,0) != TESTvalue)
     {
       BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
       return 1;
     }
-  
+
   /* clear out status variables */
   recbuf=lp->recbuf=0;
   lp->txbuf=2;
-  
+
   /* enable extended (512-byte) packets */
   ACOMMAND(CONFIGcmd|EXTconf);
-  
+
   /* and enable receive of our first packet to the first buffer */
   EnableReceiver();
-  
+
   /* re-enable interrupts */
   lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
   lp->intmask|=RECONflag;
 #endif
   SETMASK;
-  
+
   /* done!  return success. */
   return 0;
 }
@@ -565,7 +525,7 @@ arc20020_set_mc_list(struct device *dev)
 {
   struct arcnet_local *lp=dev->priv;
   int ioaddr=dev->base_addr;
-  
+
   if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP))
     {  /* Enable promiscuous mode */
       if (!(lp->setup & PROMISCflag))
@@ -583,7 +543,7 @@ arc20020_set_mc_list(struct device *dev)
        SETCONF;
        lp->setup &= ~PROMISCflag;
        outb(lp->setup,ioaddr+7);
-      } 
+      }
 }
 
 
@@ -595,11 +555,12 @@ static void arc20020_openclose(int open)
     MOD_DEC_USE_COUNT;
 }
 
+
 static void arc20020_en_dis_able_TX(struct device *dev, int enable)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr;
-  
+
   lp->config=enable?(lp->config | TXENflag):(lp->config & ~TXENflag);
   SETCONF;
 }
@@ -608,10 +569,11 @@ static void arc20020_en_dis_able_TX(struct device *dev, int enable)
 static void arc20020_setmask(struct device *dev, u_char mask)
 {
   short ioaddr=dev->base_addr;
-  
+
   AINTMASK(mask);
 }
 
+
 static u_char arc20020_status(struct device *dev)
 {
   short ioaddr=dev->base_addr;
@@ -619,6 +581,7 @@ static u_char arc20020_status(struct device *dev)
   return ARCSTATUS;
 }
 
+
 static void arc20020_command(struct device *dev, u_char cmd)
 {
   short ioaddr=dev->base_addr;
@@ -634,22 +597,20 @@ static void
 arc20020_inthandler(struct device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething, 
+  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething,
     dstatus;
-  
-       
-    
+
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arc20020_inthandler (status=%Xh, intmask=%Xh)\n",
         ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
       didsomething=0;
-      
-      
+
+
       /* RESET flag was enabled - card is resetting and if RX
        * is disabled, it's NOT because we just got a packet.
        */
@@ -658,56 +619,53 @@ arc20020_inthandler(struct device *dev)
          BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
                 status);
          arc20020_reset(dev,0);
-         
+
          /* all other flag values are just garbage */
          break;
        }
-      
-      
+
       /* RX is inhibited - we must have received something. */
       if (status & lp->intmask & NORXflag)
        {
          int recbuf=lp->recbuf=!lp->recbuf;
          int oldaddr=0;
-         
+
          BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
                 status);
-         
+
          /* enable receive of our next packet */
          EnableReceiver();
-         
+
          if (lp->intx)
            oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO);
-         
-         
+
          /* Got a packet. */
          arc20020_rx(dev,!recbuf);
-         
-         
+
          if (lp->intx)
            {
              outb( (oldaddr >> 8),  _ADDR_HI);
              outb( oldaddr & 0xff, _ADDR_LO);
            }
-         
+
          didsomething++;
        }
-      
+
       /* it can only be an xmit-done irq if we're xmitting :) */
       /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
       if (status & lp->intmask & TXFREEflag)
        {
          struct Outgoing *out=&(lp->outgoing);
          int was_sending=lp->sending;
-         
+
          lp->intmask &= ~TXFREEflag;
-         
+
          lp->in_txhandler++;
          if (was_sending) lp->sending--;
-         
+
          BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
                 status,out->numsegs,out->segnum,out->skb);
-         
+
          if (was_sending && !(status&TXACKflag))
            {
              if (lp->lasttrans_dest != 0)
@@ -724,11 +682,11 @@ arc20020_inthandler(struct device *dev)
                         lp->lasttrans_dest);
                }
            }
-         
+
          /* send packet if there is one */
          arcnet_go_tx(dev,0);
          didsomething++;
-         
+
          if (lp->intx)
            {
              BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
@@ -736,24 +694,24 @@ arc20020_inthandler(struct device *dev)
              lp->in_txhandler--;
              continue;
            }
-         
+
          if (!lp->outgoing.skb)
            {
              BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-             
+
              /* inform upper layers */
              if (!lp->txready) arcnet_tx_done(dev, lp);
              lp->in_txhandler--;
              continue;
            }
-         
+
          /* if more than one segment, and not all segments
           * are done, then continue xmit.
           */
          if (out->segnum<out->numsegs)
            arcnetA_continue_tx(dev);
          arcnet_go_tx(dev,0);
-         
+
          /* if segnum==numsegs, the transmission is finished;
           * free the skb.
           */
@@ -767,12 +725,12 @@ arc20020_inthandler(struct device *dev)
                  dev_kfree_skb(out->skb,FREE_WRITE);
                }
              out->skb=NULL;
-             
+
              /* inform upper layers */
              if (!lp->txready) arcnet_tx_done(dev, lp);
            }
          didsomething++;
-         
+
          lp->in_txhandler--;
        }
       else if (lp->txready && !lp->sending && !lp->intx)
@@ -782,27 +740,26 @@ arc20020_inthandler(struct device *dev)
          arcnet_go_tx(dev,0);
          didsomething++;
        }
-      
+
       if ((dstatus=inb(_DIAGSTAT)) & NEWNXTIDflag)
        {
          REGNXTID;
          SETCONF;
          BUGMSG(D_EXTRA,"New NextID detected: %X\n",inb(ioaddr+7));
        }
-      
-      
+
+
 #ifdef DETECT_RECONFIGS
       if (status & (lp->intmask) & RECONflag)
        {
          ACOMMAND(CFLAGScmd|CONFIGclear);
          lp->stats.tx_carrier_errors++;
-         
+
 #ifdef SHOW_RECONFIGS
-         
          BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh, diag status=%Xh, config=%X)\n",
                 status,dstatus,lp->config);
 #endif /* SHOW_RECONFIGS */
-         
+
 #ifdef RECON_THRESHOLD
          /* is the RECON info empty or old? */
          if (!lp->first_recon || !lp->last_recon ||
@@ -812,19 +769,19 @@ arc20020_inthandler(struct device *dev)
                BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
              lp->first_recon=lp->last_recon=jiffies;
              lp->num_recons=lp->network_down=0;
-             
+
              BUGMSG(D_DURING,"recon: clearing counters.\n");
            }
          else /* add to current RECON counter */
            {
              lp->last_recon=jiffies;
              lp->num_recons++;
-             
+
              BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
                     lp->num_recons,
                     (lp->last_recon-lp->first_recon)/HZ,
                     lp->network_down);
-             
+
              /* if network is marked up;
               * and first_recon and last_recon are 60+ sec
               *   apart;
@@ -856,26 +813,25 @@ arc20020_inthandler(struct device *dev)
            BUGMSG(D_NORMAL,"cabling restored?\n");
          lp->first_recon=lp->last_recon=0;
          lp->num_recons=lp->network_down=0;
-         
+
          BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
        }
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
         ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;     /* put back interrupt mask */
-  
-}
 
+}
 
 
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arc20020_rx(struct device *dev,int recbuf)
@@ -887,13 +843,13 @@ arc20020_rx(struct device *dev,int recbuf)
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket);
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -903,13 +859,13 @@ arc20020_rx(struct device *dev,int recbuf)
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   put_buffer_byte(dev,recbuf*512,0);
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -922,16 +878,15 @@ arc20020_rx(struct device *dev,int recbuf)
       arcsoft=&arcpacket->raw[offset];
       length=512-offset;
     }
-  
+
   get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset);
-  
+
   arcnet_rx(lp, arcsoft, length, saddr, daddr);
-  
+
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
 }
 
 
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -940,20 +895,20 @@ arc20020_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
                    char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   lp->txbuf=lp->txbuf^1;       /* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
         hdr,length,data);
-  
+
   put_buffer_byte(dev, lp->txbuf*512+1, daddr);
 
   /* load packet into shared memory */
   if (length<=MTU)     /* Normal (256-byte) Packet */
     put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length);
-  
+
   else if (length>=MinTU || offset)    /* Extended (512-byte) Packet */
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
@@ -963,36 +918,36 @@ arc20020_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4);
-      
+
       /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-      
+
       put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff");
       offset+=4;
     }
   else                         /* "other" Exception packet */
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
-      
+
       put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0");
-      
+
       /* now round up to MinTU */
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU);
     }
-  
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
-  
+
   put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr);
   put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data);
-  
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
         daddr,length);
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;       /* packet is ready for sending */
 }
@@ -1014,13 +969,13 @@ static struct device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
 int init_module(void)
 {
   struct device *dev;
-  
+
   cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
   if (!dev)
     return -ENOMEM;
-  
+
   memset(dev, 0, sizeof(struct device));
-  
+
   dev->name=(char *)kmalloc(9, GFP_KERNEL);
   if (!dev->name)
     {
@@ -1035,19 +990,19 @@ int init_module(void)
 
   if (node && node != 0xff)
     dev->dev_addr[0]=node;
-  
+
   if (backplane) dev->dev_addr[1]=backplane?1:0;
   if (clock) dev->dev_addr[2]=clock&7;
   dev->dev_addr[3]=timeout&3;
 
   dev->base_addr=io;
   dev->irq=irq;
-  
+
   if (dev->irq==2) dev->irq=9;
 
   if (register_netdev(dev) != 0)
     return -EIO;
-  
+
   /* Increase use count of arcnet.o */
   arcnet_use_count(1);
 
@@ -1058,9 +1013,9 @@ void cleanup_module(void)
 {
   struct device *dev=cards[0];
   int ioaddr=dev->base_addr;
-  
+
   if (dev->start) (*dev->stop)(dev);
-  
+
   /* Flush TX and disable RX */
   if (ioaddr)
     {
@@ -1068,21 +1023,22 @@ void cleanup_module(void)
       ACOMMAND(NOTXcmd);       /* stop transmit */
       ACOMMAND(NORXcmd);       /* disable receive */
     }
-  
+
   if (dev->irq)
     {
       irq2dev_map[dev->irq] = NULL;
       free_irq(dev->irq,NULL);
     }
-  
+
   if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
   unregister_netdev(dev);
   kfree(dev->priv);
   dev->priv = NULL;
-  
+
   /* Decrease use count of arcnet.o */
   arcnet_use_count(0);
 }
+
 #else
 
 __initfunc(void com20020_setup (char *str, int *ints))
@@ -1095,9 +1051,9 @@ __initfunc(void com20020_setup (char *str, int *ints))
             MAX_ARCNET_DEVS);
       return;
     }
-  
+
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   if (ints[0] < 1)
     {
       printk("com20020: You must give an IO address.\n");
@@ -1126,19 +1082,16 @@ __initfunc(void com20020_setup (char *str, int *ints))
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* IO address */
       dev->base_addr=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
-  
+
   arcnet_num_devs++;
 }
 #endif /* MODULE */
-
-
-
index 19252ba0a088c5d15ecd0b817eaf00fab0bd2345..9bd9021517efe0e354103e081d45f589eb086ab8 100644 (file)
@@ -1,11 +1,12 @@
-/* com90io.c:
+/*     $Id: com90io.c,v 1.2 1997/09/05 08:57:52 mj Exp $
+
         Written 1997 by David Woodhouse <dwmw2@cam.ac.uk>
 
        Derived from the original arcnet.c,
        Written 1994-1996 by Avery Pennarun,
        which was in turn derived from skeleton.c by Donald Becker.
 
-       Contact Avery at: apenwarr@foxnet.net or
+       Contact Avery at: apenwarr@bond.net or
        RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
        **********************
 #include <net/arp.h>
 
 
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-                           char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-                              char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
 /* Internal function declarations */
 
 static int arc90io_probe(struct device *dev);
@@ -127,13 +98,12 @@ extern int arcnet_num_devs;
 #endif
 
 
-
 /* Handy defines for ARCnet specific stuff */
 
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE 16
 
-       /* COM 9026 controller chip --> ARCnet register addresses */
+/* COM 9026 controller chip --> ARCnet register addresses */
 #define _INTMASK (ioaddr+0)    /* writable */
 #define _STATUS  (ioaddr+0)    /* readable */
 #define _COMMAND (ioaddr+1)    /* writable, returns random vals on read (?) */
@@ -149,7 +119,6 @@ extern int arcnet_num_devs;
 
 #define ARCRESET       inb(_RESET)
 
-
 #define SETCONF        outb((lp->config),_CONFIG)
 
 
@@ -163,7 +132,7 @@ u_char get_buffer_byte (struct device *dev, unsigned offset)
 {
   int ioaddr=dev->base_addr;
 
-  outb(offset >> 8,  _ADDR_HI); 
+  outb(offset >> 8,  _ADDR_HI);
   outb(offset & 0xff, _ADDR_LO);
 
   return inb(_MEMDATA);
@@ -173,7 +142,7 @@ void put_buffer_byte (struct device *dev, unsigned offset, u_char datum)
 {
   int ioaddr=dev->base_addr;
 
-  outb(offset >> 8,   _ADDR_HI); 
+  outb(offset >> 8,   _ADDR_HI);
   outb(offset & 0xff, _ADDR_LO);
 
   outb(datum, _MEMDATA);
@@ -204,7 +173,7 @@ void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, cha
 
   outb( (offset >> 8) | AUTOINCflag,   _ADDR_HI);
   outb( offset & 0xff,                 _ADDR_LO);
+
   while (length--)
 #ifdef ONE_AT_A_TIME_TX
     put_buffer_byte(dev,offset++,*(dest++));
@@ -217,14 +186,13 @@ void put_whole_buffer (struct device *dev, unsigned offset, unsigned length, cha
 static const char *version =
  "com90io.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
+
 /****************************************************************************
  *                                                                          *
  * Probe and initialization                                                 *
  *                                                                          *
  ****************************************************************************/
 
-
-
 /* We cannot probe for an IO mapped card either, although we can check that
  * it's where we were told it was, and even autoirq
  */
@@ -233,104 +201,100 @@ __initfunc(int arc90io_probe(struct device *dev))
 {
   int ioaddr=dev->base_addr,status,delayval;
   unsigned long airqmask;
-  
+
   BUGLVL(D_NORMAL) printk(version);
-  
+
   if (ioaddr<0x200)
     {
       BUGMSG(D_NORMAL,"No autoprobe for IO mapped cards; you "
             "must specify the base address!\n");
       return -ENODEV;
     }
-  
+
   if (check_region(ioaddr, ARCNET_TOTAL_SIZE))
     {
       BUGMSG(D_INIT_REASONS,"IO check_region %x-%x failed.\n",
             ioaddr,ioaddr+ARCNET_TOTAL_SIZE-1);
       return -ENXIO;
     }
-  
+
   if (ARCSTATUS == 0xFF)
     {
       BUGMSG(D_INIT_REASONS,"IO address %x empty\n",ioaddr);
       return -ENODEV;
     }
-  
+
   ARCRESET;
   JIFFER(RESETtime);
-  
+
   status=ARCSTATUS;
-  
+
   if ((status & 0x9D)
       !=  (NORXflag|RECONflag|TXFREEflag|RESETflag))
     {
       BUGMSG(D_INIT_REASONS,"Status invalid (%Xh).\n",status);
       return -ENODEV;
     }
-  
-  
+
   BUGMSG(D_INIT_REASONS,"Status after reset: %X\n",status);
-  
-  
+
   ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
-  
+
   BUGMSG(D_INIT_REASONS,"Status after reset acknowledged: %X\n",status);
-  
+
   status=ARCSTATUS;
-  
+
   if (status & RESETflag)
     {
       BUGMSG(D_INIT_REASONS,"Eternal reset (status=%Xh)\n",status);
       return -ENODEV;
     }
-  
+
   outb((0x16 | IOMAPflag) &~ENABLE16flag, _CONFIG);
-  
-  
+
   /* Read first loc'n of memory */
-  
+
   outb(AUTOINCflag ,_ADDR_HI);
   outb(0,_ADDR_LO);
-  
+
   if ((status=inb(_MEMDATA)) != 0xd1)
     {
       BUGMSG(D_INIT_REASONS,"Signature byte not found"
             " (%Xh instead).\n", status);
       return -ENODEV;
     }
-  
+
   if (!dev->irq)
     {
       /* if we do this, we're sure to get an IRQ since the
        * card has just reset and the NORXflag is on until
        * we tell it to start receiving.
        */
-      
+
       airqmask = probe_irq_on();
       outb(NORXflag,_INTMASK);
       udelay(1);
       outb(0,_INTMASK);
       dev->irq = probe_irq_off(airqmask);
-      
+
       if (dev->irq<=0)
        {
          BUGMSG(D_INIT_REASONS,"Autoprobe IRQ failed\n");
          return -ENODEV;
        }
     }
-  
+
   return arc90io_found(dev,dev->base_addr,dev->irq);
 }
 
 
-
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
 __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
 {
   struct arcnet_local *lp;
-  
+
   /* reserve the irq */
   if (request_irq(airq,&arcnet_interrupt,0,"arcnet (COM90xx-IO)",NULL))
     {
@@ -339,17 +303,15 @@ __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
     }
   irq2dev_map[airq]=dev;
   dev->irq=airq;
-  
+
   /* reserve the I/O region - guaranteed to work by check_region */
   request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (COM90xx-IO)");
   dev->base_addr=ioaddr;
-  
-  
+
   dev->mem_start=dev->mem_end=dev->rmem_start=dev->rmem_end=(long)NULL;
-  
-  
+
   /* Initialize the rest of the device structure. */
-  
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -363,7 +325,7 @@ __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
   lp=(struct arcnet_local *)(dev->priv);
   lp->card_type = ARC_90xx_IO;
   lp->card_type_str = "COM 90xx (IO)";
-  
+
   lp->arcnet_reset=arc90io_reset;
   lp->asetmask=arc90io_setmask;
   lp->astatus=arc90io_status;
@@ -371,33 +333,30 @@ __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
   lp->openclose_device=arc90io_openclose;
   lp->prepare_tx=arc90io_prepare_tx;
   lp->inthandler=arc90io_inthandler;
-  
-  
 
-  
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
         sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
         sizeof(struct archdr));
-  
+
   lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag;
   SETCONF;
-  
+
   /* get and check the station ID from offset 1 in shmem */
 
   lp->stationid = get_buffer_byte(dev,1);
-  
+
   if (!lp->stationid)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
           "for broadcasts!\n");
@@ -405,19 +364,19 @@ __initfunc(int arc90io_found(struct device *dev,int ioaddr,int airq))
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
           "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet COM90xx in IO-mapped mode:  "
         "station %02Xh found at %03lXh, IRQ %d.\n",
         lp->stationid,
         dev->base_addr,dev->irq);
-  
+
   return 0;
 }
 
 
 /****************************************************************************
  *                                                                          *
- * Utility routines for arcnet.c                                            *
+ * Utility routines                                                         *
  *                                                                          *
  ****************************************************************************/
 
@@ -433,59 +392,59 @@ int arc90io_reset(struct device *dev,int reset_delay)
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   short ioaddr=dev->base_addr;
   int delayval,recbuf=lp->recbuf;
-  
+
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
+
   /* no IRQ's, please! */
   lp->intmask=0;
   SETMASK;
-  
+
   BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
         dev->name,ARCSTATUS);
-  
+
   /* Set the thing to IO-mapped, 8-bit  mode */
   lp->config = (0x1C|IOMAPflag) & ~ENABLE16flag;
   SETCONF;
-  
+
   if (reset_delay)
     {
       /* reset the card */
       ARCRESET;
       JIFFER(RESETtime);
     }
-  
+
   ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
   ACOMMAND(CFLAGScmd|CONFIGclear);
-  
+
   /* verify that the ARCnet signature byte is present */
-  
+
   if (get_buffer_byte(dev,0) != TESTvalue)
     {
       BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
       return 1;
     }
-  
+
   /* clear out status variables */
   recbuf=lp->recbuf=0;
   lp->txbuf=2;
-  
+
   /* enable extended (512-byte) packets */
   ACOMMAND(CONFIGcmd|EXTconf);
-  
+
   /* and enable receive of our first packet to the first buffer */
   EnableReceiver();
-  
+
   /* re-enable interrupts */
   lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
   lp->intmask|=RECONflag;
 #endif
   SETMASK;
-  
+
   /* done!  return success. */
   return 0;
 }
@@ -500,11 +459,10 @@ static void arc90io_openclose(int open)
 }
 
 
-
 static void arc90io_setmask(struct device *dev, u_char mask)
 {
   short ioaddr=dev->base_addr;
-  
+
   AINTMASK(mask);
 }
 
@@ -530,22 +488,18 @@ static void
 arc90io_inthandler(struct device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething; 
+  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
 
-  
-       
-    
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arc90io_inthandler (status=%Xh, intmask=%Xh)\n",
         ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
       didsomething=0;
-      
-      
+
       /* RESET flag was enabled - card is resetting and if RX
        * is disabled, it's NOT because we just got a packet.
        */
@@ -554,56 +508,55 @@ arc90io_inthandler(struct device *dev)
          BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
                 status);
          arc90io_reset(dev,0);
-         
+
          /* all other flag values are just garbage */
          break;
        }
-      
-      
+
       /* RX is inhibited - we must have received something. */
       if (status & lp->intmask & NORXflag)
        {
          int recbuf=lp->recbuf=!lp->recbuf;
          int oldaddr=0;
-         
+
          BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
                 status);
-         
+
          /* enable receive of our next packet */
          EnableReceiver();
-         
+
          if (lp->intx)
            oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO);
-         
-         
+
+
          /* Got a packet. */
          arc90io_rx(dev,!recbuf);
-         
-         
+
+
          if (lp->intx)
            {
              outb( (oldaddr >> 8),  _ADDR_HI);
              outb( oldaddr & 0xff, _ADDR_LO);
            }
-         
+
          didsomething++;
        }
-      
+
       /* it can only be an xmit-done irq if we're xmitting :) */
       /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
       if (status & lp->intmask & TXFREEflag)
        {
          struct Outgoing *out=&(lp->outgoing);
          int was_sending=lp->sending;
-         
+
          lp->intmask &= ~TXFREEflag;
-         
+
          lp->in_txhandler++;
          if (was_sending) lp->sending--;
-         
+
          BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
                 status,out->numsegs,out->segnum,out->skb);
-         
+
          if (was_sending && !(status&TXACKflag))
            {
              if (lp->lasttrans_dest != 0)
@@ -620,11 +573,11 @@ arc90io_inthandler(struct device *dev)
                         lp->lasttrans_dest);
                }
            }
-         
+
          /* send packet if there is one */
          arcnet_go_tx(dev,0);
          didsomething++;
-         
+
          if (lp->intx)
            {
              BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
@@ -632,24 +585,24 @@ arc90io_inthandler(struct device *dev)
              lp->in_txhandler--;
              continue;
            }
-         
+
          if (!lp->outgoing.skb)
            {
              BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-             
+
              /* inform upper layers */
              if (!lp->txready) arcnet_tx_done(dev, lp);
              lp->in_txhandler--;
              continue;
            }
-         
+
          /* if more than one segment, and not all segments
           * are done, then continue xmit.
           */
          if (out->segnum<out->numsegs)
            arcnetA_continue_tx(dev);
          arcnet_go_tx(dev,0);
-         
+
          /* if segnum==numsegs, the transmission is finished;
           * free the skb.
           */
@@ -663,12 +616,12 @@ arc90io_inthandler(struct device *dev)
                  dev_kfree_skb(out->skb,FREE_WRITE);
                }
              out->skb=NULL;
-             
+
              /* inform upper layers */
              if (!lp->txready) arcnet_tx_done(dev, lp);
            }
          didsomething++;
-         
+
          lp->in_txhandler--;
        }
       else if (lp->txready && !lp->sending && !lp->intx)
@@ -678,21 +631,19 @@ arc90io_inthandler(struct device *dev)
          arcnet_go_tx(dev,0);
          didsomething++;
        }
-      
-      
+
 #ifdef DETECT_RECONFIGS
       if (status & (lp->intmask) & RECONflag)
        {
          ACOMMAND(CFLAGScmd|CONFIGclear);
          lp->stats.tx_carrier_errors++;
-         
+
 #ifdef SHOW_RECONFIGS
-         
          BUGMSG(D_NORMAL,"Network reconfiguration detected"
                 " (status=%Xh, config=%X)\n",
                 status,lp->config);
 #endif /* SHOW_RECONFIGS */
-         
+
 #ifdef RECON_THRESHOLD
          /* is the RECON info empty or old? */
          if (!lp->first_recon || !lp->last_recon ||
@@ -702,19 +653,19 @@ arc90io_inthandler(struct device *dev)
                BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
              lp->first_recon=lp->last_recon=jiffies;
              lp->num_recons=lp->network_down=0;
-             
+
              BUGMSG(D_DURING,"recon: clearing counters.\n");
            }
          else /* add to current RECON counter */
            {
              lp->last_recon=jiffies;
              lp->num_recons++;
-             
+
              BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
                     lp->num_recons,
                     (lp->last_recon-lp->first_recon)/HZ,
                     lp->network_down);
-             
+
              /* if network is marked up;
               * and first_recon and last_recon are 60+ sec
               *   apart;
@@ -746,26 +697,24 @@ arc90io_inthandler(struct device *dev)
            BUGMSG(D_NORMAL,"cabling restored?\n");
          lp->first_recon=lp->last_recon=0;
          lp->num_recons=lp->network_down=0;
-         
+
          BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
        }
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
         ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;     /* put back interrupt mask */
-  
 }
 
 
-
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arc90io_rx(struct device *dev,int recbuf)
@@ -777,13 +726,13 @@ arc90io_rx(struct device *dev,int recbuf)
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket);
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -793,13 +742,13 @@ arc90io_rx(struct device *dev,int recbuf)
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   put_buffer_byte(dev,recbuf*512,0);
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -812,16 +761,15 @@ arc90io_rx(struct device *dev,int recbuf)
       arcsoft=&arcpacket->raw[offset];
       length=512-offset;
     }
-  
+
   get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset);
-  
+
   arcnet_rx(lp, arcsoft, length, saddr, daddr);
-  
+
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
 }
 
 
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -830,20 +778,20 @@ arc90io_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
                    char *data,int length,int daddr,int exceptA, int offset)
 {
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  
+
   lp->txbuf=lp->txbuf^1;       /* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
         hdr,length,data);
-  
+
   put_buffer_byte(dev, lp->txbuf*512+1, daddr);
 
   /* load packet into shared memory */
   if (length<=MTU)     /* Normal (256-byte) Packet */
     put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length);
-  
+
   else if (length>=MinTU || offset)    /* Extended (512-byte) Packet */
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
@@ -853,36 +801,36 @@ arc90io_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
     {
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4);
-      
+
       /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-      
+
       put_whole_buffer(dev, lp->txbuf*512+offset,4,"\0\0xff\0xff\0xff");
       offset+=4;
     }
   else                         /* "other" Exception packet */
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
-      
+
       put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0");
-      
+
       /* now round up to MinTU */
       put_buffer_byte(dev, lp->txbuf*512+2, 0);
       put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU);
     }
-  
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
-  
+
   put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr);
   put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data);
-  
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
         daddr,length);
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;       /* packet is ready for sending */
 }
@@ -904,13 +852,13 @@ static struct device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
 int init_module(void)
 {
   struct device *dev=cards[0];
-  
+
   cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
   if (!dev)
     return -ENOMEM;
-  
+
   memset(dev, 0, sizeof(struct device));
-  
+
   dev->name=(char *)kmalloc(9, GFP_KERNEL);
   if (!dev->name)
     {
@@ -918,19 +866,19 @@ int init_module(void)
       return -ENOMEM;
     }
   dev->init=arc90io_probe;
-  
+
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
 
   dev->base_addr=io;
   dev->irq=irq;
-  
+
   if (dev->irq==2) dev->irq=9;
-  
+
   if (register_netdev(dev) != 0)
     return -EIO;
-  
+
   /* Increase use count of arcnet.o */
   arcnet_use_count(1);
   return 0;
@@ -940,9 +888,9 @@ void cleanup_module(void)
 {
   struct device *dev=cards[0];
   int ioaddr=dev->base_addr;
-  
+
   if (dev->start) (*dev->stop)(dev);
-  
+
   /* Flush TX and disable RX */
   if (ioaddr)
     {
@@ -954,23 +902,23 @@ void cleanup_module(void)
                 driver is loaded later */
       outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
     }
-  
+
   if (dev->irq)
     {
       irq2dev_map[dev->irq] = NULL;
       free_irq(dev->irq,NULL);
     }
-  
+
   if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
   unregister_netdev(dev);
   kfree(dev->priv);
   dev->priv = NULL;
-  
+
   /* Decrease use count of arcnet.o */
   arcnet_use_count(0);
 }
-#else
 
+#else
 
 __initfunc(void com90io_setup (char *str, int *ints))
 {
@@ -982,9 +930,9 @@ __initfunc(void com90io_setup (char *str, int *ints))
             MAX_ARCNET_DEVS);
       return;
     }
-  
+
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   if (ints[0] < 1)
     {
       printk("com90xx IO-MAP: You must give an IO address.\n");
@@ -1000,20 +948,17 @@ __initfunc(void com90io_setup (char *str, int *ints))
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* IO address */
       dev->base_addr=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
-  
+
   arcnet_num_devs++;
 }
 
 #endif /* MODULE */
-
-
-
index 48da4e5b38f8b10d625e0fe0f41d56e3420df658..ec88b7354f61174c3c386b649b59eb20d7865e2d 100644 (file)
@@ -1,9 +1,10 @@
-/* com90xx.c:
+/*     $Id: com90xx.c,v 1.3 1997/09/05 18:27:23 mj Exp $
+
        Derived from the original arcnet.c,
        Written 1994-1996 by Avery Pennarun,
        which was in turn derived from skeleton.c by Donald Becker.
 
-       Contact Avery at: apenwarr@foxnet.net or
+       Contact Avery at: apenwarr@bond.net or
        RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
        **********************
 #undef FAST_PROBE
 
 
-
-
-
-
-/* External functions from arcnet.c */
-
-
-
-#if ARCNET_DEBUG_MAX & D_SKB
-extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
-                           char *desc);
-#else
-#define arcnet_dump_skb(dev,skb,desc) ;
-#endif
-
-#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
-                              char *desc);
-#else
-#define arcnet_dump_packet(dev,buffer,ext,desc) ;
-#endif
-
-
-extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
-extern void arcnet_makename(char *device);
-extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-extern void arcnet_setup(struct device *dev);
-extern int arcnet_go_tx(struct device *dev,int enable_irq);
-extern void arcnetA_continue_tx(struct device *dev);
-extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
-extern void arcnet_use_count(int open);
-
-
-
 /* Internal function declarations */
-#ifdef MODULE 
-static 
+#ifdef MODULE
+static
 #endif
        int arc90xx_probe(struct device *dev);
 static void arc90xx_rx(struct device *dev,int recbuf);
-static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem); 
+static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem,int more);
 static void arc90xx_inthandler (struct device *dev);
 static int arc90xx_reset (struct device *dev, int reset_delay);
 static void arc90xx_setmask (struct device *dev, u_char mask);
@@ -160,18 +127,15 @@ char __initdata com90xx_explicit=0;
 extern struct device arcnet_devs[];
 extern char arcnet_dev_names[][10];
 extern int arcnet_num_devs;
-
 #endif
 
 
-
-
 /* Handy defines for ARCnet specific stuff */
 
-/* The number of low I/O ports used by the ethercard. */
+/* The number of low I/O ports used by the card. */
 #define ARCNET_TOTAL_SIZE      16
 
-       /* COM 9026 controller chip --> ARCnet register addresses */
+/* COM 9026 controller chip --> ARCnet register addresses */
 #define _INTMASK (ioaddr+0)    /* writable */
 #define _STATUS  (ioaddr+0)    /* readable */
 #define _COMMAND (ioaddr+1)    /* writable, returns random vals on read (?) */
@@ -183,14 +147,14 @@ extern int arcnet_num_devs;
 
 #define RDDATAflag      0x00     /* Next access is a read/~write */
 
-  #define ARCSTATUS    inb(_STATUS)
-  #define ACOMMAND(cmd) outb((cmd),_COMMAND)
-  #define AINTMASK(msk)        outb((msk),_INTMASK)
-  #define SETCONF      outb(lp->config,_CONFIG)
-  #define ARCRESET     inb(_RESET)
+#define ARCSTATUS      inb(_STATUS)
+#define ACOMMAND(cmd)  outb((cmd),_COMMAND)
+#define AINTMASK(msk)  outb((msk),_INTMASK)
+#define SETCONF                outb(lp->config,_CONFIG)
+#define ARCRESET       inb(_RESET)
 
 static const char *version =
- "com90xx.c: v2.91 97/08/19 Avery Pennarun <apenwarr@bond.net> et al.\n";
+ "com90xx.c: v2.92 97/09/02 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 
 /****************************************************************************
@@ -220,32 +184,28 @@ __initfunc(int arc90xx_probe(struct device *dev))
   static int init_once = 0;
   static int numports=sizeof(ports)/sizeof(ports[0]),
     numshmems=sizeof(shmems)/sizeof(shmems[0]);
-  
   int count,status,delayval,ioaddr,numprint,airq,retval=-ENODEV,
     openparen=0;
   unsigned long airqmask;
   int *port;
   u_long *shmem;
-  
+
   if (!init_once)
     {
       for (count=0x200; count<=0x3f0; count+=16)
        ports[(count-0x200)/16] = count;
       for (count=0xA0000; count<=0xFF800; count+=2048)
        shmems[(count-0xA0000)/2048] = count;
-      init_once=1;
-    }
-  
-  BUGLVL(D_NORMAL) printk(version);
-  BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n",
+      BUGLVL(D_NORMAL) printk(version);
+      BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n",
         sizeof(ports),sizeof(shmems),
         sizeof(ports)+sizeof(shmems));
-  
-  
+    }
+  init_once++;
+
   BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n",
         dev->base_addr,dev->irq,dev->mem_start);
-  
+
   if (dev->base_addr > 0x1ff)  /* Check a single specified port */
     {
       ports[0]=dev->base_addr;
@@ -253,17 +213,16 @@ __initfunc(int arc90xx_probe(struct device *dev))
     }
   else if (dev->base_addr > 0) /* Don't probe at all. */
     return -ENXIO;
-  
+
   if (dev->mem_start)
     {
       shmems[0]=dev->mem_start;
       numshmems=1;
     }
-  
-  
+
   /* Stage 1: abandon any reserved ports, or ones with status==0xFF
-        * (empty), and reset any others by reading the reset port.
-        */
+   * (empty), and reset any others by reading the reset port.
+   */
   BUGMSG(D_INIT,"Stage 1: ");
   numprint=0;
   for (port = &ports[0]; port-ports<numports; port++)
@@ -276,9 +235,9 @@ __initfunc(int arc90xx_probe(struct device *dev))
          numprint=1;
        }
       BUGMSG2(D_INIT,"%Xh ",*port);
-      
+
       ioaddr=*port;
-      
+
       if (check_region(*port, ARCNET_TOTAL_SIZE))
        {
          BUGMSG2(D_INIT_REASONS,"(check_region)\n");
@@ -289,18 +248,18 @@ __initfunc(int arc90xx_probe(struct device *dev))
          port--;
          continue;
        }
-      
+
       if (ARCSTATUS == 0xFF)
        {
-                       BUGMSG2(D_INIT_REASONS,"(empty)\n");
-                       BUGMSG(D_INIT_REASONS,"Stage 1: ");
-                       BUGLVL(D_INIT_REASONS) numprint=0;
-                       *port=ports[numports-1];
-                       numports--;
-                       port--;
-                       continue;
+         BUGMSG2(D_INIT_REASONS,"(empty)\n");
+         BUGMSG(D_INIT_REASONS,"Stage 1: ");
+         BUGLVL(D_INIT_REASONS) numprint=0;
+         *port=ports[numports-1];
+         numports--;
+         port--;
+         continue;
        }
-      
+
       ARCRESET;        /* begin resetting card */
 
       BUGMSG2(D_INIT_REASONS,"\n");
@@ -308,279 +267,280 @@ __initfunc(int arc90xx_probe(struct device *dev))
       BUGLVL(D_INIT_REASONS) numprint=0;
     }
   BUGMSG2(D_INIT,"\n");
-  
+
   if (!numports)
     {
       BUGMSG(D_NORMAL,"Stage 1: No ARCnet cards found.\n");
       return -ENODEV;
     }
-  
-  
+
   /* Stage 2: we have now reset any possible ARCnet cards, so we can't
    * do anything until they finish.  If D_INIT, print the list of
    * cards that are left.
    */
-       BUGMSG(D_INIT,"Stage 2: ");
-       numprint=0;
-       for (port = &ports[0]; port-ports<numports; port++)
-         {
-           numprint++;
-           if (numprint>8)
-             {
-               BUGMSG2(D_INIT,"\n");
-               BUGMSG(D_INIT,"Stage 2: ");
-               numprint=1;
-             }
-           BUGMSG2(D_INIT,"%Xh ",*port);
-         }
-       BUGMSG2(D_INIT,"\n");
-       JIFFER(RESETtime);
-       
-       
-       /* Stage 3: abandon any shmem addresses that don't have the signature
-        * 0xD1 byte in the right place, or are read-only.
-        */
-       BUGMSG(D_INIT,"Stage 3: ");
-       numprint=0;
-       for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-         {
-           u_long ptr;
-           
-               numprint++;
-               if (numprint>8)
-                 {
-                   BUGMSG2(D_INIT,"\n");
-                   BUGMSG(D_INIT,"Stage 3: ");
-                   numprint=1;
-                 }
-               BUGMSG2(D_INIT,"%lXh ",*shmem);
-               
-               ptr=(u_long)(*shmem);
-               
-               if (readb(ptr) != TESTvalue)
-               {
-                 BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n",
-                         readb(ptr),TESTvalue);
-                 BUGMSG(D_INIT_REASONS,"Stage 3: ");
-                 BUGLVL(D_INIT_REASONS) numprint=0;
-                 *shmem=shmems[numshmems-1];
-                 numshmems--;
-                 shmem--;
-                 continue;
-               }
-               
-               /* By writing 0x42 to the TESTvalue location, we also make
-                * sure no "mirror" shmem areas show up - if they occur
-                * in another pass through this loop, they will be discarded
-                * because *cptr != TESTvalue.
-                */
-               writeb(0x42,ptr);
-               if (readb(ptr) != 0x42)
-                 {
-                   BUGMSG2(D_INIT_REASONS,"(read only)\n");
-                   BUGMSG(D_INIT_REASONS,"Stage 3: ");
-                   *shmem=shmems[numshmems-1];
-                   numshmems--;
-                   shmem--;
-                   continue;
-                 }
-               
-               BUGMSG2(D_INIT_REASONS,"\n");
-               BUGMSG(D_INIT_REASONS,"Stage 3: ");
-               BUGLVL(D_INIT_REASONS) numprint=0;
-         }
-       BUGMSG2(D_INIT,"\n");
-       
-       if (!numshmems)
-         {
-           BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n");
-           return -ENODEV;
-         }
-       
-       /* Stage 4: something of a dummy, to report the shmems that are
-        * still possible after stage 3.
-        */
-       BUGMSG(D_INIT,"Stage 4: ");
-       numprint=0;
-       for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-         {
-           numprint++;
-           if (numprint>8)
-             {
-               BUGMSG2(D_INIT,"\n");
-               BUGMSG(D_INIT,"Stage 4: ");
-               numprint=1;
-             }
-           BUGMSG2(D_INIT,"%lXh ",*shmem);
-         }
-       BUGMSG2(D_INIT,"\n");
-       
-       
-       /* Stage 5: for any ports that have the correct status, can disable
-        * the RESET flag, and (if no irq is given) generate an autoirq,
-        * register an ARCnet device.
-        *
-        * Currently, we can only register one device per probe, so quit
-        * after the first one is found.
-        */
-       BUGMSG(D_INIT,"Stage 5: ");
-       numprint=0;
-       for (port = &ports[0]; port-ports<numports; port++)
-         {
-           numprint++;
-           if (numprint>8)
-             {
-               BUGMSG2(D_INIT,"\n");
-               BUGMSG(D_INIT,"Stage 5: ");
-               numprint=1;
-             }
-           BUGMSG2(D_INIT,"%Xh ",*port);
-           
-           ioaddr=*port;
-           status=ARCSTATUS;
-           
-           if ((status & 0x9D)
-               != (NORXflag|RECONflag|TXFREEflag|RESETflag))
-             {
-               BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status);
-               BUGMSG(D_INIT_REASONS,"Stage 5: ");
-               BUGLVL(D_INIT_REASONS) numprint=0;
-               *port=ports[numports-1];
-               numports--;
-               port--;
-               continue;
-               }
-           
-           ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
-           status=ARCSTATUS;
-           if (status & RESETflag)
-             {
-               BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n",
-                       status);
-               BUGMSG(D_INIT_REASONS,"Stage 5: ");
-               BUGLVL(D_INIT_REASONS) numprint=0;
-                       *port=ports[numports-1];
-                       numports--;
-                       port--;
-                       continue;
-             }
-           
-           /* skip this completely if an IRQ was given, because maybe
-            * we're on a machine that locks during autoirq!
-            */
-               if (!dev->irq)
-                 {
-                   /* if we do this, we're sure to get an IRQ since the
-                    * card has just reset and the NORXflag is on until
-                    * we tell it to start receiving.
-                    */
-                   airqmask = probe_irq_on();
-                   AINTMASK(NORXflag);
-                   udelay(1);
-                   AINTMASK(0);
-                   airq = probe_irq_off(airqmask);
-
-                   if (airq<=0)
-                     {
-                       BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq);
-                       BUGMSG(D_INIT_REASONS,"Stage 5: ");
-                       BUGLVL(D_INIT_REASONS) numprint=0;
-                       *port=ports[numports-1];
-                       numports--;
-                       port--;
-                               continue;
-                     }
-                 }
-               else
-               {
-                 airq=dev->irq;
-               }
-               
-               BUGMSG2(D_INIT,"(%d,", airq);
-               openparen=1;
-               
-               /* Everything seems okay.  But which shmem, if any, puts
-                * back its signature byte when the card is reset?
-                *
-                * If there are multiple cards installed, there might be
-                * multiple shmems still in the list.
-                */
+  BUGMSG(D_INIT,"Stage 2: ");
+  numprint=0;
+  for (port = &ports[0]; port-ports<numports; port++)
+    {
+      numprint++;
+      if (numprint>8)
+       {
+         BUGMSG2(D_INIT,"\n");
+         BUGMSG(D_INIT,"Stage 2: ");
+         numprint=1;
+       }
+      BUGMSG2(D_INIT,"%Xh ",*port);
+    }
+  BUGMSG2(D_INIT,"\n");
+  JIFFER(RESETtime);
+
+  /* Stage 3: abandon any shmem addresses that don't have the signature
+   * 0xD1 byte in the right place, or are read-only.
+   */
+  BUGMSG(D_INIT,"Stage 3: ");
+  numprint=0;
+  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+    {
+      u_long ptr;
+
+      numprint++;
+      if (numprint>8)
+       {
+         BUGMSG2(D_INIT,"\n");
+         BUGMSG(D_INIT,"Stage 3: ");
+         numprint=1;
+       }
+      BUGMSG2(D_INIT,"%lXh ",*shmem);
+
+      ptr=(u_long)(*shmem);
+
+      if (readb(ptr) != TESTvalue)
+       {
+         BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n",
+                 readb(ptr),TESTvalue);
+         BUGMSG(D_INIT_REASONS,"Stage 3: ");
+         BUGLVL(D_INIT_REASONS) numprint=0;
+         *shmem=shmems[numshmems-1];
+         numshmems--;
+         shmem--;
+         continue;
+       }
+
+      /* By writing 0x42 to the TESTvalue location, we also make
+       * sure no "mirror" shmem areas show up - if they occur
+       * in another pass through this loop, they will be discarded
+       * because *cptr != TESTvalue.
+       */
+      writeb(0x42,ptr);
+      if (readb(ptr) != 0x42)
+       {
+         BUGMSG2(D_INIT_REASONS,"(read only)\n");
+         BUGMSG(D_INIT_REASONS,"Stage 3: ");
+         *shmem=shmems[numshmems-1];
+         numshmems--;
+         shmem--;
+         continue;
+       }
+
+      BUGMSG2(D_INIT_REASONS,"\n");
+      BUGMSG(D_INIT_REASONS,"Stage 3: ");
+      BUGLVL(D_INIT_REASONS) numprint=0;
+    }
+  BUGMSG2(D_INIT,"\n");
+
+  if (!numshmems)
+    {
+      BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n");
+      return -ENODEV;
+    }
+
+  /* Stage 4: something of a dummy, to report the shmems that are
+   * still possible after stage 3.
+   */
+  BUGMSG(D_INIT,"Stage 4: ");
+  numprint=0;
+  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+    {
+      numprint++;
+      if (numprint>8)
+       {
+         BUGMSG2(D_INIT,"\n");
+         BUGMSG(D_INIT,"Stage 4: ");
+         numprint=1;
+       }
+      BUGMSG2(D_INIT,"%lXh ",*shmem);
+    }
+  BUGMSG2(D_INIT,"\n");
+
+  /* Stage 5: for any ports that have the correct status, can disable
+   * the RESET flag, and (if no irq is given) generate an autoirq,
+   * register an ARCnet device.
+   *
+   * Currently, we can only register one device per probe, so quit
+   * after the first one is found.
+   */
+  BUGMSG(D_INIT,"Stage 5: ");
+  numprint=0;
+  for (port = &ports[0]; port-ports<numports; port++)
+    {
+      numprint++;
+      if (numprint>8)
+       {
+         BUGMSG2(D_INIT,"\n");
+         BUGMSG(D_INIT,"Stage 5: ");
+         numprint=1;
+       }
+      BUGMSG2(D_INIT,"%Xh ",*port);
+
+      ioaddr=*port;
+      status=ARCSTATUS;
+
+      if ((status & 0x9D)
+         != (NORXflag|RECONflag|TXFREEflag|RESETflag))
+       {
+         BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status);
+         BUGMSG(D_INIT_REASONS,"Stage 5: ");
+         BUGLVL(D_INIT_REASONS) numprint=0;
+         *port=ports[numports-1];
+         numports--;
+         port--;
+         continue;
+       }
+
+      ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
+      status=ARCSTATUS;
+      if (status & RESETflag)
+       {
+         BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n",
+                 status);
+         BUGMSG(D_INIT_REASONS,"Stage 5: ");
+         BUGLVL(D_INIT_REASONS) numprint=0;
+         *port=ports[numports-1];
+         numports--;
+         port--;
+         continue;
+       }
+
+      /* skip this completely if an IRQ was given, because maybe
+       * we're on a machine that locks during autoirq!
+       */
+      if (!dev->irq)
+       {
+         /* if we do this, we're sure to get an IRQ since the
+          * card has just reset and the NORXflag is on until
+          * we tell it to start receiving.
+          */
+         airqmask = probe_irq_on();
+         AINTMASK(NORXflag);
+         udelay(1);
+         AINTMASK(0);
+         airq = probe_irq_off(airqmask);
+
+         if (airq<=0)
+           {
+             BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq);
+             BUGMSG(D_INIT_REASONS,"Stage 5: ");
+             BUGLVL(D_INIT_REASONS) numprint=0;
+             *port=ports[numports-1];
+             numports--;
+             port--;
+             continue;
+           }
+       }
+      else
+       {
+         airq=dev->irq;
+       }
+
+      BUGMSG2(D_INIT,"(%d,", airq);
+      openparen=1;
+
+      /* Everything seems okay.  But which shmem, if any, puts
+       * back its signature byte when the card is reset?
+       *
+       * If there are multiple cards installed, there might be
+       * multiple shmems still in the list.
+       */
 #ifdef FAST_PROBE
-               if (numports>1 || numshmems>1)
-                 {
-                   ARCRESET;
-                   JIFFER(RESETtime);
-                 }
-               else
-                 {
-                   /* just one shmem and port, assume they match */
-                   writeb(TESTvalue,shmems[0]);
-                 }
+      if (numports>1 || numshmems>1)
+       {
+         ARCRESET;
+         JIFFER(RESETtime);
+       }
+      else
+       {
+         /* just one shmem and port, assume they match */
+         writeb(TESTvalue,shmems[0]);
+       }
 #else
-               ARCRESET;
-               JIFFER(RESETtime);
+      ARCRESET;
+      JIFFER(RESETtime);
 #endif
-               
-               
-               for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-                 {
-                   u_long ptr;
-                   ptr=(u_long)(*shmem);
-                   
-                   if (readb(ptr) == TESTvalue)        /* found one */
-                     {
-                       BUGMSG2(D_INIT,"%lXh)\n", *shmem);
-                       openparen=0;
-                       
-                       /* register the card */
-                       retval=arc90xx_found(dev,*port,airq,*shmem);
-                       if (retval) openparen=0;
-                       
-                       /* remove shmem from the list */
-                       *shmem=shmems[numshmems-1];
-                       numshmems--;
-                       
-                       break;
-                     }
-                   else
-                     {
-                       BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr));
-                     }
-                 }
-               
-               if (openparen)
-                 {
-                   BUGMSG2(D_INIT,"no matching shmem)\n");
-                   BUGMSG(D_INIT_REASONS,"Stage 5: ");
-                   BUGLVL(D_INIT_REASONS) numprint=0;
-                 }
-               
-               *port=ports[numports-1];
-               numports--;
-               port--;
-               
-               if (!retval) break;
-         }
-       BUGMSG(D_INIT_REASONS,"\n");
-       
-       /* Now put back TESTvalue on all leftover shmems.
-        */
-       for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-         writeb(TESTvalue,*shmem);
-       
-       if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n");
-       return retval;
+
+      for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+       {
+         u_long ptr;
+         ptr=(u_long)(*shmem);
+
+         if (readb(ptr) == TESTvalue)  /* found one */
+           {
+             int probe_more;
+             BUGMSG2(D_INIT,"%lXh)\n", *shmem);
+             openparen=0;
+
+             /* register the card */
+             if (init_once == 1 && numshmems > 1)
+               probe_more = numshmems - 1;
+             else
+               probe_more = 0;
+             retval=arc90xx_found(dev,*port,airq,*shmem,probe_more);
+             if (retval) openparen=0;
+
+             /* remove shmem from the list */
+             *shmem=shmems[numshmems-1];
+             numshmems--;
+
+             break;
+           }
+         else
+           {
+             BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr));
+           }
+       }
+
+      if (openparen)
+       {
+         BUGMSG2(D_INIT,"no matching shmem)\n");
+         BUGMSG(D_INIT_REASONS,"Stage 5: ");
+         BUGLVL(D_INIT_REASONS) numprint=0;
+       }
+
+      *port=ports[numports-1];
+      numports--;
+      port--;
+
+      if (!retval) break;
+    }
+  BUGMSG(D_INIT_REASONS,"\n");
+
+  /* Now put back TESTvalue on all leftover shmems.
+   */
+  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
+    writeb(TESTvalue,*shmem);
+
+  if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n");
+  return retval;
 }
 
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
-__initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shmem))
+__initfunc(static int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shmem, int more))
 {
   struct arcnet_local *lp;
   u_long first_mirror,last_mirror;
   int mirror_size;
-  
+
   /* reserve the irq */
   if (request_irq(airq,&arcnet_interrupt,0,"arcnet (90xx)",NULL))
     {
@@ -589,40 +549,39 @@ __initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shme
     }
   irq2dev_map[airq]=dev;
   dev->irq=airq;
-  
-  
+
   /* reserve the I/O region - guaranteed to work by check_region */
   request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (90xx)");
   dev->base_addr=ioaddr;
-  
+
   /* find the real shared memory start/end points, including mirrors */
 #define BUFFER_SIZE (512)
 #define MIRROR_SIZE (BUFFER_SIZE*4)
-  
+
   /* guess the actual size of one "memory mirror" - the number of
-        * bytes between copies of the shared memory.  On most cards, it's
-        * 2k (or there are no mirrors at all) but on some, it's 4k.
-        */
+   * bytes between copies of the shared memory.  On most cards, it's
+   * 2k (or there are no mirrors at all) but on some, it's 4k.
+   */
   mirror_size=MIRROR_SIZE;
   if (readb(shmem)==TESTvalue
       && readb(shmem-mirror_size)!=TESTvalue
       && readb(shmem-2*mirror_size)==TESTvalue)
     mirror_size*=2;
-  
+
   first_mirror=last_mirror=shmem;
   while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size;
   first_mirror+=mirror_size;
-  
+
   while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size;
   last_mirror-=mirror_size;
-  
+
   dev->mem_start=first_mirror;
   dev->mem_end=last_mirror+MIRROR_SIZE-1;
   dev->rmem_start=dev->mem_start+BUFFER_SIZE*0;
   dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1;
-  
-       /* Initialize the rest of the device structure. */
-  
+
+  /* Initialize the rest of the device structure. */
+
   dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
   if (dev->priv == NULL)
     {
@@ -642,27 +601,26 @@ __initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shme
   lp->openclose_device=arc90xx_openclose;
   lp->prepare_tx=arc90xx_prepare_tx;
   lp->inthandler=arc90xx_inthandler;
-  
-  
+
   /* Fill in the fields of the device structure with generic
    * values.
    */
   arcnet_setup(dev);
-  
+
   /* And now fill particular fields with arcnet values */
   dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
   dev->hard_header_len=sizeof(struct ClientData);
   lp->sequence=1;
   lp->recbuf=0;
-  
+
   BUGMSG(D_DURING,"ClientData header size is %d.\n",
         sizeof(struct ClientData));
   BUGMSG(D_DURING,"HardHeader size is %d.\n",
         sizeof(struct archdr));
-  
+
   /* get and check the station ID from offset 1 in shmem */
   lp->stationid = readb(first_mirror+1);
-  
+
   if (lp->stationid==0)
     BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
           "for broadcasts!\n");
@@ -670,53 +628,35 @@ __initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shme
     BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
           "DOS networking programs!\n");
   dev->dev_addr[0]=lp->stationid;
-  
+
   BUGMSG(D_NORMAL,"ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, "
         "ShMem %lXh (%ld*%xh).\n",
         lp->stationid,
         dev->base_addr, dev->irq, dev->mem_start,
         (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size);
 
-#ifdef CONFIG_ARCNET_COM90xx
-  /* OK. We're finished. Now do we need to probe for other cards? */
+  /* OK. We're finished. If there are probably other cards, add other
+   * COM90xx drivers to the device chain, so they get probed later.
+   */
 
-  if (!com90xx_explicit)
+#ifndef MODULE
+  while (!com90xx_explicit && more--)
     {
-      /* We need to check whether there's another card here.
-       * Just add another COM90xx driver to the device chain.
-       */
-      
       if (arcnet_num_devs < MAX_ARCNET_DEVS)
        {
          arcnet_devs[arcnet_num_devs].next=dev->next;
          dev->next=&arcnet_devs[arcnet_num_devs];
-         dev->next->name=(char *)&arcnet_dev_names[arcnet_num_devs];
+         dev=dev->next;
+         dev->name=(char *)&arcnet_dev_names[arcnet_num_devs];
          arcnet_num_devs++;
        }
       else
        {
-         while (dev->next) dev=dev->next;
-         
-         dev->next=kmalloc(sizeof(struct device), GFP_KERNEL);
-         if (!dev->next)
-           {
-             BUGMSG(D_NORMAL, "No memory for allocating next device - no more "
-                    "will be probed for.\n");
-             return 0;
-           }
-         memset(dev->next,0,sizeof(struct device));
-         dev->next->name=kmalloc(10, GFP_KERNEL);
-         if (!dev->next->name)
-           {
-             BUGMSG(D_NORMAL, "No memory for allocating next device - no more "
-                    "will be probed for.\n");
-             kfree(dev->next);
-             dev->next=NULL;
-             return 0;
-           }
+         BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n");
+         return 0;
        }
-      arcnet_makename(dev->next->name);
-      dev->next->init=arc90xx_probe;      
+      arcnet_makename(dev->name);
+      dev->init=arc90xx_probe;
     }
 #endif
 
@@ -724,7 +664,6 @@ __initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shme
 }
 
 
-
 /* Do a hardware reset on the card, and set up necessary registers.
  *
  * This should be called as little as possible, because it disrupts the
@@ -734,67 +673,68 @@ __initfunc(int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shme
  */
 int arc90xx_reset(struct device *dev,int reset_delay)
 {
-       struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-       short ioaddr=dev->base_addr;
-       int delayval,recbuf=lp->recbuf;
+  struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+  short ioaddr=dev->base_addr;
+  int delayval,recbuf=lp->recbuf;
 
   if (reset_delay==3)
     {
       ARCRESET;
       return 0;
     }
-  
-       /* no IRQ's, please! */
-       lp->intmask=0;
-       SETMASK;
 
-       BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
-                       dev->name,ARCSTATUS);
+  /* no IRQ's, please! */
+  lp->intmask=0;
+  SETMASK;
 
-       if (reset_delay)
-       {
-               /* reset the card */
-               ARCRESET;
-               JIFFER(RESETtime);
-       }
+  BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
+        dev->name,ARCSTATUS);
 
-       ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
-       ACOMMAND(CFLAGScmd|CONFIGclear);
+  if (reset_delay)
+    {
+      /* reset the card */
+      ARCRESET;
+      JIFFER(RESETtime);
+    }
 
-       /* verify that the ARCnet signature byte is present */
-       if (readb(dev->mem_start) != TESTvalue)
-       {
-               BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
-               return 1;
-       }
+  ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
+  ACOMMAND(CFLAGScmd|CONFIGclear);
 
-       /* clear out status variables */
-       recbuf=lp->recbuf=0;
-       lp->txbuf=2;
+  /* verify that the ARCnet signature byte is present */
+  if (readb(dev->mem_start) != TESTvalue)
+    {
+      BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
+      return 1;
+    }
 
-       /* enable extended (512-byte) packets */
-       ACOMMAND(CONFIGcmd|EXTconf);
+  /* clear out status variables */
+  recbuf=lp->recbuf=0;
+  lp->txbuf=2;
+
+  /* enable extended (512-byte) packets */
+  ACOMMAND(CONFIGcmd|EXTconf);
 
 #ifndef SLOW_XMIT_COPY
-       /* clean out all the memory to make debugging make more sense :) */
-       BUGLVL(D_DURING)
-               memset_io(dev->mem_start,0x42,2048);
+  /* clean out all the memory to make debugging make more sense :) */
+  BUGLVL(D_DURING)
+    memset_io(dev->mem_start,0x42,2048);
 #endif
 
-       /* and enable receive of our first packet to the first buffer */
-       EnableReceiver();
+  /* and enable receive of our first packet to the first buffer */
+  EnableReceiver();
 
-       /* re-enable interrupts */
-       lp->intmask|=NORXflag;
+  /* re-enable interrupts */
+  lp->intmask|=NORXflag;
 #ifdef DETECT_RECONFIGS
-       lp->intmask|=RECONflag;
+  lp->intmask|=RECONflag;
 #endif
-       SETMASK;
+  SETMASK;
 
-       /* done!  return success. */
-       return 0;
+  /* done!  return success. */
+  return 0;
 }
 
+
 static void arc90xx_openclose(int open)
 {
  if (open)
@@ -811,6 +751,7 @@ static void arc90xx_setmask(struct device *dev, u_char mask)
   AINTMASK(mask);
 }
 
+
 static u_char arc90xx_status(struct device *dev)
 {
   short ioaddr=dev->base_addr;
@@ -818,6 +759,7 @@ static u_char arc90xx_status(struct device *dev)
   return ARCSTATUS;
 }
 
+
 static void arc90xx_command(struct device *dev, u_char cmd)
 {
   short ioaddr=dev->base_addr;
@@ -834,226 +776,219 @@ arc90xx_inthandler(struct device *dev)
 {
   struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
   int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
-  
-  
+
   AINTMASK(0);
-  
+
   BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
         ARCSTATUS,lp->intmask);
-  
+
   do
     {
       status = ARCSTATUS;
-               didsomething=0;
-               
-               
-               /* RESET flag was enabled - card is resetting and if RX
-                * is disabled, it's NOT because we just got a packet.
-                */
-               if (status & RESETflag)
-                 {
-                   BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
-                          status);
-                   arc90xx_reset(dev,0);
-                   
-                   /* all other flag values are just garbage */
-                   break;
-                 }
-               
-               
-               /* RX is inhibited - we must have received something. */
-               if (status & lp->intmask & NORXflag)
-                 {
-                   int recbuf=lp->recbuf=!lp->recbuf;
-                   
-                   BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
-                          status);
-                   
-                   /* enable receive of our next packet */
-                   EnableReceiver();
-                   
-                   /* Got a packet. */
-                   arc90xx_rx(dev,!recbuf);
-                       
-                   didsomething++;
-                 }
-               
-               /* it can only be an xmit-done irq if we're xmitting :) */
-               /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
-               if (status & lp->intmask & TXFREEflag)
-                 {
-                   struct Outgoing *out=&(lp->outgoing);
-                   int was_sending=lp->sending;
-                   
-                   lp->intmask &= ~TXFREEflag;
-                   
-                       lp->in_txhandler++;
-                       if (was_sending) lp->sending--;
-                       
-                       BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
-                              status,out->numsegs,out->segnum,out->skb);
-                       
-                       if (was_sending && !(status&TXACKflag))
-                         {
-                           if (lp->lasttrans_dest != 0)
-                             {
-                               BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
-                                      status,lp->lasttrans_dest);
-                               lp->stats.tx_errors++;
-                               lp->stats.tx_carrier_errors++;
-                             }
-                           else
-                             {
-                               BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
-                                      status,
-                                      lp->lasttrans_dest);
-                             }
-                         }
-                       
-                       /* send packet if there is one */
-                       arcnet_go_tx(dev,0);
-                       didsomething++;
-                       
-                       if (lp->intx)
-                         {
-                           BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
-                                  ARCSTATUS,lp->intx);
-                           lp->in_txhandler--;
-                           continue;
-                         }
-                       
-                       if (!lp->outgoing.skb)
-                         {
-                           BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-                           
-                           /* inform upper layers */
-                           if (!lp->txready) arcnet_tx_done(dev, lp);
-                           lp->in_txhandler--;
-                           continue;
-                         }
-                       
-                       /* if more than one segment, and not all segments
-                        * are done, then continue xmit.
-                        */
-                       if (out->segnum<out->numsegs)
-                         arcnetA_continue_tx(dev);
-                       arcnet_go_tx(dev,0);
-                       
-                       /* if segnum==numsegs, the transmission is finished;
-                        * free the skb.
-                        */
-                       if (out->segnum>=out->numsegs)
-                         {
-                           /* transmit completed */
-                           out->segnum++;
-                           if (out->skb)
-                             {
-                               lp->stats.tx_bytes += out->skb->len;
-                               dev_kfree_skb(out->skb,FREE_WRITE);
-                             }
-                           out->skb=NULL;
-                           
-                           /* inform upper layers */
-                           if (!lp->txready) arcnet_tx_done(dev, lp);
-                         }
-                       didsomething++;
-                       
-                       lp->in_txhandler--;
-                 }
-               else if (lp->txready && !lp->sending && !lp->intx)
-                 {
-                   BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
-                          status);
-                   arcnet_go_tx(dev,0);
-                   didsomething++;
-                 }
+      didsomething=0;
+
+      /* RESET flag was enabled - card is resetting and if RX
+       * is disabled, it's NOT because we just got a packet.
+       */
+      if (status & RESETflag)
+       {
+         BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
+                status);
+         arc90xx_reset(dev,0);
+
+         /* all other flag values are just garbage */
+         break;
+       }
+
+      /* RX is inhibited - we must have received something. */
+      if (status & lp->intmask & NORXflag)
+       {
+         int recbuf=lp->recbuf=!lp->recbuf;
+
+         BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
+                status);
+
+         /* enable receive of our next packet */
+         EnableReceiver();
+
+         /* Got a packet. */
+         arc90xx_rx(dev,!recbuf);
+
+         didsomething++;
+       }
+
+      /* it can only be an xmit-done irq if we're xmitting :) */
+      /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
+      if (status & lp->intmask & TXFREEflag)
+       {
+         struct Outgoing *out=&(lp->outgoing);
+         int was_sending=lp->sending;
+
+         lp->intmask &= ~TXFREEflag;
+
+         lp->in_txhandler++;
+         if (was_sending) lp->sending--;
+
+         BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
+                status,out->numsegs,out->segnum,out->skb);
+
+         if (was_sending && !(status&TXACKflag))
+           {
+             if (lp->lasttrans_dest != 0)
+               {
+                 BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
+                        status,lp->lasttrans_dest);
+                 lp->stats.tx_errors++;
+                 lp->stats.tx_carrier_errors++;
+               }
+             else
+               {
+                 BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
+                        status,
+                        lp->lasttrans_dest);
+               }
+           }
+
+         /* send packet if there is one */
+         arcnet_go_tx(dev,0);
+         didsomething++;
+
+         if (lp->intx)
+           {
+             BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
+                    ARCSTATUS,lp->intx);
+             lp->in_txhandler--;
+             continue;
+           }
+
+         if (!lp->outgoing.skb)
+           {
+             BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
+
+             /* inform upper layers */
+             if (!lp->txready) arcnet_tx_done(dev, lp);
+             lp->in_txhandler--;
+             continue;
+           }
+
+         /* if more than one segment, and not all segments
+          * are done, then continue xmit.
+          */
+         if (out->segnum<out->numsegs)
+           arcnetA_continue_tx(dev);
+         arcnet_go_tx(dev,0);
+
+         /* if segnum==numsegs, the transmission is finished;
+          * free the skb.
+          */
+         if (out->segnum>=out->numsegs)
+           {
+             /* transmit completed */
+             out->segnum++;
+             if (out->skb)
+               {
+                 lp->stats.tx_bytes += out->skb->len;
+                 dev_kfree_skb(out->skb,FREE_WRITE);
+               }
+             out->skb=NULL;
+
+             /* inform upper layers */
+             if (!lp->txready) arcnet_tx_done(dev, lp);
+           }
+         didsomething++;
+
+         lp->in_txhandler--;
+       }
+      else if (lp->txready && !lp->sending && !lp->intx)
+       {
+         BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
+                status);
+         arcnet_go_tx(dev,0);
+         didsomething++;
+       }
 
 #ifdef DETECT_RECONFIGS
-               if (status & (lp->intmask) & RECONflag)
-                 {
-                   ACOMMAND(CFLAGScmd|CONFIGclear);
-                   lp->stats.tx_carrier_errors++;
-                   
+      if (status & (lp->intmask) & RECONflag)
+       {
+         ACOMMAND(CFLAGScmd|CONFIGclear);
+         lp->stats.tx_carrier_errors++;
+
 #ifdef SHOW_RECONFIGS
-                   BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
-                          status);
-                   
-                   
+         BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
+                status);
 #endif /* SHOW_RECONFIGS */
-                   
+
 #ifdef RECON_THRESHOLD
-                   /* is the RECON info empty or old? */
-                   if (!lp->first_recon || !lp->last_recon ||
-                       jiffies-lp->last_recon > HZ*10)
-                     {
-                       if (lp->network_down)
-                         BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
-                       lp->first_recon=lp->last_recon=jiffies;
-                       lp->num_recons=lp->network_down=0;
-                       
-                       BUGMSG(D_DURING,"recon: clearing counters.\n");
-                     }
-                   else /* add to current RECON counter */
-                     {
-                       lp->last_recon=jiffies;
-                       lp->num_recons++;
-                       
-                       BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
-                              lp->num_recons,
-                              (lp->last_recon-lp->first_recon)/HZ,
-                              lp->network_down);
-                       
-                       /* if network is marked up;
-                        * and first_recon and last_recon are 60+ sec
-                        *   apart;
-                        * and the average no. of recons counted is
-                        *   > RECON_THRESHOLD/min;
-                        * then print a warning message.
-                        */
-                       if (!lp->network_down
-                           && (lp->last_recon-lp->first_recon)<=HZ*60
-                           && lp->num_recons >= RECON_THRESHOLD)
-                         {
-                           lp->network_down=1;
-                           BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
-                         }
-                       else if (!lp->network_down
-                                && lp->last_recon-lp->first_recon > HZ*60)
-                         {
-                           /* reset counters if we've gone for
-                            * over a minute.
-                            */
-                           lp->first_recon=lp->last_recon;
-                           lp->num_recons=1;
-                         }
-                     }
-                 }
-               else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
-                 {
-                   if (lp->network_down)
-                     BUGMSG(D_NORMAL,"cabling restored?\n");
-                   lp->first_recon=lp->last_recon=0;
-                   lp->num_recons=lp->network_down=0;
-                   
-                   BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
+         /* is the RECON info empty or old? */
+         if (!lp->first_recon || !lp->last_recon ||
+             jiffies-lp->last_recon > HZ*10)
+           {
+             if (lp->network_down)
+               BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
+             lp->first_recon=lp->last_recon=jiffies;
+             lp->num_recons=lp->network_down=0;
+
+             BUGMSG(D_DURING,"recon: clearing counters.\n");
+           }
+         else /* add to current RECON counter */
+           {
+             lp->last_recon=jiffies;
+             lp->num_recons++;
+
+             BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
+                    lp->num_recons,
+                    (lp->last_recon-lp->first_recon)/HZ,
+                    lp->network_down);
+
+             /* if network is marked up;
+              * and first_recon and last_recon are 60+ sec
+              *   apart;
+              * and the average no. of recons counted is
+              *   > RECON_THRESHOLD/min;
+              * then print a warning message.
+              */
+             if (!lp->network_down
+                 && (lp->last_recon-lp->first_recon)<=HZ*60
+                 && lp->num_recons >= RECON_THRESHOLD)
+               {
+                 lp->network_down=1;
+                 BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
+               }
+             else if (!lp->network_down
+                      && lp->last_recon-lp->first_recon > HZ*60)
+               {
+                 /* reset counters if we've gone for
+                  * over a minute.
+                  */
+                 lp->first_recon=lp->last_recon;
+                 lp->num_recons=1;
+               }
+           }
+       }
+      else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
+       {
+         if (lp->network_down)
+           BUGMSG(D_NORMAL,"cabling restored?\n");
+         lp->first_recon=lp->last_recon=0;
+         lp->num_recons=lp->network_down=0;
+
+         BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
 #endif
-                 }
+       }
 #endif /* DETECT_RECONFIGS */
     } while (--boguscount && didsomething);
-  
+
   BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
         ARCSTATUS,boguscount);
   BUGMSG(D_DURING,"\n");
-  
+
   SETMASK;     /* put back interrupt mask */
-  
 }
 
 
-
 /* A packet has arrived; grab it from the buffers and pass it to the generic
  * arcnet_rx routing to deal with it.
- */ 
+ */
 
 static void
 arc90xx_rx(struct device *dev,int recbuf)
@@ -1065,11 +1000,11 @@ arc90xx_rx(struct device *dev,int recbuf)
   u_char *arcsoft;
   short length,offset;
   u_char daddr,saddr;
-  
+
   lp->stats.rx_packets++;
-  
+
   saddr=arcpacket->hardheader.source;
-  
+
   /* if source is 0, it's a "used" packet! */
   if (saddr==0)
     {
@@ -1079,11 +1014,11 @@ arc90xx_rx(struct device *dev,int recbuf)
       return;
     }
   /* Set source address to zero to mark it as old */
-  
+
   arcpacket->hardheader.source=0;
-  
+
   daddr=arcpacket->hardheader.destination;
-  
+
   if (arcpacket->hardheader.offset1) /* Normal Packet */
     {
       offset=arcpacket->hardheader.offset1;
@@ -1094,28 +1029,22 @@ arc90xx_rx(struct device *dev,int recbuf)
     {
       offset=arcpacket->hardheader.offset2;
       arcsoft=&arcpacket->raw[offset];
-      
+
       length=512-offset;
     }
-  
-  
-  arcnet_rx(lp, arcsoft, length, saddr, daddr);
 
+  arcnet_rx(lp, arcsoft, length, saddr, daddr);
 
   BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
-   
 
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset((void *)arcpacket->raw,0x42,512);
 #endif
-  
 }
 
 
-
-
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
@@ -1126,45 +1055,45 @@ arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
   struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
   union ArcPacket *arcpacket =
     (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
-  
+
 #ifdef SLOW_XMIT_COPY
   char *iptr,*iend,*optr;
 #endif
-  
+
   lp->txbuf=lp->txbuf^1;       /* XOR with 1 to alternate between 2 and 3 */
-  
+
   length+=hdrlen;
-  
+
   BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
         hdr,length,data);
-  
+
 #ifndef SLOW_XMIT_COPY
   /* clean out the page to make debugging make more sense :) */
   BUGLVL(D_DURING)
     memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
 #endif
-  
+
   arcpacket->hardheader.destination=daddr;
-  
+
   /* load packet into shared memory */
   if (length<=MTU)     /* Normal (256-byte) Packet */
     arcpacket->hardheader.offset1=offset=offset?offset:256-length;
-  
+
   else if (length>=MinTU || offset)    /* Extended (512-byte) Packet */
     {
        arcpacket->hardheader.offset1=0;
-       arcpacket->hardheader.offset2=offset=offset?offset:512-length;   
+       arcpacket->hardheader.offset2=offset=offset?offset:512-length;
     }
   else if (exceptA)            /* RFC1201 Exception Packet */
     {
        arcpacket->hardheader.offset1=0;
        arcpacket->hardheader.offset2=offset=512-length-4;
-       
+
        /* exception-specific stuff - these four bytes
        * make the packet long enough to fit in a 512-byte
        * frame.
        */
-       
+
        arcpacket->raw[offset+0]=hdr[0];
        arcpacket->raw[offset+1]=0xFF; /* FF flag */
        arcpacket->raw[offset+2]=0xFF; /* FF padding */
@@ -1175,13 +1104,12 @@ arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
     {
       /* RFC1051 - set 4 trailing bytes to 0 */
       memset(&arcpacket->raw[508],0,4);
-      
+
       /* now round up to MinTU */
       arcpacket->hardheader.offset1=0;
       arcpacket->hardheader.offset2=offset=512-MinTU;
     }
-  
-  
+
   /* copy the packet into ARCnet shmem
    *  - the first bytes of ClientData header are skipped
    */
@@ -1197,12 +1125,12 @@ arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
 #else
   memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen);
 #endif
-   
+
   BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
         daddr,length);
-  
+
   BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx");
-  
+
   lp->lastload_dest=daddr;
   lp->txready=lp->txbuf;       /* packet is ready for sending */
 }
@@ -1232,12 +1160,12 @@ int init_module(void)
   if (device)
     strcpy(dev->name,device);
   else arcnet_makename(dev->name);
-  
+
   dev->base_addr=io;
-  
+
   dev->irq=irq;
   if (dev->irq==2) dev->irq=9;
-  
+
   if (shmem)
     {
       dev->mem_start=shmem;
@@ -1245,7 +1173,7 @@ int init_module(void)
       dev->rmem_start=thiscard.mem_start+512*0;
       dev->rmem_end=thiscard.mem_start+512*2-1;
     }
-  
+
   if (register_netdev(dev) != 0)
     return -EIO;
   arcnet_use_count(1);
@@ -1254,37 +1182,38 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-       struct device *dev=&thiscard;
-       int ioaddr=dev->mem_start;
+  struct device *dev=&thiscard;
+  int ioaddr=dev->mem_start;
 
-       if (dev->start) (*dev->stop)(dev);
+  if (dev->start) (*dev->stop)(dev);
 
-       /* Flush TX and disable RX */
-       if (ioaddr)
-       {
-               AINTMASK(0);            /* disable IRQ's */
-               ACOMMAND(NOTXcmd);      /* stop transmit */
-               ACOMMAND(NORXcmd);      /* disable receive */
+  /* Flush TX and disable RX */
+  if (ioaddr)
+    {
+      AINTMASK(0);             /* disable IRQ's */
+      ACOMMAND(NOTXcmd);       /* stop transmit */
+      ACOMMAND(NORXcmd);       /* disable receive */
 
 #if defined(IO_MAPPED_BUFFERS) && !defined(COM20020)
-               /* Set the thing back to MMAP mode, in case the old
-                          driver is loaded later */
-               outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
+      /* Set the thing back to MMAP mode, in case the old
+        driver is loaded later */
+      outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
 #endif
-       }
+    }
 
-       if (dev->irq)
-       {
-               irq2dev_map[dev->irq] = NULL;
-               free_irq(dev->irq,NULL);
-       }
+  if (dev->irq)
+    {
+      irq2dev_map[dev->irq] = NULL;
+      free_irq(dev->irq,NULL);
+    }
 
-       if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
-       unregister_netdev(dev);
-       kfree(dev->priv);
-       dev->priv = NULL;
-       arcnet_use_count(0);
+  if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
+  unregister_netdev(dev);
+  kfree(dev->priv);
+  dev->priv = NULL;
+  arcnet_use_count(0);
 }
+
 #else
 
 __initfunc(void com90xx_setup (char *str, int *ints))
@@ -1297,7 +1226,7 @@ __initfunc(void com90xx_setup (char *str, int *ints))
             MAX_ARCNET_DEVS);
       return;
     }
-  
+
   if (!ints[0] && (!str || !*str))
     {
       printk("com90xx: Disabled.\n");
@@ -1306,7 +1235,7 @@ __initfunc(void com90xx_setup (char *str, int *ints))
     }
 
   dev=&arcnet_devs[arcnet_num_devs];
-  
+
   dev->dev_addr[3]=3;
   dev->init=arc90xx_probe;
 
@@ -1320,13 +1249,13 @@ __initfunc(void com90xx_setup (char *str, int *ints))
 
     case 2: /* IRQ */
       dev->irq=ints[2];
-      
+
     case 1: /* IO address */
       dev->base_addr=ints[1];
     }
 
   dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
-  
+
   if (str)
     strncpy(dev->name, str, 9);
 
index 3f4c02ada1724e5d6d9f40059ffad88f2898a98d..ce89c7b4725ba7b40e08acc8c8dc2a67f5103270 100644 (file)
@@ -462,14 +462,17 @@ static void set_rx_mode(struct device *dev);
 /* 'options' is used to pass a transceiver override or full-duplex flag
    e.g. "options=16" for FD, "options=32" for 100mbps-only. */
 static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
 #ifdef MODULE
+
 static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int debug = -1;                 /* The debug level */
-#endif
 
 /* A list of all installed Speedo devices, for removing the driver module. */
 static struct device *root_speedo_dev = NULL;
 
+#endif
+
 int eepro100_init(struct device *dev)
 {
        int cards_found = 0;
index e3615534d866700e6cc6108ace07b600a2460907..740bfc1ffe9e524b78811e56edbb6fd40b9e9ddd 100644 (file)
@@ -521,7 +521,7 @@ ppp_free_buf (struct ppp_buffer *ptr)
 extern inline int
 lock_buffer (register struct ppp_buffer *buf)
 {
-       register int state;
+       register long state;
        int flags;
 /*
  * Save the current state and if free then set it to the "busy" state
@@ -1071,6 +1071,7 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data,
  */
        if (ppp->flags & SC_LOG_RAWIN)
                ppp_print_buffer ("receive buffer", data, count);
+
 /*
  * Collect the character and error condition for the character. Set the toss
  * flag for the first character error.
@@ -1083,6 +1084,7 @@ ppp_tty_receive (struct tty_struct *tty, const __u8 * data,
                                ppp->toss = *flags;
                        ++flags;
                }
+
 /*
  * Set the flags for 8 data bits and no parity.
  *
@@ -1467,6 +1469,7 @@ static void ppp_doframe_lower (struct ppp *ppp, __u8 *data, int count)
 {
        __u16           proto = PPP_PROTOCOL (data);
        ppp_proto_type  *proto_ptr;
+
 /*
  * Ignore empty frames
  */
@@ -1507,6 +1510,7 @@ ppp_doframe (struct ppp *ppp)
        int     addr, ctrl, proto;
        int     new_count;
        __u8 *new_data;
+
 /*
  * If there is a pending error from the receiver then log it and discard
  * the damaged frame.
index 0c62ac56cb2f1b064bd227d7609b34abf1f6c5ba..a0d79086c79b575e5f73713c22b49f6618e8ed74 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/pci/pci.c
+ * $Id: pci.c,v 1.44 1997/09/03 05:08:22 richard Exp $
  *
  * PCI services that are built on top of the BIOS32 service.
  *
@@ -20,7 +20,6 @@
 struct pci_bus pci_root;
 struct pci_dev *pci_devices = 0;
 
-
 /*
  * The bridge_id field is an offset of an item into the array
  * BRIDGE_MAPPING_TYPE. 0xff indicates that the device is not a PCI
@@ -68,6 +67,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( VLSI,           VLSI_82C597,    "82C597-AFC2"),
        DEVICE( VLSI,           VLSI_VAS96011,  "VAS96011 PowerPC"),
        DEVICE( ADL,            ADL_2301,       "2301"),
+       DEVICE( NS,             NS_87415,       "87415"),
        DEVICE( NS,             NS_87410,       "87410"),
        DEVICE( TSENG,          TSENG_W32P_2,   "ET4000W32P"),
        DEVICE( TSENG,          TSENG_W32P_b,   "ET4000W32P rev B"),
@@ -78,8 +78,9 @@ struct pci_dev_info dev_info[] = {
        DEVICE( WEITEK,         WEITEK_P9100,   "P9100"),
        BRIDGE( DEC,            DEC_BRD,        "DC21050",              0x00),
        DEVICE( DEC,            DEC_TULIP,      "DC21040"),
-       DEVICE( DEC,            DEC_TGA,        "DC21030"),
+       DEVICE( DEC,            DEC_TGA,        "TGA"),
        DEVICE( DEC,            DEC_TULIP_FAST, "DC21140"),
+       DEVICE( DEC,            DEC_TGA2,       "TGA2"),
        DEVICE( DEC,            DEC_FDDI,       "DEFPA"),
        DEVICE( DEC,            DEC_TULIP_PLUS, "DC21041"),
        DEVICE( DEC,            DEC_21142,      "DC21142"),
@@ -181,6 +182,9 @@ struct pci_dev_info dev_info[] = {
        DEVICE( OLICOM,         OLICOM_OC2183,  "OC-2183/2185"),
        DEVICE( OLICOM,         OLICOM_OC2326,  "OC-2326"),
        DEVICE( OLICOM,         OLICOM_OC6151,  "OC-6151/6152"),
+       DEVICE( SUN,            SUN_EBUS,       "EBUS"),
+       DEVICE( SUN,            SUN_HAPPYMEAL,  "Happy Meal"),
+       BRIDGE( SUN,            SUN_PBM,        "PCI Bus Module",       0x02),
        DEVICE( CMD,            CMD_640,        "640 (buggy)"),
        DEVICE( CMD,            CMD_643,        "643"),
        DEVICE( CMD,            CMD_646,        "646"),
@@ -596,6 +600,7 @@ const char *pci_strvendor(unsigned int vendor)
              case PCI_VENDOR_ID_CONTAQ:        return "Contaq";
              case PCI_VENDOR_ID_FOREX:         return "Forex";
              case PCI_VENDOR_ID_OLICOM:        return "Olicom";
+             case PCI_VENDOR_ID_SUN:           return "Sun Microsystems";
              case PCI_VENDOR_ID_CMD:           return "CMD";
              case PCI_VENDOR_ID_VISION:        return "Vision";
              case PCI_VENDOR_ID_BROOKTREE:     return "Brooktree";
@@ -668,6 +673,36 @@ const char *pci_strdev(unsigned int vendor, unsigned int device)
 }
 
 
+const char *pcibios_strerror(int error)
+{
+       static char buf[32];
+
+       switch (error) {
+               case PCIBIOS_SUCCESSFUL:
+               case PCIBIOS_BAD_VENDOR_ID:
+                       return "SUCCESSFUL";
+
+               case PCIBIOS_FUNC_NOT_SUPPORTED:
+                       return "FUNC_NOT_SUPPORTED";
+
+               case PCIBIOS_DEVICE_NOT_FOUND:
+                       return "DEVICE_NOT_FOUND";
+
+               case PCIBIOS_BAD_REGISTER_NUMBER:
+                       return "BAD_REGISTER_NUMBER";
+
+                case PCIBIOS_SET_FAILED:          
+                       return "SET_FAILED";
+
+                case PCIBIOS_BUFFER_TOO_SMALL:    
+                       return "BUFFER_TOO_SMALL";
+
+               default:
+                       sprintf (buf, "PCI ERROR 0x%x", error);
+                       return buf;
+       }
+}
+
 
 /*
  * Turn on/off PCI bridge optimization. This should allow benchmarking.
@@ -793,7 +828,7 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
                if (len + 40 > size) {
                        return -1;
                }
-               len += sprintf(buf + len, "IRQ %d.  ", dev->irq);
+               len += sprintf(buf + len, "IRQ %x.  ", dev->irq);
        }
 
        if (dev->master) {
@@ -811,20 +846,24 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
                  len += sprintf(buf + len, "Max Lat=%d.", max_lat);
        }
 
-       for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
+       for (reg = 0; reg < 6; reg++) {
                if (len + 40 > size) {
                        return -1;
                }
-               pcibios_read_config_dword(bus, devfn, reg, &l);
-               base = l;
-               if (!base) {
+               pcibios_read_config_dword(bus, devfn,
+                               PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+               if (l == 0xffffffff)
+                       base = 0;
+               else
+                       base = l;
+               if (!base)
                        continue;
-               }
 
                if (base & PCI_BASE_ADDRESS_SPACE_IO) {
                        len += sprintf(buf + len,
-                                      "\n      I/O at 0x%lx.",
-                                      base & PCI_BASE_ADDRESS_IO_MASK);
+                                      "\n      I/O at 0x%lx [0x%lx].",
+                                      base & PCI_BASE_ADDRESS_IO_MASK,
+                                      dev->base_address[reg]);
                } else {
                        const char *pref, *type = "unknown";
 
@@ -848,8 +887,9 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
                        }
                        len += sprintf(buf + len,
                                       "\n      %srefetchable %s memory at "
-                                      "0x%lx.", pref, type,
-                                      base & PCI_BASE_ADDRESS_MEM_MASK);
+                                      "0x%lx [0x%lx].", pref, type,
+                                      base & PCI_BASE_ADDRESS_MEM_MASK,
+                                      dev->base_address[reg]);
                }
        }
 
@@ -892,7 +932,7 @@ __initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
        void *mem;
 
 #ifdef DEBUG
-       printk("...pci_malloc(size=%ld,mem=%p)", size, *mem_startp);
+       printk("...pci_malloc(size=%ld,mem=%p)", size, (void *)*mem_startp);
 #endif
        mem = (void*) *mem_startp;
        *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
@@ -901,16 +941,18 @@ __initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
 }
 
 
-__initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp))
+unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
 {
        unsigned int devfn, l, max;
-       unsigned char cmd, tmp, hdr_type = 0;
+       unsigned char cmd, tmp, irq, hdr_type = 0;
        struct pci_dev_info *info;
        struct pci_dev *dev;
        struct pci_bus *child;
+       int reg;
 
 #ifdef DEBUG
-       printk("...scan_bus(busno=%d,mem=%p)\n", bus->number, *mem_startp);
+       printk("...pci_scan_bus(busno=%d,mem=%p)\n", bus->number,
+              (void *)*mem_startp);
 #endif
 
        max = bus->secondary;
@@ -952,7 +994,7 @@ __initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_
                 */
                info = pci_lookup_dev(dev->vendor, dev->device);
                if (!info) {
-                       printk("Warning : Unknown PCI device (%x:%x).  Please read include/linux/pci.h \n",
+                       printk("PCI: Warning: Unknown PCI device (%x:%x).  Please read include/linux/pci.h\n",
                                dev->vendor, dev->device);
                } else {
                        /* Some BIOS' are lazy. Let's do their job: */
@@ -975,7 +1017,20 @@ __initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_
 
                /* read irq level (may be changed during pcibios_fixup()): */
                pcibios_read_config_byte(bus->number, devfn,
-                                        PCI_INTERRUPT_LINE, &dev->irq);
+                                        PCI_INTERRUPT_LINE, &irq);
+               dev->irq = irq;
+
+               /* read base address registers, again pcibios_fixup() can
+                * tweak these
+                */
+               for (reg = 0; reg < 6; reg++) {
+                       pcibios_read_config_dword(bus->number, devfn,
+                                       PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+                       if (l == 0xffffffff)
+                               dev->base_address[reg] = 0;
+                       else
+                               dev->base_address[reg] = l;
+               }
 
                /* check to see if this device is a PCI-PCI bridge: */
                pcibios_read_config_dword(bus->number, devfn,
@@ -1033,7 +1088,7 @@ __initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_
                            child->secondary = (buses >> 8) & 0xFF;
                            child->subordinate = (buses >> 16) & 0xFF;
                            child->number = child->secondary;
-                           max = scan_bus(child, mem_startp);
+                           max = pci_scan_bus(child, mem_startp);
                          }
                        else
                          {
@@ -1050,7 +1105,7 @@ __initfunc(static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_
                            /*
                             * Now we can scan all subordinate buses:
                             */
-                           max = scan_bus(child, mem_startp);
+                           max = pci_scan_bus(child, mem_startp);
                            /*
                             * Set the subordinate bus number to its real
                             * value:
@@ -1081,14 +1136,14 @@ __initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_en
        mem_start = pcibios_init(mem_start, mem_end);
 
        if (!pcibios_present()) {
-               printk("pci_init: no PCI BIOS detected\n");
+               printk("PCI: No PCI bus detected\n");
                return mem_start;
        }
 
        printk("Probing PCI hardware.\n");
 
        memset(&pci_root, 0, sizeof(pci_root));
-       pci_root.subordinate = scan_bus(&pci_root, &mem_start);
+       pci_root.subordinate = pci_scan_bus(&pci_root, &mem_start);
 
        /* give BIOS a chance to apply platform specific fixes: */
        mem_start = pcibios_fixup(mem_start, mem_end);
index 8dd59488a5d1d5c6b454bc6e3496401e38085293..86f5270277e7cd862784064295353fd99edfcc23 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.3 1997/09/04 05:50:35 ecd Exp $
+/* $Id: pcikbd.c,v 1.4 1997/09/05 22:59:53 ecd Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -404,51 +404,37 @@ __initfunc(int pcikbd_probe(void))
 {
        struct linux_ebus *ebus;
        struct linux_ebus_device *edev;
-       int node, index, irq;
+       struct linux_ebus_child *child;
 
        for_all_ebusdev(edev, ebus) {
                if(!strcmp(edev->prom_name, "8042")) {
-                       node = prom_getchild(edev->prom_node);
-                       node = prom_searchsiblings(node, "kb_ps2");
-                       if (node == kbd_node)
-                               goto found;
+                       for_each_edevchild(edev, child) {
+                               if (!strcmp(child->prom_name, "kb_ps2"))
+                                       goto found;
+                       }
                }
        }
-       printk("pcikbd_init: no 8042 found\n");
+       printk("pcikbd_probe: no 8042 found\n");
        return -ENODEV;
 
 found:
-       if (prom_getproperty(node, "reg", (char *)&index, sizeof(index)) !=
-                                                       sizeof(index)) {
-               printk("8042: can't get property '%s' from '%s'\n",
-                      "reg", "kb_ps2");
-               return -ENODEV;
-       }
-
-       if (prom_getproperty(node, "interrupts", (char *)&irq, sizeof(irq)) !=
-                                                       sizeof(irq)) {
-               printk("8042: can't get property '%s' from '%s'\n",
-                      "interrupts", "kb_ps2");
-               return -ENODEV;
-       }
-
-       pcikbd_iobase = edev->base_address[index];
+       pcikbd_iobase = child->base_address[0];
        if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
                printk("8042: can't get region %lx, %d\n",
                       pcikbd_iobase, (int)sizeof(unsigned long));
                return -ENODEV;
        }
-
        request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
-       printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, irq);
-       pcikbd_irq = irq;
 
+       pcikbd_irq = child->irqs[0];
        if (request_irq(pcikbd_irq, &pcikbd_interrupt,
                        SA_SHIRQ, "keyboard", NULL)) {
                printk("8042: cannot register IRQ %x\n", pcikbd_irq);
                return -ENODEV;
        }
 
+       printk("8042(kbd): iobase[%016lx] irq[%x]\n", pcikbd_iobase, pcikbd_irq);
+
        /* pcikbd_init(); */
        kbd_read_mask = KBD_STAT_OBF;
        return 0;
@@ -806,36 +792,21 @@ __initfunc(int pcimouse_init(void))
 {
        struct linux_ebus *ebus;
        struct linux_ebus_device *edev;
-       int node, index, irq;
+       struct linux_ebus_child *child;
 
        for_all_ebusdev(edev, ebus) {
                if(!strcmp(edev->prom_name, "8042")) {
-                       node = prom_getchild(edev->prom_node);
-                       node = prom_searchsiblings(node, "kdmouse");
-                       if (node == ms_node)
-                               goto found;
+                       for_each_edevchild(edev, child) {
+                               if (!strcmp(child->prom_name, "kdmouse"))
+                                       goto found;
+                       }
                }
        }
        printk("pcimouse_init: no 8042 found\n");
        return -ENODEV;
 
 found:
-       if (prom_getproperty(node, "reg", (char *)&index, sizeof(index)) !=
-                                                       sizeof(index)) {
-               printk("8042: can't get property '%s' from '%s'\n",
-                      "reg", "kdmouse");
-               return -ENODEV;
-       }
-
-       if (prom_getproperty(node, "interrupts", (char *)&irq, sizeof(irq)) !=
-                                                       sizeof(irq)) {
-               printk("8042: can't get property '%s' from '%s'\n",
-                      "interrupts", "kdmouse");
-               return -ENODEV;
-       }
-
-       pcimouse_iobase = edev->base_address[index];
-
+       pcimouse_iobase = child->base_address[0];
        /*
         * Just in case the iobases for kbd/mouse ever differ...
         */
@@ -843,15 +814,16 @@ found:
                request_region(pcimouse_iobase, sizeof(unsigned long),
                               "8042 controller");
 
-       printk("8042(mouse): iobase[%016lx] irq[%x]\n", pcimouse_iobase, irq);
-       pcimouse_irq = irq;
-
+       pcimouse_irq = child->irqs[0];
        if (request_irq(pcimouse_irq, &pcimouse_interrupt,
                        SA_SHIRQ, "mouse", NULL)) {
                printk("8042: Cannot register IRQ %x\n", pcimouse_irq);
                return -ENODEV;
        }
 
+       printk("8042(mouse): iobase[%016lx] irq[%x]\n",
+              pcimouse_iobase, pcimouse_irq);
+
        printk("8042: PS/2 auxiliary pointing device detected.\n");
        aux_present = 1;
        kbd_read_mask = AUX_STAT_OBF;
@@ -873,7 +845,7 @@ found:
        poll_aux_status();
        outb(KBD_CCMD_WRITE_MODE, pcimouse_iobase + KBD_CNTL_REG);
        poll_aux_status();
-       outb(AUX_INTS_OFF, KBD_DATA_REG);
+       outb(AUX_INTS_OFF, pcimouse_iobase + KBD_DATA_REG);
        poll_aux_status();
        aux_end_atomic();
 
index b479cc9fcecacae112949dc5d77e7faf04f4609c..f1be3e5b4043f988958af8a23f093d3a862634af 100644 (file)
@@ -12,6 +12,7 @@
  * 3) Add tagged queueing.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -34,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/idprom.h>
 
 #define DEBUG_ESP
@@ -642,6 +644,9 @@ static inline void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs
  */
 __initfunc(int esp_detect(Scsi_Host_Template *tpnt))
 {
+#ifdef __sparc_v9__
+       struct devid_cookie dcookie;
+#endif
        struct Sparc_ESP *esp, *elink;
        struct Scsi_Host *esp_host;
        struct linux_sbus *sbus;
@@ -655,8 +660,13 @@ __initfunc(int esp_detect(Scsi_Host_Template *tpnt))
        int esp_node, i;
 
        espchain = 0;
-       if(!SBus_chain)
+       if(!SBus_chain) {
+#ifdef CONFIG_PCI
+               return 0;
+#else
                panic("No SBUS in esp_detect()");
+#endif
+       }
        for_each_sbus(sbus) {
                for_each_sbusdev(sbdev_iter, sbus) {
                        struct linux_sbus_device *espdma = 0;
@@ -782,6 +792,7 @@ __initfunc(int esp_detect(Scsi_Host_Template *tpnt))
                                esp->edev->reg_addrs[0].reg_size;
                        esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri;
 
+#ifndef __sparc_v9__
                        /* Allocate the irq only if necessary */
                        for_each_esp(elink) {
                                if((elink != esp) && (esp->irq == elink->irq)) {
@@ -793,6 +804,22 @@ __initfunc(int esp_detect(Scsi_Host_Template *tpnt))
                                panic("Cannot acquire ESP irq line");
 esp_irq_acquired:
                        printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq);
+#else
+                       /* On Ultra we must always call request_irq for each
+                        * esp, so that imap registers get setup etc.
+                        */
+                       dcookie.real_dev_id = esp;
+                       dcookie.imap = dcookie.iclr = 0;
+                       dcookie.pil = -1;
+                       dcookie.bus_cookie = sbus;
+                       if(request_irq(esp->ehost->irq, esp_intr,
+                                      (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
+                                      "Sparc ESP SCSI", &dcookie))
+                               panic("Cannot acquire ESP irq line");
+                       esp->ehost->irq = esp->irq = dcookie.ret_ino;
+                       printk("esp%d: INO[%x] IRQ %d ",
+                              esp->esp_id, esp->ehost->irq, dcookie.ret_pil);
+#endif
 
                        /* Figure out our scsi ID on the bus */
                        esp->scsi_id = prom_getintdefault(esp->prom_node,
@@ -2323,11 +2350,6 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
                /* Please go to msgout phase, please please please... */
                ESPLOG(("esp%d: !BSERV after data, probably to msgout\n",
                        esp->esp_id));
-#ifdef __SMP__
-               ESPLOG(("esp%d: local_irq_count[%x:%x:%x:%x]\n", esp->esp_id,
-                       local_irq_count[0], local_irq_count[1],
-                       local_irq_count[2], local_irq_count[3]));
-#endif
                return esp_do_phase_determine(esp, eregs, dregs);
        }       
 
@@ -2410,11 +2432,6 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
                ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n",
                        esp->esp_id,
                        SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual));
-#ifdef __SMP__
-               ESPLOG(("esp%d: local_irq_count[%x:%x:%x:%x]\n", esp->esp_id,
-                       local_irq_count[0], local_irq_count[1],
-                       local_irq_count[2], local_irq_count[3]));
-#endif
                bytes_sent = 0;
        }
 
@@ -4021,6 +4038,8 @@ esp_handle_done:
        return;
 }
 
+#ifndef __sparc_v9__
+
 #ifndef __SMP__
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
@@ -4031,14 +4050,7 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 repeat:
        again = 0;
        for_each_esp(esp) {
-               /* XXX Ultra: This is gross, what we really need
-                * XXX is a sbusirq_to_sparc_pil() function, call
-                * XXX that and stick the result in the esp soft
-                * XXX state structure. -DaveM
-                */
-#ifndef __sparc_v9__
                if((esp->irq & 0xf) == irq) {
-#endif
                        if(DMA_IRQ_P(esp->dregs)) {
                                again = 1;
 
@@ -4050,23 +4062,12 @@ repeat:
 
                                DMA_INTSON(esp->dregs);
                        }
-#ifndef __sparc_v9__
                }
-#endif
        }
        if(again)
                goto repeat;
 }
 #else
-
-/* XXX Gross hack for sun4u SMP, fix it right later... -DaveM */
-#ifdef __sparc_v9__
-extern unsigned char ino_to_pil[];
-#define INO_TO_PIL(esp)                (ino_to_pil[(esp)->irq])
-#else
-#define INO_TO_PIL(esp)                ((esp)->irq & 0xf)
-#endif
-
 /* For SMP we only service one ESP on the list list at our IRQ level! */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
@@ -4074,7 +4075,7 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 
        /* Handle all ESP interrupts showing at this IRQ level. */
        for_each_esp(esp) {
-               if(INO_TO_PIL(esp) == irq) {
+               if(((esp)->irq & 0xf) == irq) {
                        if(DMA_IRQ_P(esp->dregs)) {
                                DMA_INTSOFF(esp->dregs);
 
@@ -4090,3 +4091,22 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
        }
 }
 #endif
+
+#else /* __sparc_v9__ */
+
+static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+{
+       struct Sparc_ESP *esp = dev_id;
+
+       if(DMA_IRQ_P(esp->dregs)) {
+               DMA_INTSOFF(esp->dregs);
+
+               ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id));
+               esp_handle(esp);
+               ESPIRQ((")"));
+
+               DMA_INTSON(esp->dregs);
+       }
+}
+
+#endif
index 1e398a15223faa5f8be6e36060a5cb5ce5852aa2..0d65f36a9d3e9e58a31c8559f0302ee08752ecf1 100644 (file)
@@ -736,4 +736,11 @@ Scsi_Host_Template driver_template = GENERIC_NCR5380;
 
 #include <linux/module.h>
 #include "scsi_module.c"
+
+MODULE_PARM(ncr_irq, "i");
+MODULE_PARM(ncr_dma, "i");
+MODULE_PARM(ncr_addr, "i");
+MODULE_PARM(ncr_5380, "i");
+MODULE_PARM(ncr_53c400, "i");
+
 #endif
index 66c1f643f8b36200e43ac8a4e3c4e9232773658a..501aff777558c5aac1ed224729e3d8a67c698102 100644 (file)
@@ -7,9 +7,7 @@
  * Paul Mackerras, August 1996.
  * Copyright (C) 1996 Paul Mackerras.
  */
-
 #include <linux/config.h>
-
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
index b8620dfdc22ca865bee00ebfec07be98e0955815..ab6c12f5ca3c8c35a8302683eeb82b09c0f9f8b2 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/oplib.h>
 #include <asm/vaddrs.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 
 #include <linux/module.h>
 
@@ -351,7 +352,7 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
        unsigned short csum = 0;
        unsigned short param[6];
        unsigned long flags;
-#ifndef MODULE
+#if !defined(MODULE) && !defined(__sparc_v9__)
        unsigned long dvma_addr;
 #endif
        int i, timeout;
@@ -419,8 +420,7 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
        }               
 
        /* Load the firmware. */
-#ifndef MODULE
-       /* XXX THIS SHIT DOES NOT WORK ON ULTRA... FIXME -DaveM */
+#if !defined(MODULE) && !defined(__sparc_v9__)
        dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code01[0],
                                                 (sizeof(u_short) * risc_code_length01));
        param[0] = MBOX_LOAD_RAM;
@@ -435,9 +435,9 @@ __initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
                restore_flags(flags);
                return 1;
        }
-       /* XXX THIS SHIT DOES NOT WORK ON ULTRA... FIXME -DaveM */
        mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length01));
 #else
+       /* We need to do it this slow way always on Ultra. */
        for(i = 0; i < risc_code_length01; i++) {
                param[0] = MBOX_WRITE_RAM_WORD;
                param[1] = risc_code_addr01 + i;
@@ -566,6 +566,9 @@ static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
 /* Detect all PTI Qlogic ISP's in the machine. */
 __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
 {
+#ifdef __sparc_v9__
+       struct devid_cookie dcookie;
+#endif
        struct qlogicpti *qpti, *qlink;
        struct Scsi_Host *qpti_host;
        struct linux_sbus *sbus;
@@ -643,7 +646,7 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
                                /* Map this one read only. */
                                qpti->sreg = sreg = (volatile unsigned char *)
                                        sparc_alloc_io((qpti->qdev->reg_addrs[0].phys_addr +
-                                                      (16 * PAGE_SIZE)), 0,
+                                                      (16 * 4096)), 0,
                                                       sizeof(unsigned char),
                                                       "PTI Qlogic/ISP Status Reg",
                                                       qpti->qdev->reg_addrs[0].which_io, 1);
@@ -659,6 +662,7 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
 
                        qpti_host->irq = qpti->irq = qpti->qdev->irqs[0].pri;
 
+#ifndef __sparc_v9__
                        /* Allocate the irq only if necessary. */
                        for_each_qlogicpti(qlink) {
                                if((qlink != qpti) && (qpti->irq == qlink->irq)) {
@@ -673,6 +677,25 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
                        }
 qpti_irq_acquired:
                        printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->qhost->irq);
+#else
+                       /* On Ultra we must always call request_irq for each
+                        * qpti, so that imap registers get setup etc.
+                        */
+                       dcookie.real_dev_id = qpti;
+                       dcookie.imap = dcookie.iclr = 0;
+                       dcookie.pil = -1;
+                       dcookie.bus_cookie = sbus;
+                       if(request_irq(qpti->qhost->irq, qlogicpti_intr_handler,
+                                      (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
+                                      "PTI Qlogic/ISP SCSI", &dcookie)) {
+                               printk("Cannot acquire PTI Qlogic/ISP irq line\n");
+                               /* XXX Unmap regs, unregister scsi host, free things. */
+                               continue;
+                       }
+                       qpti->qhost->irq = qpti->irq = dcookie.ret_ino;
+                       printk("qpti%d: INO[%x] IRQ %d ",
+                              qpti->qpti_id, qpti->qhost->irq, dcookie.ret_pil);
+#endif
 
                        /* Figure out our scsi ID on the bus */
                        qpti->scsi_id = prom_getintdefault(qpti->prom_node,
@@ -805,7 +828,11 @@ static inline void cmd_frob(struct Command_Entry *cmd, Scsi_Cmnd *Cmnd,
        memset(cmd, 0, sizeof(struct Command_Entry));
        cmd->hdr.entry_cnt = 1;
        cmd->hdr.entry_type = ENTRY_COMMAND;
-       cmd->handle = (u_int) ((unsigned long)Cmnd);          /* magic mushroom */
+#ifdef __sparc_v9__
+       cmd->handle = (u_int) (((unsigned long)Cmnd) - PAGE_OFFSET); /* magic mushroom */
+#else
+       cmd->handle = (u_int) ((unsigned long)Cmnd);                 /* magic mushroom */
+#endif
        cmd->target_id = Cmnd->target;
        cmd->target_lun = Cmnd->lun;
        cmd->cdb_length = Cmnd->cmd_len;
@@ -1013,6 +1040,8 @@ static int qlogicpti_return_status(struct Status_Entry *sts)
        return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
 }
 
+#ifndef __sparc_v9__
+
 static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
        static int running = 0;
@@ -1099,6 +1128,76 @@ repeat:
        running--;
 }
 
+#else /* __sparc_v9__ */
+
+static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct qlogicpti *qpti = dev_id;
+       Scsi_Cmnd *Cmnd;
+       struct Status_Entry *sts;
+       u_int in_ptr, out_ptr;
+
+       if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) {
+               struct qlogicpti_regs *qregs = qpti->qregs;
+
+               in_ptr = qregs->mbox5;
+               qregs->hcctrl = HCCTRL_CRIRQ;
+               if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
+                       switch(qregs->mbox0) {
+                       case ASYNC_SCSI_BUS_RESET:
+                       case EXECUTION_TIMEOUT_RESET:
+                               qpti->send_marker = 1;
+                               break;
+                       case INVALID_COMMAND:
+                       case HOST_INTERFACE_ERROR:
+                       case COMMAND_ERROR:
+                       case COMMAND_PARAM_ERROR:
+                               break;
+                       }
+                       qregs->sbus_semaphore = 0;
+               }
+
+               /* This looks like a network driver! */
+               out_ptr = qpti->res_out_ptr;
+               while(out_ptr != in_ptr) {
+                       sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
+                       out_ptr = NEXT_RES_PTR(out_ptr);
+                       Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
+
+                       if(sts->completion_status == CS_RESET_OCCURRED ||
+                          sts->completion_status == CS_ABORTED ||
+                          (sts->status_flags & STF_BUS_RESET))
+                               qpti->send_marker = 1;
+
+                       if(sts->state_flags & SF_GOT_SENSE)
+                               memcpy(Cmnd->sense_buffer, sts->req_sense_data,
+                                      sizeof(Cmnd->sense_buffer));
+
+                       if(sts->hdr.entry_type == ENTRY_STATUS)
+                               Cmnd->result = qlogicpti_return_status(sts);
+                       else
+                               Cmnd->result = DID_ERROR << 16;
+
+                       if(Cmnd->use_sg)
+                               mmu_release_scsi_sgl((struct mmu_sglist *)
+                                                    Cmnd->buffer,
+                                                    Cmnd->use_sg - 1,
+                                                    qpti->qdev->my_bus);
+                       else
+                               mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
+                                                    Cmnd->request_bufflen,
+                                                    qpti->qdev->my_bus);
+
+                       qpti->cmd_count[Cmnd->target]--;
+                       qregs->mbox5 = out_ptr;
+                       Cmnd->scsi_done(Cmnd);
+               }
+               qpti->res_out_ptr = out_ptr;
+       }
+}
+
+#endif
+
 int qlogicpti_abort(Scsi_Cmnd *Cmnd)
 {
        u_short param[6];
index 023a1c4489123adb51847d727d09040bd4d124c9..6404809ccc21b8afab6f6e1b80de3a48112bac2a 100644 (file)
@@ -37,6 +37,7 @@
 #endif
 
 #define MAX_SCSI_DEVICE_CODE 10
+extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
 
 extern void scsi_make_blocked_list(void);
 extern volatile int in_scan_scsis;
index 17469967f5988365030b769331dcb3ac59355b5a..bf82a51cbf2f5f74c6c15f9b85c0dc2e87db0c12 100644 (file)
@@ -72,5 +72,7 @@ EXPORT_SYMBOL(scsi_hostlist);
 EXPORT_SYMBOL(scsi_hosts);
 EXPORT_SYMBOL(scsi_devicelist);
 EXPORT_SYMBOL(scsi_devices);
+EXPORT_SYMBOL(scsi_device_types);
+
 
 #endif /* CONFIG_MODULES */
index c5715819567f093d1bda327d6e6d3ae71634b9b8..f827bdae6a6866b2cf8a43ab164270471ee1b5f3 100644 (file)
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/wait.h>
-
-#define kver(a,b,c) (((a) << 16) + ((b) << 8) + (c)) 
-
-#if LINUX_VERSION_CODE < kver(2,1,0)
-
-/* Segmentation stuff for pre-2.1 kernels */
-#include <asm/segment.h>
-
-static inline int copy_to_user(void *dst, void *src, unsigned long len)
-{
-       int rv = verify_area(VERIFY_WRITE, dst, len);
-       if ( rv )
-               return -1;
-       memcpy_tofs(dst,src,len);
-       return 0;
-}
-
-static inline int copy_from_user(void *dst, void *src, unsigned long len)
-{
-       int rv = verify_area(VERIFY_READ, src, len);
-       if ( rv )
-               return -1;
-       memcpy_fromfs(dst,src,len);
-       return 0;
-}
-
-#else
-
-/* Segmentation stuff for post-2.1 kernels */
 #include <asm/uaccess.h>
-#define register_symtab(x)     ((void)0)
-
-#endif
 
 #ifdef DEBUG
 #define DPRINTK(D) (printk D)
@@ -65,9 +33,15 @@ static inline int copy_from_user(void *dst, void *src, unsigned long len)
 
 #define AUTOFS_SUPER_MAGIC 0x0187
 
-#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ)        /* Time before asking the daemon again */
+/*
+ * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
+ * kernel will keep the negative response cached for up to the time given
+ * here, although the time can be shorter if the kernel throws the dcache
+ * entry away.  This probably should be settable from user space.
+ */
+#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ)        /* 1 minute */
 
-/* Structures associated with the root directory hash */
+/* Structures associated with the root directory hash table */
 
 #define AUTOFS_HASH_SIZE 67
 
@@ -135,20 +109,14 @@ struct autofs_sb_info {
        u32 symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
 };
 
-/* autofs_oz_mode(): do we see the man behind the curtain? */
+/* autofs_oz_mode(): do we see the man behind the curtain?  (The
+   processes which do manipulations for us in user space sees the raw
+   filesystem without "magic".) */
+
 static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
        return sbi->catatonic || current->pgrp == sbi->oz_pgrp;
 }
 
-/* Debug the mysteriously disappearing wait list */
-
-#ifdef DEBUG_WAITLIST
-#define CHECK_WAITLIST(S,O) autofs_check_waitlist_integrity(S,O)
-void autofs_check_waitlist_integrity(struct autofs_sb_info *,char *);
-#else
-#define CHECK_WAITLIST(S,O)
-#endif
-
 /* Hash operations */
 
 void autofs_initialize_hash(struct autofs_dirhash *);
@@ -182,5 +150,5 @@ void autofs_catatonic_mode(struct autofs_sb_info *);
 #ifdef DEBUG
 void autofs_say(const char *name, int len);
 #else
-#define autofs_say(n,l)
+#define autofs_say(n,l) ((void)0)
 #endif
index ed4401ce5f824c46a212b1f5fe48ce1cbea2bee2..7c0508267db029c1dd9a887be619a1c96ab53add 100644 (file)
  * ------------------------------------------------------------------------- */
 
 #include <linux/module.h>
-#include "autofs_i.h"
-
-#if LINUX_VERSION_CODE < kver(2,1,36)
-#define __initfunc(X) X
-#else
 #include <linux/init.h>
-#endif
+#include "autofs_i.h"
 
 static struct file_system_type autofs_fs_type = {
        "autofs",
-       0 /* FS_NO_DCACHE doesn't work correctly */,
+       0,
        autofs_read_super,
        NULL
 };
@@ -29,11 +24,7 @@ static struct file_system_type autofs_fs_type = {
 #ifdef MODULE
 int init_module(void)
 {
-       int status;
-       
-       if ((status = register_filesystem(&autofs_fs_type)) == 0)
-               register_symtab(0);
-       return status;
+       return register_filesystem(&autofs_fs_type);
 }
 
 void cleanup_module(void)
index 387874234ccfbae6ddb0bb854e888240c904ad1f..91f9f1cbe268b5dcba34f33c01ab5f7b1a350c73 100644 (file)
@@ -394,16 +394,9 @@ static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
        int rv;
        unsigned long ntimeout;
 
-#if LINUX_VERSION_CODE < kver(2,1,0)
-       if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(unsigned long))) )
-               return rv;
-       ntimeout = get_user(p);
-       put_user(sbi->exp_timeout/HZ, p);
-#else
        if ( (rv = get_user(ntimeout, p)) ||
             (rv = put_user(sbi->exp_timeout/HZ, p)) )
                return rv;
-#endif
 
        if ( ntimeout > ULONG_MAX/HZ )
                sbi->exp_timeout = 0;
@@ -416,15 +409,7 @@ static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
 /* Return protocol version */
 static inline int autofs_get_protover(int *p)
 {
-#if LINUX_VERSION_CODE < kver(2,1,0)
-       int rv;
-       if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(int))) )
-               return rv;
-       put_user(AUTOFS_PROTO_VERSION, p);
-       return 0;
-#else
        return put_user(AUTOFS_PROTO_VERSION, p);
-#endif
 }
 
 /* Perform an expiry operation */
index 39beed699f5993217bed1d59f96fcb9d9044a50e..e56825d5e59dda8f1c0bb734c2136eee539bb4ae 100644 (file)
@@ -42,7 +42,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
 
 static int autofs_write(struct file *file, const void *addr, int bytes)
 {
-       unsigned short fs;
+       unsigned long fs;
        unsigned long old_signal;
        const char *data = (const char *)addr;
        int written = 0;
index 29956eddab1a44af799dcd4cd6fd4b5b1c76fc17..0ff5b7ff6034bb8d80ea05b81d0daddf5cdf943b 100644 (file)
@@ -82,7 +82,7 @@ do_aout_core_dump(long signr, struct pt_regs * regs)
        struct dentry * dentry = NULL;
        struct inode * inode = NULL;
        struct file file;
-       unsigned short fs;
+       unsigned long fs;
        int has_dumped = 0;
        char corefile[6+sizeof(current->comm)];
        unsigned long dump_start, dump_size;
index a830ccf804ae08aad3b5c87daaefa17972f8dd2b..8fad7f72b16684f9b2c54dae3fd9bfca666f6618 100644 (file)
@@ -391,14 +391,14 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        struct elfhdr interp_elf_ex;
        struct file * file;
        struct exec interp_ex;
-       struct dentry *interpreter_dentry;
-       unsigned long load_addr;
+       struct dentry *interpreter_dentry = NULL; /* to shut gcc up */
+       unsigned long load_addr, load_bias;
        int load_addr_set = 0;
        unsigned int interpreter_type = INTERPRETER_NONE;
        unsigned char ibcs2_interpreter;
        int i;
-       int old_fs;
-       int error;
+       unsigned long old_fs;
+       unsigned long error;
        struct elf_phdr * elf_ppnt, *elf_phdata;
        int elf_exec_fileno;
        unsigned long elf_bss, k, elf_brk;
@@ -503,7 +503,16 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        if (retval >= 0) {
                                old_fs = get_fs(); /* This could probably be optimized */
                                set_fs(get_ds());
-                               interpreter_dentry = open_namei(elf_interpreter, 0, 0);
+#ifdef __sparc__
+                               if (ibcs2_interpreter) {
+                                       unsigned long old_pers = current->personality;
+                                       
+                                       current->personality = PER_SVR4;
+                                       interpreter_dentry = open_namei(elf_interpreter, 0, 0);
+                                       current->personality = old_pers;
+                               } else
+#endif                                 
+                                       interpreter_dentry = open_namei(elf_interpreter, 0, 0);
                                set_fs(old_fs);
                                if (IS_ERR(interpreter_dentry))
                                        retval = PTR_ERR(interpreter_dentry);
@@ -593,6 +602,12 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        bprm->p = setup_arg_pages(bprm->p, bprm);
        current->mm->start_stack = bprm->p;
 
+       /* Try and get dynamic programs out of the way of the default mmap
+          base, as well as whatever program they might try to exec.  This
+          is because the brk will follow the loader, and is not movable.  */
+
+       load_bias = (elf_ex.e_type == ET_DYN ? ELF_ET_DYN_BASE : 0);
+
        /* Now we do a little grungy work by mmaping the ELF image into
           the correct location in memory.  At this point, we assume that
           the image should be loaded at fixed address, not at a variable
@@ -602,39 +617,47 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        set_fs(get_ds());
        for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
                if (elf_ppnt->p_type == PT_LOAD) {
-                       int elf_prot = 0;
+                       int elf_prot = 0, elf_flags;
+                       unsigned long vaddr = 0;
+
                        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
                        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
                        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 
+                       elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
+
+                       if (elf_ex.e_type == ET_EXEC || load_addr_set) {
+                               vaddr = elf_ppnt->p_vaddr;
+                               elf_flags |= MAP_FIXED;
+                       }
+
                        error = do_mmap(file,
-                                       ELF_PAGESTART(elf_ppnt->p_vaddr),
+                                       ELF_PAGESTART(load_bias + vaddr),
                                        (elf_ppnt->p_filesz +
                                         ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-                                       elf_prot,
-                                       (MAP_FIXED | MAP_PRIVATE |
-                                        MAP_DENYWRITE | MAP_EXECUTABLE),
+                                       elf_prot, elf_flags,
                                        (elf_ppnt->p_offset -
                                         ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
 
 #ifdef LOW_ELF_STACK
-                       if (ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
-                               elf_stack = ELF_PAGESTART(elf_ppnt->p_vaddr);
+                       if (error < elf_stack)
+                               elf_stack = error-1;
 #endif
 
                        if (!load_addr_set) {
-                         load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
-                         load_addr_set = 1;
+                               load_addr_set = 1;
+                               load_addr = (elf_ppnt->p_vaddr -
+                                            elf_ppnt->p_offset);
+                               if (elf_ex.e_type == ET_DYN) {
+                                       load_bias = error;
+                                       load_addr += error;
+                               }
                        }
                        k = elf_ppnt->p_vaddr;
                        if (k < start_code) start_code = k;
                        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
                        if (k > elf_bss) elf_bss = k;
-#if 1
                        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
-#else
-                       if ( !(elf_ppnt->p_flags & PF_W) && end_code <  k)
-#endif
                                end_code = k;
                        if (end_data < k) end_data = k;
                        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
@@ -643,6 +666,13 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        }
        set_fs(old_fs);
 
+       elf_entry += load_bias;
+       elf_bss += load_bias;
+       elf_brk += load_bias;
+       start_code += load_bias;
+       end_code += load_bias;
+       end_data += load_bias;
+
        if (elf_interpreter) {
                if (interpreter_type & 1)
                        elf_entry = load_aout_interp(&interp_ex,
@@ -683,7 +713,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        current->executable = dget(bprm->dentry);
 #endif
 #ifdef LOW_ELF_STACK
-       current->start_stack = bprm->p = elf_stack - 4;
+       current->start_stack = bprm->p = elf_stack;
 #endif
        current->suid = current->euid = current->fsuid = bprm->e_uid;
        current->sgid = current->egid = current->fsgid = bprm->e_gid;
@@ -1011,7 +1041,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
        struct file file;
        struct dentry *dentry;
        struct inode *inode;
-       unsigned short fs;
+       unsigned long fs;
        char corefile[6+sizeof(current->comm)];
        int segs;
        int i;
index 2914bcaa8327219117842f48d3021ecf9edb7217..afc24db1e71a12e473b088bab52d9fc8c2634761 100644 (file)
@@ -360,8 +360,6 @@ void d_add(struct dentry * entry, struct inode * inode)
  */
 void d_move(struct dentry * dentry, struct dentry * target)
 {
-       struct list_head * oldhead;
-
        if (!dentry->d_inode)
                printk("VFS: moving negative dcache entry\n");
 
index 55ba90afffd0e4d655a9dd794d20c8f8020abed9..8c59c896e5fd0d7e41a0ad3a682db2340b029931 100644 (file)
@@ -563,23 +563,6 @@ void inode_init(void)
        } while (i);
 }
 
-/*
- * Check whether we can mount.
- */
-int fs_may_mount(kdev_t dev)
-{
-       return 1;
-}
-
-/*
- * Check whether we can unmount.
- */
-int fs_may_umount(struct super_block *sb, struct dentry * root)
-{
-       shrink_dcache();
-       return root->d_count == 1;
-}
-
 /* This belongs in file_table.c, not here... */
 int fs_may_remount_ro(struct super_block *sb)
 {
index 04ee04bb146bdc30640bb7db77fd80fb20f4c9b2..e91b34a342626f60af70addda070fec3cc953860 100644 (file)
@@ -81,6 +81,7 @@ static void
 nfs_delete_inode(struct inode * inode)
 {
        dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);
+       clear_inode(inode);
 }
 
 void
index 02ba4457b89a202ddb499de4786db34c06d12c61..485049b6918c03bca886ce8526c55a6313b6463e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: openpromfs.c,v 1.18 1997/07/17 02:24:01 davem Exp $
+/* $Id: openpromfs.c,v 1.21 1997/08/19 02:05:48 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
index dac962324f052e1fcb672fd63fb62d684a04dcbe..bccf1b2b4ef350af1456c013ac3ba7e2265ba1f6 100644 (file)
@@ -551,8 +551,12 @@ static struct proc_dir_entry proc_root_omirr = {
 #ifdef __powerpc__
 static struct proc_dir_entry proc_root_ppc_htab = {
        PROC_PPC_HTAB, 8, "ppc_htab",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_ppc_htab_inode_operations
+       S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
+       0, &proc_ppc_htab_inode_operations,
+       NULL, NULL,                             /* get_info, fill_inode */
+       NULL,                                   /* next */
+       NULL, NULL                              /* parent, subdir */
+
 };
 #endif
 
index f38a07864c393ff79aef1c86eebca03d4dabf468..39513df4bc620350a0a9ca5e9e5ccd3d936a221b 100644 (file)
@@ -726,6 +726,19 @@ asmlinkage int sys_umount(char * name)
        return retval;
 }
 
+/*
+ * Check whether we can mount the specified device.
+ */
+int fs_may_mount(kdev_t dev)
+{
+       struct super_block * sb = get_super(dev);
+       int busy;
+
+       busy = sb && sb->s_root &&
+              (sb->s_root->d_count != 1 || sb->s_root->d_covers != sb->s_root);
+       return !busy;
+}
+
 /*
  * do_mount() does the actual mounting after sys_mount has done the ugly
  * parameter parsing. When enough time has gone by, and everything uses the
@@ -754,43 +767,56 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name, const cha
        struct vfsmount *vfsmnt;
        int error;
 
+       error = -EACCES;
        if (!(flags & MS_RDONLY) && dev && is_read_only(dev))
-               return -EACCES;
+               goto out;
                /*flags |= MS_RDONLY;*/
 
        dir_d = namei(dir_name);
        error = PTR_ERR(dir_d);
        if (IS_ERR(dir_d))
-               return error;
+               goto out;
 
-       if (dir_d->d_covers != dir_d) {
-               dput(dir_d);
-               return -EBUSY;
-       }
-       if (!S_ISDIR(dir_d->d_inode->i_mode)) {
-               dput(dir_d);
-               return -ENOTDIR;
-       }
-       if (!fs_may_mount(dev)) {
-               dput(dir_d);
-               return -EBUSY;
-       }
-       sb = read_super(dev,type,flags,data,0);
-       if (!sb) {
-               dput(dir_d);
-               return -EINVAL;
-       }
-       if (sb->s_root->d_covers != sb->s_root) {
-               dput(dir_d);
-               return -EBUSY;
+       error = -ENOTDIR;
+       if (!S_ISDIR(dir_d->d_inode->i_mode))
+               goto dput_and_out;
+
+       error = -EBUSY;
+       if (dir_d->d_covers != dir_d)
+               goto dput_and_out;
+
+       /*
+        * Check whether to read the super block
+        */
+       sb = get_super(dev);
+       if (!sb || !sb->s_root) {
+               error = -EINVAL;
+               sb = read_super(dev,type,flags,data,0);
+               if (!sb)
+                       goto dput_and_out;
        }
+
+       /*
+        * We may have slept while reading the super block, 
+        * so we check afterwards whether it's safe to mount.
+        */
+       error = -EBUSY;
+       if (!fs_may_mount(dev))
+               goto dput_and_out;
+
+       error = -ENOMEM;
        vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
        if (vfsmnt) {
                vfsmnt->mnt_sb = sb;
                vfsmnt->mnt_flags = flags;
+               d_mount(dir_d, sb->s_root);
+               return 0;               /* we don't dput(dir) - see umount */
        }
-       d_mount(dir_d, sb->s_root);
-       return 0;               /* we don't dput(dir) - see umount */
+
+dput_and_out:
+       dput(dir_d);
+out:
+       return error;   
 }
 
 
index 0cf5ecbecb449992f3e0a35629838d3e10bc2b4a..bca9bbfea8902bc4569d61af1c17075313bdd352 100644 (file)
@@ -34,6 +34,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      8192
 
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE                (2 * TASK_SIZE / 3)
+
 /* $0 is set by ld.so to a pointer to a function which might be 
    registered using atexit.  This provides a mean for the dynamic
    linker to call DT_FINI functions for shared libraries that have
index b9471de7bdc08a104803044fbcce6245cdc037e6..9be100c4fb4c75d4c51ce52b1a527c84ef992f51 100644 (file)
@@ -48,6 +48,8 @@ static int FDC2 = -1;
 #define N_FDC 2
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * Most Alphas have no problems with floppy DMA crossing 64k borders. Sigh...
  */
index 7d80c32f82b8c6ad7b015b534c7ffd91e9ced21c..fdb1e4d0ba39e867c3c207ce0ce06ce6b2691e4b 100644 (file)
@@ -18,6 +18,7 @@
 #define flush_cache_range(mm, start, end)      do { } while (0)
 #define flush_cache_page(vma, vmaddr)          do { } while (0)
 #define flush_page_to_ram(page)                        do { } while (0)
+#define flush_icache_range(start, end)         do { } while (0)
 
 /*
  * Force a context reload. This is needed when we
index 870fd290c4d9460ad0c5c7c762fec9d8daf5cbaa..a76b1fc38617e2a669e6f538726bd6cefa0fe4c7 100644 (file)
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  * get_fs() == KERNEL_DS, checking is bypassed.
  *
+ * Or at least it did once upon a time.  Nowadays it is a mask that
+ * defines which bits of the address space are off limits.  This is a
+ * wee bit faster than the above.
+ *
  * For historical reasons, these macros are grossly misnamed.
  */
 
 #define VERIFY_WRITE   1
 
 #define get_fs()  (current->tss.fs)
-#define set_fs(x) (current->tss.fs = (x))
 #define get_ds()  (KERNEL_DS)
 
+/* Our scheme relies on all bits being preserved.  Trap those evil 
+   Intellists in their plot to use unsigned short.  */
+
+extern unsigned long __bad_fs_size(void);
+
+#define set_fs(x) (current->tss.fs =                           \
+                  sizeof(x) == sizeof(unsigned long) ? (x)     \
+                  : __bad_fs_size())
+
 /*
  * Is a address valid? This does a straighforward calculation rather
  * than tests.
index a19ff035e6cbe03f0080406bed0842b6b2684570..843ca3015906fc7b346b7b1665715c38fe9cf545 100644 (file)
 
 #define CONFIG_BUGi386
 
-static void no_halt(char *s, int *ints)
+__initfunc(static void no_halt(char *s, int *ints))
 {
        hlt_works_ok = 0;
 }
 
-static void no_387(char *s, int *ints)
+__initfunc(static void no_387(char *s, int *ints))
 {
        hard_math = 0;
        __asm__("movl %%cr0,%%eax\n\t"
@@ -28,9 +28,9 @@ static void no_387(char *s, int *ints)
                "movl %%eax,%%cr0\n\t" : : : "ax");
 }
 
-static char fpu_error = 0;
+static char __initdata fpu_error = 0;
 
-static void copro_timeout(void)
+__initfunc(static void copro_timeout(void))
 {
        fpu_error = 1;
        timer_table[COPRO_TIMER].expires = jiffies+100;
@@ -41,7 +41,7 @@ static void copro_timeout(void)
        outb_p(0,0xf0);
 }
 
-static void check_fpu(void)
+__initfunc(static void check_fpu(void))
 {
        static double x = 4195835.0;
        static double y = 3145727.0;
@@ -99,7 +99,7 @@ static void check_fpu(void)
        printk("Hmm, FDIV bug i%c86 system\n", '0'+x86);
 }
 
-static void check_hlt(void)
+__initfunc(static void check_hlt(void))
 {
        printk(KERN_INFO "Checking 'hlt' instruction... ");
        if (!hlt_works_ok) {
@@ -110,7 +110,7 @@ static void check_hlt(void)
        printk("Ok.\n");
 }
 
-static void check_tlb(void)
+__initfunc(static void check_tlb(void))
 {
 #ifndef CONFIG_M386
        /*
@@ -125,7 +125,7 @@ static void check_tlb(void)
 #endif
 }
 
-static void check_bugs(void)
+__initfunc(static void check_bugs(void))
 {
        check_tlb();
        check_fpu();
index 71009ec5c3b32f7a644cdb470c4bfec388f188f9..46a4a7ada116db6bab857299ce6d643bb2352244 100644 (file)
@@ -27,18 +27,24 @@ typedef struct user_i387_struct elf_fpregset_t;
 #define ELF_DATA       ELFDATA2LSB;
 #define ELF_ARCH       EM_386
 
-       /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
-          starts %edx contains a pointer to a function which might be
-          registered using `atexit'.  This provides a mean for the
-          dynamic linker to call DT_FINI functions for shared libraries
-          that have been loaded before the code runs.
+/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
+   contains a pointer to a function which might be registered using `atexit'.
+   This provides a mean for the dynamic linker to call DT_FINI functions for
+   shared libraries that have been loaded before the code runs.
 
-          A value of 0 tells we have no such handler.  */
+   A value of 0 tells we have no such handler.  */
 #define ELF_PLAT_INIT(_r)      _r->edx = 0
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE      4096
 
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+
 /* Wow, the "main" arch needs arch dependent functions too.. :) */
 
 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
index 17f0b333d636f63434bb9bef6d043abffc27c790..210d947c937a44d2ae4a8e325592f0cbf419a755 100644 (file)
@@ -283,6 +283,8 @@ static int FDC2 = -1;
 #define N_FDC 2
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * The DMA channel used by the floppy controller cannot access data at
  * addresses >= 16MB
index c3a587d004daefe903582044c950273f23a42192..9274056f84d25a13aa47095986eda9074533c6ab 100644 (file)
@@ -19,6 +19,7 @@
 #define flush_cache_range(mm, start, end)      do { } while (0)
 #define flush_cache_page(vma, vmaddr)          do { } while (0)
 #define flush_page_to_ram(page)                        do { } while (0)
+#define flush_icache_range(start, end)         do { } while (0)
 
 /*
  * TLB flushing:
index d8b03e17c177a861bfb000c27c7371b371d90287..84bb65f76761dd9860857568d4cd2d90fcef9d11 100644 (file)
  * For historical reasons, these macros are grossly misnamed.
  */
 
+extern unsigned long __bad_fs_size(void);
+
 #define get_fs()       (current->tss.segment)
-#define set_fs(x)      (current->tss.segment = (x))
 #define get_ds()       (KERNEL_DS)
 
+/* Some architectures -- Alpha for one -- use "segment" schemes that 
+   require all bits to be preserved, thus the i386 traditional `ushort'
+   doesn't work.  To head off problems early, force the Intel folks
+   to do it Right as well.  */
+
+#define set_fs(x)      (current->tss.segment =                         \
+                        sizeof(x) == sizeof(unsigned long) ? (x)       \
+                        : __bad_fs_size())
+
 /*
  * Address Ok:
  *
index 4409b538ec2d406ed976b515ba303d0b843395c4..fae533466685ccc36b5c247331cfd20ab9302962 100644 (file)
@@ -95,6 +95,8 @@ static int FDC2=-1;
 #define N_FDC 1                        /* do you *really* want a second controller? */
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * The DMA channel used by the floppy controller cannot access data at
  * addresses >= 16MB
index 677a66118b5d0473788017132743c4f89900bcda..56dd5c6906de2eb44c5607fe20940675f5a87e48 100644 (file)
@@ -25,7 +25,16 @@ __mips_lookup_dentry(const char *name, int follow_link)
                        
        if (IS_ERR (base)) return base;
        
-       return lookup_dentry (name, base, follow_link);
+       base = lookup_dentry (name, base, follow_link);
+
+       if (IS_ERR (base)) return base;
+
+       if (!base->d_inode) {
+               dput(base);
+               return ERR_PTR(-ENOENT);
+       }
+        
+        return base;
 }
 
 #ifdef CONFIG_BINFMT_IRIX
index 342379294ee2987f65221728df980a97f8cafab2..f12eae65fb1a1238044c33851dfe9924f013826b 100644 (file)
@@ -46,6 +46,8 @@ static int FDC2 = -1;
 #define N_FDC 2                        /* Don't change this! */
 #define N_DRIVE 8
 
+#define FLOPPY_MOTOR_MASK 0xf0
+
 /*
  * The PowerPC has no problems with floppy DMA crossing 64k borders.
  */
index 9a2fe562342cb4068287d1bf4733fb594665e999..d8f559440f2da8e2fdc627b8ed125cb176758688 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.7 1997/08/29 15:52:27 jj Exp $
+/* $Id: namei.h,v 1.8 1997/09/05 12:38:51 jj Exp $
  * linux/include/asm-sparc/namei.h
  *
  * Routines to handle famous /usr/gnemul/s*.
@@ -31,7 +31,16 @@ __sparc_lookup_dentry(const char *name, int follow_link)
                        
        if (IS_ERR (base)) return base;
        
-       return lookup_dentry (name, base, follow_link);
+       base = lookup_dentry (name, base, follow_link);
+
+       if (IS_ERR (base)) return base;
+
+       if (!base->d_inode) {
+               dput(base);
+               return ERR_PTR(-ENOENT);
+       }
+        
+        return base;
 }
 
 #define __prefix_lookup_dentry(name, follow_link)                              \
index 9f1c3ac0377fcb4210d0f3803a5611805cc24ee6..0fe16f474265cffb299834563293522e0fc562b0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ebus.h,v 1.2 1997/08/17 22:40:07 ecd Exp $
+/* $Id: ebus.h,v 1.3 1997/09/05 23:00:14 ecd Exp $
  * ebus.h: PCI to Ebus pseudo driver software state.
  *
  * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -9,8 +9,20 @@
 
 #include <asm/oplib.h>
 
+struct linux_ebus_child {
+       struct linux_ebus_child         *next;
+       struct linux_ebus_device        *parent;
+       int                              prom_node;
+       char                             prom_name[64];
+       unsigned long                    base_address[PROMREG_MAX];
+       int                              num_addrs;
+       unsigned int                     irqs[PROMINTR_MAX];
+       int                              num_irqs;
+};
+
 struct linux_ebus_device {
        struct linux_ebus_device        *next;
+       struct linux_ebus_child         *children;
        struct linux_ebus               *parent;
        int                              prom_node;
        char                             prom_name[64];
@@ -19,7 +31,7 @@ struct linux_ebus_device {
        unsigned int                     irqs[PROMINTR_MAX];
        int                              num_irqs;
 };
-       
+
 struct linux_ebus {
        struct linux_ebus               *next;
        struct linux_ebus_device        *devices;
@@ -31,6 +43,39 @@ struct linux_ebus {
        int                              num_ebus_ranges;
 };
 
+struct linux_ebus_dma {
+       unsigned int dcsr;
+       unsigned int dacr;
+       unsigned int dbcr;
+};
+
+#define EBUS_DCSR_INT_PEND     0x00000001
+#define EBUS_DCSR_ERR_PEND     0x00000002
+#define EBUS_DCSR_DRAIN                0x00000004
+#define EBUS_DCSR_INT_EN       0x00000010
+#define EBUS_DCSR_RESET                0x00000080
+#define EBUS_DCSR_WRITE                0x00000100
+#define EBUS_DCSR_EN_DMA       0x00000200
+#define EBUS_DCSR_CYC_PEND     0x00000400
+#define EBUS_DCSR_DIAG_RD_DONE 0x00000800
+#define EBUS_DCSR_DIAG_WR_DONE 0x00001000
+#define EBUS_DCSR_EN_CNT       0x00002000
+#define EBUS_DCSR_TC           0x00004000
+#define EBUS_DCSR_DIS_CSR_DRN  0x00010000
+#define EBUS_DCSR_BURST_SZ_MASK        0x000c0000
+#define EBUS_DCSR_BURST_SZ_1   0x00080000
+#define EBUS_DCSR_BURST_SZ_4   0x00000000
+#define EBUS_DCSR_BURST_SZ_8   0x00040000
+#define EBUS_DCSR_BURST_SZ_16  0x000c0000
+#define EBUS_DCSR_DIAG_EN      0x00100000
+#define EBUS_DCSR_DIS_ERR_PEND 0x00400000
+#define EBUS_DCSR_TCI_DIS      0x00800000
+#define EBUS_DCSR_EN_NEXT      0x01000000
+#define EBUS_DCSR_DMA_ON       0x02000000
+#define EBUS_DCSR_A_LOADED     0x04000000
+#define EBUS_DCSR_NA_LOADED    0x08000000
+#define EBUS_DCSR_DEV_ID_MASK  0xf0000000
+
 extern struct linux_ebus               *ebus_chain;
 
 extern unsigned long ebus_init(unsigned long, unsigned long);
@@ -41,6 +86,9 @@ extern unsigned long ebus_init(unsigned long, unsigned long);
 #define for_each_ebusdev(dev, bus)                                     \
         for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
 
+#define for_each_edevchild(dev, child)                                 \
+        for((child) = (dev)->children; (child); (child) = (child)->next)
+
 #define for_all_ebusdev(dev, bus)                                      \
        for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0);  \
             (bus); ((dev) = (dev)->next ? (dev)->next :                \
index bbef85483f6a30aac9a29eeba84034c6a715c705..586541d975539b2b88e5f393c938d327020458a1 100644 (file)
@@ -1,13 +1,17 @@
-/* $Id: floppy.h,v 1.3 1997/07/11 03:03:22 davem Exp $
+/* $Id: floppy.h,v 1.4 1997/09/05 23:00:15 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
  */
 
 #ifndef __ASM_SPARC64_FLOPPY_H
 #define __ASM_SPARC64_FLOPPY_H
 
+#include <linux/config.h>
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
  * 3) Intel 82077 controller manual
  */
 struct sun_flpy_controller {
-       volatile unsigned char status_82072;  /* Main Status reg. */
-#define dcr_82072              status_82072   /* Digital Control reg. */
-#define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
-
-       volatile unsigned char data_82072;    /* Data fifo. */
-#define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
-
+       volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
+       volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
        volatile unsigned char dor_82077;     /* Digital Output reg. */
        volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
-
        volatile unsigned char status_82077;  /* Main Status Register. */
 #define drs_82077              status_82077   /* Digital Rate Select reg. */
-
        volatile unsigned char data_82077;    /* Data fifo. */
        volatile unsigned char ___unused;
        volatile unsigned char dir_82077;     /* Digital Input reg. */
@@ -47,40 +44,42 @@ static struct sun_flpy_controller *sun_fdc = NULL;
 volatile unsigned char *fdc_status;
 
 struct sun_floppy_ops {
-       unsigned char (*fd_inb)(int port);
-       void (*fd_outb)(unsigned char value, int port);
+       unsigned char   (*fd_inb) (unsigned long port);
+       void            (*fd_outb) (unsigned char value, unsigned long port);
+       void            (*fd_enable_dma) (void);
+       void            (*fd_disable_dma) (void);
+       void            (*fd_set_dma_mode) (int);
+       void            (*fd_set_dma_addr) (char *);
+       void            (*fd_set_dma_count) (int);
+       unsigned int    (*get_dma_residue) (void);
+       void            (*fd_enable_irq) (void);
+       void            (*fd_disable_irq) (void);
+       int             (*fd_request_irq) (void);
+       void            (*fd_free_irq) (void);
+       int             (*fd_eject) (int);
 };
 
 static struct sun_floppy_ops sun_fdops;
 
 #define fd_inb(port)              sun_fdops.fd_inb(port)
 #define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
-#define fd_enable_dma()           sun_fd_enable_dma()
-#define fd_disable_dma()          sun_fd_disable_dma()
+#define fd_enable_dma()           sun_fdops.fd_enable_dma()
+#define fd_disable_dma()          sun_fdops.fd_disable_dma()
 #define fd_request_dma()          (0) /* nothing... */
 #define fd_free_dma()             /* nothing... */
 #define fd_clear_dma_ff()         /* nothing... */
-#define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
-#define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
-#define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
-#define fd_enable_irq()           /* nothing... */
-#define fd_disable_irq()          /* nothing... */
+#define fd_set_dma_mode(mode)     sun_fdops.fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr)     sun_fdops.fd_set_dma_addr(addr)
+#define fd_set_dma_count(count)   sun_fdops.fd_set_dma_count(count)
+#define get_dma_residue(x)        sun_fdops.get_dma_residue()
+#define fd_enable_irq()           sun_fdops.fd_enable_irq()
+#define fd_disable_irq()          sun_fdops.fd_disable_irq()
 #define fd_cacheflush(addr, size) /* nothing... */
-#define fd_request_irq()          sun_fd_request_irq()
-#define fd_free_irq()             /* nothing... */
-#if 0  /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
-#define fd_dma_mem_alloc(size)    ((unsigned long) vmalloc(size))
-#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
-#endif
-
-#define FLOPPY_MOTOR_MASK         0x10
-
-/* It's all the same... */
-#define virt_to_bus(x)            (x)
-#define bus_to_virt(x)            (x)
+#define fd_request_irq()          sun_fdops.fd_request_irq()
+#define fd_free_irq()             sun_fdops.fd_free_irq()
+#define fd_eject(drive)           sun_fdops.fd_eject(drive)
 
-/* XXX This isn't really correct. XXX */
-#define get_dma_residue(x)        (0)
+static int FLOPPY_MOTOR_MASK = 0x10;
 
 #define FLOPPY0_TYPE  4
 #define FLOPPY1_TYPE  0
@@ -94,7 +93,7 @@ static struct sun_floppy_ops sun_fdops;
  */
 #define FDC1                      sun_floppy_init()
 
-static int FDC2=-1;
+static int FDC2 = -1;
 
 #define N_FDC    1
 #define N_DRIVE  8
@@ -102,63 +101,11 @@ static int FDC2=-1;
 /* No 64k boundary crossing problems on the Sparc. */
 #define CROSS_64KB(a,s) (0)
 
-/* Routines unique to each controller type on a Sun. */
-static unsigned char sun_82072_fd_inb(int port)
+static unsigned char sun_82077_fd_inb(unsigned long port)
 {
        switch(port & 7) {
        default:
-               printk("floppy: Asked to read unknown port %d\n", port);
-               panic("floppy: Port bolixed.");
-       case 4: /* FD_STATUS */
-               return sun_fdc->status_82072 & ~STATUS_DMA;
-       case 5: /* FD_DATA */
-               return sun_fdc->data_82072;
-       case 7: /* FD_DIR */
-               return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0;
-       };
-       panic("sun_82072_fd_inb: How did I get here?");
-}
-
-static void sun_82072_fd_outb(unsigned char value, int port)
-{
-       switch(port & 7) {
-       default:
-               printk("floppy: Asked to write to unknown port %d\n", port);
-               panic("floppy: Port bolixed.");
-       case 2: /* FD_DOR */
-               /* Oh geese, 82072 on the Sun has no DOR register,
-                * the functionality is implemented via the AUXIO
-                * I/O register.  So we must emulate the behavior.
-                *
-                * ASSUMPTIONS:  There will only ever be one floppy
-                *               drive attached to a Sun controller
-                *               and it will be at drive zero.
-                */
-               {
-                       unsigned bits = 0;
-                       if (value & 0x10) bits |= AUXIO_FLPY_DSEL;
-                       if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT;
-                       set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
-               }
-               break;
-       case 5: /* FD_DATA */
-               sun_fdc->data_82072 = value;
-               break;
-       case 7: /* FD_DCR */
-               sun_fdc->dcr_82072 = value;
-               break;
-       case 4: /* FD_STATUS */
-               sun_fdc->status_82072 = value;
-               break;
-       };
-       return;
-}
-
-static unsigned char sun_82077_fd_inb(int port)
-{
-       switch(port & 7) {
-       default:
-               printk("floppy: Asked to read unknown port %d\n", port);
+               printk("floppy: Asked to read unknown port %lx\n", port);
                panic("floppy: Port bolixed.");
        case 4: /* FD_STATUS */
                return sun_fdc->status_82077 & ~STATUS_DMA;
@@ -171,11 +118,11 @@ static unsigned char sun_82077_fd_inb(int port)
        panic("sun_82072_fd_inb: How did I get here?");
 }
 
-static void sun_82077_fd_outb(unsigned char value, int port)
+static void sun_82077_fd_outb(unsigned char value, unsigned long port)
 {
        switch(port & 7) {
        default:
-               printk("floppy: Asked to write to unknown port %d\n", port);
+               printk("floppy: Asked to write to unknown port %lx\n", port);
                panic("floppy: Port bolixed.");
        case 2: /* FD_DOR */
                /* Happily, the 82077 has a real DOR register. */
@@ -218,7 +165,7 @@ static __inline__ void virtual_dma_init(void)
        /* nothing... */
 }
 
-static __inline__ void sun_fd_disable_dma(void)
+static void sun_fd_disable_dma(void)
 {
        doing_pdma = 0;
        if (pdma_base) {
@@ -227,7 +174,7 @@ static __inline__ void sun_fd_disable_dma(void)
        }
 }
 
-static __inline__ void sun_fd_set_dma_mode(int mode)
+static void sun_fd_set_dma_mode(int mode)
 {
        switch(mode) {
        case DMA_MODE_READ:
@@ -242,17 +189,17 @@ static __inline__ void sun_fd_set_dma_mode(int mode)
        }
 }
 
-static __inline__ void sun_fd_set_dma_addr(char *buffer)
+static void sun_fd_set_dma_addr(char *buffer)
 {
        pdma_vaddr = buffer;
 }
 
-static __inline__ void sun_fd_set_dma_count(int length)
+static void sun_fd_set_dma_count(int length)
 {
        pdma_size = length;
 }
 
-static __inline__ void sun_fd_enable_dma(void)
+static void sun_fd_enable_dma(void)
 {
        pdma_vaddr = mmu_lockarea(pdma_vaddr, pdma_size);
        pdma_base = pdma_vaddr;
@@ -274,23 +221,207 @@ static int sun_fd_request_irq(void)
        } else return 0;
 }
 
+static void sun_fd_enable_irq(void)
+{
+}
+
+static void sun_fd_disable_irq(void)
+{
+}
+
+static void sun_fd_free_irq(void)
+{
+}
+
+static unsigned int sun_get_dma_residue(void)
+{
+       /* XXX This isn't really correct. XXX */
+       return 0;
+}
+
+static int sun_fd_eject(int drive)
+{
+       set_dor(0x00, 0xff, 0x90);
+       udelay(500);
+       set_dor(0x00, 0x6f, 0x00);
+       udelay(500);
+       return 0;
+}
+
+#ifdef CONFIG_PCI
+#include <asm/ebus.h>
+
+static struct linux_ebus_dma *sun_fd_ebus_dma;
+
+extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static unsigned char sun_pci_fd_inb(unsigned long port)
+{
+       return inb(port);
+}
+
+static void sun_pci_fd_outb(unsigned char val, unsigned long port)
+{
+       outb(val, port);
+}
+
+static void sun_pci_fd_enable_dma(void)
+{
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+       dcsr |= (EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT);
+       writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_disable_dma(void)
+{
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+       dcsr &= ~(EBUS_DCSR_EN_DMA | EBUS_DCSR_EN_CNT);
+       writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_set_dma_mode(int mode)
+{
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+       /*
+        * For EBus WRITE means to system memory, which is
+        * READ for us.
+        */
+       if (mode == DMA_MODE_WRITE)
+               dcsr &= ~(EBUS_DCSR_WRITE);
+       else
+               dcsr |= EBUS_DCSR_WRITE;
+       writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_set_dma_count(int length)
+{
+       writel(length, (unsigned long)&sun_fd_ebus_dma->dbcr);
+}
+
+static void sun_pci_fd_set_dma_addr(char *buffer)
+{
+       unsigned int addr;
+
+       addr = virt_to_bus(buffer);
+       writel(addr, (unsigned long)&sun_fd_ebus_dma->dacr);
+}
+
+static void sun_pci_fd_enable_irq(void)
+{
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+       dcsr |= EBUS_DCSR_INT_EN;
+       writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static void sun_pci_fd_disable_irq(void)
+{
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&sun_fd_ebus_dma->dcsr);
+       dcsr &= ~(EBUS_DCSR_INT_EN);
+       writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+}
+
+static int sun_pci_fd_request_irq(void)
+{
+       int error;
+
+       error = request_irq(FLOPPY_IRQ, floppy_interrupt, SA_SHIRQ, "floppy", sun_fdc);
+       return ((error == 0) ? 0 : -1);
+}
+
+static void sun_pci_fd_free_irq(void)
+{
+       free_irq(FLOPPY_IRQ, sun_fdc);
+}
+
+static unsigned int sun_pci_get_dma_residue(void)
+{
+       unsigned int res;
+
+       res = readl((unsigned long)&sun_fd_ebus_dma->dbcr);
+       return res;
+}
+
+static int sun_pci_fd_eject(int drive)
+{
+       return -EINVAL;
+}
+#endif
+
 static struct linux_prom_registers fd_regs[2];
 
-static int sun_floppy_init(void)
+static unsigned long sun_floppy_init(void)
 {
        char state[128];
        int fd_node, num_regs;
        struct linux_sbus *bus;
        struct linux_sbus_device *sdev;
 
-       use_virtual_dma = 1;
-       
        FLOPPY_IRQ = 11;
        for_all_sbusdev (sdev, bus) {
                if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) 
                        break;
        }
-       if (!bus) return -1;
+       if (!bus) {
+#ifdef CONFIG_PCI
+               struct linux_ebus *ebus;
+               struct linux_ebus_device *edev;
+
+               for_all_ebusdev(edev, ebus) {
+                       if (!strcmp(edev->prom_name, "fdthree"))
+                               break;
+               }
+               if (!edev)
+                       return -1;
+
+               if (check_region(edev->base_address[1], sizeof(struct linux_ebus_dma))) {
+                       printk("sun_floppy_init: can't get region %016lx (%d)\n",
+                              edev->base_address[1], (int)sizeof(struct linux_ebus_dma));
+                       return -1;
+               }
+               request_region(edev->base_address[1], sizeof(struct linux_ebus_dma), "floppy DMA");
+
+               sun_fdc = (struct sun_flpy_controller *)edev->base_address[0];
+               FLOPPY_IRQ = edev->irqs[0];
+
+               sun_fd_ebus_dma = (struct linux_ebus_dma *)edev->base_address[1];
+               writel(EBUS_DCSR_BURST_SZ_16, (unsigned long)&sun_fd_ebus_dma->dcsr);
+
+               sun_fdops.fd_inb = sun_pci_fd_inb;
+               sun_fdops.fd_outb = sun_pci_fd_outb;
+
+               use_virtual_dma = 0;
+               sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
+               sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
+               sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
+               sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
+               sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
+               sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
+
+               sun_fdops.fd_enable_irq = sun_pci_fd_enable_irq;
+               sun_fdops.fd_disable_irq = sun_pci_fd_disable_irq;
+               sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
+               sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
+
+               sun_fdops.fd_eject = sun_pci_fd_eject;
+
+               fdc_status = &sun_fdc->status_82077;
+               FLOPPY_MOTOR_MASK = 0xf0;
+
+               return (unsigned long)sun_fdc;
+#else
+               return -1;
+#endif
+       }
        fd_node = sdev->prom_node;
        prom_getproperty(fd_node, "status", state, sizeof(state));
        if(!strcmp(state, "disabled")) return -1;
@@ -304,29 +435,34 @@ static int sun_floppy_init(void)
                                                                fd_regs[0].which_io,
                                                                0x0);
        /* Last minute sanity check... */
-       if(sun_fdc->status_82072 == 0xff) {
+       if(sun_fdc->status1_82077 == 0xff) {
                sun_fdc = NULL;
                return -1;
        }
 
         sun_fdops.fd_inb = sun_82077_fd_inb;
         sun_fdops.fd_outb = sun_82077_fd_outb;
+
+       use_virtual_dma = 1;
+       sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+       sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+       sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+       sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+       sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+       sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+       sun_fdops.fd_enable_irq = sun_fd_enable_irq;
+       sun_fdops.fd_disable_irq = sun_fd_disable_irq;
+       sun_fdops.fd_request_irq = sun_fd_request_irq;
+       sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+       sun_fdops.fd_eject = sun_fd_eject;
+
         fdc_status = &sun_fdc->status_82077;
         /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
 
        /* Success... */
-       return (int) ((unsigned long)sun_fdc);
+       return (unsigned long)sun_fdc;
 }
 
-static int sparc_eject(void)
-{
-       set_dor(0x00, 0xff, 0x90);
-       udelay(500);
-       set_dor(0x00, 0x6f, 0x00);
-       udelay(500);
-       return 0;
-}
-
-#define fd_eject(drive) sparc_eject()
-
 #endif /* !(__ASM_SPARC64_FLOPPY_H) */
index 8e993c67376d52832b7bab1d2c56ecc834f2deb4..70d0f337fba201f7ee383422ffc5d83a749c682b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.7 1997/09/04 15:46:31 jj Exp $
+/* $Id: namei.h,v 1.8 1997/09/06 02:25:27 davem Exp $
  * linux/include/asm-sparc64/namei.h
  *
  * Routines to handle famous /usr/gnemul/s*.
@@ -14,7 +14,6 @@
 static inline struct dentry *
 __sparc64_lookup_dentry(const char *name, int follow_link)
 {
-       int error;
        struct dentry *base;
 
        switch (current->personality) {
index b21e347fb37a9d14cf1f0ae5f78acde87d381015..843c0ad8c487ec02ab0053b699d6628af209442a 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Definitions for the ARCnet handlers.
  *
- * Version:    @(#)arcdevice.h 1.0     31/07/97
+ * Version:    $Id: arcdevice.h,v 1.2 1997/09/05 08:57:56 mj Exp $
  *
  * Authors:    Avery Pennarun <apenwarr@bond.net>
  *              David Woodhouse <dwmw2@cam.ac.uk>
@@ -24,7 +24,6 @@
 
 #ifdef __KERNEL__
 
-
 #define ARC_20020     1
 #define ARC_RIM_I     2
 #define ARC_90xx      3
@@ -50,6 +49,7 @@
 #define DETECT_RECONFIGS
 #undef SHOW_RECONFIGS
 
+
 /* RECON_THRESHOLD is the maximum number of RECON messages to receive within
  * one minute before printing a "cabling problem" warning.  You must have
  * DETECT_RECONFIGS enabled if you want to use this.  The default value
@@ -62,6 +62,7 @@
  */
 #define RECON_THRESHOLD 30
 
+
 /* Define this to the minimum "timeout" value.  If a transmit takes longer
  * than TX_TIMEOUT jiffies, Linux will abort the TX and retry.  On a large
  * network, or one with heavy network traffic, this timeout may need to be
 #define TX_TIMEOUT 20
 
 
+/* Display warnings about the driver being an ALPHA version.
+ */
+#define ALPHA_WARNING
+
+
 /* New debugging bitflags: each option can be enabled individually.
  *
  * These can be set while the driver is running by typing:
@@ -195,7 +201,6 @@ union ArcPacket
 };
 
 
-
        /* the "client data" header - RFC1201 information
         * notice that this screws up if it's not an even number of bytes
         * <sigh>
@@ -235,7 +240,6 @@ struct S_ClientData
 #define S_EXTRA_CLIENTDATA (sizeof(struct S_ClientData)-1)
 
 
-
 /* "Incoming" is information needed for each address that could be sending
  * to us.  Mostly for partially-received split packets.
  */
@@ -260,7 +264,6 @@ struct Outgoing
 };
 
 
-
 struct arcnet_local {
   struct net_device_stats stats;
   u_short sequence;    /* sequence number (incs with each packet) */
@@ -268,12 +271,12 @@ struct arcnet_local {
   u_char stationid,    /* our 8-bit station address */
     recbuf,            /* receive buffer # (0 or 1) */
     txbuf,             /* transmit buffer # (2 or 3) */
-    txready,   /* buffer where a packet is ready to send */
-    config,         /* current value of CONFIG register */
-    timeout,        /* Extended timeout for COM20020 */
-    backplane,      /* Backplane flag for COM20020 */     
-    setup,          /* Contents of setup register */
-    intmask;   /* current value of INTMASK register */
+    txready,           /* buffer where a packet is ready to send */
+    config,            /* current value of CONFIG register */
+    timeout,           /* Extended timeout for COM20020 */
+    backplane,         /* Backplane flag for COM20020 */     
+    setup,             /* Contents of setup register */
+    intmask;           /* current value of INTMASK register */
   short intx,          /* in TX routine? */
     in_txhandler,      /* in TX_IRQ handler? */
     sending,           /* transmit in progress? */
@@ -282,8 +285,8 @@ struct arcnet_local {
   
 #if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD)
   time_t first_recon,  /* time of "first" RECON message to count */
-    last_recon;        /* time of most recent RECON */
-  int num_recons,              /* number of RECONs between first and last. */
+    last_recon;                /* time of most recent RECON */
+  int num_recons,      /* number of RECONs between first and last. */
     network_down;      /* do we think the network is down? */
 #endif
   
@@ -302,8 +305,7 @@ struct arcnet_local {
   void (*en_dis_able_TX) (struct device *dev, int enable); 
   void (*prepare_tx)(struct device *dev,u_char *hdr,int hdrlen,
                     char *data,int length,int daddr,int exceptA, int offset);
-  void (*openclose_device)(int open);
-  
+  void (*openclose_device)(int open);  
   
   struct device *adev; /* RFC1201 protocol device */
   
@@ -318,12 +320,34 @@ struct arcnet_local {
 #ifdef CONFIG_ARCNET_1051
   struct device *sdev; /* RFC1051 protocol device */
 #endif
+};
 
+/* Functions exported by arcnet.c
+ */
 
-};
+#if ARCNET_DEBUG_MAX & D_SKB
+extern void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,
+                           char *desc);
+#else
+#define arcnet_dump_skb(dev,skb,desc) ;
+#endif
 
+#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
+extern void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,
+                              char *desc);
+#else
+#define arcnet_dump_packet(dev,buffer,ext,desc) ;
+#endif
 
-#endif  /* __KERNEL__ */
-#endif /* _LINUX_ARCDEVICE_H */
+extern void arcnet_tx_done(struct device *dev, struct arcnet_local *lp);
+extern void arcnet_makename(char *device);
+extern void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
+extern void arcnet_setup(struct device *dev);
+extern int arcnet_go_tx(struct device *dev,int enable_irq);
+extern void arcnetA_continue_tx(struct device *dev);
+extern void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
+extern void arcnet_use_count(int open);
 
 
+#endif  /* __KERNEL__ */
+#endif /* _LINUX_ARCDEVICE_H */
index da7293c35b1c9f10081170e9e7985ac13887c1a9..a325326684610909878afb298184c5745a00a27b 100644 (file)
@@ -248,7 +248,7 @@ struct floppy_fdc_state {
        int dtr;
        unsigned char version;  /* FDC version code */
        unsigned char dor;
-       int address;            /* io address */
+       unsigned long address;  /* io address */
        unsigned int rawcmd:2;
        unsigned int reset:1;
        unsigned int need_configure:1;
index a628129c807d49ace2f9bc89028120f4b621f52f..8b2ba0aaef450fc70abdcea97ffb349bc6086c8c 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Global definitions for the ARCnet interface.
  *
- * Version:    @(#)if_arcnet.h 1.0     07/08/97
+ * Version:    $Id: if_arcnet.h,v 1.2 1997/09/05 08:57:54 mj Exp $
  *
  * Author:     David Woodhouse <dwmw2@cam.ac.uk>
  *             Avery Pennarun <apenwarr@bond.net>      
@@ -50,7 +50,7 @@
 /*
  *     This is an ARCnet frame header.
  */
+
 struct archdr                       /* was struct HardHeader */
 {
        u_char  source,         /* source ARCnet - filled in automagically */
@@ -61,4 +61,3 @@ struct archdr                       /* was struct HardHeader */
 };
 
 #endif /* _LINUX_IF_ARCNET_H */
-
index 51b319891ca8ceddc42bd67158305486e2e5b59e..c6f2497fd92081d87353aafe3f5aa6a85952f175 100644 (file)
@@ -68,6 +68,16 @@ asmlinkage int printk(const char * fmt, ...)
  */
 #define fsuser() (current->fsuid == 0)
 
+/*
+ *      Display an IP address in readable format.
+ */
+
+#define NIPQUAD(addr) \
+       (((addr) >> 0)  & 0xff), \
+       (((addr) >> 8)  & 0xff), \
+       (((addr) >> 16) & 0xff), \
+       (((addr) >> 24) & 0xff)
+
 #endif /* __KERNEL__ */
 
 #define SI_LOAD_SHIFT  16
diff --git a/include/linux/openpic.h b/include/linux/openpic.h
new file mode 100644 (file)
index 0000000..863e659
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ *  linux/openpic.h -- OpenPIC definitions
+ *
+ *  Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ *
+ *  This file is based on the following documentation:
+ *
+ *     The Open Programmable Interrupt Controller (PIC)
+ *     Register Interface Specification Revision 1.2
+ *
+ *     Issue Date: October 1995
+ *
+ *     Issued jointly by Advanced Micro Devices and Cyrix Corporation
+ *
+ *     AMD is a registered trademark of Advanced Micro Devices, Inc.
+ *     Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
+ *     All Rights Reserved.
+ *
+ *  To receive a copy of this documentation, send an email to openpic@amd.com.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef _LINUX_OPENPIC_H
+#define _LINUX_OPENPIC_H
+
+#if !defined(__powerpc__) && !defined(__i386__)
+#error Unsupported OpenPIC platform
+#endif
+
+
+#ifdef __KERNEL__
+
+    /*
+     *  OpenPIC supports up to 2048 interrupt sources and up to 32 processors
+     */
+
+#define OPENPIC_MAX_SOURCES    2048
+#define OPENPIC_MAX_PROCESSORS 32
+
+#define OPENPIC_NUM_TIMERS     4
+#define OPENPIC_NUM_IPI                4
+#define OPENPIC_NUM_PRI                16
+#define OPENPIC_NUM_VECTORS    256
+
+
+    /*
+     *  OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
+     */
+
+typedef struct _OpenPIC_Reg {
+    u_int Reg;                                 /* Little endian! */
+    char Pad[0xc];
+} OpenPIC_Reg;
+
+
+    /*
+     *  Per Processor Registers
+     */
+
+typedef struct _OpenPIC_Processor {
+    /*
+     *  Private Shadow Registers (for SLiC backwards compatibility)
+     */
+    u_int IPI0_Dispatch_Shadow;                        /* Write Only */
+    char Pad1[0x4];
+    u_int IPI0_Vector_Priority_Shadow;         /* Read/Write */
+    char Pad2[0x34];
+    /*
+     *  Interprocessor Interrupt Command Ports
+     */
+    OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI];        /* Write Only */
+    /*
+     *  Current Task Priority Register
+     */
+    OpenPIC_Reg _Current_Task_Priority;                /* Read/Write */
+#ifndef __powerpc__
+    /*
+     *  Who Am I Register
+     */
+    OpenPIC_Reg _Who_Am_I;                     /* Read Only */
+#else
+    char Pad3[0x10];
+#endif
+#ifndef __i386__
+    /*
+     *  Interrupt Acknowledge Register
+     */
+    OpenPIC_Reg _Interrupt_Acknowledge;                /* Read Only */
+#else
+    char Pad4[0x10];
+#endif
+    /*
+     *  End of Interrupt (EOI) Register
+     */
+    OpenPIC_Reg _EOI;                          /* Read/Write */
+    char Pad5[0xf40];
+} OpenPIC_Processor;
+
+
+    /*
+     *  Timer Registers
+     */
+
+typedef struct _OpenPIC_Timer {
+    OpenPIC_Reg _Current_Count;                        /* Read Only */
+    OpenPIC_Reg _Base_Count;                   /* Read/Write */
+    OpenPIC_Reg _Vector_Priority;              /* Read/Write */
+    OpenPIC_Reg _Destination;                  /* Read/Write */
+} OpenPIC_Timer;
+
+
+    /*
+     *  Global Registers
+     */
+
+typedef struct _OpenPIC_Global {
+    /*
+     *  Feature Reporting Registers
+     */
+    OpenPIC_Reg _Feature_Reporting0;           /* Read Only */
+    OpenPIC_Reg _Feature_Reporting1;           /* Future Expansion */
+    /*
+     *  Global Configuration Registers
+     */
+    OpenPIC_Reg _Global_Configuration0;                /* Read/Write */
+    OpenPIC_Reg _Global_Configuration1;                /* Future Expansion */
+    /*
+     *  Vendor Specific Registers
+     */
+    OpenPIC_Reg _Vendor_Specific[4];
+    /*
+     *  Vendor Identification Register
+     */
+    OpenPIC_Reg _Vendor_Identification;                /* Read Only */
+    /*
+     *  Processor Initialization Register
+     */
+    OpenPIC_Reg _Processor_Initialization;     /* Read/Write */
+    /*
+     *  IPI Vector/Priority Registers
+     */
+    OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
+    /*
+     *  Spurious Vector Register
+     */
+    OpenPIC_Reg _Spurious_Vector;              /* Read/Write */
+    /*
+     *  Global Timer Registers
+     */
+    OpenPIC_Reg _Timer_Frequency;              /* Read/Write */
+    OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
+    char Pad1[0xee00];
+} OpenPIC_Global;
+
+
+    /*
+     *  Interrupt Source Registers
+     */
+
+typedef struct _OpenPIC_Source {
+    OpenPIC_Reg _Vector_Priority;              /* Read/Write */
+    OpenPIC_Reg _Destination;                  /* Read/Write */
+} OpenPIC_Source;
+
+
+    /*
+     *  OpenPIC Register Map
+     */
+
+struct OpenPIC {
+#ifndef __powerpc__
+    /*
+     *  Per Processor Registers --- Private Access
+     */
+    OpenPIC_Processor Private;
+#else
+    char Pad1[0x1000];
+#endif
+    /*
+     *  Global Registers
+     */
+    OpenPIC_Global Global;
+    /*
+     *  Interrupt Source Configuration Registers
+     */
+    OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
+    /*
+     *  Per Processor Registers
+     */
+    OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
+};
+
+extern volatile struct OpenPIC *OpenPIC;
+
+
+    /*
+     *  Current Task Priority Register
+     */
+
+#define OPENPIC_CURRENT_TASK_PRIORITY_MASK     0x0000000f
+
+    /*
+     *  Who Am I Register
+     */
+
+#define OPENPIC_WHO_AM_I_ID_MASK               0x0000001f
+
+    /*
+     *  Feature Reporting Register 0
+     */
+
+#define OPENPIC_FEATURE_LAST_SOURCE_MASK       0x07ff0000
+#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT      16
+#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK    0x00001f00
+#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT   8
+#define OPENPIC_FEATURE_VERSION_MASK           0x000000ff
+
+    /*
+     *  Global Configuration Register 0
+     */
+
+#define OPENPIC_CONFIG_RESET                   0x80000000
+#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE        0x20000000
+#define OPENPIC_CONFIG_BASE_MASK               0x000fffff
+
+    /*
+     *  Vendor Identification Register
+     */
+
+#define OPENPIC_VENDOR_ID_STEPPING_MASK                0x00ff0000
+#define OPENPIC_VENDOR_ID_STEPPING_SHIFT       16
+#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK       0x0000ff00
+#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT      8
+#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK       0x000000ff
+
+    /*
+     *  Vector/Priority Registers
+     */
+
+#define OPENPIC_MASK                           0x80000000
+#define OPENPIC_ACTIVITY                       0x40000000      /* Read Only */
+#define OPENPIC_PRIORITY_MASK                  0x000f0000
+#define OPENPIC_PRIORITY_SHIFT                 16
+#define OPENPIC_VECTOR_MASK                    0x000000ff
+
+
+    /*
+     *  Interrupt Source Registers
+     */
+
+#define OPENPIC_SENSE_POLARITY                 0x00800000      /* Undoc'd */
+#define OPENPIC_SENSE_LEVEL                    0x00400000
+
+
+    /*
+     *  Timer Registers
+     */
+
+#define OPENPIC_COUNT_MASK                     0x7fffffff
+#define OPENPIC_TIMER_TOGGLE                   0x80000000
+#define OPENPIC_TIMER_COUNT_INHIBIT            0x80000000
+
+
+    /*
+     *  Aliases to make life simpler
+     */
+
+/* Per Processor Registers */
+#define IPI_Dispatch(i)                        _IPI_Dispatch[i].Reg
+#define Current_Task_Priority          _Current_Task_Priority.Reg
+#ifndef __powerpc__
+#define Who_Am_I                       _Who_Am_I.Reg
+#endif
+#ifndef __i386__
+#define Interrupt_Acknowledge          _Interrupt_Acknowledge.Reg
+#endif
+#define EOI                            _EOI.Reg
+
+/* Global Registers */
+#define Feature_Reporting0             _Feature_Reporting0.Reg
+#define Feature_Reporting1             _Feature_Reporting1.Reg
+#define Global_Configuration0          _Global_Configuration0.Reg
+#define Global_Configuration1          _Global_Configuration1.Reg
+#define Vendor_Specific(i)             _Vendor_Specific[i].Reg
+#define Vendor_Identification          _Vendor_Identification.Reg
+#define Processor_Initialization       _Processor_Initialization.Reg
+#define IPI_Vector_Priority(i)         _IPI_Vector_Priority[i].Reg
+#define Spurious_Vector                        _Spurious_Vector.Reg
+#define Timer_Frequency                        _Timer_Frequency.Reg
+
+/* Timer Registers */
+#define Current_Count                  _Current_Count.Reg
+#define Base_Count                     _Base_Count.Reg
+#define Vector_Priority                        _Vector_Priority.Reg
+#define Destination                    _Destination.Reg
+
+/* Interrupt Source Registers */
+#define Vector_Priority                        _Vector_Priority.Reg
+#define Destination                    _Destination.Reg
+
+
+    /*
+     *  Vendor and Device IDs
+     */
+
+#define OPENPIC_VENDOR_ID_APPLE                0x14
+#define OPENPIC_DEVICE_ID_APPLE_HYDRA  0x46
+
+
+    /*
+     *  OpenPIC Operations
+     */
+
+/* Global Operations */
+extern void openpic_init(void);
+extern void openpic_reset(void);
+extern void openpic_enable_8259_pass_through(void);
+extern void openpic_disable_8259_pass_through(void);
+#ifndef __i386__
+extern u_int openpic_irq(u_int cpu);
+#endif
+#ifndef __powerpc__
+extern void openpic_eoi(void);
+extern u_int openpic_get_priority(void);
+extern void openpic_set_priority(u_int pri);
+#else
+extern void openpic_eoi(u_int cpu);
+extern u_int openpic_get_priority(u_int cpu);
+extern void openpic_set_priority(u_int cpu, u_int pri);
+#endif
+extern u_int openpic_get_spurious(void);
+extern void openpic_set_spurious(u_int vector);
+extern void openpic_init_processor(u_int cpumask);
+
+/* Interprocessor Interrupts */
+extern void openpic_initipi(u_int ipi, u_int pri, u_int vector);
+#ifndef __powerpc__
+extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
+#else
+extern void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask);
+#endif
+
+/* Timer Interrupts */
+extern void openpic_inittimer(u_int timer, u_int pri, u_int vector);
+extern void openpic_maptimer(u_int timer, u_int cpumask);
+
+/* Interrupt Sources */
+extern void openpic_enable_irq(u_int irq);
+extern void openpic_disable_irq(u_int irq);
+extern void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
+                           int is_level);
+extern void openpic_mapirq(u_int irq, u_int cpumask);
+extern void openpic_set_sense(u_int irq, int sense);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_OPENPIC_H */
index 103089b29073cbd05f7a2fae89605490edafde35..13d06496a9b53658288552c5730509ae801e5807 100644 (file)
 #define PCI_DEVICE_ID_ADL_2301         0x2301
 
 #define PCI_VENDOR_ID_NS               0x100b
+#define PCI_DEVICE_ID_NS_87415         0x0002
 #define PCI_DEVICE_ID_NS_87410         0xd001
 
 #define PCI_VENDOR_ID_TSENG            0x100c
 #define PCI_DEVICE_ID_DEC_TULIP                0x0002
 #define PCI_DEVICE_ID_DEC_TGA          0x0004
 #define PCI_DEVICE_ID_DEC_TULIP_FAST   0x0009
+#define PCI_DEVICE_ID_DEC_TGA2         0x000D
 #define PCI_DEVICE_ID_DEC_FDDI         0x000F
 #define PCI_DEVICE_ID_DEC_TULIP_PLUS   0x0014
 #define PCI_DEVICE_ID_DEC_21142                0x0019
 #define PCI_DEVICE_ID_OLICOM_OC2326    0x0014
 #define PCI_DEVICE_ID_OLICOM_OC6151    0x0021
 
+#define PCI_VENDOR_ID_SUN              0x108e
+#define PCI_DEVICE_ID_SUN_EBUS         0x1000
+#define PCI_DEVICE_ID_SUN_HAPPYMEAL    0x1001
+#define PCI_DEVICE_ID_SUN_PBM          0x8000
+
 #define PCI_VENDOR_ID_CMD              0x1095
 #define PCI_DEVICE_ID_CMD_640          0x0640
 #define PCI_DEVICE_ID_CMD_643          0x0643
@@ -775,7 +782,12 @@ struct pci_dev {
         * necessary.  The field must not be 0 unless the device
         * cannot generate interrupts at all.
         */
-       unsigned char   irq;            /* irq generated by this device */
+       unsigned int    irq;            /* irq generated by this device */
+
+       /* Base registers for this device, can be adjusted by
+        * pcibios_fixup() as necessary.
+        */
+       unsigned long   base_address[6];
 };
 
 struct pci_bus {
@@ -812,6 +824,8 @@ extern struct pci_dev       *pci_devices;   /* list of all devices */
 
 extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end);
 
+extern unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp);
+
 extern struct pci_dev_info *pci_lookup_dev (unsigned int vendor,
                                            unsigned int dev);
 extern const char *pci_strclass (unsigned int class);
index 926575eb481dfeb3aae916a1aff6bea9de5ea1c1..61b24941ea860008de6f9399c53ed0aba0807320 100644 (file)
@@ -73,6 +73,7 @@ extern struct screen_info screen_info;
 #define VIDEO_TYPE_TGAC                0x40    /* DEC TGA */
 
 #define VIDEO_TYPE_SUN          0x50    /* Sun frame buffer. */
+#define VIDEO_TYPE_SUNPCI       0x51    /* Sun PCI based frame buffer. */
 
 #define VIDEO_TYPE_PMAC                0x60    /* PowerMacintosh frame buffer. */
 
index a1151132230c903b5062259b528568b767ddf6d3..728b6662e750c4d47fecb21fa2cd06a7fe65e023 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _INET_COMMON_H
 #define _INET_COMMON_H
 
-#include <linux/config.h>
-
 extern struct proto_ops                inet_stream_ops;
 extern struct proto_ops                inet_dgram_ops;
 
index 0843f335ed75dccc46aafbfbe588e9ce6d342512..f8da9a0d46802b6a011091457fa9ff479bc8818a 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef _SNMP_H
 #define _SNMP_H
  
-#include <linux/config.h>
-
 /*
  *     We use all unsigned longs. Linux will soon be so reliable that even these
  *     will rapidly get too small 8-). Seriously consider the IpInReceives count
index 4a6f4f1b2bd496631ac2ed8c3c928216c51308ea..a0c85d7b2ff237771f79b1a78d3ad9d47cde3314 100644 (file)
@@ -72,6 +72,7 @@ extern void uidcache_init(void);
 extern unsigned long pci_init(unsigned long, unsigned long);
 extern long mca_init(long, long);
 extern long sbus_init(long, long);
+extern long powermac_init(unsigned long, unsigned long);
 extern void sysctl_init(void);
 extern void filescache_init(void);
 
@@ -86,6 +87,18 @@ extern void msmouse_setup(char *str, int *ints);
 extern void lp_setup(char *str, int *ints);
 #endif
 extern void eth_setup(char *str, int *ints);
+#ifdef CONFIG_ARCNET_COM20020
+extern void com20020_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_ARCNET_RIM_I
+extern void arcrimi_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_ARCNET_COM90xxIO
+extern void com90io_setup(char *str, int *ints);
+#endif
+#ifdef CONFIG_ARCNET_COM90xx
+extern void com90xx_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_DECNET
 extern void decnet_setup(char *str, int *ints);
 #endif
@@ -212,6 +225,10 @@ extern void baycom_setup(char *str, int *ints);
 #ifdef CONFIG_SOUNDMODEM
 extern void sm_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_PMAC_CONSOLE
+extern void pmac_cons_setup(char *str, int *ints);
+extern void pmac_vmode_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_WDT
 extern void wdt_setup(char *str, int *ints);
 #endif
@@ -221,6 +238,9 @@ extern void parport_setup(char *str, int *ints);
 #ifdef CONFIG_PLIP
 extern void plip_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_HFMODEM
+extern void hfmodem_setup(char *str, int *ints);
+#endif
 
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 extern void ipc_init(void);
@@ -329,6 +349,18 @@ struct {
 #ifdef CONFIG_INET
        { "ether=", eth_setup },
 #endif
+#ifdef CONFIG_ARCNET_COM20020
+       { "com20020=", com20020_setup },
+#endif
+#ifdef CONFIG_ARCNET_RIM_I
+       { "arcrimi=", arcrimi_setup },
+#endif
+#ifdef CONFIG_ARCNET_COM90xxIO
+       { "com90io=", com90io_setup },
+#endif
+#ifdef CONFIG_ARCNET_COM90xx
+       { "com90xx=", com90xx_setup },
+#endif
 #ifdef CONFIG_DECNET
        { "decnet=", decnet_setup },
 #endif
@@ -516,6 +548,13 @@ struct {
 #endif
 #ifdef CONFIG_PLIP
        { "plip=", plip_setup },
+#endif
+#ifdef CONFIG_SOUNDMODEM
+       { "hfmodem=", hfmodem_setup },
+#endif
+#ifdef CONFIG_PMAC_CONSOLE
+       { "console=", pmac_cons_setup },
+       { "vmode=", pmac_vmode_setup },
 #endif
        { 0, 0 }
 };
@@ -875,6 +914,9 @@ __initfunc(asmlinkage void start_kernel(void))
        }
 #ifdef CONFIG_SBUS
        memory_start = sbus_init(memory_start,memory_end);
+#endif
+#ifdef CONFIG_PMAC
+       memory_start = powermac_init(memory_start, memory_end);
 #endif
        memory_start = console_init(memory_start,memory_end);
 #ifdef CONFIG_PCI
index b306922ec9a4be27186e8e7f5192abefe57e97a4..9a3949cc64133ff4f928be58afdafcc061fd6111 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -498,8 +498,14 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
                if (shmflg & SHM_REMAP)
                        goto out;
                err = -ENOMEM;
-               if (!(addr = get_unmapped_area(0, shp->shm_segsz)))
+               addr = 0;
+       again:
+               if (!(addr = get_unmapped_area(addr, shp->shm_segsz)))
                        goto out;
+               if(addr & (SHMLBA - 1)) {
+                       addr = (addr + (SHMLBA - 1)) & ~(SHMLBA - 1);
+                       goto again;
+               }
        } else if (addr & (SHMLBA-1)) {
                if (shmflg & SHM_RND)
                        addr &= ~(SHMLBA-1);       /* round down */
index 8dd12666ca08537884c5da8f0324861b4072d8de..d5c90133decd67b035c81dfba23f58839173afde 100644 (file)
@@ -523,10 +523,8 @@ static void exit_notify(void)
 
 NORET_TYPE void do_exit(long code)
 {
-       if (in_interrupt()) {
-               local_irq_count[smp_processor_id()] = 0;        /* Not really correct */
+       if (in_interrupt())
                printk("Aiee, killing interrupt handler\n");
-       }
 fake_volatile:
        acct_process(code);
        current->flags |= PF_EXITING;
index c584eb3ae8e7a81ec283b0729737ff1a7f39aef0..60e2f04762ff0946f6652d3486d2915e0563acff 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/vmalloc.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <asm/pgtable.h>
 
 /*
  * Originally by Anonymous (as far as I know...)
@@ -294,6 +295,10 @@ sys_init_module(const char *name_user, struct module *mod_user)
                goto err3;
        }
 
+       /* On some machines it is necessary to do something here
+          to make the I and D caches consistent.  */
+       flush_icache_range((unsigned long)mod, (unsigned long)mod + mod->size);
+
        /* Update module references.  */
        mod->next = mod_tmp.next;
        mod->refs = NULL;
index 27d41eed1eb03def359c8648826b830d2f222cd0..dbdae9058f43d16ce6d0d5acb4406da25d48be98 100644 (file)
@@ -366,7 +366,7 @@ static struct file acct_file;
 int acct_process(long exitcode)
 {
    struct acct ac;
-   unsigned short fs;
+   unsigned long fs;
 
    if (acct_active) {
       strncpy(ac.ac_comm, current->comm, ACCT_COMM);
index d20fdbd98a974b1a3ed138b46fe5cfd80a26842f..7ba688b60af4b1f41a148313ee4c734f75f22726 100644 (file)
@@ -15,7 +15,7 @@
  * 1993-10-08    Torsten Duwe
  *      adjtime interface update and CMOS clock write code
  * 1995-08-13    Torsten Duwe
- *      kernel PLL updated to 1994-12-13 specs (rfc-1489)
+ *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
  */
 
 #include <linux/errno.h>
index b63f5469c1ac676d4bdfada39ea1498dbe7afe41..8c3daf2037ada1d2dc52bbbabbbe3a55149c0b04 100644 (file)
@@ -253,41 +253,6 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                        }
                        continue;
 
-               case 'I': /* IPv4 / IPv6 printout */
-                       {
-                         __u8 *ip4;
-                         char sbuf[6];
-                         if (qualifier == 'l') {
-                           __u16 *ip6 = va_arg(args, __u16 *);
-                           i = 6;
-                           for ( ; i > 0; --i, ++ip6)
-                             if (*ip6 != 0)
-                               break;
-                           if (i < 6)
-                             *str++ = ':';
-                           for ( ; i > 0; --i, ++ip6) {
-                             sprintf(sbuf,":%04x",(int)(*ip6));
-                             s = sbuf;
-                             while (*s)
-                               *str++ = *s++;
-                           }
-                           *str++ = ':';
-                           ip4 = (__u8*) ip6;
-                         } else {
-                           ip4 = va_arg(args, __u8 *);
-                         }
-                         for (i = 0; i < 4; ++i, ++ip4) {
-                           if (i == 3)
-                             sprintf(sbuf,"%d", 0xFF & (*ip4));
-                           else
-                             sprintf(sbuf,"%d.", 0xFF & (*ip4));
-                           s = sbuf;
-                           while (*s)
-                             *str++ = *s++;
-                         }
-                       }
-                       continue;
-
                /* integer number formats - set up the flags and "break" */
                case 'o':
                        base = 8;
index b31e35ac04696499853bcb74e1b60e8e4a068a74..0fcab46d43f1988688640afab4ce8e90d882c763 100644 (file)
@@ -892,8 +892,9 @@ no_page:
 static inline int do_write_page(struct inode * inode, struct file * file,
        const char * page, unsigned long offset)
 {
-       int old_fs, retval;
+       int retval;
        unsigned long size;
+       unsigned long old_fs;
 
        size = offset + PAGE_SIZE;
        /* refuse to extend file size.. */
index 15415ddf660fca5bc95491102af7ddbb8f52ea93..71bdea02e8f3f7b489d630f6b05dba691217bea9 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The IP fragmentation functionality.
  *             
- * Version:    $Id: ip_fragment.c,v 1.25 1997/08/17 05:56:07 freitag Exp $
+ * Version:    $Id: ip_fragment.c,v 1.26 1997/09/04 22:35:00 davem Exp $
  *
  * Authors:    Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *             Alan Cox <Alan.Cox@linux.org>
@@ -313,8 +313,7 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        len = qp->ihlen + qp->len;
        
        if(len>65535) {
-               printk(KERN_INFO "Oversized IP packet from %I.\n", 
-                      &qp->iph->saddr);
+               printk(KERN_INFO "Oversized IP packet from %d.%d.%d.%d.\n", NIPQUAD(qp->iph->saddr));
                ip_statistics.IpReasmFails++;
                ip_free(qp);
                return NULL;
@@ -322,8 +321,7 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        
        if ((skb = dev_alloc_skb(len)) == NULL) {
                ip_statistics.IpReasmFails++;
-               NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing "
-                               "queue %p\n", qp));
+               NETDEBUG(printk(KERN_ERR "IP: queue_glue: no memory for gluing queue %p\n", qp));
                ip_free(qp);
                return NULL;
        }
@@ -436,8 +434,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
        
        /* Attempt to construct an oversize packet. */
        if(ntohs(iph->tot_len)+(int)offset>65535) {
-               printk(KERN_INFO "Oversized packet received from %I\n",
-                      &iph->saddr);
+               printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", NIPQUAD(iph->saddr));
                frag_kfree_skb(skb, FREE_READ);
                ip_statistics.IpReasmFails++;
                return NULL;
index baea7014408042617d193c721501bb42eb551c59..2c28ab6118fa5138f5cbae47c7103d4f133ebf37 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp.c,v 1.70 1997/09/01 03:14:28 davem Exp $
+ * Version:    $Id: tcp.c,v 1.71 1997/09/06 05:11:45 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1503,10 +1503,11 @@ void tcp_close(struct sock *sk, unsigned long timeout)
  *     Wait for an incoming connection, avoid race
  *     conditions. This must be called with the socket locked.
  */
-static struct open_request * wait_for_connect(struct sock * sk)
+static struct open_request * wait_for_connect(struct sock * sk,
+                                             struct open_request **pprev)
 {
        struct wait_queue wait = { current, NULL };
-       struct open_request *req = NULL, *dummy;
+       struct open_request *req = NULL;
 
        add_wait_queue(sk->sleep, &wait);
        for (;;) {
@@ -1514,7 +1515,7 @@ static struct open_request * wait_for_connect(struct sock * sk)
                release_sock(sk);
                schedule();
                lock_sock(sk);
-               req = tcp_find_established(&(sk->tp_pinfo.af_tcp), &dummy);
+               req = tcp_find_established(&(sk->tp_pinfo.af_tcp), pprev);
                if (req) 
                        break;
                if (current->signal & ~current->blocked)
@@ -1569,7 +1570,7 @@ no_listen:
        error = EAGAIN;
        if (flags & O_NONBLOCK)
                goto out;
-       req = wait_for_connect(sk);
+       req = wait_for_connect(sk, &prev);
        if (req)
                goto got_new_connect;
        error = ERESTARTSYS;
index 13947223950907c57d98833883d4e2aa885743f2..f8cb368947f6f5b4cece8119f650882955608946 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.61 1997/09/02 09:46:55 freitag Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.62 1997/09/04 22:34:59 davem Exp $
  *
  *             IPv4 specific functions
  *
@@ -1440,14 +1440,14 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
        case CHECKSUM_HW:
                if (tcp_v4_check(th,len,saddr,daddr,skb->csum)) {
                        struct iphdr * iph = skb->nh.iph;
-                       printk(KERN_DEBUG "TCPv4 bad checksum from %I:%04x to %I:%04x, len=%d/%d/%d\n",
-                              &saddr, ntohs(th->source), &daddr,
+                       printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, len=%d/%d/%d\n",
+                              NIPQUAD(saddr), ntohs(th->source), NIPQUAD(daddr),
                               ntohs(th->dest), len, skb->len, ntohs(iph->tot_len));
                                        goto discard_it;
                }
        default:
                /* CHECKSUM_UNNECESSARY */
-       };
+       }
 
        tcp_statistics.TcpInSegs++;
 
index 70d3c16f99c6d0801d09ecb8d8bf169a9afa3ad2..9ab63c5301ae9f32ae0bc5a64109576bb2968725 100644 (file)
@@ -341,6 +341,8 @@ EXPORT_SYMBOL(kill_fasync);
 EXPORT_SYMBOL(ip_rcv);
 EXPORT_SYMBOL(arp_rcv);
 
+EXPORT_SYMBOL(if_port_text);
+
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) 
 #include<linux/if_ltalk.h>
 EXPORT_SYMBOL(ltalk_setup);