]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.126pre1 2.1.126pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:16:59 +0000 (15:16 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:16:59 +0000 (15:16 -0500)
212 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/powerpc/00-INDEX
Documentation/powerpc/smp.txt
Documentation/powerpc/sound.txt
Documentation/powerpc/zImage_layout.txt [new file with mode: 0644]
Documentation/sound/MultiSound
MAINTAINERS
README
arch/alpha/Makefile
arch/alpha/boot/Makefile
arch/alpha/boot/bootp.c
arch/alpha/boot/head.S
arch/alpha/config.in
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/bios32.c
arch/alpha/kernel/core_pyxis.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/head.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq.h
arch/alpha/kernel/machvec.h
arch/alpha/kernel/process.c
arch/alpha/kernel/proto.h
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/smc37c93x.c
arch/alpha/kernel/smp.c
arch/alpha/kernel/sys_jensen.c
arch/alpha/kernel/sys_ruffian.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/kernel/time.c
arch/alpha/kernel/traps.c
arch/alpha/lib/Makefile
arch/alpha/lib/srm_dispatch.S [new file with mode: 0644]
arch/alpha/lib/srm_fixup.S [new file with mode: 0644]
arch/alpha/lib/srm_printk.c [new file with mode: 0644]
arch/alpha/lib/srm_puts.c [new file with mode: 0644]
arch/alpha/mm/init.c
arch/i386/kernel/bios32.c
arch/i386/kernel/setup.c
arch/i386/kernel/time.c
arch/ppc/kernel/pmac_setup.c
arch/ppc/kernel/pmac_setup.c.orig [new file with mode: 0644]
drivers/block/Config.in
drivers/block/README.fd
drivers/block/acsi.c
drivers/block/floppy.c
drivers/block/genhd.c
drivers/block/ide-dma.c
drivers/block/ide-floppy.c
drivers/block/ide-pci.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/ll_rw_blk.c
drivers/block/xd.c
drivers/cdrom/cdu31a.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/bttv.c
drivers/char/bttv.h
drivers/char/bw-qcam.c
drivers/char/esp.c
drivers/char/hfmodem/main.c
drivers/char/joystick/joy-console.c
drivers/char/joystick/joy-db9.c
drivers/char/joystick/joy-lightning.c
drivers/char/joystick/joy-turbografx.c
drivers/char/lp.c
drivers/char/misc.c
drivers/char/pc_keyb.c
drivers/char/pc_keyb.h
drivers/char/psaux.c [deleted file]
drivers/char/qpmouse.c
drivers/char/sysrq.c
drivers/char/tpqic02.c
drivers/char/tty_io.c
drivers/misc/parport_arc.c
drivers/misc/parport_ax.c
drivers/misc/parport_pc.c
drivers/misc/parport_procfs.c
drivers/misc/parport_share.c
drivers/net/3c505.c
drivers/net/eepro100.c
drivers/net/eth16i.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/dmascc.c
drivers/net/hostess_sv11.c
drivers/net/lance.c
drivers/net/ltpc.c
drivers/net/ni65.c
drivers/net/plip.c
drivers/net/sdla_fr.c
drivers/net/sdla_ppp.c
drivers/net/sdla_x25.c
drivers/net/sdladrv.c
drivers/net/sdlamain.c
drivers/net/sktr.c
drivers/net/syncppp.c
drivers/net/via-rhine.c
drivers/net/z85230.c
drivers/net/z85230.h
drivers/net/znet.c
drivers/pci/oldproc.c
drivers/pnp/parport_probe.c
drivers/scsi/Config.in
drivers/scsi/NCR53c406a.c
drivers/scsi/README.aic7xxx
drivers/scsi/aha152x.c
drivers/scsi/aha152x.h
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx/bsd_q.h [deleted file]
drivers/scsi/aic7xxx/sequencer.h
drivers/scsi/eata.c
drivers/scsi/fdomain.c
drivers/scsi/imm.c
drivers/scsi/ppa.c
drivers/scsi/scsi.c
drivers/scsi/scsi.h
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_obsolete.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sd_ioctl.c
drivers/scsi/u14-34f.c
drivers/scsi/wd7000.c
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/Readme
drivers/sound/ad1848.c
drivers/sound/ad1848_mixer.h
drivers/sound/audio.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/legacy.h
drivers/sound/msnd_pinnacle.c
drivers/sound/opl3sa2.c [new file with mode: 0644]
drivers/sound/sb_common.c
drivers/sound/sound_calls.h
drivers/video/Config.in
drivers/video/Makefile
drivers/video/atyfb.c
drivers/video/fbcon.c
drivers/video/fbmem.c
drivers/video/iga.h [new file with mode: 0644]
drivers/video/igafb.c [new file with mode: 0644]
drivers/video/imsttfb.c
fs/buffer.c
fs/ext2/balloc.c
fs/ext2/namei.c
fs/lockd/clntlock.c
fs/namei.c
fs/ntfs/attr.c
fs/ntfs/dir.c
fs/ntfs/inode.c
fs/ntfs/super.c
fs/ntfs/util.c
fs/proc/procfs_syms.c
fs/ufs/balloc.c
fs/ufs/cylinder.c
fs/ufs/dir.c
fs/ufs/ialloc.c
fs/ufs/inode.c
fs/ufs/namei.c
fs/ufs/super.c
fs/ufs/util.c
fs/ufs/util.h
include/asm-alpha/asm_offsets.h
include/asm-alpha/console.h
include/asm-alpha/fcntl.h
include/asm-alpha/hardirq.h
include/asm-alpha/hwrpb.h
include/asm-alpha/io.h
include/asm-alpha/machvec.h
include/asm-alpha/processor.h
include/asm-alpha/spinlock.h
include/asm-alpha/system.h
include/asm-arm/fcntl.h
include/asm-i386/fcntl.h
include/asm-m68k/fcntl.h
include/asm-mips/fcntl.h
include/asm-ppc/fcntl.h
include/asm-sparc/fcntl.h
include/asm-sparc64/fcntl.h
include/linux/blk.h
include/linux/loop.h
include/linux/lp.h
include/linux/major.h
include/linux/mm.h
include/linux/parport.h
include/linux/parport_pc.h
include/linux/pci.h
include/linux/sdladrv.h
include/linux/ufs_fs.h
include/linux/ufs_fs_i.h
include/linux/ufs_fs_sb.h
include/linux/videodev.h
include/linux/wanrouter.h
include/video/fbcon.h
init/main.c
kernel/dma.c
kernel/ksyms.c
mm/filemap.c
mm/vmscan.c
net/netrom/af_netrom.c
net/netrom/nr_loopback.c
net/netrom/nr_route.c
scripts/lxdialog/menubox.c
scripts/lxdialog/textbox.c

diff --git a/CREDITS b/CREDITS
index c62d27fff55ad9681436b85ae1f9d5042f3b8e08..71bc5f768cfd181866b4c7c437c302b6596bd424 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1304,7 +1304,7 @@ S: Lafayette, Indiana 47905
 S: USA
 
 N: Johan Myreen
-E: jem@vipunen.hut.fi
+E: jem@iki.fi
 D: PS/2 mouse driver writer etc.
 S: Dragonvagen 1 A 13
 S: FIN-00330 Helsingfors
@@ -1852,6 +1852,18 @@ S: Schleiermacherstrasse 12
 S: 90491 Nuernberg
 S: Germany
 
+N: Geert Uytterhoeven
+E: geert@linux-m68k.org
+W: http://www.cs.kuleuven.ac.be/~geert/
+P: 1024/EC4A1EE1 8B 88 38 35 88 1E 95 A1  CD 9E AE DC 4B 4A 2F 41
+D: m68k/Amiga and PPC/CHRP Longtrail coordinator
+D: Frame buffer device and XF68_FBDev maintainer
+D: m68k IDE maintainer
+D: Amiga Zorro maintainer
+S: C. Huysmansstraat 12
+S: B-3128 Baal
+S: Belgium
+
 N: Petr Vandrovec
 E: vandrove@vc.cvut.cz
 D: Small contributions to ncpfs
@@ -1991,14 +2003,15 @@ S: 2612 XV Delft
 S: The Netherlands
 
 N: David Woodhouse
+E: Dave@mvhi.com
 E: Dave@imladris.demon.co.uk
 D: Extensive ARCnet rewrite
 D: ARCnet COM20020, COM90xx IO-MAP drivers
 D: SO_BINDTODEVICE in 2.1.x (from Elliot Poger's code in 2.0.31)
 D: Contributed to NCPFS rewrite for 2.1.x dcache
 D: Alpha platforms: SX164, LX164 and Ruffian ported to 2.1.x
-S: Robinson College, Grange Road
-S: Cambridge. CB3 9AN
+S: 29, David Bull Way
+S: Milton, Cambridge. CB4 6DP
 S: England
 
 N: Frank Xia
index 777476de4d2bccd2aa4727dd7d5224db40b60ae8..97aaf5be68b8423fbcc16894aa1e15a289a37e56 100644 (file)
@@ -33,7 +33,7 @@ http://cyberbuzz.gatech.edu/kaboom/linux/ as well.
    Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
 needs.
 
-Last updated: September 3, 1998
+Last updated: October 9, 1998
 Current Author: Chris Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu).
 
 Current Minimal Requirements
@@ -43,13 +43,14 @@ Current Minimal Requirements
 encountered a bug!  If you're unsure what version you're currently
 running, the suggested command should tell you.
 
-- Kernel modules        2.1.85                  ; insmod -V
+- Kernel modules        2.1.121                 ; insmod -V
 - Gnu C                 2.7.2.3                 ; gcc --version
 - Binutils              2.8.1.0.23              ; ld -v
-- Linux C Library       5.4.46                  ; ls -l /lib/libc.so.*
+- Linux libc5 C Library         5.4.46                  ; ls -l /lib/libc.so.*
+- Linux libc6 C Library  2.0.7pre6               ; ls -l /lib/libc.so.*
 - Dynamic Linker (ld.so) 1.9.9                   ; ldd --version or ldd -v
 - Linux C++ Library     2.7.2.8                 ; ls -l /usr/lib/libg++.so.*
-- Procps                1.2.8                   ; ps --version
+- Procps                1.2.9                   ; ps --version
 - Procinfo               14                      ; procinfo -v
 - Psmisc                17                      ; pstree -V
 - Mount                  2.7l                    ; mount --version
@@ -57,7 +58,7 @@ running, the suggested command should tell you.
 - Loadlin                1.6a
 - Sh-utils               1.16                    ; basename --v
 - Autofs                 0.3.11                  ; automount --version
-- NFS                    0.4.21                  ; showmount --version
+- NFS                    2.2beta37               ; showmount --version
 - Bash                   1.14.7                  ; bash -version
 - Ncpfs                  2.2.0                   ; ncpmount -v
 - Pcmcia-cs              3.0.5                   ; cardmgr -V
@@ -114,8 +115,8 @@ Linux ports, and it displays a spiffy penguin logo on boot-up ;-).  For
 more information, see the files in Documentation/fb/ ; you may also
 need to download the fbset utilities.
 
-Libc
-====
+Libc (libc5)
+============
 
    Linux-2.1.x is ELF-only.  You can still compile a.out apps if you
 really want, but your kernel must be compiled ELF.  If you can't
@@ -144,11 +145,25 @@ you're using NIS.
 accompanying release notes.  The section about it breaking make is not
 a joke.
 
+GNU libc (libc6)
+================
+
+   Older versions of GNU libc (libc6) have a bug in the dynamic linker.
+/etc/ld.so.cache gets mapped into memory and is never unmapped.  If one
+of your boot scripts calls ldconfig, /etc/ld.so.cache is deleted.  Init,
+however, still references that file; as of 2.1.122, the kernel will
+consequently not be able to remount the root file system r/o at system
+shutdown.  To fix this, upgrade to at least the pre6 release of GNU
+libc 2.0.7.  As a temporary workaround, modify your boot scripts to do
+the following before calling ldconfig:
+
+       ln -f /etc/ld.so.cache /etc/ld.so.cache.old
+
 Modules
 =======
 
-   You need to upgrade to modutils-2.1.85 for kernels 2.1.85 and later.
-This version will also work with 2.0.x kernels.
+   You need to upgrade to the latest version of modutils-2.1.x for
+development kernels.  This version will also work with 2.0.x kernels.
 
    As of 2.1.90-pre1, kerneld has been replaced by a kernel thread,
 kmod.  See Documentation/kmod.txt for more information.  The main
@@ -222,12 +237,12 @@ new /proc/net/dev format.  This will also provide support for new
 features like IPv6.
 
    As of 2.1.102, the IP firewalling code has been replaced; ipfwadm
-will no longer work.  You need to optain "ipchains," available from
+will no longer work.  You need to obtain "ipchains," available from
 http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html, and use
 that instead of ipfwadm.
 
-   To use port forwarding and auto forwarding you will need 'ipmasqadm'
-tool, available from http://juanjox.home.ml.org. 
+   To use port forwarding and auto forwarding you will need to obtain
+"ipmasqadm," available from http://juanjox.home.ml.org/.
 
 Memory
 ======
@@ -281,6 +296,13 @@ parallel port may no longer be where you expect it; for example, LPT1
 /dev/lp0 with the new Plug-and-Play driver.  If printing breaks with
 the new driver, try checking your lpd configuration.
 
+Setserial
+=========
+
+   If you experience random problems (stuck lines, lost characters,
+etc.) with serial lines under recent kernels, upgrading setserial
+should help.
+
 Syncookies
 ==========
 
@@ -351,35 +373,28 @@ Installation notes:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.8.1.0.23
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.8.1.0.23
 
-The 2.9.1.0.7 release:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.7-glibc.x86.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.7-libc5.x86.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.7.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.7-glibc.x86.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.7-libc5.x86.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.7.tar.gz
+The 2.9.1.0.12 release:
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.12-glibc.x86.tar.gz
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.12-libc5.x86.tar.gz
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.12.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.12-glibc.x86.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.12-libc5.x86.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.12.tar.gz
 Installation notes:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.9.1.0.7
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.9.1.0.7
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.9.1.0.12
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.9.1.0.12
 
 Gnu C
 =====
 
-The 2.7.2.3 release:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/gcc-2.7.2.3.bin.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.3.bin.tar.gz
-Installation notes:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.gcc-2.7.2.3
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.3
-
-The egcs-1.0.2 release:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/egcs-1.0.2-glibc.x86.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/egcs-1.0.2-libc5.x86.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/egcs-1.0.2-glibc.x86.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/egcs-1.0.2-libc5.x86.tar.gz
+The egcs-1.0.3 release:
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/egcs-1.0.3-glibc.x86.tar.bz2
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/egcs-1.0.3-libc5.x86.tar.bz2
+ftp://sunsite.unc.edu/pub/Linux/GCC/egcs-1.0.3-glibc.x86.tar.bz2
+ftp://sunsite.unc.edu/pub/Linux/GCC/egcs-1.0.3-libc5.x86.tar.bz2
 Installation notes:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.egcs-1.0.2
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.egcs-1.0.2
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.egcs-1.0.3
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.egcs-1.0.3
 
 Gnu C 2.7.2.3 source:
 ftp://prep.ai.mit.edu/pub/gnu/gcc-2.7.2.3.tar.gz
@@ -388,13 +403,17 @@ ftp://sunsite.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz
 Linux C Library
 ===============
 
-The 5.4.46 release:
+The (libc5) 5.4.46 release:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libc-5.4.46.bin.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.46.bin.tar.gz
 Installation notes for 5.4.46:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libc-5.4.46
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.46
 
+The (libc6) GNU libc 2.0.7pre6 release:
+ftp://ftp.kernel.org/pub/software/libs/glibc/glibc-2.0.7pre6.tar.gz
+ftp://ftp.kernel.org/pub/software/libs/glibc/glibc-2.0.7pre6.tar.bz2
+
 Linux C++ Library
 =================
 
@@ -415,15 +434,15 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.9.9.tar.gz
 Modules utilities
 =================
 
-The 2.1.85 release:
-ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.85.tar.gz
+The 2.1.121 release:
+ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.121.tar.gz
 
 Procps utilities
 ================
 
 The 1.2 release:
-ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/procps-1.2.8.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/system/status/ps/procps-1.2.8.tgz
+ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/procps-1.2.9.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/system/status/ps/procps-1.2.9.tgz
 
 Procinfo utilities
 ==================
@@ -454,8 +473,9 @@ ftp://ftp.redhat.com/pub/redhat/old-releases/redhat-4.0/updates/sparc/rpm-devel-
 DOSEMU
 ======
 
-The 0.66.7 release:
-ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.66.7.tgz
+The 0.98.1 release:
+ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.1.tgz
+ftp://ftp.dosemu.org/dosemu/dosemu-0.98.1.tgz
 
 Loadlin
 =======
@@ -486,12 +506,13 @@ ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-3.1.1.tar.gz
 NFS
 ===
 
-The user-land 0.4.21 release:
-ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/linux-nfs-0.4.21.tar.gz
-ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/linux-nfs-0.4.21.tar.gz
+The user-land 2.2beta37 release:
+ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta37.tar.gz
+ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta37.tar.gz
 
-The kernel-level 8/30/98 release:
-ftp://ftp.yggdrasil.com/private/hjl/knfsd-980830.tar.gz
+The kernel-level 9/30/98 release:
+ftp://ftp.yggdrasil.com/private/hjl/knfsd-980930.tar.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-980930.tar.gz
 
 Net-tools
 =========
@@ -530,6 +551,13 @@ Pcmcia-cs
 The 3.0.5 release:
 ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.5.tar.gz
 
+Setserial
+=========
+
+The 2.14 release:
+ftp://tsx-11.mit.edu/pub/linux/sources/sbin/setserial-2.14.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/system/serial/setserial-2.14.tar.gz
+
 PPP
 ===
 
@@ -545,6 +573,7 @@ http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.bz2
 
 IP Masq Adm
 ===========
+
 The 0.4.1 release:
 http://juanjox.home.ml.org/ipmasqadm-0.4.1.tar.gz
 
@@ -581,12 +610,12 @@ distribution), most of these are available in RPM format.  Check around
 your favorite Red Hat mirror site before installing the non-RPM
 version.  Remember, you might need to use the -force option to get the
 upgrade to install.  ftp://ftp.redhat.com/pub/contrib/ will have almost
-everything you need, as does Red Hat 5.0.
+everything you need, and Red Hat 5.1 ships with most necessary software.
 
    Those of you running Debian (or a different distribution that
 supports .deb packages) can look in the "unstable" and
 "project/experimental" directories of your favorite Debian mirror.  The
-Debian 2.0 release should have most packages you need as well.
+Debian 2.0 release ships with most packages you need as well.
 
    For others, David Bourgin has put together a package of everything
 necessary to quickly and easily upgrade to 2.1.x.  See
index 49ff4e20f5894fbeb1609f0a09940fc14ceafa8c..a1cb8593826568aea74e0b1e9b340d3e76a9d521 100644 (file)
@@ -1196,15 +1196,6 @@ CONFIG_HUB6
   Say Y here to enable support in the dumb serial driver to support
   the HUB6 card.
 
-TGA Console Support
-CONFIG_TGA_CONSOLE
-  Many Alpha systems (e.g the Multia) are shipped with a graphics card
-  that implements the TGA interface (much like the VGA standard, but
-  older TGA adapters are *not* VGA compatible).  On such systems, you
-  should say Y here so that the TGA driver rather than the standard
-  VGA driver is used.  Note that, at this time, there is no X server
-  for these systems. If unsure, try N.
-
 PCI support
 CONFIG_PCI
   Find out whether you have a PCI motherboard. PCI is the name of a
@@ -3217,6 +3208,16 @@ CONFIG_NETLINK_DEV
   This is a backward compatibility option, choose Y for now.
   This option will be removed soon.
 
+HIgh Performance Parallel Interface support (EXPERIMENTAL)
+CONFIG_HIPPI
+  HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
+  1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
+  can run over copper (25m) or fiber (300m on multi-mode or 10km on
+  single-mode). If you are connected to a HIPPI network, and want
+  to enable HIPPI support in the kernel, say Y here (you must also
+  remember to enable the driver for your HIPPI card below). Most
+  people will say N here.
+
 SCSI support?
 CONFIG_SCSI
   If you want to use a SCSI hard disk, SCSI tape drive, SCSI CDROM or
@@ -5312,7 +5313,7 @@ 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!
+  please mail David.Woodhouse@mvhi.com, especially if it works!
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you
@@ -8187,7 +8188,7 @@ CONFIG_SOUND
   say more than an occasional beep, by programming the PC speaker.
   Kernel patches and programs to do that are in the pcsndrv package on
   ftp://sunsite.unc.edu/pub/Linux/kernel/patches/console/ and in the
-  pcsp patch at ftp://dwmw2.robinson.cam.ac.uk/pub/kernel/ .
+  pcsp patch at http://www.imladris.demon.co.uk/pcsp/
 
 OSS sound modules
 CONFIG_SOUND_OSS
@@ -9261,7 +9262,7 @@ CONFIG_TT_DMA_EMUL
 
 Ariadne support
 CONFIG_ARIADNE
-  If you have a VillageTronics Ariadne Ethernet adapter, say Y.
+  If you have a Village Tronic Ariadne Ethernet adapter, say Y.
   Otherwise, say N.
 
   This driver is also available as a module ( = code which can be
@@ -9271,7 +9272,7 @@ CONFIG_ARIADNE
 
 Ariadne II support
 CONFIG_ARIADNE2
-  If you have a VillageTronics Ariadne II Ethernet adapter, say Y.
+  If you have a Village Tronic Ariadne II Ethernet adapter, say Y.
   Otherwise, say N.
 
   This driver is also available as a module ( = code which can be
@@ -9745,6 +9746,46 @@ CONFIG_VIDC_SOUND
   Say 'Y' here for ARM systems with the VIDC video controller and 16-bit
   Linear sound DACs.  If unsure, say N.
 
+Backward compatibility mode for Xpmac
+CONFIG_FB_COMPAT_XPMAC
+  If you use the Xpmac X server (common with mklinux), you'll need
+  to enable this to use X. You should consider changing to XFree86
+  which includes a server that supports the frame buffer device
+  directly (XF68_FBDev).
+
+Support for PowerMac keyboard
+CONFIG_MAC_KEYBOARD
+  This option allows you to use an ADB keyboard attached to your
+  machine. Note that this disables any other (ie. PS/2) keyboard
+  support, even if your machine is physically capable of using both
+  at the same time.
+  
+  If you use an ADB keyboard (4 pin connector), say Y here.
+  If you use a PS/2 keyboard (6 pin connector), say N here.
+
+Support for PowerMac floppy
+CONFIG_MAC_FLOPPY
+  If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
+  floppy controller, say Y here. Most commonly found in PowerMacs.
+
+Support for PowerMac serial ports
+CONFIG_MAC_SERIAL
+  If you have Macintosh style serial ports (8 pin mini-DIN), this
+  is the driver for them. If you also have regular serial ports
+  and enable the driver for them, you can't currently use the
+  serial console feature.
+
+Support for PowerMac ADB mouse
+CONFIG_ADBMOUSE
+  If you have an ADB mouse (4 pin connector) as is common on
+  Macintoshes, say Y here.
+
+Winbond SL82c105 support
+CONFIG_BLK_DEV_SL82C105
+  If you have a Winbond SL82c105 IDE controller, say Y here to
+  enable special configuration for this chip. This is common
+  on various CHRP motherboards, but could be used elsewhere.
+  If in doubt, say Y.
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DMA, FTP, Internet, Intel, IRQ, 
@@ -9853,7 +9894,7 @@ CONFIG_VIDC_SOUND
 # LocalWords:  INSNS Ataris AutoConfig ZORRO OCS AMIFB Agnus Denise ECS CDTV GB
 # LocalWords:  AGA Cybervision CYBER GSP TMS DMI Zorro ACSI ROMs SLM BioNet GVP
 # LocalWords:  PAMsNet TekMagic Cyberstorm MkI CYBERSTORMII MkII BLZ onboard cx
-# LocalWords:  VillageTronics ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB
+# LocalWords:  Village Tronic ATARILANCE RieblCard PAMCard VME MFP sangoma LAPB
 # LocalWords:  Rhotron BioData's Multiface AMIGAMOUSE COPCON Amiga's bitplanes
 # LocalWords:  ATARIMOUSE MFPSER SCC's MegaSTE ESCC Atari's GVPIOEXT DMASOUND
 # LocalWords:  fdutils cisco univercd rpcg htm iface lapb LAPBETHER tpqic qic
index 6cd33d720d07d7e3ee4f7c95b0a39332feb75589..d4ed9cabeecb27d62b2de613a236f7ceaaafdd68 100644 (file)
@@ -11,4 +11,5 @@ smp.txt
        - use and state info about Linux/PPC on MP machines
 sound.txt
        - info on sound support under Linux/PPC
-
+zImage_layout.txt
+       - info on the kernel images for Linux/PPC
index d65dfae1964106c4f9091d3bed3b44da160978f9..e7b078e54b27c7be4c42756e910c77f23c9ba420 100644 (file)
@@ -5,7 +5,7 @@ This document and the related code was written by me
 (Cort Dougan, cort@cs.nmt.edu) please email me if you have questions,
 comments or corrections.
 
-Last Change: 4.1.98
+Last Change: 10.8.98
 
 SMP support for Linux/PPC is still in its early stages and likely to
 be buggy for a while.  If you want to help by writing code or testing
@@ -13,7 +13,7 @@ different hardware please email me!
 
 1. State of Supported Hardware
 
-  PowerSurge Architecture - UMAX s900, Apple 9500/9600/8500/8600/7500/7600
+  PowerSurge Architecture - tested on UMAX s900, Apple 9600
     The second processor on this machine boots up just fine and
     enters its idle loop.  Hopefully a completely working SMP kernel
     on this machine will be done shortly.
@@ -22,7 +22,9 @@ different hardware please email me!
     necessary to work with any number would not be overly difficult but
     I don't have any machines with >2 processors so it's not high on my
     list of priorities.  If anyone else would like do to the work email
-    me and I can point out the places that need changed.
+    me and I can point out the places that need changed.  If you have >2
+    processors and don't want to add support yourself let me know and I
+    can take a look into it.
 
   BeBox
     BeBox support hasn't been added to the 2.1.X kernels from 2.0.X
index 8f4a440347ad57bf89afd1750fa8a39a486e4c98..c028e35f1f6cb7f1052c4989a8a175dfc4fa070c 100644 (file)
@@ -1,7 +1,7 @@
             Information about PowerPC Sound support
 =====================================================================
 
-Please mail me me (Cort Dougan, cort@cs.nmt.edu) if you have questions,
+Please mail me (Cort Dougan, cort@cs.nmt.edu) if you have questions,
 comments or corrections.
 
 Last Change: 3.24.98
diff --git a/Documentation/powerpc/zImage_layout.txt b/Documentation/powerpc/zImage_layout.txt
new file mode 100644 (file)
index 0000000..a96517e
--- /dev/null
@@ -0,0 +1,47 @@
+          Information about the Linux/PPC kernel images
+=====================================================================
+
+Please mail me me (Cort Dougan, cort@cs.nmt.edu) if you have questions,
+comments or corrections.
+
+This document is meant to answer several questions I've had about how
+the PReP system boots and how Linux/PPC interacts with that mechanism.
+It would be nice if we could have information on how other architectures
+boot here as well.  If you have anything to contribute, please
+let me know.
+
+
+1. PReP boot file
+
+  This is the file necessary to boot PReP systems from floppy or
+  hard drive.  The firmware reads the PReP partition table entry
+  and will load the image accordingly.
+
+  To boot the zImage, copy it onto a floppy with dd if=zImage of=/dev/fd0h1440
+  or onto a PReP hard drive partition with dd if=zImage of=/dev/sda4
+  assuming you've created a PReP partition (type 0x41) with fdisk on
+  /dev/sda4.
+
+  The layout of the image format is:
+
+  0x0     +------------+
+          |            | PReP partition table entry
+          |            |
+  0x400   +------------+
+          |            | Bootstrap program code + data
+          |            |
+          |            |
+          +------------+
+          |            | compressed kernel, elf header removed
+          +------------+
+          |            | initrd (if loaded)
+          +------------+
+          |            | Elf section table for bootstrap program
+          +------------+
+
+
+2. MBX boot file
+
+  The MBX boards can load an elf image, and relocate it to the
+  proper location in memory - it copies the image to the location it was
+  linked at.
index 4d4313134b5a9a733e4adbd1e5eef96372c101eb..20284de9fa51af1b6a6161cf97b075fdd6b271aa 100644 (file)
-Getting Firmware
-~~~~~~~~~~~~~~~~
-
-See the end of this document on how to obtain and create the necessary
-firmware files.
-
-
-Supported Features
-~~~~~~~~~~~~~~~~~~
-
-Currently digital audio and mixer functionality is supported.  (memory
-mapped digital audio is not yet supported).  Modular MultiSound
-support is composed of the following modules:
-
-msnd           - MultiSound base (requires soundcore)
-msnd_classic   - Base audio/mixer support for Classic, Monetery and
-                  Tahiti cards
-msnd_pinnacle  - Base audio/mixer support for Pinnacle and Fiji cards
-
-
-Important Notes - Read Before Using
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* The firmware files are not included (may change in future).  You
-must obtain these images from Turtle Beach (they are included in the
-MultiSound Development Kits), and place them in /etc/sound for
-example, and give the full paths in the Linux configuration.  Please
-note these files must be binary files, not assembler.
-
-* You need the following information to use this driver: the card's
-I/O base (i.e. 0x250), the IRQ (i.e. 5), and the shared memory area
-(i.e. 0xd8000).
-
-* Probing is not currently implemented, and only the msnd_classic
-driver will actually program the card's IRQ and SMA locations; the
-msnd_pinnacle is primarily for use with the card in PnP mode, however
-it should work if you know what the card's resource values are (this
-will change in the future).
-
-* Note the Turtle Beach Pinnacle card contains a Kurzweil MA-1
-synthesizer with an MPU compatible interface, which should work with
-the mpu401 module.  You must know the resource values of the MA-1.
-
-
-Examples
-~~~~~~~~
-
-* If you have a MultiSound Classic/Monterey/Tahiti:
-
-insmod soundcore
-insmod msnd
-insmod msnd_classic io=0x290 irq=7 mem=0xd0000
-
-* If you have a MultiSound Pinnacle:
-
-insmod soundcore
-insmod msnd
-insmod msnd_pinnacle io=0x210 irq=5 mem=0xd8000
-
-* To use the MPU-compatible Kurzweil synth on the Pinnacle, add the
-following:
-
-insmod sound
-insmod mpu401 io=0x330 irq=9
-
-
-msnd_classic, msnd_pinnacle Required Options
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If the following options are not given, the module will not load.
-Examine the kernel message log for informative error messages.
-WARNING--probing isn't supported so try to make sure you have the
-correct shared memory area, otherwise you may experience problems.
-
-io                     I/O base of DSP, e.g. io=0x210
-irq                    IRQ number, e.g. irq=5
-mem                    Shared memory area, e.g. mem=0xd8000
-
-
-msnd_classic, msnd_pinnacle Additional Options
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-fifosize               The digital audio FIFOs, in kilobytes.  The
-                       default is 64kB (two FIFOs are allocated, so
-                       this uses up 128kB).
-
-calibrate_signal       Setting this to one calibrates the ADCs to the
-                       signal, zero calibrates to the card (defaults
-                       to zero).
-
-
-msnd_pinnacle Additional Options
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-digital                        Specify digital=1 to enable the S/PDIF input
-                       if you have the digital daughterboard
-                       adapter. This will enable access to the
-                       DIGITAL1 input for the soundcard in the mixer.
-                       Some mixer programs might have trouble setting
-                       the DIGITAL1 source as an input.  If you have
-                       trouble, you can try the setdigital.c program
-                       at the bottom of this document.
-
-
-Obtaining and Creating Firmware Files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-       For the Classic/Tahiti/Monterey
-       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
-
-Download to /tmp and unzip the following file from Turtle Beach:
-
-       ftp://ftp.tbeach.com/pub/tbs/pinn/msndvkit.zip
-
-When unzipped, unzip the file named MsndFiles.zip.  Then copy the
-following firmware files to /etc/sound (note the file renaming):
-
-  cp DSPCODE/MSNDINIT.BIN /etc/sound/msndinit.bin
-  cp DSPCODE/MSNDPERM.REB /etc/sound/msndperm.bin
-
-When configuring the Linux kernel, specify /etc/sound/msndinit.bin and
-/etc/sound/msndperm.bin for the two firmware files (Linux kernel
-versions older than 2.2 do not ask for firmware paths, and are
-hardcoded to /etc/sound).
-
-
-       For the Pinnacle/Fiji
-       ~~~~~~~~~~~~~~~~~~~~~
-
-Download to /tmp and unzip the following file from Turtle Beach (be
-sure to use the entire URL; some have had trouble navigating to the
-URL):
-
-       ftp://ftp.tbeach.com/oldpub/tbs/pinn/pnddk100.zip
-
-Put the following lines into a file named conv.l (between the start
-and end lines):
-
--- conv.l start --
-%%
-[ \n\t,\r]
-\;.*
-DB
-[0-9A-Fa-f]+H  { int n; sscanf(yytext, "%xH", &n); printf("%c", n); }
--- conv.l end --
-
-Then, compile the conv program with GNU make with the following
-command:
-
-  make LEX=flex LOADLIBES=-lfl conv
-
-This should give you an executable named conv.  Now, we create the
-binary firmware files by doing the following conversion (assuming the
-archive unpacked into a directory named PINNDDK):
-
-  ./conv < PINNDDK/dspcode/pndspini.asm > /etc/sound/pndspini.bin
-  ./conv < PINNDDK/dspcode/pndsperm.asm > /etc/sound/pndsperm.bin
-
-The conv (and conv.l) program is not needed after conversion and can
-be safely deleted.  Then, when configuring the Linux kernel, specify
-/etc/sound/pndspini.bin and /etc/sound/pndsperm.bin for the two
-firmware files (Linux kernel versions older than 2.2 do not ask for
-firmware paths, and are hardcoded to /etc/sound).
-
-
-Recording from the S/PDIF Input
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you have a Pinnacle or Fiji with S/PDIF input and want to set it as
-the input source, you can use this program if you have trouble trying
-to do it with a mixer program (be sure to insert the module with the
-digital=1 option).
-
-Compile with:
-cc -O setdigital.c -o setdigital
-
--- start setdigital.c --
+#! /bin/sh
+#
+#  Turtle Beach MultiSound Driver Notes
+#  -- Andrew Veliath <andrewtv@usa.net>
+#
+#  Last update:                      September 10, 1998
+#  Corresponding msnd driver:        0.8.2
+#
+# ** This file is a README (top part) and shell archive (bottom part).
+#    The corresponding archived utility sources can be unpacked by
+#    running `sh MultiSound' (the utilities are only needed for the
+#    Pinnacle and Fiji cards). **
+#
+#
+#  -=-=- Getting Firmware -=-=-
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#  
+#  See the section `Obtaining and Creating Firmware Files' in this
+#  document for instructions on obtaining the necessary firmware
+#  files.
+#  
+#  
+#  Supported Features
+#  ~~~~~~~~~~~~~~~~~~
+#  
+#  Currently, full-duplex digital audio (/dev/dsp only, /dev/audio is
+#  not currently available) and mixer functionality (/dev/mixer) are
+#  supported (memory mapped digital audio is not yet supported).
+#  Digital transfers and monitoring can be done as well if you have
+#  the digital daughterboard (see the section on using the S/PDIF port
+#  for more information).
+#
+#  Support for the Turtle Beach MultiSound Hurricane architecture is
+#  composed of the following modules (these can also operate compiled
+#  into the kernel):
+#  
+#  msnd               - MultiSound base (requires soundcore)
+#
+#  msnd_classic       - Base audio/mixer support for Classic, Monetery and
+#                       Tahiti cards
+#
+#  msnd_pinnacle      - Base audio/mixer support for Pinnacle and Fiji cards
+#  
+#  
+#  Important Notes - Read Before Using
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#  
+#  The firmware files are not included (may change in future).  You
+#  must obtain these images from Turtle Beach (they are included in
+#  the MultiSound Development Kits), and place them in /etc/sound for
+#  example, and give the full paths in the Linux configuration.  If
+#  you are compiling in support for the MultiSound driver rather than
+#  using it as a module, these firmware files must be accessible
+#  during kernel compilation.
+#
+#  Please note these files must be binary files, not assembler.  See
+#  the section later in this document for instructions to obtain these
+#  files.
+#  
+#  
+#  Configuring Card Resources
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#  ** This section is very important, as your card may not work at all
+#     or your machine may crash if you do not do this correctly. **
+#
+#  * Classic/Monterey/Tahiti
+#  
+#  These cards are configured through the driver msnd_classic.  You must
+#  know the io port, then the driver will select the irq and memory resources
+#  on the card.  It is up to you to know if these are free locations or now,
+#  a conflict can lock the machine up.
+#
+#  * Pinnacle/Fiji
+#
+#  The Pinnacle and Fiji cards have an extra config port, either
+#  0x250, 0x260 or 0x270.  This port can be disabled to have the card
+#  configured strictly through PnP, however you lose the ability to
+#  access the IDE controller and joystick devices on this card when
+#  using PnP.  The included pinnaclecfg program in this shell archive
+#  can be used to configure the card in non-PnP mode, and in PnP mode
+#  you can use isapnptools.  These are described briefly here.
+#
+#  pinnaclecfg is not required; you can use the msnd_pinnacle module
+#  to fully configure the card as well.  However, pinnaclecfg can be
+#  used to change the resource values of a particular device after the
+#  msnd_pinnacle module has been loaded.  If you are compiling the
+#  driver into the kernel, you must set these values during compile
+#  time, however other peripheral resource values can be changed with
+#  the pinnaclecfg program after the kernel is loaded.
+#
+#
+#  *** PnP mode
+#  
+#  Use pnpdump to obtain a sample configuration if you can; I was able
+#  to obtain one with the command `pnpdump 1 0x203' -- this may vary
+#  for you (running pnpdump by itself did not work for me).  Then,
+#  edit this file and use isapnp to uncomment and set the card values.
+#  Use these values when inserting the msnd_pinnacle module.  Using
+#  this method, you can set the resources for the DSP and the Kurzweil
+#  synth (Pinnacle).  Since Linux does not directly support PnP
+#  devices, you may have difficulty when using the card in PnP mode
+#  when it the driver is compiled into the kernel.  Using non-PnP mode
+#  is preferable in this case.
+#
+#  Here is an example mypinnacle.conf for isapnp that sets the card to
+#  io base 0x210, irq 5 and mem 0xd8000, and also sets the Kurzweil
+#  synth to 0x330 and irq 9 (may need editing for your system):
+#
+#  (READPORT 0x0203)
+#  (CSN 2)
+#  (IDENTIFY *)
+#  
+#  # DSP
+#  (CONFIGURE BVJ0440/-1 (LD 0
+#          (INT 0 (IRQ 5 (MODE +E))) (IO 0 (BASE 0x0210)) (MEM 0 (BASE 0x0d8000))
+#          (ACT Y)))
+#  
+#  # Kurzweil Synth (Pinnacle Only)
+#  (CONFIGURE BVJ0440/-1 (LD 1
+#          (IO 0 (BASE 0x0330)) (INT 0 (IRQ 9 (MODE +E)))
+#          (ACT Y)))
+#  
+#  (WAITFORKEY)
+#
+#
+#  *** Non-PnP mode
+#  
+#  The second way is by running the card in non-PnP mode.  This
+#  actually has some advantages in that you can access some other
+#  devices on the card, such as the joystick and IDE controller.  To
+#  configure the card, unpack this shell archive and build the
+#  pinnaclecfg program.  Using this program, you can assign the
+#  resource values to the card's devices, or disable the devices.  As
+#  an alternative to using pinnaclecfg, you can specify many of the
+#  configuration values when loading the msnd_pinnacle module (or
+#  during kernel configuration when compiling the driver into the
+#  kernel).
+#
+#  If you specify cfg=0x250 for the msnd_pinnacle module, it
+#  automatically configure the card to the given io, irq and memory
+#  values using that config port (the config port is jumper selectable
+#  on the card to 0x250, 0x260 or 0x270).
+#
+#  See the `msnd_pinnacle Additional Options' section below for more
+#  information on these parameters (also, if you compile the driver
+#  directly into the kernel, these extra parameters can be useful
+#  here).
+#
+#
+# ** It is very easy to cause problems in your machine if you choose a
+#    resource value which is incorrect. **
+#  
+#
+#  Examples
+#  ~~~~~~~~
+#  
+#  * MultiSound Classic/Monterey/Tahiti:
+#  
+#  insmod soundcore
+#  insmod msnd
+#  insmod msnd_classic io=0x290 irq=7 mem=0xd0000
+#  
+#  * MultiSound Pinnacle in PnP mode:
+#  
+#  insmod soundcore
+#  insmod msnd
+#  isapnp mypinnacle.conf
+#  insmod msnd_pinnacle io=0x210 irq=5 mem=0xd8000 <-- match mypinnacle.conf values
+#  
+#  * MultiSound Pinnacle in non-PnP mode (replace 0x250 with your configuration port,
+#    one of 0x250, 0x260 or 0x270):
+#  
+#  insmod soundcore
+#  insmod msnd
+#  insmod msnd_pinnacle cfg=0x250 io=0x290 irq=5 mem=0xd0000
+#  
+# * To use the MPU-compatible Kurzweil synth on the Pinnacle in PnP
+#   mode, add the following (assumes you did `isapnp mypinnacle.conf'):
+#  
+#  insmod sound
+#  insmod mpu401 io=0x330 irq=9                    <-- match mypinnacle.conf values
+#  
+# * To use the MPU-compatible Kurzweil synth on the Pinnacle in non-PnP
+#   mode, add the following.  Note how we first configure the peripheral's
+#   resources, _then_ install a Linux driver for it:
+#  
+#  insmod sound
+#  pinnaclecfg 0x250 mpu 0x330 9
+#  insmod mpu401 io=0x330 irq=9
+#
+#  -- OR you can use the following sequence without pinnaclecfg in non-PnP mode:
+#
+#  insmod soundcore
+#  insmod msnd
+#  insmod msnd_pinnacle cfg=0x250 io=0x290 irq=5 mem=0xd0000 mpu_io=0x330 mpu_irq=9
+#  insmod sound
+#  insmod mpu401 io=0x330 irq=9
+#
+# * To setup the joystick port on the Pinnacle in non-PnP mode (though
+#   you have to find the actual Linux joystick driver elsewhere), you
+#   can use pinnaclecfg:
+#
+#   pinnaclecfg 0x250 joystick 0x200
+#
+#  -- OR you can configure this using msnd_pinnacle with the following:
+#
+#  insmod soundcore
+#  insmod msnd
+#  insmod msnd_pinnacle cfg=0x250 io=0x290 irq=5 mem=0xd0000 joystick_io=0x200
+#
+#  
+#  msnd_classic, msnd_pinnacle Required Options
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#  
+#  If the following options are not given, the module will not load.
+#  Examine the kernel message log for informative error messages.
+#  WARNING--probing isn't supported so try to make sure you have the
+#  correct shared memory area, otherwise you may experience problems.
+#  
+#  io                   I/O base of DSP, e.g. io=0x210
+#  irq                  IRQ number, e.g. irq=5
+#  mem                  Shared memory area, e.g. mem=0xd8000
+#  
+#  
+#  msnd_classic, msnd_pinnacle Additional Options
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#  
+#  fifosize             The digital audio FIFOs, in kilobytes.  If not
+#                       specified, the default will be used.  Increasing
+#                       this value will reduce the chance of a FIFO
+#                       underflow at the expense of increasing overall
+#                       latency.  For example, fifosize=512 will
+#                       allocate 512kB read and write FIFOs (1MB total).
+#                       While this may reduce dropouts, a heavy machine
+#                       load will undoubtedly starve the FIFO of data
+#                       and you will eventually get dropouts.  One
+#                       option is to alter the scheduling priority of
+#                       the playback process, using `nice' or some form
+#                       of POSIX soft real-time scheduling.
+#
+#  calibrate_signal     Setting this to one calibrates the ADCs to the
+#                       signal, zero calibrates to the card (defaults
+#                       to zero).
+#  
+#  
+#  msnd_pinnacle Additional Options
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#  digital              Specify digital=1 to enable the S/PDIF input
+#                       if you have the digital daughterboard
+#                       adapter. This will enable access to the
+#                       DIGITAL1 input for the soundcard in the mixer.
+#                       Some mixer programs might have trouble setting
+#                       the DIGITAL1 source as an input.  If you have
+#                       trouble, you can try the setdigital.c program
+#                       at the bottom of this document.
+#
+#  cfg                  Non-PnP configuration port for the Pinnacle
+#                       and Fiji (typically 0x250, 0x260 or 0x270,
+#                       depending on the jumper configuration).  If
+#                       this option is omitted, then it is assumed
+#                       that the card is in PnP mode, and that the
+#                       specified DSP resource values are already
+#                       configured with PnP (i.e. it won't attempt to
+#                       do any sort of configuration).
+#
+#  When the Pinnacle is in non-PnP mode, you can use the following
+#  options to configure particular devices.  If a full specification
+#  for a device is not given, then the device is not configured.  Note
+#  that you still must use a Linux driver for any of these devices
+#  once their resources are setup (such as the Linux joystick driver,
+#  or the MPU401 driver from OSS for the Kurzweil synth).
+#
+#  mpu_io               I/O port of MPU (on-board Kurzweil synth)
+#  mpu_irq              IRQ of MPU (on-board Kurzweil synth)
+#  ide_io0             First I/O port of IDE controller
+#  ide_io1             Second I/O port of IDE controller
+#  ide_irq             IRQ IDE controller
+#  joystick_io          I/O port of joystick
+#  
+#  
+#  Obtaining and Creating Firmware Files
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#  
+#       For the Classic/Tahiti/Monterey
+#       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+#  
+#  Download to /tmp and unzip the following file from Turtle Beach:
+#  
+#       ftp://ftp.voyetra.com/pub/tbs/msndcl/msndvkit.zip
+#  
+#  When unzipped, unzip the file named MsndFiles.zip.  Then copy the
+#  following firmware files to /etc/sound (note the file renaming):
+#  
+#    cp DSPCODE/MSNDINIT.BIN /etc/sound/msndinit.bin
+#    cp DSPCODE/MSNDPERM.REB /etc/sound/msndperm.bin
+#  
+#  When configuring the Linux kernel, specify /etc/sound/msndinit.bin and
+#  /etc/sound/msndperm.bin for the two firmware files (Linux kernel
+#  versions older than 2.2 do not ask for firmware paths, and are
+#  hardcoded to /etc/sound).
+#
+#  If you are compiling the driver into the kernel, these files must
+#  be accessible during compilation, but will not be needed later.
+#  The files must remain, however, if the driver is used as a module.
+#  
+#  
+#       For the Pinnacle/Fiji
+#       ~~~~~~~~~~~~~~~~~~~~~
+#  
+#  Download to /tmp and unzip the following file from Turtle Beach (be
+#  sure to use the entire URL; some have had trouble navigating to the
+#  URL):
+#  
+#       ftp://ftp.voyetra.com/pub/tbs/pinn/pnddk100.zip
+#
+#  Unpack this shell archive, and run make in the created directory
+#  (you need a C compiler and flex to build the utilities).  This
+#  should give you the executables conv, pinnaclecfg and setdigital.
+#  conv is only used temporarily here to create the firmware files,
+#  while pinnaclecfg is used to configure the Pinnacle or Fiji card in
+#  non-PnP mode, and setdigital can be used to set the S/PDIF input on
+#  the mixer (pinnaclecfg and setdigital should be copied to a
+#  convenient place, possibly run during system initialization).
+#
+#  To generating the firmware files with the `conv' program, we create
+#  the binary firmware files by doing the following conversion
+#  (assuming the archive unpacked into a directory named PINNDDK):
+#  
+#    ./conv < PINNDDK/dspcode/pndspini.asm > /etc/sound/pndspini.bin
+#    ./conv < PINNDDK/dspcode/pndsperm.asm > /etc/sound/pndsperm.bin
+#  
+#  The conv (and conv.l) program is not needed after conversion and can
+#  be safely deleted.  Then, when configuring the Linux kernel, specify
+#  /etc/sound/pndspini.bin and /etc/sound/pndsperm.bin for the two
+#  firmware files (Linux kernel versions older than 2.2 do not ask for
+#  firmware paths, and are hardcoded to /etc/sound).
+#  
+#  If you are compiling the driver into the kernel, these files must
+#  be accessible during compilation, but will not be needed later.
+#  The files must remain, however, if the driver is used as a module.
+#
+#  
+#  Using Digital I/O with the S/PDIF Port
+#  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#  If you have a Pinnacle or Fiji with the digital daughterboard and
+#  want to set it as the input source, you can use this program if you
+#  have trouble trying to do it with a mixer program (be sure to
+#  insert the module with the digital=1 option, or say Y to the option
+#  during compiled-in kernel operation).  Upon selection of the S/PDIF
+#  port, you should be able monitor and record from it.
+#
+#  There is something to note about using the S/PDIF port.  Digital
+#  timing is taken from the digital signal, so if a signal is not
+#  connected to the port and it is selected as recording input, you
+#  will find PCM playback to be distorted in playback rate.  Also,
+#  attempting to record at a sampling rate other than the DAT rate may
+#  be problematic (i.e. trying to record at 8000Hz when the DAT signal
+#  is 44100Hz).  If you have a problem with this, set the recording
+#  input to the line in if you need to record at a rate other than
+#  that of the DAT rate.
+#
+#
+#  -- Shell archive attached below, just run `sh MultiSound' to extract.
+#     Contains Pinnacle/Fiji utilities to convert firmware, configure
+#     in non-PnP mode, and select the DIGITAL1 input for the mixer.
+#
+#
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 1998-09-05 08:26 EDT by <andrewtv@ztransform.velsoft.com>.
+# Source directory was `/home/andrewtv/programming/pinnacle/pinnacle'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode       name
+# ------ ---------- ------------------------------------------
+#   2111 -rw-rw-r-- MultiSound.d/setdigital.c
+#  10301 -rw-rw-r-- MultiSound.d/pinnaclecfg.c
+#     96 -rw-rw-r-- MultiSound.d/Makefile
+#    141 -rw-rw-r-- MultiSound.d/conv.l
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+     && ($dir/gettext --version >/dev/null 2>&1)
+  then
+    set `$dir/gettext --version 2>&1`
+    if test "$3" = GNU
+    then
+      gettext_dir=$dir
+    fi
+  fi
+  if test "$locale_dir" = FAILED && test -f $dir/shar \
+     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+  then
+    locale_dir=`$dir/shar --print-text-domain-dir`
+  fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+  echo=echo
+else
+  TEXTDOMAINDIR=$locale_dir
+  export TEXTDOMAINDIR
+  TEXTDOMAIN=sharutils
+  export TEXTDOMAIN
+  echo="$gettext_dir/gettext -s"
+fi
+touch -am 1231235999 $$.touch >/dev/null 2>&1
+if test ! -f 1231235999 && test -f $$.touch; then
+  shar_touch=touch
+else
+  shar_touch=:
+  echo
+  $echo 'WARNING: not restoring timestamps.  Consider getting and'
+  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+  echo
+fi
+rm -f 1231235999 $$.touch
+#
+if mkdir _sh21233; then
+  $echo 'x -' 'creating lock directory'
+else
+  $echo 'failed to create lock directory'
+  exit 1
+fi
+# ============= MultiSound.d/setdigital.c ==============
+if test ! -d 'MultiSound.d'; then
+  $echo 'x -' 'creating directory' 'MultiSound.d'
+  mkdir 'MultiSound.d'
+fi
+if test -f 'MultiSound.d/setdigital.c' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING 'MultiSound.d/setdigital.c' '(file already exists)'
+else
+  $echo 'x -' extracting 'MultiSound.d/setdigital.c' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > 'MultiSound.d/setdigital.c' &&
+/*********************************************************************
+X *
+X * setdigital.c - sets the DIGITAL1 input for a mixer
+X *
+X * Copyright (C) 1998 Andrew Veliath
+X *
+X * This program is free software; you can redistribute it and/or modify
+X * it under the terms of the GNU General Public License as published by
+X * the Free Software Foundation; either version 2 of the License, or
+X * (at your option) any later version.
+X *
+X * This program is distributed in the hope that it will be useful,
+X * but WITHOUT ANY WARRANTY; without even the implied warranty of
+X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+X * GNU General Public License for more details.
+X *
+X * You should have received a copy of the GNU General Public License
+X * along with this program; if not, write to the Free Software
+X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+X *
+X * $Id: setdigital.c,v 1.1 1998/08/29 03:32:33 andrewtv Exp $
+X *
+X ********************************************************************/
+X
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -182,53 +478,586 @@ cc -O setdigital.c -o setdigital
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/soundcard.h>
-
+X
 int main(int argc, char *argv[])
 {
-       int fd;
-       unsigned long recmask, recsrc;
-
-       if (argc != 2) {
-               fprintf(stderr, "usage: setdigital <mixer device>\n");
-               exit(1);
-       } else
-
-       if ((fd = open(argv[1], O_RDWR)) < 0) {
-               perror(argv[1]);
-               exit(1);
-       }
-
-       if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask) < 0) {
-               fprintf(stderr, "error: ioctl read recmask failed\n");
-               perror("ioctl");
-               close(fd);
-               exit(1);
-       }
-
-       if (!(recmask & SOUND_MASK_DIGITAL1)) {
-               fprintf(stderr, "error: cannot find DIGITAL1 device in mixer\n");
-               close(fd);
-               exit(1);
-       }
-
-       if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) < 0) {
-               fprintf(stderr, "error: ioctl read recsrc failed\n");
-               perror("ioctl");
-               close(fd);
-               exit(1);
-       }
-
-       recsrc |= SOUND_MASK_DIGITAL1;
-       
-       if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) < 0) {
-               fprintf(stderr, "error: ioctl write recsrc failed\n");
-               perror("ioctl");
-               close(fd);
-               exit(1);
-       }
-
-       close(fd);
-       
-       return 0;
-}
--- end setdigital.c --
+X      int fd;
+X      unsigned long recmask, recsrc;
+X
+X      if (argc != 2) {
+X              fprintf(stderr, "usage: setdigital <mixer device>\n");
+X              exit(1);
+X      }
+X
+X      if ((fd = open(argv[1], O_RDWR)) < 0) {
+X              perror(argv[1]);
+X              exit(1);
+X      }
+X
+X      if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask) < 0) {
+X              fprintf(stderr, "error: ioctl read recording mask failed\n");
+X              perror("ioctl");
+X              close(fd);
+X              exit(1);
+X      }
+X
+X      if (!(recmask & SOUND_MASK_DIGITAL1)) {
+X              fprintf(stderr, "error: cannot find DIGITAL1 device in mixer\n");
+X              close(fd);
+X              exit(1);
+X      }
+X
+X      if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) < 0) {
+X              fprintf(stderr, "error: ioctl read recording source failed\n");
+X              perror("ioctl");
+X              close(fd);
+X              exit(1);
+X      }
+X
+X      recsrc |= SOUND_MASK_DIGITAL1;
+X      
+X      if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) < 0) {
+X              fprintf(stderr, "error: ioctl write recording source failed\n");
+X              perror("ioctl");
+X              close(fd);
+X              exit(1);
+X      }
+X
+X      close(fd);
+X      
+X      return 0;
+}
+SHAR_EOF
+  $shar_touch -am 0828233298 'MultiSound.d/setdigital.c' &&
+  chmod 0664 'MultiSound.d/setdigital.c' ||
+  $echo 'restore of' 'MultiSound.d/setdigital.c' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo 'MultiSound.d/setdigital.c:' 'MD5 check failed'
+47720746d4367bae9954787c311c56fd  MultiSound.d/setdigital.c
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/setdigital.c'`"
+    test 2111 -eq "$shar_count" ||
+    $echo 'MultiSound.d/setdigital.c:' 'original size' '2111,' 'current size' "$shar_count!"
+  fi
+fi
+# ============= MultiSound.d/pinnaclecfg.c ==============
+if test -f 'MultiSound.d/pinnaclecfg.c' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING 'MultiSound.d/pinnaclecfg.c' '(file already exists)'
+else
+  $echo 'x -' extracting 'MultiSound.d/pinnaclecfg.c' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > 'MultiSound.d/pinnaclecfg.c' &&
+/*********************************************************************
+X *
+X * pinnaclecfg.c - Pinnacle/Fiji Device Configuration Program
+X *
+X * This is for NON-PnP mode only.  For PnP mode, use isapnptools.
+X *
+X * This is Linux-specific, and must be run with root permissions.
+X *
+X * Part of the Turtle Beach MultiSound Sound Card Driver for Linux
+X *
+X * Copyright (C) 1998 Andrew Veliath
+X *
+X * This program is free software; you can redistribute it and/or modify
+X * it under the terms of the GNU General Public License as published by
+X * the Free Software Foundation; either version 2 of the License, or
+X * (at your option) any later version.
+X *
+X * This program is distributed in the hope that it will be useful,
+X * but WITHOUT ANY WARRANTY; without even the implied warranty of
+X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+X * GNU General Public License for more details.
+X *
+X * You should have received a copy of the GNU General Public License
+X * along with this program; if not, write to the Free Software
+X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+X *
+X * $Id: pinnaclecfg.c,v 1.3 1998/08/29 03:32:32 andrewtv Exp $
+X *
+X ********************************************************************/
+X
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <asm/io.h>
+#include <asm/types.h>
+X
+#define IREG_LOGDEVICE         0x07
+#define IREG_ACTIVATE          0x30
+#define LD_ACTIVATE            0x01
+#define LD_DISACTIVATE         0x00
+#define IREG_EECONTROL         0x3F
+#define IREG_MEMBASEHI         0x40
+#define IREG_MEMBASELO         0x41
+#define IREG_MEMCONTROL                0x42
+#define IREG_MEMRANGEHI                0x43
+#define IREG_MEMRANGELO                0x44
+#define MEMTYPE_8BIT           0x00
+#define MEMTYPE_16BIT          0x02
+#define MEMTYPE_RANGE          0x00
+#define MEMTYPE_HIADDR         0x01
+#define IREG_IO0_BASEHI                0x60
+#define IREG_IO0_BASELO                0x61
+#define IREG_IO1_BASEHI                0x62
+#define IREG_IO1_BASELO                0x63
+#define IREG_IRQ_NUMBER                0x70
+#define IREG_IRQ_TYPE          0x71
+#define IRQTYPE_HIGH           0x02
+#define IRQTYPE_LOW            0x00
+#define IRQTYPE_LEVEL          0x01
+#define IRQTYPE_EDGE           0x00
+X
+#define HIBYTE(w)              ((BYTE)(((WORD)(w) >> 8) & 0xFF))
+#define LOBYTE(w)              ((BYTE)(w))
+#define MAKEWORD(low,hi)       ((WORD)(((BYTE)(low))|(((WORD)((BYTE)(hi)))<<8)))
+X
+typedef __u8                   BYTE;
+typedef __u16                  USHORT;
+typedef __u16                  WORD;
+X
+static int config_port = -1;
+X
+static int msnd_write_cfg(int cfg, int reg, int value)
+{
+X      outb(reg, cfg);
+X      outb(value, cfg + 1);
+X      if (value != inb(cfg + 1)) {
+X              fprintf(stderr, "error: msnd_write_cfg: I/O error\n");
+X              return -EIO;
+X      }
+X      return 0;
+}
+X
+static int msnd_read_cfg(int cfg, int reg)
+{
+X      outb(reg, cfg);
+X      return inb(cfg + 1);
+}
+X
+static int msnd_write_cfg_io0(int cfg, int num, WORD io)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io)))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io)))
+X              return -EIO;
+X      return 0;
+}
+X
+static int msnd_read_cfg_io0(int cfg, int num, WORD *io)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      
+X      *io = MAKEWORD(msnd_read_cfg(cfg, IREG_IO0_BASELO),
+X                     msnd_read_cfg(cfg, IREG_IO0_BASEHI));
+X
+X      return 0;
+}
+X
+static int msnd_write_cfg_io1(int cfg, int num, WORD io)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io)))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io)))
+X              return -EIO;
+X      return 0;
+}
+X
+static int msnd_read_cfg_io1(int cfg, int num, WORD *io)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      
+X      *io = MAKEWORD(msnd_read_cfg(cfg, IREG_IO1_BASELO),
+X                     msnd_read_cfg(cfg, IREG_IO1_BASEHI));
+X
+X      return 0;
+}
+X
+static int msnd_write_cfg_irq(int cfg, int num, WORD irq)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq)))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE))
+X              return -EIO;
+X      return 0;
+}
+X
+static int msnd_read_cfg_irq(int cfg, int num, WORD *irq)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      
+X      *irq = msnd_read_cfg(cfg, IREG_IRQ_NUMBER);
+X
+X      return 0;
+}
+X
+static int msnd_write_cfg_mem(int cfg, int num, int mem)
+{
+X      WORD wmem;
+X
+X      mem >>= 8;
+X      mem &= 0xfff;
+X      wmem = (WORD)mem;
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem)))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem)))
+X              return -EIO;
+X      if (wmem && msnd_write_cfg(cfg, IREG_MEMCONTROL, (MEMTYPE_HIADDR | MEMTYPE_16BIT)))
+X              return -EIO;
+X      return 0;
+}
+X
+static int msnd_read_cfg_mem(int cfg, int num, int *mem)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      
+X      *mem = MAKEWORD(msnd_read_cfg(cfg, IREG_MEMBASELO),
+X                      msnd_read_cfg(cfg, IREG_MEMBASEHI));
+X      *mem <<= 8;
+X
+X      return 0;
+}
+X
+static int msnd_activate_logical(int cfg, int num)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE))
+X              return -EIO;
+X      return 0;
+}
+X
+static int msnd_write_cfg_logical(int cfg, int num, WORD io0, WORD io1, WORD irq, int mem)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_write_cfg_io0(cfg, num, io0))
+X              return -EIO;
+X      if (msnd_write_cfg_io1(cfg, num, io1))
+X              return -EIO;
+X      if (msnd_write_cfg_irq(cfg, num, irq))
+X              return -EIO;
+X      if (msnd_write_cfg_mem(cfg, num, mem))
+X              return -EIO;
+X      if (msnd_activate_logical(cfg, num))
+X              return -EIO;
+X      return 0;
+}
+X
+static int msnd_read_cfg_logical(int cfg, int num, WORD *io0, WORD *io1, WORD *irq, int *mem)
+{
+X      if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+X              return -EIO;
+X      if (msnd_read_cfg_io0(cfg, num, io0))
+X              return -EIO;
+X      if (msnd_read_cfg_io1(cfg, num, io1))
+X              return -EIO;
+X      if (msnd_read_cfg_irq(cfg, num, irq))
+X              return -EIO;
+X      if (msnd_read_cfg_mem(cfg, num, mem))
+X              return -EIO;
+X      return 0;
+}
+X
+static void usage(void)
+{
+X      fprintf(stderr,
+X              "\n"
+X              "pinnaclecfg 1.0\n"
+X              "\n"
+X              "usage: pinnaclecfg <config port> [device config]\n"
+X              "\n"
+X              "This is for use with the card in NON-PnP mode only.\n"
+X              "\n"
+X              "Available devices (not all available for Fiji):\n"
+X              "\n"
+X              "        Device                       Description\n"
+X              "        -------------------------------------------------------------------\n"
+X              "        reset                        Reset all devices (i.e. disable)\n"
+X              "        show                         Display current device configurations\n"
+X              "\n"
+X              "        dsp <io> <irq> <mem>         Audio device\n"
+X              "        mpu <io> <irq>               Internal Kurzweil synth\n"
+X              "        ide <io0> <io1> <irq>        On-board IDE controller\n"
+X              "        joystick <io>                Joystick port\n"
+X              "\n");
+X      exit(1);
+}
+X
+static int cfg_reset(void)
+{
+X      int i;
+X
+X      for (i = 0; i < 4; ++i)
+X              msnd_write_cfg_logical(config_port, i, 0, 0, 0, 0);
+X      
+X      return 0;
+}
+X
+static int cfg_show(void)
+{
+X      int i;
+X      int count = 0;
+X
+X      for (i = 0; i < 4; ++i) {
+X              WORD io0, io1, irq;
+X              int mem;
+X              msnd_read_cfg_logical(config_port, i, &io0, &io1, &irq, &mem);
+X              switch (i) {
+X              case 0:
+X                      if (io0 || irq || mem) {
+X                              printf("dsp 0x%x %d 0x%x\n", io0, irq, mem);
+X                              ++count;
+X                      }
+X                      break;
+X              case 1:
+X                      if (io0 || irq) {
+X                              printf("mpu 0x%x %d\n", io0, irq);
+X                              ++count;
+X                      }
+X                      break;
+X              case 2:
+X                      if (io0 || io1 || irq) {
+X                              printf("ide 0x%x 0x%x %d\n", io0, io1, irq);
+X                              ++count;
+X                      }
+X                      break;
+X              case 3:
+X                      if (io0) {
+X                              printf("joystick 0x%x\n", io0);
+X                              ++count;
+X                      }
+X                      break;
+X              }
+X      }
+X
+X      if (count == 0)
+X              fprintf(stderr, "no devices configured\n");
+X      
+X      return 0;
+}
+X
+static int cfg_dsp(int argc, char *argv[])
+{
+X      int io, irq, mem;
+X
+X      if (argc < 3 ||
+X          sscanf(argv[0], "0x%x", &io) != 1 ||
+X          sscanf(argv[1], "%d", &irq) != 1 ||
+X          sscanf(argv[2], "0x%x", &mem) != 1)
+X              usage();
+X
+X      if (!(io == 0x290 ||
+X            io == 0x260 ||
+X            io == 0x250 ||
+X            io == 0x240 ||
+X            io == 0x230 ||
+X            io == 0x220 ||
+X            io == 0x210 ||
+X            io == 0x3e0)) {
+X              fprintf(stderr, "error: io must be one of "
+X                      "210, 220, 230, 240, 250, 260, 290, or 3E0\n");
+X              usage();
+X      }
+X      
+X      if (!(irq == 5 ||
+X            irq == 7 ||
+X            irq == 9 ||
+X            irq == 10 ||
+X            irq == 11 ||
+X            irq == 12)) {
+X              fprintf(stderr, "error: irq must be one of "
+X                      "5, 7, 9, 10, 11 or 12\n");
+X              usage();
+X      }
+X
+X      if (!(mem == 0xb0000 ||
+X            mem == 0xc8000 ||
+X            mem == 0xd0000 ||
+X            mem == 0xd8000 ||
+X            mem == 0xe0000 ||
+X            mem == 0xe8000)) {
+X              fprintf(stderr, "error: mem must be one of "
+X                      "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000\n");
+X              usage();
+X      }
+X
+X      return msnd_write_cfg_logical(config_port, 0, io, 0, irq, mem);
+}
+X
+static int cfg_mpu(int argc, char *argv[])
+{
+X      int io, irq;
+X
+X      if (argc < 2 ||
+X          sscanf(argv[0], "0x%x", &io) != 1 ||
+X          sscanf(argv[1], "%d", &irq) != 1)
+X              usage();
+X      
+X      return msnd_write_cfg_logical(config_port, 1, io, 0, irq, 0);
+}
+X
+static int cfg_ide(int argc, char *argv[])
+{
+X      int io0, io1, irq;
+X
+X      if (argc < 3 ||
+X          sscanf(argv[0], "0x%x", &io0) != 1 ||
+X          sscanf(argv[0], "0x%x", &io1) != 1 ||
+X          sscanf(argv[1], "%d", &irq) != 1)
+X              usage();
+X      
+X      return msnd_write_cfg_logical(config_port, 2, io0, io1, irq, 0);
+}
+X
+static int cfg_joystick(int argc, char *argv[])
+{
+X      int io;
+X
+X      if (argc < 1 ||
+X          sscanf(argv[0], "0x%x", &io) != 1)
+X              usage();
+X      
+X      return msnd_write_cfg_logical(config_port, 3, io, 0, 0, 0);
+}
+X
+int main(int argc, char *argv[])
+{
+X      char *device;
+X      int rv = 0;
+X
+X      --argc; ++argv;
+X
+X      if (argc < 2)
+X              usage();
+X
+X      sscanf(argv[0], "0x%x", &config_port);
+X      if (config_port != 0x250 && config_port != 0x260 && config_port != 0x270) {
+X              fprintf(stderr, "error: <config port> must be 0x250, 0x260 or 0x270\n");
+X              exit(1);
+X      }
+X      if (ioperm(config_port, 2, 1)) {
+X              perror("ioperm");
+X              fprintf(stderr, "note: pinnaclecfg must be run as root\n");
+X              exit(1);
+X      }
+X      device = argv[1];
+X
+X      argc -= 2; argv += 2;
+X
+X      if (strcmp(device, "reset") == 0)
+X              rv = cfg_reset();
+X      else if (strcmp(device, "show") == 0)
+X              rv = cfg_show();
+X      else if (strcmp(device, "dsp") == 0)
+X              rv = cfg_dsp(argc, argv);
+X      else if (strcmp(device, "mpu") == 0)
+X              rv = cfg_mpu(argc, argv);
+X      else if (strcmp(device, "ide") == 0)
+X              rv = cfg_ide(argc, argv);
+X      else if (strcmp(device, "joystick") == 0)
+X              rv = cfg_joystick(argc, argv);
+X      else {
+X              fprintf(stderr, "error: unknown device %s\n", device);
+X              usage();
+X      }
+X
+X      if (rv)
+X              fprintf(stderr, "error: device configuration failed\n");
+X      
+X      return 0;
+}
+SHAR_EOF
+  $shar_touch -am 0905082598 'MultiSound.d/pinnaclecfg.c' &&
+  chmod 0664 'MultiSound.d/pinnaclecfg.c' ||
+  $echo 'restore of' 'MultiSound.d/pinnaclecfg.c' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo 'MultiSound.d/pinnaclecfg.c:' 'MD5 check failed'
+71f99b834a2845daae8ae034623e313e  MultiSound.d/pinnaclecfg.c
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/pinnaclecfg.c'`"
+    test 10301 -eq "$shar_count" ||
+    $echo 'MultiSound.d/pinnaclecfg.c:' 'original size' '10301,' 'current size' "$shar_count!"
+  fi
+fi
+# ============= MultiSound.d/Makefile ==============
+if test -f 'MultiSound.d/Makefile' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING 'MultiSound.d/Makefile' '(file already exists)'
+else
+  $echo 'x -' extracting 'MultiSound.d/Makefile' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > 'MultiSound.d/Makefile' &&
+CC     = gcc
+CFLAGS = -O
+PROGS  = setdigital pinnaclecfg conv
+X
+all: $(PROGS)
+X
+clean:
+X      rm -f $(PROGS)
+SHAR_EOF
+  $shar_touch -am 0828231798 'MultiSound.d/Makefile' &&
+  chmod 0664 'MultiSound.d/Makefile' ||
+  $echo 'restore of' 'MultiSound.d/Makefile' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo 'MultiSound.d/Makefile:' 'MD5 check failed'
+ab95a049d10611a5e5d559a56965b33f  MultiSound.d/Makefile
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/Makefile'`"
+    test 96 -eq "$shar_count" ||
+    $echo 'MultiSound.d/Makefile:' 'original size' '96,' 'current size' "$shar_count!"
+  fi
+fi
+# ============= MultiSound.d/conv.l ==============
+if test -f 'MultiSound.d/conv.l' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING 'MultiSound.d/conv.l' '(file already exists)'
+else
+  $echo 'x -' extracting 'MultiSound.d/conv.l' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > 'MultiSound.d/conv.l' &&
+%%
+[ \n\t,\r]
+\;.*
+DB
+[0-9A-Fa-f]+H  { int n; sscanf(yytext, "%xH", &n); printf("%c", n); }
+%%
+int yywrap() { return 1; }
+main() { yylex(); }
+SHAR_EOF
+  $shar_touch -am 0828231798 'MultiSound.d/conv.l' &&
+  chmod 0664 'MultiSound.d/conv.l' ||
+  $echo 'restore of' 'MultiSound.d/conv.l' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo 'MultiSound.d/conv.l:' 'MD5 check failed'
+d2411fc32cd71a00dcdc1f009e858dd2  MultiSound.d/conv.l
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/conv.l'`"
+    test 141 -eq "$shar_count" ||
+    $echo 'MultiSound.d/conv.l:' 'original size' '141,' 'current size' "$shar_count!"
+  fi
+fi
+rm -fr _sh21233
+exit 0
index c0ca8e04bbcf7d6d4a378f23af6b6c57a100b88d..c62d2d5ca2470a75ed8793a1a3b3a2b66e9896c9 100644 (file)
@@ -16,7 +16,8 @@ trivial patch so apply some common sense.
        SMC etherpower for that.)
 
 3.     Make sure your changes compile correctly in multiple
-       configurations.
+       configurations. In paticular check changes work both as a module
+       and built into the kernel.
 
 4.     When you are happy with a change make it generally available for
        testing and await feedback.
@@ -28,7 +29,8 @@ trivial patch so apply some common sense.
        job the maintainers (and especially Linus) do is to keep things
        looking the same. Sometimes this means that the clever hack in
        your driver to get around a problem actual needs to become a
-       generalized kernel feature ready for next time.
+       generalized kernel feature ready for next time. See 
+       Documentation/CodingStyle for guidance here.
 
        PLEASE try to include any credit lines you want added with the
        patch. It avoids people being missed off by mistake and makes
@@ -240,6 +242,11 @@ M: Philip.Blundell@pobox.com
 L:     linux-net@vger.rutgers.edu
 S:     Maintained
 
+ETHERTEAM 16I DRIVER
+P:      Mika Kuoppala
+M:      miku@iki.fi
+S:      Maintained
+
 EXT2 FILE SYSTEM
 P:     Remy Card
 M:     Remy.Card@linux.org
@@ -303,6 +310,12 @@ M: oe1kib@oe1kib.ampr.org
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
 
+HIPPI
+P:     Jes Sorensen
+M:     Jes.Sorensen@cern.ch
+L:     linux-hippi@sunsite.auc.dk
+S:     Maintained
+
 HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
 P:     Jaroslav Kysela
 M:     perex@jcu.cz
@@ -702,6 +715,12 @@ M: eis@baty.hanse.de
 L:     linux-x25@vger.rutgers.edu
 S:     Maintained
 
+Z85230 SYNCHRONOUS DRIVER
+P:     Alan Cox
+M:     alan@redhat.com
+W:     http://roadrunner.swansea.linux.org.uk/synchronous.shtml
+S:     Maintained
+
 Z8530 DRIVER FOR AX.25
 P:     Joerg Reuter
 M:     jreuter@poboxes.com
@@ -710,7 +729,6 @@ W:  http://qsl.net/dl1bke/
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
 
-
 REST:
 P:     Linus Torvalds
 S:     Buried alive in diapers
diff --git a/README b/README
index 108ebb7d949d7ab3f94b2aedc58ad54a62b8fc6d..2ae083d4b847ae3ae9474a11f8b3ca0d6f52ec69 100644 (file)
--- a/README
+++ b/README
@@ -96,15 +96,6 @@ INSTALLING the kernel:
    the current directory, but an alternative directory can be specified
    as the second argument.
 
- - Make sure your /usr/include/asm, /usr/include/linux, and /usr/include/scsi
-   directories are just symlinks to the kernel sources:
-
-               cd /usr/include
-               rm -rf asm linux scsi
-               ln -s /usr/src/linux/include/asm-i386 asm
-               ln -s /usr/src/linux/include/linux linux
-               ln -s /usr/src/linux/include/scsi scsi
-
  - Make sure you have no stale .o files and dependencies lying around:
 
                cd /usr/src/linux
index 4c8fb58bf33d8c5d8f1e5bf6d4fee9081fccb792..bcdf3d5e216d902b1957ed896dd4a241338b0c3d 100644 (file)
@@ -19,17 +19,23 @@ old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; the
 # Determine if GCC understands the -mcpu= option.
 have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
 
-# If GENERIC, make sure to turn off any instruction set extensions that
-# the host compiler might have on by default.  Given that EV4 and EV5
-# have the same instruction set, prefer EV5 because an EV5 schedule is
-# more likely to keep an EV4 processor busy than vice-versa.
-ifeq ($(CONFIG_ALPHA_GENERIC)$(have_mcpu),yy)
- CFLAGS := $(CFLAGS) -mcpu=ev5
-endif
-
-# If EV6, turn on the proper optimizations.
-ifeq ($(CONFIG_ALPHA_EV6)$(have_mcpu),yy)
- CFLAGS := $(CFLAGS) -mcpu=ev6
+# Turn on the proper cpu optimizations.
+ifeq ($(have_mcpu),y)
+  # If GENERIC, make sure to turn off any instruction set extensions that
+  # the host compiler might have on by default.  Given that EV4 and EV5
+  # have the same instruction set, prefer EV5 because an EV5 schedule is
+  # more likely to keep an EV4 processor busy than vice-versa.
+  ifeq ($(CONFIG_ALPHA_GENERIC),y)
+    CFLAGS := $(CFLAGS) -mcpu=ev5
+  endif
+  ifeq ($(CONFIG_ALPHA_EV4),y)
+    CFLAGS := $(CFLAGS) -mcpu=ev4
+  endif
+  # Leave out EV5, since it is too hard to figure out whether we
+  # should use EV56 insns or not.
+  ifeq ($(CONFIG_ALPHA_EV6),y)
+    CFLAGS := $(CFLAGS) -mcpu=ev6
+  endif
 endif
 
 # For TSUNAMI, we must have the assembler not emulate our instructions.
index 13d9f514cecc95244a4add3eb528bcebc1288e51..ee3460463efde8605af8ed59b14eaa17a0778c46 100644 (file)
@@ -36,7 +36,10 @@ bootimage:   tools/mkbb tools/lxboot tools/bootlx vmlinux.nh
        tools/mkbb bootimage tools/lxboot
 
 bootpfile:     tools/bootph vmlinux.nh
-       ( cat tools/bootph vmlinux.nh ) > bootpfile
+       cat tools/bootph vmlinux.nh > bootpfile
+ifdef INITRD
+       cat $(INITRD) >> bootpfile
+endif
 
 srmboot:       bootdevice bootimage
        dd if=bootimage of=$(BOOTDEV) bs=512 seek=1 skip=1
@@ -48,15 +51,18 @@ bootdevice:
 vmlinux.gz: vmlinux
        gzip -fv9 vmlinux
 
-#
-# A raw binary without header.  Used by raw boot.
-#
 main.o: ksize.h
 
 bootp.o: ksize.h
 
-ksize.h: $(OBJSTRIP) vmlinux.nh
-       echo "#define KERNEL_SIZE `$(OBJSTRIP) -p vmlinux.nh /dev/null`" > $@
+ksize.h: vmlinux.nh dummy
+       echo "#define KERNEL_SIZE `ls -l vmlinux.nh | awk '{print $$5}'`" > $@T
+ifdef INITRD
+       [ -f $(INITRD) ] || exit 1
+       echo "#define INITRD_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T
+endif
+       cmp -s $@T $@ || mv -f $@T $@
+       rm -f $@T
 
 vmlinux.nh: $(VMLINUX) $(OBJSTRIP)
        $(OBJSTRIP) -v $(VMLINUX) vmlinux.nh
@@ -91,3 +97,5 @@ clean:
        rm -f vmlinux.nh ksize.h
 
 dep:
+
+dummy:
index 2dc8b6a4d80c9803ae249fad92485b30f34dacb4..34645a64365562b2fe25e05b8f688121f12d2b16 100644 (file)
 
 #include "ksize.h"
 
-extern int vsprintf(char *, const char *, va_list);
 extern unsigned long switch_to_osf_pal(unsigned long nr,
        struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
-       unsigned long vptb, unsigned long *kstk);
+       unsigned long *vptb);
 
-extern long dispatch(long code, ...);
-
-static void
-puts(const char *str, int len)
-{
-       long written;
-
-       while (len > 0) {
-               written = dispatch(CCB_PUTS, 0, str, len);
-               if (written < 0)
-                       break;
-               len -= (unsigned int) written;
-               str += (unsigned int) written;
-       }
-}
-
-int printk(const char * fmt, ...)
-{
-       va_list args;
-       int i, j, remaining, num_nl;
-       static char buf[1024];
-
-       va_start(args, fmt);
-       i = vsprintf(buf, fmt, args);
-       va_end(args);
-
-       /* expand \n into \r\n: */
-
-       num_nl = 0;
-       for (j = 0; j < i; ++j) {
-           if (buf[j] == '\n')
-               ++num_nl;
-       }
-       remaining = i + num_nl;
-       for (j = i - 1; j >= 0; --j) {
-           buf[j + num_nl] = buf[j];
-           if (buf[j] == '\n') {
-               --num_nl;
-               buf[j + num_nl] = '\r';
-           }
-       }
-
-       puts(buf, remaining);
-       return i;
-}
-
-#define hwrpb (*INIT_HWRPB)
+struct hwrpb_struct *hwrpb = INIT_HWRPB;
+static struct pcb_struct pcb_va[1];
 
 /*
  * Find a physical address of a virtual object..
  *
  * This is easy using the virtual page table address.
  */
-struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
+
+static inline void *
+find_pa(unsigned long *vptb, void *ptr)
 {
-       unsigned long address = (unsigned long) pcb;
+       unsigned long address = (unsigned long) ptr;
        unsigned long result;
 
        result = vptb[address >> 13];
        result >>= 32;
        result <<= 13;
        result |= address & 0x1fff;
-       return (struct pcb_struct *) result;
+       return (void *) result;
 }      
 
 /*
@@ -101,31 +57,19 @@ struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
  * code has the L1 page table identity-map itself in the second PTE
  * in the L1 page table. Thus the L1-page is virtually addressable
  * itself (through three levels) at virtual address 0x200802000.
- *
- * As we don't want it there anyway, we also move the L1 self-map
- * up as high as we can, so that the last entry in the L1 page table
- * maps the page tables.
- *
- * As a result, the OSF/1 pal-code will instead use a virtual page table
- * map located at 0xffffffe00000000.
  */
-#define pcb_va ((struct pcb_struct *) 0x20000000)
-#define old_vptb (0x0000000200000000UL)
-#define new_vptb (0xfffffffe00000000UL)
-void pal_init(void)
+
+#define VPTB   ((unsigned long *) 0x200000000)
+#define L1     ((unsigned long *) 0x200802000)
+
+void
+pal_init(void)
 {
-       unsigned long i, rev, sum;
-       unsigned long *L1, *l;
+       unsigned long i, rev;
        struct percpu_struct * percpu;
        struct pcb_struct * pcb_pa;
 
-       /* Find the level 1 page table and duplicate it in high memory */
-       L1 = (unsigned long *) 0x200802000UL; /* (1<<33 | 1<<23 | 1<<13) */
-       L1[1023] = L1[1];
-
-       percpu = (struct percpu_struct *)
-                       (hwrpb.processor_offset + (unsigned long) &hwrpb),
-               
+       /* Create the dummy PCB.  */
        pcb_va->ksp = 0;
        pcb_va->usp = 0;
        pcb_va->ptbr = L1[1] >> 32;
@@ -133,58 +77,45 @@ void pal_init(void)
        pcb_va->pcc = 0;
        pcb_va->unique = 0;
        pcb_va->flags = 1;
-       pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va);
-       printk("Switching to OSF PAL-code .. ");
+       pcb_va->res1 = 0;
+       pcb_va->res2 = 0;
+       pcb_pa = find_pa(VPTB, pcb_va);
+
        /*
         * a0 = 2 (OSF)
         * a1 = return address, but we give the asm the vaddr of the PCB
         * a2 = physical addr of PCB
         * a3 = new virtual page table pointer
-        * a4 = KSP (but we give it 0, asm sets it)
+        * a4 = KSP (but the asm sets it)
         */
-       i = switch_to_osf_pal(
-               2,
-               pcb_va,
-               pcb_pa,
-               new_vptb,
-               0);
+       srm_printk("Switching to OSF PAL-code .. ");
+
+       i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
        if (i) {
-               printk("failed, code %ld\n", i);
+               srm_printk("failed, code %ld\n", i);
                halt();
        }
-       rev = percpu->pal_revision = percpu->palcode_avail[2];
 
-       hwrpb.vptb = new_vptb;
-
-       /* update checksum: */
-       sum = 0;
-       for (l = (unsigned long *) &hwrpb;
-            l < (unsigned long *) &hwrpb.chksum;
-            ++l)
-               sum += *l;
-       hwrpb.chksum = sum;
+       percpu = (struct percpu_struct *)
+               (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
+       rev = percpu->pal_revision = percpu->palcode_avail[2];
 
-       printk("Ok (rev %lx)\n", rev);
-       /* remove the old virtual page-table mapping */
-       L1[1] = 0;
+       srm_printk("Ok (rev %lx)\n", rev);
 
        tbia(); /* do it directly in case we are SMP */
 }
 
-static inline long load(unsigned long dst,
-                       unsigned long src,
-                       unsigned long count)
+static inline void
+load(unsigned long dst, unsigned long src, unsigned long count)
 {
-       extern void * memcpy(void *, const void *, size_t);
-
        memcpy((void *)dst, (void *)src, count);
-       return count;
 }
 
 /*
  * Start the kernel.
  */
-static void runkernel(void)
+static inline void
+runkernel(void)
 {
        __asm__ __volatile__(
                "bis %1,%1,$30\n\t"
@@ -199,65 +130,82 @@ extern char _end;
 #define KERNEL_ORIGIN \
        ((((unsigned long)&_end) + 511) & ~511)
 
-void start_kernel(void)
+void
+start_kernel(void)
 {
-       static long i;
-       static int nbytes;
        /*
-        * note that this crufty stuff with static and envval and envbuf
-        * is because:
+        * Note that this crufty stuff with static and envval
+        * and envbuf is because:
         *
-        * 1. frequently, the stack is is short, and we don't want to overrun;
-        * 2. frequently the stack is where we are going to copy the kernel to;
-        * 3. a certain SRM console required the GET_ENV output to stack.
+        * 1. Frequently, the stack is short, and we don't want to overrun;
+        * 2. Frequently the stack is where we are going to copy the kernel to;
+        * 3. A certain SRM console required the GET_ENV output to stack.
+        *    ??? A comment in the aboot sources indicates that the GET_ENV
+        *    destination must be quadword aligned.  Might this explain the
+        *    behaviour, rather than requiring output to the stack, which
+        *    seems rather far-fetched.
         */
-       static char envval[256];
-       char envbuf[256];
+       static long nbytes;
+       static char envval[256] __attribute__((aligned(8)));
+#ifdef INITRD_SIZE
+       static unsigned long initrd_start;
+#endif
 
-       printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
-       if (hwrpb.pagesize != 8192) {
-               printk("Expected 8kB pages, got %ldkB\n",
-                      hwrpb.pagesize >> 10);
+       srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
+       if (INIT_HWRPB->pagesize != 8192) {
+               srm_printk("Expected 8kB pages, got %ldkB\n",
+                          INIT_HWRPB->pagesize >> 10);
+               return;
+       }
+       if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
+               srm_printk("Expected vptb at %p, got %p\n",
+                          VPTB, (void *)INIT_HWRPB->vptb);
                return;
        }
        pal_init();
 
-       nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
-                         envbuf, sizeof(envbuf));
-       if (nbytes < 0 || nbytes >= sizeof(envbuf)) {
+#ifdef INITRD_SIZE
+       /* The initrd must be page-aligned.  See below for the 
+          cause of the magic number 5.  */
+       initrd_start = ((START_ADDR + 5*KERNEL_SIZE) | (PAGE_SIZE-1)) + 1;
+       srm_printk("Initrd positioned at %#lx\n", initrd_start);
+#endif
+
+       nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
+                             envval, sizeof(envval));
+       if (nbytes < 0 || nbytes >= sizeof(envval)) {
                nbytes = 0;
        }
-       envbuf[nbytes] = '\0';
-       memcpy(envval, envbuf, nbytes+1);
-       printk("Loading the kernel...'%s'\n", envval);
+       envval[nbytes] = '\0';
+       srm_printk("Loading the kernel...'%s'\n", envval);
 
        /* NOTE: *no* callbacks or printouts from here on out!!! */
 
-#if 1
        /*
-        * this is a hack, as some consoles seem to get virtual 20000000
+        * This is a hack, as some consoles seem to get virtual 20000000
         * (ie where the SRM console puts the kernel bootp image) memory
         * overlapping physical 310000 memory, which causes real problems
         * when attempting to copy the former to the latter... :-(
         *
-        * so, we first move the kernel virtual-to-physical way above where
+        * So, we first move the kernel virtual-to-physical way above where
         * we physically want the kernel to end up, then copy it from there
         * to its final resting place... ;-}
         *
-        * sigh...
+        * Sigh...
         */
 
-        i = load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
-        i = load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
-#else
-       i = load(START_ADDR, KERNEL_ORIGIN, KERNEL_SIZE);
+#ifdef INITRD_SIZE
+       load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_SIZE);
 #endif
+        load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
+        load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
 
+       memset((char*)ZERO_PAGE, 0, PAGE_SIZE);
        strcpy((char*)ZERO_PAGE, envval);
+#ifdef INITRD_SIZE
+       ((long *)(ZERO_PAGE+256))[0] = initrd_start;
+       ((long *)(ZERO_PAGE+256))[1] = INITRD_SIZE;
+#endif
 
        runkernel();
-
-       for (i = 0 ; i < 0x100000000 ; i++)
-               /* nothing */;
-       halt();
 }
index 9fae5301a6fd85bbe21bd03277217652994d33ba..e3159d69d93a503212616351cd240262ace725f0 100644 (file)
@@ -6,28 +6,22 @@
 
 #include <asm/system.h>
 
-#define halt .long PAL_halt
-
        .set noreorder
        .globl  __start
        .ent    __start
 __start:
-       bis     $31,$31,$31
-       br      1f
-       /* room for the initial PCB, which comes here */
-       .quad   0,0,0,0,0,0,0,0
-1:     br      $27,2f
-2:     ldgp    $29,0($27)
-       lda     $27,start_kernel
-       jsr     $26,($27),start_kernel
-       halt
+       br      $29,2f
+2:     ldgp    $29,0($29)
+       jsr     $26,start_kernel
+       call_pal PAL_halt
        .end __start
 
        .align 5
        .globl  wrent
        .ent    wrent
 wrent:
-       .long PAL_wrent
+       .prologue 0
+       call_pal PAL_wrent
        ret ($26)
        .end wrent
 
@@ -35,7 +29,8 @@ wrent:
        .globl  wrkgp
        .ent    wrkgp
 wrkgp:
-       .long PAL_wrkgp
+       .prologue 0
+       call_pal PAL_wrkgp
        ret ($26)
        .end wrkgp
 
@@ -44,6 +39,7 @@ wrkgp:
        .ent    switch_to_osf_pal
 switch_to_osf_pal:
        subq    $30,128,$30
+       .frame  $30,128,$26
        stq     $26,0($30)
        stq     $1,8($30)
        stq     $2,16($30)
@@ -60,11 +56,12 @@ switch_to_osf_pal:
        stq     $13,104($30)
        stq     $14,112($30)
        stq     $15,120($30)
+       .prologue 0
 
        stq     $30,0($17)      /* save KSP in PCB */
 
        bis     $30,$30,$20     /* a4 = KSP */
-       br      $17,__do_swppal
+       br      $17,1f
 
        ldq     $26,0($30)
        ldq     $1,8($30)
@@ -84,56 +81,22 @@ switch_to_osf_pal:
        ldq     $15,120($30)
        addq    $30,128,$30
        ret ($26)
-
-__do_swppal:
-       .long   PAL_swppal
+1:     call_pal PAL_swppal
        .end    switch_to_osf_pal
 
-.globl dispatch
-.ent   dispatch
-dispatch:
-       subq    $30,80,$30
-       stq     $26,0($30)
-       stq     $29,8($30)
-
-       stq     $8,16($30)
-       stq     $9,24($30)
-       stq     $10,32($30)
-       stq     $11,40($30)
-       stq     $12,48($30)
-       stq     $13,56($30)
-       stq     $14,64($30)
-       stq     $15,72($30)
-
-       lda     $1,0x10000000           /* hwrpb */
-       ldq     $2,0xc0($1)             /* crb offset */
-       addq    $2,$1,$2                /* crb */
-       ldq     $27,0($2)               /* dispatch procedure value */
-
-       ldq     $2,8($27)               /* dispatch call address */
-       jsr     $26,($2)                /* call it (weird VMS call seq) */
-
-       ldq     $26,0($30)
-       ldq     $29,8($30)
-
-       ldq     $8,16($30)
-       ldq     $9,24($30)
-       ldq     $10,32($30)
-       ldq     $11,40($30)
-       ldq     $12,48($30)
-       ldq     $13,56($30)
-       ldq     $14,64($30)
-       ldq     $15,72($30)
-
-       addq    $30,80,$30
-       ret     $31,($26)
-.end    dispatch
-
        .align 3
        .globl  tbi
        .ent    tbi
 tbi:
-       .long PAL_tbi
+       .prologue 0
+       call_pal PAL_tbi
        ret     ($26)
        .end tbi
 
+       .align 3
+       .globl  halt
+       .ent    halt
+halt:
+       .prologue 0
+       call_pal PAL_halt
+       .end halt
index 9d0f5769ec50bf0863db2f01b95aba9b2ac54355..8b17580b541efacb249a5f2695df36793d2b2e12 100644 (file)
@@ -175,8 +175,6 @@ then
        define_bool CONFIG_ALPHA_AVANTI y
 fi
 
-#bool 'Echo console messages on /dev/ttyS0 (COM1)' CONFIG_SERIAL_ECHO
-
 if [ "$CONFIG_PCI" = "y" ]; then
   bool 'PCI quirks' CONFIG_PCI_QUIRKS
   if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
index a7047dd1f4f4fa96d4d69ca43ec450ccc4ba1d4a..f19807c4644ca185c07cc698bbc5fcd28f8a820c 100644 (file)
@@ -136,6 +136,37 @@ EXPORT_SYMBOL_NOVERS(__do_clear_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__strlen_user);
 
+/* 
+ * SMP-specific symbols.
+ */
+
+#ifdef __SMP__
+EXPORT_SYMBOL(synchronize_irq);
+EXPORT_SYMBOL(flush_tlb_all);
+EXPORT_SYMBOL(flush_tlb_mm);
+EXPORT_SYMBOL(flush_tlb_page);
+EXPORT_SYMBOL(flush_tlb_range);
+EXPORT_SYMBOL(cpu_data);
+EXPORT_SYMBOL(cpu_number_map);
+EXPORT_SYMBOL(global_bh_lock);
+EXPORT_SYMBOL(global_bh_count);
+EXPORT_SYMBOL(synchronize_bh);
+EXPORT_SYMBOL(global_irq_holder);
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
+#if DEBUG_SPINLOCK
+EXPORT_SYMBOL(spin_unlock);
+EXPORT_SYMBOL(spin_lock);
+EXPORT_SYMBOL(spin_trylock);
+#endif
+#if DEBUG_RWLOCK
+EXPORT_SYMBOL(write_lock);
+EXPORT_SYMBOL(read_lock);
+#endif
+#endif /* __SMP__ */
+
 /*
  * The following are special because they're not called
  * explicitly (the C compiler or assembler generates them in
index efeb1c5560331c7fbae922752271c2ce1ccbd4b8..7a417938bab16979b9e84424e01255e1f7652910 100644 (file)
@@ -524,16 +524,8 @@ layout_dev(struct pci_dev *dev)
                        size = (mask & base) & 0xffffffff;
                        switch (type) {
                        case PCI_BASE_ADDRESS_MEM_TYPE_32:
-                               break;
-
                        case PCI_BASE_ADDRESS_MEM_TYPE_64:
-                               printk("bios32 WARNING: "
-                                      "ignoring 64-bit device in "
-                                      "slot %d, function %d: \n",
-                                      PCI_SLOT(dev->devfn),
-                                      PCI_FUNC(dev->devfn));
-                               idx++;  /* skip extra 4 bytes */
-                               continue;
+                               break;
 
                        case PCI_BASE_ADDRESS_MEM_TYPE_1M:
                                /*
@@ -594,6 +586,29 @@ layout_dev(struct pci_dev *dev)
                                                   off, base);
                        handle = PCI_HANDLE(bus->number) | base;
                        dev->base_address[idx] = handle;
+
+                       /*
+                        * Currently for 64-bit cards, we simply do the usual
+                        * for setup of the first register (low) of the pair,
+                        * and then clear out the second (high) register, as
+                        * we are not yet able to do 64-bit addresses, and
+                        * setting the high register to 0 allows 32-bit SAC
+                        * addresses to be used.
+                        */
+                       if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
+                               pcibios_write_config_dword(bus->number,
+                                                          dev->devfn,
+                                                          off+4, 0);
+                               /* Bypass hi reg in the loop.  */
+                               dev->base_address[++idx] = 0;
+
+                               printk("bios32 WARNING: "
+                                      "handling 64-bit device in "
+                                      "slot %d, function %d: \n",
+                                      PCI_SLOT(dev->devfn),
+                                      PCI_FUNC(dev->devfn));
+                       }
+
                        DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
                                  dev->device, handle, size));
                }
@@ -692,36 +707,46 @@ layout_bus(struct pci_bus *bus)
                struct pci_dev *bridge = bus->self;
 
                DBG_DEVS(("layout_bus: config bus %d bridge\n", bus->number));
+
                /*
                 * Set up the top and bottom of the PCI I/O segment
                 * for this bus.
                 */
                pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
-                                         0x1c, &l);
+                                         PCI_IO_BASE, &l);
                l &= 0xffff0000;
                l |= ((bio >> 8) & 0x00f0) | ((tio - 1) & 0xf000);
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-                                          0x1c, l);
+                                          PCI_IO_BASE, l);
+
+               /* Also clear out the upper 16 bits.  */
+               pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
+                                          PCI_IO_BASE_UPPER16, 0);
+
                /*
                 * Set up the top and bottom of the  PCI Memory segment
                 * for this bus.
                 */
                l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-                                          0x20, l);
+                                          PCI_MEMORY_BASE, l);
                /*
                 * Turn off downstream PF memory address range:
                 */
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-                                          0x24, 0x0000ffff);
+                                          PCI_PREF_MEMORY_BASE, 0x0000ffff);
+
                /*
                 * Tell bridge that there is an ISA bus in the system,
                 * and (possibly) a VGA as well.
                 */
+               /* ??? This appears to be a single-byte write into MIN_GNT.
+                  What is up with this?  */
                l = 0x00040000; /* ISA present */
                if (found_vga) l |= 0x00080000; /* VGA present */
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
                                           0x3c, l);
+
                /*
                 * Clear status bits, enable I/O (for downstream I/O),
                 * turn on master enable (for upstream I/O), turn on
@@ -729,7 +754,7 @@ layout_bus(struct pci_bus *bus)
                 * master enable (for upstream memory and I/O).
                 */
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-                                          0x4, 0xffff0007);
+                                          PCI_COMMAND, 0xffff0007);
        }
        DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
        return found_vga;
index dc14cfaaa6b3e8b311b1017be11393ee22fcb0d2..f0a5c3eb835150c0db8e1215aefd7d18b69889ad 100644 (file)
@@ -99,33 +99,13 @@ static int
 mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
             unsigned char *type1)
 {
-       unsigned long addr;
+       *type1 = (bus == 0) ? 0 : 1;
+       *pci_addr = (bus << 16) | (device_fn << 8) | (where);
 
        DBG_CNF(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
-                " pci_addr=0x%p, type1=0x%p)\n",
-                bus, device_fn, where, pci_addr, type1));
-
-       if (bus == 0) {
-               int device;
-
-               device = device_fn >> 3;
-               /* Type 0 configuration cycle. */
-#if NOT_NOW
-               if (device > 20) {
-                       DBG_CNF(("mk_conf_addr: device (%d) > 20, return -1\n",
-                                device));
-                       return -1;
-               }
-#endif
-               *type1 = 0;
-               addr = (device_fn << 8) | (where);
-       } else {
-               /* Type 1 configuration cycle.  */
-               *type1 = 1;
-               addr = (bus << 16) | (device_fn << 8) | (where);
-       }
-       *pci_addr = addr;
-       DBG_CNF(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+                " returning address 0x%p\n"
+                bus, device_fn, where, *pci_addr));
+
        return 0;
 }
 
@@ -142,12 +122,11 @@ conf_read(unsigned long addr, unsigned char type1)
        stat0 = *(vuip)PYXIS_ERR;
        *(vuip)PYXIS_ERR = stat0; mb();
        temp = *(vuip)PYXIS_ERR;  /* re-read to force write */
-       DBG_CNF(("conf_read: PYXIS ERR was 0x%x\n", stat0));
 
        /* If Type1 access, must set PYXIS CFG.  */
        if (type1) {
                pyxis_cfg = *(vuip)PYXIS_CFG;
-               *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
+               *(vuip)PYXIS_CFG = (pyxis_cfg & ~3L) | 1; mb();
                temp = *(vuip)PYXIS_CFG;  /* re-read to force write */
        }
 
@@ -172,14 +151,15 @@ conf_read(unsigned long addr, unsigned char type1)
 
        /* If Type1 access, must reset IOC CFG so normal IO space ops work.  */
        if (type1) {
-               *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
+               *(vuip)PYXIS_CFG = pyxis_cfg & ~3L; mb();
                temp = *(vuip)PYXIS_CFG;  /* re-read to force write */
        }
 
+       __restore_flags(flags);
+
        DBG_CNF(("conf_read(addr=0x%lx, type1=%d) = %#x\n",
                 addr, type1, value));
 
-       __restore_flags(flags);
        return value;
 }
 
@@ -190,9 +170,6 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
        unsigned int stat0, temp;
        unsigned int pyxis_cfg = 0;
 
-       DBG_CNF(("conf_write(addr=%#lx, value=%#x, type1=%d)\n",
-                addr, value, type1));
-
        __save_and_cli(flags);  /* avoid getting hit by machine check */
 
        /* Reset status register to avoid losing errors.  */
@@ -203,7 +180,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
        /* If Type1 access, must set PYXIS CFG.  */
        if (type1) {
                pyxis_cfg = *(vuip)PYXIS_CFG;
-               *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
+               *(vuip)PYXIS_CFG = (pyxis_cfg & ~3L) | 1; mb();
                temp = *(vuip)PYXIS_CFG;  /* re-read to force write */
        }
 
@@ -216,18 +193,20 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
        /* Access configuration space.  */
        *(vuip)addr = value;
        mb();
-       mb();  /* magic */
-       temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */
+       temp = *(vuip)addr; /* read back to force the write */
        PYXIS_mcheck_expected = 0;
        mb();
 
        /* If Type1 access, must reset IOC CFG so normal IO space ops work.  */
        if (type1) {
-               *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
+               *(vuip)PYXIS_CFG = pyxis_cfg & ~3L; mb();
                temp = *(vuip)PYXIS_CFG;  /* re-read to force write */
        }
 
        __restore_flags(flags);
+
+       DBG_CNF(("conf_write(addr=%#lx, value=%#x, type1=%d)\n",
+                addr, value, type1));
 }
 
 int
index 82e0c71b9ef5dc28c28c18926134dea2a6e324ff..f349ebd6b8a35e5399f6b7e158276e5ad6f5fc64 100644 (file)
@@ -552,7 +552,6 @@ entSys:
 ret_from_sys_call:
        cmovne  $26,0,$19               /* $19 = 0 => non-restartable */
        /* check bottom half interrupts */
-       bne     $1,ret_from_handle_bh
        ldq     $3,bh_active
        ldq     $4,bh_mask
        and     $3,$4,$2
@@ -678,7 +677,7 @@ signal_return:
        bis     $30,$30,$18
        bis     $31,$31,$16
        jsr     $26,do_signal
-       lda     $30,SWITCH_STACK_SIZE($30)
+       bsr     $1,undo_switch_stack
        br      $31,restore_all
 .end entSys
 
index 92e11a82ec0b8d0e5fe94d32eeccf1164e4b44ec..8ba50462bc9236b8d1937a64a80ada05ae67d586 100644 (file)
@@ -9,8 +9,6 @@
 
 #include <asm/system.h>
 
-#define halt call_pal PAL_halt
-
 .globl swapper_pg_dir
 .globl _stext
 swapper_pg_dir=SWAPPER_PGD
@@ -29,28 +27,28 @@ __start:
        lda     $30,0x4000($8)
        /* ... and then we can start the kernel.  */
        jsr     $26,start_kernel
-       halt
+       call_pal PAL_halt
        .end __start
 
 #ifdef __SMP__
        .align 3
        .globl  __start_cpu
        .ent    __start_cpu
-       /* on entry here from SRM console, the HWPCB of this processor */
-       /* has been loaded, and $27 contains the task pointer */
+       /* On entry here from SRM console, the HWPCB of this processor
+          has been loaded, and $27 contains the task pointer */
 __start_cpu:
        .prologue 0
-       /* first order of business, load the GP */
+       /* First order of business, load the GP */
        br      $26,1f
 1:     ldgp    $29,0($26)
        /* We need to get current loaded up with our first task...  */
-       lda     $8,0($27)
-       /* set FEN */
+       mov     $27,$8
+       /* Set FEN */
        lda     $16,1($31)
        call_pal PAL_wrfen
        /* ... and then we can start the processor.  */
        jsr     $26,start_secondary
-       halt
+       call_pal PAL_halt
        .end __start_cpu
 #endif /* __SMP__ */
 
@@ -121,10 +119,20 @@ whami:
        .globl  wripir
        .ent    wripir
 wripir:
+       .prologue 0
        call_pal PAL_wripir
        ret     ($26)
        .end wripir
 
+       .align 3
+       .globl wrvptptr
+       .ent wrvptptr
+wrvptptr:
+       .prologue 0
+       call_pal PAL_wrvptptr
+       ret     ($26)
+       .end wrvptptr
+
        #
        # The following two functions are needed for supporting SRM PALcode
        # on the PC164 (at least), since that PALcode manages the interrupt
@@ -152,3 +160,17 @@ cserve_dis:
        call_pal PAL_cserve
        ret     ($26)
        .end    cserve_dis
+
+       #
+       # It is handy, on occasion, to make halt actually just loop. 
+       # Putting it here means we dont have to recompile the whole
+       # kernel.
+       #
+
+       .align 3
+       .globl  halt
+       .ent    halt
+halt:
+       .prologue 0
+       call_pal PAL_halt
+       .end    halt
index e8fee6a0d2fc748b5279f1cdab460ee06a839ed5..8f6afc14b93045de27ccd476ffabf989e8d8b3f4 100644 (file)
@@ -311,26 +311,41 @@ free_irq(unsigned int irq, void *dev_id)
 
 int get_irq_list(char *buf)
 {
-       int i, len = 0;
+       int i, j;
        struct irqaction * action;
-       int cpu = smp_processor_id();
+       char *p = buf;
+
+#ifdef __SMP__
+       p += sprintf(p, "           ");
+       for (j = 0; j < smp_num_cpus; j++)
+               p += sprintf(p, "CPU%d       ", j);
+       *p++ = '\n';
+#endif
 
        for (i = 0; i < NR_IRQS; i++) {
                action = irq_action[i];
                if (!action) 
                        continue;
-               len += sprintf(buf+len, "%2d: %10u %c %s",
-                              i, kstat.irqs[cpu][i],
-                              (action->flags & SA_INTERRUPT) ? '+' : ' ',
-                              action->name);
+               p += sprintf(p, "%3d: ",i);
+#ifndef __SMP__
+               p += sprintf(p, "%10u ", kstat_irqs(i));
+#else
+               for (j = 0; j < smp_num_cpus; j++)
+                       p += sprintf(p, "%10u ",
+                                    kstat.irqs[cpu_logical_map(j)][i]);
+#endif
+               p += sprintf(p, "  %c%s",
+                            (action->flags & SA_INTERRUPT)?'+':' ',
+                            action->name);
+
                for (action=action->next; action; action = action->next) {
-                       len += sprintf(buf+len, ", %s%s",
-                                      (action->flags & SA_INTERRUPT) ? "+":"",
-                                      action->name);
+                       p += sprintf(p, ", %c%s",
+                                    (action->flags & SA_INTERRUPT)?'+':' ',
+                                    action->name);
                }
-               len += sprintf(buf+len, "\n");
+               *p++ = '\n';
        }
-       return len;
+       return p - buf;
 }
 
 #ifdef __SMP__
@@ -427,8 +442,10 @@ get_irqlock(int cpu, void* where)
        /*
         * Finally.
         */
+#if DEBUG_SPINLOCK
        global_irq_lock.task = current;
        global_irq_lock.previous = where;
+#endif
        global_irq_holder = cpu;
        previous_irqholder = where;
 }
index d604b6eacbf7a8d9206891b2e318a5399aebebba..c46d5df4e82bd6ce0e50f84a343dfe92ca07d26f 100644 (file)
 #define STANDARD_INIT_IRQ_PROLOG       \
        outb(0, DMA1_RESET_REG);        \
        outb(0, DMA2_RESET_REG);        \
-       outb(0, DMA1_MASK_REG);         \
-       outb(0, DMA2_MASK_REG);         \
        outb(0, DMA1_CLR_MASK_REG);     \
-       outb(0, DMA2_CLR_MASK_REG);     \
-       outb(DMA_MODE_CASCADE, DMA2_MODE_REG)
-
+       outb(0, DMA2_CLR_MASK_REG)
 
 extern unsigned long alpha_irq_mask;
 
index 645791060ef50efa82d64b21afded64bf83d9f92..70c85c45119a52bf92a8ac20629cd5522a57aa39 100644 (file)
@@ -27,8 +27,7 @@
 #define CAT1(x,y)  x##y
 #define CAT(x,y)   CAT1(x,y)
 
-#define DO_DEFAULT_RTC                         \
-       rtc_port: 0x70, rtc_addr: 0x80, rtc_bcd: 0
+#define DO_DEFAULT_RTC rtc_port: 0x70
 
 #define DO_EV4_MMU                                                     \
        max_asn:                        EV4_MAX_ASN,                    \
index 6162e33759b4fe909c3f2f52d5d5001f6add7802..0f6c843bc058fd0b7c2c7e23dd0d12fb104c0f00 100644 (file)
@@ -181,6 +181,9 @@ generic_kill_arch (int mode, char *restart_cmd)
                return;
        }
 
+       if (alpha_using_srm)
+               srm_paging_stop();
+
        halt();
 }
 
index 43f5c18a4c6715a606e607a7adc57c0b2ca32ce2..15096703dc3077ce3d97aca8c1ca731c922f267c 100644 (file)
@@ -143,6 +143,7 @@ extern void reset_for_srm(void);
 
 /* time.c */
 extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
+extern unsigned long est_cycle_freq;
 
 /* smc37c93x.c */
 extern void SMC93x_Init(void);
@@ -172,5 +173,12 @@ extern void entSys(void);
 extern void entUna(void);
 
 /* process.c */
-void generic_kill_arch (int mode, char *reboot_cmd);
-void cpu_idle(void *) __attribute__((noreturn));
+extern void generic_kill_arch (int mode, char *reboot_cmd);
+extern void cpu_idle(void *) __attribute__((noreturn));
+
+/* ptrace.c */
+extern int ptrace_set_bpt (struct task_struct *child);
+extern int ptrace_cancel_bpt (struct task_struct *child);
+
+/* ../mm/init.c */
+void srm_paging_stop(void);
index 55f1713275dc114af5c878f65993de743aa68b9b..b6194defac658158695b95b991b8add2bccd7e49 100644 (file)
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/malloc.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
+#include "proto.h"
+
+#define DEBUG  DBG_MEM
 #undef DEBUG
 
 #ifdef DEBUG
-
 enum {
        DBG_MEM         = (1<<0),
        DBG_BPT         = (1<<1),
        DBG_MEM_ALL     = (1<<2)
 };
-
-int debug_mask = DBG_BPT;
-
-# define DBG(fac,args) {if ((fac) & debug_mask) printk args;}
-
+#define DBG(fac,args)  {if ((fac) & DEBUG) printk args;}
 #else
-# define DBG(fac,args)
+#define DBG(fac,args)
 #endif
 
 #define BREAKINST      0x00000080      /* call_pal bpt */
@@ -45,33 +44,26 @@ int debug_mask = DBG_BPT;
 /*
  * Processes always block with the following stack-layout:
  *
- *  +================================+ --------------------------
- *  | PALcode saved frame (ps, pc,   | ^                     ^
- *  | gp, a0, a1, a2)               | |                      |
- *  +================================+ | struct pt_regs              |
- *  |                               | |                      |
- *  | frame generated by SAVE_ALL    | |                     |
- *  |                               | v                      | P
- *  +================================+                       | A
- *  |                               | ^                      | G
- *  | frame saved by do_switch_stack | | struct switch_stack  |        E
- *  |                               | v                      | _
- *  +================================+                       | S
- *  |                               |                        | I
- *  |                               |                        | Z
- *  /                               /                        | E
- *  /                               /                        |
- *  |                               |                        |
- *  |                               |                        |
- *  |                               |                        v
- *  +================================+ <-------------------------
- *                                     task + PAGE_SIZE
+ *  +================================+ <---- task + 2*PAGE_SIZE
+ *  | PALcode saved frame (ps, pc,   | ^
+ *  | gp, a0, a1, a2)               | |
+ *  +================================+ | struct pt_regs
+ *  |                               | |
+ *  | frame generated by SAVE_ALL    | |
+ *  |                               | v
+ *  +================================+
+ *  |                               | ^
+ *  | frame saved by do_switch_stack | | struct switch_stack
+ *  |                               | v
+ *  +================================+
  */
-#define PT_REG(reg)    (PAGE_SIZE - sizeof(struct pt_regs)     \
+#define PT_REG(reg)    (PAGE_SIZE*2 - sizeof(struct pt_regs)           \
                         + (long)&((struct pt_regs *)0)->reg)
-#define SW_REG(reg)    (PAGE_SIZE - sizeof(struct pt_regs)     \
-                        - sizeof(struct switch_stack)          \
+
+#define SW_REG(reg)    (PAGE_SIZE*2 - sizeof(struct pt_regs)           \
+                        - sizeof(struct switch_stack)                  \
                         + (long)&((struct switch_stack *)0)->reg)
+
 /* 
  * The following table maps a register index into the stack offset at
  * which the register is saved.  Register indices are 0-31 for integer
@@ -80,10 +72,10 @@ int debug_mask = DBG_BPT;
  * get_reg/put_reg below).
  */
 enum {
-       REG_R0 = 0, REG_F0 = 32, REG_PC = 64
+       REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
 };
 
-static unsigned short regoff[] = {
+static int regoff[] = {
        PT_REG(    r0), PT_REG(    r1), PT_REG(    r2), PT_REG(   r3),
        PT_REG(    r4), PT_REG(    r5), PT_REG(    r6), PT_REG(   r7),
        PT_REG(    r8), SW_REG(    r9), SW_REG(   r10), SW_REG(  r11),
@@ -106,38 +98,40 @@ static unsigned short regoff[] = {
 static long zero;
 
 /*
- * Get contents of register REGNO in task TASK.
+ * Get address of register REGNO in task TASK.
  */
-static inline long get_reg(struct task_struct * task, long regno)
+static long *
+get_reg_addr(struct task_struct * task, unsigned long regno)
 {
        long *addr;
 
        if (regno == 30) {
                addr = &task->tss.usp;
-       } else if (regno == 31) {
+       } else if (regno == 31 || regno > 64) {
                zero = 0;
                addr = &zero;
        } else {
-               addr = (long *) (regoff[regno] + PAGE_SIZE + (long)task);
+               addr = (long *)((long)task + regoff[regno]);
        }
-       return *addr;
+       return addr;
 }
 
 /*
- * Write contents of register REGNO in task TASK.
+ * Get contents of register REGNO in task TASK.
  */
-static inline int put_reg(struct task_struct *task, long regno, long data)
+static inline long
+get_reg(struct task_struct * task, unsigned long regno)
 {
-       long *addr, zero;
+       return *get_reg_addr(task, regno);
+}
 
-       if (regno == 30) {
-               addr = &task->tss.usp;
-       } else if (regno == 31) {
-               addr = &zero;
-       } else {
-               addr = (long *) (regoff[regno] + PAGE_SIZE + (long)task);
-       }
-       *addr = data;
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int
+put_reg(struct task_struct *task, unsigned long regno, long data)
+{
+       *get_reg_addr(task, regno) = data;
        return 0;
 }
 
@@ -147,8 +141,9 @@ static inline int put_reg(struct task_struct *task, long regno, long data)
  * and that it is in the task area before calling this: this routine does
  * no checking.
  */
-static unsigned long get_long(struct task_struct * tsk,
-                             struct vm_area_struct * vma, unsigned long addr)
+static unsigned long
+get_long(struct task_struct * tsk, struct vm_area_struct * vma,
+        unsigned long addr)
 {
        pgd_t * pgdir;
        pmd_t * pgmiddle;
@@ -199,8 +194,9 @@ static unsigned long get_long(struct task_struct * tsk,
  * Now keeps R/W state of page so that a text page stays readonly
  * even if a debugger scribbles breakpoints into it.  -M.U-
  */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
-                    unsigned long addr, unsigned long data)
+static void
+put_long(struct task_struct * tsk, struct vm_area_struct * vma,
+        unsigned long addr, unsigned long data)
 {
        pgd_t *pgdir;
        pmd_t *pgmiddle;
@@ -250,8 +246,8 @@ static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
        flush_tlb();
 }
 
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
-                                              unsigned long addr)
+static struct vm_area_struct *
+find_extend_vma(struct task_struct * tsk, unsigned long addr)
 {
        struct vm_area_struct * vma;
 
@@ -274,8 +270,8 @@ static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
  * This routine checks the page boundaries, and that the offset is
  * within the task area. It then calls get_long() to read a long.
  */
-static int read_long(struct task_struct * tsk, unsigned long addr,
-                    unsigned long * result)
+static int
+read_long(struct task_struct * tsk, unsigned long addr, unsigned long * result)
 {
        struct vm_area_struct * vma = find_extend_vma(tsk, addr);
 
@@ -315,8 +311,8 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
  * This routine checks the page boundaries, and that the offset is
  * within the task area. It then calls put_long() to write a long.
  */
-static int write_long(struct task_struct * tsk, unsigned long addr,
-                     unsigned long data)
+static int
+write_long(struct task_struct * tsk, unsigned long addr, unsigned long data)
 {
        struct vm_area_struct * vma = find_extend_vma(tsk, addr);
 
@@ -349,8 +345,8 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
 /*
  * Read a 32bit int from address space TSK.
  */
-static int read_int(struct task_struct * tsk, unsigned long addr,
-                   unsigned int *data)
+static int
+read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
 {
        unsigned long l, align;
        int res;
@@ -376,8 +372,8 @@ static int read_int(struct task_struct * tsk, unsigned long addr,
  * For simplicity, do a read-modify-write of the 64bit word that
  * contains the 32bit word that we are about to write.
  */
-static int write_int(struct task_struct * tsk, unsigned long addr,
-                    unsigned int data)
+static int
+write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
 {
        unsigned long l, align;
        int res;
@@ -400,7 +396,8 @@ static int write_int(struct task_struct * tsk, unsigned long addr,
 /*
  * Set breakpoint.
  */
-int ptrace_set_bpt(struct task_struct * child)
+int
+ptrace_set_bpt(struct task_struct * child)
 {
        int displ, i, res, reg_b, nsaved = 0;
        u32 insn, op_code;
@@ -422,31 +419,31 @@ int ptrace_set_bpt(struct task_struct * child)
                 * branch (emulation can be tricky for fp branches).
                 */
                displ = ((s32)(insn << 11)) >> 9;
-               child->tss.debugreg[nsaved++] = pc + 4;
+               child->tss.bpt_addr[nsaved++] = pc + 4;
                if (displ)              /* guard against unoptimized code */
-                       child->tss.debugreg[nsaved++] = pc + 4 + displ;
+                       child->tss.bpt_addr[nsaved++] = pc + 4 + displ;
                DBG(DBG_BPT, ("execing branch\n"));
        } else if (op_code == 0x1a) {
                reg_b = (insn >> 16) & 0x1f;
-               child->tss.debugreg[nsaved++] = get_reg(child, reg_b);
+               child->tss.bpt_addr[nsaved++] = get_reg(child, reg_b);
                DBG(DBG_BPT, ("execing jump\n"));
        } else {
-               child->tss.debugreg[nsaved++] = pc + 4;
+               child->tss.bpt_addr[nsaved++] = pc + 4;
                DBG(DBG_BPT, ("execing normal insn\n"));
        }
 
        /* install breakpoints: */
        for (i = 0; i < nsaved; ++i) {
-               res = read_int(child, child->tss.debugreg[i], &insn);
+               res = read_int(child, child->tss.bpt_addr[i], &insn);
                if (res < 0)
                        return res;
-               child->tss.debugreg[i + 2] = insn;
-               DBG(DBG_BPT, ("    -> next_pc=%lx\n", child->tss.debugreg[i]));
-               res = write_int(child, child->tss.debugreg[i], BREAKINST);
+               child->tss.bpt_insn[i] = insn;
+               DBG(DBG_BPT, ("    -> next_pc=%lx\n", child->tss.bpt_addr[i]));
+               res = write_int(child, child->tss.bpt_addr[i], BREAKINST);
                if (res < 0)
                        return res;
        }
-       child->tss.debugreg[4] = nsaved;
+       child->tss.bpt_nsaved = nsaved;
        return 0;
 }
 
@@ -454,11 +451,12 @@ int ptrace_set_bpt(struct task_struct * child)
  * Ensure no single-step breakpoint is pending.  Returns non-zero
  * value if child was being single-stepped.
  */
-int ptrace_cancel_bpt(struct task_struct * child)
+int
+ptrace_cancel_bpt(struct task_struct * child)
 {
-       int i, nsaved = child->tss.debugreg[4];
+       int i, nsaved = child->tss.bpt_nsaved;
 
-       child->tss.debugreg[4] = 0;
+       child->tss.bpt_nsaved = 0;
 
        if (nsaved > 2) {
                printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
@@ -466,16 +464,18 @@ int ptrace_cancel_bpt(struct task_struct * child)
        }
 
        for (i = 0; i < nsaved; ++i) {
-               write_int(child, child->tss.debugreg[i],
-                         child->tss.debugreg[i + 2]);
+               write_int(child, child->tss.bpt_addr[i],
+                         child->tss.bpt_insn[i]);
        }
        return (nsaved != 0);
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
-                          int a4, int a5, struct pt_regs regs)
+asmlinkage long
+sys_ptrace(long request, long pid, long addr, long data,
+          int a4, int a5, struct pt_regs regs)
 {
        struct task_struct *child;
+       unsigned long tmp;
        long ret;
 
        lock_kernel();
@@ -540,9 +540,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
        switch (request) {
        /* When I and D space are separate, these will need to be fixed.  */
        case PTRACE_PEEKTEXT: /* read word at location addr. */
-       case PTRACE_PEEKDATA: {
-               unsigned long tmp;
-
+       case PTRACE_PEEKDATA:
                ret = read_long(child, addr, &tmp);
                DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
                if (ret < 0)
@@ -550,13 +548,12 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
                regs.r0 = 0;    /* special return: no errors */
                ret = tmp;
                goto out;
-       }
 
-       /* read register number ADDR. */
+       /* Read register number ADDR. */
        case PTRACE_PEEKUSR:
                regs.r0 = 0;    /* special return: no errors */
-               DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
                ret = get_reg(child, addr);
+               DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret));
                goto out;
 
        /* When I and D space are separate, this will have to be fixed.  */
@@ -573,7 +570,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
 
        case PTRACE_SYSCALL: /* continue and stop at next
                                (return from) syscall */
-       case PTRACE_CONT: { /* restart after signal. */
+       case PTRACE_CONT:    /* restart after signal. */
                ret = -EIO;
                if ((unsigned long) data > _NSIG)
                        goto out;
@@ -587,14 +584,13 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
                ptrace_cancel_bpt(child);
                ret = data;
                goto out;
-       }
 
        /*
         * Make the child exit.  Best I can do is send it a sigkill.
         * perhaps it should be put in the status that it wants to
         * exit.
         */
-       case PTRACE_KILL: {
+       case PTRACE_KILL:
                if (child->state != TASK_ZOMBIE) {
                        wake_up_process(child);
                        child->exit_code = SIGKILL;
@@ -603,22 +599,20 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
                ptrace_cancel_bpt(child);
                ret = 0;
                goto out;
-       }
 
-       case PTRACE_SINGLESTEP:  /* execute single instruction. */
+       case PTRACE_SINGLESTEP:  /* execute single instruction. */
                ret = -EIO;
                if ((unsigned long) data > _NSIG)
                        goto out;
-               child->tss.debugreg[4] = -1;    /* mark single-stepping */
+               child->tss.bpt_nsaved = -1;     /* mark single-stepping */
                child->flags &= ~PF_TRACESYS;
                wake_up_process(child);
                child->exit_code = data;
                /* give it a chance to run. */
                ret = 0;
                goto out;
-       }
 
-       case PTRACE_DETACH: /* detach a process that was attached. */
+       case PTRACE_DETACH: /* detach a process that was attached. */
                ret = -EIO;
                if ((unsigned long) data > _NSIG)
                        goto out;
@@ -632,7 +626,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
                ptrace_cancel_bpt(child);
                ret = 0;
                goto out;
-       }
 
        default:
                ret = -EIO;
@@ -643,7 +636,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
        return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage void
+syscall_trace(void)
 {
        if ((current->flags & (PF_PTRACED|PF_TRACESYS))
            != (PF_PTRACED|PF_TRACESYS))
index ba816ac05da4f6f0f38e55b2ab6c39e9e49803b4..e18cddf9510e856198933c063832378a75af7b94 100644 (file)
@@ -467,19 +467,22 @@ get_sysvec(long type, long variation, long cpu)
                                vec = eb66_vecs[eb66_indices[member]];
                        break;
                case ST_DEC_1000:
-                       if (cpu == EV5_CPU)
+                       cpu &= 0xffffffff;
+                       if (cpu == EV5_CPU || cpu == EV56_CPU)
                                vec = &mikasa_primo_mv;
                        else
                                vec = &mikasa_mv;
                        break;
                case ST_DEC_NORITAKE:
-                       if (cpu == EV5_CPU)
+                       cpu &= 0xffffffff;
+                       if (cpu == EV5_CPU || cpu == EV56_CPU)
                                vec = &noritake_primo_mv;
                        else
                                vec = &noritake_mv;
                        break;
                case ST_DEC_2100_A500:
-                       if (cpu == EV5_CPU)
+                       cpu &= 0xffffffff;
+                       if (cpu == EV5_CPU || cpu == EV56_CPU)
                                vec = &sable_gamma_mv;
                        else
                                vec = &sable_mv;
@@ -678,7 +681,7 @@ int get_cpuinfo(char *buffer)
                      "system variation\t: %s\n"
                      "system revision\t\t: %ld\n"
                      "system serial number\t: %s\n"
-                     "cycle frequency [Hz]\t: %lu\n"
+                     "cycle frequency [Hz]\t: %lu %s\n"
                      "timer frequency [Hz]\t: %lu.%02lu\n"
                      "page size [bytes]\t: %ld\n"
                      "phys. address bits\t: %ld\n"
@@ -691,7 +694,8 @@ int get_cpuinfo(char *buffer)
                       (char*)cpu->serial_no,
                       systype_name, sysvariation_name, hwrpb->sys_revision,
                       (char*)hwrpb->ssn,
-                      hwrpb->cycle_freq,
+                      hwrpb->cycle_freq ? : est_cycle_freq,
+                      hwrpb->cycle_freq ? "" : "est.",
                       hwrpb->intr_freq / 4096,
                       (100 * hwrpb->intr_freq / 4096) % 100,
                       hwrpb->pagesize,
@@ -703,8 +707,8 @@ int get_cpuinfo(char *buffer)
                       platform_string());
 
 #ifdef __SMP__
-       return len + smp_info(buffer+len);
-#else
-       return len;
+       len += smp_info(buffer+len);
 #endif
+
+       return len;
 }
index 22f8742e1c4053bfcf405a72f842aa1d5610b7d4..99bd367850d6d38363d0f97576934bc13d18b191 100644 (file)
@@ -33,9 +33,6 @@ asmlinkage void ret_from_sys_call(void);
 asmlinkage int do_signal(sigset_t *, struct pt_regs *,
                         struct switch_stack *, unsigned long, unsigned long);
 
-extern int ptrace_set_bpt (struct task_struct *child);
-extern int ptrace_cancel_bpt (struct task_struct *child);
-
 
 /*
  * The OSF/1 sigprocmask calling sequence is different from the
index 7d62ba5538a2811541e01d19e2bcfc8113573793..e583ba29b8d8e91225d961fe0bc50e1aa0bdb52f 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
@@ -86,21 +87,28 @@ static unsigned long __init SMCConfigState(unsigned long baseAddr)
        unsigned long indexPort;
        unsigned long dataPort;
 
+       int i;
+
        configPort = indexPort = baseAddr;
        dataPort = configPort + 1;
 
-       outb(CONFIG_ON_KEY, configPort);
-       outb(CONFIG_ON_KEY, configPort);
-       outb(DEVICE_ID, indexPort);
-       devId = inb(dataPort);
-       if ( devId == VALID_DEVICE_ID ) {
-               outb(DEVICE_REV, indexPort);
-               devRev = inb(dataPort);
-       }
-       else {
-               baseAddr = 0;
+#define NUM_RETRIES 5
+
+       for (i = 0; i < NUM_RETRIES; i++)
+       {
+               outb(CONFIG_ON_KEY, configPort);
+               outb(CONFIG_ON_KEY, configPort);
+               outb(DEVICE_ID, indexPort);
+               devId = inb(dataPort);
+               if (devId == VALID_DEVICE_ID) {
+                       outb(DEVICE_REV, indexPort);
+                       devRev = inb(dataPort);
+                       break;
+               }
+               else
+                       udelay(100);
        }
-       return baseAddr;
+       return (i != NUM_RETRIES) ? baseAddr : 0L;
 }
 
 static void __init SMCRunState(unsigned long baseAddr)
index 02ebc65e0eae16903ebc52115df50d4cb13771c9..19aa9a682a5f8a158fff0e8fb9bac59827831dd8 100644 (file)
@@ -39,6 +39,7 @@ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
 
 unsigned int boot_cpu_id = 0;
 static int smp_activated = 0;
+static unsigned long ipicnt[NR_CPUS] = {0,}; /* IPI counts */
 
 int smp_found_config = 0; /* Have we found an SMP box */
 static int max_cpus = -1;
@@ -619,7 +620,6 @@ local_flush_tlb_all(unsigned int this_cpu)
 {
        tbia();
        clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask);
-       mb();
        return 0;
 }
 
@@ -627,12 +627,9 @@ static int
 local_flush_tlb_mm(unsigned int this_cpu)
 {
        struct mm_struct * mm = ipi_msg_flush_tb.p.flush_mm;
-       if (mm != current->mm)
-               flush_tlb_other(mm);
-       else
+       if (mm == current->mm)
                flush_tlb_current(mm);
        clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask);
-       mb();
        return 0;
 }
 
@@ -642,12 +639,9 @@ local_flush_tlb_page(unsigned int this_cpu)
        struct vm_area_struct * vma = ipi_msg_flush_tb.p.flush_vma;
        struct mm_struct * mm = vma->vm_mm;
 
-       if (mm != current->mm)
-               flush_tlb_other(mm);
-       else
+       if (mm == current->mm)
                flush_tlb_current_page(mm, vma, ipi_msg_flush_tb.flush_addr);
        clear_bit(this_cpu, &ipi_msg_flush_tb.flush_tb_mask);
-       mb();
        return 0;
 }
 
@@ -701,7 +695,7 @@ handle_ipi(struct pt_regs *regs)
        volatile int * pending_ipis = &ipi_bits[this_cpu];
        int ops;
 
-       mb();
+       mb();           /* Order bit setting and interrupt. */
 #if 0
        printk("handle_ipi: on CPU %d ops 0x%x PC 0x%lx\n",
               this_cpu, *pending_ipis, regs->pc);
@@ -711,10 +705,10 @@ handle_ipi(struct pt_regs *regs)
                for (first = 0; (ops & 1) == 0; ++first, ops >>= 1)
                        ; /* look for the first thing to do */
                clear_bit(first, pending_ipis);
-               mb();
+               mb();   /* Order bit clearing and data access. */
                if ((*ipi_func[first])(this_cpu))
-                 printk("%d\n", first);
-               mb();
+                       printk("%d\n", first);
+               mb();   /* Order data access and bit clearing. */
        }
        if (hwrpb->txrdy)
          secondary_console_message();
@@ -726,19 +720,26 @@ send_ipi_message(long to_whom, enum ipi_message_type operation)
        int i;
        unsigned int j;
 
+       mb();                   /* Order out-of-band data and bit setting. */
        for (i = 0, j = 1; i < NR_CPUS; ++i, j += j) {
                if ((to_whom & j) == 0)
                        continue;
                set_bit(operation, &ipi_bits[i]);
-               mb();
+               mb();           /* Order bit setting and interrupt. */
                wripir(i);
        }
 }
 
-int smp_info(char *buffer)
+int
+smp_info(char *buffer)
 {
-        return sprintf(buffer, "CPUs probed %d active %d map 0x%x\n",
-                      smp_num_probed, smp_num_cpus, cpu_present_map);
+       int i;
+       unsigned long sum = 0;
+       for (i = 0; i < NR_CPUS; i++)
+               sum += ipicnt[i];
+
+        return sprintf(buffer, "CPUs probed %d active %d map 0x%x IPIs %ld\n",
+                      smp_num_probed, smp_num_cpus, cpu_present_map, sum);
 }
 
 /* wrapper for call from panic() */
@@ -763,19 +764,22 @@ flush_tlb_all(void)
        unsigned int to_whom = cpu_present_map ^ (1 << smp_processor_id());
        int timeout = 10000;
 
+       spin_lock_own(&kernel_flag, "flush_tlb_all");
+
        ipi_msg_flush_tb.flush_tb_mask = to_whom;
        send_ipi_message(to_whom, TLB_ALL);
        tbia();
 
        while (ipi_msg_flush_tb.flush_tb_mask) {
-         if (--timeout < 0) {
-           printk("flush_tlb_all: STUCK on CPU %d mask 0x%x\n",
-                  smp_processor_id(), ipi_msg_flush_tb.flush_tb_mask);
-           ipi_msg_flush_tb.flush_tb_mask = 0;
-           break;
-         }
-         udelay(100);
-               ; /* Wait for all clear from other CPUs. */
+               if (--timeout < 0) {
+                       printk("flush_tlb_all: STUCK on CPU %d mask 0x%x\n",
+                              smp_processor_id(),
+                              ipi_msg_flush_tb.flush_tb_mask);
+                       ipi_msg_flush_tb.flush_tb_mask = 0;
+                       break;
+               }
+               /* Wait for all clear from other CPUs. */
+               udelay(100);
        }
 }
 
@@ -785,6 +789,8 @@ flush_tlb_mm(struct mm_struct *mm)
        unsigned int to_whom = cpu_present_map ^ (1 << smp_processor_id());
        int timeout = 10000;
 
+       spin_lock_own(&kernel_flag, "flush_tlb_mm");
+
        ipi_msg_flush_tb.p.flush_mm = mm;
        ipi_msg_flush_tb.flush_tb_mask = to_whom;
        send_ipi_message(to_whom, TLB_MM);
@@ -814,6 +820,8 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
        struct mm_struct * mm = vma->vm_mm;
        int timeout = 10000;
 
+       spin_lock_own(&kernel_flag, "flush_tlb_page");
+
        ipi_msg_flush_tb.p.flush_vma = vma;
        ipi_msg_flush_tb.flush_addr = addr;
        ipi_msg_flush_tb.flush_tb_mask = to_whom;
@@ -849,6 +857,8 @@ flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
        timeout = 10000;
        to_whom = cpu_present_map ^ (1 << smp_processor_id());
 
+       spin_lock_own(&kernel_flag, "flush_tlb_range");
+
        ipi_msg_flush_tb.p.flush_mm = mm;
        ipi_msg_flush_tb.flush_tb_mask = to_whom;
        send_ipi_message(to_whom, TLB_MM);
@@ -871,11 +881,51 @@ flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
 }
 
 #if DEBUG_SPINLOCK
-void spin_lock(spinlock_t * lock)
+
+#ifdef MANAGE_SPINLOCK_IPL
+
+static inline long 
+spinlock_raise_ipl(spinlock_t * lock)
+{
+       long min_ipl = lock->target_ipl;
+       long last_ipl = swpipl(7);
+       if (last_ipl < 7 && min_ipl < 7)
+               setipl(min_ipl < last_ipl ? last_ipl : min_ipl);
+       return last_ipl;
+}
+
+static inline void
+spinlock_restore_ipl(long prev)
+{
+       setipl(prev);
+}
+
+#else
+
+#define spinlock_raise_ipl(LOCK)       0
+#define spinlock_restore_ipl(PREV)     ((void)0)
+
+#endif /* MANAGE_SPINLOCK_IPL */
+
+void
+spin_unlock(spinlock_t * lock)
+{
+       long old_ipl = lock->saved_ipl;
+       mb();
+       lock->lock = 0;
+       spinlock_restore_ipl(old_ipl);
+}
+
+void
+spin_lock(spinlock_t * lock)
 {
        long tmp;
-       long stuck;
+       long stuck = 1<<27;
        void *inline_pc = __builtin_return_address(0);
+       unsigned long started = jiffies;
+       int printed = 0;
+       int cpu = smp_processor_id();
+       long old_ipl = spinlock_raise_ipl(lock);
 
  try_again:
 
@@ -885,15 +935,15 @@ void spin_lock(spinlock_t * lock)
           of this object file's text section so as to perfect
           branch prediction.  */
        __asm__ __volatile__(
-       "1:     ldq_l   %0,%1\n"
+       "1:     ldl_l   %0,%1\n"
        "       subq    %2,1,%2\n"
        "       blbs    %0,2f\n"
        "       or      %0,1,%0\n"
-       "       stq_c   %0,%1\n"
+       "       stl_c   %0,%1\n"
        "       beq     %0,3f\n"
        "4:     mb\n"
        ".section .text2,\"ax\"\n"
-       "2:     ldq     %0,%1\n"
+       "2:     ldl     %0,%1\n"
        "       subq    %2,1,%2\n"
        "3:     blt     %2,4b\n"
        "       blbs    %0,2b\n"
@@ -905,13 +955,43 @@ void spin_lock(spinlock_t * lock)
        : "2" (stuck));
 
        if (stuck < 0) {
-               printk("spinlock stuck at %p (cur=%p, own=%p, prev=%p)\n",
-                      inline_pc, current, lock->task, lock->previous);
+               if (!printed) {
+                       printk("spinlock stuck at %p(%d) owner %s at %p\n",
+                              inline_pc, cpu, lock->task->comm,
+                              lock->previous);
+                       printed = 1;
+               }
+               stuck = 1<<30;
                goto try_again;
-       } else {
-               lock->previous = inline_pc;
+       }
+
+       /* Exiting.  Got the lock.  */
+       lock->saved_ipl = old_ipl;
+       lock->on_cpu = cpu;
+       lock->previous = inline_pc;
+       lock->task = current;
+
+       if (printed) {
+               printk("spinlock grabbed at %p(%d) %ld ticks\n",
+                      inline_pc, cpu, jiffies - started);
+       }
+}
+
+int
+spin_trylock(spinlock_t * lock)
+{
+       long old_ipl = spinlock_raise_ipl(lock);
+       int ret;
+       if ((ret = !test_and_set_bit(0, lock))) {
+               mb();
+               lock->saved_ipl = old_ipl;
+               lock->on_cpu = smp_processor_id();
+               lock->previous = __builtin_return_address(0);
                lock->task = current;
+       } else {
+               spinlock_restore_ipl(old_ipl);
        }
+       return ret;
 }
 #endif /* DEBUG_SPINLOCK */
 
@@ -930,22 +1010,21 @@ void write_lock(rwlock_t * lock)
        __asm__ __volatile__(
        "1:     ldl_l   %1,%0\n"
        "       blbs    %1,6f\n"
-       "       or      %1,1,%2\n"
-       "       stl_c   %2,%0\n"
-       "       beq     %2,6f\n"
        "       blt     %1,8f\n"
+       "       mov     1,%1\n"
+       "       stl_c   %1,%0\n"
+       "       beq     %1,6f\n"
        "4:     mb\n"
        ".section .text2,\"ax\"\n"
-       "6:     ldl     %1,%0\n"
-       "       blt     %3,4b   # debug\n"
+       "6:     blt     %3,4b   # debug\n"
        "       subl    %3,1,%3 # debug\n"
+       "       ldl     %1,%0\n"
        "       blbs    %1,6b\n"
-       "       br      1b\n"
-       "8:     ldl     %1,%0\n"
-       "       blt     %4,4b   # debug\n"
+       "8:     blt     %4,4b   # debug\n"
        "       subl    %4,1,%4 # debug\n"
+       "       ldl     %1,%0\n"
        "       blt     %1,8b\n"
-       "       br      4b\n"
+       "       br      1b\n"
        ".previous"
        : "=m" (__dummy_lock(lock)), "=&r" (regx), "=&r" (regy)
        , "=&r" (stuck_lock), "=&r" (stuck_reader)
index 9053b0085d1daea3e68fbf80b6cfcb0056f6596b..93a65e76ebdabc64b3ae69bd994c5bd76b2c5d9d 100644 (file)
@@ -128,7 +128,7 @@ struct alpha_machine_vector jensen_mv __initmv = {
        BUS(jensen),
        machine_check:          jensen_machine_check,
        max_dma_address:        ALPHA_MAX_DMA_ADDRESS,
-       rtc_port: 0x170, rtc_addr: 0, rtc_bcd: 1,
+       rtc_port: 0x170,
 
        nr_irqs:                16,
        irq_probe_mask:         _PROBE_MASK(16),
index e34b68952d56f5e60ccd6cba7192044e7d84d9ae..52aef8a777d1abf24ad0f0f9ed9e369e1f630fd7 100644 (file)
@@ -247,8 +247,7 @@ ruffian_kill_arch (int mode, char *reboot_cmd)
 struct alpha_machine_vector ruffian_mv __initmv = {
        vector_name:            "Ruffian",
        DO_EV5_MMU,
-       /* RUFFIAN always uses BCD, like a PeeCee.  */
-       rtc_port: 0x70, rtc_addr: 0x80, rtc_bcd: 1,
+       DO_DEFAULT_RTC,
        /* For the moment, do not use BWIO on RUFFIAN.  */
        IO(PYXIS,pyxis,pyxis),
        DO_PYXIS_BUS,
index 722b4f1a92112006a1fe9d2be985237deb748959..a03f451d07da9b83dc8551561ec456c0a7789ed3 100644 (file)
@@ -103,7 +103,10 @@ sx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
 static void
 sx164_init_irq(void)
 {
-       STANDARD_INIT_IRQ_PROLOG;
+       outb(0, DMA1_RESET_REG);
+       outb(0, DMA2_RESET_REG);
+       outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
+       outb(0, DMA2_MASK_REG);
 
        if (alpha_using_srm) {
                alpha_mv.update_irq_hw = sx164_srm_update_irq_hw;
index e0a7e115347e1d6cd0ccfa81e043e5347e29f04d..9f082b31455fda7bafb31da01e199fc39e8dc51f 100644 (file)
@@ -62,6 +62,8 @@ static struct {
        time_t last_rtc_update;
 } state;
 
+unsigned long est_cycle_freq;
+
 
 static inline __u32 rpcc(void)
 {
@@ -162,7 +164,7 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
  * drivers depend on them being initialized (e.g., joystick driver).
  */
 
-/* It is (normally) only counter 1 that presents config problems, so
+/* It is (normally) only counter 0 that presents config problems, so
    provide this support function to do the rest of the job.  */
 
 void inline
@@ -184,12 +186,20 @@ init_pit_rest(void)
 static inline void
 rtc_init_pit (void)
 {
+       unsigned char control;
+
        /* Setup interval timer if /dev/rtc is being used */
        outb(0x34, 0x43);               /* binary, mode 2, LSB/MSB, ch 0 */
        outb(LATCH & 0xff, 0x40);       /* LSB */
        outb(LATCH >> 8, 0x40);         /* MSB */
        request_region(0x40, 0x20, "timer"); /* reserve pit */
 
+       /* Turn off RTC interrupts before /dev/rtc is initialized */
+       control = CMOS_READ(RTC_CONTROL);
+        control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
+        CMOS_WRITE(control, RTC_CONTROL);
+        CMOS_READ(RTC_INTR_FLAGS);
+
        init_pit_rest();
 }
 #endif
@@ -197,11 +207,25 @@ rtc_init_pit (void)
 void
 generic_init_pit (void)
 {
-       int x;
-       if ((x = (CMOS_READ(RTC_FREQ_SELECT) & 0x3f)) != 0x26) {
+       unsigned char x;
+
+        /* Reset periodic interrupt frequency.  */
+       x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
+       if (x != 0x26 && x != 0x19 && x != 0x06) {
                printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
                CMOS_WRITE(0x26, RTC_FREQ_SELECT);
        }
+
+       /* Turn on periodic interrupts.  */
+       x = CMOS_READ(RTC_CONTROL);
+       if (!(x & RTC_PIE)) {
+               printk("Turning on RTC interrupts.\n");
+               x |= RTC_PIE;
+               x &= ~(RTC_AIE | RTC_UIE);
+               CMOS_WRITE(x, RTC_CONTROL);
+       }
+       CMOS_READ(RTC_INTR_FLAGS);
+
        request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */
 
        /* Turn off the PIT.  */
@@ -223,11 +247,9 @@ generic_init_pit (void)
 void
 time_init(void)
 {
-#ifdef CONFIG_RTC
-       unsigned char save_control;
-#endif
         void (*irq_handler)(int, void *, struct pt_regs *);
        unsigned int year, mon, day, hour, min, sec, cc1, cc2;
+       unsigned long cycle_freq;
 
        /* Initialize the timers.  */
        init_pit();
@@ -246,16 +268,17 @@ time_init(void)
 
        /* If our cycle frequency isn't valid, go another round and give
           a guess at what it should be.  */
-       if (hwrpb->cycle_freq == 0) {
+       cycle_freq = hwrpb->cycle_freq;
+       if (cycle_freq == 0) {
                printk("HWRPB cycle frequency bogus.  Estimating... ");
 
                do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
                do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
                cc2 = rpcc();
-               hwrpb->cycle_freq = cc2 - cc1;
+               est_cycle_freq = cycle_freq = cc2 - cc1;
                cc1 = cc2;
 
-               printk("%lu Hz\n", hwrpb->cycle_freq);
+               printk("%lu Hz\n", cycle_freq);
        }
 
        /* From John Bowman <bowman@math.ualberta.ca>: allow the values
@@ -300,19 +323,9 @@ time_init(void)
 
        state.last_time = cc1;
        state.scaled_ticks_per_cycle
-               = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq;
+               = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq;
        state.last_rtc_update = 0;
 
-#ifdef CONFIG_RTC 
-       /* turn off RTC interrupts before /dev/rtc is initialized */
-       save_control = CMOS_READ(RTC_CONTROL);
-        save_control &= ~RTC_PIE;
-        save_control &= ~RTC_AIE;
-        save_control &= ~RTC_UIE;
-        CMOS_WRITE(save_control, RTC_CONTROL);
-        CMOS_READ(RTC_INTR_FLAGS);
-#endif
-
        /* setup timer */ 
         irq_handler = timer_interrupt;
         if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
index c2fc4c8e692728155c1e6a819e0b488e31ec80a2..e925cf6ffa23cd83233bedf458f7ed43f4df53cd 100644 (file)
@@ -149,8 +149,6 @@ asmlinkage void do_entIF(unsigned long type, unsigned long a1,
                         unsigned long a2, unsigned long a3, unsigned long a4,
                         unsigned long a5, struct pt_regs regs)
 {
-       extern int ptrace_cancel_bpt (struct task_struct *who);
-
        lock_kernel();
        die_if_kernel("Instruction fault", &regs, type, 0);
        switch (type) {
@@ -558,11 +556,12 @@ s_reg_to_mem (unsigned long s_reg)
 
 #define OP_INT_MASK    ( 1L << 0x28 | 1L << 0x2c   /* ldl stl */       \
                        | 1L << 0x29 | 1L << 0x2d   /* ldq stq */       \
-                       | 1L << 0x0c | 1L << 0x0d ) /* ldwu stw */
+                       | 1L << 0x0c | 1L << 0x0d   /* ldwu stw */      \
+                       | 1L << 0x0a | 1L << 0x0e ) /* ldbu stb */
 
 #define OP_WRITE_MASK  ( 1L << 0x26 | 1L << 0x27   /* sts stt */       \
                        | 1L << 0x2c | 1L << 0x2d   /* stl stq */       \
-                       | 1L << 0xd )               /* stw */
+                       | 1L << 0x0d | 1L << 0x0e ) /* stw stb */
 
 #define R(x)   ((size_t) &((struct pt_regs *)0)->x)
 
index 4dd7d591d770a209ad757492aabb46402e42267f..e87f8b903db52c6e9d6fd9b55283083bcdddc976 100644 (file)
@@ -7,7 +7,8 @@ OBJS  = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
        strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
        strchr.o strrchr.o \
        copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
-       csum_ipv6_magic.o strcasecmp.o
+       csum_ipv6_magic.o strcasecmp.o \
+       srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
diff --git a/arch/alpha/lib/srm_dispatch.S b/arch/alpha/lib/srm_dispatch.S
new file mode 100644 (file)
index 0000000..2bcea30
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *     arch/alpha/lib/srm_dispatch.S
+ */
+
+.globl srm_dispatch
+.ent   srm_dispatch
+srm_dispatch:
+       .frame  $30,30,$26
+       subq    $30,80,$30
+       stq     $26,0($30)
+       stq     $8,8($30)
+       stq     $9,16($30)
+       stq     $10,24($30)
+       stq     $11,32($30)
+       stq     $12,40($30)
+       stq     $13,48($30)
+       stq     $14,56($30)
+       stq     $15,64($30)
+       stq     $29,72($30)
+       .mask   0x2400FF00, -80
+       .prologue 0
+
+       ldq     $1,hwrpb
+       ldq     $2,0xc0($1)             /* crb offset */
+       addq    $2,$1,$2                /* crb */
+       ldq     $27,0($2)               /* dispatch procedure value */
+
+       ldq     $2,8($27)               /* dispatch call address */
+       jsr     $26,($2)                /* call it (weird VMS call seq) */
+
+       ldq     $26,0($30)
+       ldq     $8,8($30)
+       ldq     $9,16($30)
+       ldq     $10,24($30)
+       ldq     $11,32($30)
+       ldq     $12,40($30)
+       ldq     $13,48($30)
+       ldq     $14,56($30)
+       ldq     $15,64($30)
+       ldq     $29,72($30)
+       addq    $30,80,$30
+       ret     $31,($26),1
+.end    srm_dispatch
diff --git a/arch/alpha/lib/srm_fixup.S b/arch/alpha/lib/srm_fixup.S
new file mode 100644 (file)
index 0000000..9cf2d78
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *     arch/alpha/lib/srm_fixup.S
+ */
+
+.globl srm_fixup
+.ent   srm_fixup
+srm_fixup:
+       .frame  $30,30,$26
+       subq    $30,80,$30
+       stq     $26,0($30)
+       stq     $8,8($30)
+       stq     $9,16($30)
+       stq     $10,24($30)
+       stq     $11,32($30)
+       stq     $12,40($30)
+       stq     $13,48($30)
+       stq     $14,56($30)
+       stq     $15,64($30)
+       stq     $29,72($30)
+       .mask   0x2400FF00, -80
+       .prologue 0
+
+       ldq     $2,0xc0($17)            /* crb offset */
+       addq    $2,$1,$2                /* crb */
+       ldq     $27,16($2)              /* fixup procedure value */
+
+       ldq     $2,8($27)               /* dispatch call address */
+       jsr     $26,($2)                /* call it (weird VMS call seq) */
+
+       ldq     $26,0($30)
+       ldq     $8,8($30)
+       ldq     $9,16($30)
+       ldq     $10,24($30)
+       ldq     $11,32($30)
+       ldq     $12,40($30)
+       ldq     $13,48($30)
+       ldq     $14,56($30)
+       ldq     $15,64($30)
+       ldq     $29,72($30)
+       addq    $30,80,$30
+       ret     $31,($26),1
+.end    srm_fixup
diff --git a/arch/alpha/lib/srm_printk.c b/arch/alpha/lib/srm_printk.c
new file mode 100644 (file)
index 0000000..b5baee1
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ *     arch/alpha/lib/srm_printk.c
+ */
+
+#include <linux/kernel.h>
+#include <asm/console.h>
+
+long
+srm_printk(const char *fmt, ...)
+{
+       static char buf[1024];
+        va_list args;
+        long i;
+
+        va_start(args, fmt);
+        i = vsprintf(buf,fmt,args);
+        va_end(args);
+
+       srm_puts(buf);  
+        return i;
+}
diff --git a/arch/alpha/lib/srm_puts.c b/arch/alpha/lib/srm_puts.c
new file mode 100644 (file)
index 0000000..87b1d11
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *     arch/alpha/lib/srm_puts.c
+ */
+
+#include <linux/string.h>
+#include <asm/console.h>
+
+void
+srm_puts(const char *str)
+{
+       /* Expand \n to \r\n as we go.  */
+
+       while (*str) {
+               long len;
+               const char *e = str;
+
+               if (*str == '\n') {
+                       if (srm_dispatch(CCB_PUTS, 0, "\r", 1) < 0)
+                               return;
+                       ++e;
+               }
+
+               e = strchr(e, '\n') ? : strchr(e, '\0');
+               len = e - str;
+
+               while (len > 0) {
+                       long written = srm_dispatch(CCB_PUTS, 0, str, len);
+                       if (written < 0)
+                               return;
+                       len -= written & 0xffffffff;
+                       str += written & 0xffffffff;
+               }
+       }
+}
index 4d85adb365acb3b89a62ff2a30dc3859d3e57e7f..2e67deb8aa8597bf3890a7c0f71156791574173d 100644 (file)
@@ -30,7 +30,7 @@
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
-struct thread_struct * original_pcb_ptr;
+struct thread_struct original_pcb;
 
 #ifndef __SMP__
 struct pgtable_cache_struct quicklists;
@@ -193,47 +193,66 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
        unsigned long newptbr;
        struct memclust_struct * cluster;
        struct memdesc_struct * memdesc;
+       struct thread_struct *original_pcb_ptr;
 
        /* initialize mem_map[] */
        start_mem = free_area_init(start_mem, end_mem);
 
        /* find free clusters, update mem_map[] accordingly */
        memdesc = (struct memdesc_struct *)
-               (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+               (hwrpb->mddt_offset + (unsigned long) hwrpb);
        cluster = memdesc->cluster;
        for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
                unsigned long pfn, nr;
-               if (cluster->usage & 1)
+
+               /* Bit 0 is console/PALcode reserved.  Bit 1 is
+                  non-volatile memory -- we might want to mark
+                  this for later */
+               if (cluster->usage & 3)
                        continue;
                pfn = cluster->start_pfn;
                nr = cluster->numpages;
 
-               /* non-volatile memory. We might want to mark this for later */
-               if (cluster->usage & 2)
-                       continue;
-
                while (nr--)
                        clear_bit(PG_reserved, &mem_map[pfn++].flags);
        }
 
-       /* unmap the console stuff: we don't need it, and we don't want it */
-       /* Also set up the real kernel PCB while we're at it.. */
+       /* Initialize the kernel's page tables.  Linux puts the vptb in
+          the last slot of the L1 page table.  */
        memset((void *) ZERO_PAGE, 0, PAGE_SIZE);
        memset(swapper_pg_dir, 0, PAGE_SIZE);
        newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
        pgd_val(swapper_pg_dir[1023]) =
                (newptbr << 32) | pgprot_val(PAGE_KERNEL);
+
+       /* Set the vptb.  This is often done by the bootloader, but 
+          shouldn't be required.  */
+       if (hwrpb->vptb != 0xfffffffe00000000) {
+               wrvptptr(0xfffffffe00000000);
+               hwrpb->vptb = 0xfffffffe00000000;
+               hwrpb_update_checksum(hwrpb);
+       }
+
+       /* Also set up the real kernel PCB while we're at it.  */
        init_task.tss.ptbr = newptbr;
        init_task.tss.pal_flags = 1;    /* set FEN, clear everything else */
        init_task.tss.flags = 0;
-       original_pcb_ptr =
-         phys_to_virt((unsigned long)load_PCB(&init_task.tss));
-#if 0
-printk("OKSP 0x%lx OPTBR 0x%lx\n",
-       original_pcb_ptr->ksp, original_pcb_ptr->ptbr);
-#endif
-
+       original_pcb_ptr = load_PCB(&init_task.tss);
        tbia();
+
+       /* Save off the contents of the original PCB so that we can
+          restore the original console's page tables for a clean reboot.
+
+          Note that the PCB is supposed to be a physical address, but
+          since KSEG values also happen to work, folks get confused.
+          Check this here.  */
+
+       if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) {
+               original_pcb_ptr = (struct thread_struct *)
+                 phys_to_virt((unsigned long) original_pcb_ptr);
+       }
+       original_pcb = *original_pcb_ptr;
+
        return start_mem;
 }
 
@@ -250,12 +269,6 @@ paging_init_secondary(void)
        current->tss.ptbr = init_task.tss.ptbr;
        current->tss.pal_flags = 1;
        current->tss.flags = 0;
-
-#if 0
-printk("paging_init_secondary: KSP 0x%lx PTBR 0x%lx\n",
-       current->tss.ksp, current->tss.ptbr);
-#endif
-
        load_PCB(&current->tss);
        tbia();
 
@@ -263,6 +276,23 @@ printk("paging_init_secondary: KSP 0x%lx PTBR 0x%lx\n",
 }
 #endif /* __SMP__ */
 
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
+void
+srm_paging_stop (void)
+{
+       /* Move the vptb back to where the SRM console expects it.  */
+       swapper_pg_dir[1] = swapper_pg_dir[1023];
+       tbia();
+       wrvptptr(0x200000000);
+       hwrpb->vptb = 0x200000000;
+       hwrpb_update_checksum(hwrpb);
+
+       /* Reload the page tables that the console had in use.  */
+       load_PCB(&original_pcb);
+       tbia();
+}
+#endif
+
 #if DEBUG_POISON
 static void
 kill_page(unsigned long pg)
index 7f156dd96eabe2df340f20e4c2a9e73fba1d6427..655d6f846eb331d7faf6a3a84351cc5da6421a76 100644 (file)
@@ -346,7 +346,7 @@ static struct pci_access pci_direct_conf2 = {
  * attempt to make use of direct access hints provided by the PCI BIOS).
  *
  * This should be close to trivial, but it isn't, because there are buggy
- * chipsets (yes, you guessed it, by Intel) that have no class ID.
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
  */
 __initfunc(int pci_sanity_check(struct pci_access *a))
 {
@@ -356,9 +356,9 @@ __initfunc(int pci_sanity_check(struct pci_access *a))
                return 1;
        for(dfn=0; dfn < 0x100; dfn++)
                if ((!a->read_config_word(0, dfn, PCI_CLASS_DEVICE, &x) &&
-                    x == PCI_CLASS_BRIDGE_HOST) ||
+                    (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
                    (!a->read_config_word(0, dfn, PCI_VENDOR_ID, &x) &&
-                    x == PCI_VENDOR_ID_INTEL))
+                    (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ)))
                        return 1;
        DBG("PCI: Sanity check failed\n");
        return 0;
index 4e29f8d859883fcf192096eb8d6be8c5bf1f028c..79347f7c504ae9ba67603b0da66f92b4cbcb17d6 100644 (file)
@@ -431,9 +431,9 @@ static struct cpu_model_info cpu_models[] __initdata = {
            "486 SX/2", NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, 
            NULL, NULL, NULL, NULL, NULL }},
        { X86_VENDOR_INTEL,     5,
-         { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75+",
+         { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75 - 200",
            "OverDrive PODP5V83", "Pentium MMX", NULL, NULL,
-           "Mobile Pentium 75+", "Mobile Pentium MMX", NULL, NULL, NULL,
+           "Mobile Pentium 75 - 200", "Mobile Pentium MMX", NULL, NULL, NULL,
            NULL, NULL, NULL, NULL }},
        { X86_VENDOR_INTEL,     6,
          { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", 
index df9a1f6ed5b2758abf8a41c0c4cbc939af258da2..eba6929dc4644ab439c0c5866cb0d12e653d85a8 100644 (file)
  *      precision CMOS clock update
  * 1996-05-03    Ingo Molnar
  *      fixed time warps in do_[slow|fast]_gettimeoffset()
+ * 1998-09-05    (Various)
+ *     More robust do_fast_gettimeoffset() algorithm implemented
+ *     (works with APM, Cyrix 6x86MX and Centaur C6),
+ *     monotonic gettimeofday() with fast_get_timeoffset(),
+ *     drift-proof precision TSC calibration on boot
+ *     (C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D.
+ *     Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>;
+ *     ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>).
  */
+
+/* What about the "updated NTP code" stuff in 2.0 time.c? It's not in
+ * 2.1, perhaps it should be ported, too.
+ *
+ * What about the BUGGY_NEPTUN_TIMER stuff in do_slow_gettimeoffset()?
+ * Whatever it fixes, is it also fixed in the new code from the Jumbo
+ * patch, so that that code can be used instead?
+ *
+ * The CPU Hz should probably be displayed in check_bugs() together
+ * with the CPU vendor and type. Perhaps even only in MHz, though that
+ * takes away some of the fun of the new code :)
+ *
+ * - Michael Krause */
+
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include "irq.h"
 
 extern int setup_x86_irq(int, struct irqaction *);
-extern volatile unsigned long lost_ticks;
 
-/* change this if you have some constant time drift */
-#define USECS_PER_JIFFY (1000020/HZ)
+unsigned long cpu_hz;  /* Detected as we calibrate the TSC */
+
+/* Number of usecs that the last interrupt was delayed */
+static int delay_at_last_interrupt;
+
+static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
 
-#ifndef        CONFIG_APM      /* cycle counter may be unreliable */
-/* Cycle counter value at the previous timer interrupt.. */
-static struct {
-       unsigned long low;
-       unsigned long high;
-} init_timer_cc, last_timer_cc;
+/* Cached *multiplier* to convert TSC counts to microseconds.
+ * (see the equation below).
+ * Equal to 2^32 * (1 / (clocks per usec) ).
+ * Initialized in time_init.
+ */
+static unsigned long fast_gettimeoffset_quotient=0;
 
 static unsigned long do_fast_gettimeoffset(void)
 {
        register unsigned long eax asm("ax");
        register unsigned long edx asm("dx");
-       unsigned long tmp, quotient, low_timer;
-
-       /* Last jiffy when do_fast_gettimeoffset() was called. */
-       static unsigned long last_jiffies=0;
-
-       /*
-        * Cached "1/(clocks per usec)*2^32" value. 
-        * It has to be recalculated once each jiffy.
-        */
-       static unsigned long cached_quotient=0;
-
-       tmp = jiffies;
-
-       quotient = cached_quotient;
-       low_timer = last_timer_cc.low;
-
-       if (last_jiffies != tmp) {
-               last_jiffies = tmp;
-
-               /* Get last timer tick in absolute kernel time */
-               eax = low_timer;
-               edx = last_timer_cc.high;
-               __asm__("subl "SYMBOL_NAME_STR(init_timer_cc)",%0\n\t"
-                       "sbbl "SYMBOL_NAME_STR(init_timer_cc)"+4,%1"
-                       :"=a" (eax), "=d" (edx)
-                       :"0" (eax), "1" (edx));
-
-               /*
-                * Divide the 64-bit time with the 32-bit jiffy counter,
-                * getting the quotient in clocks.
-                *
-                * Giving quotient = "1/(average internal clocks per usec)*2^32"
-                * we do this '1/...' trick to get the 'mull' into the critical 
-                * path. 'mull' is much faster than divl (10 vs. 41 clocks)
-                */
-               __asm__("divl %2"
-                       :"=a" (eax), "=d" (edx)
-                       :"r" (tmp),
-                        "0" (eax), "1" (edx));
-
-               edx = USECS_PER_JIFFY;
-               tmp = eax;
-               eax = 0;
-
-               __asm__("divl %2"
-                       :"=a" (eax), "=d" (edx)
-                       :"r" (tmp),
-                        "0" (eax), "1" (edx));
-               cached_quotient = eax;
-               quotient = eax;
-       }
 
-       /* Read the time counter */
-       __asm__("rdtsc" : "=a" (eax), "=d" (edx));
+       /* Read the Time Stamp Counter */
+       __asm__("rdtsc"
+               :"=a" (eax), "=d" (edx));
 
        /* .. relative to previous jiffy (32 bits is enough) */
        edx = 0;
-       eax -= low_timer;
+       eax -= last_tsc_low;    /* tsc_low delta */
 
        /*
-        * Time offset = (USECS_PER_JIFFY * time_low) * quotient.
-        */
+         * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient.
+         *             = (tsc_low delta) / (clocks_per_usec)
+         *             = (tsc_low delta) / (clocks_per_jiffy / usecs_per_jiffy)
+        *
+        * Using a mull instead of a divl saves up to 31 clock cycles
+        * in the critical path.
+         */
 
        __asm__("mull %2"
                :"=a" (eax), "=d" (edx)
-               :"r" (quotient),
+               :"r" (fast_gettimeoffset_quotient),
                 "0" (eax), "1" (edx));
 
-       /*
-        * Due to possible jiffies inconsistencies, we need to check 
-        * the result so that we'll get a timer that is monotonic.
-        */
-       if (edx >= USECS_PER_JIFFY)
-               edx = USECS_PER_JIFFY-1;
-
-       return edx;
+       /* our adjusted time offset in microseconds */
+       return edx + delay_at_last_interrupt;
 }
-#endif
 
 /* This function must be called with interrupts disabled 
  * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
@@ -249,20 +222,11 @@ static unsigned long do_slow_gettimeoffset(void)
        return count;
 }
 
-#ifndef CONFIG_APM
-/*
- * this is only used if we have fast gettimeoffset:
- */
-static void do_x86_get_fast_time(struct timeval * tv)
-{
-       do_gettimeofday(tv);
-}
-#endif
-
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
 /*
- * This version of gettimeofday has near microsecond resolution.
+ * This version of gettimeofday has microsecond resolution
+ * and better than microsecond precision on fast x86 machines with TSC.
  */
 void do_gettimeofday(struct timeval *tv)
 {
@@ -272,20 +236,11 @@ void do_gettimeofday(struct timeval *tv)
        cli();
        *tv = xtime;
        tv->tv_usec += do_gettimeoffset();
-
-       /*
-        * xtime is atomically updated in timer_bh. lost_ticks is
-        * nonzero if the timer bottom half hasnt executed yet.
-        */
-       if (lost_ticks)
-               tv->tv_usec += USECS_PER_JIFFY;
-
-       restore_flags(flags);
-
        if (tv->tv_usec >= 1000000) {
                tv->tv_usec -= 1000000;
                tv->tv_sec++;
        }
+       restore_flags(flags);
 }
 
 void do_settimeofday(struct timeval *tv)
@@ -311,13 +266,15 @@ void do_settimeofday(struct timeval *tv)
        sti();
 }
 
-
 /*
  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
  * called 500 ms after the second nowtime has started, because when
  * nowtime is written into the registers of the CMOS clock, it will
  * jump to the next second precisely 500 ms later. Check the Motorola
  * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
  */
 static int set_rtc_mmss(unsigned long nowtime)
 {
@@ -354,8 +311,12 @@ static int set_rtc_mmss(unsigned long nowtime)
                }
                CMOS_WRITE(real_seconds,RTC_SECONDS);
                CMOS_WRITE(real_minutes,RTC_MINUTES);
-       } else
+       } else {
+               printk(KERN_WARNING
+                      "set_rtc_mmss: can't update from %d to %d\n",
+                      cmos_minutes, real_minutes);
                retval = -1;
+       }
 
        /* The following flags have to be released exactly in this order,
         * otherwise the DS12887 (popular MC146818A clone with integrated
@@ -431,21 +392,37 @@ static inline void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #endif
 }
 
-#ifndef        CONFIG_APM      /* cycle counter may be unreliable */
 /*
  * This is the same as the above, except we _also_ save the current
- * cycle counter value at the time of the timer interrupt, so that
+ * Time Stamp Counter value at the time of the timer interrupt, so that
  * we later on can estimate the time of day more exactly.
  */
 static void pentium_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+       int count, flags;
+
+       /* It is important that these two operations happen almost at the
+        * same time. We do the RDTSC stuff first, since it's faster. To
+         * avoid any inconsistencies, we disable interrupts locally.
+         */
+       
+       __save_flags(flags);
+       __cli(); 
        /* read Pentium cycle counter */
        __asm__("rdtsc"
-               :"=a" (last_timer_cc.low),
-                "=d" (last_timer_cc.high));
+               :"=a" (last_tsc_low):: "eax", "edx");
+
+       outb_p(0x00, 0x43);     /* latch the count ASAP */
+
+       count = inb_p(0x40);    /* read the latched count */
+       count |= inb(0x40) << 8;
+
+       count = ((LATCH-1) - count) * TICK_SIZE;
+       delay_at_last_interrupt = (count + LATCH/2) / LATCH;
+       __restore_flags(flags);
+       
        timer_interrupt(irq, NULL, regs);
 }
-#endif
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
@@ -520,6 +497,80 @@ unsigned long get_cmos_time(void)
 
 static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
 
+/* ------ Calibrate the TSC ------- 
+ * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
+ * Too much 64-bit arithmetic here to do this cleanly in C, and for
+ * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
+ * output busy loop as low as possible. We avoid reading the CTC registers
+ * directly because of the awkward 8-bit access mechanism of the 82C54
+ * device.
+ */
+
+__initfunc(static unsigned long calibrate_tsc(void))
+{
+       unsigned long retval;
+
+       __asm__( /* set the Gate high, program CTC channel 2 for mode 0
+                * (interrupt on terminal count mode), binary count, 
+                * load 5 * LATCH count, (LSB and MSB)
+                * to begin countdown, read the TSC and busy wait.
+                * BTW LATCH is calculated in timex.h from the HZ value
+                */
+
+              /* Set the Gate high, disable speaker */
+              "inb  $0x61, %%al\n\t" /* Read port */
+              "andb $0xfd, %%al\n\t" /* Turn off speaker Data */
+              "orb  $0x01, %%al\n\t" /* Set Gate high */
+              "outb %%al, $0x61\n\t" /* Write port */
+
+              /* Now let's take care of CTC channel 2 */
+              "movb $0xb0, %%al\n\t" /* binary, mode 0, LSB/MSB, ch 2*/
+              "outb %%al, $0x43\n\t" /* Write to CTC command port */
+              "movb $0x0c, %%al\n\t"
+              "outb %%al, $0x42\n\t" /* LSB of count */
+              "movb $0xe9, %%al\n\t"
+              "outb %%al, $0x42\n\t" /* MSB of count */
+
+               /* Read the TSC; counting has just started */
+               "rdtsc\n\t"
+               /* Move the value for safe-keeping. */
+               "movl %%eax, %%ebx\n\t"
+               "movl %%edx, %%ecx\n\t"
+
+              /* Busy wait. Only 50 ms wasted at boot time. */
+               "0: inb $0x61, %%al\n\t" /* Read Speaker Output Port */
+              "testb $0x20, %%al\n\t" /* Check CTC channel 2 output (bit 5) */
+               "jz 0b\n\t"
+
+               /* And read the TSC.  5 jiffies (50.00077ms) have elapsed. */
+               "rdtsc\n\t"
+
+               /* Great.  So far so good.  Store last TSC reading in
+                * last_tsc_low (only 32 lsb bits needed) */
+               "movl %%eax, last_tsc_low\n\t"
+               /* And now calculate the difference between the readings. */
+               "subl %%ebx, %%eax\n\t"
+               "sbbl %%ecx, %%edx\n\t" /* 64-bit subtract */
+              /* but probably edx = 0 at this point (see below). */
+               /* Now we have 5 * (TSC counts per jiffy) in eax.  We want
+                * to calculate TSC->microsecond conversion factor. */
+
+               /* Note that edx (high 32-bits of difference) will now be 
+                * zero iff CPU clock speed is less than 85 GHz.  Moore's
+                * law says that this is likely to be true for the next
+                * 12 years or so.  You will have to change this code to
+                * do a real 64-by-64 divide before that time's up. */
+               "movl %%eax, %%ecx\n\t"
+               "xorl %%eax, %%eax\n\t"
+               "movl %1, %%edx\n\t"
+               "divl %%ecx\n\t" /* eax= 2^32 / (1 * TSC counts per microsecond) */
+              /* Return eax for the use of fast_gettimeoffset */
+               "movl %%eax, %0\n\t"
+               : "=r" (retval)
+               : "r" (5 * 1000020/HZ)
+               : /* we clobber: */ "ax", "bx", "cx", "dx", "cc", "memory");
+       return retval;
+}
 
 __initfunc(void time_init(void))
 {
@@ -527,36 +578,36 @@ __initfunc(void time_init(void))
        xtime.tv_usec = 0;
 
 /*
- * If we have APM enabled we can't currently depend
- * on the cycle counter, because a suspend to disk
- * will reset it. Somebody should come up with a
- * better solution than to just disable the fast time
- * code..
+ * If we have APM enabled or the CPU clock speed is variable
+ * (CPU stops clock on HLT or slows clock to save power)
+ * then the TSC timestamps may diverge by up to 1 jiffy from
+ * 'real time' but nothing will break.
+ * The most frequent case is that the CPU is "woken" from a halt
+ * state by the timer interrupt itself, so we get 0 error. In the
+ * rare cases where a driver would "wake" the CPU and request a
+ * timestamp, the maximum error is < 1 jiffy. But timestamps are
+ * still perfectly ordered.
+ * Note that the TSC counter will be reset if APM suspends
+ * to disk; this won't break the kernel, though, 'cuz we're
+ * smart.  See devices/char/apm_bios.c.
  */
-#ifndef CONFIG_APM
-       /* If we have the CPU hardware time counters, use them */
-       if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) { 
+       if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
                do_gettimeoffset = do_fast_gettimeoffset;
-               do_get_fast_time = do_x86_get_fast_time;
-
-               if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-                   boot_cpu_data.x86 == 5 &&
-                   boot_cpu_data.x86_model == 0) {
-                       /* turn on cycle counters during power down */
-                       __asm__ __volatile__ (" movl $0x83, %%ecx \n \
-                               rdmsr \n \
-                               orl $1,%%eax \n \
-                               wrmsr \n " 
-                                      : : : "ax", "cx", "dx" );
-                               udelay(500);
-               }
-
-               /* read Pentium cycle counter */
-               __asm__("rdtsc"
-                       :"=a" (init_timer_cc.low),
-                        "=d" (init_timer_cc.high));
+               do_get_fast_time = do_gettimeofday;
                irq0.handler = pentium_timer_interrupt;
+               fast_gettimeoffset_quotient = calibrate_tsc();
+               
+               /* report CPU clock rate in Hz.
+                * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
+                * clock/second. Our precision is about 100 ppm.
+                */
+               {       unsigned long eax=0, edx=1000000;
+                       __asm__("divl %2"
+                       :"=a" (cpu_hz), "=d" (edx)
+                               :"r" (fast_gettimeoffset_quotient),
+                       "0" (eax), "1" (edx));
+                       printk("Detected %ld Hz processor.\n", cpu_hz);
+               }
        }
-#endif
        setup_x86_irq(0, &irq0);
 }
index aa4be82b5fd66af32320d7787a4428afd3772844..a171fd332e54ea3ab2a896c2348910759f899148 100644 (file)
@@ -145,6 +145,12 @@ pmac_get_cpuinfo(char *buffer)
 #include "../../../drivers/scsi/sd.h"
 #include "../../../drivers/scsi/hosts.h"
 
+#define SD_MAJOR(i)            (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+#define SD_MAJOR_NUMBER(i)     SD_MAJOR((i) >> 8)
+#define SD_MINOR_NUMBER(i)     ((i) & 255)
+#define MKDEV_SD_PARTITION(i)  MKDEV(SD_MAJOR_NUMBER(i), SD_MINOR_NUMBER(i))
+#define MKDEV_SD(index)                MKDEV_SD_PARTITION((index) << 4)
+
 kdev_t sd_find_target(void *host, int tgt)
 {
     Scsi_Disk *dp;
@@ -153,7 +159,7 @@ kdev_t sd_find_target(void *host, int tgt)
     for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
         if (dp->device != NULL && dp->device->host == host
             && dp->device->id == tgt)
-            return MKDEV(SCSI_DISK_MAJOR, i << 4);
+            return MKDEV_SD(i);
     return 0;
 }
 #endif
diff --git a/arch/ppc/kernel/pmac_setup.c.orig b/arch/ppc/kernel/pmac_setup.c.orig
new file mode 100644 (file)
index 0000000..aa4be82
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Adapted for Power Macintosh by Paul Mackerras
+ *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ *  Derived from "arch/alpha/kernel/setup.c"
+ *    Copyright (C) 1995 Linus Torvalds
+ *
+ *  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.
+ *
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/vt_kern.h>
+#include <linux/console.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/adb.h>
+#include <asm/cuda.h>
+#include <asm/pmu.h>
+#include <asm/mediabay.h>
+#include <asm/ohare.h>
+#include <asm/mediabay.h>
+#include "time.h"
+
+unsigned char drive_info;
+
+extern char saved_command_line[];
+
+#define DEFAULT_ROOT_DEVICE 0x0801     /* sda1 - slightly silly choice */
+
+extern void zs_kgdb_hook(int tty_num);
+static void ohare_init(void);
+
+__pmac
+
+int
+pmac_get_cpuinfo(char *buffer)
+{
+       int len;
+       struct device_node *np;
+       char *pp;
+       int plen;
+
+       /* find motherboard type */
+       len = sprintf(buffer, "machine\t\t: ");
+       np = find_devices("device-tree");
+       if (np != NULL) {
+               pp = (char *) get_property(np, "model", NULL);
+               if (pp != NULL)
+                       len += sprintf(buffer+len, "%s\n", pp);
+               else
+                       len += sprintf(buffer+len, "PowerMac\n");
+               pp = (char *) get_property(np, "compatible", &plen);
+               if (pp != NULL) {
+                       len += sprintf(buffer+len, "motherboard\t:");
+                       while (plen > 0) {
+                               int l = strlen(pp) + 1;
+                               len += sprintf(buffer+len, " %s", pp);
+                               plen -= l;
+                               pp += l;
+                       }
+                       buffer[len++] = '\n';
+               }
+       } else
+               len += sprintf(buffer+len, "PowerMac\n");
+
+       /* find l2 cache info */
+       np = find_devices("l2-cache");
+       if (np == 0)
+               np = find_type_devices("cache");
+       if (np != 0) {
+               unsigned int *ic = (unsigned int *)
+                       get_property(np, "i-cache-size", NULL);
+               unsigned int *dc = (unsigned int *)
+                       get_property(np, "d-cache-size", NULL);
+               len += sprintf(buffer+len, "L2 cache\t:");
+               if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+                       len += sprintf(buffer+len, " %dK unified", *dc / 1024);
+               } else {
+                       if (ic)
+                               len += sprintf(buffer+len, " %dK instruction",
+                                              *ic / 1024);
+                       if (dc)
+                               len += sprintf(buffer+len, "%s %dK data",
+                                              (ic? " +": ""), *dc / 1024);
+               }
+               pp = get_property(np, "ram-type", NULL);
+               if (pp)
+                       len += sprintf(buffer+len, " %s", pp);
+               buffer[len++] = '\n';
+       }
+
+       /* find ram info */
+       np = find_devices("memory");
+       if (np != 0) {
+               struct reg_property *reg = (struct reg_property *)
+                       get_property(np, "reg", NULL);
+               if (reg != 0) {
+                       len += sprintf(buffer+len, "memory\t\t: %dMB\n",
+                                      reg->size >> 20);
+               }
+       }
+
+       return len;
+}
+
+#ifdef CONFIG_SCSI
+/* Find the device number for the disk (if any) at target tgt
+   on host adaptor host.
+   XXX this really really should be in drivers/scsi/sd.c. */
+#include <linux/blkdev.h>
+#include "../../../drivers/scsi/scsi.h"
+#include "../../../drivers/scsi/sd.h"
+#include "../../../drivers/scsi/hosts.h"
+
+kdev_t sd_find_target(void *host, int tgt)
+{
+    Scsi_Disk *dp;
+    int i;
+
+    for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
+        if (dp->device != NULL && dp->device->host == host
+            && dp->device->id == tgt)
+            return MKDEV(SCSI_DISK_MAJOR, i << 4);
+    return 0;
+}
+#endif
+
+/*
+ * Dummy mksound function that does nothing.
+ * The real one is in the dmasound driver.
+ */
+static void
+pmac_mksound(unsigned int hz, unsigned int ticks)
+{
+}
+
+static volatile u32 *sysctrl_regs;
+static volatile u32 *feature_addr;
+
+__initfunc(void
+pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
+{
+       struct device_node *cpu;
+       int *fp;
+
+       /* Set loops_per_sec to a half-way reasonable value,
+          for use until calibrate_delay gets called. */
+       cpu = find_type_devices("cpu");
+       if (cpu != 0) {
+               fp = (int *) get_property(cpu, "clock-frequency", NULL);
+               if (fp != 0) {
+                       switch (_get_PVR() >> 16) {
+                       case 4:         /* 604 */
+                       case 9:         /* 604e */
+                       case 10:        /* mach V (604ev5) */
+                       case 20:        /* 620 */
+                               loops_per_sec = *fp;
+                               break;
+                       default:        /* 601, 603, etc. */
+                               loops_per_sec = *fp / 2;
+                       }
+               } else
+                       loops_per_sec = 50000000;
+       }
+
+       /* this area has the CPU identification register
+          and some registers used by smp boards */
+       sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
+       __ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY));
+
+       *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+
+       ohare_init();
+
+#ifdef CONFIG_KGDB
+       zs_kgdb_hook(0);
+#endif
+
+       find_via_cuda();
+       find_via_pmu();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+       conswitchp = &dummy_con;
+#endif
+
+       kd_mksound = pmac_mksound;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start)
+               ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+       else
+#endif
+               ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
+}
+
+__initfunc(static void ohare_init(void))
+{
+       struct device_node *np;
+
+       np = find_devices("ohare");
+       if (np == 0)
+               return;
+       if (np->next != 0)
+               printk(KERN_WARNING "only using the first ohare\n");
+       if (np->n_addrs == 0) {
+               printk(KERN_ERR "No addresses for %s\n", np->full_name);
+               return;
+       }
+       feature_addr = (volatile u32 *)
+               ioremap(np->addrs[0].address + OHARE_FEATURE_REG, 4);
+
+       if (find_devices("via-pmu") == 0) {
+               printk(KERN_INFO "Twiddling the magic ohare bits\n");
+               out_le32(feature_addr, STARMAX_FEATURES);
+       } else {
+               out_le32(feature_addr, in_le32(feature_addr) | PBOOK_FEATURES);
+               printk(KERN_DEBUG "feature reg = %x\n", in_le32(feature_addr));
+       }
+
+       /*
+        * Turn on the L2 cache.
+        * We assume that we have a PSX memory controller iff
+        * we have an ohare I/O controller.
+        */
+       if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
+               if (sysctrl_regs[4] & 0x10)
+                       sysctrl_regs[4] |= 0x04000020;
+               else
+                       sysctrl_regs[4] |= 0x04000000;
+               printk(KERN_INFO "Level 2 cache enabled\n");
+       }
+}
+
+extern char *bootpath;
+extern char *bootdevice;
+void *boot_host;
+int boot_target;
+int boot_part;
+kdev_t boot_dev;
+
+__initfunc(void powermac_init(void))
+{
+       adb_init();
+       pmac_nvram_init();
+       if (_machine == _MACH_Pmac) {
+               media_bay_init();
+       }
+}
+
+#ifdef CONFIG_SCSI
+__initfunc(void
+note_scsi_host(struct device_node *node, void *host))
+{
+       int l;
+       char *p;
+
+       l = strlen(node->full_name);
+       if (bootpath != NULL && bootdevice != NULL
+           && strncmp(node->full_name, bootdevice, l) == 0
+           && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
+               boot_host = host;
+               /*
+                * There's a bug in OF 1.0.5.  (Why am I not surprised.)
+                * If you pass a path like scsi/sd@1:0 to canon, it returns
+                * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
+                * That is, the scsi target number doesn't get preserved.
+                * So we pick the target number out of bootpath and use that.
+                */
+               p = strstr(bootpath, "/sd@");
+               if (p != NULL) {
+                       p += 4;
+                       boot_target = simple_strtoul(p, NULL, 10);
+                       p = strchr(p, ':');
+                       if (p != NULL)
+                               boot_part = simple_strtoul(p + 1, NULL, 10);
+               }
+       }
+}
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+extern int pmac_ide_count;
+extern struct device_node *pmac_ide_node[];
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+__initfunc(kdev_t find_ide_boot(void))
+{
+       char *p;
+       int i, n;
+
+       if (bootdevice == NULL)
+               return 0;
+       p = strrchr(bootdevice, '/');
+       if (p == NULL)
+               return 0;
+       n = p - bootdevice;
+
+       /*
+        * Look through the list of IDE interfaces for this one.
+        */
+       for (i = 0; i < pmac_ide_count; ++i) {
+               char *name = pmac_ide_node[i]->full_name;
+               if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+                       /* XXX should cope with the 2nd drive as well... */
+                       return MKDEV(ide_majors[i], 0);
+               }
+       }
+
+       return 0;
+}
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+
+__initfunc(void find_boot_device(void))
+{
+#ifdef CONFIG_SCSI
+       if (boot_host != NULL) {
+               boot_dev = sd_find_target(boot_host, boot_target);
+               if (boot_dev != 0)
+                       return;
+       }
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+       boot_dev = find_ide_boot();
+#endif
+}
+
+__initfunc(void note_bootable_part(kdev_t dev, int part))
+{
+       static int found_boot = 0;
+       char *p;
+
+       /* Do nothing if the root has been set already. */
+       if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
+               return;
+       p = strstr(saved_command_line, "root=");
+       if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+               return;
+
+       if (!found_boot) {
+               find_boot_device();
+               found_boot = 1;
+       }
+       if (dev == boot_dev) {
+               ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + part);
+               boot_dev = NODEV;
+               printk(" (root)");
+       }
+}
+
index c63837287d77061b0cca9b6898d8ce981858fd11..65a9fdd19b9c03fd5c98535694a882a1c4cfc706 100644 (file)
@@ -43,6 +43,7 @@ else
             bool '     Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
             bool '     NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
             bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+            bool '     CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
           fi
         fi
       fi
index b750c89cf2bccb9c728e9325a231c8d2cbff959d..3e3e8f34624d9d6ef96c156ad13af7bf616a5aa9 100644 (file)
@@ -102,12 +102,12 @@ isn't, use the old method using environment variables.
        Tells the floppy driver that a workable DMA channel is available
        (the default).
 
-floppy=nofifo
+ floppy=nofifo
        Disables the FIFO entirely. This is needed if you get "Bus
        master arbitration error" messages from your Ethernet card (or
        from other devices) while accessing the floppy.
 
-floppy=fifo
+ floppy=fifo
        Enables the FIFO (default)
 
  floppy=<threshold>,fifo_depth
@@ -189,6 +189,13 @@ floppy=fifo
  floppy=<nr>,dma
        Sets the floppy DMA channel to <nr> instead of 2
 
+ floppy=slow
+       Use PS/2 stepping rate:
+        " PS/2 floppies have much slower step rates than regular floppies.
+          It's been recommended that take about 1/4 of the default speed
+          in some more extreme cases."
+        
+
 
 Supporting utilities and additional documentation:
 ==================================================
index f49f186a8a849e4b2bef716c00183fba27552f9c..35ad3b561ee08cc0920c6ed2ef6529998b9e5b60 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  *
- * Some parts are based on hd.c by Linus Thorvalds
+ * Some parts are based on hd.c by Linus Torvalds
  *
  * 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
index 7279d4a6ead656c84eb0b0c3e6115f8074447c7c..cf47e47909a50af3ade8439ecee77159139e7461 100644 (file)
@@ -153,6 +153,11 @@ static int irqdma_allocated = 0;
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
+/*
+ * PS/2 floppies have much slower step rates than regular floppies.
+ * It's been recommended that take about 1/4 of the default speed
+ * in some more extreme cases.
+ */
 static int slow_floppy = 0;
 
 #include <asm/dma.h>
@@ -354,7 +359,7 @@ static struct {
       0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
 
 {{2,  500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6,  83, 3*HZ, 17, {3,1,2,0,2}, 0,
-      0, { 2, 5, 6,23,10,20,11, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
+      0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
 
 {{3,  250, 16, 16, 3000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,
       0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
@@ -1051,6 +1056,7 @@ static void floppy_enable_hlt(void)
 static void setup_DMA(void)
 {
        unsigned long flags;
+       unsigned long f;
 
 #ifdef FLOPPY_SANITY_CHECK
        if (raw_cmd->length == 0){
@@ -1072,17 +1078,20 @@ static void setup_DMA(void)
        }
 #endif
        INT_OFF;
+       f=claim_dma_lock();
        fd_disable_dma();
 #ifdef fd_dma_setup
        if(fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, 
                        (raw_cmd->flags & FD_RAW_READ)?
                        DMA_MODE_READ : DMA_MODE_WRITE,
                        FDCS->address) < 0) {
+               release_dma_lock(f);
                INT_ON;
                cont->done(0);
                FDCS->reset=1;
                return;
        }
+       release_dma_lock(f);
 #else  
        fd_clear_dma_ff();
        fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
@@ -1092,6 +1101,7 @@ static void setup_DMA(void)
        fd_set_dma_count(raw_cmd->length);
        virtual_dma_port = FDCS->address;
        fd_enable_dma();
+       release_dma_lock(f);
 #endif
        INT_ON;
        floppy_disable_hlt();
@@ -1694,11 +1704,15 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        void (*handler)(void) = DEVICE_INTR;
        int do_print;
+       unsigned long f;
 
        lasthandler = handler;
        interruptjiffies = jiffies;
 
+       f=claim_dma_lock();
        fd_disable_dma();
+       release_dma_lock(f);
+       
        floppy_enable_hlt();
        CLEAR_INTR;
        if (fdc >= N_FDC || FDCS->address == -1){
@@ -1779,13 +1793,18 @@ static void reset_interrupt(void)
  */
 static void reset_fdc(void)
 {
+       unsigned long flags;
+       
        SET_INTR(reset_interrupt);
        FDCS->reset = 0;
        reset_fdc_info(0);
 
        /* Pseudo-DMA may intercept 'reset finished' interrupt.  */
        /* Irrelevant for systems with true DMA (i386).          */
+       
+       flags=claim_dma_lock();
        fd_disable_dma();
+       release_dma_lock(flags);
 
        if (FDCS->version >= FDC_82072A)
                fd_outb(0x80 | (FDCS->dtr &3), FD_STATUS);
@@ -1844,12 +1863,18 @@ static void show_floppy(void)
 
 static void floppy_shutdown(void)
 {
+       unsigned long flags;
+       
        if (!initialising)
                show_floppy();
        cancel_activity();
 
        floppy_enable_hlt();
+       
+       flags=claim_dma_lock();
        fd_disable_dma();
+       release_dma_lock(flags);
+       
        /* avoid dma going to a random drive after shutdown */
 
        if (!initialising)
@@ -1897,6 +1922,8 @@ static int start_motor(void (*function)(void) )
 
 static void floppy_ready(void)
 {
+       unsigned long flags;
+       
        CHECK_RESET;
        if (start_motor(floppy_ready)) return;
        if (fdc_dtr()) return;
@@ -1915,8 +1942,12 @@ static void floppy_ready(void)
 #ifdef fd_chose_dma_mode
        if ((raw_cmd->flags & FD_RAW_READ) || 
            (raw_cmd->flags & FD_RAW_WRITE))
+       {
+               flags=claim_dma_lock();
                fd_chose_dma_mode(raw_cmd->kernel_data,
                                  raw_cmd->length);
+               release_dma_lock(flags);
+       }
 #endif
 
        if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){
@@ -3020,7 +3051,12 @@ static void raw_cmd_done(int flag)
                        raw_cmd->reply[i] = reply_buffer[i];
 
                if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE))
+               {
+                       unsigned long flags;
+                       flags=claim_dma_lock();
                        raw_cmd->length = fd_get_dma_residue();
+                       release_dma_lock(flags);
+               }
                
                if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
                    (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
@@ -4025,6 +4061,7 @@ static struct param_table {
        { "usefifo", 0, &no_fifo, 0, 0 },
 
        { "cmos", set_cmos, 0, 0, 0 },
+       { "slow", 0, &slow_floppy, 1, 0 },
 
        { "unexpected_interrupts", 0, &print_unex, 1, 0 },
        { "no_unexpected_interrupts", 0, &print_unex, 0, 0 },
@@ -4036,15 +4073,6 @@ __initfunc(void floppy_setup(char *str, int *ints))
        int i;
        int param;
        if (str) {
-       /*
-        * PS/2 floppies have much slower step rates than regular floppies.
-        * It's been recommended that take about 1/4 of the default speed
-        * in some more extreme cases.
-        */
-       if( strcmp(str,"slow") == 0) {
-               slow_floppy = 1;
-               return;
-       }
                for (i=0; i< ARRAY_SIZE(config_params); i++){
                        if (strcmp(str,config_params[i].name) == 0){
                                if (ints[0])
@@ -4125,6 +4153,8 @@ __initfunc(int floppy_init(void))
 #endif
 
        if (floppy_grab_irq_and_dma()){
+               del_timer(&fd_timeout);
+               blk_dev[MAJOR_NR].request_fn = NULL;
                unregister_blkdev(MAJOR_NR,"fd");
                del_timer(&fd_timeout);
                return -EBUSY;
@@ -4176,7 +4206,8 @@ __initfunc(int floppy_init(void))
        current_drive = 0;
        floppy_release_irq_and_dma();
        initialising=0;
-       if (have_no_fdc) {
+       if (have_no_fdc) 
+       {
                DPRINT("no floppy controllers found\n");
                unregister_blkdev(MAJOR_NR,"fd");               
        }
index 9447cbbbe9f9cd4b09b17b92e0a9226b97f51afd..ced1261ec5121539531f6b9c4eaad7e57a078ba5 100644 (file)
@@ -71,7 +71,7 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
 {
        unsigned int part;
        const char *maj = hd->major_name;
-       char unit = (minor >> hd->minor_shift) + 'a';
+       int unit = (minor >> hd->minor_shift) + 'a';
 
        /*
         * IDE devices use multiple major numbers, but the drives
@@ -91,8 +91,19 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
                        unit += 2;
                case IDE0_MAJOR:
                        maj = "hd";
+                       break;
        }
        part = minor & ((1 << hd->minor_shift) - 1);
+       if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
+               unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
+               if (unit > 'z') {
+                       unit -= 'z' + 1;
+                       sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
+                       if (part)
+                               sprintf(buf + 4, "%d", part);
+                       return buf;
+               }
+       }
        if (part)
                sprintf(buf, "%s%c%d", maj, unit, part);
        else
index 17abec276993cde37a5fcc8cfeaeeb5424db669e..058d93b8588f7e8f669a092dad0316e57f14c564 100644 (file)
@@ -344,6 +344,21 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
        }
 }
 
+/*
+ * Needed for allowing full modular support of ide-driver
+ */
+int ide_release_dma (ide_hwif_t *hwif)
+{
+       if (hwif->dmatable) {
+               clear_page((unsigned long)hwif->dmatable);      /* clear PRD 1st */
+               free_page((unsigned long)hwif->dmatable);       /* free PRD 2nd */
+       }
+       if ((hwif->dma_extra) && (hwif->channel == 0))
+               release_region((hwif->dma_base + 16), hwif->dma_extra);
+       release_region(hwif->dma_base, 8);
+       return 1;
+}
+
 __initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports))
 {
        static unsigned long dmatable = 0;
@@ -404,6 +419,7 @@ __initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, c
                if (extra) /* PDC20246 & HPT343 */
                        request_region(dma_base+16, extra, name);
                dma_base += hwif->channel ? 8 : 0;
+               hwif->dma_extra = extra;
                if (inb(dma_base+2) & 0x80) {
                        printk("%s: simplex device:  DMA disabled\n", name);
                        dma_base = 0;
index 23725de8454822adcdb9b7f5a0e478ece75814f3..e5d48249d1661e27b99145014eeff4a1e78d24ee 100644 (file)
@@ -868,7 +868,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
 
                if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) {    /* Error detected */
 #if IDEFLOPPY_DEBUG_LOG
-                       printk (KERN_INFO "ide-floppy: %s: I/O error",drive->name);
+                       printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name);
 #endif /* IDEFLOPPY_DEBUG_LOG */
                        rq->errors++;
                        if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
@@ -1057,6 +1057,7 @@ static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc)
        pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD;
        pc->c[7] = 255;
        pc->c[8] = 255;
+       pc->request_transfer = 255;
 }
 
 /*
index 2a987e3d5dd74ca0a48876e789bb272df5423fbe..88b0dc631cd2bdd62062c78045f705bb01bc69bc 100644 (file)
@@ -117,16 +117,6 @@ typedef struct ide_pci_device_s {
        unsigned int            extra;
 } ide_pci_device_t;
 
-#ifdef CONFIG_BLK_DEV_OFFBOARD
-#  define ON_BOARD             0
-#  define OFF_BOARD            1
-#  define NEVER_BOARD          0
-#else /* CONFIG_BLK_DEV_OFFBOARD */
-#  define ON_BOARD             1
-#  define OFF_BOARD            0
-#  define NEVER_BOARD          0
-#endif /* CONFIG_BLK_DEV_OFFBOARD */
-
 static ide_pci_device_t ide_pci_chipsets[] __initdata = {
        {DEVID_PIIXa,   "PIIX",         NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
        {DEVID_PIIXb,   "PIIX",         NULL,           {{0x41,0x80,0x80}, {0x43,0x80,0x80}},   ON_BOARD,       0 },
index e19fed3f9a1f4df095a826c36f0bdf22e0fa7a6b..23a554398d05d4fd2eac1b2d74a1f323414350b0 100644 (file)
@@ -1737,6 +1737,11 @@ void ide_unregister (unsigned int index)
        else
                hwgroup->hwif = HWIF(hwgroup->drive);
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
+       if (hwif->dma_base)
+               (void) ide_release_dma(hwif);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
        /*
         * Remove us from the kernel's knowledge
         */
@@ -2998,8 +3003,13 @@ void cleanup_module (void)
 {
        int index;
 
-       for (index = 0; index < MAX_HWIFS; ++index)
+       for (index = 0; index < MAX_HWIFS; ++index) {
                ide_unregister(index);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+               if (ide_hwifs[index].dma_base)
+                       (void) ide_release_dma(&ide_hwifs[index]);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+       }
 #ifdef CONFIG_PROC_FS
        proc_ide_destroy();
 #endif
index 3ed885234f7c1ac1f9be0984406aa1631857328f..095bc51b15d8c67e743f4b3b1099b29f30df20f6 100644 (file)
@@ -328,6 +328,7 @@ typedef struct hwif_s {
        unsigned long   *dmatable;      /* dma physical region descriptor table */
        struct hwif_s   *mate;          /* other hwif from same PCI chip */
        unsigned long   dma_base;       /* base addr for dma ports */
+       unsigned        dma_extra;      /* extra addr for dma ports */
        unsigned long   config_data;    /* for use by chipset-specific code */
        unsigned long   select_data;    /* for use by chipset-specific code */
        struct proc_dir_entry *proc;    /* /proc/ide/ directory entry */
@@ -725,6 +726,14 @@ int ide_unregister_subdriver (ide_drive_t *drive);
 int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
+#define ON_BOARD               1
+#define NEVER_BOARD            0
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+#  define OFF_BOARD            ON_BOARD
+#else /* CONFIG_BLK_DEV_OFFBOARD */
+#  define OFF_BOARD            NEVER_BOARD
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+
 unsigned long ide_find_free_region (unsigned short size) __init;
 void ide_scan_pcibus (void) __init;
 #endif
@@ -735,6 +744,7 @@ int ide_build_dmatable (ide_drive_t *drive);
 void ide_dma_intr  (ide_drive_t *drive);
 int check_drive_lists (ide_drive_t *drive, int good_bad);
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+int ide_release_dma (ide_hwif_t *hwif);
 void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
 unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
 #endif
index 88ec8b308e30eb3a0c56dec4a89e9f0bb7d9ad15..b86019ecf8de9e2530d3a2da7a33f4cda39558d5 100644 (file)
@@ -93,8 +93,8 @@ int * blksize_size[MAX_BLKDEV] = { NULL, NULL, };
  *             then 512 bytes is assumed.
  * else
  *             sector_size is hardsect_size[MAJOR][MINOR]
- * This is currently set by some scsi device and read by the msdos fs driver
- * This might be a some uses later.
+ * This is currently set by some scsi devices and read by the msdos fs driver.
+ * Other uses may appear later.
  */
 int * hardsect_size[MAX_BLKDEV] = { NULL, NULL, };
 
@@ -297,8 +297,8 @@ void add_request(struct blk_dev_struct * dev, struct request * req)
        int queue_new_request = 0;
 
        switch (MAJOR(req->rq_dev)) {
-               case SCSI_DISK_MAJOR:
-                       disk_index = (MINOR(req->rq_dev) & 0x0070) >> 4;
+               case SCSI_DISK0_MAJOR:
+                       disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
                        if (disk_index < 4)
                                drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
                        break;
@@ -479,7 +479,14 @@ void make_request(int major,int rw, struct buffer_head * bh)
                        break;
                /* fall through */
 
-            case SCSI_DISK_MAJOR:
+            case SCSI_DISK0_MAJOR:
+            case SCSI_DISK1_MAJOR:
+            case SCSI_DISK2_MAJOR:
+            case SCSI_DISK3_MAJOR:
+            case SCSI_DISK4_MAJOR:
+            case SCSI_DISK5_MAJOR:
+            case SCSI_DISK6_MAJOR:
+            case SCSI_DISK7_MAJOR:
             case SCSI_CDROM_MAJOR:
 
                do {
index ccbcc0a97a959363f08e00de771e96f6f1ba7fac..7e5d4f99cb0f19dc3f489652433543becce51d7c 100644 (file)
@@ -533,6 +533,8 @@ static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs)
 /* xd_setup_dma: set up the DMA controller for a data transfer */
 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
 {
+       unsigned long f;
+       
        if (nodma)
                return (PIO_MODE);
        if (((u_int) buffer & 0xFFFF0000) != (((u_int) buffer + count) & 0xFFFF0000)) {
@@ -541,11 +543,15 @@ static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
 #endif /* DEBUG_OTHER */
                return (PIO_MODE);
        }
+       
+       f=claim_dma_lock();
        disable_dma(xd_dma);
        clear_dma_ff(xd_dma);
        set_dma_mode(xd_dma,mode);
        set_dma_addr(xd_dma,(u_int) buffer);
        set_dma_count(xd_dma,count);
+       
+       release_dma_lock(f);
 
        return (DMA_MODE);                      /* use DMA and INT */
 }
@@ -597,13 +603,22 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
 
 static inline u_int xd_wait_for_IRQ (void)
 {
+       unsigned long flags;
        xd_watchdog_int.expires = jiffies + 8 * HZ;
        add_timer(&xd_watchdog_int);
+       
+       flags=claim_dma_lock();
        enable_dma(xd_dma);
+       release_dma_lock(flags);
+       
        sleep_on(&xd_wait_int);
        del_timer(&xd_watchdog_int);
        xdc_busy = 0;
+       
+       flags=claim_dma_lock();
        disable_dma(xd_dma);
+       release_dma_lock(flags);
+       
        if (xd_error) {
                printk("xd: missed IRQ - command aborted\n");
                xd_error = 0;
index ba5fbf53d3f4b6960fd6cf794d5adf8cc5b2fb70..9da03f71bb7ae74af445c5dc7c018320d908f1b1 100644 (file)
@@ -3022,7 +3022,9 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
          {
             return -EIO;
          }
-         
+
+        copy_from_user(&ra, (char *) arg, sizeof(ra));
+
          if (ra.nframes == 0)
          {
             return 0;
@@ -3031,7 +3033,6 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
          i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes);
          if(i<0)
                return i;
-         copy_from_user(&ra, (char *) arg, sizeof(ra));
 
          if (ra.addr_format == CDROM_LBA)
          {
index 38c24c18ed5f026b84dce08722dcb8e1cedc5be1..16a24938e4c61130c675bb098874b95bb6096524 100644 (file)
@@ -56,7 +56,7 @@ if [ "$CONFIG_MOUSE" = "y" ]; then
        tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE
        tristate 'Logitech busmouse support' CONFIG_BUSMOUSE
        tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE
-       tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+       bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
        tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
        tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
 fi
index 3f9abf66c06de7d6c5ba5428bed321f691c796ca..1b711f46683fe62e83cac505a473b781d5f99f6a 100644 (file)
@@ -184,14 +184,6 @@ else
   endif
 endif
 
-ifeq ($(CONFIG_PSMOUSE),y)
-L_OBJS += psaux.o
-else
-  ifeq ($(CONFIG_PSMOUSE),m)
-  M_OBJS += psaux.o
-  endif
-endif
-
 ifeq ($(CONFIG_SOFT_WATCHDOG),y)
 L_OBJS += softdog.o
 else
index f6667efb003cd0e5f89dd3c5a44c22e6bfe78ecc..89cc8c3c225272d2668fef78d4d1170af712e188 100644 (file)
@@ -85,7 +85,7 @@ static unsigned int remap[BTTV_MAX];    /* remap Bt848 */
 static unsigned int radio[BTTV_MAX];
 static unsigned int card[BTTV_MAX] = { 0, 0, 
                                        0, 0 };
-static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0 };          
+static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0 };
 
 static int bttv_num;                   /* number of Bt848s in use */
 static struct bttv bttvs[BTTV_MAX];
@@ -96,8 +96,6 @@ static struct bttv bttvs[BTTV_MAX];
     { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
 #define I2C_GET()   (btread(BT848_I2C)&1)
 
-#define AUDIO_MUTE_DELAY 10000
-#define FREQ_CHANGE_DELAY 20000
 #define EEPROM_WRITE_DELAY 20000
 
 /*******************************/
@@ -433,9 +431,9 @@ static struct tvcard tvcards[] =
         {0, 0xc00, 0x800, 0x400, 0xc00, 0}},
         /* TurboTV */
         { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
-        /* Newer Hauppauge */
+       /* Newer Hauppauge */
        { 2, 0, 2, 1, { 2, 0, 0, 0}, {0, 1, 2, 3, 4}},
-  
+
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -585,7 +583,7 @@ static int set_pll(struct bttv *btv)
                 else
                 {
                         btwrite(0x08,BT848_TGCTRL);
-                        btv->pll.pll_crystal|=2;
+                       btv->pll.pll_crystal|=2;
                         return 1;            
                 }
                 udelay(10000);
@@ -623,8 +621,9 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input)
 
 #define VBIBUF_SIZE 65536
 
-/* Maximum sample number per VBI line is 2044, can NTSC deliver this? 
+/* Maximum sample number per VBI line is 2044, NTSC delivers 1600
    Note that we write 2048-aligned to keep alignment to memory pages 
+   VBI_RISC is written so that it applies to either 2044 or 1600
 */
 #define VBI_SPL 2044
 
@@ -783,199 +782,102 @@ static int  make_vrisctab(struct bttv *btv, unsigned int *ro,
        return 0;
 }
 
-/* does this really make a difference ???? */
-#define BURST_MAX 4096
-
-static inline void write_risc_segment(unsigned int **rp, unsigned long line_adr, unsigned int command,
-                       int *x, uint dx, uint bpp, uint width)
+static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h)
 {
-        unsigned int flags, len;
-  
-       if (!dx)
-                return;
-       len=dx*bpp;
-
-#ifdef LIMIT_DMA
-       if (command==BT848_RISC_WRITEC)
-       {
-                unsigned int dx2=BURST_MAX/bpp;
-               while (len>BURST_MAX)
-               {
-                       write_risc_segment(rp, line_adr, command,
-                                          &x,dx2, bpp, width);
-                       dx-=dx2;
-                       len=dx*bpp;
-               }
-       }
-#endif
-
-       /* mask upper 8 bits for 24+8 bit overlay modes */
-       flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
-       
-       if (*x==0) 
-       {
-                if (command==BT848_RISC_SKIP) 
-               {
-                       if (dx<width)
-                       {
-                               flags|=BT848_RISC_BYTE_ALL;
-                               command=BT848_RISC_WRITE;
-                       }
-               }
-               else
-                       if (command==BT848_RISC_WRITEC)
-                                command=BT848_RISC_WRITE;
-               flags|=BT848_RISC_SOL;
-        }
-       if (*x+dx==width)
-                flags|=BT848_RISC_EOL;
-       *((*rp)++)=command|flags|len;
-       if (command==BT848_RISC_WRITE)
-                *((*rp)++)=line_adr+*x*bpp;
-       *x+=dx;
+       int i, j;
+       /* bitmap is fixed width, 128 bytes (1024 pixels represented) */
+       if (x < 0 || y < 0 || w < 0 || h < 0)   /* catch bad clips */
+               return;
+       /* out of range data should just fall through */
+       for (i = y; i < y + h && i < 625; i++)
+               for (j = x; j < x + w && j < 1024; j++)
+                       clipmap[(i<<7)+(j>>3)] |= (1<<(j&7));
 }
 
 static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
 {
-       int i,t;
-       int yy, y, x, dx;
-       struct video_clip first, *cur, *cur2, *nx, first2, *prev, *nx2;
-       int bpp, bpl, width, height, inter;
-       unsigned int **rp,*ro,*re;
+       int i, line, x, y, bpl, width, height, inter;
+       unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len;
        unsigned long adr;
-       int cx,cx2,cy,cy2;
+       unsigned char *clipmap, cbit, lastbit, outofmem;
 
        inter=(btv->win.interlace&1)^1;
        bpp=btv->win.bpp;
+       if (bpp==15)    /* handle 15bpp as 16bpp in calculations */
+               bpp++;
        bpl=btv->win.bpl;
        ro=btv->risc_odd;
        re=btv->risc_even;
-       width=btv->win.width;
-       height=btv->win.height;
+       if((width=btv->win.width)>1023)
+               width = 1023;           /* sanity check */
+       if((height=btv->win.height)>625)
+               height = 625;           /* sanity check */
        adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
-
-       /* clip clipping rects against viewing window AND screen 
+       if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) {
+               /* can't clip, don't generate any risc code */
+               *(ro++)=BT848_RISC_JUMP;
+               *(ro++)=btv->bus_vbi_even;
+               *(re++)=BT848_RISC_JUMP;
+               *(re++)=btv->bus_vbi_odd;
+       }
+       if (ncr < 0) {  /* bitmap was pased */
+               memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE);
+       } else {        /* convert rectangular clips to a bitmap */
+               memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
+               for (i=0; i<ncr; i++)
+                       clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
+                               cr[i].width, cr[i].height);
+       }
+       /* clip against viewing window AND screen 
           so we do not have to rely on the user program
         */
-       cx=(btv->win.x<0) ? (-btv->win.x) : 0;
-       cy=(btv->win.y<0) ? (-btv->win.y) : 0;
-       cx2=(btv->win.x+width>btv->win.swidth) ? 
-               (btv->win.swidth-btv->win.x) : width;
-       cy2=(btv->win.y+height>btv->win.sheight) ? 
-               (btv->win.sheight-btv->win.y) : height;
-       first.next=NULL;
-       for (i=0; i<ncr; i++)
-       {
-                if ((t=cy-cr[i].y)>0)
-               {
-                       if (cr[i].height<=t)
-                               continue;
-                        cr[i].height-=t;
-                       cr[i].y=cy;
-               } 
-               if ((t=cy2-cr[i].y)<cr[i].height) 
-               {
-                       if (t<=0)
-                               continue;
-                       cr[i].height=t;
-               }
-                if ((t=cx-cr[i].x)>0)
-               {
-                       if (cr[i].width<=t)
-                               continue;
-                        cr[i].width-=t;
-                       cr[i].x=cx;
-               } 
-               if ((t=cx2-cr[i].x)<cr[i].width) 
-               {
-                       if (t<=0)
-                               continue;
-                       cr[i].width=t;
-               }
-               cur=&first;
-               while ((nx=cur->next) && (cr[i].y > cur->next->y))
-                       cur=nx; 
-               cur->next=&(cr[i]);
-               cr[i].next=nx;
-       }
-       first2.next=NULL;
+       clip_draw_rectangle(clipmap,(btv->win.x+width>btv->win.swidth) ?
+               (btv->win.swidth-btv->win.x) : width, 0, 1024, 768);
+       clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ?
+               (btv->win.sheight-btv->win.y) : height,1024,768);
+       if (btv->win.x<0)
+               clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768);
+       if (btv->win.y<0)
+               clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));
        
        *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
        *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
        
-       /* loop through all lines */
-       for (yy=0; yy<(height<<inter); yy++) 
+       /* translate bitmap to risc code */
+        for (line=outofmem=0; line < (height<<inter) && !outofmem; line++)
         {
-                y=yy>>inter;
-                rp= (yy&1) ? &re : &ro;
-         
-                /* remove rects with y2 > y */
-                if ((cur=first2.next))
-                {
-                        prev=&first2;
-                        do
-                        {
-                                if (cur->y+cur->height <= y) 
-                                        prev->next=cur->next;
-                                else
-                                        prev=cur;
-                        } 
-                        while ((cur=cur->next));
-                }
-                
-                /* add rect to second (x-sorted) list if rect.y == y  */
-                if ((cur=first.next))
-                {
-                        while ((cur) && (cur->y == y))
-                        { 
-                                first.next=cur->next;
-                                cur2=&first2;
-                                while ((nx2=cur2->next) && (cur->x > cur2->next->x)) 
-                                        cur2=nx2; 
-                                cur2->next=cur;
-                                cur->next=nx2;
-                                cur=first.next;
-                        }
-                }
-                x=0;
-                if ((btv->win.y+y<=0)||(btv->win.y+y>=btv->win.sheight))
-                        write_risc_segment(rp, adr, BT848_RISC_SKIP, &x,
-                                           width, bpp, width);
-                else 
-                {
-                        dx=cx;
-                        for (cur2=first2.next; cur2; cur2=cur2->next)
-                        {
-                                if (x+dx < cur2->x)
-                                {
-                                        write_risc_segment(rp, adr, BT848_RISC_SKIP,
-                                                           &x, dx, bpp, width);
-                                        dx=cur2->x-x;
-                                        write_risc_segment(rp, adr, BT848_RISC_WRITEC,
-                                                           &x, dx, bpp, width);
-                                        dx=cur2->width;
-                                }
-                                else if (x+dx < cur2->x+cur2->width) 
-                                        dx=cur2->x+cur2->width-x; 
-                        }
-                        if (cx2<width)
-                        {
-                                write_risc_segment(rp, adr, BT848_RISC_SKIP,
-                                                   &x, dx, bpp, width);
-                                write_risc_segment(rp, adr, BT848_RISC_WRITEC,
-                                                   &x, cx2-x, bpp, width);
-                                dx=width-x;
-                        }
-                        write_risc_segment(rp, adr, BT848_RISC_SKIP,
-                                           &x, dx, bpp, width);
-                        write_risc_segment(rp, adr, BT848_RISC_WRITEC,
-                                           &x, width-x, bpp, width);
-                }
-                if ((!inter)||(yy&1))
+               y = line>>inter;
+               rp= (line&1) ? &re : &ro;
+               lastbit=(clipmap[y<<7]&1);
+               for(x=dx=1,sx=0; x<=width && !outofmem; x++) {
+                       cbit = (clipmap[(y<<7)+(x>>3)] & (1<<(x&7)));
+                       if (x < width && !lastbit == !cbit)
+                               dx++;
+                       else {  /* generate the dma controller code */
+                               len = dx * bpp;
+                               flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
+                               flags |= ((!sx) ? BT848_RISC_SOL : 0);
+                               flags |= ((sx + dx == width) ? BT848_RISC_EOL : 0);
+                               if (!lastbit) {
+                                       *((*rp)++)=BT848_RISC_WRITE|flags|len;
+                                       *((*rp)++)=adr + bpp * sx;
+                               } else
+                                       *((*rp)++)=BT848_RISC_SKIP|flags|len;
+                               lastbit=cbit;
+                               sx += dx;
+                               dx = 1;
+                               if (ro - btv->risc_odd > RISCMEM_LEN/2 - 16)
+                                       outofmem++;
+                               if (re - btv->risc_even > RISCMEM_LEN/2 - 16)
+                                       outofmem++;
+                       }
+               }
+               if ((!inter)||(line&1))
                         adr+=bpl;
        }
-        
-        *(ro++)=BT848_RISC_JUMP;
+       vfree(clipmap);
+       /* outofmem flag relies on the following code to discard extra data */
+       *(ro++)=BT848_RISC_JUMP;
        *(ro++)=btv->bus_vbi_even;
        *(re++)=BT848_RISC_JUMP;
        *(re++)=btv->bus_vbi_odd;
@@ -1005,38 +907,39 @@ struct tvnorm
 static struct tvnorm tvnorms[] = {
        /* PAL-BDGHI */
         /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+       /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
         { 35468950,
           924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
-          1135, 186, 924, 0x20},
+          1135, 178, 924, 0x20},
 /*
         { 35468950, 
           768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
-         944, 186, 922, 0x20},
+         944, 178, 922, 0x20},
 */
        /* NTSC */
        { 28636363,
           640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
-          780, 135, 754, 0x1a},
-       /* SECAM */
-       { 28636363
-          640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
-         780, 135, 754, 0x16},
+          780, 122, 754, 0x1a},
+       /* SECAM - phase means nothing in SECAM, bdelay is useless */
+       { 35468950
+          924, 576,1135, 0x7f, 0x72, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+         1135, 178, 924, 0x20},
        /* PAL-M */
        { 28636363, 
           640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
-         780, 135, 754, 0x16},
+         780, 122, 754, 0x1a},
        /* PAL-N */
        { 35468950, 
           768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
-         944, 186, 922, 0x20},
+         944, 178, 922, 0x20},
        /* PAL-NC */
        { 35468950, 
           768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
-         944, 186, 922, 0x20},
+         944, 178, 922, 0x20},
        /* NTSC-Japan */
        { 28636363,
           640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
-         780, 135, 754, 0x16},
+         780, 122, 754, 0x1a},
 };
 #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
 
@@ -1146,6 +1049,12 @@ static void bt848_set_winsize(struct bttv *btv)
 {
         unsigned short format;
 
+       /* setup proper VBI capture length for given video mode */
+       if (btv->win.norm == VIDEO_MODE_NTSC)
+               btwrite(144, BT848_VBI_PACK_SIZE);      /* 1600 samples */
+       else
+               btwrite(255, BT848_VBI_PACK_SIZE);      /* 2044 samples */
+       btwrite(1, BT848_VBI_PACK_DEL);                 /* bit 9 for above */
         btv->win.color_fmt = format = 
                 (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
                         bpp2fmt[(btv->win.bpp-1)&3];
@@ -1172,11 +1081,7 @@ static void bt848_set_winsize(struct bttv *btv)
 static void set_freq(struct bttv *btv, unsigned short freq)
 {
        int fixme = freq; /* XXX */
-       int oldAudio = btv->audio;
        
-       audio(btv, AUDIO_MUTE);
-       udelay(AUDIO_MUTE_DELAY);
-
        if (btv->radio) 
        {
                if (btv->have_tuner)
@@ -1204,10 +1109,6 @@ static void set_freq(struct bttv *btv, unsigned short freq)
                }
        }
 
-       if (!(oldAudio & AUDIO_MUTE)) {
-               udelay(FREQ_CHANGE_DELAY);
-               audio(btv, AUDIO_UNMUTE);
-       }
 }
       
 
@@ -1604,15 +1505,20 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                case VIDIOCSWIN:
                {
                        struct video_window vw;
-                       struct video_clip *vcp;
+                       struct video_clip *vcp = NULL;
                        int on;
                        
                        if(copy_from_user(&vw,arg,sizeof(vw)))
                                return -EFAULT;
                                
-                       if(vw.flags)
+                       if(vw.flags || vw.width < 16 || vw.height < 16) {
+                               bt848_cap(btv,0);
                                return -EINVAL;
-                               
+                       }
+                       if (btv->win.bpp < 4) { /* adjust and align writes */
+                               vw.x = (vw.x + 3) & ~3;
+                               vw.width = (vw.width - 3) & ~3;
+                       }
                        btv->win.x=vw.x;
                        btv->win.y=vw.y;
                        btv->win.width=vw.width;
@@ -1623,26 +1529,37 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        else
                                btv->win.interlace=0;
 
-                       on=(btv->cap&3)?1:0;
+                       on=(btv->cap&3);
                        
                        bt848_cap(btv,0);
                        bt848_set_winsize(btv);
 
-                       if(vw.clipcount>256)
-                               return -EDOM;   /* Too many! */
-
                        /*
                         *      Do any clips.
                         */
-
-                       vcp=vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
-                       if(vcp==NULL)
-                               return -ENOMEM;
-                       if(vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount))
-                               return -EFAULT;
-                       make_clip_tab(btv,vcp, vw.clipcount);
-                       vfree(vcp);
-                       if(on && btv->win.vidadr!=0)
+                       if(vw.clipcount<0) {
+                               if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL)
+                                       return -ENOMEM;
+                               if(copy_from_user(vcp, vw.clips,
+                                       VIDEO_CLIPMAP_SIZE)) {
+                                       vfree(vcp);
+                                       return -EFAULT;
+                               }
+                       } else if (vw.clipcount) {
+                               if((vcp=vmalloc(sizeof(struct video_clip)*
+                                       (vw.clipcount))) == NULL)
+                                       return -ENOMEM;
+                               if(copy_from_user(vcp,vw.clips,
+                                       sizeof(struct video_clip)*
+                                       vw.clipcount)) {
+                                       vfree(vcp);
+                                       return -EFAULT;
+                               }
+                       }
+                       make_clip_tab(btv, vcp, vw.clipcount);
+                       if (vw.clipcount != 0)
+                               vfree(vcp);
+                       if(on && btv->win.vidadr != 0)
                                bt848_cap(btv,1);
                        return 0;
                }
@@ -1700,7 +1617,9 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EPERM;
                        if(copy_from_user(&v, arg,sizeof(v)))
                                return -EFAULT;
-                       if(v.depth!=8 && v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32)
+                       if(v.depth!=8 && v.depth!=15 && v.depth!=16 && 
+                               v.depth!=24 && v.depth!=32 && v.width > 16 &&
+                               v.height > 16 && v.bytesperline > 16)
                                return -EINVAL;
                        btv->win.vidadr=(unsigned long)v.base;
                        btv->win.sheight=v.height;
@@ -1801,9 +1720,6 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                case VIDIOCSYNC:
                        if(copy_from_user((void *)&i,arg,sizeof(int)))
                                return -EFAULT;
-                        if(i>1 || i<0)
-                                return -EINVAL;
-
                         switch (btv->frame_stat[i]) {
                         case GBUFFER_UNUSED:
                                 return -EINVAL;
@@ -1832,24 +1748,25 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EFAULT;
                        break;
 
-                case BTTV_FIELDNR: 
+               case BTTV_FIELDNR:
                        if(copy_to_user((void *) arg, (void *) &btv->last_field, 
                                         sizeof(btv->last_field)))
                                return -EFAULT;
                         break;
-      
-                case BTTV_PLLSET: {
-                        struct bttv_pll_info p;
-                        if(!capable(CAP_SYS_ADMIN))
-                               return -EPERM;
-                        if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
-                               return -EFAULT;
-                        btv->pll.pll_ifreq = p.pll_ifreq;
-                        btv->pll.pll_ofreq = p.pll_ofreq;
-                        btv->pll.pll_crystal = p.pll_crystal;
 
+               case BTTV_PLLSET:
+               {
+                       struct bttv_pll_info p;
+                       if(!capable(CAP_SYS_ADMIN))
+                               return -EPERM;
+                       if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
+                               return -EFAULT;
+                       btv->pll.pll_ifreq = p.pll_ifreq;
+                       btv->pll.pll_ofreq = p.pll_ofreq;
+                       btv->pll.pll_crystal = p.pll_crystal;
                        break;
-                }                                              
+               }
+
                case VIDIOCMCAPTURE:
                {
                         struct video_mmap vm;
@@ -2418,12 +2335,11 @@ static void idcard(int i)
        {
                btv->type=BTTV_MIRO;
     
-               if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0)
-               {
+               if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) {
                        if(btv->id>849)
                                btv->type=BTTV_HAUPPAUGE878;
                        else
-                               btv->type=BTTV_HAUPPAUGE;
+                               btv->type=BTTV_HAUPPAUGE;
                }
                else
                        if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
@@ -2459,7 +2375,6 @@ static void idcard(int i)
 
        /* How do I detect the tuner type for other cards but Miro ??? */
        printk(KERN_INFO "bttv%d: model: ", btv->nr);
-       
        sprintf(btv->video_dev.name,"BT%d",btv->id);
        switch (btv->type) 
        {
@@ -2472,10 +2387,9 @@ static void idcard(int i)
                                                   I2C_DRIVERID_TUNER,
                                                   TUNER_SET_TYPE,&tunertype);
                        }
-                       strcat(btv->video_dev.name, "(Miro)");
+                       strcat(btv->video_dev.name,"(Miro)");
                        break;
                case BTTV_HAUPPAUGE:
-               case BTTV_HAUPPAUGE878:
                        printk("HAUPPAUGE\n");
                        strcat(btv->video_dev.name,"(Hauppauge)");
                        break;
@@ -2650,11 +2564,6 @@ static int init_bt848(int i)
         /* select direct input */
        btwrite(0x00, BT848_GPIO_REG_INP);
 
-
-       btwrite(0xff, BT848_VBI_PACK_SIZE);
-       btwrite(1, BT848_VBI_PACK_DEL);
-
-               
        btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_PAL_BDGHI,
                BT848_IFORM);
 
@@ -2776,6 +2685,8 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                        if (stat&(1<<28)) 
                        {
                                btv->vbip=0;
+                               /* inc vbi frame count for detecting drops */
+                               (*(u32 *)&(btv->vbibuf[VBIBUF_SIZE - 4]))++;
                                wake_up_interruptible(&btv->vbiq);
                        }
 
@@ -2844,10 +2755,12 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                }
                if (astat&BT848_INT_HLOCK) 
                {
+#if 0
                        if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio))
                                audio(btv, AUDIO_ON);
                        else
                                audio(btv, AUDIO_OFF);
+#endif
                }
     
                if (astat&BT848_INT_I2CDONE) 
@@ -2923,16 +2836,16 @@ int configure_bt848(struct pci_dev *dev, int bttv_num)
         printk("irq: %d, ",btv->irq);
         printk("memory: 0x%08x.\n", btv->bt848_adr);
         
-        btv->pll.pll_ifreq=0;
-        btv->pll.pll_ofreq=0;
-        btv->pll.pll_crystal=0;
+       btv->pll.pll_ifreq=0;
+       btv->pll.pll_ofreq=0;
+       btv->pll.pll_crystal=0;
         if(pll[btv->nr])
                 if (!(btv->id==848 && btv->revision==0x11))
                 {
                         printk(KERN_INFO "bttv%d: internal PLL, single crystal operation enabled\n",bttv_num);
-                        btv->pll.pll_ofreq=28636363;
-                        btv->pll.pll_ifreq=35468950;
-                        btv->pll.pll_crystal=BT848_IFORM_XT1;
+                       btv->pll.pll_ofreq=28636363;
+                       btv->pll.pll_ifreq=35468950;
+                       btv->pll.pll_crystal=BT848_IFORM_XT1;
                 }
         
         btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
@@ -2997,7 +2910,7 @@ static int find_bt848(void)
                 dev = dev->next;
         }
        if(bttv_num)
-               printk(KERN_INFO "bttv: %d BT8xx card(s) found.\n", bttv_num);
+               printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
        return bttv_num;
 }
  
@@ -3113,4 +3026,3 @@ void cleanup_module(void)
  * tab-width: 8
  * End:
  */
index f8da6c6d0a67240ea2c34984bb4ba57eb89ad34d..bdf92b87ea647a7238d85556be116fa20982d9e3 100644 (file)
@@ -31,7 +31,6 @@
 #include "bt848.h"
 #include <linux/videodev.h>
 
-#define MAX_CLIPRECS   100
 #define MAX_GBUFFERS   2
 #define RISCMEM_LEN    (32744*2)
 
@@ -56,10 +55,9 @@ struct bttv_window
        ushort depth;
 };
 
-
 struct bttv_pll_info {
-       unsigned int pll_ifreq; /* PLL input frequency    */
-       unsigned int pll_ofreq; /* PLL output frequency   */
+       unsigned int pll_ifreq;         /* PLL input frequency    */
+       unsigned int pll_ofreq;         /* PLL output frequency   */
        unsigned int pll_crystal;       /* Crystal used for input */
 };
 
@@ -143,6 +141,7 @@ struct bttv
        int i2c_command;
        int triton1;
 };
+
 #endif
 
 /*The following should be done in more portable way. It depends on define
index 48de68db349411e421c85a7e223bf064d3f3fba1..22599060fe57134a397a077cb2373afc8a25b48b 100644 (file)
@@ -296,7 +296,7 @@ static int qc_detect(struct qcam_device *q)
                if (reg != lastreg)
                        count++;
                lastreg = reg;
-               mdelay(1);
+               mdelay(2);
        }
 
        /* Be liberal in what you accept...  */
index 3bf42a5e4078804c056cc633587974d4293e9f3c..545d2728769f72cd3c89fcef27d1a597743143f4 100644 (file)
@@ -395,15 +395,20 @@ static _INLINE_ void receive_chars_pio(struct esp_struct *info, int num_bytes)
 
 static _INLINE_ void receive_chars_dma(struct esp_struct *info, int num_bytes)
 {
+       unsigned long flags;
        info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
        dma_bytes = num_bytes;
        info->stat_flags |= ESP_STAT_DMA_RX;
+       
+       flags=claim_dma_lock();
         disable_dma(dma);
         clear_dma_ff(dma);
         set_dma_mode(dma, DMA_MODE_READ);
         set_dma_addr(dma, virt_to_bus(dma_buffer));
         set_dma_count(dma, dma_bytes);
         enable_dma(dma);
+        release_dma_lock(flags);
+        
         serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
 }
 
@@ -412,12 +417,17 @@ static _INLINE_ void receive_chars_dma_done(struct esp_struct *info,
 {
        struct tty_struct *tty = info->tty;
        int num_bytes;
-
+       unsigned long flags;
+       
+       
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
 
        info->stat_flags &= ~ESP_STAT_DMA_RX;
        num_bytes = dma_bytes - get_dma_residue(dma);
+       release_dma_lock(flags);
+       
        info->icount.rx += num_bytes;
 
        memcpy(tty->flip.char_buf_ptr, dma_buffer, num_bytes);
@@ -534,6 +544,8 @@ static _INLINE_ void transmit_chars_pio(struct esp_struct *info,
 
 static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int num_bytes)
 {
+       unsigned long flags;
+       
        dma_bytes = num_bytes;
 
        if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) {
@@ -564,34 +576,46 @@ static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int num_bytes)
        }
 
        info->stat_flags |= ESP_STAT_DMA_TX;
+       
+       flags=claim_dma_lock();
         disable_dma(dma);
         clear_dma_ff(dma);
         set_dma_mode(dma, DMA_MODE_WRITE);
         set_dma_addr(dma, virt_to_bus(dma_buffer));
         set_dma_count(dma, dma_bytes);
         enable_dma(dma);
+        release_dma_lock(flags);
+        
         serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
 }
 
 static _INLINE_ void transmit_chars_dma_done(struct esp_struct *info)
 {
        int num_bytes;
+       unsigned long flags;
+       
 
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
 
        num_bytes = dma_bytes - get_dma_residue(dma);
        info->icount.tx += dma_bytes;
+       release_dma_lock(flags);
 
        if (dma_bytes != num_bytes) {
                dma_bytes -= num_bytes;
                memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes);
+               
+               flags=claim_dma_lock();
                disable_dma(dma);
                clear_dma_ff(dma);
                set_dma_mode(dma, DMA_MODE_WRITE);
                set_dma_addr(dma, virt_to_bus(dma_buffer));
                set_dma_count(dma, dma_bytes);
                enable_dma(dma);
+               release_dma_lock(flags);
+               
                serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
        } else {
                dma_bytes = 0;
@@ -1003,7 +1027,7 @@ static int startup(struct esp_struct * info)
  */
 static void shutdown(struct esp_struct * info)
 {
-       unsigned long   flags;
+       unsigned long   flags, f;
 
        if (!(info->flags & ASYNC_INITIALIZED))
                return;
@@ -1025,8 +1049,11 @@ static void shutdown(struct esp_struct * info)
        /* stop a DMA transfer on the port being closed */
           
        if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {
+               f=claim_dma_lock();
                disable_dma(dma);
                clear_dma_ff(dma);
+               release_dma_lock(f);
+               
                dma_bytes = 0;
        }
        
index de5ed5cc2e58e2a55d0961b37e60f4a0cf5c4a76..d940bd2323dbcd7b4e16c8a60773196d92af17c8 100644 (file)
@@ -148,14 +148,6 @@ struct hfmodem_state hfmodem_state[NR_DEVICE];
 #define SP_PAR  2
 #define SP_MIDI 4
 
-/* ---------------------------------------------------------------------- */
-
-static int parptt_preempt(void *handle)
-{
-       /* we cannot relinquish the port in the middle of an operation */
-       return 1;
-}
-
 /* --------------------------------------------------------------------- */
 
 static void parptt_wakeup(void *handle)
@@ -176,8 +168,8 @@ __initfunc(static int check_lpt(struct hfmodem_state *dev, unsigned int iobase))
                pp = pp->next;
        if (!pp)
                return 0;
-       if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, parptt_preempt, parptt_wakeup, 
-                                                           NULL, PARPORT_DEV_LURK, dev)))
+       if (!(dev->ptt_out.pardev = parport_register_device(pp, hfmodem_drvname, NULL, parptt_wakeup, 
+                                                           NULL, PARPORT_DEV_EXCL, dev)))
                return 0;
        return 1;
 }
index 85a488c95113a77b4a8f5b8a97476c2c0d99796c..cad1bd26d901970599e8bdbcd2a12a6c2ef844f9 100644 (file)
@@ -466,7 +466,9 @@ static struct js_port __init *js_console_probe(int *config, struct js_port *port
                        return port;
                }
 
-               info.port = parport_register_device(pp, "joystick (console)", NULL, js_console_wakeup, NULL, 0, NULL);
+               info.port = parport_register_device(pp, "joystick (console)", NULL, js_console_wakeup, NULL, PARPORT_DEV_EXCL, NULL);
+               if (!info.port)
+                       return port;
                info.wanted = 0;
                info.use = 0;
        }
index bffbc6b2d3b39ef042572a0ba996cb69ae4075e2..10b77108ae2f7e7d07f6f9b8a13511ef629563af 100644 (file)
@@ -389,7 +389,9 @@ static struct js_port __init *js_db9_probe(int *config, struct js_port *port)
                        return port;
                }
 
-               info.port = parport_register_device(pp, "joystick (db9)", NULL, js_db9_wakeup, NULL, 0, NULL);
+               info.port = parport_register_device(pp, "joystick (db9)", NULL, js_db9_wakeup, NULL, PARPORT_DEV_EXCL, NULL);
+               if (!info.port)
+                       return port;
                info.wanted = 0;
        }
 #else
index 6c7eb0ea5c73fd790a598d45c3d92784415e979d..5b52b17fb303e270c936230d736fcaaa351769ed 100644 (file)
@@ -295,7 +295,7 @@ void __init js_l4_setup(char *str, int *ints)
 #ifdef MODULE
 int init_module(void)
 #else
-int __init js_l4_an_init(void)
+int __init js_l4_init(void)
 #endif
 {
        int i, cards;
index fb8f65e5bc17ffda9a9e65c310f2549dc5aa7ecb..2293c4351b9c45b23fea119fb52c3ac591e3195f 100644 (file)
@@ -217,7 +217,9 @@ static struct js_port __init *js_tg_probe(int *config, struct js_port *port)
                        return port;
                }
 
-               info.port = parport_register_device(pp, "joystick (turbografx)", NULL, js_tg_wakeup, NULL, 0, NULL);
+               info.port = parport_register_device(pp, "joystick (turbografx)", NULL, js_tg_wakeup, NULL, PARPORT_DEV_EXCL, NULL);
+               if (!info.port)
+                       return port;
                info.wanted = 0;
                info.use = 0;
        }
index b8d143fbea2b1a047c987b8203d2079959d3a299..0fb4a851401ae63d259e50f153984d3e8b8b3da8 100644 (file)
@@ -768,7 +768,7 @@ int lp_register(int nr, struct parport *port)
        lp_table[nr].dev = parport_register_device(port, "lp", 
                                                   lp_preempt, NULL,
                                                   lp_interrupt, 
-                                                  PARPORT_DEV_TRAN,
+                                                  0,
                                                   (void *) &lp_table[nr]);
        if (lp_table[nr].dev == NULL)
                return 1;
index 0470bdd05b661f6ed5984f48def5a52493915ee7..c651ee88baecae6e7aebd4871cdeb1103b1d43b4 100644 (file)
@@ -66,7 +66,6 @@ static unsigned char misc_minors[DYNAMIC_MINORS / 8];
 
 extern int adbdev_init(void);
 extern int bus_mouse_init(void);
-extern int psaux_init(void);
 extern int qpmouse_init(void);
 extern int ms_bus_mouse_init(void);
 extern int atixl_busmouse_init(void);
@@ -156,8 +155,13 @@ int misc_register(struct miscdevice * misc)
        }
        if (misc->minor < DYNAMIC_MINORS)
                misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
-       misc->next = &misc_list;
-       misc->prev = misc_list.prev;
+
+       /*
+        * Add it to the front, so that later devices can "override"
+        * earlier defaults
+        */
+       misc->prev = &misc_list;
+       misc->next = misc_list.next;
        misc->prev->next = misc;
        misc->next->prev = misc;
        return 0;
@@ -199,10 +203,7 @@ int __init misc_init(void)
        bus_mouse_init();
 #endif
 #if defined CONFIG_82C710_MOUSE
-       qpmouse_init();         /* This must be before psaux_init */
-#endif
-#if defined CONFIG_PSMOUSE
-       psaux_init();
+       qpmouse_init();
 #endif
 #ifdef CONFIG_MS_BUSMOUSE
        ms_bus_mouse_init();
index 5cdd615270aca6b3a82e350bf33aa99d73657629..72acddb459154b777baa25dedfa614bf41765aab 100644 (file)
@@ -5,10 +5,16 @@
  * See keyboard.c for the whole history.
  *
  * Major cleanup by Martin Mares, May 1997
+ *
+ * Combined the keyboard and PS/2 mouse handling into one file,
+ * because they share the same hardware.
+ * Johan Myreen <jem@iki.fi> 1998-10-08.
+ *
  */
 
 #include <linux/config.h>
 
+#include <asm/spinlock.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <linux/kbd_ll.h>
 #include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -43,32 +54,69 @@ unsigned char pckbd_sysrq_xlate[128] =
        "\r\000/";                                      /* 0x60 - 0x6f */
 #endif
 
-unsigned char pckbd_read_mask = KBD_STAT_OBF; /* Modified by psaux.c */
+static void kbd_write(int address, int data);
+
+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
 
 /* used only by send_data - set by keyboard_interrupt */
 static volatile unsigned char reply_expected = 0;
 static volatile unsigned char acknowledge = 0;
 static volatile unsigned char resend = 0;
 
+
+#if defined CONFIG_PSMOUSE
 /*
- *     Wait for keyboard controller input buffer is empty.
+ *     PS/2 Auxiliary Device
+ */
+
+static int __init psaux_init(void);
+
+static struct aux_queue *queue;        /* Mouse data buffer. */
+static int aux_count = 0;
+
+#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
+#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
+
+#define MAX_RETRIES    60              /* some aux operations take long time*/
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+# define AUX_IRQ       9               /* Jensen is odd indeed */
+#else
+# define AUX_IRQ       12
+#endif
+#endif /* CONFIG_PSMOUSE */
+
+/*
+ * Wait for keyboard controller input buffer is empty.
+ *
+ * Don't use 'jiffies' so that we don't depend on
+ * interrupts..
+ *
+ * Quote from PS/2 System Reference Manual:
  *
- *     Don't use 'jiffies' so that we don't depend on
- *     interrupts..
+ * "Address hex 0060 and address hex 0064 should be written only when
+ * the input-buffer-full bit and output-buffer-full bit in the
+ * Controller Status register are set 0."
  */
 
 static inline void kb_wait(void)
 {
        unsigned long timeout = KBC_TIMEOUT;
+       unsigned char status;
 
        do {
+               status = inb_p(KBD_STATUS_REG);
+               if (status & KBD_STAT_OBF) {
+                       if (status & KBD_STAT_MOUSE_OBF)
+                       inb_p(KBD_DATA_REG); /* Flush. */
+               }
+
                if (! (inb_p(KBD_STATUS_REG) & KBD_STAT_IBF))
                        return;
                mdelay(1);
                timeout--;
        } while (timeout);
 #ifdef KBD_REPORT_TIMEOUTS
-       printk(KERN_WARNING "Keyboard timed out\n");
+       printk(KERN_WARNING "Keyboard timed out[1]\n");
 #endif
 }
 
@@ -211,11 +259,16 @@ int pckbd_getkeycode(unsigned int scancode)
 #if DISABLE_KBD_DURING_INTERRUPTS
 static inline void send_cmd(unsigned char c)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&kbd_controller_lock, flags);
        kb_wait();
        outb(c, KBD_CNTL_REG);
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
-#define disable_keyboard()     do { send_cmd(KBD_CCMD_KBD_DISABLE); kb_wait(); } while (0)
+/* #define disable_keyboard()  do { send_cmd(KBD_CCMD_KBD_DISABLE); kb_wait(); } while (0) */
+#define disable_keyboard()     send_cmd(KBD_CCMD_KBD_DISABLE)
 #define enable_keyboard()      send_cmd(KBD_CCMD_KBD_ENABLE)
 #else
 #define disable_keyboard()     /* nothing */
@@ -368,27 +421,45 @@ char pckbd_unexpected_up(unsigned char keycode)
 
 static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+       unsigned long flags;
        unsigned char status;
 
-       kbd_pt_regs = regs;
        disable_keyboard();
+       spin_lock_irqsave(&kbd_controller_lock, flags);
+       kbd_pt_regs = regs;
 
-       status = inb_p(KBD_STATUS_REG);
-       do {
+       status = inb(KBD_STATUS_REG);
+       while (status & KBD_STAT_OBF) {
                unsigned char scancode;
 
-               /* mouse data? */
-               if (status & pckbd_read_mask & KBD_STAT_MOUSE_OBF)
-                       break;
-
                scancode = inb(KBD_DATA_REG);
-               if ((status & KBD_STAT_OBF) && do_acknowledge(scancode))
-                       handle_scancode(scancode);
+
+               if (status & KBD_STAT_MOUSE_OBF) {
+#ifdef CONFIG_PSMOUSE
+                       /* Mouse data. */
+                       if (aux_count) {
+                               int head = queue->head;
+                               queue->buf[head] = scancode;
+                               add_mouse_randomness(scancode);
+                               head = (head + 1) & (AUX_BUF_SIZE-1);
+                               if (head != queue->tail) {
+                                       queue->head = head;
+                                       if (queue->fasync)
+                                               kill_fasync(queue->fasync, SIGIO);
+                                       wake_up_interruptible(&queue->proc_list);
+                               }
+                       }
+#endif
+               } else {
+                       if (do_acknowledge(scancode))
+                               handle_scancode(scancode);
+                       mark_bh(KEYBOARD_BH);
+               }
 
                status = inb(KBD_STATUS_REG);
-       } while (status & KBD_STAT_OBF);
+       }
 
-       mark_bh(KEYBOARD_BH);
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
        enable_keyboard();
 }
 
@@ -406,11 +477,10 @@ static int send_data(unsigned char data)
        do {
                unsigned long timeout = KBD_TIMEOUT;
 
-               kb_wait();
-               acknowledge = 0;
+               acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
                resend = 0;
                reply_expected = 1;
-               outb_p(data, KBD_DATA_REG);
+               kbd_write(KBD_DATA_REG, data);
                for (;;) {
                        if (acknowledge)
                                return 1;
@@ -419,7 +489,7 @@ static int send_data(unsigned char data)
                        mdelay(1);
                        if (!--timeout) {
 #ifdef KBD_REPORT_TIMEOUTS
-                               printk(KERN_WARNING "Keyboard timeout\n");
+                               printk(KERN_WARNING "Keyboard timeout[2]\n");
 #endif
                                return 0;
                        }
@@ -500,16 +570,30 @@ static int __init kbd_wait_for_input(void)
        return -1;
 }
 
-static void __init kbd_write(int address, int data)
+static void kbd_write(int address, int data)
 {
-       int status;
+       unsigned long flags;
 
-       do {
-               status = inb(KBD_STATUS_REG);
-       } while (status & KBD_STAT_IBF);
+       spin_lock_irqsave(&kbd_controller_lock, flags);
+       kb_wait();
        outb(data, address);
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
+#if defined CONFIG_PSMOUSE
+static void kbd_write_cmd(int cmd)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&kbd_controller_lock, flags);
+       kb_wait();
+       outb(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG);
+       kb_wait();
+       outb(cmd, KBD_DATA_REG);
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+#endif /* CONFIG_PSMOUSE */
+
 static char * __init initialize_kbd(void)
 {
        int status;
@@ -623,6 +707,225 @@ void __init pckbd_init_hw(void)
                        printk(KERN_WARNING "initialize_kbd: %s\n", msg);
        }
 
+#if defined CONFIG_PSMOUSE
+       psaux_init();
+#endif
+
        /* Ok, finally allocate the IRQ, and off we go.. */
        request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
 }
+
+#if defined CONFIG_PSMOUSE
+/*
+ * Send a byte to the mouse.
+ */
+static void aux_write_dev(int val)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&kbd_controller_lock, flags);
+       kb_wait();
+       outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
+       kb_wait();
+       outb(val, KBD_DATA_REG);
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+static unsigned int get_from_queue(void)
+{
+       unsigned int result;
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+       result = queue->buf[queue->tail];
+       queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+       restore_flags(flags);
+       return result;
+}
+
+
+static inline int queue_empty(void)
+{
+       return queue->head == queue->tail;
+}
+
+static int fasync_aux(int fd, struct file *filp, int on)
+{
+       int retval;
+
+       retval = fasync_helper(fd, filp, on, &queue->fasync);
+       if (retval < 0)
+               return retval;
+       return 0;
+}
+
+
+static int release_aux(struct inode * inode, struct file * file)
+{
+       fasync_aux(-1, file, 0);
+       if (--aux_count)
+               return 0;
+       kbd_write_cmd(AUX_INTS_OFF);                        /* Disable controller ints */
+       kbd_write(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG);
+#ifdef CONFIG_MCA
+       free_irq(AUX_IRQ, inode);
+#else
+       free_irq(AUX_IRQ, NULL);
+#endif
+       return 0;
+}
+
+/*
+ * Install interrupt handler.
+ * Enable auxiliary device.
+ */
+
+static int open_aux(struct inode * inode, struct file * file)
+{
+       if (aux_count++) {
+               return 0;
+       }
+       queue->head = queue->tail = 0;          /* Flush input queue */
+#ifdef CONFIG_MCA
+       if (request_irq(AUX_IRQ, keyboard_interrupt, MCA_bus ? SA_SHIRQ : 0, "PS/2 Mouse", inode)) {
+#else
+       if (request_irq(AUX_IRQ, keyboard_interrupt, 0, "PS/2 Mouse", NULL)) {
+#endif
+               aux_count--;
+               return -EBUSY;
+       }
+       kbd_write(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG); /* Enable the
+                                                          auxiliary port on
+                                                          controller. */
+       aux_write_dev(AUX_ENABLE_DEV); /* Enable aux device */
+       kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */
+
+       return 0;
+}
+
+/*
+ * Put bytes from input queue to buffer.
+ */
+
+static ssize_t read_aux(struct file * file, char * buffer,
+                       size_t count, loff_t *ppos)
+{
+       struct wait_queue wait = { current, NULL };
+       ssize_t i = count;
+       unsigned char c;
+
+       if (queue_empty()) {
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               add_wait_queue(&queue->proc_list, &wait);
+repeat:
+               current->state = TASK_INTERRUPTIBLE;
+               if (queue_empty() && !signal_pending(current)) {
+                       schedule();
+                       goto repeat;
+               }
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&queue->proc_list, &wait);
+       }
+       while (i > 0 && !queue_empty()) {
+               c = get_from_queue();
+               put_user(c, buffer++);
+               i--;
+       }
+       if (count-i) {
+               file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+               return count-i;
+       }
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+       return 0;
+}
+
+/*
+ * Write to the aux device.
+ */
+
+static ssize_t write_aux(struct file * file, const char * buffer,
+                        size_t count, loff_t *ppos)
+{
+       ssize_t retval = 0;
+
+       if (count) {
+               ssize_t written = 0;
+
+               if (count > 32)
+                       count = 32; /* Limit to 32 bytes. */
+               do {
+                       char c;
+                       get_user(c, buffer++);
+                       aux_write_dev(c);
+                       written++;
+               } while (--count);
+               retval = -EIO;
+               if (written) {
+                       retval = written;
+                       file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+               }
+       }
+
+       return retval;
+}
+
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+       poll_wait(file, &queue->proc_list, wait);
+       if (!queue_empty())
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+struct file_operations psaux_fops = {
+       NULL,           /* seek */
+       read_aux,
+       write_aux,
+       NULL,           /* readdir */
+       aux_poll,
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       open_aux,
+       NULL,           /* flush */
+       release_aux,
+       NULL,
+       fasync_aux,
+};
+
+/*
+ * Initialize driver.
+ */
+static struct miscdevice psaux_mouse = {
+       PSMOUSE_MINOR, "psaux", &psaux_fops
+};
+
+static int __init psaux_init(void)
+{
+       if (aux_device_present != 0xaa)
+               return -EIO;
+
+       printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
+       misc_register(&psaux_mouse);
+       queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+       memset(queue, 0, sizeof(*queue));
+       queue->head = queue->tail = 0;
+       queue->proc_list = NULL;
+
+#ifdef INITIALIZE_MOUSE
+       kbd_write(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG); /* Enable Aux. */
+       aux_write_dev(AUX_SET_SAMPLE);
+       aux_write_dev(100);                     /* 100 samples/sec */
+       aux_write_dev(AUX_SET_RES);
+       aux_write_dev(3);                       /* 8 counts per mm */
+       aux_write_dev(AUX_SET_SCALE21);         /* 2:1 scaling */
+#endif /* INITIALIZE_MOUSE */
+       kbd_write(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable aux device. */
+       kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
+
+       return 0;
+}
+
+#endif /* CONFIG_PSMOUSE */
index 0a6df026cec8e83fe36965c0f6c714c18cbbfb54..2e1b100f2437e1c8b39c8c1df31290917e4e8adb 100644 (file)
@@ -14,6 +14,9 @@
 #define KBD_REPORT_UNKN                        /* Report unknown scan codes */
 #define KBD_REPORT_TIMEOUTS            /* Report keyboard timeouts */
 #undef KBD_IS_FOCUS_9000               /* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE                        /* Define if your PS/2 mouse needs initialization. */
+
+
 
 #define KBD_INIT_TIMEOUT 1000          /* Timeout in ms for initializing the keyboard */
 #define KBC_TIMEOUT 250                        /* Timeout in ms for sending to keyboard controller */
@@ -109,3 +112,13 @@ extern unsigned char aux_device_present;
 #define AUX_ENABLE_DEV         0xF4    /* Enable aux device */
 #define AUX_DISABLE_DEV                0xF5    /* Disable aux device */
 #define AUX_RESET              0xFF    /* Reset aux device */
+
+#define AUX_BUF_SIZE           2048
+
+struct aux_queue {
+       unsigned long head;
+       unsigned long tail;
+       struct wait_queue *proc_list;
+       struct fasync_struct *fasync;
+       unsigned char buf[AUX_BUF_SIZE];
+};
diff --git a/drivers/char/psaux.c b/drivers/char/psaux.c
deleted file mode 100644 (file)
index 236ea23..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * linux/drivers/char/psaux.c
- *
- * Driver for PS/2 type mouse by Johan Myreen.
- *
- * Supports pointing devices attached to a PS/2 type
- * Keyboard and Auxiliary Device Controller.
- *
- * Corrections in device setup for some laptop mice & trackballs.
- * 02Feb93  (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
- *
- * Changed to prevent keyboard lockups on AST Power Exec.
- * 28Jul93  Brad Bosch - brad@lachman.com
- *
- * Added support for SIGIO. 28Jul95 jem@pandora.pp.fi
- *
- * Rearranged SIGIO support to use code from tty_io.  9Sept95 ctm@ardi.com
- *
- * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
- *
- * Fixed keyboard lockups at open time
- * 3-Jul-96, 22-Aug-96 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * Cleanup by Martin Mares, 01-Jun-97 (now uses the new PC kbd include)
- *
- * Renamed misc. name to "psaux",more in keeping with Documentation/devices.txt
- * 13-Jan-1998, Richard Gooch <rgooch@atnf.csiro.au>
- */
-
-/*
- * This really should be part of the pc_kbd driver - they share the same
- * controller, and right now we have ridiculous synchronization problems.
- * Some of the SMP bootup problems may be due to not getting synchronization
- * right.
- *
- * I moved the C&T mouse driver to a file of its own, hopefully that will
- * make it easier to eventually fix this all.
- *
- *             Linus
- */
-
-/* Uncomment the following line if your mouse needs initialization. */
-
-/* #define INITIALIZE_DEVICE */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/malloc.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/semaphore.h>
-
-#include <linux/config.h>
-
-#include "pc_keyb.h"
-
-/*
- *     Generic declarations for both PS2 and 82C710
- */
-
-#define PSMOUSE_MINOR      1                   /* Minor device # for this mouse */
-#define AUX_BUF_SIZE   2048
-
-struct aux_queue {
-       unsigned long head;
-       unsigned long tail;
-       struct wait_queue *proc_list;
-       struct fasync_struct *fasync;
-       unsigned char buf[AUX_BUF_SIZE];
-};
-
-static struct aux_queue *queue;
-static int aux_count = 0;
-
-static unsigned int get_from_queue(void)
-{
-       unsigned int result;
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-       result = queue->buf[queue->tail];
-       queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
-       restore_flags(flags);
-       return result;
-}
-
-
-static inline int queue_empty(void)
-{
-       return queue->head == queue->tail;
-}
-
-static int fasync_aux(int fd, struct file *filp, int on)
-{
-       int retval;
-
-       retval = fasync_helper(fd, filp, on, &queue->fasync);
-       if (retval < 0)
-               return retval;
-       return 0;
-}
-
-/*
- *     PS/2 Aux Device
- */
-
-#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)
-#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
-
-#define MAX_RETRIES    60              /* some aux operations take long time*/
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-# define AUX_IRQ       9               /* Jensen is odd indeed */
-#else
-# define AUX_IRQ       12
-#endif
-
-/*
- *     Status polling
- */
-
-static int poll_aux_status(void)
-{
-       int retries=0;
-
-       while ((inb(KBD_STATUS_REG) & (KBD_STAT_IBF | KBD_STAT_OBF)) && retries < MAX_RETRIES) {
-               if ((inb_p(KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
-                       inb_p(KBD_DATA_REG);
-               current->state = TASK_INTERRUPTIBLE;
-               current->timeout = jiffies + (5*HZ + 99) / 100;
-               schedule();
-               retries++;
-       }
-       return (retries < MAX_RETRIES);
-}
-
-/*
- * Write to aux device
- */
-
-static void aux_write_dev(int val)
-{
-       poll_aux_status();
-       outb_p(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);         /* Write magic cookie */
-       poll_aux_status();
-       outb_p(val, KBD_DATA_REG);                          /* Write data */
-}
-
-/*
- * Write to device & handle returned ack
- */
-
-#ifdef INITIALIZE_DEVICE
-__initfunc(static int aux_write_ack(int val))
-{
-       aux_write_dev(val);
-       poll_aux_status();
-
-       if ((inb(KBD_STATUS_REG) & AUX_STAT_OBF) == AUX_STAT_OBF)
-       {
-               return (inb(KBD_DATA_REG));
-       }
-       return 0;
-}
-#endif /* INITIALIZE_DEVICE */
-
-/*
- * Write aux device command
- */
-
-static void aux_write_cmd(int val)
-{
-       poll_aux_status();
-       outb_p(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG);
-       poll_aux_status();
-       outb_p(val, KBD_DATA_REG);
-}
-
-/*
- * AUX handler critical section start and end.
- * 
- * Only one process can be in the critical section and all keyboard sends are
- * deferred as long as we're inside. This is necessary as we may sleep when
- * waiting for the keyboard controller and other processes / BH's can
- * preempt us. Please note that the input buffer must be flushed when
- * aux_end_atomic() is called and the interrupt is no longer enabled as not
- * doing so might cause the keyboard driver to ignore all incoming keystrokes.
- */
-
-static struct semaphore aux_sema4 = MUTEX;
-
-static inline void aux_start_atomic(void)
-{
-       down(&aux_sema4);
-       disable_bh(KEYBOARD_BH);
-}
-
-static inline void aux_end_atomic(void)
-{
-       enable_bh(KEYBOARD_BH);
-       up(&aux_sema4);
-}
-
-/*
- * Interrupt from the auxiliary device: a character
- * is waiting in the keyboard/aux controller.
- */
-
-static void aux_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
-{
-       int head = queue->head;
-       int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
-
-       if ((inb(KBD_STATUS_REG) & AUX_STAT_OBF) != AUX_STAT_OBF)
-               return;
-
-       add_mouse_randomness(queue->buf[head] = inb(KBD_DATA_REG));
-       if (head != maxhead) {
-               head++;
-               head &= AUX_BUF_SIZE-1;
-       }
-       queue->head = head;
-       if (queue->fasync)
-               kill_fasync(queue->fasync, SIGIO);
-       wake_up_interruptible(&queue->proc_list);
-}
-
-static int release_aux(struct inode * inode, struct file * file)
-{
-       fasync_aux(-1, file, 0);
-       if (--aux_count)
-               return 0;
-#ifdef CONFIG_VT
-       pckbd_read_mask = KBD_STAT_OBF;
-#endif
-       aux_start_atomic();
-       aux_write_cmd(AUX_INTS_OFF);                        /* Disable controller ints */
-       poll_aux_status();
-       outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG);       /* Disable Aux device */
-       poll_aux_status();
-       aux_end_atomic();
-#ifdef CONFIG_MCA
-       free_irq(AUX_IRQ, inode);
-#else
-       free_irq(AUX_IRQ, NULL);
-#endif
-       MOD_DEC_USE_COUNT;
-       return 0;
-}
-
-/*
- * Install interrupt handler.
- * Enable auxiliary device.
- */
-
-static int open_aux(struct inode * inode, struct file * file)
-{
-       aux_start_atomic();
-       if (aux_count++) {
-               aux_end_atomic();
-               return 0;
-       }
-       if (!poll_aux_status()) {               /* FIXME: Race condition */
-               aux_count--;
-               aux_end_atomic();
-               return -EBUSY;
-       }
-       queue->head = queue->tail = 0;          /* Flush input queue */
-#ifdef CONFIG_MCA
-       if (request_irq(AUX_IRQ, aux_interrupt, MCA_bus ? SA_SHIRQ : 0, "PS/2 Mouse", inode)) {
-#else
-       if (request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL)) {
-#endif
-               aux_count--;
-               aux_end_atomic();
-               return -EBUSY;
-       }
-       MOD_INC_USE_COUNT;
-       poll_aux_status();
-       outb_p(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG);        /* Enable Aux */
-       aux_write_dev(AUX_ENABLE_DEV);                      /* Enable aux device */
-       aux_write_cmd(AUX_INTS_ON);                         /* Enable controller ints */
-       poll_aux_status();
-       aux_end_atomic();
-
-#ifdef CONFIG_VT
-       pckbd_read_mask = AUX_STAT_OBF;
-#endif
-
-       return 0;
-}
-
-/*
- * Write to the aux device.
- */
-
-static ssize_t write_aux(struct file * file, const char * buffer,
-                        size_t count, loff_t *ppos)
-{
-       ssize_t retval = 0;
-
-       if (count) {
-               ssize_t written = 0;
-
-               aux_start_atomic();
-               do {
-                       char c;
-                       if (!poll_aux_status())
-                               break;
-                       outb_p(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
-                       if (!poll_aux_status())
-                               break;
-                       get_user(c, buffer++);
-                       outb_p(c, KBD_DATA_REG);
-                       written++;
-               } while (--count);
-               aux_end_atomic();
-               retval = -EIO;
-               if (written) {
-                       retval = written;
-                       file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
-               }
-       }
-
-       return retval;
-}
-
-/*
- * Put bytes from input queue to buffer.
- */
-
-static ssize_t read_aux(struct file * file, char * buffer,
-                       size_t count, loff_t *ppos)
-{
-       struct wait_queue wait = { current, NULL };
-       ssize_t i = count;
-       unsigned char c;
-
-       if (queue_empty()) {
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               add_wait_queue(&queue->proc_list, &wait);
-repeat:
-               current->state = TASK_INTERRUPTIBLE;
-               if (queue_empty() && !signal_pending(current)) {
-                       schedule();
-                       goto repeat;
-               }
-               current->state = TASK_RUNNING;
-               remove_wait_queue(&queue->proc_list, &wait);
-       }
-       while (i > 0 && !queue_empty()) {
-               c = get_from_queue();
-               put_user(c, buffer++);
-               i--;
-       }
-       if (count-i) {
-               file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-               return count-i;
-       }
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-       return 0;
-}
-
-static unsigned int aux_poll(struct file *file, poll_table * wait)
-{
-       poll_wait(file, &queue->proc_list, wait);
-       if (!queue_empty())
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-struct file_operations psaux_fops = {
-       NULL,           /* seek */
-       read_aux,
-       write_aux,
-       NULL,           /* readdir */
-       aux_poll,
-       NULL,           /* ioctl */
-       NULL,           /* mmap */
-       open_aux,
-       NULL,           /* flush */
-       release_aux,
-       NULL,
-       fasync_aux,
-};
-
-/*
- * Initialize driver.
- */
-static struct miscdevice psaux_mouse = {
-       PSMOUSE_MINOR, "psaux", &psaux_fops
-};
-
-__initfunc(int psaux_init(void))
-{
-       if (aux_device_present != 0xaa)
-               return -EIO;
-
-       printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
-       misc_register(&psaux_mouse);
-       queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-       memset(queue, 0, sizeof(*queue));
-       queue->head = queue->tail = 0;
-       queue->proc_list = NULL;
-
-       aux_start_atomic();
-#ifdef INITIALIZE_DEVICE
-       outb_p(KBD_CCMD_MOUSE_ENABLE, KBD_CNTL_REG); /* Enable Aux */
-       aux_write_ack(AUX_SET_SAMPLE);
-       aux_write_ack(100);                     /* 100 samples/sec */
-       aux_write_ack(AUX_SET_RES);
-       aux_write_ack(3);                       /* 8 counts per mm */
-       aux_write_ack(AUX_SET_SCALE21);         /* 2:1 scaling */
-       poll_aux_status();
-#endif /* INITIALIZE_DEVICE */
-       outb_p(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG); /* Disable Aux device */
-       poll_aux_status();
-       outb_p(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG);    /* Disable controller interrupts */
-       poll_aux_status();
-       outb_p(AUX_INTS_OFF, KBD_DATA_REG);
-       poll_aux_status();
-       aux_end_atomic();
-
-       return 0;
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-       return psaux_init();
-}
-
-void cleanup_module(void)
-{
-       misc_deregister(&psaux_mouse);
-       kfree(queue);
-}
-#endif
index 491ffe90ddc34c2f6e165e2ef1349e470dd9c932..32f43a6d1a3d0a5bde0d2e86dc55cb70d2cb95ae 100644 (file)
@@ -8,15 +8,15 @@
  * Corrections in device setup for some laptop mice & trackballs.
  * 02Feb93  (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
  *
- * Modified by Johan Myreen (jem@pandora.pp.fi) 04Aug93
+ * Modified by Johan Myreen (jem@iki.fi) 04Aug93
  *   to include support for QuickPort mouse.
  *
  * Changed references to "QuickPort" with "82C710" since "QuickPort"
  * is not what this driver is all about -- QuickPort is just a
  * connector type, and this driver is for the mouse port on the Chips
- * & Technologies 82C710 interface chip. 15Nov93 jem@pandora.pp.fi
+ * & Technologies 82C710 interface chip. 15Nov93 jem@iki.fi
  *
- * Added support for SIGIO. 28Jul95 jem@pandora.pp.fi
+ * Added support for SIGIO. 28Jul95 jem@iki.fi
  *
  * Rearranged SIGIO support to use code from tty_io.  9Sept95 ctm@ardi.com
  *
index fb474ea58bfd8a25aaf3331e743e5ff14ca56b33..5a4ad1c6f5c414cfc510b63f23ad738e68f084c6 100644 (file)
@@ -168,7 +168,14 @@ static int is_local_disk(kdev_t dev)           /* Guess if the device is a local hard
        case IDE1_MAJOR:
        case IDE2_MAJOR:
        case IDE3_MAJOR:
-       case SCSI_DISK_MAJOR:
+       case SCSI_DISK0_MAJOR:
+       case SCSI_DISK1_MAJOR:
+       case SCSI_DISK2_MAJOR:
+       case SCSI_DISK3_MAJOR:
+       case SCSI_DISK4_MAJOR:
+       case SCSI_DISK5_MAJOR:
+       case SCSI_DISK6_MAJOR:
+       case SCSI_DISK7_MAJOR:
                return 1;
        default:
                return 0;
index 56e2099bae914f14a41d04236fa2d2d3d700410d..35deb815bb4d5a4ad5fd3a8ef9c750e2baeb79d9 100644 (file)
@@ -1360,6 +1360,7 @@ static int do_ioctl_cmd(int cmd)
  */ 
 static inline void dma_transfer(void)
 {
+       unsigned long flags;
 
        if (QIC02_TAPE_IFC == WANGTEK) /* or EVEREX */
                outb_p(WT_CTL_ONLINE, QIC02_CTL_PORT);  /* back to normal */
@@ -1369,6 +1370,7 @@ static inline void dma_transfer(void)
                outb_p(ctlbits, QIC02_CTL_PORT);
 
 
+       flags=claim_dma_lock();
        clear_dma_ff(QIC02_TAPE_DMA);
        set_dma_mode(QIC02_TAPE_DMA, dma_mode);
        set_dma_addr(QIC02_TAPE_DMA, buffaddr+dma_bytes_done);  /* full address */
@@ -1393,6 +1395,9 @@ static inline void dma_transfer(void)
 
        /* start computer DMA controller */
        enable_dma(QIC02_TAPE_DMA);
+
+       release_dma_lock(flags);
+
        /* block transfer should start now, jumping to the 
         * interrupt routine when done or an exception was detected.
         */
@@ -1410,6 +1415,7 @@ static int start_dma(short mode, unsigned long bytes_todo)
 /* assume 'bytes_todo'>0 */
 {
        int stat;
+       unsigned long flags;
        
        tpqputs(TPQD_DEBUG, "start_dma() enter");
        TPQDEB({printk(TPQIC02_NAME ": doing_read==%d, doing_write==%d\n", doing_read, doing_write);})
@@ -1506,9 +1512,10 @@ static int start_dma(short mode, unsigned long bytes_todo)
 
        /* initiate first data block read from/write to the tape controller */
 
+       save_flags(flags);
        cli();
        dma_transfer();
-       sti();
+       restore_flags(flags);
 
        TPQPUTS("start_dma() end");
        return TE_OK;
@@ -1524,13 +1531,18 @@ static int start_dma(short mode, unsigned long bytes_todo)
 static void end_dma(unsigned long * bytes_done)
 {
        int stat = TE_OK;
+       unsigned long flags;
 
        TIMEROFF;
 
        TPQPUTS("end_dma() enter");
 
+       flags=claim_dma_lock();
+       
        disable_dma(QIC02_TAPE_DMA);
        clear_dma_ff(QIC02_TAPE_DMA);
+       
+       release_dma_lock(flags);
 
        if (QIC02_TAPE_IFC == WANGTEK) /* or EVEREX */
                outb_p(WT_CTL_ONLINE, QIC02_CTL_PORT);  /* back to normal */
@@ -1633,6 +1645,7 @@ static void qic02_tape_times_out(void)
 static void qic02_tape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        int stat, r, i;
+       unsigned long flags;
 
        TIMEROFF;
 
@@ -1682,10 +1695,14 @@ static void qic02_tape_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                r = 1;
                        }
 
+               flags=claim_dma_lock();
+               
                if ( (i = get_dma_residue(QIC02_TAPE_DMA)) != 0 ) {
                        printk(TPQIC02_NAME ": dma_residue == %x !!!\n", i);
                        r = 1;  /* big trouble, but can't do much about it... */
                }
+               
+               release_dma_lock(flags);
 
                if (r) 
                        return;
index 2a2f2deea1fbf11a6729aa222c966590b0b55315..47d7c1f24e02e674dba20ede1f354f410d362fab 100644 (file)
@@ -1132,7 +1132,6 @@ static void release_dev(struct file * filp)
         * both sides, and we've completed the last operation that could 
         * block, so it's safe to proceed with closing.
         */
-
        if (pty_master) {
                if (--o_tty->count < 0) {
                        printk("release_dev: bad pty slave count (%d) for %s\n",
@@ -1146,6 +1145,16 @@ static void release_dev(struct file * filp)
                tty->count = 0;
        }
 
+       /*
+        * We've decremented tty->count, so we should zero out
+        * filp->private_data, to break the link between the tty and
+        * the file descriptor.  Otherwise if close_fp() blocks before
+        * the the file descriptor is removed from the inuse_filp
+        * list, check_tty_count() could observe a discrepancy and
+        * printk a warning message to the user.
+        */
+       filp->private_data = 0;
+
        /*
         * Perform some housekeeping before deciding whether to return.
         *
@@ -1180,7 +1189,6 @@ static void release_dev(struct file * filp)
        /* check whether both sides are closing ... */
        if (!tty_closing || (o_tty && !o_tty_closing))
                return;
-       filp->private_data = 0;
        
 #ifdef TTY_DEBUG_HANGUP
        printk("freeing tty structure...");
@@ -1293,7 +1301,6 @@ retry_open:
                return retval;
 
 #ifdef CONFIG_UNIX98_PTYS
-       /* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */
 init_dev_done:
 #endif
        filp->private_data = tty;
@@ -2084,6 +2091,7 @@ __initfunc(int tty_init(void))
        if (tty_register_driver(&dev_syscons_driver))
                panic("Couldn't register /dev/console driver\n");
 
+#ifdef CONFIG_UNIX98_PTYS
        dev_ptmx_driver = dev_tty_driver;
        dev_ptmx_driver.driver_name = "/dev/ptmx";
        dev_ptmx_driver.name = dev_ptmx_driver.driver_name + 5;
@@ -2094,7 +2102,8 @@ __initfunc(int tty_init(void))
 
        if (tty_register_driver(&dev_ptmx_driver))
                panic("Couldn't register /dev/ptmx driver\n");
-
+#endif
+       
 #ifdef CONFIG_VT
        dev_console_driver = dev_tty_driver;
        dev_console_driver.driver_name = "/dev/tty0";
index 6825c22ac778cf8248de32b786878b0b24a318e4..37c1e4e9ae856aa79e448ff17804fc8ad3aad383 100644 (file)
 /* ARC can't read from the data latch, so we must use a soft copy. */
 static unsigned char data_copy;
 
+static void arc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
 static void arc_write_data(struct parport *p, unsigned char data)
 {
        data_copy = data;
@@ -110,7 +115,7 @@ static struct parport_operations parport_arc_ops =
 
        arc_enable_irq,
        arc_disable_irq,
-       arc_examine_irq,
+       arc_interrupt,
 
        arc_inc_use_count,
        arc_dec_use_count,
index a39177ba04959d6f274d02d555f714d4a0d34caf..b32cac13b3278a76e58ddd2d5103c670409dcefb 100644 (file)
 #define CONFIGB                0x401
 #define ECONTROL       0x402
 
-static void
-parport_ax_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+static void parport_ax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       /* NULL function - Does nothing */
+       parport_generic_irq(irq, (struct parport *) dev_id, regs);
 }
 
 void
@@ -206,7 +205,7 @@ parport_ax_release_resources(struct parport *p)
 {
        if (p->irq != PARPORT_IRQ_NONE) {
                parport_ax_disable_irq(p);
-               free_irq(p->irq, NULL);
+               free_irq(p->irq, p);
        }
        release_region(p->base, p->size);
        if (p->modes & PARPORT_MODE_PCECR)
@@ -219,11 +218,15 @@ int
 parport_ax_claim_resources(struct parport *p)
 {
        /* FIXME check that resources are free */
-       if (p->irq != PARPORT_IRQ_NONE) {
-               request_irq(p->irq, parport_ax_null_intr_func,
-                           0, p->name, NULL);
-               parport_ax_enable_irq(p);
-       }
+       int err;
+
+       if (p->irq != PARPORT_IRQ_NONE)
+               if ((err = request_irq(p->irq, parport_ax_interrupt,
+                                      0, p->name, p)) != 0)
+                       return err;
+               else
+                       parport_ax_enable_irq(p);
+
        request_region(p->base, p->size, p->name);
        if (p->modes & PARPORT_MODE_PCECR)
                request_region(p->base+0x400, 3, p->name);
@@ -281,12 +284,6 @@ parport_ax_ecp_write_block(struct parport *p, void *buf, size_t length,
        return 0; /* FIXME */
 }
 
-int
-parport_ax_examine_irq(struct parport *p)
-{
-       return 0; /* FIXME */
-}
-
 void
 parport_ax_inc_use_count(void)
 {
@@ -355,7 +352,7 @@ static struct parport_operations parport_ax_ops =
 
        parport_ax_enable_irq,
        parport_ax_disable_irq,
-       parport_ax_examine_irq,
+       parport_ax_interrupt,
 
        parport_ax_inc_use_count,
        parport_ax_dec_use_count,
index db3c3f7ab7f7b0d53dae58715085fc58df1b6740..7654c7cb0a806794fc80f7bd7fc1aeb63e8d1d36 100644 (file)
@@ -1,4 +1,4 @@
-/* Low-level parallel-port routines for PC-style hardware.
+/* Low-level parallel-port routines for 8255-based PC-style hardware.
  * 
  * Authors: Phil Blundell <Philip.Blundell@pobox.com>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  * accomodate this.
  */
 
-#include <linux/stddef.h>
-#include <linux/tasks.h>
-
-#include <asm/ptrace.h>
-#include <asm/io.h>
-
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -46,6 +41,8 @@
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 
+#include <asm/io.h>
+
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
 
@@ -53,9 +50,9 @@
    than PARPORT_MAX (in <linux/parport.h>).  */
 #define PARPORT_PC_MAX_PORTS  8
 
-static void parport_pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       /* Null function - does nothing */
+       parport_generic_irq(irq, (struct parport *) dev_id, regs);
 }
 
 void parport_pc_write_epp(struct parport *p, unsigned char d)
@@ -173,7 +170,7 @@ void parport_pc_enable_irq(struct parport *p)
 void parport_pc_release_resources(struct parport *p)
 {
        if (p->irq != PARPORT_IRQ_NONE)
-               free_irq(p->irq, NULL);
+               free_irq(p->irq, p);
        release_region(p->base, p->size);
        if (p->modes & PARPORT_MODE_PCECR)
                release_region(p->base+0x400, 3);
@@ -183,7 +180,9 @@ int parport_pc_claim_resources(struct parport *p)
 {
        int err;
        if (p->irq != PARPORT_IRQ_NONE)
-               if ((err = request_irq(p->irq, parport_pc_null_intr_func, 0, p->name, NULL)) != 0) return err;
+               if ((err = request_irq(p->irq, parport_pc_interrupt,
+                                      0, p->name, p)) != 0)
+                       return err;
        request_region(p->base, p->size, p->name);
        if (p->modes & PARPORT_MODE_PCECR)
                request_region(p->base+0x400, 3, p->name);
@@ -242,11 +241,6 @@ int parport_pc_ecp_write_block(struct parport *p, void *buf, size_t length, void
        return -ENOSYS; /* FIXME */
 }
 
-int parport_pc_examine_irq(struct parport *p)
-{
-       return 0; /* FIXME */
-}
-
 void parport_pc_inc_use_count(void)
 {
 #ifdef MODULE
@@ -313,7 +307,7 @@ struct parport_operations parport_pc_ops =
 
        parport_pc_enable_irq,
        parport_pc_disable_irq,
-       parport_pc_examine_irq,
+       parport_pc_interrupt,
 
        parport_pc_inc_use_count,
        parport_pc_dec_use_count,
index b7d35eea46e28e7903d77c3758a0d4f8f344603b..758015bd1f1587a89639c8dc1d6205fe47de9bbd 100644 (file)
 
 struct proc_dir_entry *base = NULL;
 
-extern void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
-
 static int irq_write_proc(struct file *file, const char *buffer,
-                                         unsigned long count, void *data)
+                         unsigned long count, void *data)
 {
        int retval = -EINVAL;
        int newirq = PARPORT_IRQ_NONE;
        struct parport *pp = (struct parport *)data;
        int oldirq = pp->irq;
-       unsigned long flags;
 
 /*
  * We can have these valid cases:
@@ -70,31 +67,45 @@ static int irq_write_proc(struct file *file, const char *buffer,
        if (oldirq == newirq)
                goto out;
 
-       spin_lock_irqsave(&pp->lock, flags);
        if (pp->flags & PARPORT_FLAG_COMA)
                goto out_ok;
 
        retval = -EBUSY;
+
+       /*
+        * Here we don' t need the irq version of spinlocks because
+        * the parport_lowlevel irq handler must not change the cad,
+        * and so has no one reason to write_lock() the cad_lock spinlock.
+        *                                              -arca
+        */
+       read_lock(&pp->cad_lock);
+
        if (pp->cad)
-               goto out_unlock;
+       {
+               read_unlock(&pp->cad_lock);
+               return retval;
+       }
 
        if (newirq != PARPORT_IRQ_NONE) { 
-               retval = request_irq(newirq, parport_null_intr_func,
-                                    SA_INTERRUPT, pp->name, NULL);
+               retval = request_irq(newirq, pp->ops->interrupt,
+                                    0, pp->name, pp);
                if (retval)
-                       goto out_unlock;
-               else retval = count;
+               {
+                       read_unlock(&pp->cad_lock);
+                       return retval;
+               }
        }
 
        if (oldirq != PARPORT_IRQ_NONE)
-               free_irq(oldirq, NULL);
+               free_irq(oldirq, pp);
+
+       retval = count;
+
+       read_unlock(&pp->cad_lock);
 
 out_ok:
        pp->irq = newirq;
 
-out_unlock:
-       spin_unlock_irqrestore (&pp->lock, flags);
-
 out:
        return retval;
 }
index 59788c42578e36eebbf3719cfa0fda93d32c99d9..01123bc7bcb5827779c15d10bfd2f843b0ce4537 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 
 #include <asm/spinlock.h>
+#include <asm/irq.h>
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
@@ -55,19 +56,12 @@ struct parport *parport_enumerate(void)
        return portlist;
 }
 
-void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
-{
-       /* Null function - does nothing.  IRQs are pointed here whenever
-          there is no real handler for them.  */
-}
-
 struct parport *parport_register_port(unsigned long base, int irq, int dma,
                                      struct parport_operations *ops)
 {
        struct parport *tmp;
        int portnum;
        char *name;
-       unsigned long flags;
 
        /* Check for a previously registered port.
           NOTE: we will ignore irq and dma if we find a previously
@@ -111,7 +105,9 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        tmp->ops = ops;
        tmp->number = portnum;
        memset (&tmp->probe_info, 0, sizeof (struct parport_device_info));
-       spin_lock_init (&tmp->lock);
+       spin_lock_init(&tmp->cad_lock);
+       spin_lock_init(&tmp->waitlist_lock);
+       spin_lock_init(&tmp->pardevice_lock);
 
        name = kmalloc(15, GFP_KERNEL);
        if (!name) {
@@ -122,14 +118,19 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        sprintf(name, "parport%d", portnum);
        tmp->name = name;
 
-       /* Chain the entry to our list. */
-       spin_lock_irqsave (&parportlist_lock, flags);
+       /*
+        * Chain the entry to our list.
+        *
+        * This function must not run from an irq handler so we don' t need
+        * to clear irq on the local CPU. -arca
+        */
+       spin_lock(&parportlist_lock);
        if (portlist_tail)
                portlist_tail->next = tmp;
        portlist_tail = tmp;
        if (!portlist)
                portlist = tmp;
-       spin_unlock_irqrestore (&parportlist_lock, flags);
+       spin_unlock(&parportlist_lock);
 
        tmp->probe_info.class = PARPORT_CLASS_LEGACY;  /* assume the worst */
        tmp->waithead = tmp->waittail = NULL;
@@ -140,8 +141,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
 void parport_unregister_port(struct parport *port)
 {
        struct parport *p;
-       unsigned long flags;
-       spin_lock_irqsave (&parportlist_lock, flags);
+
+       spin_lock(&parportlist_lock);
        if (portlist == port) {
                if ((portlist = port->next) == NULL)
                        portlist_tail = NULL;
@@ -155,7 +156,7 @@ void parport_unregister_port(struct parport *port)
                else printk (KERN_WARNING
                             "%s not found in port list!\n", port->name);
        }
-       spin_unlock_irqrestore (&parportlist_lock, flags);
+       spin_unlock(&parportlist_lock);
        if (port->probe_info.class_name)
                kfree (port->probe_info.class_name);
        if (port->probe_info.mfr)
@@ -195,7 +196,13 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
                          int flags, void *handle)
 {
        struct pardevice *tmp;
-       unsigned long flgs;
+
+       if (port->flags & PARPORT_FLAG_EXCL) {
+               /* An exclusive device is registered. */
+               printk (KERN_DEBUG "%s: no more devices allowed\n",
+                       port->name);
+               return NULL;
+       }
 
        if (flags & PARPORT_DEV_LURK) {
                if (!pf || !kf) {
@@ -242,12 +249,30 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
 
        /* Chain this onto the list */
        tmp->prev = NULL;
-       spin_lock_irqsave (&port->lock, flgs);
+       /*
+        * This function must not run from an irq handler so we don' t need
+        * to clear irq on the local CPU. -arca
+        */
+       spin_lock(&port->pardevice_lock);
+
+       if (flags & PARPORT_DEV_EXCL) {
+               if (port->devices) {
+                       spin_unlock (&port->pardevice_lock);
+                       kfree (tmp->state);
+                       kfree (tmp);
+                       printk (KERN_DEBUG
+                               "%s: cannot grant exclusive access for "
+                               "device %s\n", port->name, name);
+                       return NULL;
+               }
+               port->flags |= PARPORT_FLAG_EXCL;
+       }
+
        tmp->next = port->devices;
        if (port->devices)
                port->devices->prev = tmp;
        port->devices = tmp;
-       spin_unlock_irqrestore (&port->lock, flgs);
+       spin_unlock(&port->pardevice_lock);
 
        inc_parport_count();
        port->ops->inc_use_count();
@@ -262,7 +287,6 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
 void parport_unregister_device(struct pardevice *dev)
 {
        struct parport *port;
-       unsigned long flags;
 
 #ifdef PARPORT_PARANOID
        if (dev == NULL) {
@@ -279,14 +303,18 @@ void parport_unregister_device(struct pardevice *dev)
                return;
        }
 
-       spin_lock_irqsave (&port->lock, flags);
+       spin_lock(&port->pardevice_lock);
        if (dev->next)
                dev->next->prev = dev->prev;
        if (dev->prev)
                dev->prev->next = dev->next;
        else
                port->devices = dev->next;
-       spin_unlock_irqrestore (&port->lock, flags);
+
+       if (dev->flags & PARPORT_DEV_EXCL)
+               port->flags &= ~PARPORT_FLAG_EXCL;
+
+       spin_unlock(&port->pardevice_lock);
 
        kfree(dev->state);
        kfree(dev);
@@ -337,7 +365,7 @@ try_again:
                dev->waiting = 0;
 
                /* Take ourselves out of the wait list again.  */
-               spin_lock_irqsave (&port->lock, flags);
+               spin_lock_irqsave (&port->waitlist_lock, flags);
                if (dev->waitprev)
                        dev->waitprev->waitnext = dev->waitnext;
                else
@@ -346,28 +374,27 @@ try_again:
                        dev->waitnext->waitprev = dev->waitprev;
                else
                        port->waittail = dev->waitprev;
-               spin_unlock_irqrestore (&port->lock, flags);
+               spin_unlock_irqrestore (&port->waitlist_lock, flags);
                dev->waitprev = dev->waitnext = NULL;
        }
 
+       if (oldcad && port->irq != PARPORT_IRQ_NONE && !oldcad->irq_func)
+               /*
+                * If there was an irq pending it should hopefully happen
+                * before return from enable_irq(). -arca
+                */
+               enable_irq(port->irq);
+
+       /*
+        * Avoid running irq handlers if the pardevice doesn' t use it. -arca
+        */
+       if (port->irq != PARPORT_IRQ_NONE && !dev->irq_func)
+               disable_irq(port->irq);
+
        /* Now we do the change of devices */
-       spin_lock_irqsave(&port->lock, flags);
+       write_lock_irqsave(&port->cad_lock, flags);
        port->cad = dev;
-       spin_unlock_irqrestore(&port->lock, flags);
-
-       /* Swap the IRQ handlers. */
-       if (port->irq != PARPORT_IRQ_NONE) {
-               if (oldcad && oldcad->irq_func) {
-                       free_irq(port->irq, oldcad->private);
-                       request_irq(port->irq, parport_null_intr_func,
-                                   SA_INTERRUPT, port->name, NULL);
-               }
-               if (dev->irq_func) {
-                       free_irq(port->irq, NULL);
-                       request_irq(port->irq, dev->irq_func,
-                                   SA_INTERRUPT, dev->name, dev->private);
-               }
-       }
+       write_unlock_irqrestore(&port->cad_lock, flags);
 
        /* Restore control registers */
        port->ops->restore_state(port, dev->state);
@@ -379,10 +406,10 @@ blocked:
           interest.  This is only allowed for devices sleeping in
           parport_claim_or_block(), or those with a wakeup function.  */
        if (dev->waiting & 2 || dev->wakeup) {
-               spin_lock_irqsave (&port->lock, flags);
+               spin_lock_irqsave (&port->waitlist_lock, flags);
                if (port->cad == NULL) {
                        /* The port got released in the meantime. */
-                       spin_unlock_irqrestore (&port->lock, flags);
+                       spin_unlock_irqrestore (&port->waitlist_lock, flags);
                        goto try_again;
                }
                if (test_and_set_bit(0, &dev->waiting) == 0) {
@@ -395,7 +422,7 @@ blocked:
                        } else
                                port->waithead = port->waittail = dev;
                }
-               spin_unlock_irqrestore (&port->lock, flags);
+               spin_unlock_irqrestore (&port->waitlist_lock, flags);
        }
        return -EAGAIN;
 }
@@ -451,20 +478,20 @@ void parport_release(struct pardevice *dev)
                       "when not owner\n", port->name, dev->name);
                return;
        }
-       spin_lock_irqsave(&port->lock, flags);
+       write_lock_irqsave(&port->cad_lock, flags);
        port->cad = NULL;
-       spin_unlock_irqrestore(&port->lock, flags);
+       write_unlock_irqrestore(&port->cad_lock, flags);
+
+       /*
+        * Reenable irq and so discard the eventually pending irq while
+        * cad is NULL. -arca
+        */
+       if (port->irq != PARPORT_IRQ_NONE && !dev->irq_func)
+               enable_irq(port->irq);
 
        /* Save control registers */
        port->ops->save_state(port, dev->state);
 
-       /* Point IRQs somewhere harmless. */
-       if (port->irq != PARPORT_IRQ_NONE && dev->irq_func) {
-               free_irq(port->irq, dev->private);
-               request_irq(port->irq, parport_null_intr_func,
-                           SA_INTERRUPT, port->name, NULL);
-       }
-
        /* If anybody is waiting, find out who's been there longest and
           then wake them up. (Note: no locking required) */
        for (pd = port->waithead; pd; pd = pd->waitnext) {
index a1a822fa01f3e665d3567ba4e669adcfe62cdc56..b8e9936f82e8c1fc65a97b208c01ba2ec239f277 100644 (file)
@@ -327,13 +327,17 @@ static inline void check_3c505_dma(struct device *dev)
 {
        elp_device *adapter = dev->priv;
        if (adapter->dmaing && (jiffies > (adapter->current_dma.start_time + 10))) {
-               unsigned long flags;
+               unsigned long flags, f;
                printk("%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
                save_flags(flags);
                cli();
                adapter->dmaing = 0;
                adapter->busy = 0;
+               
+               f=claim_dma_lock();
                disable_dma(dev->dma);
+               release_dma_lock(f);
+               
                if (adapter->rx_active)
                        adapter->rx_active--;
                outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
@@ -601,6 +605,7 @@ static void receive_packet(struct device *dev, int len)
        elp_device *adapter = dev->priv;
        void *target;
        struct sk_buff *skb;
+       unsigned long flags;
 
        rlen = (len + 1) & ~1;
        skb = dev_alloc_skb(rlen + 2);
@@ -632,12 +637,14 @@ static void receive_packet(struct device *dev, int len)
 
        outb_control(adapter->hcr_val | DIR | TCEN | DMAE, dev);
 
+       flags=claim_dma_lock();
        disable_dma(dev->dma);
        clear_dma_ff(dev->dma);
        set_dma_mode(dev->dma, 0x04);   /* dma read */
        set_dma_addr(dev->dma, virt_to_bus(target));
        set_dma_count(dev->dma, rlen);
        enable_dma(dev->dma);
+       release_dma_lock(flags);
 
        if (elp_debug >= 3) {
                printk("%s: rx DMA transfer started\n", dev->name);
@@ -1019,6 +1026,7 @@ static int send_packet(struct device *dev, struct sk_buff *skb)
 {
        elp_device *adapter = dev->priv;
        unsigned long target;
+       unsigned long flags;
 
        /*
         * make sure the length is even and no shorter than 60 bytes
@@ -1060,7 +1068,8 @@ static int send_packet(struct device *dev, struct sk_buff *skb)
                target = virt_to_bus(adapter->dma_buffer);
        }
        adapter->current_dma.skb = skb;
-       cli();
+
+       flags=claim_dma_lock();
        disable_dma(dev->dma);
        clear_dma_ff(dev->dma);
        set_dma_mode(dev->dma, 0x48);   /* dma memory -> io */
@@ -1068,6 +1077,8 @@ static int send_packet(struct device *dev, struct sk_buff *skb)
        set_dma_count(dev->dma, nlen);
        outb_control(adapter->hcr_val | DMAE | TCEN, dev);
        enable_dma(dev->dma);
+       release_dma_lock(flags);
+       
        if (elp_debug >= 3)
                printk("%s: DMA transfer started\n", dev->name);
 
index 37d4df7f93f075719ba51ad91c0d7bdea522b8d7..52c2f6b95694136e34f0e1d19e4d6b68f2610b12 100644 (file)
@@ -1,13 +1,13 @@
 /* drivers/net/eepro100.c: An Intel i82557 Ethernet driver for Linux. */
 /*
    NOTICE: this version tested with kernels 1.3.72 and later only!
-       Written 1996-1997 by Donald Becker.
+       Written 1996-1998 by Donald Becker.
 
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
 
        This driver is for the Intel EtherExpress Pro 100B boards.
-       It should work with other i82557 boards (if any others exist).
+       It should work with other i82557 and i82558 boards.
        To use a built-in driver, install as drivers/net/eepro100.c.
        To use as a module, use the compile-command at the end of the file.
 
        Center of Excellence in Space Data and Information Sciences
           Code 930.5, NASA Goddard Space Flight Center, Greenbelt MD 20771
        For updates see
-       <base href="http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html">
+               http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html
+       There is also a mailing list based at
+               linux-eepro100@cesdis.gsfc.nasa.gov
 */
 
 static const char *version =
-"eepro100.c:v0.36 10/20/97 Donald Becker linux-eepro100@cesdis.gsfc.nasa.gov\n";
+"eepro100.c:v1.04 10/8/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
 
 /* A few user-configurable values that apply to all boards.
    First set are undocumented and spelled per Intel recommendations. */
@@ -33,125 +35,56 @@ static int rxdmacount = 0;
 
 /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
    Lower values use more memory, but are faster. */
-/*
- * NOTE! The value of 2000 means that this optimization never gets
- * used. Rationale: it seems to be broken when in low-memory situations,
- * apparently when alloc_skb() can return NULL the clever list of
- * copy-buffers can get buggered. 
- *
- * My personal suspicion is that the allocation failure will cause
- * us to not remove the skb from the list of available buffers, but
- * we'd already have done a "skb_push()" with the data we got, so
- * the buffer stays on the list but the available memory in it
- * shrinks until we panic.
- *
- * Donald, when you fix this you can shrink this value again.
- *
- *             Linus
- */
-static int rx_copybreak = 2000;
+static int rx_copybreak = 200;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 200;
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
+static int multicast_filter_limit = 64;
 
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
-#include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
-#include <asm/dma.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-
-/* A nominally proper method to handle version dependencies is to use
-   LINUX_VERSION_CODE in version.h, but that triggers recompiles w/'make'. */
-#define VERSION(v,p,s) (((v)<<16)+(p<<8)+s)
-#ifdef MODULE
-#if (LINUX_VERSION_CODE < VERSION(1,3,0))
-#define KERNEL_1_2
-#else /* 1.3.0 */
-#if (LINUX_VERSION_CODE >= VERSION(1,3,44))
-#define NEW_MULTICAST
-#define LINUX_1_4
-#else
-#warning "This driver is tested for 1.3.44 and later development kernels only."
-#endif /* 1.3.44 */
-#endif
-#else
-
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
 #include <linux/delay.h>
-#endif
 
-#ifdef HAVE_HEADER_CACHE
-#define LINUX_1_4
-#define NEW_MULTICAST
-#else
-#ifdef ETH_P_DDCMP                             /* Warning: Bogus!  This means IS_LINUX_1_3. */
-#define KERNEL_1_3
-#else
-#define KERNEL_1_2
-#endif
-#endif
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(congenb, "i");
+MODULE_PARM(txfifo, "i");
+MODULE_PARM(rxfifo, "i");
+MODULE_PARM(txdmacount, "i");
+MODULE_PARM(rxdmacount, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(multicast_filter_limit, "i");
 
-#endif
-/* This should be in a header file. */
-#if (LINUX_VERSION_CODE < VERSION(1,3,44))
-struct device *init_etherdev(struct device *dev, int sizeof_priv,
-                                                        unsigned long *mem_startp);
-#endif
-#if LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x)                  /* What to put in timer->expires.  */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#define virt_to_bus(addr)  ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-#else  /* 1.3.0 and later */
 #define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-#endif
 
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#include <linux/bios32.h>
-#endif
+#define dev_free_skb(skb) dev_kfree_skb(skb);
 
-/* The total I/O port extent of the board.  Nominally 0x18, but rounded up
-   for PCI allocation. */
+/* The total I/O port extent of the board.
+   The registers beyond 0x18 only exist on the i82558. */
 #define SPEEDO3_TOTAL_SIZE 0x20
 
-#ifdef HAVE_DEVLIST
-struct netdev_entry eepro100_drv =
-{"EEPro-100", eepro100_init, SPEEDO3_TOTAL_SIZE, NULL};
-#endif
-
-#ifdef SPEEDO3_DEBUG
-int speedo_debug = SPEEDO3_DEBUG;
-#else
-int speedo_debug = 3;
-#endif
+int speedo_debug = 0;
 
 /*
                                Theory of Operation
@@ -183,7 +116,7 @@ single buffer descriptor with each frame descriptor.
 Despite the extra space overhead in each receive skbuff, the driver must use
 the simplified Rx buffer mode to assure that only a single data buffer is
 associated with each RxFD. The driver implements this by reserving space
-for the Rx descriptor at the head of each Rx skbuff
+for the Rx descriptor at the head of each Rx skbuff.
 
 The Speedo-3 has receive and command unit base addresses that are added to
 almost all descriptor pointers.  The driver sets these to zero, so that all
@@ -198,10 +131,13 @@ IIIB. Transmit structure
 
 The driver must use the complex Tx command+descriptor mode in order to
 have a indirect pointer to the skbuff data section.  Each Tx command block
-(TxCB) is associated with a single, immediately appended Tx buffer descriptor
+(TxCB) is associated with two immediately appended Tx Buffer Descriptor
 (TxBD).  A fixed ring of these TxCB+TxBD pairs are kept as part of the
 speedo_private data structure for each adapter instance.
 
+The newer i82558 explicitly supports this structure, and can read the two
+TxBDs in the same PCI burst as the TxCB.
+
 This ring structure is used for all normal transmit packets, but the
 transmit packet descriptors aren't long enough for most non-Tx commands such
 as CmdConfigure.  This is complicated by the possibility that the chip has
@@ -290,26 +226,19 @@ having to sign an Intel NDA when I'm helping Intel sell their own product!
 #define PKT_BUF_SZ             1536
 
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  ((400*HZ)/1000)
+#define TX_TIMEOUT  ((800*HZ)/1000)
 
 /* How to wait for the command unit to accept a command.
    Typically this takes 0 ticks. */
-static inline void wait_for_cmd_done(int cmd_ioaddr)
+static inline void wait_for_cmd_done(long cmd_ioaddr)
 {
-  short wait = 100;
-  do   ;
-  while(inb(cmd_ioaddr) && --wait >= 0);
+       int wait = 100;
+       do   ;
+       while(inb(cmd_ioaddr) && --wait >= 0);
 }
 
 /* Operational parameter that usually are not changed. */
 
-#ifndef PCI_VENDOR_ID_INTEL            /* Now defined in linux/pci.h */
-#define PCI_VENDOR_ID_INTEL            0x8086 /* Hmmmm, how did they pick that? */
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82557
-#define PCI_DEVICE_ID_INTEL_82557      0x1229
-#endif
-
 /* The rest of these values should never change. */
 
 /* Offsets to the various registers.
@@ -364,17 +293,24 @@ struct RxFD {                                     /* Receive frame descriptor. */
        u16 size;
 };
 
-/* Elements of the RxFD.status word. */
-#define RX_COMPLETE 0x8000
+/* Selected elements of the Tx/RxFD.status word. */
+enum RxFD_bits {
+       RxComplete=0x8000, RxOK=0x2000,
+       RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
+       RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
+       StatusComplete=0x8000,
+};
 
 struct TxFD {                                  /* Transmit frame descriptor set. */
        s32 status;
        u32 link;                                       /* void * */
        u32 tx_desc_addr;                       /* Always points to the tx_buf_addr element. */
        s32 count;                                      /* # of TBD (=1), Tx start thresh., etc. */
-       /* This constitutes a single "TBD" entry -- we only use one. */
-       u32 tx_buf_addr;                        /* void *, frame to be transmitted.  */
-       s32 tx_buf_size;                        /* Length of Tx frame. */
+       /* This constitutes two "TBD" entries -- we only use one. */
+       u32 tx_buf_addr0;                       /* void *, frame to be transmitted.  */
+       s32 tx_buf_size0;                       /* Length of Tx frame. */
+       u32 tx_buf_addr1;                       /* void *, frame to be transmitted.  */
+       s32 tx_buf_size1;                       /* Length of Tx frame. */
 };
 
 /* Elements of the dump_statistics block. This block must be lword aligned. */
@@ -409,9 +345,6 @@ struct speedo_private {
        /* Rx descriptor ring & addresses of receive-in-place skbuffs. */
        struct RxFD *rx_ringp[RX_RING_SIZE];
        struct sk_buff* rx_skbuff[RX_RING_SIZE];
-#if (LINUX_VERSION_CODE < 0x10300)     /* Kernel v1.2.*. */
-       struct RxFD saved_skhead[RX_RING_SIZE]; /* Saved skbuff header chunk. */
-#endif
        struct RxFD *last_rxf;  /* Last command sent. */
        struct enet_statistics stats;
        struct speedo_stats lstats;
@@ -419,10 +352,10 @@ struct speedo_private {
        long last_rx_time;                      /* Last Rx, in jiffies, to handle Rx hang. */
        unsigned int cur_rx, cur_tx;            /* The next free ring entry */
        unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
-       struct descriptor config_cmd;   /* A configure command, with header... */
-       u8 config_cmd_data[22];                 /* .. and setup parameters. */
        int mc_setup_frm_len;                           /* The length of an allocated.. */
        struct descriptor *mc_setup_frm;        /* ..multicast setup frame. */
+       int mc_setup_busy;                                      /* Avoid double-use of setup frame. */
+       int in_interrupt;                                       /* Word-aligned dev->interrupt */
        char rx_mode;                                           /* Current PROMISC/ALLMULTI setting. */
        unsigned int tx_full:1;                         /* The Tx queue is full. */
        unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
@@ -436,11 +369,16 @@ struct speedo_private {
 /* The parameters for a CmdConfigure operation.
    There are so many options that it would be difficult to document each bit.
    We mostly use the default or recommended settings. */
-const char basic_config_cmd[22] = {
+const char i82557_config_cmd[22] = {
        22, 0x08, 0, 0,  0, 0x80, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
        0, 0x2E, 0,  0x60, 0,
        0xf2, 0x48,   0, 0x40, 0xf2, 0x80,              /* 0x40=Force full-duplex */
        0x3f, 0x05, };
+const char i82558_config_cmd[22] = {
+       22, 0x08, 0, 1,  0, 0x80, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
+       0, 0x2E, 0,  0x60, 0x08, 0x88,
+       0x68, 0, 0x40, 0xf2, 0xBD,              /* 0xBD->0xFD=Force full-duplex */
+       0x31, 0x05, };
 
 /* PHY media interface chips. */
 static const char *phys[] = {
@@ -452,12 +390,12 @@ enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
                                         S80C24, I82555, DP83840A=10, };
 static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
 
-static void speedo_found1(struct device *dev, int ioaddr, int irq,
-                                                 int options, int card_idx);
+static void speedo_found1(struct device *dev, long ioaddr, int irq,
+                                                 int card_idx);
 
-static int read_eeprom(int ioaddr, int location);
-static int mdio_read(int ioaddr, int phy_id, int location);
-static int mdio_write(int ioaddr, int phy_id, int location, int value);
+static int read_eeprom(long ioaddr, int location, int addr_len);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static int mdio_write(long ioaddr, int phy_id, int location, int value);
 static int speedo_open(struct device *dev);
 static void speedo_timer(unsigned long data);
 static void speedo_init_rx_ring(struct device *dev);
@@ -466,9 +404,7 @@ static int speedo_rx(struct device *dev);
 static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int speedo_close(struct device *dev);
 static struct enet_statistics *speedo_get_stats(struct device *dev);
-#ifdef HAVE_PRIVATE_IOCTL
 static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-#endif
 static void set_rx_mode(struct device *dev);
 
 \f
@@ -477,109 +413,101 @@ 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};
+#ifdef MODULE
 static int debug = -1;                 /* The debug level */
 #endif
 
+#ifdef honor_default_port
+/* Optional driver feature to allow forcing the transceiver setting.
+   Not recommended. */
+static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
+                                                  0x2000, 0x2100, 0x0400, 0x3100};
+#endif
+
 /* A list of all installed Speedo devices, for removing the driver module. */
 static struct device *root_speedo_dev = NULL;
 
 int eepro100_init(struct device *dev)
 {
        int cards_found = 0;
+       static int pci_index = 0;
 
-       if (pci_present()) {
-               static int pci_index = 0;
+       if (! pcibios_present())
+               return cards_found;
 
-               for (; pci_index < 8; pci_index++) {
-                       unsigned char pci_bus, pci_device_fn, pci_latency;
-#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
-                       unsigned int pci_irq_line;
-                       struct pci_dev *pdev;
-#else
-                       unsigned char pci_irq_line;
-#endif
-#if (LINUX_VERSION_CODE >= VERSION(1,3,44))
-                       int pci_ioaddr;
-#else
-                       long pci_ioaddr;
-#endif
-                       unsigned short pci_command;
-
-                       if (pcibios_find_device(PCI_VENDOR_ID_INTEL,
-                                               PCI_DEVICE_ID_INTEL_82557,
-                                               pci_index, &pci_bus,
-                                               &pci_device_fn))
-                         break;
-#if (LINUX_VERSION_CODE >= VERSION(2,1,85))
-                       pdev = pci_find_slot(pci_bus, pci_device_fn);
-                       pci_irq_line = pdev->irq;
-                       pci_ioaddr = pdev->base_address[1];
-#else
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                        PCI_INTERRUPT_LINE, &pci_irq_line);
-                       /* Note: BASE_ADDRESS_0 is for memory-mapping the registers. */
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                                         PCI_BASE_ADDRESS_1, &pci_ioaddr);
-#endif
-                       /* Remove I/O space marker in bit 0. */
-                       pci_ioaddr &= ~3;
-                       if (speedo_debug > 2)
-                               printk("Found Intel i82557 PCI Speedo at I/O %#x, IRQ %d.\n",
-                                          (int)pci_ioaddr, pci_irq_line);
-
-                       /* Get and check the bus-master and latency values. */
-                       pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                        PCI_COMMAND, &pci_command);
-                       if ( ! (pci_command & PCI_COMMAND_MASTER)) {
-                               printk("  PCI Master Bit has not been set! Setting...\n");
-                               pci_command |= PCI_COMMAND_MASTER;
-                               pcibios_write_config_word(pci_bus, pci_device_fn,
-                                                                                 PCI_COMMAND, pci_command);
-                       }
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                                PCI_LATENCY_TIMER, &pci_latency);
-                       if (pci_latency < 10) {
-                               printk("  PCI latency timer (CFLT) is unreasonably low at %d."
-                                          "  Setting to 255 clocks.\n", pci_latency);
-                               pcibios_write_config_byte(pci_bus, pci_device_fn,
-                                                                                 PCI_LATENCY_TIMER, 255);
-                       } else if (speedo_debug > 1)
-                               printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
+       for (; pci_index < 8; pci_index++) {
+               unsigned char pci_bus, pci_device_fn, pci_latency;
+               long ioaddr;
+               int irq;
 
-#ifdef MODULE
-                       speedo_found1(dev, pci_ioaddr, pci_irq_line, options[cards_found],
-                                                 cards_found);
-#else
-                       speedo_found1(dev, pci_ioaddr, pci_irq_line,
-                                                 dev ? dev->mem_start : 0, -1);
-#endif
-                       dev = NULL;
-                       cards_found++;
+               u16 pci_command, new_command;
+
+               if (pcibios_find_device(PCI_VENDOR_ID_INTEL,
+                                                               PCI_DEVICE_ID_INTEL_82557,
+                                                               pci_index, &pci_bus,
+                                                               &pci_device_fn))
+                       break;
+               {
+                       struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
+                       ioaddr = pdev->base_address[1];         /* Use [0] to mem-map */
+                       irq = pdev->irq;
+               }
+               /* Remove I/O space marker in bit 0. */
+               ioaddr &= ~3;
+               if (speedo_debug > 2)
+                       printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
+                                  ioaddr, irq);
+
+               /* Get and check the bus-master and latency values. */
+               pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                PCI_COMMAND, &pci_command);
+               new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+               if (pci_command != new_command) {
+                       printk(KERN_INFO "  The PCI BIOS has not enabled this"
+                                  " device!  Updating PCI command %4.4x->%4.4x.\n",
+                                  pci_command, new_command);
+                       pcibios_write_config_word(pci_bus, pci_device_fn,
+                                                                         PCI_COMMAND, new_command);
                }
+               pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                PCI_LATENCY_TIMER, &pci_latency);
+               if (pci_latency < 32) {
+                       printk("  PCI latency timer (CFLT) is unreasonably low at %d."
+                                  "  Setting to 32 clocks.\n", pci_latency);
+                       pcibios_write_config_byte(pci_bus, pci_device_fn,
+                                                                         PCI_LATENCY_TIMER, 32);
+               } else if (speedo_debug > 1)
+                       printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
+
+               speedo_found1(dev, ioaddr, irq, cards_found);
+               dev = NULL;
+               cards_found++;
        }
 
        return cards_found;
 }
 
-static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
+static void speedo_found1(struct device *dev, long ioaddr, int irq,
                                                  int card_idx)
 {
        static int did_version = 0;                     /* Already printed version info. */
        struct speedo_private *sp;
        char *product;
-       int i;
+       int i, option;
        u16 eeprom[0x40];
 
        if (speedo_debug > 0  &&  did_version++ == 0)
                printk(version);
 
-#if (LINUX_VERSION_CODE >= VERSION(1,3,44))
        dev = init_etherdev(dev, sizeof(struct speedo_private));
-#else
-       dev = init_etherdev(dev, sizeof(struct speedo_private), 0);
-#endif
+
+       if (dev->mem_start > 0)
+               option = dev->mem_start;
+       else if (card_idx >= 0  &&  options[card_idx] >= 0)
+               option = options[card_idx];
+       else
+               option = 0;
 
        /* Read the station address EEPROM before doing the reset.
           Perhaps this should even be done before accepting the device,
@@ -587,8 +515,10 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
        {
                u16 sum = 0;
                int j;
+               int addr_len = read_eeprom(ioaddr, 0, 6) == 0xffff ? 8 : 6;
+
                for (j = 0, i = 0; i < 0x40; i++) {
-                       u16 value = read_eeprom(ioaddr, i);
+                       u16 value = read_eeprom(ioaddr, i, addr_len);
                        eeprom[i] = value;
                        sum += value;
                        if (i < 3) {
@@ -614,7 +544,7 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
        else
                product = "Intel EtherExpress Pro 10/100";
 
-       printk(KERN_INFO "%s: %s at %#3x, ", dev->name, product, ioaddr);
+       printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr);
 
        for (i = 0; i < 5; i++)
                printk("%2.2X:", dev->dev_addr[i]);
@@ -643,17 +573,6 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
                if (eeprom[7] & 0x0700)
                        printk(KERN_INFO "    Secondary interface chip %s.\n",
                                   phys[(eeprom[7]>>8)&7]);
-#if defined(notdef)
-               /* ToDo: Read and set PHY registers through MDIO port. */
-               for (i = 0; i < 2; i++)
-                       printk(KERN_INFO"  MDIO register %d is %4.4x.\n",
-                                  i, mdio_read(ioaddr, eeprom[6] & 0x1f, i));
-               for (i = 5; i < 7; i++)
-                       printk(KERN_INFO"  MDIO register %d is %4.4x.\n",
-                                  i, mdio_read(ioaddr, eeprom[6] & 0x1f, i));
-               printk(KERN_INFO"  MDIO register %d is %4.4x.\n",
-                          25, mdio_read(ioaddr, eeprom[6] & 0x1f, 25));
-#endif
                if (((eeprom[6]>>8) & 0x3f) == DP83840
                        ||  ((eeprom[6]>>8) & 0x3f) == DP83840A) {
                        int mdi_reg23 = mdio_read(ioaddr, eeprom[6] & 0x1f, 23) | 0x0422;
@@ -663,13 +582,13 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
                                   mdi_reg23);
                        mdio_write(ioaddr, eeprom[6] & 0x1f, 23, mdi_reg23);
                }
-               if ((options >= 0) && (options & 0x60)) {
+               if ((option >= 0) && (option & 0x70)) {
                        printk(KERN_INFO "  Forcing %dMbs %s-duplex operation.\n",
-                                  (options & 0x20 ? 100 : 10),
-                                  (options & 0x10 ? "full" : "half"));
+                                  (option & 0x20 ? 100 : 10),
+                                  (option & 0x10 ? "full" : "half"));
                        mdio_write(ioaddr, eeprom[6] & 0x1f, 0,
-                                          ((options & 0x20) ? 0x2000 : 0) |    /* 100mbps? */
-                                          ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
+                                          ((option & 0x20) ? 0x2000 : 0) |     /* 100mbps? */
+                                          ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
                }
 
                /* Perform a system self-test. */
@@ -678,11 +597,7 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
                self_test_results[1] = -1;
                outl(virt_to_bus(self_test_results) | 1, ioaddr + SCBPort);
                do {
-#ifdef _LINUX_DELAY_H
                        udelay(10);
-#else
-                       SLOW_DOWN_IO;
-#endif
                } while (self_test_results[1] == -1  &&  --boguscnt >= 0);
 
                if (boguscnt < 0) {             /* Test optimized out. */
@@ -719,12 +634,12 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
        sp->next_module = root_speedo_dev;
        root_speedo_dev = dev;
 
+       sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
        if (card_idx >= 0) {
                if (full_duplex[card_idx] >= 0)
                        sp->full_duplex = full_duplex[card_idx];
-       } else
-               sp->full_duplex = options >= 0 && (options & 0x10) ? 1 : 0;
-       sp->default_port = options >= 0 ? (options & 0x0f) : 0;
+       }
+       sp->default_port = option >= 0 ? (option & 0x0f) : 0;
 
        sp->phy[0] = eeprom[6];
        sp->phy[1] = eeprom[7];
@@ -738,12 +653,8 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
        dev->hard_start_xmit = &speedo_start_xmit;
        dev->stop = &speedo_close;
        dev->get_stats = &speedo_get_stats;
-#ifdef NEW_MULTICAST
        dev->set_multicast_list = &set_rx_mode;
-#endif
-#ifdef HAVE_PRIVATE_IOCTL
        dev->do_ioctl = &speedo_ioctl;
-#endif
 
        return;
 }
@@ -760,38 +671,31 @@ static void speedo_found1(struct device *dev, int ioaddr, int irq, int options,
 #define EE_ENB                 (0x4800 | EE_CS)
 
 /* Delay between EEPROM clock transitions.
-   This is a "nasty" timing loop, but PC compatible machines are defined
-   to delay an ISA compatible period for the SLOW_DOWN_IO macro.  */
-#ifdef _LINUX_DELAY_H
+   This will actually work with no delay on 33Mhz PCI.  */
 #define eeprom_delay(nanosec)          udelay(1);
-#else
-#define eeprom_delay(nanosec)  do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
 
 /* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD   (5 << 6)
-#define EE_READ_CMD            (6 << 6)
-#define EE_ERASE_CMD   (7 << 6)
+#define EE_WRITE_CMD   (5 << addr_len)
+#define EE_READ_CMD            (6 << addr_len)
+#define EE_ERASE_CMD   (7 << addr_len)
 
-static int read_eeprom(int ioaddr, int location)
+static int read_eeprom(long ioaddr, int location, int addr_len)
 {
-       int i;
        unsigned short retval = 0;
        int ee_addr = ioaddr + SCBeeprom;
        int read_cmd = location | EE_READ_CMD;
+       int i;
 
        outw(EE_ENB & ~EE_CS, ee_addr);
        outw(EE_ENB, ee_addr);
 
        /* Shift the read command bits out. */
-       for (i = 10; i >= 0; i--) {
+       for (i = 12; i >= 0; i--) {
                short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
                outw(EE_ENB | dataval, ee_addr);
                eeprom_delay(100);
                outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
                eeprom_delay(150);
-               outw(EE_ENB | dataval, ee_addr);        /* Finish EEPROM a clock tick. */
-               eeprom_delay(250);
        }
        outw(EE_ENB, ee_addr);
 
@@ -808,16 +712,11 @@ static int read_eeprom(int ioaddr, int location)
        return retval;
 }
 
-static int mdio_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
 {
-       int val, boguscnt = 64*4;               /* <64 usec. to complete, typ 27 ticks */
+       int val, boguscnt = 64*10;              /* <64 usec. to complete, typ 27 ticks */
        outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
        do {
-#ifdef _LINUX_DELAY_H
-               udelay(16);
-#else
-               SLOW_DOWN_IO;
-#endif
                val = inl(ioaddr + SCBCtrlMDI);
                if (--boguscnt < 0) {
                        printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
@@ -826,17 +725,12 @@ static int mdio_read(int ioaddr, int phy_id, int location)
        return val & 0xffff;
 }
 
-static int mdio_write(int ioaddr, int phy_id, int location, int value)
+static int mdio_write(long ioaddr, int phy_id, int location, int value)
 {
-       int val, boguscnt = 64*4;               /* <64 usec. to complete, typ 27 ticks */
+       int val, boguscnt = 64*10;              /* <64 usec. to complete, typ 27 ticks */
        outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
                 ioaddr + SCBCtrlMDI);
        do {
-#ifdef _LINUX_DELAY_H
-               udelay(16);
-#else
-               SLOW_DOWN_IO;
-#endif
                val = inl(ioaddr + SCBCtrlMDI);
                if (--boguscnt < 0) {
                        printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
@@ -850,25 +744,39 @@ static int
 speedo_open(struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
 
 #ifdef notdef
        /* We could reset the chip, but should not need to. */
        outl(0, ioaddr + SCBPort);
-       for (i = 40; i >= 0; i--)
-               SLOW_DOWN_IO;                   /* At least 250ns */
+       udelay(10);
 #endif
 
        if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ,
                                        "Intel EtherExpress Pro 10/100 Ethernet", dev)) {
                return -EAGAIN;
        }
-
        if (speedo_debug > 1)
                printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
 
        MOD_INC_USE_COUNT;
 
+       /* Retrigger negotiation to reset previous errors. */
+       if ((sp->phy[0] & 0x8000) == 0) {
+               int phy_addr = sp->phy[0] & 0x1f;
+               /* Use 0x3300 for restarting NWay, other values to force xcvr:
+                  0x0000 10-HD
+                  0x0100 10-FD
+                  0x2000 100-HD
+                  0x2100 100-FD
+               */
+#ifdef honor_default_port
+               mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
+#else
+               mdio_write(ioaddr, phy_addr, 0, 0x3300);
+#endif
+       }
+
        /* Load the statistics block address. */
        wait_for_cmd_done(ioaddr + SCBCmd);
        outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer);
@@ -908,6 +816,7 @@ speedo_open(struct device *dev)
 
        dev->if_port = sp->default_port;
 
+       sp->in_interrupt = 0;
        dev->tbusy = 0;
        dev->interrupt = 0;
        dev->start = 1;
@@ -921,6 +830,7 @@ speedo_open(struct device *dev)
        /* Setup the chip and configure the multicast list. */
        sp->mc_setup_frm = NULL;
        sp->mc_setup_frm_len = 0;
+       sp->mc_setup_busy = 0;
        sp->rx_mode = -1;                       /* Invalid -> always reset the mode. */
        set_rx_mode(dev);
 
@@ -949,24 +859,22 @@ static void speedo_timer(unsigned long data)
 {
        struct device *dev = (struct device *)data;
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int tickssofar = jiffies - sp->last_rx_time;
 
        if (speedo_debug > 3) {
-               int ioaddr = dev->base_addr;
-               printk(KERN_DEBUG "%s: Media selection tick, status %4.4x.\n",
+               long ioaddr = dev->base_addr;
+               printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
                           dev->name, inw(ioaddr + SCBStatus));
        }
-       if (sp->rx_bug) {
-               if (tickssofar > 2*HZ  || sp->rx_mode < 0) {
-                       /* We haven't received a packet in a Long Time.  We might have been
-                          bitten by the receiver hang bug.  This can be cleared by sending
-                          a set multicast list command. */
-                       set_rx_mode(dev);
-               }
-               /* We must continue to monitor the media. */
-               sp->timer.expires = RUN_AT(2*HZ);                       /* 2.0 sec. */
-               add_timer(&sp->timer);
+       if (sp->rx_mode < 0  ||
+               (sp->rx_bug  && jiffies - sp->last_rx_time > 2*HZ)) {
+               /* We haven't received a packet in a Long Time.  We might have been
+                  bitten by the receiver hang bug.  This can be cleared by sending
+                  a set multicast list command. */
+               set_rx_mode(dev);
        }
+       /* We must continue to monitor the media. */
+       sp->timer.expires = RUN_AT(2*HZ);                       /* 2.0 sec. */
+       add_timer(&sp->timer);
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
@@ -978,43 +886,32 @@ speedo_init_rx_ring(struct device *dev)
        int i;
 
        sp->cur_rx = 0;
-       sp->dirty_rx = RX_RING_SIZE - 1;
 
        for (i = 0; i < RX_RING_SIZE; i++) {
                struct sk_buff *skb;
-#ifndef KERNEL_1_2
                skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-#else
-               skb = alloc_skb(PKT_BUF_SZ, GFP_ATOMIC);
-#endif
                sp->rx_skbuff[i] = skb;
                if (skb == NULL)
-                       break;                  /* Bad news!  */
+                       break;                  /* OK.  Just initially short of Rx bufs. */
                skb->dev = dev;                 /* Mark as being used by this device. */
-
-#if LINUX_VERSION_CODE >= 0x10300
                rxf = (struct RxFD *)skb->tail;
-               skb_reserve(skb, sizeof(struct RxFD));
-#else
-               /* Save the data in the header region -- it's restored later. */
-               rxf = (struct RxFD *)(skb->data - sizeof(struct RxFD));
-               memcpy(&sp->saved_skhead[i], rxf, sizeof(struct RxFD));
-#endif
                sp->rx_ringp[i] = rxf;
+               skb_reserve(skb, sizeof(struct RxFD));
                if (last_rxf)
                        last_rxf->link = virt_to_bus(rxf);
                last_rxf = rxf;
                rxf->status = 0x00000001;                       /* '1' is flag value only. */
                rxf->link = 0;                                          /* None yet. */
-#if LINUX_VERSION_CODE < 0x10300
                /* This field unused by i82557, we use it as a consistency check. */
-               rxf->rx_buf_addr = virt_to_bus(skb->data);
+#ifdef final_version
+               rxf->rx_buf_addr = 0xffffffff;
 #else
                rxf->rx_buf_addr = virt_to_bus(skb->tail);
 #endif
                rxf->count = 0;
                rxf->size = PKT_BUF_SZ;
        }
+       sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
        /* Mark the last entry as end-of-list. */
        last_rxf->status = 0xC0000002;                  /* '2' is flag value only. */
        sp->last_rxf = last_rxf;
@@ -1023,40 +920,33 @@ speedo_init_rx_ring(struct device *dev)
 static void speedo_tx_timeout(struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int ioaddr = dev->base_addr;
-       int i;
+       long ioaddr = dev->base_addr;
 
        printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
-                  "command %4.4x.\n",
-                  dev->name, inw(ioaddr + SCBStatus), inw(ioaddr + SCBCmd));
-#ifndef final_version
-       printk(KERN_WARNING "%s:  Tx timeout  fill index %d  scavenge index %d.\n",
-                  dev->name, sp->cur_tx, sp->dirty_tx);
-       printk(KERN_WARNING "    Tx queue ");
-       for (i = 0; i < TX_RING_SIZE; i++)
-         printk(" %8.8x", (int)sp->tx_ring[i].status);
-       printk(".\n" KERN_WARNING "    Rx ring ");
-       for (i = 0; i < RX_RING_SIZE; i++)
-         printk(" %8.8x", (int)sp->rx_ringp[i]->status);
-       printk(".\n");
-
-#else
-       dev->if_port ^= 1;
-       printk(KERN_WARNING "  (Media type switching not yet implemented.)\n");
-       /* Do not do 'dev->tbusy = 0;' there -- it is incorrect. */
-#endif
+                  " %4.4x at %d/%d command %8.8x.\n",
+                  dev->name, inw(ioaddr + SCBStatus), inw(ioaddr + SCBCmd),
+                  sp->dirty_tx, sp->cur_tx,
+                  sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
        if ((inw(ioaddr + SCBStatus) & 0x00C0) != 0x0080) {
-         printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
-                        dev->name);
-         outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
-                  ioaddr + SCBPointer);
-         outw(CU_START, ioaddr + SCBCmd);
+               printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
+                          dev->name);
+               outl(virt_to_bus(&sp->tx_ring[sp->dirty_tx % TX_RING_SIZE]),
+                        ioaddr + SCBPointer);
+               outw(CU_START, ioaddr + SCBCmd);
        } else {
-         outw(DRVR_INT, ioaddr + SCBCmd);
+               outw(DRVR_INT, ioaddr + SCBCmd);
+       }
+       /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
+       if ((sp->phy[0] & 0x8000) == 0) {
+               int phy_addr = sp->phy[0] & 0x1f;
+               mdio_write(ioaddr, phy_addr, 0, 0x0400);
+               mdio_write(ioaddr, phy_addr, 1, 0x0000);
+               mdio_write(ioaddr, phy_addr, 4, 0x0000);
+               mdio_write(ioaddr, phy_addr, 0, 0x8000);
+#ifdef honor_default_port
+               mdio_write(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);
+#endif
        }
-       /* Reset the MII transceiver. */
-       if ((sp->phy[0] & 0x8000) == 0)
-               mdio_write(ioaddr, sp->phy[0] & 0x1f, 0, 0x8000);
        sp->stats.tx_errors++;
        dev->trans_start = jiffies;
        return;
@@ -1066,7 +956,7 @@ static int
 speedo_start_xmit(struct sk_buff *skb, struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        int entry;
 
        /* Block a timer-based transmit from overlapping.  This could better be
@@ -1082,7 +972,7 @@ speedo_start_xmit(struct sk_buff *skb, struct device *dev)
                        return 1;
                }
                speedo_tx_timeout(dev);
-               return 0;
+               return 1;
        }
 
        /* Caution: the write order is important here, set the base address
@@ -1103,29 +993,29 @@ speedo_start_xmit(struct sk_buff *skb, struct device *dev)
                sp->tx_ring[entry].link =
                  virt_to_bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
                sp->tx_ring[entry].tx_desc_addr =
-                 virt_to_bus(&sp->tx_ring[entry].tx_buf_addr);
+                 virt_to_bus(&sp->tx_ring[entry].tx_buf_addr0);
                /* The data region is always in one buffer descriptor, Tx FIFO
                   threshold of 256. */
                sp->tx_ring[entry].count = 0x01208000;
-               sp->tx_ring[entry].tx_buf_addr = virt_to_bus(skb->data);
-               sp->tx_ring[entry].tx_buf_size = skb->len;
+               sp->tx_ring[entry].tx_buf_addr0 = virt_to_bus(skb->data);
+               sp->tx_ring[entry].tx_buf_size0 = skb->len;
                /* Todo: perhaps leave the interrupt bit set if the Tx queue is more
                   than half full.  Argument against: we should be receiving packets
                   and scavenging the queue.  Argument for: if so, it shouldn't
                   matter. */
                sp->last_cmd->command &= ~(CmdSuspend | CmdIntr);
                sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
+               restore_flags(flags);
                /* Trigger the command unit resume. */
                wait_for_cmd_done(ioaddr + SCBCmd);
                outw(CU_RESUME, ioaddr + SCBCmd);
-               restore_flags(flags);
        }
 
        /* Leave room for set_rx_mode() to fill two entries. */
        if (sp->cur_tx - sp->dirty_tx > TX_RING_SIZE - 3)
                sp->tx_full = 1;
        else
-               dev->tbusy = 0;
+               clear_bit(0, (void*)&dev->tbusy);
 
        dev->trans_start = jiffies;
 
@@ -1138,7 +1028,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
        struct device *dev = (struct device *)dev_instance;
        struct speedo_private *sp;
-       int ioaddr, boguscnt = max_interrupt_work;
+       long ioaddr, boguscnt = max_interrupt_work;
        unsigned short status;
 
 #ifndef final_version
@@ -1151,8 +1041,11 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
        ioaddr = dev->base_addr;
        sp = (struct speedo_private *)dev->priv;
 #ifndef final_version
-       if (dev->interrupt) {
-               printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+       /* A lock to prevent simultaneous entry on SMP machines. */
+       if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
+               printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+                          dev->name);
+               sp->in_interrupt = 0;   /* Avoid halting machine. */
                return;
        }
        dev->interrupt = 1;
@@ -1174,19 +1067,6 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        speedo_rx(dev);
 
                if (status & 0x1000) {
-#ifdef notdef
-                 int i;
-                 printk(KERN_WARNING"%s: The EEPro100 receiver left the ready"
-                                " state -- %4.4x!  Index %d (%d).\n", dev->name, status,
-                                sp->cur_rx, sp->cur_rx % RX_RING_SIZE);
-                 printk(KERN_WARNING "   Rx ring:\n ");
-                 for (i = 0; i < RX_RING_SIZE; i++)
-                       printk("   %d %8.8x %8.8x %8.8x %d %d.\n",
-                                  i, sp->rx_ringp[i]->status, sp->rx_ringp[i]->link,
-                                  sp->rx_ringp[i]->rx_buf_addr, sp->rx_ringp[i]->count,
-                                  sp->rx_ringp[i]->size);
-#endif
-
                  if ((status & 0x003c) == 0x0028) /* No more Rx buffers. */
                        outw(RX_RESUMENR, ioaddr + SCBCmd);
                  else if ((status & 0x003c) == 0x0008) { /* No resources (why?!) */
@@ -1209,14 +1089,15 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                if (speedo_debug > 5)
                                        printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
                                                   entry, status);
-                               if ((status & 0x8000) == 0)
+                               if ((status & StatusComplete) == 0)
                                        break;                  /* It still hasn't been processed. */
                                /* Free the original skb. */
                                if (sp->tx_skbuff[entry]) {
                                        sp->stats.tx_packets++; /* Count only user packets. */
-                                       dev_kfree_skb(sp->tx_skbuff[entry]);
+                                       dev_free_skb(sp->tx_skbuff[entry]);
                                        sp->tx_skbuff[entry] = 0;
-                               }
+                               } else if ((sp->tx_ring[entry].status&0x70000) == CmdNOp << 16)
+                                       sp->mc_setup_busy = 0;
                                dirty_tx++;
                        }
 
@@ -1233,7 +1114,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                                && dirty_tx > sp->cur_tx - TX_RING_SIZE + 2) {
                                /* The ring is no longer full, clear tbusy. */
                                sp->tx_full = 0;
-                               dev->tbusy = 0;
+                               clear_bit(0, (void*)&dev->tbusy);
                                mark_bh(NET_BH);
                        }
 
@@ -1253,19 +1134,8 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
                           dev->name, inw(ioaddr + SCBStatus));
 
-#ifndef final_version
-       /* Special code for testing *only*. */
-       {
-               static int stopit = 100;
-               if (dev->start == 0  &&  --stopit < 0) {
-                       printk(KERN_ALERT "%s: Emergency stop, interrupt is stuck.\n",
-                                  dev->name);
-                       free_irq(irq, dev);
-               }
-       }
-#endif
-
        dev->interrupt = 0;
+       clear_bit(0, (void*)&sp->in_interrupt);
        return;
 }
 
@@ -1275,150 +1145,104 @@ speedo_rx(struct device *dev)
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        int entry = sp->cur_rx % RX_RING_SIZE;
        int status;
+       int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
 
        if (speedo_debug > 4)
                printk(KERN_DEBUG " In speedo_rx().\n");
        /* If we own the next entry, it's a new packet. Send it up. */
-       while ((status = sp->rx_ringp[entry]->status) & RX_COMPLETE) {
+       while (sp->rx_ringp[entry] != NULL &&
+                  (status = sp->rx_ringp[entry]->status) & RxComplete) {
 
                if (speedo_debug > 4)
                        printk(KERN_DEBUG "  speedo_rx() status %8.8x len %d.\n", status,
                                   sp->rx_ringp[entry]->count & 0x3fff);
-               if (status & 0x0200) {
-                       printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
-                                  "status %8.8x!\n", dev->name, status);
-               } else if ( ! (status & 0x2000)) {
-                       /* There was a fatal error.  This *should* be impossible. */
-                       sp->stats.rx_errors++;
-                       printk(KERN_ERR "%s: Anomalous event in speedo_rx(), status %8.8x.\n",
-                                  dev->name, status);
+               if ((status & (RxErrTooBig|RxOK)) != RxOK) {
+                       if (status & RxErrTooBig)
+                               printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
+                                          "status %8.8x!\n", dev->name, status);
+                       else if ( ! (status & 0x2000)) {
+                               /* There was a fatal error.  This *should* be impossible. */
+                               sp->stats.rx_errors++;
+                               printk(KERN_ERR "%s: Anomalous event in speedo_rx(), "
+                                          "status %8.8x.\n",
+                                          dev->name, status);
+                       }
                } else {
-                       /* Malloc up new buffer, compatible with net-2e. */
                        int pkt_len = sp->rx_ringp[entry]->count & 0x3fff;
                        struct sk_buff *skb;
-                       int rx_in_place = 0;
 
                        /* Check if the packet is long enough to just accept without
                           copying to a properly sized skbuff. */
-                       if (pkt_len > rx_copybreak) {
-                               struct sk_buff *newskb;
-                               char *temp;
-
-                               /* Pass up the skb already on the Rx ring. */
-                               skb = sp->rx_skbuff[entry];
-#ifdef KERNEL_1_2
-                               temp = skb->data;
-                               if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp)
-                                       printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
-                                                  " in speedo_rx: %p vs. %p / %p.\n", dev->name,
-                                                  bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
-                                                  temp, skb->data);
-                               /* Get a fresh skbuff to replace the filled one. */
-                               newskb = alloc_skb(PKT_BUF_SZ, GFP_ATOMIC);
-#else
-                               temp = skb_put(skb, pkt_len);
-                               if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp)
-                                       printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
-                                                  " in speedo_rx: %8.8x vs. %p / %p.\n", dev->name,
-                                                  sp->rx_ringp[entry]->rx_buf_addr, skb->head, temp);
-                               /* Get a fresh skbuff to replace the filled one. */
-                               newskb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
-#endif
-                               if (newskb) {
-                                       struct RxFD *rxf;
-                                       rx_in_place = 1;
-                                       sp->rx_skbuff[entry] = newskb;
-                                       newskb->dev = dev;
-#ifdef KERNEL_1_2
-                                       /* Restore the data in the old header region. */
-                                       memcpy(skb->data - sizeof(struct RxFD),
-                                                  &sp->saved_skhead[entry], sizeof(struct RxFD));
-                                       /* Save the data in this header region. */
-                                       rxf = (struct RxFD *)(newskb->data - sizeof(struct RxFD));
-                                       sp->rx_ringp[entry] = rxf;
-                                       memcpy(&sp->saved_skhead[entry], rxf, sizeof(struct RxFD));
-                                       rxf->rx_buf_addr = virt_to_bus(newskb->data);
-#else
-                                       rxf = sp->rx_ringp[entry] = (struct RxFD *)newskb->tail;
-                                       skb_reserve(newskb, sizeof(struct RxFD));
-                                       /* Unused by i82557, consistency check only. */
-                                       rxf->rx_buf_addr = virt_to_bus(newskb->tail);
-#endif
-                                       rxf->status = 0x00000001;
-                               } else                  /* No memory, drop the packet. */
-                                 skb = 0;
-                       } else
-#ifdef KERNEL_1_2
-                               skb = alloc_skb(pkt_len, GFP_ATOMIC);
-#else
-                               skb = dev_alloc_skb(pkt_len + 2);
-#endif
-                       if (skb == NULL) {
-                               int i;
-                               printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", dev->name);
-                               /* Check that at least two ring entries are free.
-                                  If not, free one and mark stats->rx_dropped++. */
-                               /* ToDo: This is not correct!!!!  We should count the number
-                                  of linked-in Rx buffer to very that we have at least two
-                                  remaining. */
-                               for (i = 0; i < RX_RING_SIZE; i++)
-                                       if (! ((sp->rx_ringp[(entry+i) % RX_RING_SIZE]->status)
-                                                  & RX_COMPLETE))
-                                               break;
-
-                               if (i > RX_RING_SIZE -2) {
-                                       sp->stats.rx_dropped++;
-                                       sp->rx_ringp[entry]->status = 0;
-                                       sp->cur_rx++;
-                               }
-                               break;
-                       }
-                       skb->dev = dev;
-#if (LINUX_VERSION_CODE >= VERSION(1,3,44))
-                       if (! rx_in_place) {
-                               skb_reserve(skb, 2);    /* 16 byte align the data fields */
-#if defined(__i386__)   &&  notyet
+                       if (pkt_len < rx_copybreak
+                               && (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
+                               skb->dev = dev;
+                               skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+                               /* 'skb_put()' points to the start of sk_buff data area. */
+#if 1 || USE_IP_CSUM
                                /* Packet is in one chunk -- we can copy + cksum. */
-                               eth_io_copy_and_sum(skb, bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
-                                                                       pkt_len, 0);
+                               eth_copy_and_sum(skb,
+                                                                bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
+                                                                pkt_len, 0);
+                               skb_put(skb, pkt_len);
 #else
                                memcpy(skb_put(skb, pkt_len),
                                           bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), pkt_len);
 #endif
+                       } else {
+                               void *temp;
+                               /* Pass up the already-filled skbuff. */
+                               skb = sp->rx_skbuff[entry];
+                               if (skb == NULL) {
+                                       printk(KERN_ERR "%s: Inconsistent Rx descriptor chain.\n",
+                                                  dev->name);
+                                       break;
+                               }
+                               sp->rx_skbuff[entry] = NULL;
+                               temp = skb_put(skb, pkt_len);
+                               if (bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr) != temp)
+                                       printk(KERN_ERR "%s: Rx consistency error -- the skbuff "
+                                                  "addresses do not match in speedo_rx: %p vs. %p "
+                                                  "/ %p.\n", dev->name,
+                                                  bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
+                                                  skb->head, temp);
+                               sp->rx_ringp[entry] = NULL;
                        }
                        skb->protocol = eth_type_trans(skb, dev);
-#else
-#ifdef KERNEL_1_3
-#warning This code has only been tested with later 1.3.* kernels.
-                       skb->len = pkt_len;
-                       memcpy(skb->data, bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr),
-                                  pkt_len);
-                       /* Needed for 1.3.*. */
-                       skb->protocol = eth_type_trans(skb, dev);
-#else  /* KERNEL_1_2 */
-                       skb->len = pkt_len;
-                       if (! rx_in_place) {
-                               memcpy(skb->data,
-                                          bus_to_virt(sp->rx_ringp[entry]->rx_buf_addr), pkt_len);
-                       }
-#endif
-#endif
                        netif_rx(skb);
                        sp->stats.rx_packets++;
                }
+               entry = (++sp->cur_rx) % RX_RING_SIZE;
+               if (--rx_work_limit < 0)
+                       break;
+       }
 
-               /*      ToDo: This is better than before, but should be checked. */
-               {
-                       struct RxFD *rxf = sp->rx_ringp[entry];
-                       rxf->status = 0xC0000003;               /* '3' for verification only */
-                       rxf->link = 0;                  /* None yet. */
-                       rxf->count = 0;
-                       rxf->size = PKT_BUF_SZ;
-                       sp->last_rxf->link = virt_to_bus(rxf);
-                       sp->last_rxf->status &= ~0xC0000000;
-                       sp->last_rxf = rxf;
-                       entry = (++sp->cur_rx) % RX_RING_SIZE;
+       /* Refill the Rx ring buffers. */
+       for (; sp->dirty_rx < sp->cur_rx; sp->dirty_rx++) {
+               struct RxFD *rxf;
+               entry = sp->dirty_rx % RX_RING_SIZE;
+               if (sp->rx_skbuff[entry] == NULL) {
+                       struct sk_buff *skb;
+                       /* Get a fresh skbuff to replace the consumed one. */
+                       skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
+                       sp->rx_skbuff[entry] = skb;
+                       if (skb == NULL) {
+                               sp->rx_ringp[entry] = NULL;
+                               break;                  /* Better luck next time!  */
+                       }
+                       rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->tail;
+                       skb->dev = dev;
+                       skb_reserve(skb, sizeof(struct RxFD));
+                       rxf->rx_buf_addr = virt_to_bus(skb->tail);
+               } else {
+                       rxf = sp->rx_ringp[entry];
                }
+               rxf->status = 0xC0000001;       /* '1' for driver use only. */
+               rxf->link = 0;                  /* None yet. */
+               rxf->count = 0;
+               rxf->size = PKT_BUF_SZ;
+               sp->last_rxf->link = virt_to_bus(rxf);
+               sp->last_rxf->status &= ~0xC0000000;
+               sp->last_rxf = rxf;
        }
 
        sp->last_rx_time = jiffies;
@@ -1428,7 +1252,7 @@ speedo_rx(struct device *dev)
 static int
 speedo_close(struct device *dev)
 {
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
        int i;
 
@@ -1454,7 +1278,7 @@ speedo_close(struct device *dev)
                sp->rx_skbuff[i] = 0;
                /* Clear the Rx descriptors. */
                if (skb)
-                       dev_kfree_skb(skb);
+                       dev_free_skb(skb);
        }
 
        for (i = 0; i < TX_RING_SIZE; i++) {
@@ -1462,7 +1286,7 @@ speedo_close(struct device *dev)
                sp->tx_skbuff[i] = 0;
                /* Clear the Tx descriptors. */
                if (skb)
-                       dev_kfree_skb(skb);
+                       dev_free_skb(skb);
        }
        if (sp->mc_setup_frm) {
                kfree(sp->mc_setup_frm);
@@ -1507,7 +1331,7 @@ static struct enet_statistics *
 speedo_get_stats(struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
 
        if (sp->lstats.done_marker == 0xA007) { /* Previous dump finished */
                sp->stats.tx_aborted_errors += sp->lstats.tx_coll16_errs;
@@ -1530,11 +1354,10 @@ speedo_get_stats(struct device *dev)
        return &sp->stats;
 }
 
-#ifdef HAVE_PRIVATE_IOCTL
 static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
        u16 *data = (u16 *)&rq->ifr_data;
        int phy = sp->phy[0] & 0x1f;
 
@@ -1545,7 +1368,7 @@ static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                data[3] = mdio_read(ioaddr, data[0], data[1]);
                return 0;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
-               if (!capable(CAP_NET_ADMIN))
+               if (!suser())
                        return -EPERM;
                mdio_write(ioaddr, data[0], data[1], data[2]);
                return 0;
@@ -1553,7 +1376,6 @@ static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                return -EOPNOTSUPP;
        }
 }
-#endif  /* HAVE_PRIVATE_IOCTL */
 
 /* Set or clear the multicast filter for this adaptor.
    This is very ugly with Intel chips -- we usually have to execute an
@@ -1568,14 +1390,16 @@ static void
 set_rx_mode(struct device *dev)
 {
        struct speedo_private *sp = (struct speedo_private *)dev->priv;
-       int ioaddr = dev->base_addr;
+       long ioaddr = dev->base_addr;
+       struct descriptor *last_cmd;
        char new_rx_mode;
        unsigned long flags;
        int entry, i;
 
        if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous. */
                new_rx_mode = 3;
-       } else if (dev->flags & IFF_ALLMULTI) {
+       } else if ((dev->flags & IFF_ALLMULTI)  ||
+                          dev->mc_count > multicast_filter_limit) {
                new_rx_mode = 1;
        } else
                new_rx_mode = 0;
@@ -1588,57 +1412,55 @@ set_rx_mode(struct device *dev)
        }
 
        if (new_rx_mode != sp->rx_mode) {
-               /* We must change the configuration. Construct a CmdConfig frame. */
-               memcpy(sp->config_cmd_data, basic_config_cmd,sizeof(basic_config_cmd));
-               sp->config_cmd_data[1] = (txfifo << 4) | rxfifo;
-               sp->config_cmd_data[4] = rxdmacount;
-               sp->config_cmd_data[5] = txdmacount + 0x80;
-               sp->config_cmd_data[15] = (new_rx_mode & 2) ? 0x49 : 0x48;
-               sp->config_cmd_data[19] = sp->full_duplex ? 0xC0 : 0x80;
-               sp->config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
-               if (sp->phy[0] & 0x8000) {                      /* Use the AUI port instead. */
-                 sp->config_cmd_data[15] |= 0x80;
-                 sp->config_cmd_data[8] = 0;
-               }
-               save_flags(flags);
+               u8 *config_cmd_data;
+
+               save_flags(flags);              /* Lock to protect sp->cur_tx. */
                cli();
-               /* Fill the "real" tx_ring frame with a no-op and point it to us. */
                entry = sp->cur_tx++ % TX_RING_SIZE;
-               sp->tx_skbuff[entry] = 0;       /* Nothing to free. */
-               sp->tx_ring[entry].status = CmdNOp << 16;
-               sp->tx_ring[entry].link = virt_to_bus(&sp->config_cmd);
-               sp->config_cmd.status = 0;
-               sp->config_cmd.command = CmdSuspend | CmdConfigure;
-               sp->config_cmd.link =
-                 virt_to_bus(&(sp->tx_ring[sp->cur_tx % TX_RING_SIZE]));
-               sp->last_cmd->command &= ~CmdSuspend;
-               /* Immediately trigger the command unit resume. */
-               wait_for_cmd_done(ioaddr + SCBCmd);
-               outw(CU_RESUME, ioaddr + SCBCmd);
-               sp->last_cmd = &sp->config_cmd;
+               last_cmd = sp->last_cmd;
+               sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
                restore_flags(flags);
-               if (speedo_debug > 5) {
-                       int i;
-                       printk(KERN_DEBUG " CmdConfig frame in entry %d.\n", entry);
-                       for(i = 0; i < 32; i++)
-                               printk(" %2.2x", ((unsigned char *)&sp->config_cmd)[i]);
-                       printk(".\n");
+
+               sp->tx_skbuff[entry] = 0;                       /* Redundant. */
+               sp->tx_ring[entry].status = (CmdSuspend | CmdConfigure) << 16;
+               sp->tx_ring[entry].link =
+                       virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
+               config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
+               /* Construct a full CmdConfig frame. */
+               memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd));
+               config_cmd_data[1] = (txfifo << 4) | rxfifo;
+               config_cmd_data[4] = rxdmacount;
+               config_cmd_data[5] = txdmacount + 0x80;
+               config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
+               config_cmd_data[19] |= sp->full_duplex ? 0x40 : 0;
+               config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
+               if (sp->phy[0] & 0x8000) {                      /* Use the AUI port instead. */
+                       config_cmd_data[15] |= 0x80;
+                       config_cmd_data[8] = 0;
                }
+               /* Trigger the command unit resume. */
+               last_cmd->command &= ~CmdSuspend;
+               wait_for_cmd_done(ioaddr + SCBCmd);
+               outw(CU_RESUME, ioaddr + SCBCmd);
        }
 
-       if (new_rx_mode == 0  &&  dev->mc_count < 3) {
-               /* The simple case of 0-2 multicast list entries occurs often, and
+       if (new_rx_mode == 0  &&  dev->mc_count < 4) {
+               /* The simple case of 0-3 multicast list entries occurs often, and
                   fits within one tx_ring[] entry. */
-               u16 *setup_params, *eaddrs;
                struct dev_mc_list *mclist;
+               u16 *setup_params, *eaddrs;
 
-               save_flags(flags);
+               save_flags(flags);              /* Lock to protect sp->cur_tx. */
                cli();
                entry = sp->cur_tx++ % TX_RING_SIZE;
+               last_cmd = sp->last_cmd;
+               sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
+               restore_flags(flags);
+
                sp->tx_skbuff[entry] = 0;
                sp->tx_ring[entry].status = (CmdSuspend | CmdMulticastList) << 16;
                sp->tx_ring[entry].link =
-                 virt_to_bus(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]);
+                       virt_to_bus(&sp->tx_ring[(entry + 1) % TX_RING_SIZE]);
                sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
                setup_params = (u16 *)&sp->tx_ring[entry].tx_desc_addr;
                *setup_params++ = dev->mc_count*6;
@@ -1651,36 +1473,39 @@ set_rx_mode(struct device *dev)
                        *setup_params++ = *eaddrs++;
                }
 
-               sp->last_cmd->command &= ~CmdSuspend;
+               last_cmd->command &= ~CmdSuspend;
                /* Immediately trigger the command unit resume. */
                wait_for_cmd_done(ioaddr + SCBCmd);
                outw(CU_RESUME, ioaddr + SCBCmd);
-               sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-               restore_flags(flags);
        } else if (new_rx_mode == 0) {
-               /* This does not work correctly, but why not? */
                struct dev_mc_list *mclist;
-               u16 *eaddrs;
+               u16 *setup_params, *eaddrs;
                struct descriptor *mc_setup_frm = sp->mc_setup_frm;
-               u16 *setup_params = (u16 *)mc_setup_frm->params;
                int i;
 
                if (sp->mc_setup_frm_len < 10 + dev->mc_count*6
                        || sp->mc_setup_frm == NULL) {
-                       /* Allocate a new frame, 10bytes + addrs, with a few
-                          extra entries for growth. */
+                       /* Allocate a full setup frame, 10bytes + <max addrs>. */
                        if (sp->mc_setup_frm)
                                kfree(sp->mc_setup_frm);
-                       sp->mc_setup_frm_len = 10 + dev->mc_count*6 + 24;
+                       sp->mc_setup_busy = 0;
+                       sp->mc_setup_frm_len = 10 + multicast_filter_limit*6;
                        sp->mc_setup_frm = kmalloc(sp->mc_setup_frm_len, GFP_ATOMIC);
                        if (sp->mc_setup_frm == NULL) {
-                         printk(KERN_ERR "%s: Failed to allocate a setup frame.\n", dev->name);
+                               printk(KERN_ERR "%s: Failed to allocate a setup frame.\n",
+                                          dev->name);
                                sp->rx_mode = -1; /* We failed, try again. */
                                return;
                        }
                }
+               /* If we are busy, someone might be quickly adding to the MC list.
+                  Try again later when the list changes stop. */
+               if (sp->mc_setup_busy) {
+                       sp->rx_mode = -1;
+                       return;
+               }
                mc_setup_frm = sp->mc_setup_frm;
-               /* Construct the new setup frame. */
+               /* Fill the setup frame. */
                if (speedo_debug > 1)
                        printk(KERN_DEBUG "%s: Constructing a setup frame at %p, "
                                   "%d bytes.\n",
@@ -1688,7 +1513,7 @@ set_rx_mode(struct device *dev)
                mc_setup_frm->status = 0;
                mc_setup_frm->command = CmdSuspend | CmdIntr | CmdMulticastList;
                /* Link set below. */
-               setup_params = (u16 *)mc_setup_frm->params;
+               setup_params = (u16 *)&mc_setup_frm->params;
                *setup_params++ = dev->mc_count*6;
                /* Fill in the multicast addresses. */
                for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
@@ -1703,10 +1528,10 @@ set_rx_mode(struct device *dev)
                save_flags(flags);
                cli();
                entry = sp->cur_tx++ % TX_RING_SIZE;
-
-               if (speedo_debug > 5)
-                       printk(" CmdMCSetup frame length %d in entry %d.\n",
-                                  dev->mc_count, entry);
+               last_cmd = sp->last_cmd;
+               sp->last_cmd = mc_setup_frm;
+               sp->mc_setup_busy++;
+               restore_flags(flags);
 
                /* Change the command to a NoOp, pointing to the CmdMulti command. */
                sp->tx_skbuff[entry] = 0;
@@ -1715,41 +1540,21 @@ set_rx_mode(struct device *dev)
 
                /* Set the link in the setup frame. */
                mc_setup_frm->link =
-                 virt_to_bus(&(sp->tx_ring[sp->cur_tx % TX_RING_SIZE]));
+                       virt_to_bus(&(sp->tx_ring[(entry+1) % TX_RING_SIZE]));
 
-               sp->last_cmd->command &= ~CmdSuspend;
+               last_cmd->command &= ~CmdSuspend;
                /* Immediately trigger the command unit resume. */
                wait_for_cmd_done(ioaddr + SCBCmd);
                outw(CU_RESUME, ioaddr + SCBCmd);
-               sp->last_cmd = mc_setup_frm;
-               restore_flags(flags);
-               if (speedo_debug > 1)
-                       printk(KERN_DEBUG "%s: Last command at %p is %4.4x.\n",
-                                  dev->name, sp->last_cmd, sp->last_cmd->command);
+               if (speedo_debug > 5)
+                       printk(" CmdMCSetup frame length %d in entry %d.\n",
+                                  dev->mc_count, entry);
        }
 
        sp->rx_mode = new_rx_mode;
 }
 \f
 #ifdef MODULE
-#if (LINUX_VERSION_CODE < VERSION(1,3,38))     /* 1.3.38 and later */
-char kernel_version[] = UTS_RELEASE;
-#endif
-
-#if LINUX_VERSION_CODE > 0x20118
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("Intel i82557/i82558 EtherExpressPro driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(congenb, "i");
-MODULE_PARM(txfifo, "i");
-MODULE_PARM(rxfifo, "i");
-MODULE_PARM(txdmacount, "i");
-MODULE_PARM(rxdmacount, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(max_interrupt_work, "i");
-#endif
 
 int
 init_module(void)
@@ -1796,7 +1601,8 @@ int eepro100_probe(struct device *dev)
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
index e68c0d64dba5fcc9c609f044b58f97732d984e33..59921bfc228f65ed8f555d2707475c4408f01dc3 100644 (file)
 /* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
-
-   Written 1994-95 by Mika Kuoppala
-
-   Copyright (C) 1994, 1995 by Mika Kuoppala
-   Based on skeleton.c and at1700.c by Donald Becker
+   
+   Written 1994-1998 by Mika Kuoppala
+   
+   Copyright (C) 1994-1998 by Mika Kuoppala
+   Based on skeleton.c and heavily on at1700.c by Donald Becker
 
    This software may be used and distributed according to the terms
    of the GNU Public Licence, incorporated herein by reference.
 
-   The author may be reached as miku@elt.icl.fi
+   The author may be reached as miku@iki.fi
 
    This driver supports following cards :
        - ICL EtherTeam 16i
-       - ICL EtherTeam 32 EISA
+       - ICL EtherTeam 32 EISA 
+         (Uses true 32 bit transfers rather than 16i compability mode)
+
+   Example Module usage:
+        insmod eth16i.o ioaddr=0x2a0 mediatype=bnc
+
+       mediatype can be one of the following: bnc,tp,dix,auto,eprom
 
+       'auto' will try to autoprobe mediatype.
+       'eprom' will use whatever type defined in eprom.
+
+   I have benchmarked driver with PII/300Mhz as a ftp client
+   and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec.
+   
    Sources:
      - skeleton.c  a sample network driver core for linux,
        written by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
-     - at1700.c a driver for Allied Telesis AT1700, written
+     - at1700.c a driver for Allied Telesis AT1700, written 
        by Donald Becker.
      - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
        written by Markku Viima
      - The Fujitsu MB86965 databook.
-
-   Valuable assistance from:
-       Markku Viima (ICL)
-       Ari Valve (ICL)
+   
+   Author thanks following persons due to their valueble assistance:    
+        Markku Viima (ICL)
+       Ari Valve (ICL)      
+       Donald Becker
+       Kurt Huwig <kurt@huwig.de>
 
    Revision history:
 
    Version     Date            Description
-
-   0.01                15.12-94        Initial version (card detection)
+   
+   0.01         15.12-94        Initial version (card detection)
    0.02         23.01-95        Interrupt is now hooked correctly
    0.03         01.02-95        Rewrote initialization part
    0.04         07.02-95        Base skeleton done...
-                               Made a few changes to signature checking
-                               to make it a bit reliable.
-                               - fixed bug in tx_buf mapping
-                               - fixed bug in initialization (DLC_EN
-                                 wasn't enabled when initialization
-                                 was done.)
-   0.05                08.02-95        If there were more than one packet to send,
-                               transmit was jammed due to invalid
-                               register write...now fixed
-   0.06         19.02-95        Rewrote interrupt handling
+                                Made a few changes to signature checking
+                                to make it a bit reliable.
+                                - fixed bug in tx_buf mapping
+                                - fixed bug in initialization (DLC_EN
+                                  wasn't enabled when initialization
+                                  was done.)
+   0.05         08.02-95        If there were more than one packet to send,
+                                transmit was jammed due to invalid
+                                register write...now fixed
+   0.06         19.02-95        Rewrote interrupt handling        
    0.07         13.04-95        Wrote EEPROM read routines
                                 Card configuration now set according to
-                               data read from EEPROM
+                                data read from EEPROM
    0.08         23.06-95        Wrote part that tries to probe used interface
                                 port if AUTO is selected
 
-   0.09         01.09-95       Added module support
-
-   0.10         04.09-95       Fixed receive packet allocation to work
-                               with kernels > 1.3.x
+   0.09         01.09-95        Added module support
+   
+   0.10         04.09-95        Fixed receive packet allocation to work
+                                with kernels > 1.3.x
+      
+   0.20                20.09-95        Added support for EtherTeam32 EISA      
 
-   0.20                20.09-95        Added support for EtherTeam32 EISA
-
-   0.21         17.10-95        Removed the unnecessary extern
+   0.21         17.10-95        Removed the unnecessary extern 
                                init_etherdev() declaration. Some
                                other cleanups.
+                               
+   0.22                22.02-96        Receive buffer was not flushed
+                               correctly when faulty packet was
+                               received. Now fixed.
+
+   0.23                26.02-96        Made resetting the adapter      
+                               more reliable.
+   
+   0.24                27.02-96        Rewrote faulty packet handling in eth16i_rx
+
+   0.25                22.05-96        kfree() was missing from cleanup_module.
+
+   0.26                11.06-96        Sometimes card was not found by 
+                               check_signature(). Now made more reliable.
+   
+   0.27                23.06-96        Oops. 16 consecutive collisions halted 
+                               adapter. Now will try to retransmit 
+                               MAX_COL_16 times before finally giving up.
+   
+   0.28                28.10-97        Added dev_id parameter (NULL) for free_irq
+
+   0.29         29.10-97        Multiple card support for module users
+
+   0.30         30.10-97        Fixed irq allocation bug.
+                                (request_irq moved from probe to open)
+
+   0.30a        21.08-98        Card detection made more relaxed. Driver
+                                had problems with some TCP/IP-PROM boots
+                               to find the card. Suggested by 
+                               Kurt Huwig <kurt@huwig.de>
+
+   0.31         28.08-98        Media interface port can now be selected
+                                with module parameters or kernel
+                               boot parameters. 
+
+   0.32         31.08-98        IRQ was never freed if open/close 
+                                pair wasn't called. Now fixed.
+   
+   0.33         10.09-98        When eth16i_open() was called after
+                                eth16i_close() chip never recovered.
+                               Now more shallow reset is made on
+                               close.
+
    Bugs:
-       In some cases the interface autoprobing code doesn't find
-       the correct interface type. In this case you can
-       manually choose the interface type in DOS with E16IC.EXE which is
+       In some cases the media interface autoprobing code doesn't find 
+       the correct interface type. In this case you can 
+       manually choose the interface type in DOS with E16IC.EXE which is 
        configuration software for EtherTeam16i and EtherTeam32 cards.
+       This is also true for IRQ setting. You cannot use module
+       parameter to configure IRQ of the card (yet). 
 
    To do:
        - Real multicast support
+       - Rewrite the media interface autoprobing code. Its _horrible_ !
+       - Possibly merge all the MB86965 specific code to external
+         module for use by eth16.c and Donald's at1700.c
+       - IRQ configuration with module parameter. I will do
+         this when i will get enough info about setting
+         irq without configuration utility.
 */
 
-static char *version =
-       "eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@elt.icl.fi)\n";
+static char *version = 
+    "eth16i.c: v0.33 10-09-98 Mika Kuoppala (miku@iki.fi)\n";
 
 #include <linux/module.h>
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
+#include <linux/types.h>                 
+#include <linux/fcntl.h>                 
+#include <linux/interrupt.h>             
+#include <linux/ptrace.h>                
+#include <linux/ioport.h>                
+#include <linux/in.h>            
+#include <linux/malloc.h>                
+#include <linux/string.h>                
 #include <linux/errno.h>
-#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
+#include <asm/system.h>                  
+#include <asm/bitops.h>                  
+#include <asm/io.h>              
 #include <asm/dma.h>
-#include <asm/delay.h>
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20123
+#include <linux/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(x) x
+#endif
+
+#if LINUX_VERSION_CODE < 0x20138
+#define test_and_set_bit(val,addr) set_bit(val,addr)
+#endif
+
+#if LINUX_VERSION_CODE < 0x020100
+typedef struct enet_statistics eth16i_stats_type;
+#else
+typedef struct net_device_stats eth16i_stats_type;
+#endif
 
 /* Few macros */
-#define BIT(a)                 ( (1 << (a)) )
-#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
+#define BIT(a)                ( (1 << (a)) )  
+#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr))) 
 #define BITCLR(ioaddr, bnum)   ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
 
 /* This is the I/O address space for Etherteam 16i adapter. */
-#define ETH16I_IO_EXTENT 32
+#define ETH16I_IO_EXTENT       32
 
 /* Ticks before deciding that transmit has timed out */
-#define TIMEOUT_TICKS          30
+#define TX_TIMEOUT             (400*HZ/1000)
 
 /* Maximum loop count when receiving packets */
-#define MAX_RX_LOOP            40
+#define MAX_RX_LOOP            20
 
 /* Some interrupt masks */
-#define ETH16I_INTR_ON        0x8f82
+#define ETH16I_INTR_ON        0xef8a       /* Higher is receive mask */
 #define ETH16I_INTR_OFF               0x0000
-
+        
 /* Buffers header status byte meanings */
 #define PKT_GOOD               BIT(5)
 #define PKT_GOOD_RMT           BIT(4)
@@ -131,6 +216,7 @@ static char *version =
 #define NET_BUSY               BIT(6)
 #define TX_PKT_RCD             BIT(5)
 #define CR_LOST                BIT(4)
+#define TX_JABBER_ERR         BIT(3)
 #define COLLISION              BIT(2)
 #define COLLISIONS_16          BIT(1)
 
@@ -142,7 +228,7 @@ static char *version =
 #define ALIGN_ERR              BIT(2)
 #define CRC_ERR                BIT(1)
 #define RX_BUF_OVERFLOW        BIT(0)
-
+              
 /* Transmit Interrupt Enable Register (DLCR2) */
 #define TX_INTR_REG            2
 #define TX_INTR_DONE           BIT(7)
@@ -181,18 +267,18 @@ static char *version =
 #define SRAM_CYCLE_TIME_100NS  BIT(6)
 #define SYSTEM_BUS_WIDTH_8     BIT(5)       /* 1 = 8bit, 0 = 16bit */
 #define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
-#define TBS1                   BIT(3)
+#define TBS1                   BIT(3)       
 #define TBS0                   BIT(2)
-#define MBS1                   BIT(1)       /* 00=8kb,  01=16kb  */
-#define MBS0                   BIT(0)       /* 10=32kb, 11=64kb  */
+#define SRAM_BS1               BIT(1)       /* 00=8kb,  01=16kb  */
+#define SRAM_BS0               BIT(0)       /* 10=32kb, 11=64kb  */
 
-#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */
-#define ETH16I_TX_BUF_SIZE     2             /* 2 = 8kb, 3 = 16kb */
-#endif
-#define TX_BUF_1x2048            0
-#define TX_BUF_2x2048            1
-#define TX_BUF_2x4098            2
-#define TX_BUF_2x8192            3
+#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */ 
+#define ETH16I_TX_BUF_SIZE     3             /* 2 = 8kb, 3 = 16kb */
+#endif                                      
+#define TX_BUF_1x2048          0
+#define TX_BUF_2x2048          1
+#define TX_BUF_2x4098          2
+#define TX_BUF_2x8192          3
 
 /* Configuration Register 1 (DLCR7) */
 #define CONFIG_REG_1           7
@@ -212,18 +298,21 @@ static char *version =
 #define HASH_TABLE_RB          1
 
 /* Buffer memory ports */
-#define BUFFER_MEM_PORT_LB    8
-#define DATAPORT              BUFFER_MEM_PORT_LB
-#define BUFFER_MEM_PORT_HB    9
+#define BUFFER_MEM_PORT_LB     8
+#define DATAPORT               BUFFER_MEM_PORT_LB
+#define BUFFER_MEM_PORT_HB     9
 
 /* 16 Collision control register (BMPR11) */
 #define COL_16_REG             11
 #define HALT_ON_16             0x00
 #define RETRANS_AND_HALT_ON_16 0x02
 
+/* Maximum number of attempts to send after 16 concecutive collisions */
+#define MAX_COL_16            10
+
 /* DMA Burst and Transceiver Mode Register (BMPR13) */
 #define TRANSCEIVER_MODE_REG   13
-#define TRANSCEIVER_MODE_RB    2
+#define TRANSCEIVER_MODE_RB    2         
 #define IO_BASE_UNLOCK        BIT(7)
 #define LOWER_SQUELCH_TRESH    BIT(6)
 #define LINK_TEST_DISABLE      BIT(5)
@@ -232,9 +321,8 @@ static char *version =
 
 /* Filter Self Receive Register (BMPR14)  */
 #define FILTER_SELF_RX_REG     14
-#define SKIP_RECEIVE_PACKET    BIT(2)
+#define SKIP_RX_PACKET         BIT(2)
 #define FILTER_SELF_RECEIVE    BIT(0)
-#define RX_BUF_SKIP_PACKET     SKIP_RECEIVE_PACKET | FILTER_SELF_RECEIVE
 
 /* EEPROM Control Register (BMPR 16) */
 #define EEPROM_CTRL_REG        16
@@ -254,19 +342,20 @@ static char *version =
 #define EEPROM_READ            0x80
 
 /* NMC93CSx6 EEPROM Addresses */
-#define E_NODEID_0                     0x02
-#define E_NODEID_1                     0x03
-#define E_NODEID_2                     0x04
-#define E_PORT_SELECT                  0x14
-  #define E_PORT_BNC                   0
-  #define E_PORT_DIX                   1
-  #define E_PORT_TP                    2
-  #define E_PORT_AUTO                  3
-#define E_PRODUCT_CFG                  0x30
-
+#define E_NODEID_0             0x02
+#define E_NODEID_1             0x03
+#define E_NODEID_2             0x04
+#define E_PORT_SELECT          0x14
+  #define E_PORT_BNC           0x00
+  #define E_PORT_DIX           0x01
+  #define E_PORT_TP            0x02
+  #define E_PORT_AUTO          0x03
+  #define E_PORT_FROM_EPROM    0x04
+#define E_PRODUCT_CFG          0x30
 
 /* Macro to slow down io between EEPROM clock transitions */
-#define eeprom_slow_io()       udelay(100)     /* FIXME: smaller but right value here */
+#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0)
 
 /* Jumperless Configuration Register (BMPR19) */
 #define JUMPERLESS_CONFIG      19
@@ -277,31 +366,24 @@ static char *version =
 #define RESET                  ID_ROM_0
 
 /* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] __initdata = {
-       0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
-};
+static unsigned int eth16i_portlist[] =
+   { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 };
 
-static unsigned int eth32i_portlist[] __initdata = {
-       0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
-       0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
-};
+static unsigned int eth32i_portlist[] =
+   { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+     0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
 
 /* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] __initdata = {
-       9, 10, 5, 15
-};
+static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15, 0 };
+#define NUM_OF_ISA_IRQS    4
 
 /* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] __initdata = {
-       3, 5, 7, 9, 10, 11, 12, 15
-};
-
+static unsigned int eth32i_irqmap[] = { 3, 5, 7, 9, 10, 11, 12, 15, 0 };  
 #define EISA_IRQ_REG   0xc89
+#define NUM_OF_EISA_IRQS   8
 
-static unsigned int eth16i_tx_buf_map[] = {
-       2048, 2048, 4096, 8192 
-};
-unsigned int boot = 1;
+static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
+static unsigned int boot = 1;
 
 /* Use 0 for production, 1 for verification, >2 for debug */
 #ifndef ETH16I_DEBUG
@@ -310,60 +392,76 @@ unsigned int boot = 1;
 static unsigned int eth16i_debug = ETH16I_DEBUG;
 
 /* Information for each board */
-struct eth16i_local
-{
-       struct net_device_stats stats;
-       unsigned int tx_started:1;
-       unsigned char tx_queue;        /* Number of packets in transmit buffer */
-       unsigned short tx_queue_len;
-       unsigned int tx_buf_size;
-       unsigned long open_time;
+
+struct eth16i_local {
+       eth16i_stats_type stats;
+       unsigned char     tx_started;
+       unsigned char     tx_buf_busy;
+       unsigned short    tx_queue;  /* Number of packets in transmit buffer */
+       unsigned short    tx_queue_len;         
+       unsigned int      tx_buf_size;
+       unsigned long     open_time;
+       unsigned long     tx_buffered_packets;  
+       unsigned long     col_16;
 };
 
 /* Function prototypes */
 
-extern int eth16i_probe(struct device *dev);
-
-static int eth16i_probe1(struct device *dev, short ioaddr);
-static int eth16i_check_signature(short ioaddr);
-static int eth16i_probe_port(short ioaddr);
-static void eth16i_set_port(short ioaddr, int porttype);
-static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l);
-static int eth16i_receive_probe_packet(short ioaddr);
-static int eth16i_get_irq(short ioaddr);
-static int eth16i_read_eeprom(int ioaddr, int offset);
-static int eth16i_read_eeprom_word(int ioaddr);
-static void eth16i_eeprom_cmd(int ioaddr, unsigned char command);
-static int eth16i_open(struct device *dev);
-static int eth16i_close(struct device *dev);
-static int eth16i_tx(struct sk_buff *skb, struct device *dev);
-static void eth16i_rx(struct device *dev);
-static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void eth16i_multicast(struct device *dev);
-static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
-static void eth16i_initialize(struct device *dev);
-static struct net_device_stats *eth16i_get_stats(struct device *dev);
+extern int     eth16i_probe(struct device *dev);
+
+static int     eth16i_probe1(struct device *dev, int ioaddr);
+static int     eth16i_check_signature(int ioaddr);
+static int     eth16i_probe_port(int ioaddr);
+static void    eth16i_set_port(int ioaddr, int porttype);
+static int     eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l);
+static int     eth16i_receive_probe_packet(int ioaddr);
+static int     eth16i_get_irq(int ioaddr);
+static int     eth16i_read_eeprom(int ioaddr, int offset);
+static int     eth16i_read_eeprom_word(int ioaddr);
+static void    eth16i_eeprom_cmd(int ioaddr, unsigned char command);
+static int     eth16i_open(struct device *dev);
+static int     eth16i_close(struct device *dev);
+static int     eth16i_tx(struct sk_buff *skb, struct device *dev);
+static void    eth16i_rx(struct device *dev);
+static void    eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void    eth16i_reset(struct device *dev);
+static void    eth16i_skip_packet(struct device *dev);
+static void    eth16i_multicast(struct device *dev); 
+static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
+static void    eth16i_initialize(struct device *dev);
+
+#if 0
+static int     eth16i_set_irq(struct device *dev);
+#endif
+
+#ifdef MODULE
+static ushort  eth16i_parse_mediatype(const char* s);
+#endif
+
+static struct enet_statistics *eth16i_get_stats(struct device *dev);
 
 static char *cardname = "ICL EtherTeam 16i/32";
 
-#ifdef HAVE_DEVLIST
+#ifdef HAVE_DEVLIST 
+
 /* Support for alternate probe manager */
-/struct netdev_entry eth16i_drv =
-   {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list};
+/struct netdev_entry eth16i_drv = 
+ {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list}; 
 
 #else  /* Not HAVE_DEVLIST */
+
 __initfunc(int eth16i_probe(struct device *dev))
 {
        int i;
        int ioaddr;
        int base_addr = dev ? dev->base_addr : 0;
+    
+       if(eth16i_debug > 4) 
+               printk(KERN_DEBUG "Probing started for %s\n", cardname);
 
-       if(eth16i_debug > 4)
-               printk("Probing started for %s\n", cardname);
-
-       if(base_addr > 0x1ff)           /* Check only single location */
+       if(base_addr > 0x1ff)           /* Check only single location */
                return eth16i_probe1(dev, base_addr);
-       else if(base_addr != 0)         /* Don't probe at all */
+       else if(base_addr != 0)         /* Don't probe at all */
                return ENXIO;
 
        /* Seek card from the ISA io address space */
@@ -377,88 +475,107 @@ __initfunc(int eth16i_probe(struct device *dev))
        /* Seek card from the EISA io address space */
        for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) {
                if(check_region(ioaddr, ETH16I_IO_EXTENT))
-       continue;
+                       continue;
                if(eth16i_probe1(dev, ioaddr) == 0)
-       return 0;
-        }
+                       return 0;
+       }
 
        return ENODEV;
 }
-#endif /* Not HAVE_DEVLIST */
+#endif  /* Not HAVE_DEVLIST */
 
-__initfunc(static int eth16i_probe1(struct device *dev, short ioaddr))
+__initfunc(static int eth16i_probe1(struct device *dev, int ioaddr))
 {
        static unsigned version_printed = 0;
-       unsigned int irq = 0;
-       boot = 1;          /* To inform initialization that we are in boot probe */
+       boot = 1;  /* To inform initilization that we are in boot probe */
 
        /*
-                The MB86985 chip has on register which holds information in which
-                io address the chip lies. First read this register and compare
-                it to our current io address and if match then this could
-                be our chip.
-       */
+         The MB86985 chip has on register which holds information in which 
+         io address the chip lies. First read this register and compare
+         it to our current io address and if match then this could
+         be our chip.
+         */
 
        if(ioaddr < 0x1000) {
-               if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] != ioaddr)
+       
+               if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] 
+                  != ioaddr)
                        return -ENODEV;
        }
 
        /* Now we will go a bit deeper and try to find the chip's signature */
 
-       if(eth16i_check_signature(ioaddr) != 0) /* Can we find the signature here */
+       if(eth16i_check_signature(ioaddr) != 0) 
                return -ENODEV;
 
-       /*
-                Now it seems that we have found an ethernet chip in this particular
-                ioaddr. The MB86985 chip has this feature, that when you read a
-                certain register it will increase its io base address to next
-                configurable slot. Now when we have found the chip, first thing is
-                to make sure that the chip's ioaddr will hold still here.
-       */
+       /* 
+          Now it seems that we have found a ethernet chip in this particular
+          ioaddr. The MB86985 chip has this feature, that when you read a 
+          certain register it will increase it's io base address to next
+          configurable slot. Now when we have found the chip, first thing is
+          to make sure that the chip's ioaddr will hold still here.
+          */
 
        eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
        outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
 
-       outb(0x00, ioaddr + RESET);             /* Will reset some parts of chip */
-       BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* This will disable the data link */
+       outb(0x00, ioaddr + RESET);             /* Reset some parts of chip */
+       BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* Disable the data link */
 
        if(dev == NULL)
-               dev = init_etherdev(0, sizeof(struct eth16i_local));
+               dev = init_etherdev(0, 0);
 
        if( (eth16i_debug & version_printed++) == 0)
-               printk(version);
+               printk(KERN_INFO "%s", version);
 
        dev->base_addr = ioaddr;
+       
+#if 0
+       if(dev->irq) {
+               if(eth16i_set_irq(dev)) {
+                       dev->irq = eth16i_get_irq(ioaddr);
+               }
+
+       }
+       else {
+#endif
 
-       irq = eth16i_get_irq(ioaddr);
-       dev->irq = irq;
+       dev->irq = eth16i_get_irq(ioaddr);
 
        /* Try to obtain interrupt vector */
-       if(request_irq(dev->irq, &eth16i_interrupt, 0, "eth16i", dev)) {
-               printk("%s: %s at %#3x, but is unusable due
-                      conflict on IRQ %d.\n", dev->name, cardname, ioaddr, irq);
-               return EAGAIN;
+
+       if (request_irq(dev->irq, (void *)&eth16i_interrupt, 0, "eth16i", dev)) {       
+               printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n", 
+                      dev->name, cardname, ioaddr, dev->irq);
+               return -EAGAIN;
        }
 
-       printk("%s: %s at %#3x, IRQ %d, ",
-        dev->name, cardname, ioaddr, dev->irq);
+#if 0
+       irq2dev_map[dev->irq] = dev;
+#endif
+
+       printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
+              dev->name, cardname, ioaddr, dev->irq);
 
        /* Let's grab the region */
        request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i");
 
        /* Now we will have to lock the chip's io address */
        eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-       outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
+       outb(0x38, ioaddr + TRANSCEIVER_MODE_REG); 
 
-       eth16i_initialize(dev);  /* Initialize rest of the chip's registers */
+       eth16i_initialize(dev);   /* Initialize rest of the chip's registers */
 
        /* Now let's same some energy by shutting down the chip ;) */
        BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
 
        /* Initialize the device structure */
-       if(dev->priv == NULL)
+       if(dev->priv == NULL) {
                dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL);
+               if(dev->priv == NULL)
+                       return -ENOMEM;
+       }
+
        memset(dev->priv, 0, sizeof(struct eth16i_local));
 
        dev->open               = eth16i_open;
@@ -478,7 +595,7 @@ __initfunc(static int eth16i_probe1(struct device *dev, short ioaddr))
 
 static void eth16i_initialize(struct device *dev)
 {
-       short ioaddr = dev->base_addr;
+       int ioaddr = dev->base_addr;
        int i, node_w = 0;
        unsigned char node_byte = 0;
 
@@ -489,11 +606,9 @@ static void eth16i_initialize(struct device *dev)
                ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
        }
 
-       for(i = 0; i < 6; i++) 
-       {
+       for(i = 0; i < 6; i++) { 
                outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
-               if(boot) 
-               {
+               if(boot) {
                        printk("%02x", inb(ioaddr + NODE_ID_0 + i));
                        if(i != 5)
                                printk(":");
@@ -502,14 +617,14 @@ static void eth16i_initialize(struct device *dev)
 
        /* Now we will set multicast addresses to accept none */
        eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
-       for(i = 0; i < 8; i++)
+       for(i = 0; i < 8; i++) 
                outb(0x00, ioaddr + HASH_TABLE_0 + i);
 
        /*
-                Now let's disable the transmitter and receiver, set the buffer ram
-                cycle time, bus width and buffer data path width. Also we shall
-                set transmit buffer size and total buffer size.
-       */
+         Now let's disable the transmitter and receiver, set the buffer ram 
+         cycle time, bus width and buffer data path width. Also we shall
+         set transmit buffer size and total buffer size.
+         */
 
        eth16i_select_regbank(2, ioaddr);
 
@@ -519,38 +634,56 @@ static void eth16i_initialize(struct device *dev)
        if( (node_w & 0xFF00) == 0x0800)
                node_byte |= BUFFER_WIDTH_8;
 
-       node_byte |= MBS1;
+       node_byte |= SRAM_BS1;
 
        if( (node_w & 0x00FF) == 64)
-               node_byte |= MBS0;
+               node_byte |= SRAM_BS0;
 
        node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
 
        outb(node_byte, ioaddr + CONFIG_REG_0);
 
        /* We shall halt the transmitting, if 16 collisions are detected */
-       outb(RETRANS_AND_HALT_ON_16, ioaddr + COL_16_REG);
+       outb(HALT_ON_16, ioaddr + COL_16_REG);
 
-       if(boot) /* Now set port type */
-       {
-               char *porttype[] = {"BNC", "DIX", "TP", "AUTO"};
+#ifdef MODULE
+       /* if_port already set by init_module() */
+#else
+       dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ? 
+               dev->mem_start : E_PORT_FROM_EPROM;
+#endif
 
-               ushort ptype = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
-               dev->if_port = (ptype & 0x00FF);
+       /* Set interface port type */
+       if(boot) {
+               char *porttype[] = {"BNC", "DIX", "TP", "AUTO", "FROM_EPROM" };
 
-               printk(" %s interface.\n", porttype[dev->if_port]);
+               switch(dev->if_port)
+               {
+
+               case E_PORT_FROM_EPROM:
+                       dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
+                       break;
+
+               case E_PORT_AUTO:
+                       dev->if_port = eth16i_probe_port(ioaddr);
+                       break;
+                       
+               case E_PORT_BNC:
+               case E_PORT_TP:
+               case E_PORT_DIX:
+                       break;
+               }
 
-               if(ptype == E_PORT_AUTO)
-                       ptype = eth16i_probe_port(ioaddr);
+               printk(" %s interface.\n", porttype[dev->if_port]);
 
-               eth16i_set_port(ioaddr, ptype);
+               eth16i_set_port(ioaddr, dev->if_port);
        }
 
        /* Set Receive Mode to normal operation */
        outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
 }
 
-static int eth16i_probe_port(short ioaddr)
+static int eth16i_probe_port(int ioaddr)
 {
        int i;
        int retcode;
@@ -579,136 +712,163 @@ static int eth16i_probe_port(short ioaddr)
                eth16i_set_port(ioaddr, i);
 
                if(eth16i_debug > 1)
-                       printk("Set port number %d\n", i);
+                       printk(KERN_DEBUG "Set port number %d\n", i);
 
                retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
-               if(retcode == 0) 
-               {
+               if(retcode == 0) {
                        retcode = eth16i_receive_probe_packet(ioaddr);
-                       if(retcode != -1) 
-                       {
+                       if(retcode != -1) {
                                if(eth16i_debug > 1)
-                                       printk("Eth16i interface port found at %d\n", i);
+                                       printk(KERN_DEBUG "Eth16i interface port found at %d\n", i);
                                return i;
                        }
                }
                else {
                        if(eth16i_debug > 1)
-                               printk("TRANSMIT_DONE timeout\n");
+                               printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n");
                }
        }
 
        if( eth16i_debug > 1)
-               printk("Using default port\n");
+               printk(KERN_DEBUG "Using default port\n");
 
        return E_PORT_BNC;
 }
 
-static void eth16i_set_port(short ioaddr, int porttype)
-{
+static void eth16i_set_port(int ioaddr, int porttype)
+{ 
        unsigned short temp = 0;
 
        eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
        outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
 
        temp |= DIS_AUTO_PORT_SEL;
-       switch(porttype) 
-       {
 
-               case E_PORT_BNC :
-                       temp |= AUI_SELECT;
-                       break;
+       switch(porttype) {
 
-               case E_PORT_TP :
-                       break;
+       case E_PORT_BNC :
+               temp |= AUI_SELECT;
+               break;
+
+       case E_PORT_TP :
+               break;
+
+       case E_PORT_DIX :
+               temp |= AUI_SELECT;
+               BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
+               break;
+       }  
 
-               case E_PORT_DIX :
-                       temp |= AUI_SELECT;
-                       BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
-                       break;
-       }
        outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
 
        if(eth16i_debug > 1) {
-               printk("TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
-               printk("TRANSCEIVER_MODE_REG = %x\n", inb(ioaddr+TRANSCEIVER_MODE_REG));
+               printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
+               printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n", 
+                      inb(ioaddr+TRANSCEIVER_MODE_REG));
        }
 }
 
-static int eth16i_send_probe_packet(short ioaddr, unsigned char *b, int l)
+static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
 {
        int starttime;
 
        outb(0xff, ioaddr + TX_STATUS_REG);
 
        outw(l, ioaddr + DATAPORT);
-       outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
+       outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);  
 
        starttime = jiffies;
-       outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
+       outb(TX_START | 1, ioaddr + TRANSMIT_START_REG); 
 
-       while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) 
-               if( (jiffies - starttime) > TIMEOUT_TICKS)
-                       break;
-       return(0);
+       while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
+               if( (jiffies - starttime) > TX_TIMEOUT) {
+                       return -1;
+               }
+       }
+
+       return 0;
 }
 
-static int eth16i_receive_probe_packet(short ioaddr)
+static int eth16i_receive_probe_packet(int ioaddr)
 {
        int starttime;
 
        starttime = jiffies;
 
-       while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) 
-       {
-               if( (jiffies - starttime) > TIMEOUT_TICKS) 
-               {
+       while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
+               if( (jiffies - starttime) > TX_TIMEOUT) {
+
                        if(eth16i_debug > 1)
-                               printk("Timeout occurred waiting transmit packet received\n");
+                               printk(KERN_DEBUG "Timeout occured waiting transmit packet received\n");
                        starttime = jiffies;
-                       while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) 
-                       {
-                               if( (jiffies - starttime) > TIMEOUT_TICKS) 
-                               {
+                       while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
+                               if( (jiffies - starttime) > TX_TIMEOUT) {
                                        if(eth16i_debug > 1)
-                                               printk("Timeout occurred waiting receive packet\n");
+                                               printk(KERN_DEBUG "Timeout occured waiting receive packet\n");
                                        return -1;
                                }
                        }
 
                        if(eth16i_debug > 1)
-                               printk("RECEIVE_PACKET\n");
+                               printk(KERN_DEBUG "RECEIVE_PACKET\n");
                        return(0); /* Found receive packet */
                }
        }
 
        if(eth16i_debug > 1) {
-               printk("TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
-               printk("RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
+               printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
+               printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
        }
 
        return(0); /* Return success */
 }
 
-static int eth16i_get_irq(short ioaddr)
+#if 0
+static int eth16i_set_irq(struct device* dev)
+{
+       const int ioaddr = dev->base_addr;
+       const int irq = dev->irq;
+       int i = 0;
+
+       if(ioaddr < 0x1000) {           
+               while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq)
+                       i++;
+       
+               if(i < NUM_OF_ISA_IRQS) {
+                       u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+                       cbyte = (cbyte & 0x3F) | (i << 6);
+                       outb(cbyte, ioaddr + JUMPERLESS_CONFIG);
+                       return 0;
+               }
+       }
+       else {
+               printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name);
+       }
+       
+       return -1;
+
+}
+#endif
+
+static int eth16i_get_irq(int ioaddr)
 {
        unsigned char cbyte;
 
        if( ioaddr < 0x1000) {
                cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-       return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
-       } else {        /* Oh..the card is EISA so method getting IRQ different */
-       unsigned short index = 0;
-       cbyte = inb(ioaddr + EISA_IRQ_REG);
-       while( (cbyte & 0x01) == 0) {
-               cbyte = cbyte >> 1;
-               index++;
-                               }
-       return( eth32i_irqmap[ index ] );
+               return( eth16i_irqmap[ ((cbyte & 0xC0) >> 6) ] );
+       } else {  /* Oh..the card is EISA so method getting IRQ different */
+               unsigned short index = 0;
+               cbyte = inb(ioaddr + EISA_IRQ_REG);
+               while( (cbyte & 0x01) == 0) {
+                       cbyte = cbyte >> 1;
+                       index++;
+               }
+               return( eth32i_irqmap[ index ] );
        }
 }
 
-static int eth16i_check_signature(short ioaddr)
+static int eth16i_check_signature(int ioaddr)
 {
        int i;
        unsigned char creg[4] = { 0 };
@@ -718,36 +878,37 @@ static int eth16i_check_signature(short ioaddr)
                creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
 
                if(eth16i_debug > 1)
-       printk("eth16i: read signature byte %x at %x\n", creg[i],
-                                ioaddr + TRANSMIT_MODE_REG + i);
+                       printk("eth16i: read signature byte %x at %x\n", 
+                              creg[i],
+                              ioaddr + TRANSMIT_MODE_REG + i);
        }
 
        creg[0] &= 0x0F;      /* Mask collision cnr */
        creg[2] &= 0x7F;      /* Mask DCLEN bit */
 
-#if 0
-/*
-       This was removed because the card was sometimes left to state
-       from which it couldn't be find anymore. If there is need
-       to have a more strict check still this have to be fixed.
-*/
-       if( !(creg[0] == 0x06) && (creg[1] == 0x41)) ) {
+#ifdef 0
+       /* 
+          This was removed because the card was sometimes left to state
+          from which it couldn't be find anymore. If there is need
+          to more strict check still this have to be fixed.
+          */
+       if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) {
                if(creg[1] != 0x42)
                        return -1;
        }
 #endif
 
-       if( !( (creg[2] == 0x36) && (creg[3] == 0xE0)) ) 
-       {
-               creg[2] &= 0x42;
+       if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
+               creg[2] &= 0x40;
                creg[3] &= 0x03;
-
-               if( !( (creg[2] == 0x42) && (creg[3] == 0x00)) )
+               
+               if( !((creg[2] == 0x40) && (creg[3] == 0x00)) )
                        return -1;
        }
-
+       
        if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
                return -1;
+       
        if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
                return -1;
 
@@ -763,20 +924,22 @@ static int eth16i_read_eeprom(int ioaddr, int offset)
        data = eth16i_read_eeprom_word(ioaddr);
        outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
 
-       return(data);
+       return(data);  
 }
 
 static int eth16i_read_eeprom_word(int ioaddr)
 {
        int i;
        int data = 0;
-
+     
        for(i = 16; i > 0; i--) {
                outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
                eeprom_slow_io();
                outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
                eeprom_slow_io();
-               data = (data << 1) | ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+               data = (data << 1) | 
+                       ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+               
                eeprom_slow_io();
        }
 
@@ -800,25 +963,26 @@ static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
                eeprom_slow_io();
                outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
                eeprom_slow_io();
-       }
+       } 
 }
 
 static int eth16i_open(struct device *dev)
 {
        struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
        int ioaddr = dev->base_addr;
-
+       
        /* Powerup the chip */
        outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
 
        /* Initialize the chip */
-       eth16i_initialize(dev);
+       eth16i_initialize(dev);  
 
        /* Set the transmit buffer size */
        lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
 
-       if(eth16i_debug > 3)
-               printk("%s: transmit buffer size %d\n", dev->name, lp->tx_buf_size);
+       if(eth16i_debug > 0)
+               printk(KERN_DEBUG "%s: transmit buffer size %d\n", 
+                      dev->name, lp->tx_buf_size);
 
        /* Now enable Transmitter and Receiver sections */
        BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
@@ -832,15 +996,13 @@ static int eth16i_open(struct device *dev)
        lp->tx_queue_len = 0;
 
        /* Turn on interrupts*/
-       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);  
 
        dev->tbusy = 0;
        dev->interrupt = 0;
        dev->start = 1;
 
-#ifdef MODULE
        MOD_INC_USE_COUNT;
-#endif
 
        return 0;
 }
@@ -850,23 +1012,26 @@ static int eth16i_close(struct device *dev)
        struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
        int ioaddr = dev->base_addr;
 
-       lp->open_time = 0;
+       eth16i_reset(dev);
+
+       /* Turn off interrupts*/
+       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);  
 
-       dev->tbusy = 1;
        dev->start = 0;
+       dev->tbusy = 1;
+
+       lp->open_time = 0;
 
        /* Disable transmit and receive */
        BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
 
        /* Reset the chip */
-       outb(0xff, ioaddr + RESET);
-
-       /* Save some energy by switching off power */
-       BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+       /* outb(0xff, ioaddr + RESET); */
+       /* outw(0xffff, ioaddr + TX_STATUS_REG);    */
+       
+       outb(0x00, ioaddr + CONFIG_REG_1);
 
-#ifdef MODULE
        MOD_DEC_USE_COUNT;
-#endif
 
        return 0;
 }
@@ -875,88 +1040,120 @@ static int eth16i_tx(struct sk_buff *skb, struct device *dev)
 {
        struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
        int ioaddr = dev->base_addr;
+       int status = 0;
 
        if(dev->tbusy) {
-               /*
-                        If we get here, some higher level has decided that we are broken.
-                        There should really be a "kick me" function call instead.
-               */
+               
+               /* 
+                  If we get here, some higher level has decided that 
+                  we are broken. There should really be a "kick me" 
+                  function call instead. 
+                  */
 
                int tickssofar = jiffies - dev->trans_start;
-               if(tickssofar < TIMEOUT_TICKS)  /* Let's not rush with our timeout, */
-                       return 1;                     /* wait a couple of ticks first     */
+               if(tickssofar < TX_TIMEOUT)  
+                       return 1;                     
 
-               printk("%s: transmit timed out with status %04x, %s ?\n", dev->name,
-                inw(ioaddr + TX_STATUS_REG),
-                (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
-                "IRQ conflict" : "network cable problem");
+               outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
-               /* Let's dump all registers */
-               if(eth16i_debug > 0) {
-                       printk("%s: timeout regs: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-                        dev->name, inb(ioaddr + 0), inb(ioaddr + 1), inb(ioaddr + 2),
-                        inb(ioaddr + 3), inb(ioaddr + 4), inb(ioaddr + 5),
-                        inb(ioaddr + 6), inb(ioaddr + 7));
+               printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n", 
+                      dev->name,
+                      inw(ioaddr + TX_STATUS_REG), 
+                      (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? 
+                      "IRQ conflict" : "network cable problem");
 
+               dev->trans_start = jiffies;
 
-                       printk("lp->tx_queue = %d\n", lp->tx_queue);
-                       printk("lp->tx_queue_len = %d\n", lp->tx_queue_len);
-                       printk("lp->tx_started = %d\n", lp->tx_started);
+               /* Let's dump all registers */
+               if(eth16i_debug > 0) { 
+                       printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+                              dev->name, inb(ioaddr + 0), 
+                              inb(ioaddr + 1), inb(ioaddr + 2), 
+                              inb(ioaddr + 3), inb(ioaddr + 4), 
+                              inb(ioaddr + 5),
+                              inb(ioaddr + 6), inb(ioaddr + 7));
+
+                       printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
+                              dev->name, inb(ioaddr + TRANSMIT_START_REG),
+                              inb(ioaddr + COL_16_REG));
+
+                       printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
+                       printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
+                       printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
 
                }
 
                lp->stats.tx_errors++;
 
-               /* Now let's try to restart the adaptor */
-
-               BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-               outw(0xffff, ioaddr + RESET);
-               eth16i_initialize(dev);
-               outw(0xffff, ioaddr + TX_STATUS_REG);
-               BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+               eth16i_reset(dev);
 
-               lp->tx_started = 0;
-               lp->tx_queue = 0;
-               lp->tx_queue_len = 0;
+               dev->trans_start = jiffies;
 
                outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
 
-               dev->tbusy = 0;
-               dev->trans_start = jiffies;
        }
 
-       /* Block a timer based transmitter from overlapping. This could better be
-                done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+       /* 
+          If some higher layer thinks we've missed an tx-done interrupt
+          we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+          itself 
+          */
+       
+       if(skb == NULL) {
+#if LINUX_VERSION_CODE < 0x020100
+               dev_tint(dev);
+#endif
+               if(eth16i_debug > 0) 
+                       printk(KERN_WARNING "%s: Missed tx-done interrupt.\n", dev->name);
+               return 0;
+       }
+
+       /* Block a timer based transmitter from overlapping. 
+          This could better be done with atomic_swap(1, dev->tbusy), 
+          but set_bit() works as well. */
 
+       set_bit(0, (void *)&lp->tx_buf_busy);
+       
        /* Turn off TX interrupts */
        outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
-       if(test_and_set_bit(0, (void *)&dev->tbusy) != 0)
-               printk("%s: Transmitter access conflict.\n", dev->name);
+       if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) {
+               printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+               status = -1;
+       }
        else {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
                unsigned char *buf = skb->data;
 
-               outw(length, ioaddr + DATAPORT);
+               if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
+                       if(eth16i_debug > 0) 
+                               printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);  
+               } 
+               else {
+                       outw(length, ioaddr + DATAPORT);
 
-               if( ioaddr < 0x1000 )
-                       outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-               else 
-               {
-                       unsigned char frag = length % 4;
+                       if( ioaddr < 0x1000 ) 
+                               outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+                       else {
+                               unsigned char frag = length % 4;
 
-                       outsl(ioaddr + DATAPORT, buf, length >> 2);
+                               outsl(ioaddr + DATAPORT, buf, length >> 2);
 
-                       if( frag != 0 ) 
-                       {
-                               outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
-                               if( frag == 3 )
-                                       outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC) + 2), 1);
+                               if( frag != 0 ) {
+                                       outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+                                       if( frag == 3 ) 
+                                               outsw(ioaddr + DATAPORT, 
+                                                     (buf + (length & 0xFFFC) + 2), 1);
+                               }
                        }
-               }
 
-               lp->tx_queue++;
-               lp->tx_queue_len += length + 2;
+                       lp->tx_buffered_packets++;
+                       lp->tx_queue++;
+                       lp->tx_queue_len += length + 2;
+                       
+               }
+               
+               lp->tx_buf_busy = 0;
 
                if(lp->tx_started == 0) {
                        /* If the transmitter is idle..always trigger a transmit */
@@ -971,15 +1168,21 @@ static int eth16i_tx(struct sk_buff *skb, struct device *dev)
                        /* There is still more room for one more packet in tx buffer */
                        dev->tbusy = 0;
                }
-
+               
                outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
+               
                /* Turn TX interrupts back on */
                /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
-       }
+               status = 0;
+       } 
+
+#if LINUX_VERSION_CODE >= 0x020100
        dev_kfree_skb(skb);
+#else
+       dev_kfree_skb(skb, FREE_WRITE);
+#endif
 
-       return 0;
+       return status;
 }
 
 static void eth16i_rx(struct device *dev)
@@ -989,71 +1192,63 @@ static void eth16i_rx(struct device *dev)
        int boguscount = MAX_RX_LOOP;
 
        /* Loop until all packets have been read */
-       while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) 
-       {
-               /* Read status byte from receive buffer */
+       while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
+
+               /* Read status byte from receive buffer */ 
                ushort status = inw(ioaddr + DATAPORT);
 
-               if(eth16i_debug > 4)
-                       printk("%s: Receiving packet mode %02x status %04x.\n",
-                               dev->name, inb(ioaddr + RECEIVE_MODE_REG), status);
+               /* Get the size of the packet from receive buffer */
+               ushort pkt_len = inw(ioaddr + DATAPORT);
 
-               if( !(status & PKT_GOOD) ) 
-               {
-                       /* Hmm..something went wrong. Let's check what error occurred */
+               if(eth16i_debug > 4)
+                       printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n", 
+                              dev->name, 
+                              inb(ioaddr + RECEIVE_MODE_REG), status);
+               
+               if( !(status & PKT_GOOD) ) {
                        lp->stats.rx_errors++;
-                       if( status & PKT_SHORT)
+
+                       if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) {
                                lp->stats.rx_length_errors++;
-                       if( status & PKT_ALIGN_ERR )
-                               lp->stats.rx_frame_errors++;
-                       if( status & PKT_CRC_ERR )
-                               lp->stats.rx_crc_errors++;
-                       if( status & PKT_RX_BUF_OVERFLOW)
-                               lp->stats.rx_over_errors++;
+                               eth16i_reset(dev);
+                               return;         
+                       }
+                       else { 
+                               eth16i_skip_packet(dev);
+                               lp->stats.rx_dropped++;
+                       }       
                }
-               else
-               {        /* Ok so now we should have a good packet */
+               else {   /* Ok so now we should have a good packet */
                        struct sk_buff *skb;
-                       /* Get the size of the packet from receive buffer */
-                       ushort pkt_len = inw(ioaddr + DATAPORT);
-
-                       if(pkt_len > ETH_FRAME_LEN) 
-                       {
-                               printk("%s: %s claimed a very large packet, size of %d bytes.\n",
-                               dev->name, cardname, pkt_len);
-                               outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
-                               lp->stats.rx_dropped++;
-                               break;
-                       }
 
                        skb = dev_alloc_skb(pkt_len + 3);
-                       if( skb == NULL ) 
-                       {
-                               printk("%s: Couldn't allocate memory for packet (len %d)\n",
-                               dev->name, pkt_len);
-                               outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+                       if( skb == NULL ) {
+                               printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n", 
+                                      dev->name, pkt_len);
+                               eth16i_skip_packet(dev);
                                lp->stats.rx_dropped++;
                                break;
                        }
+
                        skb->dev = dev;
                        skb_reserve(skb,2);
-                       /*
-                               Now let's get the packet out of buffer.
-                               size is (pkt_len + 1) >> 1, cause we are now reading words
-                               and it has to be even aligned.
-                       */
-
-                       if( ioaddr < 0x1000)
-                               insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1);
-                       else 
-                       {
+                       
+                       /* 
+                          Now let's get the packet out of buffer.
+                          size is (pkt_len + 1) >> 1, cause we are now reading words
+                          and it have to be even aligned.
+                          */ 
+                       
+                       if(ioaddr < 0x1000) 
+                               insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), 
+                                    (pkt_len + 1) >> 1);
+                       else {  
                                unsigned char *buf = skb_put(skb, pkt_len);
                                unsigned char frag = pkt_len % 4;
 
                                insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
 
-                               if(frag != 0) 
-                               {
+                               if(frag != 0) {
                                        unsigned short rest[2];
                                        rest[0] = inw( ioaddr + DATAPORT );
                                        if(frag == 3)
@@ -1067,13 +1262,13 @@ static void eth16i_rx(struct device *dev)
                        netif_rx(skb);
                        lp->stats.rx_packets++;
 
-                       if( eth16i_debug > 5 ) 
-                       {
+                       if( eth16i_debug > 5 ) {
                                int i;
-                               printk("%s: Received packet of length %d.\n", dev->name, pkt_len);
-                               for(i = 0; i < 14; i++)
-                                       printk(" %02x", skb->data[i]);
-                               printk(".\n");
+                               printk(KERN_DEBUG "%s: Received packet of length %d.\n", 
+                                      dev->name, pkt_len);
+                               for(i = 0; i < 14; i++) 
+                                       printk(KERN_DEBUG " %02x", skb->data[i]);
+                               printk(KERN_DEBUG ".\n");
                        }
 
                } /* else */
@@ -1087,16 +1282,16 @@ static void eth16i_rx(struct device *dev)
        {
                int i;
 
-               for(i = 0; i < 20; i++) 
-               {
-                       if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == RX_BUFFER_EMPTY)
+               for(i = 0; i < 20; i++) {
+                       if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 
+                           RX_BUFFER_EMPTY)
                                break;
                        inw(ioaddr + DATAPORT);
-                       outb(RX_BUF_SKIP_PACKET, ioaddr + FILTER_SELF_RX_REG);
+                       outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
                }
 
                if(eth16i_debug > 1)
-                       printk("%s: Flushed receive buffer.\n", dev->name);
+                       printk(KERN_DEBUG "%s: Flushed receive buffer.\n", dev->name);
        }
 #endif
 
@@ -1108,126 +1303,302 @@ static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        struct device *dev = dev_id;
        struct eth16i_local *lp;
        int ioaddr = 0,
-                       status;
+               status;
 
        if(dev == NULL) {
-               printk("eth16i_interrupt(): irq %d for unknown device. \n", irq);
+               printk(KERN_WARNING "eth16i_interrupt(): irq %d for unknown device. \n", irq);
                return;
        }
 
        /* Turn off all interrupts from adapter */
        outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
+       set_bit(0, (void *)&dev->tbusy);        /* Set the device busy so that */
+       /* eth16i_tx wont be called */
+
+       if(dev->interrupt)
+               printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
        dev->interrupt = 1;
 
        ioaddr = dev->base_addr;
        lp = (struct eth16i_local *)dev->priv;
-       status = inw(ioaddr + TX_STATUS_REG);                   /* Get the status */
-       outw(status, ioaddr + TX_STATUS_REG);                   /* Clear status bits */
+       status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
+       outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
 
        if(eth16i_debug > 3)
-               printk("%s: Interrupt with status %04x.\n", dev->name, status);
-
-       if( status & 0x00ff ) {                 /* Let's check the transmit status reg */
-               if(status & TX_DONE) 
-               {       /* The transmit has been done */
-                       lp->stats.tx_packets++; 
-                       if(lp->tx_queue) 
-                       {       /* Are there still packets ? */
+               printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
+
+       if( status & 0x7f00 ) {
+
+               lp->stats.rx_errors++;
+
+               if(status & (BUS_RD_ERR << 8) ) 
+                       printk(KERN_WARNING "%s: Bus read error.\n",dev->name);
+               if(status & (SHORT_PKT_ERR << 8) )   lp->stats.rx_length_errors++;
+               if(status & (ALIGN_ERR << 8) )       lp->stats.rx_frame_errors++;
+               if(status & (CRC_ERR << 8) )        lp->stats.rx_crc_errors++;
+               if(status & (RX_BUF_OVERFLOW << 8) ) lp->stats.rx_over_errors++;
+       }
+       if( status & 0x001a) {
+
+               lp->stats.tx_errors++;
+
+               if(status & CR_LOST) lp->stats.tx_carrier_errors++;
+               if(status & TX_JABBER_ERR) lp->stats.tx_window_errors++;
+
+#if 0         
+               if(status & COLLISION) {
+                       lp->stats.collisions += 
+                               ((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4);
+               }
+#endif
+               if(status & COLLISIONS_16) {
+                       if(lp->col_16 < MAX_COL_16) { 
+                               lp->col_16++;
+                               lp->stats.collisions++;
+                               /* Resume transmitting, skip failed packet */
+                               outb(0x02, ioaddr + COL_16_REG);
+                       }
+                       else {
+                               printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name);
+                       }
+               }
+       }
+
+       if( status & 0x00ff ) {          /* Let's check the transmit status reg */
+
+               if(status & TX_DONE) {         /* The transmit has been done */
+                       lp->stats.tx_packets = lp->tx_buffered_packets;
+                       lp->col_16 = 0;            
+
+                       if(lp->tx_queue) {           /* Is there still packets ? */
                                /* There was packet(s) so start transmitting and write also
-                                  how many packets there is to be sent */
+                                  how many packets there is to be sended */
                                outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
                                lp->tx_queue = 0;
                                lp->tx_queue_len = 0;
+                               lp->tx_started = 1;
                                dev->trans_start = jiffies;
-                               dev->tbusy = 0;
-                               mark_bh(NET_BH);
+                               mark_bh(NET_BH); 
                        }
-                       else 
-                       {
+                       else {
                                lp->tx_started = 0;
-                               dev->tbusy = 0;
                                mark_bh(NET_BH);
                        }
                }
        }
 
-       if( ( status & 0xff00 ) ||
-                ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
-               eth16i_rx(dev); /* We have packet in receive buffer */
-       }
-
+       if( ( status & 0x8000 ) || 
+           ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
+               eth16i_rx(dev);  /* We have packet in receive buffer */
+       }  
+       
        dev->interrupt = 0;
-
+       
        /* Turn interrupts back on */
        outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
+       
+       if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+               /* There is still more room for one more packet in tx buffer */
+               dev->tbusy = 0;
+       }
+       
        return;
 }
 
-static void eth16i_multicast(struct device *dev)
+static void eth16i_skip_packet(struct device *dev)
+{       
+       int ioaddr = dev->base_addr;
+
+       inw(ioaddr + DATAPORT);
+       inw(ioaddr + DATAPORT);
+       inw(ioaddr + DATAPORT);
+
+       outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
+       while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
+}
+
+static void eth16i_reset(struct device *dev)
 {
-       short ioaddr = dev->base_addr;
+       struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+       int ioaddr = dev->base_addr;
+
+       if(eth16i_debug > 1) 
+               printk(KERN_DEBUG "%s: Resetting device.\n", dev->name);
+
+       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+       outw(0xffff, ioaddr + TX_STATUS_REG);    
+       eth16i_select_regbank(2, ioaddr);
+
+       lp->tx_started = 0;
+       lp->tx_buf_busy = 0;
+       lp->tx_queue = 0;
+       lp->tx_queue_len = 0;    
+
+       dev->interrupt = 0;
+       dev->start = 1;
+       dev->tbusy = 0;
+       BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+}
 
-       if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+static void eth16i_multicast(struct device *dev)
+{
+       int ioaddr = dev->base_addr;
+  
+       if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
        {
                dev->flags|=IFF_PROMISC;        /* Must do this */
-               outb(3, ioaddr + RECEIVE_MODE_REG);
+               outb(3, ioaddr + RECEIVE_MODE_REG);    
        } else {
                outb(2, ioaddr + RECEIVE_MODE_REG);
        }
 }
 
-static struct net_device_stats *eth16i_get_stats(struct device *dev)
+static struct enet_statistics *eth16i_get_stats(struct device *dev)
 {
        struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
 
        return &lp->stats;
 }
 
-static void eth16i_select_regbank(unsigned char banknbr, short ioaddr)
+static void eth16i_select_regbank(unsigned char banknbr, int ioaddr)
 {
        unsigned char data;
 
        data = inb(ioaddr + CONFIG_REG_1);
-       outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
+       outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1); 
 }
 
 #ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_eth16i = {
-       devicename,
-       0, 0, 0, 0,
-       0, 0,
-       0, 0, 0, NULL, eth16i_probe
+
+static ushort eth16i_parse_mediatype(const char* s)
+{
+       if(!s)
+               return E_PORT_FROM_EPROM;
+       
+        if (!strncmp(s, "bnc", 3))
+               return E_PORT_BNC;
+        else if (!strncmp(s, "tp", 2))
+                return E_PORT_TP;
+        else if (!strncmp(s, "dix", 3))
+                return E_PORT_DIX;
+        else if (!strncmp(s, "auto", 4))
+               return E_PORT_AUTO;
+       else
+               return E_PORT_FROM_EPROM;
+}
+
+#define MAX_ETH16I_CARDS 4  /* Max number of Eth16i cards per module */
+#define NAMELEN          8  /* number of chars for storing dev->name */
+
+static char namelist[NAMELEN * MAX_ETH16I_CARDS] = { 0, };
+static struct device dev_eth16i[MAX_ETH16I_CARDS] = {
+       {
+               NULL,
+               0, 0, 0, 0,
+               0, 0,
+               0, 0, 0, NULL, NULL
+       },
 };
 
-int io = 0x2a0;
-int irq = 0;
+static int ioaddr[MAX_ETH16I_CARDS] = { 0, };
+#if 0
+static int irq[MAX_ETH16I_CARDS] = { 0, };
+#endif
+static char* mediatype[MAX_ETH16I_CARDS] = { 0, };
+static int debug = -1;
 
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
+#if (LINUX_VERSION_CODE >= 0x20115) 
+MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
+MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
+
+MODULE_PARM(ioaddr, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i");
+MODULE_PARM_DESC(ioaddr, "eth16i io base address");
+
+#if 0
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "i");
+MODULE_PARM_DESC(irq, "eth16i interrupt request number");
+#endif
+
+MODULE_PARM(mediatype, "1-" __MODULE_STRING(MAX_ETH16I_CARDS) "s");
+MODULE_PARM_DESC(mediatype, "eth16i interfaceport mediatype");
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "eth16i debug level (0-4)");
+#endif
 
 int init_module(void)
 {
-       if(io == 0)
-               printk("eth16i: You should not use auto-probing with insmod!\n");
-
-       dev_eth16i.base_addr = io;
-       dev_eth16i.irq = irq;
-       if( register_netdev( &dev_eth16i ) != 0 ) {
-               printk("eth16i: register_netdev() returned non-zero.\n");
-               return -EIO;
-       }
+       int this_dev, found = 0;
+
+       for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
+       {
+               struct device *dev = &dev_eth16i[this_dev];
+       
+               dev->name = namelist + (NAMELEN*this_dev);
+               dev->irq = 0; /* irq[this_dev]; */
+               dev->base_addr = ioaddr[this_dev];
+               dev->init = eth16i_probe;
+
+               if(debug != -1)
+                       eth16i_debug = debug;
+
+               if(eth16i_debug > 1)
+                       printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" );
+
+               dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
+
+               if(ioaddr[this_dev] == 0)
+               {
+                       if(this_dev != 0) break; /* Only autoprobe 1st one */
 
+                       printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+
+               if(register_netdev(dev) != 0)
+               {
+                       printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
+                              ioaddr[this_dev]);
+           
+                       if(found != 0) return 0;
+                       return -ENXIO;
+               }
+
+               found++;
+       }
        return 0;
 }
-
+       
 void cleanup_module(void)
 {
-       unregister_netdev( &dev_eth16i );
-       free_irq( dev_eth16i.irq, &dev_eth16i );
-       release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
-}
+       int this_dev;
 
+       for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++)
+       {
+               struct device* dev = &dev_eth16i[this_dev];
+               
+               if(dev->priv != NULL)
+               {
+                       unregister_netdev(dev);
+                       kfree(dev->priv);
+                       dev->priv = NULL;
+                       
+                       free_irq(dev->irq, dev);
+                       release_region(dev->base_addr, ETH16I_IO_EXTENT);
+                       
+               }
+       }
+}
 #endif /* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eth16i.c"
+ *  alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict -prototypes -O6 -c eth16i.c"
+ *  tab-width: 8
+ *  c-basic-offset: 8
+ *  c-indent-level: 8
+ * End:
+ */
+
+/* End of file eth16i.c */
index 2a2f4e909b1288009e9a2d92eff6a6c20369aa34..f795abaf106ddf2dac7c05aa3a53c07833375c5b 100644 (file)
@@ -1010,14 +1010,6 @@ static struct net_device_stats *baycom_get_stats(struct device *dev)
 
 /* --------------------------------------------------------------------- */
 
-static int epp_preempt(void *handle)
-{
-        /* we cannot relinquish the port in the middle of an operation */
-        return 1;
-}
-
-/* --------------------------------------------------------------------- */
-
 static void epp_wakeup(void *handle)
 {
         struct device *dev = (struct device *)handle;
@@ -1070,8 +1062,8 @@ static int epp_open(struct device *dev)
         }
 #endif
        memset(&bc->modem, 0, sizeof(bc->modem));
-        if (!(bc->pdev = parport_register_device(pp, dev->name, epp_preempt, epp_wakeup, 
-                                                 epp_interrupt, PARPORT_DEV_LURK, dev))) {
+        if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup, 
+                                                 epp_interrupt, PARPORT_DEV_EXCL, dev))) {
                 printk(KERN_ERR "%s: cannot register parport at 0x%lx\n", bc_drvname, pp->base);
                 return -ENXIO;
         }
index e79a00ef637b4bcdcdb79ff7452fe2a33a2f73c3..bbc29e4c165876469d1e203c4755215614ef9fdb 100644 (file)
@@ -357,14 +357,6 @@ static void par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 /* --------------------------------------------------------------------- */
 
-static int par96_preempt(void *handle)
-{
-       /* we cannot relinquish the port in the middle of an operation */
-       return 1;
-}
-
-/* --------------------------------------------------------------------- */
-
 static void par96_wakeup(void *handle)
 {
         struct device *dev = (struct device *)handle;
@@ -396,8 +388,8 @@ static int par96_open(struct device *dev)
        }
        memset(&bc->modem, 0, sizeof(bc->modem));
        bc->hdrv.par.bitrate = 9600;
-       if (!(bc->pdev = parport_register_device(pp, dev->name, par96_preempt, par96_wakeup, 
-                                                par96_interrupt, PARPORT_DEV_LURK, dev))) {
+       if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, par96_wakeup, 
+                                                par96_interrupt, PARPORT_DEV_EXCL, dev))) {
                printk(KERN_ERR "baycom_par: cannot register parport at 0x%lx\n", pp->base);
                return -ENXIO;
        }
index fd257f11f2a478409f0bdc2284cab56900384605..ac474d0b96d8b44e059edb4baf7923ccb8fb44af 100644 (file)
@@ -966,6 +966,7 @@ static void special_condition(struct device *dev, int rc)
 {
   struct scc_priv *priv = dev->priv;
   int cb, cmd = priv->cmd;
+  unsigned long flags;
 
   /* See Figure 2-15. Only overrun and EOF need to be checked. */
   
@@ -976,9 +977,12 @@ static void special_condition(struct device *dev, int rc)
   } else if (rc & END_FR) {
     /* End of frame. Get byte count */
     if (dev->dma) {
+        flags=claim_dma_lock();
        disable_dma(dev->dma);
        clear_dma_ff(dev->dma);
        cb = BUF_SIZE - get_dma_residue(dev->dma) - 2;
+       release_dma_lock(flags);
+       
     } else {
        cb = priv->rx_ptr - 2;
     }
@@ -1013,9 +1017,13 @@ static void special_condition(struct device *dev, int rc)
     }
     /* Get ready for new frame */
     if (dev->dma) {
+      
+      flags=claim_dma_lock();
       set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
       set_dma_count(dev->dma, BUF_SIZE);
       enable_dma(dev->dma);
+      release_dma_lock(flags);
+      
     } else {
       priv->rx_ptr = 0;
     }
@@ -1102,6 +1110,7 @@ static void es_isr(struct device *dev)
   struct scc_info *info = priv->info;
   int i, cmd = priv->cmd;
   int st, dst, res;
+  unsigned long flags;
 
   /* Read status and reset interrupt bit */
   st = read_scc(cmd, R0);
@@ -1118,9 +1127,11 @@ static void es_isr(struct device *dev)
     /* Get remaining bytes */
     i = priv->tx_tail;
     if (dev->dma) {
+      flags=claim_dma_lock();
       disable_dma(dev->dma);
       clear_dma_ff(dev->dma);
       res = get_dma_residue(dev->dma);
+      release_dma_lock(flags);
     } else {
       res = priv->tx_len[i] - priv->tx_ptr;
       if (res) write_scc(cmd, R0, RES_Tx_P);
@@ -1133,9 +1144,11 @@ static void es_isr(struct device *dev)
     /* Check if another frame is available and we are allowed to transmit */
     if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
       if (dev->dma) {
+        flags=claim_dma_lock();
        set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
        set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
        enable_dma(dev->dma);
+       release_dma_lock(flags);
       } else {
        /* If we have an ESCC, we are allowed to write data bytes
           immediately. Otherwise we have to wait for the next
@@ -1170,12 +1183,14 @@ static void es_isr(struct device *dev)
     if (st & DCD) {
       if (dev->dma) {
        /* Program DMA controller */
+       flags=claim_dma_lock();
        disable_dma(dev->dma);
        clear_dma_ff(dev->dma);
        set_dma_mode(dev->dma, DMA_MODE_READ);
        set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
        set_dma_count(dev->dma, BUF_SIZE);
        enable_dma(dev->dma);
+       release_dma_lock(flags);
        /* Configure PackeTwin DMA */
        if (info->type == TYPE_TWIN) {
          outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
@@ -1195,7 +1210,12 @@ static void es_isr(struct device *dev)
       }
     } else {
       /* Disable DMA */
-      if (dev->dma) disable_dma(dev->dma);
+      if (dev->dma)
+      {
+       flags=claim_dma_lock();
+       disable_dma(dev->dma);
+       release_dma_lock(flags);
+      }
       /* Disable receiver */
       write_scc(cmd, R3, Rx8);
       /* DMA disable, RX int disable, Ext int enable */
@@ -1228,11 +1248,13 @@ static void es_isr(struct device *dev)
     while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8);
     priv->rx_over = 0;
     if (dev->dma) {
+      flags=claim_dma_lock();
       disable_dma(dev->dma);
       clear_dma_ff(dev->dma);
       set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
       set_dma_count(dev->dma, BUF_SIZE);
       enable_dma(dev->dma);
+      release_dma_lock(flags);
     } else {
       priv->rx_ptr = 0;
     }
@@ -1245,6 +1267,7 @@ static void tm_isr(struct device *dev)
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
   int cmd = priv->cmd;
+  unsigned long flags;
 
   switch (priv->tx_state) {
   case TX_OFF:
@@ -1266,12 +1289,16 @@ static void tm_isr(struct device *dev)
     priv->tx_state = TX_ACTIVE;
     if (dev->dma) {
       /* Program DMA controller */
+      
+      flags=claim_dma_lock();
       disable_dma(dev->dma);
       clear_dma_ff(dev->dma);
       set_dma_mode(dev->dma, DMA_MODE_WRITE);
       set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
       set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
       enable_dma(dev->dma);
+      release_dma_lock(flags);
+      
       /* Configure PackeTwin DMA */
       if (info->type == TYPE_TWIN) {
        outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
index 3ca2477b5b9a1f5fd31612a2df4a4235f850da7c..c933799971d2bde3665c1656d496438a83d08a08 100644 (file)
@@ -1,3 +1,5 @@
+#define LINUX_21
+
 /*
  *     Comtrol SV11 card driver
  *
@@ -7,7 +9,7 @@
  *     Its a genuine Z85230
  *
  *     It supports DMA using two DMA channels in SYNC mode. The driver doesn't
- *     use these facilities (yet).
+ *     use these facilities
  *     
  *     The control port is at io+1, the data at io+3 and turning off the DMA
  *     is done by writing 0 to io+4
@@ -19,6 +21,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/net.h>
@@ -50,7 +53,7 @@ struct sv11_device
 
 /*
  *     Frame receive. Simple for our card as we do sync ppp and there
- *     is no funny garbage involved. This is very timing sensitive.
+ *     is no funny garbage involved
  */
  
 static void hostess_input(struct z8530_channel *c, struct sk_buff *skb)
@@ -58,13 +61,12 @@ static void hostess_input(struct z8530_channel *c, struct sk_buff *skb)
        /* Drop the CRC - its not a good idea to try and negotiate it ;) */
        skb_trim(skb, skb->len-2);
        skb->protocol=htons(ETH_P_WAN_PPP);
+       skb->mac.raw=skb->data;
        skb->dev=c->netdevice;
        /*
         *      Send it to the PPP layer. We dont have time to process
         *      it right now.
         */
-       skb->mac.raw = skb->data;
-       
        netif_rx(skb);
 }
  
@@ -75,15 +77,24 @@ static void hostess_input(struct z8530_channel *c, struct sk_buff *skb)
 static int hostess_open(struct device *d)
 {
        struct sv11_device *sv11=d->priv;
-       int err;
+       int err = -1;
        
        /*
         *      Link layer up
         */
-       if(dma)
-               err=z8530_sync_dma_open(d, &sv11->sync.chanA);
-       else
-               err=z8530_sync_open(d, &sv11->sync.chanA);
+       switch(dma)
+       {
+               case 0:
+                       err=z8530_sync_open(d, &sv11->sync.chanA);
+                       break;
+               case 1:
+                       err=z8530_sync_dma_open(d, &sv11->sync.chanA);
+                       break;
+               case 2:
+                       err=z8530_sync_txdma_open(d, &sv11->sync.chanA);
+                       break;
+       }
+       
        if(err)
                return err;
        /*
@@ -92,10 +103,18 @@ static int hostess_open(struct device *d)
        err=sppp_open(d);
        if(err)
        {
-               if(dma)
-                       z8530_sync_dma_close(d, &sv11->sync.chanA);
-               else
-                       z8530_sync_close(d, &sv11->sync.chanA);
+               switch(dma)
+               {
+                       case 0:
+                               z8530_sync_close(d, &sv11->sync.chanA);
+                               break;
+                       case 1:
+                               z8530_sync_dma_close(d, &sv11->sync.chanA);
+                               break;
+                       case 2:
+                               z8530_sync_txdma_close(d, &sv11->sync.chanA);
+                               break;
+               }                               
                return err;
        }
        sv11->sync.chanA.rx_function=hostess_input;
@@ -123,10 +142,19 @@ static int hostess_close(struct device *d)
         *      Link layer down
         */
        d->tbusy=1;
-       if(dma)
-               z8530_sync_dma_close(d, &sv11->sync.chanA);
-       else
-               z8530_sync_close(d, &sv11->sync.chanA);
+       
+       switch(dma)
+       {
+               case 0:
+                       z8530_sync_close(d, &sv11->sync.chanA);
+                       break;
+               case 1:
+                       z8530_sync_dma_close(d, &sv11->sync.chanA);
+                       break;
+               case 2:
+                       z8530_sync_txdma_close(d, &sv11->sync.chanA);
+                       break;
+       }
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -135,10 +163,10 @@ static int hostess_ioctl(struct device *d, struct ifreq *ifr, int cmd)
 {
        struct sv11_device *sv11=d->priv;
        /* z8530_ioctl(d,&sv11->sync.chanA,ifr,cmd) */
-       return sppp_do_ioctl(d, ifr, cmd);
+       return sppp_do_ioctl(d, ifr,cmd);
 }
 
-static struct net_device_stats *hostess_get_stats(struct device *d)
+static struct enet_statistics *hostess_get_stats(struct device *d)
 {
        struct sv11_device *sv11=d->priv;
        if(sv11)
@@ -157,6 +185,7 @@ static int hostess_queue_xmit(struct sk_buff *skb, struct device *d)
        return z8530_queue_xmit(&sv11->sync.chanA, skb);
 }
 
+#ifdef LINUX_21
 static int hostess_neigh_setup(struct neighbour *n)
 {
        if (n->nud_state == NUD_NONE) {
@@ -176,6 +205,15 @@ static int hostess_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
        return 0;
 }
 
+#else
+
+static int return_0(struct device *d)
+{
+       return 0;
+}
+
+#endif
+
 /*
  *     Description block for a Comtrol Hostess SV11 card
  */
@@ -243,13 +281,17 @@ static struct sv11_device *sv11_init(int iobase, int irq)
                 *      You can have DMA off or 1 and 3 thats the lot
                 *      on the Comtrol.
                 */
-               dev->chanA.txdma=1;
-               dev->chanA.rxdma=3;
-               outb(14, iobase+4);             /* DMA on */
+               dev->chanA.txdma=3;
+               dev->chanA.rxdma=1;
+               outb(0x03|0x08, iobase+4);              /* DMA on */
                if(request_dma(dev->chanA.txdma, "Hostess SV/11 (TX)")!=0)
                        goto fail;
-               if(request_dma(dev->chanA.rxdma, "Hostess SV/11 (RX)")!=0)
-                       goto dmafail;
+                       
+               if(dma==1)
+               {
+                       if(request_dma(dev->chanA.rxdma, "Hostess SV/11 (RX)")!=0)
+                               goto dmafail;
+               }
        }
        save_flags(flags);
        cli();
@@ -259,7 +301,10 @@ static struct sv11_device *sv11_init(int iobase, int irq)
         */
         
        if(z8530_init(dev)!=0)
+       {
+               printk(KERN_ERR "Z8530 series device not found.\n");
                goto dmafail2;
+       }
        z8530_channel_load(&dev->chanB, z8530_dead_port);
        if(dev->type==Z85C30)
                z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream);
@@ -269,8 +314,6 @@ static struct sv11_device *sv11_init(int iobase, int irq)
        restore_flags(flags);
 
 
-       printk(KERN_INFO "begin loading hdlc\n");
-       
        /*
         *      Now we can take the IRQ
         */
@@ -291,7 +334,6 @@ static struct sv11_device *sv11_init(int iobase, int irq)
                         *      Local fields
                         */     
                        sprintf(sv->name,"hdlc%d", i);
-                       printk("Filling in device '%s' at %p\n", sv->name, d);
                        
                        d->name = sv->name;
                        d->base_addr = iobase;
@@ -305,8 +347,12 @@ static struct sv11_device *sv11_init(int iobase, int irq)
                        d->get_stats = hostess_get_stats;
                        d->set_multicast_list = NULL;
                        d->do_ioctl = hostess_ioctl;
+#ifdef LINUX_21                        
                        d->neigh_setup = hostess_neigh_setup_dev;
                        dev_init_buffers(d);
+#else
+                       d->init = return_0;
+#endif
                        d->set_mac_address = NULL;
                        
                        if(register_netdev(d)==-1)
@@ -322,11 +368,11 @@ static struct sv11_device *sv11_init(int iobase, int irq)
                }
        }
 dmafail2:
-       if(!dma)
-               goto fail;
-       free_dma(dev->chanA.rxdma);
+       if(dma==1)
+               free_dma(dev->chanA.rxdma);
 dmafail:
-       free_dma(dev->chanA.txdma);
+       if(dma)
+               free_dma(dev->chanA.txdma);
 fail:
        free_irq(irq, dev);
 fail2:
@@ -342,8 +388,11 @@ static void sv11_shutdown(struct sv11_device *dev)
        z8530_shutdown(&dev->sync);
        unregister_netdev(&dev->netdev.dev);
        free_irq(dev->sync.irq, dev);
-       free_dma(dev->sync.chanA.rxdma);
-       free_dma(dev->sync.chanA.txdma);
+       if(dma)
+       {
+               free_dma(dev->sync.chanA.rxdma);
+               free_dma(dev->sync.chanA.txdma);
+       }
        release_region(dev->sync.chanA.ctrlio-1, 8);
 }
 
@@ -352,6 +401,7 @@ static void sv11_shutdown(struct sv11_device *dev)
 static int io=0x200;
 static int irq=9;
 
+#ifdef LINUX_21
 MODULE_PARM(io,"i");
 MODULE_PARM_DESC(io, "The I/O base of the Comtrol Hostess SV11 card");
 MODULE_PARM(dma,"i");
@@ -361,12 +411,13 @@ MODULE_PARM_DESC(irq, "The interrupt line setting for the Comtrol Hostess SV11 c
 
 MODULE_AUTHOR("Bulding Number Three Ltd");
 MODULE_DESCRIPTION("Modular driver for the Comtrol Hostess SV11");
+#endif
 
 static struct sv11_device *sv11_unit;
 
 int init_module(void)
 {
-       printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.02.\n");
+       printk(KERN_INFO "SV-11 Z85230 Synchronous Driver v 0.01.\n");
        printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");   
        if(dma)
                printk(KERN_WARNING "DMA mode probably wont work right now.\n");
index 5a7d1fee51b1fded7af581833a165f8b5d241dae..15f7f9ad7c8b188e5fe1ca071c445c16600dcbef 100644 (file)
@@ -377,6 +377,7 @@ __initfunc(void lance_probe1(int ioaddr))
        unsigned char hpJ2405A = 0;                     /* HP ISA adaptor */
        int hp_builtin = 0;                                     /* HP on-board ethernet. */
        static int did_version = 0;                     /* Already printed version info. */
+       unsigned long flags;
 
        /* First we look for special cases.
           Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
@@ -563,8 +564,11 @@ __initfunc(void lance_probe1(int ioaddr))
                        outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */
                        if (request_dma(dma, chipname))
                                continue;
+                               
+                       flags=claim_dma_lock();
                        set_dma_mode(dma, DMA_MODE_CASCADE);
                        enable_dma(dma);
+                       release_dma_lock(flags);
 
                        /* Trigger an initialization. */
                        outw(0x0001, ioaddr+LANCE_DATA);
@@ -576,7 +580,9 @@ __initfunc(void lance_probe1(int ioaddr))
                                printk(", DMA %d.\n", dev->dma);
                                break;
                        } else {
+                               flags=claim_dma_lock();
                                disable_dma(dma);
+                               release_dma_lock(flags);
                                free_dma(dma);
                        }
                }
@@ -649,8 +655,10 @@ lance_open(struct device *dev)
 
        /* The DMA controller is used as a no-operation slave, "cascade mode". */
        if (dev->dma != 4) {
+               unsigned long flags=claim_dma_lock();
                enable_dma(dev->dma);
                set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+               release_dma_lock(flags);
        }
 
        /* Un-Reset the LANCE, needed only for the NE2100. */
@@ -1121,7 +1129,11 @@ lance_close(struct device *dev)
        outw(0x0004, ioaddr+LANCE_DATA);
 
        if (dev->dma != 4)
+       {
+               unsigned long flags=claim_dma_lock();
                disable_dma(dev->dma);
+               release_dma_lock(flags);
+       }
 
        free_irq(dev->irq, dev);
 
index 205ec6ac286439ca7ff5466a10bc20665224ffd5..1392fa60a0c91902c24373ad79ffe215b512ec39 100644 (file)
@@ -352,13 +352,17 @@ static void handlefc(struct device *dev)
        /* called *only* from idle, non-reentrant */
        int dma = dev->dma;
        int base = dev->base_addr;
+       unsigned long flags;
+
 
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
        set_dma_mode(dma,DMA_MODE_READ);
        set_dma_addr(dma,virt_to_bus(ltdmacbuf));
        set_dma_count(dma,50);
        enable_dma(dma);
+       release_dma_lock(flags);
 
        inb_p(base+3);
        inb_p(base+2);
@@ -370,13 +374,16 @@ static void handlefd(struct device *dev)
 {
        int dma = dev->dma;
        int base = dev->base_addr;
+       unsigned long flags;
 
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
        set_dma_mode(dma,DMA_MODE_READ);
        set_dma_addr(dma,virt_to_bus(ltdmabuf));
        set_dma_count(dma,800);
        enable_dma(dma);
+       release_dma_lock(flags);
 
        inb_p(base+3);
        inb_p(base+2);
@@ -391,21 +398,25 @@ static void handlewrite(struct device *dev)
        /* on entry, 0xfb and ltdmabuf holds data */
        int dma = dev->dma;
        int base = dev->base_addr;
-
-
+       unsigned long flags;
+       
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
        set_dma_mode(dma,DMA_MODE_WRITE);
        set_dma_addr(dma,virt_to_bus(ltdmabuf));
        set_dma_count(dma,800);
        enable_dma(dma);
-
+       release_dma_lock(flags);
+       
        inb_p(base+3);
        inb_p(base+2);
 
        if ( wait_timeout(dev,0xfb) ) {
+               flags=claim_dma_lock();
                printk("timed out in handlewrite, dma res %d\n",
                        get_dma_residue(dev->dma) );
+               release_dma_lock(flags);
        }
 }
 
@@ -415,15 +426,17 @@ static void handleread(struct device *dev)
        /* on exit, ltdmabuf holds data */
        int dma = dev->dma;
        int base = dev->base_addr;
+       unsigned long flags;
 
-
-
+       
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
        set_dma_mode(dma,DMA_MODE_READ);
        set_dma_addr(dma,virt_to_bus(ltdmabuf));
        set_dma_count(dma,800);
        enable_dma(dma);
+       release_dma_lock(flags);
 
        inb_p(base+3);
        inb_p(base+2);
@@ -435,14 +448,16 @@ static void handlecommand(struct device *dev)
        /* on entry, 0xfa and ltdmacbuf holds command */
        int dma = dev->dma;
        int base = dev->base_addr;
+       unsigned long flags;
 
+       flags=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
        set_dma_mode(dma,DMA_MODE_WRITE);
        set_dma_addr(dma,virt_to_bus(ltdmacbuf));
        set_dma_count(dma,50);
        enable_dma(dma);
-
+       release_dma_lock(flags);
        inb_p(base+3);
        inb_p(base+2);
        if ( wait_timeout(dev,0xfa) ) printk("timed out in handlecommand\n");
@@ -978,6 +993,7 @@ __initfunc(int ltpc_probe(struct device *dev))
        int probe3, probe4, probe9;
        unsigned short straymask;
        unsigned long flags;
+       unsigned long f;
 
        err = ltpc_init(dev);
        if (err) return err;
@@ -1089,6 +1105,7 @@ __initfunc(int ltpc_probe(struct device *dev))
        inb_p(base+6); /* tri-state interrupt line */
 
        timeout = jiffies+100;
+       
        while(timeout>jiffies) {
                /* wait for the card to complete initialization */
        }
@@ -1098,21 +1115,26 @@ __initfunc(int ltpc_probe(struct device *dev))
        /* set up both dma 1 and 3 for read call */
 
        if (!request_dma(1,"ltpc")) {
+       
+               f=claim_dma_lock();
                disable_dma(1);
                clear_dma_ff(1);
                set_dma_mode(1,DMA_MODE_WRITE);
                set_dma_addr(1,virt_to_bus(ltdmabuf));
                set_dma_count(1,sizeof(struct lt_mem));
                enable_dma(1);
+               release_dma_lock(f);
                dma|=1;
        }
        if (!request_dma(3,"ltpc")) {
+               f=claim_dma_lock();
                disable_dma(3);
                clear_dma_ff(3);
                set_dma_mode(3,DMA_MODE_WRITE);
                set_dma_addr(3,virt_to_bus(ltdmabuf));
                set_dma_count(3,sizeof(struct lt_mem));
                enable_dma(3);
+               release_dma_lock(f);
                dma|=2;
        }
 
@@ -1174,13 +1196,15 @@ __initfunc(int ltpc_probe(struct device *dev))
        if(debug&DEBUG_VERBOSE) {
                printk("finishing up transfer\n");
        }
-
+       
+       f=claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
        set_dma_mode(dma,DMA_MODE_READ);
        set_dma_addr(dma,virt_to_bus(ltdmabuf));
        set_dma_count(dma,0x100);
        enable_dma(dma);
+       release_dma_lock(f);
 
        (void) inb_p(base+3);
        (void) inb_p(base+2);
index c778255cb74724d8ea6dbc5663fe2814675a7d0f..8fd432aa99dff909c6c791e93be166c792e41ef2 100644 (file)
@@ -351,6 +351,7 @@ __initfunc(static int ni65_probe1(struct device *dev,int ioaddr))
 {
        int i,j;
        struct priv *p;
+       unsigned long flags;
 
        for(i=0;i<NUM_CARDS;i++) {
                if(check_region(ioaddr, cards[i].total_size))
@@ -417,12 +418,20 @@ __initfunc(static int ni65_probe1(struct device *dev,int ioaddr))
                                int dma = dmatab[i];
                                if(test_bit(dma,&dma_channels) || request_dma(dma,"ni6510"))
                                        continue;
+                                       
+                               flags=claim_dma_lock();
                                disable_dma(dma);
                                set_dma_mode(dma,DMA_MODE_CASCADE);
                                enable_dma(dma);
+                               release_dma_lock(flags);
+                               
                                ni65_init_lance(p,dev->dev_addr,0,0); /* trigger memory access */
+                               
+                               flags=claim_dma_lock();
                                disable_dma(dma);
                                free_dma(dma);
+                               release_dma_lock(flags);
+                               
                                if(readreg(CSR0) & CSR0_IDON)
                                        break;
                        }
@@ -718,20 +727,25 @@ static int ni65_lance_reinit(struct device *dev)
 {
         int i;
         struct priv *p = (struct priv *) dev->priv;
+        unsigned long flags;
 
         p->lock = 0;
         p->xmit_queued = 0;
 
+        flags=claim_dma_lock();
         disable_dma(dev->dma); /* I've never worked with dma, but we do it like the packetdriver */
         set_dma_mode(dev->dma,DMA_MODE_CASCADE);
         enable_dma(dev->dma);
+        release_dma_lock(flags);
 
         outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */
         if( (i=readreg(CSR0) ) != 0x4)
         {
                 printk(KERN_ERR "%s: can't RESET %s card: %04x\n",dev->name,
                                                        cards[p->cardno].cardname,(int) i);
+                flags=claim_dma_lock();
                 disable_dma(dev->dma);
+                release_dma_lock(flags);
                 return 0;
         }
 
@@ -782,7 +796,9 @@ static int ni65_lance_reinit(struct device *dev)
                 return 1; /* ->OK */
         }
         printk(KERN_ERR "%s: can't init lance, status: %04x\n",dev->name,(int) inw(PORT+L_DATAREG));
+        flags=claim_dma_lock();
         disable_dma(dev->dma);
+        release_dma_lock(flags);
         return 0; /* ->Error */
 }
 
@@ -1167,8 +1183,10 @@ static void set_multicast_list(struct device *dev)
 }
 
 #ifdef MODULE
+static char devicename[9] = { 0, };
+
 static struct device dev_ni65 = {
-       "                               ",      /* "ni6510": device name inserted by net_init.c */
+       devicename,     /* "ni6510": device name inserted by net_init.c */
        0, 0, 0, 0,
        0x360, 9,        /* I/O address, IRQ */
        0, 0, 0, NULL, ni65_probe };
index 89193380683b467f3d871dcc519d5dca8725313a..91666827e4100228d3e11b99f1f530dd79b9f60d 100644 (file)
@@ -242,7 +242,10 @@ plip_init_dev(struct device *dev, struct parport *pb))
 
        pardev = parport_register_device(pb, dev->name, plip_preempt,
                                         plip_wakeup, plip_interrupt, 
-                                        PARPORT_DEV_LURK, dev);
+                                        0, dev);
+
+       if (!pardev)
+               return -ENODEV;
 
        printk(KERN_INFO "%s", version);
        printk(KERN_INFO "%s: Parallel port at %#3lx, using IRQ %d\n", dev->name,
index a687135dcb96bbf0f6357ff9c0a7c806677ebfff..0a886c6db0d7dd4769b180d7167918af768f2fad 100644 (file)
@@ -650,8 +650,8 @@ static int if_init(struct device *dev)
        dev->irq = wandev->irq;
        dev->dma = wandev->dma;
        dev->base_addr = wandev->ioport;
-       dev->mem_start = wandev->maddr;
-       dev->mem_end = wandev->maddr + wandev->msize - 1;
+       dev->mem_start = (unsigned long)wandev->maddr;
+       dev->mem_end = dev->mem_start + wandev->msize - 1;
        /* Set transmit buffer queue length */
        dev->tx_queue_len = 10;
        /* Initialize socket buffers */
index 37c1d78899cb6b5ed27c4f482d3993d06bb7320a..69038be9a716e41dd6a1bc0319078e62df47969b 100644 (file)
@@ -412,8 +412,8 @@ static int if_init(struct device *dev)
        dev->irq = wandev->irq;
        dev->dma = wandev->dma;
        dev->base_addr = wandev->ioport;
-       dev->mem_start = wandev->maddr;
-       dev->mem_end = wandev->maddr + wandev->msize - 1;
+       dev->mem_start = (unsigned long)wandev->maddr;
+       dev->mem_end = dev->mem_start + wandev->msize - 1;
        /* Set transmit buffer queue length */
        dev->tx_queue_len = 100;
        /* Initialize socket buffers */
index 4b92186d15242a81598ed44dc5fd6d936a538887..5aa649117191901474573da6621b438c4428e817 100644 (file)
@@ -560,8 +560,8 @@ static int if_init (struct device* dev)
        dev->irq        = wandev->irq;
        dev->dma        = wandev->dma;
        dev->base_addr  = wandev->ioport;
-       dev->mem_start  = wandev->maddr;
-       dev->mem_end    = wandev->maddr + wandev->msize - 1;
+       dev->mem_start  = (unsigned long)wandev->maddr;
+       dev->mem_end    = dev->mem_end + wandev->msize - 1;
 
         /* Set transmit buffer queue length */
         dev->tx_queue_len = 10;
index 5dbe2b37fe53e8d316aecd0a267d265a0970e55f..46992d97ac4fdd748d8fe3366fbb272d8831b531 100644 (file)
@@ -421,10 +421,10 @@ int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
                        return err;
                }
        }
-       else if (!get_option_index(dpmbase_opt, virt_to_phys((void *)hw->dpmbase)))
+       else if (!get_option_index(dpmbase_opt, virt_to_phys(hw->dpmbase)))
        {
                printk(KERN_ERR "%s: memory address 0x%lX is illegal!\n",
-                       modname, hw->dpmbase)
+                       modname, virt_to_phys(hw->dpmbase))
                ;
                return -EINVAL;
        } 
@@ -432,16 +432,14 @@ int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
        {
                printk(KERN_ERR
                        "%s: 8K memory region at 0x%lX is not available!\n",
-                       modname, hw->dpmbase)
-               ;
+                       modname, virt_to_phys(hw->dpmbase));
                return -EINVAL;
        } 
        printk(KERN_INFO "%s: dual-port memory window is set at 0x%lX.\n",
-               modname, virt_to_phys((void *)hw->dpmbase))
-       ;
+               modname, virt_to_phys(hw->dpmbase));
+
        printk(KERN_INFO "%s: found %luK bytes of on-board memory.\n",
-               modname, hw->memory / 1024)
-       ;
+               modname, hw->memory / 1024);
 
        /* Load firmware. If loader fails then shut down adapter */
        err = sdla_load(hw, sfm, len);
@@ -830,7 +828,7 @@ int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
 
                /* Relocate window and copy block of data */
                err = sdla_mapmem(hw, curvec);
-               memcpy((void*)buf, (void*)(hw->dpmbase + curpos), curlen);
+               memcpy(buf, (void *)((u8 *)hw->dpmbase + curpos), curlen);
                addr       += curlen;
                (char*)buf += curlen;
                len        -= curlen;
@@ -872,7 +870,7 @@ int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
 
                /* Relocate window and copy block of data */
                sdla_mapmem(hw, curvec);
-               memcpy((void*)(hw->dpmbase + curpos), (void*)buf, curlen);
+               memcpy((void*)((u8 *)hw->dpmbase + curpos), buf, curlen);
                addr       += curlen;
                (char*)buf += curlen;
                len        -= curlen;
@@ -980,7 +978,7 @@ static int sdla_autodpm (sdlahw_t* hw)
 
        for (i = opt[0]; i && err; --i)
        {
-               hw->dpmbase = (unsigned long )(phys_to_virt(opt[i]));
+               hw->dpmbase = phys_to_virt(opt[i]);
                err = sdla_setdpm(hw);
        }
        return err;
@@ -1001,7 +999,7 @@ static int sdla_setdpm (sdlahw_t* hw)
 
        /* Shut down card and verify memory region */
        sdla_down(hw);
-       if (check_memregion((void*)hw->dpmbase, hw->dpmsize))
+       if (check_memregion(hw->dpmbase, hw->dpmsize))
                return -EINVAL
        ;
 
@@ -1154,7 +1152,7 @@ static unsigned long sdla_memtest (sdlahw_t* hw)
 
        for (memsize = 0, winsize = hw->dpmsize;
             !sdla_mapmem(hw, memsize) &&
-               (test_memregion((void*)hw->dpmbase, winsize) == winsize)
+               (test_memregion(hw->dpmbase, winsize) == winsize)
             ;
             memsize += winsize)
        ;
@@ -1176,7 +1174,7 @@ static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo)
        if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)
                return -EIO
        ;
-       data = (void*)(hw->dpmbase + (sfminfo->dataoffs - hw->vector));
+       data = (void*)((u8 *)hw->dpmbase + (sfminfo->dataoffs - hw->vector));
        memset(data, 0, sfminfo->datasize);
 
        data[0x00] = make_config_byte(hw);
@@ -1229,7 +1227,7 @@ static unsigned char make_config_byte (sdlahw_t* hw)
 static int sdla_start (sdlahw_t* hw, unsigned addr)
 {
        unsigned port = hw->port;
-       unsigned charbootp;
+       unsigned char *bootp;
        int err, tmp, i;
 
        if (!port) return -EFAULT;
@@ -1237,14 +1235,15 @@ static int sdla_start (sdlahw_t* hw, unsigned addr)
        switch (hw->type)
        {
        case SDLA_S502A:
-               bootp = (void*)(hw->dpmbase + 0x66);
+               bootp = hw->dpmbase;
+               bootp += 0x66;
                break;
 
        case SDLA_S502E:
        case SDLA_S503:
        case SDLA_S507:
        case SDLA_S508:
-               bootp = (void*)hw->dpmbase;
+               bootp = hw->dpmbase;
                break;
 
        default:
@@ -1333,7 +1332,7 @@ static int init_s502a (sdlahw_t* hw)
        hw->regs[1] = 0xFF;
 
        /* Verify configuration options */
-       i = get_option_index(s502a_dpmbase_options, virt_to_phys((void *)hw->dpmbase));
+       i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));
        if (i == 0)
                return -EINVAL
        ;
@@ -1372,7 +1371,7 @@ static int init_s502e (sdlahw_t* hw)
        ;
 
        /* Verify configuration options */
-       i = get_option_index(s508_dpmbase_options, virt_to_phys((void *)hw->dpmbase));
+       i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
        if (i == 0)
                return -EINVAL
        ;
@@ -1416,7 +1415,7 @@ static int init_s503 (sdlahw_t* hw)
        ;
 
        /* Verify configuration options */
-       i = get_option_index(s508_dpmbase_options, virt_to_phys((void *)hw->dpmbase));
+       i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
        if (i == 0)
                return -EINVAL
        ;
@@ -1458,7 +1457,7 @@ static int init_s507 (sdlahw_t* hw)
        ;
 
        /* Verify configuration options */
-       i = get_option_index(s507_dpmbase_options, virt_to_phys((void *)hw->dpmbase));
+       i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));
        if (i == 0)
                return -EINVAL
        ;
@@ -1515,7 +1514,7 @@ static int init_s508 (sdlahw_t* hw)
        ;
 
        /* Verify configuration options */
-       i = get_option_index(s508_dpmbase_options, virt_to_phys((void *)hw->dpmbase));
+       i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
        if (i == 0)
                return -EINVAL
        ;
index bc6288197cfe214dec57869fb2373430662aa93d..00454c5d63aaa920d721ae6981b4c5af2fe9ac0b 100644 (file)
@@ -269,9 +269,9 @@ static int setup (wan_device_t* wandev, wandev_conf_t* conf)
        card->hw.irq     = (conf->irq == 9) ? 2 : conf->irq;
        /* Compute the virtual address of the card in kernel space */
        if(conf->maddr)
-               card->hw.dpmbase = (unsigned long)phys_to_virt(conf->maddr);
+               card->hw.dpmbase = phys_to_virt(conf->maddr);
        else    /* But 0 means NULL */
-               card->hw.dpmbase = conf->maddr;
+               card->hw.dpmbase = (void *)conf->maddr;
 
        card->hw.dpmsize = SDLA_WINDOWSIZE;
        card->hw.type    = conf->hw_opt[0];
@@ -470,8 +470,8 @@ static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
                }
                /* FIXME::: COPY TO KERNEL BUFFER FIRST ?? */
                sti();  /* Not ideal but tough we have to do this */
-               if(copy_to_user((void*)(dump.ptr),
-                       (void*)(card->hw.dpmbase + pos), len))  
+               if(copy_to_user((void *)dump.ptr,
+                       (u8 *)card->hw.dpmbase + pos, len))     
                        return -EFAULT;
                cli();
                dump.length     -= len;
index 82880703372eb1612edb34c52d39873eb2d77760..a01000f88c9c47210da7049b6d2c47eadb414839 100644 (file)
@@ -298,6 +298,7 @@ __initfunc(static int sktr_pci_chk_card(struct device *dev))
 __initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
 {
        int i, err;
+       unsigned long flags;
 
        err = sktr_isa_chk_ioaddr(ioaddr);
        if(err < 0)
@@ -373,9 +374,11 @@ __initfunc(static int sktr_isa_chk_card(struct device *dev, int ioaddr))
                 }
         }
 
+       flags=claim_dma_lock();
        disable_dma(dev->dma);
         set_dma_mode(dev->dma, DMA_MODE_CASCADE);
         enable_dma(dev->dma);
+        release_dma_lock(flags);
 
        printk("%s: %s found at %#4x, using IRQ %d and DMA %d.\n",
                 dev->name, AdapterName, ioaddr, dev->irq, dev->dma);
@@ -1446,7 +1449,12 @@ static int sktr_close(struct device *dev)
        sktr_disable_interrupts(dev);
    
        if(dev->dma > 0) 
+       {
+               unsigned long flags=claim_dma_lock();
                disable_dma(dev->dma);
+               release_dma_lock(flags);
+       }
+       
        outw(0xFF00, dev->base_addr + SIFCMD);
        if(dev->dma > 0)
                outb(0xff, dev->base_addr + POSREG);
index 7113ba5240345f9cccb5f9065ed1c5cc6a133d8f..c7c9e3339019e0128bedf8d0bf567b388c49cfb4 100644 (file)
@@ -770,6 +770,7 @@ static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
        sp->obytes += skb->len;
        /* Control is high priority so it doesnt get queued behind data */
        skb->priority=1;
+       skb->dev = dev;
        dev_queue_xmit(skb);
 }
 
@@ -811,6 +812,7 @@ static void sppp_cisco_send (struct sppp *sp, int type, long par1, long par2)
                        ch->par2, ch->rel, ch->time0, ch->time1);
        sp->obytes += skb->len;
        skb->priority=1;
+       skb->dev = dev;
        dev_queue_xmit(skb);
 }
 
@@ -861,9 +863,11 @@ int sppp_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
        {
                case SPPPIOCCISCO:
                        sp->pp_flags|=PP_CISCO;
+                       dev->type = ARPHRD_HDLC;
                        break;
                case SPPPIOCPPP:
                        sp->pp_flags&=~PP_CISCO;
+                       dev->type = ARPHRD_PPP;
                        break;
                default:
                        return -EINVAL;
@@ -908,7 +912,7 @@ void sppp_attach(struct ppp_device *pd)
        dev->hard_header = sppp_hard_header;
        dev->rebuild_header = sppp_rebuild_header;
        dev->tx_queue_len = 10;
-       dev->type = ARPHRD_PPP;
+       dev->type = ARPHRD_HDLC;
        dev->addr_len = 0;
        dev->hard_header_len = sizeof(struct ppp_header);
        dev->mtu = PPP_MTU;
@@ -924,7 +928,7 @@ void sppp_attach(struct ppp_device *pd)
        dev->change_mtu = sppp_change_mtu;
        dev->hard_header_cache = NULL;
        dev->header_cache_update = NULL;
-       dev->flags = IFF_MULTICAST;
+       dev->flags = IFF_MULTICAST|IFF_POINTOPOINT|IFF_NOARP;
        dev_init_buffers(dev);
 }
 
index 7665f710e9f5bf52b05beecab6d166a243c6c046..4bb93aba15f006a93f6dac7dac8c31e8bc673feb 100644 (file)
@@ -65,7 +65,6 @@ static const int multicast_filter_limit = 32;
 #define PKT_BUF_SZ             1536                    /* Size of each temporary Rx buffer.*/
 
 /* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/config.h>
 #include <linux/version.h>
 #ifdef MODULE
 #ifdef MODVERSIONS
index 25f70ad3f09d4859720ce93765a3d24de3fffa3e..75cbb44b1cc54ce851145002f97709262733874a 100644 (file)
@@ -152,8 +152,9 @@ u8 z8530_hdlc_kilostream[]=
        3,      ENT_HM|RxCRC_ENAB|Rx8,
        5,      TxCRC_ENAB|RTS|TxENAB|Tx8|DTR,
        9,      0,              /* Disable interrupts */
+       6,      0xFF,
        7,      FLAG,
-       10,     ABUNDER|MARKIDLE|NRZ|CRCPS,
+       10,     ABUNDER|NRZ|CRCPS,/*MARKIDLE ??*/
        11,     TCTRxCP,
        14,     DISDPLL,
        15,     DCDIE|SYNCIE|CTSIE|TxUIE|BRKIE,
@@ -176,8 +177,9 @@ u8 z8530_hdlc_kilostream_85230[]=
        3,      ENT_HM|RxCRC_ENAB|Rx8,
        5,      TxCRC_ENAB|RTS|TxENAB|Tx8|DTR,
        9,      0,              /* Disable interrupts */
+       6,      0xFF,
        7,      FLAG,
-       10,     ABUNDER|MARKIDLE|NRZ|CRCPS,
+       10,     ABUNDER|NRZ|CRCPS,      /* MARKIDLE?? */
        11,     TCTRxCP,
        14,     DISDPLL,
        15,     DCDIE|SYNCIE|CTSIE|TxUIE|BRKIE,
@@ -389,6 +391,8 @@ static void z8530_dma_rx(struct z8530_channel *chan)
        if(chan->rxdma_on)
        {
                /* Special condition check only */
+               u8 r7=read_zsreg(chan, R7);
+               u8 r6=read_zsreg(chan, R6);
                u8 status=read_zsreg(chan, R1);
                if(status&END_FR)
                {
@@ -418,6 +422,7 @@ static void z8530_dma_tx(struct z8530_channel *chan)
 
 static void z8530_dma_status(struct z8530_channel *chan)
 {
+       unsigned long flags;
        u8 status=read_zsreg(chan, R0);
        u8 altered=chan->status^status;
        
@@ -427,10 +432,12 @@ static void z8530_dma_status(struct z8530_channel *chan)
        {
                if(status&TxEOM)
                {
+                       flags=claim_dma_lock();
                        /* Transmit underrun */
                        disable_dma(chan->txdma);
                        clear_dma_ff(chan->txdma);      
                        chan->txdma_on=0;
+                       release_dma_lock(flags);
                        z8530_tx_done(chan);
                }
        }
@@ -461,6 +468,15 @@ struct z8530_irqhandler z8530_dma_sync=
 
 EXPORT_SYMBOL(z8530_dma_sync);
 
+struct z8530_irqhandler z8530_txdma_sync=
+{
+       z8530_rx,
+       z8530_dma_tx,
+       z8530_dma_status
+};
+
+EXPORT_SYMBOL(z8530_txdma_sync);
+
 /*
  *     Interrupt vectors for a Z8530 that is in 'parked' mode.
  *     For machines with PCI Z85x30 cards, or level triggered interrupts
@@ -566,7 +582,7 @@ void z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                irqs->status(&dev->chanB);
                }
        }
-       if(work==200)
+       if(work==5000)
                printk(KERN_ERR "%s: interrupt jammed - abort(0x%X)!\n", dev->name, intr);
        /* Ok all done */
        locker=0;
@@ -619,6 +635,8 @@ EXPORT_SYMBOL(z8530_sync_close);
 
 int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
 {
+       unsigned long flags;
+       
        c->sync = 1;
        c->mtu = dev->mtu;
        c->count = 0;
@@ -665,6 +683,7 @@ int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
                return -ENOBUFS;
        }
        c->tx_dma_used=0;
+       c->dma_tx = 1;
        c->dma_num=0;
        c->dma_ready=1;
        
@@ -672,13 +691,23 @@ int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
         *      Enable DMA control mode
         */
         
-       c->regs[R1]|= WT_RDY_RT|WT_FN_RDYFN;
+       /*
+        *      TX DMA via DIR/REQ
+        */
+        
+       c->regs[R14]|= DTRREQ;
+       write_zsreg(c, R14, c->regs[R14]);     
+
+       /*
+        *      RX DMA via W/Req
+        */      
+
+       c->regs[R1]|= WT_FN_RDYFN;
+       c->regs[R1]|= WT_RDY_RT;
        c->regs[R1]|= INT_ERR_Rx;
        write_zsreg(c, R1, c->regs[R1]);
        c->regs[R1]|= WT_RDY_ENAB;
        write_zsreg(c, R1, c->regs[R1]);            
-       c->regs[R14]|= DTRREQ;
-       write_zsreg(c, R14, c->regs[R14]);     
        
        /*
         *      DMA interrupts
@@ -688,9 +717,11 @@ int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
         *      Set up the DMA configuration
         */     
         
+       flags=claim_dma_lock();
+        
        disable_dma(c->rxdma);
        clear_dma_ff(c->rxdma);
-       set_dma_mode(c->rxdma, DMA_MODE_READ);
+       set_dma_mode(c->rxdma, DMA_MODE_READ|0x10);
        set_dma_addr(c->rxdma, virt_to_bus(c->rx_buf[0]));
        set_dma_count(c->rxdma, c->mtu);
        enable_dma(c->rxdma);
@@ -700,6 +731,8 @@ int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
        set_dma_mode(c->txdma, DMA_MODE_WRITE);
        disable_dma(c->txdma);
        
+       release_dma_lock(flags);
+       
        /*
         *      Select the DMA interrupt handlers
         */
@@ -719,6 +752,8 @@ EXPORT_SYMBOL(z8530_sync_dma_open);
 int z8530_sync_dma_close(struct device *dev, struct z8530_channel *c)
 {
        u8 chk;
+       unsigned long flags;
+       
        c->irqs = &z8530_nop;
        c->max = 0;
        c->sync = 0;
@@ -726,12 +761,17 @@ int z8530_sync_dma_close(struct device *dev, struct z8530_channel *c)
        /*
         *      Disable the PC DMA channels
         */
-        
+       
+       flags=claim_dma_lock(); 
        disable_dma(c->rxdma);
        clear_dma_ff(c->rxdma);
+       
        c->rxdma_on = 0;
+       
        disable_dma(c->txdma);
        clear_dma_ff(c->txdma);
+       release_dma_lock(flags);
+       
        c->txdma_on = 0;
        c->tx_dma_used = 0;
 
@@ -775,6 +815,137 @@ int z8530_sync_dma_close(struct device *dev, struct z8530_channel *c)
 
 EXPORT_SYMBOL(z8530_sync_dma_close);
 
+int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c)
+{
+       printk("Opening sync interface for TX-DMA\n");
+       c->sync = 1;
+       c->mtu = dev->mtu;
+       c->count = 0;
+       c->skb = NULL;
+       c->skb2 = NULL;
+       
+       /*
+        *      Load the PIO receive ring
+        */
+
+       z8530_rx_done(c);
+       z8530_rx_done(c);
+
+       /*
+        *      Load the DMA interfaces up
+        */
+
+       c->rxdma_on = 0;
+       c->txdma_on = 0;
+       
+       c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+       if(c->tx_dma_buf[0]==NULL)
+       {
+               kfree(c->rx_buf[0]);
+               kfree(c->rx_buf[1]);
+               c->rx_buf[0]=NULL;
+               return -ENOBUFS;
+       }
+       c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA);
+       if(c->tx_dma_buf[1]==NULL)
+       {
+               kfree(c->tx_dma_buf[0]);
+               kfree(c->rx_buf[0]);
+               kfree(c->rx_buf[1]);
+               c->rx_buf[0]=NULL;
+               c->rx_buf[1]=NULL;
+               c->tx_dma_buf[0]=NULL;
+               return -ENOBUFS;
+       }
+       c->tx_dma_used=0;
+       c->dma_num=0;
+       c->dma_ready=1;
+       c->dma_tx = 1;
+
+       /*
+        *      Enable DMA control mode
+        */
+
+       /*
+        *      TX DMA via DIR/REQ
+        */
+       c->regs[R14]|= DTRREQ;
+       write_zsreg(c, R14, c->regs[R14]);     
+       
+       /*
+        *      Set up the DMA configuration
+        */     
+        
+       disable_dma(c->txdma);
+       clear_dma_ff(c->txdma);
+       set_dma_mode(c->txdma, DMA_MODE_WRITE);
+       disable_dma(c->txdma);
+       
+       /*
+        *      Select the DMA interrupt handlers
+        */
+
+       c->rxdma_on = 0;
+       c->txdma_on = 1;
+       c->tx_dma_used = 1;
+        
+       c->irqs = &z8530_txdma_sync;
+       printk("Loading RX\n");
+       z8530_rtsdtr(c,1);
+       printk("Rx interrupts ON\n");   
+       write_zsreg(c, R3, c->regs[R3]|RxENABLE);
+       return 0;
+}
+
+EXPORT_SYMBOL(z8530_sync_txdma_open);
+       
+int z8530_sync_txdma_close(struct device *dev, struct z8530_channel *c)
+{
+       u8 chk;
+       c->irqs = &z8530_nop;
+       c->max = 0;
+       c->sync = 0;
+       
+       /*
+        *      Disable the PC DMA channels
+        */
+        
+       disable_dma(c->txdma);
+       clear_dma_ff(c->txdma);
+       c->txdma_on = 0;
+       c->tx_dma_used = 0;
+
+       /*
+        *      Disable DMA control mode
+        */
+        
+       c->regs[R1]&= ~WT_RDY_ENAB;
+       write_zsreg(c, R1, c->regs[R1]);            
+       c->regs[R1]&= ~(WT_RDY_RT|WT_FN_RDYFN|INT_ERR_Rx);
+       c->regs[R1]|= INT_ALL_Rx;
+       write_zsreg(c, R1, c->regs[R1]);
+       c->regs[R14]&= ~DTRREQ;
+       write_zsreg(c, R14, c->regs[R14]);   
+       
+       if(c->tx_dma_buf[0])
+       {
+               kfree(c->tx_dma_buf[0]);
+               c->tx_dma_buf[0]=NULL;
+       }
+       if(c->tx_dma_buf[1])
+       {
+               kfree(c->tx_dma_buf[1]);
+               c->tx_dma_buf[1]=NULL;
+       }
+       chk=read_zsreg(c,R0);
+       write_zsreg(c, R3, c->regs[R3]);
+       z8530_rtsdtr(c,0);
+       return 0;
+}
+
+
+EXPORT_SYMBOL(z8530_sync_txdma_close);
+
 /*
  *     Describe a Z8530 in a standard format. We must pass the I/O as
  *     the port offset isnt predictable. The main reason for this function
@@ -929,7 +1100,12 @@ static void z8530_tx_begin(struct z8530_channel *c)
        if(c->tx_skb==NULL)
        {
                /* Idle on */
-               disable_dma(c->txdma);
+               if(c->txdma)
+               {
+                       flags=claim_dma_lock();
+                       disable_dma(c->txdma);
+                       release_dma_lock(flags);
+               }
                c->txcount=0;
        }
        else
@@ -938,19 +1114,22 @@ static void z8530_tx_begin(struct z8530_channel *c)
                c->txcount=c->tx_skb->len;
                
                
-               if(c->tx_dma_used)
+               if(c->dma_tx)
                {
                        /*
-                        *      FIXME. DMA is broken for the non 85230,
+                        *      FIXME. DMA is broken for the original 8530,
                         *      on the older parts we need to set a flag and
                         *      wait for a further TX interrupt to fire this
                         *      stage off       
                         */
+                        
+                       flags=claim_dma_lock();
                        disable_dma(c->txdma);
                        clear_dma_ff(c->txdma);
                        set_dma_addr(c->txdma, virt_to_bus(c->tx_ptr));
                        set_dma_count(c->txdma, c->txcount);
                        enable_dma(c->txdma);
+                       release_dma_lock(flags);
                        write_zsreg(c, R5, c->regs[R5]|TxENAB);
                }
                else
@@ -1020,12 +1199,17 @@ static void z8530_rx_done(struct z8530_channel *c)
                 *      Save the ready state and the buffer currently
                 *      being used as the DMA target
                 */
+
                int ready=c->dma_ready;
-               char *rxb=c->rx_buf[c->dma_num];
+               unsigned char *rxb=c->rx_buf[c->dma_num];
+               unsigned long flags;
                
                /*
                 *      Complete this DMA. Neccessary to find the length
                 */             
+                
+               flags=claim_dma_lock();
+               
                disable_dma(c->rxdma);
                clear_dma_ff(c->rxdma);
                c->rxdma_on=0;
@@ -1042,16 +1226,21 @@ static void z8530_rx_done(struct z8530_channel *c)
                if(ready)
                {
                        c->dma_num^=1;
-                       set_dma_mode(c->rxdma, DMA_MODE_READ);
+                       set_dma_mode(c->rxdma, DMA_MODE_READ|0x10);
                        set_dma_addr(c->rxdma, virt_to_bus(c->rx_buf[c->dma_num]));
                        set_dma_count(c->rxdma, c->mtu);
                        c->rxdma_on = 1;
                        enable_dma(c->rxdma);
+                       /* Stop any frames that we missed the head of 
+                          from passing */
+                       write_zsreg(c, R0, RES_Rx_CRC);
                }
                else
                        /* Can't occur as we dont reenable the DMA irq until
                           after the flip is done */
                        printk("DMA flip overrun!\n");
+                       
+               release_dma_lock(flags);
                
                /*
                 *      Shove the old buffer into an sk_buff. We can't DMA
@@ -1127,6 +1316,21 @@ static void z8530_rx_done(struct z8530_channel *c)
                printk("Lost a frame\n");
 }
 
+/*
+ *     Cannot DMA over a 64K boundary on a PC
+ */
+extern inline int spans_boundary(struct sk_buff *skb)
+{
+       unsigned long a=(unsigned long)skb->data;
+       a^=(a+skb->len);
+       if(a&0x00010000)        /* If the 64K bit is different.. */
+       {
+               printk("spanner\n");
+               return 1;
+       }
+       return 0;
+}
 
 /*
  *     Queue a packet for transmission. Because we have rather
@@ -1151,7 +1355,7 @@ int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb)
         *      limit, then copy to the flip buffer
         */
         
-       if(c->dma_tx && (unsigned long)(virt_to_bus(skb->data+skb->len))>=16*1024*1024)
+       if(c->dma_tx && ((unsigned long)(virt_to_bus(skb->data+skb->len))>=16*1024*1024 || spans_boundary(skb)))
        {
                /* 
                 *      Send the flip buffer, and flip the flippy bit.
index 1fcb3dc6e73e02469802f60a954c4ecf017c4f37..e04176054a2b757bdd5ebcb890f85daec5a32673 100644 (file)
@@ -401,6 +401,8 @@ extern int z8530_sync_open(struct device *, struct z8530_channel *);
 extern int z8530_sync_close(struct device *, struct z8530_channel *);
 extern int z8530_sync_dma_open(struct device *, struct z8530_channel *);
 extern int z8530_sync_dma_close(struct device *, struct z8530_channel *);
+extern int z8530_sync_txdma_open(struct device *, struct z8530_channel *);
+extern int z8530_sync_txdma_close(struct device *, struct z8530_channel *);
 extern int z8530_channel_load(struct z8530_channel *, u8 *);
 extern int z8530_queue_xmit(struct z8530_channel *c, struct sk_buff *skb);
 extern struct net_device_stats *z8530_get_stats(struct z8530_channel *c);
index da6d30a53efa0bb0433a6213a326cfc0874726bf..7b12da6ee8da4d14c2780d1e49694fc3bb9509ed 100644 (file)
@@ -591,6 +591,7 @@ static void znet_rx(struct device *dev)
 /* The inverse routine to znet_open(). */
 static int znet_close(struct device *dev)
 {
+       unsigned long flags;
        int ioaddr = dev->base_addr;
 
        dev->tbusy = 1;
@@ -598,8 +599,10 @@ static int znet_close(struct device *dev)
 
        outb(CMD0_RESET, ioaddr);                       /* CMD0_RESET */
 
+       flags=claim_dma_lock();
        disable_dma(zn.rx_dma);
        disable_dma(zn.tx_dma);
+       release_dma_lock(flags);
 
        free_irq(dev->irq, dev);
 
@@ -662,10 +665,14 @@ static void set_multicast_list(struct device *dev)
 
 void show_dma(void)
 {
+       unsigned long flags;
        short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE;
        unsigned addr = inb(dma_port);
        addr |= inb(dma_port) << 8;
+
+       flags=claim_dma_lock();
        printk("Addr: %04x cnt:%3x...", addr<<1, get_dma_residue(zn.tx_dma));
+       release_dma_lock(flags);
 }
 
 /* Initialize the hardware.  We have to do this when the board is open()ed
@@ -680,22 +687,22 @@ static void hardware_init(struct device *dev)
        /* Reset the chip, and start it up. */
        outb(CMD0_RESET, ioaddr);
 
-       cli(); {                                                        /* Protect against a DMA flip-flop */
-               disable_dma(zn.rx_dma);                 /* reset by an interrupting task. */
-               clear_dma_ff(zn.rx_dma);
-               set_dma_mode(zn.rx_dma, DMA_RX_MODE);
-               set_dma_addr(zn.rx_dma, (unsigned int) zn.rx_start);
-               set_dma_count(zn.rx_dma, RX_BUF_SIZE);
-               enable_dma(zn.rx_dma);
-               /* Now set up the Tx channel. */
-               disable_dma(zn.tx_dma);
-               clear_dma_ff(zn.tx_dma);
-               set_dma_mode(zn.tx_dma, DMA_TX_MODE);
-               set_dma_addr(zn.tx_dma, (unsigned int) zn.tx_start);
-               set_dma_count(zn.tx_dma, zn.tx_buf_len<<1);
-               enable_dma(zn.tx_dma);
-       } sti();
-
+       flags=claim_dma_lock();
+       disable_dma(zn.rx_dma);                 /* reset by an interrupting task. */
+       clear_dma_ff(zn.rx_dma);
+       set_dma_mode(zn.rx_dma, DMA_RX_MODE);
+       set_dma_addr(zn.rx_dma, (unsigned int) zn.rx_start);
+       set_dma_count(zn.rx_dma, RX_BUF_SIZE);
+       enable_dma(zn.rx_dma);
+       /* Now set up the Tx channel. */
+       disable_dma(zn.tx_dma);
+       clear_dma_ff(zn.tx_dma);
+       set_dma_mode(zn.tx_dma, DMA_TX_MODE);
+       set_dma_addr(zn.tx_dma, (unsigned int) zn.tx_start);
+       set_dma_count(zn.tx_dma, zn.tx_buf_len<<1);
+       enable_dma(zn.tx_dma);
+       release_dma_lock(flags);
+       
        if (znet_debug > 1)
          printk(KERN_DEBUG "%s: Initializing the i82593, tx buf %p... ", dev->name,
                         zn.tx_start);
index 8a79c8400fab857824624e9b7e7f9498951ef5f5..ab60f25f51c7865f0ef41e25d929f41be736c176 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Id: oldproc.c,v 1.20 1998/08/23 12:12:01 mj Exp $
+ *     $Id: oldproc.c,v 1.24 1998/10/11 15:13:04 mj Exp $
  *
  *     Backward-compatible procfs interface for PCI.
  *
@@ -200,6 +200,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( PROMISE,        PROMISE_5300,   "DC5030"),
        DEVICE( N9,             N9_I128,        "Imagine 128"),
        DEVICE( N9,             N9_I128_2,      "Imagine 128v2"),
+       DEVICE( N9,             N9_I128_T2R,    "Revolution 3D"),
        DEVICE( UMC,            UMC_UM8673F,    "UM8673F"),
        DEVICE( UMC,            UMC_UM8891A,    "UM8891A"),
        DEVICE( UMC,            UMC_UM8886BF,   "UM8886BF"),
@@ -528,10 +529,10 @@ struct pci_dev_info dev_info[] = {
        DEVICE( ADAPTEC,        ADAPTEC_7883,   "AIC-7883U"),
        DEVICE( ADAPTEC,        ADAPTEC_7884,   "AIC-7884U"),
        DEVICE( ADAPTEC,        ADAPTEC_1030,   "ABA-1030 DVB receiver"),
-  DEVICE( ADAPTEC2, ADAPTEC2_2940U2, "AHA-2940U2"),
-  DEVICE( ADAPTEC2, ADAPTEC2_7890, "AIC-7890/1"),
-  DEVICE( ADAPTEC2, ADAPTEC2_3940U2, "AHA-3940U2"),
-  DEVICE( ADAPTEC2, ADAPTEC2_7896, "AIC-7896/7"),
+       DEVICE( ADAPTEC2,       ADAPTEC2_2940U2,"AHA-2940U2"),
+       DEVICE( ADAPTEC2,       ADAPTEC2_7890,  "AIC-7890/1"),
+       DEVICE( ADAPTEC2,       ADAPTEC2_3940U2,"AHA-3940U2"),
+       DEVICE( ADAPTEC2,       ADAPTEC2_7896,  "AIC-7896/7"),
        DEVICE( ATRONICS,       ATRONICS_2015,  "IDE-2015PL"),
        DEVICE( TIGERJET,       TIGERJET_300,   "Tiger300 ISDN"),
        DEVICE( ARK,            ARK_STING,      "Stingray"),
index 82ba36ef1222ad8905922b125937be79a266c456..6118eb6435bf0e1a1d3c541e33b332428658ff53 100644 (file)
@@ -91,7 +91,7 @@ static long read_polled(struct parport *port, char *buf,
 
 int parport_probe(struct parport *port, char *buffer, int len)
 {
-       struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, NULL, NULL, PARPORT_DEV_TRAN, &dev);
+       struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, NULL, NULL, 0, &dev);
 
        int result = 0;
 
index 61d35daeb065abf4be6869461c41c4c84249bfd2..f637860577f51ed978f9421c92cca6be89755ba7 100644 (file)
@@ -53,7 +53,7 @@ dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
   if [ "$CONFIG_SCSI_PPA" != "n" ]; then
-    int  '  Pedantic EPP-checking'   CONFIG_SCSI_PPA_HAVE_PEDANTIC 2 0 3
+    bool  '  Pedantic EPP-checking'   CONFIG_SCSI_PPA_HAVE_PEDANTIC
   fi
   dep_tristate 'IOMEGA ZIP Plus drive SCSI support' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
 fi
index 3080edc96d88af40df69873003583246e9a4735a..5548630805cd6acea6f591474aafaab1a905394e 100644 (file)
@@ -317,15 +317,14 @@ NCR53c406a_dma_setup (unsigned char *ptr,
     if ((count & 1) || (((unsigned) ptr) & 1))
         panic ("NCR53c406a: attempted unaligned DMA transfer\n"); 
     
-    save_flags(flags);
-    cli();
+    flags=claim_dma_lock();
     disable_dma(dma_chan);
     clear_dma_ff(dma_chan);
     set_dma_addr(dma_chan, (long) ptr);
     set_dma_count(dma_chan, count);
     set_dma_mode(dma_chan, mode);
     enable_dma(dma_chan);
-    restore_flags(flags);
+    release_dma_lock(flags);    
     
     return count;
 }
@@ -343,12 +342,12 @@ NCR53c406a_dma_read(unsigned char *src, unsigned int count) {
 static __inline__ int 
 NCR53c406a_dma_residual (void) {
     register int tmp;
-    unsigned long flags = 0;
-    save_flags(flags);
-    cli();
+    unsigned long flags;
+
+    flags=claim_dma_lock();
     clear_dma_ff(dma_chan);
     tmp = get_dma_residue(dma_chan);
-    restore_flags(flags);
+    release_dma_lock(flags);
     
     return tmp;
 }
index 597cb8ddd629d1b6c5b64f4afb54de5ee9fdf994..b350d9d5812f67bfce4f9e9c4b24a3490a58f83d 100644 (file)
@@ -412,7 +412,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
     the system. Each file presents the current configuration and transfer
     statistics (enabled with #define in aic7xxx.c) for each controller.
 
-    Thanks to Michael Neuffer for for his upper-level SCSI help, and
+    Thanks to Michael Neuffer for his upper-level SCSI help, and
     Matthew Jacob for statistics support.
 
   Debugging the driver
index 9999990f3e034e257dfde448d862649342f0076b..0d16c28762fe57321cf08e5e7d6a5839418fd80f 100644 (file)
@@ -444,6 +444,7 @@ MODULE_PARM(aha152x1, "1-8i");
 
 /* set by aha152x_setup according to the command line */
 static int  setup_count=0;
+static int  registered_count=0;
 static struct aha152x_setup {
   int io_port;
   int irq;
@@ -951,6 +952,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
 
     shpnt = aha152x_host[setup[i].irq-IRQ_MIN] =
       scsi_register(tpnt, sizeof(struct aha152x_hostdata));
+    registered_count++;
 
     shpnt->io_port                     = setup[i].io_port;
     shpnt->n_io_port                   = IO_RANGE;
@@ -1013,7 +1015,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
 
     SETBITS(DMACNTRL0, INTEN);
 
-    ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", NULL);
+    ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", shpnt);
     if(ok<0) {
       if(ok == -EINVAL)
         printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq);
@@ -1024,6 +1026,8 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
       printk("aha152x: driver needs an IRQ.\n");
 
       scsi_unregister(shpnt);
+      registered_count--;
+      release_region(shpnt->io_port, IO_RANGE);
       shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0;
       continue;
     }
@@ -1037,7 +1041,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
     while(!HOSTDATA(shpnt)->swint && jiffies<the_time)
       barrier();
 
-    free_irq(shpnt->irq,0);
+    free_irq(shpnt->irq,shpnt);
 
     if(!HOSTDATA(shpnt)->swint) {
       if(TESTHI(DMASTAT, INTSTAT)) {
@@ -1049,6 +1053,8 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
       printk("aha152x: IRQ %d possibly wrong.  Please verify.\n", shpnt->irq);
 
       scsi_unregister(shpnt);
+      registered_count--;
+      release_region(shpnt->io_port, IO_RANGE);
       shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0;
       continue;
     }
@@ -1061,12 +1067,23 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
     SETPORT(SSTAT0, 0x7f);
     SETPORT(SSTAT1, 0xef);
 
-    if(request_irq(shpnt->irq,aha152x_intr,SA_INTERRUPT,"aha152x",NULL)<0) {
+    if(request_irq(shpnt->irq,aha152x_intr,SA_INTERRUPT,"aha152x",shpnt)<0) {
       printk("aha152x: failed to reassign interrupt.\n");
     }
   }
   
-  return (setup_count>0);
+  return (registered_count>0);
+}
+
+
+int aha152x_release(struct Scsi_Host *shpnt)
+{
+  if (shpnt->irq)
+    free_irq(shpnt->irq, shpnt);
+  if (shpnt->io_port)
+    release_region(shpnt->io_port, IO_RANGE);
+
+  return 0;
 }
 
 /* 
index dba7eba9313bace8916a95ec17cf1096cb6ff5ae..694adcb7331c8d573b11ece5068fce79d03909a8 100644 (file)
@@ -36,6 +36,7 @@ extern struct proc_dir_entry proc_scsi_aha152x;
                   queuecommand:       aha152x_queue,     \
                   abort:              aha152x_abort,     \
                   reset:              aha152x_reset,     \
+                  release:            aha152x_release,   \
                   slave_attach:       0,                 \
                   bios_param:         aha152x_biosparam,  \
                   can_queue:          1,                 \
index e528e0cc08c18a9b0c3a3573f5b6a55f01369446..7d40dae7459663337ab0d06181811fb060e96475 100644 (file)
 #include "hosts.h"
 #include "aic7xxx.h"
 
-#include "aic7xxx/bsd_q.h"
 #include "aic7xxx/sequencer.h"
 #include "aic7xxx/scsi_message.h"
 #include "aic7xxx_reg.h"
@@ -350,7 +349,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.0"
+#define AIC7XXX_C_VERSION  "5.1.2"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -6281,8 +6280,10 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
       (((aic_inb(p, SEQADDR1) << 8) & 0x100) | aic_inb(p, SEQADDR0)));
     if (aic7xxx_panic_on_abort)
       aic7xxx_panic_abort(p, NULL);
+#ifdef CONFIG_PCI
     if (errno & PCIERRSTAT)
       aic7xxx_pci_intr(p);
+#endif
     if (errno & (SQPARERR | ILLOPCODE | ILLSADDR))
     {
       sti();
diff --git a/drivers/scsi/aic7xxx/bsd_q.h b/drivers/scsi/aic7xxx/bsd_q.h
deleted file mode 100644 (file)
index 042fc39..0000000
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Copyright (c) 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     @(#)queue.h     8.5 (Berkeley) 8/20/94
- * $Id: queue.h,v 1.21 1998/05/12 03:55:25 gibbs Exp $
- */
-
-#ifndef _SYS_QUEUE_H_
-#define        _SYS_QUEUE_H_
-
-/*
- * This file defines five types of data structures: singly-linked lists,
- * slingly-linked tail queues, lists, tail queues, and circular queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction.  Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may only be traversed in the forward direction.
- *
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- *                     SLIST   LIST    STAILQ  TAILQ   CIRCLEQ
- * _HEAD               +       +       +       +       +
- * _ENTRY              +       +       +       +       +
- * _INIT               +       +       +       +       +
- * _EMPTY              +       +       +       +       +
- * _FIRST              +       +       -       +       +
- * _NEXT               +       +       -       +       +
- * _PREV               -       -       -       +       +
- * _LAST               -       -       -       +       +
- * _FOREACH            +       +       -       +       -
- * _INSERT_HEAD                +       +       +       +       +
- * _INSERT_BEFORE      -       +       -       +       +
- * _INSERT_AFTER       +       +       +       +       +
- * _INSERT_TAIL                -       -       +       +       +
- * _REMOVE_HEAD                +       -       +       -       -
- * _REMOVE             +       +       +       +       +
- *
- */
-
-/*
- * Singly-linked List definitions.
- */
-#define SLIST_HEAD(name, type)                                         \
-struct name {                                                          \
-       struct type *slh_first; /* first element */                     \
-}
-#define SLIST_ENTRY(type)                                              \
-struct {                                                               \
-       struct type *sle_next;  /* next element */                      \
-}
-/*
- * Singly-linked List functions.
- */
-#define        SLIST_EMPTY(head)       ((head)->slh_first == NULL)
-
-#define        SLIST_FIRST(head)       ((head)->slh_first)
-
-#define SLIST_FOREACH(var, head, field)                                        \
-       for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
-
-#define SLIST_INIT(head) {                                             \
-       (head)->slh_first = NULL;                                       \
-}
-
-#define SLIST_INSERT_AFTER(slistelm, elm, field) do  {                 \
-       (elm)->field.sle_next = (slistelm)->field.sle_next;             \
-       (slistelm)->field.sle_next = (elm);                             \
-} while (0)
-
-#define SLIST_INSERT_HEAD(head, elm, field) do {                       \
-       (elm)->field.sle_next = (head)->slh_first;                      \
-       (head)->slh_first = (elm);                                      \
-} while (0)
-
-#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
-
-#define SLIST_REMOVE_HEAD(head, field) do {                            \
-       (head)->slh_first = (head)->slh_first->field.sle_next;          \
-} while (0)
-
-#define SLIST_REMOVE(head, elm, type, field) do {                      \
-       if ((head)->slh_first == (elm)) {                               \
-               SLIST_REMOVE_HEAD((head), field);                       \
-       }                                                               \
-       else {                                                          \
-               struct type *curelm = (head)->slh_first;                \
-               while( curelm->field.sle_next != (elm) )                \
-                       curelm = curelm->field.sle_next;                \
-               curelm->field.sle_next =                                \
-                   curelm->field.sle_next->field.sle_next;             \
-       }                                                               \
-} while (0)
-
-/*
- * Singly-linked Tail queue definitions.
- */
-#define STAILQ_HEAD(name, type)                                                \
-struct name {                                                          \
-       struct type *stqh_first;/* first element */                     \
-       struct type **stqh_last;/* addr of last next element */         \
-}
-
-#define STAILQ_ENTRY(type)                                             \
-struct {                                                               \
-       struct type *stqe_next; /* next element */                      \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#define        STAILQ_INIT(head) do {                                          \
-       (head)->stqh_first = NULL;                                      \
-       (head)->stqh_last = &(head)->stqh_first;                        \
-} while (0)
-
-#define STAILQ_FIRST(head)     ((head)->stqh_first)
-#define STAILQ_LAST(head)      (*(head)->stqh_last)
-
-#define STAILQ_INSERT_HEAD(head, elm, field) do {                      \
-       if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)      \
-               (head)->stqh_last = &(elm)->field.stqe_next;            \
-       (head)->stqh_first = (elm);                                     \
-} while (0)
-
-#define STAILQ_INSERT_TAIL(head, elm, field) do {                      \
-       (elm)->field.stqe_next = NULL;                                  \
-       *(head)->stqh_last = (elm);                                     \
-       (head)->stqh_last = &(elm)->field.stqe_next;                    \
-} while (0)
-
-#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {              \
-       if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
-               (head)->stqh_last = &(elm)->field.stqe_next;            \
-       (tqelm)->field.stqe_next = (elm);                               \
-} while (0)
-
-#define STAILQ_NEXT(elm, field)        ((elm)->field.stqe_next)
-
-#define STAILQ_REMOVE_HEAD(head, field) do {                           \
-       if (((head)->stqh_first =                                       \
-            (head)->stqh_first->field.stqe_next) == NULL)              \
-               (head)->stqh_last = &(head)->stqh_first;                \
-} while (0)
-
-#define STAILQ_REMOVE(head, elm, type, field) do {                     \
-       if ((head)->stqh_first == (elm)) {                              \
-               STAILQ_REMOVE_HEAD(head, field);                        \
-       }                                                               \
-       else {                                                          \
-               struct type *curelm = (head)->stqh_first;               \
-               while( curelm->field.stqe_next != (elm) )               \
-                       curelm = curelm->field.stqe_next;               \
-               if((curelm->field.stqe_next =                           \
-                   curelm->field.stqe_next->field.stqe_next) == NULL)  \
-                       (head)->stqh_last = &(curelm)->field.stqe_next; \
-       }                                                               \
-} while (0)
-
-/*
- * List definitions.
- */
-
-#define LIST_ENTRY(type)                                               \
-struct {                                                               \
-       struct type *le_next;   /* next element */                      \
-       struct type **le_prev;  /* address of previous next element */  \
-}
-
-/*
- * List functions.
- */
-
-#define        LIST_EMPTY(head) ((head)->lh_first == NULL)
-
-#define LIST_FIRST(head)       ((head)->lh_first)
-
-#define LIST_FOREACH(var, head, field)                                 \
-       for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
-
-#define        LIST_INIT(head) do {                                            \
-       (head)->lh_first = NULL;                                        \
-} while (0)
-
-#define LIST_INSERT_AFTER(listelm, elm, field) do {                    \
-       if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
-               (listelm)->field.le_next->field.le_prev =               \
-                   &(elm)->field.le_next;                              \
-       (listelm)->field.le_next = (elm);                               \
-       (elm)->field.le_prev = &(listelm)->field.le_next;               \
-} while (0)
-
-#define LIST_INSERT_BEFORE(listelm, elm, field) do {                   \
-       (elm)->field.le_prev = (listelm)->field.le_prev;                \
-       (elm)->field.le_next = (listelm);                               \
-       *(listelm)->field.le_prev = (elm);                              \
-       (listelm)->field.le_prev = &(elm)->field.le_next;               \
-} while (0)
-
-#define LIST_INSERT_HEAD(head, elm, field) do {                                \
-       if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
-               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
-       (head)->lh_first = (elm);                                       \
-       (elm)->field.le_prev = &(head)->lh_first;                       \
-} while (0)
-
-#define LIST_NEXT(elm, field)  ((elm)->field.le_next)
-
-#define LIST_REMOVE(elm, field) do {                                   \
-       if ((elm)->field.le_next != NULL)                               \
-               (elm)->field.le_next->field.le_prev =                   \
-                   (elm)->field.le_prev;                               \
-       *(elm)->field.le_prev = (elm)->field.le_next;                   \
-} while (0)
-
-/*
- * Tail queue definitions.
- */
-#define TAILQ_HEAD(name, type)                                         \
-struct name {                                                          \
-       struct type *tqh_first; /* first element */                     \
-       struct type **tqh_last; /* addr of last next element */         \
-}
-
-#define TAILQ_HEAD_INITIALIZER(head)                                   \
-       { NULL, &(head).tqh_first }
-
-#define TAILQ_ENTRY(type)                                              \
-struct {                                                               \
-       struct type *tqe_next;  /* next element */                      \
-       struct type **tqe_prev; /* address of previous next element */  \
-}
-
-/*
- * Tail queue functions.
- */
-#define        TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
-
-#define TAILQ_FOREACH(var, head, field)                                        \
-       for (var = TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))
-
-#define        TAILQ_FIRST(head) ((head)->tqh_first)
-
-#define        TAILQ_LAST(head, headname) \
-       (*(((struct headname *)((head)->tqh_last))->tqh_last))
-
-#define        TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define TAILQ_PREV(elm, headname, field) \
-       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define        TAILQ_INIT(head) do {                                           \
-       (head)->tqh_first = NULL;                                       \
-       (head)->tqh_last = &(head)->tqh_first;                          \
-} while (0)
-
-#define TAILQ_INSERT_HEAD(head, elm, field) do {                       \
-       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
-               (head)->tqh_first->field.tqe_prev =                     \
-                   &(elm)->field.tqe_next;                             \
-       else                                                            \
-               (head)->tqh_last = &(elm)->field.tqe_next;              \
-       (head)->tqh_first = (elm);                                      \
-       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
-} while (0)
-
-#define TAILQ_INSERT_TAIL(head, elm, field) do {                       \
-       (elm)->field.tqe_next = NULL;                                   \
-       (elm)->field.tqe_prev = (head)->tqh_last;                       \
-       *(head)->tqh_last = (elm);                                      \
-       (head)->tqh_last = &(elm)->field.tqe_next;                      \
-} while (0)
-
-#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {             \
-       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
-               (elm)->field.tqe_next->field.tqe_prev =                 \
-                   &(elm)->field.tqe_next;                             \
-       else                                                            \
-               (head)->tqh_last = &(elm)->field.tqe_next;              \
-       (listelm)->field.tqe_next = (elm);                              \
-       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
-} while (0)
-
-#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                  \
-       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
-       (elm)->field.tqe_next = (listelm);                              \
-       *(listelm)->field.tqe_prev = (elm);                             \
-       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
-} while (0)
-
-#define TAILQ_REMOVE(head, elm, field) do {                            \
-       if (((elm)->field.tqe_next) != NULL)                            \
-               (elm)->field.tqe_next->field.tqe_prev =                 \
-                   (elm)->field.tqe_prev;                              \
-       else                                                            \
-               (head)->tqh_last = (elm)->field.tqe_prev;               \
-       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
-} while (0)
-
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type)                                       \
-struct name {                                                          \
-       struct type *cqh_first;         /* first element */             \
-       struct type *cqh_last;          /* last element */              \
-}
-
-#define CIRCLEQ_ENTRY(type)                                            \
-struct {                                                               \
-       struct type *cqe_next;          /* next element */              \
-       struct type *cqe_prev;          /* previous element */          \
-}
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
-
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-
-#define CIRCLEQ_FOREACH(var, head, field)                              \
-       for((var) = (head)->cqh_first;                                  \
-           (var) != (void *)(head);                                    \
-           (var) = (var)->field.cqe_next)
-
-#define        CIRCLEQ_INIT(head) do {                                         \
-       (head)->cqh_first = (void *)(head);                             \
-       (head)->cqh_last = (void *)(head);                              \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {           \
-       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
-       (elm)->field.cqe_prev = (listelm);                              \
-       if ((listelm)->field.cqe_next == (void *)(head))                \
-               (head)->cqh_last = (elm);                               \
-       else                                                            \
-               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
-       (listelm)->field.cqe_next = (elm);                              \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {          \
-       (elm)->field.cqe_next = (listelm);                              \
-       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
-       if ((listelm)->field.cqe_prev == (void *)(head))                \
-               (head)->cqh_first = (elm);                              \
-       else                                                            \
-               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
-       (listelm)->field.cqe_prev = (elm);                              \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {                     \
-       (elm)->field.cqe_next = (head)->cqh_first;                      \
-       (elm)->field.cqe_prev = (void *)(head);                         \
-       if ((head)->cqh_last == (void *)(head))                         \
-               (head)->cqh_last = (elm);                               \
-       else                                                            \
-               (head)->cqh_first->field.cqe_prev = (elm);              \
-       (head)->cqh_first = (elm);                                      \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {                     \
-       (elm)->field.cqe_next = (void *)(head);                         \
-       (elm)->field.cqe_prev = (head)->cqh_last;                       \
-       if ((head)->cqh_first == (void *)(head))                        \
-               (head)->cqh_first = (elm);                              \
-       else                                                            \
-               (head)->cqh_last->field.cqe_next = (elm);               \
-       (head)->cqh_last = (elm);                                       \
-} while (0)
-
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-
-#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
-
-#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
-
-#define        CIRCLEQ_REMOVE(head, elm, field) do {                           \
-       if ((elm)->field.cqe_next == (void *)(head))                    \
-               (head)->cqh_last = (elm)->field.cqe_prev;               \
-       else                                                            \
-               (elm)->field.cqe_next->field.cqe_prev =                 \
-                   (elm)->field.cqe_prev;                              \
-       if ((elm)->field.cqe_prev == (void *)(head))                    \
-               (head)->cqh_first = (elm)->field.cqe_next;              \
-       else                                                            \
-               (elm)->field.cqe_prev->field.cqe_next =                 \
-                   (elm)->field.cqe_next;                              \
-} while (0)
-
-#ifdef KERNEL
-
-/*
- * XXX insque() and remque() are an old way of handling certain queues.
- * They bogusly assumes that all queue heads look alike.
- */
-
-struct quehead {
-       struct quehead *qh_link;
-       struct quehead *qh_rlink;
-};
-
-#ifdef __GNUC__
-
-static __inline void
-insque(void *a, void *b)
-{
-       struct quehead *element = a, *head = b;
-
-       element->qh_link = head->qh_link;
-       element->qh_rlink = head;
-       head->qh_link = element;
-       element->qh_link->qh_rlink = element;
-}
-
-static __inline void
-remque(void *a)
-{
-       struct quehead *element = a;
-
-       element->qh_link->qh_rlink = element->qh_rlink;
-       element->qh_rlink->qh_link = element->qh_link;
-       element->qh_rlink = 0;
-}
-
-#else /* !__GNUC__ */
-
-void   insque __P((void *a, void *b));
-void   remque __P((void *a));
-
-#endif /* __GNUC__ */
-
-#endif /* KERNEL */
-
-#endif /* !_SYS_QUEUE_H_ */
index 27f839365499a8f01d82eedd9227db3ac61cde0f..669e1b88daf6ce7e01045e6443c42c8668b8a9ea 100644 (file)
@@ -73,7 +73,9 @@ struct instruction {
        union   ins_formats format;
        unsigned int    srcline;
        struct symbol *patch_label;
-       STAILQ_ENTRY(instruction) links;
+  struct {
+    struct instruction *stqe_next;
+  } links;
 };
 
 #define        AIC_OP_OR       0x0
index 8d7ba08311cb781b3c7645f7fb5b4a5cb432082a..49ee2e9fdfb87b500ca50dc2b8db2735ee573566 100644 (file)
@@ -1034,12 +1034,17 @@ __initfunc (static inline int port_detect \
    if (HD(j)->subversion == ESA)
       sh[j]->unchecked_isa_dma = FALSE;
    else {
+      unsigned long flags;
       sh[j]->wish_block = TRUE;
       sh[j]->unchecked_isa_dma = TRUE;
+      
+      flags=claim_dma_lock();
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
+      release_dma_lock(flags);
+      
       }
 
    strcpy(BN(j), name);
index bbabf471bee41b81c2eac44a1dd6fc1c26fb833c..3c26b45571cb6bdd3a32dca0c4e46083acea47ef 100644 (file)
  2.0.12      5.44         8 Aug 1996  Use ID 7 for all PCI cards
  2.1.1       5.45         2 Oct 1996  Update ROM accesses for 2.1.x
  2.1.97      5.46       23 Apr 1998  Rewritten PCI detection routines [mj]
+ 2.1.11x     5.47        9 Aug 1998  Touched for 8 SCSI disk majors support
 
  
 
@@ -1891,7 +1892,11 @@ int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
       0x0a bytes long.  Heads are one less than we need to report.
     */
 
-   drive = MINOR(dev) / 16;
+   if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
+      printk("fdomain_16x0_biosparam: too many disks");
+      return 0;
+   }
+   drive = MINOR(dev) >> 4;
 
    if (bios_major == 2) {
       switch (Quantum) {
index 1005bdcc88a515bb09949d7f341971367803c792..7bb8f961a201613787517b7c5d6b11123ad4c55f 100644 (file)
@@ -172,14 +172,29 @@ int imm_detect(Scsi_Host_Template * host)
 
         imm_hosts[i].dev =
             parport_register_device(pb, "imm", NULL, imm_wakeup,
-                         NULL, PARPORT_DEV_TRAN, (void *) &imm_hosts[i]);
+                         NULL, 0, (void *) &imm_hosts[i]);
+
+       if (!imm_hosts[i].dev)
+               continue;
 
         /* Claim the bus so it remembers what we do to the control
          * registers. [ CTR and ECP ]
          */
-        if (imm_pb_claim(i))
-            while (imm_hosts[i].p_busy)
-                schedule();     /* We are safe to schedule here */
+       if (imm_pb_claim(i))
+       {
+           unsigned long now = jiffies;
+           while (imm_hosts[i].p_busy)
+           {
+               schedule();     /* We are safe to schedule here */
+               if (jiffies > now + 3*HZ)
+               {
+                   printk(KERN_ERR "imm%d: failed to claim parport because a "
+                          "pardevice is owning the port for too longtime!\n",
+                          i);
+                   return 0;
+               }
+           }
+       }
 
         ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
         w_ctr(ppb, 0x0c);
index 8a80985f7f055f41a83a2ac0ff4c3d3859cfa7e6..75ab70e594fa2007b3dc2bd8a949cf86fe22dcd9 100644 (file)
@@ -133,14 +133,29 @@ int ppa_detect(Scsi_Host_Template * host)
 
        ppa_hosts[i].dev =
            parport_register_device(pb, "ppa", NULL, ppa_wakeup,
-                        NULL, PARPORT_DEV_TRAN, (void *) &ppa_hosts[i]);
+                        NULL, 0, (void *) &ppa_hosts[i]);
+
+       if (!ppa_hosts[i].dev)
+               continue;
 
        /* Claim the bus so it remembers what we do to the control
         * registers. [ CTR and ECP ]
         */
        if (ppa_pb_claim(i))
+       {
+           unsigned long now = jiffies;
            while (ppa_hosts[i].p_busy)
+           {
                schedule();     /* We are safe to schedule here */
+               if (jiffies > now + 3*HZ)
+               {
+                   printk(KERN_ERR "ppa%d: failed to claim parport because a "
+                          "pardevice is owning the port for too longtime!\n",
+                          i);
+                   return 0;
+               }
+           }
+       }
 
        ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
        w_ctr(ppb, 0x0c);
index 1ade47f91863e390b213478e395c2494817806a7..805e1f8111f873bfcbcacfab1fe2eae5205098b2 100644 (file)
@@ -1734,8 +1734,7 @@ scsi_finish_command(Scsi_Cmnd * SCpnt)
         host_active = NULL;
         
         /* For block devices "wake_up" is done in end_scsi_request */
-        if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
-            MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
+        if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
             struct Scsi_Host * next;
             
             for (next = host->block; next != host; next = next->block)
index 045ec15da7df5104c76bebaba751a06c438b4326..2539774c667df1c8aaf74bec235dfeb1558bd975 100644 (file)
@@ -690,16 +690,22 @@ static Scsi_Cmnd * end_scsi_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors
  * that an interrupt may start another request, so we run this with interrupts
  * turned off 
  */
-#define INIT_SCSI_REQUEST       \
-    if (!CURRENT) {             \
-       CLEAR_INTR;             \
-       return;                 \
-    }                           \
-    if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)           \
-       panic(DEVICE_NAME ": request list destroyed");\
-    if (CURRENT->bh) {                                \
-       if (!buffer_locked(CURRENT->bh))              \
-           panic(DEVICE_NAME ": block not locked");  \
+#if MAJOR_NR == SCSI_DISK0_MAJOR
+#define CHECK_INITREQ_SD_MAJOR(major) SCSI_DISK_MAJOR(major)
+#else
+#define CHECK_INITREQ_SD_MAJOR(major) ((major) == MAJOR_NR)
+#endif
+
+#define INIT_SCSI_REQUEST                              \
+    if (!CURRENT) {                                    \
+       CLEAR_INTR;                                     \
+       return;                                         \
+    }                                                  \
+    if (!CHECK_INITREQ_SD_MAJOR(MAJOR(CURRENT->rq_dev)))\
+       panic(DEVICE_NAME ": request list destroyed");  \
+    if (CURRENT->bh) {                                 \
+       if (!buffer_locked(CURRENT->bh))                \
+           panic(DEVICE_NAME ": block not locked");    \
     }
 #endif
 
index 34effd8bb4321f1754389737f692225ea620afb7..281c9ce289518f0e8ca0052a2f0558d883c33ee0 100644 (file)
@@ -42,8 +42,8 @@ struct proc_dir_entry proc_scsi_scsi_debug = {
 
 /* A few options that we want selected */
 
-#define NR_HOSTS_PRESENT 1
-#define NR_FAKE_DISKS   3
+#define NR_HOSTS_PRESENT 20
+#define NR_FAKE_DISKS   6
 #define N_HEAD          32
 #define N_SECTOR        64
 #define DISK_READONLY(TGT)      (1)
@@ -55,6 +55,8 @@ struct proc_dir_entry proc_scsi_scsi_debug = {
 
 /* Skip some consistency checking.  Good for benchmarking */
 #define SPEEDY
+/* Read return zeros. Undefine for benchmarking */
+#define CLEAR
 
 /* Number of real scsi disks that will be detected ahead of time */
 static int NR_REAL=-1;
@@ -299,11 +301,8 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 #if defined(SCSI_SETUP_LATENCY) || defined(SCSI_DATARATE)
     {
        int delay = SCSI_SETUP_LATENCY;
-       double usec;
        
-       usec = 0.0;
-       usec = (SCpnt->request.nr_sectors << 9) * 1.0e6 / SCSI_DATARATE;
-       delay += usec;
+       delay += SCpnt->request.nr_sectors * SCSI_DATARATE;
        if(delay) usleep(delay);
     };
 #endif
@@ -323,29 +322,31 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
        do{
            VERIFY1_DEBUG(READ);
            /* For the speedy test, we do not even want to fill the buffer with anything */
-#ifndef SPEEDY
+#ifdef CLEAR
            memset(buff, 0, bufflen);
 #endif
            /* If this is block 0, then we want to read the partition table for this
             * device.  Let's make one up */
-           if(block == 0 && target == 0) {
+           if(block == 0) {
+               int i;
                 memset(buff, 0, bufflen);
                *((unsigned short *) (buff+510)) = 0xAA55;
                p = (struct partition* ) (buff + 0x1be);
-               npart = 0;
-               while(starts[npart+1]){
-                   p->start_sect = starts[npart];
-                   p->nr_sects = starts[npart+1] - starts [npart];
+               i = 0;
+               while(starts[i+1]){
+                   p->start_sect = starts[i];
+                   p->nr_sects = starts[i+1] - starts [i];
                    p->sys_ind = 0x81;  /* Linux partition */
-                    p->head       = (npart == 0 ? 1 : 0);
+                    p->head       = (i == 0 ? 1 : 0);
                     p->sector     = 1;
-                    p->cyl        = starts[npart] / N_HEAD / N_SECTOR;
+                    p->cyl        = starts[i] / N_HEAD / N_SECTOR;
                     p->end_head   = N_HEAD - 1;
                     p->end_sector = N_SECTOR;
-                    p->end_cyl    = starts[npart + 1] / N_HEAD / N_SECTOR;
+                    p->end_cyl    = starts[i + 1] / N_HEAD / N_SECTOR;
                    p++;
-                   npart++;
+                   i++;
                };
+               if (!npart) npart = i;
                scsi_debug_errsts = 0;
                break;
            };
@@ -376,7 +377,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
            } /* End phony disk change code */
 #endif
            
-#ifndef SPEEDY
+#ifdef CLEAR
            memcpy(buff, &target, sizeof(target));
            memcpy(buff+sizeof(target), cmd, 24);
            memcpy(buff+60, &block, sizeof(block));
@@ -384,7 +385,7 @@ int scsi_debug_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
 #endif
            nbytes -= bufflen;
            if(SCpnt->use_sg){
-#ifndef SPEEDY
+#ifdef CLEAR
                memcpy(buff+128, bh, sizeof(struct buffer_head));
 #endif
                block += bufflen >> 9;
index 54b53d3922f64dfb334039b398967fa7b51bacec..5932ba870c6217bf17dd45abce4b9dc3cb4970b3 100644 (file)
@@ -658,8 +658,7 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
            host_active = NULL;
 
            /* For block devices "wake_up" is done in end_scsi_request */
-           if (MAJOR(SCpnt->request.rq_dev) != SCSI_DISK_MAJOR &&
-               MAJOR(SCpnt->request.rq_dev) != SCSI_CDROM_MAJOR) {
+           if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
                struct Scsi_Host * next;
 
                for (next = host->block; next != host; next = next->block)
index 328829767bb6d44819e1d877322d9ca4ba354e96..ededdce3b70f34f9b86afa3c8e2ef813a37da245 100644 (file)
  *
  *       Modified by Eric Youngdale eric@aib.com to support loadable
  *       low-level scsi drivers.
+ *
+ *       Modified by Jirka Hanika geo@ff.cuni.cz to support more
+ *       scsi disks using eight major numbers.
  */
-
 #include <linux/module.h>
 #ifdef MODULE
 /*
@@ -41,7 +44,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#define MAJOR_NR SCSI_DISK_MAJOR
+#define MAJOR_NR SCSI_DISK0_MAJOR
 #include <linux/blk.h>
 #include "scsi.h"
 #include "hosts.h"
 /*
  *  static const char RCSid[] = "$Header:";
  */
+#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+#define SCSI_DISKS_PER_MAJOR   16
+#define SD_MAJOR_NUMBER(i)     SD_MAJOR((i) >> 8)
+#define SD_MINOR_NUMBER(i)     ((i) & 255)
+#define MKDEV_SD_PARTITION(i)  MKDEV(SD_MAJOR_NUMBER(i), (i) & 255)
+#define MKDEV_SD(index)                MKDEV_SD_PARTITION((index) << 4)
+#define N_USED_SD_MAJORS       ((sd_template.dev_max + SCSI_DISKS_PER_MAJOR - 1) / SCSI_DISKS_PER_MAJOR)
 
 #define MAX_RETRIES 5
 
@@ -91,12 +103,9 @@ static void sd_detach(Scsi_Device *);
 
 static void sd_devname(unsigned int disknum, char * buffer)
 {
-    if( disknum <= 26 )
-    {
+    if( disknum < 26 )
         sprintf(buffer, "sd%c", 'a' + disknum);
-    }
-    else
-    {
+    else {
         unsigned int min1;
         unsigned int min2;
         /*
@@ -105,13 +114,13 @@ static void sd_devname(unsigned int disknum, char * buffer)
          */
         min1 = disknum / 26;
         min2 = disknum % 26;
-        sprintf(buffer, "sd%c%c", 'a' + min1, 'a' + min2);
+        sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
     }
 }
 
 struct Scsi_Device_Template sd_template =
 { NULL, "disk", "sd", NULL, TYPE_DISK,
-      SCSI_DISK_MAJOR, 0, 0, 0, 1,
+      SCSI_DISK0_MAJOR, 0, 0, 0, 1,
       sd_detect, sd_init,
       sd_finish, sd_attach, sd_detach
 };
@@ -175,7 +184,7 @@ static int sd_open(struct inode * inode, struct file * filp)
      * See if we are requesting a non-existent partition.  Do this
      * after checking for disk change.
      */
-    if(sd_sizes[MINOR(inode->i_rdev)] == 0)
+    if(sd_sizes[SD_PARTITION(inode->i_rdev)] == 0)
        return -ENXIO;
 
     if(rscsi_disks[target].device->removable)
@@ -230,8 +239,13 @@ static struct file_operations sd_fops = {
     fop_revalidate_scsidisk      /* revalidate */
 };
 
+/*
+ *     If we need more than one SCSI disk major (i.e. more than
+ *     16 SCSI disks), we'll have to kmalloc() more gendisks later.
+ */
+
 static struct gendisk sd_gendisk = {
-    MAJOR_NR,                    /* Major number */
+    SCSI_DISK0_MAJOR,            /* Major number */
     "sd",                        /* Major name */
     4,                           /* Bits to shift to get real from partition */
     1 << 4,                      /* Number of partitions per real */
@@ -242,7 +256,12 @@ static struct gendisk sd_gendisk = {
     0,                           /* number */
     NULL,                        /* internal */
     NULL                         /* next */
-};
+}; 
+
+static struct gendisk *sd_gendisks = &sd_gendisk;
+
+#define SD_GENDISK(i)    sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
+#define LAST_SD_GENDISK  sd_gendisks[N_USED_SD_MAJORS - 1]
 
 static void sd_geninit (struct gendisk *ignored)
 {
@@ -251,10 +270,6 @@ static void sd_geninit (struct gendisk *ignored)
     for (i = 0; i < sd_template.dev_max; ++i)
        if(rscsi_disks[i].device)
            sd[i << 4].nr_sects = rscsi_disks[i].capacity;
-#if 0
-    /* No longer needed - we keep track of this as we attach/detach */
-    sd_gendisk.nr_real = sd_template.dev_max;
-#endif
 }
 
 /*
@@ -271,7 +286,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
     int good_sectors = (result == 0 ? this_count : 0);
     int block_sectors = 1;
 
-    sd_devname(MINOR(SCpnt->request.rq_dev) >> 4, nbuff);
+    sd_devname(DEVICE_NR(SCpnt->request.rq_dev), nbuff);
 
     SCSI_LOG_HLCOMPLETE(1,printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff,
           SCpnt->host->host_no, 
@@ -309,7 +324,7 @@ static void rw_intr (Scsi_Cmnd *SCpnt)
          }
        else if (sector_size == 256)
          error_sector >>= 1;
-       error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
+       error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect;
        error_sector &= ~ (block_sectors - 1);
        good_sectors = error_sector - SCpnt->request.sector;
        if (good_sectors < 0 || good_sectors >= this_count)
@@ -524,7 +539,7 @@ static void do_sd_request (void)
        }
 
        INIT_SCSI_REQUEST;
-        SDev = rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device;
+        SDev = rscsi_disks[CURRENT_DEV].device;
 
         /*
          * If the host for this device is in error recovery mode, don't
@@ -578,7 +593,7 @@ static void do_sd_request (void)
 
        if (flag++ == 0)
            SCpnt = scsi_allocate_device(&CURRENT,
-                          rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0);
+                          rscsi_disks[CURRENT_DEV].device, 0);
        else SCpnt = NULL;
 
        /*
@@ -643,7 +658,7 @@ static void requeue_sd_request (Scsi_Cmnd * SCpnt)
        return;
     }
 
-    devm =  MINOR(SCpnt->request.rq_dev);
+    devm =  SD_PARTITION(SCpnt->request.rq_dev);
     dev = DEVICE_NR(SCpnt->request.rq_dev);
 
     block = SCpnt->request.sector;
@@ -1329,7 +1344,7 @@ static int sd_init_onedisk(int i)
                printk ("scsi : deleting disk entry.\n");
                rscsi_disks[i].device = NULL;
                sd_template.nr_dev--;
-               sd_gendisk.nr_real--;
+               SD_GENDISK(i).nr_real--;
 
                 /* Wake up a process waiting for device */
                 wake_up(&SCpnt->device->device_wait);
@@ -1463,67 +1478,99 @@ static int sd_init()
 
     if (sd_template.dev_noticed == 0) return 0;
 
+    if (!rscsi_disks)
+        sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
+
+    /* 128 disks is our current limit (8 majors, 16 disks per major) */
+    if(sd_template.dev_max > 128)
+       sd_template.dev_max = 128;
+
     if(!sd_registered) {
-         if (register_blkdev(MAJOR_NR,"sd",&sd_fops)) {
-             printk("Unable to get major %d for SCSI disk\n",MAJOR_NR);
-             return 1;
-         }
-         sd_registered++;
-      }
+       for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+           if (register_blkdev(SD_MAJOR(i),"sd",&sd_fops)) {
+               printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i));
+               return 1;
+           }
+       }
+       sd_registered++;
+    }
 
     /* We do not support attaching loadable devices yet. */
     if(rscsi_disks) return 0;
 
-    sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
-
     rscsi_disks = (Scsi_Disk *)
        scsi_init_malloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
     memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));
-
-    sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
-                                       sizeof(int), GFP_ATOMIC);
+    
+  /* for every (necessary) major: */
+    sd_sizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
     memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));
 
-    sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
-                                            sizeof(int), GFP_ATOMIC);
-
-    sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) *
-                                           sizeof(int), GFP_ATOMIC);
+    sd_blocksizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+    sd_hardsizes = (int *) scsi_init_malloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
 
-     for(i=0;i<(sd_template.dev_max << 4);i++)
-       {
-         sd_blocksizes[i] = 1024;
-         sd_hardsizes[i] = 512;
-       }
+    for(i=0; i < sd_template.dev_max << 4; i++) {
+       sd_blocksizes[i] = 1024;
+       sd_hardsizes[i] = 512;
+    }
  
-    blksize_size[MAJOR_NR] = sd_blocksizes;
-    hardsect_size[MAJOR_NR] = sd_hardsizes;
+    for (i=0; i < N_USED_SD_MAJORS; i++) {
+       blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
+       hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
+    }
     sd = (struct hd_struct *) scsi_init_malloc((sd_template.dev_max << 4) *
                                               sizeof(struct hd_struct),
                                               GFP_ATOMIC);
 
-
-    sd_gendisk.max_nr = sd_template.dev_max;
-    sd_gendisk.part = sd;
-    sd_gendisk.sizes = sd_sizes;
-    sd_gendisk.real_devices = (void *) rscsi_disks;
+    if (N_USED_SD_MAJORS > 1)
+       sd_gendisks = (struct gendisk *)
+           kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+    for (i=0; i < N_USED_SD_MAJORS; i++) {
+       sd_gendisks[i].major = SD_MAJOR(i);
+       sd_gendisks[i].major_name = "sd";
+       sd_gendisks[i].minor_shift = 4;
+       sd_gendisks[i].max_p = 1 << 4;
+       sd_gendisks[i].max_nr = SCSI_DISKS_PER_MAJOR;
+       sd_gendisks[i].init = sd_geninit;
+       sd_gendisks[i].part = sd + (i * SCSI_DISKS_PER_MAJOR << 4);
+       sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4);
+       sd_gendisks[i].nr_real = 0;
+       sd_gendisks[i].next = sd_gendisks + i + 1;
+       sd_gendisks[i].real_devices =
+                (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
+    }
+    LAST_SD_GENDISK.max_nr =
+       sd_template.dev_max % SCSI_DISKS_PER_MAJOR;
+    LAST_SD_GENDISK.next = NULL;
     return 0;
 }
 
+/*
+ * sd_get_queue() returns the queue which corresponds to a given device.
+ */
+static struct request **sd_get_queue (kdev_t dev)
+{
+       return &blk_dev[MAJOR_NR].current_request;
+}
+
 static void sd_finish()
 {
     struct gendisk *gendisk;
     int i;
 
-    blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+    for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+        /* FIXME: After 2.2 we should implement multiple sd queues */
+        blk_dev[SD_MAJOR(i)].request_fn = DEVICE_REQUEST;
+        if (i) blk_dev[SD_MAJOR(i)].queue = sd_get_queue;
+    }
 
     for (gendisk = gendisk_head; gendisk != NULL; gendisk = gendisk->next)
-      if (gendisk == &sd_gendisk)
+      if (gendisk == sd_gendisks)
        break;
     if (gendisk == NULL)
       {
-       sd_gendisk.next = gendisk_head;
-       gendisk_head = &sd_gendisk;
+       LAST_SD_GENDISK.next = gendisk_head;
+       gendisk_head = sd_gendisks;
       }
 
     for (i = 0; i < sd_template.dev_max; ++i)
@@ -1534,7 +1581,7 @@ static void sd_finish()
                && !rscsi_disks[i].has_part_table) {
                sd_sizes[i << 4] = rscsi_disks[i].capacity;
                /* revalidate does sd_init_onedisk via MAYBE_REINIT*/
-               revalidate_scsidisk(MKDEV(MAJOR_NR, i << 4), 0);
+               revalidate_scsidisk(MKDEV_SD(i), 0);
            }
            else
                i=sd_init_onedisk(i);
@@ -1542,13 +1589,17 @@ static void sd_finish()
        }
 
     /* If our host adapter is capable of scatter-gather, then we increase
-     * the read-ahead to 16 blocks (32 sectors).  If not, we use
-     * a two block (4 sector) read ahead.
+     * the read-ahead to 60 blocks (120 sectors).  If not, we use
+     * a two block (4 sector) read ahead. We can only respect this with the
+     * granularity of every 16 disks (one device major).
      */
-    if(rscsi_disks[0].device && rscsi_disks[0].device->host->sg_tablesize)
-       read_ahead[MAJOR_NR] = 120;  /* 120 sector read-ahead */
-    else
-       read_ahead[MAJOR_NR] = 4;  /* 4 sector read-ahead */
+    for (i=0; i < N_USED_SD_MAJORS; i++) {
+        read_ahead[SD_MAJOR(i)] =
+            (rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device
+          && rscsi_disks[i * SCSI_DISKS_PER_MAJOR].device->host->sg_tablesize)
+            ? 120  /* 120 sector read-ahead */
+            : 4;   /* 4 sector read-ahead */
+    }
 
     return;
 }
@@ -1586,7 +1637,7 @@ static int sd_attach(Scsi_Device * SDp){
     rscsi_disks[i].device = SDp;
     rscsi_disks[i].has_part_table = 0;
     sd_template.nr_dev++;
-    sd_gendisk.nr_real++;
+    SD_GENDISK(i).nr_real++;
     return 0;
 }
 
@@ -1594,7 +1645,6 @@ static int sd_attach(Scsi_Device * SDp){
 #define USAGE rscsi_disks[target].device->access_count
 #define CAPACITY rscsi_disks[target].capacity
 #define MAYBE_REINIT  sd_init_onedisk(target)
-#define GENDISK_STRUCT sd_gendisk
 
 /* This routine is called to flush all partitions and partition tables
  * for a changed scsi disk, and then re-read the new partition table.
@@ -1603,15 +1653,13 @@ static int sd_attach(Scsi_Device * SDp){
  * usage == 1 (we need an open channel to use an ioctl :-), so this
  * is our limit.
  */
-int revalidate_scsidisk(kdev_t dev, int maxusage){
+int revalidate_scsidisk(kdev_t dev, int maxusage) {
     int target;
-    struct gendisk * gdev;
     int max_p;
     int start;
     int i;
 
     target =  DEVICE_NR(dev);
-    gdev = &GENDISK_STRUCT;
 
     if (DEVICE_BUSY || USAGE > maxusage) {
        printk("Device busy for revalidation (usage=%d)\n", USAGE);
@@ -1619,37 +1667,38 @@ int revalidate_scsidisk(kdev_t dev, int maxusage){
     }
     DEVICE_BUSY = 1;
 
-    max_p = gdev->max_p;
-    start = target << gdev->minor_shift;
+    max_p = sd_gendisks->max_p;
+    start = target << sd_gendisks->minor_shift;
 
     for (i=max_p - 1; i >=0 ; i--) {
-       int minor = start+i;
-       kdev_t devi = MKDEV(MAJOR_NR, minor);
+       int index = start+i;
+       kdev_t devi = MKDEV_SD_PARTITION(index);
         struct super_block *sb = get_super(devi);
        sync_dev(devi);
        if (sb) invalidate_inodes(sb);
        invalidate_buffers(devi);
-       gdev->part[minor].start_sect = 0;
-       gdev->part[minor].nr_sects = 0;
+       sd_gendisks->part[index].start_sect = 0;
+       sd_gendisks->part[index].nr_sects = 0;
         /*
          * Reset the blocksize for everything so that we can read
          * the partition table.  Technically we will determine the
          * correct block size when we revalidate, but we do this just
          * to make sure that everything remains consistent.
          */
-        blksize_size[MAJOR_NR][minor] = 1024;
+        sd_blocksizes[index] = 1024;
         if( rscsi_disks[target].sector_size == 2048 )
-          blksize_size[MAJOR_NR][minor] = 2048;
+          sd_blocksizes[index] = 2048;
         else
-          blksize_size[MAJOR_NR][minor] = 1024;
+          sd_blocksizes[index] = 1024;
     }
 
 #ifdef MAYBE_REINIT
     MAYBE_REINIT;
 #endif
 
-    gdev->part[start].nr_sects = CAPACITY;
-    resetup_one_dev(gdev, target);
+    sd_gendisks->part[start].nr_sects = CAPACITY;
+    resetup_one_dev(&SD_GENDISK(target),
+                   target % SCSI_DISKS_PER_MAJOR);
 
     DEVICE_BUSY = 0;
     return 0;
@@ -1676,15 +1725,15 @@ static void sd_detach(Scsi_Device * SDp)
            start = i << sd_gendisk.minor_shift;
 
            for (i=max_p - 1; i >=0 ; i--) {
-               int minor = start+i;
-               kdev_t devi = MKDEV(MAJOR_NR, minor);
+               int index = start+i;
+               kdev_t devi = MKDEV_SD_PARTITION(index);
                 struct super_block *sb = get_super(devi);
                sync_dev(devi);
                if (sb) invalidate_inodes(sb);
                invalidate_buffers(devi);
-               sd_gendisk.part[minor].start_sect = 0;
-               sd_gendisk.part[minor].nr_sects = 0;
-               sd_sizes[minor] = 0;
+               sd_gendisks->part[index].start_sect = 0;
+               sd_gendisks->part[index].nr_sects = 0;
+               sd_sizes[index] = 0;
            }
 
            dpnt->has_part_table = 0;
@@ -1693,7 +1742,7 @@ static void sd_detach(Scsi_Device * SDp)
            SDp->attached--;
            sd_template.dev_noticed--;
            sd_template.nr_dev--;
-           sd_gendisk.nr_real--;
+           SD_GENDISK(start).nr_real--;
            return;
        }
     return;
@@ -1710,48 +1759,48 @@ void cleanup_module( void)
 {
     struct gendisk * prev_sdgd;
     struct gendisk * sdgd;
+    int i;
+    int removed = 0;
 
     scsi_unregister_module(MODULE_SCSI_DEV, &sd_template);
-    unregister_blkdev(SCSI_DISK_MAJOR, "sd");
+
+    for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) 
+    unregister_blkdev(SD_MAJOR(i),"sd");
+    
     sd_registered--;
     if( rscsi_disks != NULL )
     {
-       scsi_init_free((char *) rscsi_disks,
-                      (sd_template.dev_noticed + SD_EXTRA_DEVS)
-                      * sizeof(Scsi_Disk));
-
+       scsi_init_free((char *) rscsi_disks, 
+                       sd_template.dev_max * sizeof(Scsi_Disk));
        scsi_init_free((char *) sd_sizes, sd_template.dev_max * sizeof(int));
        scsi_init_free((char *) sd_blocksizes, sd_template.dev_max * sizeof(int));
        scsi_init_free((char *) sd_hardsizes, sd_template.dev_max * sizeof(int));
        scsi_init_free((char *) sd,
                       (sd_template.dev_max << 4) * sizeof(struct hd_struct));
        /*
-        * Now remove sd_gendisk from the linked list
+        * Now remove sd_gendisks from the linked list
         */
-       sdgd = gendisk_head;
-       prev_sdgd = NULL;
-       while(sdgd != &sd_gendisk)
-       {
-           prev_sdgd = sdgd;
-           sdgd = sdgd->next;
-       }
 
-       if(sdgd != &sd_gendisk)
-           printk("sd_gendisk not in disk chain.\n");
-       else {
-           if(prev_sdgd != NULL)
-               prev_sdgd->next = sdgd->next;
-           else
-               gendisk_head = sdgd->next;
+       for (sdgd = gendisk_head; sdgd; sdgd = sdgd->next)
+       {
+           if (sdgd->next >= sd_gendisks && sdgd->next <= LAST_SD_GENDISK)
+                   removed++, sdgd->next = sdgd->next->next;
+           else sdgd = sdgd->next;
        }
+       if (removed != N_USED_SCSI_DISKS)
+           printk("%s %d sd_gendisks in disk chain",
+               removed > N_USED_SCSI_DISKS ? "total" : "just", removed);
+       
     }
 
-    blksize_size[MAJOR_NR] = NULL;
-    blk_dev[MAJOR_NR].request_fn = NULL;
-    blk_size[MAJOR_NR] = NULL;
-    hardsect_size[MAJOR_NR] = NULL;
-    read_ahead[MAJOR_NR] = 0;
+    for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+        blk_dev[SD_MAJOR(i)].request_fn = NULL;
+        blk_size[SD_MAJOR(i)] = NULL;
+        hardsect_size[SD_MAJOR(i)] = NULL;
+        read_ahead[SD_MAJOR(i)] = 0;
+    }
     sd_template.dev_max = 0;
+    if (sd_gendisks != &sd_gendisk) kfree(sd_gendisks);
 }
 #endif /* MODULE */
 
index 8e2031e679454beae11c61ebb41016a620296a78..4d298959073528e7fd9a32af93ac2b923e419dee 100644 (file)
@@ -42,6 +42,11 @@ extern Scsi_Disk * rscsi_disks;
 
 extern int revalidate_scsidisk(kdev_t dev, int maxusage);
 
+#define N_SD_MAJORS    8
+
+#define SD_MAJOR_MASK  (N_SD_MAJORS - 1)
+#define SD_PARTITION(i)                (((MAJOR(i) & SD_MAJOR_MASK) << 8) | (MINOR(i) & 255))
+
 #endif
 
 /*
index a29d958d1d17035bc410ea7c2a4b688a6e737779..26ea27a33d36928939523e3f10990044eb572329 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <asm/uaccess.h>
 
+#define MAJOR_NR       SCSI_DISK0_MAJOR
 #include <linux/blk.h>
 #include "scsi.h"
 #include <scsi/scsi_ioctl.h>
@@ -29,7 +30,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
     int diskinfo[4];
     struct hd_geometry *loc = (struct hd_geometry *) arg;
     
-    SDev = rscsi_disks[MINOR(dev) >> 4].device;
+    SDev = rscsi_disks[DEVICE_NR(dev)].device;
     /*
      * If we are in the middle of error recovery, don't let anyone
      * else try and use this device.  Also, if error recovery fails, it
@@ -47,34 +48,34 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        error = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
        if (error)
            return error;
-       host = rscsi_disks[MINOR(dev) >> 4].device->host;
+       host = rscsi_disks[DEVICE_NR(dev)].device->host;
 
 /* default to most commonly used values */
 
         diskinfo[0] = 0x40;
         diskinfo[1] = 0x20;
-        diskinfo[2] = rscsi_disks[MINOR(dev) >> 4].capacity >> 11;
+        diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
 
 /* override with calculated, extended default, or driver values */
 
        if(host->hostt->bios_param != NULL)
-           host->hostt->bios_param(&rscsi_disks[MINOR(dev) >> 4],
+           host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
                                    dev,
                                    &diskinfo[0]);
-        else scsicam_bios_param(&rscsi_disks[MINOR(dev) >> 4],
+        else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
                                dev, &diskinfo[0]);
 
        put_user(diskinfo[0], &loc->heads);
        put_user(diskinfo[1], &loc->sectors);
        put_user(diskinfo[2], &loc->cylinders);
-       put_user(sd[MINOR(inode->i_rdev)].start_sect, &loc->start);
+       put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start);
        return 0;
     case BLKGETSIZE:   /* Return device size */
        if (!arg)  return -EINVAL;
        error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
        if (error)
            return error;
-       put_user(sd[MINOR(inode->i_rdev)].nr_sects,
+       put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects,
                 (long *) arg);
        return 0;
 
@@ -110,7 +111,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
     RO_IOCTLS(dev, arg);
 
     default:
-       return scsi_ioctl(rscsi_disks[MINOR(dev) >> 4].device , cmd, (void *) arg);
+       return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
     }
 }
 
index cad88bc29a731623e6f325ca1f77c4b4fc3323e6..3493fb40c215edc305f91c459d843b9428a87c93 100644 (file)
@@ -844,12 +844,17 @@ __initfunc (static inline int port_detect \
       bus_type = "VESA";
       }
    else {
+      unsigned long flags;
       sh[j]->wish_block = TRUE;
       sh[j]->unchecked_isa_dma = TRUE;
+      
+      flags=claim_dma_lock();
       disable_dma(dma_channel);
       clear_dma_ff(dma_channel);
       set_dma_mode(dma_channel, DMA_MODE_CASCADE);
       enable_dma(dma_channel);
+      release_dma_lock(flags);
+      
       sh[j]->dma_channel = dma_channel;
       sprintf(BN(j), "U14F%d", j);
       bus_type = "ISA";
index 51a772cfd7a21eefd08296d4abea0a599163c246..3ce29e72bb7b7d995915e035c9d7fc68637d8f43 100644 (file)
@@ -772,10 +772,15 @@ static inline void wd7000_enable_intr (Adapter *host)
 
 static inline void wd7000_enable_dma (Adapter *host)
 {
+    unsigned long flags;
     host->control |= DMA_EN;
     outb (host->control, host->iobase + ASC_CONTROL);
+    
+    flags = claim_dma_lock();
     set_dma_mode (host->dma, DMA_MODE_CASCADE);
     enable_dma (host->dma);
+    release_dma_lock(flags);
+    
 }
 
 
index b43addc1b923f48ad51ce456542104624ee1197a..7e1f8b33d439e44cec91a1c19cac641e5a6d9f6f 100644 (file)
@@ -20,11 +20,11 @@ if [ "$CONFIG_SOUND_MSNDCLAS" = "y" -o "$CONFIG_SOUND_MSNDCLAS" = "m" ]; then
    if [ "$CONFIG_SOUND_MSNDCLAS" = "y" ]; then
      comment 'Compiled-in MSND Classic support requires firmware during compilation.'
      define_bool CONFIG_MSNDCLAS_HAVE_BOOT y
-     string '  Full pathname of MSNDINIT.BIN firmware file' CONFIG_MSNDCLAS_INIT_FILE "/etc/sound/msndinit.bin"
-     string '  Full pathname of MSNDPERM.BIN firmware file' CONFIG_MSNDCLAS_PERM_FILE "/etc/sound/msndperm.bin"
    else
      define_bool CONFIG_MSNDCLAS_HAVE_BOOT n
    fi
+   string '  Full pathname of MSNDINIT.BIN firmware file' CONFIG_MSNDCLAS_INIT_FILE "/etc/sound/msndinit.bin"
+   string '  Full pathname of MSNDPERM.BIN firmware file' CONFIG_MSNDCLAS_PERM_FILE "/etc/sound/msndperm.bin"
 fi
 if [ "$CONFIG_SOUND_MSNDCLAS" = "y" ]; then
    int 'MSND Classic IRQ 5,7,9,10,11,12' CONFIG_MSNDCLAS_IRQ 5
@@ -36,29 +36,29 @@ dep_tristate 'Support for Turtle Beach MultiSound Pinnacle, Fiji' CONFIG_SOUND_M
 if [ "$CONFIG_SOUND_MSNDPIN" = "y" -o "$CONFIG_SOUND_MSNDPIN" = "m" ]; then
    if [ "$CONFIG_SOUND_MSNDPIN" = "y" ]; then
      comment 'Compiled-in MSND Pinnacle support requires firmware during compilation.'
-     string '  Full pathname of PNDSPINI.BIN firmware file' CONFIG_MSNDPIN_INIT_FILE "/etc/sound/pndspini.bin"
-     string '  Full pathname of PNDSPERM.BIN firmware file' CONFIG_MSNDPIN_PERM_FILE "/etc/sound/pndsperm.bin"
      define_bool CONFIG_MSNDPIN_HAVE_BOOT y
    else
      define_bool CONFIG_MSNDPIN_HAVE_BOOT n
    fi
+   string '  Full pathname of PNDSPINI.BIN firmware file' CONFIG_MSNDPIN_INIT_FILE "/etc/sound/pndspini.bin"
+   string '  Full pathname of PNDSPERM.BIN firmware file' CONFIG_MSNDPIN_PERM_FILE "/etc/sound/pndsperm.bin"
 fi
 if [ "$CONFIG_SOUND_MSNDPIN" = "y" ]; then
    int 'MSND Pinnacle IRQ 5,7,9,10,11,12' CONFIG_MSNDPIN_IRQ 5
    hex 'MSND Pinnacle memory B0000,C8000,D0000,D8000,E0000,E8000' CONFIG_MSNDPIN_MEM D0000
    hex 'MSND Pinnacle I/O 210,220,230,240,250,260,290,3E0' CONFIG_MSNDPIN_IO 290
    bool 'MSND Pinnacle has S/PDIF I/O' CONFIG_MSNDPIN_DIGITAL
-   bool 'MSND Pinnacle Non-PnP Mode' CONFIG_MSNDPIN_NONPNP
+   bool 'MSND Pinnacle non-PnP Mode' CONFIG_MSNDPIN_NONPNP
    if [ "$CONFIG_MSNDPIN_NONPNP" = "y" ]; then
      comment 'MSND Pinnacle DSP section will be configured to above parameters.'
-     hex 'MSDN Pinnacle config port 250,260,270' CONFIG_MSNDPIN_CFG 250
+     hex 'MSND Pinnacle config port 250,260,270' CONFIG_MSNDPIN_CFG 250
      comment 'Pinnacle-specific Device Configuration (0 disables)'
      hex 'MSND Pinnacle MPU I/O (e.g. 330)' CONFIG_MSNDPIN_MPU_IO 0
      int 'MSND Pinnacle MPU IRQ (e.g. 9)' CONFIG_MSNDPIN_MPU_IRQ 0
      hex 'MSND Pinnacle IDE I/O 0 (e.g. 170)' CONFIG_MSNDPIN_IDE_IO0 0
      hex 'MSND Pinnacle IDE I/O 1 (e.g. 376)' CONFIG_MSNDPIN_IDE_IO1 0
      int 'MSND Pinnacle IDE IRQ (e.g. 15)' CONFIG_MSNDPIN_IDE_IRQ 0
-     hex 'MSDN Pinnacle joystick I/O (e.g. 200)' CONFIG_MSNDPIN_JOYSTICK_IO 0
+     hex 'MSND Pinnacle joystick I/O (e.g. 200)' CONFIG_MSNDPIN_JOYSTICK_IO 0
    fi
 fi
 if [ "$CONFIG_SOUND_MSNDPIN" = "y" -o "$CONFIG_SOUND_MSNDCLAS" = "y" ]; then
@@ -192,6 +192,16 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
       int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_MPU_IRQ 9
   fi
 
+  dep_tristate 'Support for Yamaha OPL3-SA[2,3,x] based (PnP) cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
+  if [ "$CONFIG_SOUND_OPL3SA2" = "y" ]; then
+      hex 'OPL3SA2 audio I/O base 530, 604, E80 or F40' CONFIG_OPL3SA2_BASE 530
+      int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 11
+      int 'OPL3SA2 audio DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA 0
+      int 'OPL3SA2 second (duplex) DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA2 1
+      hex 'OPL3SA2 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_OPL3SA2_MPU_BASE 330
+      int 'OPL3SA2 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_MPU_IRQ 9
+  fi
+
   dep_tristate 'Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_SOUND_MAUI $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_MAUI" = "y" ]; then
       hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' CONFIG_MAUI_BASE 330
index 5ca95dd5f804a5669b2df23c49458ddb875e311d..126a689c48ba8b76606152d2fc1dc64c115574fd 100644 (file)
@@ -72,6 +72,7 @@ obj-$(CONFIG_SOUND_MSNDCLAS)  += msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)    += msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_MSS)                += ad1848.o
 obj-$(CONFIG_SOUND_OPL3SA1)    += opl3sa.o ad1848.o uart401.o
+obj-$(CONFIG_SOUND_OPL3SA2)    += opl3sa2.o ad1848.o uart401.o mpu401.o
 obj-$(CONFIG_SOUND_PAS)                += pas2.o sb.o uart401.o
 obj-$(CONFIG_SOUND_PSS)                += pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_SB)         += sb.o uart401.o
@@ -219,7 +220,7 @@ maui.o: maui_boot.h
 
 ifeq ($(CONFIG_MAUI_HAVE_BOOT),y)
     maui_boot.h: $(patsubst "%", %, $(CONFIG_MAUI_BOOT_FILE)) bin2hex
-       bin2hex -i maui_os < $(CONFIG_MAUI_BOOT_FILE) > $@
+       ./bin2hex -i maui_os < $(CONFIG_MAUI_BOOT_FILE) > $@
 else
     maui_boot.h:
        (                                                       \
index 2bb76549f5f881738c47b8309d3daf4a2072bd99..cd506f29ac7f80eeba9dc14d7f24843341d5e6c8 100644 (file)
@@ -168,7 +168,7 @@ The following errors are likely with /dev/dsp and /dev/audio.
        with impossible parameters. Check that the application is
        for sound driver version 2.X or later.
 
-In general the printout of of /dev/sndstat should tell what is the problem.
+In general the printout of /dev/sndstat should tell what is the problem.
 It's possible that there are bugs in the sound driver but 99% of the problems
 reported to me are caused by somehow incorrect setup during "make config".
 
index 684456c590e45345aff54f85b3b00e07b4cde270..a9ccdfc2e84326dd251dc9e40af2c913357d0e64 100644 (file)
@@ -206,7 +206,7 @@ static void wait_for_calibration(ad1848_info * devc)
                return;
 
        timeout = 80000;
-       while (timeout > 0 && ad_read(devc, 11) & 0x20)
+       while (timeout > 0 && (ad_read(devc, 11) & 0x20))
                timeout--;
        if (ad_read(devc, 11) & 0x20)
                if (devc->model != MD_1845)
@@ -916,7 +916,7 @@ static void ad1848_output_block(int dev, unsigned long buf, int count, int intrf
                cnt >>= 1;
        cnt--;
 
-       if (devc->audio_mode & PCM_ENABLE_OUTPUT && audio_devs[dev]->flags & DMA_AUTOMODE &&
+       if ((devc->audio_mode & PCM_ENABLE_OUTPUT) && (audio_devs[dev]->flags & DMA_AUTOMODE) &&
            intrflag &&
            cnt == devc->xfer_count)
        {
@@ -958,7 +958,7 @@ static void ad1848_start_input(int dev, unsigned long buf, int count, int intrfl
                cnt >>= 1;
        cnt--;
 
-       if (devc->audio_mode & PCM_ENABLE_INPUT && audio_devs[dev]->flags & DMA_AUTOMODE &&
+       if ((devc->audio_mode & PCM_ENABLE_INPUT) && (audio_devs[dev]->flags & DMA_AUTOMODE) &&
                intrflag &&
                cnt == devc->xfer_count)
        {
@@ -1182,10 +1182,10 @@ static void ad1848_halt(int dev)
 
        unsigned char   bits = ad_read(devc, 9);
 
-       if (bits & 0x01 && portc->open_mode & OPEN_WRITE)
+       if (bits & 0x01 && (portc->open_mode & OPEN_WRITE))
                ad1848_halt_output(dev);
 
-       if (bits & 0x02 && portc->open_mode & OPEN_READ)
+       if (bits & 0x02 && (portc->open_mode & OPEN_READ))
                ad1848_halt_input(dev);
        devc->audio_mode = 0;
 }
@@ -1308,7 +1308,7 @@ static void ad1848_init_hw(ad1848_info * devc)
                0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,
 
        /* Positions 16 to 31 just for CS4231/2 and ad1845 */
-               0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+               0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        };
 
@@ -1997,16 +1997,16 @@ interrupt_again:                /* Jump back here if int status doesn't reset */
                        ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat);      /* Selective ack */
                }
 
-               if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
+               if ((devc->open_mode & OPEN_READ) && (devc->audio_mode & PCM_ENABLE_INPUT) && (alt_stat & 0x20))
                {
                        DMAbuf_inputintr(devc->record_dev);
                }
-               if (devc->open_mode & OPEN_WRITE && devc->audio_mode & PCM_ENABLE_OUTPUT &&
-                     alt_stat & 0x10)
+               if ((devc->open_mode & OPEN_WRITE) && (devc->audio_mode & PCM_ENABLE_OUTPUT) &&
+                     (alt_stat & 0x10))
                {
                        DMAbuf_outputintr(devc->playback_dev, 1);
                }
-               if (devc->model != MD_1848 && alt_stat & 0x40)  /* Timer interrupt */
+               if (devc->model != MD_1848 && (alt_stat & 0x40))        /* Timer interrupt */
                {
                        devc->timer_ticks++;
 #if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)
index ab8eb20350882108d83c9d8ab3fe4ed4274488f6..5768420a9746f550fdd5a7c7c92a8c6f36911416 100644 (file)
@@ -17,7 +17,7 @@
  * The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
  * Sound card manufacturers have connected actual inputs (CD, synth, line,
  * etc) to these inputs in different order. Therefore it's difficult
- * to assign mixer channels to to these inputs correctly. The following
+ * to assign mixer channels to these inputs correctly. The following
  * contains two alternative mappings. The first one is for GUS MAX and
  * the second is just a generic one (line1, line2 and line3).
  * (Actually this is not a mapping but rather some kind of interleaving
index 54d8e5f5b67d368f003f48526ccdde316456e222..45c79c817c4a901aa0e3ffa75b41efa001053c9f 100644 (file)
@@ -279,7 +279,7 @@ int audio_read(int dev, struct file *file, char *buf, int count)
                         *      Nonblocking mode handling. Return current # of bytes
                         */
 
-                       if (file->f_flags & O_NONBLOCK && buf_no == -EAGAIN)
+                       if ((file->f_flags & O_NONBLOCK) && buf_no == -EAGAIN)
                                return p;
 
                        if (p > 0)              /* Avoid throwing away data */
index 215df408a4eda06786340b3e249dc525bb948e30..4864521716c902979c34ecf799cd7f5b5e1316df 100644 (file)
@@ -31,6 +31,8 @@
 #define SNDCARD_SOFTOSS                        36
 #define SNDCARD_VMIDI                  37
 #define SNDCARD_WAVEFRONT               41
+#define SNDCARD_OPL3SA2                 42
+#define SNDCARD_OPL3SA2_MPU             43
 
 void attach_opl3sa_wss (struct address_info *hw_config);
 int probe_opl3sa_wss (struct address_info *hw_config);
@@ -412,6 +414,11 @@ struct driver_info sound_drivers[] =
        {"CS4232MPU", 0, SNDCARD_CS4232_MPU,    "CS4232 MIDI",          attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu},
 #endif
 
+#ifdef CONFIG_SOUND_OPL3SA2
+       {"OPL3SA2", 0, SNDCARD_OPL3SA2, "OPL3SA2",              attach_opl3sa2, probe_opl3sa2, unload_opl3sa2},
+       {"OPL3SA2MPU", 0, SNDCARD_OPL3SA2_MPU,  "OPL3SA2 MIDI",         attach_opl3sa2_mpu, probe_opl3sa2_mpu, unload_opl3sa2_mpu},
+#endif
+
 #ifdef CONFIG_SGALAXY
        {"SGALAXY", 0, SNDCARD_SGALAXY, "Sound Galaxy WSS",             attach_sgalaxy, probe_sgalaxy, unload_sgalaxy},
 #endif
@@ -560,6 +567,16 @@ struct card_info snd_installed_cards[] =
        {SNDCARD_CS4232, {CONFIG_CS4232_BASE, CONFIG_CS4232_IRQ, CONFIG_CS4232_DMA, CONFIG_CS4232_DMA2}, SND_DEFAULT_ENABLE},
 #endif
 
+#ifdef CONFIG_SOUND_OPL3SA2
+#ifndef CONFIG_OPL3SA2_DMA2
+#define CONFIG_OPL3SA2_DMA2 CONFIG_OPL3SA2_DMA
+#endif
+#ifdef CONFIG_OPL3SA2_MPU_BASE
+       {SNDCARD_OPL3SA2_MPU, {CONFIG_OPL3SA2_MPU_BASE, CONFIG_OPL3SA2_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+#endif
+       {SNDCARD_OPL3SA2, {CONFIG_OPL3SA2_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE},
+#endif
+
 #ifdef CONFIG_SGALAXY
 #ifndef CONFIG_SGALAXY_DMA2
 #define CONFIG_SGALAXY_DMA2 CONFIG_SGALAXY_DMA
index 51b9d87de38345a0ed683e3a5f2b21eef65456fc..4f9f9f276ddf8cf691e8b36f411ba7283c5405ef 100644 (file)
@@ -138,15 +138,15 @@ static int sound_start_dma(struct dma_buffparms *dmap, unsigned long physaddr, i
        int chan = dmap->dma;
 
        /* printk( "Start DMA%d %d, %d\n",  chan,  (int)(physaddr-dmap->raw_buf_phys),  count); */
-       save_flags(flags);
-       cli();
+
+       flags = claim_dma_lock();
        disable_dma(chan);
        clear_dma_ff(chan);
        set_dma_mode(chan, dma_mode);
        set_dma_addr(chan, physaddr);
        set_dma_count(chan, count);
        enable_dma(chan);
-       restore_flags(flags);
+       release_dma_lock(flags);
 
        return 0;
 }
@@ -201,11 +201,17 @@ static int open_dmap(struct audio_operations *adev, int mode, struct dma_buffpar
 
 static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap)
 {
+       unsigned long flags;
+       
        sound_close_dma(dmap->dma);
        if (dmap->flags & DMA_BUSY)
                dmap->dma_mode = DMODE_NONE;
        dmap->flags &= ~DMA_BUSY;
+       
+       flags=claim_dma_lock();
        disable_dma(dmap->dma);
+       release_dma_lock(flags);
+       
        sound_free_dmap(dmap);
 }
 
@@ -279,7 +285,7 @@ int DMAbuf_open(int dev, int mode)
        }
        adev->enable_bits = mode;
 
-       if (mode == OPEN_READ || (mode != OPEN_WRITE && adev->flags & DMA_DUPLEX)) {
+       if (mode == OPEN_READ || (mode != OPEN_WRITE && (adev->flags & DMA_DUPLEX))) {
                if ((retval = open_dmap(adev, mode, dmap_in)) < 0) {
                        adev->d->close(dev);
                        if (mode & OPEN_WRITE)
@@ -311,7 +317,7 @@ void DMAbuf_reset(int dev)
 static void dma_reset_output(int dev)
 {
        struct audio_operations *adev = audio_devs[dev];
-       unsigned long flags;
+       unsigned long flags,f ;
        struct dma_buffparms *dmap = adev->dmap_out;
 
        if (!(dmap->flags & DMA_STARTED))       /* DMA is not active */
@@ -341,8 +347,12 @@ static void dma_reset_output(int dev)
        else
                adev->d->halt_output(dev);
        adev->dmap_out->flags &= ~DMA_STARTED;
+       
+       f=claim_dma_lock();
        clear_dma_ff(dmap->dma);
        disable_dma(dmap->dma);
+       release_dma_lock(f);
+       
        restore_flags(flags);
        dmap->byte_counter = 0;
        reorganize_buffers(dev, adev->dmap_out, 0);
@@ -377,7 +387,7 @@ void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap)
                return;         /* Don't start DMA yet */
        dmap->dma_mode = DMODE_OUTPUT;
 
-       if (!(dmap->flags & DMA_ACTIVE) || !(adev->flags & DMA_AUTOMODE) || dmap->flags & DMA_NODMA) {
+       if (!(dmap->flags & DMA_ACTIVE) || !(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) {
                if (!(dmap->flags & DMA_STARTED)) {
                        reorganize_buffers(dev, dmap, 0);
                        if (adev->d->prepare_for_output(dev, dmap->fragment_size, dmap->nbufs))
@@ -404,7 +414,7 @@ int DMAbuf_sync(int dev)
        int n = 0;
        struct dma_buffparms *dmap;
 
-       if (!adev->go && (!adev->enable_bits & PCM_ENABLE_OUTPUT))
+       if (!adev->go && !(adev->enable_bits & PCM_ENABLE_OUTPUT))
                return 0;
 
        if (adev->dmap_out->dma_mode == DMODE_OUTPUT) {
@@ -476,7 +486,7 @@ int DMAbuf_release(int dev, int mode)
 
        if (adev->open_mode == OPEN_READ ||
            (adev->open_mode != OPEN_WRITE &&
-            adev->flags & DMA_DUPLEX))
+            (adev->flags & DMA_DUPLEX)))
                close_dmap(adev, adev->dmap_in);
        adev->open_mode = 0;
        restore_flags(flags);
@@ -606,6 +616,7 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
 
        int pos;
        unsigned long flags;
+       unsigned long f;
 
        save_flags(flags);
        cli();
@@ -613,9 +624,12 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
                pos = 0;
        else {
                int chan = dmap->dma;
+               
+               f=claim_dma_lock();
                clear_dma_ff(chan);
                disable_dma(dmap->dma);
                pos = get_dma_residue(chan);
+               
                pos = dmap->bytes_in_use - pos;
 
                if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) {
@@ -634,6 +648,7 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
                if (pos >= dmap->bytes_in_use)
                        pos = 0;
                enable_dma(dmap->dma);
+               release_dma_lock(f);
        }
        restore_flags(flags);
        /* printk( "%04x ",  pos); */
@@ -961,10 +976,16 @@ static void do_outputintr(int dev, int dummy)
        }
        if (!(adev->flags & DMA_AUTOMODE))
                dmap->flags &= ~DMA_ACTIVE;
-       while (dmap->qlen <= 0) {
+               
+       /*
+        *      This is  dmap->qlen <= 0 except when closing when
+        *      dmap->qlen < 0
+        */
+        
+       while (dmap->qlen <= -dmap->closing) {
                dmap->underrun_count++;
                dmap->qlen++;
-               if (dmap->flags & DMA_DIRTY && dmap->applic_profile != APF_CPUINTENS) {
+               if ((dmap->flags & DMA_DIRTY) && dmap->applic_profile != APF_CPUINTENS) {
                        dmap->flags &= ~DMA_DIRTY;
                        memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte,
                               adev->dmap_out->buffsize);
@@ -988,10 +1009,15 @@ void DMAbuf_outputintr(int dev, int notify_only)
        cli();
        if (!(dmap->flags & DMA_NODMA)) {
                int chan = dmap->dma, pos, n;
+               unsigned long f;
+               
+               f=claim_dma_lock();
                clear_dma_ff(chan);
                disable_dma(dmap->dma);
                pos = dmap->bytes_in_use - get_dma_residue(chan);
                enable_dma(dmap->dma);
+               release_dma_lock(f);
+               
                pos = pos / dmap->fragment_size;        /* Actual qhead */
                if (pos < 0 || pos >= dmap->nbufs)
                        pos = 0;
@@ -1056,7 +1082,7 @@ static void do_inputintr(int dev)
                        }
                }
        }
-       if (!(adev->flags & DMA_AUTOMODE) || dmap->flags & DMA_NODMA) {
+       if (!(adev->flags & DMA_AUTOMODE) || (dmap->flags & DMA_NODMA)) {
                local_start_dma(adev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ);
                adev->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, dmap->fragment_size, 1);
                if (adev->d->trigger)
@@ -1078,10 +1104,14 @@ void DMAbuf_inputintr(int dev)
 
        if (!(dmap->flags & DMA_NODMA)) {
                int chan = dmap->dma, pos, n;
+               unsigned long f;
+               
+               f=claim_dma_lock();
                clear_dma_ff(chan);
                disable_dma(dmap->dma);
                pos = dmap->bytes_in_use - get_dma_residue(chan);
                enable_dma(dmap->dma);
+               release_dma_lock(f);
 
                pos = pos / dmap->fragment_size;        /* Actual qhead */
                if (pos < 0 || pos >= dmap->nbufs)
@@ -1112,11 +1142,10 @@ int DMAbuf_open_dma(int dev)
        if (adev->dmap_out->dma >= 0) {
                unsigned long flags;
 
-               save_flags(flags);
-               cli();
+               flags=claim_dma_lock();
                clear_dma_ff(adev->dmap_out->dma);
                disable_dma(adev->dmap_out->dma);
-               restore_flags(flags);
+               release_dma_lock(flags);
        }
        return 0;
 }
index c9b39b1c9a89191e2c7abac8e317b8b582f22c43..cde5bc2fc48c6faa6042fa062f0aa9b57cad8d99 100644 (file)
@@ -27,6 +27,7 @@
 #define CONFIG_MPU401
 #define CONFIG_MSS
 #define CONFIG_OPL3SA1
+#define CONFIG_OPL3SA2
 #define CONFIG_PAS
 #define CONFIG_PSS
 #define CONFIG_SB
index 03e6a177e0d944774b1c8ee8857abeafa8975e43..899d40404acd855487c8d7b19303efe441c1d184 100644 (file)
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.c,v 1.63 1998/09/10 18:37:19 andrewtv Exp $
+ * $Id: msnd_pinnacle.c,v 1.65 1998/09/18 19:13:03 andrewtv Exp $
  *
  ********************************************************************/
 
@@ -1099,7 +1099,9 @@ static struct file_operations dev_fileops = {
        dev_ioctl,      /* ioctl */
        NULL,           /* mmap */
        dev_open,       /* open */
+#ifndef LINUX20
        NULL,           /* flush */
+#endif
        dev_release,    /* release */
        NULL,           /* fsync */
        NULL,           /* fasync */
diff --git a/drivers/sound/opl3sa2.c b/drivers/sound/opl3sa2.c
new file mode 100644 (file)
index 0000000..d9d95c2
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * sound/opl3sa2.c
+ *
+ * A low level driver for Yamaha OPL3-SA[2,3,x] based cards.
+ *
+ * Scott Murray, Jun 14, 1998
+ *
+ */
+
+/* Based on the CS4232 driver:
+ *
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include "sound_config.h"
+#include "soundmodule.h"
+
+#ifdef CONFIG_OPL3SA2
+
+int probe_opl3sa2_mpu(struct address_info *hw_config)
+{
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+       return probe_mpu401(hw_config);
+#else
+       return 0;
+#endif
+}
+
+
+void attach_opl3sa2_mpu(struct address_info *hw_config)
+{
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+       attach_mpu401(hw_config);
+#endif
+}
+
+
+void unload_opl3sa2_mpu(struct address_info *hw_config)
+{
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+       unload_mpu401(hw_config);
+#endif
+}
+
+
+int probe_opl3sa2_mss(struct address_info *hw_config)
+{
+       return probe_ms_sound(hw_config);
+}
+
+
+void attach_opl3sa2_mss(struct address_info *hw_config)
+{
+       printk(KERN_INFO "opl3sa2.c: trying to init WSS\n");   
+   
+       attach_ms_sound(hw_config);
+
+       /* request_region(hw_config->io_base, 4, "Yamaha 7xx WSS Config"); */
+   
+       if (hw_config->slots[0] != -1 &&
+           audio_devs[hw_config->slots[0]]->mixer_dev != -1)
+       {
+               AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
+               AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
+               /* GSM! test the following: */
+                AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+       }
+}
+
+
+void unload_opl3sa2_mss(struct address_info *hw_config)
+{
+        int mixer;
+
+        /* Find mixer */
+       mixer = audio_devs[hw_config->slots[0]]->mixer_dev;
+
+        /* Unload MSS audio codec */
+       unload_ms_sound(hw_config);
+
+       sound_unload_audiodev(hw_config->slots[0]);
+
+        /* Unload mixer if there */
+       if(mixer >= 0)
+       {
+               sound_unload_mixerdev(mixer);
+       }
+
+        /* Release MSS config ports */
+       release_region(hw_config->io_base, 4);
+}
+
+
+int probe_opl3sa2(struct address_info *hw_config)
+{
+       /*
+        * Verify that the I/O port range is free.
+        */
+
+       printk(KERN_INFO "opl3sa2.c: Control using I/O port 0x%03x\n", hw_config->io_base);
+
+       if (check_region(hw_config->io_base, 2))
+       {
+           printk(KERN_ERR "opl3sa2.c: Control I/O port 0x%03x not free\n", hw_config->io_base);
+           return 0;
+       }
+
+       /* GSM!: Add some kind of other test here... */
+
+       return 1;
+}
+
+
+void attach_opl3sa2(struct address_info *hw_config)
+{
+       printk(KERN_INFO "opl3sa2.c: trying to init!\n");   
+   
+       request_region(hw_config->io_base, 2, "Yamaha 7xx Control");
+
+       /* GSM! Mixer stuff should go here... */
+}   
+
+
+void unload_opl3sa2(struct address_info *hw_config)
+{
+        /* Release control ports */
+       release_region(hw_config->io_base, 2);
+
+       /* GSM! Mixer stuff should go here... */
+}
+
+
+#ifdef MODULE
+
+int io      = -1;
+int mss_io  = -1;
+int mpu_io  = -1;
+int irq     = -1;
+int dma     = -1;
+int dma2    = -1;
+
+MODULE_PARM(io,"i");
+MODULE_PARM(mss_io,"i");
+MODULE_PARM(mpu_io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma2,"i");
+
+EXPORT_NO_SYMBOLS;
+
+struct address_info cfg;
+struct address_info mss_cfg;
+struct address_info mpu_cfg;
+
+/*
+ *     Install a OPL3SA2 based card. Need to have ad1848 and mpu401
+ *     loaded ready.
+ */
+int init_module(void)
+{
+        int i;
+
+       if (io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
+       {
+               printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n");
+               return -EINVAL;
+       }
+   
+        /* Our own config: */
+        cfg.io_base = io;
+       cfg.irq     = irq;
+       cfg.dma     = dma;
+       cfg.dma2    = dma2;
+
+        /* The MSS config: */
+       mss_cfg.io_base      = mss_io;
+       mss_cfg.irq          = irq;
+       mss_cfg.dma          = dma;
+       mss_cfg.dma2         = dma2;
+       mss_cfg.card_subtype = 1;      /* No IRQ or DMA setup */
+
+       /* Call me paranoid: */
+       for(i = 0; i < 6; i++)
+       {
+           cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1;
+       }
+
+       if (probe_opl3sa2(&cfg) == 0)
+       {
+           return -ENODEV;
+       }
+       attach_opl3sa2(&cfg);
+
+       if (probe_opl3sa2_mss(&mss_cfg) == 0)
+       {
+           return -ENODEV;
+       }
+       attach_opl3sa2_mss(&mss_cfg);
+
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+       if(mpu_io != -1)
+       {
+            /* MPU config: */
+           mpu_cfg.io_base       = mpu_io;
+           mpu_cfg.irq           = irq;
+           mpu_cfg.dma           = dma;
+           mpu_cfg.always_detect = 1;  /* It's there, so use shared IRQs */
+
+           if (probe_opl3sa2_mpu(&mpu_cfg))
+           {
+               attach_opl3sa2_mpu(&mpu_cfg);
+           }
+       }
+#endif
+       SOUND_LOCK;
+       return 0;
+}
+
+
+void cleanup_module(void)
+{
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+        if(mpu_cfg.slots[1] != -1)
+       {
+            unload_opl3sa2_mpu(&mpu_cfg);
+       }
+#endif
+       unload_opl3sa2_mss(&mss_cfg);
+       unload_opl3sa2(&cfg);
+       SOUND_LOCK_END;
+}
+
+#endif
+#endif
index f1a24cc109c25fe20286e4e30e90fba371a7f4e8..c243ed6184896dd2fd6ca7e3b4dca4c613b34ab9 100644 (file)
@@ -954,8 +954,7 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
                if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && devc->irq > 0)
                {
                        free_irq(devc->irq, devc);
-                       if (devc->my_mixerdev)
-                               sound_unload_mixerdev(devc->my_mixerdev);
+                       sound_unload_mixerdev(devc->my_mixerdev);
                        /* We don't have to do this bit any more the UART401 is its own
                                master  -- Krzysztof Halasa */
                        /* But we have to do it, if UART401 is not detected */
index a5d2272b4658daf6c97af639f165e555629fbd4c..8c91cb72d1b791ba4a82f7afd47377cc112d1508 100644 (file)
@@ -251,6 +251,8 @@ void unload_trix_sb(struct address_info *hw_info);
 void unload_trix_mpu(struct address_info *hw_info);
 void unload_cs4232(struct address_info *hw_info);
 void unload_cs4232_mpu(struct address_info *hw_info);
+void unload_opl3sa2(struct address_info *hw_info);
+void unload_opl3sa2_mpu(struct address_info *hw_info);
 
 /* From cs4232.c */
 
@@ -259,6 +261,12 @@ void attach_cs4232 (struct address_info *hw_config);
 int probe_cs4232_mpu (struct address_info *hw_config);
 void attach_cs4232_mpu (struct address_info *hw_config);
 
+/* From opl3sa2.c */
+int probe_opl3sa2 (struct address_info *hw_config);
+void attach_opl3sa2 (struct address_info *hw_config);
+int probe_opl3sa2_mpu (struct address_info *hw_config);
+void attach_opl3sa2_mpu (struct address_info *hw_config);
+
 /*     From maui.c */
 void attach_maui(struct address_info * hw_config);
 int probe_maui(struct address_info *hw_config);
index 3869fbd3414408b5f73004ae13ff00591ee3847f..e6aa9697fd3378d3d55469fa53541f7bbffe4763 100644 (file)
@@ -71,6 +71,14 @@ if [ "$CONFIG_FB" = "y" ]; then
       bool '  Leo (ZX) support' CONFIG_FB_LEO
     fi
   fi
+  if [ "$ARCH" = "sparc" ]; then
+    if [ "$CONFIG_PCI" != "n" ]; then
+      bool 'PCI framebuffers' CONFIG_FB_PCI
+      if [ "$CONFIG_FB_PCI" != "n" ]; then
+        bool '  IGA 168x display support' CONFIG_FB_IGA
+      fi
+    fi
+  fi
   if [ "$ARCH" = "sparc64" ]; then
     if [ "$CONFIG_PCI" != "n" ]; then
       bool 'PCI framebuffers' CONFIG_FB_PCI
@@ -133,7 +141,8 @@ if [ "$CONFIG_FB" = "y" ]; then
         "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
         "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
         "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
-        "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then
+        "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
+         "$CONFIG_FB_IGA" = "y" ]; then
       define_bool CONFIG_FBCON_CFB8 y
     else
       if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -143,7 +152,8 @@ if [ "$CONFIG_FB" = "y" ]; then
           "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
           "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
           "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
-          "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then
+          "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
+           "$CONFIG_FB_IGA" = "y" ]; then
        define_bool CONFIG_FBCON_CFB8 m
       fi
     fi
index 409d58c6cc85a5f4761d3ee27b10a1e36960a4e7..18ce5c3ea76a4a3914bee3c0dcfa0dce520caff5 100644 (file)
@@ -95,6 +95,10 @@ ifeq ($(CONFIG_FB_ATY),y)
 L_OBJS += atyfb.o
 endif
 
+ifeq ($(CONFIG_FB_IGA),y)
+L_OBJS += igafb.o
+endif
+
 ifeq ($(CONFIG_FB_CONTROL),y)
 L_OBJS += controlfb.o
 endif
@@ -447,7 +451,7 @@ endif
 
 include $(TOPDIR)/Rules.make
 
-promcon_tbl.c: prom.uni
+promcon_tbl.c: prom.uni ../char/conmakehash
        ../char/conmakehash prom.uni | \
        sed -e '/#include <[^>]*>/p' -e 's/types/init/' \
            -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
index 51bf7e5ccef5537bf8bfb6928efdb8e6e481044f..170fb93a2fa7181301560a21a59a20a190b96b1b 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.77 1998/09/14 08:01:46 jj Exp $
+/*  $Id: atyfb.c,v 1.81 1998/10/14 16:45:38 ecd Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *     Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -28,6 +28,8 @@
 
     - cursor support on all cards and all ramdacs.
     - cursor parameters controlable via ioctl()s.
+    - guess PLL and MCLK based on the original PLL register values initialized
+      by the BIOS or Open Firmware (if they are initialized).
 
                                                (Anyone to help with this?)
 
@@ -60,7 +62,7 @@
 
 #include <asm/io.h>
 
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <video/macmodes.h>
@@ -83,7 +85,7 @@
 /*
  * Debug flags.
  */
-#undef PLL_DEBUG
+#undef DEBUG
 
 
 #define GUI_RESERVE    0x00001000
@@ -322,7 +324,7 @@ static void init_engine(const struct atyfb_par *par,
                        const struct fb_info_aty *info);
 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
-#ifdef PLL_DEBUG
+#if defined(__sparc__) || defined(DEBUG)
 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
 #endif
 static void aty_set_crtc(const struct fb_info_aty *info,
@@ -366,7 +368,7 @@ static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                         u_int transp, struct fb_info *fb);
 static void do_install_cmap(int con, struct fb_info *info);
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
 static int read_aty_sense(const struct fb_info_aty *info);
 #endif
 
@@ -401,7 +403,7 @@ static char noaccel __initdata = 0;
 
 static const u32 ref_clk_per = 1000000000000ULL/14318180;
 
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
 static int default_vmode = VMODE_NVRAM;
 static int default_cmode = CMODE_NVRAM;
 #endif
@@ -445,6 +447,14 @@ static struct aty_features {
     { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
 };
 
+static const char *aty_gx_ram[8] __initdata = {
+    "DRAM", "VRAM", "VRAM", "DRAM", "GDRAM", "EVRAM", "EVRAM", "RESV"
+};
+
+static const char *aty_ct_ram[8] __initdata = {
+    "OFF", "DRAM", "EDO", "HPDRAM", "SDRAM", "SGRAM", "WRAM", "RESV"
+};
+
 
 static inline u32 aty_ld_le32(volatile unsigned int regindex,
                              const struct fb_info_aty *info)
@@ -670,7 +680,7 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
     aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
 }
 
-#ifdef PLL_DEBUG
+#if defined(__sparc__) || defined(DEBUG)
 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
 {
     u8 res;
@@ -685,7 +695,7 @@ static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
 }
 #endif
 
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
 
     /*
      *  Apple monitor sense
@@ -725,7 +735,7 @@ static int read_aty_sense(const struct fb_info_aty *info)
     return sense;
 }
 
-#endif /* defined(CONFIG_PMAC) || defined(CONFIG_CHRP) */
+#endif /* defined(CONFIG_PPC) */
 
 /* ------------------------------------------------------------------------- */
 
@@ -2289,6 +2299,78 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
        }
        return 0;
 }
+
+static struct {
+       u32     yoffset;
+       u8      r[2][256];
+       u8      g[2][256];
+       u8      b[2][256];
+} atyfb_save;
+
+static void atyfb_save_palette(struct fb_info *fb, int enter)
+{
+       struct fb_info_aty *info = (struct fb_info_aty *)fb;
+       int i, tmp, scale;
+
+       for (i = 0; i < 256; i++) {
+               tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
+               if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) ||
+                   (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) ||
+                   (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) ||
+                   (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+                       tmp |= 0x2;
+               aty_st_8(DAC_CNTL, tmp, info);
+               aty_st_8(DAC_REGS + DAC_MASK, 0xff, info);
+               eieio();
+               scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
+                       (info->current_par.crtc.bpp == 16)) ? 3 : 0;
+               info->aty_cmap_regs->rindex = i << scale;
+               eieio();
+               atyfb_save.r[enter][i] = info->aty_cmap_regs->lut;
+               eieio();
+               atyfb_save.g[enter][i] = info->aty_cmap_regs->lut;
+               eieio();
+               atyfb_save.b[enter][i] = info->aty_cmap_regs->lut;
+               eieio();
+               info->aty_cmap_regs->windex = i << scale;
+               eieio();
+               info->aty_cmap_regs->lut = atyfb_save.r[1-enter][i];
+               eieio();
+               info->aty_cmap_regs->lut = atyfb_save.g[1-enter][i];
+               eieio();
+               info->aty_cmap_regs->lut = atyfb_save.b[1-enter][i];
+               eieio();
+       }
+}
+
+static void atyfb_palette(int enter)
+{
+       struct fb_info_aty *info;
+       struct atyfb_par *par;
+       struct display *d;
+       int i;
+
+       for (i = 0; i < MAX_NR_CONSOLES; i++) {
+               d = &fb_display[i];
+               if (d->fb_info &&
+                   d->fb_info->fbops == &atyfb_ops &&
+                   d->fb_info->display_fg &&
+                   d->fb_info->display_fg->vc_num == i) {
+                       atyfb_save_palette(d->fb_info, enter);
+                       info = (struct fb_info_aty *)d->fb_info;
+                       par = &info->current_par;
+                       if (enter) {
+                               atyfb_save.yoffset = par->crtc.yoffset;
+                               par->crtc.yoffset = 0;
+                               set_off_pitch(par, info);
+                       } else {
+                               par->crtc.yoffset = atyfb_save.yoffset;
+                               set_off_pitch(par, info);
+                       }
+                       break;
+               }
+       }
+}
 #endif /* __sparc__ */
 
     /*
@@ -2302,9 +2384,9 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
     int j, k;
     struct fb_var_screeninfo var;
     struct display *disp;
-    const char *chipname = NULL;
+    const char *chipname = NULL, *ramname = NULL;
     int pll, mclk;
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
     int sense;
 #endif
 
@@ -2325,6 +2407,7 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
     if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
        info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
        info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
+       ramname = aty_gx_ram[info->ram_type];
        /* FIXME: clockchip/RAMDAC probing? */
 #ifdef CONFIG_ATARI
        info->dac_type = DAC_ATI68860_B;
@@ -2339,6 +2422,7 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
     } else {
        info->bus_type = PCI;
        info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
+       ramname = aty_ct_ram[info->ram_type];
        info->dac_type = DAC_INTERNAL;
        info->clk_type = CLK_INTERNAL;
        if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
@@ -2454,17 +2538,34 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
          info->total_vram += 0x400000;
     }
 
-    printk("%d%c %d MHz PLL, %d Mhz MCLK\n", 
+    printk("%d%c %s, %d MHz PLL, %d Mhz MCLK\n", 
           info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20), 
-          info->total_vram == 0x80000 ? 'K' : 'M', pll, mclk);
-    
+          info->total_vram == 0x80000 ? 'K' : 'M', ramname, pll, mclk);
+
+#ifdef DEBUG
+    if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
+       int i;
+       printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+              "DSP_CONFIG DSP_ON_OFF\n"
+              "%08x %08x %08x %08x     %08x      %08x   %08x\n"
+              "PLL",
+              aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
+              aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
+              aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
+              aty_ld_le32(DSP_ON_OFF, info));
+       for (i = 0; i < 16; i++)
+           printk(" %02x", aty_ld_pll(i, info));
+       printk("\n");
+    }
+#endif
+
     if (info->bus_type == ISA)
        if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
            /* protect GUI-regs if complete Aperture is VRAM */
            info->total_vram -= GUI_RESERVE;
        }
 
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
     if (default_vmode == VMODE_NVRAM) {
        default_vmode = nvram_read_byte(NV_VMODE);
        if (default_vmode <= 0 || default_vmode > VMODE_MAX)
@@ -2487,9 +2588,9 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
        default_cmode = CMODE_8;
     if (mac_vmode_to_var(default_vmode, default_cmode, &var))
        var = default_var;
-#else /* !CONFIG_PMAC && !CONFIG_CHRP */
+#else /* !CONFIG_PPC */
     var = default_var;
-#endif /* !CONFIG_PMAC && !CONFIG_CHRP */
+#endif /* !CONFIG_PPC */
     if (noaccel)
         var.accel_flags &= ~FB_ACCELF_TEXT;
     else
@@ -2520,6 +2621,9 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
     info->fb_info.blank = &atyfbcon_blank;
     info->fb_info.flags = FBINFO_FLAG_DEFAULT;
 
+#ifdef __sparc__
+    atyfb_save_palette(&info->fb_info, 0);
+#endif
     for (j = 0; j < 16; j++) {
        k = color_table[j];
        info->palette[j].red = default_red[k];
@@ -2555,6 +2659,7 @@ __initfunc(void atyfb_init(void))
     struct fb_info_aty *info;
     unsigned long addr;
 #ifdef __sparc__
+    extern void (*prom_palette) (int);
     extern int con_is_present(void);
     struct pcidev_cookie *pcp;
     char prop[128];
@@ -2703,6 +2808,9 @@ __initfunc(void atyfb_init(void))
                struct fb_var_screeninfo *var = &default_var;
                u32 v_total, h_total;
                struct crtc crtc;
+               u8 pll_regs[16];
+               u8 clock_cntl;
+               unsigned int N, P, Q, M, T;
 
                crtc.vxres = prom_getintdefault(node, "width", 1024);
                crtc.vyres = prom_getintdefault(node, "height", 768);
@@ -2715,15 +2823,59 @@ __initfunc(void atyfb_init(void))
                crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
                aty_crtc_to_var(&crtc, var);
 
-               /*
-                * FIXME: Read the PLL to figure actual Refresh Rate.
-                *        Default to 66Hz for now.
-                */
                h_total = var->xres + var->right_margin +
                          var->hsync_len + var->left_margin;
                v_total = var->yres + var->lower_margin +
                          var->vsync_len + var->upper_margin;
-               default_var.pixclock = 1000000000000ULL/(66*h_total*v_total);
+
+               /*
+                * Read the PLL to figure actual Refresh Rate.
+                */
+               clock_cntl = aty_ld_8(CLOCK_CNTL, info);
+               /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
+               for (i = 0; i < 16; i++) {
+                       pll_regs[i] = aty_ld_pll(i, info);
+                       /* printk("atyfb: PLL %2d: %02x\n", i, pll_regs[i]); */
+               }
+               /*
+                * PLL Reference Devider M:
+                */
+               M = pll_regs[2];
+               /* printk("atyfb: M: %02x\n", M); */
+
+               /*
+                * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
+                */
+               N = pll_regs[7 + (clock_cntl & 3)];
+               /* printk("atyfb: N: %02x\n", N); */
+
+               /*
+                * PLL Post Devider P (Dependant on CLOCK_CNTL):
+                */
+               P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
+               /* printk("atyfb: P: %2d\n", P); */
+
+               /*
+                * PLL Devider Q:
+                */
+               Q = N / P;
+               /* printk("atyfb: Q: %d\n", Q); */
+
+               /*
+                * Target Frequency:
+                *
+                *      T * M
+                * Q = -------
+                *      2 * R
+                *
+                * where R is XTALIN (= 14318 kHz).
+                */
+               T = 2 * Q * 14318 / M;
+               /* printk("atyfb: T: %d\n", T); */
+
+               default_var.pixclock =
+                       ((1000000000000ULL / v_total) * 1000) / (T * h_total);
+               /* printk("atyfb: pixclock: %d\n", default_var.pixclock); */
            }
 
 #else /* __sparc__ */
@@ -2764,6 +2916,9 @@ __initfunc(void atyfb_init(void))
            }
 
 #ifdef __sparc__
+           if (!prom_palette)
+               prom_palette = atyfb_palette;
+
            /*
             * Add /dev/fb mmap values.
             */
@@ -2920,7 +3075,7 @@ __initfunc(void atyfb_setup(char *options, int *ints))
        } else if (!strncmp(this_opt, "noaccel", 7)) {
                noaccel = 1;
        }
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
        else if (!strncmp(this_opt, "vmode:", 6)) {
            unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
            if (vmode > 0 && vmode <= VMODE_MAX)
index f0d1fd29db5e78a744a0898c510487af497099b4..bfe01d4ba7114f18c0e1e74237d23ec78d87ddae 100644 (file)
@@ -1338,11 +1338,6 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
     if (resize) {
        /* reset wrap/pan */
        p->var.xoffset = p->var.yoffset = p->yscroll = 0;
-       if (!p->dispsw->set_font || 
-           !p->dispsw->set_font(p, fontwidth(p), fontheight(p))) {
-           /* Adjust the virtual screen-size to fontheight*rows */
-           p->var.yres_virtual = (p->var.yres/h)*h;
-       }
        p->vrows = p->var.yres_virtual/h;
        updatescrollmode(p);
        vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
index 0178aadaef460c728cbabc05619af98e8ea5259e..748d5705f3bcc5059597e47dd046538b1eb6d945 100644 (file)
@@ -66,6 +66,8 @@ extern void offb_init(void);
 extern void offb_setup(char *options, int *ints);
 extern void atyfb_init(void);
 extern void atyfb_setup(char *options, int *ints);
+extern void igafb_init(void);
+extern void igafb_setup(char *options, int *ints);
 extern void imsttfb_init(void);
 extern void dnfb_init(void);
 extern void tgafb_init(void);
@@ -116,6 +118,9 @@ static struct {
 #ifdef CONFIG_FB_ATY
        { "atyfb", atyfb_init, atyfb_setup },
 #endif
+#ifdef CONFIG_FB_IGA
+        { "igafb", igafb_init, igafb_setup },
+#endif
 #ifdef CONFIG_FB_IMSTT
        { "imsttfb", imsttfb_init, NULL },
 #endif
diff --git a/drivers/video/iga.h b/drivers/video/iga.h
new file mode 100644 (file)
index 0000000..f688993
--- /dev/null
@@ -0,0 +1,27 @@
+/* $Id: iga.h,v 1.1 1998/10/07 11:36:07 jj Exp $
+ * iga1682.h: Sparc/PCI iga1682 driver constants etc.
+ *
+ * Copyleft 1998 V. Roganov and G. Raiko
+ */
+
+#ifndef _IGA1682_H
+#define _IGA1682_H 1
+
+struct iga1682_info
+{
+    unsigned int total_vram;
+};
+
+#define DAC_W_INDEX                     0x03C8
+#define DAC_DATA                        0x03C9
+#define IGA_EXT_CNTRL                   0x3CE
+#define   IGA_IDX_EXT_BUS_CNTL          0x30
+#define     MEM_SIZE_ALIAS              0x3
+#define     MEM_SIZE_1M                 0x0
+#define     MEM_SIZE_2M                 0x1
+#define     MEM_SIZE_4M                 0x2
+#define     MEM_SIZE_RESERVED           0x3
+#define   IGA_IDX_OVERSCAN_COLOR        0x58
+#define   IGA_IDX_EXT_MEM_2             0x72
+
+#endif /* !(_IGA1682_H) */
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
new file mode 100644 (file)
index 0000000..b7a710d
--- /dev/null
@@ -0,0 +1,785 @@
+/*
+ *  linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
+ *
+ *      Copyright (C) 1998  Vladimir Roganov and Gleb Raiko
+ *
+ *  This driver is partly based on the Frame buffer device for ATI Mach64
+ *  and partially on VESA-related code.
+ *
+ *      Copyright (C) 1997-1998  Geert Uytterhoeven
+ *      Copyright (C) 1998  Bernd Harries
+ *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ *
+ *  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.
+ */
+
+/******************************************************************************
+
+  TODO:
+       Despite of IGA Card has advanced graphic acceleration, 
+       initial version is almost dummy and does not support it.
+       Support for video modes and acceleration must be added
+       together with accelerated X-Windows driver implementation.
+
+                                                (Anyone to help with this?)
+
+       Most important thing at this moment is that we have working
+       JavaEngine1  console & X  with new console interface.
+       
+******************************************************************************/
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/nvram.h>
+#include <linux/kd.h>
+#include <linux/vt_kern.h>
+
+#include <asm/io.h>
+
+#ifdef __sparc__
+#include <asm/pbm.h>
+#include <asm/pcic.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#include "iga.h"
+
+static char igafb_name[16] = "IGA 1682";
+static char fontname[40] __initdata = { 0 };
+
+struct pci_mmap_map {
+    unsigned long voff;
+    unsigned long poff;
+    unsigned long size;
+    unsigned long prot_flag;
+    unsigned long prot_mask;
+};
+
+struct fb_info_iga {
+    struct fb_info fb_info;
+    unsigned long frame_buffer_phys;
+    unsigned long frame_buffer;
+    unsigned long io_base_phys;
+    unsigned long io_base;
+    u32 total_vram;
+    struct pci_mmap_map *mmap_map;
+    struct { u_short blue, green, red, pad; } palette[256];
+    int video_cmap_len;
+    int currcon;
+    struct display disp;
+    struct display_switch dispsw; 
+    union {
+#ifdef FBCON_HAS_CFB16
+           u16 cfb16[16];  
+#endif
+#ifdef FBCON_HAS_CFB24
+           u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+           u32 cfb32[16];
+#endif
+    } fbcon_cmap;
+#ifdef __sparc__
+    u8 open;
+    u8 mmaped;
+    int vtconsole;
+    int consolecnt;
+#endif
+};
+
+struct fb_var_screeninfo default_var = {
+    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+    640, 480, 640, 480, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+    0, FB_VMODE_NONINTERLACED
+};
+
+#ifdef __sparc__
+struct fb_var_screeninfo default_var_1024x768 __initdata = {
+    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
+    1024, 768, 1024, 768, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+struct fb_var_screeninfo default_var_1152x900 __initdata = {
+    /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
+    1152, 900, 1152, 900, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+struct fb_var_screeninfo default_var_1280x1024 __initdata = {
+    /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
+    1280, 1024, 1280, 1024, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
+    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+};
+
+/*
+ *   Memory-mapped I/O functions for Sparc PCI
+ */ 
+static inline unsigned char pci_inb (struct fb_info_iga *info, 
+                                    unsigned int reg) 
+{
+       return *(volatile unsigned char*)(info->io_base + reg);
+}
+static inline void pci_outb (struct fb_info_iga *info, unsigned char c,
+                            unsigned int reg) 
+{
+       *(volatile unsigned char*)(info->io_base + reg) = c;
+}
+static inline unsigned int iga_inb(struct fb_info_iga *info,
+                                  unsigned int reg, unsigned int idx )
+{
+        pci_outb(info, idx, reg);
+        return pci_inb(info, reg + 1);
+}
+static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
+                           unsigned int reg, unsigned int idx )
+{
+        pci_outb(info, idx, reg);
+        pci_outb(info, val, reg+1);
+}
+
+#endif /* __sparc__ */
+
+/*
+ *  Very important functionality for the JavaEngine1 computer:
+ *  make screen border black (usign special IGA registers) 
+ */
+static void iga_blank_border(struct fb_info_iga *info)
+{
+        int i;
+
+        for (i=0; i < 3; i++) 
+                iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
+}
+
+
+/*
+ *  Frame buffer device API
+ */
+
+/*
+ * Open/Release the frame buffer device
+ */
+
+static int igafb_open(struct fb_info *info, int user)
+{
+        /*
+         * Nothing, only a usage count for the moment
+         */
+        MOD_INC_USE_COUNT;
+        return(0);
+}
+
+static int igafb_release(struct fb_info *info, int user)
+{
+        MOD_DEC_USE_COUNT;
+        return(0);
+}
+
+static int igafb_update_var(int con, struct fb_info *info)
+{
+        return 0;
+}
+
+static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                         struct fb_info *info)
+{
+        struct fb_info_iga *fb = (struct fb_info_iga*)info;
+
+        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+        strcpy(fix->id, igafb_name);
+
+        fix->smem_start = (char *)fb->frame_buffer;
+        fix->smem_len = fb->total_vram;
+        fix->xpanstep = 0;
+        fix->ypanstep = 0;
+        fix->ywrapstep = 0;
+
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->type_aux = 0;
+       fix->line_length = default_var.xres * (default_var.bits_per_pixel/8);
+       fix->visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR
+                                                     : FB_VISUAL_DIRECTCOLOR;
+        return 0;
+}
+
+static int igafb_get_var(struct fb_var_screeninfo *var, int con,
+                         struct fb_info *info)
+{
+        if(con == -1)
+                memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+        else
+                *var = fb_display[con].var;
+        return 0;
+}
+
+static int igafb_set_var(struct fb_var_screeninfo *var, int con,
+                         struct fb_info *info)
+{
+        memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+        return 0;
+}
+
+#ifdef __sparc__
+static int igafb_mmap(struct fb_info *info, struct file *file,
+                     struct vm_area_struct *vma)
+{
+       struct fb_info_iga *fb = (struct fb_info_iga *)info;
+       unsigned int size, page, map_size = 0;
+       unsigned long map_offset = 0;
+       int i;
+
+       if (!fb->mmap_map)
+               return -ENXIO;
+
+       size = vma->vm_end - vma->vm_start;
+       if (vma->vm_offset & ~PAGE_MASK)
+               return -ENXIO;
+
+       /* To stop the swapper from even considering these pages. */
+       vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+       /* Each page, see which map applies */
+       for (page = 0; page < size; ) {
+               map_size = 0;
+               for (i = 0; fb->mmap_map[i].size; i++) {
+                       unsigned long start = fb->mmap_map[i].voff;
+                       unsigned long end = start + fb->mmap_map[i].size;
+                       unsigned long offset = vma->vm_offset + page;
+
+                       if (start > offset)
+                               continue;
+                       if (offset >= end)
+                               continue;
+
+                       map_size = fb->mmap_map[i].size - (offset - start);
+                       map_offset = fb->mmap_map[i].poff + (offset - start);
+                       break;
+               }
+               if (!map_size) {
+                       page += PAGE_SIZE;
+                       continue;
+               }
+               if (page + map_size > size)
+                       map_size = size - page;
+
+               pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
+               pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
+
+               if (remap_page_range(vma->vm_start + page, map_offset,
+                                    map_size, vma->vm_page_prot))
+                       return -EAGAIN;
+
+               page += map_size;
+       }
+
+       if (!map_size)
+               return -EINVAL;
+
+       vma->vm_file = file;
+       file->f_count++;
+       vma->vm_flags |= VM_IO;
+
+       if (!fb->mmaped) {
+               int lastconsole = 0;
+
+               if (info->display_fg)
+                       lastconsole = info->display_fg->vc_num;
+               fb->mmaped = 1;
+               if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) {
+                       fb->vtconsole = lastconsole;
+                       vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
+               }
+       }
+       return 0;
+}
+#endif /* __sparc__ */
+
+
+static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+                          unsigned *blue, unsigned *transp,
+                          struct fb_info *fb_info)
+{
+        /*
+         *  Read a single color register and split it into colors/transparent.
+         *  Return != 0 for invalid regno.
+         */
+       struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+        if (regno >= info->video_cmap_len)
+                return 1;
+
+       *red    = info->palette[regno].red;
+       *green  = info->palette[regno].green;
+       *blue   = info->palette[regno].blue;
+       *transp = 0;
+       return 0;
+}
+
+static int iga_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *fb_info)
+{
+        /*
+         *  Set a single color register. The values supplied are
+         *  already rounded down to the hardware's capabilities
+         *  (according to the entries in the `var' structure). Return
+         *  != 0 for invalid regno.
+         */
+        
+       struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+        if (regno >= info->video_cmap_len)
+                return 1;
+
+        info->palette[regno].red   = red;
+        info->palette[regno].green = green;
+        info->palette[regno].blue  = blue;
+        
+       pci_outb(info, regno, DAC_W_INDEX);
+       pci_outb(info, red,   DAC_DATA);
+       pci_outb(info, green, DAC_DATA);
+       pci_outb(info, blue,  DAC_DATA);
+
+       if (regno << 16)
+               switch (default_var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB16
+               case 16:
+                       info->fbcon_cmap.cfb16[regno] = 
+                               (regno << 10) | (regno << 5) | regno;
+                       break;
+#endif
+#ifdef FBCON_HAS_CFB24
+               case 24:
+                       info->fbcon_cmap.cfb24[regno] = 
+                               (regno << 16) | (regno << 8) | regno;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB32
+               case 32:
+                       i = (regno << 8) | regno;
+                       info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+                       break;
+#endif
+               }
+       return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *fb_info)
+{
+       struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+        if (con != info->currcon)
+                return;
+        if (fb_display[con].cmap.len)
+                fb_set_cmap(&fb_display[con].cmap, 1,
+                            iga_setcolreg, &info->fb_info);
+        else
+                fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1, 
+                           iga_setcolreg, &info->fb_info);
+}
+
+static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+                           struct fb_info *fb_info)
+{
+       struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+       
+        if (con == info->currcon) /* current console? */
+                return fb_get_cmap(cmap, kspc, iga_getcolreg, &info->fb_info);
+        else if (fb_display[con].cmap.len) /* non default colormap? */
+                fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+        else
+                fb_copy_cmap(fb_default_cmap(info->video_cmap_len),
+                     cmap, kspc ? 0 : 2);
+        return 0;
+}
+
+static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+                         struct fb_info *info)
+{
+        int err;
+       struct fb_info_iga *fb = (struct fb_info_iga*) info;
+
+        if (!fb_display[con].cmap.len) {        /* no colormap allocated? */
+                err = fb_alloc_cmap(&fb_display[con].cmap,
+                                   fb->video_cmap_len,0);
+                if (err)
+                        return err;
+        }
+        if (con == fb->currcon)                     /* current console? */
+                return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
+        else
+                fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+        return 0;
+}
+
+static int igafb_pan_display(struct fb_var_screeninfo *var, int con,
+                             struct fb_info *info)
+{
+        /* no panning */
+        return -EINVAL;
+}
+
+static int igafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+                      u_long arg, int con, struct fb_info *info)
+{
+       return -EINVAL;
+}
+
+/*
+ * Framebuffer option structure
+ */
+static struct fb_ops igafb_ops = {
+    igafb_open, 
+    igafb_release, 
+    igafb_get_fix, 
+    igafb_get_var, 
+    igafb_set_var,
+    igafb_get_cmap, 
+    igafb_set_cmap, 
+    igafb_pan_display, 
+    igafb_ioctl,
+#ifdef __sparc__
+    igafb_mmap
+#else
+    NULL
+#endif
+};
+
+static void igafb_set_disp(int con, struct fb_info_iga *info)
+{
+        struct fb_fix_screeninfo fix;
+        struct display *display;
+        struct display_switch *sw;
+        
+        if (con >= 0)
+                display = &fb_display[con];
+        else 
+                display = &info->disp;        /* used during initialization */
+
+        igafb_get_fix(&fix, con, &info->fb_info);
+
+        memset(display, 0, sizeof(struct display));
+        display->screen_base = (char*)info->frame_buffer;
+        display->visual = fix.visual;
+        display->type = fix.type;
+        display->type_aux = fix.type_aux;
+        display->ypanstep = fix.ypanstep;
+        display->ywrapstep = fix.ywrapstep;
+        display->line_length = fix.line_length;
+        display->next_line = fix.line_length;
+        display->can_soft_blank = 0; 
+        display->inverse = 0;
+        igafb_get_var(&display->var, -1, &info->fb_info);
+
+        switch (default_var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+        case 8:
+                sw = &fbcon_cfb8;
+                break;
+#endif
+#ifdef FBCON_HAS_CFB16
+        case 15:
+        case 16:
+                sw = &fbcon_cfb16;
+               display->dispsw_data = fbcon_cmap.cfb16;
+                break;
+#endif
+#ifdef FBCON_HAS_CFB24
+       case 24:
+               sw = &fbcon_cfb24;
+               display->dispsw_data = fbcon_cmap.cfb24;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB32
+        case 32:
+                sw = &fbcon_cfb32;
+               display->dispsw_data = fbcon_cmap.cfb32;
+                break;
+#endif
+        default:
+                return;
+        }
+        memcpy(&info->dispsw, sw, sizeof(*sw));
+        display->dispsw = &info->dispsw;
+
+       display->scrollmode = SCROLL_YREDRAW;
+       info->dispsw.bmove = fbcon_redraw_bmove;
+}
+
+static int igafb_switch(int con, struct fb_info *fb_info)
+{
+       struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+       
+        /* Do we have to save the colormap? */
+        if (fb_display[info->currcon].cmap.len)
+                fb_get_cmap(&fb_display[info->currcon].cmap, 1,
+                            iga_getcolreg, fb_info);
+        
+        info->currcon = con;
+        /* Install new colormap */
+        do_install_cmap(con, fb_info);
+       igafb_update_var(con, fb_info);
+        return 1;
+}
+
+
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+
+static void igafb_blank(int blank, struct fb_info *info)
+{
+        /* Not supported */
+}
+
+
+__initfunc(static int iga_init(struct fb_info_iga *info))
+{
+        char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 
+                                                        & MEM_SIZE_ALIAS;
+        switch (vramsz) {
+        case MEM_SIZE_1M:
+                info->total_vram = 0x100000;
+                break;
+        case MEM_SIZE_2M:
+                info->total_vram = 0x200000;
+                break;
+        case MEM_SIZE_4M:
+        case MEM_SIZE_RESERVED:
+                info->total_vram = 0x400000;
+                break;
+        }
+
+        if (default_var.bits_per_pixel > 8) {
+                info->video_cmap_len = 16;
+        } else {
+               int i, j;
+                for(i = 0; i < 16; i++) {
+                        j = color_table[i];
+                        info->palette[i].red   = default_red[j];
+                        info->palette[i].green = default_grn[j];
+                        info->palette[i].blue  = default_blu[j];
+                }
+                info->video_cmap_len = 256;
+        }
+
+       strcpy(info->fb_info.modename, igafb_name);
+       info->fb_info.node = -1;
+       info->fb_info.fbops = &igafb_ops;
+       info->fb_info.disp = &info->disp;
+       strcpy(info->fb_info.fontname, fontname);
+       info->fb_info.changevar = NULL;
+       info->fb_info.switch_con = &igafb_switch;
+       info->fb_info.updatevar = &igafb_update_var;
+       info->fb_info.blank = &igafb_blank;
+       info->fb_info.flags=FBINFO_FLAG_DEFAULT;
+
+       {
+               int j, k;
+               for (j = 0; j < 16; j++) {
+                       k = color_table[j];
+                       info->palette[j].red = default_red[k];
+                       info->palette[j].green = default_grn[k];
+                       info->palette[j].blue = default_blu[k];
+               }
+       }
+
+       igafb_set_disp(-1, info);
+
+       if (register_framebuffer(&info->fb_info) < 0)
+               return 0;
+
+       printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n",
+              GET_FB_IDX(info->fb_info.node), igafb_name, 
+              info->frame_buffer_phys, info->total_vram >> 20);
+
+       iga_blank_border(info); 
+       return 1;
+}      
+
+
+__initfunc(void igafb_init(void))
+{
+        struct pci_dev *pdev;
+        struct fb_info_iga *info;
+        unsigned long addr;
+        extern int con_is_present(void);
+
+        /* Do not attach when we have a serial console. */
+        if (!con_is_present())
+                return;
+
+        pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
+                               PCI_DEVICE_ID_INTERG_1682, 0);
+        if(pdev == NULL)
+                return;
+
+        info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
+        if (!info) {
+                printk("igafb_init: can't alloc fb_info_iga\n");
+                return;
+        }
+        memset(info, 0, sizeof(struct fb_info_iga));
+
+       info->frame_buffer = pdev->base_address[0];
+       if (!info->frame_buffer)
+               return;
+
+        pcibios_read_config_dword(0, pdev->devfn,
+                                  PCI_BASE_ADDRESS_0, 
+                                  (unsigned int*)&addr);
+       if (!addr)
+               return;
+       info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
+
+#ifdef __sparc__
+       
+       info->io_base_phys = info->frame_buffer_phys;
+       
+       /* Obtain virtual address and correct physical by PCIC shift */
+       info->io_base = pcic_alloc_io(&info->io_base_phys);
+       if (!info->io_base) {
+               return;
+       }
+
+       /*
+        * Figure mmap addresses from PCI config space.
+        * We need two regions: for video memory and for I/O ports.
+        * Later one can add region for video coprocessor registers.
+        * However, mmap routine loops until size != 0, so we put
+        * one additional region with size == 0. 
+        */
+
+       info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
+       if (!info->mmap_map) {
+                printk("igafb_init: can't alloc mmap_map\n");
+                kfree(info);
+               return;
+       }
+
+       memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
+
+       /*
+        * Set default vmode and cmode from PROM properties.
+        */
+       {
+                struct pcidev_cookie *cookie = pdev->sysdata;
+                int node = cookie->prom_node;
+                int width = prom_getintdefault(node, "width", 1024);
+                int height = prom_getintdefault(node, "height", 768);
+                int depth = prom_getintdefault(node, "depth", 8);
+                switch (width) {
+                    case 1024:
+                        if (height == 768)
+                            default_var = default_var_1024x768;
+                        break;
+                    case 1152:
+                        if (height == 900)
+                            default_var = default_var_1152x900;
+                        break;
+                    case 1280:
+                        if (height == 1024)
+                            default_var = default_var_1280x1024;
+                        break;
+                    default:
+                        break;
+                }
+
+                switch (depth) {
+                    case 8:
+                        default_var.bits_per_pixel = 8;
+                        break;
+                    case 16:
+                        default_var.bits_per_pixel = 16;
+                        break;
+                    case 24:
+                        default_var.bits_per_pixel = 24;
+                        break;
+                    case 32:
+                        default_var.bits_per_pixel = 32;
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+#endif
+            if (!iga_init(info)) {
+                   if (info->mmap_map)
+                           kfree(info->mmap_map);
+                   kfree(info);
+            }
+
+#ifdef __sparc__
+           /*
+            * Add /dev/fb mmap values.
+            */
+           
+           /* First region is for video memory */
+           info->mmap_map[0].voff = 0x0;  
+           info->mmap_map[0].poff = info->frame_buffer_phys & PAGE_MASK;
+           info->mmap_map[0].size = info->total_vram   & PAGE_MASK;
+           info->mmap_map[0].prot_mask = SRMMU_CACHE;
+           info->mmap_map[0].prot_flag = SRMMU_WRITE;
+
+           /* Second region is for I/O ports */
+           info->mmap_map[1].voff = info->frame_buffer_phys & PAGE_MASK;
+           info->mmap_map[1].poff = info->io_base_phys & PAGE_MASK;
+           info->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
+           info->mmap_map[1].prot_mask = SRMMU_CACHE;
+           info->mmap_map[1].prot_flag = SRMMU_WRITE;
+#endif /* __sparc__ */
+}
+
+__initfunc(void igafb_setup(char *options, int *ints))
+{
+    char *this_opt;
+
+    if (!options || !*options)
+        return;
+
+    for (this_opt = strtok(options, ","); this_opt;
+         this_opt = strtok(NULL, ",")) {
+        if (!strncmp(this_opt, "font:", 5)) {
+                char *p;
+                int i;
+
+                p = this_opt + 5;
+                for (i = 0; i < sizeof(fontname) - 1; i++)
+                        if (!*p || *p == ' ' || *p == ',')
+                                break;
+                memcpy(fontname, this_opt + 5, i);
+                fontname[i] = 0;
+        }
+    }
+}
index 105d7d7d1faa8d5fd4a1b4da71afe18e0b87f3f0..b71973a3dd8dfada9fa5bccc5268a148d229723b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  drivers/video/imsttfb.c -- frame buffer device for IMS Twin Turbo
+ *  drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
  *
  *  This file is derived from the powermac console "imstt" driver:
  *  Copyright (C) 1997 Sigurdur Asgeirsson
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/fb.h>
+#include <linux/console.h>
 #include <linux/selection.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
 #include <linux/nvram.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -55,7 +56,7 @@ enum {
        TVP = 0x01
 };
 
-/* TwinTurbo registers */
+/* TwinTurbo (Cosmo) registers */
 enum {
        S1SA    =  0, /* 0x00 */
        S2SA    =  1, /* 0x04 */
@@ -112,23 +113,70 @@ enum {
 #endif
 };
 
-/* IBM ramdac registers */
+/* IBM ramdac direct registers */
 enum {
        PADDRW  = 0x00,
        PDATA   = 0x04,
        PPMASK  = 0x08,
-       PADDRR  = 0x0C,
+       PADDRR  = 0x0c,
        PIDXLO  = 0x10, 
        PIDXHI  = 0x14, 
        PIDXDATA= 0x18,
-       PIDXCTL = 0x1C,
-
-       PPIXREP = 0x0A,
-       PM0     = 0x20,
-       PN0     = 0x21,
-       PP0     = 0x22,
-       PC0     = 0x23,
-       MCTL_3  = 0x72
+       PIDXCTL = 0x1c
+};
+
+/* IBM ramdac indirect registers */
+enum {
+       CLKCTL          = 0x02, /* (0x01) Miscellaneous Clock Control */
+       SYNCCTL         = 0x03, /* (0x00) Sync Control */
+       HSYNCPOS        = 0x04, /* (0x00) Horizontal Sync Position */
+       PWRMNGMT        = 0x05, /* (0x00) Power Management  [multiples of 4 unblack screen] */
+       DACOP           = 0x06, /* (0x02) DAC Operation  [0-3 coloured, 4-7 green, odd light, even dark] */
+       PALETCTL        = 0x07, /* (0x00) Palette Control */
+       SYSCLKCTL       = 0x08, /* (0x01) System Clock Control */
+       PIXFMT          = 0x0a, /* () Pixel Format  [bpp >> 3 + 2] */
+       BPP8            = 0x0b, /* () 8 Bits/Pixel Control */
+       BPP16           = 0x0c, /* () 16 Bits/Pixel Control  [15 or 1 for 555] */
+       BPP24           = 0x0d, /* () 24 Bits/Pixel Control */
+       BPP32           = 0x0e, /* () 32 Bits/Pixel Control */
+       PIXCTL1         = 0x10, /* (0x05) Pixel PLL Control 1  [5-7 ok] */
+       PIXCTL2         = 0x11, /* (0x00) Pixel PLL Control 2  [multiples of 20 ok] */
+       SYSCLKN         = 0x15, /* () System Clock N (System PLL Reference Divider) */
+       SYSCLKM         = 0x16, /* () System Clock M (System PLL VCO Divider) */
+       SYSCLKP         = 0x17, /* () System Clock P */
+       SYSCLKC         = 0x18, /* () System Clock C */
+       /*
+        * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
+        * c is charge pump bias which depends on the VCO frequency  
+        */
+       PIXCLKM         = 0x20, /* () Pixel Clock M */
+       PIXCLKN         = 0x21, /* () Pixel Clock N */
+       PIXCLKP         = 0x22, /* () Pixel Clock P */
+       PIXCLKC         = 0x23, /* () Pixel Clock C */
+       CURSCTL         = 0x30, /* (0x00) Cursor Control  [1=curs1, 2=curs2, 5=curs3] */
+       CURSXLO         = 0x31, /* () Cursor X position, low 8 bits */
+       CURSXHI         = 0x32, /* () Cursor X position, high 8 bits */
+       CURSYLO         = 0x33, /* () Cursor Y position, low 8 bits */
+       CURSYHI         = 0x34, /* () Cursor Y position, high 8 bits */
+       CURSHOTX        = 0x35, /* () ???  [position relative to CURSX] */
+       CURSHOTY        = 0x36, /* () ???  [position relative to CURSY] */
+       CURSACAEN       = 0x37, /* () ???  [even=cursor on, odd=cursor off] */
+       CURS1R          = 0x40, /* () Cursor 1 Red */
+       CURS1G          = 0x41, /* () Cursor 1 Green */
+       CURS1B          = 0x42, /* () Cursor 1 Blue */
+       CURS2R          = 0x43, /* () Cursor 2 Red */
+       CURS2G          = 0x44, /* () Cursor 2 Green */
+       CURS2B          = 0x45, /* () Cursor 2 Blue */
+       CURS3R          = 0x46, /* () Cursor 3 Red */
+       CURS3G          = 0x47, /* () Cursor 3 Green */
+       CURS3B          = 0x48, /* () Cursor 3 Blue */
+       BORDR           = 0x60, /* () Border Color Red */
+       BORDG           = 0x61, /* () Border Color Green */
+       BORDB           = 0x62, /* () Border Color Blue */
+       MISCTL1         = 0x70, /* (0x00) Miscellaneous Control 1 */
+       MISCTL2         = 0x71, /* (0x00) Miscellaneous Control 2 */
+       MISCTL3         = 0x72, /* (0x00) Miscellaneous Control 3 */
+       KEYCTL          = 0x78  /* (0x00) Key Control/DB Operation */
 };
 
 /* TI TVP 3030 RAMDAC Direct Registers */
@@ -191,13 +239,13 @@ struct initvalues {
 };
 
 static struct initvalues ibm_initregs[] = {
-       { 0x02, 0x21 }, /* (0x01) Miscellaneous Clock Control */
-       { 0x03, 0x00 }, /* (0x00) Sync Control */
-       { 0x04, 0x00 }, /* (0x00) Horizontal Sync Position */
-       { 0x05, 0x00 }, /* (0x00) Power Management */
-       { 0x06, 0x03 }, /* (0x02) DAC Operation */
-       { 0x07, 0x00 }, /* (0x00) Palette Control */
-       { 0x08, 0x01 }, /* (0x01) System Clock Control */
+       { CLKCTL,       0x21 },
+       { SYNCCTL,      0x00 },
+       { HSYNCPOS,     0x00 },
+       { PWRMNGMT,     0x00 },
+       { DACOP,        0x02 },
+       { PALETCTL,     0x00 },
+       { SYSCLKCTL,    0x01 },
 
        /*
         * Note that colors in X are correct only if all video data is
@@ -205,72 +253,86 @@ static struct initvalues ibm_initregs[] = {
         * color" must be configured.  This is the case for the IBM DAC
         * used in the 2MB and 4MB cards, at least.
         */
-       { 0x0b, 0x00 }, /* (U) 8 BPP Control */
-       { 0x0c, 0x00 }, /* (U) 16 BPP Control; the "1" means use 555 RGB color encoding */
-       { 0x0d, 0x00 }, /* (U) 24 BPP Packed Control */
-       { 0x0e, 0x00 }, /* (U) 32 BPP Control */
-
-       { 0x10, 0x05 }, /* (0x00) Pixel PLL Control 1 */
-       { 0x11, 0x00 }, /* (0x00) Pixel PLL Control 2 */
-       { 0x15, 0x08 }, /* (0x08) SYSCLK N (System PLL Reference Divider) */
-       { 0x16, 0x4f }, /* (0x41) SYSCLK M (System PLL VCO Divider) */
-       { 0x17, 0x00 }, /* (U) SYSCLK P */
-       { 0x18, 0x00 }, /* (U) SYSCLK C */
-       { 0x30, 0x00 }, /* (0x00) Cursor Control */
-       { 0x60, 0xff }, /* (U) Border Color Red */
-       { 0x61, 0xff }, /* (U) Border Color Green */
-       { 0x62, 0xff }, /* (U) Border Color Blue */
-       { 0x70, 0x01 }, /* (0x00) Miscellaneous Control 1 */
-       { 0x71, 0x45 }, /* (0x00) Miscellaneous Control 2 */
-       { 0x72, 0x00 }, /* (0x00) Miscellaneous Control 3 */
-       { 0x78, 0x00 }  /* (0x00) Key Control/DB Operation */
+       { BPP8,         0x00 },
+       { BPP16,        0x00 },
+       { BPP24,        0x00 },
+       { BPP32,        0x00 },
+
+       { PIXCTL1,      0x05 },
+       { PIXCTL2,      0x00 },
+       { SYSCLKN,      0x08 },
+       { SYSCLKM,      0x4f },
+       { SYSCLKP,      0x00 },
+       { SYSCLKC,      0x00 },
+       { CURSCTL,      0x00 },
+       { CURS2R,       0xff },
+       { CURS2G,       0xff },
+       { CURS2B,       0xff },
+       { BORDR,        0xff },
+       { BORDG,        0xff },
+       { BORDB,        0xff },
+       { MISCTL1,      0x01 },
+       { MISCTL2,      0x45 },
+       { MISCTL3,      0x00 },
+       { KEYCTL,       0x00 }
 };
 
 static struct initvalues tvp_initregs[] = {
-       { 0x6, 0x00 },
-       { 0x7, 0xe4 },
-       { 0xf, 0x06 },
-       { 0x18, 0x80 },
-       { 0x19, 0x4d },
-       { 0x1a, 0x05 },
-       { 0x1c, 0x00 },
-       { 0x1d, 0x00 },
-       { 0x1e, 0x08 },
-       { 0x30, 0xff },
-       { 0x31, 0xff },
-       { 0x32, 0xff },
-       { 0x33, 0xff },
-       { 0x34, 0xff },
-       { 0x35, 0xff },
-       { 0x36, 0xff },
-       { 0x37, 0xff },
-       { 0x38, 0x00 },
-       { TVPIRPLA, 0x00 },
-       { TVPIRPPD, 0xc0 },
-       { TVPIRPPD, 0xd5 },
-       { TVPIRPPD, 0xea },
-       { TVPIRPLA, 0x00 },
-       { TVPIRMPD, 0xb9 },
-       { TVPIRMPD, 0x3a },
-       { TVPIRMPD, 0xb1 },
-       { TVPIRPLA, 0x00 },
-       { TVPIRLPD, 0xc1 },
-       { TVPIRLPD, 0x3d },
-       { TVPIRLPD, 0xf3 },
+       { 0x6,  0x00 },
+       { 0x7,  0xe4 },
+       { 0xf,  0x06 },
+       { 0x18, 0x80 },
+       { 0x19, 0x4d },
+       { 0x1a, 0x05 },
+       { 0x1c, 0x00 },
+       { 0x1d, 0x00 },
+       { 0x1e, 0x08 },
+       { 0x30, 0xff },
+       { 0x31, 0xff },
+       { 0x32, 0xff },
+       { 0x33, 0xff },
+       { 0x34, 0xff },
+       { 0x35, 0xff },
+       { 0x36, 0xff },
+       { 0x37, 0xff },
+       { 0x38, 0x00 },
+       { TVPIRPLA,     0x00 },
+       { TVPIRPPD,     0xc0 },
+       { TVPIRPPD,     0xd5 },
+       { TVPIRPPD,     0xea },
+       { TVPIRPLA,     0x00 },
+       { TVPIRMPD,     0xb9 },
+       { TVPIRMPD,     0x3a },
+       { TVPIRMPD,     0xb1 },
+       { TVPIRPLA,     0x00 },
+       { TVPIRLPD,     0xc1 },
+       { TVPIRLPD,     0x3d },
+       { TVPIRLPD,     0xf3 },
+};
+
+struct imstt_regvals {
+       __u32 pitch;
+       __u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
+       __u8 pclk_m, pclk_n, pclk_p;
+       /* Values of the tvp which change depending on colormode x resolution */
+       __u8 mlc[3];    /* Memory Loop Config 0x39 */
+       __u8 lckl_p[3]; /* P value of LCKL PLL */
+};
+
+struct imstt_cursor {
+       int enable;
+       int on;
+       int vbl_cnt;
+       int blink_rate;
+       __u16 x, y;
+       struct timer_list timer;
 };
 
 struct fb_info_imstt {
        struct fb_info info;
        struct fb_fix_screeninfo fix;
        struct display disp;
-       struct {
-               __u8 red, green, blue;
-       } palette[256];
-       __u8 *frame_buffer_phys, *frame_buffer;
-       __u32 *dc_regs_phys, *dc_regs;
-       __u8 *cmap_regs_phys, *cmap_regs;
-       __u32 total_vram;
-       __u32 ramdac;
+       struct display_switch dispsw;
        union {
 #ifdef FBCON_HAS_CFB16
                __u16 cfb16[16];
@@ -282,178 +344,181 @@ struct fb_info_imstt {
                __u32 cfb32[16];
 #endif
        } fbcon_cmap;
+       struct {
+               __u8 red, green, blue;
+       } palette[256];
+       struct imstt_regvals init;
+       struct imstt_cursor cursor;
+       __u8 *frame_buffer_phys, *frame_buffer;
+       __u32 *dc_regs_phys, *dc_regs;
+       __u8 *cmap_regs_phys, *cmap_regs;
+       __u32 total_vram;
+       __u32 ramdac;
 };
 
-#define USE_NV_MODES   1
-#define INIT_BPP       8
-#define INIT_XRES      640
-#define INIT_YRES      480
+#define USE_NV_MODES           1
+#define INIT_BPP               8
+#define INIT_XRES              640
+#define INIT_YRES              480
+#define CURSOR_BLINK_RATE      20
+#define CURSOR_DRAW_DELAY      2
 
 static int currcon = 0;
 
-/*
- * for the IBM ramdac:
- * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
- * where m = clk[0], n = clk[1], p = clk[2]
- * clk[3] is c, charge pump bias which depends on the VCO frequency  
- */
-struct imstt_regvals {
-       __u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
-       __u8 pclk_m, pclk_n, pclk_p;
-       __u32 pitch;
-       /* Values of the tvp which change depending on colormode x resolution */
-       __u8 mlc[3];    /* Memory Loop Config 0x39 */
-       __u8 lckl_p[3]; /* P value of LCKL PLL */
-};
-
-/* 1600x1200, 75Hz */
-static struct imstt_regvals ibm_reg_init_1600x1200x75 = {
-       0x0018, 0x0040, 0x0108, 0x010c, 0x0003, 0x002a, 0x04da, 0x04dd, 0x04da,
-       0x09, 0x00, 0x00,
-       1600
-};
-
-/* 1280x1024, 75Hz (20) */
-static struct imstt_regvals ibm_reg_init_20 = {
-       0x0012, 0x002f, 0x00cf, 0x00d3, 0x0003, 0x0029, 0x0429, 0x042a, 0x0429,
-       0x1a, 0x03, 0x00,
-       1280
-};
-
-/* 1280x960, 75Hz (19) */
-static struct imstt_regvals ibm_reg_init_19 = {
-       0x0012, 0x0030, 0x00d0, 0x00d2, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
-       0x3e, 0x09, 0x00,
-       1280
-};
-
-/* 1152x870, 75Hz (18) */
-static struct imstt_regvals ibm_reg_init_18 = {
-       0x0012, 0x0022, 0x00b2, 0x00b6, 0x0003, 0x0031, 0x0397, 0x039a, 0x0397, 
-       0x3c, 0x0b, 0x00,
-       1152
-};
-
-/* 1024x768, 75Hz (17) */
-#if 1
-static struct imstt_regvals ibm_reg_init_17 = {
-       0x000a, 0x001c, 0x009c, 0x00a6, 0x0003, 0x0020, 0x0320, 0x0323, 0x0320, 
-       0x07, 0x00, 0x01,
-       1024
-};
-#else
-/* this almost works with a 14" apple multiple scan monitor */
-static struct imstt_regvals ibm_reg_init_17 = {
-       0x000a, 0x001d, 0x009c, 0x00ac, 0x0003, 0x0020, 0x0320, 0x0323, 0x0320, 
-       0x3e, 0x0a, 0x01,
-       1024
-};
-#endif
-
-/* 832x624, 75Hz (13) */
-static struct imstt_regvals ibm_reg_init_13 = {
-       0x0005, 0x0020, 0x0088, 0x0090, 0x0003, 0x0028, 0x0298, 0x029b, 0x0298,
-       0x3e, 0x0a, 0x01,
-       832
-};
-
-/* 640x480, 67Hz (6) */
-static struct imstt_regvals ibm_reg_init_6 = {
-       0x0008, 0x0012, 0x0062, 0x006c, 0x0003, 0x002a, 0x020a, 0x020c, 0x020a,
-       0x78, 0x13, 0x02,
-       640
-};
-
 static struct imstt_regvals tvp_reg_init_2 = {
+       512,
        0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
        0xec, 0x2a, 0xf3,
-       512,
        { 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
 };
 
 static struct imstt_regvals tvp_reg_init_6 = {
+       640,
        0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
        0xef, 0x2e, 0xb2,
-       640,
        { 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
 };
 
 static struct imstt_regvals tvp_reg_init_12 = {
+       800,
        0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
        0xf6, 0x2e, 0xf2,
-       800,
        { 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
 };
 
 static struct imstt_regvals tvp_reg_init_13 = {
+       832,
        0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
        0xfe, 0x3e, 0xf1,
-       832,
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
 };
 
 static struct imstt_regvals tvp_reg_init_17 = {
+       1024,
        0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
        0xfc, 0x3a, 0xf1,
-       1024,
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
 };
 
 static struct imstt_regvals tvp_reg_init_18 = {
+       1152,
        0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 
        0xfd, 0x3a, 0xf1,
-       1152,
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
 };
 
 static struct imstt_regvals tvp_reg_init_19 = {
+       1280,
        0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
        0xf7, 0x36, 0xf0,
-       1280,
        { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
 };
 
 static struct imstt_regvals tvp_reg_init_20 = {
+       1280,
        0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
        0xf0, 0x2d, 0xf0,
-       1280,
        { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
 };
 
+static __u32
+getclkMHz (struct fb_info_imstt *p)
+{
+       __u32 clk_m, clk_n, clk_p;
+
+       clk_m = p->init.pclk_m;
+       clk_n = p->init.pclk_n;
+       clk_p = p->init.pclk_p;
+
+       return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+}
+
+static void
+setclkMHz (struct fb_info_imstt *p, __u32 MHz)
+{
+       __u32 clk_m, clk_n, clk_p, x, stage, spilled;
+
+       clk_m = clk_n = clk_p = 0;
+       stage = spilled = 0;
+       for (;;) {
+               switch (stage) {
+                       case 0:
+                               clk_m++;
+                               break;
+                       case 1:
+                               clk_n++;
+                               break;
+               }
+               x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+               if (x == MHz)
+                       break;
+               if (x > MHz) {
+                       spilled = 1;
+                       stage = 1;
+               } else if (spilled && x < MHz) {
+                       stage = 0;
+               }
+       }
+
+       p->init.pclk_m = clk_m;
+       p->init.pclk_n = clk_n;
+       p->init.pclk_p = clk_p;
+}
+
 static struct imstt_regvals *
-compute_imstt_regvals_ibm (int xres, int yres)
+compute_imstt_regvals_ibm (struct fb_info_imstt *p, int xres, int yres)
 {
-       struct imstt_regvals *init;
+       struct imstt_regvals *init = &p->init;
+       __u32 MHz, hes, heb, veb, htp, vtp;
 
        switch (xres) {
                case 640:
-                       init = &ibm_reg_init_6;
+                       hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
+                       MHz = 30 /* .25 */ ;
                        break;
                case 832:
-                       init = &ibm_reg_init_13;
+                       hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
+                       MHz = 57 /* .27_ */ ;
                        break;
                case 1024:
-                       init = &ibm_reg_init_17;
+                       hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
+                       MHz = 80;
                        break;
                case 1152:
-                       init = &ibm_reg_init_18;
+                       hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
+                       MHz = 101 /* .6_ */ ;
                        break;
                case 1280:
-                       init = yres == 960 ? &ibm_reg_init_19 : &ibm_reg_init_20;
+                       hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
+                       MHz = yres == 960 ? 126 : 135;
                        break;
                case 1600:
-                       init = &ibm_reg_init_1600x1200x75;
+                       hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
+                       MHz = 200;
                        break;
                default:
-                       init = 0;
-                       break;
+                       return 0;
        }
 
+       setclkMHz(p, MHz);
+
+       init->hes = hes;
+       init->heb = heb;
+       init->hsb = init->heb + xres / 8;
+       init->ht = init->hsb + htp;
+       init->ves = 0x0003;
+       init->veb = veb;
+       init->vsb = init->veb + yres;
+       init->vt = init->vsb + vtp;
+       init->vil = init->vsb;
+
+       init->pitch = xres;
+
        return init;
 }
 
 static struct imstt_regvals *
-compute_imstt_regvals_tvp (int xres, int yres)
+compute_imstt_regvals_tvp (struct fb_info_imstt *p, int xres, int yres)
 {
        struct imstt_regvals *init;
 
@@ -480,46 +545,47 @@ compute_imstt_regvals_tvp (int xres, int yres)
                        init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
                        break;
                default:
-                       init = 0;
-                       break;
+                       return 0;
        }
+       p->init = *init;
 
        return init;
 }
 
 static struct imstt_regvals *
-compute_imstt_regvals (struct fb_info_imstt *p, int xres, int yres)
+compute_imstt_regvals (struct fb_info_imstt *p, u_int xres, u_int yres)
 {
        if (p->ramdac == IBM)
-               return compute_imstt_regvals_ibm(xres, yres);
+               return compute_imstt_regvals_ibm(p, xres, yres);
        else
-               return compute_imstt_regvals_tvp(xres, yres);
+               return compute_imstt_regvals_tvp(p, xres, yres);
 }
 
 static void
-set_imstt_regvals_ibm (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
+set_imstt_regvals_ibm (struct fb_info_imstt *p, u_int bpp)
 {
+       struct imstt_regvals *init = &p->init;
        __u8 pformat = (bpp >> 3) + 2;
 
        p->cmap_regs[PIDXHI] = 0;               eieio();
-       p->cmap_regs[PIDXLO] = PM0;             eieio();
+       p->cmap_regs[PIDXLO] = PIXCLKM;         eieio();
        p->cmap_regs[PIDXDATA] = init->pclk_m;  eieio();
-       p->cmap_regs[PIDXLO] = PN0;             eieio();
+       p->cmap_regs[PIDXLO] = PIXCLKN;         eieio();
        p->cmap_regs[PIDXDATA] = init->pclk_n;  eieio();
-       p->cmap_regs[PIDXLO] = PP0;             eieio();
+       p->cmap_regs[PIDXLO] = PIXCLKP;         eieio();
        p->cmap_regs[PIDXDATA] = init->pclk_p;  eieio();
-       p->cmap_regs[PIDXLO] = PC0;             eieio();
+       p->cmap_regs[PIDXLO] = PIXCLKC;         eieio();
        p->cmap_regs[PIDXDATA] = 0x02;          eieio();
 
        p->cmap_regs[PIDXHI] = 0;               eieio();
-       p->cmap_regs[PIDXLO] = PPIXREP;         eieio();
+       p->cmap_regs[PIDXLO] = PIXFMT;          eieio();
        p->cmap_regs[PIDXDATA] = pformat;       eieio();
-       p->cmap_regs[PIDXHI] = 0;               eieio();
 }
 
 static void
-set_imstt_regvals_tvp (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
+set_imstt_regvals_tvp (struct fb_info_imstt *p, u_int bpp)
 {
+       struct imstt_regvals *init = &p->init;
        __u8 tcc, mxc, lckl_n, mic;
        __u8 mlc, lckl_p;
 
@@ -583,14 +649,15 @@ set_imstt_regvals_tvp (struct fb_info_imstt *p, struct imstt_regvals *init, int
 }
 
 static void
-set_imstt_regvals (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
+set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
 {
+       struct imstt_regvals *init = &p->init;
        __u32 ctl, pitch, byteswap, scr;
 
        if (p->ramdac == IBM)
-               set_imstt_regvals_ibm(p, init, bpp);
+               set_imstt_regvals_ibm(p, bpp);
        else
-               set_imstt_regvals_tvp(p, init, bpp);
+               set_imstt_regvals_tvp(p, bpp);
 
   /*
    * From what I (jsk) can gather poking around with MacsBug,
@@ -617,7 +684,7 @@ set_imstt_regvals (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
                        break;
                case 24:
                        ctl = 0x17b9;
-                       pitch = init->pitch - (init->pitch / 4);
+                       pitch = init->pitch - (p->init.pitch / 4);
                        byteswap = 0x2;
                        break;
                case 32:
@@ -676,60 +743,161 @@ set_imstt_regvals (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
        out_le32(&p->dc_regs[STGCTL], ctl);
 }
 
-void
+static void
 set_16 (struct fb_info_imstt *p, __u8 x)
 {
        if (p->ramdac == IBM) {
                p->cmap_regs[PIDXHI] = 0;       eieio();
-               p->cmap_regs[PIDXLO] = 0x0c;    eieio();
+               p->cmap_regs[PIDXLO] = BPP16;   eieio();
                p->cmap_regs[PIDXDATA] = x;     eieio();
        } else {
                /* ?!? */
        }
 }
 
-#define set_555(_p)    set_16(_p, 15)  /* need 220 or 224 for X */
+#define set_555(_p)    set_16(_p, 15)
 #define set_565(_p)    set_16(_p, 0)   /* 220, 224 is darker in X */
 
-void
+static void
+imstt_set_cursor (struct fb_info_imstt *p, int on)
+{
+       struct imstt_cursor *c = &p->cursor;
+
+       p->cmap_regs[PIDXHI] = 0;
+       if (!on) {
+               p->cmap_regs[PIDXLO] = CURSCTL;
+               p->cmap_regs[PIDXDATA] = 0x00;
+       } else {
+               p->cmap_regs[PIDXLO] = CURSXHI;
+               p->cmap_regs[PIDXDATA] = c->x >> 8;
+               p->cmap_regs[PIDXLO] = CURSXLO;
+               p->cmap_regs[PIDXDATA] = c->x & 0xff;
+               p->cmap_regs[PIDXLO] = CURSYHI;
+               p->cmap_regs[PIDXDATA] = c->y >> 8;
+               p->cmap_regs[PIDXLO] = CURSYLO;
+               p->cmap_regs[PIDXDATA] = c->y & 0xff;
+               p->cmap_regs[PIDXLO] = CURSCTL;
+               p->cmap_regs[PIDXDATA] = 0x02;
+       }
+}
+
+static void
+imsttfb_cursor (struct display *disp, int mode, int x, int y)
+{
+       struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+       struct imstt_cursor *c = &p->cursor;
+
+       x *= fontwidth(disp);
+       y *= fontheight(disp);
+
+       if (c->x == x && c->y == y && (mode == CM_ERASE) == !c->enable)
+               return;
+
+       c->enable = 0;
+       if (c->on)
+               imstt_set_cursor(p, 0);
+       c->x = x;
+       c->y = y;
+
+       switch (mode) {
+               case CM_ERASE:
+                       c->on = 0;
+                       break;
+               case CM_DRAW:
+               case CM_MOVE:
+                       if (c->on)
+                               imstt_set_cursor(p, c->on);
+                       else
+                               c->vbl_cnt = CURSOR_DRAW_DELAY;
+                       c->enable = 1;
+                       break;
+       }
+}
+
+static int
+imsttfb_set_font (struct display *disp, int width, int height)
+{
+       return 1;
+}
+
+static void
+imstt_cursor_timer_handler (unsigned long dev_addr)
+{
+       struct fb_info_imstt *p = (struct fb_info_imstt *)dev_addr;
+       struct imstt_cursor *c = &p->cursor;
+
+       if (!c->enable)
+               goto out;
+
+       if (c->vbl_cnt && --c->vbl_cnt == 0) {
+               c->on ^= 1;
+               imstt_set_cursor(p, c->on);
+               c->vbl_cnt = c->blink_rate;
+       }
+
+out:
+       c->timer.expires = jiffies + (HZ / 50);
+       add_timer(&c->timer);
+}
+
+__initfunc(static void
+imstt_cursor_init (struct fb_info_imstt *p))
+{
+       struct imstt_cursor *c = &p->cursor;
+
+       c->enable = 1;
+       c->on = 1;
+       c->blink_rate = CURSOR_BLINK_RATE;
+       c->vbl_cnt = CURSOR_DRAW_DELAY;
+       c->x = c->y = 0;
+
+       init_timer(&c->timer);
+       c->timer.expires = jiffies + (HZ / 50);
+       c->timer.data = (unsigned long)p;
+       c->timer.function = imstt_cursor_timer_handler;
+       add_timer(&c->timer);
+}
+
+static void
 imsttfb_rectcopy (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
 {
        struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
-       __u32 tmp, cnt_reg;
+       __u32 cnt_reg, stat, xxx = 0;
        __u32   line_pitch = disp->var.xres * (disp->var.bits_per_pixel >> 3),
                rect_height = height,
                rect_width = width * (disp->var.bits_per_pixel >> 3),
                fb_offset_old = sy * line_pitch + (sx * (disp->var.bits_per_pixel >> 3)),
                fb_offset_new = dy * line_pitch + (dx * (disp->var.bits_per_pixel >> 3));
 
+       stat = in_le32(&p->dc_regs[SSTATUS]) & 0xff;
+
        cnt_reg = ((rect_height - 1) << 16) | (rect_width - 1);
+       out_le32(&p->dc_regs[CNT], cnt_reg);
+       out_le32(&p->dc_regs[S1SA], fb_offset_old);
+       out_le32(&p->dc_regs[DSA], fb_offset_old);
+       out_le32(&p->dc_regs[SP], line_pitch);
+       out_le32(&p->dc_regs[DP_OCTRL], line_pitch);
+       out_le32(&p->dc_regs[BLTCTL], 0x5);
 
-       tmp = (line_pitch << 16) | line_pitch;
-       out_le32(&p->dc_regs[SP], tmp);
-       tmp = line_pitch;
-       out_le32(&p->dc_regs[DP_OCTRL], tmp);
-#if 0
-       do {
-               tmp = in_le32(&p->dc_regs[SSTATUS]);
+       if (++stat == 0x20)
+               stat = 0x10;
+       while ((in_le32(&p->dc_regs[SSTATUS]) & 0xff) != stat && xxx++ < 0xff)
                eieio();
-       } while (tmp & 0x80);
-#endif
+
+       cnt_reg = ((rect_height - 1) << 16) | (0xffff - (rect_width - 2));
        out_le32(&p->dc_regs[CNT], cnt_reg);
-       out_le32(&p->dc_regs[S1SA], fb_offset_old);
-       out_le32(&p->dc_regs[S2SA], fb_offset_new);
        out_le32(&p->dc_regs[DSA], fb_offset_new);
-       out_le32(&p->dc_regs[BLTCTL], 0x5);
 #if 0
-       do {
-               tmp = in_le32(&p->dc_regs[SSTATUS]);
-               eieio();
-       } while (tmp & 0x80);
+       out_le32(&p->dc_regs[S1SA], fb_offset_old);
+       out_le32(&p->dc_regs[SP], line_pitch);
+       out_le32(&p->dc_regs[DP_OCTRL], line_pitch);
+#endif
+       out_le32(&p->dc_regs[BLTCTL], 0x85);
 
-       do {
-               tmp = in_le32(&p->dc_regs[SSTATUS]);
+       if (++stat == 0x20)
+               stat = 0x10;
+       while ((in_le32(&p->dc_regs[SSTATUS]) & 0xff) != stat && xxx++ < 0xff)
                eieio();
-       } while (tmp & 0x40);
-#endif
 }
 
 static void
@@ -745,29 +913,34 @@ imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int heig
        imsttfb_rectcopy(disp, sy, sx, dy, dx, height, width);
 }
 
+#ifdef FBCON_HAS_CFB8
 static struct display_switch fbcon_imstt8 = {
        fbcon_cfb8_setup, imsttfbcon_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
        fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
        FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
-
+#endif
+#ifdef FBCON_HAS_CFB16
 static struct display_switch fbcon_imstt16 = {
        fbcon_cfb16_setup, imsttfbcon_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
        fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
        FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
-
+#endif
+#ifdef FBCON_HAS_CFB24
 static struct display_switch fbcon_imstt24 = {
        fbcon_cfb24_setup, imsttfbcon_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
        fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
        FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
-
+#endif
+#ifdef FBCON_HAS_CFB32
 static struct display_switch fbcon_imstt32 = {
        fbcon_cfb32_setup, imsttfbcon_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
        fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
        FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
+#endif
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
 #include <asm/vc_ioctl.h>
@@ -832,8 +1005,8 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
                   u_int transp, struct fb_info *info)
 {
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
-       unsigned int bpp = fb_display[currcon].var.bits_per_pixel;
-       unsigned int i;
+       u_int bpp = fb_display[currcon].var.bits_per_pixel;
+       u_int i;
 
        if (regno > 255)
                return 1;
@@ -847,7 +1020,7 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
        p->palette[regno].blue = blue;
 
        /* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
-       if (fb_display[currcon].var.green.length == 5 /* && bpp == 16 */ && p->ramdac == TVP) {
+       if (p->ramdac == TVP && fb_display[currcon].var.green.length == 5 /* && bpp == 16 */) {
                p->cmap_regs[PADDRW] = regno << 3;      eieio();
        } else {
                p->cmap_regs[PADDRW] = regno;           eieio();
@@ -885,7 +1058,7 @@ do_install_cmap (int con, struct fb_info *info)
        if (fb_display[con].cmap.len)
                fb_set_cmap(&fb_display[con].cmap, 1, imsttfb_setcolreg, info);
        else {
-               int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+               u_int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
                fb_set_cmap(fb_default_cmap(size), 1, imsttfb_setcolreg, info);
        }
 }
@@ -926,13 +1099,88 @@ imsttfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
        return 0;
 }
 
+static void
+set_dispsw (struct display *disp, struct fb_info_imstt *p)
+{
+       u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+       disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+                                                    : FB_VISUAL_DIRECTCOLOR;
+       p->dispsw = fbcon_dummy;
+       disp->dispsw = &p->dispsw;
+       disp->dispsw_data = 0;
+       switch (disp->var.bits_per_pixel) {
+               case 8:
+                       disp->var.red.offset = 0;
+                       disp->var.red.length = 8;
+                       disp->var.green.offset = 0;
+                       disp->var.green.length = 8;
+                       disp->var.blue.offset = 0;
+                       disp->var.blue.length = 8;
+                       disp->var.transp.offset = 0;
+                       disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB8
+                       p->dispsw = accel ? fbcon_imstt8 : fbcon_cfb8;
+#endif
+                       break;
+               case 16:        /* RGB 555 */
+                       if (disp->var.red.offset != 11)
+                               disp->var.red.offset = 10;
+                       disp->var.red.length = 5;
+                       disp->var.green.offset = 5;
+                       if (disp->var.green.length != 6)
+                               disp->var.green.length = 5;
+                       disp->var.blue.offset = 0;
+                       disp->var.blue.length = 5;
+                       disp->var.transp.offset = 0;
+                       disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB16
+                       p->dispsw = accel ? fbcon_imstt16 : fbcon_cfb16;
+                       disp->dispsw_data = p->fbcon_cmap.cfb16;
+#endif
+                       break;
+               case 24:        /* RGB 888 */
+                       disp->var.red.offset = 16;
+                       disp->var.red.length = 8;
+                       disp->var.green.offset = 8;
+                       disp->var.green.length = 8;
+                       disp->var.blue.offset = 0;
+                       disp->var.blue.length = 8;
+                       disp->var.transp.offset = 0;
+                       disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB24
+                       p->dispsw = accel ? fbcon_imstt24 : fbcon_cfb24;
+                       disp->dispsw_data = p->fbcon_cmap.cfb24;
+#endif
+                       break;
+               case 32:        /* RGBA 8888 */
+                       disp->var.red.offset = 16;
+                       disp->var.red.length = 8;
+                       disp->var.green.offset = 8;
+                       disp->var.green.length = 8;
+                       disp->var.blue.offset = 0;
+                       disp->var.blue.length = 8;
+                       disp->var.transp.offset = 24;
+                       disp->var.transp.length = 8;
+#ifdef FBCON_HAS_CFB32
+                       p->dispsw = accel ? fbcon_imstt32 : fbcon_cfb32;
+                       disp->dispsw_data = p->fbcon_cmap.cfb32;
+#endif
+                       break;
+       }
+
+       if (p->ramdac == IBM) {
+               p->dispsw.cursor = imsttfb_cursor;
+               p->dispsw.set_font = imsttfb_set_font;
+       }
+}
+
 static int
 imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
        struct display *disp;
-       unsigned int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
-       struct imstt_regvals *init;
+       u_int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
 
        disp = &fb_display[con];
 
@@ -950,8 +1198,7 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
        if (!((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW))
                return 0;
 
-       init = compute_imstt_regvals(p, var->xres, var->yres);
-       if (!init)
+       if (!compute_imstt_regvals(p, var->xres, var->yres))
                return -EINVAL;
 
        oldbpp = disp->var.bits_per_pixel;
@@ -970,7 +1217,6 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
        disp->var.height = -1;
        disp->var.width = -1;
        disp->var.vmode = FB_VMODE_NONINTERLACED;
-       disp->var.pixclock = 10000;
        disp->var.left_margin = disp->var.right_margin = 16;
        disp->var.upper_margin = disp->var.lower_margin = 16;
        disp->var.hsync_len = disp->var.vsync_len = 8;
@@ -981,73 +1227,8 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
        disp->ywrapstep = 0;
        disp->scrollmode = SCROLL_YREDRAW;
 
-       if (oldbpp != disp->var.bits_per_pixel || oldaccel != disp->var.accel_flags) {
-               unsigned int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
-
-               disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
-                                                            : FB_VISUAL_DIRECTCOLOR;
-               disp->dispsw = &fbcon_dummy;
-               disp->dispsw_data = 0;
-               switch (disp->var.bits_per_pixel) {
-                       case 8:
-                               disp->var.red.offset = 0;
-                               disp->var.red.length = 8;
-                               disp->var.green.offset = 0;
-                               disp->var.green.length = 8;
-                               disp->var.blue.offset = 0;
-                               disp->var.blue.length = 8;
-                               disp->var.transp.offset = 0;
-                               disp->var.transp.length = 0;
-#ifdef FBCON_HAS_CFB8
-                               disp->dispsw = accel ? &fbcon_imstt8 : &fbcon_cfb8;
-#endif
-                               break;
-                       case 16:        /* RGB 565 */
-                               if (disp->var.red.offset != 10 && disp->var.red.offset != 11)
-                                       disp->var.red.offset = 10;
-                               disp->var.red.length = 5;
-                               disp->var.green.offset = 5;
-                               if (disp->var.green.length != 5 && disp->var.green.length != 6)
-                                       disp->var.green.length = 5;
-                               disp->var.blue.offset = 0;
-                               disp->var.blue.length = 5;
-                               disp->var.transp.offset = 0;
-                               disp->var.transp.length = 0;
-#ifdef FBCON_HAS_CFB16
-                               disp->dispsw = accel ? &fbcon_imstt16 : &fbcon_cfb16;
-                               disp->dispsw_data = p->fbcon_cmap.cfb16;
-#endif
-                               break;
-                       case 24:        /* RGB 888 */
-                               disp->var.red.offset = 16;
-                               disp->var.red.length = 8;
-                               disp->var.green.offset = 8;
-                               disp->var.green.length = 8;
-                               disp->var.blue.offset = 0;
-                               disp->var.blue.length = 8;
-                               disp->var.transp.offset = 0;
-                               disp->var.transp.length = 0;
-#ifdef FBCON_HAS_CFB24
-                               disp->dispsw = accel ? &fbcon_imstt24 : &fbcon_cfb24;
-                               disp->dispsw_data = p->fbcon_cmap.cfb24;
-#endif
-                               break;
-                       case 32:        /* RGBA 8888 */
-                               disp->var.red.offset = 16;
-                               disp->var.red.length = 8;
-                               disp->var.green.offset = 8;
-                               disp->var.green.length = 8;
-                               disp->var.blue.offset = 0;
-                               disp->var.blue.length = 8;
-                               disp->var.transp.offset = 24;
-                               disp->var.transp.length = 8;
-#ifdef FBCON_HAS_CFB32
-                               disp->dispsw = accel ? &fbcon_imstt32 : &fbcon_cfb32;
-                               disp->dispsw_data = p->fbcon_cmap.cfb32;
-#endif
-                               break;
-               }
-       }
+       if (oldbpp != disp->var.bits_per_pixel || oldgreenlen != disp->var.green.length || oldaccel != disp->var.accel_flags)
+               set_dispsw(disp, p);
 
        if (oldxres != disp->var.xres || oldbpp != disp->var.bits_per_pixel)
                disp->line_length = disp->var.xres * (disp->var.bits_per_pixel >> 3);
@@ -1067,9 +1248,11 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
                                set_555(p);
                }
                if (oldxres != disp->var.xres || oldyres != disp->var.yres || oldbpp != disp->var.bits_per_pixel)
-                       set_imstt_regvals(p, init, disp->var.bits_per_pixel);
+                       set_imstt_regvals(p, disp->var.bits_per_pixel);
                        
        }
+       disp->var.pixclock = 1000000 / getclkMHz(p);
+
        if (oldbpp != disp->var.bits_per_pixel) {
                int err = fb_alloc_cmap(&disp->cmap, 0, 0);
                if (err)
@@ -1084,7 +1267,7 @@ static int
 imsttfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
-       unsigned int off;
+       u_int off;
 
        if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
            || var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
@@ -1109,7 +1292,7 @@ imsttfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
        else if (fb_display[con].cmap.len)      /* non default colormap? */
                fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
        else {
-               int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+               u_int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
                fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
        }
 
@@ -1165,12 +1348,12 @@ imsttfb_ioctl (struct inode *inode, struct file *file, u_int cmd,
                case FBIMSTT_SETCMAPREG:
                        if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
                                return -EFAULT;
-                       out_le32(&((unsigned int *)p->cmap_regs)[reg[0]], reg[1]);
+                       out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]);
                        break;
                case FBIMSTT_GETCMAPREG:
                        if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
                                return -EFAULT;
-                       reg[1] = in_le32(&((unsigned int *)p->cmap_regs)[reg[0]]);
+                       reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]);
                        if (copy_to_user((void *)(arg + 4), &reg[1], 4))
                                return -EFAULT;
                        break;
@@ -1212,28 +1395,36 @@ static struct fb_ops imsttfb_ops = {
 static int
 imsttfbcon_switch (int con, struct fb_info *info)
 {
+       struct fb_info_imstt *p = (struct fb_info_imstt *)info;
        struct display *old = &fb_display[currcon], *new = &fb_display[con];
 
+       if (old->cmap.len)
+               fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
+       
+       if (p->ramdac == IBM)
+               imsttfb_cursor(old, CM_ERASE, p->cursor.x, p->cursor.y);
+
+       currcon = con;
+
        if (old->var.xres != new->var.xres
            || old->var.yres != new->var.yres
-           || old->var.bits_per_pixel != new->var.bits_per_pixel) {
-               struct fb_info_imstt *p = (struct fb_info_imstt *)info;
-               struct imstt_regvals *init = compute_imstt_regvals(p, new->var.xres, new->var.yres);
-               if (!init) /* ?!? */ return -1;
+           || old->var.bits_per_pixel != new->var.bits_per_pixel
+           || old->var.green.length != new->var.green.length) {
+               set_dispsw(new, p);
+               if (!compute_imstt_regvals(p, new->var.xres, new->var.yres))
+                       return -1;
                if (new->var.bits_per_pixel == 16) {
                        if (new->var.green.length == 6)
                                set_565(p);
                        else
                                set_555(p);
                }
-               set_imstt_regvals(p, init, new->var.bits_per_pixel);
+               set_imstt_regvals(p, new->var.bits_per_pixel);
 #ifdef CONFIG_FB_COMPAT_XPMAC
                set_display_info(new);
 #endif
        }
-       if (old->cmap.len)
-               fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
-       currcon = con;
+
        do_install_cmap(con, info);
 
        return 0;
@@ -1243,7 +1434,7 @@ static int
 imsttfbcon_updatevar (int con, struct fb_info *info)
 {
        struct fb_info_imstt *p = (struct fb_info_imstt *)info;
-       unsigned int off;
+       u_int off;
 
        if (con == currcon) {
                off = fb_display[con].var.yoffset * (fb_display[con].line_length / 8)
@@ -1264,7 +1455,7 @@ imsttfbcon_blank (int blank, struct fb_info *info)
        if (blank > 0) {
                switch (blank - 1) {
                        case VESA_NO_BLANKING:
-                               ctrl &= ~0x000000f0;
+                               ctrl &= ~0x00000380;
                                break;
                        case VESA_VSYNC_SUSPEND:
                                ctrl &= ~0x00000020;
@@ -1273,23 +1464,19 @@ imsttfbcon_blank (int blank, struct fb_info *info)
                                ctrl &= ~0x00000010;
                                break;
                        case VESA_POWERDOWN:
-                               ctrl &= ~0x000000f0;
+                               ctrl &= ~0x00000380;
                                break;
                }
        } else {
-               ctrl |= p->ramdac == IBM ? 0x000000b0 : 0x00000080;
+               ctrl |= p->ramdac == IBM ? 0x000017b0 : 0x00001780;
        }
        out_le32(&p->dc_regs[STGCTL], ctrl);
 }
 
-__initfunc(static void init_imstt(struct fb_info_imstt *p))
+__initfunc(static void
+init_imstt(struct fb_info_imstt *p))
 {
        __u32 i, tmp;
-       struct imstt_regvals *init;
-       unsigned int accel;
-
-       tmp = in_le32(&p->dc_regs[SSTATUS]);
-       /* printk("chip version %ld, ", (tmp & 0x0F00) >> 8); */
 
        tmp = in_le32(&p->dc_regs[PRC]);
        if (p->ramdac == IBM)
@@ -1318,7 +1505,7 @@ __initfunc(static void init_imstt(struct fb_info_imstt *p))
                }
        }
 
-#if USE_NV_MODES && (defined(CONFIG_PMAC) || defined(CONFIG_CHRP))
+#if USE_NV_MODES && defined(CONFIG_PPC)
        {
                int vmode, cmode;
 
@@ -1342,75 +1529,14 @@ __initfunc(static void init_imstt(struct fb_info_imstt *p))
 
        p->disp.var.height = p->disp.var.width = -1;
        p->disp.var.vmode = FB_VMODE_NONINTERLACED;
-       p->disp.var.pixclock = 10000;
        p->disp.var.left_margin = p->disp.var.right_margin = 16;
        p->disp.var.upper_margin = p->disp.var.lower_margin = 16;
        p->disp.var.hsync_len = p->disp.var.vsync_len = 8;
        p->disp.var.accel_flags = 0; /* FB_ACCELF_TEXT; */
 
-       accel = p->disp.var.accel_flags & FB_ACCELF_TEXT;
-
-       p->disp.dispsw = &fbcon_dummy;
-       p->disp.dispsw_data = 0;
-       switch (p->disp.var.bits_per_pixel) {
-               case 8:
-                       p->disp.var.red.offset = 0;
-                       p->disp.var.red.length = 8;
-                       p->disp.var.green.offset = 0;
-                       p->disp.var.green.length = 8;
-                       p->disp.var.blue.offset = 0;
-                       p->disp.var.blue.length = 8;
-                       p->disp.var.transp.offset = 0;
-                       p->disp.var.transp.length = 0;
-#ifdef FBCON_HAS_CFB8
-                       p->disp.dispsw = accel ? &fbcon_imstt8 : &fbcon_cfb8;
-#endif
-                       break;
-               case 16:        /* RGB 565 */
-                       if (p->disp.var.red.offset != 10 && p->disp.var.red.offset != 11)
-                               p->disp.var.red.offset = 10;
-                       p->disp.var.red.length = 5;
-                       p->disp.var.green.offset = 5;
-                       if (p->disp.var.green.length != 5 && p->disp.var.green.length != 6)
-                               p->disp.var.green.length = 5;
-                       p->disp.var.blue.offset = 0;
-                       p->disp.var.blue.length = 5;
-                       p->disp.var.transp.offset = 0;
-                       p->disp.var.transp.length = 0;
-#ifdef FBCON_HAS_CFB16
-                       p->disp.dispsw = accel ? &fbcon_imstt16 : &fbcon_cfb16;
-                       p->disp.dispsw_data = p->fbcon_cmap.cfb16;
-#endif
-                       break;
-               case 24:        /* RGB 888 */
-                       p->disp.var.red.offset = 16;
-                       p->disp.var.red.length = 8;
-                       p->disp.var.green.offset = 8;
-                       p->disp.var.green.length = 8;
-                       p->disp.var.blue.offset = 0;
-                       p->disp.var.blue.length = 8;
-                       p->disp.var.transp.offset = 0;
-                       p->disp.var.transp.length = 0;
-#ifdef FBCON_HAS_CFB24
-                       p->disp.dispsw = accel ? &fbcon_imstt24 : &fbcon_cfb24;
-                       p->disp.dispsw_data = p->fbcon_cmap.cfb24;
-#endif
-                       break;
-               case 32:        /* RGBA 8888 */
-                       p->disp.var.red.offset = 16;
-                       p->disp.var.red.length = 8;
-                       p->disp.var.green.offset = 8;
-                       p->disp.var.green.length = 8;
-                       p->disp.var.blue.offset = 0;
-                       p->disp.var.blue.length = 8;
-                       p->disp.var.transp.offset = 24;
-                       p->disp.var.transp.length = 8;
-#ifdef FBCON_HAS_CFB32
-                       p->disp.dispsw = accel ? &fbcon_imstt32 : &fbcon_cfb32;
-                       p->disp.dispsw_data = p->fbcon_cmap.cfb32;
-#endif
-                       break;
-       }
+       set_dispsw(&p->disp, p);
+       if (p->ramdac == IBM)
+               imstt_cursor_init(p);
 
        if (p->disp.var.green.length == 6)
                set_565(p);
@@ -1418,13 +1544,15 @@ __initfunc(static void init_imstt(struct fb_info_imstt *p))
                set_555(p);
 
        if ((p->disp.var.xres * p->disp.var.yres) * (p->disp.var.bits_per_pixel >> 3) > p->total_vram
-           || !(init = compute_imstt_regvals(p, p->disp.var.xres, p->disp.var.yres))) {
-               printk("imsttfb: %dx%dx%d not supported\n", p->disp.var.xres, p->disp.var.yres, p->disp.var.bits_per_pixel);
+           || !(compute_imstt_regvals(p, p->disp.var.xres, p->disp.var.yres))) {
+               printk("imsttfb: %ux%ux%u not supported\n", p->disp.var.xres, p->disp.var.yres, p->disp.var.bits_per_pixel);
                kfree(p);
                return;
        }
 
-       set_imstt_regvals(p, init, p->disp.var.bits_per_pixel);
+       set_imstt_regvals(p, p->disp.var.bits_per_pixel);
+
+       p->disp.var.pixclock = 1000000 / getclkMHz(p);
 
        sprintf(p->fix.id, "IMS TT (%s)", p->ramdac == IBM ? "IBM" : "TVP");
        p->fix.smem_start = (__u8 *)p->frame_buffer_phys;
@@ -1462,7 +1590,7 @@ __initfunc(static void init_imstt(struct fb_info_imstt *p))
        p->info.flags = FBINFO_FLAG_DEFAULT;
 
        for (i = 0; i < 16; i++) {
-               unsigned int j = color_table[i];
+               u_int j = color_table[i];
                p->palette[i].red = default_red[j];
                p->palette[i].green = default_grn[j];
                p->palette[i].blue = default_blu[j];
@@ -1473,8 +1601,9 @@ __initfunc(static void init_imstt(struct fb_info_imstt *p))
                return;
        }
 
-       printk("fb%d: %s frame buffer; %uMB vram\n",
-               GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20);
+       tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
+       printk("fb%d: %s frame buffer; %uMB vram; chip version %u\n",
+               GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20, tmp);
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
        strncpy(display_info.name, p->fix.id, sizeof display_info.name);
@@ -1483,11 +1612,14 @@ __initfunc(static void init_imstt(struct fb_info_imstt *p))
        display_info.cmap_data_address = (__u32)&p->cmap_regs_phys[PDATA];
        display_info.disp_reg_address = 0;
        set_display_info(&p->disp);
-       console_fb_info = &p->info;
+       if (!console_fb_info)
+               console_fb_info = &p->info;
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
-__initfunc(void imsttfb_of_init(struct device_node *dp))
+#if defined(CONFIG_FB_OF) || defined(CONFIG_PPC)
+__initfunc(void
+imsttfb_of_init(struct device_node *dp))
 {
        struct fb_info_imstt *p;
        int i;
@@ -1530,19 +1662,27 @@ __initfunc(void imsttfb_of_init(struct device_node *dp))
 
        init_imstt(p);
 }
+#endif
 
-__initfunc(void imsttfb_init(void))
+__initfunc(void
+imsttfb_init(void))
 {
-       unsigned int i;
+#if defined(CONFIG_PPC)
+       u_int i;
        struct device_node *dp;
        char *names[4] = {"IMS,tt128mb","IMS,tt128mbA","IMS,tt128mb8","IMS,tt128mb8A"};
 
+#ifdef CONFIG_FB_OF
        if (prom_num_displays)
                return;
+#endif
 
        for (i = 0; i < 4; i++) {
                dp = find_devices(names[i]);
                if (dp)
                        imsttfb_of_init(dp);
        }
+#else
+       /* ... */
+#endif
 }
index 103caefa32a65206f00887c1dd8b537fd1999f65..3810ab115414f9fc0798f8fa8fdc8647b47fd987 100644 (file)
@@ -734,7 +734,7 @@ static void refill_freelist(int size)
        needed = bdf_prm.b_un.nrefill * size;  
 
        while ((nr_free_pages > freepages.min*2) &&
-               (buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.max_percent * num_physpages) &&
+               !buffer_over_max() &&
                grow_buffers(GFP_BUFFER, size)) {
                obtained += PAGE_SIZE;
                if (obtained >= needed)
index b92e3efe97b5d47b6e5f074438de88c6a47b316e..698eb9718ad66baa35cee21576f258af24ef56bc 100644 (file)
@@ -86,11 +86,12 @@ static int read_block_bitmap (struct super_block * sb,
 {
        struct ext2_group_desc * gdp;
        struct buffer_head * bh = NULL;
-       int retval = 0;
+       int retval = -EIO;
        
        gdp = ext2_get_group_desc (sb, block_group, NULL);
        if (!gdp)
                goto error_out;
+       retval = 0;
        bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_block_bitmap), sb->s_blocksize);
        if (!bh) {
                ext2_error (sb, "read_block_bitmap",
index ddf72ec4cc0cfb2ac34b9d71f6591113fc135cc8..4621e02f5a7c9f2a75e7c09d0ef8bad398907445 100644 (file)
@@ -257,7 +257,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                                ext2_debug ("creating next block\n");
 
                                de = (struct ext2_dir_entry_2 *) bh->b_data;
-                               de->inode = le32_to_cpu(0);
+                               de->inode = 0;
                                de->rec_len = le16_to_cpu(sb->s_blocksize);
                                dir->i_size = offset + sb->s_blocksize;
                                dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
@@ -291,7 +291,7 @@ static struct buffer_head * ext2_add_entry (struct inode * dir,
                                de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
                                de = de1;
                        }
-                       de->inode = cpu_to_le32(0);
+                       de->inode = 0;
                        de->name_len = namelen;
                        de->file_type = 0;
                        memcpy (de->name, name, namelen);
@@ -344,7 +344,8 @@ static int ext2_delete_entry (struct ext2_dir_entry_2 * dir,
                                pde->rec_len =
                                        cpu_to_le16(le16_to_cpu(pde->rec_len) +
                                                    le16_to_cpu(dir->rec_len));
-                       dir->inode = le32_to_cpu(0);
+                       else
+                               dir->inode = 0;
                        return 0;
                }
                i += le16_to_cpu(de->rec_len);
index ad70f7b552fc7cea33c3d40716d389ed7c877762..aeb30f2b93907c1d98d7a85e5a5d36ce25a43b14 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/lockd/lockd.h>
+#include <linux/smp_lock.h>
 
 #define NLMDBG_FACILITY                NLMDBG_CIENT
 
@@ -167,6 +168,7 @@ reclaimer(void *ptr)
 
        /* This one ensures that our parent doesn't terminate while the
         * reclaim is in progress */
+       lock_kernel();
        lockd_up();
 
        /* First, reclaim all locks that have been granted previously. */
@@ -198,6 +200,7 @@ reclaimer(void *ptr)
        /* Release host handle after use */
        nlm_release_host(host);
        lockd_down();
+       unlock_kernel();
 
        return 0;
 }
index c30e6252fd3d1b0ba0ef3587a84bc9a2de53c647..7cc566da1b41ad6a5e240d1ce35dae8ac4670daf 100644 (file)
@@ -460,7 +460,6 @@ no_inode:
                        break;
                if (flags & LOOKUP_SLASHOK)
                        goto return_base;
-               dentry = ERR_PTR(-ENOTDIR);
                break;
        }
        dput(base);
@@ -536,6 +535,18 @@ static inline struct dentry *lock_parent(struct dentry *dentry)
        return dir;
 }
 
+/* 
+ * Special case: O_CREAT|O_EXCL on a dangling symlink should
+ * give EEXIST for security reasons.  While inconsistent, this
+ * is the same scheme used by, for example, Solaris 2.5.1.  --KAB
+ *
+ * O_DIRECTORY translates into forcing a directory lookup.
+ */
+#define no_follow(f)   (((f) & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+#define opendir(f)     ((f) & O_DIRECTORY)
+#define lookup_flags(f)        \
+       (no_follow(f) ? 0 : opendir(f) ? (LOOKUP_FOLLOW | LOOKUP_DIRECTORY) : LOOKUP_FOLLOW)
+
 /*
  *     open_namei()
  *
@@ -558,13 +569,7 @@ struct dentry * open_namei(const char * pathname, int flag, int mode)
        mode &= S_IALLUGO & ~current->fs->umask;
        mode |= S_IFREG;
 
-       /* 
-        * Special case: O_CREAT|O_EXCL on a dangling symlink should
-        * give EEXIST for security reasons.  While inconsistent, this
-        * is the same scheme used by, for example, Solaris 2.5.1.  --KAB
-        */
-       dentry = lookup_dentry(pathname, NULL,
-                              (flag & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL));
+       dentry = lookup_dentry(pathname, NULL, lookup_flags(flag));
        if (IS_ERR(dentry))
                return dentry;
 
index 7c6a64e0da8b5c96a30ff36a66e6487076918115..8b53cb88392d5b4df59aeeefc67fba083c7367b5 100644 (file)
@@ -9,7 +9,7 @@
 #include "struct.h"
 #include "attr.h"
 
-#include <errno.h>
+#include <linux/errno.h>
 #include "macros.h"
 #include "support.h"
 #include "util.h"
index c626035aa47889340c4d2741e021db794a52ad74..ee995c046f7b2e06513175ec4045f0ea78506891 100644 (file)
@@ -8,7 +8,7 @@
 #include "struct.h"
 #include "dir.h"
 
-#include <errno.h>
+#include <linux/errno.h>
 #include "super.h"
 #include "inode.h"
 #include "attr.h"
index 05c5a047bbc63a732d9847d04e96e0169a570b97..4d2ae30c3404443d463d91503ff294790380ebf3 100644 (file)
@@ -10,7 +10,7 @@
 #include "struct.h"
 #include "inode.h"
 
-#include <errno.h>
+#include <linux/errno.h>
 #include "macros.h"
 #include "attr.h"
 #include "super.h"
index 7c7b005d3829539b05d0c37d33aa42ee028b2cb9..be1aedbea0f7289145571689c66fecc75f3ccc86 100644 (file)
@@ -9,7 +9,7 @@
 #include "struct.h"
 #include "super.h"
 
-#include <errno.h>
+#include <linux/errno.h>
 #include "macros.h"
 #include "inode.h"
 #include "support.h"
index 0cd5561779aef1280bcbd906e907771579f57d29..4c5d456a7f6248558c82fb95bf3d8c880a257ef4 100644 (file)
@@ -12,7 +12,7 @@
 #include "struct.h"
 #include "util.h"
 
-#include <errno.h>
+#include <linux/errno.h>
 /* FreeBSD doesn't seem to have EILSEQ in errno.h */
 #ifndef EILSEQ
 # define EILSEQ        EINVAL
index 6a6ef687e9b44ecb54b17146a32f14211e7fcb4e..5537a35e6a4689bcbfb8fee11e4567541bafb252 100644 (file)
@@ -13,7 +13,9 @@ extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
 extern struct inode_operations proc_scsi_inode_operations;
 extern struct proc_dir_entry proc_sys_root;
 
+#ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(proc_sys_root);
+#endif
 EXPORT_SYMBOL(proc_register);
 EXPORT_SYMBOL(proc_unregister);
 EXPORT_SYMBOL(create_proc_entry);
index 6567c515b9041db4da98b3bfc24c699dbbe1aea6..ed71ec1794f1328bd20284074255c1068a3c37ad 100644 (file)
@@ -20,7 +20,6 @@
 #include "util.h"
 
 #undef UFS_BALLOC_DEBUG
-#undef UFS_BALLOC_DEBUG_MORE
 
 #ifdef UFS_BALLOC_DEBUG
 #define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;
 #define UFSD(x)
 #endif
 
-#ifdef UFS_BALLOC_DEBUG_MORE
-#define UFSDM \
-ufs_print_cylinder_stuff (ucg, swab); \
-printk("inode: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nifree), \
-SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nifree), SWAB32(ucg->cg_cs.cs_nifree)); \
-printk("block: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree), \
-SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nbfree), SWAB32(ucg->cg_cs.cs_nbfree)); \
-printk("fragment: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nffree), \
-SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nffree), SWAB32(ucg->cg_cs.cs_nffree)); \
-printk("ndir: total %u, fs %u, cg %u\n\n", SWAB32(usb1->fs_cstotal.cs_ndir), \
-SWAB32(sb->fs_cs(ucpi->c_cgx).cs_ndir), SWAB32(ucg->cg_cs.cs_ndir));
-#else
-#define UFSDM
-#endif
-
-
 unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
 unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
 unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
 unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
 static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
+void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
 
 /*
  * Free 'count' fragments from fragment number 'fragment'
@@ -90,8 +74,6 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
                goto failed;
        }
 
-       UFSDM
-       
        end_bit = bit + count;
        bbase = ufs_blknum (bit);
        blkmap = ubh_blkmap (UCPI_UBH, ucpi->c_freeoff, bbase);
@@ -118,6 +100,8 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
                SUB_SWAB32(ucg->cg_cs.cs_nffree, uspi->s_fpb);
                SUB_SWAB32(usb1->fs_cstotal.cs_nffree, uspi->s_fpb);
                SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, uspi->s_fpb);
+               if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
+                       ufs_clusteracct (sb, ucpi, blkno, 1);
                INC_SWAB32(ucg->cg_cs.cs_nbfree);
                INC_SWAB32(usb1->fs_cstotal.cs_nbfree);
                INC_SWAB32(sb->fs_cs(cgno).cs_nbfree);
@@ -126,8 +110,6 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
                INC_SWAB32(ubh_cg_blktot (ucpi, cylno));
        }
        
-       UFSDM
-       
        ubh_mark_buffer_dirty (USPI_UBH, 1);
        ubh_mark_buffer_dirty (UCPI_UBH, 1);
        if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -166,7 +148,8 @@ void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) {
        UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
        
        if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
-               ufs_error (sb, "ufs_free_blocks", "internal error");
+               ufs_error (sb, "ufs_free_blocks", "internal error, "
+                       "fragment %u, count %u\n", fragment, count);
                goto failed;
        }
 
@@ -196,14 +179,14 @@ do_more:
                goto failed;
        }
 
-       UFSDM
-       
        for (i = bit; i < end_bit; i += uspi->s_fpb) {
                blkno = ufs_fragstoblks(i);
                if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) {
                        ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
                }
                ubh_setblock(UCPI_UBH, ucpi->c_freeoff, blkno);
+               if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
+                       ufs_clusteracct (sb, ucpi, blkno, 1);
                DQUOT_FREE_BLOCK(sb, inode, uspi->s_fpb);
                INC_SWAB32(ucg->cg_cs.cs_nbfree);
                INC_SWAB32(usb1->fs_cstotal.cs_nbfree);
@@ -213,8 +196,6 @@ do_more:
                INC_SWAB32(ubh_cg_blktot(ucpi, cylno));
        }
 
-       UFSDM
-       
        ubh_mark_buffer_dirty (USPI_UBH, 1);
        ubh_mark_buffer_dirty (UCPI_UBH, 1);
        if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -294,7 +275,6 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment,
                }
                if (fragment < inode->u.ufs_i.i_lastfrag) {
                        UFSD(("EXIT (ALREADY ALLOCATED)\n"))
-                       printk("hlaska 2\n");
                        unlock_super (sb);
                        return 0;
                }
@@ -302,7 +282,6 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment,
        else {
                if (tmp) {
                        UFSD(("EXIT (ALREADY ALLOCATED)\n"))
-                       printk("hlaska 3, fragment %u, tmp %u, oldcount %u\n", fragment, tmp, oldcount);
                        unlock_super(sb);
                        return 0;
                }
@@ -442,8 +421,6 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,
                return 0;
        }
 
-       UFSDM
-       
        fragno = ufs_dtogd (fragment);
        fragoff = ufs_fragnum (fragno);
        for (i = oldcount; i < newcount; i++)
@@ -472,9 +449,6 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,
        SUB_SWAB32(ucg->cg_cs.cs_nffree, count);
        SUB_SWAB32(sb->fs_cs(cgno).cs_nffree, count);
        SUB_SWAB32(usb1->fs_cstotal.cs_nffree, count);
-       usb1->fs_fmod = SWAB32(1);
-       
-       UFSDM
        
        ubh_mark_buffer_dirty (USPI_UBH, 1);
        ubh_mark_buffer_dirty (UCPI_UBH, 1);
@@ -556,8 +530,6 @@ cg_found:
                        "internal error, bad magic number on cg %u", cgno);
        ucg->cg_time = SWAB32(CURRENT_TIME);
 
-       UFSDM
-       
        if (count == uspi->s_fpb) {
                result = ufs_alloccg_block (inode, ucpi, goal, err);
                if (result == (unsigned)-1)
@@ -602,10 +574,6 @@ cg_found:
                INC_SWAB32(ucg->cg_frsum[allocsize - count]);
 
 succed:
-       usb1->fs_fmod = SWAB32(1);
-       
-       UFSDM
-       
        ubh_mark_buffer_dirty (USPI_UBH, 1);
        ubh_mark_buffer_dirty (UCPI_UBH, 1);
        if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -652,8 +620,6 @@ unsigned ufs_alloccg_block (struct inode * inode,
                goto gotit;
        }
        
-       /*** This function should be optimized later ***/
-
 norot: 
        result = ufs_bitmap_search (sb, ucpi, goal, uspi->s_fpb);
        if (result == (unsigned)-1)
@@ -661,7 +627,9 @@ norot:
        ucpi->c_rotor = result;
 gotit:
        blkno = ufs_fragstoblks(result);
-       ubh_clrblock(UCPI_UBH, ucpi->c_freeoff, blkno);
+       ubh_clrblock (UCPI_UBH, ucpi->c_freeoff, blkno);
+       if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
+               ufs_clusteracct (sb, ucpi, blkno, -1);
        if(DQUOT_ALLOC_BLOCK(sb, inode, uspi->s_fpb)) {
                *err = -EDQUOT;
                return (unsigned)-1;
@@ -672,7 +640,6 @@ gotit:
        cylno = ufs_cbtocylno(result);
        DEC_SWAB16(ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)));
        DEC_SWAB32(ubh_cg_blktot(ucpi, cylno));
-       usb1->fs_fmod = 1;
        
        UFSD(("EXIT, result %u\n", result))
 
@@ -685,7 +652,7 @@ unsigned ufs_bitmap_search (struct super_block * sb,
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
        struct ufs_cylinder_group * ucg;
-       unsigned start, length, length2, location, result;
+       unsigned start, length, location, result;
        unsigned possition, fragsize, blockmap, mask;
        unsigned swab;
        
@@ -706,8 +673,8 @@ unsigned ufs_bitmap_search (struct super_block * sb,
                (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
                1 << (count - 1 + (uspi->s_fpb & 7))); 
        if (location == 0) {
-               length2 = start + 1;
-               location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff, length2
+               length = start + 1;
+               location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff, length, 
                        (uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
                        1 << (count - 1 + (uspi->s_fpb & 7)));
                if (location == 0) {
@@ -717,7 +684,6 @@ unsigned ufs_bitmap_search (struct super_block * sb,
                        return (unsigned)-1;
                }
                start = 0;
-               length = length2;
        }
        result = (start + length - location) << 3;
        ucpi->c_frotor = result;
@@ -753,6 +719,64 @@ unsigned ufs_bitmap_search (struct super_block * sb,
        return (unsigned)-1;
 }
 
+void ufs_clusteracct(struct super_block * sb, 
+       struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
+{
+       struct ufs_sb_private_info * uspi;
+       int i, start, end, forw, back;
+       unsigned swab;
+       
+       
+       uspi = sb->u.ufs_sb.s_uspi;
+       swab = sb->u.ufs_sb.s_swab;
+       
+       if (uspi->s_contigsumsize <= 0)
+               return;
+
+       if (cnt > 0)
+               ubh_setbit(UCPI_UBH, ucpi->c_clusteroff, blkno);
+       else
+               ubh_clrbit(UCPI_UBH, ucpi->c_clusteroff, blkno);
+
+       /*
+        * Find the size of the cluster going forward.
+        */
+       start = blkno + 1;
+       end = start + uspi->s_contigsumsize;
+       if ( end >= ucpi->c_nclusterblks)
+               end = ucpi->c_nclusterblks;
+       i = ubh_find_next_zero_bit (UCPI_UBH, ucpi->c_clusteroff, end, start);
+       if (i > end)
+               i = end;
+       forw = i - start;
+       
+       /*
+        * Find the size of the cluster going backward.
+        */
+       start = blkno - 1;
+       end = start - uspi->s_contigsumsize;
+       if (end < 0 ) 
+               end = -1;
+       i = ubh_find_last_zero_bit (UCPI_UBH, ucpi->c_clusteroff, start, end);
+       if ( i < end) 
+               i = end;
+       back = start - i;
+       
+       /*
+        * Account for old cluster and the possibly new forward and
+        * back clusters.
+        */
+       i = back + forw + 1;
+       if (i > uspi->s_contigsumsize)
+               i = uspi->s_contigsumsize;
+       ADD_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2))), cnt);
+       if (back > 0)
+               SUB_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2))), cnt);
+       if (forw > 0)
+               SUB_SWAB32(*((u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2))), cnt);
+}
+
+
 static unsigned char ufs_fragtable_8fpb[] = {
        0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08,
        0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, 0x02, 0x03, 0x03, 0x02, 0x04, 0x05, 0x08, 0x10,
index a822438b62b741805b85c711e293a074d0778336..295332d1751ca76dde255e24c24f0cc510e01657 100644 (file)
@@ -22,7 +22,6 @@
 #include "util.h"
 
 #undef UFS_CYLINDER_DEBUG
-#undef UFS_CYLINDER_DEBUG_MORE
 
 #ifdef UFS_CYLINDER_DEBUG
 #define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;
@@ -50,10 +49,6 @@ static void ufs_read_cylinder (struct super_block * sb,
        ucpi = sb->u.ufs_sb.s_ucpi[bitmap_nr];
        ucg = (struct ufs_cylinder_group *)sb->u.ufs_sb.s_ucg[cgno]->b_data;
 
-#ifdef UFS_CYLINDER_DEBUG_MORE
-       ufs_print_cylinder_stuff (ucg, swab);
-#endif
-
        UCPI_UBH->fragment = ufs_cgcmin(cgno);
        UCPI_UBH->count = uspi->s_cgsize >> sb->s_blocksize_bits;
        /*
@@ -77,7 +72,9 @@ static void ufs_read_cylinder (struct super_block * sb,
        ucpi->c_iusedoff = SWAB32(ucg->cg_iusedoff);
        ucpi->c_freeoff = SWAB32(ucg->cg_freeoff);
        ucpi->c_nextfreeoff = SWAB32(ucg->cg_nextfreeoff);
-       
+       ucpi->c_clustersumoff = SWAB32(ucg->cg_u.cg_44.cg_clustersumoff);
+       ucpi->c_clusteroff = SWAB32(ucg->cg_u.cg_44.cg_clusteroff);
+       ucpi->c_nclusterblks = SWAB32(ucg->cg_u.cg_44.cg_nclusterblks);
        UFSD(("EXIT\n"))
        return; 
        
@@ -201,10 +198,12 @@ struct ufs_cg_private_info * ufs_load_cylinder (
                        sb->u.ufs_sb.s_cg_loaded++;
                else
                        ufs_put_cylinder (sb, UFS_MAX_GROUP_LOADED-1);
+               ucpi = sb->u.ufs_sb.s_ucpi[sb->u.ufs_sb.s_cg_loaded - 1];
                for (j = sb->u.ufs_sb.s_cg_loaded - 1; j > 0; j--) {
                        sb->u.ufs_sb.s_cgno[j] = sb->u.ufs_sb.s_cgno[j-1];
                        sb->u.ufs_sb.s_ucpi[j] = sb->u.ufs_sb.s_ucpi[j-1];
                }
+               sb->u.ufs_sb.s_ucpi[0] = ucpi;
                ufs_read_cylinder (sb, cgno, 0);
        }
        UFSD(("EXIT\n"))
index 470847dca6be44bce0ef9b7bcaf953acefdefc5a..f3497dc7bda46eaed34653666979bacddaa53b17 100644 (file)
@@ -11,8 +11,6 @@
  * 4.4BSD (FreeBSD) support added on February 1st 1998 by
  * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
  * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
- *
- * write support by Daniel Pirkl <daniel.pirkl@email.cz> 1998
  */
 
 #include <linux/fs.h>
@@ -104,11 +102,11 @@ revalidate:
                       && offset < sb->s_blocksize) {
                        de = (struct ufs_dir_entry *) (bh->b_data + offset);
                        /* XXX - put in a real ufs_check_dir_entry() */
-                       if ((de->d_reclen == 0) || (ufs_namlen(de) == 0)) {
+                       if ((de->d_reclen == 0) || (ufs_get_de_namlen(de) == 0)) {
                        /* SWAB16() was unneeded -- compare to 0 */
                                filp->f_pos = (filp->f_pos &
-                                             (sb->s_blocksize - 1)) +
-                                              sb->s_blocksize;
+                                             (sb->s_blocksize - 1)) +
+                                              sb->s_blocksize;
                                brelse(bh);
                                return stored;
                        }
@@ -119,7 +117,7 @@ revalidate:
                                /* On error, skip the f_pos to the
                                   next block. */
                                filp->f_pos = (filp->f_pos &
-                                             (sb->s_blocksize - 1)) +
+                                             (sb->s_blocksize - 1)) +
                                               sb->s_blocksize;
                                brelse (bh);
                                return stored;
@@ -137,8 +135,8 @@ revalidate:
                                unsigned long version = inode->i_version;
 
                                UFSD(("filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino)))
-                               UFSD(("namlen %u\n", ufs_namlen(de)))
-                               error = filldir(dirent, de->d_name, ufs_namlen(de),
+                               UFSD(("namlen %u\n", ufs_get_de_namlen(de)))
+                               error = filldir(dirent, de->d_name, ufs_get_de_namlen(de),
                                                filp->f_pos, SWAB32(de->d_ino));
                                if (error)
                                        break;
@@ -172,7 +170,7 @@ int ufs_check_dir_entry (const char * function,     struct inode * dir,
                error_msg = "reclen is smaller than minimal";
        else if (SWAB16(de->d_reclen) % 4 != 0)
                error_msg = "reclen % 4 != 0";
-       else if (SWAB16(de->d_reclen) < UFS_DIR_REC_LEN(ufs_namlen(de)))
+       else if (SWAB16(de->d_reclen) < UFS_DIR_REC_LEN(ufs_get_de_namlen(de)))
                error_msg = "reclen is too small for namlen";
        else if (dir && ((char *) de - bh->b_data) + SWAB16(de->d_reclen) >
                 dir->i_sb->s_blocksize)
@@ -185,7 +183,7 @@ int ufs_check_dir_entry (const char * function,     struct inode * dir,
                            "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
                            dir->i_ino, dir->i_size, error_msg, offset,
                            (unsigned long) SWAB32(de->d_ino),
-                           SWAB16(de->d_reclen), ufs_namlen(de));
+                           SWAB16(de->d_reclen), ufs_get_de_namlen(de));
        
        return (error_msg == NULL ? 1 : 0);
 }
index 6da43f20a9f3c5137f85e5ea1af8e5e691708ae5..562a0f78bcaf5624abae01b5e7f48d9d2005ee3b 100644 (file)
@@ -34,7 +34,6 @@
 #include "util.h"
 
 #undef UFS_IALLOC_DEBUG
-#undef UFS_IALLOC_DEBUG_MORE
 
 #ifdef UFS_IALLOC_DEBUG
 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
 #define UFSD(x)
 #endif
 
-#ifdef UFS_IALLOC_DEBUG_MORE
-#define UFSDM \
-ufs_print_cylinder_stuff (ucg, swab); \
-printk("inode: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nifree), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nifree), SWAB32(ucg->cg_cs.cs_nifree)); \
-printk("block: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nbfree), SWAB32(ucg->cg_cs.cs_nbfree)); \
-printk("fragment: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_nffree), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_nffree), SWAB32(ucg->cg_cs.cs_nffree)); \
-printk("ndir: total %u, fs %u, cg %u\n", SWAB32(usb1->fs_cstotal.cs_ndir), SWAB32(sb->fs_cs(ucpi->c_cgx).cs_ndir), SWAB32(ucg->cg_cs.cs_ndir));
-#else
-#define UFSDM
-#endif
-
-
 /*
  * NOTE! When we get the inode, we're the only people
  * that have access to it, and as such there are no
@@ -120,8 +107,6 @@ void ufs_free_inode (struct inode * inode)
        if (!ufs_cg_chkmagic(ucg))
                ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number");
 
-       UFSDM
-       
        ucg->cg_time = SWAB32(CURRENT_TIME);
 
        is_directory = S_ISDIR(inode->i_mode);
@@ -153,8 +138,6 @@ void ufs_free_inode (struct inode * inode)
                ubh_wait_on_buffer (UCPI_UBH);
        }
        
-       UFSDM
-       
        sb->s_dirt = 1;
        unlock_super (sb);
        UFSD(("EXIT\n"))
@@ -251,8 +234,6 @@ cg_found:
        if (!ufs_cg_chkmagic(ucg)) 
                ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
 
-       UFSDM
-       
        start = ucpi->c_irotor;
        bit = ubh_find_next_zero_bit (UCPI_UBH, ucpi->c_iusedoff, uspi->s_ipg, start);
        if (!(bit < uspi->s_ipg)) {
@@ -316,8 +297,6 @@ cg_found:
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
 
-       UFSDM
-       
        unlock_super (sb);
 
        if(DQUOT_ALLOC_INODE(sb, inode)) {
index afea7180a660c9d34b7c7290d0305ff209a610d5..c40be747be6f00693110958ba7d864f1b8fca1b5 100644 (file)
@@ -117,7 +117,7 @@ int ufs_bmap (struct inode * inode, int fragment)
         * direct fragment
         */
        if (fragment < UFS_NDIR_FRAGMENT)
-               return ufs_inode_bmap (inode, fragment);
+               return (uspi->s_sbbase + ufs_inode_bmap (inode, fragment));
 
        /*
         * indirect fragment
@@ -128,8 +128,9 @@ int ufs_bmap (struct inode * inode, int fragment)
                        UFS_IND_FRAGMENT + (fragment >> uspi->s_apbshift));
                if (!tmp)
                        return 0;
-               return ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize), 
-                       fragment & uspi->s_apbmask, uspi, swab);
+               return (uspi->s_sbbase + 
+                       ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
+                       fragment & uspi->s_apbmask, uspi, swab));
        }
 
        /*
@@ -141,12 +142,13 @@ int ufs_bmap (struct inode * inode, int fragment)
                        UFS_DIND_FRAGMENT + (fragment >> uspi->s_2apbshift));
                if (!tmp)
                        return 0;
-               tmp = ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize),
+               tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
                        (fragment >> uspi->s_apbshift) & uspi->s_apbmask, uspi, swab);
                if (!tmp)
                        return 0;
-               return ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize),
-                       fragment & uspi->s_apbmask, uspi, swab);
+               return (uspi->s_sbbase + 
+                       ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
+                       fragment & uspi->s_apbmask, uspi, swab));
        }
 
        /*
@@ -157,16 +159,17 @@ int ufs_bmap (struct inode * inode, int fragment)
                UFS_TIND_FRAGMENT + (fragment >> uspi->s_3apbshift));
        if (!tmp)
                return 0;
-       tmp = ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize),
+       tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
                (fragment >> uspi->s_2apbshift) & uspi->s_apbmask, uspi, swab);
        if (!tmp)
                return 0;
-       tmp = ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize),
+       tmp = ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
                (fragment >> uspi->s_apbshift) & uspi->s_apbmask, uspi, swab);
        if (!tmp)
                return 0;
-       return ufs_block_bmap (bread (sb->s_dev, tmp, sb->s_blocksize),
-               fragment & uspi->s_apbmask, uspi, swab);
+       return (uspi->s_sbbase + 
+               ufs_block_bmap (bread (sb->s_dev, uspi->s_sbbase + tmp, sb->s_blocksize),
+               fragment & uspi->s_apbmask, uspi, swab));
 }
 
 static struct buffer_head * ufs_inode_getfrag (struct inode * inode, 
@@ -197,7 +200,7 @@ repeat:
        tmp = SWAB32(*p);
        lastfrag = inode->u.ufs_i.i_lastfrag;
        if (tmp && fragment < lastfrag) {
-               result = getblk (sb->s_dev, tmp + blockoff, sb->s_blocksize);
+               result = getblk (sb->s_dev, uspi->s_sbbase + tmp + blockoff, sb->s_blocksize);
                if (tmp == SWAB32(*p)) {
                        UFSD(("EXIT, result %u\n", tmp + blockoff))
                        return result;
@@ -308,7 +311,7 @@ static struct buffer_head * ufs_block_getfrag (struct inode * inode,
 repeat:
        tmp = SWAB32(*p);
        if (tmp) {
-               result = getblk (bh->b_dev, tmp + blockoff, sb->s_blocksize);
+               result = getblk (bh->b_dev, uspi->s_sbbase + tmp + blockoff, sb->s_blocksize);
                if (tmp == SWAB32(*p)) {
                        brelse (bh);
                        UFSD(("EXIT, result %u\n", tmp + blockoff))
@@ -329,7 +332,6 @@ repeat:
        tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err);
        if (!tmp) {
                if (SWAB32(*p)) {
-                       printk("REPEAT\n");
                        goto repeat;
                }
                else {
@@ -464,7 +466,7 @@ void ufs_read_inode (struct inode * inode)
                return;
        }
        
-       bh = bread (sb->s_dev, ufs_inotofsba(inode->i_ino), sb->s_blocksize);
+       bh = bread (sb->s_dev, uspi->s_sbbase + ufs_inotofsba(inode->i_ino), sb->s_blocksize);
        if (!bh) {
                ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
                return;
@@ -483,7 +485,8 @@ void ufs_read_inode (struct inode * inode)
         * Linux has only 16-bit uid and gid, so we can't support EFT.
         * Files are dynamically chown()ed to root.
         */
-       inode->i_uid = ufs_uid(ufs_inode);
+       inode->i_uid = inode->u.ufs_i.i_uid = ufs_get_inode_uid(ufs_inode);
+       inode->i_gid = inode->u.ufs_i.i_gid = ufs_get_inode_gid(ufs_inode);
        if (inode->i_uid == UFS_USEEFT) {
                inode->i_uid = 0;
        }
@@ -510,8 +513,6 @@ void ufs_read_inode (struct inode * inode)
        inode->u.ufs_i.i_flags = SWAB32(ufs_inode->ui_flags);
        inode->u.ufs_i.i_gen = SWAB32(ufs_inode->ui_gen);
        inode->u.ufs_i.i_shadow = SWAB32(ufs_inode->ui_u3.ui_sun.ui_shadow);
-       inode->u.ufs_i.i_uid = SWAB32(ufs_inode->ui_u3.ui_sun.ui_uid);
-       inode->u.ufs_i.i_gid = SWAB32(ufs_inode->ui_u3.ui_sun.ui_gid);
        inode->u.ufs_i.i_oeftflag = SWAB32(ufs_inode->ui_u3.ui_sun.ui_oeftflag);
        inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize);
        
@@ -540,8 +541,6 @@ void ufs_read_inode (struct inode * inode)
                inode->i_op = &chrdev_inode_operations;
        else if (S_ISBLK(inode->i_mode))
                inode->i_op = &blkdev_inode_operations;
-       else if (S_ISSOCK(inode->i_mode))
-               ; /* nothing */
        else if (S_ISFIFO(inode->i_mode))
                init_fifo(inode);
 
@@ -558,12 +557,13 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
        struct buffer_head * bh;
        struct ufs_inode * ufs_inode;
        unsigned i;
-       unsigned swab;
+       unsigned flags, swab;
 
        UFSD(("ENTER, ino %lu\n", inode->i_ino))
 
        sb = inode->i_sb;
        uspi = sb->u.ufs_sb.s_uspi;
+       flags = sb->u.ufs_sb.s_flags;
        swab = sb->u.ufs_sb.s_swab;
 
        if (inode->i_ino < UFS_ROOTINO || 
@@ -582,22 +582,15 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
        ufs_inode->ui_mode = SWAB16(inode->i_mode);
        ufs_inode->ui_nlink = SWAB16(inode->i_nlink);
 
-       if (inode->i_uid == 0 && inode->u.ufs_i.i_uid >= UFS_USEEFT) {
-               ufs_inode->ui_u3.ui_sun.ui_uid = SWAB32(inode->u.ufs_i.i_uid);
-               ufs_inode->ui_u1.oldids.ui_suid = (__u16)ufs_inode->ui_u3.ui_sun.ui_uid;
-       }
-       else {
-               ufs_inode->ui_u1.oldids.ui_suid = SWAB16(inode->i_uid);
-               ufs_inode->ui_u3.ui_sun.ui_uid = (__u32) ufs_inode->ui_u1.oldids.ui_suid;
-       }
-       if (inode->i_gid == 0 && inode->u.ufs_i.i_gid >= UFS_USEEFT) {
-               ufs_inode->ui_u3.ui_sun.ui_gid = SWAB32(inode->u.ufs_i.i_gid);
-               ufs_inode->ui_u1.oldids.ui_sgid = (__u16)ufs_inode->ui_u3.ui_sun.ui_gid;
-       }
-       else {
-               ufs_inode->ui_u1.oldids.ui_sgid = SWAB16(inode->i_gid);
-               ufs_inode->ui_u3.ui_sun.ui_gid = (__u32) ufs_inode->ui_u1.oldids.ui_sgid;
-       }
+       if (inode->i_uid == 0 && inode->u.ufs_i.i_uid >= UFS_USEEFT)
+               ufs_set_inode_uid (ufs_inode, inode->u.ufs_i.i_uid);
+       else
+               ufs_set_inode_uid (ufs_inode, inode->i_uid);
+
+       if (inode->i_gid == 0 && inode->u.ufs_i.i_gid >= UFS_USEEFT)
+               ufs_set_inode_gid (ufs_inode, inode->u.ufs_i.i_gid);
+       else
+               ufs_set_inode_gid (ufs_inode, inode->i_gid);
                
        ufs_inode->ui_size = SWAB64((u64)inode->i_size);
        ufs_inode->ui_atime.tv_sec = SWAB32(inode->i_atime);
index 9542d27707c466bab01afdeb40f639f563ae34dc..bebfe1f66bee6ee318c62099eb23854294df2d34 100644 (file)
@@ -65,10 +65,10 @@ static int ufs_match (int len, const char * const name,
        /*
         * "" means "." ---> so paths like "/usr/lib//libc.a" work
         */
-       if (!len && ufs_namlen(de) == 1 && (de->d_name[0] == '.') &&
+       if (!len && ufs_get_de_namlen(de) == 1 && (de->d_name[0] == '.') &&
           (de->d_name[1] == '\0'))
                return 1;
-       if (len != ufs_namlen(de))
+       if (len != ufs_get_de_namlen(de))
                return 0;
        return !memcmp(name, de->d_name, len);
 }
@@ -286,7 +286,7 @@ static struct buffer_head * ufs_add_entry (struct inode * dir,
                                de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
                                de->d_ino = SWAB32(0);
                                de->d_reclen = SWAB16(UFS_SECTOR_SIZE);
-                               de->d_u.d_namlen = SWAB16(0);
+                               ufs_set_de_namlen(de,0);
                                dir->i_size = offset + UFS_SECTOR_SIZE;
                                mark_inode_dirty(dir);
                        } else {
@@ -304,18 +304,18 @@ static struct buffer_head * ufs_add_entry (struct inode * dir,
                                return NULL;
                }
                if ((SWAB32(de->d_ino) == 0 && SWAB16(de->d_reclen) >= rec_len) ||
-                   (SWAB16(de->d_reclen) >= UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen)) + rec_len)) {
+                   (SWAB16(de->d_reclen) >= UFS_DIR_REC_LEN(ufs_get_de_namlen(de)) + rec_len)) {
                        offset += SWAB16(de->d_reclen);
                        if (SWAB32(de->d_ino)) {
                                de1 = (struct ufs_dir_entry *) ((char *) de +
-                                       UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen)));
+                                       UFS_DIR_REC_LEN(ufs_get_de_namlen(de)));
                                de1->d_reclen = SWAB16(SWAB16(de->d_reclen) -
-                                       UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen)));
-                               de->d_reclen = SWAB16(UFS_DIR_REC_LEN(SWAB16(de->d_u.d_namlen)));
+                                       UFS_DIR_REC_LEN(ufs_get_de_namlen(de)));
+                               de->d_reclen = SWAB16(UFS_DIR_REC_LEN(ufs_get_de_namlen(de)));
                                de = de1;
                        }
                        de->d_ino = SWAB32(0);
-                       de->d_u.d_namlen = SWAB16(namelen);
+                       ufs_set_de_namlen(de, namelen);
                        memcpy (de->d_name, name, namelen + 1);
                        /*
                         * XXX shouldn't update any times until successful
@@ -369,7 +369,7 @@ static int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
        de = (struct ufs_dir_entry *) bh->b_data;
        
        UFSD(("ino %u, reclen %u, namlen %u, name %s\n", SWAB32(de->d_ino),
-               SWAB16(de->d_reclen), ufs_namlen(de), de->d_name))
+               SWAB16(de->d_reclen), ufs_get_de_namlen(de), de->d_name))
 
        while (i < bh->b_size) {
                if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i))
@@ -410,11 +410,11 @@ int ufs_create (struct inode * dir, struct dentry * dentry, int mode)
        struct buffer_head * bh;
        struct ufs_dir_entry * de;
        int err = -EIO;
-       unsigned swab;
+       unsigned flags, swab;
        
        sb = dir->i_sb;
        swab = sb->u.ufs_sb.s_swab;
-
+       flags = sb->u.ufs_sb.s_flags;
        /*
         * N.B. Several error exits in ufs_new_inode don't set err.
         */
@@ -434,6 +434,7 @@ int ufs_create (struct inode * dir, struct dentry * dentry, int mode)
                return err;
        }
        de->d_ino = SWAB32(inode->i_ino);
+       ufs_set_de_type (de, inode->i_mode);
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -455,9 +456,10 @@ int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        struct buffer_head * bh;
        struct ufs_dir_entry * de;
        int err = -EIO;
-       unsigned swab;
+       unsigned flags, swab;
        
        sb = dir->i_sb;
+       flags = sb->u.ufs_sb.s_flags;
        swab = sb->u.ufs_sb.s_swab;
        
        err = -ENAMETOOLONG;
@@ -493,6 +495,7 @@ int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
        if (!bh)
                goto out_no_entry;
        de->d_ino = SWAB32(inode->i_ino);
+       ufs_set_de_type (de, inode->i_mode);
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -519,9 +522,10 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        struct buffer_head * bh, * dir_block;
        struct ufs_dir_entry * de;
        int err;
-       unsigned swab;
+       unsigned flags, swab;
        
        sb = dir->i_sb;
+       flags = sb->u.ufs_sb.s_flags;
        swab = sb->u.ufs_sb.s_swab;
        
        err = -ENAMETOOLONG;
@@ -548,13 +552,15 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
        de = (struct ufs_dir_entry *) dir_block->b_data;
        de->d_ino = SWAB32(inode->i_ino);
-       de->d_u.d_namlen = SWAB16(1);
+       ufs_set_de_type (de, inode->i_mode);
+       ufs_set_de_namlen(de,1);
        de->d_reclen = SWAB16(UFS_DIR_REC_LEN(1));
        strcpy (de->d_name, ".");
        de = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));
        de->d_ino = SWAB32(dir->i_ino);
+       ufs_set_de_type (de, dir->i_mode);
        de->d_reclen = SWAB16(UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
-       de->d_u.d_namlen = SWAB16(2);
+       ufs_set_de_namlen(de,2);
        strcpy (de->d_name, "..");
        inode->i_nlink = 2;
        mark_buffer_dirty(dir_block, 1);
@@ -567,6 +573,7 @@ int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        if (!bh)
                goto out_no_entry;
        de->d_ino = SWAB32(inode->i_ino);
+       ufs_set_de_type (de, inode->i_mode);
        dir->i_version = ++event;
        mark_buffer_dirty(bh, 1);
        if (IS_SYNC(dir)) {
@@ -605,7 +612,7 @@ static int ufs_empty_dir (struct inode * inode)
 
        if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
            !(bh = ufs_bread (inode, 0, 0, &err))) {
-               ufs_warning (inode->i_sb, "empty_dir",
+               ufs_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no data block",
                              inode->i_ino);
                return 1;
@@ -614,7 +621,7 @@ static int ufs_empty_dir (struct inode * inode)
        de1 = (struct ufs_dir_entry *) ((char *) de + SWAB16(de->d_reclen));
        if (SWAB32(de->d_ino) != inode->i_ino || !SWAB32(de1->d_ino) || 
            strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
-               ufs_warning (inode->i_sb, "empty_dir",
+               ufs_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no `.' or `..'",
                              inode->i_ino);
                return 1;
@@ -625,7 +632,7 @@ static int ufs_empty_dir (struct inode * inode)
                if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
                        brelse (bh);
                        bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);
-                       if (!bh) {
+                       if (!bh) {
                                ufs_error (sb, "empty_dir",
                                            "directory #%lu contains a hole at offset %lu",
                                            inode->i_ino, offset);
@@ -768,7 +775,7 @@ int ufs_unlink(struct inode * dir, struct dentry *dentry)
        retval = -ENOENT;
        bh = ufs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
        UFSD(("de: ino %u, reclen %u, namelen %u, name %s\n", SWAB32(de->d_ino),
-               SWAB16(de->d_reclen), ufs_namlen(de), de->d_name))
+               SWAB16(de->d_reclen), ufs_get_de_namlen(de), de->d_name))
        if (!bh)
                goto end_unlink;
 
@@ -984,7 +991,7 @@ static int do_ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
        UFSD(("name %s, len %u\n", old_dentry->d_name.name, old_dentry->d_name.len)) 
        old_bh = ufs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
        UFSD(("ino %u, reclen %u, namlen %u, name %s\n", SWAB32(old_de->d_ino),
-               SWAB16(old_de->d_reclen), ufs_namlen(old_de), old_de->d_name))
+               SWAB16(old_de->d_reclen), ufs_get_de_namlen(old_de), old_de->d_name))
            
        retval = -ENOENT;
        if (!old_bh)
index d4426ad5dfa96920b92efdc596512c8da375d596..dd481546997b7f6bda3112265db37ae2ccba8ea1 100644 (file)
@@ -1,4 +1,33 @@
 /*
+ *  linux/fs/ufs/super.c
+ *
+ * Copyright (C) 1998
+ * Daniel Pirkl <daniel.pirkl@email.cz>
+ * Charles University, Faculty of Mathematics and Physics
+ */
+
+/* Derivated from
+ *
+ *  linux/fs/ext2/super.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ *  from
+ *
+ *  linux/fs/minix/inode.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Big-endian to little-endian byte-swapping/bitmaps by
+ *        David S. Miller (davem@caip.rutgers.edu), 1995
+ */
+/*
+ * Inspirated by
+ *
  *  linux/fs/ufs/super.c
  *
  * Copyright (C) 1996
  * 
  */
 
+
 #include <linux/module.h>
-#include <linux/init.h>
 
-#include <linux/kernel.h>
+#include <stdarg.h>
+
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
-#include <linux/locks.h>
-#include <asm/uaccess.h>
 #include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
 
 #include "swab.h"
 #include "util.h"
 
-
 #undef UFS_SUPER_DEBUG
 #undef UFS_SUPER_DEBUG_MORE
 
@@ -59,39 +97,41 @@ void ufs_print_super_stuff(struct ufs_super_block_first * usb1,
        struct ufs_super_block_second * usb2, 
        struct ufs_super_block_third * usb3, unsigned swab)
 {
-       printk("\nufs_print_super_stuff\n");
-       printk("size of usb:    %lu\n", sizeof(struct ufs_super_block));
-       printk("  magic:        0x%x\n", SWAB32(usb3->fs_magic));
-       printk("  sblkno:       %u\n", SWAB32(usb1->fs_sblkno));
-       printk("  cblkno:       %u\n", SWAB32(usb1->fs_cblkno));
-       printk("  iblkno:       %u\n", SWAB32(usb1->fs_iblkno));
-       printk("  dblkno:       %u\n", SWAB32(usb1->fs_dblkno));
-       printk("  cgoffset:     %u\n", SWAB32(usb1->fs_cgoffset));
-       printk("  ~cgmask:      0x%x\n", ~SWAB32(usb1->fs_cgmask));
-       printk("  size:         %u\n", SWAB32(usb1->fs_size));
-       printk("  dsize:        %u\n", SWAB32(usb1->fs_dsize));
-       printk("  ncg:          %u\n", SWAB32(usb1->fs_ncg));
-       printk("  bsize:        %u\n", SWAB32(usb1->fs_bsize));
-       printk("  fsize:        %u\n", SWAB32(usb1->fs_fsize));
-       printk("  frag:         %u\n", SWAB32(usb1->fs_frag));
-       printk("  fragshift:    %u\n", SWAB32(usb1->fs_fragshift));
-       printk("  ~fmask:       %u\n", ~SWAB32(usb1->fs_fmask));
-       printk("  fshift:       %u\n", SWAB32(usb1->fs_fshift));
-       printk("  sbsize:       %u\n", SWAB32(usb1->fs_sbsize));
-       printk("  spc:          %u\n", SWAB32(usb1->fs_spc));
-       printk("  cpg:          %u\n", SWAB32(usb1->fs_cpg));
-       printk("  ipg:          %u\n", SWAB32(usb1->fs_ipg));
-       printk("  fpg:          %u\n", SWAB32(usb1->fs_fpg));
-       printk("  csaddr:       %u\n", SWAB32(usb1->fs_csaddr));
-       printk("  cssize:       %u\n", SWAB32(usb1->fs_cssize));
-       printk("  cgsize:       %u\n", SWAB32(usb1->fs_cgsize));
-       printk("  fstodb:       %u\n", SWAB32(usb1->fs_fsbtodb));
-       printk("  postblformat: %u\n", SWAB32(usb3->fs_postblformat));
-       printk("  nrpos:        %u\n", SWAB32(usb3->fs_nrpos));
-       printk("  ndir          %u\n", SWAB32(usb1->fs_cstotal.cs_ndir));
-       printk("  nifree        %u\n", SWAB32(usb1->fs_cstotal.cs_nifree));
-       printk("  nbfree        %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree));
-       printk("  nffree        %u\n", SWAB32(usb1->fs_cstotal.cs_nffree));
+       printk("ufs_print_super_stuff\n");
+       printk("size of usb:     %u\n", sizeof(struct ufs_super_block));
+       printk("  magic:         0x%x\n", SWAB32(usb3->fs_magic));
+       printk("  sblkno:        %u\n", SWAB32(usb1->fs_sblkno));
+       printk("  cblkno:        %u\n", SWAB32(usb1->fs_cblkno));
+       printk("  iblkno:        %u\n", SWAB32(usb1->fs_iblkno));
+       printk("  dblkno:        %u\n", SWAB32(usb1->fs_dblkno));
+       printk("  cgoffset:      %u\n", SWAB32(usb1->fs_cgoffset));
+       printk("  ~cgmask:       0x%x\n", ~SWAB32(usb1->fs_cgmask));
+       printk("  size:          %u\n", SWAB32(usb1->fs_size));
+       printk("  dsize:         %u\n", SWAB32(usb1->fs_dsize));
+       printk("  ncg:           %u\n", SWAB32(usb1->fs_ncg));
+       printk("  bsize:         %u\n", SWAB32(usb1->fs_bsize));
+       printk("  fsize:         %u\n", SWAB32(usb1->fs_fsize));
+       printk("  frag:          %u\n", SWAB32(usb1->fs_frag));
+       printk("  fragshift:     %u\n", SWAB32(usb1->fs_fragshift));
+       printk("  ~fmask:        %u\n", ~SWAB32(usb1->fs_fmask));
+       printk("  fshift:        %u\n", SWAB32(usb1->fs_fshift));
+       printk("  sbsize:        %u\n", SWAB32(usb1->fs_sbsize));
+       printk("  spc:           %u\n", SWAB32(usb1->fs_spc));
+       printk("  cpg:           %u\n", SWAB32(usb1->fs_cpg));
+       printk("  ipg:           %u\n", SWAB32(usb1->fs_ipg));
+       printk("  fpg:           %u\n", SWAB32(usb1->fs_fpg));
+       printk("  csaddr:        %u\n", SWAB32(usb1->fs_csaddr));
+       printk("  cssize:        %u\n", SWAB32(usb1->fs_cssize));
+       printk("  cgsize:        %u\n", SWAB32(usb1->fs_cgsize));
+       printk("  fstodb:        %u\n", SWAB32(usb1->fs_fsbtodb));
+       printk("  contigsumsize: %d\n", SWAB32(usb3->fs_u.fs_44.fs_contigsumsize));
+       printk("  postblformat:  %u\n", SWAB32(usb3->fs_postblformat));
+       printk("  nrpos:         %u\n", SWAB32(usb3->fs_nrpos));
+       printk("  ndir           %u\n", SWAB32(usb1->fs_cstotal.cs_ndir));
+       printk("  nifree         %u\n", SWAB32(usb1->fs_cstotal.cs_nifree));
+       printk("  nbfree         %u\n", SWAB32(usb1->fs_cstotal.cs_nbfree));
+       printk("  nffree         %u\n", SWAB32(usb1->fs_cstotal.cs_nffree));
+       printk("\n");
 }
 
 
@@ -101,107 +141,411 @@ void ufs_print_super_stuff(struct ufs_super_block_first * usb1,
 void ufs_print_cylinder_stuff(struct ufs_cylinder_group *cg, unsigned swab)
 {
        printk("\nufs_print_cylinder_stuff\n");
-       printk("size of ucg: %lu\n", sizeof(struct ufs_cylinder_group));
-       printk("  magic:       %x\n", SWAB32(cg->cg_magic));
-       printk("  time:        %u\n", SWAB32(cg->cg_time));
-       printk("  cgx:         %u\n", SWAB32(cg->cg_cgx));
-       printk("  ncyl:        %u\n", SWAB16(cg->cg_ncyl));
-       printk("  niblk:       %u\n", SWAB16(cg->cg_niblk));
-       printk("  ndblk:       %u\n", SWAB32(cg->cg_ndblk));
-       printk("  cs_ndir:     %u\n", SWAB32(cg->cg_cs.cs_ndir));
-       printk("  cs_nbfree:   %u\n", SWAB32(cg->cg_cs.cs_nbfree));
-       printk("  cs_nifree:   %u\n", SWAB32(cg->cg_cs.cs_nifree));
-       printk("  cs_nffree:   %u\n", SWAB32(cg->cg_cs.cs_nffree));
-       printk("  rotor:       %u\n", SWAB32(cg->cg_rotor));
-       printk("  frotor:      %u\n", SWAB32(cg->cg_frotor));
-       printk("  irotor:      %u\n", SWAB32(cg->cg_irotor));
-       printk("  frsum:       %u, %u, %u, %u, %u, %u, %u, %u\n",
+       printk("size of ucg: %u\n", sizeof(struct ufs_cylinder_group));
+       printk("  magic:        %x\n", SWAB32(cg->cg_magic));
+       printk("  time:         %u\n", SWAB32(cg->cg_time));
+       printk("  cgx:          %u\n", SWAB32(cg->cg_cgx));
+       printk("  ncyl:         %u\n", SWAB16(cg->cg_ncyl));
+       printk("  niblk:        %u\n", SWAB16(cg->cg_niblk));
+       printk("  ndblk:        %u\n", SWAB32(cg->cg_ndblk));
+       printk("  cs_ndir:      %u\n", SWAB32(cg->cg_cs.cs_ndir));
+       printk("  cs_nbfree:    %u\n", SWAB32(cg->cg_cs.cs_nbfree));
+       printk("  cs_nifree:    %u\n", SWAB32(cg->cg_cs.cs_nifree));
+       printk("  cs_nffree:    %u\n", SWAB32(cg->cg_cs.cs_nffree));
+       printk("  rotor:        %u\n", SWAB32(cg->cg_rotor));
+       printk("  frotor:       %u\n", SWAB32(cg->cg_frotor));
+       printk("  irotor:       %u\n", SWAB32(cg->cg_irotor));
+       printk("  frsum:        %u, %u, %u, %u, %u, %u, %u, %u\n",
            SWAB32(cg->cg_frsum[0]), SWAB32(cg->cg_frsum[1]),
            SWAB32(cg->cg_frsum[2]), SWAB32(cg->cg_frsum[3]),
            SWAB32(cg->cg_frsum[4]), SWAB32(cg->cg_frsum[5]),
            SWAB32(cg->cg_frsum[6]), SWAB32(cg->cg_frsum[7]));
-       printk("  btotoff:     %u\n", SWAB32(cg->cg_btotoff));
-       printk("  boff:        %u\n", SWAB32(cg->cg_boff));
-       printk("  iuseoff:     %u\n", SWAB32(cg->cg_iusedoff));
-       printk("  freeoff:     %u\n", SWAB32(cg->cg_freeoff));
-       printk("  nextfreeoff: %u\n", SWAB32(cg->cg_nextfreeoff));
+       printk("  btotoff:      %u\n", SWAB32(cg->cg_btotoff));
+       printk("  boff:         %u\n", SWAB32(cg->cg_boff));
+       printk("  iuseoff:      %u\n", SWAB32(cg->cg_iusedoff));
+       printk("  freeoff:      %u\n", SWAB32(cg->cg_freeoff));
+       printk("  nextfreeoff:  %u\n", SWAB32(cg->cg_nextfreeoff));
+       printk("  clustersumoff %u\n", SWAB32(cg->cg_u.cg_44.cg_clustersumoff));
+       printk("  clusteroff    %u\n", SWAB32(cg->cg_u.cg_44.cg_clusteroff));
+       printk("  nclusterblks  %u\n", SWAB32(cg->cg_u.cg_44.cg_nclusterblks));
+       printk("\n");
 }
 #endif /* UFS_SUPER_DEBUG_MORE */
 
+static char error_buf[1024];
+
+void ufs_error (struct super_block * sb, const char * function,
+       const char * fmt, ...)
+{
+       struct ufs_sb_private_info * uspi;
+       struct ufs_super_block_first * usb1;
+       va_list args;
+
+       uspi = sb->u.ufs_sb.s_uspi;
+       usb1 = ubh_get_usb_first(USPI_UBH);
+       
+       if (!(sb->s_flags & MS_RDONLY)) {
+               usb1->fs_clean = UFS_FSBAD;
+               ubh_mark_buffer_dirty(USPI_UBH, 1);
+               sb->s_dirt = 1;
+               sb->s_flags |= MS_RDONLY;
+       }
+       va_start (args, fmt);
+       vsprintf (error_buf, fmt, args);
+       va_end (args);
+       switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_ONERROR) {
+       case UFS_MOUNT_ONERROR_PANIC:
+               panic ("UFS-fs panic (device %s): %s: %s\n", 
+                       kdevname(sb->s_dev), function, error_buf);
+
+       case UFS_MOUNT_ONERROR_LOCK:
+       case UFS_MOUNT_ONERROR_UMOUNT:
+       case UFS_MOUNT_ONERROR_REPAIR:
+               printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n",
+                       kdevname(sb->s_dev), function, error_buf);
+       }               
+}
+
+void ufs_panic (struct super_block * sb, const char * function,
+       const char * fmt, ...)
+{
+       struct ufs_sb_private_info * uspi;
+       struct ufs_super_block_first * usb1;
+       va_list args;
+       
+       uspi = sb->u.ufs_sb.s_uspi;
+       usb1 = ubh_get_usb_first(USPI_UBH);
+       
+       if (!(sb->s_flags & MS_RDONLY)) {
+               usb1->fs_clean = UFS_FSBAD;
+               ubh_mark_buffer_dirty(USPI_UBH, 1);
+               sb->s_dirt = 1;
+       }
+       va_start (args, fmt);
+       vsprintf (error_buf, fmt, args);
+       va_end (args);
+       /* this is to prevent panic from syncing this filesystem */
+       if (sb->s_lock)
+               sb->s_lock = 0;
+       sb->s_flags |= MS_RDONLY;
+       printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
+               kdevname(sb->s_dev), function, error_buf);
+/*** 
+       panic ("UFS-fs panic (device %s): %s: %s\n", 
+               kdevname(sb->s_dev), function, error_buf);
+***/
+}
+
+void ufs_warning (struct super_block * sb, const char * function,
+       const char * fmt, ...)
+{
+       va_list args;
+
+       va_start (args, fmt);
+       vsprintf (error_buf, fmt, args);
+       va_end (args);
+       printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n",
+               kdevname(sb->s_dev), function, error_buf);
+}
+
+static int ufs_parse_options (char * options, unsigned * mount_options)
+{
+       char * this_char;
+       char * value;
+       
+       UFSD(("ENTER\n"))
+       
+       if (!options)
+               return 1;
+               
+       for (this_char = strtok (options, ",");
+            this_char != NULL;
+            this_char = strtok (NULL, ",")) {
+            
+               if ((value = strchr (this_char, '=')) != NULL)
+                       *value++ = 0;
+               if (!strcmp (this_char, "ufstype")) {
+                       ufs_clear_opt (*mount_options, UFSTYPE);
+                       if (!strcmp (value, "old"))
+                               ufs_set_opt (*mount_options, UFSTYPE_OLD);
+                       else if (!strcmp (value, "sun"))
+                               ufs_set_opt (*mount_options, UFSTYPE_SUN);
+                       else if (!strcmp (value, "44bsd"))
+                               ufs_set_opt (*mount_options, UFSTYPE_44BSD);
+                       else if (!strcmp (value, "next"))
+                               ufs_set_opt (*mount_options, UFSTYPE_NEXT);
+                       else {
+                               printk ("UFS-fs: Invalid type option: %s\n", value);
+                               return 0;
+                       }
+               }
+               else if (!strcmp (this_char, "onerror")) {
+                       ufs_clear_opt (*mount_options, ONERROR);
+                       if (!strcmp (value, "panic"))
+                               ufs_set_opt (*mount_options, ONERROR_PANIC);
+                       else if (!strcmp (value, "lock"))
+                               ufs_set_opt (*mount_options, ONERROR_LOCK);
+                       else if (!strcmp (value, "umount"))
+                               ufs_set_opt (*mount_options, ONERROR_UMOUNT);
+                       else if (!strcmp (value, "repair")) {
+                               printk("UFS-fs: Unable to do repair on error, "
+                                       "will lock lock instead \n");
+                               ufs_set_opt (*mount_options, ONERROR_REPAIR);
+                       }
+                       else {
+                               printk ("UFS-fs: Invalid action onerror: %s\n", value);
+                               return 0;
+                       }
+               }
+               else {
+                       printk("UFS-fs: Invalid option: %s\n", this_char);
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/*
+ * Read on-disk structures asscoiated with cylinder groups
+ */
+int ufs_read_cylinder_structures (struct super_block * sb) {
+       struct ufs_sb_private_info * uspi;
+       struct ufs_buffer_head * ubh;
+       unsigned char * base, * space;
+       unsigned size, blks, i;
+       unsigned swab;
+       
+       UFSD(("ENTER\n"))
+       
+       uspi = sb->u.ufs_sb.s_uspi;
+       swab = sb->u.ufs_sb.s_swab;
+       
+       /*
+        * Read cs structures from (usually) first data block
+        * on the device. 
+        */
+       size = uspi->s_cssize;
+       blks = howmany(size, uspi->s_fsize);
+       base = space = kmalloc(size, GFP_KERNEL);
+       if (!base)
+               goto failed; 
+       for (i = 0; i < blks; i += uspi->s_fpb) {
+               size = uspi->s_bsize;
+               if (i + uspi->s_fpb > blks)
+                       size = (blks - i) * uspi->s_fsize;
+               ubh = ubh_bread(sb->s_dev, uspi->s_csaddr + i, size);
+               if (!ubh)
+                       goto failed;
+               ubh_ubhcpymem (space, ubh, size);
+               sb->u.ufs_sb.s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space;
+               space += size;
+               ubh_brelse (ubh);
+               ubh = NULL;
+       }
+
+       /*
+        * Read cylinder group (we read only first fragment from block
+        * at this time) and prepare internal data structures for cg caching.
+        */
+       if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL)))
+               goto failed;
+       for (i = 0; i < uspi->s_ncg; i++) 
+               sb->u.ufs_sb.s_ucg[i] = NULL;
+       for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
+               sb->u.ufs_sb.s_ucpi[i] = NULL;
+               sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY;
+       }
+       for (i = 0; i < uspi->s_ncg; i++) {
+               UFSD(("read cg %u\n", i))
+               if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize)))
+                       goto failed;
+               if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data))
+                       goto failed;
+#ifdef UFS_SUPER_DEBUG_MORE
+               ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab);
+#endif
+       }
+       for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
+               if (!(sb->u.ufs_sb.s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL)))
+                       goto failed;
+               sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY;
+       }
+       sb->u.ufs_sb.s_cg_loaded = 0;
+       UFSD(("EXIT\n"))
+       return 1;
+
+failed:
+       if (base) kfree (base);
+       if (sb->u.ufs_sb.s_ucg) {
+               for (i = 0; i < uspi->s_ncg; i++)
+                       if (sb->u.ufs_sb.s_ucg[i]) brelse (sb->u.ufs_sb.s_ucg[i]);
+               kfree (sb->u.ufs_sb.s_ucg);
+               for (i = 0; i < UFS_MAX_GROUP_LOADED; i++)
+                       if (sb->u.ufs_sb.s_ucpi[i]) kfree (sb->u.ufs_sb.s_ucpi[i]);
+       }
+       UFSD(("EXIT (FAILED)\n"))
+       return 0;
+}
+
 /*
- * Called while file system is mounted, read super block
- * and create important internal structures.
+ * Put on-disk structures associated with cylidner groups and 
+ * write them back to disk
  */
-struct super_block * ufs_read_super (
-       struct super_block * sb,
-       void * data,
+void ufs_put_cylinder_structures (struct super_block * sb) {
+       struct ufs_sb_private_info * uspi;
+       struct ufs_buffer_head * ubh;
+       unsigned char * base, * space;
+       unsigned blks, size, i;
+       
+       UFSD(("ENTER\n"))
+       
+       uspi = sb->u.ufs_sb.s_uspi;
+
+       size = uspi->s_cssize;
+       blks = howmany(size, uspi->s_fsize);
+       base = space = (char*) sb->u.ufs_sb.s_csp[0];
+       for (i = 0; i < blks; i += uspi->s_fpb) {
+               size = uspi->s_bsize;
+               if (i + uspi->s_fpb > blks)
+                       size = (blks - i) * uspi->s_fsize;
+               ubh = ubh_bread (sb->s_dev, uspi->s_csaddr + i, size);
+               ubh_memcpyubh (ubh, space, size);
+               space += size;
+               ubh_mark_buffer_uptodate (ubh, 1);
+               ubh_mark_buffer_dirty (ubh, 0);
+               ubh_brelse (ubh);
+       }
+       for (i = 0; i < sb->u.ufs_sb.s_cg_loaded; i++) {
+               ufs_put_cylinder (sb, i);
+               kfree (sb->u.ufs_sb.s_ucpi[i]);
+       }
+       for (; i < UFS_MAX_GROUP_LOADED; i++) 
+               kfree (sb->u.ufs_sb.s_ucpi[i]);
+       for (i = 0; i < uspi->s_ncg; i++) 
+               brelse (sb->u.ufs_sb.s_ucg[i]);
+       kfree (sb->u.ufs_sb.s_ucg);
+       kfree (base);
+       UFSD(("EXIT\n"))
+}
+
+struct super_block * ufs_read_super (struct super_block * sb, void * data,
        int silent)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
        struct ufs_super_block_second * usb2;
        struct ufs_super_block_third * usb3;
-       struct ufs_buffer_head * ubh;
-       unsigned char * base, * space;
-       unsigned size, blks, i;
+       struct ufs_buffer_head * ubh;   
        unsigned block_size, super_block_size;
        unsigned flags, swab;
-       s64 tmp;
-       static unsigned offsets[] = {0, 96, 160};  /* different superblock locations */
-                   
-       UFSD(("ENTER\n"))
-       
+
        uspi = NULL;
        ubh = NULL;
-       base = space = NULL;
-       sb->u.ufs_sb.s_ucg = NULL;
        flags = 0;
+       swab = 0;
        
-       /* sb->s_dev and sb->s_flags are set by our caller
-        * data is the mystery argument to sys_mount()
-        *
-        * Our caller also sets s_dev, s_covered, s_rd_only, s_dirt,
-        *   and s_type when we return.
-        */
-
+       UFSD(("ENTER\n"))
+               
        MOD_INC_USE_COUNT;
        lock_super (sb);
 
-       sb->u.ufs_sb.s_uspi = uspi = 
+       /*
+        * Set default mount options
+        * Parse mount options
+        */
+       sb->u.ufs_sb.s_mount_opt = 0;
+       ufs_set_opt (sb->u.ufs_sb.s_mount_opt, ONERROR_LOCK);
+       if (!ufs_parse_options ((char *) data, &sb->u.ufs_sb.s_mount_opt)) {
+               printk("wrong mount options\n");
+               goto failed;
+       }
+       if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) {
+               printk("You didn't specify type of your ufs file system\n\n"
+               "       mount -t ufs -o ufstype=sun|44bsd|old|next ....\n\n"
+               "!!! WARNING !!! wrong value may corrupt you file system\n"
+               "default value is ufstype=old\n");
+               ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD);
+       }
+
+       sb->u.ufs_sb.s_uspi = uspi =
                kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL);
        if (!uspi)
                goto failed;
+
+       switch (sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) {
+       case UFS_MOUNT_UFSTYPE_44BSD:
+               UFSD(("44bsd ufstype\n"))
+               uspi->s_fsize = block_size = 512;
+               uspi->s_fmask = ~(512 - 1);
+               uspi->s_fshift = 9;
+               uspi->s_sbsize = super_block_size = 1536;
+               uspi->s_sbbase = 0;
+               flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
+               break;
+               
+       case UFS_MOUNT_UFSTYPE_SUN:
+               UFSD(("sun  ufstype\n"))
+               uspi->s_fsize = block_size = 1024;
+               uspi->s_fmask = ~(1024 - 1);
+               uspi->s_fshift = 10;
+               uspi->s_sbsize = super_block_size = 2048;
+               uspi->s_sbbase = 0;
+               flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN;
+               break;
+
+       case UFS_MOUNT_UFSTYPE_OLD:
+               UFSD(("old ufstype\n"))
+               uspi->s_fsize = block_size = 1024;
+               uspi->s_fmask = ~(1024 - 1);
+               uspi->s_fshift = 10;
+               uspi->s_sbsize = super_block_size = 2048;
+               uspi->s_sbbase = 0;
+               flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
+               if (!(sb->s_flags & MS_RDONLY)) {
+                       printk("old type of ufs is supported read-only\n"); 
+                       goto failed;
+               }
+               break;
        
-       block_size = BLOCK_SIZE;
-       super_block_size = BLOCK_SIZE * 2;
+       case UFS_MOUNT_UFSTYPE_NEXT:
+               UFSD(("next ufstype\n"))
+               uspi->s_fsize = block_size = 1024;
+               uspi->s_fmask = ~(1024 - 1);
+               uspi->s_fshift = 10;
+               uspi->s_sbsize = super_block_size = 2048;
+               uspi->s_sbbase = 0;
+               flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
+               if (!(sb->s_flags & MS_RDONLY)) {
+                       printk("nextstep type of ufs is supported read-only\n");
+                       goto failed;
+               }
+               break;
        
-       uspi->s_fsize = block_size;
-       uspi->s_fmask = ~(BLOCK_SIZE - 1);
-       uspi->s_fshift = BLOCK_SIZE_BITS;
-       uspi->s_sbsize = super_block_size;
-       i = 0;
-       uspi->s_sbbase = offsets[i];
        
-again:
+       default:
+               printk("this fs type of ufs is not supported\n");
+               goto failed;
+       }
+       
+       if (!(sb->s_flags & MS_RDONLY))
+               printk("!!! warning !!! write support of ufs is still in experimental state\n"); 
+
+again: 
        set_blocksize (sb->s_dev, block_size);
 
        /*
         * read ufs super block from device
         */
-       ubh = ubh_bread2 (sb->s_dev, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
+       ubh = ubh_bread_uspi (uspi, sb->s_dev, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
        if (!ubh) 
                goto failed;
        
        usb1 = ubh_get_usb_first(USPI_UBH);
        usb2 = ubh_get_usb_second(USPI_UBH);
        usb3 = ubh_get_usb_third(USPI_UBH);
-       
+
        /*
         * Check ufs magic number
-        * This code uses goto, because it's a lesser evil than unbalanced
-        * structure in conditional code. Brought to you by Fare' as a minimal
-        * hack to live with Daniel's (unnecessary, IMNSHO) manual swab
-        * optimization -- see swab.h.
         */
 #if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN) /* sane bytesex */
        switch (usb3->fs_magic) {
@@ -222,108 +566,68 @@ again:
                        goto magic_found;
        }
 #endif
-       /*
-        * Magic number not found -- try another super block location
-        */
-       if (++i < sizeof(offsets)/sizeof(unsigned)) {
-               ubh_brelse2(ubh);
+
+       if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == 
+       UFS_MOUNT_UFSTYPE_NEXT && uspi->s_sbbase < 256) {
+               ubh_brelse_uspi(uspi);
                ubh = NULL;
-               uspi->s_sbbase = offsets[i];
+               uspi->s_sbbase += 8;
                goto again;
-       } else {
-               printk("ufs_read_super: "
-                      "super block location not in "
-                      "{ 0, 96, 160} "
-                      "or bad magic number\n");
-               goto failed;
        }
-       magic_found:
+       printk("ufs_read_super: bad magic number\n");
+       goto failed;
 
+magic_found:
        /*
         * Check block and fragment sizes
         */
        uspi->s_bsize = SWAB32(usb1->fs_bsize);
        uspi->s_fsize = SWAB32(usb1->fs_fsize);
        uspi->s_sbsize = SWAB32(usb1->fs_sbsize);
+       uspi->s_fmask = SWAB32(usb1->fs_fmask);
+       uspi->s_fshift = SWAB32(usb1->fs_fshift);
 
        if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192) {
-               printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n",
-                      uspi->s_bsize);
+               printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", uspi->s_bsize);
                goto failed;
        }
        if (uspi->s_fsize != 512 && uspi->s_fsize != 1024) {
-               printk("ufs_read_super: fs_fsize %u != {512, 1024}\n",
-                      uspi->s_fsize);
+               printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", uspi->s_fsize);
                goto failed;
        }
-       
-       /*
-        * Block size is not 1024. Free buffers, set block_size and
-        * super_block_size to superblock-declared values, and try again.
-        */
        if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) {
-               ubh_brelse2(ubh);
+               ubh_brelse_uspi(uspi);
                ubh = NULL;
-               uspi->s_fmask = SWAB32(usb1->fs_fmask);
-               uspi->s_fshift = SWAB32(usb1->fs_fshift);
                block_size = uspi->s_fsize;
                super_block_size = uspi->s_sbsize;
+               UFSD(("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size))
                goto again;
        }
 
 #ifdef UFS_SUPER_DEBUG_MORE
        ufs_print_super_stuff (usb1, usb2, usb3, swab);
 #endif
-       /*
-        * Check file system flavor
-        */
-       flags |= UFS_VANILLA;
-       /* XXX more consistency check */
-       UFSD(("ufs_read_super: maxsymlinklen 0x%8.8x\n", usb3->fs_u.fs_44.fs_maxsymlinklen))
-       if (usb3->fs_u.fs_44.fs_maxsymlinklen >= 0) {
-               if (usb3->fs_u.fs_44.fs_inodefmt >= UFS_44INODEFMT) {
-                       UFSD(("Flavor: 44BSD\n"))
-                       flags |= UFS_44BSD;
-                       sb->s_flags |= MS_RDONLY;
-               } else {
-                       UFSD(("Flavor: OLD\n"))
-                       sb->s_flags |= UFS_OLD;       /* 4.2BSD */
-               }
-       } else if (uspi->s_sbbase > 0) {
-               UFSD(("Flavor: NEXT\n"))
-               flags |= UFS_NEXT;
-               sb->s_flags |= MS_RDONLY;
-       } else {
-               UFSD(("Flavor: SUN\n"))
-               flags |= UFS_SUN;
-       }
 
        /*
-        * Check whether file system was correctly unmounted.
+        * Check, if file system was correctly unmounted.
         * If not, make it read only.
         */
        if (((flags & UFS_ST_MASK) == UFS_ST_44BSD) ||
            ((flags & UFS_ST_MASK) == UFS_ST_OLD) ||
-           ((flags & UFS_ST_MASK) == UFS_ST_NEXT) ||
-           (((flags & UFS_ST_MASK) == UFS_ST_SUN) &&
-           ufs_state(usb3) == UFS_FSOK - usb1->fs_time)) {
+          (((flags & UFS_ST_MASK) == UFS_ST_SUN) && 
+            (ufs_get_fs_state(usb3) == (UFS_FSOK - SWAB32(usb1->fs_time))))) {
                switch(usb1->fs_clean) {
-               case UFS_FSACTIVE:      /* 0x00 */
-                       printk("ufs_read_super: fs is active\n");
-                       sb->s_flags |= MS_RDONLY;
-                       break;
-               case UFS_FSCLEAN:       /* 0x01 */
-                       UFSD(("ufs_read_super: fs is clean\n"))
+               case UFS_FSCLEAN:
+                       UFSD(("fs is clean\n"))
                        break;
                case UFS_FSSTABLE:
-                       UFSD(("ufs_read_super: fs is stable\n"))
+                       UFSD(("fs is stable\n"))
                        break;
-               case UFS_FSOSF1:        /* 0x03 */
-               /* XXX - is this the correct interpretation under DEC OSF/1? */
-                       printk("ufs_read_super: "
-                              "fs is clean and stable (OSF/1)\n");
+               case UFS_FSACTIVE:
+                       printk("ufs_read_super: fs is active\n");
+                       sb->s_flags |= MS_RDONLY;
                        break;
-               case UFS_FSBAD:         /* 0xFF */
+                   case UFS_FSBAD:
                        printk("ufs_read_super: fs is bad\n");
                        sb->s_flags |= MS_RDONLY;
                        break;
@@ -333,19 +637,19 @@ again:
                        sb->s_flags |= MS_RDONLY;
                        break;
                }
-       } else {
+       }
+       else {
                printk("ufs_read_super: fs needs fsck\n");
                sb->s_flags |= MS_RDONLY;
        }
 
-       sb->s_flags &= ~MS_RDONLY;
        /*
         * Read ufs_super_block into internal data structures
         */
        sb->s_blocksize =  SWAB32(usb1->fs_fsize);
        sb->s_blocksize_bits = SWAB32(usb1->fs_fshift);
        sb->s_op = &ufs_super_ops;
-       sb->dq_op = 0; /* XXX */
+       sb->dq_op = NULL; /***/
        sb->s_magic = SWAB32(usb3->fs_magic);
 
        uspi->s_sblkno = SWAB32(usb1->fs_sblkno);
@@ -385,12 +689,9 @@ again:
        uspi->s_ipg = SWAB32(usb1->fs_ipg);
        uspi->s_fpg = SWAB32(usb1->fs_fpg);
        uspi->s_cpc = SWAB32(usb2->fs_cpc);
-       ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0];
-       ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1];
-       uspi->s_qbmask = SWAB64(tmp);
-       ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0];
-       ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1];
-       uspi->s_qfmask = SWAB64(tmp);
+       uspi->s_contigsumsize = SWAB32(usb3->fs_u.fs_44.fs_contigsumsize);
+       uspi->s_qbmask = ufs_get_fs_qbmask(usb3);
+       uspi->s_qfmask = ufs_get_fs_qfmask(usb3);
        uspi->s_postblformat = SWAB32(usb3->fs_postblformat);
        uspi->s_nrpos = SWAB32(usb3->fs_nrpos);
        uspi->s_postbloff = SWAB32(usb3->fs_postbloff);
@@ -410,86 +711,32 @@ again:
        uspi->s_nspfshift = uspi->s_fshift - UFS_SECTOR_BITS;
        uspi->s_nspb = uspi->s_nspf << uspi->s_fpbshift;
        uspi->s_inopf = uspi->s_inopb >> uspi->s_fpbshift;
-
-       /* we could merge back s_swab and s_flags by having
-          foo.s_flags = flags | swab; here, and #defining
-          s_swab to s_flags & UFS_BYTESEX in swab.h */
+       uspi->s_bpf = uspi->s_fsize << 3;
+       uspi->s_bpfshift = uspi->s_fshift + 3;
+       uspi->s_bpfmask = uspi->s_bpf - 1;
+       
        sb->u.ufs_sb.s_flags = flags;
        sb->u.ufs_sb.s_swab = swab;
        sb->u.ufs_sb.s_rename_lock = 0;
        sb->u.ufs_sb.s_rename_wait = NULL;
-                                                                         
+                                                                         
        sb->s_root = d_alloc_root(iget(sb, UFS_ROOTINO), NULL);
 
-       /*
-        * Read cs structures from (usually) first data block
-        * on the device. 
-        */
-       size = uspi->s_cssize;
-       blks = howmany(size, uspi->s_fsize);
-       base = space = kmalloc(size, GFP_KERNEL);
-       if (!base)
-               goto failed; 
-       for (i = 0; i < blks; i += uspi->s_fpb) {
-               size = uspi->s_bsize;
-               if (i + uspi->s_fpb > blks)
-                       size = (blks - i) * uspi->s_fsize;
-               ubh = ubh_bread(sb->s_dev, uspi->s_csaddr + i, size);
-               if (!ubh)
-                       goto failed;
-               ubh_ubhcpymem (space, ubh, size);
-               sb->u.ufs_sb.s_csp[ufs_fragstoblks(i)] = (struct ufs_csum *)space;
-               space += size;
-               ubh_brelse (ubh);
-               ubh = NULL;
-       }
 
        /*
-        * Read cylinder group (we read only first fragment from block
-        * at this time) and prepare internal data structures for cg caching.
-        * XXX - something here fails on CDROMs from DEC!
+        * Read cylinder group structures
         */
-       if (!(sb->u.ufs_sb.s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL)))
-               goto failed;
-       for (i = 0; i < uspi->s_ncg; i++) 
-               sb->u.ufs_sb.s_ucg[i] = NULL;
-       for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
-               sb->u.ufs_sb.s_ucpi[i] = NULL;
-               sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY;
-       }
-       for (i = 0; i < uspi->s_ncg; i++) {
-               UFSD(("read cg %u\n", i))
-               if (!(sb->u.ufs_sb.s_ucg[i] = bread (sb->s_dev, ufs_cgcmin(i), sb->s_blocksize)))
-                       goto failed;
-               if (!ufs_cg_chkmagic ((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data))
-                       goto failed;
-#ifdef UFS_SUPER_DEBUG_MORE
-               ufs_print_cylinder_stuff((struct ufs_cylinder_group *) sb->u.ufs_sb.s_ucg[i]->b_data, swab);
-#endif
-       }
-       for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
-               if (!(sb->u.ufs_sb.s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL)))
+       if (!(sb->s_flags & MS_RDONLY))
+               if (!ufs_read_cylinder_structures(sb))
                        goto failed;
-               sb->u.ufs_sb.s_cgno[i] = UFS_CGNO_EMPTY;
-       }
-       sb->u.ufs_sb.s_cg_loaded = 0;
 
        unlock_super(sb);
        UFSD(("EXIT\n"))
        return(sb);
 
 failed:
-       if (ubh) ubh_brelse2 (ubh);
+       if (ubh) ubh_brelse_uspi (uspi);
        if (uspi) kfree (uspi);
-       if (base) kfree (base);
-
-       if (sb->u.ufs_sb.s_ucg) {
-               for (i = 0; i < uspi->s_ncg; i++)
-                       if (sb->u.ufs_sb.s_ucg[i]) brelse (sb->u.ufs_sb.s_ucg[i]);
-               kfree (sb->u.ufs_sb.s_ucg);
-               for (i = 0; i < UFS_MAX_GROUP_LOADED; i++)
-                       if (sb->u.ufs_sb.s_ucpi[i]) kfree (sb->u.ufs_sb.s_ucpi[i]);
-       }
        sb->s_dev = 0;
        unlock_super (sb);
        MOD_DEC_USE_COUNT;
@@ -497,187 +744,132 @@ failed:
        return(NULL);
 }
 
-/*
- * Put super block, release internal structures
- */
-void ufs_put_super (struct super_block * sb)
-{
-       struct ufs_sb_private_info * uspi;
-       struct ufs_buffer_head * ubh;
-       unsigned char * base, * space;
-       unsigned size, blks, i;
-       
-       UFSD(("ENTER\n"))
-       
-       uspi = sb->u.ufs_sb.s_uspi;
-       size = uspi->s_cssize;
-       blks = howmany(size, uspi->s_fsize);
-       base = space = (char*) sb->u.ufs_sb.s_csp[0];
-       for (i = 0; i < blks; i += uspi->s_fpb) {
-               size = uspi->s_bsize;
-               if (i + uspi->s_fpb > blks)
-                       size = (blks - i) * uspi->s_fsize;
-               ubh = ubh_bread (sb->s_dev, uspi->s_csaddr + i, size);
-               if (!ubh)
-                       goto go_on;
-               ubh_memcpyubh (ubh, space, size);
-               space += size;
-               ubh_mark_buffer_uptodate (ubh, 1);
-               ubh_mark_buffer_dirty (ubh, 0);
-               ubh_brelse (ubh);
-       }
-
-go_on:
-       for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
-               ufs_put_cylinder (sb, i);
-               kfree (sb->u.ufs_sb.s_ucpi[i]);
-       }
-       for (i = 0; i < uspi->s_ncg; i++) 
-               brelse (sb->u.ufs_sb.s_ucg[i]);
-       kfree (sb->u.ufs_sb.s_ucg);
-       kfree (base);
-       ubh_brelse2 (USPI_UBH);
-       kfree (sb->u.ufs_sb.s_uspi);
-       sb->s_dev = 0;
-       MOD_DEC_USE_COUNT;
-       return;
-}
-
-/*
- * Write super block to device
- */
 void ufs_write_super (struct super_block * sb) {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
        struct ufs_super_block_third * usb3;
-       unsigned swab;
-       
+       unsigned flags, swab;
+
        UFSD(("ENTER\n"))
        swab = sb->u.ufs_sb.s_swab;
+       flags = sb->u.ufs_sb.s_flags;
        uspi = sb->u.ufs_sb.s_uspi;
        usb1 = ubh_get_usb_first(USPI_UBH);
        usb3 = ubh_get_usb_third(USPI_UBH);
-       
+
        if (!(sb->s_flags & MS_RDONLY)) {
-               if (SWAB16(usb3->fs_u.fs_sun.fs_state) & UFS_FSOK)
-                       usb3->fs_u.fs_sun.fs_state = SWAB16(SWAB16(usb3->fs_u.fs_sun.fs_state) & ~UFS_FSOK);
                usb1->fs_time = SWAB32(CURRENT_TIME);
-               usb3->fs_u.fs_sun.fs_state = SWAB32(UFS_FSOK - SWAB32(usb1->fs_time));
+               if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN)
+                       ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time));
                ubh_mark_buffer_dirty (USPI_UBH, 1);
        }
        sb->s_dirt = 0;
        UFSD(("EXIT\n"))
 }
 
-/*
- * Copy some info about file system to user
- */
-int ufs_statfs(struct super_block * sb, struct statfs * buf, int bufsiz)
+void ufs_put_super (struct super_block * sb)
 {
        struct ufs_sb_private_info * uspi;
-       struct ufs_super_block_first * usb1;
-       struct statfs tmp;
-       struct statfs *sp = &tmp;
-       unsigned long used, avail;
        unsigned swab;
-       
+               
        UFSD(("ENTER\n"))
-       
-       swab = sb->u.ufs_sb.s_swab;
-       uspi = sb->u.ufs_sb.s_uspi;
-       usb1 = ubh_get_usb_first (USPI_UBH);
 
-       sp->f_type = UFS_MAGIC;
-       sp->f_bsize = sb->s_blocksize;
-       sp->f_blocks = uspi->s_dsize;
-       sp->f_bfree = (SWAB32(usb1->fs_cstotal.cs_nbfree) << uspi->s_fpbshift )+
-               SWAB32(usb1->fs_cstotal.cs_nffree);
+       uspi = sb->u.ufs_sb.s_uspi;
+       swab = sb->u.ufs_sb.s_swab;
 
-       avail = sp->f_blocks - (sp->f_blocks / 100) * uspi->s_minfree;
-       used = sp->f_blocks - sp->f_bfree;
-       if (avail > used)
-               sp->f_bavail = avail - used;
-       else
-               sp->f_bavail = 0;
-       sp->f_files = uspi->s_ncg * uspi->s_ipg;
-       sp->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
-       sp->f_fsid.val[0] = SWAB32(usb1->fs_id[0]);
-       sp->f_fsid.val[1] = SWAB32(usb1->fs_id[1]);
-       sp->f_namelen = UFS_MAXNAMLEN;
+       if (!(sb->s_flags & MS_RDONLY))
+               ufs_put_cylinder_structures (sb);
        
-       UFSD(("EXIT\n"))
-
-       return copy_to_user(buf, sp, bufsiz) ? -EFAULT : 0;
+       ubh_brelse_uspi (uspi);
+       kfree (sb->u.ufs_sb.s_uspi);
+       sb->s_dev = 0;
+       MOD_DEC_USE_COUNT;
+       return;
 }
 
 
-static char error_buf[1024];
-
-void ufs_warning (struct super_block * sb, const char * function,
-       const char * fmt, ...)
-{
-       va_list args;
-
-       va_start (args, fmt);
-       vsprintf (error_buf, fmt, args);
-       va_end (args);
-       printk (KERN_WARNING "UFS-fs warning (device %s): %s: %s\n",
-               kdevname(sb->s_dev), function, error_buf);
-}
-
-void ufs_error (struct super_block * sb, const char * function,
-       const char * fmt, ...)
+int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
-       va_list args;
-
+       struct ufs_super_block_third * usb3;
+       unsigned new_mount_opt, ufstype;
+       unsigned flags, swab;
+       
        uspi = sb->u.ufs_sb.s_uspi;
+       flags = sb->u.ufs_sb.s_flags;
+       swab = sb->u.ufs_sb.s_swab;
        usb1 = ubh_get_usb_first(USPI_UBH);
+       usb3 = ubh_get_usb_third(USPI_UBH);
        
-       if (!(sb->s_flags & MS_RDONLY)) {
-               usb1->fs_clean = UFS_FSBAD;
-               ubh_mark_buffer_dirty(USPI_UBH, 1);
-               sb->s_dirt = 1;
+       /*
+        * Allow the "check" option to be passed as a remount option.
+        * It is not possible to change ufstype option during remount
+        */
+       ufstype = sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE;
+       new_mount_opt = 0;
+       ufs_set_opt (new_mount_opt, ONERROR_LOCK);
+       if (!ufs_parse_options (data, &new_mount_opt))
+               return -EINVAL;
+       if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
+               new_mount_opt |= ufstype;
+       }
+       else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
+               printk("ufstype can't be changed during remount\n");
+               return -EINVAL;
+       }
+       sb->u.ufs_sb.s_mount_opt = new_mount_opt;
+
+       if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+               return 0;
+       if (*mount_flags & MS_RDONLY) {
+               ufs_put_cylinder_structures(sb);
+               usb1->fs_time = SWAB32(CURRENT_TIME);
+               if (usb1->fs_clean == UFS_FSCLEAN && (flags&UFS_ST_MASK) == UFS_ST_SUN)
+                       ufs_set_fs_state(usb3, UFS_FSOK - SWAB32(usb1->fs_time));
+               ubh_mark_buffer_dirty (USPI_UBH, 1);
+               sb->s_dirt = 0;
                sb->s_flags |= MS_RDONLY;
        }
-       va_start (args, fmt);
-       vsprintf (error_buf, fmt, args);
-       va_end (args);
-       printk (KERN_CRIT "UFS-fs error (device %s): %s: %s\n",
-               kdevname(sb->s_dev), function, error_buf);
+       else {
+               if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
+                   ufstype != UFS_MOUNT_UFSTYPE_44BSD) {
+                       printk("this ufstype is read-only supported\n");
+                       return 0;
+               }
+               if (!ufs_read_cylinder_structures (sb)) {
+                       printk("failed during remounting\n");
+                       return 0;
+               }
+               sb->s_flags &= ~MS_RDONLY;
+       }
+       return 0;
 }
 
-void ufs_panic (struct super_block * sb, const char * function,
-       const char * fmt, ...)
+int ufs_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
 {
        struct ufs_sb_private_info * uspi;
        struct ufs_super_block_first * usb1;
-       va_list args;
-       
+       struct statfs tmp;
+       unsigned swab;
+
+       swab = sb->u.ufs_sb.s_swab;
        uspi = sb->u.ufs_sb.s_uspi;
-       usb1 = ubh_get_usb_first(USPI_UBH);
+       usb1 = ubh_get_usb_first (USPI_UBH);
        
-       if (!(sb->s_flags & MS_RDONLY)) {
-               usb1->fs_clean = UFS_FSBAD;
-               ubh_mark_buffer_dirty(USPI_UBH, 1);
-               sb->s_dirt = 1;
-       }
-       va_start (args, fmt);
-       vsprintf (error_buf, fmt, args);
-       va_end (args);
-       /* this is to prevent panic from syncing this filesystem */
-       if (sb->s_lock)
-               sb->s_lock = 0;
-       sb->s_flags |= MS_RDONLY;
-       printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
-               kdevname(sb->s_dev), function, error_buf);
-/*     panic ("UFS-fs panic (device %s): %s: %s\n", 
-               kdevname(sb->s_dev), function, error_buf);
-*/
+       tmp.f_type = UFS_MAGIC;
+       tmp.f_bsize = sb->s_blocksize;
+       tmp.f_blocks = uspi->s_dsize;
+       tmp.f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) +
+               SWAB32(usb1->fs_cstotal.cs_nffree);
+       tmp.f_bavail = (tmp.f_bfree > ((tmp.f_blocks / 100) * uspi->s_minfree))
+               ? (tmp.f_bfree - ((tmp.f_blocks / 100) * uspi->s_minfree)) : 0;
+       tmp.f_files = uspi->s_ncg * uspi->s_ipg;
+       tmp.f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
+       tmp.f_namelen = UFS_MAXNAMLEN;
+       return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
 }
 
-
 static struct super_operations ufs_super_ops = {
        ufs_read_inode,
        ufs_write_inode,
@@ -687,20 +879,19 @@ static struct super_operations ufs_super_ops = {
        ufs_put_super,
        ufs_write_super,
        ufs_statfs,
-       NULL,                   /* XXX - ufs_remount() */
+       ufs_remount
 };
 
 static struct file_system_type ufs_fs_type = {
-       "ufs",
+       "ufs", 
        FS_REQUIRES_DEV,
        ufs_read_super,
        NULL
 };
 
-
 __initfunc(int init_ufs_fs(void))
 {
-       return(register_filesystem(&ufs_fs_type));
+       return register_filesystem(&ufs_fs_type);
 }
 
 #ifdef MODULE
@@ -715,5 +906,5 @@ void cleanup_module(void)
 {
        unregister_filesystem(&ufs_fs_type);
 }
-#endif
 
+#endif
index 527ba02aaca6b307e56f43343dba8472917fac62..23f5052bb523e3c3a041f2ee747713899e46127c 100644 (file)
@@ -49,7 +49,7 @@ failed:
        return NULL;
 }
 
-struct ufs_buffer_head * _ubh_bread2_ (struct ufs_sb_private_info * uspi,
+struct ufs_buffer_head * ubh_bread_uspi (struct ufs_sb_private_info * uspi,
        kdev_t dev, unsigned fragment, unsigned size)
 {
        unsigned i, j, count;
@@ -82,14 +82,14 @@ void ubh_brelse (struct ufs_buffer_head * ubh)
        kfree (ubh);
 }
 
-void ubh_brelse2 (struct ufs_buffer_head * ubh)
+void ubh_brelse_uspi (struct ufs_sb_private_info * uspi)
 {
        unsigned i;
-       if (!ubh)
+       if (!USPI_UBH)
                return;
-       for ( i = 0; i < ubh->count; i++ ) {
-               brelse (ubh->bh[i]);
-               ubh->bh[i] = NULL;
+       for ( i = 0; i < USPI_UBH->count; i++ ) {
+               brelse (USPI_UBH->bh[i]);
+               USPI_UBH->bh[i] = NULL;
        }
 }
 
@@ -138,8 +138,6 @@ unsigned ubh_max_bcount (struct ufs_buffer_head * ubh)
        for ( i = 0; i < ubh->count; i++ ) 
                if ( ubh->bh[i]->b_count > max )
                        max = ubh->bh[i]->b_count;
-       if (max == 0)
-               printk("Je cosi shnileho v kralovstvi Danskem!\n");
        return max;
 }
 
index 7443f9fc914e3360e5e64f088b0051fd4a76e271..1509c5bfce25bb44a2d09cc427f04c755171e5a6 100644 (file)
 #define max(x,y)               ((x)>(y)?(x):(y))
 
 
+
 /*
- * current filesystem state; method depends on flags
+ * macros used for retyping
  */
-#define ufs_state(usb3) \
-       (((flags & UFS_ST_MASK) == UFS_ST_OLD) \
-       ? (usb3)->fs_u.fs_sun.fs_state /* old normal way */ \
-       : (usb3)->fs_u.fs_44.fs_state /* 4.4BSD way */)
+#define UCPI_UBH ((struct ufs_buffer_head *)ucpi)
+#define USPI_UBH ((struct ufs_buffer_head *)uspi)
+
+
 
 /*
- * namlen, its format depends of flags
+ * macros used for accesing structures
  */
-#define ufs_namlen(de) _ufs_namlen_(de,flags,swab)
-static inline __u16 _ufs_namlen_(struct ufs_dir_entry * de, unsigned flags, unsigned swab) {
-       if ((flags & UFS_DE_MASK) == UFS_DE_OLD) {
-               return SWAB16(de->d_u.d_namlen);
-       } else /* UFS_DE_44BSD */ {
-               return de->d_u.d_44.d_namlen;
+#define ufs_get_fs_state(usb3) _ufs_get_fs_state_(usb3,flags,swab)
+static inline __s32 _ufs_get_fs_state_(struct ufs_super_block_third * usb3,
+       unsigned flags, unsigned swab)
+{
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN)
+               return SWAB32((usb3)->fs_u.fs_sun.fs_state);
+       else 
+               return SWAB32((usb3)->fs_u.fs_44.fs_state);
+}
+
+#define ufs_set_fs_state(usb3,value) _ufs_set_fs_state_(usb3,value,flags,swab)
+static inline void _ufs_set_fs_state_(struct ufs_super_block_third * usb3,
+       __s32 value, unsigned flags, unsigned swab)
+{
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN)
+               (usb3)->fs_u.fs_sun.fs_state = SWAB32(value);
+       else 
+               (usb3)->fs_u.fs_44.fs_state = SWAB32(value);
+}
+
+#define ufs_get_fs_qbmask(usb3) _ufs_get_fs_qbmask_(usb3,flags,swab)
+static inline __u64 _ufs_get_fs_qbmask_(struct ufs_super_block_third * usb3,
+       unsigned flags, unsigned swab)
+{
+       __u64 tmp;
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN) {
+               ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qbmask[0];
+               ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qbmask[1];
+       }
+       else {
+               ((u32 *)&tmp)[0] = usb3->fs_u.fs_44.fs_qbmask[0];
+               ((u32 *)&tmp)[1] = usb3->fs_u.fs_44.fs_qbmask[1];
        }
+       return SWAB64(tmp);
 }
 
-/*
- * Here is how the uid is computed:
- * if the file system is 4.2BSD, get it from oldids.
- * if it has sun extension and oldids is USEEFT, get it from ui_sun.
- * if it is 4.4 or Hurd, get it from ui_44 (which is the same as from ui_hurd).
- */
-#define ufs_uid(inode) _ufs_uid_(inode,flags,swab)
-static inline __u32 _ufs_uid_(struct ufs_inode * inode, unsigned flags, unsigned swab) {
+#define ufs_get_fs_qfmask(usb3) _ufs_get_fs_qfmask_(usb3,flags,swab)
+static inline __u64 _ufs_get_fs_qfmask_(struct ufs_super_block_third * usb3,
+       unsigned flags, unsigned swab)
+{
+       __u64 tmp;
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN) {
+               ((u32 *)&tmp)[0] = usb3->fs_u.fs_sun.fs_qfmask[0];
+               ((u32 *)&tmp)[1] = usb3->fs_u.fs_sun.fs_qfmask[1];
+       }
+       else {
+               ((u32 *)&tmp)[0] = usb3->fs_u.fs_44.fs_qfmask[0];
+               ((u32 *)&tmp)[1] = usb3->fs_u.fs_44.fs_qfmask[1];
+       }
+       return SWAB64(tmp);
+}
+
+#define ufs_get_de_namlen(de) \
+       (((flags & UFS_DE_MASK) == UFS_DE_OLD) \
+       ? SWAB16(de->d_u.d_namlen) \
+       : de->d_u.d_44.d_namlen)
+
+#define ufs_set_de_namlen(de,value) \
+       (((flags & UFS_DE_MASK) == UFS_DE_OLD) \
+       ? (de->d_u.d_namlen = SWAB16(value)) \
+       : (de->d_u.d_44.d_namlen = value))
+
+#define ufs_set_de_type(de,mode) _ufs_set_de_type_(de,mode,flags,swab)
+static inline void _ufs_set_de_type_(struct ufs_dir_entry * de, int mode, 
+       unsigned flags, unsigned swab)
+{
+       if ((flags & UFS_DE_MASK) == UFS_DE_44BSD) {
+               switch (mode & S_IFMT) {
+                       case S_IFSOCK: de->d_u.d_44.d_type = DT_SOCK; break;
+                       case S_IFLNK: de->d_u.d_44.d_type = DT_LNK; break;
+                       case S_IFREG: de->d_u.d_44.d_type = DT_REG; break;
+                       case S_IFBLK: de->d_u.d_44.d_type = DT_BLK; break;
+                       case S_IFDIR: de->d_u.d_44.d_type = DT_DIR; break;
+                       case S_IFCHR: de->d_u.d_44.d_type = DT_CHR; break;
+                       case S_IFIFO: de->d_u.d_44.d_type = DT_FIFO; break;
+                       default: de->d_u.d_44.d_type = DT_UNKNOWN;
+               }
+       }
+}
+
+#define ufs_get_inode_uid(inode) _ufs_get_inode_uid_(inode,flags,swab)
+static inline __u32 _ufs_get_inode_uid_(struct ufs_inode * inode,
+       unsigned flags, unsigned swab)
+{
        switch (flags & UFS_UID_MASK) {
                case UFS_UID_EFT:
                        return SWAB32(inode->ui_u3.ui_sun.ui_uid);
@@ -58,8 +126,30 @@ static inline __u32 _ufs_uid_(struct ufs_inode * inode, unsigned flags, unsigned
        }
 }
 
-#define ufs_gid(inode) _ufs_gid_(inode,flags,swab)
-static inline __u32 _ufs_gid_(struct ufs_inode * inode, unsigned flags, unsigned swab) {
+#define ufs_set_inode_uid(inode,value) _ufs_set_inode_uid_(inode,value,flags,swab)
+static inline void _ufs_set_inode_uid_(struct ufs_inode * inode, __u32 value,
+       unsigned flags, unsigned swab)
+{
+       
+       switch (flags & UFS_UID_MASK) {
+               case UFS_UID_EFT:
+                       inode->ui_u1.oldids.ui_suid = 
+                       inode->ui_u3.ui_sun.ui_uid = SWAB32(value);
+                       break;
+               case UFS_UID_44BSD:
+                       inode->ui_u1.oldids.ui_suid = 
+                       inode->ui_u3.ui_44.ui_uid = SWAB32(value);
+                       break;
+               case UFS_UID_OLD:
+               default:
+                       inode->ui_u1.oldids.ui_suid = SWAB16(value);
+       }
+}
+
+#define ufs_get_inode_gid(inode) _ufs_get_inode_gid_(inode,flags,swab)
+static inline __u32 _ufs_get_inode_gid_(struct ufs_inode * inode, 
+       unsigned flags, unsigned swab)
+{
        switch (flags & UFS_UID_MASK) {
                case UFS_UID_EFT:
                        return SWAB32(inode->ui_u3.ui_sun.ui_gid);
@@ -71,21 +161,35 @@ static inline __u32 _ufs_gid_(struct ufs_inode * inode, unsigned flags, unsigned
        }
 }
 
-/*
- * macros used to avoid needless retyping
- */
-#define UCPI_UBH ((struct ufs_buffer_head *)ucpi)
-#define USPI_UBH ((struct ufs_buffer_head *)uspi)
+#define ufs_set_inode_gid(inode,value) _ufs_set_inode_gid_(inode,value,flags,swab)
+static inline void _ufs_set_inode_gid_(struct ufs_inode * inode, __u32 value, 
+       unsigned flags, unsigned swab)
+{
+       switch (flags & UFS_UID_MASK) {
+               case UFS_UID_EFT:
+                       inode->ui_u1.oldids.ui_sgid = 
+                       inode->ui_u3.ui_sun.ui_gid = SWAB32(value);
+                       break;
+               case UFS_UID_44BSD:
+                       inode->ui_u1.oldids.ui_sgid = 
+                       inode->ui_u3.ui_44.ui_gid = SWAB32(value);
+                       break;
+               case UFS_UID_OLD:
+               default:
+                       inode->ui_u1.oldids.ui_sgid = SWAB16(value);
+       }
+}
+
+
 
 /*
  * These functions manipulate ufs buffers
  */
 #define ubh_bread(dev,fragment,size) _ubh_bread_(uspi,dev,fragment,size)  
 extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned);
-#define ubh_bread2(dev,fragment,size) _ubh_bread2_(uspi,dev,fragment,size)  
-extern struct ufs_buffer_head * _ubh_bread2_(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned);
+extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, kdev_t, unsigned, unsigned);
 extern void ubh_brelse (struct ufs_buffer_head *);
-extern void ubh_brelse2 (struct ufs_buffer_head *);
+extern void ubh_brelse_uspi (struct ufs_sb_private_info *);
 extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *, int);
 extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int);
 extern void ubh_ll_rw_block (int, unsigned, struct ufs_buffer_head **);
@@ -98,6 +202,8 @@ extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struc
 #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size)
 extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned);
 
+
+
 /*
  * macros to get important structures from ufs_buffer_head
  */
@@ -115,25 +221,29 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
 #define ubh_get_ucg(ubh) \
        ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data))
 
+
 /*
  * Extract byte from ufs_buffer_head
  * Extract the bits for a block from a map inside ufs_buffer_head
  */
 #define ubh_get_addr8(ubh,begin) \
-       ((u8*)(ubh)->bh[(begin) >> uspi->s_fshift]->b_data + ((begin) & ~uspi->s_fmask))
+       ((u8*)(ubh)->bh[(begin) >> uspi->s_fshift]->b_data + \
+       ((begin) & ~uspi->s_fmask))
 
 #define ubh_get_addr16(ubh,begin) \
-       (((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + ((begin) & (uspi->fsize>>1) - 1)))
+       (((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
+       ((begin) & (uspi->fsize>>1) - 1)))
 
 #define ubh_get_addr32(ubh,begin) \
-       (((u32*)((ubh)->bh[(begin) >> (BLOCK_SIZE_BITS-2)]->b_data)) + \
-       ((begin) & ((BLOCK_SIZE>>2) - 1)))
+       (((u32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
+       ((begin) & ((uspi->s_fsize>>2) - 1)))
 
 #define ubh_get_addr ubh_get_addr8
 
 #define ubh_blkmap(ubh,begin,bit) \
        ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
 
+
 /*
  * Macros for access to superblock array structures
  */
@@ -188,45 +298,90 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
 
 #define ubh_isclr(ubh,begin,bit) (!ubh_isset(ubh,begin,bit))
 
-#define ubh_find_first_zero_bit(ubh,begin,size) \
-       _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0)
-#define ubh_find_next_zero_bit(ubh,begin,size,offset) \
-       _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset)
+#define ubh_find_first_zero_bit(ubh,begin,size) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0)
 
+#define ubh_find_next_zero_bit(ubh,begin,size,offset) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset)
 static inline unsigned _ubh_find_next_zero_bit_(
        struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh,
        unsigned begin, unsigned size, unsigned offset)
 {
-       unsigned base, rest;
+       unsigned base, count, pos;
 
+       size -= offset;
        begin <<= 3;
-       size += begin;
        offset += begin;
-       base = offset >> (uspi->s_fshift + 3);
-       offset &= ((uspi->s_fsize << 3) - 1);
+       base = offset >> uspi->s_bpfshift;
+       offset &= uspi->s_bpfmask;
        for (;;) {
-               rest = min (size, uspi->s_fsize << 3);
-               size -= rest;
-               offset = ext2_find_next_zero_bit (ubh->bh[base]->b_data, rest, offset);
-               if (offset < rest || !size)
+               count = min (size + offset, uspi->s_bpf);
+               size -= count - offset;
+               pos = ext2_find_next_zero_bit (ubh->bh[base]->b_data, count, offset);
+               if (pos < count + offset || !size)
                        break;
                base++;
                offset = 0;
        }
-       return (base << (uspi->s_fshift + 3)) + offset - begin;
+       return (base << uspi->s_bpfshift) + pos - begin;
 }      
 
-#define ubh_isblockclear(ubh,begin,block) \
-       (!_ubh_isblockset_(uspi,ubh,begin,block))
-#define ubh_isblockset(ubh,begin,block) \
-       _ubh_isblockset_(uspi,ubh,begin,block)
+static inline unsigned find_last_zero_bit (unsigned char * bitmap,
+       unsigned size, unsigned offset)
+{
+       unsigned bit, i;
+       unsigned char * mapp;
+       unsigned char map;
+
+       mapp = bitmap + (size >> 3);
+       map = *mapp--;
+       bit = 1 << (size & 7);
+       for (i = size; i > offset; i--) {
+               if ((map & bit) == 0)
+                       break;
+               if ((i & 7) != 0) {
+                       bit >>= 1;
+               } else {
+                       map = *mapp--;
+                       bit = 1 << 7;
+               }
+       }
+       return i;
+}
 
+#define ubh_find_last_zero_bit(ubh,begin,size,offset) _ubh_find_last_zero_bit_(uspi,ubh,begin,size,offset)
+static inline unsigned _ubh_find_last_zero_bit_(
+       struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh,
+       unsigned begin, unsigned start, unsigned end)
+{
+       unsigned base, count, pos, size;
+
+       size = start - end;
+       begin <<= 3;
+       start += begin;
+       base = start >> uspi->s_bpfshift;
+       start &= uspi->s_bpfmask;
+       for (;;) {
+               count = min (size + (uspi->s_bpf - start), uspi->s_bpf)
+                       - (uspi->s_bpf - start);
+               size -= count;
+               pos = find_last_zero_bit (ubh->bh[base]->b_data,
+                       start, start - count);
+               if (pos > start - count || !size)
+                       break;
+               base--;
+               start = uspi->s_bpf;
+       }
+       return (base << uspi->s_bpfshift) + pos - begin;
+}      
+
+#define ubh_isblockclear(ubh,begin,block) (!_ubh_isblockset_(uspi,ubh,begin,block))
+
+#define ubh_isblockset(ubh,begin,block) _ubh_isblockset_(uspi,ubh,begin,block)
 static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi,
        struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
 {
        switch (uspi->s_fpb) {
        case 8:
-               return (*ubh_get_addr (ubh, begin + block) == 0xff);
+               return (*ubh_get_addr (ubh, begin + block) == 0xff);
        case 4:
                return (*ubh_get_addr (ubh, begin + (block >> 1)) == (0x0f << ((block & 0x01) << 2)));
        case 2:
@@ -243,8 +398,8 @@ static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi,
 {
        switch (uspi->s_fpb) {
        case 8:
-               *ubh_get_addr (ubh, begin + block) = 0x00;
-               return; 
+               *ubh_get_addr (ubh, begin + block) = 0x00;
+               return; 
        case 4:
                *ubh_get_addr (ubh, begin + (block >> 1)) &= ~(0x0f << ((block & 0x01) << 2));
                return;
@@ -263,8 +418,8 @@ static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi,
 {
        switch (uspi->s_fpb) {
        case 8:
-               *ubh_get_addr(ubh, begin + block) = 0xff;
-               return;
+               *ubh_get_addr(ubh, begin + block) = 0xff;
+               return;
        case 4:
                *ubh_get_addr(ubh, begin + (block >> 1)) |= (0x0f << ((block & 0x01) << 2));
                return;
@@ -301,8 +456,7 @@ static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
                ADD_SWAB32(fraglist[fragsize], cnt);
 }
 
-#define ubh_scanc(ubh,begin,size,table,mask) \
-       _ubh_scanc_(uspi,ubh,begin,size,table,mask)
+#define ubh_scanc(ubh,begin,size,table,mask) _ubh_scanc_(uspi,ubh,begin,size,table,mask)
 static inline unsigned _ubh_scanc_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, 
        unsigned begin, unsigned size, unsigned char * table, unsigned char mask)
 {
index b4c55a0bb042fb05f92124c82fa5f583a073a438..29b359d018cb4bbb593f8037362942ebf8091b5f 100644 (file)
@@ -6,7 +6,7 @@
 #define TASK_ADDR_LIMIT 24
 #define TASK_EXEC_DOMAIN 32
 #define TASK_NEED_RESCHED 40
-#define TASK_SIZE 1120
+#define TASK_SIZE 1096
 #define STACK_SIZE 16384
 #define HAE_CACHE 0
 #define HAE_REG 8
index 6ea27483064d34dacdd2f6d05e8fd4b12a953e6d..89f39911f33726e0ef835467f2a9bb38b7b12a25 100644 (file)
 #define ENV_LANGUAGE           0x0E
 #define ENV_TTY_DEV            0x0F
 
-#endif
+#ifdef __KERNEL__
+extern long srm_dispatch(long code, ...);
+extern void srm_puts(const char *);
+extern long srm_printk(const char *, ...)
+       __attribute__ ((format (printf, 1, 2)));
+
+struct crb_struct;
+struct hwrpb_struct;
+extern long srm_fixup(struct crb_struct *, struct hwrpb_struct *);
+#endif /* __KERNEL__ */
+
+#endif /* __AXP_CONSOLE_H */
index 7df92de11270b951858c76ea25ded8576526a901..7c0d5a591eeaca44913641a4058e3bbe9a7db538 100644 (file)
@@ -18,6 +18,7 @@
 #define O_SYNC         040000
 #define FASYNC         020000  /* fcntl, for BSD compatibility */
 #define O_DIRECT       040000  /* direct disk access - should check with OSF/1 */
+#define O_DIRECTORY    0100000 /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index 1b0c1a05142c60634689b06b1378295df2d54ebf..1468b28e33c00b46cc59bcc68a2254a06505c313 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/tasks.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
+extern unsigned long hardirq_no[NR_CPUS];
 
 /*
  * Are we in an interrupt context? Either doing bottom half
@@ -32,6 +33,7 @@ extern unsigned int local_irq_count[NR_CPUS];
 
 #include <asm/atomic.h>
 #include <asm/spinlock.h>
+#include <asm/smp.h>
 
 extern int global_irq_holder;
 extern spinlock_t global_irq_lock;
@@ -50,10 +52,12 @@ static inline void hardirq_enter(int cpu, int irq)
 {
        ++local_irq_count[cpu];
         atomic_inc(&global_irq_count);
+       hardirq_no[cpu] |= 1L << irq;           /* debugging only */
 }
 
 static inline void hardirq_exit(int cpu, int irq)
 {
+       hardirq_no[cpu] &= ~(1L << irq);        /* debugging only */
        atomic_dec(&global_irq_count);
         --local_irq_count[cpu];
 }
index 6ab7225e361d0a9a1047ca02cffbb5f223d54b1e..69823af357c43fa1b42013f6e40206f566299a6e 100644 (file)
@@ -185,6 +185,19 @@ struct hwrpb_struct {
        unsigned long dsr_offset;       /* "Dynamic System Recognition Data Block Table" */
 };
 
+#ifdef __KERNEL__
+
 extern struct hwrpb_struct *hwrpb;
 
+static inline void
+hwrpb_update_checksum(struct hwrpb_struct *h)
+{
+       unsigned long sum = 0, *l;
+        for (l = (unsigned long *) h; l < (unsigned long *) &h->chksum; ++l)
+                sum += *l;
+        h->chksum = sum;
+}
+
+#endif /* __KERNEL__ */
+
 #endif /* __ALPHA_HWRPB_H */
index 516fff5e17615ead85eb716177b9936c69d6a5f6..51d2af5968920e6f98ab422a463672dd1050568e 100644 (file)
@@ -323,23 +323,14 @@ out:
 
 #ifdef CONFIG_ALPHA_GENERIC
 # define RTC_PORT(x)   ((x) + alpha_mv.rtc_port)
-# define RTC_ADDR(x)   ((x) | alpha_mv.rtc_addr)
-# define RTC_ALWAYS_BCD        (alpha_mv.rtc_bcd)
 #else
 # ifdef CONFIG_ALPHA_JENSEN
 #  define RTC_PORT(x)  (0x170+(x))
-#  define RTC_ADDR(x)  (x)
 # else
 #  define RTC_PORT(x)  (0x70 + (x))
-#  define RTC_ADDR(x)  (0x80 | (x))
-# endif
-# ifdef CONFIG_ALPHA_RUFFIAN
-#  define RTC_ALWAYS_BCD       1
-# else
-#  define RTC_ALWAYS_BCD       0
 # endif
 #endif
-
+#define RTC_ALWAYS_BCD 0
 
 #endif /* __KERNEL__ */
 
index eb39cffc195b28140270d0b8b3e319128d4bb63e..17d50c777690e34780bbb673faa7e278751f1a28 100644 (file)
@@ -22,11 +22,9 @@ struct alpha_machine_vector
        unsigned long hae_cache;
        unsigned long *hae_register;
 
-       unsigned int nr_irqs  : 16;
-       unsigned int rtc_port : 16;
-       unsigned int rtc_addr : 15;
-       unsigned int rtc_bcd  : 1;
-       unsigned int max_asn  : 16;
+       int nr_irqs;
+       int rtc_port;
+       int max_asn;
        unsigned long max_dma_address;
        unsigned long mmu_context_mask;
        unsigned long irq_probe_mask;
index df86116d3b56b48b4166e2ae6b20e276a685ce71..eb5d487a5210cb4b4a028ede0126e07d6009caa7 100644 (file)
@@ -59,7 +59,9 @@ struct thread_struct {
        mm_segment_t fs;
 
        /* Breakpoint handling for ptrace.  */
-       long debugreg[8];
+       unsigned long bpt_addr[2];
+       unsigned int bpt_insn[2];
+       int bpt_nsaved;
 };
 
 #define INIT_MMAP { &init_mm, PAGE_OFFSET,  PAGE_OFFSET+0x10000000, \
index 5fae6e924555ce643a0d47cb949f3c6186b8c552..194d5f1b7a2bc905ee99404d3c7a8e88754a28ed 100644 (file)
@@ -63,15 +63,24 @@ typedef struct { int dummy; } rwlock_t;
  */
 
 typedef struct {
-       volatile unsigned long lock;
+       volatile unsigned int lock;
+#if DEBUG_SPINLOCK
+       char debug_state, target_ipl, saved_ipl, on_cpu;
        void *previous;
        struct task_struct * task;
+#endif
 } spinlock_t;
 
-#define SPIN_LOCK_UNLOCKED { 0, 0, 0 }
+#if DEBUG_SPINLOCK
+#define SPIN_LOCK_UNLOCKED {0, 1, 0, 0, 0, 0}
+#define spin_lock_init(x)                                              \
+       ((x)->lock = 0, (x)->target_ipl = 0, (x)->debug_state = 1,      \
+        (x)->previous = 0, (x)->task = 0)
+#else
+#define SPIN_LOCK_UNLOCKED     { 0 }
+#define spin_lock_init(x)      ((x)->lock = 0)
+#endif
 
-#define spin_lock_init(x) \
-       ((x)->lock = 0, (x)->previous = 0, (x)->task = 0)
 #define spin_unlock_wait(x) \
        ({ do { barrier(); } while(((volatile spinlock_t *)x)->lock); })
 
@@ -79,8 +88,25 @@ typedef struct { unsigned long a[100]; } __dummy_lock_t;
 #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
 
 #if DEBUG_SPINLOCK
+extern void spin_unlock(spinlock_t * lock);
 extern void spin_lock(spinlock_t * lock);
+extern int spin_trylock(spinlock_t * lock);
+
+#define spin_lock_own(LOCK, LOCATION)                                  \
+do {                                                                   \
+       if (!((LOCK)->lock && (LOCK)->on_cpu == smp_processor_id()))    \
+               printk("%s: called on %d from %p but lock %s on %d\n",  \
+                      LOCATION, smp_processor_id(),                    \
+                      __builtin_return_address(0),                     \
+                      (LOCK)->lock ? "taken" : "freed", (LOCK)->on_cpu); \
+} while (0)
 #else
+static inline void spin_unlock(spinlock_t * lock)
+{
+       mb();
+       lock->lock = 0;
+}
+
 static inline void spin_lock(spinlock_t * lock)
 {
        long tmp;
@@ -89,29 +115,24 @@ static inline void spin_lock(spinlock_t * lock)
           of this object file's text section so as to perfect
           branch prediction.  */
        __asm__ __volatile__(
-       "1:     ldq_l   %0,%1\n"
+       "1:     ldl_l   %0,%1\n"
        "       blbs    %0,2f\n"
        "       or      %0,1,%0\n"
-       "       stq_c   %0,%1\n"
+       "       stl_c   %0,%1\n"
        "       beq     %0,2f\n"
        "       mb\n"
        ".section .text2,\"ax\"\n"
-       "2:     ldq     %0,%1\n"
+       "2:     ldl     %0,%1\n"
        "       blbs    %0,2b\n"
        "       br      1b\n"
        ".previous"
        : "=r" (tmp), "=m" (__dummy_lock(lock))
        : "m"(__dummy_lock(lock)));
 }
-#endif /* DEBUG_SPINLOCK */
-
-static inline void spin_unlock(spinlock_t * lock)
-{
-       mb();
-       lock->lock = 0;
-}
 
 #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
+#define spin_lock_own(LOCK, LOCATION)  ((void)0)
+#endif /* DEBUG_SPINLOCK */
 
 #define spin_lock_irq(lock) \
   (__cli(), spin_lock(lock))
index 4ed5d54819b471449c8f1ed51fa53d157c75e54d..798207747f95c2d0ce6dfa592f690e1ff1381af5 100644 (file)
@@ -95,8 +95,7 @@ extern void wrmces (unsigned long);
 extern unsigned long whami(void);
 extern void wripir(unsigned long);
 
-#define halt() \
-__asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt) : "memory")
+extern void halt(void) __attribute__((noreturn));
 
 #define switch_to(prev,next) do {                                      \
        current = next;                                                 \
index a9e469a492ce96739108847e1969c363fb02cc68..61933734e84813e96b1c37def39b10ff1cc55ea0 100644 (file)
@@ -16,6 +16,7 @@
 #define O_NDELAY       O_NONBLOCK
 #define O_SYNC         010000
 #define FASYNC         020000  /* fcntl, for BSD compatibility */
+#define O_DIRECTORY    040000  /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index f0ddc3e616fc3c7f58bcec296731036746781137..64f8e61d0ade79ca08fc9b6c4f9bcd0f8e77c670 100644 (file)
@@ -18,6 +18,7 @@
 #define FASYNC          020000 /* fcntl, for BSD compatibility */
 #define O_DIRECT        040000 /* direct disk access hint - currently ignored */
 #define O_LARGEFILE    0100000
+#define O_DIRECTORY    0200000 /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index 500d495bf21b0770c2b691b72fff247a368203be..132abcec412ddcb2d69ab8303543a26e9a2f843c 100644 (file)
@@ -16,6 +16,7 @@
 #define O_NDELAY       O_NONBLOCK
 #define O_SYNC         010000
 #define FASYNC         020000  /* fcntl, for BSD compatibility */
+#define O_DIRECTORY    040000  /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index d40aac7e84540aed83f8c984860a9427f57f37bd..b1652d03f2328423a04ecc6504edefe4c62dfc4b 100644 (file)
@@ -15,6 +15,7 @@
 #define O_EXCL         0x0400  /* not fcntl */
 #define O_NOCTTY       0x0800  /* not fcntl */
 #define FASYNC         0x1000  /* fcntl, for BSD compatibility */
+#define O_DIRECTORY    0x2000  /* must be a directory */
 
 #define O_NDELAY       O_NONBLOCK
 
index 773e6a252435e71cb981880ebb653b36df7f632b..dac4b05dcc762fd0618629b87fbd34a974c2a3f9 100644 (file)
@@ -16,6 +16,7 @@
 #define O_NDELAY       O_NONBLOCK
 #define O_SYNC         010000
 #define FASYNC         020000  /* fcntl, for BSD compatibility */
+#define O_DIRECTORY    040000  /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index a8a3423cdeed969c6ccf1caea508cc17e94ec337..e2e7ecd8c0543ae7cb31cf1fdd8982237fb4c06e 100644 (file)
@@ -17,6 +17,7 @@
 #define O_NONBLOCK     0x4000
 #define O_NDELAY       (0x0004 | O_NONBLOCK)
 #define O_NOCTTY       0x8000  /* not fcntl */
+#define O_DIRECTORY    0x10000 /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index 9fca6fdb5277f1d3c8ca5f13e87e8f253bfd7264..e0d1d5e297ec1ce1d6a42182d80ecb383de68770 100644 (file)
@@ -17,6 +17,7 @@
 #define O_SYNC         0x2000
 #define O_NONBLOCK     0x4000
 #define O_NOCTTY       0x8000  /* not fcntl */
+#define O_DIRECTORY    0x10000 /* must be a directory */
 
 #define F_DUPFD                0       /* dup */
 #define F_GETFD                1       /* get f_flags */
index e069791f2b222abdd3a44c77b8ffb17dc4ec3656..e0d904fc16c76da5fbb43a2fba7ef2abdceb91c8 100644 (file)
@@ -147,13 +147,13 @@ static void floppy_off(unsigned int nr);
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
-#elif (MAJOR_NR == SCSI_DISK_MAJOR)
+#elif (SCSI_DISK_MAJOR(MAJOR_NR))
 
 #define DEVICE_NAME "scsidisk"
 #define DEVICE_INTR do_sd  
 #define TIMEOUT_VALUE (2*HZ)
 #define DEVICE_REQUEST do_sd_request
-#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_NR(device) (((MAJOR(device) & SD_MAJOR_MASK) << (8 - 4)) + (MINOR(device) >> 4))
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
index 41bd00856b821e789809fdedbde34b32a9e318cb..bb1d2a5844f104033acd3170febbc625db2be6aa 100644 (file)
@@ -85,10 +85,14 @@ struct loop_info {
  * Loop filter types
  */
 
-#define LO_CRYPT_NONE  0
-#define LO_CRYPT_XOR   1
-#define LO_CRYPT_DES   2
-#define LO_CRYPT_DUMMY     9
+#define LO_CRYPT_NONE    0
+#define LO_CRYPT_XOR     1
+#define LO_CRYPT_DES     2
+#define LO_CRYPT_FISH2    3    /* Brand new Twofish encryption */
+#define LO_CRYPT_BLOW     4
+#define LO_CRYPT_CAST128  5
+#define LO_CRYPT_IDEA     6
+#define LO_CRYPT_DUMMY    9
 #define LO_CRYPT_SKIPJACK 10
 #define MAX_LO_CRYPT   20
 
index 937df93864f4220992623f5d7ff21e7611fc99fd..15656ff08ca3df9e909696a49fac352d4c8b98e5 100644 (file)
 /* The parallel port specs apparently say that there needs to be
  * a .5usec wait before and after the strobe.  Since there are wildly
  * different computers running linux, I can't come up with a perfect
- * value, but since it worked well on most printers before without,
- * I'll initialize it to 0.
+ * value so if 20 is not good for you use `tunelp /dev/lp? -w ?`.
+ * You can also set it to 0 if your printer handle that.
  */
 
-#define LP_INIT_WAIT 0
+#define LP_INIT_WAIT 20
 
 /* This is the amount of time that the driver waits for the printer to
  * catch up when the printer's buffer appears to be filled.  If you
index 9c76aeba3ee937c47957f5370f5156d11c4922d5..66e7ee8291f4eecc90c022ecd956c4ac8dae8caf 100644 (file)
@@ -28,7 +28,7 @@
 #define LP_MAJOR       6
 #define VCS_MAJOR      7
 #define LOOP_MAJOR     7
-#define SCSI_DISK_MAJOR        8
+#define SCSI_DISK0_MAJOR 8
 #define SCSI_TAPE_MAJOR        9
 #define MD_MAJOR        9
 #define MISC_MAJOR     10
 #define IDE4_MAJOR     56
 #define IDE5_MAJOR     57
 
+#define SCSI_DISK1_MAJOR       65
+#define SCSI_DISK2_MAJOR       66
+#define SCSI_DISK3_MAJOR       67
+#define SCSI_DISK4_MAJOR       68
+#define SCSI_DISK5_MAJOR       69
+#define SCSI_DISK6_MAJOR       70
+#define SCSI_DISK7_MAJOR       71
+
 #define SPECIALIX_NORMAL_MAJOR 75
 #define SPECIALIX_CALLOUT_MAJOR 76
 
  * Tests for SCSI devices.
  */
 
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+  
 #define SCSI_BLK_MAJOR(M) \
-  ((M) == SCSI_DISK_MAJOR      \
+  (SCSI_DISK_MAJOR(M)  \
    || (M) == SCSI_CDROM_MAJOR)
 
 static __inline__ int scsi_blk_major(int m) {
index d5b6081991b78b186014402ffef5d02ba295dc2b..29692b65cf0a7213ae247acad03ee3d13403cc6c 100644 (file)
@@ -380,6 +380,36 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m
        return vma;
 }
 
+extern __inline__ void kswapd_wakeup(void)
+{
+       wake_up(&kswapd_wait);
+}
+
+#define buffer_under_min()     ((buffermem >> PAGE_SHIFT) * 100 < \
+                               buffer_mem.min_percent * num_physpages)
+#define buffer_under_borrow()  ((buffermem >> PAGE_SHIFT) * 100 < \
+                               buffer_mem.borrow_percent * num_physpages)
+#define buffer_under_max()     ((buffermem >> PAGE_SHIFT) * 100 < \
+                               buffer_mem.max_percent * num_physpages)
+#define buffer_over_min()      ((buffermem >> PAGE_SHIFT) * 100 > \
+                               buffer_mem.min_percent * num_physpages)
+#define buffer_over_borrow()   ((buffermem >> PAGE_SHIFT) * 100 > \
+                               buffer_mem.borrow_percent * num_physpages)
+#define buffer_over_max()      ((buffermem >> PAGE_SHIFT) * 100 > \
+                               buffer_mem.max_percent * num_physpages)
+#define pgcache_under_min()    (page_cache_size * 100 < \
+                               page_cache.min_percent * num_physpages)
+#define pgcache_under_borrow() (page_cache_size * 100 < \
+                               page_cache.borrow_percent * num_physpages)
+#define pgcache_under_max()    (page_cache_size * 100 < \
+                               page_cache.max_percent * num_physpages)
+#define pgcache_over_min()     (page_cache_size * 100 > \
+                               page_cache.min_percent * num_physpages)
+#define pgcache_over_borrow()  (page_cache_size * 100 > \
+                               page_cache.borrow_percent * num_physpages)
+#define pgcache_over_max()     (page_cache_size * 100 > \
+                               page_cache.max_percent * num_physpages)
+
 #endif /* __KERNEL__ */
 
 #endif
index a840395e31a0d71c5006e679c12ef034439a603f..ac6dbb3e9cac79d920c94b1dd771b43458436425 100644 (file)
@@ -123,7 +123,7 @@ struct parport_operations {
 
        void (*enable_irq)(struct parport *);
        void (*disable_irq)(struct parport *);
-       int (*examine_irq)(struct parport *);
+       void (*interrupt)(int, void *, struct pt_regs *);
 
        void (*inc_use_count)(void);
        void (*dec_use_count)(void);
@@ -206,7 +206,9 @@ struct parport {
        void *private_data;     /* for lowlevel driver */
 
        int number;             /* port index - the `n' in `parportn' */
-       spinlock_t lock;
+       spinlock_t pardevice_lock;
+       spinlock_t waitlist_lock;
+       spinlock_t cad_lock;
 };
 
 /* parport_register_port registers a new parallel port at the given address (if
@@ -234,10 +236,9 @@ struct parport *parport_enumerate(void);
 
 /* parport_register_device declares that a device is connected to a port, and 
  * tells the kernel all it needs to know.  
- * pf is the preemption function (may be NULL for a transient driver)
- * kf is the wake-up function (may be NULL for a transient driver)
+ * pf is the preemption function (may be NULL for no callback)
+ * kf is the wake-up function (may be NULL for no callback)
  * irq_func is the interrupt handler (may be NULL for no interrupts)
- * Only one lurking driver can be used on a given port. 
  * handle is a user pointer that gets handed to callback functions. 
  */
 struct pardevice *parport_register_device(struct parport *port, 
@@ -294,11 +295,31 @@ extern __inline__ int parport_yield_blocking(struct pardevice *dev)
        return parport_claim_or_block(dev);
 }
 
+/*
+ * Lowlevel drivers _can_ call this support function to handle irqs.
+ */
+extern __inline__ void parport_generic_irq(int irq, struct parport *port,
+                                          struct pt_regs *regs)
+{
+       read_lock(&port->cad_lock);
+       if (!port->cad)
+               goto out_unlock;
+       if (port->cad->irq_func)
+               port->cad->irq_func(irq, port->cad->private, regs);
+       else
+               printk(KERN_ERR "%s: irq%d happened with irq_func NULL "
+                      "with %s as cad!\n", port->name, irq, port->cad->name);
+ out_unlock:
+       read_unlock(&port->cad_lock);
+}
+
 /* Flags used to identify what a device does. */
-#define PARPORT_DEV_TRAN               0x0000  /* We're transient. */
-#define PARPORT_DEV_LURK               0x0001  /* We lurk. */
+#define PARPORT_DEV_TRAN               0       /* WARNING !! DEPRECATED !! */
+#define PARPORT_DEV_LURK               (1<<0)  /* WARNING !! DEPRECATED !! */
+#define PARPORT_DEV_EXCL               (1<<1)  /* Need exclusive access. */
 
-#define PARPORT_FLAG_COMA              1
+#define PARPORT_FLAG_COMA              (1<<0)
+#define PARPORT_FLAG_EXCL              (1<<1)  /* EXCL driver registered. */
 
 extern void parport_parse_irqs(int, const char *[], int irqval[]);
 extern int parport_ieee1284_nibble_mode_ok(struct parport *, unsigned char);
index b61a970a72b613bc0cd84bf8da3ec998ea64dd5b..65d8209e526f0e72f38737b5acbb59c96cd3534c 100644 (file)
@@ -132,8 +132,6 @@ extern int parport_pc_ecp_read_block(struct parport *p, void *buf, size_t length
 
 extern int parport_pc_ecp_write_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle);
 
-extern int parport_pc_examine_irq(struct parport *p);
-
 extern void parport_pc_inc_use_count(void);
 
 extern void parport_pc_dec_use_count(void);
index d820bc848f465c73377f02088552d4451a1613c1..7aa5b82adc84797b1a91be6e4b669477ae7f14be 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *     $Id: pci.h,v 1.84 1998/08/17 23:06:43 cort Exp $
+ *     $Id: pci.h,v 1.87 1998/10/11 15:13:12 mj Exp $
  *
  *     PCI defines and function prototypes
  *     Copyright 1994, Drew Eckhardt
 #define PCI_DEVICE_ID_ADAPTEC_7884     0x8478
 #define PCI_DEVICE_ID_ADAPTEC_1030     0x8b78
 
-#define PCI_VENDOR_ID_ADAPTEC2  0x9005
-#define PCI_DEVICE_ID_ADAPTEC2_2940U2  0x0010
-#define PCI_DEVICE_ID_ADAPTEC2_7890  0x001f
-#define PCI_DEVICE_ID_ADAPTEC2_3940U2  0x0050
-#define PCI_DEVICE_ID_ADAPTEC2_7896  0x005f
-
+#define PCI_VENDOR_ID_ADAPTEC2         0x9005
+#define PCI_DEVICE_ID_ADAPTEC2_2940U2  0x0010
+#define PCI_DEVICE_ID_ADAPTEC2_7890    0x001f
+#define PCI_DEVICE_ID_ADAPTEC2_3940U2  0x0050
+#define PCI_DEVICE_ID_ADAPTEC2_7896    0x005f
 
 #define PCI_VENDOR_ID_ATRONICS         0x907f
 #define PCI_DEVICE_ID_ATRONICS_2015    0x2015
index af18e4b9f299c2fdcd2f8f7faa83fe64d3fae179..23ae8a1e22056263875a3a21775ace9bc6e498bf 100644 (file)
@@ -33,7 +33,7 @@ typedef struct sdlahw
        unsigned fwid;                  /* firmware ID */
        unsigned port;                  /* adapter I/O port base */
        int irq;                        /* interrupt request level */
-       unsigned long dpmbase;          /* dual-port memory base */
+       void * dpmbase;                 /* dual-port memory base */
        unsigned dpmsize;               /* dual-port memory size */
        unsigned pclk;                  /* CPU clock rate, kHz */
        unsigned long memory;           /* memory size */
index 1b8d98b22e5bd87cef4be6b8776d6ab3bf5ac69a..0f5975b6e5cba54806ae2b9e52239d71bb51ac0e 100644 (file)
@@ -16,6 +16,8 @@
  *
  * NeXTstep support added on February 5th 1998 by
  * Niels Kristian Bech Jensen <nkbj@image.dk>.
+ *
+ * Write support by Daniel Pirkl <daniel.pirkl@email.cz>
  */
 
 #ifndef __LINUX_UFS_FS_H
@@ -67,7 +69,7 @@
 
 /* From here to next blank line, s_flags for ufs_sb_info */
 /* endianness */
-#define UFS_BYTESEX            0x00000001      /* mask; leave room to 0xF */
+#define UFS_BYTESEX             0x00000001      /* mask; leave room to 0xF */
 #if defined(__LITTLE_ENDIAN) || defined(__BIG_ENDIAN)
 /* these are for sane architectures */
 #define UFS_NATIVE_ENDIAN      0x00000000
 #define UFS_ST_OLD             0x00000000
 #define UFS_ST_44BSD           0x00000100
 #define UFS_ST_SUN             0x00000200
-#define UFS_ST_NEXT            0x00000400
-/* filesystem flavors (combo of features) */
-#define UFS_FEATURES           0x00FFFFF0      /* room for extension */
-#define UFS_VANILLA            0x00000000
-#define UFS_OLD                        0x00000000      /* 4.2BSD */
-#define UFS_44BSD              0x00000130
-#define UFS_HURD               0x00000130
-#define UFS_SUN                        0x00000200
-#define UFS_NEXT               0x00000400
+/*cylinder group encoding */
+#define UFS_CG_MASK            0x00003000      /* mask for the following */
+#define UFS_CG_OLD             0x00000000
+#define UFS_CG_44BSD           0x00002000
+#define UFS_CG_SUN             0x00001000
 
 /* fs_inodefmt options */
 #define UFS_42INODEFMT -1
 #define UFS_44INODEFMT 2
 
+/* mount options */
+#define UFS_MOUNT_ONERROR              0x0000000F
+#define UFS_MOUNT_ONERROR_PANIC                0x00000001
+#define UFS_MOUNT_ONERROR_LOCK         0x00000002
+#define UFS_MOUNT_ONERROR_UMOUNT       0x00000004
+#define UFS_MOUNT_ONERROR_REPAIR       0x00000008
+
+#define UFS_MOUNT_UFSTYPE              0x000000F0
+#define UFS_MOUNT_UFSTYPE_OLD          0x00000010
+#define UFS_MOUNT_UFSTYPE_44BSD                0x00000020
+#define UFS_MOUNT_UFSTYPE_SUN          0x00000040
+#define UFS_MOUNT_UFSTYPE_NEXT         0x00000080
+
+
+#define ufs_clear_opt(o,opt)   o &= ~UFS_MOUNT_##opt
+#define ufs_set_opt(o,opt)     o |= UFS_MOUNT_##opt
+#define ufs_test_opt(o,opt)    ((o) & UFS_MOUNT_##opt)
+
 /*
  * MINFREE gives the minimum acceptable percentage of file system
  * blocks which may be free. If the freelist drops below this level
@@ -202,6 +218,19 @@ struct ufs_timeval {
        __s32   tv_usec;
 };
 
+/*
+ * File types
+ */
+#define DT_UNKNOWN     0
+#define DT_FIFO                1
+#define DT_CHR         2
+#define DT_DIR         4
+#define DT_BLK         6
+#define DT_REG         8
+#define DT_LNK         10
+#define DT_SOCK                12
+#define DT_WHT         14
+   
 struct ufs_dir_entry {
        __u32  d_ino;                   /* inode number of this entry */
        __u16  d_reclen;                /* length of this entry */
@@ -377,7 +406,15 @@ struct     ufs_cylinder_group {
        __u32   cg_iusedoff;            /* (char) used inode map */
        __u32   cg_freeoff;             /* (u_char) free block map */
        __u32   cg_nextfreeoff;         /* (u_char) next available space */
-       __u32   cg_sparecon[16];        /* reserved for future use */
+       union {
+               struct {
+                       __u32   cg_clustersumoff;       /* (u_int32) counts of avail clusters */
+                       __u32   cg_clusteroff;          /* (u_int8) free cluster map */
+                       __u32   cg_nclusterblks;        /* number of clusters this cg */
+                       __u32   cg_sparecon[13];        /* reserved for future use */
+               } cg_44;
+               __u32   cg_sparecon[16];        /* reserved for future use */
+       } cg_u;
        __u8    cg_space[1];            /* space for cylinder group maps */
 /* actually longer */
 };
@@ -393,7 +430,7 @@ struct ufs_inode {
                        __u16   ui_suid;        /*  0x4 */
                        __u16   ui_sgid;        /*  0x6 */
                } oldids;
-               __u32   ui_inumber;     /*  0x4 lsf: inode number */
+               __u32   ui_inumber;             /*  0x4 lsf: inode number */
                __u32   ui_author;              /*  0x4 GNU HURD: author */
        } ui_u1;
        __u64   ui_size;                /*  0x8 */
@@ -412,22 +449,22 @@ struct ufs_inode {
        __u32   ui_gen;                 /* 0x6c like ext2 i_version, for NFS support */
        union {
                struct {
-                       __u32   ui_shadow;/* 0x70 shadow inode with security data */
-                       __u32   ui_uid; /* 0x74 long EFT version of uid */
-                       __u32   ui_gid; /* 0x78 long EFT version of gid */
-                       __u32   ui_oeftflag;/* 0x7c reserved */
+                       __u32   ui_shadow;      /* 0x70 shadow inode with security data */
+                       __u32   ui_uid;         /* 0x74 long EFT version of uid */
+                       __u32   ui_gid;         /* 0x78 long EFT version of gid */
+                       __u32   ui_oeftflag;    /* 0x7c reserved */
                } ui_sun;
                struct {
-                       __u32   ui_uid; /* 0x70 File owner */
-                       __u32   ui_gid; /* 0x74 File group */
-                       __s32   ui_spare[2];/* 0x78 reserved */
+                       __u32   ui_uid;         /* 0x70 File owner */
+                       __u32   ui_gid;         /* 0x74 File group */
+                       __s32   ui_spare[2];    /* 0x78 reserved */
                } ui_44;
                struct {
-                       __u32   ui_uid; /* 0x70 */
-                       __u32   ui_gid; /* 0x74 */
-                       __u16   ui_modeh;/* 0x78 mode high bits */
-                       __u16   ui_spare;/* 0x7A unused */
-                       __u32   ui_trans;/* 0x7c filesystem translator */
+                       __u32   ui_uid;         /* 0x70 */
+                       __u32   ui_gid;         /* 0x74 */
+                       __u16   ui_modeh;       /* 0x78 mode high bits */
+                       __u16   ui_spare;       /* 0x7A unused */
+                       __u32   ui_trans;       /* 0x7c filesystem translator */
                } ui_hurd;
        } ui_u3;
 };
@@ -480,7 +517,6 @@ extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
 extern void ufs_write_inode (struct inode *);
 extern int ufs_sync_inode (struct inode *);
-extern void ufs_print_inode (struct inode *);
 extern void ufs_write_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
@@ -503,10 +539,8 @@ extern struct file_system_type ufs_fs_type;
 extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-        
 extern int init_ufs_fs(void);
 extern void ufs_write_super (struct super_block *);
-extern void ufs_print_cylinder_stuff(struct ufs_cylinder_group *, __u32);
 
 /* symlink.c */
 extern struct inode_operations ufs_symlink_inode_operations;
index e270b71aa8c1b43615fc4171f580bfd43ae7aaa0..df4c7575507d506bc6f43bbc4dacf047722ac691 100644 (file)
@@ -8,8 +8,6 @@
  *
  * NeXTstep support added on February 5th 1998 by
  * Niels Kristian Bech Jensen <nkbj@image.dk>.
- *
- * write support by Daniel Pirkl <daniel.pirkl@email.cz>
  */
 
 #ifndef _LINUX_UFS_FS_I_H
index 3f89d407921b0ae8b91f8042076974e83bf41b17..6ad0e0d960191c9e38e16244a347dc3544ff24b3 100644 (file)
@@ -8,8 +8,7 @@
  *
  * $Id: ufs_fs_sb.h,v 1.8 1998/05/06 12:04:40 jj Exp $
  *
- * Write support by Daniel Pirkl (daniel.pirkl@email.cz)
- * Charles University (Prague), Faculty of Mathematics and Physics
+ * Write support by Daniel Pirkl <daniel.pirkl@email.cz>
  */
 
 #ifndef __LINUX_UFS_FS_SB_H
@@ -41,8 +40,10 @@ struct ufs_cg_private_info {
        __u32   c_iusedoff;     /* (char) used inode map */
        __u32   c_freeoff;      /* (u_char) free block map */
        __u32   c_nextfreeoff;  /* (u_char) next available space */
+       __u32   c_clustersumoff;/* (u_int32) counts of avail clusters */
+       __u32   c_clusteroff;   /* (u_int8) free cluster map */
+       __u32   c_nclusterblks; /* number of clusters this cg */
 };     
-       
 
 struct ufs_sb_private_info {
        struct ufs_buffer_head s_ubh; /* buffer containing super block */
@@ -83,6 +84,7 @@ struct ufs_sb_private_info {
        __u32   s_ipg;          /* inodes per group */
        __u32   s_fpg;          /* fragments per group */
        __u32   s_cpc;          /* cyl per cycle in postbl */
+       __s32   s_contigsumsize;/* size of cluster summary array, 44bsd */
        __s64   s_qbmask;       /* ~usb_bmask */
        __s64   s_qfmask;       /* ~usb_fmask */
        __s32   s_postblformat; /* format of positional layout tables */
@@ -102,11 +104,14 @@ struct ufs_sb_private_info {
        __u32   s_nspb;         /* number of sector per block */
        __u32   s_inopf;        /* inodes per fragment */
        __u32   s_sbbase;       /* offset of NeXTstep superblock */
+       __u32   s_bpf;          /* bits per fragment */
+       __u32   s_bpfshift;     /* bits per fragment shift*/
+       __u32   s_bpfmask;      /* bits per fragment mask */
 };
 
 
-#define UFS_MAX_GROUP_LOADED 1
-#define UFS_CGNO_EMPTY uspi->s_ncg
+#define UFS_MAX_GROUP_LOADED 8
+#define UFS_CGNO_EMPTY ((unsigned)-1)
 
 struct ufs_sb_info {
        struct ufs_sb_private_info * s_uspi;    
@@ -119,6 +124,7 @@ struct ufs_sb_info {
        struct ufs_cg_private_info * s_ucpi[UFS_MAX_GROUP_LOADED]; 
        unsigned s_cgno[UFS_MAX_GROUP_LOADED];
        unsigned short s_cg_loaded;
+       unsigned s_mount_opt;
 };
 
 /*
index 043d4c9e2bd594f92bf3d67884c994280c291f6a..42bc34839184062b7e7c3f15bfa81a1002ea1c44 100644 (file)
@@ -159,6 +159,9 @@ struct video_window
        struct  video_clip *clips;      /* Set only */
        int     clipcount;
 #define VIDEO_WINDOW_INTERLACE 1
+#define VIDEO_CLIP_BITMAP      -1
+/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
+#define VIDEO_CLIPMAP_SIZE     (128 * 625)
 };
 
 struct video_capture
index ed38830ceecae26bcd8e9233804c170780b7bfec..fd63868f96c964ab512188c8a9e6636a8017c9a4 100644 (file)
@@ -319,7 +319,7 @@ typedef struct wan_device
        void* private;                  /* -> driver private data */
                                        /****** hardware configuration ******/
        unsigned ioport;                /* adapter I/O port base #1 */
-       unsigned long maddr;            /* dual-port memory address */
+       void * maddr;                   /* dual-port memory address */
        unsigned msize;                 /* dual-port memory size */
        int irq;                        /* interrupt request level */
        int dma;                        /* DMA request level */
index 76860e18c9bbf13dec95d2150b2163de4dd21fa0..8f82db4c2a5b76ccae3d0b0fcc75a7a3713f71a3 100644 (file)
@@ -465,7 +465,30 @@ static __inline__ void *mymemmove(char *dst, const char *src, size_t size)
     fast_memmove(dst, src, size);
     return dst;
 }
+
 #else
+
+#ifdef CONFIG_SUN4
+/* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */
+static __inline__ void fast_memmove(void *d, const void *s, size_t count)
+{
+    int i;
+    if (d<s) {
+       for (i=0; i<count; i++)
+           ((char *) d)[i] = ((char *) s)[i];
+    } else
+       for (i=0; i<count; i++)
+           ((char *) d)[count-i-1] = ((char *) s)[count-i-1];
+}
+
+static __inline__ void *mymemmove(char *dst, const char *src, size_t size)
+{
+    fast_memmove(dst, src, size);
+    return dst;
+}
+
+#else
+
 static __inline__ void *mymemmove(void *d, const void *s, size_t count)
 {
     return(memmove(d, s, count));
@@ -475,7 +498,10 @@ static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
 {
     memmove(dst, src, size);
 }
-#endif /* !i386 */
+
+#endif /* !sun4 */
+
+#endif /* !i386 */
 
 #endif /* !m68k */
 
index 2720c936641b194bf46fde650124ef8007a5fd07..b15ada607aedbaead6322bc22e12fb13c8ff6964 100644 (file)
@@ -302,9 +302,8 @@ extern void baycom_ser_hdx_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);
+#ifdef CONFIG_ADBMOUSE
+extern void adb_mouse_setup(char *str, int *ints);
 #endif
 #ifdef CONFIG_WDT
 extern void wdt_setup(char *str, int *ints);
index f3610272d5e6ece56d1048a40834e59a2ea466f6..4ae38f4e5b214f93875a93cf13d7b411ce5352da 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <asm/dma.h>
 #include <asm/system.h>
+#include <asm/spinlock.h>
 
 
 /* A note on resource allocation:
index 1b3fb7fc94a00a84a419bf00bf5927824d157345..3457d00a391ed137adf30dd8955505b323342f0d 100644 (file)
@@ -53,6 +53,8 @@
 #include <linux/console.h>
 #include <linux/time.h>
 
+#include <asm/spinlock.h>
+
 extern unsigned char aux_device_present, pckbd_read_mask;
 
 #if defined(CONFIG_PROC_FS)
@@ -79,6 +81,7 @@ extern void *sys_call_table;
 extern int sys_tz;
 extern int request_dma(unsigned int dmanr, char * deviceID);
 extern void free_dma(unsigned int dmanr);
+extern spinlock_t dma_spin_lock;
 
 #ifdef MODVERSIONS
 const struct module_symbol __export_Using_Versions
@@ -300,6 +303,7 @@ EXPORT_SYMBOL(autoirq_report);
 /* dma handling */
 EXPORT_SYMBOL(request_dma);
 EXPORT_SYMBOL(free_dma);
+EXPORT_SYMBOL(dma_spin_lock);
 #ifdef HAVE_DISABLE_HLT
 EXPORT_SYMBOL(disable_hlt);
 EXPORT_SYMBOL(enable_hlt);
index cea727b964671c448c3d2e1e6c5c8681a2c266b0..ed3f2dd0fcf0368fddc3652bdcdfc4ddfd145b81 100644 (file)
@@ -153,7 +153,7 @@ static inline int shrink_one_page(struct page *page, int gfp_mask)
                } while (tmp != bh);
 
                /* Refuse to swap out all buffer pages */
-               if ((buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.min_percent * num_physpages))
+               if (buffer_under_min())
                        goto next;
        }
 
@@ -174,7 +174,7 @@ static inline int shrink_one_page(struct page *page, int gfp_mask)
                        age_page(page);
                        if (page->age)
                                break;
-                       if (page_cache_size * 100 < (page_cache.min_percent * num_physpages))
+                       if (pgcache_under_min())
                                break;
                        if (PageSwapCache(page)) {
                                delete_from_swap_cache(page);
index f3cdb93107e77c8af10b30ae0fb207450e64d6b7..ca0b7303bf83ca74c4b95cb2ceefa625f6f421bc 100644 (file)
@@ -458,8 +458,7 @@ static int do_try_to_free_page(int gfp_mask)
        if (gfp_mask & __GFP_WAIT)
                stop = 0;
 
-       if (((buffermem >> PAGE_SHIFT) * 100 > buffer_mem.borrow_percent * num_physpages)
-                  || (page_cache_size * 100 > page_cache.borrow_percent * num_physpages))
+       if (buffer_over_borrow() || pgcache_over_borrow())
                shrink_mmap(i, gfp_mask);
 
        switch (state) {
@@ -650,11 +649,10 @@ void swap_tick(void)
        }
  
        if ((long) (now - want) >= 0) {
-               if (want_wakeup || (num_physpages * buffer_mem.max_percent) < (buffermem >> PAGE_SHIFT) * 100
-                               || (num_physpages * page_cache.max_percent < page_cache_size * 100)) {
+               if (want_wakeup || buffer_over_max() || pgcache_over_max()) {
                        /* Set the next wake-up time */
                        next_swap_jiffies = now + swapout_interval;
-                       wake_up(&kswapd_wait);
+                       kswapd_wakeup();
                }
        }
        timer_active |= (1<<SWAP_TIMER);
index 66b49db8a79d72310704913e33f221742214e786..7813f30729fff4c0e2f4d97839f1af921ed848fe 100644 (file)
@@ -238,7 +238,7 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id)
 /*
  *     Find a connected NET/ROM socket given their circuit IDs.
  */
-static struct sock *nr_find_peer(unsigned char index, unsigned char id)
+static struct sock *nr_find_peer(unsigned char index, unsigned char id, ax25_address *dest)
 {
        struct sock *s;
        unsigned long flags;
@@ -247,7 +247,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id)
        cli();
 
        for (s = nr_list; s != NULL; s = s->next) {
-               if (s->protinfo.nr->your_index == index && s->protinfo.nr->your_id == id) {
+               if (s->protinfo.nr->your_index == index && s->protinfo.nr->your_id == id && ax25cmp(&s->protinfo.nr->dest_addr, dest) == 0) {
                        restore_flags(flags);
                        return s;
                }
@@ -575,14 +575,15 @@ static int nr_release(struct socket *sock, struct socket *peer)
                        sk->state_change(sk);
                        sk->dead                 = 1;
                        sk->destroy              = 1;
+                       sk->socket               = NULL;
                        break;
 
                default:
+                       sk->socket = NULL;
                        break;
        }
 
        sock->sk   = NULL;      
-       sk->socket = NULL;      /* Not used, but we should do this */
 
        return 0;
 }
@@ -597,7 +598,11 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (sk->zapped == 0)
                return -EINVAL;
 
-       if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
+       if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct
+full_sockaddr_ax25))
+               return -EINVAL;
+
+       if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25)))
                return -EINVAL;
 
        if (addr->fsa_ax25.sax25_family != AF_NETROM)
@@ -863,10 +868,10 @@ int nr_rx_frame(struct sk_buff *skb, struct device *dev)
 
        if (circuit_index == 0 && circuit_id == 0) {
                if (frametype == NR_CONNACK && flags == NR_CHOKE_FLAG)
-                       sk = nr_find_peer(peer_circuit_index, peer_circuit_id);
+                       sk = nr_find_peer(peer_circuit_index, peer_circuit_id, src);
        } else {
                if (frametype == NR_CONNREQ)
-                       sk = nr_find_peer(circuit_index, circuit_id);
+                       sk = nr_find_peer(circuit_index, circuit_id, src);
                else
                        sk = nr_find_socket(circuit_index, circuit_id);
        }
index ba9644cbeff5b3d0f131bd950fb07d07af82187d..007cb87389c5c0c9be5cb71e461a5f40908e5fd2 100644 (file)
@@ -77,16 +77,16 @@ static void nr_loopback_timer(unsigned long param)
        ax25_address *nr_dest;
        struct device *dev;
 
-       while ((skb = skb_dequeue(&loopback_queue)) != NULL) {
+       if ((skb = skb_dequeue(&loopback_queue)) != NULL) {
                nr_dest = (ax25_address *)(skb->data + 7);
 
-               if ((dev = nr_dev_get(nr_dest)) == NULL) {
-                       kfree_skb(skb);
-                       continue;
-               }
+               dev = nr_dev_get(nr_dest);
 
-               if (nr_rx_frame(skb, dev) == 0)
+               if (dev == NULL || nr_rx_frame(skb, dev) == 0)
                        kfree_skb(skb);
+
+               if (!skb_queue_empty(&loopback_queue) && !nr_loopback_running())
+                       nr_set_loopback_timer();
        }
 }
 
index 26f5ac8ddf6497cde1d6017aa59b97397e940fff..d46e45eb664c73eb00c732dc32eebf16b3748db8 100644 (file)
@@ -81,6 +81,22 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
                if (ax25cmp(ax25, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev)
                        break;
 
+       /*
+        * The L2 link to a neighbour has failed in the past
+        * and now a frame comes from this neighbour. We assume
+        * it was a temporary trouble with the link and reset the
+        * routes now (and not wait for a node broadcast).
+        */
+       if (nr_neigh != NULL && nr_neigh->failed != 0 && quality == 0) {
+               struct nr_node *node;
+
+               for (node = nr_node_list; node != NULL; node = node->next)
+                       for (i = 0; i < node->count; i++)
+                               if (node->routes[i].neighbour == nr_neigh)
+                                       if (i < node->which)
+                                               node->which = i;
+       }
+
        if (nr_neigh != NULL)
                nr_neigh->failed = 0;
 
index a9762037885e0b908d617f71501ed13d852bd9e7..c7c2fdc26195c64d3f71edf78c2d1dd6cae00650 100644 (file)
@@ -60,8 +60,11 @@ static int menu_width, item_x;
 static void
 print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
 {
-    int i, j;
+    int j;
     char menu_item[menu_width+1];
+#if OLD_NCURSES
+     int i;
+#endif
 
     strncpy(menu_item, item, menu_width);
     menu_item[menu_width] = 0;
index 5127e5f2c0175dbad9b9faa3b9b5d3d645da6bb8..848e82e70d64d13d138e1b1b1d49de0d780232f9 100644 (file)
@@ -451,8 +451,11 @@ print_page (WINDOW * win, int height, int width)
 static void
 print_line (WINDOW * win, int row, int width)
 {
-    int i, y, x;
+    int y, x;
     char *line;
+#if OLD_NCURSES
+     int i;
+#endif
 
     line = get_line ();
     line += MIN (strlen (line), hscroll);      /* Scroll horizontally */