]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.4.0-test7-pre4 2.4.0-test7pre4
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:03 +0000 (15:38 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:03 +0000 (15:38 -0500)
    - "USE_STANDARD_AS_RULE" - generic Rules.make as rule
    - arm update (arch/arm, asm-arm, drivers/acorn, Documentation/arm etc)
    - eicon ISDN driver update (big).
    - serial.c warnings removal.
    - compilation fixes under different configurations..
    - bounds checking for hpfs code page index.
    - sparc64 bugfix for atomic_dec_and_lock. Oops. And use flock64.
    - FAT missed the d_type thing from readdir.
    - fix tsk->files race fixes from -pre3 ("struct files_struct", not
      "struct file" and make sure to register the socket fs before we
      use a pointer to it)
    - ns558.c: don't leave the driver registered after a failed module
      load.  Either return success, or unregister the PCI driver. And
      don't leak IO port allocations.
    - USB OHCI controller fixes for oopses due to races..
    - usb updates
    - 3c59x driver update
    - VIA KX-133/KT-133 chipset detection and AGP bridge support
    - raid/raw-io cleanup: use generic_make_request instead of ll_rw_block.
    - Emu10k1 sound driver update

257 files changed:
Documentation/Changes
Documentation/Configure.help
Documentation/arm/SA1100/CERF [new file with mode: 0644]
Documentation/arm/SA1100/nanoEngine [new file with mode: 0644]
Documentation/isdn/README
Documentation/isdn/README.eicon
Documentation/isdn/README.fax
Documentation/networking/vortex.txt
Documentation/usb/usb-serial.txt
Rules.make
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/bootp/Makefile [new file with mode: 0644]
arch/arm/boot/bootp/init.S [new file with mode: 0644]
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-l7200.S [new file with mode: 0644]
arch/arm/boot/compressed/head-netwinder.S
arch/arm/boot/compressed/head-sa1100.S
arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/hw-bse.c [new file with mode: 0644]
arch/arm/boot/compressed/setup-sa1100.S
arch/arm/config.in
arch/arm/kernel/Makefile
arch/arm/kernel/arch.c
arch/arm/kernel/armksyms.c
arch/arm/kernel/bios32.c
arch/arm/kernel/debug-armv.S
arch/arm/kernel/dec21285.c
arch/arm/kernel/dma-arc.c
arch/arm/kernel/dma-rpc.c
arch/arm/kernel/dma.c
arch/arm/kernel/ecard.c
arch/arm/kernel/entry-armo.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/fiq.c
arch/arm/kernel/head-armo.S
arch/arm/kernel/head-armv.S
arch/arm/kernel/hw-footbridge.c
arch/arm/kernel/hw-sa1100.c
arch/arm/kernel/irq.c
arch/arm/kernel/leds-footbridge.c
arch/arm/kernel/leds-sa1100.c
arch/arm/kernel/oldlatches.c
arch/arm/kernel/process.c
arch/arm/kernel/semaphore.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/traps.c
arch/arm/lib/Makefile
arch/arm/lib/uaccess.S
arch/arm/mm/Makefile
arch/arm/mm/init.c
arch/arm/mm/mm-footbridge.c
arch/arm/mm/mm-l7200.c
arch/arm/mm/mm-sa1100.c
arch/arm/mm/proc-arm720.S
arch/arm/mm/proc-sa110.S
arch/arm/nwfpe/Makefile
arch/arm/tools/gen-mach-types [new file with mode: 0644]
arch/arm/tools/mach-types [new file with mode: 0644]
arch/i386/kernel/apic.c
arch/ia64/kernel/machvec.c
arch/ia64/kernel/palinfo.c
arch/sparc/kernel/systbls.S
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/systbls.S
arch/sparc64/lib/dec_and_lock.S
drivers/acorn/block/Makefile
drivers/acorn/block/fd1772.c
drivers/acorn/char/Makefile
drivers/acorn/scsi/Makefile
drivers/block/ll_rw_blk.c
drivers/block/raid1.c
drivers/block/raid5.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/agp/agp.h
drivers/char/agp/agpgart_be.c
drivers/char/drm/agpsupport.c
drivers/char/ds1620.c
drivers/char/joystick/Config.in
drivers/char/joystick/ns558.c
drivers/char/nwbutton.c
drivers/char/nwflash.c
drivers/char/serial.c
drivers/char/serial_21285.c [new file with mode: 0644]
drivers/char/wdt285.c
drivers/isdn/Config.in
drivers/isdn/eicon/Divas_mod.c [new file with mode: 0644]
drivers/isdn/eicon/Makefile
drivers/isdn/eicon/adapter.h [new file with mode: 0644]
drivers/isdn/eicon/bri.c [new file with mode: 0644]
drivers/isdn/eicon/common.c [new file with mode: 0644]
drivers/isdn/eicon/constant.h [new file with mode: 0644]
drivers/isdn/eicon/divalog.h [new file with mode: 0644]
drivers/isdn/eicon/divas.h [new file with mode: 0644]
drivers/isdn/eicon/dsp_defs.h [new file with mode: 0644]
drivers/isdn/eicon/dspdids.h [new file with mode: 0644]
drivers/isdn/eicon/eicon.h
drivers/isdn/eicon/eicon_dsp.h
drivers/isdn/eicon/eicon_idi.c
drivers/isdn/eicon/eicon_idi.h
drivers/isdn/eicon/eicon_io.c
drivers/isdn/eicon/eicon_isa.c
drivers/isdn/eicon/eicon_isa.h
drivers/isdn/eicon/eicon_mod.c
drivers/isdn/eicon/eicon_pci.c
drivers/isdn/eicon/eicon_pci.h
drivers/isdn/eicon/fcheck.c [new file with mode: 0644]
drivers/isdn/eicon/fourbri.c [new file with mode: 0644]
drivers/isdn/eicon/fpga.c [new file with mode: 0644]
drivers/isdn/eicon/idi.c [new file with mode: 0644]
drivers/isdn/eicon/idi.h [new file with mode: 0644]
drivers/isdn/eicon/kprintf.c [new file with mode: 0644]
drivers/isdn/eicon/lincfg.c [new file with mode: 0644]
drivers/isdn/eicon/linchr.c [new file with mode: 0644]
drivers/isdn/eicon/linio.c [new file with mode: 0644]
drivers/isdn/eicon/linsys.c [new file with mode: 0644]
drivers/isdn/eicon/log.c [new file with mode: 0644]
drivers/isdn/eicon/md5sums.asc [new file with mode: 0644]
drivers/isdn/eicon/pc.h [new file with mode: 0644]
drivers/isdn/eicon/pc_maint.h [new file with mode: 0644]
drivers/isdn/eicon/pr_pc.h [new file with mode: 0644]
drivers/isdn/eicon/pri.c [new file with mode: 0644]
drivers/isdn/eicon/sys.h [new file with mode: 0644]
drivers/isdn/eicon/uxio.h [new file with mode: 0644]
drivers/isdn/eicon/xlog.c [new file with mode: 0644]
drivers/mtd/Config.in
drivers/net/3c59x.c
drivers/net/pcmcia/Config.in
drivers/net/sunlance.c
drivers/net/wan/Makefile
drivers/net/wan/cycx_main.c
drivers/net/wan/hostess_sv11.c
drivers/net/wan/sealevel.c
drivers/pci/pci.ids
drivers/sound/Config.in
drivers/sound/emu10k1/8010.h
drivers/sound/emu10k1/Makefile
drivers/sound/emu10k1/audio.c
drivers/sound/emu10k1/audio.h
drivers/sound/emu10k1/cardmi.c
drivers/sound/emu10k1/cardmi.h
drivers/sound/emu10k1/cardmo.c
drivers/sound/emu10k1/cardmo.h
drivers/sound/emu10k1/cardwi.c
drivers/sound/emu10k1/cardwi.h
drivers/sound/emu10k1/cardwo.c
drivers/sound/emu10k1/cardwo.h
drivers/sound/emu10k1/ecard.c [new file with mode: 0644]
drivers/sound/emu10k1/ecard.h [new file with mode: 0644]
drivers/sound/emu10k1/efxmgr.c [deleted file]
drivers/sound/emu10k1/emu_wrapper.h
drivers/sound/emu10k1/emuadxmg.c
drivers/sound/emu10k1/hwaccess.c
drivers/sound/emu10k1/hwaccess.h
drivers/sound/emu10k1/icardwav.h
drivers/sound/emu10k1/irqmgr.c
drivers/sound/emu10k1/irqmgr.h
drivers/sound/emu10k1/main.c
drivers/sound/emu10k1/midi.c
drivers/sound/emu10k1/mixer.c
drivers/sound/emu10k1/osutils.c [deleted file]
drivers/sound/emu10k1/recmgr.c
drivers/sound/emu10k1/recmgr.h
drivers/sound/emu10k1/timer.c
drivers/sound/emu10k1/timer.h
drivers/sound/emu10k1/voicemgr.c
drivers/sound/emu10k1/voicemgr.h
drivers/sound/waveartist.c
drivers/usb/Makefile
drivers/usb/bluetooth.c
drivers/usb/devio.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/usb-serial.h
drivers/usb/serial/visor.c
drivers/usb/usb-core.c
drivers/usb/usb-ohci.c
drivers/usb/usb-ohci.h
drivers/usb/usb-uhci.c
drivers/video/acornfb.c
drivers/video/sa1100fb.c
fs/buffer.c
fs/exec.c
fs/fat/dir.c
fs/hpfs/hpfs.h
fs/hpfs/map.c
include/asm-arm/a.out.h
include/asm-arm/arch-arc/hardware.h
include/asm-arm/arch-arc/ide.h
include/asm-arm/arch-arc/irq.h
include/asm-arm/arch-arc/system.h
include/asm-arm/arch-cl7500/dma.h
include/asm-arm/arch-cl7500/hardware.h
include/asm-arm/arch-cl7500/ide.h
include/asm-arm/arch-cl7500/serial.h
include/asm-arm/arch-cl7500/time.h
include/asm-arm/arch-cl7500/uncompress.h
include/asm-arm/arch-ebsa110/hardware.h
include/asm-arm/arch-ebsa285/hardware.h
include/asm-arm/arch-ebsa285/irq.h
include/asm-arm/arch-ebsa285/irqs.h
include/asm-arm/arch-ebsa285/keyboard.h
include/asm-arm/arch-ebsa285/memory.h
include/asm-arm/arch-ebsa285/system.h
include/asm-arm/arch-ebsa285/time.h
include/asm-arm/arch-l7200/hardware.h
include/asm-arm/arch-l7200/ide.h
include/asm-arm/arch-l7200/io.h
include/asm-arm/arch-l7200/memory.h
include/asm-arm/arch-l7200/system.h
include/asm-arm/arch-l7200/time.h
include/asm-arm/arch-l7200/uncompress.h
include/asm-arm/arch-rpc/hardware.h
include/asm-arm/arch-sa1100/cerf.h [new file with mode: 0644]
include/asm-arm/arch-sa1100/hardware.h
include/asm-arm/arch-sa1100/ide.h
include/asm-arm/arch-sa1100/irq.h
include/asm-arm/arch-sa1100/uncompress.h
include/asm-arm/arch-shark/keyboard.h
include/asm-arm/assembler.h
include/asm-arm/dma.h
include/asm-arm/hardware.h
include/asm-arm/leds.h
include/asm-arm/mc146818rtc.h
include/asm-arm/page.h
include/asm-arm/pgalloc.h
include/asm-arm/pgtable.h
include/asm-arm/proc-armo/assembler.h
include/asm-arm/proc-armo/cache.h
include/asm-arm/proc-armo/locks.h [new file with mode: 0644]
include/asm-arm/proc-armo/system.h
include/asm-arm/proc-armv/assembler.h
include/asm-arm/proc-armv/elf.h
include/asm-arm/proc-armv/system.h
include/asm-arm/proc-armv/uaccess.h
include/asm-arm/resource.h
include/asm-arm/system.h
include/asm-arm/termbits.h
include/asm-arm/termios.h
include/asm-arm/uaccess.h
include/asm-arm/unaligned.h
include/asm-arm/user.h
include/asm-ia64/pci.h
include/asm-ia64/pgtable.h
include/asm-sparc/fcntl.h
include/asm-sparc/unistd.h
include/asm-sparc64/fcntl.h
include/asm-sparc64/openprom.h
include/asm-sparc64/unistd.h
include/linux/agp_backend.h
include/linux/fs.h
init/main.c
net/ipv4/netfilter/ipt_owner.c
net/irda/Config.in
net/socket.c

index f856fe16b880724b2736fcbd219102c7f6656866..46cd70f3e9c27d55c98674fe4ac0cdb4b4ce3e98 100644 (file)
@@ -23,7 +23,7 @@ Feel free to translate this document.  If you do so, please send me a
 URL to your translation for inclusion in future revisions of this
 document.
 
-Last updated: June 11, 2000
+Last updated: August 12, 2000
 
 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
@@ -41,8 +41,9 @@ Card) hardware, for example, you probably needn't concern yourself
 with pcmcia-cs.
 
 o  Gnu C                  2.7.2.3                 # gcc --version
+o  Gnu make               3.77                    # make --version
 o  binutils               2.9.1.0.22              # ld -v
-o  util-linux             2.10g                   # chsh -v
+o  util-linux             2.10o                   # kbdrate -v
 o  modutils               2.3.13                  # insmod -V
 o  e2fsprogs              1.18                    # /sbin/tune2fs --version
 o  pcmcia-cs              3.1.13                  # cardmgr -V
@@ -59,7 +60,7 @@ You will need at least gcc 2.7.2 to compile the kernel.  You currently
 have several options for gcc-derived compilers:  gcc 2.7.2.3, various
 versions of egcs, the new gcc 2.95 and upcoming gcc 3.0, and experimental
 compilers like pgcc.  For absolute stability, it is still recommended
-that gcc 2.7.2.3 be used to compile your kernel.  egcs 1.12 should also
+that gcc 2.7.2.3 be used to compile your kernel.  egcs 1.1.2 should also
 work.  gcc 2.95 is known to have problems, and using pgcc for your kernel
 is just asking for trouble.
 
@@ -68,6 +69,11 @@ greater than -O2 may not be wise.  Similarly, if you choose to use gcc-2.95
 or derivatives, be sure not to use -fstrict-aliasing (which, depending on
 your version of gcc 2.95, may necessitate using -fno-strict-aliasing).
 
+Make
+----
+
+You will need Gnu make 3.77 or later to build the kernel.
+
 Binutils
 --------
 
@@ -95,7 +101,7 @@ System V shared memory is now implemented via a virtual filesystem.
 You do not have to mount it to use it as long as you can live with the
 default maxima for shared memory and segments.  If you wish to change
 these variables, you have to mount it with the options nr_blocks
-and/or nr_inodes.  POSIX shared memory is also now implemented via a
+and / or nr_inodes.  POSIX shared memory is also now implemented via a
 virtual filesystem.  If you want to use it, you'll need to mount the
 filesystem.  The recommended mount location is /dev/shm, and adding the
 following line to /etc/fstab should take care of things:
@@ -124,7 +130,8 @@ Util-linux
 
 New versions of util-linux provide *fdisk support for larger disks,
 support new options to mount, recognize more supported partition
-types, and similar goodies.  You'll probably want to upgrade.
+types, have a fdformat which works with 2.4 kernels, and similar goodies.
+You'll probably want to upgrade.
 
 Ksymoops
 --------
@@ -138,7 +145,15 @@ Modutils
 
 Upgrade to recent modutils to fix various outstanding bugs which are
 seen more frequently under 2.3.x, and to enable auto-loading of USB
-modules.
+modules.  In addition, the layout of modules under
+/lib/modules/`uname -r`/ has been made more sane.  This change also
+requires that you upgrade to a recent modutils.
+
+Mkinitrd
+--------
+
+These changes to the /lib/modules file tree layout also require that
+mkinitrd be upgraded.
 
 E2fsprogs
 ---------
@@ -224,110 +239,86 @@ Compilers
 
 gcc 2.7.2.3
 -----------
-o  ftp://ftp.gnu.org/gnu/gcc/gcc-2.7.2.3.tar.gz
-     <ftp://ftp.gnu.org/gnu/gcc/gcc-2.7.2.3.tar.gz>
-o  ftp://metalab.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz
-     <ftp://metalab.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz>
+o  <ftp://ftp.gnu.org/gnu/gcc/gcc-2.7.2.3.tar.gz>
+o  <ftp://metalab.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz>
 
-egcs 1.12
+egcs 1.1.2
 ---------
-o  ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2
-     <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2>
-o  ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2
-     <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2>
-o  ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2
-     <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2>
+o  <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2>
+o  <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2>
+o  <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2>
 
 Binutils
 ********
 
 2.9.1 series
 ------------
-o  ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz
-     <ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz>
+o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz>
 
 2.9.5 series
 ------------
-o  ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.gz
-     <ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.bz2>
+o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.bz2>
 
 System utilities
 ****************
 
 Util-linux
 ----------
-o  ftp://ftp.cwi.nl/pub/aeb/util-linux/util-linux-2.10g.tar.gz
-     <ftp://ftp.cwi.nl/pub/aeb/util-linux/util-linux-2.10g.tar.gz>
+o  <ftp://ftp.win.tue.nl/pub/linux-local/util-linux/util-linux-2.10o.tar.gz>
 
 Ksymoops
 --------
-o  ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.3
-     <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.3>
+o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.3>
 
 Modutils
 --------
-o  ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.13.tar.gz
-     <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.13.tar.gz>
+o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.3/modutils-2.3.13.tar.gz>
 
 E2fsprogs
 ---------
-o  http://web.mit.edu/tytso/www/linux/dist/e2fsprogs-1.18.tar.gz
-     <http://web.mit.edu/tytso/www/linux/dist/e2fsprogs-1.18.tar.gz>
-o  http://web.mit.edu/tytso/www/linux/dist/e2fsprogs-1.18.src.rpm
-     <http://web.mit.edu/tytso/www/linux/dist/e2fsprogs-1.18.src.rpm>
+o  <http://web.mit.edu/tytso/www/linux/dist/e2fsprogs-1.18.tar.gz>
+o  <http://web.mit.edu/tytso/www/linux/dist/e2fsprogs-1.18.src.rpm>
 
 LVM toolset
 -----------
-o  http://linux.msede.com/lvm/ <http://linux.msede.com/lvm/>
+o  <http://linux.msede.com/lvm/>
 
 Pcmcia-cs
 ---------
-o  ftp://sourceforge.org/pcmcia/pcmcia-cs-3.1.13.tar.gz
-     <ftp://sourceforge.org/pcmcia/pcmcia-cs-3.1.13.tar.gz>
+o  <ftp://sourceforge.org/pcmcia/pcmcia-cs-3.1.13.tar.gz>
 
 Jade
 ----
-o  ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz
-     <ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz>
+o  <ftp://ftp.jclark.com/pub/jade/jade-1.2.1.tar.gz>
 
 DocBook Stylesheets
 -------------------
-o  http://nwalsh.com/docbook/dsssl/
-     <http://nwalsh.com/docbook/dsssl/>
+o  <http://nwalsh.com/docbook/dsssl/>
 
 Intel P6 microcode
 ------------------
-o  http://www.urbanmyth.org/microcode/
-     <http://www.urbanmyth.org/microcode/>
+o  <http://www.urbanmyth.org/microcode/>
 
 Network
 *******
 
 PPP
 ---
-o  ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz
-     <ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz>
+o  <ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz>
 
 Isdn4k-utils
 ------------
-o  ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/testing/isdn4k-
-     utils.v3.1beta7.tar.gz
-     <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/testing/isdn4k-
-     utils.v3.1beta7.tar.gz>
+o  <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/testing/isdn4k-utils.v3.1beta7.tar.gz>
 
 Netfilter
 ---------
-o  http://netfilter.filewatcher.org/iptables-1.1.1.tar.bz2
-     <http://netfilter.filewatcher.org/iptables-1.1.1.tar.bz2>
-o  http://www.samba.org/netfilter/iptables-1.1.1.tar.bz2
-     <http://www.samba.org/netfilter/iptables-1.1.1.tar.bz2>
-o  http://netfilter.kernelnotes.org/iptables-1.1.1.tar.bz2
-     <http://netfilter.kernelnotes.org/iptables-1.1.1.tar.bz2>
+o  <http://netfilter.filewatcher.org/iptables-1.1.1.tar.bz2>
+o  <http://www.samba.org/netfilter/iptables-1.1.1.tar.bz2>
+o  <http://netfilter.kernelnotes.org/iptables-1.1.1.tar.bz2>
 
 Ip-route2
 ---------
-o  ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss991023.tar.gz
-     <ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss991023.tar.gz>
+o  <ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss991023.tar.gz>
 
 Suggestions and corrections
 ===========================
index 920f550ecfe1a48dc8a43991584895c8c28feaad..12f162feb13d78ee1f466bd7c47f7eb5a2edf711 100644 (file)
@@ -10180,9 +10180,10 @@ CONFIG_USB_SERIAL_OMNINET
 
 USB Digi International AccelePort USB Serial Driver
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT
-  Say Y here if you want to use a Digi AccelePort USB 4 device,
-  a 4 port USB serial converter.  The Digi Acceleport USB 2 and
-  8 are not yet supported by this driver.
+  Say Y here if you want to use Digi AccelePort USB 2 or 4 devices,
+  2 port (plus parallel port) and 4 port USB serial converters.  The
+  parallel port on the USB 2 appears as a third serial port on Linux.
+  The Digi Acceleport USB 8 is not yet supported by this driver.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -14092,7 +14093,7 @@ CONFIG_AEDSP16_MPU401
 Creative EMU10K1 based PCI sound cards
 CONFIG_SOUND_EMU10K1
   Say Y or M if you have a PCI sound card using the EMU10K1
-  chipset, such as the Creative SBLive! or SB PCI512.
+  chipset, such as the Creative SBLive!,  SB PCI512 or Emu-APS.
 
 Ensoniq ES1370 based PCI sound cards
 CONFIG_SOUND_ES1370
@@ -14597,7 +14598,7 @@ CONFIG_ISDN_DRV_SC
   called sc.o. See Documentation/isdn/README.sc and
   http://www.spellcast.com for more information.
 
-Eicon.Diehl active card support
+Eicon active card support
 CONFIG_ISDN_DRV_EICON
   Say Y here if you have an Eicon active ISDN card. In order to use
   this card, additional firmware is necessary, which has to be loaded
@@ -14605,6 +14606,11 @@ CONFIG_ISDN_DRV_EICON
   latest isdn4k-utils package. Please read the file
   Documentation/isdn/README.eicon for more information.
   
+Eicon Diva Server card support
+CONFIG_ISDN_DRV_EICON_PCI
+  Say Y here if you have an Eicon Diva Server (BRI/PRI/4BRI) ISDN card.
+  Please read Documentation/isdn/README.eicon for more information.
+  
 Eicon old-type card support
 CONFIG_ISDN_DRV_EICON_ISA
   Say Y here if you have an old-type Eicon active ISDN card. In order
@@ -14613,6 +14619,14 @@ CONFIG_ISDN_DRV_EICON_ISA
   the latest isdn4k-utils package. Please read the file
   Documentation/isdn/README.eicon for more information.
 
+Eicon driver type standalone
+CONFIG_ISDN_DRV_EICON_STANDALONE
+  Enable this option if you want the eicon driver as standalone
+  version with no interface to the ISDN4Linux isdn module. If you
+  say Y here, the eicon module only supports the Diva Server PCI
+  cards and will provide its own IDI interface. You should say N
+  here.
+
 Support AT-Fax Class 2 commands
 CONFIG_ISDN_TTY_FAX
   If you say Y here, the modem-emulator will support a subset of the
diff --git a/Documentation/arm/SA1100/CERF b/Documentation/arm/SA1100/CERF
new file mode 100644 (file)
index 0000000..3dfcab4
--- /dev/null
@@ -0,0 +1,34 @@
+The Intrinsyc CerfBoard is a StrongARM 1110-based computer on a board that measures 
+approximately 2" square. It includes an Ethernet controller, an RS232-compatible serial port, a
+USB function port, and one CompactFlash+ slot on the back. Pictures can be found at the
+Intrinsyc website, http://www.intrinsyc.com.
+
+This document describes the support in the Linux kernel for the Intrinsyc CerfBoard as of
+version 2.4.0-test4-np1.
+
+Supported in this version:
+   - CompactFlash+ slot (select PCMCIA in General Setup and any options that may be required)
+   - Onboard Crystal CS8900 Ethernet controller (Cerf CS8900A support in Network Devices)
+   - Serial ports with a serial console (hardcoded to 38400 8N1)
+
+Not supported in this version (yet):
+   - LCD driver/touchscreen interface
+   - UDC (a driver exists right now, but is unstable and slow and only works with the Linux USB)
+
+In order to get this kernel onto your Cerf, you need a server that runs both BOOTP and
+TFTP. Detailed instructions should have come with your evaluation kit on how to use the
+bootloader. This series of commands will suffice:
+
+   make cerf_config
+   make xconfig
+   make dep
+   make zImage
+   cp arch/arm/boot/zImage <TFTP directory>
+
+The default config uses a 4MB RAM disk located at 0xc0500000 as root. Setting the board to
+mount root from a NFS partition works, too.
+
+
+I-Gene Leong, Intrinsyc Software Inc.
+ileong@intrinsyc.com
+
diff --git a/Documentation/arm/SA1100/nanoEngine b/Documentation/arm/SA1100/nanoEngine
new file mode 100644 (file)
index 0000000..ff34c4f
--- /dev/null
@@ -0,0 +1,9 @@
+nanoEngine
+----------
+
+"nanoEngine" is a SA1110 based single board computer from 
+Bright Star Engineering Inc.  See www.brightstareng.com/arm
+for more info.
+
+Ref: Stuart Adams <sja@brightstareng.com>
+
index 0d3b0b02331bfd9b208180d59a0574386d2fc0f0..6df4d2bb9b55de1a54220cf121f7df798d185057 100644 (file)
@@ -242,7 +242,7 @@ README for the ISDN-subsystem
                                       0 = transparent
                                       1 = transparent with audio features (e.g. DSP)
                                       2 = Fax G3 Class 2 commands (S14 has to be set to 11)
-                                      2 = Fax G3 Class 1 commands (S14 has to be set to 11)
+                                      3 = Fax G3 Class 1 commands (S14 has to be set to 11)
              16   250       Send-Packet-size/16
              17   8         Window-size (not yet implemented)
              18   4         Bit coded register, Service-Octet-1 to accept,
index 87b40c6dd1116aa6fd296008ce5d036f34c8cb3d..a77542a67beaca4eda2629df1618c0c83a17e744 100644 (file)
@@ -1,4 +1,4 @@
-$Id: README.eicon,v 1.7 2000/03/06 16:38:43 armin Exp $
+$Id: README.eicon,v 1.9 2000/06/08 08:50:25 armin Exp $
 
 (c) 1999,2000 Armin Schindler (mac@melware.de)
 (c) 1999,2000 Cytronics & Melware (info@melware.de)
@@ -40,6 +40,7 @@ DIVA Server family
 ------------------
 - DIVA Server BRI/PCI 2M
 - DIVA Server PRI/PCI 2M (9M 23M 30M)
+- DIVA Server 4BRI/PCI
        supported functions of onboard DSPs:
        - analog modem
        - fax group 2/3 (Fax Class 2 commands)
@@ -80,7 +81,7 @@ Example for loading and starting a BRI card with E-DSS1 Protocol.
 
 Example for a BRI card with E-DSS1 Protocol with PtP configuration.
 
-       eiconctrl [-d DriverId] load etsi -n -t0 -s1
+       eiconctrl [-d DriverId] load etsi -n -t1 -s1
 
 
 Example for loading and starting a PRI card with E-DSS1 Protocol.
@@ -99,6 +100,18 @@ Just use "eiconctrl isdnlog on" and the driver will generate
 the necessary D-Channel traces for isdnlog.
 
 
+FILECHECK:
+A part of the eicon driver source code files are provided
+by Eicon Technology. In order to get the best support from Eicon,
+these files are tested with a checksum, just to know if the files
+were modified. This does *not* mean, you are not allowed to modify the
+driver. If you want to improve the driver or you fix a bug, please do
+so and let me (or Eicon) know, about the necessary changes. So
+every user knows, if the driver he uses is modified or checked with
+Eicon files. When the driver has been loaded, in the syslog you will
+find something like "verified" or "modified" right after the version.
+
+
 Thanks to 
        Deutsche Mailbox Saar-Lor-Lux GmbH
        for sponsoring and testing fax
@@ -113,3 +126,4 @@ Have fun !
 Armin Schindler
 mac@melware.de
 http://www.melware.de
+
index eeff9ce9f2c0d983a6a91a94900480760867aaee..5314958a8a6ef9495f793dce9c75639d7fdfc747 100644 (file)
@@ -24,6 +24,9 @@ Supported ISDN-Cards
 Eicon DIVA Server BRI/PCI
        - full support with both B-channels.
 
+Eicon DIVA Server 4BRI/PCI
+       - full support with all B-channels.
+
 Eicon DIVA Server PRI/PCI
        - full support on amount of B-channels
                depending on DSPs on board.
index 9a8039234c815f4653556d43ab32ea35322a22f7..687dcf343be02833618e5c67fb9c3fef5d879f67 100644 (file)
@@ -52,7 +52,6 @@ This driver supports the following hardware:
    3CCFE656 Cyclone CardBus
    3CCFEM656 Cyclone CardBus
    3c450 Cyclone/unknown
-   3Com Boomerang (unknown version)
 
 
 Module parameters
@@ -67,7 +66,7 @@ options 3c59x debug=3 rx_copybreak=300
 If you are using the PCMCIA tools (cardmgr) then the options may be
 placed in /etc/pcmcia/config.opts:
 
-module "3c59x" opts "debug=3 extra_reset=1"
+module "3c59x" opts "debug=3 rx_copybreak=300"
 
 
 The supported parameters are:
@@ -104,8 +103,8 @@ options=N1,N2,N3,...
   When generating a value for the 'options' setting, the above media
   selection values may be OR'ed (or added to) the following:
 
-  512 (0x200)  Force full-duplex
-  16  (0x10)   Bus-master enable bit (Old Vortex cards only)
+  512  (0x200) Force full duplex mode.
+  16   (0x10)  Bus-master enable bit (Old Vortex cards only)
 
   For example:
 
@@ -119,6 +118,22 @@ full_duplex=N1,N2,N3...
   Similar to bit 9 of 'options'.  Forces the corresponding card into
   full-duplex mode.
 
+flow_ctrl=N1,N2,N3...
+
+  Use 802.3x MAC-layer flow control.  The 3com cards only support the
+  PAUSE command, which means that they will stop sending packets for a
+  short period if they receive a PAUSE frame from the link partner. 
+
+  The driver only allows flow control on a link which is operating in
+  full duplex mode.
+
+  This feature does not appear to work on the 3c905 - only 3c905B and
+  3c905C have been tested.
+
+  The 3com cards appear to only respond to PAUSE frames which are
+  sent to the reserved destination address of 01:80:c2:00:00:01.  They
+  do not honour PAUSE frames which are sent to the station MAC address.
+
 rx_copybreak=M
 
   The driver preallocates 32 full-sized (1536 byte) network buffers
@@ -141,15 +156,6 @@ max_interrupt_work=N
   is exceeded the interrupt service routine gives up and generates a
   warning message "eth0: Too much work in interrupt".
 
-extra_reset=N
-
-  Where N is 0 or 1 (default 0).
-
-  Some network cards (notably 3CCFE575CT Cardbus) do not initialise
-  correctly and need an extra transmitter reset.  If you find that the
-  card comes up receiving but not transmitting, try giving the module
-  the 'extra_reset=1' option.
-
 compaq_ioaddr=N
 compaq_irq=N
 compaq_device_id=N
@@ -220,29 +226,102 @@ Autonegotiation notes
 Reporting and diagnosing problems
 ---------------------------------
 
-If the driver plays up, there are a number of things you can do analyse
-the problem and to help others do this:
+Maintainers find that accurate and complete problem reports are
+invaluable in resolving driver problems.  We are frequently not able to
+reproduce problems and must rely on your patience and efforts to get to
+the bottom of the problem.
+
+If you believe you have a driver problem here are some of the
+steps you should take:
+
+- Is it really a driver problem?
+
+   Eliminate some variables: try different cards, different
+   computers, different cables, different ports on the switch/hub,
+   different versions of the kernel or ofthe driver, etc.
+
+- OK, it's a driver problem.
+
+   You need to generate a report.  Typically this is an email to the
+   maintainer and/or linux-net@vger.rutgers.edu.  The maintainer's
+   email address will be inthe driver source or in the MAINTAINERS file.
+
+- The contents of your report will vary a lot depending upon the
+  problem.  If it's a kernel crash then you should refer to the
+  REPORTING-BUGS file.
+
+  But for most problems it is useful to provide the following:
+
+   o Kernel version, driver version
+
+   o A copy of the banner message which the driver generates when
+     it is initialised.  For example:
+
+     eth0: 3Com PCI 3c905C Tornado at 0xa400,  00:50:da:6a:88:f0, IRQ 19
+     8K byte-wide RAM 5:3 Rx:Tx split, autoselect/Autonegotiate interface.
+     MII transceiver found at address 24, status 782d.
+     Enabling bus-master transmits and whole-frame receives.
+
+   o If it is a PCI device, the relevant output from 'lspci -vx', eg:
+
+     00:09.0 Ethernet controller: 3Com Corporation 3c905C-TX [Fast Etherlink] (rev 74)
+             Subsystem: 3Com Corporation: Unknown device 9200
+             Flags: bus master, medium devsel, latency 32, IRQ 19
+             I/O ports at a400 [size=128]
+             Memory at db000000 (32-bit, non-prefetchable) [size=128]
+             Expansion ROM at <unassigned> [disabled] [size=128K]
+             Capabilities: [dc] Power Management version 2
+     00: b7 10 00 92 07 00 10 02 74 00 00 02 08 20 00 00
+     10: 01 a4 00 00 00 00 00 db 00 00 00 00 00 00 00 00
+     20: 00 00 00 00 00 00 00 00 00 00 00 00 b7 10 00 10
+     30: 00 00 00 00 dc 00 00 00 00 00 00 00 05 01 0a 0a
+
+   o A description of the environment: 10baseT? 100baseT?
+     full/half duplex? switched or hubbed?
+
+   o Any additional module parameters which you may be providing to the driver.
+
+   o Any kernel logs which are produced.  The more the merrier. 
+     If this is a large file and you are sending your report to a
+     mailing list, mention that you have the logfile, but don't send
+     it.  If you're reporting direct to the maintainer then just send
+     it.
+
+     To ensure that all kernel logs are available, add the
+     following line to /etc/syslog.conf:
+
+         kern.* /var/log/messages
+
+     Then restart syslogd with:
+
+         /etc/rc.d/init.d/syslog restart
 
-- Turn on debugging in the driver
-       Add 'debug=7' to /etc/modules.conf (/etc/conf.modules)
-       Change 'vortex_debug' to 7 in the source code.
+     (The above may vary, depending upon which Linux distribution you use).
 
-- Send all kernel logs, starting with the first probe of the card.
+    o If your problem is reproducible then that's great.  Try the
+      following:
 
-- Run 'mii-diag -v' to show the state of the Media Independent
-  Interface.  If the card sometimes works and sometimes doesn't, run
-  'mii-diag -v' in both states.
+      1) Increase the debug level.  Usually this is done via:
 
-- Please run 'vortex-diag -aaee' in both good and bad states.  This
-  show the NIC's registers and EEPROM contents.
+         a) modprobe driver.o debug=7
+         b) In /etc/conf.modules (or modules.conf):
+            options driver_name debug=7
 
-- Describe your setup: 10baseT, 100baseT, full/half duplex, etc.
+      2) Recreate the problem with the higher debug level,
+         send all logs to the maintainer.
 
-- Note any additional module insertion commands you're using.
+      3) Download you card's diagnostic tool from Donald
+         Backer's website http://www.scyld.com/diag.  Download
+         mii-diag.c as well.  Build these.
 
-- Try different media type settings (see above).
+         a) Run 'vortex-diag -aaee' and 'mii-diag -v' when the card is
+            working correctly.  Save the output.
 
-- Try inserting the module with 'extra_reset=1' (or compile this into
-  the driver).
+         b) Run the above commands when the card is malfunctioning.  Send
+            both sets of output.
 
+Finally, please be patient and be prepared to do some work.  You may end up working on
+this problem for a week or more as the maintainer asks more questions, asks for more
+tests, asks for patches to be applied, etc.  At the end of it all, the problem may even
+remain unresolved.
 
index da7d1909075620a3a08565533df48cf2d96ff589..4ffe021a7404bc575607df7409ea157ef1d87c7f 100644 (file)
@@ -135,16 +135,16 @@ ZyXEL omni.net lcd plus ISDN TA
 
 Digi AccelePort Driver
 
-  This driver supports the Digi AccelePort USB 4 device, a 4 port
-  USB serial converter.  The driver does NOT yet support the Digi
-  AccelePort USB 2 or 8.
-
-  The driver supports open, close, read, write, termios settings (baud
-  rate, word size, parity, stop bits, hardware/software flow control,
-  CREAD), DTR/RTS, and TIOCMGET/SET/BIS/BIC ioctls.  It has not been
-  thoroughly tested, but it seems to be working reasonable well.  There
-  is more work to do, including flow control, ioctls, and support for
-  the Digi AccelePort USB 2 and 8.
+  This driver supports the Digi AccelePort USB 2 and 4 devices, 2 port
+  (plus a parallel port) and 4 port USB serial converters.  The driver
+  does NOT yet support the Digi AccelePort USB 8.
+
+  The driver is generally working, though we still have a few more ioctls
+  to implement and final testing and debugging to do.  The paralled port
+  on the USB 2 is supported as a serial to parallel converter; in other
+  words, it appears as another USB serial port on Linux, even though
+  physically it is really a parallel port.  The Digi Acceleport USB 8
+  is not yet supported.
 
   Please contact Peter Berger (pberger@brimson.com) or Al Borchers
   (alborchers@steinerpoint.com) for questions or problems with this
index 599f8966c47fe28f52a4037800c7f52f1407bfc8..dd79396c666c1aaffb76600d9863b218e4816eda 100644 (file)
@@ -10,7 +10,7 @@
 #
 # Special variables which should not be exported
 #
-unexport EXTRA_ASFLAGS
+unexport EXTRA_AFLAGS
 unexport EXTRA_CFLAGS
 unexport EXTRA_LDFLAGS
 unexport EXTRA_ARFLAGS
@@ -57,7 +57,21 @@ first_rule: sub_dirs
        ) > $(dir $@)/.$(notdir $@).flags
 
 %.o: %.s
-       $(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+       $(AS) $(AFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+
+# Old makefiles define their own rules for compiling .S files,
+# but these standard rules are available for any Makefile that
+# wants to use them.  Our plan is to incrementally convert all
+# the Makefiles to these standard rules.  -- rmk, mec
+ifdef USE_STANDARD_AS_RULE
+
+%.s: %.S
+       $(CPP) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) $< > $@
+
+%.o: %.S
+       $(CC) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) -c -o $@ $<
+
+endif
 
 #
 #
index 5bd7af915dd8eb3a46b9961a9027c2698c13e2ca..81b78feb9fbd64cd1b48775916fb654ead8921a3 100644 (file)
@@ -48,7 +48,7 @@ NEW_GCC               := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then ech
 #
 ifeq ($(NEW_GCC),y)
 CFLAGS                 += -mshort-load-bytes
-CFLAGS_PROC_CPU_26     := -mcpu=arm3 -Os
+CFLAGS_PROC_CPU_26     := -mcpu=arm3 -mapcs-26 -Os
 CFLAGS_PROC_CPU_32v3   := -march=armv3
 CFLAGS_PROC_CPU_32v4   := -march=armv4
 CFLAGS_ARM6            := -mtune=arm6
@@ -166,10 +166,9 @@ endif
 HEAD           := arch/arm/kernel/head-$(PROCESSOR).o \
                   arch/arm/kernel/init_task.o
 SUBDIRS                += arch/arm/kernel arch/arm/mm arch/arm/lib \
-                  arch/arm/special arch/arm/nwfpe
+                  arch/arm/nwfpe
 CORE_FILES     := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
 LIBS           := arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(LIBGCC)
-DRIVERS                += arch/arm/special/special.a
 
 ifeq ($(CONFIG_NWFPE),y)
 LIBS           := arch/arm/nwfpe/math-emu.o $(LIBS)
@@ -193,7 +192,14 @@ MAKEBOOT    = $(MAKE) -C arch/$(ARCH)/boot
 # The following is a hack to get 'constants.h' up
 # to date before starting compilation
 
-$(patsubst %, _dir_%, $(SUBDIRS)) : constants
+$(patsubst %, _dir_%, $(SUBDIRS)) init/main.o init/version.o : \
+       constants \
+       include/asm-arm/mach-types.h
+
+include/asm-arm/mach-types.h: \
+       arch/arm/tools/mach-types \
+       arch/arm/tools/gen-mach-types
+       @awk -f arch/arm/tools/gen-mach-types arch/arm/tools/mach-types > $@
 
 constants: $(TOPDIR)/include/asm-arm/proc-fns.h dummy
        @$(MAKE) -C arch/arm/lib constants.h
@@ -218,16 +224,16 @@ arch/arm/mm: dummy
 arch/arm/lib: dummy
        $(MAKE) linuxsubdirs SUBDIRS=arch/arm/lib
 
-zImage zinstall Image install: vmlinux
+bzImage zImage zinstall Image bootpImage install: vmlinux
        @$(MAKEBOOT) $@
 
 archmrproper:
-       @$(MAKE) -C arch/$(ARCH)/special mrproper
        $(RM) include/asm-arm/arch include/asm-arm/proc
 
 archclean:
        @$(MAKEBOOT) clean
        $(RM) arch/arm/lib/constants.h arch/arm/vmlinux.lds
+       $(RM) include/asm-arm/mach-types.h
 
 archdep: symlinks
        @$(MAKEBOOT) dep
@@ -241,46 +247,25 @@ zi:;      @$(MAKEBOOT) zinstall
 #
 # Configuration targets.  Use these to select a
 # configuration for your architecture
-#
-a5k_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/a5k arch/arm/defconfig
-
-ebsa110_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/ebsa110 arch/arm/defconfig
-
-footbridge_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/footbridge arch/arm/defconfig
-
-rpc_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/rpc arch/arm/defconfig
-
-brutus_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/brutus arch/arm/defconfig
-
-victor_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/victor arch/arm/defconfig
-
-empeg_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/empeg arch/arm/defconfig
-
-thinclient_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/thinclient arch/arm/defconfig
-
-assabet_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/assabet arch/arm/defconfig
-
-lart_config:
-       $(RM) arch/arm/defconfig
-       cp arch/arm/def-configs/lart arch/arm/defconfig
+CFGS=  a5k_config              ebsa110_config          \
+       footbridge_config       rpc_config              \
+       brutus_config           victor_config           \
+       empeg_config            thinclient_config       \
+       assabet_config          lart_config             \
+       cerf_config 
+
+$(CFGS):
+       @( \
+       CFG=$(@:_config=); \
+       if [ -f arch/arm/def-configs/$$CFG ]; then \
+         $(RM) arch/arm/defconfig; \
+         cp arch/arm/def-configs/$$CFG arch/arm/defconfig; \
+         echo "*** Default configuration for $$CFG installed"; \
+         echo "*** Next, you may run 'make oldconfig'"; \
+       else \
+         echo "$$CFG does not exist"; \
+       fi; \
+       )
 
 l7200_config:
        $(RM) arch/arm/defconfig
index d210b92c2b747f72ccae4a79b53cab7644ef324e..2811e80efdccc5257bac4e20311e1c74bbc1c1cc 100644 (file)
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1995, 1996 Russell King
+# Copyright (C) 1995-2000 Russell King
 #
 
 SYSTEM =$(TOPDIR)/vmlinux
 
+ifeq ($(CONFIG_CPU_26),y)
+ZTEXTADDR       = 0x02080000
+PARAMS_PHYS     = 0x0207c000
+INITRD_PHYS     = 0x02180000
+INITRD_VIRT     = 0x02180000
+endif
+
+ifeq ($(CONFIG_ARCH_RPC),y)
+ZTEXTADDR       = 0x10008000
+PARAMS_PHYS     = 0x10000100
+INITRD_PHYS     = 0x18000000
+INITRD_VIRT     = 0xc8000000
+endif
+
+ifeq ($(CONFIG_ARCH_CLPS7500),y)
+ZTEXTADDR       = 0x10008000
+endif
+
+ifeq ($(CONFIG_ARCH_EBSA110),y)
+ZTEXTADDR       = 0x00008000
+PARAMS_PHYS     = 0x00000400
+INITRD_PHYS     = 0x00800000
+INITRD_VIRT     = 0xc0800000
+endif
+
+ifeq ($(CONFIG_FOOTBRIDGE),y)
+ZTEXTADDR       = 0x00008000
+PARAMS          = 0x00000100
+INITRD_PHYS     = 0x00800000
+INITRD_VIRT     = 0xc0800000
+endif
+
+ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
+ZTEXTADDR       = 0x40200000
+ZRELADDR        = 0x40008000
+endif
+
+ifeq ($(CONFIG_ARCH_L7200),y)
+# RAM based kernel
+#ZTEXTADDR      = 0xf0400000
+#ZRELADDR       = 0xf0008000
+
+# FLASH based kernel
+ZTEXTADDR       = 0x00010000
+ZRELADDR        = 0xf0008000
+ZBSSADDR        = 0xf03e0000
+endif
+
+ifeq ($(CONFIG_ARCH_SA1100),y)
+ZTEXTADDR       = 0xc0008000
+ZRELADDR        = 0xc0008000
+ifeq ($(CONFIG_SA1100_VICTOR),y)
+  ZTEXTADDR     = 0x00002000
+  ZBSSADDR      = 0xc0100000
+endif
+ifeq ($(CONFIG_SA1100_THINCLIENT),y)
+  ZTEXTADDR     = 0xC0200000
+endif
+ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
+  ZTEXTADDR     = 0xC0200000
+endif
+endif
+
+#
+# If you don't define ZRELADDR above,
+# then it defaults to ZTEXTADDR
+#
+ifeq ($(ZRELADDR),)
+ZRELADDR       = $(ZTEXTADDR)
+endif
+
+export SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS
+
 Image: $(CONFIGURE) $(SYSTEM)
        $(OBJCOPY) $(SYSTEM) $@
 
+bzImage: zImage
+
 zImage:        $(CONFIGURE) compressed/vmlinux
        $(OBJCOPY) compressed/vmlinux $@
 
+bootpImage: bootp/bootp
+       $(OBJCOPY) bootp/bootp $@
+
 compressed/vmlinux: $(TOPDIR)/vmlinux dep
        @$(MAKE) -C compressed vmlinux
 
+bootp/bootp: zImage initrd
+       @$(MAKE) -C bootp bootp
+
+initrd:
+       @test "$(INITRD_VIRT)" != "" || (echo This architecture does not support INITRD; exit -1)
+       @test "$(INITRD)" != "" || (echo You must specify INITRD; exit -1)
+
 install: $(CONFIGURE) Image
        sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
@@ -26,7 +111,8 @@ zinstall: $(CONFIGURE) zImage
        sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
 clean:
-       rm -f Image zImage
+       $(RM) Image zImage bootpImage
        @$(MAKE) -C compressed clean
+       @$(MAKE) -C bootp clean
 
 dep:
diff --git a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile
new file mode 100644 (file)
index 0000000..c513c8a
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# linux/arch/arm/boot/bootp/Makefile
+#
+
+ZSYSTEM                =$(TOPDIR)/arch/arm/boot/zImage
+INITRD         =$(ZSYSTEM)
+ZLDFLAGS       =-p -X -T bootp.lds \
+                --defsym initrd_addr=$(INITRD_PHYS) \
+                --defsym initrd_virt=$(INITRD_VIRT) \
+                --defsym params=$(PARAMS_PHYS)
+
+all:           bootp
+
+# Note that bootp.lds picks up kernel.o and initrd.o
+bootp:         init.o kernel.o initrd.o bootp.lds
+               $(LD) $(ZLDFLAGS) -o $@ init.o
+
+kernel.o:      $(ZSYSTEM)
+               $(LD) -r -s -o $@ -b binary $(ZSYSTEM)
+
+initrd.o:      $(INITRD)
+               $(LD) -r -s -o $@ -b binary $(INITRD)
+
+.PHONY:                $(INITRD) $(ZSYSTEM)
+
+clean:;                $(RM) bootp bootp.lds
diff --git a/arch/arm/boot/bootp/init.S b/arch/arm/boot/bootp/init.S
new file mode 100644 (file)
index 0000000..c568221
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Header file for splitting kernel + initrd.  Note that we pass
+ * r0 through to r3 straight through.
+ */
+               .section .start,#alloc,#execinstr
+               .type   _entry, #function
+_entry:
+kernel_addr:   adr     r10, initdata
+               ldmia   r10, {r11, r12}
+               sub     r11, r10, r11           @ work out exec offset
+               add     r12, r12, r11           @ correct "splitify"
+               mov     pc, r12                 @ jump to splitify
+               .size   _entry,. - _entry
+
+               .type   initdata, #object
+initdata:      .word   initdata                @ compiled address of this
+               .word   splitify
+               .size   initdata,. - initdata
+
+               .text
+splitify:      adr     r13, data
+               ldmia   r13!, {r4-r6}           @ move the kernel
+               add     r4, r4, r11             @ correction
+               mov     r12, r5
+               bl      move
+
+               ldmia   r13!, {r4-r6}           @ then the initrd
+               add     r4, r4, r11             @ correction
+               bl      move
+
+               ldmib   r13, {r5,r6,r7}         @ get size and addr of initrd
+               add     r7, r7, #16*4           @ offset of initrd_start in param_struct
+               stmia   r7, {r5,r6}             @ save in param_struct
+               mov     pc, r12                 @ call kernel
+
+move:          ldmia   r4!, {r7 - r10}         @ move 32-bytes at a time
+               stmia   r5!, {r7 - r10}
+               ldmia   r4!, {r7 - r10}
+               stmia   r5!, {r7 - r10}
+               subs    r6, r6, #8 * 4
+               bcs     move
+               mov     pc, lr
+
+data:          .word   kernel_start
+               .word   kernel_addr
+               .word   kernel_len
+
+               .word   initrd_start
+               .word   initrd_addr
+               .word   initrd_len
+
+               .word   initrd_virt
+               .word   initrd_len
+               .word   params
+
+               .type   kernel_start,#object
+               .type   initrd_start,#object
index f3c45c553f6d181361ef95d8ab487135d13d3267..2a010802104eb29fbc133c3c34f635d9dc1f3b9a 100644 (file)
@@ -2,10 +2,13 @@
 # linux/arch/arm/boot/compressed/Makefile
 #
 # create a compressed vmlinuz image from the original vmlinux
+#
+# Note! SYSTEM, ZTEXTADDR, ZBSSADDR and ZRELADDR are now exported
+# from arch/arm/boot/Makefile
+#
 
 HEAD            = head.o
 OBJS            = misc.o
-SYSTEM          = $(TOPDIR)/vmlinux
 CFLAGS          = $(CPPFLAGS) -O2 -DSTDC_HEADERS $(CFLAGS_PROC)
 FONTC           = $(TOPDIR)/drivers/video/font_acorn_8x8.c
 ZLDFLAGS        = -p -X -T vmlinux.lds
@@ -17,60 +20,25 @@ ifeq ($(CONFIG_ARCH_ACORN),y)
 OBJS           += ll_char_wr.o font.o
 endif
 
-ifeq ($(CONFIG_CPU_26),y)
-ZTEXTADDR       = 0x02080000
-endif
-
-ifeq ($(CONFIG_ARCH_RPC),y)
-ZTEXTADDR       = 0x10008000
-endif
-
-ifeq ($(CONFIG_ARCH_CLPS7500),y)
-ZTEXTADDR       = 0x10008000
-endif
-
-ifeq ($(CONFIG_ARCH_EBSA110),y)
-ZTEXTADDR       = 0x00008000
-endif
-
-ifeq ($(CONFIG_FOOTBRIDGE),y)
-ZTEXTADDR       = 0x00008000
-endif
-
 ifeq ($(CONFIG_ARCH_NETWINDER),y)
 OBJS           += head-netwinder.o
 endif
 
 ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
 HEAD            = head-nexuspci.o
-ZTEXTADDR       = 0x40200000
-ZRELADDR        = 0x40008000
+endif
+
+ifeq ($(CONFIG_ARCH_L7200),y)
+OBJS           += head-l7200.o
 endif
 
 ifeq ($(CONFIG_ARCH_SA1100),y)
 OBJS           += head-sa1100.o setup-sa1100.o
-ZTEXTADDR       = 0xc0008000
-ZRELADDR        = 0xc0008000
-ifeq ($(CONFIG_SA1100_VICTOR),y)
-  ZTEXTADDR     = 0x00002000
-  ZBSSADDR      = 0xc0100000
-endif
-ifeq ($(CONFIG_SA1100_THINCLIENT),y)
-  ZTEXTADDR     = 0xC0200000
-endif
-ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
-  ZTEXTADDR     = 0xC0200000
+ifeq ($(CONFIG_SA1100_NANOENGINE),y)
+  OBJS += hw-bse.o
 endif
 endif
 
-#
-# If you don't define ZRELADDR above,
-# then it defaults to ZTEXTADDR
-#
-ifeq ($(ZRELADDR),)
-ZRELADDR       = $(ZTEXTADDR)
-endif
-
 SEDFLAGS       = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;
 
 ifneq ($(ZBSSADDR),)
@@ -104,3 +72,6 @@ clean:;              rm -f vmlinux core piggy* vmlinux.lds
 .PHONY:        vmlinux.lds clean
 
 misc.o: misc.c $(TOPDIR)/include/asm/arch/uncompress.h $(TOPDIR)/lib/inflate.c
+
+%.o: %.S
+       $(CC) $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$@) -c -o $@ $<
diff --git a/arch/arm/boot/compressed/head-l7200.S b/arch/arm/boot/compressed/head-l7200.S
new file mode 100644 (file)
index 0000000..ecf4d68
--- /dev/null
@@ -0,0 +1,30 @@
+/* 
+ * linux/arch/arm/boot/compressed/head-l7200.S
+ * 
+ * Copyright (C) 2000 Steve Hill <sjhill@cotw.com>
+ * 
+ * Some code borrowed from Nicola Pitre's 'head-sa1100.S' file. This
+ * is merged with head.S by the linker.
+ */
+
+#include <linux/config.h>
+
+#ifndef CONFIG_ARCH_L7200
+#error What am I doing here...
+#endif
+
+               .section        ".start", #alloc, #execinstr
+
+__L7200_start:
+
+               mov     r0, #0x00100000         @ FLASH address of initrd
+               mov     r2, #0xf1000000         @ RAM address of initrd
+               add     r1, r2, #0x00700000     @ Size of initrd 
+1:
+               ldmia   r0!, {r3, r4, r5, r6}
+               stmia   r2!, {r3, r4, r5, r6}
+               cmp     r2, r1
+               ble     1b
+               
+               mov     r8, #0                  @ Zero it out
+               mov     r7, #19                 @ Set architecture ID
index 489bb4d96c5b8ecd8b376223e7a20957cd901594..eca1d773d2771b37b6318d24702be078ff9f46af 100644 (file)
@@ -1,15 +1,24 @@
+#define K(a,b,c)       ((a) << 24 | (b) << 12 | (c))
+
                .section        ".start", #alloc, #execinstr
 
+               /*
+                * check to see if we are running from the correct address.
+                * If not, we move ourselves in a two stage process.  Firstly,
+                * we copy the start of the kernel (which includes this code)
+                * to 0x8000, and then jump to this code to continue with the
+                * rest (since this code will get overwritten).
+                */
                adr     r2, 1f
-               ldmdb   r2, {r7, r8}
+               ldmdb   r2, {r9, r10}
                and     r3, r2, #0xc000
-               teq     r3, #0x8000
-               beq     2f
+               teq     r3, #0x8000     @ correctly located?
+               beq     2f              @ skip this code
                bic     r3, r2, #0xc000
                orr     r3, r3, #0x8000
-               mov     r0, r3
-               mov     r4, #64
-               sub     r5, r8, r7
+               mov     r0, r3          @ new address if '1'
+               mov     r4, #64         @ number of bytes to copy
+               sub     r5, r10, r9     @ total number of bytes to copy
                b       1f
 
                .word   _start
 
 1:
                .rept   4
-               ldmia   r2!, {r6, r7, r8, r9}
-               stmia   r3!, {r6, r7, r8, r9}
+               ldmia   r2!, {r6, r9, r10, r11}
+               stmia   r3!, {r6, r9, r10, r11}
                .endr
                subs    r4, r4, #64
                bcs     1b
-               movs    r4, r5
-               mov     r5, #0
-               mov     r1, #5          @ only here to fix NeTTroms which dont set r1
-               movne   pc, r0
-
-               mov     r0, #0
+               movs    r4, r5          @ remaining length
+               mov     r5, #0          @ no more to copy
+               movne   pc, r0          @ jump back to 1 (in the newly copied
+                                       @ code)
+               mov     r7, #5          @ only here to fix NeTTroms which dont
+               mov     r8, #2 << 24            @ scheduled for removal in 2.5.xx
+               orr     r8, r8, #5 << 12
 2:
index 6b0d4624d8ddd37269a128afecb18ce8a437a394..73cef4bd8a7ee1af589f8a1e35203a0d4b13d7c5 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/config.h>
 #include <linux/linkage.h>
+#include <asm/mach-types.h>
 
 #ifndef CONFIG_ARCH_SA1100
 #error What am I doing here...
 
 __SA1100_start:
 
-               @ Preserve r0/r1 i.e. kernel entry values
-               mov     r8, r0
-               mov     r9, r1
-
-#if    defined( CONFIG_SA1100_ASSABET ) || \
-       defined( CONFIG_SA1100_BRUTUS ) || \
-       defined( CONFIG_SA1100_THINCLIENT )
-@ Booting from Angel -- need to enter SVC mode
-#define angel_SWIreason_EnterSVC 0x17   /* from arm.h, in angel source */
-#define angel_SWI_ARM (0x123456)
-               mov     r0, #angel_SWIreason_EnterSVC
-               swi     #angel_SWI_ARM
-
-               @ turn off interrupts to prevent the angel from running
-               mrs     r0, cpsr
-               orr     r0, r0, #0xc0
-               msr     cpsr_c, r0
-#endif
+               @ Preserve r8/r7 i.e. kernel entry values
 
 #ifdef CONFIG_SA1100_VICTOR
-               teq     r9, #26                 @ MACH_TYPE_VICTOR
+               teq     r7, #MACH_TYPE_VICTOR
                bne     10f
 
                @ Copy cmdline to 0xc0000000
@@ -74,10 +58,6 @@ __SA1100_start:
  * Pause for a short time so that we give enough time
  * for the host to start a terminal up.
  */
-               mov     r0, #0x02000000
+               mov     r0, #0x00200000
 1:             subs    r0, r0, #1
                bne     1b
-
-               @ Restore initial r0/r1
-               mov     r0, r8
-               mov     r1, r9
index 10c2290a00fb9b48b319b4e8ce171e53a5b305a9..ef9090f726222b628c2c6b7f8c173d687d1f4bc3 100644 (file)
@@ -3,9 +3,9 @@
  *
  * Copyright (C) 1996-1999 Russell King
  */
+#include <linux/config.h>
 #include <linux/linkage.h>
 
-
 /*
  * Debugging stuff
  */
@@ -84,18 +84,31 @@ start:
                b       1f
                .word   0x016f2818              @ Magic numbers to help the loader
                .word   start   
-1:
+1:             mov     r7, r1                  @ save architecture ID
+               mov     r8, r0                  @ save r0
+#ifdef CONFIG_ANGELBOOT
+               /*
+                * Booting from Angel - need to enter SVC mode and disable
+                * FIQs/IRQs (numeric definitions from angel arm.h source)
+                */
+               mov     r0, #0x17               @ angel_SWIreason_EnterSVC
+               swi     0x123456                @ angel_SWI_ARM
+               mrs     r0, cpsr                @ turn off interrupts to
+               orr     r0, r0, #0xc0           @ prevent angel from running
+               msr     cpsr_c, r0
+
+               /*
+                * Note that some cache flushing and other stuff may
+                * be needed here - is there an Angel SWI call for this?
+                */
+#endif
                /*
                 * some architecture specific code can be inserted
-                * by the linker here, but it should preserve r0, r1
-                * and r8.
+                * by the linker here, but it should preserve r7 and r8.
                 */
 
                .text
-1:             teq     r0, #0
-               bne     1b
-               mov     r7, r1                  @ save architecture ID
-               mrc     p15, 0, r6, c0, c0      @ get processor ID
+1:             mrc     p15, 0, r6, c0, c0      @ get processor ID
                adr     r2, LC0
                ldmia   r2, {r2, r3, r4, r5, sp}
 
diff --git a/arch/arm/boot/compressed/hw-bse.c b/arch/arm/boot/compressed/hw-bse.c
new file mode 100644 (file)
index 0000000..3e8f07f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Bright Star Engineering Inc.
+ *
+ * code for readng parameters from the
+ * parameter blocks of the boot block
+ * flash memory
+ *
+ */
+
+static int strcmp(const char *s1, const char *s2)
+{
+  while (*s1 != '\0' && *s1 == *s2)
+    {
+      s1++;
+      s2++;
+    }
+
+  return (*(unsigned char *) s1) - (*(unsigned char *) s2);
+}
+
+struct pblk_t {
+  char type;
+  unsigned short size;
+};
+
+static char *bse_getflashparam(char *name) {
+  unsigned int esize;
+  char *q,*r;
+  unsigned char *p,*e;
+  struct pblk_t *thepb = (struct pblk_t *) 0x00004000;
+  struct pblk_t *altpb = (struct pblk_t *) 0x00006000;  
+  if (thepb->type&1) {
+    if (altpb->type&1) {
+      /* no valid param block */ 
+      return (char*)0;
+    } else {
+      /* altpb is valid */
+      struct pblk_t *tmp;
+      tmp = thepb;
+      thepb = altpb;
+      altpb = tmp;
+    }
+  }
+  p = (char*)thepb + sizeof(struct pblk_t);
+  e = p + thepb->size; 
+  while (p < e) {
+    q = p;
+    esize = *p;
+    if (esize == 0xFF) break;
+    if (esize == 0) break;
+    if (esize > 127) {
+      esize = (esize&0x7F)<<8 | p[1];
+      q++;
+    }
+    q++;
+    r=q;
+    if (*r && ((name == 0) || (!strcmp(name,r)))) {
+      while (*q++) ;
+      return q;
+    }
+    p+=esize;
+  }
+  return (char*)0;
+}
+
+void bse_setup(void) {
+  /* extract the linux cmdline from flash */
+  char *name=bse_getflashparam("linuxboot");
+  char *x = (char *)0xc0000100;
+  if (name) { 
+    while (*name) *x++=*name++;
+  }
+  *x=0;
+}
index 6fd5b84e66857998649fe9e1d790d2169b13bcec..f7657773b4e868cf51deaff2b7a0a977716adaea 100644 (file)
@@ -9,8 +9,9 @@
  *  Runtime test for Neponset added.
  */
 
-#define __ASSEMBLY__
 #include <linux/linkage.h>
+#include <linux/config.h>
+#include <asm/mach-types.h>
 
                .text
 
@@ -44,6 +45,12 @@ SCR_loc:     .long   SYMBOL_NAME(SCR_value)
 #define GPIO_2_9       0x3fc
 
 
+/*
+ * void sa1100_setup( int arch_id );
+ *
+ * This is called from decompress_kernel() with the arch_decomp_setup() macro.
+ */
+
 ENTRY(sa1100_setup)
                mov     r3, r0                  @ keep machine type in r3
 
@@ -51,7 +58,7 @@ ENTRY(sa1100_setup)
 @ (taken from "Intel StrongARM SA-1110 Microprocessor Development Board
 @ User's Guide," p.4-9)
 
-               teq     r3, #25                 @ MACH_TYPE_ASSABET
+               teq     r3, #MACH_TYPE_ASSABET
                bne     skip_SCR
 
                ldr     r0, GPIO_BASE
@@ -80,8 +87,8 @@ ENTRY(sa1100_setup)
 skip_SCR:
 
                @ Initialize UART (if bootloader has not done it yet)...
-               teq     r3, #16                 @ MACH_TYPE_BRUTUS
-               teqne   r3, #25                 @ MACH_TYPE_ASSABET
+               teq     r3, #MACH_TYPE_BRUTUS
+               teqne   r3, #MACH_TYPE_ASSABET
                bne     skip_uart
 
                @ UART3 if Assabet is used with Neponset
@@ -92,7 +99,7 @@ skip_SCR:
 
                @ At least for Brutus, the UART1 is used through
                @ the alternate GPIO function...
-               teq     r3, #16                 @ MACH_TYPE_BRUTUS
+               teq     r3, #MACH_TYPE_BRUTUS
                bne     uart1
 
 alt_GPIO_uart: ldr     r0, GPIO_BASE
@@ -126,5 +133,14 @@ uart_init: ldr     r1, [r0, #UTSR1]
                mov     r1, #0xff               @ flush status reg
                str     r1, [r0, #UTSR0]
 skip_uart:
+
+               @ Extra specific setup calls
+               @ The machine type is passed in r0
+               mov     r0, r3
+#ifdef CONFIG_SA1100_NANOENGINE
+               teq     r0, #32                 @ MACH_TYPE_NANOENGINE
+               beq     SYMBOL_NAME(bse_setup)
+#endif
+
 out:           mov     pc, lr
 
index 95c94d66684d56466e2efee7ce5c3110b203d4c8..55f937a13a7add6e77132eeca2835e0bed5d497c 100644 (file)
@@ -29,6 +29,7 @@ comment 'System Type'
 
 choice 'ARM system type'       \
        "Archimedes/A5000       CONFIG_ARCH_ARCA5K \
+        Cirrus-CL-PS7500FE     CONFIG_ARCH_CLPS7500 \
         Co-EBSA285             CONFIG_ARCH_CO285 \
         EBSA-110               CONFIG_ARCH_EBSA110 \
         FootBridge             CONFIG_ARCH_FOOTBRIDGE \
@@ -62,6 +63,7 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
       bool '  Include support for Neponset' CONFIG_ASSABET_NEPONSET
    fi
    bool '  Include support for Brutus' CONFIG_SA1100_BRUTUS
+   bool '  Include support for CerfBoard' CONFIG_SA1100_CERF
    bool '  Include support for Compaq iPAQ H3600 (Bitsy)' CONFIG_SA1100_BITSY
 #   bool '  Include support for Empeg' CONFIG_SA1100_EMPEG
 #   bool '  Include support for Itsy' CONFIG_SA1100_ITSY
@@ -69,9 +71,52 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
 #   bool '  Include support for PLEB' CONFIG_SA1100_PLEB
    bool '  Include support for ThinClient' CONFIG_SA1100_THINCLIENT
    bool '  Include support for GraphicsClient' CONFIG_SA1100_GRAPHICSCLIENT
+   bool '  Include support for nanoEngine' CONFIG_SA1100_NANOENGINE
    bool '  Include support for Victor' CONFIG_SA1100_VICTOR
 #   bool '  Include support for Tifon' CONFIG_SA1100_TIFON
-#   bool '  Include support for XP860' CONFIG_SA1100_XP860
+   bool '  Include support for XP860' CONFIG_SA1100_XP860
+
+   bool '  Load kernel using Angel Debug Monitor' CONFIG_ANGELBOOT
+
+   # Determine if SA1111 support is required
+   if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
+       "$CONFIG_SA1100_XP860" = "y" ]; then
+      define_bool CONFIG_SA1111 y
+   fi
+fi
+
+# Definitions to make life easier
+if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \
+     "$CONFIG_ARCH_RPC" = "y" ]; then
+   define_bool CONFIG_ARCH_ACORN y
+else
+   define_bool CONFIG_ARCH_ACORN n
+fi
+
+# see Documentation/arm/ConfigVars for a description of these
+if [ "$CONFIG_ARCH_CO285" = "y" -o \
+     "$CONFIG_ARCH_FOOTBRIDGE" = "y" ]; then
+   define_bool CONFIG_FOOTBRIDGE y
+else
+   define_bool CONFIG_FOOTBRIDGE n
+fi
+if [ "$CONFIG_ARCH_CATS" = "y" -o \
+     "$CONFIG_ARCH_EBSA285_HOST" = "y" -o \
+     "$CONFIG_ARCH_NETWINDER" = "y" -o \
+     "$CONFIG_ARCH_PERSONAL_SERVER" = "y" ]; then
+   define_bool CONFIG_FOOTBRIDGE_HOST y
+else
+   define_bool CONFIG_FOOTBRIDGE_HOST n
+fi
+if [ "$CONFIG_ARCH_CO285" = "y" -o \
+     "$CONFIG_ARCH_EBSA285_ADDIN" = "y" ]; then
+   define_bool CONFIG_FOOTBRIDGE_ADDIN y
+else
+   define_bool CONFIG_FOOTBRIDGE_ADDIN n
+fi
+if [ "$CONFIG_ARCH_EBSA285_HOST" = "y" -o \
+     "$CONFIG_ARCH_EBSA285_ADDIN" = "y" ]; then
+   define_bool CONFIG_ARCH_EBSA285 y
 fi
 
 # Figure out whether this system uses 26-bit or 32-bit CPUs.
@@ -113,38 +158,6 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
 fi
 
 # Select various configuration options depending on the machine type
-if [ "$CONFIG_ARCH_ARCA5K" = "y" -o \
-     "$CONFIG_ARCH_RPC" = "y" ]; then
-   define_bool CONFIG_ARCH_ACORN y
-else
-   define_bool CONFIG_ARCH_ACORN n
-fi
-
-if [ "$CONFIG_ARCH_CO285" = "y" -o \
-     "$CONFIG_ARCH_FOOTBRIDGE" = "y" ]; then
-   define_bool CONFIG_FOOTBRIDGE y
-else
-   define_bool CONFIG_FOOTBRIDGE n
-fi
-if [ "$CONFIG_ARCH_CATS" = "y" -o \
-     "$CONFIG_ARCH_EBSA285_HOST" = "y" -o \
-     "$CONFIG_ARCH_NETWINDER" = "y" -o \
-     "$CONFIG_ARCH_PERSONAL_SERVER" = "y" ]; then
-   define_bool CONFIG_FOOTBRIDGE_HOST y
-else
-   define_bool CONFIG_FOOTBRIDGE_HOST n
-fi
-if [ "$CONFIG_ARCH_CO285" = "y" -o \
-     "$CONFIG_ARCH_EBSA285_ADDIN" = "y" ]; then
-   define_bool CONFIG_FOOTBRIDGE_ADDIN y
-else
-   define_bool CONFIG_FOOTBRIDGE_ADDIN n
-fi
-if [ "$CONFIG_ARCH_EBSA285_HOST" = "y" -o \
-     "$CONFIG_ARCH_EBSA285_ADDIN" = "y" ]; then
-   define_bool CONFIG_ARCH_EBSA285 y
-fi
-
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    define_bool CONFIG_DISCONTIGMEM y
 else
@@ -167,6 +180,15 @@ else
    define_bool CONFIG_ISA n
    define_bool CONFIG_ISA_DMA n
 fi
+
+# Do we have a PC-type keyboard in this architecture?
+if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" ]; then
+   define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_PC_KEYMAP y
+fi
+if [ "$CONFIG_SA1100_ASSABET" = "y" ]; then
+   define_bool CONFIG_PC_KEYMAP y
+fi
 endmenu
 
 mainmenu_option next_comment
@@ -199,6 +221,7 @@ if [ "$CONFIG_CPU_32" = "y" ]; then
 fi
 if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
      "$CONFIG_ARCH_SA1100" = "y" -o \
+     "$CONFIG_ARCH_CLPS7500" = "y" -o \
      "$CONFIG_ARCH_PERSONAL_SERVER" = "y" -o \
      "$CONFIG_ARCH_CATS" = "y" ]; then
    string 'Default kernel command string' CONFIG_CMDLINE ""
index 62c0ca60e0fbe452ec99b86d5ea10fa3750891bb..9fa2e8e86d929d6a4e0b9cde26775e0c470db8f1 100644 (file)
@@ -5,9 +5,14 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 
+USE_STANDARD_AS_RULE := true
+
 HEAD_OBJ  = head-$(PROCESSOR).o
 ENTRY_OBJ = entry-$(PROCESSOR).o
 
+AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
+AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional
+
 O_OBJS_arc        = dma-arc.o oldlatches.o
 O_OBJS_rpc        = dma-rpc.o
 O_OBJS_footbridge = dma-footbridge.o hw-footbridge.o isa.o
@@ -54,14 +59,8 @@ MX_OBJS      := $(sort $(filter     $(export-objs), $(obj-m)))
 
 all: kernel.o $(HEAD_OBJ) init_task.o
 
-$(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
-       $(CC) $(AFLAGS) -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@
-
 include $(TOPDIR)/Rules.make
 
-.S.o:
-       $(CC) $(AFLAGS) $(AFLAGS_$@) -c -o $*.o $<
-
 # Spell out some dependencies that `make dep' doesn't spot
 entry-armv.o: calls.S ../lib/constants.h
 entry-armo.o: calls.S ../lib/constants.h
index 0ce6d9d21c2df6d1ead2c41fcb4d90134d4ea927..e25331e03497699e06564c1da3a04f78f142b893 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/dec21285.h>
 #include <asm/elf.h>
 #include <asm/setup.h>
-#include <asm/system.h>
+#include <asm/mach-types.h>
 
 #include "arch.h"
 
@@ -219,6 +219,17 @@ static void victor_power_off(void)
        while (1);
 }
 
+
+static void xp860_power_off(void)
+{
+       GPDR |= GPIO_GPIO20;
+       GPSR = GPIO_GPIO20;
+       mdelay(1000);
+       GPCR = GPIO_GPIO20;
+       while(1);
+}
+
+
 extern void select_sa1100_io_desc(void);
 #define SET_BANK(__nr,__start,__size) \
        mi->bank[__nr].start = (__start), \
@@ -273,6 +284,18 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
                setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 );
        }
 
+        else if (machine_is_cerf()) {
+                // 16Meg Ram.
+                SET_BANK( 0, 0xc0000000, 8*1024*1024 );
+                SET_BANK( 1, 0xc8000000, 8*1024*1024 );                        // comment this out for 8MB Cerfs
+                mi->nr_banks = 2;
+
+                ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+                setup_ramdisk(1,  0, 0, 8192);
+                // Save 2Meg for RAMDisk
+                setup_initrd(0xc0500000, 3*1024*1024);
+        }
+
        else if (machine_is_empeg()) {
                SET_BANK( 0, 0xc0000000, 4*1024*1024 );
                SET_BANK( 1, 0xc8000000, 4*1024*1024 );
@@ -309,6 +332,18 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
                setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
        }
 
+       else if (machine_is_nanoengine()) {
+               SET_BANK( 0, 0xc0000000, 32*1024*1024 );
+               mi->nr_banks = 1;
+
+               ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+               setup_ramdisk( 1, 0, 0, 8192 );
+               setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
+
+               /* Get command line parameters passed from the loader (if any) */
+               if( *((char*)0xc0000100) )
+                       *cmdline = ((char *)0xc0000100);
+       }
        else if (machine_is_tifon()) {
                SET_BANK( 0, 0xc0000000, 16*1024*1024 );
                SET_BANK( 1, 0xc8000000, 16*1024*1024 );
@@ -335,6 +370,12 @@ fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
                pm_power_off = victor_power_off;
        }
 
+       else if (machine_is_xp860()) {
+               SET_BANK( 0, 0xc0000000, 32*1024*1024 );
+               mi->nr_banks = 1;
+
+               pm_power_off = xp860_power_off;
+       }
 }
 
 #ifdef CONFIG_SA1100_ASSABET
@@ -356,6 +397,13 @@ MACHINE_START(BRUTUS, "Intel Brutus (SA1100 eval board)")
        FIXUP(fixup_sa1100)
 MACHINE_END
 #endif
+#ifdef CONFIG_SA1100_CERF
+MACHINE_START(CERF, "Intrinsyc CerfBoard")
+       MAINTAINER("Pieter Truter")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
+#endif
 #ifdef CONFIG_SA1100_EMPEG
 MACHINE_START(EMPEG, "empeg MP3 Car Audio Player")
        BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
@@ -381,6 +429,12 @@ MACHINE_START(LART, "LART")
        FIXUP(fixup_sa1100)
 MACHINE_END
 #endif
+#ifdef CONFIG_SA1100_NANOENGINE
+MACHINE_START(NANOENGINE, "BSE nanoEngine")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
+#endif
 #ifdef CONFIG_SA1100_PLEB
 MACHINE_START(PLEB, "PLEB")
        BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
index fc14d6c45661868a1e6387078d17a948bed66750..8dafc4db96f4f3834bd6519bbb95458e45c6395f 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
+#include <asm/mach-types.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
@@ -187,10 +188,6 @@ EXPORT_SYMBOL(__arch_copy_from_user);
 EXPORT_SYMBOL(__arch_copy_to_user);
 EXPORT_SYMBOL(__arch_clear_user);
 EXPORT_SYMBOL(__arch_strnlen_user);
-#elif defined(CONFIG_CPU_26)
-EXPORT_SYMBOL(uaccess_kernel);
-EXPORT_SYMBOL(uaccess_user);
-#endif
 
        /* consistent area handling */
 EXPORT_SYMBOL(pci_alloc_consistent);
@@ -198,6 +195,11 @@ EXPORT_SYMBOL(consistent_alloc);
 EXPORT_SYMBOL(consistent_free);
 EXPORT_SYMBOL(consistent_sync);
 
+#elif defined(CONFIG_CPU_26)
+EXPORT_SYMBOL(uaccess_kernel);
+EXPORT_SYMBOL(uaccess_user);
+#endif
+
        /* gcc lib functions */
 EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
 EXPORT_SYMBOL_NOVERS(__ashldi3);
index b2c6441988ff1b95b34ce4c82165edc1d24fa605..0b519e9c3fe2e1f6a91163965a3ca5ca8b252730 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 
 #include <asm/irq.h>
-#include <asm/system.h>
+#include <asm/mach-types.h>
 
 #include "bios32.h"
 
@@ -198,20 +198,35 @@ void __init
 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                        struct resource *res, int resource)
 {
-       unsigned long where, size;
-       u32 reg;
+       u32 val, check;
+       int reg;
 
        if (debug_pci)
                printk("PCI: Assigning %3s %08lx to %s\n",
                        res->flags & IORESOURCE_IO ? "IO" : "MEM",
                        res->start, dev->name);
 
-       where = PCI_BASE_ADDRESS_0 + resource * 4;
-       size  = res->end - res->start;
-
-       pci_read_config_dword(dev, where, &reg);
-       reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-       pci_write_config_dword(dev, where, reg);
+       val = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+       if (resource < 6) {
+               reg = PCI_BASE_ADDRESS_0 + 4*resource;
+       } else if (resource == PCI_ROM_RESOURCE) {
+               res->flags |= PCI_ROM_ADDRESS_ENABLE;
+               val |= PCI_ROM_ADDRESS_ENABLE;
+               reg = dev->rom_base_reg;
+       } else {
+               /* Somebody might have asked allocation of a
+                * non-standard resource.
+                */
+               return;
+       }
+       pci_write_config_dword(dev, reg, val);
+       pci_read_config_dword(dev, reg, &check);
+       if ((val ^ check) & ((val & PCI_BASE_ADDRESS_SPACE_IO) ?
+           PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+               printk(KERN_ERR "PCI: Error while updating region "
+                       "%s/%d (%08x != %08x)\n", dev->slot_name,
+                       resource, val, check);
+       }
 }
 
 void __init pcibios_update_irq(struct pci_dev *dev, int irq)
index da81b3b057c7a2a7d2eb5a158f42bec04ec55e49..e0b9164381047363c72c04edd45a1c29ba5bd973 100644 (file)
 
 #elif defined(CONFIG_ARCH_L7200)
 
-               .macro  addruart,rx
+               .equ    io_virt, IO_BASE
+               .equ    io_phys, IO_START
 
+               .macro  addruart,rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
-               moveq   \rx, #0x80000000        @ physical base address
-               movne   \rx, #0xd0000000        @ virtual address
+               moveq   \rx, #io_phys           @ physical base address
+               movne   \rx, #io_virt           @ virtual address
                add     \rx, \rx, #0x00044000   @ Ser1
 @              add     \rx, \rx, #0x00045000   @ Ser2
                .endm
index 7fb43c68a9998982e1d001b22a05bd18e03f197b..3238b3a3c82b370f66c2566e47da5fc34783baa0 100644 (file)
@@ -274,7 +274,7 @@ void __init dc21285_init(void)
 
        cfn_mode = __footbridge_cfn_mode();
 
-       printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX in "
+       printk(KERN_INFO "PCI: DC21285 footbridge, revision %02lX, in "
                "%s mode\n", *CSR_CLASSREV & 0xff, cfn_mode ?
                "central function" : "addin");
 
index 5a2f93b67f9fb324c11a23cfc8805af4edb60781..25fbcccd82c203983421b7e2a0e8f22223f281b2 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/fiq.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 
 #include "dma.h"
 
index 35e3c35a3ed41d1355ffc5814480d8d8e1c24e9a..c7eecfe42f500fb77f101583c82989cf4baed7ba 100644 (file)
@@ -315,7 +315,7 @@ static struct dma_ops floppy_dma_ops = {
 /*
  * This is virtual DMA - we don't need anything here.
  */
-static int sound_enable_disable_dma(dmach_t channel, dma_t *dma)
+static void sound_enable_disable_dma(dmach_t channel, dma_t *dma)
 {
 }
 
index 7ed4c28ca251f7f932c6936f6cfba899e7fe1de2..6fe844db405640354b0194216c1bdd0c777b79c1 100644 (file)
@@ -248,24 +248,23 @@ int request_dma(dmach_t channel, const char *device_id)
        return -EINVAL;
 }
 
-static int no_dma(void)
+int get_dma_residue(dmach_t channel)
 {
        return 0;
 }
 
 #define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a)
-GLOBAL_ALIAS(disable_dma, no_dma);
-GLOBAL_ALIAS(enable_dma, no_dma);
-GLOBAL_ALIAS(free_dma, no_dma);
-GLOBAL_ALIAS(get_dma_residue, no_dma);
-GLOBAL_ALIAS(get_dma_list, no_dma);
-GLOBAL_ALIAS(set_dma_mode, no_dma);
-GLOBAL_ALIAS(set_dma_page, no_dma);
-GLOBAL_ALIAS(set_dma_count, no_dma);
-GLOBAL_ALIAS(set_dma_addr, no_dma);
-GLOBAL_ALIAS(set_dma_sg, no_dma);
-GLOBAL_ALIAS(set_dma_speed, no_dma);
-GLOBAL_ALIAS(init_dma, no_dma);
+GLOBAL_ALIAS(disable_dma, get_dma_residue);
+GLOBAL_ALIAS(enable_dma, get_dma_residue);
+GLOBAL_ALIAS(free_dma, get_dma_residue);
+GLOBAL_ALIAS(get_dma_list, get_dma_residue);
+GLOBAL_ALIAS(set_dma_mode, get_dma_residue);
+GLOBAL_ALIAS(set_dma_page, get_dma_residue);
+GLOBAL_ALIAS(set_dma_count, get_dma_residue);
+GLOBAL_ALIAS(set_dma_addr, get_dma_residue);
+GLOBAL_ALIAS(set_dma_sg, get_dma_residue);
+GLOBAL_ALIAS(set_dma_speed, get_dma_residue);
+GLOBAL_ALIAS(init_dma, get_dma_residue);
 
 #endif
 
index 5acfd9f24673d532600cad597b3bc657f37c05c5..6d9b425ea8a23b1e5e3f6df1a0be4f5b64e49be6 100644 (file)
@@ -265,8 +265,7 @@ static int exec_mmap(void)
  * Set up the expansion card
  * daemon's environment.
  */
-static void
-ecard_init_task(void)
+static void ecard_init_task(int force)
 {
        /* We want to set up the page tables for the following mapping:
         *  Virtual     Physical
@@ -282,7 +281,8 @@ ecard_init_task(void)
        pgd_t *src_pgd, *dst_pgd;
        unsigned int dst_addr = IO_START;
 
-       exec_mmap();
+       if (!force)
+               exec_mmap();
 
        src_pgd = pgd_offset(current->mm, IO_BASE);
        dst_pgd = pgd_offset(current->mm, dst_addr);
@@ -309,21 +309,24 @@ ecard_init_task(void)
 static int
 ecard_task(void * unused)
 {
-       current->session = 1;
-       current->pgrp = 1;
+       struct task_struct *tsk = current;
+
+       tsk->session = 1;
+       tsk->pgrp = 1;
 
        /*
         * We don't want /any/ signals, not even SIGKILL
         */
-       sigfillset(&current->blocked);
-       sigemptyset(&current->signal);
+       sigfillset(&tsk->blocked);
+       sigemptyset(&tsk->signal);
+       recalc_sigpending(tsk);
 
-       strcpy(current->comm, "kecardd");
+       strcpy(tsk->comm, "kecardd");
 
        /*
         * Set up the environment
         */
-       ecard_init_task();
+       ecard_init_task(0);
 
        while (1) {
                struct ecard_request *req;
@@ -332,7 +335,7 @@ ecard_task(void * unused)
                        req = xchg(&ecard_req, NULL);
 
                        if (req == NULL) {
-                               sigemptyset(&current->signal);
+                               sigemptyset(&tsk->signal);
                                interruptible_sleep_on(&ecard_wait);
                        }
                } while (req == NULL);
@@ -368,7 +371,7 @@ ecard_call(struct ecard_request *req)
         */
        if ((current == &init_task || in_interrupt()) &&
            req->req == req_reset && req->ec == NULL) {
-               ecard_init_task();
+               ecard_init_task(1);
                ecard_task_reset(req);
        } else {
                if (ecard_pid <= 0)
index d6fa94867f607a1cbd8f8faabd6e3c6a562842f2..ab0f4e69e45bd1e99014200b817521810650ae2a 100644 (file)
 
                .text
 
-@ Offsets into task structure
-@ ---------------------------
-@
-#define STATE          0
-#define COUNTER                4
-#define PRIORITY       8
-#define FLAGS          12
-#define SIGPENDING     16
-
-#define PF_TRACESYS    0x20
-
 @ Bad Abort numbers
 @ -----------------
 @
 #define BAD_IRQ                3
 #define BAD_UNDEFINSTR 4
 
-@ OS version number used in SWIs
-@  RISC OS is 0
-@  RISC iX is 8
-@
-#define OS_NUMBER      9
-
 @
 @ Stack format (ensured by USER_* and SVC_*)
 @
@@ -456,6 +439,7 @@ vector_IRQ: ldr     r13, .LCirq                     @ I will leave this one in just in case...
                orr     lr, lr, #0x08000003             @ Force SVC
                bne     do_IRQ
                mov     r4, #0
+               get_current_task r5
                b       ret_with_reschedule
 
                irq_prio_table
index 5d4f216b6737ae812613fde4000cbdc2b5b511e2..002c399333cb84a93d4fe1a94d165e99ed9c41c7 100644 (file)
@@ -32,8 +32,6 @@
 
                .text
 
-#define PT_TRACESYS    0x00000002
-
 @ Bad Abort numbers
 @ -----------------
 @
 #define BAD_IRQ                3
 #define BAD_UNDEFINSTR 4
 
-@ OS version number used in SWIs
-@  RISC OS is 0
-@  RISC iX is 8
-@
-#define OS_NUMBER      9
-
 @
 @ Stack format (ensured by USER_* and SVC_*)
 @
@@ -426,12 +418,15 @@ ENTRY(soft_irq_mask)
                .endm
 
 #elif defined(CONFIG_ARCH_L7200)
-/* Don't use fast interrupts */
+       
+               .equ    irq_base_addr,  IO_BASE_2
+
                .macro  disable_fiq
                .endm
  
                .macro  get_irqnr_and_base, irqnr, irqstat, base
-               ldr     r4, =0xe0001000                 @ Virt addr status reg
+               mov     r4, #irq_base_addr              @ Virt addr IRQ regs
+               add     r4, r4, #0x00001000             @ Status reg
                ldr     \irqstat, [r4]                  @ get interrupts
                mov     \irqnr, #0
 1001:          tst     \irqstat, #1
@@ -727,6 +722,7 @@ __irq_usr:  sub     sp, sp, #S_FRAME_SIZE
                @
                bne     do_IRQ
                mov     r4, #0
+               get_current_task r5
                b       ret_with_reschedule
 
                .align  5
index c260b8e1919ec576727646942c8534eef1f4adf3..b22720cd5790f6d2f4bc4830e42517784a1ac3a2 100644 (file)
@@ -1,4 +1,13 @@
 #include <linux/config.h>
+
+#define PT_TRACESYS    0x00000002
+
+@ OS version number used in SWIs
+@  RISC OS is 0
+@  RISC iX is 8
+@
+#define OS_NUMBER      9
+
 /*============================================================================
  * All exits to user mode from the kernel go through this code.
  */
@@ -22,25 +31,23 @@ slow_syscall_return:
                add     sp, sp, #S_OFF
 ret_from_sys_call:                             @ external entry
                get_softirq r0
+               get_current_task r5
                ldmia   r0, {r0, r1}            @ softirq_active, softirq_mask
                mov     r4, #1                  @ flag this as being syscall return
                tst     r0, r1
                blne    SYMBOL_NAME(do_softirq)
-ret_with_reschedule:                           @ external entry (__irq_usr)
-               get_current_task r5
+ret_with_reschedule:                           @ external entry (r5 must be set) (__irq_usr)
                ldr     r0, [r5, #TSK_NEED_RESCHED]
                ldr     r1, [r5, #TSK_SIGPENDING]
                teq     r0, #0
                bne     ret_reschedule
                teq     r1, #0                  @ check for signals
-               bne     ret_signal
-
+               blne    ret_signal
 ret_from_all:  restore_user_regs               @ internal
 
 ret_signal:    mov     r1, sp                  @ internal
-               adrsvc  al, lr, ret_from_all
                mov     r2, r4
-               b       SYMBOL_NAME(do_signal)
+               b       SYMBOL_NAME(do_signal)  @ note the bl above sets lr
 
 ret_reschedule:        adrsvc  al, lr, ret_with_reschedule     @ internal
                b       SYMBOL_NAME(schedule)
@@ -48,12 +55,13 @@ ret_reschedule:     adrsvc  al, lr, ret_with_reschedule     @ internal
                .globl  ret_from_exception
 ret_from_exception:                            @ external entry
                get_softirq r0
+               get_current_task r5
                ldmia   r0, {r0, r1}            @ softirq_active, softirq_mask
                mov     r4, #0
                tst     r0, r1
+               ldr     r6, [sp, #S_PSR]
                blne    SYMBOL_NAME(do_softirq)
-               ldr     r0, [sp, #S_PSR]
-               tst     r0, #3                  @ returning to user mode?
+               tst     r6, #3                  @ returning to user mode?
                beq     ret_with_reschedule
                b       ret_from_all
 
index 6597de1846a3194b109f54d0480612d914d1630d..b74d7550f6d60c94a42885a7fbd4ed7316b07164 100644 (file)
@@ -83,8 +83,11 @@ int fiq_def_op(void *ref, int relinquish)
        return 0;
 }
 
-static struct fiq_handler default_owner =
-       { NULL, "default", fiq_def_op, NULL };
+static struct fiq_handler default_owner = {
+       name:   "default",
+       fiq_op: fiq_def_op,
+};
+
 static struct fiq_handler *current_fiq = &default_owner;
 
 int get_fiq_list(char *buf)
index df5b02ae83dc45be5038cc288b47ad6172b10494..f0360a3d9c8e3af5edcce16345de6df7b0c7f120 100644 (file)
@@ -1,11 +1,13 @@
 /*
  * linux/arch/arm/kernel/head-armo.S
  *
- * Copyright (C) 1994, 1995, 1996, 1997 Russell King
+ * Copyright (C) 1994-2000 Russell King
  *
  * 26-bit kernel startup code
  */
+#include <linux/config.h>
 #include <linux/linkage.h>
+#include <asm/mach-types.h>
 
                .globl  SYMBOL_NAME(swapper_pg_dir)
                .equ    SYMBOL_NAME(swapper_pg_dir),    0x0207d000
 ENTRY(stext)
 ENTRY(_stext)
 __entry:       cmp     pc, #0x02000000
-               ldrlt   pc, LC1                 @ if 0x01800000, call at 0x02080000
+               ldrlt   pc, LC0                 @ if 0x01800000, call at 0x02080000
                teq     r0, #0                  @ Check for old calling method
-               blne    Loldparams              @ Move page if old
-               adr     r5, LC0
-               ldmia   r5, {r5, r6, sl, sp}    @ Setup stack
-               mov     r4, #0
-1:             cmp     r5, sl                  @ Clear BSS
-               strcc   r4, [r5], #4
+               blne    oldparams               @ Move page if old
+               adr     r0, LC0
+               ldmib   r0, {r2-r5, sp}         @ Setup stack
+               mov     r0, #0
+1:             cmp     r2, r3                  @ Clear BSS
+               strcc   r0, [r2], #4
                bcc     1b
-               mov     r0, #0xea000000         @ Point undef instr to continuation
-               adr     r5, Lcontinue - 12
-               orr     r5, r0, r5, lsr #2
-               str     r5, [r4, #4]
-               mov     r2, r4
-               ldr     r5, Larm2_id
-               swp     r0, r0, [r2]            @ check for swp (ARM2 can't)
-               ldr     r5, Larm250_id
-               mrc     15, 0, r0, c0, c0       @ check for CP#15 (ARM250 can't)
-               mov     r5, r0                  @ Use processor ID if we do have CP#15
-Lcontinue:     str     r5, [r6]
-               mov     r5, #0xeb000000         @ Point undef instr vector to itself
-               sub     r5, r5, #2
-               str     r5, [r4, #4]
+
+               bl      detect_proc_type
+               str     r0, [r4]
+               bl      detect_arch_type
+               str     r0, [r5]
+
                mov     fp, #0
                b       SYMBOL_NAME(start_kernel)
 
-LC1:           .word   SYMBOL_NAME(_stext)
-LC0:           .word   SYMBOL_NAME(__bss_start)
-               .word   SYMBOL_NAME(processor_id)
-               .word   SYMBOL_NAME(_end)
-               .word   SYMBOL_NAME(init_task_union)+8192
-Larm2_id:      .long   0x41560200
-Larm250_id:    .long   0x41560250
+LC0:           .word   SYMBOL_NAME(_stext)
+               .word   SYMBOL_NAME(__bss_start)                @ r2
+               .word   SYMBOL_NAME(_end)                       @ r3
+               .word   SYMBOL_NAME(processor_id)               @ r4
+               .word   SYMBOL_NAME(__machine_arch_type)        @ r5
+               .word   SYMBOL_NAME(init_task_union)+8192       @ sp
+arm2_id:       .long   0x41560200
+arm250_id:     .long   0x41560250
                .align
 
-Loldparams:    mov     r4, #0x02000000
+oldparams:     mov     r4, #0x02000000
                add     r3, r4, #0x00080000
                add     r4, r4, #0x0007c000
 1:             ldmia   r0!, {r5 - r12}
                stmia   r4!, {r5 - r12}
                cmp     r4, r3
                blt     1b
-               movs    pc, lr
+               mov     pc, lr
+
+/*
+ * We need some way to automatically detect the difference between
+ * these two machines.  Unfortunately, it is not possible to detect
+ * the presence of the SuperIO chip, because that will hang the old
+ * Archimedes machines solid.
+ */
+/* DAG: Outdated, these have been combined !!!!!!! */
+detect_arch_type:
+#if defined(CONFIG_ARCH_ARC)
+               mov     r0, #MACH_TYPE_ARCHIMEDES
+#elif defined(CONFIG_ARCH_A5K)
+               mov     r0, #MACH_TYPE_A5K
+#endif
+               mov     pc, lr
+
+detect_proc_type:
+               mov     r2, #0xea000000         @ Point undef instr to continuation
+               adr     r0, continue - 12
+               orr     r0, r2, r0, lsr #2
+               mov     r1, #0
+               str     r0, [r1, #4]
+               ldr     r0, arm2_id
+               swp     r2, r2, [r1]            @ check for swp (ARM2 can't)
+               ldr     r0, arm250_id
+               mrc     15, 0, r0, c0, c0       @ check for CP#15 (ARM250 can't)
+continue:      mov     r2, #0xeb000000         @ Make undef vector loop
+               sub     r2, r2, #2
+               str     r2, [r1, #4]
+               mov     pc, lr
index 38bfc87603ca75eb45211b8d0f5f552f23b432cf..e253c7efa0ef9e1fead4d1264210d7731b6afe8e 100644 (file)
@@ -19,6 +19,7 @@
 #endif
 
 #define SWAPPER_PGDIR_OFFSET   0x4000
+#define K(a,b,c)       ((a) << 24 | (b) << 12 | (c))
 
                .globl  SYMBOL_NAME(swapper_pg_dir)
                .equ    SYMBOL_NAME(swapper_pg_dir),    TEXTADDR - 0x8000 + SWAPPER_PGDIR_OFFSET
                .type   stext, #function
 ENTRY(stext)
 ENTRY(_stext)
-
+/*
+ * Entry point.  The general rules are:
+ *  should be called with r0 == 0
+ *  r1 contains the unique architecture number
+ *  with MMU is off, I-cache may be on or off, D-cache should be off.
+ * See linux/arch/arm/kernel/arch.c and linux/include/asm-arm/system.h
+ * for the complete list of numbers for r1.  If you require a new number,
+ * please follow the instructions given towards the end of
+ * linux/Documentation/arm/README.
+ */
+               mov     r12, r0
+/*
+ * NOTE!  Any code which is placed here should be done for one of
+ * the following reasons:
+ *
+ *  1. Compatability with old production boot firmware (ie, users
+ *     actually have and are booting the kernel with the old firmware)
+ *     and therefore will be eventually removed.
+ *  2. Cover the case when there is no boot firmware.  This is not
+ *     ideal, but in this case, it should ONLY set r0 and r1 to the
+ *     appropriate value.
+ */
 #ifdef CONFIG_ARCH_NETWINDER
 /*
  * Compatability cruft for old NetWinder NeTTroms.  This
@@ -63,28 +85,18 @@ ENTRY(_stext)
                mov     r5, #0
                movne   pc, r0
 
-               mov     r0, #0                  @ catch old NeTTroms
                mov     r1, #5                  @ (will go in 2.5)
+               mov     r12, #2 << 24           @ scheduled for removal in 2.5.xx
+               orr     r12, r12, #5 << 12
 #endif
 #ifdef CONFIG_ARCH_L7200
 /*
  * FIXME - No bootloader, so manually set 'r1' with our architecture number.
  */
-               mov     r0, #0
                mov     r1, #19
 #endif
 
-/*
- * Entry point.  Entry *must* be called with r0 == 0, with the MMU off.
- *  r1 contains the unique architecture number.  See
- * linux/arch/arm/kernel/arch.c and linux/include/asm-arm/system.h for
- * the complete list.  If you require a new number, please follow the
- * instructions given towards the end of Documentation/arm/README.
- */
-__entry:       teq     r0, #0                          @ wrong register vals?
-               movne   r0, #'i'                        @ yes, error 'i'
-               bne     __error
-               bl      __lookup_processor_type
+__entry:       bl      __lookup_processor_type
                teq     r10, #0                         @ invalid processor?
                moveq   r0, #'p'                        @ yes, error 'p'
                beq     __error
@@ -98,6 +110,7 @@ __entry:     teq     r0, #0                          @ wrong register vals?
                                                        @ (return control reg)
 
 __switch_data: .long   __mmap_switched
+               .long   SYMBOL_NAME(compat)
                .long   SYMBOL_NAME(__bss_start)
                .long   SYMBOL_NAME(_end)
                .long   SYMBOL_NAME(processor_id)
@@ -123,8 +136,9 @@ __ret:              ldr     lr, __switch_data
                .align  5
 __mmap_switched:
                adr     r3, __switch_data + 4
-               ldmia   r3, {r4, r5, r6, r7, r8, sp}    @ r4 = __bss_start
+               ldmia   r3, {r2, r4, r5, r6, r7, r8, sp}@ r2 = compat
                                                        @ sp = stack pointer
+               str     r12, [r2]
 
                mov     fp, #0                          @ Clear BSS
 1:             cmp     r4, r5
index b56b944e7a9529e70aea0e660fede6fb5a12cd30..41ff450a57069ea2606fd53bfaaf718863519e37 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <asm/io.h>
 #include <asm/leds.h>
-#include <asm/system.h>
+#include <asm/mach-types.h>
 
 #define IRDA_IO_BASE           0x180
 #define GP1_IO_BASE            0x338
index 27786cdd23d3f54c60bba3d59a10333838b2fd23..5acfab1e27a144ef7baca16ec5c6aa253d599e2e 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <asm/delay.h>
 #include <asm/hardware.h>
-
+#include <asm/mach-types.h>
 
 /*
  * SA1100 GPIO edge detection for IRQs:
@@ -130,12 +130,40 @@ void __init sa1111_init(void){
    * any other SA-1111 functional blocks must be enabled separately
    * using the SKPCR.
    */
+
+  {
+  /*
+   * SA1111 DMA bus master setup 
+   */
+       int cas;
+
+       /* SA1111 side */
+       switch ( (MDCNFG>>12) & 0x03 ) {
+       case 0x02:
+               cas = 0; break;
+       case 0x03:
+               cas = 1; break;
+       default:
+               cas = 1; break;
+       }
+       SMCR = 1                /* 1: memory is SDRAM */
+               | ( 1 << 1 )    /* 1:MBGNT is enable */
+               | ( ((MDCNFG >> 4) & 0x07) << 2 )       /* row address lines */
+               | ( cas << 5 ); /* CAS latency */
+
+       /* SA1110 side */
+       GPDR |= 1<<21;
+       GPDR &= ~(1<<22);
+       GAFR |= ( (1<<21) | (1<<22) );
+
+       TUCR |= (1<<10);
+  }
 }
 
 #endif
 
 
-static void __init hw_sa1100_init(void)
+static int __init hw_sa1100_init(void)
 {
        if( machine_is_assabet() ){
                if(machine_has_neponset()){
@@ -147,7 +175,10 @@ static void __init hw_sa1100_init(void)
                                "hasn't been configured in the kernel\n" );
 #endif
                }
+       } else if (machine_is_xp860()) {
+               sa1111_init();
        }
+       return 0;
 }
 
 module_init(hw_sa1100_init);
index 8af0c3b3f72c0fc2396035dc6815d3eb87a28675..69b72624d8c047dbf19ce16499f8401044ca6eb4 100644 (file)
 #include <asm/io.h>
 #include <asm/system.h>
 
-#ifndef cliIF
-#define cliIF()
-#endif
-
 /*
- * Maximum IRQ count.  Currently, this is arbitary.
- * However, it should not be set too low to prevent
- * false triggering.  Conversely, if it is set too
- * high, then you could miss a stuck IRQ.
+ * Maximum IRQ count.  Currently, this is arbitary.  However, it should
+ * not be set too low to prevent false triggering.  Conversely, if it
+ * is set too high, then you could miss a stuck IRQ.
  *
- * Maybe we ought to set a timer and re-enable the
- * IRQ at a later time?
+ * Maybe we ought to set a timer and re-enable the IRQ at a later time?
  */
 #define MAX_IRQ_CNT    100000
 
@@ -94,7 +88,6 @@ void disable_irq(unsigned int irq)
        unsigned long flags;
 
        spin_lock_irqsave(&irq_controller_lock, flags);
-       cliIF();
        irq_desc[irq].enabled = 0;
        irq_desc[irq].mask(irq);
        spin_unlock_irqrestore(&irq_controller_lock, flags);
@@ -105,7 +98,6 @@ void enable_irq(unsigned int irq)
        unsigned long flags;
 
        spin_lock_irqsave(&irq_controller_lock, flags);
-       cliIF();
        irq_desc[irq].probing = 0;
        irq_desc[irq].triggered = 0;
        irq_desc[irq].enabled = 1;
index b309c2ea329e9906e3802dcc7507a263024d3b18..3de4c96f935e6c74d4a7f4357548a87c636e67a4 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <asm/hardware.h>
 #include <asm/leds.h>
+#include <asm/mach-types.h>
 #include <asm/system.h>
 
 #define LED_STATE_ENABLED      1
@@ -35,7 +36,7 @@ static char hw_led_state;
 static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED;
 extern spinlock_t gpio_lock;
 
-#ifdef CONFIG_FOOTBRIDGE
+#if defined(CONFIG_ARCH_EBSA285) || defined(CONFIG_ARCH_CO285)
 
 static void ebsa285_leds_event(led_event_t evt)
 {
@@ -76,15 +77,20 @@ static void ebsa285_leds_event(led_event_t evt)
 #ifdef CONFIG_LEDS_CPU
        case led_idle_start:
                if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state |= XBUS_LED_RED;
+                       hw_led_state |= XBUS_LED_AMBER;
                break;
 
        case led_idle_end:
                if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state &= ~XBUS_LED_RED;
+                       hw_led_state &= ~XBUS_LED_AMBER;
                break;
 #endif
 
+       case led_halted:
+               if (!(led_state & LED_STATE_CLAIMED))
+                       hw_led_state &= ~XBUS_LED_RED;
+               break;
+
        case led_green_on:
                if (led_state & LED_STATE_CLAIMED)
                        hw_led_state &= ~XBUS_LED_GREEN;
@@ -174,6 +180,11 @@ static void netwinder_leds_event(led_event_t evt)
                break;
 #endif
 
+       case led_halted:
+               if (!(led_state & LED_STATE_CLAIMED))
+                       hw_led_state |= GPIO_RED_LED;
+               break;
+
        case led_green_on:
                if (led_state & LED_STATE_CLAIMED)
                        hw_led_state |= GPIO_GREEN_LED;
@@ -229,7 +240,7 @@ EXPORT_SYMBOL(leds_event);
 
 static int __init leds_init(void)
 {
-#ifdef CONFIG_FOOTBRIDGE
+#if defined(CONFIG_ARCH_EBSA285) || defined(CONFIG_ARCH_CO285)
        if (machine_is_ebsa285() || machine_is_co285())
                leds_event = ebsa285_leds_event;
 #endif
index f2f0325c3fa3e223bd68abe8152cf8e5ab733cc9..fc4662c2aee775f9c10e0dc212f3f3b1c8271373 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <asm/hardware.h>
 #include <asm/leds.h>
+#include <asm/mach-types.h>
 #include <asm/system.h>
 
 
@@ -95,6 +96,9 @@ static void assabet_leds_event(led_event_t evt)
                break;
 #endif
 
+       case led_halted:
+               break;
+
        case led_green_on:
                if (led_state & LED_STATE_CLAIMED)
                        hw_led_state &= ~BCR_LED_GREEN;
@@ -302,6 +306,100 @@ static void lart_leds_event(led_event_t evt)
 
 #endif /* CONFIG_SA1100_LART */
 
+#ifdef CONFIG_SA1100_CERF
+#define LED_D0          GPIO_GPIO(0)
+#define LED_D1          GPIO_GPIO(1)
+#define LED_D2          GPIO_GPIO(2)
+#define LED_D3          GPIO_GPIO(3)
+#define LED_MASK        (LED_D0|LED_D1|LED_D2|LED_D3)
+
+static void cerf_leds_event(led_event_t evt)
+{
+        unsigned long flags;
+
+        save_flags_cli(flags);
+
+        switch (evt) {
+        case led_start:
+                hw_led_state = LED_MASK;
+                led_state = LED_STATE_ENABLED;
+                break;
+
+        case led_stop:
+                led_state &= ~LED_STATE_ENABLED;
+                break;
+
+        case led_claim:
+                led_state |= LED_STATE_CLAIMED;
+                hw_led_state = LED_MASK;
+                break;
+        case led_release:
+                led_state &= ~LED_STATE_CLAIMED;
+                hw_led_state = LED_MASK;
+                break;
+
+#ifdef CONFIG_LEDS_TIMER
+        case led_timer:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state ^= LED_D0;
+                break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+        case led_idle_start:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D1;
+                break;
+
+        case led_idle_end:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D1;
+                break;
+#endif
+        case led_green_on:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D2;
+                break;
+
+        case led_green_off:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D2;
+                break;
+
+        case led_amber_on:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D3;
+                break;
+
+        case led_amber_off:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D3;
+                break;
+
+        case led_red_on:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D1;
+                break;
+
+        case led_red_off:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D1;
+                break;
+
+        default:
+                break;
+        }
+
+        if  (led_state & LED_STATE_ENABLED) {
+                GPSR = hw_led_state;
+                GPCR = hw_led_state ^ LED_MASK;
+        }
+
+        restore_flags(flags);
+}
+
+#endif /* CONFIG_SA1100_CERF */
+
 static void dummy_leds_event(led_event_t evt)
 {
 }
@@ -325,7 +423,13 @@ sa1100_leds_init(void)
        if (machine_is_lart())
                leds_event = lart_leds_event;
 #endif
-
+#ifdef CONFIG_SA1100_CERF
+       if (machine_is_cerf())
+       {
+                //GPDR |= 0x0000000F;
+               leds_event = cerf_leds_event;
+       }
+#endif
        leds_event(led_start);
        return 0;
 }
index 3d6758ff45f75164074e9beafdc96b3af9d86ebb..91b9e5d62e2ec8ff982371e87213e05aaff56027 100644 (file)
@@ -1,14 +1,17 @@
 /* Support for the latches on the old Archimedes which control the floppy,
  * hard disc and printer
  *
- * (c) David Alan Gilbert 1995/1996
+ * (c) David Alan Gilbert 1995/1996,2000
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <asm/io.h>
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/arch/oldlatches.h>
 
 static unsigned char latch_a_copy;
 static unsigned char latch_b_copy;
index 3ef5bc59df9a2ca53fbe63f92218f8fb9fa5556f..478810936cf7e83e31f59b1bd6539d8f620c7296 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/leds.h>
 #include <asm/uaccess.h>
 
 /*
@@ -32,7 +33,7 @@
 #define IDLE_CLOCK_SLOW        2
 #define IDLE_CLOCK_FAST        3
 
-extern char *processor_modes[];
+extern const char *processor_modes[];
 extern void setup_mm_for_reboot(char mode);
 
 asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
@@ -109,10 +110,12 @@ __setup("reboot=", reboot_setup);
 
 void machine_halt(void)
 {
+       leds_event(led_halted);
 }
 
 void machine_power_off(void)
 {
+       leds_event(led_halted);
        if (pm_power_off)
                pm_power_off();
 }
index 8118b6a683165c34b6b7b57105d6f8dab36a4092..ab2e095afecfed632579f8f8f5c608cf2d1d4cd4 100644 (file)
@@ -53,8 +53,8 @@ void __down(struct semaphore * sem)
 {
        struct task_struct *tsk = current;
        DECLARE_WAITQUEUE(wait, tsk);
-       tsk->state = TASK_UNINTERRUPTIBLE;
-       add_wait_queue(&sem->wait, &wait);
+       tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
+       add_wait_queue_exclusive(&sem->wait, &wait);
 
        spin_lock_irq(&semaphore_lock);
        sem->sleepers++;
@@ -67,28 +67,28 @@ void __down(struct semaphore * sem)
                 */
                if (!atomic_add_negative(sleepers - 1, &sem->count)) {
                        sem->sleepers = 0;
-                       wake_up(&sem->wait);
                        break;
                }
                sem->sleepers = 1;      /* us - see -1 above */
                spin_unlock_irq(&semaphore_lock);
 
                schedule();
-               tsk->state = TASK_UNINTERRUPTIBLE;
+               tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
                spin_lock_irq(&semaphore_lock);
        }
        spin_unlock_irq(&semaphore_lock);
        remove_wait_queue(&sem->wait, &wait);
        tsk->state = TASK_RUNNING;
+       wake_up(&sem->wait);
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-       int retval;
+       int retval = 0;
        struct task_struct *tsk = current;
        DECLARE_WAITQUEUE(wait, tsk);
-       tsk->state = TASK_INTERRUPTIBLE;
-       add_wait_queue(&sem->wait, &wait);
+       tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+       add_wait_queue_exclusive(&sem->wait, &wait);
 
        spin_lock_irq(&semaphore_lock);
        sem->sleepers ++;
@@ -102,12 +102,10 @@ int __down_interruptible(struct semaphore * sem)
                 * it has contention. Just correct the count
                 * and exit.
                 */
-               retval = -EINTR;
                if (signal_pending(current)) {
+                       retval = -EINTR;
                        sem->sleepers = 0;
-                       if (atomic_add_negative(sleepers, &sem->count))
-                               break;
-                       wake_up(&sem->wait);
+                       atomic_add(sleepers, &sem->count);
                        break;
                }
 
@@ -118,8 +116,6 @@ int __down_interruptible(struct semaphore * sem)
                 * the lock.
                 */
                if (!atomic_add_negative(sleepers - 1, &sem->count)) {
-                       wake_up(&sem->wait);
-                       retval = 0;
                        sem->sleepers = 0;
                        break;
                }
@@ -127,12 +123,13 @@ int __down_interruptible(struct semaphore * sem)
                spin_unlock_irq(&semaphore_lock);
 
                schedule();
-               tsk->state = TASK_INTERRUPTIBLE;
+               tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
                spin_lock_irq(&semaphore_lock);
        }
        spin_unlock_irq(&semaphore_lock);
        tsk->state = TASK_RUNNING;
        remove_wait_queue(&sem->wait, &wait);
+       wake_up(&sem->wait);
        return retval;
 }
 
@@ -147,8 +144,9 @@ int __down_interruptible(struct semaphore * sem)
 int __down_trylock(struct semaphore * sem)
 {
        int sleepers;
+       unsigned long flags;
 
-       spin_lock_irq(&semaphore_lock);
+       spin_lock_irqsave(&semaphore_lock, flags);
        sleepers = sem->sleepers + 1;
        sem->sleepers = 0;
 
@@ -159,7 +157,7 @@ int __down_trylock(struct semaphore * sem)
        if (!atomic_add_negative(sleepers, &sem->count))
                wake_up(&sem->wait);
 
-       spin_unlock_irq(&semaphore_lock);
+       spin_unlock_irqrestore(&semaphore_lock, flags);
        return 1;
 }
 
@@ -254,7 +252,8 @@ struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
        while (atomic_read(&sem->count) < 0) {
                set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
                if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to aquire or bias the lock */                schedule();
+                       break;  /* we must attempt to aquire or bias the lock */
+               schedule();
        }
 
        remove_wait_queue(&sem->wait, &wait);
@@ -293,6 +292,102 @@ struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
  * registers (r0 to r3 and lr), but not ip, as we use it as a return
  * value in some cases..
  */
+#ifdef CONFIG_CPU_26
+asm("  .section        .text.lock, \"ax\"
+       .align  5
+       .globl  __down_failed
+__down_failed:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       bl      __down
+       ldmfd   sp!, {r0 - r3, pc}^
+
+       .align  5
+       .globl  __down_interruptible_failed
+__down_interruptible_failed:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       bl      __down_interruptible
+       mov     ip, r0
+       ldmfd   sp!, {r0 - r3, pc}^
+
+       .align  5
+       .globl  __down_trylock_failed
+__down_trylock_failed:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       bl      __down_trylock
+       mov     ip, r0
+       ldmfd   sp!, {r0 - r3, pc}^
+
+       .align  5
+       .globl  __up_wakeup
+__up_wakeup:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       bl      __up
+       ldmfd   sp!, {r0 - r3, pc}^
+
+       .align  5
+       .globl  __down_read_failed
+__down_read_failed:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       bcc     1f
+1:     bl      down_read_failed_biased
+       ldmfd   sp!, {r0 - r3, pc}^
+2:     bl      down_read_failed
+       mov     r1, pc
+       orr     r2, r1, #
+       teqp r2, #0
+
+       ldr     r3, [r0]
+       subs    r3, r3, #1
+       str     r3, [r0]
+       ldmplfd sp!, {r0 - r3, pc}^
+  orrcs r1, r1, #0x20000000   @ Set carry
+  teqp r1, #0
+       bcc     2b
+       b       1b
+
+       .align  5
+       .globl  __down_write_failed
+__down_write_failed:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       bcc     1f
+1:     bl      down_write_failed_biased
+       ldmfd   sp!, {r0 - r3, pc}^
+2:     bl      down_write_failed
+       mov r1, pc
+       orr     r2, r1, #128
+       teqp r2, #0
+
+       ldr     r3, [r0]
+       subs    r3, r3, #"RW_LOCK_BIAS_STR"
+       str     r3, [r0]
+       ldmeqfd sp!, {r0 - r3, pc}^
+  orrcs r1, r1, #0x20000000   @ Set carry
+       teqp r1, #0
+       bcc     2b
+       b       1b
+
+       .align  5
+       .globl  __rwsem_wake
+__rwsem_wake:
+       stmfd   sp!, {r0 - r3, lr}
+       mov     r0, ip
+       beq     1f
+       bl      rwsem_wake_readers
+       ldmfd   sp!, {r0 - r3, pc}^
+1:     bl      rwsem_wake_writer
+       ldmfd   sp!, {r0 - r3, pc}^
+
+       .previous
+       ");
+
+#else
+/* 32 bit version */
 asm("  .section        .text.lock, \"ax\"
        .align  5
        .globl  __down_failed
@@ -382,3 +477,4 @@ __rwsem_wake:
        .previous
        ");
 
+#endif
index c6010476a8f266bb92ec261532f631c2addc4316..c20ffab21b6ee9e94ddd9ff393ee1b3f3e45092c 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/io.h>
 #include <asm/procinfo.h>
 #include <asm/setup.h>
-#include <asm/system.h>
+#include <asm/mach-types.h>
 
 #include "arch.h"
 
@@ -40,6 +40,7 @@ extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
 
 unsigned int processor_id;
+unsigned int compat;
 unsigned int __machine_arch_type;
 unsigned int system_rev;
 unsigned int system_serial_low;
@@ -161,6 +162,11 @@ static struct machine_desc * __init setup_architecture(unsigned int nr)
        }
 
        printk("Architecture: %s\n", list->name);
+       if (compat)
+               printk(KERN_WARNING "Using compatability code "
+                       "scheduled for removal in v%d.%d.%d\n",
+                       compat >> 24, (compat >> 12) & 0x3ff,
+                       compat & 0x3ff);
 
        return list;
 }
@@ -305,12 +311,6 @@ void __init setup_arch(char **cmdline_p)
 
        memset(&meminfo, 0, sizeof(meminfo));
 
-#if defined(CONFIG_ARCH_ARC)
-       __machine_arch_type = MACH_TYPE_ARCHIMEDES;
-#elif defined(CONFIG_ARCH_A5K)
-       __machine_arch_type = MACH_TYPE_A5K;
-#endif
-
        setup_processor();
 
        ROOT_DEV = MKDEV(0, 255);
index 4d489bcf346f8a32e957a4d74e6945da4c8ad25e..5c2e240b7bde2db9c3483b468ba62a827042d623 100644 (file)
@@ -35,37 +35,38 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
+       int err = -EFAULT;;
+
        if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
-               return -EFAULT;
+               goto out;
+
        if (from->si_code < 0)
                return __copy_to_user(to, from, sizeof(siginfo_t));
-       else {
-               int err;
-
-               /* If you change siginfo_t structure, please be sure
-                  this code is fixed accordingly.
-                  It should never copy any pad contained in the structure
-                  to avoid security leaks, but must copy the generic
-                  3 ints plus the relevant union member.  */
-               err = __put_user(from->si_signo, &to->si_signo);
-               err |= __put_user(from->si_errno, &to->si_errno);
-               err |= __put_user((short)from->si_code, &to->si_code);
-               /* First 32bits of unions are always present.  */
-               err |= __put_user(from->si_pid, &to->si_pid);
-               switch (from->si_code >> 16) {
-               case __SI_FAULT >> 16:
-                       break;
-               case __SI_CHLD >> 16:
-                       err |= __put_user(from->si_utime, &to->si_utime);
-                       err |= __put_user(from->si_stime, &to->si_stime);
-                       err |= __put_user(from->si_status, &to->si_status);
-               default:
-                       err |= __put_user(from->si_uid, &to->si_uid);
-                       break;
-               /* case __SI_RT: This is not generated by the kernel as of now.  */
-               }
-               return err;
+
+       /* If you change siginfo_t structure, please be sure
+          this code is fixed accordingly.
+          It should never copy any pad contained in the structure
+          to avoid security leaks, but must copy the generic
+          3 ints plus the relevant union member.  */
+       err = __put_user(from->si_signo, &to->si_signo);
+       err |= __put_user(from->si_errno, &to->si_errno);
+       err |= __put_user((short)from->si_code, &to->si_code);
+       /* First 32bits of unions are always present.  */
+       err |= __put_user(from->si_pid, &to->si_pid);
+       switch (from->si_code >> 16) {
+       case __SI_FAULT >> 16:
+               break;
+       case __SI_CHLD >> 16:
+               err |= __put_user(from->si_utime, &to->si_utime);
+               err |= __put_user(from->si_stime, &to->si_stime);
+               err |= __put_user(from->si_status, &to->si_status);
+       default:
+               err |= __put_user(from->si_uid, &to->si_uid);
+               break;
+       /* case __SI_RT: This is not generated by the kernel as of now.  */
        }
+out:
+       return err;
 }
 
 /*
@@ -175,24 +176,24 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
        int err = 0;
 
-       err |= __get_user(regs->ARM_r0, &sc->arm_r0);
-       err |= __get_user(regs->ARM_r1, &sc->arm_r1);
-       err |= __get_user(regs->ARM_r2, &sc->arm_r2);
-       err |= __get_user(regs->ARM_r3, &sc->arm_r3);
-       err |= __get_user(regs->ARM_r4, &sc->arm_r4);
-       err |= __get_user(regs->ARM_r5, &sc->arm_r5);
-       err |= __get_user(regs->ARM_r6, &sc->arm_r6);
-       err |= __get_user(regs->ARM_r7, &sc->arm_r7);
-       err |= __get_user(regs->ARM_r8, &sc->arm_r8);
-       err |= __get_user(regs->ARM_r9, &sc->arm_r9);
-       err |= __get_user(regs->ARM_r10, &sc->arm_r10);
-       err |= __get_user(regs->ARM_fp, &sc->arm_fp);
-       err |= __get_user(regs->ARM_ip, &sc->arm_ip);
-       err |= __get_user(regs->ARM_sp, &sc->arm_sp);
-       err |= __get_user(regs->ARM_lr, &sc->arm_lr);
-       err |= __get_user(regs->ARM_pc, &sc->arm_pc);
+       __get_user_error(regs->ARM_r0, &sc->arm_r0, err);
+       __get_user_error(regs->ARM_r1, &sc->arm_r1, err);
+       __get_user_error(regs->ARM_r2, &sc->arm_r2, err);
+       __get_user_error(regs->ARM_r3, &sc->arm_r3, err);
+       __get_user_error(regs->ARM_r4, &sc->arm_r4, err);
+       __get_user_error(regs->ARM_r5, &sc->arm_r5, err);
+       __get_user_error(regs->ARM_r6, &sc->arm_r6, err);
+       __get_user_error(regs->ARM_r7, &sc->arm_r7, err);
+       __get_user_error(regs->ARM_r8, &sc->arm_r8, err);
+       __get_user_error(regs->ARM_r9, &sc->arm_r9, err);
+       __get_user_error(regs->ARM_r10, &sc->arm_r10, err);
+       __get_user_error(regs->ARM_fp, &sc->arm_fp, err);
+       __get_user_error(regs->ARM_ip, &sc->arm_ip, err);
+       __get_user_error(regs->ARM_sp, &sc->arm_sp, err);
+       __get_user_error(regs->ARM_lr, &sc->arm_lr, err);
+       __get_user_error(regs->ARM_pc, &sc->arm_pc, err);
 #ifdef CONFIG_CPU_32
-       err |= __get_user(regs->ARM_cpsr, &sc->arm_cpsr);
+       __get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
 #endif
 
        err |= !valid_user_regs(regs);
@@ -289,30 +290,30 @@ setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/
 {
        int err = 0;
 
-       err |= __put_user (regs->ARM_r0, &sc->arm_r0);
-       err |= __put_user (regs->ARM_r1, &sc->arm_r1);
-       err |= __put_user (regs->ARM_r2, &sc->arm_r2);
-       err |= __put_user (regs->ARM_r3, &sc->arm_r3);
-       err |= __put_user (regs->ARM_r4, &sc->arm_r4);
-       err |= __put_user (regs->ARM_r5, &sc->arm_r5);
-       err |= __put_user (regs->ARM_r6, &sc->arm_r6);
-       err |= __put_user (regs->ARM_r7, &sc->arm_r7);
-       err |= __put_user (regs->ARM_r8, &sc->arm_r8);
-       err |= __put_user (regs->ARM_r9, &sc->arm_r9);
-       err |= __put_user (regs->ARM_r10, &sc->arm_r10);
-       err |= __put_user (regs->ARM_fp, &sc->arm_fp);
-       err |= __put_user (regs->ARM_ip, &sc->arm_ip);
-       err |= __put_user (regs->ARM_sp, &sc->arm_sp);
-       err |= __put_user (regs->ARM_lr, &sc->arm_lr);
-       err |= __put_user (regs->ARM_pc, &sc->arm_pc);
+       __put_user_error(regs->ARM_r0, &sc->arm_r0, err);
+       __put_user_error(regs->ARM_r1, &sc->arm_r1, err);
+       __put_user_error(regs->ARM_r2, &sc->arm_r2, err);
+       __put_user_error(regs->ARM_r3, &sc->arm_r3, err);
+       __put_user_error(regs->ARM_r4, &sc->arm_r4, err);
+       __put_user_error(regs->ARM_r5, &sc->arm_r5, err);
+       __put_user_error(regs->ARM_r6, &sc->arm_r6, err);
+       __put_user_error(regs->ARM_r7, &sc->arm_r7, err);
+       __put_user_error(regs->ARM_r8, &sc->arm_r8, err);
+       __put_user_error(regs->ARM_r9, &sc->arm_r9, err);
+       __put_user_error(regs->ARM_r10, &sc->arm_r10, err);
+       __put_user_error(regs->ARM_fp, &sc->arm_fp, err);
+       __put_user_error(regs->ARM_ip, &sc->arm_ip, err);
+       __put_user_error(regs->ARM_sp, &sc->arm_sp, err);
+       __put_user_error(regs->ARM_lr, &sc->arm_lr, err);
+       __put_user_error(regs->ARM_pc, &sc->arm_pc, err);
 #ifdef CONFIG_CPU_32
-       err |= __put_user (regs->ARM_cpsr, &sc->arm_cpsr);
+       __put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
 #endif
 
-       err |= __put_user (current->thread.trap_no, &sc->trap_no);
-       err |= __put_user (current->thread.error_code, &sc->error_code);
-       err |= __put_user (current->thread.address, &sc->fault_address);
-       err |= __put_user (mask, &sc->oldmask);
+       __put_user_error(current->thread.trap_no, &sc->trap_no, err);
+       __put_user_error(current->thread.error_code, &sc->error_code, err);
+       __put_user_error(current->thread.address, &sc->fault_address, err);
+       __put_user_error(mask, &sc->oldmask, err);
 
        return err;
 }
index c76a95736aa7f0e77d9ca7c64661b60190e69a3d..197107138bcb15fd55a83d8f792e52cb650c825b 100644 (file)
@@ -30,7 +30,7 @@
 
 extern void c_backtrace (unsigned long fp, int pmode);
 
-char *processor_modes[]=
+const char *processor_modes[]=
 { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
   "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
   "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
@@ -414,7 +414,7 @@ void __bug(const char *file, int line, void *data)
        if (data)
                printk(KERN_CRIT" - extra data = %p", data);
        printk("\n");
-       BUG();
+       *(int *)0 = 0;
 }
 
 void __readwrite_bug(const char *fn)
index 991b4a3c8321c0a591a7c759ff833a8f8c630bca..cfa371d5ed84a533ea2ae45dd2fa0ac08a071c15 100644 (file)
@@ -4,6 +4,8 @@
 # Copyright (C) 1995-1999 Russell King
 #
 
+USE_STANDARD_AS_RULE := true
+
 L_TARGET := lib.a
 L_OBJS   := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \
            csumpartialcopyuser.o clearbit.o copy_page.o findbit.o \
@@ -36,9 +38,6 @@ L_OBJS        += $(L_OBJS_$(MACHINE))
 
 include $(TOPDIR)/Rules.make
 
-.S.o:
-       $(CC) $(AFLAGS) -traditional -c -o $*.o $<
-
 constants.h: getconsdata.o extractconstants.pl
        $(PERL) extractconstants.pl $(OBJDUMP) > $@
 
index e95160e38b9f25822ad1f6f2b4b173f208126512..f2ea3231dab667e138606ec1e2e331fbd4442e70 100644 (file)
@@ -76,20 +76,20 @@ USER(               strt    r3, [r0], #4)                   @ May fault
                blt     .c2u_0rem8lp
 
 .c2u_0cpy8lp:  ldmia   r1!, {r3 - r6}
-               stmia   r0!, {r3 - r6}                  @ Shouldn't fault
+               stmia   r0!, {r3 - r6}                  @ Shouldnt fault
                ldmia   r1!, {r3 - r6}
-               stmia   r0!, {r3 - r6}                  @ Shouldn't fault
+               stmia   r0!, {r3 - r6}                  @ Shouldnt fault
                subs    ip, ip, #32
                bpl     .c2u_0cpy8lp
 .c2u_0rem8lp:  cmn     ip, #16
                ldmgeia r1!, {r3 - r6}
-               stmgeia r0!, {r3 - r6}                  @ Shouldn't fault
+               stmgeia r0!, {r3 - r6}                  @ Shouldnt fault
                tst     ip, #8
                ldmneia r1!, {r3 - r4}
-               stmneia r0!, {r3 - r4}                  @ Shouldn't fault
+               stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                ldrne   r3, [r1], #4
-               strnet  r3, [r0], #4                    @ Shouldn't fault
+               strnet  r3, [r0], #4                    @ Shouldnt fault
                ands    ip, ip, #3
                beq     .c2u_0fupi
 .c2u_0nowords: teq     ip, #0
@@ -141,7 +141,7 @@ USER(               strt    r3, [r0], #4)                   @ May fault
                orr     r5, r5, r6, lsl #24
                mov     r6, r6, lsr #8
                orr     r6, r6, r7, lsl #24
-               stmia   r0!, {r3 - r6}                  @ Shouldn't fault
+               stmia   r0!, {r3 - r6}                  @ Shouldnt fault
                subs    ip, ip, #16
                bpl     .c2u_1cpy8lp
 .c2u_1rem8lp:  tst     ip, #8
@@ -150,12 +150,12 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                orrne   r3, r3, r4, lsl #24
                movne   r4, r4, lsr #8
                orrne   r4, r4, r7, lsl #24
-               stmneia r0!, {r3 - r4}                  @ Shouldn't fault
+               stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                movne   r3, r7, lsr #8
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, lsl #24
-               strnet  r3, [r0], #4                    @ Shouldn't fault
+               strnet  r3, [r0], #4                    @ Shouldnt fault
                ands    ip, ip, #3
                beq     .c2u_1fupi
 .c2u_1nowords: mov     r3, r7, lsr #8
@@ -195,7 +195,7 @@ USER(               strt    r3, [r0], #4)                   @ May fault
                orr     r5, r5, r6, lsl #16
                mov     r6, r6, lsr #16
                orr     r6, r6, r7, lsl #16
-               stmia   r0!, {r3 - r6}                  @ Shouldn't fault
+               stmia   r0!, {r3 - r6}                  @ Shouldnt fault
                subs    ip, ip, #16
                bpl     .c2u_2cpy8lp
 .c2u_2rem8lp:  tst     ip, #8
@@ -204,12 +204,12 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                orrne   r3, r3, r4, lsl #16
                movne   r4, r4, lsr #16
                orrne   r4, r4, r7, lsl #16
-               stmneia r0!, {r3 - r4}                  @ Shouldn't fault
+               stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                movne   r3, r7, lsr #16
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, lsl #16
-               strnet  r3, [r0], #4                    @ Shouldn't fault
+               strnet  r3, [r0], #4                    @ Shouldnt fault
                ands    ip, ip, #3
                beq     .c2u_2fupi
 .c2u_2nowords: mov     r3, r7, lsr #16
@@ -249,7 +249,7 @@ USER(               strt    r3, [r0], #4)                   @ May fault
                orr     r5, r5, r6, lsl #8
                mov     r6, r6, lsr #24
                orr     r6, r6, r7, lsl #8
-               stmia   r0!, {r3 - r6}                  @ Shouldn't fault
+               stmia   r0!, {r3 - r6}                  @ Shouldnt fault
                subs    ip, ip, #16
                bpl     .c2u_3cpy8lp
 .c2u_3rem8lp:  tst     ip, #8
@@ -258,12 +258,12 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                orrne   r3, r3, r4, lsl #8
                movne   r4, r4, lsr #24
                orrne   r4, r4, r7, lsl #8
-               stmneia r0!, {r3 - r4}                  @ Shouldn't fault
+               stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                movne   r3, r7, lsr #24
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, lsl #8
-               strnet  r3, [r0], #4                    @ Shouldn't fault
+               strnet  r3, [r0], #4                    @ Shouldnt fault
                ands    ip, ip, #3
                beq     .c2u_3fupi
 .c2u_3nowords: mov     r3, r7, lsr #24
@@ -333,20 +333,20 @@ USER(             ldrt    r3, [r1], #4)
                subs    ip, ip, #32
                blt     .cfu_0rem8lp
 
-.cfu_0cpy8lp:  ldmia   r1!, {r3 - r6}                  @ Shouldn't fault
+.cfu_0cpy8lp:  ldmia   r1!, {r3 - r6}                  @ Shouldnt fault
                stmia   r0!, {r3 - r6}
-               ldmia   r1!, {r3 - r6}                  @ Shouldn't fault
+               ldmia   r1!, {r3 - r6}                  @ Shouldnt fault
                stmia   r0!, {r3 - r6}
                subs    ip, ip, #32
                bpl     .cfu_0cpy8lp
 .cfu_0rem8lp:  cmn     ip, #16
-               ldmgeia r1!, {r3 - r6}                  @ Shouldn't fault
+               ldmgeia r1!, {r3 - r6}                  @ Shouldnt fault
                stmgeia r0!, {r3 - r6}
                tst     ip, #8
-               ldmneia r1!, {r3 - r4}                  @ Shouldn't fault
+               ldmneia r1!, {r3 - r4}                  @ Shouldnt fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
-               ldrnet  r3, [r1], #4                    @ Shouldn't fault
+               ldrnet  r3, [r1], #4                    @ Shouldnt fault
                strne   r3, [r0], #4
                ands    ip, ip, #3
                beq     .cfu_0fupi
@@ -392,7 +392,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                blt     .cfu_1rem8lp
 
 .cfu_1cpy8lp:  mov     r3, r7, lsr #8
-               ldmia   r1!, {r4 - r7}                  @ Shouldn't fault
+               ldmia   r1!, {r4 - r7}                  @ Shouldnt fault
                orr     r3, r3, r4, lsl #24
                mov     r4, r4, lsr #8
                orr     r4, r4, r5, lsl #24
@@ -405,7 +405,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                bpl     .cfu_1cpy8lp
 .cfu_1rem8lp:  tst     ip, #8
                movne   r3, r7, lsr #8
-               ldmneia r1!, {r4, r7}                   @ Shouldn't fault
+               ldmneia r1!, {r4, r7}                   @ Shouldnt fault
                orrne   r3, r3, r4, lsl #24
                movne   r4, r4, lsr #8
                orrne   r4, r4, r7, lsl #24
@@ -446,7 +446,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                blt     .cfu_2rem8lp
 
 .cfu_2cpy8lp:  mov     r3, r7, lsr #16
-               ldmia   r1!, {r4 - r7}                  @ Shouldn't fault
+               ldmia   r1!, {r4 - r7}                  @ Shouldnt fault
                orr     r3, r3, r4, lsl #16
                mov     r4, r4, lsr #16
                orr     r4, r4, r5, lsl #16
@@ -459,7 +459,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                bpl     .cfu_2cpy8lp
 .cfu_2rem8lp:  tst     ip, #8
                movne   r3, r7, lsr #16
-               ldmneia r1!, {r4, r7}                   @ Shouldn't fault
+               ldmneia r1!, {r4, r7}                   @ Shouldnt fault
                orrne   r3, r3, r4, lsl #16
                movne   r4, r4, lsr #16
                orrne   r4, r4, r7, lsl #16
@@ -500,7 +500,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                blt     .cfu_3rem8lp
 
 .cfu_3cpy8lp:  mov     r3, r7, lsr #24
-               ldmia   r1!, {r4 - r7}                  @ Shouldn't fault
+               ldmia   r1!, {r4 - r7}                  @ Shouldnt fault
                orr     r3, r3, r4, lsl #8
                mov     r4, r4, lsr #24
                orr     r4, r4, r5, lsl #8
@@ -513,7 +513,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                bpl     .cfu_3cpy8lp
 .cfu_3rem8lp:  tst     ip, #8
                movne   r3, r7, lsr #24
-               ldmneia r1!, {r4, r7}                   @ Shouldn't fault
+               ldmneia r1!, {r4, r7}                   @ Shouldnt fault
                orrne   r3, r3, r4, lsl #8
                movne   r4, r4, lsr #24
                orrne   r4, r4, r7, lsl #8
@@ -597,7 +597,7 @@ USER(               strnebt r2, [r0], #1)
  *           or zero on exception, or n + 1 if too long
  */
 ENTRY(__arch_strnlen_user)
-               stmfd   sp!, {lr}
+               str     lr, [sp, #-4]!
                mov     r2, r0
 1:
 USER(          ldrbt   r3, [r0], #1)
@@ -623,7 +623,7 @@ USER(               ldrbt   r3, [r0], #1)
  * Returns  : number of characters copied
  */
 ENTRY(__arch_strncpy_from_user)
-               stmfd   sp!, {lr}
+               str     lr, [sp, #-4]!
                add     ip, r1, #1
 1:             subs    r2, r2, #1
                bmi     2f
index faedecd2de016f0b1b5b1fed8738f2bcb4db6c74..075193467defbb13027d3d727fe2272f2c242bc3 100644 (file)
@@ -7,8 +7,10 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+USE_STANDARD_AS_RULE := true
+
 O_TARGET       := mm.o
-O_OBJS         := consistent.o extable.o fault-$(PROCESSOR).o init.o \
+O_OBJS         := extable.o fault-$(PROCESSOR).o init.o \
                   mm-$(PROCESSOR).o small_page.o
 
 ifeq ($(CONFIG_CPU_26),y)
@@ -31,14 +33,11 @@ ifeq ($(CONFIG_CPU_32),y)
   ifeq ($(CONFIG_CPU_SA1100),y)
     P_OBJS     += proc-sa110.o
   endif
-  O_OBJS       += mm-$(MACHINE).o ioremap.o $(sort $(P_OBJS))
+  O_OBJS       += mm-$(MACHINE).o consistent.o ioremap.o $(sort $(P_OBJS))
 endif
 
 include $(TOPDIR)/Rules.make
 
-.S.o:
-       $(CC) $(AFLAGS) $(AFLAGS_$@) -traditional -c -o $*.o $<
-
 # Special dependencies
 fault-armv.o: fault-common.c
 fault-armo.o: fault-common.c
index 72eaa2e4752104d631f39630426192e01e204511..ba58e8bade42dce48fbfab296d02503d3c619e0e 100644 (file)
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
-#ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
-#endif
 
-#include <asm/system.h>
 #include <asm/segment.h>
+#include <asm/mach-types.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
 #include <asm/hardware.h>
@@ -151,11 +149,18 @@ void show_mem(void)
                end  = page + NODE_DATA(node)->node_size;
 
                do {
-                       if (PageSkip(page)) {
-                               page = page->next_hash;
-                               if (page == NULL)
-                                       break;
-                       }
+/* This is currently broken
+ * PG_skip is used on sparc/sparc64 architectures to "skip" certain
+ * parts of the address space.
+ *
+ * #define PG_skip     10
+ * #define PageSkip(page) (machine_is_riscpc() && test_bit(PG_skip, &(page)->flags))
+ *                     if (PageSkip(page)) {
+ *                             page = page->next_hash;
+ *                             if (page == NULL)
+ *                                     break;
+ *                     }
+ */
                        total++;
                        if (PageReserved(page))
                                reserved++;
@@ -554,7 +559,7 @@ void __init mem_init(void)
        initpages = &__init_end - &__init_begin;
 
        high_memory = (void *)__va(meminfo.end);
-       max_mapnr   = MAP_NR(high_memory);
+       max_mapnr   = virt_to_page(high_memory) - mem_map;
 
        /*
         * We may have non-contiguous memory.
@@ -598,9 +603,9 @@ void __init mem_init(void)
 static inline void free_area(unsigned long addr, unsigned long end, char *s)
 {
        unsigned int size = (end - addr) >> 10;
-       struct page *page = virt_to_page(addr);
 
-       for (; addr < end; addr += PAGE_SIZE, page ++) {
+       for (; addr < end; addr += PAGE_SIZE) {
+               struct page *page = virt_to_page(addr);
                ClearPageReserved(page);
                set_page_count(page, 1);
                free_page(addr);
@@ -608,18 +613,14 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s)
        }
 
        if (size)
-               printk(" %dk %s", size, s);
+               printk("Freeing %s memory: %dK\n", s, size);
 }
 
 void free_initmem(void)
 {
-       printk("Freeing unused kernel memory:");
-
        free_area((unsigned long)(&__init_begin),
                  (unsigned long)(&__init_end),
                  "init");
-
-       printk("\n");
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -628,17 +629,8 @@ static int keep_initrd;
 
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-       unsigned long addr;
-
-       if (!keep_initrd) {
-               for (addr = start; addr < end; addr += PAGE_SIZE) {
-                       ClearPageReserved(virt_to_page(addr));
-                       set_page_count(virt_to_page(addr), 1);
-                       free_page(addr);
-                       totalram_pages++;
-               }
-               printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-       }
+       if (!keep_initrd)
+               free_area(start, end, "initrd");
 }
 
 static int __init keepinitrd_setup(char *__unused)
index b11d55a1b51d406d197fca246363d82d84cf9fd8..2c555f46dffa83cc914ceee8e68f3be9a4d66478 100644 (file)
 
 #else
 
+/*
+ * The mapping when the footbridge is in add-in mode.
+ */
+#define MAPPING \
+ { PCIO_BASE,   DC21285_PCI_IO,                PCIO_SIZE,      DOMAIN_IO, 0, 1, 0, 0 }, \
+ { XBUS_BASE,   0x40000000,                    XBUS_SIZE,      DOMAIN_IO, 0, 1, 0, 0 }, \
+ { ARMCSR_BASE,  DC21285_ARMCSR_BASE,          ARMCSR_SIZE,    DOMAIN_IO, 0, 1, 0, 0 }, \
+ { WFLUSH_BASE,         DC21285_OUTBOUND_WRITE_FLUSH,  WFLUSH_SIZE,    DOMAIN_IO, 0, 1, 0, 0 }, \
+ { FLASH_BASE,  DC21285_FLASH,                 FLASH_SIZE,     DOMAIN_IO, 0, 1, 0, 0 }, \
+ { PCIMEM_BASE,         DC21285_PCI_MEM,               PCIMEM_SIZE,    DOMAIN_IO, 0, 1, 0, 0 }
+
+#endif
+
+struct map_desc io_desc[] __initdata = {
+       MAPPING
+};
+
+unsigned int __initdata io_desc_size = SIZE(io_desc);
+
+
+#ifdef CONFIG_FOOTBRIDGE_ADDIN
+
 /*
  * These two functions convert virtual addresses to PCI addresses
  * and PCI addresses to virtual addresses.  Note that it is only
@@ -78,22 +100,4 @@ unsigned long __bus_to_virt(unsigned long res)
        return res;
 }
 
-/*
- * The mapping when the footbridge is in add-in mode.
- */
-#define MAPPING \
- { PCIO_BASE,   DC21285_PCI_IO,                PCIO_SIZE,      DOMAIN_IO, 0, 1, 0, 0 }, \
- { XBUS_BASE,   0x40000000,                    XBUS_SIZE,      DOMAIN_IO, 0, 1, 0, 0 }, \
- { ARMCSR_BASE,  DC21285_ARMCSR_BASE,          ARMCSR_SIZE,    DOMAIN_IO, 0, 1, 0, 0 }, \
- { WFLUSH_BASE,         DC21285_OUTBOUND_WRITE_FLUSH,  WFLUSH_SIZE,    DOMAIN_IO, 0, 1, 0, 0 }, \
- { FLASH_BASE,  DC21285_FLASH,                 FLASH_SIZE,     DOMAIN_IO, 0, 1, 0, 0 }, \
- { PCIMEM_BASE,         DC21285_PCI_MEM,               PCIMEM_SIZE,    DOMAIN_IO, 0, 1, 0, 0 }
-
 #endif
-
-struct map_desc io_desc[] __initdata = {
-       MAPPING
-};
-
-unsigned int __initdata io_desc_size = SIZE(io_desc);
-
index 14dc5c6e4ff2946736e6aa34b4022b4e154cb6cc..8a252d6848b026a6000e8c152e06d0a75bffbd1f 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * arch/arm/mm/mm-lusl7200.c
  *
- * Extra MM routines for LUSL7200 architecture
+ * Extra MM routines for L7200 architecture
  *
- * Copyright (C) 2000 Steven J. Hill
+ * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
  */
 
 #include <linux/init.h>
index c1ecf3fb1ac062388b01e7d19476c6220adf81e7..aaf28f8808b8c9a25b05fa79c0a0013337066e5f 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/mach-types.h>
 
 #include "map.h"
  
@@ -53,6 +54,15 @@ static struct map_desc assabet_io_desc[] __initdata = {
 #endif
 };
 
+static struct map_desc nanoengine_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_NANOENGINE
+  { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+  { 0xd4000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
+  { 0xdc000000, 0x18A00000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Internal PCI Config Space */
+  SA1100_STD_IO_MAPPING
+#endif
+};
+
 static struct map_desc bitsy_io_desc[] __initdata = {
 #ifdef CONFIG_SA1100_BITSY
   { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
@@ -61,6 +71,14 @@ static struct map_desc bitsy_io_desc[] __initdata = {
 #endif
 };
 
+static struct map_desc cerf_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_CERF
+  { 0xd8000000, 0x08000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Crystal Chip */
+  { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+  SA1100_STD_IO_MAPPING
+#endif
+};
+
 static struct map_desc empeg_io_desc[] __initdata = {
 #ifdef CONFIG_SA1100_EMPEG
   { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
@@ -77,6 +95,14 @@ static struct map_desc graphicsclient_io_desc[] __initdata = {
 #endif
 };
 
+static struct map_desc lart_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_LART
+  { 0xd0000000, 0x00000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash memory */
+  { 0xd8000000, 0x08000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash, alternative location */
+  SA1100_STD_IO_MAPPING
+#endif
+};
+
 static struct map_desc thinclient_io_desc[] __initdata = {
 #ifdef CONFIG_SA1100_THINCLIENT
 #if 0
@@ -104,6 +130,14 @@ static struct map_desc victor_io_desc[] __initdata = {
 #endif
 };
 
+static struct map_desc xp860_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_XP860
+  { 0xd8000000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+  { 0xda000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SCSI */
+  { 0xdc000000, 0x18000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* LAN */
+  SA1100_STD_IO_MAPPING
+#endif
+};
 
 static struct map_desc default_io_desc[] __initdata = {
   SA1100_STD_IO_MAPPING
@@ -122,15 +156,24 @@ void __init select_sa1100_io_desc(void)
        if( machine_is_assabet() ) {
                memcpy( io_desc, assabet_io_desc, sizeof(assabet_io_desc) );
                io_desc_size = SIZE(assabet_io_desc);
+       } else if( machine_is_nanoengine() ) {
+               memcpy( io_desc, nanoengine_io_desc, sizeof(nanoengine_io_desc) );
+               io_desc_size = SIZE(nanoengine_io_desc);
        } else if( machine_is_bitsy() ) {
                memcpy( io_desc, bitsy_io_desc, sizeof(bitsy_io_desc) );
                io_desc_size = SIZE(bitsy_io_desc);
+       } else if( machine_is_cerf() ) {
+               memcpy( io_desc, cerf_io_desc, sizeof(cerf_io_desc) );
+               io_desc_size = SIZE(cerf_io_desc);
        } else if( machine_is_empeg() ) {
                memcpy( io_desc, empeg_io_desc, sizeof(empeg_io_desc) );
                io_desc_size = SIZE(empeg_io_desc);
        } else if( machine_is_graphicsclient() ) {
                memcpy( io_desc, graphicsclient_io_desc, sizeof(graphicsclient_io_desc) );
                io_desc_size = SIZE(graphicsclient_io_desc);
+       } else if( machine_is_lart() ) {
+               memcpy( io_desc, lart_io_desc, sizeof(lart_io_desc) );
+               io_desc_size = SIZE(lart_io_desc);
        } else if( machine_is_thinclient() ) {
                memcpy( io_desc, thinclient_io_desc, sizeof(thinclient_io_desc) );
                io_desc_size = SIZE(thinclient_io_desc);
@@ -140,6 +183,9 @@ void __init select_sa1100_io_desc(void)
        } else if( machine_is_victor() ) {
                memcpy( io_desc, victor_io_desc, sizeof(victor_io_desc) );
                io_desc_size = SIZE(victor_io_desc);
+       } else if( machine_is_xp860() ) {
+               memcpy( io_desc, xp860_io_desc, sizeof(xp860_io_desc) );
+               io_desc_size = SIZE(xp860_io_desc);
        } else {
                memcpy( io_desc, default_io_desc, sizeof(default_io_desc) );
                io_desc_size = SIZE(default_io_desc);
index d4919662520fb0787fc0c8f2aa62ec2e92eaeb8e..262a4fd8bb7823de3e9c2a3485c8eb40f25b25f4 100644 (file)
  * Changelog:
  *  05-09-2000  SJH    Created by moving 720 specific functions
  *                     out of 'proc-arm6,7.S' per RSK discussion
+ *  07-25-2000  SJH    Added idle function.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/procinfo.h>
 #include <asm/errno.h>
+#include <asm/hardware.h>
 #include "../lib/constants.h"
 
 /*
@@ -127,8 +129,8 @@ ENTRY(cpu_arm720_data_abort)
                add     pc, pc, r2, lsr #22             @ Now branch to the relevent processing routine
                movs    pc, lr
 
-               b       Ldata_unknown
-               b       Ldata_unknown
+               b       Ldata_lateldrhpost              @ ldrh  rd, [rn], #m/rm
+               b       Ldata_lateldrhpre               @ ldrh  rd, [rn, #m/rm]
                b       Ldata_unknown
                b       Ldata_unknown
                b       Ldata_lateldrpostconst          @ ldr   rd, [rn], #m
@@ -142,6 +144,7 @@ ENTRY(cpu_arm720_data_abort)
                b       Ldata_simple                    @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
                b       Ldata_simple                    @ ldc   rd, [rn, #m]
                b       Ldata_unknown
+
 Ldata_unknown: @ Part of jumptable
                mov     r0, r2
                mov     r1, r4
@@ -149,6 +152,33 @@ Ldata_unknown:     @ Part of jumptable
                bl      baddataabort
                b       ret_from_sys_call
 
+Ldata_lateldrhpre:
+               tst     r4, #1 << 21                    @ check writeback bit
+               beq     Ldata_simple
+Ldata_lateldrhpost:
+               tst     r4, #1 << 22                    @ check if register or immediate offset
+               beq     Ldata_lateldrhpostreg
+Ldata_lateldrhpostconst:
+               and     r2, r4, #0xf                    @ load and clear low nibble of const offset
+               and     r5, r4, #0xf00                  @ load and clear high nibble of const offset
+               orrs    r2, r2, r5, lsr #4              @ create offset
+               beq     Ldata_simple                    @ don't have to do anything if zero
+               and     r5, r4, #0xf << 16              @ get Rn
+               ldr     r0, [sp, r5, lsr #14]
+               tst     r4, #1 << 23                    @ U bit
+               subne   r7, r0, r2, lsr #20
+               addeq   r7, r0, r2, lsr #20
+               b       Ldata_saver7
+Ldata_lateldrhpostreg:
+               and     r5, r4, #0xf
+               ldr     r2, [sp, r5, lsl #2]            @ get Rm
+               and     r5, r4, #0xf << 16
+               ldr     r0, [sp, r5, lsr #14]           @ get Rn
+               tst     r4, #1 << 23
+               subne   r7, r0, r2
+               addeq   r7, r0, r2
+               b       Ldata_saver7
+
 Ldata_lateldrpreconst:
                tst     r4, #1 << 21                    @ check writeback bit
                beq     Ldata_simple
@@ -219,7 +249,6 @@ Ldata_lateldrpostreg:
  * Function: arm720_check_bugs (void)
  *        : arm720_proc_init (void)
  *        : arm720_proc_fin (void)
- *        : arm720_proc_do_idle (void)
  *
  * Notes   : This processor does not require these
  */
@@ -240,8 +269,22 @@ ENTRY(cpu_arm720_proc_fin)
                mcr     p15, 0, r0, c1, c0, 0           @ disable caches
                mov     pc, lr
 
+/*
+ * Function: arm720_proc_do_idle (void)
+ *
+ * Params  : r0 = call type:
+ *           0 = slow idle
+ *           1 = fast idle
+ *           2 = switch to slow processor clock
+ *           3 = switch to fast processor clock
+ *
+ * Purpose : put the processer in proper idle mode
+ */
 ENTRY(cpu_arm720_do_idle)
-               mov     r0, #-EINVAL
+               ldr     r2, =IO_BASE                    @ Virt addr of IO
+               add     r2, r2, #0x00050000             @ Start of PMU regs
+               mov     r1, #0x01                       @ Idle mode
+               str     r1, [r2, #4]                    
                mov     pc, lr
 
 /*
index 8c7a6b749847f1e71c31e8731c9d47204e6ed5b8..bf75c97a2c07d1290c307f1181e8f3d5ad69cd80 100644 (file)
@@ -313,8 +313,8 @@ ENTRY(cpu_sa1100_data_abort)
                ldr     r1, [r0]                        @ read instruction causing problem
                mrc     p15, 0, r0, c6, c0, 0           @ get FAR
                mov     r1, r1, lsr #19                 @ b1 = L
-               and     r1, r1, #2
                mrc     p15, 0, r3, c5, c0, 0           @ get FSR
+               and     r1, r1, #2
                and     r3, r3, #255
                mov     pc, lr
 
index a14371e5d9ac8a7e5b4c410d4de69db4eaa3794e..a7f69d405a7845db52ec8c33c1de049d8660acce 100644 (file)
@@ -4,6 +4,8 @@
 # Copyright (C) 1998, 1999 Philip Blundell
 #
 
+USE_STANDARD_AS_RULE := true
+
 NWFPE_OBJS := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \
              fpmodule.o fpopcode.o softfloat.o \
              single_cpdo.o double_cpdo.o extended_cpdo.o
diff --git a/arch/arm/tools/gen-mach-types b/arch/arm/tools/gen-mach-types
new file mode 100644 (file)
index 0000000..2f9c9b5
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/awk
+#
+# Awk script to generate include/asm-arm/mach-types.h
+#
+BEGIN  { nr = 0 }
+/^#/   { next }
+/^[    ]*$/ { next }
+
+NF == 4 {
+         machine_is[nr] = "machine_is_"$1;
+         config[nr] = "CONFIG_"$2;
+         mach_type[nr] = "MACH_TYPE_"$3;
+         num[nr] = $4; nr++
+       }
+
+NF == 3 {
+         machine_is[nr] = "machine_is_"$1;
+         config[nr] = "CONFIG_"$2;
+         mach_type[nr] = "MACH_TYPE_"$3;
+         num[nr] = ""; nr++
+       }
+
+
+END    {
+         printf("/*\n");
+         printf(" * This was automagically generated from %s!\n", FILENAME);
+         printf(" * Do NOT edit\n");
+         printf(" */\n\n");
+         printf("#ifndef __ASM_ARM_MACH_TYPE_H\n");
+         printf("#define __ASM_ARM_MACH_TYPE_H\n\n");
+         printf("#include <linux/config.h>\n\n");
+         printf("#ifndef __ASSEMBLY__\n");
+         printf("/* The type of machine we're running on */\n");
+         printf("extern unsigned int __machine_arch_type;\n");
+         printf("#endif\n\n");
+
+         printf("/* see arch/arm/kernel/arch.c for a description of these */\n");
+         for (i = 0; i < nr; i++)
+           if (num[i] ~ /..*/)
+             printf("#define %-30s %d\n", mach_type[i], num[i]);
+
+         printf("\n");
+
+         for (i = 0; i < nr; i++)
+           if (num[i] ~ /..*/) {
+             printf("#ifdef %s\n", config[i]);
+             printf("# ifdef machine_arch_type\n");
+             printf("#  undef machine_arch_type\n");
+             printf("#  define machine_arch_type\t__machine_arch_type\n");
+             printf("# else\n");
+             printf("#  define machine_arch_type\t%s\n", mach_type[i]);
+             printf("# endif\n");
+             printf("# define %s()\t(machine_arch_type == %s)\n", machine_is[i], mach_type[i]);
+             printf("#else\n");
+             printf("# define %s()\t(0)\n", machine_is[i]);
+             printf("#endif\n\n");
+           }
+
+         printf("/*\n * These have not yet been registered\n */\n");
+         for (i = 0; i < nr; i++)
+           if (num[i] !~ /..*/)
+             printf("/* #define %-30s <<not registered>> */\n", mach_type[i]);
+
+         for (i = 0; i < nr; i++)
+           if (num[i] !~ /..*/) {
+             printf("#define %s()\t(0)\n", machine_is[i]);
+           }
+
+         printf("\n#ifndef machine_arch_type\n");
+         printf("#define machine_arch_type\t__machine_arch_type\n");
+         printf("#endif\n\n");
+         printf("#endif\n");
+       }
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
new file mode 100644 (file)
index 0000000..b922786
--- /dev/null
@@ -0,0 +1,44 @@
+# Database of machine macros and numbers
+#
+# To add an entry into this database, please see
+# Documentation/arm/README
+#
+# machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
+#
+ebsa110                        ARCH_EBSA110            EBSA110                 0
+riscpc                 ARCH_RPC                RISCPC                  1
+nexuspci               ARCH_NEXUSPCI           NEXUSPCI                3
+ebsa285                        ARCH_EBSA285            EBSA285                 4
+netwinder              ARCH_NETWINDER          NETWINDER               5
+cats                   ARCH_CATS               CATS                    6
+tbox                   ARCH_TBOX               TBOX                    7
+co285                  ARCH_CO285              CO285                   8
+clps7110               ARCH_CLPS7110           CLPS7110                9
+arc                    ARCH_ARC                ARCHIMEDES              10
+a5k                    ARCH_A5K                A5K                     11
+etoile                 ARCH_ETOILE             ETOILE                  12
+lacie_nas              ARCH_LACIE_NAS          LACIE_NAS               13
+clps7500               ARCH_CLPS7500           CLPS7500                14
+shark                  ARCH_SHARK              SHARK                   15
+brutus                 SA1100_BRUTUS           BRUTUS                  16
+personal_server                ARCH_PERSONAL_SERVER    PERSONAL_SERVER         17
+itsy                   SA1100_ITSY             ITSY                    18
+l7200                  ARCH_L7200              L7200                   19
+pleb                   SA1100_PLEB             PLEB                    20
+integrator             ARCH_INTEGRATOR         INTEGRATOR              21
+bitsy                  SA1100_BITSY            BITSY                   22
+ixp1200                        ARCH_IXP1200            IXP1200                 23
+thinclient             SA1100_THINCLIENT       THINCLIENT              24
+assabet                        SA1100_ASSABET          ASSABET                 25
+victor                 SA1100_VICTOR           VICTOR                  26
+lart                   SA1100_LART             LART                    27
+ranger                 ARCH_RANGER             RANGER                  28
+graphicsclient         SA1100_GRAPHICSCLIENT   GRAPHICSCLIENT          29
+xp860                  SA1100_XP860            XP860                   30
+cerf                   SA1100_CERF             CERF                    31
+nanoengine             SA1100_NANOENGINE       NANOENGINE              32
+
+# The following are unallocated
+empeg                  SA1100_EMPEG            EMPEG
+tifon                  SA1100_TIFON            TIFON
+penny                  SA1100_PENNY            PENNY
index a839790f898f3ded16e25acf740e93bd35033011..c07b50df94b999882989e73b4a295493e95a3ca2 100644 (file)
@@ -682,46 +682,28 @@ asmlinkage void smp_spurious_interrupt(void)
  * This interrupt should never happen with our APIC/SMP architecture
  */
 
-static spinlock_t err_lock = SPIN_LOCK_UNLOCKED;
-
 asmlinkage void smp_error_interrupt(void)
 {
-       unsigned long v;
-
-       spin_lock(&err_lock);
+       unsigned long v, v1;
 
+       /* First tickle the hardware, only then report what went on. -- REW */
        v = apic_read(APIC_ESR);
-       printk(KERN_INFO "APIC error interrupt on CPU#%d, should never happen.\n",
-                       smp_processor_id());
-       printk(KERN_INFO "... APIC ESR0: %08lx\n", v);
-
        apic_write(APIC_ESR, 0);
-       v |= apic_read(APIC_ESR);
-       printk(KERN_INFO "... APIC ESR1: %08lx\n", v);
-       /*
-        * Be a bit more verbose. (multiple bits can be set)
-        */
-       if (v & 0x01)
-               printk(KERN_INFO "... bit 0: APIC Send CS Error (hw problem).\n");
-       if (v & 0x02)
-               printk(KERN_INFO "... bit 1: APIC Receive CS Error (hw problem).\n");
-       if (v & 0x04)
-               printk(KERN_INFO "... bit 2: APIC Send Accept Error.\n");
-       if (v & 0x08)
-               printk(KERN_INFO "... bit 3: APIC Receive Accept Error.\n");
-       if (v & 0x10)
-               printk(KERN_INFO "... bit 4: Reserved!.\n");
-       if (v & 0x20)
-               printk(KERN_INFO "... bit 5: Send Illegal Vector (kernel bug).\n");
-       if (v & 0x40)
-               printk(KERN_INFO "... bit 6: Received Illegal Vector.\n");
-       if (v & 0x80)
-               printk(KERN_INFO "... bit 7: Illegal Register Address.\n");
-
+       v1 = apic_read(APIC_ESR);
        ack_APIC_irq();
-
        irq_err_count++;
 
-       spin_unlock(&err_lock);
+       /* Here is what the APIC error bits mean:
+          0: Send CS error
+          1: Receive CS error
+          2: Send accept error
+          3: Receive accept error
+          4: Reserved
+          5: Send illegal vector
+          6: Received illegal vector
+          7: Illegal register address
+       */
+       printk (KERN_ERR "APIC error on CPU%d: %02x(%02x)\n",
+               smp_processor_id(), v , v1);
 }
 
index 68227302c7a8c4c67564d81f87241093a579987d..2afb5613e46661704b3a54dd0e3e61094a1d2d12 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/kernel.h>
 
 #include <asm/page.h>
index 0e33a4e0bc0d528fa72251e0c61c46349b588069..ecd7b0886009f2678b12c502651211e9e0b19cf9 100644 (file)
@@ -16,6 +16,7 @@
  *       are empty for now.
  *     - remove hack to avoid problem with <= 256M RAM for itr.
  */
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/init.h>
index d243122a149ad67cb9e9ba5b78fbc3fa7c22a99d..84daa1bd9621665e3547d854b2d6d87b10ed8370 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.98 2000/08/12 13:25:41 davem Exp $
+/* $Id: systbls.S,v 1.99 2000/08/12 20:49:49 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -49,7 +49,7 @@ sys_call_table:
 /*140*/        .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
 /*145*/        .long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/        .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-/*155*/        .long sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
+/*155*/        .long sys_fcntl64, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/        .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 /*165*/        .long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
 /*170*/        .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
index 181909080a9b6945d20ef6f7bc71bcee53eda4bc..003df6183631cce9b7b65d08e749e536e571d50e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.160 2000/08/12 13:25:41 davem Exp $
+/* $Id: sys_sparc32.c,v 1.161 2000/08/12 20:49:49 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -866,15 +866,27 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg
                        old_fs = get_fs(); set_fs (KERNEL_DS);
                        ret = sys_fcntl(fd, cmd, (unsigned long)&f);
                        set_fs (old_fs);
+                       if (ret) return ret;
+                       if (f.l_start >= 0x7fffffffUL ||
+                           f.l_len >= 0x7fffffffUL ||
+                           f.l_start + f.l_len >= 0x7fffffffUL)
+                               return -EOVERFLOW;
                        if(put_flock(&f, (struct flock32 *)arg))
                                return -EFAULT;
-                       return ret;
+                       return 0;
                }
        default:
                return sys_fcntl(fd, cmd, (unsigned long)arg);
        }
 }
 
+asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
+               return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
+       return sys32_fcntl(fd, cmd, arg);
+}
+
 struct dqblk32 {
     __u32 dqb_bhardlimit;
     __u32 dqb_bsoftlimit;
index bb5066db4cf8628942e55f3b496cd7c03f155c13..5fd92b9e4926dd4a601e47541406a943b646bb5a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.75 2000/08/12 13:25:42 davem Exp $
+/* $Id: systbls.S,v 1.76 2000/08/12 20:49:49 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -50,7 +50,7 @@ sys_call_table32:
 /*140*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
        .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
 /*150*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
-       .word sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
+       .word sys32_fcntl64, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
 /*160*/        .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
        .word sys32_quotactl, sys_nis_syscall, sys32_mount, sys_ustat, sys_nis_syscall
 /*170*/        .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
index 75dfdbfcf5aa8cf06a202aa8bbd7c7b5a1100458..2a59b278821f890df327eb2c062a5f4b82971508 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: dec_and_lock.S,v 1.1 2000/07/10 20:57:34 davem Exp $
+/* $Id: dec_and_lock.S,v 1.2 2000/08/13 18:24:12 davem Exp $
  * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()"
  *                 using cas and ldstub instructions.
  *
         *     TMP = *(MEM);
         *     *(MEM) = REG2;
         *     REG2 = TMP;
-        *   }
+        *   } else
+        *     REG2 = *(MEM);
         *   END_ATOMIC();
         * }
-        *
-        * All non-contention cases are handled in 2 I-cache
-        * lines which is 1 L2 cache line.
         */
 
        .globl  atomic_dec_and_lock
@@ -42,20 +40,24 @@ to_zero:ldstub      [%o1], %g3
        brnz,pn %g3, spin_on_lock
         membar #StoreLoad | #StoreStore
 loop2: cas     [%o0], %g5, %g7         /* ASSERT(g7 == 0) */
-       brnz,pt %g7, out
-        mov    1, %g1
+       nop
+       cmp     %g5, %g7
 
+       be,pt   %icc, out
+        mov    1, %g1
        lduw    [%o0], %g5
        subcc   %g5, 1, %g7
        be,pn   %icc, loop2
         nop
        membar  #StoreStore | #LoadStore
        stb     %g0, [%o1]
+
        b,pt    %xcc, nzero
         nop
-
 spin_on_lock:
        ldub    [%o1], %g3
        brnz,pt %g3, spin_on_lock
         membar #LoadLoad
-       b,a,pt  %xcc, to_zero
+       ba,pt   %xcc, to_zero
+        nop
+       nop
index 50171ce472e80b8e9fb8cee289030a502a949c86..7ee1e3c99dd8aea591703c3a96f7f58b3467a695 100644 (file)
@@ -9,6 +9,8 @@
 # parent makefile.
 #
 
+USE_STANDARD_AS_RULE := true
+
 L_TARGET       := acorn-block.a
 
 obj-y          :=
index 5e90e6ba42498a40d4762bacb9a09031050e4bb6..c1e7dc4696dd2ccf461e09753cb75be86687755f 100644 (file)
 #include <asm/io.h>
 #include <asm/ioc.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 #include <asm/pgtable.h>
 #include <asm/segment.h>
 #include <asm/uaccess.h>
index d102cc876b307d4d892f3486ff5f92b6c9c55f5a..64980434854eb9cadca19da997405e7d3ae5c3a3 100644 (file)
@@ -35,7 +35,12 @@ obj-$(CONFIG_DUALSP_SERIAL)  += serial-dualsp.o
 obj-$(CONFIG_ARCH_ACORN)       += defkeymap-acorn.o
 
 # Do the i2c and rtc last
-obj-y          += $(obj-$(MACHINE)) i2c.o pcf8583.o
+obj-y          += $(obj-$(MACHINE)) 
+
+# CL-PS7500 does not have these devices.
+ifneq ($(CONFIG_ARCH_CLPS7500),y)
+obj-y += i2c.o pcf8583.o
+endif
 
 O_OBJS         := $(filter-out $(export-objs), $(obj-y))
 OX_OBJS                := $(filter     $(export-objs), $(obj-y))
index bde60136fa0c5500c9165495ab8c29ad8639dec8..1d9bc6dd4f5d653d6796d510ba903f6c6a70a6c7 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for drivers/acorn/scsi
 #
 
+USE_STANDARD_AS_RULE := true
+
 L_TARGET       := acorn-scsi.a
 
 obj-y          :=
index b56c19dc8fc2a3d5b659ed24d550dd9ba6b99dbd..8a61d1e843461e68965a75bd5b6bd9fd9d7ef4ea 100644 (file)
@@ -696,19 +696,7 @@ static int __make_request(request_queue_t * q, int rw,
                        rw_ahead = 1;
                        rw = READ;      /* drop into READ */
                case READ:
-                       if (buffer_uptodate(bh)) /* Hmmph! Already have it */
-                               goto end_io;
-                       kstat.pgpgin++;
-                       break;
-               case WRITERAW:
-                       rw = WRITE;
-                       goto do_write;  /* Skip the buffer refile */
                case WRITE:
-                       if (!test_and_clear_bit(BH_Dirty, &bh->b_state))
-                               goto end_io;    /* Hmmph! Nothing to write */
-                       refile_buffer(bh);
-               do_write:
-                       kstat.pgpgout++;
                        break;
                default:
                        BUG();
@@ -941,6 +929,30 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
 
                set_bit(BH_Req, &bh->b_state);
 
+               switch(rw) {
+               case WRITE:
+                       if (!atomic_set_buffer_clean(bh))
+                               /* Hmmph! Nothing to write */
+                               goto end_io;
+                       __mark_buffer_clean(bh);
+                       kstat.pgpgout++;
+                       break;
+
+               case READA:
+               case READ:
+                       if (buffer_uptodate(bh))
+                               /* Hmmph! Already have it */
+                               goto end_io;
+                       kstat.pgpgin++;
+                       break;
+               default:
+                       BUG();
+       end_io:
+                       bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
+                       continue;
+                       
+               }
+
                /*
                 * First step, 'identity mapping' - RAID or LVM might
                 * further remap this.
index 4c364712a3305209cde645ffe9db4da445a6da34..b39c87e0e797e35d20182329f2b805e8a9d71a92 100644 (file)
@@ -564,28 +564,6 @@ static int raid1_make_request (mddev_t *mddev, int rw,
        if (rw == READA)
                rw = READ;
 
-       if (rw == WRITE) {
-               rw = WRITERAW;
-               /*
-                * we first clean the bh, then we start the IO, then
-                * when the IO has finished, we end_io the bh and
-                * mark it uptodate. This way we do not miss the
-                * case when the bh got dirty again during the IO.
-                *
-                * We do an important optimization here - if the
-                * buffer was not dirty and we are during resync or
-                * reconstruction, then we can skip writing it back
-                * to the master disk! (we still have to write it
-                * back to the other disks, because we are not sync
-                * yet.)
-                */
-               if (atomic_set_buffer_clean(bh))
-                       __mark_buffer_clean(bh);
-               else {
-                       bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
-                       return 0;
-               }
-       }
        r1_bh = raid1_alloc_r1bh (conf);
 
        spin_lock_irq(&conf->segment_lock);
index 5d575a7f55cc1506fbbc729d4dfa2be3bf4e4ace..cff836dc4cbd7814e882210f31beaaf2419c2bdf 100644 (file)
@@ -863,8 +863,7 @@ static void compute_parity(struct stripe_head *sh, int method)
                if (!sh->bh_copy[i])
                        sh->bh_copy[i] = raid5_alloc_buffer(sh, sh->size);
                raid5_build_block(sh, sh->bh_copy[i], i);
-               if (atomic_set_buffer_clean(sh->bh_new[i]))
-                       atomic_set_buffer_dirty(sh->bh_copy[i]);
+               atomic_set_buffer_dirty(sh->bh_copy[i]);
                memcpy(sh->bh_copy[i]->b_data, sh->bh_new[i]->b_data, sh->size);
        }
        if (sh->bh_copy[pd_idx] == NULL) {
@@ -995,28 +994,12 @@ static void complete_stripe(struct stripe_head *sh)
 }
 
 
-static int is_stripe_allclean(struct stripe_head *sh, int disks)
-{
-       int i;
-
-       return 0;
-       for (i = 0; i < disks; i++) {
-               if (sh->bh_new[i])
-                       if (test_bit(BH_Dirty, &sh->bh_new[i]))
-                               return 0;
-               if (sh->bh_old[i])
-                       if (test_bit(BH_Dirty, &sh->bh_old[i]))
-                               return 0;
-       }
-       return 1;
-}
-
 static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf,
        struct stripe_head *sh, int nr_write, int * operational, int disks,
        int parity, int parity_failed, int nr_cache, int nr_cache_other,
        int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite)
 {
-       int i, allclean;
+       int i;
        unsigned int block;
        struct buffer_head *bh;
        int method1 = INT_MAX, method2 = INT_MAX;
@@ -1068,7 +1051,6 @@ static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf,
        PRINTK("handle_stripe(), sector %lu, nr_write %d, method1 %d, method2 %d\n", sh->sector, nr_write, method1, method2);
 
        if (!method1 || !method2) {
-               allclean = is_stripe_allclean(sh, disks);
                sh->phase = PHASE_WRITE;
                compute_parity(sh, method1 <= method2 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
 
@@ -1087,24 +1069,11 @@ static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf,
                                        PRINTK("writing spare %d\n", i);
                                        atomic_inc(&sh->nr_pending);
                                        bh->b_dev = bh->b_rdev = conf->spare->dev;
-                                       generic_make_request(WRITERAW, bh);
+                                       generic_make_request(WRITE, bh);
                                } else {
-#if 0
                                        atomic_inc(&sh->nr_pending);
                                        bh->b_dev = bh->b_rdev = conf->disks[i].dev;
-                                       generic_make_request(WRITERAW, bh);
-#else
-                                       if (!allclean || (i==sh->pd_idx)) {
-                                               PRINTK("writing dirty %d\n", i);
-                                               atomic_inc(&sh->nr_pending);
-                                               bh->b_dev = bh->b_rdev = conf->disks[i].dev;
-                                               generic_make_request(WRITERAW, bh);
-                                       } else {
-                                               PRINTK("not writing clean %d\n", i);
-                                               raid5_end_request(bh, 1);
-                                               sh->new[i] = 0;
-                                       }
-#endif
+                                       generic_make_request(WRITE, bh);
                                }
                                atomic_dec(&bh->b_count);
                        }
@@ -1282,7 +1251,7 @@ static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf,
                                atomic_inc(&sh->nr_pending);
                                lock_get_bh(bh);
                                bh->b_dev = bh->b_rdev = conf->spare->dev;
-                               generic_make_request(WRITERAW, bh);
+                               generic_make_request(WRITE, bh);
                                md_sync_acct(bh->b_rdev, bh->b_size/512);
                                atomic_dec(&bh->b_count);
                PRINTK("handle_stripe_sync() %lu, phase WRITE, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending));
@@ -1308,7 +1277,7 @@ static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf,
                lock_get_bh(bh);
                atomic_inc(&sh->nr_pending);
                bh->b_dev = bh->b_rdev = conf->disks[pd_idx].dev;
-               generic_make_request(WRITERAW, bh);
+               generic_make_request(WRITE, bh);
                md_sync_acct(bh->b_rdev, bh->b_size/512);
                atomic_dec(&bh->b_count);
                PRINTK("handle_stripe_sync() %lu phase WRITE, pending %d buffers\n",
index fd0486f34594549b834d24ec87362e3bd94742c2..85f84629cb3857b463b37f111f4b07a117123255 100644 (file)
@@ -60,6 +60,15 @@ if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
      tristate '    Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
    fi
 fi
+if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
+   bool 'DC21285 serial port support' CONFIG_SERIAL_21285
+   if [ "$CONFIG_SERIAL_21285" = "y" ]; then
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
+         bool '  Use /dev/ttyS0 device (OBSOLETE)' CONFIG_SERIAL_21285_OLD
+      fi
+      bool '  Console on DC21285 serial port' CONFIG_SERIAL_21285_CONSOLE
+   fi
+fi
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
    int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
@@ -238,7 +247,7 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
       fi
       dep_tristate '  Stradis 4:2:2 MPEG-2 video driver  (EXPERIMENTAL)' CONFIG_VIDEO_STRADIS $CONFIG_VIDEO_DEV $CONFIG_PCI
    fi
-   dep_tristate '  Zoran ZR36057/36060 Video For Linux' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI
+   dep_tristate '  Zoran ZR36057/36060 Video For Linux' CONFIG_VIDEO_ZORAN $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
    dep_tristate '    Include support for Iomega Buz' CONFIG_VIDEO_BUZ $CONFIG_VIDEO_ZORAN
    dep_tristate '  Zoran ZR36120/36125 Video For Linux' CONFIG_VIDEO_ZR36120 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C
 fi
index c47164131eabdefb0b92e23902320a21cd4f3028..cb7ab35a108319194c5e101e259db774eb103d40 100644 (file)
@@ -65,11 +65,12 @@ ifeq ($(ARCH),m68k)
 endif
 
 ifeq ($(ARCH),arm)
-# we actually need to be able to select various different keymaps
-# and keyboards dependent on which actual machine we're going to
-# run on.
-  KEYMAP   =
-  KEYBD    =
+  ifneq ($(CONFIG_PC_KEYMAP),y)
+    KEYMAP   =
+  endif
+  ifneq ($(CONFIG_PC_KEYB),y)
+    KEYBD    =
+  endif
 endif
 
 ifeq ($(ARCH),sh)
index af32ba284e8b483e82d252f314b5a81d143c415e..acad5947acec6dbfb9a87c106646b5eace290be6 100644 (file)
@@ -154,8 +154,11 @@ struct agp_bridge_data {
 #ifndef PCI_DEVICE_ID_VIA_82C691_0
 #define PCI_DEVICE_ID_VIA_82C691_0      0x0691
 #endif
-#ifndef PCI_DEVICE_ID_VIA_82C691_1
-#define PCI_DEVICE_ID_VIA_82C691_1      0x8691
+#ifndef PCI_DEVICE_ID_VIA_8371_0
+#define PCI_DEVICE_ID_VIA_8371_0      0x0391
+#endif
+#ifndef PCI_DEVICE_ID_VIA_8363_0
+#define PCI_DEVICE_ID_VIA_8363_0      0x0305
 #endif
 #ifndef PCI_DEVICE_ID_INTEL_810_0
 #define PCI_DEVICE_ID_INTEL_810_0       0x7120
index b775446edd6dfa0f9c162521fd86c80b13de59dd..c0a5308faad06c95004dfac653e136274947ad83 100644 (file)
@@ -414,10 +414,9 @@ int agp_unbind_memory(agp_memory * curr)
 
 /* 
  * Driver routines - start
- * Currently this module supports the 
- * i810, 440lx, 440bx, 440gx, via vp3, via mvp3,
- * amd irongate, ALi M1541 and generic support for the
- * SiS chipsets.
+ * Currently this module supports the following chipsets:
+ * i810, 440lx, 440bx, 440gx, via vp3, via mvp3, via kx133, via kt133,
+ * amd irongate, ALi M1541, and generic support for the SiS chipsets.
  */
 
 /* Generic Agp routines - Start */
@@ -2129,12 +2128,6 @@ static struct {
 #endif /* CONFIG_AGP_SIS */
 
 #ifdef CONFIG_AGP_VIA
-       { PCI_DEVICE_ID_VIA_8371_0,
-               PCI_VENDOR_ID_VIA,
-               VIA_APOLLO_SUPER,
-               "Via",
-               "Apollo Super",
-               via_generic_setup },
        { PCI_DEVICE_ID_VIA_8501_0,
                PCI_VENDOR_ID_VIA,
                VIA_MVP4,
@@ -2159,6 +2152,18 @@ static struct {
                "Via",
                "Apollo Pro",
                via_generic_setup },
+       { PCI_DEVICE_ID_VIA_8371_0,
+               PCI_VENDOR_ID_VIA,
+               VIA_APOLLO_KX133,
+               "Via",
+               "Apollo Pro KX133",
+               via_generic_setup },
+       { PCI_DEVICE_ID_VIA_8363_0,
+               PCI_VENDOR_ID_VIA,
+               VIA_APOLLO_KT133,
+               "Via",
+               "Apollo Pro KT133",
+               via_generic_setup },
        { 0,
                PCI_VENDOR_ID_VIA,
                VIA_GENERIC,
index 8b04dc6e06d0952d4965ae958d5edee0089c0062..42a1bc2f6d559e5541ccfcb59815828a8ceeb260 100644 (file)
@@ -309,7 +309,9 @@ drm_agp_head_t *drm_agp_init(void)
 
 #if LINUX_VERSION_CODE >= 0x020400
                case VIA_MVP4:          head->chipset = "VIA MVP4";      break;
-               case VIA_APOLLO_SUPER:  head->chipset = "VIA Apollo Super"; 
+               case VIA_APOLLO_KX133:  head->chipset = "VIA Apollo KX133"; 
+                       break;
+               case VIA_APOLLO_KT133:  head->chipset = "VIA Apollo KT133"; 
                        break;
 #endif
 
index f0c76181ba39ac95f03ea1f5668b6adbf339d299..8b8d0f1231a83ecab06a472614b2486faa97ab69 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <asm/therm.h>
 
index b020f17288dfe8a8691eb37d60041f1f19d17c64..698bc97a0821c3f355bc05b995fb2c5d31ff3999 100644 (file)
@@ -40,9 +40,9 @@ if [ "$CONFIG_JOYSTICK" != "n" ]; then
 
    if [ "$CONFIG_PARPORT" != "n" ]; then
    comment 'Parallel port joysticks'
-      dep_tristate '  Multisystem, Sega Genesis, Saturn joysticks and gamepads' CONFIG_INPUT_DB9 $CONFIG_JOYSTICK
-      dep_tristate '  Multisystem, NES, SNES, N64, PSX joysticks and gamepads' CONFIG_INPUT_GAMECON $CONFIG_JOYSTICK
-      dep_tristate '  Multisystem joysticks via TurboGraFX device' CONFIG_INPUT_TURBOGRAFX $CONFIG_JOYSTICK
+      dep_tristate '  Multisystem, Sega Genesis, Saturn joysticks and gamepads' CONFIG_INPUT_DB9 $CONFIG_JOYSTICK $CONFIG_PARPORT
+      dep_tristate '  Multisystem, NES, SNES, N64, PSX joysticks and gamepads' CONFIG_INPUT_GAMECON $CONFIG_JOYSTICK $CONFIG_PARPORT
+      dep_tristate '  Multisystem joysticks via TurboGraFX device' CONFIG_INPUT_TURBOGRAFX $CONFIG_JOYSTICK $CONFIG_PARPORT
    fi
 
    if [ "$CONFIG_AMIGA" = "y" ]; then
index f34a1864003e8afef21b0588c910feaab9affaf1..e8a1c46c8dd892a595811394f058869312727192 100644 (file)
@@ -182,6 +182,7 @@ static int __devinit ns558_pci_probe(struct pci_dev *pdev, const struct pci_devi
 
        if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
                printk(KERN_ERR "Memory allocation failed.\n");
+               release_region(ioport, iolen);
                return -ENOMEM;
        }
        memset(port, 0, sizeof(struct ns558));
@@ -328,7 +329,7 @@ int __init ns558_init(void)
        }
 #endif
 
-       return -!ns558;
+       return 0;
 }
 
 void __exit ns558_exit(void)
index 8cf8a15a7cd33cc4d5897ac23ac6620cd54dc40f..e99d928560b219d0e208798dd33cbcc3bc37fa8d 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <asm/uaccess.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
+
 #define __NWBUTTON_C           /* Tell the header file who we are */
 #include "nwbutton.h"
 
index 5be07b7696a16059ba87966a659ad657fc6136fe..8b5c266a650bc5f820d17c5bd0fdd5e2ad383b6e 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/dec21285.h>
 #include <asm/io.h>
 #include <asm/leds.h>
+#include <asm/mach-types.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
index 8fb32fb5a595da96703fbd726c4d51f553b77a33..f23f911ad88f7cb45dd2b14e74d9f8ed19231b87 100644 (file)
@@ -303,18 +303,16 @@ static struct serial_uart_config uart_config[] = {
        { 0, 0}
 };
 
-#ifdef CONFIG_SERIAL_RSA
+#if defined(CONFIG_SERIAL_RSA) && defined(MODULE)
 
 #define PORT_RSA_MAX 4
 static int probe_rsa[PORT_RSA_MAX];
 static int force_rsa[PORT_RSA_MAX];
 
-#ifdef MODULE
 MODULE_PARM(probe_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
 MODULE_PARM(force_rsa, "1-" __MODULE_STRING(PORT_RSA_MAX) "i");
 MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
-#endif
 #endif /* CONFIG_SERIAL_RSA  */
 
 static struct serial_state rs_table[RS_TABLE_SIZE] = {
diff --git a/drivers/char/serial_21285.c b/drivers/char/serial_21285.c
new file mode 100644 (file)
index 0000000..575cf0b
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * linux/drivers/char/serial_21285.c
+ *
+ * Driver for the serial port on the 21285 StrongArm-110 core logic chip.
+ *
+ * Based on drivers/char/serial.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/dec21285.h>
+#include <asm/hardware.h>
+
+#define BAUD_BASE              (mem_fclk_21285/64)
+
+#define SERIAL_21285_NAME      "ttyFB"
+#define SERIAL_21285_MAJOR     204
+#define SERIAL_21285_MINOR     4
+
+#define SERIAL_21285_AUXNAME   "cuafb"
+#define SERIAL_21285_AUXMAJOR  205
+#define SERIAL_21285_AUXMINOR  4
+
+static struct tty_driver rs285_driver, callout_driver;
+static int rs285_refcount;
+static struct tty_struct *rs285_table[1];
+
+static struct termios *rs285_termios[1];
+static struct termios *rs285_termios_locked[1];
+
+static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
+static struct tty_struct *rs285_tty;
+static int rs285_use_count;
+
+static int rs285_write_room(struct tty_struct *tty)
+{
+       return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
+}
+
+static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+       if (!rs285_tty) {
+               disable_irq(IRQ_CONRX);
+               return;
+       }
+       while (!(*CSR_UARTFLG & 0x10)) {
+               int ch, flag;
+               ch = *CSR_UARTDR;
+               flag = *CSR_RXSTAT;
+               if (flag & 4)
+                       tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
+               if (flag & 2)
+                       flag = TTY_PARITY;
+               else if (flag & 1)
+                       flag = TTY_FRAME;
+               tty_insert_flip_char(rs285_tty, ch, flag);
+       }
+       tty_flip_buffer_push(rs285_tty);
+}
+
+static void rs285_send_xchar(struct tty_struct *tty, char ch)
+{
+       x_char = ch;
+       enable_irq(IRQ_CONTX);
+}
+
+static void rs285_throttle(struct tty_struct *tty)
+{
+       if (I_IXOFF(tty))
+               rs285_send_xchar(tty, STOP_CHAR(tty));
+}
+
+static void rs285_unthrottle(struct tty_struct *tty)
+{
+       if (I_IXOFF(tty)) {
+               if (x_char)
+                       x_char = 0;
+               else
+                       rs285_send_xchar(tty, START_CHAR(tty));
+       }
+}
+
+static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+       while (!(*CSR_UARTFLG & 0x20)) {
+               if (x_char) {
+                       *CSR_UARTDR = x_char;
+                       x_char = 0;
+                       continue;
+               }
+               if (putp == getp) {
+                       disable_irq(IRQ_CONTX);
+                       break;
+               }
+               *CSR_UARTDR = *getp;
+               if (++getp >= wbuf + sizeof(wbuf))
+                       getp = wbuf;
+       }
+       if (rs285_tty)
+               wake_up_interruptible(&rs285_tty->write_wait);
+}
+
+static inline int rs285_xmit(int ch)
+{
+       if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
+               return 0;
+       *putp = ch;
+       if (++putp >= wbuf + sizeof(wbuf))
+               putp = wbuf;
+       enable_irq(IRQ_CONTX);
+       return 1;
+}
+
+static int rs285_write(struct tty_struct *tty, int from_user,
+                      const u_char * buf, int count)
+{
+       int i;
+
+       if (from_user && verify_area(VERIFY_READ, buf, count))
+               return -EINVAL;
+
+       for (i = 0; i < count; i++) {
+               char ch;
+               if (from_user)
+                       __get_user(ch, buf + i);
+               else
+                       ch = buf[i];
+               if (!rs285_xmit(ch))
+                       break;
+       }
+       return i;
+}
+
+static void rs285_put_char(struct tty_struct *tty, u_char ch)
+{
+       rs285_xmit(ch);
+}
+
+static int rs285_chars_in_buffer(struct tty_struct *tty)
+{
+       return sizeof(wbuf) - rs285_write_room(tty);
+}
+
+static void rs285_flush_buffer(struct tty_struct *tty)
+{
+       disable_irq(IRQ_CONTX);
+       putp = getp = wbuf;
+       if (x_char)
+               enable_irq(IRQ_CONTX);
+}
+
+static inline void rs285_set_cflag(int cflag)
+{
+       int h_lcr, baud, quot;
+
+       switch (cflag & CSIZE) {
+       case CS5:
+               h_lcr = 0x10;
+               break;
+       case CS6:
+               h_lcr = 0x30;
+               break;
+       case CS7:
+               h_lcr = 0x50;
+               break;
+       default: /* CS8 */
+               h_lcr = 0x70;
+               break;
+
+       }
+       if (cflag & CSTOPB)
+               h_lcr |= 0x08;
+       if (cflag & PARENB)
+               h_lcr |= 0x02;
+       if (!(cflag & PARODD))
+               h_lcr |= 0x04;
+
+       switch (cflag & CBAUD) {
+       case B200:      baud = 200;             break;
+       case B300:      baud = 300;             break;
+       case B1200:     baud = 1200;            break;
+       case B1800:     baud = 1800;            break;
+       case B2400:     baud = 2400;            break;
+       case B4800:     baud = 4800;            break;
+       default:
+       case B9600:     baud = 9600;            break;
+       case B19200:    baud = 19200;           break;
+       case B38400:    baud = 38400;           break;
+       case B57600:    baud = 57600;           break;
+       case B115200:   baud = 115200;          break;
+       }
+
+       /*
+        * The documented expression for selecting the divisor is:
+        *  BAUD_BASE / baud - 1
+        * However, typically BAUD_BASE is not divisible by baud, so
+        * we want to select the divisor that gives us the minimum
+        * error.  Therefore, we want:
+        *  int(BAUD_BASE / baud - 0.5) ->
+        *  int(BAUD_BASE / baud - (baud >> 1) / baud) ->
+        *  int((BAUD_BASE - (baud >> 1)) / baud)
+        */
+       quot = (BAUD_BASE - (baud >> 1)) / baud;
+
+       *CSR_UARTCON = 0;
+       *CSR_L_UBRLCR = quot & 0xff;
+       *CSR_M_UBRLCR = (quot >> 8) & 0x0f;
+       *CSR_H_UBRLCR = h_lcr;
+       *CSR_UARTCON = 1;
+}
+
+static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
+{
+       if (old && tty->termios->c_cflag == old->c_cflag)
+               return;
+       rs285_set_cflag(tty->termios->c_cflag);
+}
+
+
+static void rs285_stop(struct tty_struct *tty)
+{
+       disable_irq(IRQ_CONTX);
+}
+
+static void rs285_start(struct tty_struct *tty)
+{
+       enable_irq(IRQ_CONTX);
+}
+
+static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+       int orig_jiffies = jiffies;
+       while (*CSR_UARTFLG & 8) {
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(1);
+               if (signal_pending(current))
+                       break;
+               if (timeout && time_after(jiffies, orig_jiffies + timeout))
+                       break;
+       }
+       current->state = TASK_RUNNING;
+}
+
+static int rs285_open(struct tty_struct *tty, struct file *filp)
+{
+       int line;
+
+       MOD_INC_USE_COUNT;
+       line = MINOR(tty->device) - tty->driver.minor_start;
+       if (line) {
+               MOD_DEC_USE_COUNT;
+               return -ENODEV;
+       }
+
+       tty->driver_data = NULL;
+       if (!rs285_tty)
+               rs285_tty = tty;
+
+       enable_irq(IRQ_CONRX);
+       rs285_use_count++;
+       return 0;
+}
+
+static void rs285_close(struct tty_struct *tty, struct file *filp)
+{
+       if (!--rs285_use_count) {
+               rs285_wait_until_sent(tty, 0);
+               disable_irq(IRQ_CONRX);
+               disable_irq(IRQ_CONTX);
+               rs285_tty = NULL;
+       }
+       MOD_DEC_USE_COUNT;
+}
+
+static int __init rs285_init(void)
+{
+       int baud = B9600;
+
+       if (machine_is_personal_server())
+               baud = B57600;
+
+       rs285_driver.magic = TTY_DRIVER_MAGIC;
+       rs285_driver.driver_name = "serial_21285";
+       rs285_driver.name = SERIAL_21285_NAME;
+       rs285_driver.major = SERIAL_21285_MAJOR;
+       rs285_driver.minor_start = SERIAL_21285_MINOR;
+       rs285_driver.num = 1;
+       rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
+       rs285_driver.subtype = SERIAL_TYPE_NORMAL;
+       rs285_driver.init_termios = tty_std_termios;
+       rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
+       rs285_driver.flags = TTY_DRIVER_REAL_RAW;
+       rs285_driver.refcount = &rs285_refcount;
+       rs285_driver.table = rs285_table;
+       rs285_driver.termios = rs285_termios;
+       rs285_driver.termios_locked = rs285_termios_locked;
+
+       rs285_driver.open = rs285_open;
+       rs285_driver.close = rs285_close;
+       rs285_driver.write = rs285_write;
+       rs285_driver.put_char = rs285_put_char;
+       rs285_driver.write_room = rs285_write_room;
+       rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
+       rs285_driver.flush_buffer = rs285_flush_buffer;
+       rs285_driver.throttle = rs285_throttle;
+       rs285_driver.unthrottle = rs285_unthrottle;
+       rs285_driver.send_xchar = rs285_send_xchar;
+       rs285_driver.set_termios = rs285_set_termios;
+       rs285_driver.stop = rs285_stop;
+       rs285_driver.start = rs285_start;
+       rs285_driver.wait_until_sent = rs285_wait_until_sent;
+
+       callout_driver = rs285_driver;
+       callout_driver.name = SERIAL_21285_AUXNAME;
+       callout_driver.major = SERIAL_21285_AUXMAJOR;
+       callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+       if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
+               panic("Couldn't get rx irq for rs285");
+
+       if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
+               panic("Couldn't get tx irq for rs285");
+
+       if (tty_register_driver(&rs285_driver))
+               printk(KERN_ERR "Couldn't register 21285 serial driver\n");
+       if (tty_register_driver(&callout_driver))
+               printk(KERN_ERR "Couldn't register 21285 callout driver\n");
+
+       return 0;
+}
+
+static void __exit rs285_fini(void)
+{
+       unsigned long flags;
+       int ret;
+
+       save_flags(flags);
+       cli();
+       ret = tty_unregister_driver(&callout_driver);
+       if (ret)
+               printk(KERN_ERR "Unable to unregister 21285 callout driver "
+                       "(%d)\n", ret);
+       ret = tty_unregister_driver(&rs285_driver);
+       if (ret)
+               printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
+                       ret);
+       free_irq(IRQ_CONTX, NULL);
+       free_irq(IRQ_CONRX, NULL);
+       restore_flags(flags);
+}
+
+module_init(rs285_init);
+module_exit(rs285_fini);
+
+#ifdef CONFIG_SERIAL_21285_CONSOLE
+/************** console driver *****************/
+
+static void rs285_console_write(struct console *co, const char *s, u_int count)
+{
+       int i;
+
+       disable_irq(IRQ_CONTX);
+       for (i = 0; i < count; i++) {
+               while (*CSR_UARTFLG & 0x20);
+               *CSR_UARTDR = s[i];
+               if (s[i] == '\n') {
+                       while (*CSR_UARTFLG & 0x20);
+                       *CSR_UARTDR = '\r';
+               }
+       }
+       enable_irq(IRQ_CONTX);
+}
+
+static int rs285_console_wait_key(struct console *co)
+{
+       int c;
+
+       disable_irq(IRQ_CONRX);
+       while (*CSR_UARTFLG & 0x10);
+       c = *CSR_UARTDR;
+       enable_irq(IRQ_CONRX);
+       return c;
+}
+
+static kdev_t rs285_console_device(struct console *c)
+{
+       return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
+}
+
+static int __init rs285_console_setup(struct console *co, char *options)
+{
+       int baud = 9600;
+       int bits = 8;
+       int parity = 'n';
+       int cflag = CREAD | HUPCL | CLOCAL;
+
+       if (machine_is_personal_server())
+               baud = 57600;
+
+       if (options) {
+               char *s = options;
+               baud = simple_strtoul(options, NULL, 10);
+               while (*s >= '0' && *s <= '9')
+                       s++;
+               if (*s)
+                       parity = *s++;
+               if (*s)
+                       bits = *s - '0';
+       }
+
+       /*
+        *    Now construct a cflag setting.
+        */
+       switch (baud) {
+       case 1200:
+               cflag |= B1200;
+               break;
+       case 2400:
+               cflag |= B2400;
+               break;
+       case 4800:
+               cflag |= B4800;
+               break;
+       case 9600:
+               cflag |= B9600;
+               break;
+       case 19200:
+               cflag |= B19200;
+               break;
+       case 38400:
+               cflag |= B38400;
+               break;
+       case 57600:
+               cflag |= B57600;
+               break;
+       case 115200:
+               cflag |= B115200;
+               break;
+       default:
+               cflag |= B9600;
+               break;
+       }
+       switch (bits) {
+       case 7:
+               cflag |= CS7;
+               break;
+       default:
+               cflag |= CS8;
+               break;
+       }
+       switch (parity) {
+       case 'o':
+       case 'O':
+               cflag |= PARODD;
+               break;
+       case 'e':
+       case 'E':
+               cflag |= PARENB;
+               break;
+       }
+       co->cflag = cflag;
+       rs285_set_cflag(cflag);
+       rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
+       if (options)
+               rs285_console_write(NULL, options, strlen(options));
+       else
+               rs285_console_write(NULL, "no options", 10);
+       rs285_console_write(NULL, "\n", 1);
+
+       return 0;
+}
+
+static struct console rs285_cons =
+{
+       SERIAL_21285_NAME,
+       rs285_console_write,
+       NULL,
+       rs285_console_device,
+       rs285_console_wait_key,
+       NULL,
+       rs285_console_setup,
+       CON_PRINTBUFFER,
+       -1,
+       0,
+       NULL
+};
+
+void __init rs285_console_init(void)
+{
+       register_console(&rs285_cons);
+}
+
+#endif /* CONFIG_SERIAL_21285_CONSOLE */
index 66633fd2088c42ee991a19245f8427c791143467..6745493de264252148418a16e83bf357b338383c 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/hardware.h>
-#include <asm/system.h>
+#include <asm/mach-types.h>
 #include <asm/dec21285.h>
 
 /*
index e4ba2cf1f3dfc7343a075a8828f54c4d60874aa0..e79a3cf200b8c6fac66e5b335775be3e623bd23d 100644 (file)
@@ -83,7 +83,15 @@ if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
 fi
 dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
-   bool '  Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+   if [ "$CONFIG_ISDN_DRV_EICON_STANDALONE" != "y" ]; then
+      if [ "$CONFIG_PCI" = "y" ]; then
+         bool '    Eicon PCI DIVA Server BRI/PRI/4BRI support' CONFIG_ISDN_DRV_EICON_PCI
+      fi
+      bool '    Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
+   fi
+   if [ "$CONFIG_PCI" = "y" ]; then
+      bool '    build eicon driver type standalone' CONFIG_ISDN_DRV_EICON_STANDALONE
+   fi
 fi
 dep_tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI $CONFIG_ISDN
 if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
diff --git a/drivers/isdn/eicon/Divas_mod.c b/drivers/isdn/eicon/Divas_mod.c
new file mode 100644 (file)
index 0000000..7522556
--- /dev/null
@@ -0,0 +1,171 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.15  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/fs.h>
+#undef N_DATA
+
+#include <linux/kernel.h>
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <errno.h>
+
+#include "adapter.h"
+#include "uxio.h"
+
+#ifdef MODULE
+#include "idi.h"
+void EtdM_DIDD_Write(DESCRIPTOR *, int);
+EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Read);
+EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Write);
+EXPORT_SYMBOL_NOVERS(DivasPrintf);
+#define Divas_init init_module
+#endif
+
+extern char *file_check(void);
+
+int DivasCardsDiscover(void);
+
+int
+Divas_init(void)
+{
+       printk(KERN_DEBUG "DIVA Server Driver - initialising\n");
+       
+       printk(KERN_DEBUG "DIVA Server Driver - Version 2.0.12 (%s)\n",file_check());
+
+
+#if !defined(CONFIG_PCI)
+       printk(KERN_WARNING "CONFIG_PCI is not defined!\n");
+       return -ENODEV;
+#endif
+
+       if (pci_present())
+       {
+               if (DivasCardsDiscover() < 0)
+               {
+                       printk(KERN_WARNING "Divas: Not loaded\n");
+                       return -ENODEV;
+               }
+       }
+       else
+       {
+               printk(KERN_WARNING "Divas: No PCI bus present\n");
+               return -ENODEV;
+       }
+
+    return 0;
+}
+
+#ifdef MODULE
+void
+cleanup_module(void)
+{
+       card_t *pCard;
+       word wCardIndex;
+       extern int Divas_major;
+
+       printk(KERN_DEBUG "DIVA Server Driver - unloading\n");
+
+       pCard = DivasCards;
+       for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
+       {
+               if ((pCard->hw) && (pCard->hw->in_use))
+               {
+
+                       (*pCard->card_reset)(pCard);
+                       
+                       UxIsrRemove(pCard->hw, pCard);
+                       UxCardHandleFree(pCard->hw);
+
+                       if(pCard->e_tbl != NULL)
+                       {
+                               kfree(pCard->e_tbl);
+                       }
+
+                       
+                       if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
+                       {       
+                               release_region(pCard->hw->io_base,0x20);                
+                               release_region(pCard->hw->reset_base,0x80);             
+                       }
+
+                       // If this is a 4BRI ...
+                       if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
+                       {
+                               // Skip over the next 3 virtual adapters
+                               wCardIndex += 3;
+
+                               // But free their handles 
+                               pCard++;
+                               UxCardHandleFree(pCard->hw);
+                       
+                               if(pCard->e_tbl != NULL)
+                               {
+                                       kfree(pCard->e_tbl);
+                               }
+                               
+                               pCard++;
+                               UxCardHandleFree(pCard->hw);
+                               
+                               if(pCard->e_tbl != NULL)
+                               {
+                                       kfree(pCard->e_tbl);
+                               }
+                               
+                               pCard++;
+                               UxCardHandleFree(pCard->hw);
+                               
+                               if(pCard->e_tbl != NULL)
+                               {
+                                       kfree(pCard->e_tbl);
+                               }
+                       }
+               }
+               pCard++;
+       }
+
+       unregister_chrdev(Divas_major, "Divas");
+}
+
+void mod_inc_use_count(void)
+{
+       MOD_INC_USE_COUNT;
+}
+
+void mod_dec_use_count(void)
+{
+       MOD_DEC_USE_COUNT;
+}
+
+#else
+Divas_setup(char *str, int *ints)
+{
+}
+#endif
+
index 306aac0e826554dfeb7de0df2e1b83646a8fc94a..63c557492b4c1722ae4d4bbebba9ef3263ee1240 100644 (file)
@@ -1,8 +1,37 @@
 L_OBJS :=
 M_OBJS :=
-O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
+LX_OBJS :=
+MX_OBJS :=
+O_OBJS :=
+OX_OBJS :=
+L_TARGET :=
+O_TARGET :=
+
+ifeq ($(CONFIG_ISDN_DRV_EICON_STANDALONE),y)
+
+ ifeq ($(CONFIG_PCI),y)
+   O_OBJS += common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o fourbri.o
+   O_OBJS += lincfg.o linchr.o linsys.o linio.o
+   O_OBJS += fcheck.o
+   OX_OBJS += Divas_mod.o
+ endif
+
+else
+
+ OX_OBJS += eicon_mod.o
+ O_OBJS := eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
+ O_OBJS += fcheck.o
+ ifeq ($(CONFIG_PCI),y)
+  ifeq ($(CONFIG_ISDN_DRV_EICON_PCI),y)
+   O_OBJS += common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o fourbri.o
+   O_OBJS += lincfg.o linchr.o linsys.o linio.o
+  endif
+ endif
+
+endif
 
 O_TARGET :=
+
 ifeq ($(CONFIG_ISDN_DRV_EICON),y)
   O_TARGET += eicon.o
 else
@@ -10,4 +39,14 @@ else
   M_OBJS   = eicon.o
 endif
 
+
 include $(TOPDIR)/Rules.make
+
+MD5FILES += common.c idi.c bri.c pri.c log.c xlog.c kprintf.c fpga.c \
+            fourbri.c fcheck.c
+
+FCHECK = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+
+fcheck.o: $(MD5FILES)
+       $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D FILECHECK=$(FCHECK) -c -o fcheck.o fcheck.c
+
diff --git a/drivers/isdn/eicon/adapter.h b/drivers/isdn/eicon/adapter.h
new file mode 100644 (file)
index 0000000..cabba68
--- /dev/null
@@ -0,0 +1,265 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.7  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* Main internal include file for Diva Server driver */
+
+#if !defined(ADAPTER_H)
+#define ADAPTER_H
+
+#include "sys.h"
+#include "idi.h"
+#include "divas.h"
+#undef ID_MASK
+#include "pc.h"
+
+#define XMOREC 0x1f
+#define XMOREF 0x20
+#define XBUSY  0x40
+#define RMORE  0x80
+
+        /* structure for all information we have to keep on a per   */
+        /* adapater basis                                           */
+
+typedef struct adapter_s ADAPTER;
+
+struct adapter_s {
+  void * io;
+
+  byte IdTable[256];
+  byte ReadyInt;
+
+  byte (* ram_in)(ADAPTER * a, void * adr);
+  word (* ram_inw)(ADAPTER * a, void * adr);
+  void (* ram_in_buffer)(ADAPTER * a, void * adr, void * P, word length);
+  void (* ram_look_ahead)(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
+
+  void (* ram_out)(ADAPTER * a, void * adr, byte data);
+  void (* ram_outw)(ADAPTER * a, void * adr, word data);
+  void (* ram_out_buffer)(ADAPTER * a, void * adr, void * P, word length);
+
+  void (* ram_inc)(ADAPTER * a, void * adr);
+};
+
+typedef struct card card_t;
+
+typedef int    card_load_fn_t(card_t *card, dia_load_t *load);
+typedef int    card_config_fn_t(card_t *card, dia_config_t *config);
+typedef int    card_start_fn_t(card_t *card, byte *channels);
+typedef        int     card_reset_fn_t(card_t *card);
+typedef int card_mem_get_fn_t(card_t *card, mem_block_t *mem_block);
+
+#define        MAX_PENTITIES   256             /* Number of entities primary adapter */
+#define MAX_ENTITIES   16              /* Number of entities standard adapter */
+
+typedef struct e_info_s E_INFO;
+
+struct e_info_s
+{
+       ENTITY          *e;                             /* entity pointer */
+       byte            next;                   /* chaining index */
+       word            assign_ref;             /* assign reference */
+};
+
+/* DIVA card info (details hidden from user) */
+
+typedef struct ux_diva_card_s ux_diva_card_t;
+
+/* card info */
+
+struct card
+{
+       ADAPTER                         a;                              /* per-adapter information */
+       dia_card_t                      cfg;                    /* card configuration */
+       int                             state;                  /* State of the adapter */
+       dword                           serial_no;              /* serial number */
+       int                             test_int_pend;  /* set for interrupt testing */
+       ux_diva_card_t          *hw;                    /* O/S-specific handle */
+       card_reset_fn_t         *card_reset;    /* call this to reset card */
+       card_load_fn_t          *card_load;             /* call this to load card */
+       card_config_fn_t        *card_config;   /* call this to config card */
+       card_start_fn_t         *card_start;    /* call this to start card */
+       card_mem_get_fn_t       *card_mem_get;  /* call this to get card memory */
+       E_INFO                          *e_tbl;                 /* table of ENTITY pointers */
+       byte                            e_head;                 /* list of active ENTITIES */
+       byte                            e_tail;                 /* list of active ENTITIES */
+       int                                     e_count;                /* # of active ENTITIES */
+       int                                     e_max;                  /* total # of ENTITIES */
+       byte                            assign;                 /* assign queue entry */
+       PBUFFER                         RBuffer;                /* Copy of receive lookahead buffer */
+       int                                     log_types;              /* bit-mask of active logs */
+       word                            xlog_offset;    /* offset to XLOG buffer on card */
+       void            (*out)(ADAPTER *a);
+       byte            (*dpc)(ADAPTER * a);
+       byte            (*test_int)(ADAPTER * a);
+       void            (*clear_int)(ADAPTER * a);
+       void            (*reset_int)(card_t *c);
+       int             is_live;
+
+       int             (*card_isr)(card_t *card);
+
+       int             int_pend;               /* interrupt pending */
+       long            interrupt_reentered;
+       long            dpc_reentered;
+       int             set_xlog_request;
+
+} ;
+
+/* card information */
+
+#define        MAX_CARDS       20              /* max number of cards on a system */
+
+extern
+card_t                 DivasCards[];
+
+extern
+int                            DivasCardNext;
+
+extern
+dia_config_t   DivasCardConfigs[];
+
+extern
+byte                   DivasFlavourConfig[];
+
+/*------------------------------------------------------------------*/
+/* public functions of IDI common code                              */
+/*------------------------------------------------------------------*/
+
+void DivasOut(ADAPTER * a);
+byte DivasDpc(ADAPTER * a);
+byte DivasTestInt(ADAPTER * a);
+void DivasClearInt(ADAPTER * a);
+
+/*------------------------------------------------------------------*/
+/* public functions of configuration platform-specific code         */
+/*------------------------------------------------------------------*/
+
+int DivasConfigGet(dia_card_t *card);
+
+/*------------------------------------------------------------------*/
+/* public functions of LOG related code                             */
+/*------------------------------------------------------------------*/
+
+void   DivasXlogReq(int card_num);
+int            DivasXlogRetrieve(card_t *card);
+void   DivasLog(dia_log_t *log);
+void   DivasLogIdi(card_t *card, ENTITY *e, int request);
+
+/*------------------------------------------------------------------*/
+/* public functions to initialise cards for each type supported     */
+/*------------------------------------------------------------------*/
+
+int            DivasPriInit(card_t *card, dia_card_t *cfg);
+
+int            DivasBriInit(card_t *card, dia_card_t *cfg);
+int            Divas4BriInit(card_t *card, dia_card_t *cfg);
+void   DivasBriPatch(card_t *card);
+
+/*------------------------------------------------------------------*/
+/* public functions of log common code                              */
+/*------------------------------------------------------------------*/
+
+extern char    *DivasLogFifoRead(void);
+extern void    DivasLogFifoWrite(char *entry, int length);
+extern int             DivasLogFifoEmpty(void);
+extern int             DivasLogFifoFull(void);
+extern void    DivasLogAdd(void *buffer, int length);
+
+/*------------------------------------------------------------------*/
+/* public functions of misc. platform-specific code                    */
+/*------------------------------------------------------------------*/
+
+int            DivasDpcSchedule(void);
+void           DivasDoDpc(void *);
+void           DivasDoRequestDpc(void *pData);
+int            DivasScheduleRequestDpc(void);
+
+/* table of IDI request functions */
+
+extern
+IDI_CALL       DivasIdiRequest[];
+
+/*
+ * intialisation entry point
+ */
+
+int            DivasInit(void);
+
+/*
+ * Get information on the number and type of cards present
+ */
+
+extern
+int    DivasCardsDiscover(void);
+
+/*
+ * initialise a new card
+ */
+
+int            DivasCardNew(dia_card_t *card);
+
+/*
+ * configure specified card
+ */
+
+int            DivasCardConfig(dia_config_t *config);
+
+/*
+ * load specified binary code onto card
+ */
+
+int            DivasCardLoad(dia_load_t *load);
+
+/*
+ * start specified card running
+ */
+
+int            DivasCardStart(int card_id);
+
+/*
+ * ISR for card
+ * Returns 0 if specified card was interrupting
+ */
+
+int            DivasIsr(void *arg);
+
+/*
+ * Get number of active cards
+ */
+
+int            DivasGetNum(void);
+
+/*
+ * Get list of active cards
+ */
+
+int            DivasGetList(dia_card_list_t *card_list);
+
+/* definitions common to several card types */
+
+#define DIVAS_SHARED_OFFSET     (0x1000)
+
+#endif /* ADAPTER_H */
diff --git a/drivers/isdn/eicon/bri.c b/drivers/isdn/eicon/bri.c
new file mode 100644 (file)
index 0000000..5a8afc1
--- /dev/null
@@ -0,0 +1,717 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.8  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <sys/types.h>
+
+#include "sys.h"
+#include "idi.h"
+#include "divas.h"
+#include "pc.h"
+#include "pr_pc.h"
+#include "dsp_defs.h"
+
+#include "adapter.h"
+#include "uxio.h"
+
+#define PCI_COMMAND    0x04
+#define PCI_STATUS     0x06
+#define PCI_LATENCY    0x0D
+#define PCI_BADDR0     0x10
+#define PCI_BADDR1     0x14
+#define PCI_BADDR2     0x18
+
+#define DIVAS_SIGNATURE 0x4447
+
+/* offset to start of MAINT area (used by xlog) */
+
+#define        DIVAS_MAINT_OFFSET      0xff00          /* value for BRI card */
+
+#define PROTCAP_TELINDUS       0x1
+#define PROTCAP_V90D           0x8
+
+word GetProtFeatureValue(char *sw_id);
+byte io_in(ADAPTER *a, void *adr);
+word io_inw(ADAPTER *a, void *adr);
+void io_in_buffer(ADAPTER *a, void *adr, void *P, word length);
+void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
+void io_out(ADAPTER *a, void *adr, byte data);
+void io_outw(ADAPTER *a, void *adr, word data);
+void io_out_buffer(ADAPTER *a, void *adr, void *P, word length);
+void io_inc(ADAPTER *a, void *adr);
+
+static int diva_server_bri_test_int(card_t *card);
+
+#define PLX_IOBASE             0
+#define        DIVAS_IOBASE    1
+
+#define        REG_DATA                0x00
+#define        REG_ADDRLO              0x04
+#define REG_ADDRHI             0x0C
+#define REG_IOCTRL             0x10
+
+#define M_PCI_RESET    0x10
+
+byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
+word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
+void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
+void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
+
+int DivasBRIInitPCI(card_t *card, dia_card_t *cfg);
+int bri_ISR (card_t* card);
+
+static
+int    diva_server_bri_reset(card_t *card)
+{
+       byte *DivasIOBase;
+       word i;
+       dword dwWait;
+
+       UxCardLog(0);
+
+       DPRINTF(("divas: resetting BRI adapter"));
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0);
+
+       for (i=0; i < 50000; i++)
+               ;
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0);
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0);
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA  , 0);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x0000);
+
+       for (i=0; i<0x8000; i++)
+       {
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
+       }
+
+       for (dwWait=0; dwWait < 0x00FFFFFF; dwWait++)
+               ;
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return 0;
+}
+
+static
+void diva_server_bri_reset_int(card_t *card)
+{
+       byte *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return;
+}
+
+static
+int diva_server_bri_start(card_t *card, byte *channels)
+{
+       byte *DivasIOBase, *PLXIOBase;
+       word wSig = 0;
+       word i;
+       dword dwSerialNum;
+       byte bPLX9060 = FALSE;
+
+       DPRINTF(("divas: starting Diva Server BRI card"));
+
+       card->is_live = FALSE;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA  , 0);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA  , 0);
+       
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
+
+       /* wait for signature to indicate card has started */
+       for (i = 0; i < 300; i++)
+       {
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
+               wSig = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
+
+               if (wSig == DIVAS_SIGNATURE)
+               {
+                       DPRINTF(("divas: card started after %d ms", i * 10));
+                       break;
+               }
+               UxPause(10);
+       }
+
+       if (wSig != DIVAS_SIGNATURE)
+       {
+               DPRINTF(("divas: card failed to start (Sig=0x%x)", wSig));
+               UxCardMemDetach(card->hw, DivasIOBase);
+               return -1;
+       }
+
+       card->is_live = TRUE;
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x3F6);
+       *channels = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
+
+       bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) | UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
+
+       if (bPLX9060)
+       { 
+               dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x1E) << 16) | 
+                                       (UxCardPortIoInW(card->hw, PLXIOBase, 0x22));
+               DPRINTF(("divas: PLX9060 in use. Serial number 0x%04X", dwSerialNum));
+       }
+       else
+       {
+               dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x22) << 16) | 
+                                       (UxCardPortIoInW(card->hw, PLXIOBase, 0x26));
+               DPRINTF(("divas: PLX9050 in use. Serial number 0x%04X", dwSerialNum));
+       }
+
+       UxCardMemDetach(card->hw, PLXIOBase);
+
+       card->serial_no = dwSerialNum;
+
+       diva_server_bri_test_int(card);
+       
+       return 0;
+}
+
+static
+int diva_server_bri_load(card_t *card, dia_load_t *load)
+{
+       byte *DivasIOBase;
+       dword r3000_base;
+       dword dwAddr, dwLength, i;
+       word wTest, aWord;
+
+       DPRINTF(("divas: loading Diva Server BRI card"));
+
+       switch (load->code_type)
+       {
+               case DIA_CPU_CODE:
+               DPRINTF(("divas: loading RISC %s", &load->code[0x80]));
+
+               card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
+               DPRINTF(("divas: features 0x%x", card->hw->features));
+               if (card->hw->features == 0xFFFF)
+               {
+                       DPRINTF(("divas: invalid feature string failed load\n"));
+                       return -1;
+               }
+
+               r3000_base = 0;
+               break;
+
+               case DIA_DSP_CODE:
+               DPRINTF(("divas: DSP code \"%s\"", load->code));
+
+               if ((card->hw->features) && (!(card->hw->features & PROTCAP_TELINDUS)))
+               {
+                       DPRINTF(("divas: only Telindus style binaries supported"));
+                       return -1;
+               }
+
+               if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+               {
+                       DPRINTF(("divas: V.90 DSP binary"));
+                       r3000_base = (0xBF790000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
+               }
+               else
+               {
+                       DPRINTF(("divas: non-V.90 DSP binary"));
+                       r3000_base = (0xBF7A0000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
+               }
+               DPRINTF(("divas: loading at 0x%x", r3000_base));
+               break;
+
+               case DIA_TABLE_CODE:
+               DPRINTF(("divas: TABLE code"));
+               if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+               {
+                       r3000_base = 0xBF790000 + sizeof(dword);
+               }
+               else
+               {
+                       r3000_base = 0xBF7A0000 + sizeof(dword);
+               }
+
+               break;
+
+               case DIA_DLOAD_CNT:
+               DPRINTF(("divas: COUNT code"));
+               if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+               {
+                       r3000_base = 0xBF790000;
+               }
+               else
+               {
+                       r3000_base = 0xBF7A0000;
+               }
+               break;
+
+               default:
+               DPRINTF(("divas: unknown code type %d", load->code_type));
+               return -1;
+               break;
+       }
+
+       DPRINTF(("divas: Writing %d bytes to adapter, address 0x%x", load->length, r3000_base));
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       DPRINTF(("divas: Attached to 0x%04X", DivasIOBase));
+
+       dwLength = load->length;
+
+       for (i=0; i < dwLength; i++)
+       {
+               dwAddr = r3000_base + i;
+
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
+
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, load->code[i]);
+       }
+
+       DPRINTF(("divas: Verifying"));
+
+       for (i=0; i<dwLength; i++)
+       {
+               dwAddr = r3000_base + i;
+
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
+
+               wTest = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
+
+               aWord = load->code[i];
+
+               if (wTest != aWord)
+               {
+                       DPRINTF(("divas: load verify failed on byte %d", i));
+                       DPRINTF(("divas: RAM 0x%x   File 0x%x",wTest,aWord));
+                       
+                       UxCardMemDetach(card->hw, DivasIOBase);
+
+                       return -1;
+               }
+       }
+
+       DPRINTF(("divas: Loaded and verified. Detaching from adapter"));
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       UxCardLog(0);
+
+       return 0;
+}
+
+static
+int diva_server_bri_config(card_t *card, dia_config_t *config)
+{
+       byte *DivasIOBase, i;
+
+       DPRINTF(("divas: configuring Diva Server BRI card"));
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 8);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->tei);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 9);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->nt2);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 10);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 11);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->watchdog);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 12);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->permanent);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 13);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 14);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->stable_l2);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 15);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->no_order_check);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 16);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 17);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 18);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->low_channel);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 19);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->prot_version);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 20);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->crc4);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 21);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
+
+       if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+       {
+               DPRINTF(("divas: Signifying V.90"));
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 4);
+       }
+       else
+       {
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
+       }
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 23);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, card->serial_no & 0xFF);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 24);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 8) & 0xFF);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 25);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 16) & 0xFF);
+
+       UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 26);
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 21);
+
+       for (i=0; i<32; i++)
+       {
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 32+i);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].oad[i]);
+
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 64+i);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].osa[i]);
+
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 96+i);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].spid[i]);
+
+
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 128+i);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].oad[i]);
+
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 160+i);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].osa[i]);
+
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 192+i);
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].spid[i]);
+       }
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return 0;
+}
+
+void DivasBriPatch(card_t *card)
+{
+       dword   PLXIOBase = 0;
+       dword   DivasIOBase = 0;
+
+       PLXIOBase = card->cfg.reset_base;
+       DivasIOBase = card->cfg.io_base;
+
+       if(card->hw == NULL)
+       {
+               DPRINTF(("Divas: BRI PATCH (PLX chip) card->hw is null"));
+               return;
+       }
+
+       if (PLXIOBase == 0)
+       {
+               DPRINTF(("Divas: BRI (PLX chip) cannot be patched. The BRI adapter may"));
+               DPRINTF(("Divas:   not function properly. If you do encounter problems,"));
+               DPRINTF(("Divas:   ensure that your machine is using the latest BIOS."));
+               return;
+       }
+
+       DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
+       DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
+
+       if (PLXIOBase & 0x80)
+       {
+               dword dwSize, dwSerialNum, dwCmd;
+               boolean_t bPLX9060;
+               word wSerHi, wSerLo;
+
+               DPRINTF(("Divas: Patch required"));
+               dwCmd = 0;
+               UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
+
+               PLXIOBase &= ~0x80;
+               UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &PLXIOBase);
+
+               dwSize = 0xFFFFFFFF;
+               UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &dwSize);
+               UxPciConfigRead(card->hw, 4, PCI_BADDR1, &dwSize);
+               
+               dwSize = (~ (dwSize & ~7)) + 1;
+
+               DivasIOBase = PLXIOBase + dwSize;
+
+               card->cfg.reset_base = PLXIOBase;
+               card->cfg.io_base = DivasIOBase;
+               UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &card->cfg.reset_base);
+               UxPciConfigWrite(card->hw, 4, PCI_BADDR2, &card->cfg.io_base);
+
+               dwCmd = 5;
+               UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
+
+               bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) | 
+                          UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
+
+               if (bPLX9060)
+               {
+                       wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
+                       wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
+                       dwSerialNum = (wSerHi << 16) | wSerLo;
+                       UxCardLog(0);
+               }
+               else
+               {
+                       wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
+                       wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
+                       dwSerialNum = (wSerHi << 16) | wSerLo;
+                       UxCardLog(0);
+               }
+       }
+       else
+       {
+               word wSerHi, wSerLo;
+               boolean_t bPLX9060;
+               dword dwSerialNum;
+
+               DPRINTF(("divas: No patch required"));
+
+               bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) | 
+                          UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
+
+               if (bPLX9060)
+               {
+                       wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
+                       wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
+                       dwSerialNum = (wSerHi << 16) | wSerLo;
+               }
+               else
+               {
+                       wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
+                       wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
+                       dwSerialNum = (wSerHi << 16) | wSerLo;
+               }
+       }
+       DPRINTF(("Divas: After patching:"));
+       DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
+       DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
+
+}
+
+#define TEST_INT_DIVAS_BRI     0x12
+static
+int    diva_server_bri_test_int(card_t *card)
+{
+       boolean_t bPLX9060 = FALSE;
+       byte *PLXIOBase = NULL, *DivasIOBase = NULL;
+
+       DPRINTF(("divas: test interrupt for Diva Server BRI card"));
+
+       PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
+
+       bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) || UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
+
+       if (bPLX9060)
+       { /* PLX9060 */
+               UxCardPortIoOut(card->hw, PLXIOBase, 0x69, 0x09);
+       }
+       else
+       { /* PLX9050 */
+               UxCardPortIoOut(card->hw, PLXIOBase, 0x4C, 0x41);
+       }
+
+       card->test_int_pend = TEST_INT_DIVAS_BRI;
+
+       UxCardMemDetach(card->hw, PLXIOBase);
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x89);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+       
+       return 0;
+}
+
+static
+int diva_server_bri_mem_get(card_t *card, mem_block_t *mem_block)
+{
+       dword user_addr = mem_block->addr;
+       word    length = 0;
+       dword   addr;
+       word    i;
+       byte *DivasIOBase;
+
+       DPRINTF(("divas: Retrieving memory from 0x%x", user_addr));
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       addr = user_addr;
+
+       for (i=0; i < (16 * 8); i++)
+       {
+               addr = user_addr + i;
+
+               UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, addr >> 16);
+               UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, (word) addr);
+
+               mem_block->data[i] = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
+               length++;
+       }
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return length;
+}
+
+int DivasBriInit(card_t *card, dia_card_t *cfg)
+{
+       DPRINTF(("divas: initialise Diva Server BRI card"));
+
+       if (DivasBRIInitPCI(card, cfg) == -1)
+       {
+               return -1;
+       }
+
+       card->card_reset                = diva_server_bri_reset;
+       card->card_start                = diva_server_bri_start;
+       card->card_load                 = diva_server_bri_load;
+       card->card_config               = diva_server_bri_config;
+       card->reset_int                 = diva_server_bri_reset_int;
+       card->card_mem_get              = diva_server_bri_mem_get;
+
+       card->xlog_offset               = DIVAS_MAINT_OFFSET;
+
+       card->out                       = DivasOut;
+       card->test_int                  = DivasTestInt;
+       card->dpc                       = DivasDpc;
+       card->clear_int                 = DivasClearInt;
+       card->card_isr                  = bri_ISR;
+
+       card->a.ram_out                 = io_out;
+       card->a.ram_outw                = io_outw;
+       card->a.ram_out_buffer  = io_out_buffer;
+       card->a.ram_inc                 = io_inc;
+
+       card->a.ram_in                  = io_in;
+       card->a.ram_inw                 = io_inw;
+       card->a.ram_in_buffer   = io_in_buffer;
+       card->a.ram_look_ahead  = io_look_ahead;
+
+       return 0;
+}
+
+word GetProtFeatureValue(char *sw_id)
+{
+       word features = 0;
+
+       while ((*sw_id) && (sw_id[0] != '['))
+               sw_id++;
+
+       if (sw_id == NULL)
+       {
+               DPRINTF(("divas: no feature string present"));
+               features = -1;
+       }
+       else
+       {
+               byte i, shifter;
+
+               sw_id += 3;
+
+               for (i=0, shifter=12; i<4; i++, shifter-=4)
+               {
+                       if ((sw_id[i] >= '0') && (sw_id[i] <= '9'))
+                       {
+                               features |= (sw_id[i] - '0') << shifter;
+                       }
+                       else if ((sw_id[i] >= 'a') && (sw_id[i] <= 'f'))
+                       {
+                               features |= (sw_id[i] - 'a' + 10) << shifter;
+                       }
+                       else if ((sw_id[i] >= 'A') && (sw_id[i] <= 'F'))
+                       {
+                               features |= (sw_id[i] - 'A' + 10) << shifter;
+                       }
+                       else
+                       {
+                               DPRINTF(("divas: invalid feature string"));
+                               return -1;
+                       }
+               }
+       }
+
+       return features;
+}
+
+
+int bri_ISR (card_t* card) 
+{
+       int served = 0;
+       byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01) 
+       {
+               served = 1;
+               card->int_pend  += 1;
+               DivasDpcSchedule(); /* ISR DPC */
+               UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
+       }
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return (served != 0);
+}
+
+
diff --git a/drivers/isdn/eicon/common.c b/drivers/isdn/eicon/common.c
new file mode 100644 (file)
index 0000000..4a4f77d
--- /dev/null
@@ -0,0 +1,896 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.15  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include "sys.h"
+#include "idi.h"
+#include "constant.h"
+#include "divas.h"
+#include "pc.h"
+#include "pr_pc.h"
+
+#include "uxio.h"
+#include <sys/types.h>
+
+#define MAX_ADDR_LEN
+
+#define DIVAS_LOAD_CMD         0x02
+#define DIVAS_START_CMD                0x03
+#define DIVAS_IRQ_RESET                0xC18
+#define DIVAS_IRQ_RESET_VAL    0xFE
+
+#define        PCI_COMMAND     0x04
+#define        PCI_STATUS      0x06
+#define        PCI_LATENCY     0x0D
+#define PCI_INTERRUPT  0x3C
+
+#define TEST_INT_DIVAS         0x11
+#define TEST_INT_DIVAS_BRI     0x12
+#define TEST_INT_DIVAS_Q       0x13
+
+#define DIVAS_RESET    0x81
+#define DIVAS_LED1     0x04
+#define DIVAS_LED2     0x08
+#define DIVAS_LED3     0x20
+#define DIVAS_LED4     0x40
+
+#define DIVAS_SIGNATURE 0x4447
+
+#define MP_PROTOCOL_ADDR 0xA0011000
+
+#define PLX_IOBASE     0
+#define        DIVAS_IOBASE    1
+
+typedef struct {
+               dword cmd;
+               dword addr;
+               dword len;
+               dword err;
+               dword live;
+               dword reserved[(0x1020>>2)-6];
+               dword signature;
+               byte  data[1];
+} diva_server_boot_t;
+
+int            DivasCardNext;
+card_t DivasCards[MAX_CARDS];
+
+dia_config_t *DivasConfig(card_t *, dia_config_t *);
+
+static
+DESCRIPTOR DIDD_Table[16];
+static
+int DIDD_Length = 0;
+
+void    EtdM_DIDD_Read( DESCRIPTOR *table, int *tablelength )
+{
+       int table_size = sizeof(DIDD_Table);
+
+    bcopy((caddr_t)DIDD_Table, (caddr_t)table, table_size);
+
+       *tablelength = DIDD_Length;
+
+       return;
+}
+
+static
+void   EtdM_DIDD_Write(DESCRIPTOR *table, int tablelength)
+{
+       int table_size = sizeof(DIDD_Table);
+
+       bcopy((caddr_t)table, (caddr_t)DIDD_Table, table_size);
+
+       DIDD_Length = tablelength;      
+
+       return;
+}
+
+static
+void    init_idi_tab(void)
+{
+    int length = 0;
+
+    DESCRIPTOR d[16];
+
+    EtdM_DIDD_Read(d, &length);
+
+    d[length].type = IDI_DIMAINT;  /* identify the DIMAINT entry */
+    d[length].channels = 0; /* zero channels associated with dimaint*/
+    d[length].features = 0; /* no features associated with dimaint */
+    d[length].request = (IDI_CALL) DivasPrintf;
+    length++;
+    
+    EtdM_DIDD_Write(d, length);
+
+    return;
+}
+
+/*
+ * I/O routines for memory mapped cards
+ */
+
+byte mem_in(ADAPTER *a, void *adr)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+       byte                    value;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       value = UxCardMemIn(card->hw, m);
+
+       UxCardMemDetach(card->hw, b);
+
+       return value;
+}
+
+word mem_inw(ADAPTER *a, void *adr)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+       word                    value;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       value = UxCardMemInW(card->hw, m);
+
+       UxCardMemDetach(card->hw, b);
+
+       return value;
+}
+
+void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       UxCardMemInBuffer(card->hw, m, P, length);
+
+       UxCardMemDetach(card->hw, b);
+
+       return;
+}
+
+void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (dword) &RBuffer->length;
+       card->RBuffer.length = UxCardMemInW(card->hw, m);
+
+       m = b;
+       m += (dword) &RBuffer->P;
+       UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
+
+       e->RBuffer = (DBUFFER *) &card->RBuffer;
+
+       UxCardMemDetach(card->hw, b);
+
+       return;
+}
+
+void mem_out(ADAPTER *a, void *adr, byte data)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       UxCardMemOut(card->hw, m, data);
+
+       UxCardMemDetach(card->hw, b);
+
+       return;
+}
+
+void mem_outw(ADAPTER *a, void *adr, word data)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       UxCardMemOutW(card->hw, m, data);
+
+       UxCardMemDetach(card->hw, b);
+
+       return;
+}
+
+void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
+{
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       UxCardMemOutBuffer(card->hw, m, P, length);
+
+       UxCardMemDetach(card->hw, b);
+
+       return;
+}
+
+void mem_inc(ADAPTER *a, void *adr)
+{
+       word                    value;
+       card_t                  *card = a->io;
+       unsigned char   *b, *m;
+
+       m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       m += (unsigned int) adr;
+
+       value = UxCardMemInW(card->hw, m);
+       value++;
+       UxCardMemOutW(card->hw, m, value);
+
+       UxCardMemDetach(card->hw, b);
+
+       return;
+}
+
+/*
+ * I/O routines for I/O mapped cards
+ */
+
+byte io_in(ADAPTER *a, void *adr)
+{
+       card_t              *card = a->io;
+       byte                value;
+       byte    *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       value = UxCardIoIn(card->hw, DivasIOBase, adr);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+    return value;
+}
+
+word io_inw(ADAPTER *a, void *adr)
+{
+       card_t          *card = a->io;
+       word            value;
+       byte    *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       value = UxCardIoInW(card->hw, DivasIOBase, adr);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return value;
+}
+
+void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
+{
+       card_t *card = a->io;
+       byte *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+    return;
+}
+
+void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
+{
+       card_t *card = a->io;
+       byte *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
+
+       UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       e->RBuffer = (DBUFFER *) &card->RBuffer;
+
+    return;
+}
+
+void io_out(ADAPTER *a, void *adr, byte data)
+{
+       card_t          *card = a->io;
+       byte    *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardIoOut(card->hw, DivasIOBase, adr, data);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+    return;
+}
+
+void io_outw(ADAPTER *a, void *adr, word data)
+{
+       card_t          *card = a->io;
+       byte    *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardIoOutW(card->hw, DivasIOBase, adr, data);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+    return;
+}
+
+void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
+{
+       card_t          *card = a->io;
+       byte *DivasIOBase = NULL;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+    return;
+}
+
+void io_inc(ADAPTER *a, void *adr)
+{
+       word            value;
+       card_t          *card = a->io;
+       byte *DivasIOBase;
+
+       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+
+       value = UxCardIoInW(card->hw, DivasIOBase, adr);
+       
+       value++;
+
+       UxCardIoOutW(card->hw, DivasIOBase, adr, value);
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+    return;
+}
+
+static
+void test_int(card_t *card)
+
+{
+       byte *shared, *DivasIOBase;
+
+       switch (card->test_int_pend)
+       {
+               case TEST_INT_DIVAS:
+                       DPRINTF(("divas: test interrupt pending"));
+                       shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+                       if (UxCardMemIn(card->hw, &shared[0x3FE]))
+                       {
+                               UxCardMemOut(card->hw, 
+                                                               &(((struct pr_ram *)shared)->RcOutput), 0);
+                               UxCardMemDetach(card->hw, shared);
+               (*card->reset_int)(card);
+                               shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+                               UxCardMemOut(card->hw, &shared[0x3FE], 0);
+                               DPRINTF(("divas: test interrupt cleared"));
+                       }
+
+                       UxCardMemDetach(card->hw, shared);
+
+                       card->test_int_pend = 0;
+                       break;
+
+               case TEST_INT_DIVAS_BRI:
+                       DPRINTF(("divas: BRI test interrupt pending"));
+                       (*card->reset_int)(card);
+                       DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+                       UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
+                       UxCardMemDetach(card->hw, DivasIOBase);
+                       DPRINTF(("divas: test interrupt cleared"));
+                       card->test_int_pend = 0;
+                       break;
+
+               case TEST_INT_DIVAS_Q:
+                       DPRINTF(("divas: 4BRI test interrupt pending"));
+                       (*card->reset_int)(card);
+                       card->test_int_pend = 0;
+                       break;
+
+               default:
+                       DPRINTF(("divas: unknown test interrupt pending"));
+                       return;
+       }
+       return;
+}
+
+void card_isr (void *dev_id)
+{
+       card_t *card = (card_t *) dev_id;
+       ADAPTER *a = &card->a;
+       int ipl;
+
+       if (card->test_int_pend)
+       {
+               ipl = UxCardLock(card->hw);
+               card->int_pend=0;
+               test_int(card);
+               UxCardUnlock(card->hw,ipl);
+               return;
+       }
+       
+       if(card->card_isr)
+       {
+               (*(card->card_isr))(card);
+       }
+       else
+       {
+               ipl = UxCardLock(card->hw);
+       
+               if ((card->test_int)(a))
+               {
+                       (card->reset_int)(card);
+               }
+               
+               UxCardUnlock(card->hw,ipl);
+               
+       }
+
+}
+
+int DivasCardNew(dia_card_t *card_info)
+{
+       card_t *card;
+       byte b;
+       static boolean_t first_call = TRUE;
+       boolean_t NeedISRandReset = FALSE;
+
+       DPRINTF(("divas: new card "));
+
+       if (first_call)
+       {
+               first_call = FALSE;
+               init_idi_tab();
+       }
+
+       DivasConfigGet(card_info);
+       
+       if (DivasCardNext == DIM(DivasCards))
+       {
+               KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
+               return -1;
+       }
+
+       card = &DivasCards[DivasCardNext];
+
+       card->state = DIA_UNKNOWN;
+
+       card->cfg = *card_info;
+
+       card->a.io = card;
+
+       if (UxCardHandleGet(&card->hw, card_info))
+       {
+               KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
+               return -1;
+       }
+
+       if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
+       {
+               DivasBriPatch(card);
+               card_info->io_base = card->cfg.io_base;
+       }
+
+       switch (card_info->card_type)
+       {
+               case DIA_CARD_TYPE_DIVA_SERVER:
+                       if (DivasPriInit(card, card_info))
+                       {
+                               return -1;
+                       }
+                       NeedISRandReset = TRUE;
+                       break;
+
+               case DIA_CARD_TYPE_DIVA_SERVER_B:
+                       if (DivasBriInit(card, card_info))
+                       {
+                               return -1;
+                       }
+                       NeedISRandReset = TRUE;
+                       break;
+
+               case DIA_CARD_TYPE_DIVA_SERVER_Q:
+                       if (Divas4BriInit(card, card_info))
+                       {
+                               return -1;
+                       }
+
+                       if (card_info->name[6] == '0')
+                       {
+                               NeedISRandReset = TRUE;
+                       }
+                       else // Need to set paramater for ISR anyway
+                       {
+                               card->hw->user_isr_arg = card;
+                               card->hw->user_isr = card_isr;
+                       }
+                       break;   
+
+               default:
+                       KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
+                       return -1;
+       }
+
+       if (NeedISRandReset)
+       {
+               if (UxIsrInstall(card->hw, card_isr, card))
+               {
+                       KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
+                       UxCardHandleFree(card->hw);
+                       return -1;
+               }
+
+               b = card->cfg.irq;
+
+               UxPciConfigWrite(card->hw, sizeof(b), PCI_INTERRUPT, &b);
+
+               if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
+               {
+                       if ((*card->card_reset)(card))
+                       {
+                               KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
+                               return -1;
+                       }
+                       card->state = DIA_RESET;
+               }
+
+               NeedISRandReset = FALSE;
+       }
+
+       DivasCardNext++;
+
+       return 0;
+}
+
+void   *get_card(int card_id)
+{
+       int i;
+
+       for (i=0; i < DivasCardNext; i++)
+       {
+               if (DivasCards[i].cfg.card_id == card_id)
+               {
+                       return(&DivasCards[i]);
+               }
+       }
+
+       DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
+
+       return NULL;
+}
+
+int DivasCardConfig(dia_config_t *config)
+{
+       card_t *card;
+       int status;
+
+       DPRINTF(("divas: configuring card"));
+
+       card = get_card(config->card_id);
+       if (!card)
+       {
+               return -1;
+       }
+
+       config = DivasConfig(card, config);
+
+       status = (*card->card_config)(card, config);
+
+       if (!status)
+       {
+               card->state = DIA_CONFIGURED;
+       }
+       return status;
+}
+
+int DivasCardLoad(dia_load_t *load)
+{
+       card_t *card;
+       int     status;
+
+       card = get_card(load->card_id);
+       if (!card)
+       {
+               return -1;
+       }
+
+       if (card->state == DIA_RUNNING)
+       {
+               (*card->card_reset)(card);
+       }
+
+       status = (*card->card_load)(card, load);
+       if (!status)
+       {
+               card->state = DIA_LOADED;
+       }
+       return status;
+}
+
+static int idi_register(card_t *card, byte channels)
+{
+    DESCRIPTOR d[16];
+    int length, num_entities;
+
+       DPRINTF(("divas: registering card with IDI"));
+
+       num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
+       card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
+
+       if (!card->e_tbl)
+       {
+               KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
+               return -1;
+       }
+
+       bzero(card->e_tbl, sizeof(E_INFO) * num_entities);
+       card->e_max = num_entities;
+
+    EtdM_DIDD_Read(d, &length);
+
+       if (length == DIM(d))
+       {
+               KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
+               return -1;
+       }
+
+       switch (card->cfg.card_type)
+       {
+               case DIA_CARD_TYPE_DIVA_SERVER:
+               d[length].type = IDI_ADAPTER_PR;
+               d[length].serial = card->serial_no;
+               break;
+
+               case DIA_CARD_TYPE_DIVA_SERVER_B:
+               d[length].type = IDI_ADAPTER_MAESTRA;
+               d[length].serial = card->serial_no;
+               break;
+
+               // 4BRI is treated as 4 BRI adapters
+               case DIA_CARD_TYPE_DIVA_SERVER_Q:
+               d[length].type = IDI_ADAPTER_MAESTRA;
+               d[length].serial = card->cfg.serial;
+       }
+
+       d[length].features = 0;
+       d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
+
+       if ( card->hw->features & PROTCAP_MANIF )
+       {
+               d[length].features |= DI_MANAGE ;
+       }
+       if ( card->hw->features & PROTCAP_V_42 )
+       {
+               d[length].features |= DI_V_42 ;
+       }
+       if ( card->hw->features & PROTCAP_EXTD_FAX )
+       {
+               d[length].features |= DI_EXTD_FAX ;
+       }
+
+       d[length].channels = channels;
+       d[length].request = DivasIdiRequest[card - DivasCards];
+
+       length++;
+
+       EtdM_DIDD_Write(d, length);
+
+    return 0;
+}
+
+int DivasCardStart(int card_id)
+{
+       card_t *card;
+       byte channels;
+       int status;
+
+       DPRINTF(("divas: starting card"));
+
+       card = get_card(card_id);
+       if (!card)
+       {
+               return -1;
+       }
+
+       status = (*card->card_start)(card, &channels);
+       if (status)
+       {
+               return status;
+       }
+
+       /* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
+       if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
+       {
+               int i;
+               card_t *FourBRISlave;
+
+               for (i=3; i >= 0; i--)
+               {
+                       FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
+                       if (FourBRISlave)
+                       {
+                               idi_register(FourBRISlave, 2);
+                               FourBRISlave->state = DIA_RUNNING;
+                       }
+               }
+               card->serial_no = card->cfg.serial;
+
+               DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels", 
+                               card_id - 3, card->serial_no, (int) channels));
+       }
+       else
+       {
+               status = idi_register(card, channels);
+               if (!status)
+               {
+                       card->state = DIA_RUNNING;
+                       DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels", 
+                                               card_id, card->serial_no, (int) channels));
+               }
+       }
+
+       return status;
+}
+
+int DivasGetMem(mem_block_t *mem_block)
+{
+       card_t *card;
+       word    card_id = mem_block->card_id;
+
+       card = get_card(card_id);
+       if (!card)
+       {
+               return 0;
+       }
+
+       return (*card->card_mem_get)(card, mem_block);
+}
+
+
+/*
+ * Deleyed Procedure Call for handling interrupts from card
+ */
+
+void   DivaDoCardDpc(card_t *card)
+{
+       ADAPTER *a;
+
+       a = &card->a;
+
+       if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1)
+       {
+               return;
+       }
+
+       do{
+               if((*(card->test_int))(a))
+               {
+                       (*(card->dpc))(a);
+                       (*(card->clear_int))(a);
+               }
+                       (*(card->out))(a);
+       }while(UxInterlockedDecrement(card->hw, &card->dpc_reentered));
+                       
+}
+
+void   DivasDoDpc(void *pData)
+{
+       card_t  *card = DivasCards;
+       int     i = DivasCardNext;
+       
+       while(i--)
+       {
+               DivaDoCardDpc(card++);
+       }
+}
+
+void   DivasDoRequestDpc(void *pData)
+{
+       DivasDoDpc(pData);
+}
+
+/*
+ * DivasGetNum
+ * Returns the number of active adapters
+ */
+
+int DivasGetNum(void)
+{
+       return(DivasCardNext);
+}
+
+/*
+ * DivasGetList
+ * Returns a list of active adapters
+ */
+int DivasGetList(dia_card_list_t *card_list)
+{
+       int i;
+
+       bzero(card_list, sizeof(dia_card_list_t));
+
+       for(i = 0; i < DivasCardNext; i++)
+       {
+               card_list->card_type = DivasCards[i].cfg.card_type;
+               card_list->card_slot = DivasCards[i].cfg.slot;
+               card_list->state     = DivasCards[i].state;
+               card_list++;
+       }
+
+       return 0;
+
+}
+
+/*
+ * control logging for specified card
+ */
+
+void   DivasLog(dia_log_t *log)
+{
+       card_t *card;
+
+       card = get_card(log->card_id);
+       if (!card)
+       {
+               return;
+       }
+
+       card->log_types = log->log_types;
+
+       return;
+}
+
diff --git a/drivers/isdn/eicon/constant.h b/drivers/isdn/eicon/constant.h
new file mode 100644 (file)
index 0000000..ea92f05
--- /dev/null
@@ -0,0 +1,179 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+
+/*------------------------------------------------------------------*/
+/* Q.931 information elements maximum length                        */
+/* excluding the identifier, including the length field             */
+/*------------------------------------------------------------------*/
+
+#define MAX_LEN_BC      13
+#define MAX_LEN_LLC     19 /* ctr3 */
+#define MAX_LEN_HLC     6  /* ctr3 */
+#define MAX_LEN_UUI     200 /* Hicom USBS req */
+#define MAX_LEN_NUM     24
+#define MAX_LEN_DSP     83 /* ctr3 */
+#define MAX_LEN_NI      4
+#define MAX_LEN_PI      5
+#define MAX_LEN_SIN     3
+#define MAX_LEN_CST     4
+#define MAX_LEN_SIG     2
+#define MAX_LEN_SPID    32
+#define MAX_LEN_EID     3
+#define MAX_LEN_CHI     35  /* ctr3 */
+#define MAX_LEN_CAU     33
+#define MAX_LEN_FTY     130
+#define MAX_LEN_KEY     83  /* ctr3 */
+#define MAX_LEN_RSI     4
+#define MAX_LEN_CAI     11
+#define MAX_NUM_SPID    4
+#define MAX_LEN_USERID  9
+#define MAX_LEN_APPLID  5
+#define MAX_LEN_NTTCIF  15
+
+/*------------------------------------------------------------------*/
+/* decision return values                                           */
+/*------------------------------------------------------------------*/
+
+#define YES             1
+#define NO              0
+
+
+/*-------------------------------------------------------------------*/
+/* w element coding                                                  */
+/*-------------------------------------------------------------------*/
+
+#define NTTCIF          0x01
+#define BC              0x04
+#define CAU             0x08
+#define CAD             0x0c
+#define CAI             0x10
+#define CST             0x14
+#define CHI             0x18
+#define LLI             0x19
+#define CHA             0x1a
+#define FTY             0x1c
+#define PI              0x1e
+#define NFAC            0x20
+#define TC              0x24
+#define ATT_EID         0x26
+#define NI              0x27
+#define DSP             0x28
+#define DT              0x29
+#define KEY             0x2c
+#define KP              0x2c
+#define UID             0x2d
+#define SIG             0x34
+#define FI              0x39
+#define SPID            0x3a
+#define EID             0x3b
+#define DSPF            0x3c
+#define ECAD            0x4c
+#define OAD             0x6c
+#define OSA             0x6d
+#define DAD             0x70
+#define CPN             0x70
+#define DSA             0x71
+#define RDX             0x73
+#define RAD             0x74
+#define RDN             0x74
+#define RSI             0x79
+#define SCR             0x7A   /* internal unscreened CPN          */
+#define MIE             0x7a   /* internal management info element */
+#define LLC             0x7c
+#define HLC             0x7d
+#define UUI             0x7e
+#define ESC             0x7f
+
+#define SHIFT           0x90
+#define MORE            0xa0
+#define CL              0xb0
+
+/* information elements used on the spid interface */
+#define SPID_CMD        0xc0
+#define SPID_LINK       0x10
+#define SPID_DN         0x70
+#define SPID_BC         0x04
+#define SPID_SWITCH     0x11
+
+/*------------------------------------------------------------------*/
+/* global configuration parameters, defined in exec.c               */
+/* these parameters are configured with program loading             */
+/*------------------------------------------------------------------*/
+
+#define PROT_1TR6       0
+#define PROT_ETSI       1
+#define PROT_FRANC      2
+#define PROT_BELG       3
+#define PROT_SWED       4
+#define PROT_NI         5
+#define PROT_5ESS       6
+#define PROT_JAPAN      7
+#define PROT_ATEL       8
+#define PROT_US         9
+#define PROT_ITALY      10
+#define PROT_TWAN       11
+#define PROT_AUSTRAL    12
+
+#define INIT_PROT_1TR6    0x80|PROT_1TR6
+#define INIT_PROT_ETSI    0x80|PROT_ETSI
+#define INIT_PROT_FRANC   0x80|PROT_FRANC
+#define INIT_PROT_BELG    0x80|PROT_BELG
+#define INIT_PROT_SWED    0x80|PROT_SWED
+#define INIT_PROT_NI      0x80|PROT_NI
+#define INIT_PROT_5ESS    0x80|PROT_5ESS
+#define INIT_PROT_JAPAN   0x80|PROT_JAPAN
+#define INIT_PROT_ATEL    0x80|PROT_ATEL
+#define INIT_PROT_ITALY   0x80|PROT_ITALY
+#define INIT_PROT_TWAN    0x80|PROT_TWAN
+#define INIT_PROT_AUSTRAL 0x80|PROT_AUSTRAL
+
+
+/* -----------------------------------------------------------**
+** The PROTOCOL_FEATURE_STRING in feature.h (included         **
+** in prstart.sx and astart.sx) defines capabilities and      **
+** features of the actual protocol code. It's used as a bit   **
+** mask.                                                      **
+** The following Bits are defined:                            **
+** -----------------------------------------------------------*/
+                                           
+#define PROTCAP_TELINDUS  0x0001  /* Telindus Variant of protocol code   */
+#define PROTCAP_MANIF     0x0002  /* Management interface implemented    */
+#define PROTCAP_V_42      0x0004  /* V42 implemented                     */
+#define PROTCAP_V90D      0x0008  /* V.90D (implies up to 384k DSP code) */
+#define PROTCAP_EXTD_FAX  0x0010  /* Extended FAX (ECM, 2D, T6, Polling) */
+#define PROTCAP_FREE4     0x0020  /* not used                            */
+#define PROTCAP_FREE5     0x0040  /* not used                            */
+#define PROTCAP_FREE6     0x0080  /* not used                            */
+#define PROTCAP_FREE7     0x0100  /* not used                            */
+#define PROTCAP_FREE8     0x0200  /* not used                            */
+#define PROTCAP_FREE9     0x0400  /* not used                            */
+#define PROTCAP_FREE10    0x0800  /* not used                            */
+#define PROTCAP_FREE11    0x1000  /* not used                            */
+#define PROTCAP_FREE12    0x2000  /* not used                            */
+#define PROTCAP_FREE13    0x4000  /* not used                            */
+#define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
diff --git a/drivers/isdn/eicon/divalog.h b/drivers/isdn/eicon/divalog.h
new file mode 100644 (file)
index 0000000..93bd56a
--- /dev/null
@@ -0,0 +1,57 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/*
+ * Include file for defining the kernel loggger messages
+ * These definitions are shared between the klog driver and the
+ * klogd daemon process
+ */
+
+#if !defined(_KLOGMSG_H)
+#define _KLOGMSG_H
+
+/* define a type for a log entry */
+
+#define KLOG_TEXT_MSG          (0)
+#define KLOG_XLOG_MSG          (1)
+#define KLOG_XTXT_MSG          (2)
+#define KLOG_IDI_REQ                   (4)
+#define KLOG_IDI_CALLBACK   (5)
+#define KLOG_CAPI_MSG          (6)
+
+typedef struct
+{
+    unsigned long   time_stamp; /* in ms since last system boot */
+    int                        card;       /* card number (-1 for all) */
+    unsigned int    type;       /* type of log message (0 is text) */
+    unsigned int    length;     /* message length (non-text messages only) */
+    unsigned short  code;       /* message code (non-text messages only) */
+    char            buffer[110];/* text/data to log */
+} klog_t;
+
+void    DivasLogAdd(void *buffer, int length);
+#endif /* of _KLOGMSG_H */
diff --git a/drivers/isdn/eicon/divas.h b/drivers/isdn/eicon/divas.h
new file mode 100644 (file)
index 0000000..2fcd834
--- /dev/null
@@ -0,0 +1,232 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.5  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* External Diva Server driver include file */
+
+#if !defined(DIVAS_H)
+#define DIVAS_H
+
+#include "sys.h"
+
+
+/* IOCTL commands */
+
+#define        DIA_IOCTL_INIT                          (0)
+#define        DIA_IOCTL_LOAD                          (1)
+#define        DIA_IOCTL_CONFIG                        (2)
+#define        DIA_IOCTL_START                         (3)
+#define        DIA_IOCTL_GET_NUM                       (4)
+#define        DIA_IOCTL_GET_LIST                      (5)
+#define        DIA_IOCTL_LOG                           (6)
+#define        DIA_IOCTL_DETECT                        (7)
+#define        DIA_IOCTL_SPACE                         (8)
+#define DIA_IOCTL_GET_MEM           (9)
+#define DIA_IOCTL_FLAVOUR                      (10)
+#define        DIA_IOCTL_XLOG_REQ                      (11)
+
+/* Error codes */
+
+#define XLOG_ERR_CARD_NUM      (13)
+#define XLOG_ERR_DONE          (14)
+#define XLOG_ERR_CMD           (15)
+#define XLOG_ERR_TIMEOUT       (16)
+#define XLOG_ERR_CARD_STATE    (17)
+#define XLOG_ERR_UNKNOWN       (18)
+#define XLOG_OK                        (0)
+
+/* Adapter states */
+
+#define DIA_UNKNOWN            (0)
+#define DIA_RESET              (1)
+#define DIA_LOADED             (2)
+#define DIA_CONFIGURED (3)
+#define DIA_RUNNING            (4)
+
+/* Stucture for getting card specific information from active cad driver */
+
+typedef struct
+{
+       int card_type;
+       int card_slot;
+       int     state;
+} dia_card_list_t;
+
+/* use following to select which logging to have active */
+
+#define        DIVAS_LOG_DEBUG         (1 << 0)
+#define        DIVAS_LOG_XLOG          (1 << 1)
+#define        DIVAS_LOG_IDI           (1 << 2)
+#define        DIVAS_LOG_CAPI          (1 << 3)
+
+/* stucture for DIA_IOCTL_LOG to get information from adapter */
+
+typedef struct
+{
+       int             card_id;
+       int             log_types;      /* bit mask of log types: use DIVAS_LOG_XXX */
+} dia_log_t;
+
+/* list of cards supported by this driver */
+
+#define        DIA_CARD_TYPE_DIVA_SERVER       (0)     /* Diva Server PRI */
+#define        DIA_CARD_TYPE_DIVA_SERVER_B     (1)     /* Diva Server BRI */
+#define        DIA_CARD_TYPE_DIVA_SERVER_Q     (2)     /* Diva Server 4-BRI */
+
+/* bus types */
+
+#define        DIA_BUS_TYPE_ISA                (0)
+#define        DIA_BUS_TYPE_ISA_PNP    (1)
+#define        DIA_BUS_TYPE_PCI                (2)
+#define        DIA_BUS_TYPE_MCA                (3)
+
+/* types of memory used (index for memory array below) */
+
+#define DIVAS_RAM_MEMORY       0
+#define DIVAS_REG_MEMORY       1
+#define DIVAS_CFG_MEMORY       2
+#define DIVAS_SHARED_MEMORY 3
+#define DIVAS_CTL_MEMORY       4
+/*
+ * card config information
+ * passed as parameter to DIA_IOCTL_INIT ioctl to initialise new card
+ */
+
+typedef struct
+{
+       int             card_id;        /* unique id assigned to this card */
+       int             card_type;      /* use DIA_CARD_TYPE_xxx above */
+       int             bus_type;       /* use DIA_BUS_TYPE_xxx above */
+       int             bus_num;        /* bus number (instance number of bus type) */
+       int             func_num;       /* adapter function number (PCI register) */
+       int             slot;           /* slot number in bus */
+       unsigned char   irq;            /* IRQ number */
+    int     reset_base; /* Reset register  for I/O mapped cards */
+       int             io_base;        /* I/O base for I/O mapped cards */
+       void    *memory[5];     /* memory base addresses for memory mapped cards */
+       char    name[9];        /* name of adapter */
+       int             serial;         /* serial number */
+       unsigned char   int_priority;   /* Interrupt priority */
+} dia_card_t;
+
+/*
+ * protocol configuration information
+ * passed as parameter to DIA_IOCTL_CONFIG ioctl to configure card
+ */
+
+typedef struct
+{
+       int                             card_id;                        /* to identify particular card */
+       unsigned char   tei;
+       unsigned char   nt2;
+       unsigned char   watchdog;
+       unsigned char   permanent;
+       unsigned char   x_interface;
+       unsigned char   stable_l2;
+       unsigned char   no_order_check;
+       unsigned char   handset_type;
+       unsigned char   sig_flags;
+       unsigned char   low_channel;
+       unsigned char   prot_version;
+       unsigned char   crc4;
+       struct
+       {
+               unsigned char oad[32];
+               unsigned char osa[32];
+               unsigned char spid[32];
+       }terminal[2];
+} dia_config_t;
+
+/*
+ * code configuration 
+ * passed as parameter to DIA_IOCTL_LOAD ioctl
+ * one of these ioctl per code file to load
+ */
+
+typedef struct
+{
+       int                             card_id;        /* card to load */
+       enum
+       {
+               DIA_CPU_CODE,                   /* CPU code */
+               DIA_DSP_CODE,                   /* DSP code */
+               DIA_CONT_CODE,                  /* continuation of code */
+               DIA_TABLE_CODE,                 /* code table */
+               DIA_DLOAD_CNT,           /* number of downloads*/
+               DIA_FPGA_CODE
+       }                               code_type;      /* code for CPU or DSP ? */
+       int                             length;         /* length of code */
+       unsigned char   *code;          /* pointer (in user-space) to code */
+} dia_load_t;
+
+/*
+ * start configuration 
+ * passed as parameter to DIA_IOCTL_START ioctl
+ */
+
+typedef struct
+{
+       int                             card_id;        /* card to start */
+} dia_start_t;
+
+/* used for retrieving memory from the card */
+
+typedef struct {
+       word    card_id;
+       dword   addr;
+       byte    data[16 * 8];
+} mem_block_t;
+
+/* DIVA Server specific addresses */
+
+#define DIVAS_CPU_START_ADDR    (0x0)
+#define        ORG_MAX_PROTOCOL_CODE_SIZE      0x000A0000
+#define        ORG_MAX_DSP_CODE_SIZE           (0x000F0000 - ORG_MAX_PROTOCOL_CODE_SIZE)
+#define        ORG_DSP_CODE_BASE               (0xBF7F0000 - ORG_MAX_DSP_CODE_SIZE)
+#define DIVAS_DSP_START_ADDR    (0xBF7A0000)
+#define DIVAS_SHARED_OFFSET     (0x1000)
+#define MP_DSP_CODE_BASE           0xa03a0000
+#define MQ_PROTCODE_OFFSET  0x100000
+#define MQ_SM_OFFSET           0X0f0000
+
+#define        V90D_MAX_PROTOCOL_CODE_SIZE     0x00090000
+#define V90D_MAX_DSP_CODE_SIZE         (0x000F0000 - V90D_MAX_PROTOCOL_CODE_SIZE)
+#define        V90D_DSP_CODE_BASE              (0xBF7F0000 - V90D_MAX_DSP_CODE_SIZE)
+
+#define MQ_ORG_MAX_PROTOCOL_CODE_SIZE   0x000a0000  /* max 640K Protocol-Code */
+#define MQ_ORG_MAX_DSP_CODE_SIZE        0x00050000  /* max 320K DSP-Code */
+#define MQ_ORG_DSP_CODE_BASE           (MQ_MAX_DSP_DOWNLOAD_ADDR \
+                                      - MQ_ORG_MAX_DSP_CODE_SIZE)
+#define MQ_V90D_MAX_PROTOCOL_CODE_SIZE  0x00090000  /* max 576K Protocol-Code */
+#define MQ_V90D_MAX_DSP_CODE_SIZE       0x00060000  /* max 384K DSP-Code if V.90D included */
+#define        MQ_MAX_DSP_DOWNLOAD_ADDR        0xa03f0000
+#define MQ_V90D_DSP_CODE_BASE          (MQ_MAX_DSP_DOWNLOAD_ADDR \
+                                      - MQ_V90D_MAX_DSP_CODE_SIZE)
+
+
+#define ALIGNMENT_MASK_MAESTRA        0xfffffffc
+
+#endif /* DIVAS_H */
diff --git a/drivers/isdn/eicon/dsp_defs.h b/drivers/isdn/eicon/dsp_defs.h
new file mode 100644 (file)
index 0000000..ee7c142
--- /dev/null
@@ -0,0 +1,303 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef DSP_DEFS_H_
+#define DSP_DEFS_H_
+
+#ifndef DSPDIDS_H_
+#include "dspdids.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*---------------------------------------------------------------------------*/
+
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef TRUE
+#define TRUE (0 == 0)
+#endif
+#ifndef FALSE
+#define FALSE (0 != 0)
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+
+#define DSP_MEMORY_TYPE_EXTERNAL_DM         0
+#define DSP_MEMORY_TYPE_EXTERNAL_PM         1
+#define DSP_MEMORY_TYPE_INTERNAL_DM         2
+#define DSP_MEMORY_TYPE_INTERNAL_PM         3
+
+#define DSP_DOWNLOAD_FLAG_BOOTABLE          0x0001
+#define DSP_DOWNLOAD_FLAG_2181              0x0002
+#define DSP_DOWNLOAD_FLAG_TIMECRITICAL      0x0004
+#define DSP_DOWNLOAD_FLAG_COMPAND           0x0008
+
+#define DSP_MEMORY_BLOCK_COUNT              16
+
+#define DSP_SEGMENT_PM_FLAG                 0x0001
+#define DSP_SEGMENT_SHARED_FLAG             0x0002
+
+#define DSP_SEGMENT_EXTERNAL_DM             DSP_MEMORY_TYPE_EXTERNAL_DM
+#define DSP_SEGMENT_EXTERNAL_PM             DSP_MEMORY_TYPE_EXTERNAL_PM
+#define DSP_SEGMENT_INTERNAL_DM             DSP_MEMORY_TYPE_INTERNAL_DM
+#define DSP_SEGMENT_INTERNAL_PM             DSP_MEMORY_TYPE_INTERNAL_PM
+#define DSP_SEGMENT_FIRST_RELOCATABLE       4
+
+#define DSP_DATA_BLOCK_PM_FLAG              0x0001
+#define DSP_DATA_BLOCK_DWORD_FLAG           0x0002
+#define DSP_DATA_BLOCK_RESOLVE_FLAG         0x0004
+
+#define DSP_RELOC_NONE                      0x00
+#define DSP_RELOC_SEGMENT_MASK              0x3f
+#define DSP_RELOC_TYPE_MASK                 0xc0
+#define DSP_RELOC_TYPE_0                    0x00  /* relocation of address in DM word / high part of PM word */
+#define DSP_RELOC_TYPE_1                    0x40  /* relocation of address in low part of PM data word */
+#define DSP_RELOC_TYPE_2                    0x80  /* relocation of address in standard command */
+#define DSP_RELOC_TYPE_3                    0xc0  /* relocation of address in call/jump on flag in */
+
+#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
+#define DSP_COMBIFILE_FORMAT_VERSION_BCD    0x0100
+
+#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
+#define DSP_FILE_FORMAT_VERSION_BCD         0x0100
+
+
+typedef struct tag_dsp_combifile_header
+{
+  char                  format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE];
+  word                  format_version_bcd;
+  word                  header_size;
+  word                  combifile_description_size;
+  word                  directory_entries;
+  word                  directory_size;
+  word                  download_count;
+  word                  usage_mask_size;
+} t_dsp_combifile_header;
+
+typedef struct tag_dsp_combifile_directory_entry
+{
+  word                  card_type_number;
+  word                  file_set_number;
+} t_dsp_combifile_directory_entry;
+
+typedef struct tag_dsp_file_header
+{
+  char                  format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE];
+  word                  format_version_bcd;
+  word                  download_id;
+  word                  download_flags;
+  word                  required_processing_power;
+  word                  interface_channel_count;
+  word                  header_size;
+  word                  download_description_size;
+  word                  memory_block_table_size;
+  word                  memory_block_count;
+  word                  segment_table_size;
+  word                  segment_count;
+  word                  symbol_table_size;
+  word                  symbol_count;
+  word                  total_data_size_dm;
+  word                  data_block_count_dm;
+  word                  total_data_size_pm;
+  word                  data_block_count_pm;
+} t_dsp_file_header;
+
+typedef struct tag_dsp_memory_block_desc
+{
+  word                  alias_memory_block;
+  word                  memory_type;
+  word                  address;
+  word                  size;             /* DSP words */
+} t_dsp_memory_block_desc;
+
+typedef struct tag_dsp_segment_desc
+{
+  word                  memory_block;
+  word                  attributes;
+  word                  base;
+  word                  size;
+  word                  alignment;        /* ==0 -> no other legal start address than base */
+} t_dsp_segment_desc;
+
+typedef struct tag_dsp_symbol_desc
+{
+  word                  symbol_id;
+  word                  segment;
+  word                  offset;
+  word                  size;             /* DSP words */
+} t_dsp_symbol_desc;
+
+typedef struct tag_dsp_data_block_header
+{
+  word                  attributes;
+  word                  segment;
+  word                  offset;
+  word                  size;             /* DSP words */
+} t_dsp_data_block_header;
+
+typedef struct tag_dsp_download_desc      /* be sure to keep native alignment for MAESTRA's */
+{
+  word                  download_id;
+  word                  download_flags;
+  word                  required_processing_power;
+  word                  interface_channel_count;
+  word                  excess_header_size;
+  word                  memory_block_count;
+  word                  segment_count;
+  word                  symbol_count;
+  word                  data_block_count_dm;
+  word                  data_block_count_pm;
+  byte                 *p_excess_header_data;
+  char                                         *p_download_description;
+  t_dsp_memory_block_desc *p_memory_block_table;
+  t_dsp_segment_desc   *p_segment_table;
+  t_dsp_symbol_desc    *p_symbol_table;
+  word                                         *p_data_blocks_dm;
+  word                                         *p_data_blocks_pm;
+} t_dsp_download_desc;
+
+#define DSP_DOWNLOAD_INDEX_KERNEL               0
+#define DSP30TX_DOWNLOAD_INDEX_KERNEL           1
+#define DSP30RX_DOWNLOAD_INDEX_KERNEL           2
+#define DSP_MAX_DOWNLOAD_COUNT                  35
+
+
+#define DSP_DOWNLOAD_MAX_SEGMENTS         16
+
+#define DSP_UDATA_REQUEST_RECONFIGURE     0
+/*
+parameters:
+  <word> reconfigure delay (in 8kHz samples)
+  <word> reconfigure code
+  <byte> reconfigure hdlc preamble flags
+*/
+
+#define DSP_RECONFIGURE_TX_FLAG           0x8000
+#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG  0x4000
+#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000
+#define DSP_RECONFIGURE_HDLC_FLAG         0x1000
+#define DSP_RECONFIGURE_SYNC_FLAG         0x0800
+#define DSP_RECONFIGURE_PROTOCOL_MASK     0x00ff
+#define DSP_RECONFIGURE_IDLE              0
+#define DSP_RECONFIGURE_V25               1
+#define DSP_RECONFIGURE_V21_CH2           2
+#define DSP_RECONFIGURE_V27_2400          3
+#define DSP_RECONFIGURE_V27_4800          4
+#define DSP_RECONFIGURE_V29_7200          5
+#define DSP_RECONFIGURE_V29_9600          6
+#define DSP_RECONFIGURE_V33_12000         7
+#define DSP_RECONFIGURE_V33_14400         8
+#define DSP_RECONFIGURE_V17_7200          9
+#define DSP_RECONFIGURE_V17_9600          10
+#define DSP_RECONFIGURE_V17_12000         11
+#define DSP_RECONFIGURE_V17_14400         12
+
+/*
+data indications if transparent framer
+  <byte> data 0
+  <byte> data 1
+  ...
+
+data indications if HDLC framer
+  <byte> data 0
+  <byte> data 1
+  ...
+  <byte> CRC 0
+  <byte> CRC 1
+  <byte> preamble flags
+*/
+
+#define DSP_UDATA_INDICATION_SYNC         0
+/*
+returns:
+  <word> time of sync (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_DCD_OFF      1
+/*
+returns:
+  <word> time of DCD off (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_DCD_ON       2
+/*
+returns:
+  <word> time of DCD on (sampled from counter at 8kHz)
+  <byte> connected norm
+  <word> connected options
+  <dword> connected speed (bit/s)
+*/
+
+#define DSP_UDATA_INDICATION_CTS_OFF      3
+/*
+returns:
+  <word> time of CTS off (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_CTS_ON       4
+/*
+returns:
+  <word> time of CTS on (sampled from counter at 8kHz)
+  <byte> connected norm
+  <word> connected options
+  <dword> connected speed (bit/s)
+*/
+
+#define DSP_CONNECTED_NORM_UNSPECIFIED      0
+#define DSP_CONNECTED_NORM_V21              1
+#define DSP_CONNECTED_NORM_V23              2
+#define DSP_CONNECTED_NORM_V22              3
+#define DSP_CONNECTED_NORM_V22_BIS          4
+#define DSP_CONNECTED_NORM_V32_BIS          5
+#define DSP_CONNECTED_NORM_V34              6
+#define DSP_CONNECTED_NORM_V8               7
+#define DSP_CONNECTED_NORM_BELL_212A        8
+#define DSP_CONNECTED_NORM_BELL_103         9
+#define DSP_CONNECTED_NORM_V29_LEASED_LINE  10
+#define DSP_CONNECTED_NORM_V33_LEASED_LINE  11
+#define DSP_CONNECTED_NORM_TFAST            12
+#define DSP_CONNECTED_NORM_V21_CH2          13
+#define DSP_CONNECTED_NORM_V27_TER          14
+#define DSP_CONNECTED_NORM_V29              15
+#define DSP_CONNECTED_NORM_V33              16
+#define DSP_CONNECTED_NORM_V17              17
+
+#define DSP_CONNECTED_OPTION_TRELLIS        0x0001
+
+
+/*---------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*---------------------------------------------------------------------------*/
diff --git a/drivers/isdn/eicon/dspdids.h b/drivers/isdn/eicon/dspdids.h
new file mode 100644 (file)
index 0000000..1ac6a9b
--- /dev/null
@@ -0,0 +1,84 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef DSPDIDS_H_
+#define DSPDIDS_H_
+
+
+/*---------------------------------------------------------------------------*/
+
+#define DSP_DID_INVALID                        0
+#define DSP_DID_DIVA                   1
+#define DSP_DID_DIVA_PRO               2
+#define DSP_DID_DIVA_PRO_20            3
+#define DSP_DID_DIVA_PRO_PCCARD                4
+#define DSP_DID_DIVA_SERVER_BRI_1M     5
+#define DSP_DID_DIVA_SERVER_BRI_2M     6
+#define DSP_DID_DIVA_SERVER_PRI_2M_TX  7
+#define DSP_DID_DIVA_SERVER_PRI_2M_RX  8
+#define DSP_DID_DIVA_SERVER_PRI_30M    9
+#define DSP_DID_TASK_HSCX              100
+#define DSP_DID_TASK_HSCX_PRI_2M_TX    101
+#define DSP_DID_TASK_HSCX_PRI_2M_RX    102
+#define DSP_DID_TASK_V110KRNL          200
+#define DSP_DID_OVERLAY_V1100          201
+#define DSP_DID_OVERLAY_V1101          202
+#define DSP_DID_OVERLAY_V1102          203
+#define DSP_DID_OVERLAY_V1103          204
+#define DSP_DID_OVERLAY_V1104          205
+#define DSP_DID_OVERLAY_V1105          206
+#define DSP_DID_OVERLAY_V1106          207
+#define DSP_DID_OVERLAY_V1107          208
+#define DSP_DID_OVERLAY_V1108          209
+#define DSP_DID_OVERLAY_V1109          210
+#define DSP_DID_TASK_V110_PRI_2M_TX    220
+#define DSP_DID_TASK_V110_PRI_2M_RX    221
+#define DSP_DID_TASK_MODEM             300
+#define DSP_DID_TASK_FAX05             400
+#define DSP_DID_TASK_VOICE             500
+#define DSP_DID_TASK_TIKRNL81          600
+#define DSP_DID_OVERLAY_DIAL           601
+#define DSP_DID_OVERLAY_V22            602
+#define DSP_DID_OVERLAY_V32            603
+#define DSP_DID_OVERLAY_FSK            604
+#define DSP_DID_OVERLAY_FAX            605
+#define DSP_DID_OVERLAY_VXX            606
+#define DSP_DID_OVERLAY_V8             607
+#define DSP_DID_OVERLAY_INFO           608
+#define DSP_DID_OVERLAY_V34            609
+#define DSP_DID_OVERLAY_DFX            610
+#define DSP_DID_PARTIAL_OVERLAY_DIAL   611
+#define DSP_DID_PARTIAL_OVERLAY_FSK    612
+#define DSP_DID_PARTIAL_OVERLAY_FAX    613
+#define DSP_DID_TASK_TIKRNL05          700
+
+
+/*---------------------------------------------------------------------------*/
+
+#endif
+
+/*---------------------------------------------------------------------------*/
index 5ad1645189ca1f5167170bd819e2b46d6404c24a..42e9b3b954f7eeb4ed380d0ecd2b654b76d0d3c0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.19 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon.h,v 1.23 2000/06/21 11:28:42 armin Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  *
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon.h,v $
- * Revision 1.19  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.18  1999/11/25 11:43:27  armin
- * Fixed statectrl and connect message.
- * X.75 fix and HDLC/transparent with autoconnect.
- * Minor cleanup.
- *
- * Revision 1.17  1999/10/26 21:15:33  armin
- * using define for checking phone number len to avoid buffer overflow.
- *
- * Revision 1.16  1999/10/08 22:09:33  armin
- * Some fixes of cards interface handling.
- * Bugfix of NULL pointer occurence.
- * Changed a few log outputs.
- *
- * Revision 1.15  1999/09/26 14:17:53  armin
- * Improved debug and log via readstat()
- *
- * Revision 1.14  1999/09/08 20:17:31  armin
- * Added microchannel patch from Erik Weber.
- *
- * Revision 1.13  1999/09/06 07:29:35  fritz
- * Changed my mail-address.
- *
- * Revision 1.12  1999/09/04 06:20:05  keil
- * Changes from kernel set_current_state()
- *
- * Revision 1.11  1999/08/29 17:23:44  armin
- * New setup compat.
- * Bugfix if compile as not module.
- *
- * Revision 1.10  1999/08/22 20:26:41  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.9  1999/08/18 20:16:57  armin
- * Added XLOG function for all cards.
- * Bugfix of alloc_skb NULL pointer.
- *
- * Revision 1.8  1999/07/25 15:12:01  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.7  1999/07/11 17:16:23  armin
- * Bugfixes in queue handling.
- * Added DSP-DTMF decoder functions.
- * Reorganized ack_handler.
- *
- * Revision 1.6  1999/06/09 19:31:24  armin
- * Wrong PLX size for request_region() corrected.
- * Added first MCA code from Erik Weber.
- *
- * Revision 1.5  1999/03/29 11:19:41  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.4  1999/03/02 12:37:42  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.3  1999/01/24 20:14:07  armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.2  1999/01/10 18:46:04  armin
- * Bug with wrong values in HLC fixed.
- * Bytes to send are counted and limited now.
- *
- * Revision 1.1  1999/01/01 18:09:41  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
 
 #define EICON_IOCTL_TEST     98
 #define EICON_IOCTL_DEBUGVAR 99
 
+#define EICON_IOCTL_DIA_OFFSET 100
+
 /* Bus types */
 #define EICON_BUS_ISA          1
 #define EICON_BUS_MCA          2
@@ -185,39 +107,10 @@ typedef struct {
        unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */
 } eicon_isa_codebuf;
 
-/* Struct for downloading protocol via ioctl for PCI cards */
-typedef struct {
-        /* start-up parameters */
-        unsigned char tei;
-        unsigned char nt2;
-        unsigned char WatchDog;
-        unsigned char Permanent;
-        unsigned char XInterface;
-        unsigned char StableL2;
-        unsigned char NoOrderCheck;
-        unsigned char HandsetType;
-        unsigned char LowChannel;
-        unsigned char ProtVersion;
-        unsigned char Crc4;
-        unsigned char NoHscx30Mode;  /* switch PRI into No HSCX30 test mode */
-        unsigned char Loopback;      /* switch card into Loopback mode */
-        struct q931_link_s
-        {
-          unsigned char oad[32];
-          unsigned char osa[32];
-          unsigned char spid[32];
-        } l[2];
-        unsigned long protocol_len;
-       unsigned int  dsp_code_num;
-        unsigned long dsp_code_len[9];
-        unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */
-} eicon_pci_codebuf;
-
 /* Data for downloading protocol via ioctl */
 typedef union {
        eicon_isa_codebuf isa;
        eicon_isa_codebuf mca;
-       eicon_pci_codebuf pci;
 } eicon_codebuf;
 
 /* Data for Management interface */
@@ -228,6 +121,7 @@ typedef struct {
        unsigned char data[700]; 
 } eicon_manifbuf;
 
+#define TRACE_OK                 (1)
 
 #ifdef __KERNEL__
 
@@ -265,206 +159,34 @@ typedef struct {
 
 #include "eicon_isa.h"
 
+#include "idi.h"
+
+typedef struct {
+  __u16 NextReq  __attribute__ ((packed));  /* pointer to next Req Buffer */
+  __u16 NextRc   __attribute__ ((packed));  /* pointer to next Rc Buffer  */
+  __u16 NextInd  __attribute__ ((packed));  /* pointer to next Ind Buffer */
+  __u8 ReqInput  __attribute__ ((packed));  /* number of Req Buffers sent */
+  __u8 ReqOutput  __attribute__ ((packed)); /* number of Req Buffers returned */
+  __u8 ReqReserved  __attribute__ ((packed));/*number of Req Buffers reserved */
+  __u8 Int  __attribute__ ((packed));       /* ISDN-P interrupt           */
+  __u8 XLock  __attribute__ ((packed));     /* Lock field for arbitration */
+  __u8 RcOutput  __attribute__ ((packed));  /* number of Rc buffers received */
+  __u8 IndOutput  __attribute__ ((packed)); /* number of Ind buffers received */
+  __u8 IMask  __attribute__ ((packed));     /* Interrupt Mask Flag        */
+  __u8 Reserved1[2]  __attribute__ ((packed)); /* reserved field, do not use */
+  __u8 ReadyInt  __attribute__ ((packed));  /* request field for ready int */
+  __u8 Reserved2[12]  __attribute__ ((packed)); /* reserved field, do not use */
+  __u8 InterfaceType  __attribute__ ((packed)); /* interface type 1=16K    */
+  __u16 Signature  __attribute__ ((packed));    /* ISDN-P initialized ind  */
+  __u8 B[1];                            /* buffer space for Req,Ind and Rc */
+} eicon_pr_ram;
+
 /* Macro for delay via schedule() */
 #define SLEEP(j) {                     \
   set_current_state(TASK_UNINTERRUPTIBLE); \
   schedule_timeout(j);                 \
 }
 
-#endif /* KERNEL */
-
-#define DIVAS_SHARED_OFFSET    (0x1000)
-
-#define MIPS_BUFFER_SZ  128
-#define MIPS_MAINT_OFFS 0xff00
-
-#define XLOG_ERR_CARD_NUM       (13)
-#define XLOG_ERR_DONE           (14)
-#define XLOG_ERR_CMD            (15)
-#define XLOG_ERR_TIMEOUT        (16)
-#define XLOG_ERR_CARD_STATE     (17)
-#define XLOG_ERR_UNKNOWN        (18)
-#define XLOG_OK                  (0)
-
-#define TRACE_OK                 (1)
-
-typedef struct {
-  __u8 Id      __attribute__ ((packed));
-  __u8 uX      __attribute__ ((packed));
-  __u8 listen  __attribute__ ((packed));
-  __u8 active  __attribute__ ((packed));
-  __u8 sin[3]  __attribute__ ((packed));
-  __u8 bc[6]   __attribute__ ((packed));
-  __u8 llc[6]  __attribute__ ((packed));
-  __u8 hlc[6]  __attribute__ ((packed));
-  __u8 oad[20] __attribute__ ((packed));
-}DSigStruc;
-
-typedef struct {
-  __u32 cx_b1  __attribute__ ((packed));
-  __u32 cx_b2  __attribute__ ((packed));
-  __u32 cr_b1  __attribute__ ((packed));
-  __u32 cr_b2  __attribute__ ((packed));
-  __u32 px_b1  __attribute__ ((packed));
-  __u32 px_b2  __attribute__ ((packed));
-  __u32 pr_b1  __attribute__ ((packed));
-  __u32 pr_b2  __attribute__ ((packed));
-  __u16 er_b1  __attribute__ ((packed));
-  __u16 er_b2  __attribute__ ((packed));
-}BL1Struc;
-
-typedef struct {
-  __u32 XTotal __attribute__ ((packed));
-  __u32 RTotal __attribute__ ((packed));
-  __u16 XError __attribute__ ((packed));
-  __u16 RError __attribute__ ((packed));
-}L2Struc;
-
-typedef struct {
-  __u16 free_n;
-}OSStruc;
-
-typedef union
-{
-  DSigStruc DSigStats;
-  BL1Struc BL1Stats;
-  L2Struc L2Stats;
-  OSStruc OSStats;
-  __u8   b[MIPS_BUFFER_SZ];
-  __u16   w[MIPS_BUFFER_SZ>>1];
-  __u16   l[MIPS_BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
-  __u32  d[MIPS_BUFFER_SZ>>2];
-} MIPS_BUFFER;
-
-typedef struct
-{
-  __u8 req     __attribute__ ((packed));
-  __u8 rc      __attribute__ ((packed));
-  __u8 reserved[2]     __attribute__ ((packed));     /* R3000 alignment ... */
-  __u8 *mem    __attribute__ ((packed));
-  __u16 length __attribute__ ((packed));               /* used to be short */
-  __u16 port   __attribute__ ((packed));
-  __u8 fill[4] __attribute__ ((packed));         /* data at offset 16   */
-  MIPS_BUFFER data     __attribute__ ((packed));
-} mi_pc_maint_t;
-
-typedef struct
-{
-        __u16 command;
-        mi_pc_maint_t pcm;
-}xlogreq_t;
-
-typedef struct{
-        __u16 code     __attribute__ ((packed));       /* used to be short */
-        __u16 timeh    __attribute__ ((packed));
-        __u16 timel    __attribute__ ((packed));
-        char buffer[MIPS_BUFFER_SZ - 6];
-}xlog_entry_t;
-
-
-#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
-#define DSP_COMBIFILE_FORMAT_VERSION_BCD    0x0100
-
-#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
-#define DSP_FILE_FORMAT_VERSION_BCD         0x0100
-
-typedef struct tag_dsp_combifile_header
-{
-  char                  format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
-  __u16                  format_version_bcd             __attribute__ ((packed));
-  __u16                  header_size                    __attribute__ ((packed));
-  __u16                  combifile_description_size     __attribute__ ((packed));
-  __u16                  directory_entries              __attribute__ ((packed));
-  __u16                  directory_size                 __attribute__ ((packed));
-  __u16                  download_count                 __attribute__ ((packed));
-  __u16                  usage_mask_size                __attribute__ ((packed));
-} t_dsp_combifile_header;
-
-typedef struct tag_dsp_combifile_directory_entry
-{
-  __u16                  card_type_number               __attribute__ ((packed));
-  __u16                  file_set_number                __attribute__ ((packed));
-} t_dsp_combifile_directory_entry;
-
-typedef struct tag_dsp_file_header
-{
-  char                  format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
-  __u16                 format_version_bcd              __attribute__ ((packed));
-  __u16                 download_id                     __attribute__ ((packed));
-  __u16                 download_flags                  __attribute__ ((packed));
-  __u16                 required_processing_power       __attribute__ ((packed));
-  __u16                 interface_channel_count         __attribute__ ((packed));
-  __u16                 header_size                     __attribute__ ((packed));
-  __u16                 download_description_size       __attribute__ ((packed));
-  __u16                 memory_block_table_size         __attribute__ ((packed));
-  __u16                 memory_block_count              __attribute__ ((packed));
-  __u16                 segment_table_size              __attribute__ ((packed));
-  __u16                 segment_count                   __attribute__ ((packed));
-  __u16                 symbol_table_size               __attribute__ ((packed));
-  __u16                 symbol_count                    __attribute__ ((packed));
-  __u16                 total_data_size_dm              __attribute__ ((packed));
-  __u16                 data_block_count_dm             __attribute__ ((packed));
-  __u16                 total_data_size_pm              __attribute__ ((packed));
-  __u16                 data_block_count_pm             __attribute__ ((packed));
-} t_dsp_file_header;
-
-typedef struct tag_dsp_memory_block_desc
-{
-  __u16                 alias_memory_block;
-  __u16                 memory_type;
-  __u16                 address;
-  __u16                 size;             /* DSP words */
-} t_dsp_memory_block_desc;
-
-typedef struct tag_dsp_segment_desc
-{
-  __u16                 memory_block;
-  __u16                 attributes;
-  __u16                 base;
-  __u16                 size;
-  __u16                 alignment;        /* ==0 -> no other legal start address than base */
-} t_dsp_segment_desc;
-
-typedef struct tag_dsp_symbol_desc
-{
-  __u16                 symbol_id;
-  __u16                 segment;
-  __u16                 offset;
-  __u16                 size;             /* DSP words */
-} t_dsp_symbol_desc;
-
-typedef struct tag_dsp_data_block_header
-{
-  __u16                 attributes;
-  __u16                 segment;
-  __u16                 offset;
-  __u16                 size;             /* DSP words */
-} t_dsp_data_block_header;
-
-typedef struct tag_dsp_download_desc      /* be sure to keep native alignment for MAESTRA's */
-{
-  __u16                 download_id;
-  __u16                 download_flags;
-  __u16                 required_processing_power;
-  __u16                 interface_channel_count;
-  __u16                 excess_header_size;
-  __u16                 memory_block_count;
-  __u16                 segment_count;
-  __u16                 symbol_count;
-  __u16                 data_block_count_dm;
-  __u16                 data_block_count_pm;
-  __u8  *            p_excess_header_data               __attribute__ ((packed));
-  char  *            p_download_description             __attribute__ ((packed));
-  t_dsp_memory_block_desc  *p_memory_block_table        __attribute__ ((packed));
-  t_dsp_segment_desc  *p_segment_table                  __attribute__ ((packed));
-  t_dsp_symbol_desc  *p_symbol_table                    __attribute__ ((packed));
-  __u16 *            p_data_blocks_dm                   __attribute__ ((packed));
-  __u16 *            p_data_blocks_pm                   __attribute__ ((packed));
-} t_dsp_download_desc;
-
-
-#ifdef __KERNEL__
-
 typedef struct {
   __u8                  Req;            /* pending request          */
   __u8                  Rc;             /* return code received     */
@@ -508,6 +230,7 @@ typedef struct {
        unsigned short statectrl;        /* State controling bits       */
        unsigned short eazmask;          /* EAZ-Mask for this Channel   */
        int             queued;          /* User-Data Bytes in TX queue */
+       int             pqueued;         /* User-Data Packets in TX queue */
        int             waitq;           /* User-Data Bytes in wait queue */
        int             waitpq;          /* User-Data Bytes in packet queue */
        struct sk_buff *tskb1;           /* temp skb 1                  */
@@ -518,7 +241,9 @@ typedef struct {
        T30_s           *fax;            /* pointer to fax data in LL   */
        eicon_ch_fax_buf fax2;           /* fax related struct          */
 #endif
-       entity          e;               /* Entity                      */
+       entity          e;               /* Native Entity               */
+       ENTITY          de;              /* Divas D Entity              */
+       ENTITY          be;              /* Divas B Entity              */
        char            cpn[32];         /* remember cpn                */
        char            oad[32];         /* remember oad                */
        char            dsa[32];         /* remember dsa                */
@@ -542,8 +267,6 @@ typedef struct {
 #define EICON_FLAGS_MVALID   8 /* Cards membase is valid */
 #define EICON_FLAGS_LOADED   8 /* Firmware loaded        */
 
-#define EICON_BCH            2 /* # of channels per card */
-
 /* D-Channel states */
 #define EICON_STATE_NULL     0
 #define EICON_STATE_ICALL    1
@@ -565,9 +288,6 @@ typedef struct {
 
 #define EICON_MAX_QUEUE  2138
 
-#define EICON_LOCK_TX 0
-#define EICON_LOCK_RX 1
-
 typedef union {
        eicon_isa_card isa;
        eicon_pci_card pci;
@@ -593,17 +313,12 @@ typedef struct {
        __u8 more;
 } eicon_indhdr;
 
-typedef struct msn_entry {
-       char eaz;
-        char msn[16];
-        struct msn_entry * next;
-} msn_entry;
-
 /*
  * Per card driver data
  */
 typedef struct eicon_card {
        eicon_hwif hwif;                 /* Hardware dependant interface     */
+       DESCRIPTOR *d;                   /* IDI Descriptor                   */
         u_char ptype;                    /* Protocol type (1TR6 or Euro)     */
         u_char bus;                      /* Bustype (ISA, MCA, PCI)          */
         u_char type;                     /* Cardtype (EICON_CTYPE_...)       */
@@ -621,49 +336,23 @@ typedef struct eicon_card {
        struct tq_struct snd_tq;         /* Task struct for xmit bh          */
        struct tq_struct rcv_tq;         /* Task struct for rcv bh           */
        struct tq_struct ack_tq;         /* Task struct for ack bh           */
-       msn_entry *msn_list;
        eicon_chan*     IdTable[256];    /* Table to find entity   */
        __u16  ref_in;
        __u16  ref_out;
        int    nchannels;                /* Number of B-Channels             */
        int    ReadyInt;                 /* Ready Interrupt                  */
        eicon_chan *bch;                 /* B-Channel status/control         */
-       char   status_buf[256];          /* Buffer for status messages       */
-       char   *status_buf_read;
-       char   *status_buf_write;
-       char   *status_buf_end;
+       DBUFFER *dbuf;                   /* Dbuffer for Diva Server          */
+       BUFFERS *sbuf;                   /* Buffer for Diva Server           */
+       char *sbufp;                     /* Data Buffer for Diva Server      */
         isdn_if interface;               /* Interface to upper layer         */
-        char regname[35];                /* Name used for request_region     */
+        char regname[35];                /* Drivers card name               */
 #ifdef CONFIG_MCA
         int    mca_slot;                /* # of cards MCA slot              */
        int     mca_io;                  /* MCA cards IO port                */
 #endif /* CONFIG_MCA */
 } eicon_card;
 
-/* -----------------------------------------------------------**
-** The PROTOCOL_FEATURE_STRING                                **
-** defines capabilities and                                   **
-** features of the actual protocol code. It's used as a bit   **
-** mask.                                                      **
-** The following Bits are defined:                            **
-** -----------------------------------------------------------*/
-#define PROTCAP_TELINDUS  0x0001  /* Telindus Variant of protocol code   */
-#define PROTCAP_MANIF     0x0002  /* Management interface implemented    */
-#define PROTCAP_V_42      0x0004  /* V42 implemented                     */
-#define PROTCAP_V90D      0x0008  /* V.90D (implies up to 384k DSP code) */
-#define PROTCAP_EXTD_FAX  0x0010  /* Extended FAX (ECM, 2D, T6, Polling) */
-#define PROTCAP_FREE4     0x0020  /* not used                            */
-#define PROTCAP_FREE5     0x0040  /* not used                            */
-#define PROTCAP_FREE6     0x0080  /* not used                            */
-#define PROTCAP_FREE7     0x0100  /* not used                            */
-#define PROTCAP_FREE8     0x0200  /* not used                            */
-#define PROTCAP_FREE9     0x0400  /* not used                            */
-#define PROTCAP_FREE10    0x0800  /* not used                            */
-#define PROTCAP_FREE11    0x1000  /* not used                            */
-#define PROTCAP_FREE12    0x2000  /* not used                            */
-#define PROTCAP_FREE13    0x4000  /* not used                            */
-#define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
-
 #include "eicon_idi.h"
 
 extern eicon_card *cards;
@@ -688,13 +377,11 @@ extern __inline__ void eicon_schedule_ack(eicon_card *card)
         mark_bh(IMMEDIATE_BH);
 }
 
-extern char *eicon_find_eaz(eicon_card *, char);
-extern int eicon_addcard(int, int, int, char *);
+extern int eicon_addcard(int, int, int, char *, int);
 extern void eicon_io_transmit(eicon_card *card);
 extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
 extern void eicon_io_rcv_dispatch(eicon_card *ccard);
 extern void eicon_io_ack_dispatch(eicon_card *ccard);
-extern int eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq);
 #ifdef CONFIG_MCA
 extern int eicon_mca_find_card(int, int, int, char *);
 extern int eicon_mca_probe(int, int, int, int, char *);
@@ -705,6 +392,8 @@ extern ulong DebugVar;
 extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
 extern void eicon_putstatus(eicon_card * card, char * buf);
 
+extern spinlock_t eicon_lock;
+
 #endif  /* __KERNEL__ */
 
 #endif /* eicon_h */
index 420d73f6ea8f18c415f2c5105bd6099caf0acc2a..1470fa7e6d856052e5add96c452afe1bd914c410 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_dsp.h,v 1.5 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon_dsp.h,v 1.7 2000/05/07 08:51:04 armin Exp $
  *
  * ISDN lowlevel-module for Eicon active cards.
  *        DSP definitions
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Log: eicon_dsp.h,v $
- * Revision 1.5  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.4  1999/07/25 15:12:02  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.3  1999/07/11 17:16:24  armin
- * Bugfixes in queue handling.
- * Added DSP-DTMF decoder functions.
- * Reorganized ack_handler.
- *
- * Revision 1.2  1999/03/29 11:19:42  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.1  1999/03/02 12:18:54  armin
- * First checkin of DSP defines for audio features.
- *
  *
  */
 
 #ifndef DSP_H 
 #define DSP_H
 
-#define DSP_UDATA_REQUEST_RECONFIGURE           0
-/*
-parameters:
-  <word> reconfigure delay (in 8kHz samples)
-  <word> reconfigure code
-  <byte> reconfigure hdlc preamble flags
-*/
+#include "dsp_defs.h"
 
-#define DSP_RECONFIGURE_TX_FLAG             0x8000
-#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG    0x4000
-#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG   0x2000
-#define DSP_RECONFIGURE_HDLC_FLAG           0x1000
-#define DSP_RECONFIGURE_SYNC_FLAG           0x0800
-#define DSP_RECONFIGURE_PROTOCOL_MASK       0x00ff
-#define DSP_RECONFIGURE_IDLE                0
-#define DSP_RECONFIGURE_V25                 1
-#define DSP_RECONFIGURE_V21_CH2             2
-#define DSP_RECONFIGURE_V27_2400            3
-#define DSP_RECONFIGURE_V27_4800            4
-#define DSP_RECONFIGURE_V29_7200            5
-#define DSP_RECONFIGURE_V29_9600            6
-#define DSP_RECONFIGURE_V33_12000           7
-#define DSP_RECONFIGURE_V33_14400           8
-#define DSP_RECONFIGURE_V17_7200            9
-#define DSP_RECONFIGURE_V17_9600            10
-#define DSP_RECONFIGURE_V17_12000           11
-#define DSP_RECONFIGURE_V17_14400           12
-
-/*
-data indications if transparent framer
-  <byte> data 0
-  <byte> data 1
-  ...
-
-data indications if HDLC framer
-  <byte> data 0
-  <byte> data 1
-  ...
-  <byte> CRC 0
-  <byte> CRC 1
-  <byte> preamble flags
-*/
 
 #define DSP_UDATA_REQUEST_SWITCH_FRAMER         1
 /*
@@ -122,49 +61,6 @@ parameters:
   - none -
 */
 
-
-#define DSP_UDATA_INDICATION_SYNC               0
-/*
-returns:
-  <word> time of sync (sampled from counter at 8kHz)
-*/
-
-#define DSP_UDATA_INDICATION_DCD_OFF            1
-/*
-returns:
-  <word> time of DCD off (sampled from counter at 8kHz)
-*/
-
-#define DSP_UDATA_INDICATION_DCD_ON             2
-/*
-returns:
-  <word> time of DCD on (sampled from counter at 8kHz)
-  <byte> connected norm
-  <word> connected options
-  <dword> connected speed (bit/s, max of tx and rx speed)
-  <word> roundtrip delay (ms)
-  <dword> connected speed tx (bit/s)
-  <dword> connected speed rx (bit/s)
-*/
-
-#define DSP_UDATA_INDICATION_CTS_OFF            3
-/*
-returns:
-  <word> time of CTS off (sampled from counter at 8kHz)
-*/
-
-#define DSP_UDATA_INDICATION_CTS_ON             4
-/*
-returns:
-  <word> time of CTS on (sampled from counter at 8kHz)
-  <byte> connected norm
-  <word> connected options
-  <dword> connected speed (bit/s, max of tx and rx speed)
-  <word> roundtrip delay (ms)
-  <dword> connected speed tx (bit/s)
-  <dword> connected speed rx (bit/s)
-*/
-
 typedef struct eicon_dsp_ind {
        __u16   time            __attribute__ ((packed));
        __u8    norm            __attribute__ ((packed));
@@ -175,32 +71,11 @@ typedef struct eicon_dsp_ind {
        __u32   rxspeed         __attribute__ ((packed));
 } eicon_dsp_ind;
 
-#define DSP_CONNECTED_NORM_UNSPECIFIED      0
-#define DSP_CONNECTED_NORM_V21              1
-#define DSP_CONNECTED_NORM_V23              2
-#define DSP_CONNECTED_NORM_V22              3
-#define DSP_CONNECTED_NORM_V22_BIS          4
-#define DSP_CONNECTED_NORM_V32_BIS          5
-#define DSP_CONNECTED_NORM_V34              6
-#define DSP_CONNECTED_NORM_V8               7
-#define DSP_CONNECTED_NORM_BELL_212A        8
-#define DSP_CONNECTED_NORM_BELL_103         9
-#define DSP_CONNECTED_NORM_V29_LEASED_LINE  10
-#define DSP_CONNECTED_NORM_V33_LEASED_LINE  11
-#define DSP_CONNECTED_NORM_V90              12
-#define DSP_CONNECTED_NORM_V21_CH2          13
-#define DSP_CONNECTED_NORM_V27_TER          14
-#define DSP_CONNECTED_NORM_V29              15
-#define DSP_CONNECTED_NORM_V33              16
-#define DSP_CONNECTED_NORM_V17              17
-
-#define DSP_CONNECTED_OPTION_TRELLIS             0x0001
 #define DSP_CONNECTED_OPTION_V42_TRANS           0x0002
 #define DSP_CONNECTED_OPTION_V42_LAPM            0x0004
 #define DSP_CONNECTED_OPTION_SHORT_TRAIN         0x0008
 #define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
 
-
 #define DSP_UDATA_INDICATION_DISCONNECT         5
 /*
 returns:
@@ -214,7 +89,6 @@ returns:
 #define DSP_DISCONNECT_CAUSE_CLEARDOWN          0x04
 #define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT   0x05
 
-
 #define DSP_UDATA_INDICATION_TX_CONFIRMATION    6
 /*
 returns:
index 9cef520bc5271eb07130ec245cc5b16bd6587cb2..5b63311da145c72cc55d6bd7ff221178263b9825 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.33 2000/03/06 15:45:17 armin Exp $
+/* $Id: eicon_idi.c,v 1.41 2000/08/12 18:00:47 armin Exp $
  *
  * ISDN lowlevel-module for Eicon active cards.
  *        IDI interface 
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_idi.c,v $
- * Revision 1.33  2000/03/06 15:45:17  armin
- * Fixed incomplete number handling with BRI PtP connection.
- *
- * Revision 1.32  2000/03/04 17:04:21  armin
- * Fix of statemachine, B-connect before D-connect,
- * thanks to Helmut Adams <adams@ipcon.de>
- * Minor change in send-data packet handling.
- *
- * Revision 1.31  2000/02/22 16:26:40  armin
- * Fixed membase error message.
- * Fixed missing log buffer struct.
- *
- * Revision 1.30  2000/02/16 16:08:46  armin
- * Fixed virtual channel handling of IDI.
- *
- * Revision 1.29  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.28  2000/01/20 19:55:34  keil
- * Add FAX Class 1 support
- *
- * Revision 1.27  1999/11/29 13:12:03  armin
- * Autoconnect on L2_TRANS doesn't work with link_level correctly,
- * changed back to former mode.
- *
- * Revision 1.26  1999/11/25 11:43:27  armin
- * Fixed statectrl and connect message.
- * X.75 fix and HDLC/transparent with autoconnect.
- * Minor cleanup.
- *
- * Revision 1.25  1999/11/18 20:30:55  armin
- * removed old workaround for ISA cards.
- *
- * Revision 1.24  1999/10/26 21:15:33  armin
- * using define for checking phone number len to avoid buffer overflow.
- *
- * Revision 1.23  1999/10/11 18:13:25  armin
- * Added fax capabilities for Eicon Diva Server cards.
- *
- * Revision 1.22  1999/10/08 22:09:33  armin
- * Some fixes of cards interface handling.
- * Bugfix of NULL pointer occurence.
- * Changed a few log outputs.
- *
- * Revision 1.21  1999/09/26 14:17:53  armin
- * Improved debug and log via readstat()
- *
- * Revision 1.20  1999/09/21 20:35:43  armin
- * added more error checking.
- *
- * Revision 1.19  1999/09/21 20:06:40  armin
- * Added pointer checks.
- *
- * Revision 1.18  1999/09/07 12:48:05  armin
- * Prepared for sub-address usage.
- *
- * Revision 1.17  1999/09/07 12:35:39  armin
- * Better checking and channel Id handling.
- *
- * Revision 1.16  1999/09/04 13:44:19  armin
- * Fix of V.42 analog Modem negotiation handling.
- *
- * Revision 1.15  1999/08/28 21:32:50  armin
- * Prepared for fax related functions.
- * Now compilable without errors/warnings.
- *
- * Revision 1.14  1999/08/28 20:24:40  armin
- * Corrected octet 3/3a in CPN/OAD information element.
- * Thanks to John Simpson <xfl23@dial.pipex.com>
- *
- * Revision 1.13  1999/08/22 20:26:44  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.12  1999/08/18 20:16:59  armin
- * Added XLOG function for all cards.
- * Bugfix of alloc_skb NULL pointer.
- *
- * Revision 1.11  1999/07/25 15:12:03  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.10  1999/07/11 17:16:24  armin
- * Bugfixes in queue handling.
- * Added DSP-DTMF decoder functions.
- * Reorganized ack_handler.
- *
- * Revision 1.9  1999/03/29 11:19:42  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.8  1999/03/02 12:37:43  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.7  1999/02/03 18:34:35  armin
- * Channel selection for outgoing calls w/o CHI.
- * Added channel # in debug messages.
- * L2 Transparent should work with 800 byte/packet now.
- *
- * Revision 1.6  1999/01/26 07:18:59  armin
- * Bug with wrong added CPN fixed.
- *
- * Revision 1.5  1999/01/24 20:14:11  armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.4  1999/01/10 18:46:05  armin
- * Bug with wrong values in HLC fixed.
- * Bytes to send are counted and limited now.
- *
- * Revision 1.3  1999/01/05 14:49:34  armin
- * Added experimental usage of full BC and HLC for
- * speech, 3.1kHz audio, fax gr.2/3
- *
- * Revision 1.2  1999/01/04 13:19:29  armin
- * Channel status with listen-request wrong - fixed.
- *
- * Revision 1.1  1999/01/01 18:09:41  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
 #include <linux/config.h>
 #include "eicon.h"
 #include "eicon_idi.h"
 #include "eicon_dsp.h"
+#include "uxio.h"
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.33 $";
+char *eicon_idi_revision = "$Revision: 1.41 $";
 
 eicon_manifbuf *manbuf;
 
-static char BC_Speech[3] =     { 0x80, 0x90, 0xa3 };
-static char BC_31khz[3] =      { 0x90, 0x90, 0xa3 };
-static char BC_64k[2] =        { 0x88, 0x90 };
-static char BC_video[3] =      { 0x91, 0x90, 0xa5 };
-
-#ifdef EICON_FULL_SERVICE_OKTETT
-/* 
-static char HLC_telephony[2] = { 0x91, 0x81 }; 
-*/
-static char HLC_faxg3[2] =     { 0x91, 0x84 };
-#endif
-
 int eicon_idi_manage_assign(eicon_card *card);
 int eicon_idi_manage_remove(eicon_card *card);
 int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer);
@@ -209,7 +69,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
        reqbuf->XBuffer.P[l++] = 0; /* end */
        reqbuf->Req = ASSIGN;
        reqbuf->ReqCh = 0;
-       reqbuf->ReqId = 0;
+       reqbuf->ReqId = DSIG_ID;
        reqbuf->XBuffer.length = l;
        reqbuf->Reference = 0; /* Sig Entity */
   }
@@ -221,6 +81,9 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
        reqbuf->XBuffer.P[l++] = LLC;
        reqbuf->XBuffer.P[l++] = 2;
        switch(chan->l2prot) {
+               case ISDN_PROTO_L2_V11096:
+               case ISDN_PROTO_L2_V11019:
+               case ISDN_PROTO_L2_V11038:
                case ISDN_PROTO_L2_TRANS:
                        reqbuf->XBuffer.P[l++] = 2; /* transparent */
                        break;
@@ -262,7 +125,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
        reqbuf->XBuffer.P[l++] = 0; /* end */
        reqbuf->Req = ASSIGN;
        reqbuf->ReqCh = 0;
-       reqbuf->ReqId = 0x20;
+       reqbuf->ReqId = NL_ID;
        reqbuf->XBuffer.length = l;
        reqbuf->Reference = 1; /* Net Entity */
   }
@@ -281,6 +144,21 @@ idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
    return(0);
 }
 
+int
+idi_put_suspend_req(eicon_REQ *reqbuf, eicon_chan *chan)
+{
+       reqbuf->Req = SUSPEND;
+       reqbuf->ReqCh = 0;
+       reqbuf->ReqId = 1;
+       reqbuf->XBuffer.P[0] = CAI;
+       reqbuf->XBuffer.P[1] = 1;
+       reqbuf->XBuffer.P[2] = chan->No;
+       reqbuf->XBuffer.P[3] = 0;
+       reqbuf->XBuffer.length = 4;
+       reqbuf->Reference = 0; /* Sig Entity */
+   return(0);
+}
+
 int
 idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
 {
@@ -295,7 +173,7 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
        reqbuf->XBuffer.P[4] = 0;
        reqbuf->XBuffer.P[5] = 0;
        reqbuf->XBuffer.P[6] = 32;
-       reqbuf->XBuffer.P[7] = 3;
+       reqbuf->XBuffer.P[7] = 0;
        switch(chan->l2prot) {
                case ISDN_PROTO_L2_X75I:
                case ISDN_PROTO_L2_X75UI:
@@ -391,6 +269,12 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
                case HANGUP:
                        idi_put_req(reqbuf, HANGUP, 0, 0);
                        break;
+               case SUSPEND:
+                       idi_put_suspend_req(reqbuf, chan);
+                       break;
+               case RESUME:
+                       idi_put_req(reqbuf, RESUME, 0 ,0);
+                       break;
                case REJECT:
                        idi_put_req(reqbuf, REJECT, 0 ,0);
                        break;
@@ -400,17 +284,20 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
                case CALL_RES:
                        idi_call_res_req(reqbuf, chan);
                        break;
-               case IDI_N_CONNECT|0x700:
-                       idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
+               case CALL_HOLD:
+                       idi_put_req(reqbuf, CALL_HOLD, 0, 0);
+                       break;
+               case N_CONNECT|0x700:
+                       idi_put_req(reqbuf, N_CONNECT, 1, 0);
                        break;
-               case IDI_N_CONNECT_ACK|0x700:
-                       idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
+               case N_CONNECT_ACK|0x700:
+                       idi_put_req(reqbuf, N_CONNECT_ACK, 1, 0);
                        break;
-               case IDI_N_DISC|0x700:
-                       idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
+               case N_DISC|0x700:
+                       idi_put_req(reqbuf, N_DISC, 1, chan->e.IndCh);
                        break;
-               case IDI_N_DISC_ACK|0x700:
-                       idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
+               case N_DISC_ACK|0x700:
+                       idi_put_req(reqbuf, N_DISC_ACK, 1, chan->e.IndCh);
                        break;
                default:
                        eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
@@ -492,7 +379,7 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
 
        if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
            (chan->fsm_state == EICON_STATE_WMCONN)) {
-               if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
+               if (chan->e.B2Id) idi_do_req(card, chan, N_DISC, 1);
        }
        if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
        if (chan->fsm_state != EICON_STATE_NULL) {
@@ -507,6 +394,32 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
   return(0);
 }
 
+int
+capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm)
+{
+       if ((cm->para[0] != 3) || (cm->para[1] != 0))
+               return -1;
+       if (cm->para[2] < 3)
+               return -1;
+       if (cm->para[4] != 0)
+               return -1;
+       switch(cm->para[3]) {
+               case 4: /* Suspend */
+                       eicon_log(card, 8, "idi_req: Ch%d: Call Suspend\n", chan->No);
+                       if (cm->para[5]) {
+                               idi_do_req(card, chan, SUSPEND, 0);
+                       } else {
+                               idi_do_req(card, chan, CALL_HOLD, 0);
+                       }
+                       break;
+               case 5: /* Resume */
+                       eicon_log(card, 8, "idi_req: Ch%d: Call Resume\n", chan->No);
+                       idi_do_req(card, chan, RESUME, 0);
+                       break;
+        }
+       return 0;
+}
+
 int
 idi_connect_res(eicon_card *card, eicon_chan *chan)
 {
@@ -612,7 +525,14 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
                        reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
        }
 
-       if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
+       if (si2 > 2) {
+               reqbuf->XBuffer.P[l++] = SHIFT|6;
+               reqbuf->XBuffer.P[l++] = SIN;
+               reqbuf->XBuffer.P[l++] = 2;
+               reqbuf->XBuffer.P[l++] = si1;
+               reqbuf->XBuffer.P[l++] = si2;
+       }
+       else if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
                reqbuf->XBuffer.P[l++] = BC;
                reqbuf->XBuffer.P[l++] = tmp;
                for(i=0; i<tmp;i++) 
@@ -632,7 +552,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
        reqbuf->XBuffer.P[l++] = 0;
        reqbuf->XBuffer.P[l++] = 0;
        reqbuf->XBuffer.P[l++] = 32;
-       reqbuf->XBuffer.P[l++] = 3;
+       reqbuf->XBuffer.P[l++] = 0;
         switch(chan->l2prot) {
                case ISDN_PROTO_L2_X75I:
                case ISDN_PROTO_L2_X75UI:
@@ -859,7 +779,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
                                }
                                for(i=0; i < wlen; i++) 
                                        message->llc[i] = buffer[pos++];
-                               eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0],
+                               eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d ...\n", chan->No, message->llc[0],
                                        message->llc[1],message->llc[2],message->llc[3]);
                                break;
                        case HLC:
@@ -869,7 +789,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
                                }
                                for(i=0; i < wlen; i++) 
                                        message->hlc[i] = buffer[pos++];
-                               eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No,
+                               eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x ...\n", chan->No,
                                        message->hlc[0], message->hlc[1],
                                        message->hlc[2], message->hlc[3], message->hlc[4]);
                                break;
@@ -1061,31 +981,55 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
 }
 
 void
-idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2)
+idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *sin, unsigned char *si1, unsigned char *si2)
 {
-  si1[0] = 0;
-  si2[0] = 0;
-  if (memcmp(bc, BC_Speech, 3) == 0) {         /* Speech */
-       si1[0] = 1;
+       si1[0] = 0;
+       si2[0] = 0;
+
+       switch (bc[0] & 0x7f) {
+               case 0x00: /* Speech */
+                       si1[0] = 1;
 #ifdef EICON_FULL_SERVICE_OKTETT
-       si2[0] = 1;
+                       si1[0] = sin[0];
+                       si2[0] = sin[1];
 #endif
-  }
-  if (memcmp(bc, BC_31khz, 3) == 0) {          /* 3.1kHz audio */
-       si1[0] = 1;
+                       break;
+               case 0x10: /* 3.1 Khz audio */
+                       si1[0] = 1;
 #ifdef EICON_FULL_SERVICE_OKTETT
-       si2[0] = 2;
-       if (memcmp(hlc, HLC_faxg3, 2) == 0) {   /* Fax Gr.2/3 */
-               si1[0] = 2;
-       }
+                       si1[0] = sin[0];
+                       si2[0] = sin[1];
 #endif
-  }
-  if (memcmp(bc, BC_64k, 2) == 0) {            /* unrestricted 64 kbits */
-       si1[0] = 7;
-  }
-  if (memcmp(bc, BC_video, 3) == 0) {          /* video */
-       si1[0] = 4;
-  }
+                       break;
+               case 0x08: /* Unrestricted digital information */
+                       si1[0] = 7;
+                       si2[0] = sin[1];
+                       break;
+               case 0x09: /* Restricted digital information */
+                       si1[0] = 2;
+                       break;
+               case 0x11:
+                       /* Unrestr. digital information  with
+                        * tones/announcements ( or 7 kHz audio
+                        */
+                       si1[0] = 3;
+                       break;
+               case 0x18: /* Video */
+                       si1[0] = 4;
+                       break;
+       }
+       switch (bc[1] & 0x7f) {
+               case 0x40: /* packed mode */
+                       si1[0] = 8;
+                       break;
+               case 0x10: /* 64 kbit */
+               case 0x11: /* 2*64 kbit */
+               case 0x13: /* 384 kbit */
+               case 0x15: /* 1536 kbit */
+               case 0x17: /* 1920 kbit */
+                       /* moderate = bc[1] & 0x7f; */
+                       break;
+       }
 }
 
 /********************* FAX stuff ***************************/
@@ -1225,7 +1169,7 @@ idi_send_edata(eicon_card *card, eicon_chan *chan)
 
        reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
 
-       reqbuf->Req = IDI_N_EDATA;
+       reqbuf->Req = N_EDATA;
        reqbuf->ReqCh = chan->e.IndCh;
        reqbuf->ReqId = 1;
 
@@ -1359,7 +1303,7 @@ idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
                        eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength);
                        break;
        }
-       idi_send_data(card, chan, 0, skb, 0);
+       idi_send_data(card, chan, 0, skb, 0, 0);
 }
 
 void
@@ -1913,7 +1857,7 @@ idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf
        OutBuf->Len = 0;
        OutBuf->Next = OutBuf->Data;
 
-       return(idi_send_data(ccard, chan, 0, skb, 1));
+       return(idi_send_data(ccard, chan, 0, skb, 1, 0));
 }
 
 int
@@ -1958,6 +1902,8 @@ idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
 
         if (chan->queued + skb->len > 1200)
                 return 0;
+       if (chan->pqueued > 1)
+               return 0;
 
        InBuf.Data = skb->data;
        InBuf.Size = skb->len;
@@ -2183,6 +2129,7 @@ idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
        }
        if ((chan->fax->code > 1) && (chan->fax->code < 120))
                chan->fax->code += 120;
+       eicon_log(ccard, 8, "idi_fax: Ch%d: Hangup (code=%d)\n", chan->No, chan->fax->code);
        chan->fax->r_code = ISDN_TTY_FAX_HNG;
        cmd.driver = ccard->myid;
        cmd.command = ISDN_STAT_FAXIND;
@@ -2224,7 +2171,7 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int
 
        reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
 
-       reqbuf->Req = IDI_N_UDATA;
+       reqbuf->Req = N_UDATA;
        reqbuf->ReqCh = chan->e.IndCh;
        reqbuf->ReqId = 1;
 
@@ -2418,12 +2365,12 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                while((skb2 = skb_dequeue(&chan->e.X))) {
                                        dev_kfree_skb(skb2);
                                }
-                               save_flags(flags);
-                               cli();
+                               spin_lock_irqsave(&eicon_lock, flags);
                                chan->queued = 0;
+                               chan->pqueued = 0;
                                chan->waitq = 0;
                                chan->waitpq = 0;
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
                                if (message.e_cau[0] & 0x7f) {
                                        cmd.driver = ccard->myid;
                                        cmd.arg = chan->No;
@@ -2433,10 +2380,6 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                        ccard->interface.statcallb(&cmd);
                                }
                                chan->cause[0] = 0; 
-#ifdef CONFIG_ISDN_TTY_FAX
-                               if (!chan->e.B2Id)
-                                       chan->fax = 0;
-#endif
                                if (((chan->fsm_state == EICON_STATE_ACTIVE) ||
                                    (chan->fsm_state == EICON_STATE_WMCONN)) ||
                                    ((chan->l2prot == ISDN_PROTO_L2_FAX) &&
@@ -2446,6 +2389,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                        if (chan->e.B2Id)
                                                idi_do_req(ccard, chan, REMOVE, 1);
                                        chan->statectrl &= ~WAITING_FOR_HANGUP;
+                                       chan->statectrl &= ~IN_HOLD;
                                        if (chan->statectrl & HAVE_CONN_REQ) {
                                                eicon_log(ccard, 32, "idi_req: Ch%d: queueing delayed conn_req\n", chan->No);
                                                chan->statectrl &= ~HAVE_CONN_REQ;
@@ -2463,6 +2407,9 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                                cmd.command = ISDN_STAT_DHUP;
                                                ccard->interface.statcallb(&cmd);
                                                eicon_idi_listen_req(ccard, chan);
+#ifdef CONFIG_ISDN_TTY_FAX
+                                               chan->fax = 0;
+#endif
                                        }
                                }
                                break;
@@ -2475,7 +2422,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                        break;
                                }
                                chan->fsm_state = EICON_STATE_ICALL;
-                               idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2);
+                               idi_bc2si(message.bc, message.hlc, message.sin, &chan->si1, &chan->si2);
                                strcpy(chan->cpn, message.cpn + 1);
                                strcpy(chan->oad, message.oad);
                                strcpy(chan->dsa, message.dsa);
@@ -2553,12 +2500,15 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                                case ISDN_PROTO_L2_MODEM:
                                                        /* do nothing, wait for connect */
                                                        break;
+                                               case ISDN_PROTO_L2_V11096:
+                                               case ISDN_PROTO_L2_V11019:
+                                               case ISDN_PROTO_L2_V11038:
                                                case ISDN_PROTO_L2_TRANS:
-                                                       idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+                                                       idi_do_req(ccard, chan, N_CONNECT, 1);
                                                        break;
                                                default:
                                                        /* On most incoming calls we use automatic connect */
-                                                       /* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
+                                                       /* idi_do_req(ccard, chan, N_CONNECT, 1); */
                                        }
                                } else {
                                        if (chan->fsm_state != EICON_STATE_ACTIVE)
@@ -2568,33 +2518,50 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                        case CALL_CON:
                                eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
                                if (chan->fsm_state == EICON_STATE_OCALL) {
-                                       chan->fsm_state = EICON_STATE_OBWAIT;
-                                       cmd.driver = ccard->myid;
-                                       cmd.command = ISDN_STAT_DCONN;
-                                       cmd.arg = chan->No;
-                                       ccard->interface.statcallb(&cmd);
-
                                        /* check if old NetID has been removed */
                                        if (chan->e.B2Id) {
                                                eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n",
                                                        chan->No, chan->e.B2Id);
                                                idi_do_req(ccard, chan, REMOVE, 1);
                                        }
-
-                                       idi_do_req(ccard, chan, ASSIGN, 1); 
-                                       idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
 #ifdef CONFIG_ISDN_TTY_FAX
                                        if (chan->l2prot == ISDN_PROTO_L2_FAX) {
-                                               if (chan->fax)
+                                               if (chan->fax) {
                                                        chan->fax->phase = ISDN_FAX_PHASE_A;
+                                               } else {
+                                                       eicon_log(ccard, 1, "idi_ind: Call_Con with NULL fax struct, ERROR\n");
+                                                       idi_hangup(ccard, chan);
+                                                       break;
+                                               }
                                        }
 #endif
+                                       chan->fsm_state = EICON_STATE_OBWAIT;
+                                       cmd.driver = ccard->myid;
+                                       cmd.command = ISDN_STAT_DCONN;
+                                       cmd.arg = chan->No;
+                                       ccard->interface.statcallb(&cmd);
+
+                                       idi_do_req(ccard, chan, ASSIGN, 1); 
+                                       idi_do_req(ccard, chan, N_CONNECT, 1);
                                } else
-                               idi_hangup(ccard, chan);
+                                       idi_hangup(ccard, chan);
                                break;
                        case AOC_IND:
                                eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No);
                                break;
+                       case CALL_HOLD_ACK:
+                               chan->statectrl |= IN_HOLD;
+                               eicon_log(ccard, 8, "idi_ind: Ch%d: Call Hold Ack\n", chan->No);
+                               break;
+                       case SUSPEND_REJ:
+                               eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Rejected\n", chan->No);
+                               break;
+                       case SUSPEND:
+                               eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Ack\n", chan->No);
+                               break;
+                       case RESUME:
+                               eicon_log(ccard, 8, "idi_ind: Ch%d: Resume Ack\n", chan->No);
+                               break;
                        default:
                                eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
                }
@@ -2613,7 +2580,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                } 
                else
                switch(ind->Ind) {
-                       case IDI_N_CONNECT_ACK:
+                       case N_CONNECT_ACK:
                                eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
                                if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
                                        chan->fsm_state = EICON_STATE_WMCONN;
@@ -2634,7 +2601,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                                }
                                        }
                                        else {
-                                               eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
+                                               eicon_log(ccard, 1, "idi_ind: N_Connect_Ack with NULL fax struct, ERROR\n");
                                        }
 #endif
                                        break;
@@ -2646,10 +2613,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                strcpy(cmd.parm.num, "64000");
                                ccard->interface.statcallb(&cmd);
                                break; 
-                       case IDI_N_CONNECT:
+                       case N_CONNECT:
                                eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
                                chan->e.IndCh = ind->IndCh;
-                               if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
+                               if (chan->e.B2Id) idi_do_req(ccard, chan, N_CONNECT_ACK, 1);
                                if (chan->l2prot == ISDN_PROTO_L2_FAX) {
                                        break;
                                }
@@ -2664,43 +2631,47 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                strcpy(cmd.parm.num, "64000");
                                ccard->interface.statcallb(&cmd);
                                break; 
-                       case IDI_N_DISC:
-                               eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No);
+                       case N_DISC:
+                               eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc\n", chan->No);
                                if (chan->e.B2Id) {
                                        while((skb2 = skb_dequeue(&chan->e.X))) {
                                                dev_kfree_skb(skb2);
                                        }
-                                       idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
+                                       idi_do_req(ccard, chan, N_DISC_ACK, 1);
                                        idi_do_req(ccard, chan, REMOVE, 1);
                                }
 #ifdef CONFIG_ISDN_TTY_FAX
-                               if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+                               if ((chan->l2prot == ISDN_PROTO_L2_FAX) && (chan->fax)){
                                        idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
                                        idi_fax_hangup(ccard, chan);
                                }
 #endif
                                chan->e.IndCh = 0;
-                               save_flags(flags);
-                               cli();
+                               spin_lock_irqsave(&eicon_lock, flags);
                                chan->queued = 0;
+                               chan->pqueued = 0;
                                chan->waitq = 0;
                                chan->waitpq = 0;
-                               restore_flags(flags);
-                               idi_do_req(ccard, chan, HANGUP, 0);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
+                               if (!(chan->statectrl & IN_HOLD)) {
+                                       idi_do_req(ccard, chan, HANGUP, 0);
+                               }
                                if (chan->fsm_state == EICON_STATE_ACTIVE) {
                                        cmd.driver = ccard->myid;
                                        cmd.command = ISDN_STAT_BHUP;
                                        cmd.arg = chan->No;
                                        ccard->interface.statcallb(&cmd);
                                        chan->fsm_state = EICON_STATE_NULL;
-                                       chan->statectrl |= WAITING_FOR_HANGUP;
+                                       if (!(chan->statectrl & IN_HOLD)) {
+                                               chan->statectrl |= WAITING_FOR_HANGUP;
+                                       }
                                }
 #ifdef CONFIG_ISDN_TTY_FAX
                                chan->fax = 0;
 #endif
                                break; 
-                       case IDI_N_DISC_ACK:
-                               eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
+                       case N_DISC_ACK:
+                               eicon_log(ccard, 16, "idi_ind: Ch%d: N_Disc_Ack\n", chan->No);
 #ifdef CONFIG_ISDN_TTY_FAX
                                if (chan->l2prot == ISDN_PROTO_L2_FAX) {
                                        idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
@@ -2708,10 +2679,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                }
 #endif
                                break; 
-                       case IDI_N_DATA_ACK:
-                               eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
+                       case N_DATA_ACK:
+                               eicon_log(ccard, 128, "idi_ind: Ch%d: N_Data_Ack\n", chan->No);
                                break;
-                       case IDI_N_DATA:
+                       case N_DATA:
                                skb_pull(skb, sizeof(eicon_IND) - 1);
                                eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
                                if (chan->l2prot == ISDN_PROTO_L2_FAX) {
@@ -2723,11 +2694,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                        free_buff = 0; 
                                }
                                break; 
-                       case IDI_N_UDATA:
+                       case N_UDATA:
                                idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
                                break; 
 #ifdef CONFIG_ISDN_TTY_FAX
-                       case IDI_N_EDATA:
+                       case N_EDATA:
                                idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
                                break; 
 #endif
@@ -2747,6 +2718,8 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 {
        ulong flags;
        isdn_ctrl cmd;
+       int tqueued = 0;
+       int twaitpq = 0;
 
        if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
                /* I dont know why this happens, should not ! */
@@ -2770,16 +2743,15 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
                        eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
                                ack->Reference, chan->e.ref);
                }
-               save_flags(flags);
-               cli();
+               spin_lock_irqsave(&eicon_lock, flags);
                ccard->IdTable[ack->RcId] = NULL;
-               eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
-                       ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
                if (!chan->e.ReqCh) 
                        chan->e.D3Id = 0;
                else
                        chan->e.B2Id = 0;
-               restore_flags(flags);
+               spin_unlock_irqrestore(&eicon_lock, flags);
+               eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
+                       ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
                return 1;
        }
 
@@ -2790,25 +2762,21 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
        } else {
        /* Network layer */
                switch(chan->e.Req & 0x0f) {
-                       case IDI_N_CONNECT:
+                       case N_CONNECT:
                                chan->e.IndCh = ack->RcCh;
                                eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
                                        ack->RcId, ack->RcCh, ack->Reference);
                                break;
-                       case IDI_N_MDATA:
-                       case IDI_N_DATA:
-                               if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
-                                       if (chan->queued) {
-                                               cmd.driver = ccard->myid;
-                                               cmd.command = ISDN_STAT_BSENT;
-                                               cmd.arg = chan->No;
-                                               cmd.parm.length = chan->waitpq;
-                                               ccard->interface.statcallb(&cmd);
-                                       }
-                                       save_flags(flags);
-                                       cli();
+                       case N_MDATA:
+                       case N_DATA:
+                               tqueued = chan->queued;
+                               twaitpq = chan->waitpq;
+                               if ((chan->e.Req & 0x0f) == N_DATA) {
+                                       spin_lock_irqsave(&eicon_lock, flags);
                                        chan->waitpq = 0;
-                                       restore_flags(flags);
+                                       if(chan->pqueued)
+                                               chan->pqueued--;
+                                       spin_unlock_irqrestore(&eicon_lock, flags);
 #ifdef CONFIG_ISDN_TTY_FAX
                                        if (chan->l2prot == ISDN_PROTO_L2_FAX) {
                                                if (((chan->queued - chan->waitq) < 1) &&
@@ -2828,11 +2796,17 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
                                        }
 #endif
                                }
-                               save_flags(flags);
-                               cli();
+                               spin_lock_irqsave(&eicon_lock, flags);
                                chan->queued -= chan->waitq;
                                if (chan->queued < 0) chan->queued = 0;
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
+                               if (((chan->e.Req & 0x0f) == N_DATA) && (tqueued)) {
+                                       cmd.driver = ccard->myid;
+                                       cmd.command = ISDN_STAT_BSENT;
+                                       cmd.arg = chan->No;
+                                       cmd.parm.length = twaitpq;
+                                       ccard->interface.statcallb(&cmd);
+                               }
                                break;
                        default:
                                eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
@@ -2858,11 +2832,10 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                return;
        }
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&eicon_lock, flags);
        if ((chan = ccard->IdTable[ack->RcId]) != NULL)
                dCh = chan->No;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&eicon_lock, flags);
 
        switch (ack->Rc) {
                case OK_FC:
@@ -2890,8 +2863,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                                eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n",
                                        chan->No, chan->e.D3Id, chan->e.B2Id);
                        }
-                       save_flags(flags);
-                       cli();
+                       spin_lock_irqsave(&eicon_lock, flags);
                        for(j = 0; j < ccard->nchannels + 1; j++) {
                                if ((ccard->bch[j].e.ref == ack->Reference) &&
                                        (ccard->bch[j].e.Req == ASSIGN)) {
@@ -2901,12 +2873,12 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                                                ccard->bch[j].e.B2Id  = ack->RcId;
                                        ccard->IdTable[ack->RcId] = &ccard->bch[j];
                                        chan = &ccard->bch[j];
-                                       eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, 
-                                               ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
                                        break;
                                }
-                       }               
-                       restore_flags(flags);
+                       }
+                       spin_unlock_irqrestore(&eicon_lock, flags);
+                       eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, 
+                               ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
                        if (j > ccard->nchannels) {
                                eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n", 
                                        ack->Reference, ack->RcId);
@@ -2917,6 +2889,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                case UNKNOWN_COMMAND:
                case WRONG_COMMAND:
                case WRONG_ID:
+               case ADAPTER_DEAD:
                case WRONG_CH:
                case UNKNOWN_IE:
                case WRONG_IE:
@@ -2949,19 +2922,18 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                                ccard->interface.statcallb(&cmd);
                        }
        }
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&eicon_lock, flags);
        if (chan) {
                chan->e.ref = 0;
                chan->e.busy = 0;
        }
-       restore_flags(flags);
+       spin_unlock_irqrestore(&eicon_lock, flags);
        dev_kfree_skb(skb);
        eicon_schedule_tx(ccard);
 }
 
 int
-idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que)
+idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk)
 {
         struct sk_buff *xmit_skb;
         struct sk_buff *skb2;
@@ -2985,13 +2957,14 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
                return -1;
         if (!len)
                 return 0;
-       if (chan->queued + len > EICON_MAX_QUEUE)
+
+       if ((chk) && (chan->pqueued > 1))
                return 0;
 
-       eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len);
+       eicon_log(card, 128, "idi_snd: Ch%d: %d bytes (Pqueue=%d)\n",
+               chan->No, len, chan->pqueued);
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&eicon_lock, flags);
        while(offset < len) {
 
                plen = ((len - offset) > 270) ? 270 : len - offset;
@@ -3000,7 +2973,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
                skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
 
                if ((!xmit_skb) || (!skb2)) {
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&eicon_lock, flags);
                        eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No);
                        if (xmit_skb) 
                                dev_kfree_skb(skb);
@@ -3013,13 +2986,10 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
                chan2->ptr = chan;
 
                reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
-               if (((len - offset) > 270) &&
-                       (chan->l2prot != ISDN_PROTO_L2_MODEM) &&
-                       (chan->l2prot != ISDN_PROTO_L2_FAX) &&
-                       (chan->l2prot != ISDN_PROTO_L2_TRANS)) {
-                       reqbuf->Req = IDI_N_MDATA;
+               if ((len - offset) > 270) { 
+                       reqbuf->Req = N_MDATA;
                } else {
-                       reqbuf->Req = IDI_N_DATA;
+                       reqbuf->Req = N_DATA;
                        /* if (ack) reqbuf->Req |= N_D_BIT; */
                }       
                reqbuf->ReqCh = chan->e.IndCh;
@@ -3033,9 +3003,11 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
 
                offset += plen;
        }
-       if (que)
+       if (que) {
                chan->queued += len;
-       restore_flags(flags);
+               chan->pqueued++;
+       }
+       spin_unlock_irqrestore(&eicon_lock, flags);
        eicon_schedule_tx(card);
         dev_kfree_skb(skb);
         return len;
@@ -3073,7 +3045,7 @@ eicon_idi_manage_assign(eicon_card *card)
         reqbuf->XBuffer.P[0] = 0;
         reqbuf->Req = ASSIGN;
         reqbuf->ReqCh = 0;
-        reqbuf->ReqId = 0xe0;
+        reqbuf->ReqId = MAN_ID;
         reqbuf->XBuffer.length = 1;
         reqbuf->Reference = 2; /* Man Entity */
 
@@ -3199,7 +3171,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
         reqbuf->XBuffer.P[1] = manbuf->length[0] + 1;
 
         reqbuf->XBuffer.P[l++] = 0;
-        reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */
+        reqbuf->Req = (manbuf->count) ? manbuf->count : MAN_READ;
         reqbuf->ReqCh = 0;
         reqbuf->ReqId = 1;
         reqbuf->XBuffer.length = l;
index 2fe6167a4347238833f541951a7dd590cd99d01b..a1103921931260d4347c415d8d37112858ab22da 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.h,v 1.9 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon_idi.h,v 1.11 2000/05/07 08:51:04 armin Exp $
  *
  * ISDN lowlevel-module for the Eicon active cards.
  * IDI-Interface
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_idi.h,v $
- * Revision 1.9  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.8  1999/11/25 11:43:27  armin
- * Fixed statectrl and connect message.
- * X.75 fix and HDLC/transparent with autoconnect.
- * Minor cleanup.
- *
- * Revision 1.7  1999/08/22 20:26:46  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.6  1999/07/25 15:12:04  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.5  1999/07/11 17:16:26  armin
- * Bugfixes in queue handling.
- * Added DSP-DTMF decoder functions.
- * Reorganized ack_handler.
- *
- * Revision 1.4  1999/03/29 11:19:44  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.3  1999/03/02 12:37:45  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.2  1999/01/24 20:14:18  armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.1  1999/01/01 18:09:42  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
  *
  */
 
-#ifndef IDI_H
-#define IDI_H
+#ifndef E_IDI_H
+#define E_IDI_H
 
 #include <linux/config.h>
 
-#define ASSIGN  0x01
-#define REMOVE  0xff
-       
-#define CALL_REQ 1      /* call request                             */
-#define CALL_CON 1      /* call confirmation                        */
-#define CALL_IND 2      /* incoming call connected                  */
-#define LISTEN_REQ 2    /* listen request                           */
-#define HANGUP 3        /* hangup request/indication                */
-#define SUSPEND 4       /* call suspend request/confirm             */
-#define RESUME 5        /* call resume request/confirm              */
-#define SUSPEND_REJ 6   /* suspend rejected indication              */
-#define USER_DATA 8     /* user data for user to user signaling     */
-#define CONGESTION 9    /* network congestion indication            */
-#define INDICATE_REQ 10 /* request to indicate an incoming call     */
-#define INDICATE_IND 10 /* indicates that there is an incoming call */
-#define CALL_RES 11     /* accept an incoming call                  */
-#define CALL_ALERT 12   /* send ALERT for incoming call             */
-#define INFO_REQ 13     /* INFO request                             */
-#define INFO_IND 13     /* INFO indication                          */
-#define REJECT 14       /* reject an incoming call                  */
-#define RESOURCES 15    /* reserve B-Channel hardware resources     */
-#define TEL_CTRL 16     /* Telephone control request/indication     */
-#define STATUS_REQ 17   /* Request D-State (returned in INFO_IND)   */
-#define FAC_REG_REQ 18  /* connection idependent fac registration   */
-#define FAC_REG_ACK 19  /* fac registration acknowledge             */
-#define FAC_REG_REJ 20  /* fac registration reject                  */
-#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call       */
-#define AOC_IND       26/* Advice of Charge                         */
-
-#define IDI_N_MDATA         (0x01)
-#define IDI_N_CONNECT       (0x02)
-#define IDI_N_CONNECT_ACK   (0x03)
-#define IDI_N_DISC          (0x04)
-#define IDI_N_DISC_ACK      (0x05)
-#define IDI_N_RESET         (0x06)
-#define IDI_N_RESET_ACK     (0x07)
-#define IDI_N_DATA          (0x08)
-#define IDI_N_EDATA         (0x09)
-#define IDI_N_UDATA         (0x0a)
-#define IDI_N_BDATA         (0x0b)
-#define IDI_N_DATA_ACK      (0x0c)
-#define IDI_N_EDATA_ACK     (0x0d)
+#undef N_DATA
+#undef ID_MASK
 
-#define N_Q_BIT         0x10    /* Q-bit for req/ind                */
-#define N_M_BIT         0x20    /* M-bit for req/ind                */
-#define N_D_BIT         0x40    /* D-bit for req/ind                */
+#include "pc.h"
 
+#define AOC_IND  26            /* Advice of Charge                         */
+#define PI  0x1e                /* Progress Indicator               */
+#define NI  0x27                /* Notification Indicator           */
 
-#define SHIFT 0x90              /* codeset shift                    */
-#define MORE 0xa0               /* more data                        */
-#define CL 0xb0                 /* congestion level                 */
-
-        /* codeset 0                                                */
-
-#define BC  0x04                /* Bearer Capability                */
-#define CAU 0x08                /* cause                            */
-#define CAD 0x0c                /* Connected address                */
-#define CAI 0x10                /* call identity                    */
-#define CHI 0x18                /* channel identification           */
-#define LLI 0x19                /* logical link id                  */
-#define CHA 0x1a                /* charge advice                    */
-#define FTY 0x1c
-#define PI  0x1e               /* Progress Indicator               */
-#define NI  0x27               /* Notification Indicator           */
-#define DT  0x29                /* ETSI date/time                   */
-#define KEY 0x2c                /* keypad information element       */
-#define DSP 0x28                /* display                          */
-#define OAD 0x6c                /* origination address              */
-#define OSA 0x6d                /* origination sub-address          */
-#define CPN 0x70                /* called party number              */
-#define DSA 0x71                /* destination sub-address          */
-#define RDN 0x74               /* redirecting number               */
-#define LLC 0x7c                /* low layer compatibility          */
-#define HLC 0x7d                /* high layer compatibility         */
-#define UUI 0x7e                /* user user information            */
-#define ESC 0x7f                /* escape extension                 */
-
-#define DLC 0x20                /* data link layer configuration    */
-#define NLC 0x21                /* network layer configuration      */
-
-        /* codeset 6                                                */
-
-#define SIN 0x01                /* service indicator                */
-#define CIF 0x02                /* charging information             */
-#define DATE 0x03               /* date                             */
-#define CPS 0x07                /* called party status              */
-
-/*------------------------------------------------------------------*/
-/* return code coding                                               */
-/*------------------------------------------------------------------*/
-
-#define UNKNOWN_COMMAND         0x01    /* unknown command          */
-#define WRONG_COMMAND           0x02    /* wrong command            */
-#define WRONG_ID                0x03    /* unknown task/entity id   */
-#define WRONG_CH                0x04    /* wrong task/entity id     */
-#define UNKNOWN_IE              0x05    /* unknown information el.  */
-#define WRONG_IE                0x06    /* wrong information el.    */
-#define OUT_OF_RESOURCES        0x07    /* card out of res.         */
-#define N_FLOW_CONTROL          0x10    /* Flow-Control, retry      */
-#define ASSIGN_RC               0xe0    /* ASSIGN acknowledgement   */
-#define ASSIGN_OK               0xef    /* ASSIGN OK                */
-#define OK_FC                   0xfc    /* Flow-Control RC          */
-#define READY_INT               0xfd    /* Ready interrupt          */
-#define TIMER_INT               0xfe    /* timer interrupt          */
-#define OK                      0xff    /* command accepted         */
-
-/*------------------------------------------------------------------*/
+#define CALL_HOLD      0x22
+#define CALL_HOLD_ACK  0x24
 
 /* defines for statectrl */
 #define WAITING_FOR_HANGUP     0x01
 #define HAVE_CONN_REQ          0x02
+#define IN_HOLD                        0x04
 
 typedef struct {
        char cpn[32];
@@ -241,26 +103,6 @@ typedef struct {
   eicon_PBUFFER RBuffer;
 } eicon_IND;
 
-typedef struct {
-  __u16 NextReq  __attribute__ ((packed));  /* pointer to next Req Buffer */
-  __u16 NextRc   __attribute__ ((packed));  /* pointer to next Rc Buffer  */
-  __u16 NextInd  __attribute__ ((packed));  /* pointer to next Ind Buffer */
-  __u8 ReqInput  __attribute__ ((packed));  /* number of Req Buffers sent */
-  __u8 ReqOutput  __attribute__ ((packed)); /* number of Req Buffers returned */
-  __u8 ReqReserved  __attribute__ ((packed));/*number of Req Buffers reserved */
-  __u8 Int  __attribute__ ((packed));       /* ISDN-P interrupt           */
-  __u8 XLock  __attribute__ ((packed));     /* Lock field for arbitration */
-  __u8 RcOutput  __attribute__ ((packed));  /* number of Rc buffers received */
-  __u8 IndOutput  __attribute__ ((packed)); /* number of Ind buffers received */
-  __u8 IMask  __attribute__ ((packed));     /* Interrupt Mask Flag        */
-  __u8 Reserved1[2]  __attribute__ ((packed)); /* reserved field, do not use */
-  __u8 ReadyInt  __attribute__ ((packed));  /* request field for ready int */
-  __u8 Reserved2[12]  __attribute__ ((packed)); /* reserved field, do not use */
-  __u8 InterfaceType  __attribute__ ((packed)); /* interface type 1=16K    */
-  __u16 Signature  __attribute__ ((packed));    /* ISDN-P initialized ind  */
-  __u8 B[1];                            /* buffer space for Req,Ind and Rc */
-} eicon_pr_ram;
-
 typedef struct {
        __u8            *Data;
        unsigned int    Size;
@@ -278,8 +120,9 @@ extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
 extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb);
 extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb);
 extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb);
-extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que);
+extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk);
 extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value);
+extern int capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm);
 #ifdef CONFIG_ISDN_TTY_FAX
 extern void idi_fax_cmd(eicon_card *card, eicon_chan *chan);
 extern int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb);
index 4f4180ed6effcb2b6925cdd6f4c50445b6279ae8..6f294e8b77c12399561bb4b8b334d6b313ccc462 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_io.c,v 1.10 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon_io.c,v 1.13 2000/05/07 08:51:04 armin Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  * Code for communicating with hardware.
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_io.c,v $
- * Revision 1.10  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.9  1999/11/18 20:55:25  armin
- * Ready_Int fix of ISA cards.
- *
- * Revision 1.8  1999/10/08 22:09:34  armin
- * Some fixes of cards interface handling.
- * Bugfix of NULL pointer occurence.
- * Changed a few log outputs.
- *
- * Revision 1.7  1999/09/26 14:17:53  armin
- * Improved debug and log via readstat()
- *
- * Revision 1.6  1999/09/21 20:35:43  armin
- * added more error checking.
- *
- * Revision 1.5  1999/08/31 11:20:11  paul
- * various spelling corrections (new checksums may be needed, Karsten!)
- *
- * Revision 1.4  1999/08/22 20:26:47  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.3  1999/08/18 20:17:01  armin
- * Added XLOG function for all cards.
- * Bugfix of alloc_skb NULL pointer.
- *
- * Revision 1.2  1999/07/25 15:12:05  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.1  1999/03/29 11:19:45  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- *
  */
 
 
 #include <linux/config.h>
 #include "eicon.h"
+#include "uxio.h"
 
 void
 eicon_io_rcv_dispatch(eicon_card *ccard) {
@@ -85,12 +45,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
        while((skb = skb_dequeue(&ccard->rcvq))) {
                ind = (eicon_IND *)skb->data;
 
-               save_flags(flags);
-               cli();
+               spin_lock_irqsave(&eicon_lock, flags);
                if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
+                       spin_unlock_irqrestore(&eicon_lock, flags);
                        if (DebugVar & 1) {
                                switch(ind->Ind) {
-                                       case IDI_N_DISC_ACK: 
+                                       case N_DISC_ACK: 
                                                /* doesn't matter if this happens */ 
                                                break;
                                        default: 
@@ -99,11 +59,10 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                                                        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
                                }
                        }
-                       restore_flags(flags);
                        dev_kfree_skb(skb);
                        continue;
                }
-               restore_flags(flags);
+               spin_unlock_irqrestore(&eicon_lock, flags);
 
                if (chan->e.complete) { /* check for rec-buffer chaining */
                        if (ind->MLength == ind->RBuffer.length) {
@@ -119,12 +78,9 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                        }
                }
                else {
-                       save_flags(flags);
-                       cli();
                        if (!(skb2 = skb_dequeue(&chan->e.R))) {
                                chan->e.complete = 1;
                                eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n");
-                               restore_flags(flags);
                                dev_kfree_skb(skb);
                                continue;       
                        }
@@ -133,7 +89,6 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                                        GFP_ATOMIC);
                        if (!skb_new) {
                                eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n");
-                               restore_flags(flags);
                                dev_kfree_skb(skb);
                                dev_kfree_skb(skb2);
                                continue;       
@@ -152,14 +107,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                        dev_kfree_skb(skb2);
                        if (ind->MLength == ind->RBuffer.length) {
                                chan->e.complete = 2;
-                               restore_flags(flags);
                                idi_handle_ind(ccard, skb_new);
                                continue;
                        }
                        else {
                                chan->e.complete = 0;
                                skb_queue_tail(&chan->e.R, skb_new);
-                               restore_flags(flags);
                                continue;
                        }
                }
@@ -181,242 +134,120 @@ eicon_io_ack_dispatch(eicon_card *ccard) {
 
 
 /*
- *  IO-Functions for different card-types
+ *  IO-Functions for ISA cards
  */
 
 u8 ram_inb(eicon_card *card, void *adr) {
-        eicon_pci_card *pcard;
-        eicon_isa_card *icard;
         u32 addr = (u32) adr;
        
-       pcard = &card->hwif.pci;
-       icard = &card->hwif.isa;
-
-        switch(card->type) {
-                case EICON_CTYPE_MAESTRA:
-                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
-                        return(inb((u16)pcard->PCIreg + M_DATA));
-                case EICON_CTYPE_MAESTRAP:
-                case EICON_CTYPE_S2M:
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-                        return(readb(addr));
-        }
- return(0);
+       return(readb(addr));
 }
 
 u16 ram_inw(eicon_card *card, void *adr) {
-        eicon_pci_card *pcard;
-        eicon_isa_card *icard;
         u32 addr = (u32) adr;
-       
-       pcard = &card->hwif.pci;
-       icard = &card->hwif.isa;
-
-        switch(card->type) {
-                case EICON_CTYPE_MAESTRA:
-                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
-                        return(inw((u16)pcard->PCIreg + M_DATA));
-                case EICON_CTYPE_MAESTRAP:
-                case EICON_CTYPE_S2M:
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-                        return(readw(addr));
-        }
- return(0);
+
+       return(readw(addr));
 }
 
 void ram_outb(eicon_card *card, void *adr, u8 data) {
-        eicon_pci_card *pcard;
-        eicon_isa_card *icard;
         u32 addr = (u32) adr;
 
-       pcard = &card->hwif.pci;
-       icard = &card->hwif.isa;
-
-        switch(card->type) {
-                case EICON_CTYPE_MAESTRA:
-                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
-                        outb((u8)data, (u16)pcard->PCIreg + M_DATA);
-                        break;
-                case EICON_CTYPE_MAESTRAP:
-                case EICON_CTYPE_S2M:
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-                        writeb(data, addr);
-                        break;
-        }
+       writeb(data, addr);
 }
 
 void ram_outw(eicon_card *card, void *adr , u16 data) {
-        eicon_pci_card *pcard;
-        eicon_isa_card *icard;
         u32 addr = (u32) adr;
 
-       pcard = &card->hwif.pci;
-       icard = &card->hwif.isa;
-
-        switch(card->type) {
-                case EICON_CTYPE_MAESTRA:
-                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
-                        outw((u16)data, (u16)pcard->PCIreg + M_DATA);
-                        break;
-                case EICON_CTYPE_MAESTRAP:
-                case EICON_CTYPE_S2M:
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-                        writew(data, addr);
-                        break;
-        }
+       writew(data, addr);
 }
 
 void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) {
-        int i;
-        switch(card->type) {
-                case EICON_CTYPE_MAESTRA:
-                        for(i = 0; i < len; i++) {
-                                writeb(ram_inb(card, adr + i), adrto + i);
-                        }
-                        break;
-                case EICON_CTYPE_MAESTRAP:
-                        memcpy(adrto, adr, len);
-                        break;
-                case EICON_CTYPE_S2M:
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-                        memcpy_fromio(adrto, adr, len);
-                        break;
-        }
+       memcpy_fromio(adrto, adr, len);
 }
 
 void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {
-        int i;
-        switch(card->type) {
-                case EICON_CTYPE_MAESTRA:
-                        for(i = 0; i < len; i++) {
-                                ram_outb(card, adrto + i, readb(adr + i));
-                        }
-                        break;
-                case EICON_CTYPE_MAESTRAP:
-                        memcpy(adrto, adr, len);
-                        break;
-                case EICON_CTYPE_S2M:
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-                        memcpy_toio(adrto, adr, len);
-                        break;
-        }
+       memcpy_toio(adrto, adr, len);
 }
 
+
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
 /*
- * XLOG
+ *  IDI-Callback function
  */
-int
-eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq)
+void
+eicon_idi_callback(ENTITY *de)
 {
-       int timeout, i;
-       int divas_shared_offset = 0;
+       eicon_card *ccard = (eicon_card *)de->R;
+       struct sk_buff *skb;
+       eicon_RC *ack;
+       eicon_IND *ind;
        int len = 0;
-       int stype = 0;
-       __u32 time = 0;
-       mi_pc_maint_t   *pcm = &xlogreq->pcm;
-        eicon_pci_card *pci_card = &card->hwif.pci;
-        eicon_isa_card *isa_card = &card->hwif.isa;
-       eicon_pr_ram  *prram = 0;
-        char *ram;
 
-       switch(card->type) {
-               case EICON_CTYPE_MAESTRAP:
-                       ram = (char *)pci_card->PCIram;
-                       prram = (eicon_pr_ram *)ram;
-                       divas_shared_offset = DIVAS_SHARED_OFFSET;
-                       len = sizeof(mi_pc_maint_t);
-                       break;
-               case EICON_CTYPE_MAESTRA:
-                       prram = 0;
-                       divas_shared_offset = 0;
-                       len = sizeof(mi_pc_maint_t);
-                       break;
-               case EICON_CTYPE_S:
-               case EICON_CTYPE_SX:
-               case EICON_CTYPE_SCOM:
-               case EICON_CTYPE_QUADRO:
-               case EICON_CTYPE_S2M:
-                       prram = (eicon_pr_ram *)isa_card->shmem;
-                       divas_shared_offset = 0xfb80;
-                       len = sizeof(mi_pc_maint_t) - 78;
-                       stype = 1;
-                       break;
-               default:
-                       return -ENODEV;
-       }
-
-        memset(&(xlogreq->pcm), 0, sizeof(mi_pc_maint_t));
-
-        xlogreq->pcm.rc = 0;
-        xlogreq->pcm.req = 1; /* DO_LOG */
-
-        ram = ((char *)prram) + MIPS_MAINT_OFFS - divas_shared_offset;
-
-       ram_outb(card, ram+1, pcm->rc); 
-       ram_outb(card, ram+0, pcm->req); 
-
-        timeout = jiffies + 50;
-        while (timeout > jiffies) {
-               pcm->rc = ram_inb(card, ram+1);
-               pcm->req = ram_inb(card, ram+0);
-                if (!pcm->req) break;
-                SLEEP(10);
-        }
-
-       if (pcm->req) {
-               return XLOG_ERR_TIMEOUT;
-       }
-
-       if (pcm->rc != OK) {
-               return XLOG_ERR_DONE;
-       }
-       
-       ram_copyfromcard(card, pcm, ram, len);
-
-       if (stype) {
-               for (i=0; i<8; i++)
-                       ((__u8 *)pcm)[11-i] = ((__u8 *)pcm)[9-i];
-               time =  (__u32)pcm->data.w[2] * 3600    * 1000 +
-                       (__u32)pcm->data.w[1]           * 1000 +
-                       (__u32)pcm->data.b[1]           * 20 +
-                       (__u32)pcm->data.b[0]           ;
-               pcm->data.w[1] = (__u16) (time >> 16);
-               pcm->data.w[2] = (__u16) (time & 0x0000ffff);
-               pcm->data.w[0] = 2;
+       if (de->complete == 255) {
+               /* Return Code */
+               skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
+               if (!skb) {
+                       eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
+               } else {
+                       ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
+                       ack->Rc = de->Rc;
+                       if (de->Rc == ASSIGN_OK) {
+                               ack->RcId = de->Id;
+                               de->user[1] = de->Id;
+                       } else {
+                               ack->RcId = de->user[1];
+                       }
+                       ack->RcCh = de->RcCh;
+                       ack->Reference = de->user[0];
+                       skb_queue_tail(&ccard->rackq, skb);
+                       eicon_schedule_ack(ccard);
+                       eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",
+                               de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);
+               }
+       } else {
+               /* Indication */
+               if (de->complete) {
+                       len = de->RLength;
+               } else {
+                       len = 270;
+                       if (de->RLength <= 270)
+                               eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");
+               }
+               skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
+               if (!skb) {
+                       eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
+               } else {
+                       ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
+                       ind->Ind = de->Ind;
+                       ind->IndId = de->user[1];
+                       ind->IndCh = de->IndCh;
+                       ind->MInd  = de->Ind;
+                       ind->RBuffer.length = len;
+                       ind->MLength = de->RLength;
+                       memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);
+                       skb_queue_tail(&ccard->rcvq, skb);
+                       eicon_schedule_rx(ccard);
+                       eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",
+                               de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);
+               }
        }
 
-       return XLOG_OK;
+       de->RNum = 0;
+       de->RNR = 0;
+       de->Rc = 0;
+       de->Ind = 0;
 }
+#endif /* CONFIG_ISDN_DRV_EICON_PCI */
 
 /*
  *  Transmit-Function
  */
 void
 eicon_io_transmit(eicon_card *ccard) {
-        eicon_pci_card *pci_card;
         eicon_isa_card *isa_card;
         struct sk_buff *skb;
         struct sk_buff *skb2;
         unsigned long flags;
-        char *ram, *reg, *cfg;
        eicon_pr_ram  *prram = 0;
        eicon_isa_com   *com = 0;
        eicon_REQ *ReqOut = 0;
@@ -426,10 +257,11 @@ eicon_io_transmit(eicon_card *ccard) {
        int ReqCount;
        int scom = 0;
        int tmp = 0;
+       int tmpid = 0;
        int quloop = 1;
        int dlev = 0;
+       ENTITY *ep = 0;
 
-       pci_card = &ccard->hwif.pci;
        isa_card = &ccard->hwif.isa;
 
         if (!ccard) {
@@ -451,20 +283,17 @@ eicon_io_transmit(eicon_card *ccard) {
                        prram = (eicon_pr_ram *)isa_card->shmem;
                        break;
 #endif
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
                case EICON_CTYPE_MAESTRAP:
-                       scom = 0;
-                       ram = (char *)pci_card->PCIram;
-                       reg = (char *)pci_card->PCIreg;
-                       cfg = (char *)pci_card->PCIcfg;
-                       prram = (eicon_pr_ram *)ram;
+                       scom = 2;
+                       break;
+               case EICON_CTYPE_MAESTRAQ:
+                       scom = 2;
                        break;
                case EICON_CTYPE_MAESTRA:
-                       scom = 0;
-                       ram = (char *)pci_card->PCIram;
-                       reg = (char *)pci_card->PCIreg;
-                       cfg = (char *)pci_card->PCIcfg;
-                       prram = 0;
+                       scom = 2;
                        break;
+#endif
                default:
                        eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
                        return;
@@ -474,69 +303,91 @@ eicon_io_transmit(eicon_card *ccard) {
        if (!(skb2 = skb_dequeue(&ccard->sndq)))
                quloop = 0; 
        while(quloop) { 
-                save_flags(flags);
-                cli();
-               if (scom) {
+               spin_lock_irqsave(&eicon_lock, flags);
+               switch (scom) {
+                 case 1:
                        if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) {
                                if (!ccard->ReadyInt) {
                                        tmp = ram_inb(ccard, &com->ReadyInt) + 1;
                                        ram_outb(ccard, &com->ReadyInt, tmp);
                                        ccard->ReadyInt++;
                                }
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
                                skb_queue_head(&ccard->sndq, skb2);
                                        eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
                                return;
                        }
-               } else {
+                       break;
+                 case 0:
                        if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
                                skb_queue_head(&ccard->sndq, skb2);
                                        eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
                                return;
                        }
+                       break;
                }
-               restore_flags(flags);
+               spin_unlock_irqrestore(&eicon_lock, flags);
+
                chan2 = (eicon_chan_ptr *)skb2->data;
                chan = chan2->ptr;
                if (!chan->e.busy) {
                 if((skb = skb_dequeue(&chan->e.X))) { 
-                 save_flags(flags);
-                 cli();
+
                  reqbuf = (eicon_REQ *)skb->data;
                  if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
                        eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); 
                  } else {
-                       if (scom) {
+                       spin_lock_irqsave(&eicon_lock, flags);
+
+                       switch (scom) {
+                         case 1:
                                ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
                                ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
                                ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);
-                               
-                       } else {
+                               break;  
+                         case 0:
                                /* get address of next available request buffer */
                                ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];
                                ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);
                                ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
                                ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
                                ram_outb(ccard, &ReqOut->Req, reqbuf->Req); 
+                               break;
                        }
+
                        dlev = 160;
+
                        if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
 
                                if (!reqbuf->Reference) { /* Signal Layer */
-                                       if (scom)
+                                       switch (scom) {
+                                         case 1:
                                                ram_outb(ccard, &com->ReqId, chan->e.D3Id); 
-                                       else
+                                               break;
+                                         case 0:
                                                ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id); 
-
+                                               break;
+                                         case 2:
+                                               ep = &chan->de;
+                                               break;
+                                       }
+                                       tmpid = chan->e.D3Id;
                                        chan->e.ReqCh = 0; 
                                }
                                else {                  /* Net Layer */
-                                       if (scom)
+                                       switch(scom) {
+                                         case 1:
                                                ram_outb(ccard, &com->ReqId, chan->e.B2Id); 
-                                       else
+                                               break;
+                                         case 0:
                                                ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id); 
-
+                                               break;
+                                         case 2:
+                                               ep = &chan->be;
+                                               break;
+                                       }
+                                       tmpid = chan->e.B2Id;
                                        chan->e.ReqCh = 1;
                                        if (((reqbuf->Req & 0x0f) == 0x08) ||
                                           ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
@@ -548,51 +399,106 @@ eicon_io_transmit(eicon_card *ccard) {
 
                        } else {        /* It is an ASSIGN */
 
-                               if (scom)
+                               switch(scom) {
+                                 case 1:
                                        ram_outb(ccard, &com->ReqId, reqbuf->ReqId); 
-                               else
+                                       break;
+                                 case 0:
                                        ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId); 
+                                       break;
+                                 case 2:
+                                       if (!reqbuf->Reference) 
+                                               ep = &chan->de;
+                                       else
+                                               ep = &chan->be;
+                                       ep->Id = reqbuf->ReqId;
+                                       break;
+                               }
+                               tmpid = reqbuf->ReqId;
 
                                if (!reqbuf->Reference) 
                                        chan->e.ReqCh = 0; 
                                 else
                                        chan->e.ReqCh = 1; 
                        } 
-                       if (scom)
+
+                       switch(scom) {
+                         case 1:
                                chan->e.ref = ccard->ref_out++;
-                       else
+                               break;
+                         case 0:
                                chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
+                               break;
+                         case 2:
+                               chan->e.ref = chan->No;
+                               break;
+                       }
 
                        chan->e.Req = reqbuf->Req;
                        ReqCount++; 
-                       if (scom)
+
+                       switch (scom) {
+                         case 1:
                                ram_outb(ccard, &com->Req, reqbuf->Req); 
-                       else
+                               break;
+                         case 0:
                                ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); 
+                               break;
+                         case 2:
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+                               if (!ep) break;
+                               ep->callback = eicon_idi_callback;
+                               ep->R = (BUFFERS *)ccard;
+                               ep->user[0] = (word)chan->No;
+                               ep->user[1] = (word)tmpid;
+                               ep->XNum = 1;
+                               ep->RNum = 0;
+                               ep->RNR = 0;
+                               ep->Rc = 0;
+                               ep->Ind = 0;
+                               ep->X->PLength = reqbuf->XBuffer.length;
+                               memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
+                               ep->ReqCh = reqbuf->ReqCh;
+                               ep->Req = reqbuf->Req;
+#endif
+                               break;
+                       }
 
                        chan->e.busy = 1;
+                       spin_unlock_irqrestore(&eicon_lock, flags);
                        eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", 
-                                       reqbuf->Req, 
-                                       (scom) ? ram_inb(ccard, &com->ReqId) :
-                                               ram_inb(ccard, &ReqOut->ReqId),
+                                       reqbuf->Req, tmpid, 
                                        reqbuf->ReqCh, reqbuf->XBuffer.length,
                                        chan->e.ref); 
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+                       if (scom == 2) {
+                               if (ep) {
+                                       ccard->d->request(ep);
+                                       if (ep->Rc)
+                                               eicon_idi_callback(ep);
+                               }
+                       }
+#endif
                  }
-                 restore_flags(flags);
                  dev_kfree_skb(skb);
                 }
                 dev_kfree_skb(skb2);
                } 
                else {
-               skb_queue_tail(&ccard->sackq, skb2);
-                       eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); 
+                       skb_queue_tail(&ccard->sackq, skb2);
+                       eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); 
                }
 
-               if (scom)
-                       quloop = 0;
-               else
-                       if (!(skb2 = skb_dequeue(&ccard->sndq)))
+               switch(scom) {
+                       case 1:
                                quloop = 0;
+                               break;
+                       case 0:
+                       case 2:
+                               if (!(skb2 = skb_dequeue(&ccard->sndq)))
+                                       quloop = 0;
+                               break;
+               }
 
        }
        if (!scom)
@@ -603,18 +509,14 @@ eicon_io_transmit(eicon_card *ccard) {
        }
 }
 
-
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
 /*
  * IRQ handler 
  */
 void
 eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
        eicon_card *ccard = (eicon_card *)dev_id;
-        eicon_pci_card *pci_card;
         eicon_isa_card *isa_card;
-       char *ram = 0;
-       char *reg = 0;
-       char *cfg = 0;  
        eicon_pr_ram  *prram = 0;
        eicon_isa_com   *com = 0;
         eicon_RC *RcIn;
@@ -646,11 +548,9 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                }
        }
 
-       pci_card = &ccard->hwif.pci;
        isa_card = &ccard->hwif.isa;
 
        switch(ccard->type) {
-#ifdef CONFIG_ISDN_DRV_EICON_ISA
                case EICON_CTYPE_S:
                case EICON_CTYPE_SX:
                case EICON_CTYPE_SCOM:
@@ -664,23 +564,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                        prram = (eicon_pr_ram *)isa_card->shmem;
                        irqprobe = &isa_card->irqprobe;
                        break;
-#endif
-               case EICON_CTYPE_MAESTRAP:
-                       scom = 0;
-                       ram = (char *)pci_card->PCIram;
-                       reg = (char *)pci_card->PCIreg;
-                       cfg = (char *)pci_card->PCIcfg;
-                       irqprobe = &pci_card->irqprobe;
-                       prram = (eicon_pr_ram *)ram;
-                       break;
-               case EICON_CTYPE_MAESTRA:
-                       scom = 0;
-                       ram = (char *)pci_card->PCIram;
-                       reg = (char *)pci_card->PCIreg;
-                       cfg = (char *)pci_card->PCIcfg;
-                       irqprobe = &pci_card->irqprobe;
-                       prram = 0;
-                       break;
                default:
                        eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n");
                        return;
@@ -688,7 +571,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 
        if (*irqprobe) {
                switch(ccard->type) {
-#ifdef CONFIG_ISDN_DRV_EICON_ISA
                        case EICON_CTYPE_S:
                        case EICON_CTYPE_SX:
                        case EICON_CTYPE_SCOM:
@@ -706,26 +588,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                                }
                                (*irqprobe)++;
                                break;
-#endif
-                       case EICON_CTYPE_MAESTRAP:
-                               if (readb(&ram[0x3fe])) { 
-                                       writeb(0, &prram->RcOutput);
-                                       writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
-                                       writew(0, &cfg[MP_IRQ_RESET + 2]);
-                                       writeb(0, &ram[0x3fe]);
-                                       } 
-                               *irqprobe = 0;
-                               break;
-                       case EICON_CTYPE_MAESTRA:
-                               outb(0x08, pci_card->PCIreg + M_RESET);
-                               *irqprobe = 0;
-                               break;
                }
                return;
        }
 
        switch(ccard->type) {
-#ifdef CONFIG_ISDN_DRV_EICON_ISA
                case EICON_CTYPE_S:
                case EICON_CTYPE_SX:
                case EICON_CTYPE_SCOM:
@@ -736,20 +603,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                                return;
                        } 
                        break;
-#endif
-               case EICON_CTYPE_MAESTRAP:
-                       if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */
-                               eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
-                               return;
-                       } 
-                       break;
-               case EICON_CTYPE_MAESTRA:
-                       outw(0x3fe, pci_card->PCIreg + M_ADDR);
-                       if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */
-                               eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n");
-                               return;
-                       } 
-                       break;
        }
 
     if (scom) {
@@ -891,7 +744,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 
        /* clear interrupt */
        switch(ccard->type) {
-#ifdef CONFIG_ISDN_DRV_EICON_ISA
                case EICON_CTYPE_QUADRO:
                        writeb(0, isa_card->intack);
                        writeb(0, &com[0x401]);
@@ -902,19 +754,8 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                case EICON_CTYPE_S2M:
                        writeb(0, isa_card->intack);
                        break;
-#endif
-               case EICON_CTYPE_MAESTRAP:
-                       writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
-                       writew(0, &cfg[MP_IRQ_RESET + 2]); 
-                       writeb(0, &ram[0x3fe]); 
-                       break;
-               case EICON_CTYPE_MAESTRA:
-                       outb(0x08, pci_card->PCIreg + M_RESET);
-                       outw(0x3fe, pci_card->PCIreg + M_ADDR);
-                       outb(0, pci_card->PCIreg + M_DATA);
-                       break;
        }
 
   return;
 }
-
+#endif
index 265e07e081b0e896e858160d01e698d9af8b1806..1d2ece7cd9384012c93c8128683be14b60af566b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.c,v 1.14 2000/02/22 16:26:40 armin Exp $
+/* $Id: eicon_isa.c,v 1.16 2000/06/12 12:44:02 armin Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  * Hardware-specific code for old ISA cards.
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_isa.c,v $
- * Revision 1.14  2000/02/22 16:26:40  armin
- * Fixed membase error message.
- * Fixed missing log buffer struct.
- *
- * Revision 1.13  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.12  1999/11/27 12:56:19  armin
- * Forgot some iomem changes for last ioremap compat.
- *
- * Revision 1.11  1999/11/25 11:33:09  armin
- * Microchannel fix from Erik Weber (exrz73@ibm.net).
- *
- * Revision 1.10  1999/11/18 21:14:30  armin
- * New ISA memory mapped IO
- *
- * Revision 1.9  1999/09/08 20:17:31  armin
- * Added microchannel patch from Erik Weber (exrz73@ibm.net).
- *
- * Revision 1.8  1999/09/06 07:29:35  fritz
- * Changed my mail-address.
- *
- * Revision 1.7  1999/08/22 20:26:48  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.6  1999/07/25 15:12:06  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.5  1999/04/01 12:48:33  armin
- * Changed some log outputs.
- *
- * Revision 1.4  1999/03/29 11:19:46  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.3  1999/03/02 12:37:45  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.2  1999/01/24 20:14:19  armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.1  1999/01/01 18:09:43  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
 #include <linux/config.h>
@@ -87,7 +31,7 @@
 #define release_shmem release_region
 #define request_shmem request_region
 
-char *eicon_isa_revision = "$Revision: 1.14 $";
+char *eicon_isa_revision = "$Revision: 1.16 $";
 
 #undef EICON_MCA_DEBUG
 
@@ -357,7 +301,7 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
        printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]); 
        if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) {
                tmp = eicon_addcard(card->type, card->physmem, card->irq, 
-                                       ((eicon_card *)card->card)->regname);
+                               ((eicon_card *)card->card)->regname, 0);
                printk(KERN_INFO "Eicon: %d adapters added\n", tmp);
        }
        return 0;
index b53adfcbf66ae577333d80d47ff40189d394fbf3..1c8034f77786e6412b0611418764e88a39ef5ebd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.h,v 1.8 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon_isa.h,v 1.10 2000/05/07 08:51:04 armin Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  *
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_isa.h,v $
- * Revision 1.8  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.7  1999/11/18 21:14:30  armin
- * New ISA memory mapped IO
- *
- * Revision 1.6  1999/11/15 19:37:04  keil
- * need config.h
- *
- * Revision 1.5  1999/09/08 20:17:31  armin
- * Added microchannel patch from Erik Weber.
- *
- * Revision 1.4  1999/09/06 07:29:35  fritz
- * Changed my mail-address.
- *
- * Revision 1.3  1999/03/29 11:19:47  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.2  1999/03/02 12:37:46  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.1  1999/01/01 18:09:44  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
 #ifndef eicon_isa_h
@@ -138,7 +106,6 @@ typedef struct {
        unsigned char     mvalid;   /* Flag: Memory is valid      */
        unsigned char     ivalid;   /* Flag: IRQ is valid         */
        unsigned char     master;   /* Flag: Card ist Quadro 1/4  */
-       void*             generic;  /* Ptr to generic card struct */
 } eicon_isa_card;
 
 /* Offsets for special locations on standard cards */
index 9bc91d6f4f42fedaf23da51eda234cec3f1c9750..f3af22b2704e5e3a6a34efd82fa0f916cacd84f1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.25 2000/02/22 16:26:40 armin Exp $
+/* $Id: eicon_mod.c,v 1.35 2000/08/12 18:00:47 armin Exp $
  *
  * ISDN lowlevel-module for Eicon active cards.
  * 
@@ -9,8 +9,6 @@
  * Thanks to    Eicon Technology GmbH & Co. oHG for
  *              documents, informations and hardware.
  *
- *              Deutsche Telekom AG for S2M support.
- *
  *             Deutsche Mailbox Saar-Lor-Lux GmbH
  *             for sponsoring and testing fax
  *             capabilities with Diva Server cards.
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_mod.c,v $
- * Revision 1.25  2000/02/22 16:26:40  armin
- * Fixed membase error message.
- * Fixed missing log buffer struct.
- *
- * Revision 1.24  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.23  2000/01/20 19:55:34  keil
- * Add FAX Class 1 support
- *
- * Revision 1.22  1999/11/27 12:56:19  armin
- * Forgot some iomem changes for last ioremap compat.
- *
- * Revision 1.21  1999/11/25 11:35:10  armin
- * Microchannel fix from Erik Weber (exrz73@ibm.net).
- * Minor cleanup.
- *
- * Revision 1.20  1999/11/18 21:14:30  armin
- * New ISA memory mapped IO
- *
- * Revision 1.19  1999/11/12 13:21:44  armin
- * Bugfix of undefined reference with CONFIG_MCA
- *
- * Revision 1.18  1999/10/11 18:13:25  armin
- * Added fax capabilities for Eicon Diva Server cards.
- *
- * Revision 1.17  1999/10/08 22:09:34  armin
- * Some fixes of cards interface handling.
- * Bugfix of NULL pointer occurence.
- * Changed a few log outputs.
- *
- * Revision 1.16  1999/09/26 14:17:53  armin
- * Improved debug and log via readstat()
- *
- * Revision 1.15  1999/09/08 20:17:31  armin
- * Added microchannel patch from Erik Weber (exrz73@ibm.net).
- *
- * Revision 1.14  1999/09/06 07:29:35  fritz
- * Changed my mail-address.
- *
- * Revision 1.13  1999/09/04 17:37:59  armin
- * Removed not used define, did not work and caused error
- * in 2.3.16
- *
- * Revision 1.12  1999/08/31 11:20:14  paul
- * various spelling corrections (new checksums may be needed, Karsten!)
- *
- * Revision 1.11  1999/08/29 17:23:45  armin
- * New setup compat.
- * Bugfix if compile as not module.
- *
- * Revision 1.10  1999/08/28 21:32:53  armin
- * Prepared for fax related functions.
- * Now compilable without errors/warnings.
- *
- * Revision 1.9  1999/08/18 20:17:02  armin
- * Added XLOG function for all cards.
- * Bugfix of alloc_skb NULL pointer.
- *
- * Revision 1.8  1999/07/25 15:12:08  armin
- * fix of some debug logs.
- * enabled ISA-cards option.
- *
- * Revision 1.7  1999/07/11 17:16:27  armin
- * Bugfixes in queue handling.
- * Added DSP-DTMF decoder functions.
- * Reorganized ack_handler.
- *
- * Revision 1.6  1999/06/09 19:31:26  armin
- * Wrong PLX size for request_region() corrected.
- * Added first MCA code from Erik Weber.
- *
- * Revision 1.5  1999/04/01 12:48:35  armin
- * Changed some log outputs.
- *
- * Revision 1.4  1999/03/29 11:19:47  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.3  1999/03/02 12:37:47  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.2  1999/01/24 20:14:21  armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.1  1999/01/01 18:09:44  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
-#define DRIVERPATCH ""
+#define DRIVERNAME "Eicon active ISDN driver"
+#define DRIVERRELEASE "2.0"
+#define DRIVERPATCH ".14"
+
 
 #include <linux/config.h>
 #include <linux/module.h>
 
 #include "eicon.h"
 
+#include "../avmb1/capicmd.h"  /* this should be moved in a common place */
+
+#undef N_DATA
+#include "adapter.h"
+#include "uxio.h"
+
 #define INCLUDE_INLINE_FUNCS
 
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.25 $";
+static char *eicon_revision = "$Revision: 1.35 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
 extern char *eicon_idi_revision;
 
+extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
+                       unsigned int command, unsigned long arg);
+extern void eicon_pci_init_conf(eicon_card *card);
+void mod_inc_use_count(void);
+void mod_dec_use_count(void);
+extern char *file_check(void);
+
 #ifdef MODULE
 #define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))
 #endif
@@ -158,6 +76,11 @@ extern char *eicon_idi_revision;
 
 ulong DebugVar;
 
+spinlock_t eicon_lock;
+
+DESCRIPTOR idi_d[16];
+int idi_dlength;
+
 /* Parameters to be set by insmod */
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
 static int   membase      = -1;
@@ -189,23 +112,6 @@ char *eicon_ctype_name[] = {
         "DIVA Server PRI/PCI"
 };
 
-static int
-getrel(char *p)
-{
-        int v = 0;
-       char *tmp = 0;
-
-       if ((tmp = strchr(p, '.')))
-               p = tmp + 1;
-        while (p[0] >= '0' && p[0] <= '9') {
-                v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0');
-               p++;
-       }
-        return v;
-
-
-}
-
 static char *
 eicon_getrev(const char *revision)
 {
@@ -229,68 +135,26 @@ find_channel(eicon_card *card, int channel)
        return NULL;
 }
 
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
 /*
- * Free MSN list
+ * Find pcicard with given card number 
  */
-static void
-eicon_clear_msn(eicon_card *card)
+static inline eicon_card *
+eicon_findnpcicard(int driverid)
 {
-        struct msn_entry *p = card->msn_list;
-        struct msn_entry *q;
-       unsigned long flags;
+        eicon_card *p = cards;
 
-       save_flags(flags);
-       cli();
-        card->msn_list = NULL;
-       restore_flags(flags);
         while (p) {
-                q  = p->next;
-                kfree(p);
-                p = q;
+                if ((p->regname[strlen(p->regname)-1] == (driverid + '0')) &&
+                       (p->bus == EICON_BUS_PCI))
+                        return p;
+                p = p->next;
         }
+        return (eicon_card *) 0;
 }
-
-/*
- * Find an MSN entry in the list.
- * If ia5 != 0, return IA5-encoded EAZ, else
- * return a bitmask with corresponding bit set.
- */
-static __u16
-eicon_find_msn(eicon_card *card, char *msn, int ia5)
-{
-        struct msn_entry *p = card->msn_list;
-       __u8 eaz = '0';
-
-       while (p) {
-               if (!strcmp(p->msn, msn)) {
-                       eaz = p->eaz;
-                       break;
-               }
-               p = p->next;
-       }
-       if (!ia5)
-               return (1 << (eaz - '0'));
-       else
-               return eaz;
-}
-
-/*
- * Find an EAZ entry in the list.
- * return a string with corresponding msn.
- */
-char *
-eicon_find_eaz(eicon_card *card, char eaz)
-{
-        struct msn_entry *p = card->msn_list;
-
-       while (p) {
-               if (p->eaz == eaz)
-                       return(p->msn);
-               p = p->next;
-       }
-       return("\0");
-}
-
+#endif
+#endif /* CONFIG_PCI */
 
 static void
 eicon_rcv_dispatch(struct eicon_card *card)
@@ -337,39 +201,18 @@ eicon_transmit(struct eicon_card *card)
        }
 }
 
-static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq)
-{
-       xlogreq_t *xlr;
-       int ret_val;
-
-       if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) {
-               eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n");
-               return -ENOMEM;
-       }
-       if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) {
-               kfree(xlr);
-               return -EFAULT;
-       }
-
-       ret_val = eicon_get_xlog(card, xlr);
-
-       if (copy_to_user(xlogreq, xlr, sizeof(xlogreq_t))) {
-               kfree(xlr);
-               return -EFAULT;
-       }
-       kfree(xlr);
-
-       return ret_val;
-}
-
 static int
 eicon_command(eicon_card * card, isdn_ctrl * c)
 {
         ulong a;
         eicon_chan *chan;
        eicon_cdef cdef;
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+       dia_start_t dstart;
+#endif
+#endif
        isdn_ctrl cmd;
-       char tmp[17];
        int ret = 0;
        unsigned long flags;
  
@@ -383,16 +226,15 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                case EICON_IOCTL_GETVER:
                                        return(EICON_CTRL_VERSION);
                                case EICON_IOCTL_GETTYPE:
+                                       if (card->bus == EICON_BUS_PCI) {
+                                               copy_to_user((char *)a, &card->hwif.pci.master, sizeof(int));
+                                       }
                                        return(card->type);
                                case EICON_IOCTL_GETMMIO:
                                        switch (card->bus) {
                                                case EICON_BUS_ISA:
                                                case EICON_BUS_MCA:
                                                        return (int)card->hwif.isa.shmem;
-#if CONFIG_PCI
-                                               case EICON_BUS_PCI:
-                                                       return card->hwif.pci.PCIram;
-#endif
                                                default:
                                                        eicon_log(card, 1,
                                                               "eicon: Illegal BUS type %d\n",
@@ -433,10 +275,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                                case EICON_BUS_ISA:
                                                case EICON_BUS_MCA:
                                                        return card->hwif.isa.irq;
-#if CONFIG_PCI
-                                               case EICON_BUS_PCI:
-                                                       return card->hwif.pci.irq;
-#endif
                                                default:
                                                        eicon_log(card, 1,
                                                               "eicon: Illegal BUS type %d\n",
@@ -514,7 +352,9 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                case EICON_IOCTL_MANIF:
                                        if (!card->flags & EICON_FLAGS_RUNNING)
                                                return -ENODEV;
-                                       if (!card->Feature & PROTCAP_MANIF)
+                                       if (!card->d)
+                                               return -ENODEV;
+                                       if (!card->d->features & DI_MANAGE)
                                                return -ENODEV;
                                        ret = eicon_idi_manage(
                                                card, 
@@ -522,49 +362,12 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                        return ret;
 
                                case EICON_IOCTL_GETXLOG:
-                                       if (!card->flags & EICON_FLAGS_RUNNING)
-                                               return XLOG_ERR_CARD_STATE;
-                                       ret = eicon_xlog(card, (xlogreq_t *)a);
-                                       return ret;
-#if CONFIG_PCI 
-                               case EICON_IOCTL_LOADPCI:
-                                               if (card->flags & EICON_FLAGS_RUNNING)
-                                                       return -EBUSY;  
-                                                if (card->bus == EICON_BUS_PCI) {
-                                                       switch(card->type) {
-                                                               case EICON_CTYPE_MAESTRA:
-                                                                       ret = eicon_pci_load_bri(
-                                                                               &(card->hwif.pci),
-                                                                               &(((eicon_codebuf *)a)->pci)); 
-                                                                       break;
-
-                                                               case EICON_CTYPE_MAESTRAP:
-                                                                       ret = eicon_pci_load_pri(
-                                                                               &(card->hwif.pci),
-                                                                               &(((eicon_codebuf *)a)->pci)); 
-                                                                       break;
-                                                       }
-                                                        if (!ret) {
-                                                                card->flags |= EICON_FLAGS_LOADED;
-                                                                card->flags |= EICON_FLAGS_RUNNING;
-                                                               if (card->hwif.pci.channels > 1) {
-                                                                       cmd.command = ISDN_STAT_ADDCH;
-                                                                       cmd.driver = card->myid;
-                                                                       cmd.arg = card->hwif.pci.channels - 1;
-                                                                       card->interface.statcallb(&cmd);
-                                                               }
-                                                               cmd.command = ISDN_STAT_RUN;    
-                                                               cmd.driver = card->myid;        
-                                                               cmd.arg = 0;                    
-                                                               card->interface.statcallb(&cmd);
-                                                       } 
-                                                        return ret;
-                                               } else return -ENODEV;
-#endif
+                                       return -ENODEV;
+
                                case EICON_IOCTL_ADDCARD:
                                        if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
                                                return -EFAULT;
-                                       if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id)))
+                                       if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id, 0)))
                                                return -EIO;
                                        return 0;
                                case EICON_IOCTL_DEBUGVAR:
@@ -574,11 +377,77 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
 #ifdef MODULE
                                case EICON_IOCTL_FREEIT:
                                        while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;
-                                       MOD_INC_USE_COUNT;
+                                       mod_inc_use_count();
                                        return 0;
 #endif
-                               default:
+                               case EICON_IOCTL_LOADPCI:
+                                       eicon_log(card, 1, "Eicon: Wrong version of load-utility,\n");
+                                       eicon_log(card, 1, "Eicon: re-compile eiconctrl !\n");
+                                       eicon_log(card, 1, "Eicon: Maybe update of utility is necessary !\n");
                                        return -EINVAL;
+                               default:        
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+                                       if (c->arg < EICON_IOCTL_DIA_OFFSET)
+                                               return -EINVAL;
+                                       if (copy_from_user(&dstart, (char *)a, sizeof(dstart)))
+                                               return -1;
+                                       if (!(card = eicon_findnpcicard(dstart.card_id)))
+                                               return -EINVAL;
+                                       ret = do_ioctl(NULL, NULL,
+                                               c->arg - EICON_IOCTL_DIA_OFFSET,
+                                               (unsigned long) a);
+                                       if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {
+                                               if (card->type != EICON_CTYPE_MAESTRAQ) {
+                                                       EtdM_DIDD_Read(idi_d, &idi_dlength);
+                                                       card->d = &idi_d[idi_dlength - 1];
+                                                       card->flags |= EICON_FLAGS_LOADED;
+                                                       card->flags |= EICON_FLAGS_RUNNING;
+                                                       eicon_pci_init_conf(card);
+                                                       if (card->d->channels > 1) {
+                                                               cmd.command = ISDN_STAT_ADDCH;
+                                                               cmd.driver = card->myid;
+                                                               cmd.arg = card->d->channels - 1;
+                                                               card->interface.statcallb(&cmd);
+                                                       }
+                                                       cmd.command = ISDN_STAT_RUN;    
+                                                       cmd.driver = card->myid;        
+                                                       cmd.arg = 0;                    
+                                                       card->interface.statcallb(&cmd);
+                                                       eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x, SerNo. %d)\n",
+                                                               (card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",
+                                                               card->d->channels, card->d->features, card->d->serial);
+                                               } else {
+                                                       int i;
+                                                       EtdM_DIDD_Read(idi_d, &idi_dlength);
+                                                       for(i = 3; i >= 0; i--) {
+                                                               if (!(card = eicon_findnpcicard(dstart.card_id - i)))
+                                                                       return -EINVAL;
+       
+                                                               card->flags |= EICON_FLAGS_LOADED;
+                                                               card->flags |= EICON_FLAGS_RUNNING;
+                                                               card->d = &idi_d[idi_dlength - (i+1)];
+                                                               eicon_pci_init_conf(card);
+                                                               if (card->d->channels > 1) {
+                                                                       cmd.command = ISDN_STAT_ADDCH;
+                                                                       cmd.driver = card->myid;
+                                                                       cmd.arg = card->d->channels - 1;
+                                                                       card->interface.statcallb(&cmd);
+                                                               }
+                                                               cmd.command = ISDN_STAT_RUN;    
+                                                               cmd.driver = card->myid;        
+                                                               cmd.arg = 0;                    
+                                                               card->interface.statcallb(&cmd);
+                                                               eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x, SerNo. %d)\n",
+                                                                       4-i, card->d->channels, card->d->features, card->d->serial);
+                                                       }
+                                               }
+                                       }
+                                       return ret;
+#else
+                                       return -EINVAL;
+#endif
+#endif /* CONFIG_PCI */
                        }
                        break;
                case ISDN_CMD_DIAL:
@@ -586,20 +455,15 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                return -ENODEV;
                        if (!(chan = find_channel(card, c->arg & 0x1f)))
                                break;
-                       save_flags(flags);
-                       cli();
+                       spin_lock_irqsave(&eicon_lock, flags);
                        if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
                                eicon_log(card, 1, "Dial on channel %d with state %d\n",
                                        chan->No, chan->fsm_state);
                                return -EBUSY;
                        }
-                       if (card->ptype == ISDN_PTYPE_EURO)
-                               tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1);
-                       else
-                               tmp[0] = c->parm.setup.eazmsn[0];
                        chan->fsm_state = EICON_STATE_OCALL;
-                       restore_flags(flags);
+                       spin_unlock_irqrestore(&eicon_lock, flags);
                        
                        ret = idi_connect_req(card, chan, c->parm.setup.phone,
                                                     c->parm.setup.eazmsn,
@@ -637,19 +501,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                return -ENODEV;
                        if (!(chan = find_channel(card, c->arg & 0x1f)))
                                break;
-                       if (strlen(c->parm.num)) {
-                               if (card->ptype == ISDN_PTYPE_EURO) {
-                                       chan->eazmask = eicon_find_msn(card, c->parm.num, 0);
-                               }
-                               if (card->ptype == ISDN_PTYPE_1TR6) {
-                                       int i;
-                                       chan->eazmask = 0;
-                                       for (i = 0; i < strlen(c->parm.num); i++)
-                                               if (isdigit(c->parm.num[i]))
-                                                       chan->eazmask |= (1 << (c->parm.num[i] - '0'));
-                               }
-                       } else
-                               chan->eazmask = 0x3ff;
+                       chan->eazmask = 0x3ff;
                        eicon_idi_listen_req(card, chan);
                        return 0;
                case ISDN_CMD_CLREAZ:
@@ -680,8 +532,10 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                break;
                        chan->l3prot = (c->arg >> 8);
 #ifdef CONFIG_ISDN_TTY_FAX
-                       if (chan->l3prot == ISDN_PROTO_L3_FCLASS2)
+                       if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) {
                                chan->fax = c->parm.fax;
+                               eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax);
+                       }
 #endif
                        return 0;
                case ISDN_CMD_GETL3:
@@ -706,10 +560,14 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                        eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");
                        return 0;
                case ISDN_CMD_LOCK:
-                       MOD_INC_USE_COUNT;
+#ifdef MODULE
+                       mod_inc_use_count();
+#endif
                        return 0;
                case ISDN_CMD_UNLOCK:
-                       MOD_DEC_USE_COUNT;
+#ifdef MODULE
+                       mod_dec_use_count();
+#endif
                        return 0;
 #ifdef CONFIG_ISDN_TTY_FAX
                case ISDN_CMD_FAXCMD:
@@ -729,6 +587,23 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                break;
                        idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
                        return 0;
+               case CAPI_PUT_MESSAGE:
+                       if (!card->flags & EICON_FLAGS_RUNNING)
+                               return -ENODEV;
+                       if (!(chan = find_channel(card, c->arg & 0x1f)))
+                               break;
+                       if (c->parm.cmsg.Length < 8)
+                               break;
+                       switch(c->parm.cmsg.Command) {
+                               case CAPI_FACILITY:
+                                       if (c->parm.cmsg.Subcommand == CAPI_REQ)
+                                               return(capipmsg(card, chan, &c->parm.cmsg));
+                                       break;
+                               case CAPI_MANUFACTURER:
+                               default:
+                                       break;
+                       }
+                       return 0;
         }
        
         return -EINVAL;
@@ -787,8 +662,7 @@ if_readstatus(u_char * buf, int len, int user, int id, int channel)
                 if (!card->flags & EICON_FLAGS_RUNNING)
                         return -ENODEV;
        
-               save_flags(flags);
-               cli();
+               spin_lock_irqsave(&eicon_lock, flags);
                while((skb = skb_dequeue(&card->statq))) {
 
                        if ((skb->len + count) > len)
@@ -811,12 +685,12 @@ if_readstatus(u_char * buf, int len, int user, int id, int channel)
                        } else {
                                skb_pull(skb, cnt);
                                skb_queue_head(&card->statq, skb);
-                               restore_flags(flags);
+                               spin_unlock_irqrestore(&eicon_lock, flags);
                                return count;
                        }
                }
                card->statq_entries = 0;
-               restore_flags(flags);
+               spin_unlock_irqrestore(&eicon_lock, flags);
                return count;
         }
         printk(KERN_ERR
@@ -848,7 +722,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
                        }
                        else
 #endif
-                               ret = idi_send_data(card, chan, ack, skb, 1);
+                               ret = idi_send_data(card, chan, ack, skb, 1, 1);
                        return (ret);
                } else {
                        return -ENODEV;
@@ -895,12 +769,11 @@ eicon_putstatus(eicon_card * card, char * buf)
                        return;
        }
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&eicon_lock, flags);
        count = strlen(buf);
        skb = alloc_skb(count, GFP_ATOMIC);
        if (!skb) {
-               restore_flags(flags);
+               spin_unlock_irqrestore(&eicon_lock, flags);
                printk(KERN_ERR "eicon: could not alloc skb in putstatus\n");
                return;
        }
@@ -918,7 +791,7 @@ eicon_putstatus(eicon_card * card, char * buf)
        } else
                card->statq_entries++;
 
-       restore_flags(flags);
+       spin_unlock_irqrestore(&eicon_lock, flags);
         if (count) {
                 cmd.command = ISDN_STAT_STAVAIL;
                 cmd.driver = card->myid;
@@ -967,7 +840,7 @@ eicon_log(eicon_card * card, int level, const char *fmt, ...)
  * link it into cards-list.
  */
 static void
-eicon_alloccard(int Type, int membase, int irq, char *id)
+eicon_alloccard(int Type, int membase, int irq, char *id, int card_id)
 {
        int i;
        int j;
@@ -976,9 +849,6 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
        char qid[5];
 #endif
         eicon_card *card;
-#if CONFIG_PCI
-       eicon_pci_card *pcic;
-#endif
 
        qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
        for (i = 0; i <= qloop; i++) {
@@ -1088,9 +958,9 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
                                card->interface.channels = 1;
                                break;
 #endif
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
                        case EICON_CTYPE_MAESTRA:
-                               (eicon_pci_card *)pcic = (eicon_pci_card *)membase;
                                 card->bus = EICON_BUS_PCI;
                                card->interface.features |=
                                        ISDN_FEATURE_L2_V11096 |
@@ -1101,11 +971,26 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
                                        ISDN_FEATURE_L3_TRANSDSP |
                                        ISDN_FEATURE_L3_FCLASS2;
                                 card->hwif.pci.card = (void *)card;
-                               card->hwif.pci.PCIreg = pcic->PCIreg;
-                               card->hwif.pci.PCIcfg = pcic->PCIcfg;
-                                card->hwif.pci.master = 1;
-                                card->hwif.pci.mvalid = pcic->mvalid;
-                                card->hwif.pci.ivalid = 0;
+                                card->hwif.pci.master = card_id;
+                                card->hwif.pci.irq = irq;
+                                card->hwif.pci.type = Type;
+                               card->flags = 0;
+                                card->nchannels = 2;
+                               card->interface.channels = 1;
+                               break;
+
+                       case EICON_CTYPE_MAESTRAQ:
+                                card->bus = EICON_BUS_PCI;
+                               card->interface.features |=
+                                       ISDN_FEATURE_L2_V11096 |
+                                       ISDN_FEATURE_L2_V11019 |
+                                       ISDN_FEATURE_L2_V11038 |
+                                       ISDN_FEATURE_L2_MODEM |
+                                       ISDN_FEATURE_L2_FAX | 
+                                       ISDN_FEATURE_L3_TRANSDSP |
+                                       ISDN_FEATURE_L3_FCLASS2;
+                                card->hwif.pci.card = (void *)card;
+                                card->hwif.pci.master = card_id;
                                 card->hwif.pci.irq = irq;
                                 card->hwif.pci.type = Type;
                                card->flags = 0;
@@ -1114,7 +999,6 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
                                break;
 
                        case EICON_CTYPE_MAESTRAP:
-                               (eicon_pci_card *)pcic = (eicon_pci_card *)membase;
                                 card->bus = EICON_BUS_PCI;
                                card->interface.features |=
                                        ISDN_FEATURE_L2_V11096 |
@@ -1125,13 +1009,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
                                        ISDN_FEATURE_L3_TRANSDSP |
                                        ISDN_FEATURE_L3_FCLASS2;
                                 card->hwif.pci.card = (void *)card;
-                                card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
-                               card->hwif.pci.PCIreg = pcic->PCIreg;
-                               card->hwif.pci.PCIram = pcic->PCIram;
-                               card->hwif.pci.PCIcfg = pcic->PCIcfg;
-                                card->hwif.pci.master = 1;
-                                card->hwif.pci.mvalid = pcic->mvalid;
-                                card->hwif.pci.ivalid = 0;
+                                card->hwif.pci.master = card_id;
                                 card->hwif.pci.irq = irq;
                                 card->hwif.pci.type = Type;
                                card->flags = 0;
@@ -1139,6 +1017,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
                                card->interface.channels = 1;
                                break;
 #endif
+#endif
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
                        case EICON_CTYPE_ISABRI:
                                if (membase == -1)
@@ -1197,6 +1076,53 @@ eicon_alloccard(int Type, int membase, int irq, char *id)
                        skb_queue_head_init(&card->bch[j].e.X);
                        skb_queue_head_init(&card->bch[j].e.R);
                }
+
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+               /* *** Diva Server *** */
+               if (!(card->dbuf = (DBUFFER *) kmalloc((sizeof(DBUFFER) * (card->nchannels + 1))*2
+                                                        , GFP_KERNEL))) {
+                       eicon_log(card, 1,
+                              "eicon: (%s) Could not allocate DBUFFER-struct.\n", id);
+                       kfree(card);
+                       kfree(card->bch);
+                       return;
+               }
+               if (!(card->sbuf = (BUFFERS *) kmalloc((sizeof(BUFFERS) * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
+                       eicon_log(card, 1,
+                              "eicon: (%s) Could not allocate BUFFERS-struct.\n", id);
+                       kfree(card);
+                       kfree(card->bch);
+                       kfree(card->dbuf);
+                       return;
+               }
+               if (!(card->sbufp = (char *) kmalloc((270 * (card->nchannels + 1)) * 2, GFP_KERNEL))) {
+                       eicon_log(card, 1,
+                              "eicon: (%s) Could not allocate BUFFERSP-struct.\n", id);
+                       kfree(card);
+                       kfree(card->bch);
+                       kfree(card->dbuf);
+                       kfree(card->sbuf);
+                       return;
+               }
+               for (j=0; j< (card->nchannels + 1); j++) {
+                       memset((char *)&card->dbuf[j], 0, sizeof(DBUFFER));
+                       card->bch[j].de.RBuffer = (DBUFFER *)&card->dbuf[j];
+                       memset((char *)&card->dbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
+                       card->bch[j].be.RBuffer = (DBUFFER *)&card->dbuf[j+(card->nchannels+1)];
+
+                       memset((char *)&card->sbuf[j], 0, sizeof(BUFFERS));
+                       card->bch[j].de.X = (BUFFERS *)&card->sbuf[j];
+                       memset((char *)&card->sbuf[j+(card->nchannels+1)], 0, sizeof(BUFFERS));
+                       card->bch[j].be.X = (BUFFERS *)&card->sbuf[j+(card->nchannels+1)];
+
+                       memset((char *)&card->sbufp[j], 0, 270);
+                       card->bch[j].de.X->P = (char *)&card->sbufp[j * 270];
+                       memset((char *)&card->sbufp[j+(card->nchannels+1)], 0, 270);
+                       card->bch[j].be.X->P = (char *)&card->sbufp[(j+(card->nchannels+1)) * 270];
+               }
+               /* *** */
+#endif /* CONFIG_ISDN_DRV_EICON_PCI */
+
                card->next = cards;
                cards = card;
        }
@@ -1220,10 +1146,7 @@ eicon_registercard(eicon_card * card)
 #endif /* CONFIG_MCA */
 #endif
                case EICON_BUS_PCI:
-#if CONFIG_PCI
-                       eicon_pci_printpar(&card->hwif.pci); 
                        break;
-#endif
                default:
                        eicon_log(card, 1,
                               "eicon_registercard: Illegal BUS type %d\n",
@@ -1260,10 +1183,7 @@ unregister_card(eicon_card * card)
                        break;
 #endif
                case EICON_BUS_PCI:
-#if CONFIG_PCI
-                       eicon_pci_release(&card->hwif.pci);
                        break;
-#endif
                default:
                        eicon_log(card, 1,
                               "eicon: Invalid BUS type %d\n",
@@ -1295,13 +1215,17 @@ eicon_freecard(eicon_card *card) {
        while((skb = skb_dequeue(&card->statq)))
                dev_kfree_skb(skb);
 
-       eicon_clear_msn(card);
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+       kfree(card->sbufp);
+       kfree(card->sbuf);
+       kfree(card->dbuf);
+#endif
        kfree(card->bch);
        kfree(card);
 }
 
 int
-eicon_addcard(int Type, int membase, int irq, char *id)
+eicon_addcard(int Type, int membase, int irq, char *id, int card_id)
 {
        eicon_card *p;
        eicon_card *q = NULL;
@@ -1314,7 +1238,7 @@ eicon_addcard(int Type, int membase, int irq, char *id)
                if ((Type = eicon_isa_find_card(membase, irq, id)) < 0)
                        return 0;
 #endif
-       eicon_alloccard(Type, membase, irq, id);
+       eicon_alloccard(Type, membase, irq, id, card_id);
         p = cards;
         while (p) {
                registered = 0;
@@ -1333,11 +1257,13 @@ eicon_addcard(int Type, int membase, int irq, char *id)
                                        break;
 #endif
                                case EICON_BUS_PCI:
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
                                        if (eicon_registercard(p))
                                                break;
                                        registered = 1;
                                        break;
+#endif
 #endif
                                default:
                                        printk(KERN_ERR
@@ -1371,8 +1297,6 @@ eicon_addcard(int Type, int membase, int irq, char *id)
         return (added - failed);
 }
 
-#define DRIVERNAME "Eicon active ISDN driver"
-#define DRIVERRELEASE "1"
 
 #ifdef MODULE
 #define eicon_init init_module
@@ -1382,35 +1306,30 @@ int
 eicon_init(void)
 {
        int card_count = 0;
-       int release = 0;
        char tmprev[50];
 
        DebugVar = 1;
+       eicon_lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 
         printk(KERN_INFO "%s Rev: ", DRIVERNAME);
        strcpy(tmprev, eicon_revision);
        printk("%s/", eicon_getrev(tmprev));
-       release += getrel(tmprev);
        strcpy(tmprev, eicon_pci_revision);
-#if CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
        printk("%s/", eicon_getrev(tmprev));
 #else
        printk("---/");
 #endif
-       release += getrel(tmprev);
        strcpy(tmprev, eicon_isa_revision);
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
        printk("%s/", eicon_getrev(tmprev));
 #else
        printk("---/");
 #endif
-       release += getrel(tmprev);
        strcpy(tmprev, eicon_idi_revision);
        printk("%s\n", eicon_getrev(tmprev));
-       release += getrel(tmprev);
-       sprintf(tmprev,"%d", release);
-        printk(KERN_INFO "%s Release: %s.%s%s\n", DRIVERNAME,
-               DRIVERRELEASE, tmprev, DRIVERPATCH);
+        printk(KERN_INFO "%s Release: %s%s (%s)\n", DRIVERNAME,
+               DRIVERRELEASE, DRIVERPATCH, file_check());
 
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
 #ifdef CONFIG_MCA
@@ -1427,18 +1346,23 @@ eicon_init(void)
                        card_count++;
         };
 #else
-       card_count = eicon_addcard(0, membase, irq, id);
+       card_count = eicon_addcard(0, membase, irq, id, 0);
 #endif /* CONFIG_MCA */
 #endif /* CONFIG_ISDN_DRV_EICON_ISA */
  
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+       DivasCardsDiscover();
        card_count += eicon_pci_find_card(id);
 #endif
+#endif
+
         if (!cards) {
 #ifdef MODULE
-#ifndef CONFIG_PCI
+#ifndef CONFIG_ISDN_DRV_EICON_PCI
 #ifndef CONFIG_ISDN_DRV_EICON_ISA
                 printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n");
+                printk(KERN_INFO "Eicon: Driver not loaded !\n");
 #else
                 printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
 #endif
@@ -1451,17 +1375,47 @@ eicon_init(void)
        } else
                printk(KERN_INFO "Eicon: %d card%s added\n", card_count, 
                        (card_count>1)?"s":"");
-        /* No symbols to export, hide all symbols */
-        EXPORT_NO_SYMBOLS;
         return 0;
 }
 
+
 #ifdef MODULE
+
+void mod_inc_use_count(void)
+{
+        MOD_INC_USE_COUNT;
+}
+
+void mod_dec_use_count(void)
+{
+        MOD_DEC_USE_COUNT;
+}
+
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+void EtdM_DIDD_Write(DESCRIPTOR *, int);
+EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Read);
+EXPORT_SYMBOL_NOVERS(EtdM_DIDD_Write);
+EXPORT_SYMBOL_NOVERS(DivasPrintf);
+#else
+int DivasCardNext;
+card_t DivasCards[1];
+#endif
+
 void
 cleanup_module(void)
 {
+#if CONFIG_PCI 
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+       card_t *pCard;
+       word wCardIndex;
+       extern int Divas_major;
+       int iTmp = 0;
+#endif
+#endif
+       
         eicon_card *card = cards;
         eicon_card *last;
+
         while (card) {
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
 #ifdef CONFIG_MCA
@@ -1481,6 +1435,54 @@ cleanup_module(void)
                 card = card->next;
                eicon_freecard(last);
         }
+
+#if CONFIG_PCI 
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
+       pCard = DivasCards;
+       for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
+       {
+               if ((pCard->hw) && (pCard->hw->in_use))
+               {
+                       (*pCard->card_reset)(pCard);
+                       
+                       UxIsrRemove(pCard->hw, pCard);
+                       UxCardHandleFree(pCard->hw);
+
+                       if(pCard->e_tbl != NULL)
+                       {
+                               kfree(pCard->e_tbl);
+                       }
+
+                       if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
+                       {
+                               release_region(pCard->hw->io_base,0x20);
+                               release_region(pCard->hw->reset_base,0x80);
+                       }
+
+                        // If this is a 4BRI ...
+                        if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
+                        {
+                                // Skip over the next 3 virtual adapters
+                                wCardIndex += 3;
+
+                                // But free their handles
+                               for (iTmp = 0; iTmp < 3; iTmp++)
+                               {
+                                       pCard++;
+                                       UxCardHandleFree(pCard->hw);
+
+                                       if(pCard->e_tbl != NULL)
+                                       {
+                                               kfree(pCard->e_tbl);
+                                       }
+                               }
+                        }
+               }
+               pCard++;
+       }
+       unregister_chrdev(Divas_major, "Divas");
+#endif
+#endif /* CONFIG_PCI */
         printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
 }
 
@@ -1675,7 +1677,7 @@ int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
                        return  ENODEV;
        };
        /* matching membase & irq */
-       if ( 1 == eicon_addcard(type, membase, irq, id)) { 
+       if ( 1 == eicon_addcard(type, membase, irq, id, 0)) { 
                mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name);
                mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards);
 
index e696b55844e18bee4e5ff8ce1d4d5073e774f33d..6cb3bca6dccf421b07541cea29f25bc192d14a89 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.c,v 1.11 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon_pci.c,v 1.15 2000/06/12 12:44:02 armin Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards.
  * Hardware-specific code for PCI cards.
@@ -9,8 +9,6 @@
  * Thanks to   Eicon Technology GmbH & Co. oHG for 
  *             documents, informations and hardware. 
  *
- *             Deutsche Telekom AG for S2M support.
- *
  * 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, or (at your option)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_pci.c,v $
- * Revision 1.11  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.10  1999/08/22 20:26:49  calle
- * backported changes from kernel 2.3.14:
- * - several #include "config.h" gone, others come.
- * - "struct device" changed to "struct net_device" in 2.3.14, added a
- *   define in isdn_compat.h for older kernel versions.
- *
- * Revision 1.9  1999/08/11 21:01:11  keil
- * new PCI codefix
- *
- * Revision 1.8  1999/08/10 16:02:20  calle
- * struct pci_dev changed in 2.3.13. Made the necessary changes.
- *
- * Revision 1.7  1999/06/09 19:31:29  armin
- * Wrong PLX size for request_region() corrected.
- * Added first MCA code from Erik Weber.
- *
- * Revision 1.6  1999/04/01 12:48:37  armin
- * Changed some log outputs.
- *
- * Revision 1.5  1999/03/29 11:19:49  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.4  1999/03/02 12:37:48  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.3  1999/01/24 20:14:24  armin
- * Changed and added debug stuff.
- * Better data sending. (still problems with tty's flip buffer)
- *
- * Revision 1.2  1999/01/10 18:46:06  armin
- * Bug with wrong values in HLC fixed.
- * Bytes to send are counted and limited now.
- *
- * Revision 1.1  1999/01/01 18:09:45  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
 #include <linux/config.h>
 #include "eicon.h"
 #include "eicon_pci.h"
 
+#undef N_DATA
+#include "adapter.h"
+#include "uxio.h"
 
-char *eicon_pci_revision = "$Revision: 1.11 $";
+char *eicon_pci_revision = "$Revision: 1.15 $";
 
 #if CONFIG_PCI          /* intire stuff is only for PCI */
-
-#undef EICON_PCI_DEBUG 
+#ifdef CONFIG_ISDN_DRV_EICON_PCI
 
 int eicon_pci_find_card(char *ID)
 {
-  if (pci_present()) { 
-    struct pci_dev *pdev = NULL;  
-    int pci_nextindex=0, pci_cards=0, pci_akt=0; 
-    int pci_type = PCI_MAESTRA;
-    int NoMorePCICards = FALSE;
-    char *ram, *reg, *cfg;     
-    unsigned int pram=0, preg=0, pcfg=0;
-    char did[12];
-    eicon_pci_card *aparms;
-
-   if (!(aparms = (eicon_pci_card *) kmalloc(sizeof(eicon_pci_card), GFP_KERNEL))) {
-                  printk(KERN_WARNING
-                      "eicon_pci: Could not allocate card-struct.\n");
-                  return 0;
-   }
-
-  for (pci_cards = 0; pci_cards < 0x0f; pci_cards++)
-  {
-  do {
-      if ((pdev = pci_find_device(PCI_VENDOR_EICON,          
-                                  pci_type,                  
-                                  pdev)))                    
+       int pci_cards = 0;
+       int card_id = 0;
+       int had_q = 0;
+       int ctype = 0;
+       char did[20];
+       card_t *pCard;
+       word wCardIndex;
+
+       pCard = DivasCards;
+       for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
        {
-              pci_nextindex++;
-              break;
-       }
-       else {
-              pci_nextindex = 0;
-              switch (pci_type) /* switch to next card type */
-               {
-               case PCI_MAESTRA:
-                 pci_type = PCI_MAESTRAQ; break;
-               case PCI_MAESTRAQ:
-                 pci_type = PCI_MAESTRAQ_U; break;
-               case PCI_MAESTRAQ_U:
-                 pci_type = PCI_MAESTRAP; break;
-               default:
-               case PCI_MAESTRAP:
-                 NoMorePCICards = TRUE;
-               }
-       }
-     }
-     while (!NoMorePCICards);
-     if (NoMorePCICards)
-        {
-           if (pci_cards < 1) {
-           printk(KERN_INFO "Eicon: No supported PCI cards found.\n");
-          kfree(aparms);       
-           return 0;
-           }
-           else
-           {
-           printk(KERN_INFO "Eicon: %d PCI card%s registered.\n",
-                       pci_cards, (pci_cards > 1) ? "s":"");
-          kfree(aparms);       
-           return (pci_cards);
-           }
-        }
-
-   pci_enable_device(pdev); /* XXX handle error return */
-
-   pci_akt = 0;
-   switch(pci_type)
-   {
-    case PCI_MAESTRA:
-         printk(KERN_INFO "Eicon: DIVA Server BRI/PCI detected !\n");
-          aparms->type = EICON_CTYPE_MAESTRA;
-
-          aparms->irq = pdev->irq;
-          preg = pci_resource_start(pdev, 2);
-          pcfg = pci_resource_start(pdev, 1);
-
-#ifdef EICON_PCI_DEBUG
-          printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
-          printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", preg);
-          printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", pcfg);
-#endif
-        pci_akt = 1;
-         break;
-
-    case PCI_MAESTRAQ:
-    case PCI_MAESTRAQ_U:
-         printk(KERN_ERR "Eicon: DIVA Server 4BRI/PCI detected but not supported !\n");
-         pci_cards--;
-        pci_akt = 0;
-         break;
-
-    case PCI_MAESTRAP:
-         printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n");
-          aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/
-          aparms->irq = pdev->irq;
-          pram = pci_resource_start(pdev, 0);
-          preg = pci_resource_start(pdev, 2);
-          pcfg = pci_resource_start(pdev, 4);
-
-#ifdef EICON_PCI_DEBUG
-          printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
-          printk(KERN_DEBUG "eicon_pci: ram=0x%x\n",
-               (pram));
-          printk(KERN_DEBUG "eicon_pci: reg=0x%x\n",
-               (preg));
-          printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n",
-               (pcfg));
-#endif
-         pci_akt = 1;
-         break;        
-    default:
-         printk(KERN_ERR "eicon_pci: Unknown PCI card detected !\n");
-         pci_cards--;
-        pci_akt = 0;
-        break;
-   }
-
-       if (pci_akt) {
-               /* remapping memory */
-               switch(pci_type)
+       if ((pCard->hw) && (pCard->hw->in_use))
                {
-               case PCI_MAESTRA:
-                       aparms->PCIreg = (unsigned int) preg;
-                       aparms->PCIcfg = (unsigned int) pcfg;
-                       if (check_region((aparms->PCIreg), 0x20)) {
-                               printk(KERN_WARNING "eicon_pci: reg port already in use !\n");
-                               aparms->PCIreg = 0;
-                               break;  
-                       } else {
-                               request_region(aparms->PCIreg, 0x20, "eicon reg");
+                       switch(pCard->hw->card_type) {
+                               case DIA_CARD_TYPE_DIVA_SERVER:
+                                       ctype = EICON_CTYPE_MAESTRAP;
+                                       card_id++;
+                                       had_q = 0;
+                                       break;
+                               case DIA_CARD_TYPE_DIVA_SERVER_B:
+                                       ctype = EICON_CTYPE_MAESTRA;
+                                       card_id++;
+                                       had_q = 0;
+                                       break;
+                               case DIA_CARD_TYPE_DIVA_SERVER_Q:
+                                       ctype = EICON_CTYPE_MAESTRAQ;
+                                       if (!had_q)
+                                               card_id++;
+                                       if (++had_q >=4)
+                                               had_q = 0;
+                                       break;
+                               default:
+                                       printk(KERN_ERR "eicon_pci: unknown card type %d !\n",
+                                               pCard->hw->card_type);
+                                       goto err;
                        }
-                       if (check_region((aparms->PCIcfg), 0x80)) {
-                               printk(KERN_WARNING "eicon_pci: cfg port already in use !\n");
-                               aparms->PCIcfg = 0;
-                               release_region(aparms->PCIreg, 0x20);
-                               break;  
-                       } else {
-                               request_region(aparms->PCIcfg, 0x80, "eicon cfg");
-                       }
-                       break;
-               case PCI_MAESTRAQ:
-               case PCI_MAESTRAQ_U:
-               case PCI_MAESTRAP:
-                       aparms->shmem = (eicon_pci_shmem *) ioremap(pram, 0x10000);
-                       ram = (u8 *) ((u32)aparms->shmem + MP_SHARED_RAM_OFFSET);
-                       reg =  ioremap(preg, 0x4000);
-                       cfg =  ioremap(pcfg, 0x1000);   
-                       aparms->PCIram = (unsigned int) ram;
-                       aparms->PCIreg = (unsigned int) reg;
-                       aparms->PCIcfg = (unsigned int) cfg;
-                       break;
-                }
-               if ((!aparms->PCIreg) || (!aparms->PCIcfg)) {
-                       printk(KERN_ERR "eicon_pci: Card could not be added !\n");
-                       pci_cards--;
-               } else {
-                       aparms->mvalid = 1;
-       
                        sprintf(did, "%s%d", (strlen(ID) < 1) ? "eicon":ID, pci_cards);
-
-                       printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[aparms->type] , did);
-
-                       if (!(eicon_addcard(aparms->type, (int) aparms, aparms->irq, did))) {
+                       if ((!ctype) || (!(eicon_addcard(ctype, 0, pCard->hw->irq, did, card_id)))) {
                                printk(KERN_ERR "eicon_pci: Card could not be added !\n");
-                               pci_cards--;
+                       } else {
+                               pci_cards++;
+                               printk(KERN_INFO "%s: DriverID='%s' CardID=%d\n",
+                                       eicon_ctype_name[ctype], did, card_id);
                        }
+err:
                }
+               pCard++;
        }
-
-  }
- } else
-       printk(KERN_ERR "eicon_pci: Kernel compiled with PCI but no PCI-bios found !\n");
- return 0;
-}
-
-/*
- * Checks protocol file id for "F#xxxx" string fragment to
- * extract the features, supported by this protocol version.
- * binary representation of the feature string value is returned
- * in *value. The function returns 0 if feature string was not
- * found or has a wrong format, else 1.
- */
-static int GetProtFeatureValue(char *sw_id, int *value)
-{
-  __u8 i, offset;
-
-  while (*sw_id)
-  {
-    if ((sw_id[0] == 'F') && (sw_id[1] == '#'))
-    {
-      sw_id = &sw_id[2];
-      for (i=0, *value=0; i<4; i++, sw_id++)
-      {
-        if ((*sw_id >= '0') && (*sw_id <= '9'))
-        {
-          offset = '0';
-        }
-        else if ((*sw_id >= 'A') && (*sw_id <= 'F'))
-        {
-          offset = 'A' + 10;
-        }
-        else if ((*sw_id >= 'a') && (*sw_id <= 'f'))
-        {
-          offset = 'a' + 10;
-        }
-        else
-        {
-          return 0;
-        }
-        *value |= (*sw_id - offset) << (4*(3-i));
-      }
-      return 1;
-    }
-    else
-    {
-      sw_id++;
-    }
-  }
-  return 0;
+       return pci_cards;
 }
 
-
 void
-eicon_pci_printpar(eicon_pci_card *card) {
-        switch (card->type) {
-                case EICON_CTYPE_MAESTRA:
-                       printk(KERN_INFO "%s at 0x%x / 0x%x, irq %d\n",
-                               eicon_ctype_name[card->type],
-                               (unsigned int)card->PCIreg,
-                               (unsigned int)card->PCIcfg,
-                               card->irq); 
-                       break;
-                case EICON_CTYPE_MAESTRAQ:
-                case EICON_CTYPE_MAESTRAQ_U:
-                case EICON_CTYPE_MAESTRAP:
-                       printk(KERN_INFO "%s at 0x%x, irq %d\n",
-                               eicon_ctype_name[card->type],
-                               (unsigned int)card->shmem,
-                               card->irq); 
-#ifdef EICON_PCI_DEBUG
-                       printk(KERN_INFO "eicon_pci: remapped ram= 0x%x\n",(unsigned int)card->PCIram);
-                       printk(KERN_INFO "eicon_pci: remapped reg= 0x%x\n",(unsigned int)card->PCIreg);
-                       printk(KERN_INFO "eicon_pci: remapped cfg= 0x%x\n",(unsigned int)card->PCIcfg); 
-#endif
-                       break;
-       }
-}
-
-
-static void
-eicon_pci_release_shmem(eicon_pci_card *card) {
-       if (!card->master)
-               return;
-       if (card->mvalid) {
-               switch (card->type) {
-                       case EICON_CTYPE_MAESTRA:
-                               /* reset board */
-                               outb(0, card->PCIcfg + 0x4c);   /* disable interrupts from PLX */
-                               outb(0, card->PCIreg + M_RESET);
-                               SLEEP(20);
-                               outb(0, card->PCIreg + M_ADDRH);
-                               outw(0, card->PCIreg + M_ADDR);
-                               outw(0, card->PCIreg + M_DATA);
-
-                               release_region(card->PCIreg, 0x20);
-                               release_region(card->PCIcfg, 0x80);
-                               break;
-                       case EICON_CTYPE_MAESTRAQ:
-                       case EICON_CTYPE_MAESTRAQ_U:
-                       case EICON_CTYPE_MAESTRAP:
-                               /* reset board */
-                               writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
-                               SLEEP(20);
-                               writeb(0, card->PCIreg + MP_RESET);
-                               SLEEP(20);
-
-                               iounmap((void *)card->shmem);
-                               iounmap((void *)card->PCIreg);
-                               iounmap((void *)card->PCIcfg);
-                               break;
-               }
-       }
-       card->mvalid = 0;
-}
-
-static void
-eicon_pci_release_irq(eicon_pci_card *card) {
-       if (!card->master)
-               return;
-       if (card->ivalid)
-               free_irq(card->irq, card);
-       card->ivalid = 0;
-}
-
-void
-eicon_pci_release(eicon_pci_card *card) {
-        eicon_pci_release_irq(card);
-        eicon_pci_release_shmem(card);
-}
-
-/*
- * Upload buffer content to adapters shared memory
- * on verify error, 1 is returned and a message is printed on screen
- * else 0 is returned
- * Can serve IO-Type and Memory type adapters
- */
-int eicon_upload(t_dsp_download_space   *p_para,
-            __u16                 length,   /* byte count */
-            __u8                  *buffer,
-            int                   verify)
+eicon_pci_init_conf(eicon_card *card)
 {
-  __u32               i, dwdata = 0, val = 0, timeout;
-  __u16               data;
-  eicon_pci_boot *boot = 0;
-
-  switch (p_para->type) /* actions depend on type of union */
-  {
-    case DL_PARA_IO_TYPE:
-      for (i=0; i<length; i+=2)
-      {
-       outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
-       outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); 
-       /* outw (((u16 *)code)[i >> 1], p_para->dat.io.ioDATA); */
-       outw (*(u16 *)&buffer[i], p_para->dat.io.ioDATA); 
-      }
-      if (verify) /* check written block */
-      {
-        for (i=0; i<length; i+=2)
-        {
-         outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
-          outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); 
-          data = inw(p_para->dat.io.ioDATA);
-          if (data != *(u16 *)&buffer[i])
-          {
-            p_para->dat.io.r3addr  += i;
-            p_para->dat.io.BadData  = data;
-            p_para->dat.io.GoodData = *(u16 *)&buffer[i];
-            return 1;
-          }
-        }
-      }
-      break;
-
-    case DL_PARA_MEM_TYPE:
-      boot = p_para->dat.mem.boot;
-      writel(p_para->dat.mem.r3addr, &boot->addr);
-      for (i=0; i<length; i+=4)
-      {
-        writel(((u32 *)buffer)[i >> 2], &boot->data[i]);
-      }
-      if (verify) /* check written block */
-      {
-        for (i=0; i<length; i+=4)
-        {
-          dwdata = readl(&boot->data[i]);
-          if (((u32 *)buffer)[i >> 2] != dwdata)
-          {
-            p_para->dat.mem.r3addr  += i;
-            p_para->dat.mem.BadData  = dwdata;
-            p_para->dat.mem.GoodData = ((u32 *)buffer)[i >> 2];
-            return 1;
-          }
-        }
-      }
-      writel(((length + 3) / 4), &boot->len);  /* len in dwords */
-      writel(2, &boot->cmd);
-
-       timeout = jiffies + 20;
-       while (timeout > jiffies) {
-               val = readl(&boot->cmd);
-               if (!val) break;
-               SLEEP(2);
-       }
-       if (val)
-         {
-               p_para->dat.mem.timeout = 1;
-               return 1;
-        }
-      break;
-  }
-  return 0;
-}
-
-
-/* show header information of code file */
-static
-int eicon_pci_print_hdr(unsigned char *code, int offset)
-{
-  unsigned char hdr[80];
-  int i, fvalue = 0;
-
-  i = 0;
-  while ((i < (sizeof(hdr) -1))
-          && (code[offset + i] != '\0')
-          && (code[offset + i] != '\r')
-          && (code[offset + i] != '\n'))
-   {
-     hdr[i] = code[offset + i];
-     i++;
-   }
-   hdr[i] = '\0';
-   printk(KERN_DEBUG "Eicon: loading %s\n", hdr);
-   if (GetProtFeatureValue(hdr, &fvalue)) return(fvalue);
-    else return(0);
-}
-
-
-/*
- * Configure a card, download code into BRI card,
- * check if we get interrupts and return 0 on succes.
- * Return -ERRNO on failure.
- */
-int
-eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
-        int               i,j;
-        int               timeout;
-       unsigned int      offset, offp=0, size, length;
-       int               signature = 0;
-       int               FeatureValue = 0;
-        eicon_pci_codebuf cbuf;
-       t_dsp_download_space dl_para;
-       t_dsp_download_desc  dsp_download_table;
-        unsigned char     *code;
-       unsigned int      reg;
-       unsigned int      cfg;
-
-        if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
-                return -EFAULT;
-
-       reg = card->PCIreg;
-       cfg = card->PCIcfg;
-
-       /* reset board */
-       outb(0, reg + M_RESET);
-       SLEEP(10);
-       outb(0, reg + M_ADDRH);
-       outw(0, reg + M_ADDR);
-       outw(0, reg + M_DATA);
-
-#ifdef EICON_PCI_DEBUG
-        printk(KERN_DEBUG "eicon_pci: reset card\n");
-#endif
-
-       /* clear shared memory */
-       outb(0xff, reg + M_ADDRH);
-       outw(0, reg + M_ADDR);
-       for(i = 0; i < 0xffff; i++) outw(0, reg + M_DATA);
-       SLEEP(10);
-
-#ifdef EICON_PCI_DEBUG
-        printk(KERN_DEBUG "eicon_pci: clear shared memory\n");
-#endif
-
-       /* download protocol and dsp file */
-
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
-#endif
-
-               /* Allocate code-buffer */
-               if (!(code = kmalloc(400, GFP_KERNEL))) {
-                printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
-                       return -ENOMEM;
-        }
-
-       /* prepare protocol upload */
-       dl_para.type            = DL_PARA_IO_TYPE;
-       dl_para.dat.io.ioADDR   = reg + M_ADDR;
-       dl_para.dat.io.ioADDRH  = reg + M_ADDRH;
-       dl_para.dat.io.ioDATA   = reg + M_DATA;
-
-       for (j = 0; j <= cbuf.dsp_code_num; j++) 
-        {      
-          if (j == 0)  size = cbuf.protocol_len;
-                  else size = cbuf.dsp_code_len[j];
-
-               offset = 0;
-
-               if (j == 0) dl_para.dat.io.r3addr = 0;
-               if (j == 1) dl_para.dat.io.r3addr = M_DSP_CODE_BASE +
-                                       ((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
-               if (j == 2) dl_para.dat.io.r3addr = M_DSP_CODE_BASE;
-               if (j == 3) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + sizeof(__u32);
-
-           do  /* download block of up to 400 bytes */
-            {
-              length = ((size - offset) >= 400) ? 400 : (size - offset);
-
-               if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
-                       kfree(code);
-                       return -EFAULT;
-               }
-
-               if ((offset == 0) && (j < 2)) {
-                       FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); 
-#ifdef EICON_PCI_DEBUG
-       if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%04x.\n", FeatureValue);
-#endif
-                       if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
-                               printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
-                               kfree(code);
-                               return -EFAULT;
-                       }
-                       ((eicon_card *)card->card)->Feature = FeatureValue;
-               }
-
-               if (eicon_upload(&dl_para, length, code, 1))
-               {
-                  printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
-                 kfree(code);
-                  return -EIO;
-               }
-              /* move onto next block */
-              offset += length;
-             dl_para.dat.io.r3addr += length;
-            } while (offset < size);
-
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "Eicon: %d bytes loaded.\n", offset);
-#endif
-       offp += size;
-       }
-       kfree(code);    
-
-       /* clear signature */
-       outb(0xff, reg + M_ADDRH);
-       outw(0x1e, reg + M_ADDR);
-       outw(0, reg + M_DATA);
-
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
-#endif
-       /* copy configuration data into shared memory */
-       outw(8, reg + M_ADDR); outb(cbuf.tei, reg + M_DATA);
-       outw(9, reg + M_ADDR); outb(cbuf.nt2, reg + M_DATA);
-       outw(10,reg + M_ADDR); outb(0, reg + M_DATA);
-       outw(11,reg + M_ADDR); outb(cbuf.WatchDog, reg + M_DATA);
-       outw(12,reg + M_ADDR); outb(cbuf.Permanent, reg + M_DATA);
-       outw(13,reg + M_ADDR); outb(0, reg + M_DATA);                 /* XInterface */
-       outw(14,reg + M_ADDR); outb(cbuf.StableL2, reg + M_DATA);
-       outw(15,reg + M_ADDR); outb(cbuf.NoOrderCheck, reg + M_DATA);
-       outw(16,reg + M_ADDR); outb(0, reg + M_DATA);                 /* HandsetType */
-       outw(17,reg + M_ADDR); outb(0, reg + M_DATA);                 /* SigFlags */
-       outw(18,reg + M_ADDR); outb(cbuf.LowChannel, reg + M_DATA);
-       outw(19,reg + M_ADDR); outb(cbuf.ProtVersion, reg + M_DATA);
-       outw(20,reg + M_ADDR); outb(cbuf.Crc4, reg + M_DATA);
-       outw(21,reg + M_ADDR); outb((cbuf.Loopback) ? 2:0, reg + M_DATA);
-
-       for (i=0;i<32;i++)
-       {
-               outw( 32+i, reg + M_ADDR); outb(cbuf.l[0].oad[i], reg + M_DATA);
-               outw( 64+i, reg + M_ADDR); outb(cbuf.l[0].osa[i], reg + M_DATA);
-               outw( 96+i, reg + M_ADDR); outb(cbuf.l[0].spid[i], reg + M_DATA);
-               outw(128+i, reg + M_ADDR); outb(cbuf.l[1].oad[i], reg + M_DATA);
-               outw(160+i, reg + M_ADDR); outb(cbuf.l[1].osa[i], reg + M_DATA);
-               outw(192+i, reg + M_ADDR); outb(cbuf.l[1].spid[i], reg + M_DATA);
+       int j;
+
+       /* initializing some variables */
+       card->ReadyInt = 0;
+
+       for(j = 0; j < 256; j++)
+               card->IdTable[j] = NULL;
+
+       for(j = 0; j < (card->d->channels + 1); j++) {
+               card->bch[j].e.busy = 0;
+               card->bch[j].e.D3Id = 0;
+               card->bch[j].e.B2Id = 0;
+               card->bch[j].e.ref = 0;
+               card->bch[j].e.Req = 0;
+               card->bch[j].e.complete = 1;
+               card->bch[j].fsm_state = EICON_STATE_NULL;
        }
-
-#ifdef EICON_PCI_DEBUG
-           printk(KERN_ERR "eicon_pci: starting CPU...\n");
-#endif
-       /* let the CPU run */
-       outw(0x08, reg + M_RESET);
-
-        timeout = jiffies + (5*HZ);
-        while (timeout > jiffies) {
-          outw(0x1e, reg + M_ADDR);    
-           signature = inw(reg + M_DATA);
-           if (signature == DIVAS_SIGNATURE) break;
-           SLEEP(2);
-         }
-        if (signature != DIVAS_SIGNATURE)
-         {
-#ifdef EICON_PCI_DEBUG
-           printk(KERN_ERR "eicon_pci: signature 0x%x expected 0x%x\n",signature,DIVAS_SIGNATURE);
-#endif
-           printk(KERN_ERR "eicon_pci: Timeout, protocol code not running !\n");
-           return -EIO; 
-         }
-#ifdef EICON_PCI_DEBUG
-        printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
-#endif
-
-        /* get serial number and number of channels supported by card */
-       outb(0xff, reg + M_ADDRH);
-       outw(0x3f6, reg + M_ADDR);
-        card->channels = inw(reg + M_DATA);
-        card->serial = (u32)inw(cfg + 0x22) << 16 | (u32)inw(cfg + 0x26);
-        printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
-        printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
-
-        /* test interrupt */
-        card->irqprobe = 1;
-
-        if (!card->ivalid) {
-                if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card))
-                 {
-                  printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
-                  return -EIO;
-                 }
-        }
-        card->ivalid = 1;
-
-#ifdef EICON_PCI_DEBUG
-        printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
-#endif
-        /* Trigger an interrupt and check if it is delivered */
-        outb(0x41, cfg + 0x4c);                /* enable PLX for interrupts */
-       outb(0x89, reg + M_RESET);      /* place int request */
-
-        timeout = jiffies + 20;
-        while (timeout > jiffies) {
-          if (card->irqprobe != 1) break;
-          SLEEP(5);
-         }
-        if (card->irqprobe == 1) {
-           free_irq(card->irq, card); 
-           card->ivalid = 0; 
-           printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
-           return -EIO;
-         }
-
-   /* initializing some variables */
-   ((eicon_card *)card->card)->ReadyInt = 0;
-   for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
-   for(j=0; j< (card->channels + 1); j++) {
-                ((eicon_card *)card->card)->bch[j].e.busy = 0;
-                ((eicon_card *)card->card)->bch[j].e.D3Id = 0;
-                ((eicon_card *)card->card)->bch[j].e.B2Id = 0;
-                ((eicon_card *)card->card)->bch[j].e.ref = 0;
-                ((eicon_card *)card->card)->bch[j].e.Req = 0;
-                ((eicon_card *)card->card)->bch[j].e.complete = 1;
-                ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
-   }
-
-   printk(KERN_INFO "Eicon: Card successfully started\n");
-
- return 0;
 }
 
-
-/*
- * Configure a card, download code into PRI card,
- * check if we get interrupts and return 0 on succes.
- * Return -ERRNO on failure.
- */
-int
-eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
-        eicon_pci_boot    *boot;
-       eicon_pr_ram  *prram;
-        int               i,j;
-        int               timeout;
-       int               FeatureValue = 0;
-       unsigned int      offset, offp=0, size, length;
-       unsigned long int signature = 0;
-       t_dsp_download_space dl_para;
-       t_dsp_download_desc  dsp_download_table;
-        eicon_pci_codebuf cbuf;
-        unsigned char     *code;
-       unsigned char     req_int;
-       char *ram, *reg, *cfg;  
-
-        if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
-                return -EFAULT;
-
-        boot = &card->shmem->boot;
-       ram = (char *)card->PCIram;
-       reg = (char *)card->PCIreg;
-       cfg = (char *)card->PCIcfg;
-       prram = (eicon_pr_ram *)ram;
-
-       /* reset board */
-       writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
-       SLEEP(20);
-       writeb(0, card->PCIreg + MP_RESET);
-       SLEEP(20);
-
-       /* set command count to 0 */
-       writel(0, &boot->reserved); 
-
-       /* check if CPU increments the life word */
-        i = readw(&boot->live);
-        SLEEP(20);
-        if (i == readw(&boot->live)) {
-           printk(KERN_ERR "eicon_pci: card is reset, but CPU not running !\n");
-           return -EIO;
-         }
-#ifdef EICON_PCI_DEBUG
-        printk(KERN_DEBUG "eicon_pci: reset card OK (CPU running)\n");
 #endif
-
-       /* download firmware : DSP and Protocol */
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
-#endif
-
-               /* Allocate code-buffer */
-               if (!(code = kmalloc(400, GFP_KERNEL))) {
-                printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
-                       return -ENOMEM;
-        }
-
-       /* prepare protocol upload */
-       dl_para.type            = DL_PARA_MEM_TYPE;
-       dl_para.dat.mem.boot    = boot;
-
-        for (j = 0; j <= cbuf.dsp_code_num; j++)
-         {
-          if (j==0) size = cbuf.protocol_len;
-               else size = cbuf.dsp_code_len[j];       
-
-           if (j==1) writel(MP_DSP_ADDR, &boot->addr); /* DSP code entry point */
-
-               if (j == 0) dl_para.dat.io.r3addr = MP_PROTOCOL_ADDR;
-               if (j == 1) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE +
-                                       ((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
-               if (j == 2) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE;
-               if (j == 3) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + sizeof(__u32);
-
-           offset = 0;
-           do  /* download block of up to 400 bytes */
-            {
-              length = ((size - offset) >= 400) ? 400 : (size - offset);
-
-               if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
-                       kfree(code);
-                       return -EFAULT;
-               }
-
-               if ((offset == 0) && (j < 2)) {
-                       FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); 
-#ifdef EICON_PCI_DEBUG
-       if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%x.\n", FeatureValue);
-#endif
-                       if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
-                               printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
-                               kfree(code);
-                               return -EFAULT;
-                       }
-                       ((eicon_card *)card->card)->Feature = FeatureValue;
-               }
-
-               if (eicon_upload(&dl_para, length, code, 1))
-               {
-                 if (dl_para.dat.mem.timeout == 0)
-                         printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
-                       else
-                         printk(KERN_ERR "eicon_pci: timeout, no ACK to load !\n");
-                 kfree(code);
-                  return -EIO;
-               }
-
-              /* move onto next block */
-              offset += length;
-             dl_para.dat.mem.r3addr += length;
-            } while (offset < size);
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: %d bytes loaded.\n", offset);
-#endif
-        offp += size;
-         }
-        kfree(code);   
-
-       /* initialize the adapter data structure */
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
-#endif
-        /* clear out config space */
-        for (i = 0; i < 256; i++) writeb(0, &ram[i]);
-
-        /* copy configuration down to the card */
-        writeb(cbuf.tei, &ram[8]);
-        writeb(cbuf.nt2, &ram[9]);
-        writeb(0, &ram[10]);
-        writeb(cbuf.WatchDog, &ram[11]);
-        writeb(cbuf.Permanent, &ram[12]);
-        writeb(cbuf.XInterface, &ram[13]);
-        writeb(cbuf.StableL2, &ram[14]);
-        writeb(cbuf.NoOrderCheck, &ram[15]);
-        writeb(cbuf.HandsetType, &ram[16]);
-        writeb(0, &ram[17]);
-        writeb(cbuf.LowChannel, &ram[18]);
-        writeb(cbuf.ProtVersion, &ram[19]);
-        writeb(cbuf.Crc4, &ram[20]);
-        for (i = 0; i < 32; i++)
-         {
-           writeb(cbuf.l[0].oad[i], &ram[32 + i]);
-           writeb(cbuf.l[0].osa[i], &ram[64 + i]);
-           writeb(cbuf.l[0].spid[i], &ram[96 + i]);
-           writeb(cbuf.l[1].oad[i], &ram[128 + i]);
-           writeb(cbuf.l[1].osa[i], &ram[160 + i]);
-           writeb(cbuf.l[1].spid[i], &ram[192 + i]);
-         }
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: configured card OK\n");
-#endif
-
-       /* start adapter */
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: tell card to start...\n");
-#endif
-        writel(MP_PROTOCOL_ADDR, &boot->addr); /* RISC code entry point */
-        writel(3, &boot->cmd); /* DIVAS_START_CMD */
-
-        /* wait till card ACKs */
-        timeout = jiffies + (5*HZ);
-        while (timeout > jiffies) {
-           signature = readl(&boot->signature);
-           if ((signature >> 16) == DIVAS_SIGNATURE) break;
-           SLEEP(2);
-         }
-        if ((signature >> 16) != DIVAS_SIGNATURE)
-         {
-#ifdef EICON_PCI_DEBUG
-           printk(KERN_ERR "eicon_pci: signature 0x%lx expected 0x%x\n",(signature >> 16),DIVAS_SIGNATURE);
-#endif
-           printk(KERN_ERR "eicon_pci: timeout, protocol code not running !\n");
-           return -EIO;
-         }
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
-#endif
-
-       /* get serial number and number of channels supported by card */
-        card->channels = readb(&ram[0x3f6]);
-        card->serial = readl(&ram[0x3f0]);
-        printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
-        printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
-
-       /* test interrupt */
-       readb(&ram[0x3fe]);
-        writeb(0, &ram[0x3fe]); /* reset any pending interrupt */
-       readb(&ram[0x3fe]);
-
-        writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
-        writew(0, &cfg[MP_IRQ_RESET + 2]);
-
-        card->irqprobe = 1;
-
-       if (!card->ivalid) {
-               if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) 
-                {
-                 printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
-                 return -EIO;
-                }
-       }
-       card->ivalid = 1;
-
-        req_int = readb(&prram->ReadyInt);
-#ifdef EICON_PCI_DEBUG
-       printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
-#endif
-        req_int++;
-        /* Trigger an interrupt and check if it is delivered */
-        writeb(req_int, &prram->ReadyInt);
-
-        timeout = jiffies + 20;
-        while (timeout > jiffies) {
-          if (card->irqprobe != 1) break;
-          SLEEP(2);
-         }
-        if (card->irqprobe == 1) {
-           free_irq(card->irq, card);
-          card->ivalid = 0;
-           printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
-           return -EIO;
-         }
-
-   /* initializing some variables */
-   ((eicon_card *)card->card)->ReadyInt = 0;
-   for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
-   for(j=0; j< (card->channels + 1); j++) {
-               ((eicon_card *)card->card)->bch[j].e.busy = 0;
-               ((eicon_card *)card->card)->bch[j].e.D3Id = 0;
-               ((eicon_card *)card->card)->bch[j].e.B2Id = 0;
-               ((eicon_card *)card->card)->bch[j].e.ref = 0;
-               ((eicon_card *)card->card)->bch[j].e.Req = 0;
-                ((eicon_card *)card->card)->bch[j].e.complete = 1;
-                ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
-   }
-
-   printk(KERN_INFO "Eicon: Card successfully started\n");
-
- return 0;
-}
-
 #endif /* CONFIG_PCI */
 
index 384cc422c536aef74197043d54858840aee9ecfe..17fd4183a7a9bee16ae061f2d3bee52e4a46238c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.h,v 1.4 2000/01/23 21:21:23 armin Exp $
+/* $Id: eicon_pci.h,v 1.6 2000/05/07 08:51:04 armin Exp $
  *
  * ISDN low-level module for Eicon active ISDN-Cards (PCI part).
  *
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * $Log: eicon_pci.h,v $
- * Revision 1.4  2000/01/23 21:21:23  armin
- * Added new trace capability and some updates.
- * DIVA Server BRI now supports data for ISDNLOG.
- *
- * Revision 1.3  1999/03/29 11:19:51  armin
- * I/O stuff now in seperate file (eicon_io.c)
- * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
- *
- * Revision 1.2  1999/03/02 12:37:50  armin
- * Added some important checks.
- * Analog Modem with DSP.
- * Channels will be added to Link-Level after loading firmware.
- *
- * Revision 1.1  1999/01/01 18:09:46  armin
- * First checkin of new eicon driver.
- * DIVA-Server BRI/PCI and PRI/PCI are supported.
- * Old diehl code is obsolete.
- *
- *
  */
 
 #ifndef eicon_pci_h
 
 #ifdef __KERNEL__
 
-
-#define PCI_VENDOR_EICON        0x1133
-#define PCI_DIVA_PRO20          0xe001 /* Not supported */
-#define PCI_DIVA20              0xe002 /* Not supported */
-#define PCI_DIVA_PRO20_U        0xe003 /* Not supported */
-#define PCI_DIVA20_U            0xe004 /* Not supported */
-#define PCI_MAESTRA             0xe010
-#define PCI_MAESTRAQ            0xe012
-#define PCI_MAESTRAQ_U          0xe013
-#define PCI_MAESTRAP            0xe014
-
-#define DIVA_PRO20          1
-#define DIVA20              2
-#define DIVA_PRO20_U        3
-#define DIVA20_U            4
-#define MAESTRA             5
-#define MAESTRAQ            6
-#define MAESTRAQ_U          7
-#define MAESTRAP            8
-
-#define TRUE  1
-#define FALSE 0
-
-#define DIVAS_SIGNATURE 0x4447
-
-
-/* MAESTRA BRI PCI */
-
-#define M_RESET                0x10            /* offset of reset register */
-#define M_DATA         0x00            /* offset of data register */
-#define M_ADDR         0x04            /* offset of address register */
-#define M_ADDRH                0x0c            /* offset of high address register */
-
-#define M_DSP_CODE_LEN            0xbf7d0000
-#define M_DSP_CODE                0xbf7d0004  /* max 128K DSP-Code */ 
-#define M_DSP_CODE_BASE           0xbf7a0000  
-#define M_MAX_DSP_CODE_SIZE       0x00050000  /* max 320K DSP-Code (Telindus) */
-
-
-
-/* MAESTRA PRI PCI */
-
-#define MP_SHARED_RAM_OFFSET 0x1000  /* offset of shared RAM base in the DRAM memory bar */
-
-#define MP_IRQ_RESET     0xc18       /* offset of interrupt status register in the CONFIG memory bar */
-#define MP_IRQ_RESET_VAL 0xfe        /* value to clear an interrupt */
-
-#define MP_PROTOCOL_ADDR 0xa0011000  /* load address of protocol code */
-#define MP_DSP_ADDR      0xa03c0000  /* load address of DSP code */
-#define MP_MAX_PROTOCOL_CODE_SIZE  0x000a0000   /* max 640K Protocol-Code */
-#define MP_DSP_CODE_BASE           0xa03a0000
-#define MP_MAX_DSP_CODE_SIZE       0x00060000   /* max 384K DSP-Code */
-
-#define MP_RESET         0x20        /* offset of RESET register in the DEVICES memory bar */
-
-/* RESET register bits */
-#define _MP_S2M_RESET    0x10        /* active lo   */
-#define _MP_LED2         0x08        /* 1 = on      */
-#define _MP_LED1         0x04        /* 1 = on      */
-#define _MP_DSP_RESET    0x02        /* active lo   */
-#define _MP_RISC_RESET   0x81        /* active hi, bit 7 for compatibility with old boards */
-
-/* boot interface structure */
-typedef struct {
-       __u32 cmd       __attribute__ ((packed));
-       __u32 addr      __attribute__ ((packed));
-       __u32 len       __attribute__ ((packed));
-       __u32 err       __attribute__ ((packed));
-       __u32 live      __attribute__ ((packed));
-       __u32 reserved[(0x1020>>2)-6] __attribute__ ((packed));
-       __u32 signature __attribute__ ((packed));
-       __u8 data[1];    /* real interface description */
-} eicon_pci_boot;
-
-
-#define DL_PARA_IO_TYPE   0
-#define DL_PARA_MEM_TYPE  1
-
-typedef struct tag_dsp_download_space
-{
-  __u16 type;  /* see definitions above to differ union elements */
-  union
-  {
-    struct
-    {
-      __u32               r3addr;
-      __u16               ioADDR;
-      __u16               ioADDRH;
-      __u16               ioDATA;
-      __u16               BadData;  /* in case of verify error */
-      __u16               GoodData;
-    } io;     /* for io based adapters */
-    struct
-    {
-      __u32               r3addr;
-      eicon_pci_boot     *boot;
-      __u32               BadData;  /* in case of verify error */
-      __u32               GoodData;
-      __u16               timeout;
-    } mem;    /* for memory based adapters */
-  } dat;
-} t_dsp_download_space;
-
-
-/* Shared memory */
-typedef union {
-       eicon_pci_boot boot;
-} eicon_pci_shmem;
-
 /*
  * card's description
  */
 typedef struct {
-       int               ramsize;
        int               irq;      /* IRQ                        */
-       unsigned int      PCIram;
-       unsigned int      PCIreg;
-       unsigned int      PCIcfg;
-       long int          serial;   /* Serial No.                 */
        int               channels; /* No. of supported channels  */
         void*             card;
-        eicon_pci_shmem*  shmem;    /* Shared-memory area         */
-        unsigned char*    intack;   /* Int-Acknowledge            */
-        unsigned char*    stopcpu;  /* Writing here stops CPU     */
-        unsigned char*    startcpu; /* Writing here starts CPU    */
         unsigned char     type;     /* card type                  */
-        unsigned char     irqprobe; /* Flag: IRQ-probing          */
-        unsigned char     mvalid;   /* Flag: Memory is valid      */
-        unsigned char     ivalid;   /* Flag: IRQ is valid         */
         unsigned char     master;   /* Flag: Card is Quadro 1/4   */
-        void*             generic;  /* Ptr to generic card struct */
 } eicon_pci_card;
 
-
-
-extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb);
-extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb);
-extern void eicon_pci_release(eicon_pci_card *card);
-extern void eicon_pci_printpar(eicon_pci_card *card);
 extern int eicon_pci_find_card(char *ID);
 
 #endif  /* __KERNEL__ */
 
 #endif /* eicon_pci_h */
+
diff --git a/drivers/isdn/eicon/fcheck.c b/drivers/isdn/eicon/fcheck.c
new file mode 100644 (file)
index 0000000..c86f7d3
--- /dev/null
@@ -0,0 +1,31 @@
+/* $Id: fcheck.c,v 1.3 2000/06/12 12:44:02 armin Exp $
+ * 
+ * (c) 2000 Cytronics & Melware
+ *
+ *  This file is (c) under GNU PUBLIC LICENSE
+ *  For changes and modifications please read
+ *  ../../../Documentation/isdn/README.eicon
+ *
+ *
+ */
+#include <linux/kernel.h>
+
+char *
+file_check(void) {
+
+#ifdef FILECHECK
+#if FILECHECK == 0
+       return("verified");
+#endif
+#if FILECHECK == 1 
+       return("modified");
+#endif
+#if FILECHECK == 127 
+       return("verification failed");
+#endif
+#else
+       return("not verified");
+#endif
+}
+
diff --git a/drivers/isdn/eicon/fourbri.c b/drivers/isdn/eicon/fourbri.c
new file mode 100644 (file)
index 0000000..5fe9817
--- /dev/null
@@ -0,0 +1,583 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.7  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* Diva Server 4BRI specific part of initialisation */
+#include "sys.h"
+#include "idi.h"
+#include "divas.h"
+#include "pc.h"
+#include "pr_pc.h"
+#include "dsp_defs.h"
+#include "constant.h"
+#include "adapter.h"
+#include "uxio.h"
+
+#define TEST_INT_DIVAS_Q       0x13
+
+#define        DIVAS_MAINT_OFFSET      0xff00  /* value for 4BRI card */
+#define MQ_BOARD_DSP_OFFSET 0x00a00000
+#define MQ_DSP1_ADDR_OFFSET 0x00000008
+#define MQ_DSP_JUNK_OFFSET  0x00000400
+#define MQ_DSP1_DATA_OFFSET 0x00000000
+#define MQ_BOARD_ISAC_DSP_RESET  0x00800028
+#define MQ_BREG_RISC  0x1200      /* RISC Reset */
+#define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
+#define MQ_RISC_COLD_RESET_MASK         0x0001      /* RISC Cold reset                        */
+#define MQ_RISC_WARM_RESET_MASK         0x0002      /* RISC Warm reset                        */
+#define MQ_IRQ_REQ_ON                   0x1
+#define MQ_IRQ_REQ_OFF                  0x0
+#define MQ_BREG_IRQ_TEST                0x0608
+#define PLX9054_INTCSR      0x69 
+#define PLX9054_INT_ENA     0x09
+
+#define DIVAS_IOBASE   0x01
+#define M_PCI_RESET    0x10
+
+byte mem_in(ADAPTER *a, void *adr);
+word mem_inw(ADAPTER *a, void *adr);
+void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
+void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
+void mem_out(ADAPTER *a, void *adr, byte data);
+void mem_outw(ADAPTER *a, void *adr, word data);
+void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
+void mem_inc(ADAPTER *a, void *adr);
+
+int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg);
+int fourbri_ISR (card_t* card);
+
+int FPGA_Download(word, dword, byte *, byte *, int);
+extern byte FPGA_Bytes[];
+extern void *get_card(int);
+
+byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
+void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
+word GetProtFeatureValue(char *sw_id);
+
+void memcp(byte *dst, byte *src, dword dwLen);
+int memcm(byte *dst, byte *src, dword dwLen);
+
+static int diva_server_4bri_reset(card_t *card)
+{
+       byte *ctl;
+
+       DPRINTF(("divas: reset Diva Server 4BRI"));
+
+       ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
+
+       /* stop RISC, DSP's and ISAC  */
+   UxCardMemOut(card->hw, &ctl[MQ_BREG_RISC], 0);
+   UxCardMemOut(card->hw, &ctl[MQ_ISAC_DSP_RESET], 0);
+
+       UxCardMemDetach(card->hw, ctl);
+
+       return 0;
+}
+
+static int diva_server_4bri_config(card_t *card, dia_config_t *config)
+{
+       byte *shared;
+       int i, j;
+
+       DPRINTF(("divas: configure Diva Server 4BRI"));
+
+       shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+       
+       for (i=0; i<256; i++)
+       {
+               UxCardMemOut(card->hw, &shared[i], 0);
+       }
+
+       UxCardMemOut(card->hw, &shared[ 8], config->tei);
+       UxCardMemOut(card->hw, &shared[ 9], config->nt2);
+       UxCardMemOut(card->hw, &shared[10], 0);
+       UxCardMemOut(card->hw, &shared[11], config->watchdog);
+       UxCardMemOut(card->hw, &shared[12], config->permanent);
+       UxCardMemOut(card->hw, &shared[13], config->x_interface);
+       UxCardMemOut(card->hw, &shared[14], config->stable_l2);
+       UxCardMemOut(card->hw, &shared[15], config->no_order_check);
+       UxCardMemOut(card->hw, &shared[16], config->handset_type);
+       UxCardMemOut(card->hw, &shared[17], 0);
+       UxCardMemOut(card->hw, &shared[18], config->low_channel);
+       UxCardMemOut(card->hw, &shared[19], config->prot_version);
+       UxCardMemOut(card->hw, &shared[20], config->crc4);
+
+       if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+       {
+               DPRINTF(("divas: Signifying V.90"));
+               UxCardMemOut(card->hw, &shared[22], 4);
+       }
+       else
+       {
+               UxCardMemOut(card->hw, &shared[22], 0);
+       }
+
+       for (i=0; i<2; i++)
+       {
+               for (j=0; j<32; j++)
+               {
+                       UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
+               }
+
+               for (j=0; j<32; j++)
+               {
+                       UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
+               }
+
+               for (j=0; j<32; j++)
+               {
+                       UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
+               }
+       }
+
+       UxCardMemDetach(card->hw, shared);
+
+       return 0;
+}
+
+static
+void diva_server_4bri_reset_int(card_t *card)
+{
+       byte *ctl;
+
+       ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
+
+       UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
+
+       UxCardMemDetach(card->hw, ctl);
+
+       return;
+}
+
+static int diva_server_4bri_test_int(card_t *card)
+{
+       byte *ctl, i;
+       byte *reg;
+
+       DPRINTF(("divas: test interrupt for Diva Server 4BRI"));
+
+       /* We get the last (dummy) adapter in so we need to go back to the first */
+
+       card = get_card(card->cfg.card_id - 3);
+
+       /* Enable interrupts on PLX chip */
+
+       reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
+
+       UxCardPortIoOut(card->hw, reg, PLX9054_INTCSR, PLX9054_INT_ENA);
+
+       UxCardMemDetach(card->hw, reg);
+
+       /* Set the test interrupt flag */
+       card->test_int_pend = TEST_INT_DIVAS_Q;
+
+       /* Now to trigger the interrupt */
+
+       ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
+
+       UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_ON);
+
+       UxCardMemDetach(card->hw, ctl);
+
+       for (i = 0; i < 50; i++)
+       {
+               if (!card->test_int_pend)
+               {
+                       break;
+               }
+               UxPause(10);
+       }
+
+       if (card->test_int_pend)
+       {
+               DPRINTF(("active: timeout waiting for card to interrupt"));
+               return (-1);
+       }
+       
+       return 0;
+}
+
+
+static void print_hdr(unsigned char *code, int offset)
+{
+       unsigned char hdr[80];
+       int i;
+
+       i = 0;
+
+       while ((i < (DIM(hdr) -1)) && 
+               (code[offset + i] != '\0') &&
+               (code[offset + i] != '\r') &&
+               (code[offset + i] != '\n'))
+       {
+               hdr[i] = code[offset + i];
+               i++;
+       }
+
+       hdr[i] = '\0';
+
+       DPRINTF(("divas: loading %s", hdr));
+}
+
+static int diva_server_4bri_load(card_t *card, dia_load_t *load)
+{
+       byte *pRAM=NULL;
+       int download_offset=0;
+       card_t *FirstCard;
+       byte sw_id[80];
+
+       DPRINTF(("divas: loading Diva Server 4BRI[%d]", load->card_id));
+
+       switch(load->code_type)
+       {
+               case DIA_CPU_CODE:
+                       DPRINTF(("divas: RISC code"));
+                       print_hdr(load->code, 0x80);
+                       card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
+                       download_offset = 0; // Protocol code written to offset 0
+                       pRAM = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
+                       break;
+
+               case DIA_DSP_CODE:
+                       DPRINTF(("divas: DSP code"));
+                       print_hdr(load->code, 0x0); 
+                       FirstCard = get_card(load->card_id - 3);
+                       if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+                       {
+                               download_offset = MQ_V90D_DSP_CODE_BASE;
+                       }
+                       else
+                       {
+                               download_offset = MQ_ORG_DSP_CODE_BASE;
+                       }
+                       pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
+                       download_offset += (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC);
+
+                       break;
+
+               case DIA_TABLE_CODE:
+                       DPRINTF(("divas: TABLE code"));
+                       FirstCard = get_card(load->card_id - 3);
+                       if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+                       {
+                               download_offset = MQ_V90D_DSP_CODE_BASE + sizeof(dword);
+                       }
+                       else
+                       {
+                               download_offset = MQ_ORG_DSP_CODE_BASE + sizeof(dword);
+                       }
+                       pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
+                       break;
+
+               case DIA_CONT_CODE:
+                       DPRINTF(("divas: continuation code"));
+                       break;
+
+        case DIA_DLOAD_CNT:
+                       DPRINTF(("divas: COUNT code"));
+                       FirstCard = get_card(load->card_id - 3);
+                       if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
+                       {
+                               download_offset = MQ_V90D_DSP_CODE_BASE;
+                       }
+                       else
+                       {
+                               download_offset = MQ_ORG_DSP_CODE_BASE;
+                       }
+                       pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
+                       break;
+
+               case DIA_FPGA_CODE:
+                       DPRINTF(("divas: 4BRI FPGA download - %d bytes", load->length));
+                       if (FPGA_Download(IDI_ADAPTER_MAESTRAQ,
+                       card->hw->io_base,
+                        sw_id,
+                        load->code,
+                        load->length
+                       ) == -1)
+                       {
+                               DPRINTF(("divas: FPGA download failed"));
+                               return -1;
+                       }
+
+                       /* NOW reset the 4BRI */
+                       diva_server_4bri_reset(card);
+                       return 0; // No need for anything further loading
+
+               default:
+                       DPRINTF(("divas: unknown code type"));
+                       return -1;
+       }
+
+   memcp(pRAM + (download_offset & 0x3FFFFF), load->code, load->length);
+
+       {
+               int mism_off;
+       if ((mism_off = memcm(pRAM + (download_offset & 0x3FFFFF), load->code, load->length)))
+       {
+               DPRINTF(("divas: memory mismatch at offset %d", mism_off));
+               UxCardMemDetach(card->hw, pRAM);
+               return -1;
+       }
+       }
+
+       UxCardMemDetach(card->hw, pRAM);
+
+       return 0;
+}
+
+static int diva_server_4bri_start(card_t *card, byte *channels)
+{
+       byte *ctl;
+       byte *shared, i;
+       int adapter_num;
+
+       DPRINTF(("divas: start Diva Server 4BRI"));
+       *channels = 0;
+       card->is_live = FALSE;
+
+       ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
+
+       UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_COLD_RESET_MASK);
+
+       UxPause(2);
+
+       UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
+
+       UxPause(10);
+       
+       UxCardMemDetach(card->hw, ctl);
+
+       shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       for ( i = 0 ; i < 300 ; ++i )
+       {
+               UxPause (10) ;
+
+               if ( UxCardMemInW(card->hw, &shared[0x1E]) == 0x4447 )
+               {
+                       DPRINTF(("divas: Protocol startup time %d.%02d seconds",
+                                (i / 100), (i % 100) ));
+
+                       break;
+               }
+       }
+
+       if (i==300)
+       {
+               DPRINTF(("divas: Timeout starting card"));
+               DPRINTF(("divas: Signature == 0x%04X", UxCardMemInW(card->hw, &shared[0x1E])));
+
+               UxCardMemDetach(card->hw, shared);
+               return -1;
+       }
+
+       UxCardMemDetach(card->hw, shared);
+
+       for (adapter_num=3; adapter_num >= 0; adapter_num--)
+       {
+               card_t *qbri_card;
+
+               qbri_card = get_card(card->cfg.card_id - adapter_num);
+
+               if (qbri_card)
+               {
+                       qbri_card->is_live = TRUE;
+                       shared = UxCardMemAttach(qbri_card->hw, DIVAS_SHARED_MEMORY);
+                       *channels += UxCardMemIn(qbri_card->hw, &shared[0x3F6]);
+                       UxCardMemDetach(qbri_card->hw, shared);
+               }
+               else
+               {
+                       DPRINTF(("divas: Couldn't get card info %d", card->cfg.card_id));
+               }
+       }
+
+       diva_server_4bri_test_int(card);
+
+       return 0;
+}
+
+static
+int    diva_server_4bri_mem_get(card_t *card, mem_block_t *mem_block)
+
+{
+       byte    *a;
+       byte    *card_addr;
+       word    length = 0;
+       int             i;
+
+       a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
+
+       card_addr = a;
+       card_addr += mem_block->addr;
+
+       for (i=0; i < sizeof(mem_block->data); i++)
+       {
+               mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
+               card_addr++;
+               length++;
+       }
+
+       UxCardMemDetach(card->hw, a);
+
+       return length;
+}
+
+/*
+ * Initialise 4BRI specific entry points
+ */
+
+int Divas4BriInit(card_t *card, dia_card_t *cfg)
+{
+//     byte sw_id[80];
+//     extern int FPGA_Done;
+
+       DPRINTF(("divas: initialise Diva Server 4BRI"));
+
+       if (Divas4BRIInitPCI(card, cfg) == -1)
+       {
+               return -1;
+       }
+
+       /* Need to download the FPGA */
+/*     if (!FPGA_Done)
+       {
+               int retVal;
+
+               retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
+                       cfg->io_base,
+                        sw_id,
+                        FPGA_Bytes
+                       );
+               if(retVal==-1)
+               {
+               
+                       DPRINTF(("divas: FPGA Download Failed"));
+                       return -1;
+
+               }
+               FPGA_Done = 1;
+       } */
+
+       card->card_reset = diva_server_4bri_reset;
+       card->card_load = diva_server_4bri_load;
+       card->card_config = diva_server_4bri_config;
+       card->card_start = diva_server_4bri_start;
+       card->reset_int = diva_server_4bri_reset_int;
+       card->card_mem_get = diva_server_4bri_mem_get;
+
+       card->xlog_offset = DIVAS_MAINT_OFFSET;
+
+       card->out = DivasOut;
+       card->test_int = DivasTestInt;
+       card->dpc = DivasDpc;
+       card->clear_int = DivasClearInt;
+       card->card_isr = fourbri_ISR;
+
+       card->a.ram_out = mem_out;
+       card->a.ram_outw = mem_outw;
+       card->a.ram_out_buffer = mem_out_buffer;
+       card->a.ram_inc = mem_inc;
+
+       card->a.ram_in = mem_in;
+       card->a.ram_inw = mem_inw;
+       card->a.ram_in_buffer = mem_in_buffer;
+       card->a.ram_look_ahead = mem_look_ahead;
+
+       return 0;
+}
+
+void memcp(byte *dst, byte *src, dword dwLen)
+{
+       while (dwLen)
+       {
+               *dst = *src;
+               dst++; src++;
+               dwLen--;
+       }
+}
+
+int memcm(byte *dst, byte *src, dword dwLen)
+{
+       int offset = 0;
+
+       while (offset < dwLen)
+       {
+               if(*dst != *src)
+                       return (offset+1);
+
+               offset++;
+               src++;
+               dst++;
+       }
+
+       return 0;
+}
+
+
+
+/*int fourbri_ISR (card_t* card) 
+{
+       int served = 0;
+       byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
+       
+
+       if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01) 
+       {
+               served = 1;
+               card->int_pend  += 1;
+               DivasDpcSchedule(); 
+               UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
+       }
+
+       UxCardMemDetach(card->hw, DivasIOBase);
+
+       return (served != 0);
+}*/
+
+
+int fourbri_ISR (card_t* card) 
+{
+       int served = 0;
+       byte *ctl;
+       byte *reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
+
+       if (UxCardPortIoIn(card->hw, reg, PLX9054_INTCSR) & 0x80) 
+       {
+               served = 1;
+               card->int_pend  += 1;
+               DivasDpcSchedule(); /* ISR DPC */
+
+               ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
+               UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
+               UxCardMemDetach(card->hw, ctl);
+       }
+
+       UxCardMemDetach(card->hw, reg);
+       return (served != 0);
+}
diff --git a/drivers/isdn/eicon/fpga.c b/drivers/isdn/eicon/fpga.c
new file mode 100644 (file)
index 0000000..b5f2167
--- /dev/null
@@ -0,0 +1,158 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.2  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include "sys.h"
+#include "idi.h"
+#include "uxio.h"
+
+#define FPGA_PORT              0x6E
+#define FPGA_DLOAD_BUFLEN      256
+#define NAME_OFFSET            0x10
+#define NAME_MAXLEN            12
+#define DATE_OFFSET            0x2c
+#define DATE_MAXLEN            10
+
+word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
+void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
+void UxPause(long int);
+
+/*-------------------------------------------------------------------------*/
+/* Loads the FPGA configuration file onto the hardware.                    */
+/* Function returns 0 on success, else an error number.                    */
+/* On success, an identifier string is returned in the buffer              */
+/*                                                                         */
+/* A buffer of FPGA_BUFSIZE, a handle to the already opened bitstream      */
+/* file and a file read function has to be provided by the operating       */
+/* system part.                                                            */
+/* ----------------------------------------------------------------------- */
+int FPGA_Download( word      cardtype,
+                        dword     RegBase,
+                        byte *strbuf,
+                        byte FPGA_SRC[],
+                       int FPGA_LEN
+                      )
+{
+  word        i, j, k;
+  word        baseval, Mask_PROGRAM, Mask_DONE, Mask_CCLK, Mask_DIN;
+  dword       addr;
+  byte        *pFPGA;
+
+  //--- check for legal cardtype
+  switch (cardtype)
+  {
+    case IDI_ADAPTER_MAESTRAQ:
+      addr          = RegBase ; // address where to access FPGA
+      Mask_PROGRAM  = 0x0001;         // FPGA pins at address
+      Mask_DONE     = 0x0002;
+      Mask_CCLK     = 0x0100;
+      Mask_DIN      = 0x0400;
+      baseval       = 0x000d;         // PROGRAM hi, CCLK lo, DIN lo by default
+    break;
+      
+    default:
+       
+       DPRINTF(("divas: FPGA Download ,Illegal Card"));
+       return -1; // illegal card 
+  }
+
+  //--- generate id string from file content
+  for (j=NAME_OFFSET, k=0; j<(NAME_OFFSET+NAME_MAXLEN); j++, k++) //name
+  {
+    if (!FPGA_SRC[j]) break;
+    strbuf[k] = FPGA_SRC[j];
+  } 
+  strbuf[k++] = ' ';
+  for (j=DATE_OFFSET; j<(DATE_OFFSET+DATE_MAXLEN); j++, k++) // date
+  {
+    if (!FPGA_SRC[j]) break;
+    strbuf[k] = FPGA_SRC[j];
+  } 
+  strbuf[k] = 0;
+
+  DPRINTF(("divas: FPGA Download - %s", strbuf));
+
+  //--- prepare download, Pulse PROGRAM pin down.
+  UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval &~Mask_PROGRAM);  // PROGRAM low pulse
+  UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);                 // release
+  UxPause(50);  // wait until FPGA finised internal memory clear
+  
+  //--- check done pin, must be low
+  if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE) 
+  {
+    DPRINTF(("divas: FPGA_ERR_DONE_WRONG_LEVEL"));
+    return -1;
+  }
+
+  pFPGA = FPGA_SRC;
+
+  i = 0; 
+  /* Move past the header */
+  while ((FPGA_SRC[i] != 0xFF) && (i < FPGA_LEN)) 
+  {
+    i++;
+  }
+
+  // We've hit the 0xFF so move on to the next byte
+  // i++;
+  DPRINTF(("divas: FPGA Code starts at offset %d", i));
+
+  //--- put data onto the FPGA
+  for (;i<FPGA_LEN; i++)
+  {
+    //--- put byte onto FPGA
+    for (j=0; j<8; j++)
+    {
+      if (FPGA_SRC[i] &(0x80>>j)) baseval |= Mask_DIN; // write a hi
+      else                      baseval &=~Mask_DIN; // write a lo
+      UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);
+      UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK);     // set CCLK hi
+      UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);                 // set CCLK lo
+    }
+  }
+
+  //--- add some additional startup clock cycles and check done pin
+  for (i=0; i<5; i++) 
+  {
+    UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK);     // set CCLK hi
+    UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);                 // set CCLK lo
+  }
+
+  UxPause(100);
+
+  if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE) 
+  {
+    DPRINTF(("divas: FPGA download successful"));
+  }
+  else
+  {
+    DPRINTF(("divas: FPGA download failed - 0x%x", UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT)));
+       return -1;
+  }
+
+return 0;
+}
+
diff --git a/drivers/isdn/eicon/idi.c b/drivers/isdn/eicon/idi.c
new file mode 100644 (file)
index 0000000..f9b8a0e
--- /dev/null
@@ -0,0 +1,870 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.8  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/*
+ * Core driver for Diva Server cards
+ * Implements the IDI interface
+ */
+
+#include "idi.h"
+#include "adapter.h"
+#include "pc.h"
+#include "pr_pc.h"
+#include "sys.h"
+#include "uxio.h"
+
+/* IDI request functions */
+
+static void    request(card_t *card, ENTITY *e);
+
+static void req_0(ENTITY *e)   { request(&DivasCards[ 0], e); }
+static void req_1(ENTITY *e)   { request(&DivasCards[ 1], e); }
+static void req_2(ENTITY *e)   { request(&DivasCards[ 2], e); }
+static void req_3(ENTITY *e)   { request(&DivasCards[ 3], e); }
+static void req_4(ENTITY *e)   { request(&DivasCards[ 4], e); }
+static void req_5(ENTITY *e)   { request(&DivasCards[ 5], e); }
+static void req_6(ENTITY *e)   { request(&DivasCards[ 6], e); }
+static void req_7(ENTITY *e)   { request(&DivasCards[ 7], e); }
+static void req_8(ENTITY *e)   { request(&DivasCards[ 8], e); }
+static void req_9(ENTITY *e)   { request(&DivasCards[ 9], e); }
+static void req_10(ENTITY *e)  { request(&DivasCards[10], e); }
+static void req_11(ENTITY *e)  { request(&DivasCards[11], e); }
+static void req_12(ENTITY *e)  { request(&DivasCards[12], e); }
+static void req_13(ENTITY *e)  { request(&DivasCards[13], e); }
+static void req_14(ENTITY *e)  { request(&DivasCards[14], e); }
+static void req_15(ENTITY *e)  { request(&DivasCards[15], e); }
+
+IDI_CALL DivasIdiRequest[16] =
+{
+    &req_0,            &req_1,         &req_2,         &req_3,
+    &req_4,            &req_5,         &req_6,         &req_7,
+    &req_8,            &req_9,         &req_10,        &req_11,
+       &req_12,        &req_13,        &req_14,        &req_15
+};
+
+#define PR_RAM  ((struct pr_ram *)0)
+#define RAM ((struct dual *)0)
+
+/*------------------------------------------------------------------*/
+/* local function prototypes                                        */
+/*------------------------------------------------------------------*/
+
+static byte isdn_rc(ADAPTER *, byte, byte, byte, word);
+static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
+
+/*
+ * IDI related functions
+ */
+
+static
+ENTITY *entity_ptr(ADAPTER *a, byte e_no)
+{
+       card_t  *card;
+
+       card = a->io;
+
+       return card->e_tbl[e_no].e;
+}
+
+static
+void   CALLBACK(ADAPTER *a, ENTITY *e)
+{
+       card_t  *card = a->io;
+
+       if (card->log_types & DIVAS_LOG_IDI)
+       {
+               DivasLogIdi(card, e, FALSE);
+       }
+
+       (*e->callback)(e);
+}
+
+static
+void   *PTR_P(ADAPTER *a, ENTITY *e, void *P)
+{
+       return(P);
+}
+
+static
+void   *PTR_R(ADAPTER *a, ENTITY *e)
+{
+       return((void*)e->R);
+}
+
+static
+void   *PTR_X(ADAPTER *a, ENTITY *e)
+{
+       return((void*)e->X);
+}
+
+static
+void   free_entity(ADAPTER *a, byte e_no) 
+{
+       card_t  *card;
+       int             ipl;
+
+       card = a->io;
+
+       ipl = UxCardLock(card->hw);
+
+       card->e_tbl[e_no].e = NULL;
+       card->e_count--;
+
+       UxCardUnlock(card->hw, ipl);
+
+       return;
+}
+
+static
+void   assign_queue(ADAPTER * a, byte e_no, word ref)
+{
+       card_t  *card;
+       int             ipl;
+
+       card = a->io;
+
+       ipl = UxCardLock(card->hw);
+
+       card->e_tbl[e_no].assign_ref = ref;
+       card->e_tbl[e_no].next = card->assign;
+       card->assign = e_no;
+
+       UxCardUnlock(card->hw, ipl);
+
+       return;
+}
+
+static
+byte   get_assign(ADAPTER *a, word ref)
+{
+       card_t  *card;
+       byte    e_no;
+       int             ipl;
+
+       card = a->io;
+
+       ipl = UxCardLock(card->hw);
+
+       e_no = (byte)card->assign;
+       while (e_no)
+       {
+               if (card->e_tbl[e_no].assign_ref == ref)
+               {
+                       break;
+               }
+               e_no = card->e_tbl[e_no].next;
+       }
+
+       UxCardUnlock(card->hw, ipl);
+
+       return e_no;
+}
+
+static
+void   req_queue(ADAPTER * a, byte e_no)
+{
+       card_t  *card;
+       int             ipl;
+
+       card = a->io;
+
+       ipl = UxCardLock(card->hw);
+
+       card->e_tbl[e_no].next = 0;
+
+       if (card->e_head)
+       {
+               card->e_tbl[card->e_tail].next = e_no;
+               card->e_tail = e_no;
+       }
+       else
+       {
+               card->e_head = e_no;
+               card->e_tail = e_no;
+       }
+
+       UxCardUnlock(card->hw, ipl);
+
+       return;
+}
+
+static
+byte   look_req(ADAPTER * a)
+{
+       card_t  *card;
+
+       card = a->io;
+
+       return(card->e_head);
+}
+
+static
+void   next_req(ADAPTER * a)
+{
+       card_t  *card;
+       int             ipl;
+
+
+       card = a->io;
+
+       ipl = UxCardLock(card->hw);
+
+       card->e_head = card->e_tbl[card->e_head].next;
+       if (!card->e_head)
+       {
+               card->e_tail = 0;
+       }
+
+       UxCardUnlock(card->hw, ipl);
+
+       return;
+}
+
+
+/*
+ * IDI request function for active cards
+ */
+
+static
+void   request(card_t *card, ENTITY *e)
+{
+       word    *special_req;
+       int             i;
+       int             ipl;
+
+       if (card->log_types & DIVAS_LOG_IDI)
+       {
+               DivasLogIdi(card, e, TRUE);
+       }
+
+       if (!e->Req)
+       {
+               special_req = (word *) e;
+
+               switch (*special_req)
+               {
+               case REQ_REMOVE:
+                       return;
+
+               case REQ_NAME:
+                       for (i=0; i < DIM(card->cfg.name); i++)
+                       {
+                               ((struct get_name_s *) e)->name[i] = card->cfg.name[i];
+                       }
+                       return;
+
+               case REQ_SERIAL:
+               case REQ_XLOG:
+                       DPRINTF(("IDI: attempted REQ_SERIAL or REQ_XLOG"));
+                       return;
+
+               default:
+                       return;
+               }
+       }
+
+       ipl = UxCardLock(card->hw);
+
+       if (!(e->Id & 0x1f))
+       {
+               DPRINTF(("IDI: ASSIGN req"));
+
+               for (i = 1; i < card->e_max; i++)
+               {
+                       if (!card->e_tbl[i].e)
+                       {
+                               break;
+                       }
+               }
+
+               if (i == card->e_max)
+               {
+                       DPRINTF(("IDI: request all ids in use (IDI req ignored)"));
+                       UxCardUnlock(card->hw, ipl);
+                       e->Rc = OUT_OF_RESOURCES;
+                       return;
+               }
+
+               card->e_tbl[i].e = e;
+               card->e_count++;
+
+               e->No = (byte) i;
+               e->More = 0;
+               e->RCurrent = 0xff;
+       }
+       else
+       {
+               i = e->No;
+       }
+    
+    if (e->More & XBUSY)
+       {
+               DPRINTF(("IDI: request - entity is busy"));
+               UxCardUnlock(card->hw, ipl);
+               return;
+       }
+
+       e->More |= XBUSY;
+       e->More &= ~ XMOREF;
+       e->XCurrent = 0;
+       e->XOffset = 0;
+
+       card->e_tbl[i].next = 0;
+
+       if(card->e_head)
+       {
+               card->e_tbl[card->e_tail].next = i;
+               card->e_tail = i;
+       }
+       else
+       {
+               card->e_head = i;
+               card->e_tail = i;
+       }
+
+       UxCardUnlock(card->hw, ipl);
+
+       DivasScheduleRequestDpc();
+
+       return;
+}
+
+static byte pr_ready(ADAPTER * a)
+{
+  byte ReadyCount;
+
+  ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
+                      a->ram_in(a, &PR_RAM->ReqInput));
+
+  if(!ReadyCount) {
+    if(!a->ReadyInt) {
+      a->ram_inc(a, &PR_RAM->ReadyInt);
+      a->ReadyInt++;
+    }
+  }
+  return ReadyCount;
+}
+
+/*------------------------------------------------------------------*/
+/* output function                                                  */
+/*------------------------------------------------------------------*/
+
+void DivasOut(ADAPTER * a)
+{
+  byte e_no;
+  ENTITY  * this = NULL;
+  BUFFERS  *X;
+  word length;
+  word i;
+  word clength;
+  REQ * ReqOut;
+  byte more;
+  byte ReadyCount;
+  byte ReqCount;
+  byte Id;
+
+        /* while a request is pending ...                           */
+  e_no = look_req(a);
+  if(!e_no)
+  {
+    return;
+  }
+
+  ReadyCount = pr_ready(a);
+  if(!ReadyCount)
+  {
+    DPRINTF(("IDI: card not ready for next request"));
+    return;
+  }
+
+  ReqCount = 0;
+  while(e_no && ReadyCount) {
+
+    next_req(a);
+
+    this = entity_ptr(a, e_no);
+
+#ifdef USE_EXTENDED_DEBUGS
+       if ( !this )
+       {
+               ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
+               DBG_FTL(("!A%d ==> NULL entity ptr - try to ignore", (int)io->ANum))
+               e_no = look_req(a) ;
+               ReadyCount-- ;
+               continue ;
+       }
+       {
+               ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
+               DPRINTF(("IDI: >A%d Id=0x%x Req=0x%x", io->ANum, this->Id, this->Req))
+       }
+#else
+    DPRINTF(("IDI: >REQ=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
+#endif
+
+        /* get address of next available request buffer             */
+    ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
+
+        /* now copy the data from the current data buffer into the  */
+        /* adapters request buffer                                  */
+    length = 0;
+    i = this->XCurrent;
+    X = PTR_X(a,this);
+    while(i<this->XNum && length<270) {
+      clength = MIN((word)(270-length),X[i].PLength-this->XOffset);
+      a->ram_out_buffer(a,
+                        &ReqOut->XBuffer.P[length],
+                        PTR_P(a,this,&X[i].P[this->XOffset]),
+                        clength);
+
+      length +=clength;
+      this->XOffset +=clength;
+      if(this->XOffset==X[i].PLength) {
+        this->XCurrent = (byte)++i;
+        this->XOffset = 0;
+      }
+    }
+
+    a->ram_outw(a, &ReqOut->XBuffer.length, length);
+    a->ram_out(a, &ReqOut->ReqId, this->Id);
+    a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
+
+        /* if its a specific request (no ASSIGN) ...                */
+
+    if(this->Id &0x1f) {
+
+        /* if buffers are left in the list of data buffers do       */
+        /* do chaining (LL_MDATA, N_MDATA)                          */
+
+      this->More++;
+      if(i<this->XNum && this->MInd) {
+        a->ram_out(a, &ReqOut->Req, this->MInd);
+        more = TRUE;
+      }
+      else {
+        this->More |=XMOREF;
+        a->ram_out(a, &ReqOut->Req, this->Req);
+        more = FALSE;
+      }
+
+        /* if we did chaining, this entity is put back into the     */
+        /* request queue                                            */
+
+      if(more) {
+        req_queue(a,this->No);
+      }
+    }
+
+        /* else it's a ASSIGN                                       */
+
+    else {
+
+        /* save the request code used for buffer chaining           */
+
+      this->MInd = 0;
+      if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
+      if (this->Id==NL_ID   ||
+          this->Id==TASK_ID ||
+          this->Id==MAN_ID
+        ) this->MInd = N_MDATA;
+
+        /* send the ASSIGN                                          */
+
+      this->More |=XMOREF;
+      a->ram_out(a, &ReqOut->Req, this->Req);
+
+        /* save the reference of the ASSIGN                         */
+
+      assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
+    }
+    a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
+    ReadyCount--;
+    ReqCount++;
+
+    e_no = look_req(a);
+  }
+
+        /* send the filled request buffers to the ISDN adapter      */
+
+  a->ram_out(a, &PR_RAM->ReqInput,
+             (byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
+
+        /* if it is a 'unreturncoded' UREMOVE request, remove the  */
+        /* Id from our table after sending the request             */
+  if(this->Req==UREMOVE && this->Id) {
+    Id = this->Id;
+    e_no = a->IdTable[Id];
+    free_entity(a, e_no);
+    a->IdTable[Id] = 0;
+    this->Id = 0;
+  }
+
+}
+
+/*------------------------------------------------------------------*/
+/* isdn interrupt handler                                           */
+/*------------------------------------------------------------------*/
+
+byte DivasDpc(ADAPTER * a)
+{
+  byte Count;
+  RC * RcIn;
+  IND * IndIn;
+  byte c;
+  byte RNRId;
+  byte Rc;
+  byte Ind;
+
+        /* if return codes are available ...                        */
+  if((Count = a->ram_in(a, &PR_RAM->RcOutput))) {
+
+    DPRINTF(("IDI: #Rc=%x",Count));
+
+        /* get the buffer address of the first return code          */
+    RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
+
+        /* for all return codes do ...                              */
+    while(Count--) {
+
+      if((Rc=a->ram_in(a, &RcIn->Rc))) {
+
+        /* call return code handler, if it is not our return code   */
+        /* the handler returns 2                                    */
+        /* for all return codes we process, we clear the Rc field   */
+        isdn_rc(a,
+                Rc,
+                a->ram_in(a, &RcIn->RcId),
+                a->ram_in(a, &RcIn->RcCh),
+                a->ram_inw(a, &RcIn->Reference));
+
+        a->ram_out(a, &RcIn->Rc, 0);
+      }
+
+        /* get buffer address of next return code                   */
+      RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
+    }
+
+        /* clear all return codes (no chaining!)                    */
+    a->ram_out(a, &PR_RAM->RcOutput ,0);
+
+        /* call output function                                     */
+    DivasOut(a);
+  }
+
+        /* clear RNR flag                                           */
+  RNRId = 0;
+
+        /* if indications are available ...                         */
+  if((Count = a->ram_in(a, &PR_RAM->IndOutput))) {
+
+    DPRINTF(("IDI: #Ind=%x",Count));
+
+        /* get the buffer address of the first indication           */
+    IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
+
+        /* for all indications do ...                               */
+    while(Count--) {
+
+        /* if the application marks an indication as RNR, all       */
+        /* indications from the same Id delivered in this interrupt */
+        /* are marked RNR                                           */
+      if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
+        a->ram_out(a, &IndIn->Ind, 0);
+        a->ram_out(a, &IndIn->RNR, TRUE);
+      }
+      else {
+        Ind = a->ram_in(a, &IndIn->Ind);
+        if(Ind) {
+          RNRId = 0;
+
+        /* call indication handler, a return value of 2 means chain */
+        /* a return value of 1 means RNR                            */
+        /* for all indications we process, we clear the Ind field   */
+          c = isdn_ind(a,
+                       Ind,
+                       a->ram_in(a, &IndIn->IndId),
+                       a->ram_in(a, &IndIn->IndCh),
+                       &IndIn->RBuffer,
+                       a->ram_in(a, &IndIn->MInd),
+                       a->ram_inw(a, &IndIn->MLength));
+
+          if(c==1) {
+            DPRINTF(("IDI: RNR"));
+            a->ram_out(a, &IndIn->Ind, 0);
+            RNRId = a->ram_in(a, &IndIn->IndId);
+            a->ram_out(a, &IndIn->RNR, TRUE);
+          }
+        }
+      }
+
+        /* get buffer address of next indication                    */
+      IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
+    }
+
+    a->ram_out(a, &PR_RAM->IndOutput, 0);
+  }
+  return FALSE;
+}
+
+byte DivasTestInt(ADAPTER * a)
+{
+  return a->ram_in(a,(void *)0x3fe);
+}
+
+void DivasClearInt(ADAPTER * a)
+{
+  a->ram_out(a,(void *)0x3fe,0); 
+}
+
+/*------------------------------------------------------------------*/
+/* return code handler                                              */
+/*------------------------------------------------------------------*/
+
+static
+byte isdn_rc(ADAPTER * a,
+             byte Rc,
+             byte Id,
+             byte Ch,
+             word Ref)
+{
+  ENTITY  * this;
+  byte e_no;
+
+#ifdef USE_EXTENDED_DEBUGS
+       {
+               ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
+               DPRINTF(("IDI: <A%d Id=0x%x Rc=0x%x", io->ANum, Id, Rc))
+       }
+#else
+  DPRINTF(("IDI: <RC(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
+#endif
+
+        /* check for ready interrupt                                */
+  if(Rc==READY_INT) {
+    if(a->ReadyInt) {
+      a->ReadyInt--;
+      return 0;
+    }
+    return 2;
+  }
+
+        /* if we know this Id ...                                   */
+  e_no = a->IdTable[Id];
+  if(e_no) {
+
+    this = entity_ptr(a,e_no);
+
+    this->RcCh = Ch;
+
+        /* if it is a return code to a REMOVE request, remove the   */
+        /* Id from our table                                        */
+    if(this->Req==REMOVE && Rc==OK) {
+      free_entity(a, e_no);
+      a->IdTable[Id] = 0;
+      this->Id = 0;
+/**************************************************************/
+      if ((this->More & XMOREC) > 1) {
+        this->More &= ~XMOREC;
+       this->More |= 1;
+       DPRINTF(("isdn_rc, Id=%x, correct More on REMOVE", Id));
+      }
+    }
+
+    if (Rc==OK_FC) {
+      this->Rc = Rc;
+      this->More = (this->More & (~XBUSY | XMOREC)) | 1;
+      this->complete = 0xFF;
+      CALLBACK(a, this);
+      return 0;
+    }
+    if(this->More &XMOREC)
+      this->More--;
+
+        /* call the application callback function                   */
+    if(this->More &XMOREF && !(this->More &XMOREC)) {
+      this->Rc = Rc;
+      this->More &=~XBUSY;
+      this->complete=0xff;
+      CALLBACK(a, this);
+    }
+    return 0;
+  }
+
+        /* if it's an ASSIGN return code check if it's a return     */
+        /* code to an ASSIGN request from us                        */
+  if((Rc &0xf0)==ASSIGN_RC) {
+
+    e_no = get_assign(a, Ref);
+
+    if(e_no) {
+
+      this = entity_ptr(a,e_no);
+
+      this->Id = Id;
+
+        /* call the application callback function                   */
+      this->Rc = Rc;
+      this->More &=~XBUSY;
+      this->complete=0xff;
+      CALLBACK(a, this);
+
+      if(Rc==ASSIGN_OK) {
+        a->IdTable[Id] = e_no;
+      }
+      else
+      {
+        free_entity(a, e_no);
+        a->IdTable[Id] = 0;
+        this->Id = 0;
+      }
+      return 1;
+    }
+  }
+  return 2;
+}
+
+/*------------------------------------------------------------------*/
+/* indication handler                                               */
+/*------------------------------------------------------------------*/
+
+static
+byte isdn_ind(ADAPTER * a,
+              byte Ind,
+              byte Id,
+              byte Ch,
+              PBUFFER * RBuffer,
+              byte MInd,
+              word MLength)
+{
+  ENTITY  * this;
+  word clength;
+  word offset;
+  BUFFERS  *R;
+
+#ifdef USE_EXTENDED_DEBUGS
+       {
+               ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
+               DPRINTF(("IDI: <A%d Id=0x%x Ind=0x%x", io->ANum, Id, Ind))
+       }
+#else
+  DPRINTF(("IDI: <IND(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
+#endif
+
+  if(a->IdTable[Id]) {
+
+    this = entity_ptr(a,a->IdTable[Id]);
+
+    this->IndCh = Ch;
+
+        /* if the Receive More flag is not yet set, this is the     */
+        /* first buffer of the packet                               */
+    if(this->RCurrent==0xff) {
+
+        /* check for receive buffer chaining                        */
+      if(Ind==this->MInd) {
+        this->complete = 0;
+        this->Ind = MInd;
+      }
+      else {
+        this->complete = 1;
+        this->Ind = Ind;
+      }
+
+        /* call the application callback function for the receive   */
+        /* look ahead                                               */
+      this->RLength = MLength;
+
+      a->ram_look_ahead(a, RBuffer, this);
+
+      this->RNum = 0;
+      CALLBACK(a, this);
+
+        /* map entity ptr, selector could be re-mapped by call to   */
+        /* IDI from within callback                                 */
+      this = entity_ptr(a,a->IdTable[Id]);
+
+        /* check for RNR                                            */
+      if(this->RNR==1) {
+        this->RNR = 0;
+        return 1;
+      }
+
+        /* if no buffers are provided by the application, the       */
+        /* application want to copy the data itself including       */
+        /* N_MDATA/LL_MDATA chaining                                */
+      if(!this->RNR && !this->RNum) {
+        return 0;
+      }
+
+        /* if there is no RNR, set the More flag                    */
+      this->RCurrent = 0;
+      this->ROffset = 0;
+    }
+
+    if(this->RNR==2) {
+      if(Ind!=this->MInd) {
+        this->RCurrent = 0xff;
+        this->RNR = 0;
+      }
+      return 0;
+    }
+        /* if we have received buffers from the application, copy   */
+        /* the data into these buffers                              */
+    offset = 0;
+    R = PTR_R(a,this);
+    do {
+      if(this->ROffset==R[this->RCurrent].PLength) {
+        this->ROffset = 0;
+        this->RCurrent++;
+      }
+      clength = MIN(a->ram_inw(a, &RBuffer->length)-offset,
+                    R[this->RCurrent].PLength-this->ROffset);
+      if(R[this->RCurrent].P) {
+        a->ram_in_buffer(a,
+                         &RBuffer->P[offset],
+                         PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
+                         clength);
+      }
+      offset +=clength;
+      this->ROffset +=clength;
+    } while(offset<(a->ram_inw(a, &RBuffer->length)));
+
+        /* if it's the last buffer of the packet, call the          */
+        /* application callback function for the receive complete   */
+        /* call                                                     */
+    if(Ind!=this->MInd) {
+      R[this->RCurrent].PLength = this->ROffset;
+      if(this->ROffset) this->RCurrent++;
+      this->RNum = this->RCurrent;
+      this->RCurrent = 0xff;
+      this->Ind = Ind;
+      this->complete = 2;
+      CALLBACK(a, this);
+    }
+    return 0;
+  }
+  return 2;
+}
diff --git a/drivers/isdn/eicon/idi.h b/drivers/isdn/eicon/idi.h
new file mode 100644 (file)
index 0000000..0819665
--- /dev/null
@@ -0,0 +1,146 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* External IDI interface */
+
+#if !defined(IDI_H)
+#define IDI_H
+
+#include "sys.h"
+
+/* typedefs for our data structures */
+
+typedef struct get_name_s GET_NAME;
+typedef struct entity_s ENTITY;
+typedef struct buffers_s BUFFERS;
+
+/* IDI request/callback function pointer */
+
+typedef void (* IDI_CALL)(ENTITY *);
+
+typedef struct {
+  word length;          /* length of data/parameter field           */
+  byte P[270];          /* data/parameter field                     */
+} DBUFFER;
+
+#define REQ_NAME       0x0100
+#define BOARD_NAME_LENGTH 9
+struct get_name_s {
+  word command;         /* command = 0x0100 */
+  byte name[BOARD_NAME_LENGTH];
+};
+
+#define REQ_REMOVE    0x0000    /* pointer to word which is 0 */
+#define REQ_SERIAL    0x0200  
+struct get_serial_s {
+  word      command;            /* command = 0x0200 */
+  dword     serial;             /* serial number */
+};
+
+#define REQ_POSTCALL  0x0300  
+struct postcall_s {
+  word        command;         /* command = 0x0300 */
+  word        dummy;           /* not used */
+  IDI_CALL    callback;        /* routine adress to call back */
+  ENTITY      *contxt;         /* ptr to entity to use */
+};
+
+#define REQ_XLOG      0x0400   /* structure is card dependent/defined locally */
+
+struct buffers_s {
+  word PLength;
+  byte *P;
+};
+
+struct entity_s {
+  byte                  Req;            /* pending request          */
+  byte                  Rc;             /* return code received     */
+  byte                  Ind;            /* indication received      */
+  byte                  ReqCh;          /* channel of current Req   */
+  byte                  RcCh;           /* channel of current Rc    */
+  byte                  IndCh;          /* channel of current Ind   */
+  byte                  Id;             /* ID used by this entity   */
+  byte                  GlobalId;       /* reserved field           */
+  byte                  XNum;           /* number of X-buffers      */
+  byte                  RNum;           /* number of R-buffers      */
+  BUFFERS               *X;                    /* pointer to X-buffer list */
+  BUFFERS               *R;                    /* pointer to R-buffer list */
+  word                  RLength;        /* length of current R-data */
+  DBUFFER               *RBuffer;       /* buffer of current R-data */
+  byte                  RNR;            /* receive not ready flag   */
+  byte                  complete;       /* receive complete status  */
+  IDI_CALL              callback;
+
+  word                  user[2];
+
+        /* fields used by the driver internally                     */
+  byte                  No;             /* entity number            */
+  byte                  reserved2;      /* reserved field           */
+  byte                  More;           /* R/X More flags           */
+  byte                  MInd;           /* MDATA coding for this ID */
+  byte                  XCurrent;       /* current transmit buffer  */
+  byte                  RCurrent;       /* current receive buffer   */
+  word                  XOffset;        /* offset in x-buffer       */
+  word                  ROffset;        /* offset in r-buffer       */
+};
+
+typedef struct {
+  byte                  type;
+  byte                  channels;
+  word                  features;
+  dword                        serial;
+  IDI_CALL              request;
+} DESCRIPTOR;
+
+extern void    EtdM_DIDD_Read(DESCRIPTOR *, int *);
+
+        /* descriptor type field coding */
+#define IDI_ADAPTER_S           1
+#define IDI_ADAPTER_PR          2
+#define IDI_ADAPTER_DIVA        3
+#define IDI_ADAPTER_MAESTRA     4
+#define IDI_ADAPTER_MAESTRAQ    5
+#define IDI_ADAPTER_MAESTRAP    6
+#define IDI_VADAPTER            0x40
+#define IDI_DRIVER              0x80
+#define IDI_DIMAINT             0xff
+
+/* feature bit mask values */
+
+#define DI_VOICE        0x0 /* obsolete define */
+#define DI_FAX3         0x1
+#define DI_MODEM        0x2
+#define DI_POST         0x4
+#define DI_V110         0x8
+#define DI_V120         0x10
+#define DI_POTS         0x20
+#define DI_CODEC        0x40
+#define DI_MANAGE       0x80
+#define DI_V_42         0x0100
+#define DI_EXTD_FAX     0x0200 /* Extended FAX (ECM, 2D, T.6, Polling) */
+
+#endif /* IDI_H */
diff --git a/drivers/isdn/eicon/kprintf.c b/drivers/isdn/eicon/kprintf.c
new file mode 100644 (file)
index 0000000..3282b7f
--- /dev/null
@@ -0,0 +1,538 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.3  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/*
+ * Source file for kernel interface to kernel log facility
+ */
+
+
+#include "sys.h"
+#include <stdarg.h>
+#undef MAX
+#undef MIN
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include "divas.h"
+#include "divalog.h"
+#include "uxio.h"
+
+/*
+ * Implementation of printf and sprintf for kernel
+ */
+
+#define MAX_BUFF    (80)        /* limit size of temporary buffers */
+
+#define WRITE_CHAR(BUFFER, SIZE, C) \
+  if (--(SIZE) < 0) { (BUFFER)--; *(BUFFER) = '\0'; return; } *(BUFFER)++ = (C)
+
+
+/*
+ * convert a number to decimal ASCII
+ */
+
+static
+void    do_decimal( char            *temp,
+                    int             temp_len,
+                    unsigned int    value,
+                    char            *s)
+
+{
+    int     i;
+
+    temp[0] = '\0';
+
+    for (i = 1; i < temp_len; i++)
+    {
+        temp[i] = (char) ((value % 10) + (int) '0');
+        value /= 10;
+    }
+
+    for (i = (temp_len - 1); temp[i] == '0'; i--)
+    {
+        ;
+    }
+
+    if (i == 0)
+    {
+        i++;
+    }
+
+    while (i >= 0)
+    {
+        *s++ = temp[i--];
+    }
+
+    return;
+}
+
+/*
+ * convert a number to octal ASCII
+ */
+
+static
+void    do_octal(   char            *temp,
+                    unsigned int    value,
+                    char            *s)
+
+{
+    int     i;
+
+    temp[0] = '\0';
+
+    for (i = 1; i <= 11; i++)
+    {
+        temp[i] = (char) ((value & 07) + (int) '0');
+        value >>= 3;
+    }
+    temp[11] &= '3';
+
+    for (i = 11; temp[i] == '0'; i--)
+    {
+        ;
+    }
+
+    if (i == 0)
+    {
+        i++;
+    }
+
+    while (i >= 0)
+    {
+        *s++ = temp[i--];
+    }
+
+    return;
+}
+
+/*
+ * convert a number to hex ASCII
+ */
+
+static
+void    do_hex( char            *temp,
+                unsigned int    value,
+                char            *s)
+
+{
+    int     i;
+    static
+    char    *dec_to_hex = "0123456789abcdef";
+
+    temp[0] = '\0';
+
+    for (i = 1; i <= 8; i++)
+    {
+        temp[i] = dec_to_hex[value & 0x0f];
+        value >>= 4;
+    }
+
+    for (i = 8; temp[i] == '0'; i--)
+    {
+        ;
+    }
+
+    if (i == 0)
+    {
+        i++;
+    }
+
+    while (i >= 0)
+    {
+        *s++ = temp[i--];
+    }
+
+    return;
+}
+
+/*
+ * convert a buffer to ASCII HEX
+ */
+
+static
+void    do_buffer(  char    *buffer,
+                    int     length,
+                    char    *s)
+
+{
+    static
+    char    hex_char [] = "0123456789abcdef";
+    char    *b = buffer;
+    int     hex_byte;
+    int     nybble;
+
+    length = (length >= ((MAX_BUFF / 3) + 1)) ? (MAX_BUFF / 3) : length;
+
+    while (length)
+    {
+        hex_byte = (int) *b++;
+        nybble = (hex_byte >> 4) & 0xf;
+        *s++ = hex_char[nybble];
+        nybble = hex_byte & 0xf;
+        *s++ = hex_char[nybble];
+        *s++ = ' ';
+        length--;
+    }
+    *s = '\0';
+
+    return;
+}
+
+/*
+ * Body of sprintf function: behaves just like standard sprintf, except we
+ * have an extra argument (buffer size) which we use to ensure we don't
+ * overflow
+ */
+
+void    Divas_vsprintf(   char    *buffer,
+                    int     size,
+                    char    *fmt,
+                    va_list argptr)
+
+{
+    char        c;          /* single character buffer */
+    int         i;          /* handy scratch counter */
+    int         f;          /* format character (after %) */
+    char        *str;       /* pointer into string */
+    char        temp[20];   /* temp buffer used in printing numbers */
+    char        string[MAX_BUFF]; /* output from number conversion */
+    int         length;     /* length of string "str" */
+    char        fill;       /* fill character ' ' or '0' */
+    boolean_t   leftjust;   /* TRUE if left justified, else right justified */
+    int         fmax, fmin; /* field specifiers % MIN . MAX s */
+    int         leading;    /* number of leading/trailing fill characters */
+    char        sign;       /* set to '-' for negative decimals */
+    int         number;     /* numeric argument */
+
+    char        *buff_ptr;  /* pointer to user's buffer of hex data */
+    int         buff_len;   /* length of hex data */
+
+    /* make sure we have somthing to write into */
+
+    if ((!buffer) || (size <= 0))
+    {
+        return;
+    }
+
+    while (TRUE)
+    {
+        /* echo characters until end or '%' encountered */
+
+        while ((c = *fmt++) != '%')
+        {
+            if (!c)
+            {
+                *buffer = '\0';
+                return;
+            }
+            WRITE_CHAR(buffer, size, c);
+        }
+
+        /* echo %% as % */
+
+        if (*fmt == '%')
+        {
+            WRITE_CHAR(buffer, size, *fmt);
+            continue;
+        }
+
+        /* %- turns on left-justify */
+
+        if ((leftjust = (boolean_t) ((*fmt == '-') ? TRUE : FALSE)))
+        {
+            fmt++;
+        }
+
+        /* %0 turns on zero filling */
+
+        if (*fmt == '0')
+        {
+            fill = '0';
+        }
+        else
+        {
+            fill = ' ';
+        }
+
+        /* minium field width specifier for %d, u, x, c, s */
+
+        fmin = 0;
+
+        if (*fmt == '*')
+        {
+            fmin = va_arg(argptr, int);
+            fmt++;
+        }
+        else
+        {
+            while ('0' <= *fmt && *fmt <= '9')
+            {
+                fmin = (fmin * 10) + (*fmt++ - '0');
+            }
+        }
+
+        /* maximum string width specifier for %s */
+
+        fmax = 0;
+
+        if (*fmt == '.')
+        {
+            if (*(++fmt) == '*')
+            {
+                fmax = va_arg(argptr, int);
+                fmt++;
+            }
+            else
+            {
+                while ('0' <= *fmt && *fmt <= '9')
+                {
+                    fmax = (fmax * 10) + (*fmt++ - '0');
+                }
+            }
+        }
+
+        /* skip over 'l' option (ints are assumed same size as longs) */
+
+        if (*fmt == 'l')
+        {
+            fmt++;
+        }
+
+        /* get the format chacater */
+
+        if (!(f = *fmt++))
+        {
+            WRITE_CHAR(buffer, size, '%');
+            *buffer = '\0';
+            return;
+        }
+
+        sign = '\0';        /* sign == '-' for negative decimal */
+
+        str = string;
+
+        switch (f)
+        {
+        case 'c' :
+            string[0] = (char) va_arg(argptr, int);
+            string[1] = '\0';
+            fmax = 0;
+            fill = ' ';
+            break;
+
+        case 's' :
+            str = va_arg(argptr, char *);
+            fill = ' ';
+            break;
+
+        case 'D' :
+        case 'd' :
+            number = va_arg(argptr, int);
+            if (number < 0)
+            {
+                sign = '-';
+                number = -number;
+            }
+            do_decimal(temp, DIM(temp), (unsigned int) number, str);
+            fmax = 0;
+            break;
+
+        case 'U' :
+        case 'u' :
+            number = va_arg(argptr, int);
+            do_decimal(temp, DIM(temp), (unsigned int) number, str);
+            fmax = 0;
+            break;
+
+        case 'O' :
+        case 'o' :
+            number = va_arg(argptr, int);
+            do_octal(temp, (unsigned int) number, str);
+            fmax = 0;
+            break;
+
+        case 'X' :
+        case 'x' :
+            number = va_arg(argptr, int);
+            do_hex(temp, (unsigned int) number, str);
+            fmax = 0;
+            break;
+
+        case 'H' :
+        case 'h' :
+            buff_ptr = va_arg(argptr, char *);
+            buff_len = va_arg(argptr, int);
+            do_buffer(buff_ptr, buff_len, str);
+            fmax = 0;
+            break;
+
+        default :
+            WRITE_CHAR(buffer, size, ((char) f));
+            break;
+        }
+
+        /* get the length of the string */
+
+        length = 0;
+        while (str[length])
+        {
+            length++;
+        }
+
+        /* make sure we have fmax and fmin values that are O.K. */
+
+        if (fmin > DIM(string) || fmin < 0)
+        {
+            fmin = 0;
+        }
+
+        if (fmax > DIM(string) || fmax < 0)
+        {
+            fmax = 0;
+        }
+
+        /* figure out how many leading characters thare are */
+
+        leading = 0;
+
+        if (fmax || fmin)
+        {
+            if (fmax)
+            {
+                if (length > fmax)
+                {
+                    length = fmax;
+                }
+            }
+
+            if (fmin)
+            {
+                leading = fmin - length;
+            }
+
+            if (sign == '-')
+            {
+                leading--;
+            }
+        }
+
+        /* output sign now, if fill is numeric */
+
+        if (sign == '-' && fill == '0')
+        {
+            WRITE_CHAR(buffer, size, '-');
+        }
+
+        /* if right justified, output fill characters */
+
+        if (!leftjust)
+        {
+            for (i = 0; i < leading; i++)
+            {
+                WRITE_CHAR(buffer, size, fill);
+            }
+        }
+
+        /* output sign now, if fill is spaces */
+
+        if (sign == '-' && fill == ' ')
+        {
+            WRITE_CHAR(buffer, size, '-');
+        }
+
+        /* now the actual value */
+
+        for (i = 0; i < length; i++)
+        {
+            WRITE_CHAR(buffer, size, str[i]);
+        }
+
+        /* if left justified, fill out with the fill character */
+
+        if (leftjust)
+        {
+            for (i = 0; i < leading; i++)
+            {
+                WRITE_CHAR(buffer, size, fill);
+            }
+        }
+    }
+}
+
+/*
+ * sprintf for kernel
+ *
+ * call our vsprintf assuming user has a big buffer....
+ */
+
+void    DivasSprintf(char *buffer, char *fmt, ...)
+
+{
+    va_list     argptr;         /* pointer to additional args */
+
+    va_start(argptr, fmt);
+
+    Divas_vsprintf(buffer, 1024, fmt, argptr);
+
+    va_end(argptr);
+
+    return;
+}
+
+void    DivasPrintf(char  *fmt, ...)
+
+{
+    klog_t      log;            /* log entry buffer */
+
+    va_list     argptr;         /* pointer to additional args */
+
+    va_start(argptr, fmt);
+
+    /* clear log entry */
+
+    bzero((caddr_t) &log, sizeof(klog_t));
+
+    log.card = -1;
+    log.type = KLOG_TEXT_MSG;
+
+    /* time stamp the entry */
+
+    log.time_stamp = UxTimeGet();
+
+    /* call vsprintf to format the user's information */
+
+    Divas_vsprintf(log.buffer, DIM(log.buffer), fmt, argptr);
+
+    va_end(argptr);
+
+    /* send to the log streams driver and return */
+
+    DivasLogAdd(&log, sizeof(klog_t));
+
+    return;
+}
diff --git a/drivers/isdn/eicon/lincfg.c b/drivers/isdn/eicon/lincfg.c
new file mode 100644 (file)
index 0000000..3d2a8bf
--- /dev/null
@@ -0,0 +1,410 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.9  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/fs.h>
+#undef N_DATA   /* Because we have our own definition */
+
+#include <asm/segment.h>
+#include <asm/io.h>
+
+#include "sys.h"
+#include "idi.h"
+#include "constant.h"
+#include "divas.h"
+#undef ID_MASK
+#include "pc.h"
+#include "pr_pc.h"
+
+#include "adapter.h"
+#include "uxio.h"
+
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+
+#define HW_ID_EICON_PCI                        0x1133
+#define HW_ID_DIVA_SERVER_P            0xE014
+#define HW_ID_DIVA_SERVER_B_ST 0xE010
+#define HW_ID_DIVA_SERVER_B_U  0xE013
+#define HW_ID_DIVA_SERVER_Q    0xE012
+
+struct file_operations Divas_fops;
+int Divas_major;
+
+extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile, 
+                        unsigned int command, unsigned long arg);
+extern unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable);
+extern ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset);
+extern int do_open(struct inode *, struct file *);
+extern int do_release(struct inode *, struct file *);
+
+int FPGA_Done=0;
+
+int DivasCardsDiscover(void)
+{
+       word wNumCards = 0, wDeviceIndex = 0;
+       byte byBus, byFunc;
+       word wPCIConsultation, PCItmp;
+       dword j, i;
+       unsigned int PCIserial;
+       dia_card_t Card;
+       byte *b;
+       
+       while (wDeviceIndex < 10)
+       {
+               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
+                               HW_ID_DIVA_SERVER_Q, 
+                               wDeviceIndex, 
+                               &byBus, &byFunc);
+
+               if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
+               {
+
+                       dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;                       
+                       byte byIRQ;
+                       
+                       printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
+                       dwRAM &= 0xFFC00000;
+                       
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
+                       dwDivasIOBase &= 0xFFFFFF00;
+                       
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
+                       dwCFG &= 0xFFFFFF00;
+                       
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
+                       dwCTL &= 0xFFFFE000;
+                       
+
+                       pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+                       /* Retrieve the serial number */
+
+                       pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
+
+                       for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
+                       {
+                               pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
+                               PCItmp &= 0x8000;  // extract done flag
+                       }
+
+                       pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
+
+               
+                       Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
+                       Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
+                       Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
+                       Card.io_base=dwDivasIOBase;
+
+                       Card.irq = byIRQ;
+                       
+                       Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
+                       Card.bus_type = DIA_BUS_TYPE_PCI;
+       
+                       FPGA_Done = 0;
+
+                       /* Create four virtual card structures as we want to treat 
+                          the 4Bri card as 4 Bri cards*/
+                       for(i=0;i<4;i++)
+                       {
+
+                               b=Card.memory[DIVAS_RAM_MEMORY];
+                               b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1); 
+                               DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
+                               Card.memory[DIVAS_RAM_MEMORY]=b;
+                               b = Card.memory[DIVAS_RAM_MEMORY];
+                               b += MQ_SM_OFFSET;
+                               Card.memory[DIVAS_SHARED_MEMORY] = b;
+
+                               Card.bus_num = byBus;
+                               Card.func_num = byFunc;
+                               Card.slot = -1;
+
+                       
+                               /* Fill in Name */
+                               Card.name[0] = 'D';
+                               Card.name[1] = 'I';
+                               Card.name[2] = 'V';
+                               Card.name[3] = 'A';
+                               Card.name[4] = 'S';
+                               Card.name[5] = 'Q';
+                               Card.name[6] = '0' + i;
+                               Card.name[7] = '\0';
+
+                               Card.serial = PCIserial;
+
+                               Card.card_id = wNumCards;
+
+                               if (DivasCardNew(&Card) != 0)
+                               {
+                                       // Force for loop to terminate
+                                       i = 4;
+                                       continue;
+                               }
+                               wNumCards++;
+
+                       }//for
+               }
+               wDeviceIndex++;
+       }
+
+       wDeviceIndex = 0;
+
+       while (wDeviceIndex < 10)
+       {
+               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
+                               HW_ID_DIVA_SERVER_B_ST, 
+                               wDeviceIndex, 
+                               &byBus, &byFunc);
+
+               if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
+               {
+                       dword dwPLXIOBase, dwDivasIOBase;
+                       byte byIRQ;
+
+                       printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
+                       dwPLXIOBase &= 0xFFFFFF80;
+
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
+                       dwDivasIOBase &= 0xFFFFFFFC;
+
+                       pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+
+                       Card.card_id = wNumCards;
+                       Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
+                       Card.bus_type = DIA_BUS_TYPE_PCI;
+                       Card.irq = byIRQ;
+                       Card.reset_base = dwPLXIOBase;
+                       Card.io_base = dwDivasIOBase;
+                       Card.bus_num = byBus;
+                       Card.func_num = byFunc;
+                       Card.slot = -1;
+                       Card.name[0] = 'D';
+                       Card.name[1] = 'I';
+                       Card.name[2] = 'V';
+                       Card.name[3] = 'A';
+                       Card.name[4] = 'S';
+                       Card.name[5] = 'B';
+                       Card.name[6] = '\0';
+
+                       if (check_region(Card.io_base, 0x20))
+                       {
+                               printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
+                               wDeviceIndex++;
+                               continue;
+                       }
+
+                       if (check_region(Card.reset_base, 0x80))
+                       {
+                               printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
+                               wDeviceIndex++;
+                               continue;
+                       }
+
+                       if (DivasCardNew(&Card) != 0)
+                       {
+                               wDeviceIndex++;
+                               continue;
+                       }
+                       wNumCards++;
+               }
+
+               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
+                               HW_ID_DIVA_SERVER_B_U, 
+                               wDeviceIndex, 
+                               &byBus, &byFunc);
+
+               if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
+               {
+                       dword dwPLXIOBase, dwDivasIOBase;
+                       byte byIRQ;
+
+                       printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
+
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
+                       dwPLXIOBase &= 0xFFFFFF80;
+
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
+                       dwDivasIOBase &= 0xFFFFFFFC;
+
+                       pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+
+                       Card.card_id = wNumCards;
+                       Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
+                       Card.bus_type = DIA_BUS_TYPE_PCI;
+                       Card.irq = byIRQ;
+                       Card.reset_base = dwPLXIOBase;
+                       Card.io_base = dwDivasIOBase;
+                       Card.bus_num = byBus;
+                       Card.func_num = byFunc;
+                       Card.slot = -1;
+                       Card.name[0] = 'D';
+                       Card.name[1] = 'I';
+                       Card.name[2] = 'V';
+                       Card.name[3] = 'A';
+                       Card.name[4] = 'S';
+                       Card.name[5] = 'B';
+                       Card.name[6] = '\0';
+
+                       if (check_region(Card.io_base, 0x20))
+                       {
+                               printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);      
+                               wDeviceIndex++;
+                               continue;
+                       }
+
+                       if (check_region(Card.reset_base, 0x80))
+                       {
+                               printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
+                               wDeviceIndex++;
+                               continue;
+                       }
+
+                       if (DivasCardNew(&Card) != 0)
+                       {
+                               wDeviceIndex++;
+                               continue;
+                       }
+                       wNumCards++;
+               }
+
+               wDeviceIndex++;
+       }
+
+       wDeviceIndex = 0;
+
+       while (wDeviceIndex < 10)
+       {
+               wPCIConsultation = pcibios_find_device(HW_ID_EICON_PCI, 
+                               HW_ID_DIVA_SERVER_P, 
+                               wDeviceIndex, 
+                               &byBus, &byFunc);
+
+               if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
+               {
+                       dword dwRAM, dwREG, dwCFG;
+                       byte byIRQ;
+
+                       printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
+
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
+                       dwRAM &= 0xFFFFF000;
+
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
+                       dwREG &= 0xFFFFF000;
+                       
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
+                       dwCFG &= 0xFFFFF000;
+
+                       pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+
+                       Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
+                       Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
+                       Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
+                       Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
+
+/*                     pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
+                       dwPLXIOBase &= 0xFFFFFFFc;
+
+                       pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
+                       dwDivasIOBase &= 0xFFFFFF80;
+
+                       pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
+*/
+                       Card.card_id = wNumCards;
+                       Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
+                       Card.bus_type = DIA_BUS_TYPE_PCI;
+                       Card.irq = byIRQ;
+/*                     Card.reset_base = dwPLXIOBase;
+                       Card.io_base = dwDivasIOBase;*/
+                       Card.bus_num = byBus;
+                       Card.func_num = byFunc;
+                       Card.slot = -1;
+                       Card.name[0] = 'D';
+                       Card.name[1] = 'I';
+                       Card.name[2] = 'V';
+                       Card.name[3] = 'A';
+                       Card.name[4] = 'S';
+                       Card.name[5] = 'P';
+                       Card.name[6] = '\0';
+
+                       if (DivasCardNew(&Card) != 0)
+                       {
+                               wDeviceIndex++;
+                               continue;
+                       }
+                       wNumCards++;
+               }
+
+               wDeviceIndex++;
+       }
+
+
+       printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
+
+       if(wNumCards == 0)
+       {
+               return -1;
+       }
+
+       Divas_fops.ioctl = do_ioctl;
+       Divas_fops.poll = do_poll;
+       Divas_fops.read = do_read;
+       Divas_fops.open = do_open;
+       Divas_fops.release = do_release;
+
+       Divas_major = register_chrdev(0, "Divas", &Divas_fops);
+
+       if (Divas_major < 0)
+       {
+               printk(KERN_WARNING "Divas: Unable to register character driver\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Error return -1 */
+int DivasConfigGet(dia_card_t *card)
+{
+       /* Retrieve Config from O/S? Not in Linux */
+       return 0;
+}
+
+dia_config_t *DivasConfig(card_t *card, dia_config_t *config)
+{
+       /*      If config retrieved from OS then copy the data into a dia_config_t structure here
+               and return the pointer here. If the config 'came from above' then just 
+
+                       return config;
+       */
+
+       return config;
+}
+
diff --git a/drivers/isdn/eicon/linchr.c b/drivers/isdn/eicon/linchr.c
new file mode 100644 (file)
index 0000000..7824295
--- /dev/null
@@ -0,0 +1,274 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.12  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/malloc.h>
+
+#undef N_DATA
+
+#include "adapter.h"
+#include "divas.h"
+#include "divalog.h"
+
+extern int DivasCardNext;
+void UxPause(long ms);
+void bcopy(void *pSource, void *pDest, dword dwLength);
+int DivasGetMem(mem_block_t *);
+
+#define DIA_IOCTL_UNLOCK 12
+void UnlockDivas(void);
+
+int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile, 
+                        unsigned int command, unsigned long arg)
+{
+       dia_load_t *pDivaLoad;
+       dia_start_t *pDivaStart;
+       dia_config_t *pDivaConfig;
+       dia_log_t *pDivaLog;
+       byte *pUserCards, card_i;
+       word wCardNum;
+       mem_block_t *mem_block;
+
+       switch (command)
+       {
+               case DIA_IOCTL_CONFIG:
+                       pDivaConfig = (dia_config_t *) arg;
+                       
+                       if (!verify_area(VERIFY_READ, pDivaConfig, sizeof(dia_config_t)))
+                       {
+                               DivasCardConfig(pDivaConfig);
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete CONFIG ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                               return 0;
+
+               case DIA_IOCTL_DETECT:
+                       pUserCards = (byte *) arg;
+
+                       if (!verify_area(VERIFY_WRITE, pUserCards, 20))
+                       {
+                               put_user(DivasCardNext, pUserCards++);
+
+                               for (card_i=1; card_i < 20; card_i++)
+                               {
+                                       put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++);
+                               }
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete DETECT ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_START:
+                       pDivaStart = (dia_start_t *) arg;
+                       
+                       if (!verify_area(VERIFY_READ, pDivaStart, sizeof(dia_start_t)))
+                       {
+                               return DivasCardStart(pDivaStart->card_id);
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete START ioctl (verify area failed)\n");
+                               return -1;
+                       }
+
+
+               case DIA_IOCTL_FLAVOUR:
+                       return 0;
+
+               case DIA_IOCTL_LOAD:
+                       pDivaLoad = (dia_load_t *) arg;
+                       if (!verify_area(VERIFY_READ, pDivaLoad->code,pDivaLoad->length))
+                       {
+                               if (DivasCardLoad(pDivaLoad))
+                               {
+                                       printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n");
+                                       return -EINVAL;
+                               }
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Error in LOAD parameters (verify failed)\n");
+                               return -EINVAL;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_LOG:
+                       pDivaLog = (dia_log_t *) arg;
+                       
+                       if (!verify_area(VERIFY_READ, pDivaLog, sizeof(dia_log_t)))
+                       {
+                               DivasLog(pDivaLog);
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete LOG ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_XLOG_REQ:
+                       
+                       if (!verify_area(VERIFY_READ, (void *)arg, sizeof(word)))
+                       {
+                               wCardNum = * (word *) arg;
+                               DivasXlogReq(wCardNum);
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete XLOG_REQ ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_GET_NUM:
+                       
+                       if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(int)))
+                       {
+                               * (int *) arg = DivasCardNext;
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete GET_NUM ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_GET_LIST:
+                       DPRINTF(("divas: DIA_IOCTL_GET_LIST"));
+                       
+                       if (!verify_area(VERIFY_WRITE, (void *)arg, sizeof(dia_card_list_t)))
+                       {
+                               DivasGetList((dia_card_list_t *)arg);
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete GET_LIST ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_GET_MEM:
+                       mem_block = (mem_block_t *) arg;
+                       
+                       if (!verify_area(VERIFY_WRITE, mem_block, sizeof(mem_block_t)))
+                       {
+                               DivasGetMem(mem_block);
+                       }
+                       else
+                       {
+                               printk(KERN_WARNING "Divas: Unable to complete GET_MEM ioctl (verify area failed)\n");
+                               return -1;
+                       }
+                       return 0;
+
+               case DIA_IOCTL_UNLOCK:
+                       UnlockDivas();
+                       return 0;
+
+               default:
+                       printk(KERN_WARNING "Divas: Unknown IOCTL Received by DIVA Server Driver(%d)\n", command);
+                       return -EINVAL;
+       }
+       
+       return -EINVAL;
+}
+
+unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
+{
+       word wMask = 0;
+
+    if (!DivasLogFifoEmpty())
+    {
+               wMask |= POLLIN | POLLRDNORM;
+       }
+
+       return wMask;
+}
+
+ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset)
+{
+       klog_t *pClientLogBuffer = (klog_t *) pUserBuffer;
+       klog_t *pHeadItem;
+
+       if (BufferSize < sizeof(klog_t))
+       {
+               printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
+                       BufferSize, sizeof(klog_t));
+               return 0;
+       }
+
+       pHeadItem = (klog_t *) DivasLogFifoRead();
+
+       if (pHeadItem)
+       {
+               bcopy(pHeadItem, pClientLogBuffer, sizeof(klog_t));
+               kfree(pHeadItem);
+               return sizeof(klog_t);
+       }
+
+       return 0;
+}
+int private_usage_count;
+extern void mod_inc_use_count(void);
+extern void mod_dec_use_count(void);
+
+int do_open(struct inode *pInode, struct file *pFile)
+{
+#if defined(MODULE)
+       mod_inc_use_count();
+       private_usage_count++;
+#endif
+       return 0;
+}
+
+int do_release(struct inode *pInode, struct file *pFile)
+{
+#if defined(MODULE)
+       mod_dec_use_count();
+       private_usage_count--;
+#endif
+       return 0;
+}
+
+void UnlockDivas(void)
+{
+       while (private_usage_count > 0)
+       {
+               private_usage_count--;
+#if defined(MODULE)
+               mod_dec_use_count();
+#endif
+       }
+}
diff --git a/drivers/isdn/eicon/linio.c b/drivers/isdn/eicon/linio.c
new file mode 100644 (file)
index 0000000..74c5990
--- /dev/null
@@ -0,0 +1,750 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.16  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#define N_DATA
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#undef N_DATA
+
+#include "uxio.h"
+
+static
+int log_on=0;
+
+int            Divasdevflag = 0;
+
+//spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
+
+static
+ux_diva_card_t card_pool[MAX_CARDS];
+
+void UxPause(long int ms)
+{
+       int timeout = jiffies + ((ms * HZ) / 1000);
+
+       while (time_before(jiffies, timeout));
+}
+
+int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
+{
+       int             i;
+       ux_diva_card_t  *c;
+
+       if (cfg->bus_type != DIA_BUS_TYPE_PCI)
+       {
+               DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
+               return -1;
+       }
+
+       for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
+       {
+               ;
+       }
+
+       if (i == DIM(card_pool))
+       {
+               DPRINTF(("divas hw: card_pool exhausted"));
+               return -1;
+       }
+
+       c = *card = &card_pool[i];
+
+       switch (cfg->bus_type)
+       {
+       case DIA_BUS_TYPE_PCI:
+               c->bus_num = cfg->bus_num;
+               c->func_num = cfg->func_num;
+               c->io_base = cfg->io_base;
+               c->reset_base = cfg->reset_base;
+               c->card_type    = cfg->card_type;
+               c->mapped = NULL;
+               c->slot         = cfg->slot;
+               c->irq          = (int) cfg->irq;
+               c->pDRAM        = cfg->memory[DIVAS_RAM_MEMORY];
+               c->pDEVICES     = cfg->memory[DIVAS_REG_MEMORY];
+               c->pCONFIG      = cfg->memory[DIVAS_CFG_MEMORY];
+               c->pSHARED      = cfg->memory[DIVAS_SHARED_MEMORY];
+               c->pCONTROL     = cfg->memory[DIVAS_CTL_MEMORY];
+
+       /*              c->bus_type     = DIA_BUS_TYPE_PCI;
+               c->bus_num      = cfg->bus_num & 0x3f;
+               c->slot         = cfg->slot;
+               c->irq          = (int) cfg->irq;
+               c->int_priority = (int) cfg->int_priority;
+               c->card_type    = cfg->card_type;
+               c->io_base      = cfg->io_base;
+               c->reset_base   = cfg->reset_base;
+               c->pDRAM        = cfg->memory[DIVAS_RAM_MEMORY];
+               c->pDEVICES     = cfg->memory[DIVAS_REG_MEMORY];
+               c->pCONFIG      = cfg->memory[DIVAS_CFG_MEMORY];
+               c->pSHARED      = cfg->memory[DIVAS_SHARED_MEMORY];
+               DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
+               DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
+               DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
+               c->cm_key               = cm_getbrdkey("Divas", cfg->card_id);*/
+               break;
+       default:
+               break;
+       }
+
+       c->in_use = TRUE;
+
+       return 0;
+}
+
+void UxCardHandleFree(ux_diva_card_t *card)
+{
+       card->in_use = FALSE;
+}
+
+
+#define PLX_IOBASE 0
+#define DIVAS_IOBASE 1
+void *UxCardMemAttach(ux_diva_card_t *card, int id)
+{
+       if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
+       {
+               switch (id)
+               {
+               case DIVAS_SHARED_MEMORY:
+                       card->mapped = card->pSHARED;
+                       return card->pSHARED;
+                       break;
+               case DIVAS_RAM_MEMORY:
+                       card->mapped = card->pDRAM;
+                       return card->pDRAM;
+                       break;
+               case DIVAS_REG_MEMORY:
+                       card->mapped = card->pDEVICES;
+                       return card->pDEVICES;
+                       break;
+               case DIVAS_CFG_MEMORY:
+                       card->mapped = card->pCONFIG;
+                       return card->pCONFIG;
+                       break;
+               default:
+                       ASSERT(FALSE);
+                       card->mapped = NULL;
+                       return (void *) 0;
+               }
+       }
+       else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
+       {
+               switch (id)
+               {
+               case PLX_IOBASE:
+                       return (void *) card->reset_base;
+                       break;
+               case DIVAS_IOBASE:
+                       return (void *) card->io_base;
+                       break;
+               default:
+                       ASSERT(FALSE);
+                       return 0;
+               }
+       }
+       
+       else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
+       {
+               switch (id)
+               {
+               case DIVAS_SHARED_MEMORY:
+                       card->mapped = card->pSHARED;
+                       return card->pSHARED;
+                       break;
+               case DIVAS_RAM_MEMORY:
+                       card->mapped = card->pDRAM;
+                       return card->pDRAM;
+                       break;
+               case DIVAS_REG_MEMORY:
+                       card->mapped = (void *) card->io_base;
+                       return (void *) card->io_base;
+                       break;
+               case DIVAS_CTL_MEMORY:
+                       card->mapped = card->pCONTROL;
+                       return card->pCONTROL;
+                       break;
+               default:
+                       // ASSERT(FALSE);
+                       DPRINTF(("divas: Trying to attach to mem %d", id));
+                       card->mapped = NULL;
+                       return (void *) 0;
+               }
+       } else
+               DPRINTF(("divas: Tried to attach to unknown card"));
+
+       /* Unknown card type */
+       return NULL;
+}
+
+void UxCardMemDetach(ux_diva_card_t *card, void *address)
+{
+       return; // Just a place holder. No un-mapping done.
+}
+
+void UxCardLog(int turn_on)
+{
+       log_on = turn_on;
+}
+
+/*
+ * Control Register I/O Routines to be performed on Attached I/O ports
+ */
+
+void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
+{
+       word base = (word) (dword) AttachedBase;
+
+       base += offset;
+
+       outb(the_byte, base);
+}
+
+void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
+{
+       word base = (word) (dword) AttachedBase;
+
+       base += offset;
+
+       outw(the_word, base);
+}
+
+void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
+{
+       word base = (word) (dword) AttachedBase;
+
+       base += offset;
+
+       outl(the_dword, base);
+}
+
+byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
+{
+       word base = (word) (dword) AttachedBase;
+
+       base += offset;
+
+       return inb(base);
+}
+
+word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
+{
+       word base = (word) (dword) AttachedBase;
+
+       base += offset;
+
+       return inw(base);
+}
+
+/*
+ * Memory mapped card I/O functions
+ */
+
+byte UxCardMemIn(ux_diva_card_t *card, void *address)
+{
+       byte    b;
+       volatile byte* t = (byte*)address;
+
+       b = *t;
+
+       if (log_on)
+       {
+               byte *a = address;
+               a -= (int) card->mapped;
+               DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
+       }
+
+    return(b); 
+}
+
+word UxCardMemInW(ux_diva_card_t *card, void *address)
+{
+       word    w;
+       volatile word* t = (word*)address;
+
+    w = *t;
+
+       if (log_on)
+    {
+               byte *a = address;
+               a -= (int) card->mapped;
+               DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
+    }
+
+    return (w);
+}
+
+dword UxCardMemInD(ux_diva_card_t *card, void *address)
+{
+       dword   dw;
+       volatile dword* t = (dword*)address;
+
+    dw = *t;
+
+       if (log_on)
+    {
+               byte *a = address;
+               a -= (int) card->mapped;
+               DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
+    }
+
+    return (dw);
+}
+
+void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
+{
+       volatile byte *pSource = address;
+       byte *pDest = buffer;
+
+       while (length--)
+       {
+               *pDest++ = *pSource++;
+       }
+
+       if (log_on)
+    {
+               byte *a = address;
+               a -= (int) card->mapped;
+               pDest = buffer;
+               DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)", 
+               pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
+               pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
+               a));
+    }
+
+    return;
+}
+
+void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
+{
+       volatile byte* t = (byte*)address;
+
+       if (log_on)
+       {
+               byte *a = address;
+               a -= (int) card->mapped;
+               DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
+       }
+
+       *t = data;
+
+       return;
+}
+
+void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
+{
+       volatile word* t = (word*)address;
+
+       if (log_on)
+       {
+               byte *a = address;
+               a -= (int) card->mapped;
+               DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
+       }
+
+       *t = data;
+    return;
+}
+
+void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
+{
+       volatile dword* t = (dword*)address;
+
+       if (log_on)
+       {
+               byte *a = address;
+               a -= (int) card->mapped;
+               DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
+       }
+
+       *t = data;
+    return;
+}
+
+void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
+{
+       byte    *pSource = buffer;
+       byte    *pDest = address;
+
+       while (length--)
+       {
+               *pDest++ = *pSource++;
+       }
+
+       if (log_on)
+    {
+               byte *a = address;
+               a -= (int) card->mapped;
+               pDest = buffer;
+               DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)", 
+               pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
+               pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
+               a));
+    }
+
+    return;
+}
+
+/*
+ * Memory mapped card I/O functions
+ */
+
+byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
+
+{
+       byte the_byte;
+
+    outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) address, card->io_base + 4);
+
+       the_byte = inb(card->io_base);
+
+       if (log_on)
+    {
+               DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)", 
+                                       the_byte & 0xff, address));
+    }
+    
+       return the_byte;
+}
+
+word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
+
+{
+       word the_word;
+
+       outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) address, card->io_base + 4);
+       the_word = inw(card->io_base);
+
+       if (log_on)
+    {
+               DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)", 
+                                       the_word & 0xffff, address));
+    }
+
+       return the_word;
+}
+
+dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
+
+{
+       dword the_dword;
+
+       outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) address, card->io_base + 4);
+       the_dword = inl(card->io_base);
+
+       if (log_on)
+    {
+               DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)", 
+                                       the_dword, address));
+    }
+
+    return the_dword;
+}
+
+void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
+
+{
+       byte *pSource = address;
+       byte *pDest = buffer;
+
+       if ((word) (dword) address & 0x1)
+       {
+               outb(0xFF, card->io_base + 0xC);
+               outw((word) (dword) pSource, card->io_base + 4);
+               *pDest = (byte) inb(card->io_base);
+               pDest++;
+               pSource++;
+               length--;
+               if (!length)
+        {
+            return;
+        }
+    }
+
+       outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) pSource, card->io_base + 4);
+       insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
+
+       if (log_on)
+    {
+               pDest = buffer;
+               DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)", 
+               pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
+               pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
+               address));
+    }
+
+    return;
+}
+
+/* Output */
+
+void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
+{
+       if (log_on)
+    {
+               DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)", 
+                                       data & 0xff, address));
+    }
+
+       outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) address, card->io_base + 4);
+       outb((byte) data & 0xFF, card->io_base);
+
+    return;
+}
+
+void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
+{
+       if (log_on)
+    {
+               DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)", 
+                                       data & 0xffff, address));
+    }
+
+       outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) address, card->io_base + 4);
+       outw((word) data & 0xFFFF, card->io_base);
+
+    return;
+}
+
+void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
+{
+       if (log_on)
+    {
+               DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
+    }
+
+       outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) address, card->io_base + 4);
+       outl((dword) data & 0xFFFFFFFF, card->io_base);
+
+    return;
+}
+
+void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
+
+{
+       byte    *pSource = buffer;
+       byte    *pDest = address;
+
+       if ((word) (dword) address & 1)
+       {
+               outb(0xFF, card->io_base + 0xC);
+               outw((word) (dword) pDest, card->io_base + 4);
+               outb(*pSource, card->io_base);
+               pSource++;
+               pDest++;
+               length--;
+               if (!length)
+        {
+                       return;
+        }
+       }
+
+    outb(0xFF, card->io_base + 0xC);
+       outw((word) (dword) pDest, card->io_base + 4);
+       outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
+
+       if (log_on)
+    {
+               pDest = buffer;
+               DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)", 
+               pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
+               pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
+               address));
+    }
+
+    return;
+}
+
+void   Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
+{
+       int i;
+       card_t *card = NULL;
+       ux_diva_card_t *ux_ref = NULL;
+
+       for (i = 0; i < DivasCardNext; i++)
+       {
+
+               if (arg == DivasCards[i].cfg.irq)
+               {
+                       card = &DivasCards[i];
+                       ux_ref = card->hw;
+       
+                       if ((ux_ref) && (card->is_live))
+                       {
+                               (*ux_ref->user_isr)(ux_ref->user_isr_arg);      
+                       }
+                       else 
+                       {
+                               DPRINTF(("divas: ISR couldn't locate card"));
+                       }
+               }
+       }
+
+       return;
+}
+
+
+int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
+{
+       int result;
+
+        card->user_isr = isr_fn;
+        card->user_isr_arg = isr_arg;
+
+       result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
+
+       return result;
+}
+
+void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
+{
+       free_irq(card->irq, card->user_isr_arg);
+}
+
+void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
+{
+       switch (size)
+       {
+       case sizeof(byte):
+               pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
+               break;
+       case sizeof(word):
+               pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
+               break;
+       case sizeof(dword):
+               pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
+               break;
+       default:
+               printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
+       }
+}
+
+void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
+{
+       switch (size)
+       {
+       case sizeof(byte):
+               pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
+               break;
+       case sizeof(word):
+               pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
+               break;
+       case sizeof(dword):
+               pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
+               break;
+       default:
+               printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
+       }
+}
+
+void *UxAlloc(unsigned int size)
+{
+       void *m;
+
+       m = kmalloc(size, GFP_ATOMIC);
+
+       return m;
+}
+
+void UxFree(void *ptr)
+{
+       kfree(ptr);
+}
+
+int UxCardLock(ux_diva_card_t *card)
+{
+       unsigned long flags;
+
+       //spin_lock_irqsave(&diva_lock, flags);
+       
+       save_flags(flags);
+       cli();
+       return flags;
+       
+}
+
+void UxCardUnlock(ux_diva_card_t *card, int ipl)
+{
+       //spin_unlock_irqrestore(&diva_lock, ipl);
+
+       restore_flags(ipl);
+
+}
+
+dword UxTimeGet(void)
+{
+       return jiffies;
+}
+
+long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
+{
+       register volatile long *p;
+       register long ret;
+       int ipl;
+
+       p =dst;
+       
+       ipl = UxCardLock(card);
+
+       *p += 1;
+       ret = *p;
+
+       UxCardUnlock(card,ipl);
+
+       return(ret);
+
+}
+
+long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
+{
+       register volatile long *p;
+       register long ret;
+       int ipl;
+
+       p =dst;
+       
+       ipl = UxCardLock(card);
+
+       *p -= 1;
+       ret = *p;
+
+       UxCardUnlock(card,ipl);
+
+       return(ret);
+
+}
diff --git a/drivers/isdn/eicon/linsys.c b/drivers/isdn/eicon/linsys.c
new file mode 100644 (file)
index 0000000..3f167ed
--- /dev/null
@@ -0,0 +1,170 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.10  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/sched.h>
+#undef N_DATA
+#include <linux/tqueue.h>
+
+#include <linux/smp.h>
+struct pt_regs;
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include "sys.h"
+#include "divas.h"
+#include "adapter.h"
+#include "divalog.h"
+
+#include "uxio.h"
+
+#ifdef MODULE
+void bcopy(void *pSource, void *pDest, dword dwLength)
+{
+       memcpy(pDest, pSource, dwLength);
+}
+#endif
+
+void bzero(void *pDataArea, dword dwLength)
+{
+       memset(pDataArea, 0, dwLength);
+}
+
+int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg)
+{
+       /* Use UxPciConfigWrite routines to initialise PCI config space */
+
+/*     wPCIcommand = 0x03;
+       cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
+
+       wPCIcommand = 0x280;
+       cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
+
+       bPCIcommand = 0x30;
+       cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
+*/
+       return 0; 
+}
+
+int DivasPRIInitPCI(card_t *card, dia_card_t *cfg)
+{
+       /* Use UxPciConfigWrite routines to initialise PCI config space */
+
+/*             wPCIcommand = 0x03;
+       cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
+       
+       wPCIcommand = 0x280;
+       cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
+       
+       bPCIcommand = 0x30;
+       cm_write_devconfig8(CMKey, PCI_LATENCY, &bPCIcommand);*/
+
+       return 0;  
+}
+
+int DivasBRIInitPCI(card_t *card, dia_card_t *cfg)
+{
+       /* Need to set these platform dependent values after patching */
+
+       card->hw->reset_base = card->cfg.reset_base;
+       card->hw->io_base = card->cfg.io_base;
+
+       request_region(card->hw->reset_base,0x80,"Divas");
+       request_region(card->hw->io_base,0x20,"Divas");
+
+
+       /* Same as for PRI */
+       return DivasPRIInitPCI(card, cfg);
+}
+
+/* ######################### Stubs of routines that are not done yet ################## */
+/*void DivasLogIdi(card_t *card, ENTITY *e, int request)
+{
+}
+*/
+
+int    DivasDpcSchedule(void)
+{
+       static  struct tq_struct DivasTask;
+
+       DivasTask.routine = DivasDoDpc;
+       DivasTask.data = (void *) 0;
+
+       queue_task(&DivasTask, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+
+       return 0;
+}
+
+int    DivasScheduleRequestDpc(void)
+{
+       static  struct tq_struct DivasTask;
+
+       DivasTask.routine = DivasDoRequestDpc;
+       DivasTask.data = (void *) 0;
+
+       queue_task(&DivasTask, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+
+       return 0;
+}
+
+void    DivasLogAdd(void *buffer, int length)
+{
+    static
+    boolean_t   overflow = FALSE;
+    static
+    boolean_t   busy = FALSE;
+
+    /* make sure we're not interrupting ourselves */
+
+    if (busy)
+    {
+        printk(KERN_DEBUG "Divas: Logging interrupting self !\n");
+        return;
+    }
+    busy = TRUE;
+
+    /* ignore call if daemon isn't running and we've reached limit */
+
+    if (DivasLogFifoFull())
+    {
+        if (!overflow)
+        {
+            printk(KERN_DEBUG "Divas: Trace buffer full\n");
+            overflow = TRUE;
+        }
+        busy = FALSE;
+        return;
+    }
+
+       DivasLogFifoWrite(buffer, length);
+
+    busy = FALSE;
+    return;
+}
+
+/* #################################################################################### */
diff --git a/drivers/isdn/eicon/log.c b/drivers/isdn/eicon/log.c
new file mode 100644 (file)
index 0000000..1d847f0
--- /dev/null
@@ -0,0 +1,179 @@
+   
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.5  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/*
+ * Source file for diva log facility
+ */
+
+#include "sys.h"
+#include "idi.h"
+#include "divas.h"
+#include "adapter.h"
+#include "divalog.h"
+
+#include "uxio.h"
+
+/*Counter to monitor number of messages */ 
+static int m_count;
+#define     MAX_BUFFERED_MSGS   (1000)
+
+/* Our Linked List Structure to hold message */
+typedef struct klog_link{
+  klog_t klog;
+  struct klog_link *next;
+}KNODE;
+
+/* First & Last structures in list*/
+KNODE *head;
+KNODE *tail;
+
+/* 
+ * retrieve message from FIFO buffer
+ * returns NULL if buffer empty
+ * otherwise returns pointer to entry 
+ */
+
+char   *DivasLogFifoRead(void)
+
+{
+       KNODE *old_head;
+
+       if(head==NULL) 
+       {
+               /* Buffer Empty - No Messages */
+               return NULL;    
+       }
+
+       m_count--;
+       /* Keep track of message to be read & increment to next message*/
+       old_head = head;
+       head = head->next;
+    /*Return ptr to Msg */     
+    return((char *)old_head);
+}
+
+/* 
+ * write message into FIFO buffer
+ */
+
+void   DivasLogFifoWrite(char *entry, int length)
+
+{
+    KNODE *new_klog;
+
+    if(head == NULL) 
+    {
+       /* No Entries in Log */
+       tail=NULL;
+       m_count=0;
+       new_klog=UxAlloc(sizeof(KNODE));
+
+       if(new_klog==NULL)
+       {
+               return;
+       }
+
+       m_count++;
+       bzero(new_klog,sizeof(KNODE));
+
+       /* Set head & tail to point to the new Msg Struct */
+       head=tail=new_klog;
+       tail->next=NULL;
+    }
+    else
+    {
+       new_klog=UxAlloc(sizeof(KNODE));
+       
+       if(new_klog==NULL)
+       {
+               return;
+       }
+
+       m_count++;
+       bzero(new_klog,sizeof(KNODE));
+
+       /* Let last Msg Struct point to new Msg Struct & inc tail */
+       tail->next=new_klog;
+       tail=new_klog;
+       tail->next=NULL;
+    }
+
+    if (length > sizeof(klog_t))
+    {
+        length = sizeof(klog_t);
+    }
+
+    bcopy(entry,&tail->klog,length);
+
+    return;
+}
+
+/*
+ * DivaslogFifoEmpty:return TRUE if FIFO buffer is empty,otherwise FALSE
+ */
+int DivasLogFifoEmpty(void)
+{
+       return (m_count == 0);
+}
+
+/*
+ *DivasLogFifoFull:return TRUE if FIFO buffer is full,otherwise FALSE
+ */
+int DivasLogFifoFull(void)
+{
+       return (m_count == MAX_BUFFERED_MSGS);
+}
+
+/*
+ * generate an IDI log entry
+ */
+
+void   DivasLogIdi(card_t *card, ENTITY *e, int request)
+
+{
+       klog_t          klog;
+
+       bzero(&klog, sizeof(klog));
+
+       klog.time_stamp = UxTimeGet();
+
+       klog.length = sizeof(ENTITY) > sizeof(klog.buffer) ?
+                                               sizeof(klog.buffer) : sizeof(ENTITY);
+
+       klog.card = (int) (card - DivasCards);
+
+       klog.type = request ? KLOG_IDI_REQ : KLOG_IDI_CALLBACK;
+       klog.code = 0;
+       bcopy(e, klog.buffer, klog.length);
+
+    /* send to the log driver and return */
+
+    DivasLogAdd(&klog, sizeof(klog));
+
+       return;
+}
diff --git a/drivers/isdn/eicon/md5sums.asc b/drivers/isdn/eicon/md5sums.asc
new file mode 100644 (file)
index 0000000..aa1cd90
--- /dev/null
@@ -0,0 +1,16 @@
+# These are valid md5sums to detect modifications
+# in eicon driver files provided by Eicon Technology.
+# For changes and modifications in these files please
+# read ../../../Documentation/isdn/README.eicon
+# 
+9b0e381d4558af3a6eba66843e1ee5d9  common.c
+dbb92cba52db31ff8325a252b3f595c3  idi.c
+15687687ef82f099966ed42772001cd3  bri.c
+c3e3b720c3351b66635bd548195e29e8  pri.c
+b0a6d2ab49bcfcfd1825860f178a84b4  log.c
+673746176316b72271a09c0a27287a01  xlog.c
+07e1bbabdb4d69880db196ef31bfb241  kprintf.c
+b60b40ad630f26b7923369df95b4d1b9  fpga.c
+5013ecca0a38a8fcc4a61642754f2076  fourbri.c
+1501ae468a0c5eaab1e60720fa723a67  fcheck.c
+# end of md5sums
diff --git a/drivers/isdn/eicon/pc.h b/drivers/isdn/eicon/pc.h
new file mode 100644 (file)
index 0000000..412a61f
--- /dev/null
@@ -0,0 +1,320 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.2  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef PC_H_INCLUDED
+#define PC_H_INCLUDED
+
+
+#define byte unsigned char
+#define word unsigned short
+#define dword unsigned long
+#if !defined(MIN)
+#define MIN(a,b) ((a)>(b) ? (b) : (a))
+#endif
+#if !defined(MAX)
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#endif
+
+/*------------------------------------------------------------------*/
+/* buffer definition                                                */
+/*------------------------------------------------------------------*/
+
+typedef struct {
+  word length;          /* length of data/parameter field           */
+  byte P[270];          /* data/parameter field                     */
+} PBUFFER;
+
+/*------------------------------------------------------------------*/
+/* dual port ram structure                                          */
+/*------------------------------------------------------------------*/
+
+struct dual
+{
+  byte Req;             /* request register                         */
+  byte ReqId;           /* request task/entity identification       */
+  byte Rc;              /* return code register                     */
+  byte RcId;            /* return code task/entity identification   */
+  byte Ind;             /* Indication register                      */
+  byte IndId;           /* Indication task/entity identification    */
+  byte IMask;           /* Interrupt Mask Flag                      */
+  byte RNR;             /* Receiver Not Ready (set by PC)           */
+  byte XLock;           /* XBuffer locked Flag                      */
+  byte Int;             /* ISDN-S interrupt                         */
+  byte ReqCh;           /* Channel field for layer-3 Requests       */
+  byte RcCh;            /* Channel field for layer-3 Returncodes    */
+  byte IndCh;           /* Channel field for layer-3 Indications    */
+  byte MInd;            /* more data indication field               */
+  word MLength;         /* more data total packet length            */
+  byte ReadyInt;        /* request field for ready interrupt        */
+  byte SWReg;           /* Software register for special purposes   */  
+  byte Reserved[11];    /* reserved space                           */
+  byte InterfaceType;   /* interface type 1=16K interface           */
+  word Signature;       /* ISDN-S adapter Signature (GD)            */
+  PBUFFER XBuffer;      /* Transmit Buffer                          */
+  PBUFFER RBuffer;      /* Receive Buffer                           */
+};
+
+/*------------------------------------------------------------------*/
+/* SWReg Values (0 means no command)                                */
+/*------------------------------------------------------------------*/
+#define SWREG_DIE_WITH_LEDON  0x01
+#define SWREG_HALT_CPU        0x02 /* Push CPU into a while(1) loop */         
+
+/*------------------------------------------------------------------*/
+/* Id Fields Coding                                                 */
+/*------------------------------------------------------------------*/
+
+#define ID_MASK 0xe0    /* Mask for the ID field                    */
+#define GL_ERR_ID 0x1f  /* ID for error reporting on global requests*/
+
+#define DSIG_ID  0x00   /* ID for D-channel signaling               */
+#define NL_ID    0x20   /* ID for network-layer access (B or D)     */
+#define BLLC_ID  0x60   /* ID for B-channel link level access       */
+#define TASK_ID  0x80   /* ID for dynamic user tasks                */
+#define TIMER_ID 0xa0   /* ID for timer task                        */
+#define TEL_ID   0xc0   /* ID for telephone support                 */
+#define MAN_ID   0xe0   /* ID for management                        */
+
+/*------------------------------------------------------------------*/
+/* ASSIGN and REMOVE requests are the same for all entities         */
+/*------------------------------------------------------------------*/
+
+#define ASSIGN  0x01
+#define UREMOVE  0xfe   /* without returncode */  
+#define REMOVE  0xff
+
+/*------------------------------------------------------------------*/
+/* Timer Interrupt Task Interface                                   */
+/*------------------------------------------------------------------*/
+
+#define ASSIGN_TIM 0x01
+#define REMOVE_TIM 0xff
+
+/*------------------------------------------------------------------*/
+/* dynamic user task interface                                      */
+/*------------------------------------------------------------------*/
+
+#define ASSIGN_TSK 0x01
+#define REMOVE_TSK 0xff
+
+#define LOAD 0xf0
+#define RELOCATE 0xf1
+#define START 0xf2
+#define LOAD2 0xf3
+#define RELOCATE2 0xf4
+
+/*------------------------------------------------------------------*/
+/* dynamic user task messages                                       */
+/*------------------------------------------------------------------*/
+
+#define TSK_B2          0x0000
+#define TSK_WAKEUP      0x2000
+#define TSK_TIMER       0x4000
+#define TSK_TSK         0x6000
+#define TSK_PC          0xe000
+
+/*------------------------------------------------------------------*/
+/* LL management primitives                                         */
+/*------------------------------------------------------------------*/
+
+#define ASSIGN_LL 1     /* assign logical link                      */
+#define REMOVE_LL 0xff  /* remove logical link                      */
+
+/*------------------------------------------------------------------*/
+/* LL service primitives                                            */
+/*------------------------------------------------------------------*/
+
+#define LL_UDATA 1      /* link unit data request/indication        */
+#define LL_ESTABLISH 2  /* link establish request/indication        */
+#define LL_RELEASE 3    /* link release request/indication          */
+#define LL_DATA 4       /* data request/indication                  */
+#define LL_LOCAL 5      /* switch to local operation (COM only)     */
+#define LL_DATA_PEND 5  /* data pending indication (SDLC SHM only)  */
+#define LL_REMOTE 6     /* switch to remote operation (COM only)    */
+#define LL_TEST 8       /* link test request                        */
+#define LL_MDATA 9      /* more data request/indication             */
+#define LL_BUDATA 10    /* broadcast unit data request/indication   */
+#define LL_XID 12       /* XID command request/indication           */
+#define LL_XID_R 13     /* XID response request/indication          */
+
+/*------------------------------------------------------------------*/
+/* NL service primitives                                            */
+/*------------------------------------------------------------------*/
+
+#define N_MDATA         1       /* more data to come REQ/IND        */
+#define N_CONNECT       2       /* OSI N-CONNECT REQ/IND            */
+#define N_CONNECT_ACK   3       /* OSI N-CONNECT CON/RES            */
+#define N_DISC          4       /* OSI N-DISC REQ/IND               */
+#define N_DISC_ACK      5       /* OSI N-DISC CON/RES               */
+#define N_RESET         6       /* OSI N-RESET REQ/IND              */
+#define N_RESET_ACK     7       /* OSI N-RESET CON/RES              */
+#define N_DATA          8       /* OSI N-DATA REQ/IND               */
+#define N_EDATA         9       /* OSI N-EXPEDITED DATA REQ/IND     */
+#define N_UDATA         10      /* OSI D-UNIT-DATA REQ/IND          */
+#define N_BDATA         11      /* BROADCAST-DATA REQ/IND           */
+#define N_DATA_ACK      12      /* data ack ind for D-bit procedure */
+#define N_EDATA_ACK     13      /* data ack ind for INTERRUPT       */
+
+#define N_Q_BIT         0x10    /* Q-bit for req/ind                */
+#define N_M_BIT         0x20    /* M-bit for req/ind                */
+#define N_D_BIT         0x40    /* D-bit for req/ind                */
+
+/*------------------------------------------------------------------*/
+/* Signaling management primitives                                  */
+/*------------------------------------------------------------------*/
+
+#define ASSIGN_SIG 1    /* assign signaling task                    */
+#define UREMOVE_SIG 0xfe /* remove signaling task without returncode */
+#define REMOVE_SIG 0xff /* remove signaling task                    */
+
+/*------------------------------------------------------------------*/
+/* Signaling service primitives                                     */
+/*------------------------------------------------------------------*/
+
+#define CALL_REQ 1      /* call request                             */
+#define CALL_CON 1      /* call confirmation                        */
+#define CALL_IND 2      /* incoming call connected                  */
+#define LISTEN_REQ 2    /* listen request                           */
+#define HANGUP 3        /* hangup request/indication                */
+#define SUSPEND 4       /* call suspend request/confirm             */
+#define RESUME 5        /* call resume request/confirm              */
+#define SUSPEND_REJ 6   /* suspend rejected indication              */
+#define USER_DATA 8     /* user data for user to user signaling     */
+#define CONGESTION 9    /* network congestion indication            */
+#define INDICATE_REQ 10 /* request to indicate an incoming call     */
+#define INDICATE_IND 10 /* indicates that there is an incoming call */
+#define CALL_RES 11     /* accept an incoming call                  */
+#define CALL_ALERT 12   /* send ALERT for incoming call             */
+#define INFO_REQ 13     /* INFO request                             */
+#define INFO_IND 13     /* INFO indication                          */
+#define REJECT 14       /* reject an incoming call                  */
+#define RESOURCES 15    /* reserve B-Channel hardware resources     */
+#define TEL_CTRL 16     /* Telephone control request/indication     */
+#define STATUS_REQ 17   /* Request D-State (returned in INFO_IND)   */
+#define FAC_REG_REQ 18  /* connection idependent fac registration   */
+#define FAC_REG_ACK 19  /* fac registration acknowledge             */
+#define FAC_REG_REJ 20  /* fac registration reject                  */
+#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call       */
+#define FACILITY_REQ 22 /* send a Facility Message type             */
+#define FACILITY_IND 22 /* Facility Message type indication         */
+#define SIG_CTRL     29 /* Control for signalling hardware          */
+#define DSP_CTRL     30 /* Control for DSPs                         */
+#define LAW_REQ      31 /* Law config request for (returns info_i)  */ 
+
+/*------------------------------------------------------------------*/
+/* management service primitives                                    */
+/*------------------------------------------------------------------*/
+
+#define MAN_READ        2
+#define MAN_WRITE       3
+#define MAN_EXECUTE     4
+#define MAN_EVENT_ON    5
+#define MAN_EVENT_OFF   6
+#define MAN_LOCK        7
+#define MAN_UNLOCK      8   
+
+#define MAN_INFO_IND    2
+#define MAN_EVENT_IND   3
+#define MAN_TRACE_IND   4  
+
+#define MAN_ESC         0x80
+
+/*------------------------------------------------------------------*/
+/* return code coding                                               */
+/*------------------------------------------------------------------*/
+
+#define UNKNOWN_COMMAND         0x01    /* unknown command          */
+#define WRONG_COMMAND           0x02    /* wrong command            */
+#define WRONG_ID                0x03    /* unknown task/entity id   */
+#define WRONG_CH                0x04    /* wrong task/entity id     */
+#define UNKNOWN_IE              0x05    /* unknown information el.  */
+#define WRONG_IE                0x06    /* wrong information el.    */
+#define OUT_OF_RESOURCES        0x07    /* ISDN-S card out of res.  */
+#define ADAPTER_DEAD            0x08    /* ISDN card CPU halted     */ 
+#define N_FLOW_CONTROL          0x10    /* Flow-Control, retry      */
+#define ASSIGN_RC               0xe0    /* ASSIGN acknowledgement   */
+#define ASSIGN_OK               0xef    /* ASSIGN OK                */
+#define OK_FC                   0xfc    /* Flow-Control RC          */
+#define READY_INT               0xfd    /* Ready interrupt          */
+#define TIMER_INT               0xfe    /* timer interrupt          */
+#define OK                      0xff    /* command accepted         */
+
+/*------------------------------------------------------------------*/
+/* information elements                                             */
+/*------------------------------------------------------------------*/
+
+#define SHIFT 0x90              /* codeset shift                    */
+#define MORE 0xa0               /* more data                        */
+#define CL 0xb0                 /* congestion level                 */
+
+        /* codeset 0                                                */
+
+#define BC  0x04                /* Bearer Capability                */
+#define CAU 0x08                /* cause                            */
+#define CAD 0x0c                /* Connected address                */
+#define CAI 0x10                /* call identity                    */
+#define CHI 0x18                /* channel identification           */
+#define LLI 0x19                /* logical link id                  */
+#define CHA 0x1a                /* charge advice                    */
+#define DT  0x29                /* ETSI date/time                   */
+#define KEY 0x2c                /* keypad information element       */
+#define FTY 0x1c                /* facility information element     */ 
+#define DSP 0x28                /* display                          */
+#define OAD 0x6c                /* origination address              */
+#define OSA 0x6d                /* origination sub-address          */
+#define CPN 0x70                /* called party number              */
+#define DSA 0x71                /* destination sub-address          */
+#define RDX 0x73                /* redirected number extended       */
+#define RDN 0x74                /* redirected number                */  
+#define LLC 0x7c                /* low layer compatibility          */
+#define HLC 0x7d                /* high layer compatibility         */
+#define UUI 0x7e                /* user user information            */
+#define ESC 0x7f                /* escape extension                 */
+
+#define DLC 0x20                /* data link layer configuration    */
+#define NLC 0x21                /* network layer configuration      */
+
+        /* codeset 6                                                */
+
+#define SIN 0x01                /* service indicator                */
+#define CIF 0x02                /* charging information             */
+#define DATE 0x03               /* date                             */
+#define CPS 0x07                /* called party status              */
+
+/*------------------------------------------------------------------*/
+/* TEL_CTRL contents                                                */
+/*------------------------------------------------------------------*/
+
+#define RING_ON         0x01
+#define RING_OFF        0x02
+#define HANDS_FREE_ON   0x03
+#define HANDS_FREE_OFF  0x04
+#define ON_HOOK         0x80
+#define OFF_HOOK        0x90
+
+#endif
diff --git a/drivers/isdn/eicon/pc_maint.h b/drivers/isdn/eicon/pc_maint.h
new file mode 100644 (file)
index 0000000..e6e902f
--- /dev/null
@@ -0,0 +1,165 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#ifndef PC_MAINT_H
+#define PC_MAINT_H
+
+#if !defined(MIPS_SCOM)
+#define BUFFER_SZ  48
+#define MAINT_OFFS 0x380
+#else
+#define BUFFER_SZ  128
+#define MAINT_OFFS 0xff00
+#endif
+
+#define MIPS_BUFFER_SZ  128
+#define MIPS_MAINT_OFFS 0xff00
+
+#define DO_LOG                     1
+#define MEMR                    2
+#define MEMW                    3
+#define IOR                     4
+#define IOW                     5
+#define B1TEST                  6
+#define B2TEST                  7
+#define BTESTOFF                8
+#define DSIG_STATS              9
+#define B_CH_STATS              10
+#define D_CH_STATS              11
+#define BL1_STATS               12
+#define BL1_STATS_C             13
+#define GET_VERSION             14
+#define OS_STATS                15
+#define XLOG_SET_MASK           16
+#define XLOG_GET_MASK           17
+#define DSP_READ                20
+#define DSP_WRITE               21
+
+#define OK 0xff
+#define MORE_EVENTS 0xfe
+#define NO_EVENT 1
+
+struct DSigStruc
+{
+  byte Id;
+  byte uX;
+  byte listen;
+  byte active;
+  byte sin[3];
+  byte bc[6];
+  byte llc[6];
+  byte hlc[6];
+  byte oad[20];
+};
+
+struct BL1Struc {
+  dword cx_b1;
+  dword cx_b2;
+  dword cr_b1;
+  dword cr_b2;
+  dword px_b1;
+  dword px_b2;
+  dword pr_b1;
+  dword pr_b2;
+  word er_b1;
+  word er_b2;
+};
+
+struct L2Struc {
+  dword XTotal;
+  dword RTotal;
+  word XError;
+  word RError;
+};
+
+struct OSStruc {
+  word free_n;
+};
+
+typedef union
+{
+  struct DSigStruc DSigStats;
+  struct BL1Struc BL1Stats;
+  struct L2Struc L2Stats;
+  struct OSStruc OSStats;
+  byte   b[BUFFER_SZ];
+  word   w[BUFFER_SZ>>1];
+  word   l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
+  dword  d[BUFFER_SZ>>2];
+} BUFFER;
+
+typedef union
+{
+  struct DSigStruc DSigStats;
+  struct BL1Struc BL1Stats;
+  struct L2Struc L2Stats;
+  struct OSStruc OSStats;
+  byte   b[MIPS_BUFFER_SZ];
+  word   w[MIPS_BUFFER_SZ>>1];
+  word   l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
+  dword  d[MIPS_BUFFER_SZ>>2];
+} MIPS_BUFFER;
+
+
+#if !defined(MIPS_SCOM)
+struct pc_maint
+{
+  byte req;
+  byte rc;
+  byte *mem;  /*far*/
+  short length;
+  word port;
+  byte fill[6];
+  BUFFER data;
+};
+#else
+struct pc_maint
+{
+  byte req;
+  byte rc;
+  byte reserved[2];     /* R3000 alignment ... */
+  byte far *mem;
+  short length;
+  word port;
+  byte fill[4];         /* data at offset 16   */
+  BUFFER data;
+};
+#endif
+
+struct mi_pc_maint
+{
+  byte req;
+  byte rc;
+  byte reserved[2];     /* R3000 alignment ... */
+  byte *mem; /*far*/
+  short length;
+  word port;
+  byte fill[4];         /* data at offset 16   */
+  MIPS_BUFFER data;
+};
+
+#endif /* PC_MAINT_H */
diff --git a/drivers/isdn/eicon/pr_pc.h b/drivers/isdn/eicon/pr_pc.h
new file mode 100644 (file)
index 0000000..f01ad44
--- /dev/null
@@ -0,0 +1,86 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.0  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#if !defined(PR_PC_H)
+#define PR_PC_H
+
+struct pr_ram {
+  word NextReq;         /* pointer to next Req Buffer               */
+  word NextRc;          /* pointer to next Rc Buffer                */
+  word NextInd;         /* pointer to next Ind Buffer               */
+  byte ReqInput;        /* number of Req Buffers sent               */
+  byte ReqOutput;       /* number of Req Buffers returned           */
+  byte ReqReserved;     /* number of Req Buffers reserved           */
+  byte Int;             /* ISDN-P interrupt                         */
+  byte XLock;           /* Lock field for arbitration               */
+  byte RcOutput;        /* number of Rc buffers received            */
+  byte IndOutput;       /* number of Ind buffers received           */
+  byte IMask;           /* Interrupt Mask Flag                      */
+  byte Reserved1[2];    /* reserved field, do not use               */
+  byte ReadyInt;        /* request field for ready interrupt        */
+  byte Reserved2[12];   /* reserved field, do not use               */
+  byte InterfaceType;   /* interface type 1=16K interface           */
+  word Signature;       /* ISDN-P initialized indication            */
+  byte B[1];            /* buffer space for Req,Ind and Rc          */
+};
+
+typedef struct {
+  word next;
+  byte Req;
+  byte ReqId;
+  byte ReqCh;
+  byte Reserved1;
+  word Reference;
+  byte Reserved[8];
+  PBUFFER XBuffer;
+} REQ;
+
+typedef struct {
+  word next;
+  byte Rc;
+  byte RcId;
+  byte RcCh;
+  byte Reserved1;
+  word Reference;
+  byte Reserved2[8];
+} RC;
+
+typedef struct {
+  word next;
+  byte Ind;
+  byte IndId;
+  byte IndCh;
+  byte MInd;
+  word MLength;
+  word Reference;
+  byte RNR;
+  byte Reserved;
+  dword Ack;
+  PBUFFER RBuffer;
+} IND;
+
+#endif
diff --git a/drivers/isdn/eicon/pri.c b/drivers/isdn/eicon/pri.c
new file mode 100644 (file)
index 0000000..a6a6394
--- /dev/null
@@ -0,0 +1,533 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.5  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* Diva Server PRI specific part of initialisation */
+#include "sys.h"
+#include "idi.h"
+#include "divas.h"
+#include "pc.h"
+#include "pr_pc.h"
+#include "dsp_defs.h"
+
+#include "adapter.h"
+#include "uxio.h"
+
+#define        DIVAS_LOAD_CMD          0x02
+#define        DIVAS_START_CMD         0x03
+#define        DIVAS_IRQ_RESET         0xC18
+#define DIVAS_IRQ_RESET_VAL    0xFE
+
+#define        TEST_INT_DIVAS          0x11
+#define TEST_INT_DIVAS_BRI     0x12
+
+#define DIVAS_RESET    0x81
+#define DIVAS_LED1     0x04
+#define DIVAS_LED2     0x08
+#define DIVAS_LED3     0x20
+#define DIVAS_LED4     0x40
+
+#define        DIVAS_RESET_REG         0x20
+
+#define        DIVAS_SIGNATURE 0x4447
+
+/* offset to start of MAINT area (used by xlog) */
+
+#define        DIVAS_MAINT_OFFSET      0xef00  /* value for PRI card */
+
+#define MP_PROTOCOL_ADDR               0xA0011000
+#define MP_DSP_CODE_BASE               0xa03a0000  
+
+typedef struct {
+               dword cmd;
+               dword addr;
+               dword len;
+               dword err;
+               dword live;
+               dword reserved[(0x1020>>2)-6];
+               dword signature;
+               byte  data[1];
+} diva_server_boot_t;
+
+byte mem_in(ADAPTER *a, void *adr);
+word mem_inw(ADAPTER *a, void *adr);
+void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
+void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
+void mem_out(ADAPTER *a, void *adr, byte data);
+void mem_outw(ADAPTER *a, void *adr, word data);
+void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
+void mem_inc(ADAPTER *a, void *adr);
+
+int DivasPRIInitPCI(card_t *card, dia_card_t *cfg);
+int pri_ISR (card_t* card);
+
+static int diva_server_reset(card_t *card)
+{
+       byte *reg;
+       diva_server_boot_t *boot = NULL;
+       dword live = 0;
+       int     i = 0;
+       dword   dwWait;
+
+       DPRINTF(("divas: reset Diva Server PRI"));
+
+       reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
+
+       UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], DIVAS_RESET | 
+                                               DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
+
+       for (dwWait = 0x000fffff; dwWait; dwWait--)
+               ;
+
+       UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], 0x00);
+
+       for (dwWait = 0x000fffff; dwWait; dwWait--)
+               ;
+
+       UxCardMemDetach(card->hw, reg);
+
+       boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
+
+       UxCardMemOutD(card->hw, boot->reserved, 0);
+
+       live = UxCardMemInD(card->hw, &boot->live);
+
+       for (i=0; i<5; i++)
+       {
+               if (live != UxCardMemInD(card->hw, &boot->live))
+               {
+                       break;
+               }
+               UxPause(10);
+       }
+
+       if (i == 5)
+       {
+               UxCardMemDetach(card->hw, boot);
+
+               DPRINTF(("divas: card is reset but CPU not running"));
+               return -1;
+       }
+
+       UxCardMemDetach(card->hw, boot);
+
+       DPRINTF(("divas: card reset after %d ms", i * 10));
+
+       return 0;
+}
+
+static int diva_server_config(card_t *card, dia_config_t *config)
+{
+       byte *shared;
+       int i, j;
+
+       DPRINTF(("divas: configure Diva Server PRI"));
+
+       shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       UxCardLog(0);
+       for (i=0; i<256; i++)
+       {
+               UxCardMemOut(card->hw, &shared[i], 0);
+       }
+
+       UxCardMemOut(card->hw, &shared[ 8], config->tei);
+       UxCardMemOut(card->hw, &shared[ 9], config->nt2);
+       UxCardMemOut(card->hw, &shared[10], 0);
+       UxCardMemOut(card->hw, &shared[11], config->watchdog);
+       UxCardMemOut(card->hw, &shared[12], config->permanent);
+       UxCardMemOut(card->hw, &shared[13], config->x_interface);
+       UxCardMemOut(card->hw, &shared[14], config->stable_l2);
+       UxCardMemOut(card->hw, &shared[15], config->no_order_check);
+       UxCardMemOut(card->hw, &shared[16], config->handset_type);
+       UxCardMemOut(card->hw, &shared[17], 0);
+       UxCardMemOut(card->hw, &shared[18], config->low_channel);
+       UxCardMemOut(card->hw, &shared[19], config->prot_version);
+       UxCardMemOut(card->hw, &shared[20], config->crc4);
+
+       for (i=0; i<2; i++)
+       {
+               for (j=0; j<32; j++)
+               {
+                       UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
+               }
+
+               for (j=0; j<32; j++)
+               {
+                       UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
+               }
+
+               for (j=0; j<32; j++)
+               {
+                       UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
+               }
+       }
+
+       UxCardMemDetach(card->hw, shared);
+
+       return 0;
+}
+
+static
+void diva_server_reset_int(card_t *card)
+{
+       byte *cfg;
+
+       cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
+
+       UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL);
+       UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0);
+       UxCardMemDetach(card->hw, cfg);
+
+       return;
+}
+
+static int diva_server_test_int(card_t *card)
+{
+       int i;
+       byte *shared;
+       byte req_int;
+
+       DPRINTF(("divas: test interrupt for Diva Server PRI"));
+
+       shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       UxCardMemIn(card->hw, &shared[0x3FE]);
+       UxCardMemOut(card->hw, &shared[0x3FE], 0);
+       UxCardMemIn(card->hw, &shared[0x3FE]);
+
+       UxCardMemDetach(card->hw, shared);
+
+       diva_server_reset_int(card);
+
+       shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
+
+       card->test_int_pend = TEST_INT_DIVAS;
+
+       req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt));
+
+       req_int++;
+
+       UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int);
+
+       UxCardMemDetach(card->hw, shared);
+
+       UxCardLog(0);
+       for (i = 0; i < 50; i++)
+       {
+               if (!card->test_int_pend)
+               {
+                       break;
+               }
+               UxPause(10);
+       }
+
+
+       if (card->test_int_pend)
+       {
+
+               DPRINTF(("active: timeout waiting for card to interrupt"));
+               return (-1);
+       
+       }
+       
+       return 0;
+}
+
+
+static void print_hdr(unsigned char *code, int offset)
+{
+       unsigned char hdr[80];
+               int i;
+
+       i = 0;
+
+       while ((i < (DIM(hdr) -1)) && 
+               (code[offset + i] != '\0') &&
+               (code[offset + i] != '\r') &&
+               (code[offset + i] != '\n'))
+       {
+               hdr[i] = code[offset + i];
+               i++;
+       }
+
+       hdr[i] = '\0';
+
+       DPRINTF(("divas: loading %s", hdr));
+}
+
+static int diva_server_load(card_t *card, dia_load_t *load)
+{
+       diva_server_boot_t *boot;
+       int i, offset, length;
+       dword cmd = 0;
+
+       DPRINTF(("divas: loading Diva Server PRI"));
+
+       boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
+
+       switch(load->code_type)
+       {
+               case DIA_CPU_CODE:
+                       DPRINTF(("divas: RISC code"));
+                       print_hdr(load->code, 0x80);
+
+                       UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
+                       break;
+
+               case DIA_DSP_CODE:
+                       DPRINTF(("divas: DSP code"));
+                       print_hdr(load->code, 0x0);
+
+                       UxCardMemOutD(card->hw, &boot->addr,  
+                               (MP_DSP_CODE_BASE + (((sizeof(dword) +
+                               (sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT))
+                               + ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA)));
+                       break;
+
+               case DIA_TABLE_CODE:
+                       DPRINTF(("divas: TABLE code"));
+                       UxCardMemOutD(card->hw, &boot->addr,
+                               (MP_DSP_CODE_BASE + sizeof(dword)));
+                       break;
+
+               case DIA_CONT_CODE:
+                       DPRINTF(("divas: continuation code"));
+                       break;
+
+        case DIA_DLOAD_CNT:
+                       DPRINTF(("divas: COUNT code"));
+                       UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE);
+                       break;
+
+               default:
+                       DPRINTF(("divas: unknown code type"));
+                       UxCardMemDetach(card->hw, boot);
+                       return -1;
+       }
+
+       UxCardLog(0);
+       offset = 0;
+
+       do
+       {
+               length = (load->length - offset >= 400) ? 400 : load->length - offset;
+
+               for (i=0; i<length; i++)
+               {
+                       UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]);
+               }
+
+        for (i=0; i<length; i++)
+               {
+                       if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i]))
+                       {
+                               UxCardMemDetach(card->hw, boot);
+
+                               DPRINTF(("divas: card code block verify failed"));
+                               return -1;
+                       }
+               }
+       
+               UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4);
+               UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD);
+
+               for (i=0; i<50000; i++)
+               {
+                       cmd = UxCardMemInD(card->hw, &boot->cmd);
+                       if (!cmd)
+                       {
+                               break;
+                       }
+                       /*UxPause(1);*/
+               }
+
+               if (cmd)
+               {
+                       DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset));
+                       UxCardMemDetach(card->hw, boot);
+                       return -1;
+               }
+
+               offset += length;
+
+       } while (offset < load->length);
+
+       UxCardMemDetach(card->hw, boot);
+
+       DPRINTF(("divas: DIVA Server card loaded"));
+
+       return 0;
+}
+
+static int diva_server_start(card_t *card, byte *channels)
+{
+       diva_server_boot_t *boot;
+       byte *ram;
+       int     i;
+       dword signature = 0;
+
+       DPRINTF(("divas: start Diva Server PRI"));
+
+       card->is_live = FALSE;
+
+       boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
+
+       UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
+       UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD);
+
+       UxCardLog(0);
+
+       for (i = 0; i < 300; i++)
+       {
+               signature = UxCardMemInD(card->hw, &boot->signature);
+               if ((signature >> 16) == DIVAS_SIGNATURE)
+               {
+                       DPRINTF(("divas: started card after %d ms", i * 10));
+                       break;
+               }
+               UxPause(10);
+       }
+
+       if ((signature >> 16) != DIVAS_SIGNATURE)
+       {
+               UxCardMemDetach(card->hw, boot);
+               DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature));
+               return -1;
+       }
+
+       card->is_live = TRUE;
+
+       ram = (byte *) boot;
+       ram += DIVAS_SHARED_OFFSET;
+
+       *channels = UxCardMemIn(card->hw, &ram[0x3F6]);
+       card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]);
+
+       UxCardMemDetach(card->hw, boot);
+
+       if (diva_server_test_int(card))
+       {
+               DPRINTF(("divas: interrupt test failed"));
+               return -1;      
+       }
+
+       DPRINTF(("divas: DIVA Server card started"));
+
+       return 0;
+}
+
+static
+int    diva_server_mem_get(card_t *card, mem_block_t *mem_block)
+
+{
+       byte    *a;
+       byte    *card_addr;
+       word    length = 0;
+       int             i;
+
+       a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
+
+       card_addr = a;
+       card_addr += mem_block->addr;
+
+       for (i=0; i < sizeof(mem_block->data); i++)
+       {
+               mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
+               card_addr++;
+               length++;
+       }
+
+       UxCardMemDetach(card->hw, a);
+
+       return length;
+}
+
+/*
+ * Initialise PRI specific entry points
+ */
+
+int DivasPriInit(card_t *card, dia_card_t *cfg)
+{
+       DPRINTF(("divas: initialise Diva Server PRI"));
+
+       if (DivasPRIInitPCI(card, cfg) == -1)
+       {
+               return -1;
+       }
+
+       card->card_reset = diva_server_reset;
+       card->card_load = diva_server_load;
+       card->card_config = diva_server_config;
+       card->card_start = diva_server_start;
+       card->reset_int = diva_server_reset_int;
+       card->card_mem_get = diva_server_mem_get;
+
+       card->xlog_offset = DIVAS_MAINT_OFFSET;
+
+       card->out = DivasOut;
+       card->test_int = DivasTestInt;
+       card->dpc = DivasDpc;
+       card->clear_int = DivasClearInt;
+       card->card_isr  = pri_ISR;
+
+       card->a.ram_out = mem_out;
+       card->a.ram_outw = mem_outw;
+       card->a.ram_out_buffer = mem_out_buffer;
+       card->a.ram_inc = mem_inc;
+
+       card->a.ram_in = mem_in;
+       card->a.ram_inw = mem_inw;
+       card->a.ram_in_buffer = mem_in_buffer;
+       card->a.ram_look_ahead = mem_look_ahead;
+
+       return 0;
+}
+
+
+int pri_ISR (card_t* card) 
+{
+       int served = 0;
+       byte* cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
+       volatile unsigned long* isr = (unsigned long*)&cfg[DIVAS_IRQ_RESET];
+       register unsigned long val = *isr;
+       
+       if (val & 0x80000000)  /* our card had caused interrupt ??? */
+       {
+               served = 1;
+               card->int_pend  += 1;
+               DivasDpcSchedule(); /* ISR DPC */
+
+               *isr = (unsigned long)~0x03E00000; /* Clear interrupt line */
+       }
+
+       UxCardMemDetach(card->hw, cfg);
+
+       return (served != 0);
+}
+
+
diff --git a/drivers/isdn/eicon/sys.h b/drivers/isdn/eicon/sys.h
new file mode 100644 (file)
index 0000000..0e636c5
--- /dev/null
@@ -0,0 +1,119 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.2  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* Environment provided by system and miscellaneous definitions */
+
+#if !defined(SYS_H)
+#define SYS_H
+
+/* abreviations for unsigned types */
+typedef int boolean_t;
+
+typedef unsigned char byte;
+
+typedef unsigned long dword;
+typedef unsigned short word;
+
+/* abreviations for volatile types */
+
+typedef volatile byte  vbyte;
+typedef volatile word  vword;
+typedef volatile dword vdword;
+
+/* Booleans */
+
+#if !defined(TRUE)
+#define TRUE    (1)
+#define FALSE   (0)
+#endif
+
+/* NULL pointer */
+
+#if !defined(NULL)
+#define NULL    ((void *) 0)
+#endif
+
+/* MIN and MAX */
+
+#if !defined(MIN)
+#define MIN(a,b) ((a)>(b) ? (b) : (a))
+#endif
+#if !defined(MAX)
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#endif
+
+/* Return the dimension of an array */
+
+#if !defined(DIM)
+#define DIM(array)  (sizeof (array)/sizeof ((array)[0]))
+#endif
+
+/*
+ * Return the number of milliseconds since last boot
+ */
+
+extern dword   UxTimeGet(void);
+
+extern void    DivasSprintf(char *buffer, char *format, ...);
+extern void    DivasPrintf(char *format, ...);
+
+/* fatal errors, asserts and tracing */
+
+void HwFatalErrorFrom(char *file, int line);
+void HwFatalError(void);
+/* void HwAssert(char *file, int line, char *condition); */
+
+#include <linux/kernel.h>
+#define _PRINTK printk
+
+#define _PRINTF        DivasPrintf
+void _PRINTF(char *format, ...);
+#define PRINTF(arg_list)       _PRINTF arg_list
+#if defined DTRACE
+# define DPRINTF(arg_list)     _PRINTF arg_list
+# define KDPRINTF(arg_list)    _PRINTF arg_list ; _PRINTK arg_list ; _PRINTK("\n");
+#else
+# define DPRINTF(arg_list)     (void)0
+# define KDPRINTF(arg_list)    _PRINTK arg_list ; _PRINTK("\n");
+#endif
+
+#if !defined(ASSERT)
+#if defined DEBUG || defined DBG
+# define HwFatalError()        HwFatalErrorFrom(__FILE__, __LINE__)
+# define ASSERT(cond)                                                          \
+               if (!(cond))                                                            \
+               {                                                                                       \
+/*                     HwAssert(__FILE__, __LINE__, #cond);*/  \
+               }
+#else
+# define ASSERT(cond)  ((void)0)
+#endif
+#endif /* !defined(ASSERT) */
+
+#define TRACE  (_PRINTF(__FILE__"@%d\n", __LINE__))
+
+#endif /* SYS_H */
diff --git a/drivers/isdn/eicon/uxio.h b/drivers/isdn/eicon/uxio.h
new file mode 100644 (file)
index 0000000..c15d93f
--- /dev/null
@@ -0,0 +1,220 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.6  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/*
+ * Interface to Unix specific code for performing card I/O
+ */
+
+#if !defined(UXIO_H)
+#define UXIO_H
+
+#include "sys.h"
+#include "adapter.h"
+
+
+struct pt_regs;
+
+/* user callback, returns zero if interrupt was from this card */
+typedef        void            isr_fn_t(void *);
+struct ux_diva_card_s
+{
+       word    in_use;
+       int             io_base;
+       int             reset_base;
+       int             card_type;
+       byte            *mapped;
+       int             bus_num;
+       int             func_num;
+       int             slot;
+       int             irq;
+       byte            *pDRAM;
+       byte            *pDEVICES;
+       byte            *pCONFIG;
+       byte            *pSHARED;
+       byte            *pCONTROL;
+       word            features;
+       void            *user_isr_arg;
+       isr_fn_t        *user_isr;
+};
+
+void bcopy(void *pSource, void *pDest, dword dwLength);
+void bzero(void *pDataArea, dword dwLength);
+
+
+/*
+ * Get a card handle to enable card to be accessed
+ */
+
+int            UxCardHandleGet(        ux_diva_card_t  **card,
+                                                       dia_card_t              *cfg);
+
+/*
+ * Free a card handle as no longer needed
+ */
+
+void   UxCardHandleFree(ux_diva_card_t *card);
+
+/*
+ * Lock and unlock access to a card
+ */
+
+int            UxCardLock(ux_diva_card_t *card);
+void   UxCardUnlock(ux_diva_card_t *card, int ipl);
+
+/*
+ * Set the mapping address for PCI cards
+ */
+
+int            UxCardAddrMappingSet(ux_diva_card_t     *card,
+                                                       int                             id,
+                                                       void                    *address,
+                                                       int                             size);
+
+/*
+ * Attach card to memory to enable it to be accessed
+ * Returns the mapped address
+ */
+
+void   *UxCardMemAttach(ux_diva_card_t *card, int id);
+
+/*
+ * map card out of memory after completion of access
+ */
+
+void   UxCardMemDetach(ux_diva_card_t *card, void *address);
+
+/*
+ * input functions for memory-mapped cards
+ */
+
+byte   UxCardMemIn(ux_diva_card_t *card, void *address);
+
+word   UxCardMemInW(ux_diva_card_t *card, void *address);
+
+dword  UxCardMemInD(ux_diva_card_t *card, void *address);
+
+void   UxCardMemInBuffer(      ux_diva_card_t *card,
+                                                       void                    *address,
+                                                       void                    *buffer,
+                                                       int                             length);
+
+/*
+ * output functions for memory-mapped cards
+ */
+
+void UxCardMemOut(ux_diva_card_t *card, void *address, byte data);
+
+void UxCardMemOutW(ux_diva_card_t *card, void *address, word data);
+
+void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data);
+
+void UxCardMemOutBuffer(       ux_diva_card_t  *card,
+                                                       void                    *address,
+                                                       void                    *buffer,
+                                                       int                             length);
+
+/*
+ * input functions for I/O-mapped cards
+ */
+
+byte   UxCardIoIn(ux_diva_card_t *card, void *, void *address);
+
+word   UxCardIoInW(ux_diva_card_t *card, void *, void *address);
+
+dword  UxCardIoInD(ux_diva_card_t *card, void *, void *address);
+
+void   UxCardIoInBuffer(       ux_diva_card_t *card,
+                                                       void *, void                    *address,
+                                                       void                    *buffer,
+                                                       int                             length);
+
+/*
+ * output functions for I/O-mapped cards
+ */
+
+void UxCardIoOut(ux_diva_card_t *card, void *, void *address, byte data);
+
+void UxCardIoOutW(ux_diva_card_t *card, void *, void *address, word data);
+
+void UxCardIoOutD(ux_diva_card_t *card, void *, void *address, dword data);
+
+void UxCardIoOutBuffer(        ux_diva_card_t  *card,
+                                                       void *, void                    *address,
+                                                       void                    *buffer,
+                                                       int                             length);
+
+/*
+ * Get specified PCI config
+ */
+
+void   UxPciConfigRead(ux_diva_card_t  *card, 
+                                               int                             size,
+                                               int                             offset,
+                                               void                    *value);
+
+/*
+ * Set specified PCI config
+ */
+
+void   UxPciConfigWrite(ux_diva_card_t *card, 
+                                               int                             size,
+                                               int                             offset,
+                                               void                    *value);
+
+/* allocate memory, returning NULL if none available */
+
+void   *UxAlloc(unsigned int size);
+
+void   UxFree(void *);
+
+/*
+ * Pause for specified number of milli-seconds 
+ */
+
+void   UxPause(long ms);
+
+/*
+ * Install an ISR for the specified card
+ */
+
+int            UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg);
+
+/*
+ * Remove an ISR for the specified card
+ */
+void   UxIsrRemove(ux_diva_card_t *card, void *);
+
+/*
+ * DEBUG function to turn logging ON or OFF
+ */
+
+void   UxCardLog(int turn_on);
+
+long   UxInterlockedIncrement(ux_diva_card_t *card, long *dst);
+long   UxInterlockedDecrement(ux_diva_card_t *card, long *dst);
+
+#endif /* of UXIO_H */
diff --git a/drivers/isdn/eicon/xlog.c b/drivers/isdn/eicon/xlog.c
new file mode 100644 (file)
index 0000000..282662c
--- /dev/null
@@ -0,0 +1,183 @@
+
+/*
+ *
+ * Copyright (C) Eicon Technology Corporation, 2000.
+ *
+ * This source file is supplied for the exclusive use with Eicon
+ * Technology Corporation's range of DIVA Server Adapters.
+ *
+ * Eicon File Revision :    1.2  
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/*
+ * Unix Eicon active card driver
+ * XLOG related functions
+ */
+
+#include "sys.h"
+#include "idi.h"
+#include "pc.h"
+#include "pc_maint.h"
+#include "divalog.h"
+
+#include "adapter.h"
+#include "uxio.h"
+
+/*
+ * convert/copy XLOG info into a KLOG entry
+ */
+
+static
+void   xlog_to_klog(byte *b, int size, int card_num)
+
+{
+       typedef struct
+       {
+               word    code;
+               word    time_hi;
+               word    time_lo;
+               word    xcode;
+               byte    data[2];
+       } card_xlog_t;
+
+       card_xlog_t     *x;
+
+       klog_t          klog;
+
+       x = (card_xlog_t *) b;
+
+       bzero(&klog, sizeof(klog));
+
+       klog.time_stamp = (dword) x->time_hi;
+       klog.time_stamp = (klog.time_stamp << 16) | (dword) x->time_lo;
+
+       klog.length = size > sizeof(klog.buffer) ? sizeof(klog.buffer) : size;
+
+       klog.card = card_num;
+       if (x->code == 1)
+       {
+               klog.type = KLOG_XTXT_MSG;
+               klog.code = 0;
+               bcopy(&x->xcode, klog.buffer, klog.length);
+       }
+       else if (x->code == 2)
+       {
+               klog.type = KLOG_XLOG_MSG;
+               klog.code = x->xcode;
+               bcopy(&x->data, klog.buffer, klog.length);
+       }
+       else
+       {
+               char    *c; int i;
+               klog.type = KLOG_TEXT_MSG;
+               klog.code = 0;
+               c = "divas: invalid xlog message code from card";
+               i = 0;
+               while (*c)
+               {
+                       klog.buffer[i] = *c;
+                       c++;
+                       i++;
+               }
+               klog.buffer[i] = *c;
+       }
+
+    /* send to the log driver and return */
+
+    DivasLogAdd(&klog, sizeof(klog));
+
+       return;
+}
+
+/*
+ * send an XLOG request down to specified card
+ * if response available from previous request then read it
+ * if not then just send down new request, ready for next time
+ */
+
+void   DivasXlogReq(int card_num)
+
+{
+       card_t                          *card;
+       ADAPTER                         *a;
+
+       if ((card_num < 0) || (card_num > DivasCardNext))
+       {
+               DPRINTF(("xlog: invalid card number"));
+               return;
+       }
+
+       card = &DivasCards[card_num];
+
+       if (DivasXlogRetrieve(card))
+       {
+               return;
+       }
+
+       /* send down request for next time */
+
+       a = &card->a;
+
+       a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
+       a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
+
+       return;
+}
+
+/*
+ * retrieve XLOG request from specified card
+ * returns non-zero if new request sent to card
+ */
+
+int            DivasXlogRetrieve(card_t *card)
+
+{
+       ADAPTER                         *a;
+       struct mi_pc_maint      pcm;
+
+       a = &card->a;
+
+       /* get status of last request */
+
+       pcm.rc = a->ram_in(a, (word *)(card->xlog_offset + 1));
+
+       /* if nothing there from previous request, send down a new one */
+
+       if (pcm.rc == OK)
+       {
+               /* read in response */
+
+               a->ram_in_buffer(a, (word *) (dword) card->xlog_offset, &pcm, sizeof(pcm)); 
+
+               xlog_to_klog((byte *) &pcm.data, sizeof(pcm.data), 
+                                               (int) (card - DivasCards));
+       }
+
+       /* if any response received from card, re-send request */
+
+       if (pcm.rc)
+       {
+               a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
+               a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
+
+               return 1;
+       } 
+
+       return 0;
+}
index 5f7622572e0bfc48950e939ef72c42471d6845a1..9023f0a81bbb2e3ddc49f39a037b869e76016fd0 100644 (file)
@@ -20,7 +20,7 @@ if [ "$CONFIG_MTD" != "n" ]; then
       fi
    fi
    dep_tristate '  Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD
-   dep_tristate '  Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD
+   dep_tristate '  Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI
    if [ "$CONFIG_MTD_PMC551" != "n" ]; then
       bool '    PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
    fi
index 9bb2fa52f1c922f94216ca136c2560d4b2615b46..fd01a602558585ba58bd28cf8f8f59d5cb5024d7 100644 (file)
     - Print a warning on out-of-memory (rate limited to 1 per 10 secs)
     - Added two more Cardbus 575 NICs: 5b57 and 6564 (Paul Wagland)
 
+    LK1.1.7 2 Jul 2000 andrewm
+    - Better handling of shared IRQs
+    - Reset the transmitter on a Tx reclaim error
+    - Fixed crash under OOM during vortex_open() (Mark Hemment)
+    - Fix Rx cessation problem during OOM (help from Mark Hemment)
+    - The spinlocks around the mdio access were blocking interrupts for 300uS.
+      Fix all this to use spin_lock_bh() within mdio_read/write
+    - Only write to TxFreeThreshold if it's a boomerang - other NICs don't
+      have one.
+    - Added 802.3x MAC-layer flow control support
+
+   LK1.1.8 13 Aug 2000 andrewm
+    - Ignore request_region() return value - already reserved if Cardbus.
+    - Merged some additional Cardbus flags from Don's 0.99Qk
+    - Some fixes for 3c556 (Fred Maciel)
+    - Fix for EISA initialisation (Jan Rkorajski)
+    - Renamed MII_XCVR_PWR and EEPROM_230 to align with 3c575_cb and D. Becker's drivers
+    - Fixed MII_XCVR_PWR for 3CCFE575CT
+    - Added INVERT_LED_PWR, used it.
+    - Backed out the extra_reset stuff
+
     - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
+    - Also see Documentation/networking/vortex.txt
 */
 
 /*
@@ -103,8 +125,6 @@ static const int rx_copybreak = 200;
 static const int mtu = 1500;
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 32;
-/* Give the NIC an extra reset at the end of vortex_up() */
-static int extra_reset = 0;
 /* Tx timeout interval (millisecs) */
 static int watchdog = 400;
 
@@ -163,16 +183,16 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
 #include <linux/delay.h>
 
 static char version[] __devinitdata =
-"3c59x.c:v0.99L+LK1.1.6  28 May 2000  Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.97 $\n";
+"3c59x.c:LK1.1.8  13 Aug 2000  Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.25 $\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver");
 MODULE_PARM(debug, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(flow_ctrl, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(extra_reset, "i");
 MODULE_PARM(compaq_ioaddr, "i");
 MODULE_PARM(compaq_irq, "i");
 MODULE_PARM(compaq_device_id, "i");
@@ -281,8 +301,9 @@ enum pci_flags_bit {
 };
 
 enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
-       EEPROM_230=0x10,        /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */
-       HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, };
+       EEPROM_8BIT=0x10,       /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */
+       HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100,
+       INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400 };
 
 
 enum vortex_chips {
@@ -312,14 +333,16 @@ enum vortex_chips {
 
        CH_3CSOHO100_TX,
        CH_3C555,
+       CH_3C556,
        CH_3C575,
        CH_3C575_1,
-       CH_3CCFE575,
 
+       CH_3CCFE575,
        CH_3CCFE575CT,
        CH_3CCFE656,
        CH_3CCFEM656,
        CH_3CCFEM656_1,
+
        CH_3C450,
 };
 
@@ -383,24 +406,26 @@ static struct vortex_chip_info {
         PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
        {"3c555 Laptop Hurricane",
         PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+       {"3c556 10/100 Mini PCI Adapter",
+        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR, 128, },
        {"3c575 [Megahertz] 10/100 LAN  CardBus",
-        PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 128, },
+        PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
        {"3c575 Boomerang CardBus",
-        PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 128, },
-       {"3CCFE575 Cyclone CardBus",
-        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
+        PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
 
+       {"3CCFE575BT Cyclone CardBus",
+        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_LED_PWR, 128, },
        {"3CCFE575CT Cyclone CardBus",
-        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
+        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR, 128, },
        {"3CCFE656 Cyclone CardBus",
-        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
-       {"3CCFEM656 Cyclone CardBus",
-        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
-       {"3CCFEM656 Cyclone CardBus(0x6564)",                   /* From pcmcia-cs-3.1.5 */
-        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
+        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|INVERT_LED_PWR, 128, },
+       {"3CCFEM656B Cyclone+Winmodem CardBus",
+        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|INVERT_LED_PWR, 128, },
+       {"3CCFE656C Tornado+Winmodem CardBus",                  /* From pcmcia-cs-3.1.5 */
+        PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR, 128, },
+
        {"3c450 HomePNA Tornado",                                               /* AKPM: from Don's 0.99Q */
         PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, },
-
        {0,}, /* 0 terminated list. */
 };
 
@@ -432,16 +457,17 @@ static struct pci_device_id vortex_pci_tbl[] __devinitdata = {
 
        { 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX },
        { 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 },
+       { 0x10B7, 0x6055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556 },
        { 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 },
        { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 },
-       { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 },
 
+       { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 },
        { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT },
        { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 },
        { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 },
        { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 },
-       { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
 
+       { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
        {0,}                                            /* 0 terminated list. */
 };
 MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
@@ -612,16 +638,20 @@ struct vortex_private {
 
        /* The remainder are related to chip state, mostly media selection. */
        struct timer_list timer;                        /* Media selection timer. */
+       struct timer_list rx_oom_timer;         /* Rx skb allocation retry timer */
        int options;                                            /* User-settable misc. driver options. */
        unsigned int media_override:4,          /* Passed-in media type. */
                default_media:4,                                /* Read from the EEPROM/Wn3_Config. */
                full_duplex:1, force_fd:1, autoselect:1,
                bus_master:1,                                   /* Vortex can only do a fragment bus-m. */
                full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
-               hw_csums:1,                                             /* Has hardware checksums. */
+               flow_ctrl:1,                                    /* Use 802.3x flow control (PAUSE only) */
+               partner_flow_ctrl:1,                    /* Partner supports flow control */
                tx_full:1,
                has_nway:1,
-               open:1;
+               open:1,
+               must_free_region:1;                             /* Flag: if zero, Cardbus owns the I/O region */
+       int drv_flags;
        int tx_reset_resume;                            /* Flag to retart timer after vortex_error handling */
        u16 status_enable;
        u16 intr_enable;
@@ -632,7 +662,8 @@ struct vortex_private {
        u16 deferred;                                           /* Resend these interrupts when we
                                                                                 * bale from the ISR */
        u16 io_size;                                            /* Size of PCI region (for release_region) */
-       spinlock_t lock;
+       spinlock_t lock;                                        /* Serialise access to device & its vortex_private */
+       spinlock_t mdio_lock;                           /* Serialise access to mdio hardware */
 };
 
 /* The action to take with a media selection timer tick.
@@ -669,9 +700,10 @@ static void vortex_up(struct net_device *dev);
 static void vortex_down(struct net_device *dev);
 static int vortex_open(struct net_device *dev);
 static void mdio_sync(long ioaddr, int bits);
-static int mdio_read(long ioaddr, int phy_id, int location);
-static void mdio_write(long ioaddr, int phy_id, int location, int value);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *vp, int phy_id, int location, int value);
 static void vortex_timer(unsigned long arg);
+static void rx_oom_timer(unsigned long arg);
 static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int vortex_rx(struct net_device *dev);
@@ -692,7 +724,9 @@ static void acpi_set_WOL(struct net_device *dev);
 #define MAX_UNITS 8
 static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
 static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
+/* #define dev_alloc_skb dev_alloc_skb_debug */
 
 /* A list of all installed Vortex EISA devices, for removing the driver module. */
 static struct net_device *root_vortex_eisa_dev = NULL;
@@ -746,7 +780,7 @@ static int __init vortex_eisa_init (void)
        for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
                int device_id;
 
-               if (request_region(ioaddr, VORTEX_TOTAL_SIZE, "vortex") == NULL)
+               if (request_region(ioaddr, VORTEX_TOTAL_SIZE, "3c59x") == NULL)
                        continue;
 
                /* Check the standard EISA ID register for an encoded '3Com'. */
@@ -780,7 +814,6 @@ static int __init vortex_eisa_init (void)
        return vortex_cards_found - orig_cards_found;
 }
 
-
 /* returns count (>= 0), or negative on error */
 static int __devinit vortex_init_one (struct pci_dev *pdev,
                                      const struct pci_device_id *ent)
@@ -815,6 +848,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
 
        if (!printed_version) {
                printk (KERN_INFO "%s", version);
+               printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
                printed_version = 1;
        }
 
@@ -836,6 +870,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
        dev->base_addr = ioaddr;
        dev->irq = irq;
        dev->mtu = mtu;
+       vp->drv_flags = vci->drv_flags;
        vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
        vp->io_size = vci->io_size;
 
@@ -848,11 +883,9 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
        /* PCI-only startup logic */
        if (pdev) {
                /* EISA resources already marked, so only PCI needs to do this here */
-               if (!request_region (ioaddr, vci->io_size, dev->name)) {
-                       printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
-                               dev->name, vci->io_size, ioaddr);
-                       retval = -EBUSY;
-                       goto free_dev;
+               /* Ignore return value, because Cardbus drivers already allocate for us */
+               if (request_region(ioaddr, vci->io_size, dev->name) != NULL) {
+                       vp->must_free_region = 1;
                }
 
                /* wake up and enable device */         
@@ -866,15 +899,15 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
                        pci_set_master (pdev);
        }
 
-       vp->lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&vp->lock);
+       spin_lock_init(&vp->mdio_lock);
        vp->pdev = pdev;
 
        /* Makes sure rings are at least 16 byte aligned. */
        vp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct boom_rx_desc) * RX_RING_SIZE
                                           + sizeof(struct boom_tx_desc) * TX_RING_SIZE,
                                           &vp->rx_ring_dma);
-       if (vp->rx_ring == 0)
-       {
+       if (vp->rx_ring == 0) {
                retval = -ENOMEM;
                goto free_region;
        }
@@ -888,8 +921,8 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
                pdev->driver_data = dev;
 
        /* The lower four bits are the media type. */
-       if (dev->mem_start)
-       {       /*
+       if (dev->mem_start) {
+               /*
                 * AKPM: ewww..  The 'options' param is passed in as the third arg to the
                 * LILO 'ether=' argument for non-modular use
                 */
@@ -900,24 +933,26 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
        else
                option = -1;
 
+       vp->media_override = 7;
        if (option >= 0) {
                vp->media_override = ((option & 7) == 2)  ?  0  :  option & 15;
                vp->full_duplex = (option & 0x200) ? 1 : 0;
                vp->bus_master = (option & 16) ? 1 : 0;
-       } else {
-               vp->media_override = 7;
-               vp->full_duplex = 0;
-               vp->bus_master = 0;
        }
-       if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
-               vp->full_duplex = 1;
+
+       if (card_idx < MAX_UNITS) {
+               if (full_duplex[card_idx] > 0)
+                       vp->full_duplex = 1;
+               if (flow_ctrl[card_idx] > 0)
+                       vp->flow_ctrl = 1;
+       }
 
        vp->force_fd = vp->full_duplex;
        vp->options = option;
        /* Read the station address from the EEPROM. */
        EL3WINDOW(0);
        {
-               int base = (vci->drv_flags & EEPROM_230) ? 0x230 : EEPROM_Read;
+               int base = (vci->drv_flags & EEPROM_8BIT) ? 0x230 : EEPROM_Read;
                for (i = 0; i < 0x40; i++) {
                        int timer;
                        outw(base + i, ioaddr + Wn0EepromCmd);
@@ -960,17 +995,21 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
 
        if (pdev && vci->drv_flags & HAS_CB_FNS) {
                unsigned long fn_st_addr;                       /* Cardbus function status space */
+               unsigned short n;
+
                fn_st_addr = pci_resource_start (pdev, 2);
                if (fn_st_addr)
                        vp->cb_fn_base = ioremap(fn_st_addr, 128);
                printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n",
                           dev->name, fn_st_addr, vp->cb_fn_base);
-#if 1 /* AKPM: the 575_cb and 905B LEDs seem OK without this */
-               if (vortex_pci_tbl[chip_idx].device != 0x5257) {
-                       EL3WINDOW(2);
-                       outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);
-               }
-#endif
+               EL3WINDOW(2);
+
+               n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
+               if (vp->drv_flags & INVERT_LED_PWR)
+                       n |= 0x10;
+               if (vp->drv_flags & INVERT_MII_PWR)
+                       n |= 0x4000;
+               outw(n, ioaddr + Wn2_ResetOptions);
        }
 
        /* Extract our information from the EEPROM data. */
@@ -978,8 +1017,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
        vp->info2 = eeprom[15];
        vp->capabilities = eeprom[16];
 
-       if (vp->info1 & 0x8000)
-       {
+       if (vp->info1 & 0x8000) {
                vp->full_duplex = 1;
                printk(KERN_INFO "Full duplex capable\n");
        }
@@ -1018,10 +1056,10 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
                EL3WINDOW(4);
                mii_preamble_required++;
                mii_preamble_required++;
-               mdio_read(ioaddr, 24, 1);
+               mdio_read(dev, 24, 1);
                for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
                        int mii_status, phyx = phy & 0x1f;
-                       mii_status = mdio_read(ioaddr, phyx, 1);
+                       mii_status = mdio_read(dev, phyx, 1);
                        if (mii_status  &&  mii_status != 0xffff) {
                                vp->phys[phy_idx++] = phyx;
                                printk(KERN_INFO "  MII transceiver found at address %d,"
@@ -1035,11 +1073,11 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
                        printk(KERN_WARNING"  ***WARNING*** No MII transceivers found!\n");
                        vp->phys[0] = 24;
                } else {
-                       vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);
+                       vp->advertising = mdio_read(dev, vp->phys[0], 4);
                        if (vp->full_duplex) {
                                /* Only advertise the FD media types. */
                                vp->advertising &= ~0x02A0;
-                               mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);
+                               mdio_write(dev, vp->phys[0], 4, vp->advertising);
                        }
                }
        }
@@ -1056,20 +1094,21 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
        }
 
        /* The 3c59x-specific entries in the device structure. */
-       dev->open = &vortex_open;
-       dev->hard_start_xmit = &vortex_start_xmit;
-       dev->stop = &vortex_close;
-       dev->get_stats = &vortex_get_stats;
-       dev->do_ioctl = &vortex_ioctl;
-       dev->set_multicast_list = &set_rx_mode;
-       dev->tx_timeout = &vortex_tx_timeout;
+       dev->open = vortex_open;
+       dev->hard_start_xmit = vp->full_bus_master_tx ?
+                                       boomerang_start_xmit : vortex_start_xmit;
+       dev->stop = vortex_close;
+       dev->get_stats = vortex_get_stats;
+       dev->do_ioctl = vortex_ioctl;
+       dev->set_multicast_list = set_rx_mode;
+       dev->tx_timeout = vortex_tx_timeout;
        dev->watchdog_timeo = (watchdog * HZ) / 1000;
 
        return 0;
 
 free_region:
-       release_region (ioaddr, vci->io_size);
-free_dev:
+       if (vp->must_free_region)
+               release_region(ioaddr, vci->io_size);
        unregister_netdev(dev);
        kfree (dev);
        printk(KERN_ERR PFX "vortex_probe1 fails.  Returns %d\n", retval);
@@ -1082,8 +1121,7 @@ static void wait_for_completion(struct net_device *dev, int cmd)
        int i = 4000;
 
        outw(cmd, dev->base_addr + EL3_CMD);
-       while (--i > 0)
-       {
+       while (--i > 0) {
                if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
                        return;
        }
@@ -1136,9 +1174,13 @@ vortex_up(struct net_device *dev)
        init_timer(&vp->timer);
        vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
        vp->timer.data = (unsigned long)dev;
-       vp->timer.function = &vortex_timer;             /* timer handler */
+       vp->timer.function = vortex_timer;              /* timer handler */
        add_timer(&vp->timer);
 
+       init_timer(&vp->rx_oom_timer);
+       vp->rx_oom_timer.data = (unsigned long)dev;
+       vp->rx_oom_timer.function = rx_oom_timer;
+
        if (vortex_debug > 1)
                printk(KERN_DEBUG "%s: Initial media type %s.\n",
                           dev->name, media_tbl[dev->if_port].name);
@@ -1157,13 +1199,14 @@ vortex_up(struct net_device *dev)
                int mii_reg1, mii_reg5;
                EL3WINDOW(4);
                /* Read BMSR (reg1) only to clear old status. */
-               mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
-               mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
+               mii_reg1 = mdio_read(dev, vp->phys[0], 1);
+               mii_reg5 = mdio_read(dev, vp->phys[0], 5);
                if (mii_reg5 == 0xffff  ||  mii_reg5 == 0x0000)
                        ;                                       /* No MII device or no link partner report */
                else if ((mii_reg5 & 0x0100) != 0       /* 100baseTx-FD */
                                 || (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */
                        vp->full_duplex = 1;
+               vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0);
                if (vortex_debug > 1)
                        printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x,"
                                   " setting %s-duplex.\n", dev->name, vp->phys[0],
@@ -1172,8 +1215,10 @@ vortex_up(struct net_device *dev)
        }
 
        /* Set the full-duplex bit. */
-       outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-                (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);
+       outw(   ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+                       (dev->mtu > 1500 ? 0x40 : 0) |
+                       ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
+                       ioaddr + Wn3_MAC_Ctrl);
 
        if (vortex_debug > 1) {
                printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n",
@@ -1199,15 +1244,10 @@ vortex_up(struct net_device *dev)
                outw(0, ioaddr + i);
 
        if (vp->cb_fn_base) {
-               u_short n = inw(ioaddr + Wn2_ResetOptions);
-#if 0  /* AKPM: This is done in vortex_probe1, and seems to be wrong anyway... */
-               /* Inverted LED polarity */
-               if (device_id != 0x5257)
-                       n |= 0x0010;
-#endif
-               /* Inverted polarity of MII power bit */
-               if ((device_id == 0x6560) || (device_id == 0x6562) ||
-                       (device_id == 0x5257))
+               unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
+               if (vp->drv_flags & INVERT_LED_PWR)
+                       n |= 0x10;
+               if (vp->drv_flags & INVERT_MII_PWR)
                        n |= 0x4000;
                outw(n, ioaddr + Wn2_ResetOptions);
        }
@@ -1245,9 +1285,9 @@ vortex_up(struct net_device *dev)
                outl(vp->rx_ring_dma, ioaddr + UpListPtr);
        }
        if (vp->full_bus_master_tx) {           /* Boomerang bus master Tx. */
-               dev->hard_start_xmit = &boomerang_start_xmit;
                vp->cur_tx = vp->dirty_tx = 0;
-               outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+               if (vp->drv_flags & IS_BOOMERANG)
+                       outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
                /* Clear the Rx, Tx rings. */
                for (i = 0; i < RX_RING_SIZE; i++)      /* AKPM: this is done in vortex_open, too */
                        vp->rx_ring[i].status = 0;
@@ -1277,17 +1317,6 @@ vortex_up(struct net_device *dev)
        outw(vp->intr_enable, ioaddr + EL3_CMD);
        if (vp->cb_fn_base)                     /* The PCMCIA people are idiots.  */
                writel(0x8000, vp->cb_fn_base + 4);
-
-       if (extra_reset)
-       {
-               /* AKPM: unjam the 3CCFE575CT */
-               wait_for_completion(dev, TxReset);
-               if (vp->full_bus_master_tx) {
-                       outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
-                       outw(DownUnstall, ioaddr + EL3_CMD);
-               }
-               outw(TxEnable, ioaddr + EL3_CMD);
-       }
        netif_start_queue (dev);
 }
 
@@ -1301,9 +1330,9 @@ vortex_open(struct net_device *dev)
        MOD_INC_USE_COUNT;
 
        /* Use the now-standard shared IRQ implementation. */
-       if (request_irq(dev->irq, vp->full_bus_master_rx ? &boomerang_interrupt : &vortex_interrupt,
-                                       SA_SHIRQ, dev->name, dev)) {
-               retval = -EAGAIN;
+       if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ?
+                               &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev))) {
+               printk(KERN_ERR "%s: Could not reserve IRQ %d\n", dev->name, dev->irq);
                goto out;
        }
 
@@ -1323,6 +1352,17 @@ vortex_open(struct net_device *dev)
                        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
                        vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
                }
+               if (i != RX_RING_SIZE) {
+                       int j;
+                       for (j = 0; j < RX_RING_SIZE; j++) {
+                               if (vp->rx_skbuff[j]) {
+                                       dev_kfree_skb(vp->rx_skbuff[j]);
+                                       vp->rx_skbuff[j] = 0;
+                               }
+                       }
+                       retval = -ENOMEM;
+                       goto out_free_irq;
+               }
                /* Wrap the ring. */
                vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
        }
@@ -1330,10 +1370,13 @@ vortex_open(struct net_device *dev)
        vortex_up(dev);
        vp->open = 1;
        return 0;
+
+out_free_irq:
+       free_irq(dev->irq, dev);
 out:
-       MOD_DEC_USE_COUNT;
        if (vortex_debug > 1)
-               printk(KERN_ERR PFX "vortex_open() fails: returning %d\n", retval);
+               printk(KERN_ERR "%s: vortex_open() fails: returning %d\n", dev->name, retval);
+       MOD_DEC_USE_COUNT;
        return retval;
 }
 
@@ -1346,7 +1389,7 @@ static void vortex_timer(unsigned long data)
        int ok = 0;
        int media_status, mii_status, old_window;
 
-       if (vortex_debug > 1) {
+       if (vortex_debug > 2) {
                printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
                           dev->name, media_tbl[dev->if_port].name);
                printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
@@ -1369,16 +1412,13 @@ static void vortex_timer(unsigned long data)
                break;
        case XCVR_MII: case XCVR_NWAY:
                {
-                       unsigned long flags;
-                       spin_lock_irqsave(&vp->lock, flags);    /* AKPM: protect mdio state */
-
-                       mii_status = mdio_read(ioaddr, vp->phys[0], 1);
+                       mii_status = mdio_read(dev, vp->phys[0], 1);
                        ok = 1;
-                       if (vortex_debug > 1)
+                       if (vortex_debug > 2)
                                printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
                                        dev->name, mii_status);
                        if (mii_status & 0x0004) {
-                               int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
+                               int mii_reg5 = mdio_read(dev, vp->phys[0], 5);
                                if (! vp->force_fd  &&  mii_reg5 != 0xffff) {
                                        int duplex = (mii_reg5&0x0100) ||
                                                (mii_reg5 & 0x01C0) == 0x0040;
@@ -1390,17 +1430,16 @@ static void vortex_timer(unsigned long data)
                                                        vp->phys[0], mii_reg5);
                                                /* Set the full-duplex bit. */
                                                EL3WINDOW(3);   /* AKPM: this was missing from 2.3.99 3c59x.c! */
-                                               outb((vp->full_duplex ? 0x20 : 0) |
-                                                       (dev->mtu > 1500 ? 0x40 : 0),
-                                                       ioaddr + Wn3_MAC_Ctrl);
+                                               outw(   (vp->full_duplex ? 0x20 : 0) |
+                                                               (dev->mtu > 1500 ? 0x40 : 0) |
+                                                               ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
+                                                               ioaddr + Wn3_MAC_Ctrl);
                                                if (vortex_debug > 1)
                                                        printk(KERN_DEBUG "Setting duplex in Wn3_MAC_Ctrl\n");
                                                /* AKPM: bug: should reset Tx and Rx after setting Duplex.  Page 180 */
                                        }
-                                       next_tick = 60*HZ;
                                }
                        }
-                       spin_unlock_irqrestore(&vp->lock, flags);
                }
                break;
          default:                                      /* Other media types handled by Tx timeouts. */
@@ -1445,7 +1484,7 @@ static void vortex_timer(unsigned long data)
        EL3WINDOW(old_window);
        enable_irq(dev->irq);
 
-       if (vortex_debug > 1)
+       if (vortex_debug > 2)
          printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
                         dev->name, media_tbl[dev->if_port].name);
 
@@ -1506,7 +1545,8 @@ static void vortex_tx_timeout(struct net_device *dev)
                }
                if (vp->tx_full)
                        netif_stop_queue (dev);
-               outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+               if (vp->drv_flags & IS_BOOMERANG)
+                       outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
                outw(DownUnstall, ioaddr + EL3_CMD);
        } else {
                vp->stats.tx_dropped++;
@@ -1549,8 +1589,8 @@ vortex_error(struct net_device *dev, int status)
                if (tx_status & 0x14)  vp->stats.tx_fifo_errors++;
                if (tx_status & 0x38)  vp->stats.tx_aborted_errors++;
                outb(0, ioaddr + TxStatus);
-               if (tx_status & 0x38)   /* AKPM: tx reset after 16 collisions, despite what the manual says */
-                       do_tx_reset = 1;
+               if (tx_status & 0x3a)   /* TxReset after 16 collisions, despite what the manual says */
+                       do_tx_reset = 1;        /* Also reset on reclaim errors */
                else                                    /* Merely re-enable the transmitter. */
                        outw(TxEnable, ioaddr + EL3_CMD);
        }
@@ -1592,7 +1632,7 @@ vortex_error(struct net_device *dev, int status)
                        /* In this case, blow the card away */
                        vortex_down(dev);
                        wait_for_completion(dev, TotalReset | 0xff);
-                       vortex_up(dev);
+                       vortex_up(dev);         /* AKPM: bug.  vortex_up() assumes that the rx ring is full. It may not be. */
                } else if (fifo_diag & 0x0400)
                        do_tx_reset = 1;
                if (fifo_diag & 0x3000) {
@@ -1706,12 +1746,13 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
        unsigned long flags;
 
-       if (vortex_debug > 6)
+       if (vortex_debug > 6) {
                printk(KERN_DEBUG "boomerang_start_xmit()\n");
+               if (vortex_debug > 3)
+                       printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+                                  dev->name, vp->cur_tx);
+       }
 
-       if (vortex_debug > 3)
-               printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
-                          dev->name, vp->cur_tx);
        if (vp->tx_full) {
                if (vortex_debug > 0)
                        printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
@@ -1765,15 +1806,18 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        long ioaddr;
        int status;
        int work_done = max_interrupt_work;
-
-       spin_lock(&vp->lock);
        
        ioaddr = dev->base_addr;
+       spin_lock(&vp->lock);
+
        status = inw(ioaddr + EL3_STATUS);
 
        if (vortex_debug > 6)
                printk("vortex_interrupt(). status=0x%4x\n", status);
 
+       if ((status & IntLatch) == 0)
+               goto handler_exit;              /* No interrupt: shared IRQs cause this */
+
        if (status & IntReq) {
                status |= vp->deferred;
                vp->deferred = 0;
@@ -1785,6 +1829,7 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        if (vortex_debug > 4)
                printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
                           dev->name, status, inb(ioaddr + Timer));
+
        do {
                if (vortex_debug > 5)
                                printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
@@ -1841,9 +1886,6 @@ static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                }
                /* Acknowledge the IRQ. */
                outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-               if (vp->cb_fn_base)                     /* The PCMCIA people are idiots.  */
-                       writel(0x8000, vp->cb_fn_base + 4);
-
        } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
 
        if (vortex_debug > 4)
@@ -1866,14 +1908,22 @@ static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        int status;
        int work_done = max_interrupt_work;
 
-       spin_lock(&vp->lock);
-       
        ioaddr = dev->base_addr;
+
+       /*
+        * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
+        * and boomerang_start_xmit
+        */
+       spin_lock(&vp->lock);
+
        status = inw(ioaddr + EL3_STATUS);
 
        if (vortex_debug > 6)
                printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status);
 
+       if ((status & IntLatch) == 0)
+               goto handler_exit;              /* No interrupt: shared IRQs can cause this */
+
        if (status == 0xffff) {         /* AKPM: h/w no longer present (hotplug)? */
                if (vortex_debug > 1)
                        printk(KERN_DEBUG "boomerang_interrupt(1): status = 0xffff\n");
@@ -2120,6 +2170,8 @@ boomerang_rx(struct net_device *dev)
                                        printk(KERN_WARNING "%s: memory shortage\n", dev->name);
                                        last_jif = jiffies;
                                }
+                               if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)
+                                       mod_timer(&vp->rx_oom_timer, RUN_AT(HZ * 1));
                                break;                  /* Bad news!  */
                        }
                        skb->dev = dev;                 /* Mark as being used by this device. */
@@ -2133,6 +2185,26 @@ boomerang_rx(struct net_device *dev)
        return 0;
 }
 
+/*
+ * If we've hit a total OOM refilling the Rx ring we poll once a second
+ * for some memory.  Otherwise there is no way to restart the rx process.
+ */
+static void
+rx_oom_timer(unsigned long arg)
+{
+       struct net_device *dev = (struct net_device *)arg;
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+
+       spin_lock_irq(&vp->lock);
+       if ((vp->cur_rx - vp->dirty_rx) == RX_RING_SIZE)        /* This test is redundant, but makes me feel good */
+               boomerang_rx(dev);
+       if (vortex_debug > 1) {
+               printk(KERN_DEBUG "%s: rx_oom_timer %s\n", dev->name,
+                       ((vp->cur_rx - vp->dirty_rx) != RX_RING_SIZE) ? "succeeded" : "retrying");
+       }
+       spin_unlock_irq(&vp->lock);
+}
+
 static void
 vortex_down(struct net_device *dev)
 {
@@ -2141,6 +2213,7 @@ vortex_down(struct net_device *dev)
 
        netif_stop_queue (dev);
 
+       del_timer_sync(&vp->rx_oom_timer);
        del_timer_sync(&vp->timer);
 
        /* Turn off statistics ASAP.  We update vp->stats below. */
@@ -2311,16 +2384,13 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        u16 *data = (u16 *)&rq->ifr_data;
        int phy = vp->phys[0] & 0x1f;
        int retval;
-       unsigned long flags;
-
-       spin_lock_irqsave(&vp->lock, flags);
 
        switch(cmd) {
        case SIOCDEVPRIVATE:            /* Get the address of the PHY in use. */
                data[0] = phy;
        case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
                EL3WINDOW(4);
-               data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+               data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
                retval = 0;
                break;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
@@ -2328,7 +2398,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        retval = -EPERM;
                } else {
                        EL3WINDOW(4);
-                       mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+                       mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
                        retval = 0;
                }
                break;
@@ -2337,7 +2407,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                break;
        }
 
-       spin_unlock_irqrestore(&vp->lock, flags);
        return retval;
 }
 
@@ -2393,13 +2462,17 @@ static void mdio_sync(long ioaddr, int bits)
        }
 }
 
-static int mdio_read(long ioaddr, int phy_id, int location)
+static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
        int i;
+       long ioaddr = dev->base_addr;
        int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
        unsigned int retval = 0;
        long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
 
+       spin_lock_bh(&vp->mdio_lock);
+
        if (mii_preamble_required)
                mdio_sync(ioaddr, 32);
 
@@ -2419,15 +2492,20 @@ static int mdio_read(long ioaddr, int phy_id, int location)
                outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
                mdio_delay();
        }
+       spin_unlock_bh(&vp->mdio_lock);
        return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
 }
 
-static void mdio_write(long ioaddr, int phy_id, int location, int value)
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
+       struct vortex_private *vp = (struct vortex_private *)dev->priv;
+       long ioaddr = dev->base_addr;
        int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
        long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
        int i;
 
+       spin_lock_bh(&vp->mdio_lock);
+
        if (mii_preamble_required)
                mdio_sync(ioaddr, 32);
 
@@ -2446,7 +2524,7 @@ static void mdio_write(long ioaddr, int phy_id, int location, int value)
                outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
                mdio_delay();
        }
-
+       spin_unlock_bh(&vp->mdio_lock);
        return;
 }
 \f
@@ -2458,7 +2536,7 @@ static void acpi_set_WOL(struct net_device *dev)
        long ioaddr = dev->base_addr;
 
        /* AKPM: This kills the 905 */
-       if (vortex_debug > 0) {
+       if (vortex_debug > 1) {
                printk(KERN_INFO PFX "Wake-on-LAN functions disabled\n");
        }
        return;
@@ -2493,7 +2571,8 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev)
         */
        unregister_netdev(dev);
        outw(TotalReset, dev->base_addr + EL3_CMD);
-       release_region(dev->base_addr, vp->io_size);
+       if (vp->must_free_region)
+               release_region(dev->base_addr, vp->io_size);
        kfree(dev);
 }
 
@@ -2516,21 +2595,15 @@ static int __init vortex_init (void)
 {
        int rc;
        
-       rc = pci_module_init (&vortex_driver);
-       if (rc < 0)
-               goto out;
-
-       if (rc >= 0)    /* AKPM: had "> 0" */
+       rc = pci_module_init(&vortex_driver);
+       if (rc < 0) {
+               rc = vortex_eisa_init();
+               if (rc > 0)
+                       vortex_have_eisa = 1;
+       } else {
                vortex_have_pci = 1;
+       }
 
-       rc = vortex_eisa_init ();
-       if (rc < 0)
-               goto out;
-
-       if (rc > 0)
-               vortex_have_eisa = 1;
-
-out:
        return rc;
 }
 
@@ -2575,8 +2648,6 @@ module_exit(vortex_cleanup);
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  cardbus-compile-command: "gcc -DCONFIG_HOTPLUG -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/linux/pcmcia-cs-3.0.9/include/"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
index e1070f8f0e0057dcd05ccc17531bd2dfa0a85c17..4ad9683904cb5a615665a62251cc10d0a9d05d8d 100644 (file)
@@ -15,7 +15,9 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then
    dep_tristate '  SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA
    dep_tristate '  Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA
    dep_tristate '  COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA
-   dep_tristate '  IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA
+   if [ "$CONFIG_IBMTR" != "y" ]; then
+      dep_tristate '  IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA
+   fi
 
    if [ "$CONFIG_CARDBUS" = "y" ]; then
       tristate '  Xircom Tulip-like CardBus support' CONFIG_PCMCIA_XIRTULIP
index 39d278bb1828abf53db99eaf2fa02376fe9b2385..ad98ac40583f4d50e655a90045037fc84b22670e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.102 2000/06/30 10:18:35 davem Exp $
+/* $Id: sunlance.c,v 1.103 2000/08/12 19:23:38 anton Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *     Written 1995, 1996 by Miguel de Icaza
@@ -109,8 +109,6 @@ static char *lancestr = "LANCE";
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-#include <asm/machines.h>
-
 /* Define: 2^4 Tx buffers and 2^4 Rx buffers */
 #ifndef LANCE_LOG_TX_BUFFERS
 #define LANCE_LOG_TX_BUFFERS 4
index ce7bfa2b91b97a61fe56ebe887a629ad895f1935..5b13578e7ff4bc467f16d1a658faab2c2bf1853e 100644 (file)
@@ -9,7 +9,7 @@ SUB_DIRS     :=
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS) lmc
 
-O_TARGET := wan.a
+O_TARGET := wan.o
 
 export-objs =  z85230.o syncppp.o comx.o sdladrv.o cycx_drv.o
 list-multi =   wanpipe.o cyclomx.o
@@ -28,7 +28,7 @@ obj-$(CONFIG_HOSTESS_SV11)    += z85230.o     syncppp.o       hostess_sv11.o
 obj-$(CONFIG_SEALEVEL_4021)    += z85230.o     syncppp.o       sealevel.o
 obj-$(CONFIG_COMX)             +=                              comx.o
 obj-$(CONFIG_COMX_HW_COMX)     +=                              comx-hw-comx.o
-obj-$(CONFIG_COMX_HW_LOCOMX)   += cz85230.o    syncppp.o       comx-hw-locomx.o
+obj-$(CONFIG_COMX_HW_LOCOMX)   += z85230.o     syncppp.o       comx-hw-locomx.o
 obj-$(CONFIG_COMX_HW_MIXCOM)   +=                              comx-hw-mixcom.o
 obj-$(CONFIG_COMX_PROTO_PPP)   +=              syncppp.o       comx-proto-ppp.o
 obj-$(CONFIG_COMX_PROTO_LAPB)  +=                              comx-proto-lapb.o
index 207c9e21c4bb29ef5b78a2c9f76774b26840f3bf..0426143af5f2f000bb57dc1c2c45c0c70686460d 100644 (file)
@@ -101,7 +101,7 @@ static cycx_t *card_array = NULL;   /* adapter data space */
  *             < 0     error.
  * Context:    process
  */
-static int __init cyclomx_init (void)
+int __init cyclomx_init (void)
 {
        int cnt, err = 0;
 
index 09d6c9556e034c3fda10095f5899fd3682e94d75..4c7bf4bf466eb971bc1ddfda353459feab5dab19 100644 (file)
@@ -305,6 +305,7 @@ static struct sv11_device *sv11_init(int iobase, int irq)
        if(z8530_init(dev)!=0)
        {
                printk(KERN_ERR "Z8530 series device not found.\n");
+               restore_flags(flags);
                goto dmafail2;
        }
        z8530_channel_load(&dev->chanB, z8530_dead_port);
index f1a895e36da3ed211d10a1f96fac73c4d54855b2..2128a386e6b140d7c942dd849fe62c899b2719cb 100644 (file)
@@ -323,6 +323,7 @@ static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, i
        if(z8530_init(dev)!=0)
        {
                printk(KERN_ERR "Z8530 series device not found.\n");
+               restore_flags(flags);
                goto dmafail2;
        }
        if(dev->type==Z85C30)
index 36ecd489e435156309df805669f8325f6c360a1c..bda378365e53161d9b5d4b6ca59f59546c3d4469 100644 (file)
                10b7 3590  TokenLink Velocity XL Adapter
        4500  3c450 Cyclone/unknown
        5055  3c555 Laptop Hurricane
+       6055  3c556 Laptop Hurricane
        5057  3c575 [Megahertz] 10/100 LAN CardBus
                10b7 5a57  3C575 Megahertz 10/100 LAN Cardbus PC Card
        5157  3c575 [Megahertz] 10/100 LAN CardBus
        6100  VT85C100A [Rhine II]
        8231  VT8231 [PCI-to-ISA Bridge]
        8235  VT8235 Power Management
-       8305  VT8365 [KM133 AGP]
-       8391  VT8363/8371 [KT133/KX133 AGP] 
+       8305  VT8363/8365 [KT133/KM133 AGP]
+       8391  VT8371 [KX133 AGP] 
        8501  VT8501 [Apollo MVP4 AGP]
        8596  VT82C596 [Apollo PRO AGP]
        8597  VT82C597 [Apollo VP3 AGP]
index 640d9b21912aa774e9c6c43638562b15f6bdab39..c1725673664ddb13da184daf99f000d46e98e23c 100644 (file)
@@ -85,7 +85,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
    bool '      Persistent DMA buffers' CONFIG_SOUND_DMAP
 
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      dep_tristate '    AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND
+      dep_tristate '    AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND_OSS
    fi
    dep_tristate '    Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS
    dep_tristate '    Adlib Cards' CONFIG_SOUND_ADLIB $CONFIG_SOUND_OSS
index 8f4526013502bf00b9a0f9b587b732f0860ffcec..f79ec65cd01cb7025d41b5bddc30b8b418dff2bb 100644 (file)
 #ifndef _8010_H
 #define _8010_H
 
-/* ------------------- DEFINES -------------------- */
+#include <linux/types.h>
 
-#define EMUPAGESIZE    4096            /* don't change */
-#define RESERVED       0
-#define NUM_G          64              /* use all channels */
-#define NUM_FXSENDS    4               /* don't change */
-#define MAXPAGES        (32768 * NUM_G / EMUPAGESIZE)      /* WAVEOUT_MAXBUFSIZE * NUM_G / EMUPAGESIZE */
+/* ------------------- DEFINES -------------------- */
 
-#define TMEMSIZE       256*1024
-#define TMEMSIZEREG    4
+#define CMD_WRITEFN0           0x0
+#define CMD_READFN0            0x1
+#define CMD_WRITEPTR           0x2
+#define CMD_READPTR            0x3
+#define CMD_SETRECSRC          0x4
+#define CMD_GETRECSRC          0x5
+#define CMD_GETVOICEPARAM      0x6
+#define CMD_SETVOICEPARAM      0x7
 
-#define IP_TO_CP(ip) ((ip == 0) ? 0 : (((0x00001000uL | (ip & 0x00000FFFL)) << (((ip >> 12) & 0x000FL) + 4)) & 0xFFFF0000uL))
+struct mixer_private_ioctl {
+       u32 cmd;
+       u32 val[10];
+};
 
 /************************************************************************************************/
 /* PCI function 0 registers, address = <val> + PCIBASE0                                                */
 #define HCFG_AC3ENABLE_MASK    0x0x0000e0      /* AC3 async input control - Not implemented    */
 #define HCFG_AC3ENABLE_ZVIDEO  0x00000080      /* Channels 0 and 1 replace ZVIDEO              */
 #define HCFG_AC3ENABLE_CDSPDIF 0x00000040      /* Channels 0 and 1 replace CDSPDIF             */
+#define HCFG_AC3ENABLE_GPSPDIF  0x00000020      /* Channels 0 and 1 replace GPSPDIF             */
 #define HCFG_AUTOMUTE          0x00000010      /* When set, the async sample rate convertors   */
                                                /* will automatically mute their output when    */
                                                /* they are not rate-locked to the external     */
                                                /* async audio source                           */
 #define HCFG_LOCKSOUNDCACHE    0x00000008      /* 1 = Cancel bustmaster accesses to soundcache */
                                                /* NOTE: This should generally never be used.   */
-#define HCFG_LOCKTANKCACHE     0x00000004      /* 1 = Cancel bustmaster accesses to tankcache  */
+#define HCFG_LOCKTANKCACHE_MASK        0x00000004      /* 1 = Cancel bustmaster accesses to tankcache  */
                                                /* NOTE: This should generally never be used.   */
+#define HCFG_LOCKTANKCACHE     0x01020014
 #define HCFG_MUTEBUTTONENABLE  0x00000002      /* 1 = Master mute button sets AUDIOENABLE = 0. */
                                                /* NOTE: This is a 'cheap' way to implement a   */
                                                /* master mute function on the mute button, and */
 #define AC97_RECORDSELECT      0x1a
 #define AC97_RECORDGAIN                0x1c
 #define AC97_RECORDGAINMIC     0x1e
-#define AC97_GENERALPUPOSE     0x20
+#define AC97_GENERALPURPOSE    0x20
 #define AC97_3DCONTROL         0x22
 #define AC97_MODEMRATE         0x24
 #define AC97_POWERDOWN         0x26
 #define CCCA_CURRADDR          0x18000008
 
 #define CCR                    0x09            /* Cache control register                               */
-#define CCR_CACHEINVALIDSIZE   0xfe000000      /* Number of invalid samples cache for this channel     */
+#define CCR_CACHEINVALIDSIZE   0x07190009
+#define CCR_CACHEINVALIDSIZE_MASK      0xfe000000      /* Number of invalid samples cache for this channel     */
 #define CCR_CACHELOOPFLAG      0x01000000      /* 1 = Cache has a loop service pending                 */
 #define CCR_INTERLEAVEDSAMPLES 0x00800000      /* 1 = A cache service will fetch interleaved samples   */
 #define CCR_WORDSIZEDSAMPLES   0x00400000      /* 1 = A cache service will fetch word sized samples    */
+#define CCR_READADDRESS                0x06100009
 #define CCR_READADDRESS_MASK   0x003f0000      /* Location of cache just beyond current cache service  */
 #define CCR_LOOPINVALSIZE      0x0000fe00      /* Number of invalid samples in cache prior to loop     */
                                                /* NOTE: This is valid only if CACHELOOPFLAG is set     */
index 3f4d227f14933fd5fb12bc4c4b889e9b397dbd83..0ae31514085edfdc1bbd3921f91e8166623af507 100644 (file)
@@ -4,21 +4,19 @@
 
 ifeq ($(CONFIG_SOUND_EMU10K1),y)
     O_TARGET := emu10k1.o
-    O_OBJS = audio.o cardmi.o cardmo.o cardwi.o cardwo.o efxmgr.o \
+    O_OBJS = audio.o cardmi.o cardmo.o cardwi.o cardwo.o ecard.o \
              emuadxmg.o hwaccess.o irqmgr.o main.o midi.o mixer.o \
-             osutils.o recmgr.o timer.o voicemgr.o
+             recmgr.o timer.o voicemgr.o
 else
   ifeq ($(CONFIG_SOUND_EMU10K1),m)
     M_OBJS := emu10k1.o
     O_TARGET := emu10k1.o
-    O_OBJS = audio.o cardmi.o cardmo.o cardwi.o cardwo.o efxmgr.o \
+    O_OBJS = audio.o cardmi.o cardmo.o cardwi.o cardwo.o ecard.o \
              emuadxmg.o hwaccess.o irqmgr.o main.o midi.o mixer.o \
-             osutils.o recmgr.o timer.o voicemgr.o
+             recmgr.o timer.o voicemgr.o
   endif
 endif
 
-EXTRA_CFLAGS += -I.
-
 ifdef DEBUG
     EXTRA_CFLAGS += -DEMU10K1_DEBUG
 endif
index 4d81c1a464536564716382cb523cc119a947d84b..dca8d564d069d2b7753f256277eb31d09490ff5d 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     audio.c -- /dev/dsp interface for emu10k1 driver
  **********************************************************************
  */
 
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/malloc.h>
+#include <linux/version.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/wrapper.h>
+
+
 #include "hwaccess.h"
 #include "cardwo.h"
 #include "cardwi.h"
 #include "recmgr.h"
+#include "irqmgr.h"
 #include "audio.h"
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/wrapper.h>
 
 static void calculate_ofrag(struct woinst *);
 static void calculate_ifrag(struct wiinst *);
 
 /* Audio file operations */
-static loff_t emu10k1_audio_llseek(struct file *file, loff_t offset, int nOrigin)
+static loff_t emu10k1_audio_llseek(struct file *file, loff_t offset, int origin)
 {
        return -ESPIPE;
 }
@@ -53,11 +62,10 @@ static ssize_t emu10k1_audio_read(struct file *file, char *buffer, size_t count,
 {
        struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
        struct wiinst *wiinst = wave_dev->wiinst;
-       struct wave_in *wave_in;
        ssize_t ret = 0;
        unsigned long flags;
 
-       DPD(4, "emu10k1_audio_read(), buffer=%p, count=%x\n", buffer, (u32) count);
+       DPD(3, "emu10k1_audio_read(), buffer=%p, count=%d\n", buffer, (u32) count);
 
        if (ppos != &file->f_pos)
                return -ESPIPE;
@@ -67,23 +75,21 @@ static ssize_t emu10k1_audio_read(struct file *file, char *buffer, size_t count,
 
        spin_lock_irqsave(&wiinst->lock, flags);
 
-       if (wiinst->mapped) {
+       if (wiinst->mmapped) {
                spin_unlock_irqrestore(&wiinst->lock, flags);
                return -ENXIO;
        }
 
-       if (!wiinst->wave_in) {
+       if (wiinst->state == WAVE_STATE_CLOSED) {
                calculate_ifrag(wiinst);
 
-               while (emu10k1_wavein_open(wave_dev) != CTSTATUS_SUCCESS) {
+               while (emu10k1_wavein_open(wave_dev) < 0) {
                        spin_unlock_irqrestore(&wiinst->lock, flags);
 
                        if (file->f_flags & O_NONBLOCK)
                                return -EAGAIN;
 
-                       UP_INODE_SEM(&inode->i_sem);
                        interruptible_sleep_on(&wave_dev->card->open_wait);
-                       DOWN_INODE_SEM(&inode->i_sem);
 
                        if (signal_pending(current))
                                return -ERESTARTSYS;
@@ -92,26 +98,25 @@ static ssize_t emu10k1_audio_read(struct file *file, char *buffer, size_t count,
                }
        }
 
-       wave_in = wiinst->wave_in;
-
        spin_unlock_irqrestore(&wiinst->lock, flags);
 
        while (count > 0) {
-               u32 bytestocopy, dummy;
+               u32 bytestocopy;
 
                spin_lock_irqsave(&wiinst->lock, flags);
 
-               if ((wave_in->state != CARDWAVE_STATE_STARTED)
+               if (!(wiinst->state & WAVE_STATE_STARTED)
                    && (wave_dev->enablebits & PCM_ENABLE_INPUT))
                        emu10k1_wavein_start(wave_dev);
 
-               emu10k1_wavein_getxfersize(wave_in, &bytestocopy, &dummy);
+               emu10k1_wavein_update(wave_dev->card, wiinst);
+               emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
 
                spin_unlock_irqrestore(&wiinst->lock, flags);
 
-               DPD(4, "bytestocopy --> %x\n", bytestocopy);
+               DPD(3, "bytestocopy --> %d\n", bytestocopy);
 
-               if ((bytestocopy >= wiinst->fragment_size)
+               if ((bytestocopy >= wiinst->buffer.fragment_size)
                    || (bytestocopy >= count)) {
                        bytestocopy = min(bytestocopy, count);
 
@@ -127,9 +132,7 @@ static ssize_t emu10k1_audio_read(struct file *file, char *buffer, size_t count,
                            || (!(wave_dev->enablebits & PCM_ENABLE_INPUT)))
                                return (ret ? ret : -EAGAIN);
 
-                       UP_INODE_SEM(&inode->i_sem);
                        interruptible_sleep_on(&wiinst->wait_queue);
-                       DOWN_INODE_SEM(&inode->i_sem);
 
                        if (signal_pending(current))
                                return (ret ? ret : -ERESTARTSYS);
@@ -137,7 +140,7 @@ static ssize_t emu10k1_audio_read(struct file *file, char *buffer, size_t count,
                }
        }
 
-       DPD(4, "bytes copied -> %x\n", (u32) ret);
+       DPD(3, "bytes copied -> %d\n", (u32) ret);
 
        return ret;
 }
@@ -146,13 +149,10 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t
 {
        struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
        struct woinst *woinst = wave_dev->woinst;
-       struct wave_out *wave_out;
        ssize_t ret;
        unsigned long flags;
 
-       GET_INODE_STRUCT();
-
-       DPD(4, "emu10k1_audio_write(), buffer=%p, count=%x\n", buffer, (u32) count);
+       DPD(3, "emu10k1_audio_write(), buffer=%p, count=%d\n", buffer, (u32) count);
 
        if (ppos != &file->f_pos)
                return -ESPIPE;
@@ -162,23 +162,21 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t
 
        spin_lock_irqsave(&woinst->lock, flags);
 
-       if (woinst->mapped) {
+       if (woinst->mmapped) {
                spin_unlock_irqrestore(&woinst->lock, flags);
                return -ENXIO;
        }
 
-       if (!woinst->wave_out) {
+       if (woinst->state == WAVE_STATE_CLOSED) {
                calculate_ofrag(woinst);
 
-               while (emu10k1_waveout_open(wave_dev) != CTSTATUS_SUCCESS) {
+               while (emu10k1_waveout_open(wave_dev) < 0) {
                        spin_unlock_irqrestore(&woinst->lock, flags);
 
                        if (file->f_flags & O_NONBLOCK)
                                return -EAGAIN;
 
-                       UP_INODE_SEM(&inode->i_sem);
                        interruptible_sleep_on(&wave_dev->card->open_wait);
-                       DOWN_INODE_SEM(&inode->i_sem);
 
                        if (signal_pending(current))
                                return -ERESTARTSYS;
@@ -187,23 +185,20 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t
                }
        }
 
-       wave_out = woinst->wave_out;
-
        spin_unlock_irqrestore(&woinst->lock, flags);
 
        ret = 0;
        while (count > 0) {
-               u32 bytestocopy, pending, dummy;
+               u32 bytestocopy;
 
                spin_lock_irqsave(&woinst->lock, flags);
-
-               emu10k1_waveout_getxfersize(wave_out, &bytestocopy, &pending, &dummy);
-
+               emu10k1_waveout_update(woinst);
+               emu10k1_waveout_getxfersize(woinst, &bytestocopy);
                spin_unlock_irqrestore(&woinst->lock, flags);
 
-               DPD(4, "bytestocopy --> %x\n", bytestocopy);
+               DPD(3, "bytestocopy --> %d\n", bytestocopy);
 
-               if ((bytestocopy >= woinst->fragment_size)
+               if ((bytestocopy >= woinst->buffer.fragment_size)
                    || (bytestocopy >= count)) {
 
                        bytestocopy = min(bytestocopy, count);
@@ -217,16 +212,11 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t
                        spin_lock_irqsave(&woinst->lock, flags);
                        woinst->total_copied += bytestocopy;
 
-                       if ((wave_out->state != CARDWAVE_STATE_STARTED)
+                       if (!(woinst->state & WAVE_STATE_STARTED)
                            && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
-                           && (woinst->total_copied >= woinst->fragment_size)) {
+                           && (woinst->total_copied >= woinst->buffer.fragment_size))
+                               emu10k1_waveout_start(wave_dev);
 
-                               if (emu10k1_waveout_start(wave_dev) != CTSTATUS_SUCCESS) {
-                                       spin_unlock_irqrestore(&woinst->lock, flags);
-                                       ERROR();
-                                       return -EFAULT;
-                               }
-                       }
                        spin_unlock_irqrestore(&woinst->lock, flags);
                }
 
@@ -235,16 +225,14 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t
                            || (!(wave_dev->enablebits & PCM_ENABLE_OUTPUT)))
                                return (ret ? ret : -EAGAIN);
 
-                       UP_INODE_SEM(&inode->i_sem);
                        interruptible_sleep_on(&woinst->wait_queue);
-                       DOWN_INODE_SEM(&inode->i_sem);
 
                        if (signal_pending(current))
                                return (ret ? ret : -ERESTARTSYS);
                }
        }
 
-       DPD(4, "bytes copied -> %x\n", (u32) ret);
+       DPD(3, "bytes copied -> %d\n", (u32) ret);
 
        return ret;
 }
@@ -252,29 +240,19 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t
 static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data;
-       int val = 0;
        struct woinst *woinst = NULL;
-       struct wave_out *wave_out = NULL;
        struct wiinst *wiinst = NULL;
-       struct wave_in *wave_in = NULL;
-       u32 pending, bytestocopy, dummy;
+       int val = 0;
+       u32 bytestocopy;
        unsigned long flags;
 
        DPF(4, "emu10k1_audio_ioctl()\n");
 
-       if (file->f_mode & FMODE_WRITE) {
+       if (file->f_mode & FMODE_WRITE)
                woinst = wave_dev->woinst;
-               spin_lock_irqsave(&woinst->lock, flags);
-               wave_out = woinst->wave_out;
-               spin_unlock_irqrestore(&woinst->lock, flags);
-       }
 
-       if (file->f_mode & FMODE_READ) {
+       if (file->f_mode & FMODE_READ)
                wiinst = wave_dev->wiinst;
-               spin_lock_irqsave(&wiinst->lock, flags);
-               wave_in = wiinst->wave_in;
-               spin_unlock_irqrestore(&wiinst->lock, flags);
-       }
 
        switch (cmd) {
        case OSS_GETVERSION:
@@ -288,13 +266,22 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                if (file->f_mode & FMODE_WRITE) {
                        spin_lock_irqsave(&woinst->lock, flags);
 
-                       if (wave_out)
+                       if (woinst->state & WAVE_STATE_OPEN) {
+                               if (woinst->mmapped) {
+                                       int i;
+
+                                       /* Undo marking the pages as reserved */
+                                       for (i = 0; i < woinst->buffer.pages; i++)
+                                               mem_map_reserve(virt_to_page(woinst->buffer.addr[i]));
+                               }
+
                                emu10k1_waveout_close(wave_dev);
+                       }
 
+                       woinst->mmapped = 0;
                        woinst->total_copied = 0;
                        woinst->total_played = 0;
                        woinst->blocks = 0;
-                       woinst->curpos = 0;
 
                        spin_unlock_irqrestore(&woinst->lock, flags);
                }
@@ -302,12 +289,12 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                if (file->f_mode & FMODE_READ) {
                        spin_lock_irqsave(&wiinst->lock, flags);
 
-                       if (wave_in)
+                       if (wiinst->state & WAVE_STATE_OPEN)
                                emu10k1_wavein_close(wave_dev);
 
+                       wiinst->mmapped = 0;
                        wiinst->total_recorded = 0;
                        wiinst->blocks = 0;
-                       wiinst->curpos = 0;
                        spin_unlock_irqrestore(&wiinst->lock, flags);
                }
 
@@ -318,10 +305,11 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                if (file->f_mode & FMODE_WRITE) {
 
-                       if (wave_out) {
-                               spin_lock_irqsave(&woinst->lock, flags);
+                       spin_lock_irqsave(&woinst->lock, flags);
+
+                       if (woinst->state & WAVE_STATE_OPEN) {
 
-                               if (wave_out->state == CARDWAVE_STATE_STARTED)
+                               if (woinst->state & WAVE_STATE_STARTED)
                                        while ((woinst->total_played < woinst->total_copied)
                                               && !signal_pending(current)) {
                                                spin_unlock_irqrestore(&woinst->lock, flags);
@@ -329,25 +317,34 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                                                spin_lock_irqsave(&woinst->lock, flags);
                                        }
 
-                               emu10k1_waveout_close(wave_dev);
-                               woinst->total_copied = 0;
-                               woinst->total_played = 0;
-                               woinst->blocks = 0;
-                               woinst->curpos = 0;
+                               if (woinst->mmapped) {
+                                       int i;
 
-                               spin_unlock_irqrestore(&woinst->lock, flags);
+                                       /* Undo marking the pages as reserved */
+                                       for (i = 0; i < woinst->buffer.pages; i++)
+                                               mem_map_reserve(virt_to_page(woinst->buffer.addr[i]));
+                               }
+
+                               emu10k1_waveout_close(wave_dev);
                        }
+
+                       woinst->mmapped = 0;
+                       woinst->total_copied = 0;
+                       woinst->total_played = 0;
+                       woinst->blocks = 0;
+
+                       spin_unlock_irqrestore(&woinst->lock, flags);
                }
 
                if (file->f_mode & FMODE_READ) {
                        spin_lock_irqsave(&wiinst->lock, flags);
 
-                       if (wave_in)
+                       if (wiinst->state & WAVE_STATE_OPEN)
                                emu10k1_wavein_close(wave_dev);
 
+                       wiinst->mmapped = 0;
                        wiinst->total_recorded = 0;
                        wiinst->blocks = 0;
-                       wiinst->curpos = 0;
                        spin_unlock_irqrestore(&wiinst->lock, flags);
                }
 
@@ -367,43 +364,49 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                get_user_ret(val, (int *) arg, -EFAULT);
                DPD(2, "val is %d\n", val);
 
-               if (val >= 0) {
-                       if (file->f_mode & FMODE_WRITE) {
-                               spin_lock_irqsave(&woinst->lock, flags);
+               if (val > 0) {
+                       if (file->f_mode & FMODE_READ) {
+                               struct wave_format format;
 
-                               woinst->wave_fmt.samplingrate = val;
+                               spin_lock_irqsave(&wiinst->lock, flags);
+
+                               format = wiinst->format;
+                               format.samplingrate = val;
 
-                               if (emu10k1_waveout_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                               if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
                                        return -EINVAL;
 
-                               val = woinst->wave_fmt.samplingrate;
+                               val = wiinst->format.samplingrate;
 
-                               spin_unlock_irqrestore(&woinst->lock, flags);
+                               spin_unlock_irqrestore(&wiinst->lock, flags);
 
-                               DPD(2, "set playback sampling rate -> %d\n", val);
+                               DPD(2, "set recording sampling rate -> %d\n", val);
                        }
 
-                       if (file->f_mode & FMODE_READ) {
-                               spin_lock_irqsave(&wiinst->lock, flags);
+                       if (file->f_mode & FMODE_WRITE) {
+                               struct wave_format format;
+
+                               spin_lock_irqsave(&woinst->lock, flags);
 
-                               wiinst->wave_fmt.samplingrate = val;
+                               format = woinst->format;
+                               format.samplingrate = val;
 
-                               if (emu10k1_wavein_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                               if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
                                        return -EINVAL;
 
-                               val = wiinst->wave_fmt.samplingrate;
+                               val = woinst->format.samplingrate;
 
-                               spin_unlock_irqrestore(&wiinst->lock, flags);
+                               spin_unlock_irqrestore(&woinst->lock, flags);
 
-                               DPD(2, "set recording sampling rate -> %d\n", val);
+                               DPD(2, "set playback sampling rate -> %d\n", val);
                        }
 
                        return put_user(val, (int *) arg);
                } else {
                        if (file->f_mode & FMODE_READ)
-                               val = wiinst->wave_fmt.samplingrate;
+                               val = wiinst->format.samplingrate;
                        else if (file->f_mode & FMODE_WRITE)
-                               val = woinst->wave_fmt.samplingrate;
+                               val = woinst->format.samplingrate;
 
                        return put_user(val, (int *) arg);
                }
@@ -415,33 +418,39 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                get_user_ret(val, (int *) arg, -EFAULT);
                DPD(2, " val is %d\n", val);
 
-               if (file->f_mode & FMODE_WRITE) {
-                       spin_lock_irqsave(&woinst->lock, flags);
+               if (file->f_mode & FMODE_READ) {
+                       struct wave_format format;
 
-                       woinst->wave_fmt.channels = val ? 2 : 1;
+                       spin_lock_irqsave(&wiinst->lock, flags);
 
-                       if (emu10k1_waveout_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                       format = wiinst->format;
+                       format.channels = val ? 2 : 1;
+
+                       if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
                                return -EINVAL;
 
-                       val = woinst->wave_fmt.channels - 1;
+                       val = wiinst->format.channels - 1;
 
-                       spin_unlock_irqrestore(&woinst->lock, flags);
-
-                       DPD(2, "set playback stereo -> %d\n", val);
+                       spin_unlock_irqrestore(&wiinst->lock, flags);
+                       DPD(2, "set recording stereo -> %d\n", val);
                }
 
-               if (file->f_mode & FMODE_READ) {
-                       spin_lock_irqsave(&wiinst->lock, flags);
+               if (file->f_mode & FMODE_WRITE) {
+                       struct wave_format format;
+
+                       spin_lock_irqsave(&woinst->lock, flags);
 
-                       wiinst->wave_fmt.channels = val ? 2 : 1;
+                       format = woinst->format;
+                       format.channels = val ? 2 : 1;
 
-                       if (emu10k1_wavein_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                       if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
                                return -EINVAL;
 
-                       val = wiinst->wave_fmt.channels - 1;
+                       val = woinst->format.channels - 1;
 
-                       spin_unlock_irqrestore(&wiinst->lock, flags);
-                       DPD(2, "set recording stereo -> %d\n", val);
+                       spin_unlock_irqrestore(&woinst->lock, flags);
+
+                       DPD(2, "set playback stereo -> %d\n", val);
                }
 
                return put_user(val, (int *) arg);
@@ -454,41 +463,47 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                get_user_ret(val, (int *) arg, -EFAULT);
                DPD(2, " val is %d\n", val);
 
-               if (val != 0) {
-                       if (file->f_mode & FMODE_WRITE) {
-                               spin_lock_irqsave(&woinst->lock, flags);
+               if (val > 0) {
+                       if (file->f_mode & FMODE_READ) {
+                               struct wave_format format;
+
+                               spin_lock_irqsave(&wiinst->lock, flags);
 
-                               woinst->wave_fmt.channels = val;
+                               format = wiinst->format;
+                               format.channels = val;
 
-                               if (emu10k1_waveout_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                               if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
                                        return -EINVAL;
 
-                               val = woinst->wave_fmt.channels;
+                               val = wiinst->format.channels;
 
-                               spin_unlock_irqrestore(&woinst->lock, flags);
-                               DPD(2, "set playback number of channels -> %d\n", val);
+                               spin_unlock_irqrestore(&wiinst->lock, flags);
+                               DPD(2, "set recording number of channels -> %d\n", val);
                        }
 
-                       if (file->f_mode & FMODE_READ) {
-                               spin_lock_irqsave(&wiinst->lock, flags);
+                       if (file->f_mode & FMODE_WRITE) {
+                               struct wave_format format;
+
+                               spin_lock_irqsave(&woinst->lock, flags);
 
-                               wiinst->wave_fmt.channels = val;
+                               format = woinst->format;
+                               format.channels = val;
 
-                               if (emu10k1_wavein_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                               if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
                                        return -EINVAL;
 
-                               val = wiinst->wave_fmt.channels;
+                               val = woinst->format.channels;
 
-                               spin_unlock_irqrestore(&wiinst->lock, flags);
-                               DPD(2, "set recording number of channels -> %d\n", val);
+                               spin_unlock_irqrestore(&woinst->lock, flags);
+                               DPD(2, "set playback number of channels -> %d\n", val);
                        }
 
                        return put_user(val, (int *) arg);
                } else {
                        if (file->f_mode & FMODE_READ)
-                               val = wiinst->wave_fmt.channels;
+                               val = wiinst->format.channels;
                        else if (file->f_mode & FMODE_WRITE)
-                               val = woinst->wave_fmt.channels;
+                               val = woinst->format.channels;
 
                        return put_user(val, (int *) arg);
                }
@@ -511,40 +526,46 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                DPD(2, " val is %d\n", val);
 
                if (val != AFMT_QUERY) {
-                       if (file->f_mode & FMODE_WRITE) {
-                               spin_lock_irqsave(&woinst->lock, flags);
+                       if (file->f_mode & FMODE_READ) {
+                               struct wave_format format;
+
+                               spin_lock_irqsave(&wiinst->lock, flags);
 
-                               woinst->wave_fmt.bitsperchannel = val;
+                               format = wiinst->format;
+                               format.bitsperchannel = val;
 
-                               if (emu10k1_waveout_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                               if (emu10k1_wavein_setformat(wave_dev, &format) < 0)
                                        return -EINVAL;
 
-                               val = woinst->wave_fmt.bitsperchannel;
+                               val = wiinst->format.bitsperchannel;
 
-                               spin_unlock_irqrestore(&woinst->lock, flags);
-                               DPD(2, "set playback sample size -> %d\n", val);
+                               spin_unlock_irqrestore(&wiinst->lock, flags);
+                               DPD(2, "set recording sample size -> %d\n", val);
                        }
 
-                       if (file->f_mode & FMODE_READ) {
-                               spin_lock_irqsave(&wiinst->lock, flags);
+                       if (file->f_mode & FMODE_WRITE) {
+                               struct wave_format format;
 
-                               wiinst->wave_fmt.bitsperchannel = val;
+                               spin_lock_irqsave(&woinst->lock, flags);
 
-                               if (emu10k1_wavein_setformat(wave_dev) != CTSTATUS_SUCCESS)
+                               format = woinst->format;
+                               format.bitsperchannel = val;
+
+                               if (emu10k1_waveout_setformat(wave_dev, &format) < 0)
                                        return -EINVAL;
 
-                               val = wiinst->wave_fmt.bitsperchannel;
+                               val = woinst->format.bitsperchannel;
 
-                               spin_unlock_irqrestore(&wiinst->lock, flags);
-                               DPD(2, "set recording sample size -> %d\n", val);
+                               spin_unlock_irqrestore(&woinst->lock, flags);
+                               DPD(2, "set playback sample size -> %d\n", val);
                        }
 
                        return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg);
                } else {
                        if (file->f_mode & FMODE_READ)
-                               val = wiinst->wave_fmt.bitsperchannel;
+                               val = wiinst->format.bitsperchannel;
                        else if (file->f_mode & FMODE_WRITE)
-                               val = woinst->wave_fmt.bitsperchannel;
+                               val = woinst->format.bitsperchannel;
 
                        return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg);
                }
@@ -553,27 +574,27 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
        case SOUND_PCM_READ_BITS:
 
                if (file->f_mode & FMODE_READ)
-                       val = wiinst->wave_fmt.bitsperchannel;
+                       val = wiinst->format.bitsperchannel;
                else if (file->f_mode & FMODE_WRITE)
-                       val = woinst->wave_fmt.bitsperchannel;
+                       val = woinst->format.bitsperchannel;
 
                return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg);
 
        case SOUND_PCM_READ_RATE:
 
                if (file->f_mode & FMODE_READ)
-                       val = wiinst->wave_fmt.samplingrate;
+                       val = wiinst->format.samplingrate;
                else if (file->f_mode & FMODE_WRITE)
-                       val = woinst->wave_fmt.samplingrate;
+                       val = woinst->format.samplingrate;
 
                return put_user(val, (int *) arg);
 
        case SOUND_PCM_READ_CHANNELS:
 
                if (file->f_mode & FMODE_READ)
-                       val = wiinst->wave_fmt.channels;
+                       val = wiinst->format.channels;
                else if (file->f_mode & FMODE_WRITE)
-                       val = woinst->wave_fmt.channels;
+                       val = woinst->format.channels;
 
                return put_user(val, (int *) arg);
 
@@ -594,6 +615,7 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT))
                        val |= PCM_ENABLE_OUTPUT;
+
                if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT))
                        val |= PCM_ENABLE_INPUT;
 
@@ -609,11 +631,11 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                        if (val & PCM_ENABLE_OUTPUT) {
                                wave_dev->enablebits |= PCM_ENABLE_OUTPUT;
-                               if (wave_out)
+                               if (woinst->state & WAVE_STATE_OPEN)
                                        emu10k1_waveout_start(wave_dev);
                        } else {
                                wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT;
-                               if (wave_out)
+                               if (woinst->state & WAVE_STATE_STARTED)
                                        emu10k1_waveout_stop(wave_dev);
                        }
 
@@ -625,11 +647,11 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                        if (val & PCM_ENABLE_INPUT) {
                                wave_dev->enablebits |= PCM_ENABLE_INPUT;
-                               if (wave_in)
+                               if (wiinst->state & WAVE_STATE_OPEN)
                                        emu10k1_wavein_start(wave_dev);
                        } else {
                                wave_dev->enablebits &= ~PCM_ENABLE_INPUT;
-                               if (wave_in)
+                               if (wiinst->state & WAVE_STATE_STARTED)
                                        emu10k1_wavein_stop(wave_dev);
                        }
 
@@ -646,23 +668,21 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                        if (!(file->f_mode & FMODE_WRITE))
                                return -EINVAL;
 
-                       if (wave_out) {
-                               spin_lock_irqsave(&woinst->lock, flags);
-                               emu10k1_waveout_getxfersize(wave_out, &bytestocopy, &pending, &dummy);
-                               spin_unlock_irqrestore(&woinst->lock, flags);
+                       spin_lock_irqsave(&woinst->lock, flags);
 
+                       if (woinst->state & WAVE_STATE_OPEN) {
+                               emu10k1_waveout_update(woinst);
+                               emu10k1_waveout_getxfersize(woinst, &bytestocopy);
                                info.bytes = bytestocopy;
                        } else {
-                               spin_lock_irqsave(&woinst->lock, flags);
                                calculate_ofrag(woinst);
-                               spin_unlock_irqrestore(&woinst->lock, flags);
-
-                               info.bytes = woinst->numfrags * woinst->fragment_size;
+                               info.bytes = woinst->buffer.size;
                        }
+                       spin_unlock_irqrestore(&woinst->lock, flags);
 
-                       info.fragstotal = woinst->numfrags;
-                       info.fragments = info.bytes / woinst->fragment_size;
-                       info.fragsize = woinst->fragment_size;
+                       info.fragstotal = woinst->buffer.numfrags;
+                       info.fragments = info.bytes / woinst->buffer.fragment_size;
+                       info.fragsize = woinst->buffer.fragment_size;
 
                        if (copy_to_user((int *) arg, &info, sizeof(info)))
                                return -EFAULT;
@@ -678,23 +698,20 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                        if (!(file->f_mode & FMODE_READ))
                                return -EINVAL;
 
-                       if (wave_in) {
-                               spin_lock_irqsave(&wiinst->lock, flags);
-                               emu10k1_wavein_getxfersize(wave_in, &bytestocopy, &dummy);
-                               spin_unlock_irqrestore(&wiinst->lock, flags);
-
+                       spin_lock_irqsave(&wiinst->lock, flags);
+                       if (wiinst->state & WAVE_STATE_OPEN) {
+                               emu10k1_wavein_update(wave_dev->card, wiinst);
+                               emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
                                info.bytes = bytestocopy;
                        } else {
-                               spin_lock_irqsave(&wiinst->lock, flags);
                                calculate_ifrag(wiinst);
-                               spin_unlock_irqrestore(&wiinst->lock, flags);
-
                                info.bytes = 0;
                        }
+                       spin_unlock_irqrestore(&wiinst->lock, flags);
 
-                       info.fragstotal = wiinst->numfrags;
-                       info.fragments = info.bytes / wiinst->fragment_size;
-                       info.fragsize = wiinst->fragment_size;
+                       info.fragstotal = wiinst->buffer.numfrags;
+                       info.fragments = info.bytes / wiinst->buffer.fragment_size;
+                       info.fragsize = wiinst->buffer.fragment_size;
 
                        if (copy_to_user((int *) arg, &info, sizeof(info)))
                                return -EFAULT;
@@ -713,15 +730,16 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
 
-               if (wave_out) {
-                       spin_lock_irqsave(&woinst->lock, flags);
-                       emu10k1_waveout_getxfersize(wave_out, &bytestocopy, &pending, &dummy);
-                       spin_unlock_irqrestore(&woinst->lock, flags);
-
-                       val = pending;
+               spin_lock_irqsave(&woinst->lock, flags);
+               if (woinst->state & WAVE_STATE_OPEN) {
+                       emu10k1_waveout_update(woinst);
+                       emu10k1_waveout_getxfersize(woinst, &bytestocopy);
+                       val = woinst->buffer.size - bytestocopy;
                } else
                        val = 0;
 
+               spin_unlock_irqrestore(&woinst->lock, flags);
+
                return put_user(val, (int *) arg);
 
        case SNDCTL_DSP_GETIPTR:
@@ -735,17 +753,16 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                        spin_lock_irqsave(&wiinst->lock, flags);
 
-                       if (wave_in) {
-                               emu10k1_wavein_getcontrol(wave_in, WAVECURPOS, (u32 *) & cinfo.ptr);
-                               cinfo.bytes =
-                                   cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % (wiinst->fragment_size * wiinst->numfrags);
-                               cinfo.blocks = cinfo.bytes / wiinst->fragment_size - wiinst->blocks;
-                               wiinst->blocks = cinfo.bytes / wiinst->fragment_size;
+                       if (wiinst->state & WAVE_STATE_OPEN) {
+                               emu10k1_wavein_update(wave_dev->card, wiinst);
+                               cinfo.ptr = wiinst->buffer.hw_pos;
+                               cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size;
+                               cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks;
+                               wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size;
                        } else {
                                cinfo.ptr = 0;
                                cinfo.bytes = 0;
                                cinfo.blocks = 0;
-                               wiinst->blocks = 0;
                        }
 
                        spin_unlock_irqrestore(&wiinst->lock, flags);
@@ -766,17 +783,19 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                        spin_lock_irqsave(&woinst->lock, flags);
 
-                       if (wave_out) {
-                               emu10k1_waveout_getcontrol(wave_out, WAVECURPOS, (u32 *) & cinfo.ptr);
-                               cinfo.bytes = cinfo.ptr + woinst->total_played - woinst->total_played % (woinst->fragment_size * woinst->numfrags);
-                               cinfo.blocks = cinfo.bytes / woinst->fragment_size - woinst->blocks;
-                               woinst->blocks = cinfo.bytes / woinst->fragment_size;
+                       if (woinst->state & WAVE_STATE_OPEN) {
+                               emu10k1_waveout_update(woinst);
+                               cinfo.ptr = woinst->buffer.hw_pos;
+                               cinfo.bytes = cinfo.ptr + woinst->total_played - woinst->total_played % woinst->buffer.size;
+                               cinfo.blocks = cinfo.bytes / woinst->buffer.fragment_size - woinst->blocks;
+                               woinst->blocks = cinfo.bytes / woinst->buffer.fragment_size;
                        } else {
                                cinfo.ptr = 0;
                                cinfo.bytes = 0;
                                cinfo.blocks = 0;
-                               woinst->blocks = 0;
                        }
+                       if(woinst->mmapped)
+                               woinst->buffer.bytestocopy %= woinst->buffer.fragment_size;
 
                        spin_unlock_irqrestore(&woinst->lock, flags);
 
@@ -792,7 +811,7 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                        spin_lock_irqsave(&woinst->lock, flags);
 
                        calculate_ofrag(woinst);
-                       val = woinst->fragment_size;
+                       val = woinst->buffer.fragment_size;
 
                        spin_unlock_irqrestore(&woinst->lock, flags);
                }
@@ -801,7 +820,7 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                        spin_lock_irqsave(&wiinst->lock, flags);
 
                        calculate_ifrag(wiinst);
-                       val = wiinst->fragment_size;
+                       val = wiinst->buffer.fragment_size;
 
                        spin_unlock_irqrestore(&wiinst->lock, flags);
                }
@@ -811,7 +830,17 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                break;
 
        case SNDCTL_DSP_POST:
-               DPF(2, "SNDCTL_DSP_POST: not implemented\n");
+               if (file->f_mode & FMODE_WRITE) {
+                       spin_lock_irqsave(&woinst->lock, flags);
+
+                       if (!(woinst->state & WAVE_STATE_STARTED)
+                           && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)
+                           && (woinst->total_copied > 0))
+                               emu10k1_waveout_start(wave_dev);
+
+                       spin_unlock_irqrestore(&woinst->lock, flags);
+               }
+
                break;
 
        case SNDCTL_DSP_SUBDIVIDE:
@@ -823,25 +852,25 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
 
                get_user_ret(val, (int *) arg, -EFAULT);
 
-               DPD(2, "val is %x\n", val);
+               DPD(2, "val is 0x%x\n", val);
 
                if (val == 0)
                        return -EIO;
 
                if (file->f_mode & FMODE_WRITE) {
-                       if (wave_out)
+                       if (woinst->state & WAVE_STATE_OPEN)
                                return -EINVAL; /* too late to change */
 
-                       woinst->ossfragshift = val & 0xffff;
-                       woinst->numfrags = (val >> 16) & 0xffff;
+                       woinst->buffer.ossfragshift = val & 0xffff;
+                       woinst->buffer.numfrags = (val >> 16) & 0xffff;
                }
 
                if (file->f_mode & FMODE_READ) {
-                       if (wave_in)
+                       if (wiinst->state & WAVE_STATE_OPEN)
                                return -EINVAL; /* too late to change */
 
-                       wiinst->ossfragshift = val & 0xffff;
-                       wiinst->numfrags = (val >> 16) & 0xffff;
+                       wiinst->buffer.ossfragshift = val & 0xffff;
+                       wiinst->buffer.numfrags = (val >> 16) & 0xffff;
                }
 
                break;
@@ -859,15 +888,15 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                        if ((buf.command != 1) && (buf.command != 2))
                                return -EINVAL;
 
-                       if (((buf.offs < 0x100) && (buf.command == 2))
+                       if ((buf.offs < 0x100)
                            || (buf.offs < 0x000)
                            || (buf.offs + buf.len > 0x800) || (buf.len > 1000))
                                return -EINVAL;
 
                        if (buf.command == 1) {
                                for (i = 0; i < buf.len; i++)
-
                                        ((u32 *) buf.data)[i] = sblive_readptr(wave_dev->card, buf.offs + i, 0);
+
                                if (copy_to_user((copr_buffer *) arg, &buf, sizeof(buf)))
                                        return -EFAULT;
                        } else {
@@ -878,7 +907,7 @@ static int emu10k1_audio_ioctl(struct inode *inode, struct file *file, unsigned
                }
 
        default:                /* Default is unrecognized command */
-               DPD(2, "default: %x\n", cmd);
+               DPD(2, "default: 0x%x\n", cmd);
                return -EINVAL;
        }
        return 0;
@@ -894,51 +923,46 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
                return -ENXIO;
 
        lock_kernel();
+
        if (vma->vm_flags & VM_WRITE) {
                struct woinst *woinst = wave_dev->woinst;
-               struct wave_out *wave_out;
                u32 size;
                unsigned long flags;
                int i;
 
                spin_lock_irqsave(&woinst->lock, flags);
 
-               wave_out = woinst->wave_out;
-
-               if (!wave_out) {
+               if (woinst->state == WAVE_STATE_CLOSED) {
                        calculate_ofrag(woinst);
 
-                       if (emu10k1_waveout_open(wave_dev) != CTSTATUS_SUCCESS) {
+                       if (emu10k1_waveout_open(wave_dev) < 0) {
                                spin_unlock_irqrestore(&woinst->lock, flags);
                                ERROR();
                                unlock_kernel();
                                return -EINVAL;
                        }
 
-                       wave_out = woinst->wave_out;
-
                        /* Now mark the pages as reserved, otherwise remap_page_range doesn't do what we want */
-                       for (i = 0; i < wave_out->wavexferbuf->numpages; i++)
-                               mem_map_reserve(virt_to_page(wave_out->pagetable[i]));
+                       for (i = 0; i < woinst->buffer.pages; i++)
+                               mem_map_reserve(virt_to_page(woinst->buffer.addr[i]));
                }
 
                size = vma->vm_end - vma->vm_start;
 
-               if (size > (PAGE_SIZE * wave_out->wavexferbuf->numpages)) {
+               if (size > (PAGE_SIZE * woinst->buffer.pages)) {
                        spin_unlock_irqrestore(&woinst->lock, flags);
                        unlock_kernel();
                        return -EINVAL;
                }
 
-               for (i = 0; i < wave_out->wavexferbuf->numpages; i++) {
-                       if (remap_page_range(vma->vm_start + (i * PAGE_SIZE), virt_to_phys(wave_out->pagetable[i]), PAGE_SIZE, vma->vm_page_prot)) {
+               for (i = 0; i < woinst->buffer.pages; i++) {
+                       if (remap_page_range(vma->vm_start + (i * PAGE_SIZE), virt_to_phys(woinst->buffer.addr[i]), PAGE_SIZE, vma->vm_page_prot)) {
                                spin_unlock_irqrestore(&woinst->lock, flags);
-                               unlock_kernel();
                                return -EAGAIN;
                        }
                }
 
-               woinst->mapped = 1;
+               woinst->mmapped = 1;
 
                spin_unlock_irqrestore(&woinst->lock, flags);
        }
@@ -948,9 +972,10 @@ static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma)
                unsigned long flags;
 
                spin_lock_irqsave(&wiinst->lock, flags);
-               wiinst->mapped = 1;
+               wiinst->mmapped = 1;
                spin_unlock_irqrestore(&wiinst->lock, flags);
        }
+
        unlock_kernel();
 
        return 0;
@@ -970,7 +995,7 @@ static int emu10k1_audio_open(struct inode *inode, struct file *file)
        list_for_each(entry, &emu10k1_devs) {
                card = list_entry(entry, struct emu10k1_card, list);
 
-               if (card->audio1_num == minor || card->audio2_num == minor)
+               if (!((card->audio_num ^ minor) & ~0xf) || !((card->audio1_num ^ minor) & ~0xf))
                        break;
        }
 
@@ -988,6 +1013,56 @@ static int emu10k1_audio_open(struct inode *inode, struct file *file)
        wave_dev->woinst = NULL;
        wave_dev->enablebits = PCM_ENABLE_OUTPUT | PCM_ENABLE_INPUT;    /* Default */
 
+       if (file->f_mode & FMODE_READ) {
+               /* Recording */
+               struct wiinst *wiinst;
+
+               if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
+                       ERROR();
+                       return -ENODEV;
+               }
+
+               wiinst->recsrc = card->wavein.recsrc;
+                wiinst->fxwc = card->wavein.fxwc;
+
+               switch (wiinst->recsrc) {
+               case WAVERECORD_AC97:
+                       wiinst->format.samplingrate = 8000;
+                       wiinst->format.bitsperchannel = 16;
+                       wiinst->format.channels = 1;
+                       break;
+               case WAVERECORD_MIC:
+                       wiinst->format.samplingrate = 8000;
+                       wiinst->format.bitsperchannel = 16;
+                       wiinst->format.channels = 1;
+                       break;
+               case WAVERECORD_FX:
+                       wiinst->format.samplingrate = 48000;
+                       wiinst->format.bitsperchannel = 16;
+                       wiinst->format.channels = hweight32(wiinst->fxwc);
+                       break;
+               default:
+                       BUG();
+                       break;
+               }
+
+               wiinst->state = WAVE_STATE_CLOSED;
+
+               wiinst->buffer.ossfragshift = 0;
+               wiinst->buffer.fragment_size = 0;
+               wiinst->buffer.numfrags = 0;
+
+               init_waitqueue_head(&wiinst->wait_queue);
+
+               wiinst->mmapped = 0;
+               wiinst->total_recorded = 0;
+               wiinst->blocks = 0;
+               wiinst->lock = SPIN_LOCK_UNLOCKED;
+               tasklet_init(&wiinst->timer.tasklet, emu10k1_wavein_bh, (unsigned long) wave_dev);
+               wave_dev->wiinst = wiinst;
+               emu10k1_wavein_setformat(wave_dev, &wiinst->format);
+       }
+
        if (file->f_mode & FMODE_WRITE) {
                struct woinst *woinst;
 
@@ -996,24 +1071,31 @@ static int emu10k1_audio_open(struct inode *inode, struct file *file)
                        return -ENODEV;
                }
 
-               woinst->wave_fmt.samplingrate = 8000;
-               woinst->wave_fmt.bitsperchannel = 8;
-               woinst->wave_fmt.channels = 1;
-               woinst->ossfragshift = 0;
-               woinst->fragment_size = 0;
-               woinst->numfrags = 0;
-               woinst->device = (card->audio2_num == minor);
-               woinst->wave_out = NULL;
+               if (wave_dev->wiinst != NULL) {
+                       woinst->format = wave_dev->wiinst->format;
+               } else {
+                       woinst->format.samplingrate = 8000;
+                       woinst->format.bitsperchannel = 8;
+                       woinst->format.channels = 1;
+               }
+
+               woinst->state = WAVE_STATE_CLOSED;
+
+               woinst->buffer.fragment_size = 0;
+               woinst->buffer.ossfragshift = 0;
+               woinst->buffer.numfrags = 0;
+               woinst->device = (card->audio1_num == minor);
 
                init_waitqueue_head(&woinst->wait_queue);
 
-               woinst->mapped = 0;
+               woinst->mmapped = 0;
                woinst->total_copied = 0;
                woinst->total_played = 0;
                woinst->blocks = 0;
-               woinst->curpos = 0;
                woinst->lock = SPIN_LOCK_UNLOCKED;
+               tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev);
                wave_dev->woinst = woinst;
+               emu10k1_waveout_setformat(wave_dev, &woinst->format);
 
 #ifdef PRIVATE_PCM_VOLUME
                {
@@ -1038,69 +1120,27 @@ static int emu10k1_audio_open(struct inode *inode, struct file *file)
                        if (i == MAX_PCM_CHANNELS) {
                                // add new entry
                                if (j < 0)
-                                       printk("TOO MANY WRITTERS!!!\n");
+                                       printk(KERN_WARNING "emu10k1: too many writters!\n");
                                i = (j >= 0) ? j : 0;
                                DPD(2, "new pcm private %p\n", current->files);
                                sblive_pcm_volume[i].files = current->files;
-                               sblive_pcm_volume[i].mixer = 0x6464;    // max
+                               sblive_pcm_volume[i].mixer = pcm_last_mixer;
                                sblive_pcm_volume[i].attn_l = 0;
                                sblive_pcm_volume[i].attn_r = 0;
                                sblive_pcm_volume[i].channel_l = NUM_G;
                                sblive_pcm_volume[i].channel_r = NUM_G;
-                       }
+                       } else
+                               DPD(2, "old pcm private %p  0x%x\n", current->files,
+                                   sblive_pcm_volume[i].mixer);
+
                        sblive_pcm_volume[i].opened++;
                }
 #endif
        }
 
-       if (file->f_mode & FMODE_READ) {
-               /* Recording */
-               struct wiinst *wiinst;
-
-               if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) {
-                       ERROR();
-                       return -ENODEV;
-               }
-
-               switch (card->wavein->recsrc) {
-               case WAVERECORD_AC97:
-                       wiinst->wave_fmt.samplingrate = 8000;
-                       wiinst->wave_fmt.bitsperchannel = 8;
-                       wiinst->wave_fmt.channels = 1;
-                       break;
-               case WAVERECORD_MIC:
-                       wiinst->wave_fmt.samplingrate = 8000;
-                       wiinst->wave_fmt.bitsperchannel = 8;
-                       wiinst->wave_fmt.channels = 1;
-                       break;
-               case WAVERECORD_FX:
-                       wiinst->wave_fmt.samplingrate = 48000;
-                       wiinst->wave_fmt.bitsperchannel = 16;
-                       wiinst->wave_fmt.channels = 2;
-                       break;
-               default:
-                       break;
-               }
-
-               wiinst->recsrc = card->wavein->recsrc;
-               wiinst->ossfragshift = 0;
-               wiinst->fragment_size = 0;
-               wiinst->numfrags = 0;
-               wiinst->wave_in = NULL;
-
-               init_waitqueue_head(&wiinst->wait_queue);
-
-               wiinst->mapped = 0;
-               wiinst->total_recorded = 0;
-               wiinst->blocks = 0;
-               wiinst->curpos = 0;
-               wiinst->lock = SPIN_LOCK_UNLOCKED;
-               wave_dev->wiinst = wiinst;
-       }
-
        file->private_data = (void *) wave_dev;
 
-       return 0;               /* Success? */
+       return 0;
 }
 
 static int emu10k1_audio_release(struct inode *inode, struct file *file)
@@ -1111,37 +1151,35 @@ static int emu10k1_audio_release(struct inode *inode, struct file *file)
 
        lock_kernel();
        card = wave_dev->card;
+
        DPF(2, "emu10k1_audio_release()\n");
 
        if (file->f_mode & FMODE_WRITE) {
                struct woinst *woinst = wave_dev->woinst;
-               struct wave_out *wave_out;
 
                spin_lock_irqsave(&woinst->lock, flags);
 
-               wave_out = woinst->wave_out;
-
-               if (wave_out) {
-                       if ((wave_out->state == CARDWAVE_STATE_STARTED)
-                           && !(file->f_flags & O_NONBLOCK)) {
-                               while (!signal_pending(current)
-                                      && (woinst->total_played < woinst->total_copied)) {
-                                       DPF(4, "Buffer hasn't been totally played, sleep....\n");
-                                       spin_unlock_irqrestore(&woinst->lock, flags);
-                                       interruptible_sleep_on(&woinst->wait_queue);
-                                       spin_lock_irqsave(&woinst->lock, flags);
+               if (woinst->state & WAVE_STATE_OPEN) {
+                       if (woinst->state & WAVE_STATE_STARTED) {
+                               if (!(file->f_flags & O_NONBLOCK)) {
+                                       while (!signal_pending(current)
+                                              && (woinst->total_played < woinst->total_copied)) {
+                                               DPF(4, "Buffer hasn't been totally played, sleep....\n");
+                                               spin_unlock_irqrestore(&woinst->lock, flags);
+                                               interruptible_sleep_on(&woinst->wait_queue);
+                                               spin_lock_irqsave(&woinst->lock, flags);
+                                       }
                                }
                        }
 
-                       if (woinst->mapped && wave_out->pagetable) {
+                       if (woinst->mmapped) {
                                int i;
 
                                /* Undo marking the pages as reserved */
-                               for (i = 0; i < woinst->wave_out->wavexferbuf->numpages; i++)
-                                       mem_map_reserve(virt_to_page(woinst->wave_out->pagetable[i]));
+                               for (i = 0; i < woinst->buffer.pages; i++)
+                                       mem_map_reserve(virt_to_page(woinst->buffer.addr[i]));
                        }
 
-                       woinst->mapped = 0;
                        emu10k1_waveout_close(wave_dev);
                }
 #ifdef PRIVATE_PCM_VOLUME
@@ -1159,22 +1197,21 @@ static int emu10k1_audio_release(struct inode *inode, struct file *file)
                }
 #endif
                spin_unlock_irqrestore(&woinst->lock, flags);
+               /* wait for the tasklet (bottom-half) to finish */
+               tasklet_unlock_wait(&woinst->timer.tasklet);
                kfree(wave_dev->woinst);
        }
 
        if (file->f_mode & FMODE_READ) {
                struct wiinst *wiinst = wave_dev->wiinst;
-               struct wave_in *wave_in;
 
                spin_lock_irqsave(&wiinst->lock, flags);
 
-               wave_in = wiinst->wave_in;
-
-               if (wave_in) {
-                       wiinst->mapped = 0;
+               if (wiinst->state & WAVE_STATE_OPEN)
                        emu10k1_wavein_close(wave_dev);
-               }
+
                spin_unlock_irqrestore(&wiinst->lock, flags);
+               tasklet_unlock_wait(&wiinst->timer.tasklet);
                kfree(wave_dev->wiinst);
        }
 
@@ -1192,7 +1229,7 @@ static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_stru
        struct woinst *woinst = wave_dev->woinst;
        struct wiinst *wiinst = wave_dev->wiinst;
        unsigned int mask = 0;
-       u32 bytestocopy, pending, dummy;
+       u32 bytestocopy;
        unsigned long flags;
 
        DPF(4, "emu10k1_audio_poll()\n");
@@ -1204,49 +1241,44 @@ static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_stru
                poll_wait(file, &wiinst->wait_queue, wait);
 
        if (file->f_mode & FMODE_WRITE) {
-               struct wave_out *wave_out;
-
                spin_lock_irqsave(&woinst->lock, flags);
 
-               wave_out = woinst->wave_out;
-
-               if (wave_out) {
+               if (woinst->state & WAVE_STATE_OPEN) {
+                       emu10k1_waveout_update(woinst);
+                       emu10k1_waveout_getxfersize(woinst, &bytestocopy);
 
-                       emu10k1_waveout_getxfersize(wave_out, &bytestocopy, &pending, &dummy);
-
-                       if (bytestocopy >= woinst->fragment_size)
+                       if (bytestocopy >= woinst->buffer.fragment_size)
                                mask |= POLLOUT | POLLWRNORM;
                } else
                        mask |= POLLOUT | POLLWRNORM;
 
+               if(woinst->mmapped) {
+                       spin_unlock_irqrestore(&woinst->lock, flags);
+                       return mask;
+               }
+
                spin_unlock_irqrestore(&woinst->lock, flags);
        }
 
        if (file->f_mode & FMODE_READ) {
-               struct wave_in *wave_in;
-
                spin_lock_irqsave(&wiinst->lock, flags);
 
-               wave_in = wiinst->wave_in;
-
-               if (!wave_in) {
+               if (wiinst->state == WAVE_STATE_CLOSED) {
                        calculate_ifrag(wiinst);
-                       if (emu10k1_wavein_open(wave_dev) != CTSTATUS_SUCCESS) {
+                       if (emu10k1_wavein_open(wave_dev) < 0) {
                                spin_unlock_irqrestore(&wiinst->lock, flags);
                                return (mask |= POLLERR);
                        }
-
-                       wave_in = wiinst->wave_in;
                }
 
-               if (wave_in->state != CARDWAVE_STATE_STARTED) {
+               if (!(wiinst->state & WAVE_STATE_STARTED)) {
                        wave_dev->enablebits |= PCM_ENABLE_INPUT;
                        emu10k1_wavein_start(wave_dev);
                }
+               emu10k1_wavein_update(wave_dev->card, wiinst);
+               emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
 
-               emu10k1_wavein_getxfersize(wave_in, &bytestocopy, &dummy);
-
-               if (bytestocopy >= wiinst->fragment_size)
+               if (bytestocopy >= wiinst->buffer.fragment_size)
                        mask |= POLLIN | POLLRDNORM;
 
                spin_unlock_irqrestore(&wiinst->lock, flags);
@@ -1257,136 +1289,169 @@ static unsigned int emu10k1_audio_poll(struct file *file, struct poll_table_stru
 
 static void calculate_ofrag(struct woinst *woinst)
 {
-       u32 fragsize, bytespersec;
+       struct waveout_buffer *buffer = &woinst->buffer;
+       u32 fragsize;
 
-       if (woinst->fragment_size)
+       if (buffer->fragment_size)
                return;
 
-       bytespersec = woinst->wave_fmt.channels * (woinst->wave_fmt.bitsperchannel >> 3) * woinst->wave_fmt.samplingrate;
-
-       if (!woinst->ossfragshift) {
-               fragsize = (bytespersec * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
+       if (!buffer->ossfragshift) {
+               fragsize = (woinst->format.bytespersec * WAVEOUT_DEFAULTFRAGLEN) / 1000 - 1;
 
                while (fragsize) {
                        fragsize >>= 1;
-                       woinst->ossfragshift++;
+                       buffer->ossfragshift++;
                }
        }
 
-       if (woinst->ossfragshift < WAVEOUT_MINFRAGSHIFT)
-               woinst->ossfragshift = WAVEOUT_MINFRAGSHIFT;
+       if (buffer->ossfragshift < WAVEOUT_MINFRAGSHIFT)
+               buffer->ossfragshift = WAVEOUT_MINFRAGSHIFT;
 
-       woinst->fragment_size = 1 << woinst->ossfragshift;
+       buffer->fragment_size = 1 << buffer->ossfragshift;
 
-       if (!woinst->numfrags) {
+       if (!buffer->numfrags) {
                u32 numfrags;
 
-               numfrags = (bytespersec * WAVEOUT_DEFAULTBUFLEN) / (woinst->fragment_size * 1000) - 1;
+               numfrags = (woinst->format.bytespersec * WAVEOUT_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
 
-               woinst->numfrags = 1;
+               buffer->numfrags = 1;
 
                while (numfrags) {
                        numfrags >>= 1;
-                       woinst->numfrags <<= 1;
+                       buffer->numfrags <<= 1;
                }
        }
 
-       if (woinst->numfrags < MINFRAGS)
-               woinst->numfrags = MINFRAGS;
+       if (buffer->numfrags < MINFRAGS)
+               buffer->numfrags = MINFRAGS;
 
-       if (woinst->numfrags * woinst->fragment_size > WAVEOUT_MAXBUFSIZE) {
-               woinst->numfrags = WAVEOUT_MAXBUFSIZE / woinst->fragment_size;
+       if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) {
+               buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size;
 
-               if (woinst->numfrags < MINFRAGS) {
-                       woinst->numfrags = MINFRAGS;
-                       woinst->fragment_size = WAVEOUT_MAXBUFSIZE / MINFRAGS;
+               if (buffer->numfrags < MINFRAGS) {
+                       buffer->numfrags = MINFRAGS;
+                       buffer->fragment_size = WAVEOUT_MAXBUFSIZE / MINFRAGS;
                }
 
-       } else if (woinst->numfrags * woinst->fragment_size < WAVEOUT_MINBUFSIZE)
-               woinst->numfrags = WAVEOUT_MINBUFSIZE / woinst->fragment_size;
+       } else if (buffer->numfrags * buffer->fragment_size < WAVEOUT_MINBUFSIZE)
+               buffer->numfrags = WAVEOUT_MINBUFSIZE / buffer->fragment_size;
+
+       buffer->size = buffer->fragment_size * buffer->numfrags;
+       buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0);
 
-       DPD(2, " calculated playback fragment_size -> %d\n", woinst->fragment_size);
-       DPD(2, " calculated playback numfrags -> %d\n", woinst->numfrags);
+       DPD(2, " calculated playback fragment_size -> %d\n", buffer->fragment_size);
+       DPD(2, " calculated playback numfrags -> %d\n", buffer->numfrags);
+
+       return;
 }
 
 static void calculate_ifrag(struct wiinst *wiinst)
 {
-       u32 fragsize, bytespersec;
+       struct wavein_buffer *buffer = &wiinst->buffer;
+       u32 fragsize, bufsize, size[4];
+       int i, j;
 
-       if (wiinst->fragment_size)
+       if (buffer->fragment_size)
                return;
 
-       bytespersec = wiinst->wave_fmt.channels * (wiinst->wave_fmt.bitsperchannel >> 3) * wiinst->wave_fmt.samplingrate;
-
-       if (!wiinst->ossfragshift) {
-               fragsize = (bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1;
+       if (!buffer->ossfragshift) {
+               fragsize = (wiinst->format.bytespersec * WAVEIN_DEFAULTFRAGLEN) / 1000 - 1;
 
                while (fragsize) {
                        fragsize >>= 1;
-                       wiinst->ossfragshift++;
+                       buffer->ossfragshift++;
                }
        }
 
-       if (wiinst->ossfragshift < WAVEIN_MINFRAGSHIFT)
-               wiinst->ossfragshift = WAVEIN_MINFRAGSHIFT;
+       if (buffer->ossfragshift < WAVEIN_MINFRAGSHIFT)
+               buffer->ossfragshift = WAVEIN_MINFRAGSHIFT;
 
-       wiinst->fragment_size = 1 << wiinst->ossfragshift;
+       buffer->fragment_size = 1 << buffer->ossfragshift;
 
-       if (!wiinst->numfrags)
-               wiinst->numfrags = (bytespersec * WAVEIN_DEFAULTBUFLEN) / (wiinst->fragment_size * 1000) - 1;
+       if (!buffer->numfrags)
+               buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1;
 
-       if (wiinst->numfrags < MINFRAGS)
-               wiinst->numfrags = MINFRAGS;
+       if (buffer->numfrags < MINFRAGS)
+               buffer->numfrags = MINFRAGS;
 
-       if (wiinst->numfrags * wiinst->fragment_size > WAVEIN_MAXBUFSIZE) {
-               wiinst->numfrags = WAVEIN_MAXBUFSIZE / wiinst->fragment_size;
+       if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) {
+               buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size;
 
-               if (wiinst->numfrags < MINFRAGS) {
-                       wiinst->numfrags = MINFRAGS;
-                       wiinst->fragment_size = WAVEIN_MAXBUFSIZE / MINFRAGS;
+               if (buffer->numfrags < MINFRAGS) {
+                       buffer->numfrags = MINFRAGS;
+                       buffer->fragment_size = WAVEIN_MAXBUFSIZE / MINFRAGS;
+               }
+       } else if (buffer->numfrags * buffer->fragment_size < WAVEIN_MINBUFSIZE)
+               buffer->numfrags = WAVEIN_MINBUFSIZE / buffer->fragment_size;
+
+       bufsize = buffer->fragment_size * buffer->numfrags;
+
+       if (bufsize >= 0x10000) {
+               buffer->size = 0x10000;
+               buffer->sizeregval = 0x1f;
+       } else {
+               buffer->size = 0;
+               size[0] = 384;
+               size[1] = 448;
+               size[2] = 512;
+               size[3] = 640;
+
+               for (i = 0; i < 8; i++)
+                       for (j = 0; j < 4; j++)
+                               if (bufsize >= size[j]) {
+                                       buffer->size = size[j];
+                                       size[j] *= 2;
+                                       buffer->sizeregval = i * 4 + j + 1;
+                               } else
+                                       goto exitloop;
+             exitloop:
+               if (buffer->size == 0) {
+                       buffer->size = 384;
+                       buffer->sizeregval = 0x01;
                }
-       } else if (wiinst->numfrags * wiinst->fragment_size < WAVEIN_MINBUFSIZE)
-               wiinst->numfrags = WAVEIN_MINBUFSIZE / wiinst->fragment_size;
+       }
+
+       buffer->numfrags = buffer->size / buffer->fragment_size;
+
+       if (buffer->size % buffer->fragment_size)
+               BUG();
+
+       DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size);
+       DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags);
+       DPD(2, " buffer size register -> 0x%2x\n", buffer->sizeregval);
 
-       DPD(2, " calculated recording fragment_size -> %d\n", wiinst->fragment_size);
-       DPD(2, " calculated recording numfrags -> %d\n", wiinst->numfrags);
+       return;
 }
 
 void emu10k1_wavein_bh(unsigned long refdata)
 {
        struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
        struct wiinst *wiinst = wave_dev->wiinst;
-       struct wave_in *wave_in = wiinst->wave_in;
-       u32 bytestocopy, curpos;
+       u32 bytestocopy;
        unsigned long flags;
 
        spin_lock_irqsave(&wiinst->lock, flags);
 
-       if (wave_in->state == CARDWAVE_STATE_STOPPED) {
+       if (!(wiinst->state & WAVE_STATE_STARTED)) {
                spin_unlock_irqrestore(&wiinst->lock, flags);
                return;
        }
 
-       emu10k1_wavein_getxfersize(wave_in, &bytestocopy, &curpos);
-
-       wiinst->total_recorded += curpos - wiinst->curpos;
-
-       if (curpos < wiinst->curpos)
-               wiinst->total_recorded += wiinst->fragment_size * wiinst->numfrags;
-
-       wiinst->curpos = curpos;
+       emu10k1_wavein_update(wave_dev->card, wiinst);
 
-       if (wiinst->mapped) {
+       if (wiinst->mmapped) {
                spin_unlock_irqrestore(&wiinst->lock, flags);
                return;
        }
 
+       emu10k1_wavein_getxfersize(wiinst, &bytestocopy);
+
        spin_unlock_irqrestore(&wiinst->lock, flags);
 
-       if (bytestocopy >= wiinst->fragment_size)
+       if (bytestocopy >= wiinst->buffer.fragment_size)
                wake_up_interruptible(&wiinst->wait_queue);
        else
-               DPD(4, "Not enough transfer size, %d\n", bytestocopy);
+               DPD(3, "Not enough transfer size, %d\n", bytestocopy);
 
        return;
 }
@@ -1395,53 +1460,41 @@ void emu10k1_waveout_bh(unsigned long refdata)
 {
        struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) refdata;
        struct woinst *woinst = wave_dev->woinst;
-       struct wave_out *wave_out = woinst->wave_out;
-       u32 bytestocopy, pending, curpos;
+       u32 bytestocopy;
        unsigned long flags;
 
        spin_lock_irqsave(&woinst->lock, flags);
 
-       if (wave_out->state == CARDWAVE_STATE_STOPPED) {
+       if (!(woinst->state & WAVE_STATE_STARTED)) {
                spin_unlock_irqrestore(&woinst->lock, flags);
                return;
        }
 
-       emu10k1_waveout_getxfersize(wave_out, &bytestocopy, &pending, &curpos);
-
-       woinst->total_played += curpos - woinst->curpos;
-
-       if (curpos < woinst->curpos)
-               woinst->total_played += woinst->fragment_size * woinst->numfrags;
-
-       woinst->curpos = curpos;
-
-       if (woinst->mapped) {
-               spin_unlock_irqrestore(&woinst->lock, flags);
-               return;
-       }
+       emu10k1_waveout_update(woinst);
+       emu10k1_waveout_getxfersize(woinst, &bytestocopy);
 
-       if (wave_out->fill_silence) {
+       if (woinst->buffer.fill_silence) {
                spin_unlock_irqrestore(&woinst->lock, flags);
                emu10k1_waveout_fillsilence(woinst);
        } else
                spin_unlock_irqrestore(&woinst->lock, flags);
 
-       if (bytestocopy >= woinst->fragment_size)
+       if (bytestocopy >= woinst->buffer.fragment_size)
                wake_up_interruptible(&woinst->wait_queue);
        else
-               DPD(4, "Not enough transfer size -> %x\n", bytestocopy);
+               DPD(3, "Not enough transfer size -> %d\n", bytestocopy);
 
        return;
 }
 
 struct file_operations emu10k1_audio_fops = {
-       owner:THIS_MODULE,
-       llseek:emu10k1_audio_llseek,
-       read:emu10k1_audio_read,
-       write:emu10k1_audio_write,
-       poll:emu10k1_audio_poll,
-       ioctl:emu10k1_audio_ioctl,
-       mmap:emu10k1_audio_mmap,
-       open:emu10k1_audio_open,
-       release:emu10k1_audio_release,
+       owner:          THIS_MODULE,
+       llseek:         emu10k1_audio_llseek,
+       read:           emu10k1_audio_read,
+       write:          emu10k1_audio_write,
+       poll:           emu10k1_audio_poll,
+       ioctl:          emu10k1_audio_ioctl,
+       mmap:           emu10k1_audio_mmap,
+       open:           emu10k1_audio_open,
+       release:        emu10k1_audio_release,
 };
index 357479acb35dd1c336ea3ecf385e96498f8eb036..2f0464c211a0448f5456b70b39471c31ddda1135 100644 (file)
 #ifndef _AUDIO_H
 #define _AUDIO_H
 
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <asm/uaccess.h>
-
 #define MINFRAGS       2       /* _don't_ got bellow 2 */
 
+struct emu10k1_wavedevice
+{
+        struct emu10k1_card *card;
+        struct wiinst *wiinst;
+        struct woinst *woinst;
+        u16 enablebits;
+};
+
 void emu10k1_waveout_bh(unsigned long);
 void emu10k1_wavein_bh(unsigned long);
 
index f741b9d6d8931387b8b5931c8506081eea1ae0d8..e39e8f0f818da480355114d6b07c66d0c2fee7b6 100644 (file)
  **********************************************************************
  */
 
+#include <linux/malloc.h>
+#include <linux/sched.h>
+
 #include "hwaccess.h"
+#include "8010.h"
 #include "cardmi.h"
+#include "irqmgr.h"
 
 static struct {
        int (*Fn) (struct emu10k1_mpuin *, u8);
@@ -76,7 +81,7 @@ int emu10k1_mpuin_open(struct emu10k1_card *card, struct midi_openinfo *openinfo
        DPF(2, "emu10k1_mpuin_open\n");
 
        if (!(card_mpuin->status & FLAGS_AVAILABLE))
-               return CTSTATUS_INUSE;
+               return -1;
 
        /* Copy open info and mark channel as in use */
        card_mpuin->openinfo = *openinfo;
@@ -93,7 +98,7 @@ int emu10k1_mpuin_open(struct emu10k1_card *card, struct midi_openinfo *openinfo
        emu10k1_mpu_reset(card);
        emu10k1_mpu_acquire(card);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int emu10k1_mpuin_close(struct emu10k1_card *card)
@@ -105,7 +110,7 @@ int emu10k1_mpuin_close(struct emu10k1_card *card)
        /* Check if there are pending input SysEx buffers */
        if (card_mpuin->firstmidiq != NULL) {
                ERROR();
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        /* Disable RX interrupt */
@@ -116,7 +121,7 @@ int emu10k1_mpuin_close(struct emu10k1_card *card)
        card_mpuin->status |= FLAGS_AVAILABLE;  /* set */
        card_mpuin->status &= ~FLAGS_MIDM_STARTED;      /* clear */
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* Adds MIDI buffer to local queue list                         */
@@ -134,7 +139,7 @@ int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *card_mpuin, struct midi_hdr *
 
        if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_ATOMIC)) == NULL) {
                /* Message lost */
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        midiq->next = NULL;
@@ -156,7 +161,7 @@ int emu10k1_mpuin_add_buffer(struct emu10k1_mpuin *card_mpuin, struct midi_hdr *
 
        spin_unlock_irqrestore(&card_mpuin->lock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* First set the Time Stamp if MIDI IN has not started.         */
@@ -174,7 +179,7 @@ int emu10k1_mpuin_start(struct emu10k1_card *card)
        if (card_mpuin->status & FLAGS_MIDM_STARTED) {
                DPF(2, "Time Stamp not changed\n");
        } else {
-               while (emu10k1_mpu_read_data(card, &dummy) == CTSTATUS_SUCCESS);
+               while (!emu10k1_mpu_read_data(card, &dummy));
 
                card_mpuin->status |= FLAGS_MIDM_STARTED;       /* set */
 
@@ -188,7 +193,7 @@ int emu10k1_mpuin_start(struct emu10k1_card *card)
                emu10k1_irq_enable(card, INTE_MIDIRXENABLE);
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* Disable the RX Irq.  If a partial recorded buffer            */
@@ -229,7 +234,7 @@ int emu10k1_mpuin_stop(struct emu10k1_card *card)
                }
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* Disable the RX Irq.  If any buffer                           */
@@ -259,7 +264,7 @@ int emu10k1_mpuin_reset(struct emu10k1_card *card)
        card_mpuin->lastmidiq = NULL;
        card_mpuin->status &= ~FLAGS_MIDM_STARTED;
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* Passes the message with the data back to the client          */
@@ -302,7 +307,7 @@ int emu10k1_mpuin_callback(struct emu10k1_mpuin *card_mpuin, u32 msg, unsigned l
        /* Notify client that Sysex buffer has been sent */
        emu10k1_midi_callback(msg, card_mpuin->openinfo.refdata, callback_msg);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 void emu10k1_mpuin_bh(unsigned long refdata)
@@ -344,13 +349,13 @@ int emu10k1_mpuin_irqhandler(struct emu10k1_card *card)
        idx = card_mpuin->qtail;
 
        while (1) {
-               if (emu10k1_mpu_read_data(card, &MPUIvalue) == CTSTATUS_SUCCESS) {
+               if (emu10k1_mpu_read_data(card, &MPUIvalue) < 0) {
+                       break;
+               } else {
                        ++count;
                        card_mpuin->midiq[idx].data = MPUIvalue;
                        card_mpuin->midiq[idx].timein = (jiffies * 1000) / HZ;
                        idx = (idx + 1) % MIDIIN_MAX_BUFFER_SIZE;
-               } else {
-                       break;
                }
        }
 
@@ -360,7 +365,7 @@ int emu10k1_mpuin_irqhandler(struct emu10k1_card *card)
                tasklet_hi_schedule(&card_mpuin->tasklet);
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /*****************************************************************************/
@@ -380,7 +385,7 @@ int sblive_miStateInit(struct emu10k1_mpuin *card_mpuin)
        card_mpuin->timestart = 0;
        card_mpuin->timein = 0;
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* FIXME: This should be a macro */
@@ -425,7 +430,7 @@ int sblive_miStateParse(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                case 0x7:
                        emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, 0xf7, 0);
-                       return CTSTATUS_ERROR;
+                       return -1;
 
                case 0x2:
                        card_mpuin->laststate = card_mpuin->curstate;
@@ -447,7 +452,7 @@ int sblive_miStateParse(struct emu10k1_mpuin *card_mpuin, u8 data)
 
        default:
                DPF(2, "BUG: default case hit\n");
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        return midistatefn[card_mpuin->curstate].Fn(card_mpuin, data);
@@ -489,7 +494,7 @@ int sblive_miState3ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        card_mpuin->data = data;
@@ -520,7 +525,7 @@ int sblive_miState3ByteVel(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        card_mpuin->curstate = STIN_3BYTE;
@@ -532,7 +537,7 @@ int sblive_miState3ByteVel(struct emu10k1_mpuin *card_mpuin, u8 data)
 
        emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int sblive_miState2Byte(struct emu10k1_mpuin *card_mpuin, u8 data)
@@ -573,7 +578,7 @@ int sblive_miState2ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        card_mpuin->curstate = STIN_2BYTE;
@@ -583,7 +588,7 @@ int sblive_miState2ByteKey(struct emu10k1_mpuin *card_mpuin, u8 data)
 
        emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int sblive_miStateSysCommon2(struct emu10k1_mpuin *card_mpuin, u8 data)
@@ -615,7 +620,7 @@ int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        card_mpuin->curstate = card_mpuin->laststate;
@@ -625,7 +630,7 @@ int sblive_miStateSysCommon2Key(struct emu10k1_mpuin *card_mpuin, u8 data)
 
        emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 2);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int sblive_miStateSysCommon3(struct emu10k1_mpuin *card_mpuin, u8 data)
@@ -657,7 +662,7 @@ int sblive_miStateSysCommon3Key(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        card_mpuin->data = data;
@@ -689,7 +694,7 @@ int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *card_mpuin, u8 data)
 
                emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATAERROR, tmp, 0);
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        card_mpuin->curstate = card_mpuin->laststate;
@@ -701,7 +706,7 @@ int sblive_miStateSysCommon3Vel(struct emu10k1_mpuin *card_mpuin, u8 data)
 
        emu10k1_mpuin_callback(card_mpuin, ICARDMIDI_INDATA, tmp, 3);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int sblive_miStateSysExNorm(struct emu10k1_mpuin *card_mpuin, u8 data)
@@ -739,7 +744,7 @@ int sblive_miStateSysExNorm(struct emu10k1_mpuin *card_mpuin, u8 data)
                        kfree(midiq);
                }
 
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        if (card_mpuin->firstmidiq) {
@@ -775,7 +780,7 @@ int sblive_miStateSysExNorm(struct emu10k1_mpuin *card_mpuin, u8 data)
                        kfree(midiq);
                }
 
-               return CTSTATUS_SUCCESS;
+               return 0;
        }
 
        if (card_mpuin->firstmidiq) {
index f78fc1f70dfda1b99bfbd7d6f15fee9c39b6bfd9..bd922c0175d2d52cd5c0d5bf742ba25c104bbd9f 100644 (file)
@@ -34,6 +34,7 @@
 #define _CARDMI_H
 
 #include "icardmid.h"
+#include <linux/interrupt.h>
 
 typedef enum
 {
index e7a8612d231abdf9592885e3851fb0bf31495df9..726a83424cdc27ba23bae2d2db77b4e2cc414f73 100644 (file)
  ********************************************************************** 
  */
 
+#include <linux/malloc.h>
+
 #include "hwaccess.h"
+#include "8010.h"
 #include "cardmo.h"
+#include "irqmgr.h"
 
 /* Installs the IRQ handler for the MPU out port               *
  * and initialize parameters                                    */
@@ -44,7 +48,7 @@ int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinf
        DPF(2, "emu10k1_mpuout_open()\n");
 
        if (!(card_mpuout->status & FLAGS_AVAILABLE))
-               return CTSTATUS_INUSE;
+               return -1;
 
        /* Copy open info and mark channel as in use */
        card_mpuout->intr = 0;
@@ -57,7 +61,7 @@ int emu10k1_mpuout_open(struct emu10k1_card *card, struct midi_openinfo *openinf
        emu10k1_mpu_reset(card);
        emu10k1_mpu_acquire(card);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int emu10k1_mpuout_close(struct emu10k1_card *card)
@@ -92,7 +96,7 @@ int emu10k1_mpuout_close(struct emu10k1_card *card)
 
        spin_unlock_irqrestore(&card_mpuout->lock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* If there isn't enough buffer space, reject Midi Buffer.     *
@@ -109,14 +113,14 @@ int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihd
        DPF(2, "emu10k1_mpuout_add_buffer()\n");
 
        if (card_mpuout->state == CARDMIDIOUT_STATE_SUSPEND)
-               return CTSTATUS_SUCCESS;
+               return 0;
 
        midihdr->flags |= MIDIBUF_INQUEUE;
        midihdr->flags &= ~MIDIBUF_DONE;
 
        if ((midiq = (struct midi_queue *) kmalloc(sizeof(struct midi_queue), GFP_KERNEL)) == NULL) {
                /* Message lost */
-               return CTSTATUS_NOMEMORY;
+               return -1;
        }
 
        midiq->next = NULL;
@@ -143,7 +147,7 @@ int emu10k1_mpuout_add_buffer(struct emu10k1_card *card, struct midi_hdr *midihd
 
        spin_unlock_irqrestore(&card_mpuout->lock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 void emu10k1_mpuout_bh(unsigned long refdata)
@@ -151,7 +155,6 @@ void emu10k1_mpuout_bh(unsigned long refdata)
        struct emu10k1_card *card = (struct emu10k1_card *) refdata;
        struct emu10k1_mpuout *card_mpuout = card->mpuout;
        int cByteSent = 0;
-       int status;
        struct midi_queue *midiq;
        struct midi_queue *doneq = NULL;
        unsigned long flags;
@@ -162,14 +165,12 @@ void emu10k1_mpuout_bh(unsigned long refdata)
                midiq = card_mpuout->firstmidiq;
 
                while (cByteSent < 4 && midiq->sizeLeft) {
-                       status = emu10k1_mpu_write_data(card, *midiq->midibyte);
-
-                       if (status == CTSTATUS_SUCCESS) {
+                       if (emu10k1_mpu_write_data(card, *midiq->midibyte) < 0) {
+                               DPF(2, "emu10k1_mpuoutDpcCallback error!!\n");
+                       } else {
                                ++cByteSent;
                                --midiq->sizeLeft;
                                ++midiq->midibyte;
-                       } else {
-                               DPF(2, "emu10k1_mpuoutDpcCallback error!!\n");
                        }
                }
 
@@ -225,5 +226,5 @@ int emu10k1_mpuout_irqhandler(struct emu10k1_card *card)
 
        tasklet_hi_schedule(&card_mpuout->tasklet);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
index 83871185ed0857a40ef4519d7bb544b9427c2a9a..7026eb3a85af47455ffc3b92b5a56df5cc0284e1 100644 (file)
@@ -34,6 +34,7 @@
 #define _CARDMO_H
 
 #include "icardmid.h"
+#include <linux/interrupt.h>
 
 #define CARDMIDIOUT_STATE_DEFAULT    0x00000000
 #define CARDMIDIOUT_STATE_SUSPEND    0x00000001
index fce4f0fdf11e0bf6470b5ff77f95f28d2a67d0fb..01f5516196e154474ac00172b7a4054af230a309 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     cardwi.c - PCM input HAL for emu10k1 driver
@@ -30,7 +29,9 @@
  **********************************************************************
  */
 
+#include <linux/poll.h>
 #include "hwaccess.h"
+#include "timer.h"
 #include "recmgr.h"
 #include "audio.h"
 #include "cardwi.h"
@@ -41,7 +42,7 @@ void query_format(int recsrc, struct wave_format *wave_fmt)
        switch (recsrc) {
        case WAVERECORD_AC97:
 
-               if ((wave_fmt->channels != 2) && (wave_fmt->channels != 1))
+               if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
                        wave_fmt->channels = 2;
 
                if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
@@ -61,110 +62,41 @@ void query_format(int recsrc, struct wave_format *wave_fmt)
                else
                        wave_fmt->samplingrate = 0x1F40;
 
-               if ((wave_fmt->bitsperchannel != 16) && (wave_fmt->bitsperchannel != 8))
+               if ((wave_fmt->bitsperchannel != 8) && (wave_fmt->bitsperchannel != 16))
                        wave_fmt->bitsperchannel = 16;
 
                break;
 
+       /* these can't be changed from the original values */
        case WAVERECORD_MIC:
-               wave_fmt->channels = 1;
-               wave_fmt->samplingrate = 0x1F40;
-               wave_fmt->bitsperchannel = 8;
-               break;
-
        case WAVERECORD_FX:
-               wave_fmt->channels = 2;
-               wave_fmt->samplingrate = 0xBB80;
-               wave_fmt->bitsperchannel = 16;
                break;
 
        default:
+               BUG();
                break;
        }
 
+       wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
+       wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
+       wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
+
        return;
 }
 
-static int alloc_recbuffer(struct wave_in *wave_in, u32 * bufsize, u8 ** buffer)
+static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
 {
-       u32 reqsize;
-       int i, j;
-       u32 size[4];
-
-       /* NOTE: record buffer size only can be certain sizes.  If the requested
-        * size is not a nice size, use the smaller nearest size. The minimum size is 1k. */
-       if (!wave_in->rec_ptr->is_16bit)
-               *bufsize <<= 1;
-
-       if (*bufsize >= 0x10000) {
-               *bufsize = reqsize = 0x10000;
-               wave_in->rec_ptr->bufsize = 31;
-       } else {
-               reqsize = 0;
-               size[0] = 384;
-               size[1] = 448;
-               size[2] = 512;
-               size[3] = 640;
-
-               for (i = 0; i < 8; i++)
-                       for (j = 0; j < 4; j++)
-                               if (*bufsize >= size[j]) {
-                                       reqsize = size[j];
-                                       size[j] = size[j] * 2;
-                                       wave_in->rec_ptr->bufsize = i * 4 + j + 1;
-                               } else
-                                       goto exitloop;
-             exitloop:
-               if (reqsize == 0) {
-                       reqsize = 384;
-                       wave_in->rec_ptr->bufsize = 1;
-               }
-
-               *bufsize = reqsize;
-       }
-
-       DPD(2, "bufsizereg: %x\n", wave_in->rec_ptr->bufsize);
+       if ((buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov, &buffer->dma_handle)) == NULL)
+               return -1;
 
-       /* Recording buffer must be continuous and page-aligned */
-       if ((wave_in->memhandle = emu10k1_alloc_memphysical(reqsize)) == NULL)
-               return CTSTATUS_ERROR;
-
-       DPD(2, "recbufsize: %x\n", *bufsize);
-
-       *buffer = (u8 *) wave_in->memhandle->virtaddx;
-
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
-static int get_recbuffer(struct emu10k1_card *card, struct wave_in *wave_in, u32 * size)
+static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
 {
-       u8 *buffer;
+       if (buffer->addr != NULL)
+               pci_free_consistent(card->pci_dev, buffer->size * buffer->cov, buffer->addr, buffer->dma_handle);
 
-       wave_in->rec_ptr->card = card;
-       wave_in->rec_ptr->recpos = 0;
-       wave_in->rec_ptr->samplingrate = wave_in->wave_fmt.samplingrate;
-       wave_in->rec_ptr->is_stereo = (wave_in->wave_fmt.channels == 2) ? 1 : 0;
-       wave_in->rec_ptr->is_16bit = (wave_in->wave_fmt.bitsperchannel == 16) ? 1 : 0;
-
-       /* Allocate buffer here */
-       if (alloc_recbuffer(wave_in, size, &buffer) != CTSTATUS_SUCCESS) {
-               ERROR();
-               return CTSTATUS_ERROR;
-       }
-
-       /* recbufsize contains actual record buffer size          */
-       /* for 8 bit samples the size is twice the requested      */
-       /* value since we only make use of one in every two bytes */
-       wave_in->rec_ptr->recbufsize = *size;
-       wave_in->rec_ptr->recbuffer = buffer;
-       wave_in->rec_ptr->busaddx = wave_in->memhandle->busaddx;
-
-       return CTSTATUS_SUCCESS;
-}
-
-static void dealloc_recbuffer(struct wave_in *wave_in)
-{
-       emu10k1_free_memphysical(wave_in->memhandle);
        return;
 }
 
@@ -172,301 +104,264 @@ int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
 {
        struct emu10k1_card *card = wave_dev->card;
        struct wiinst *wiinst = wave_dev->wiinst;
-       struct wave_in *wave_in;
-       struct wave_in **wave_in_tmp = NULL;
-       u32 buffsize, bytespersec, delay;
+       struct wiinst **wiinst_tmp = NULL;
+       u32 delay;
        unsigned long flags;
 
        DPF(2, "emu10k1_wavein_open()\n");
 
-       if ((wave_in = (struct wave_in *) kmalloc(sizeof(struct wave_in), GFP_KERNEL)) == NULL) {
-               ERROR();
-               return CTSTATUS_ERROR;
-       }
-
-       wave_in->state = CARDWAVE_STATE_STOPPED;
-       wave_in->wave_fmt = wiinst->wave_fmt;
-       wave_in->memhandle = NULL;
-       wave_in->timer = NULL;
-
        switch (wiinst->recsrc) {
        case WAVERECORD_AC97:
-               wave_in_tmp = &card->wavein->ac97;
+               wiinst_tmp = &card->wavein.ac97;
                break;
        case WAVERECORD_MIC:
-               wave_in_tmp = &card->wavein->mic;
+               wiinst_tmp = &card->wavein.mic;
                break;
        case WAVERECORD_FX:
-               wave_in_tmp = &card->wavein->fx;
+               wiinst_tmp = &card->wavein.fx;
                break;
        default:
+               BUG();
                break;
        }
 
        spin_lock_irqsave(&card->lock, flags);
-       if (*wave_in_tmp != NULL) {
+       if (*wiinst_tmp != NULL) {
                spin_unlock_irqrestore(&card->lock, flags);
-               kfree(wave_in);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       *wave_in_tmp = wave_in;
+       *wiinst_tmp = wiinst;
        spin_unlock_irqrestore(&card->lock, flags);
 
-       wiinst->wave_in = wave_in;
+       /* handle 8 bit recording */
+       if (wiinst->format.bytesperchannel == 1) {
+               if (wiinst->buffer.size > 0x8000) {
+                       wiinst->buffer.size = 0x8000;
+                       wiinst->buffer.sizeregval = 0x1f;
+               } else
+                       wiinst->buffer.sizeregval += 4;
 
-       if ((wave_in->rec_ptr = (struct record *) kmalloc(sizeof(struct record), GFP_KERNEL)) == NULL) {
-               ERROR();
-               emu10k1_wavein_close(wave_dev);
-               return CTSTATUS_ERROR;
-       }
+               wiinst->buffer.cov = 2;
+       } else
+               wiinst->buffer.cov = 1;
 
-       buffsize = wiinst->fragment_size * wiinst->numfrags;
-
-       if (get_recbuffer(card, wave_in, &buffsize) != CTSTATUS_SUCCESS) {
+       if (alloc_buffer(card, &wiinst->buffer) < 0) {
                ERROR();
                emu10k1_wavein_close(wave_dev);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       wiinst->fragment_size = buffsize / wiinst->numfrags;
-
-       /* This callback size returned is the size in the play buffer.
-        * For 8-bit samples, callbacksize of user buffer should be
-        * half of the callbacksize in play buffer. */
-       if (wave_in->wave_fmt.bitsperchannel == 8)
-               wiinst->fragment_size >>= 1;
+       emu10k1_set_record_src(card, wiinst);
 
-       wave_in->callbacksize = wiinst->fragment_size;
+       delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
 
-       emu10k1_set_record_src(wave_in->rec_ptr, wiinst->recsrc);
+       emu10k1_timer_install(card, &wiinst->timer, delay / 2);
 
-       bytespersec = wave_in->wave_fmt.channels * (wave_in->wave_fmt.bitsperchannel >> 3) * (wave_in->wave_fmt.samplingrate);
-       delay = (48000 * wave_in->callbacksize) / bytespersec;
-
-       if ((wave_in->timer = emu10k1_timer_install(card, emu10k1_wavein_bh, (unsigned long) wave_dev, delay / 2)) == NULL) {
-               ERROR();
-               emu10k1_wavein_close(wave_dev);
-               return CTSTATUS_ERROR;
-       }
+       wiinst->state = WAVE_STATE_OPEN;
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
 {
        struct emu10k1_card *card = wave_dev->card;
-       struct wave_in *wave_in = wave_dev->wiinst->wave_in;
+       struct wiinst *wiinst = wave_dev->wiinst;
        unsigned long flags;
 
-       if (wave_in->state != CARDWAVE_STATE_STOPPED)
-               emu10k1_wavein_stop(wave_dev);
+       DPF(2, "emu10k1_wavein_close()\n");
 
-       if (wave_in->timer != NULL)
-               emu10k1_timer_uninstall(card, wave_in->timer);
+       emu10k1_wavein_stop(wave_dev);
 
-       if (wave_in->memhandle != NULL)
-               dealloc_recbuffer(wave_in);
+       emu10k1_timer_uninstall(card, &wiinst->timer);
 
-       if (wave_in->rec_ptr != NULL)
-               kfree(wave_in->rec_ptr);
+       free_buffer(card, &wiinst->buffer);
 
        spin_lock_irqsave(&card->lock, flags);
        switch (wave_dev->wiinst->recsrc) {
        case WAVERECORD_AC97:
-               card->wavein->ac97 = NULL;
+               card->wavein.ac97 = NULL;
                break;
        case WAVERECORD_MIC:
-               card->wavein->mic = NULL;
+               card->wavein.mic = NULL;
                break;
        case WAVERECORD_FX:
-               card->wavein->fx = NULL;
+               card->wavein.fx = NULL;
                break;
        default:
+               BUG();
                break;
        }
        spin_unlock_irqrestore(&card->lock, flags);
 
-       kfree(wave_in);
-       wave_dev->wiinst->wave_in = NULL;
+       wiinst->state = WAVE_STATE_CLOSED;
 
        return;
 }
 
 void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
 {
-       struct wave_in *wave_in = wave_dev->wiinst->wave_in;
+       struct emu10k1_card *card = wave_dev->card;
+       struct wiinst *wiinst = wave_dev->wiinst;
 
        DPF(2, "emu10k1_wavein_start()\n");
 
-       if (wave_in->state == CARDWAVE_STATE_STARTED)
-               return;
+       emu10k1_start_record(card, &wiinst->buffer);
+       emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
 
-       emu10k1_start_record(wave_in->rec_ptr);
-       wave_in->state = CARDWAVE_STATE_STARTED;
+       wiinst->buffer.hw_pos = 0;
+       wiinst->buffer.pos = 0;
+       wiinst->buffer.bytestocopy = 0;
 
-       emu10k1_timer_enable(wave_dev->card, wave_in->timer);
+       wiinst->state |= WAVE_STATE_STARTED;
 
        return;
 }
 
 void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
 {
-       struct wave_in *wave_in = wave_dev->wiinst->wave_in;
+       struct emu10k1_card *card = wave_dev->card;
+       struct wiinst *wiinst = wave_dev->wiinst;
 
        DPF(2, "emu10k1_wavein_stop()\n");
 
-       emu10k1_stop_record(wave_in->rec_ptr);
-       emu10k1_timer_disable(wave_dev->card, wave_in->timer);
+       if (!(wiinst->state & WAVE_STATE_STARTED))
+               return;
 
-       wave_in->rec_ptr->recpos = 0;
-       wave_in->state = CARDWAVE_STATE_STOPPED;
+       emu10k1_timer_disable(card, &wiinst->timer);
+       emu10k1_stop_record(card, &wiinst->buffer);
+
+       wiinst->state &= ~WAVE_STATE_STARTED;
 
        return;
 }
 
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev)
+int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
 {
        struct emu10k1_card *card = wave_dev->card;
        struct wiinst *wiinst = wave_dev->wiinst;
-       struct wave_in *wave_in = wiinst->wave_in;
-       u32 bytespersec, delay;
+       u32 delay;
 
        DPF(2, "emu10k1_wavein_setformat()\n");
 
-       query_format(wiinst->recsrc, &wiinst->wave_fmt);
+       if (wiinst->state & WAVE_STATE_STARTED)
+               return -1;
 
-       if (!wave_in)
-               return CTSTATUS_SUCCESS;
+       query_format(wiinst->recsrc, format);
 
-       if (wave_in->state == CARDWAVE_STATE_STARTED) {
-               wiinst->wave_fmt = wave_in->wave_fmt;
-               return CTSTATUS_SUCCESS;
-       }
+       if ((wiinst->format.samplingrate != format->samplingrate)
+           || (wiinst->format.bitsperchannel != format->bitsperchannel)
+           || (wiinst->format.channels != format->channels)) {
 
-       if ((wave_in->wave_fmt.samplingrate != wiinst->wave_fmt.samplingrate)
-           || (wave_in->wave_fmt.bitsperchannel != wiinst->wave_fmt.bitsperchannel)
-           || (wave_in->wave_fmt.channels != wiinst->wave_fmt.channels)) {
+               wiinst->format = *format;
 
-               emu10k1_timer_uninstall(card, wave_in->timer);
+               if (wiinst->state == WAVE_STATE_CLOSED)
+                       return 0;
 
-               wave_in->wave_fmt = wiinst->wave_fmt;
+               wiinst->buffer.size *= wiinst->buffer.cov;
 
-               bytespersec = wave_in->wave_fmt.channels * (wave_in->wave_fmt.bitsperchannel >> 3) * (wave_in->wave_fmt.samplingrate);
-               delay = (48000 * wave_in->callbacksize) / bytespersec;
+               if (wiinst->format.bytesperchannel == 1) {
+                       wiinst->buffer.cov = 2;
+                       wiinst->buffer.size /= wiinst->buffer.cov;
+               } else
+                       wiinst->buffer.cov = 1;
 
-               if ((wave_in->timer = emu10k1_timer_install(card, emu10k1_wavein_bh, (unsigned long) wave_dev, delay / 2)) == NULL) {
-                       ERROR();
-                       emu10k1_wavein_close(wave_dev);
-                       return CTSTATUS_ERROR;
-               }
+               emu10k1_timer_uninstall(card, &wiinst->timer);
+
+               delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
+
+               emu10k1_timer_install(card, &wiinst->timer, delay / 2);
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
-void emu10k1_wavein_getxfersize(struct wave_in *wave_in, u32 * size, u32 * curpos)
+void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
 {
-       struct record *rec_ptr = wave_in->rec_ptr;
-
-       /* Get position of current address, this is in no. of bytes in play buffer */
-       emu10k1_wavein_getcontrol(wave_in, WAVECURPOS, curpos);
+       struct wavein_buffer *buffer = &wiinst->buffer;
 
-       *size = *curpos - rec_ptr->recpos;
+       *size = buffer->bytestocopy;
 
-       /* Recpos is the actual position in user buffer and play buffer */
-       if (*curpos < rec_ptr->recpos)
-               *size += rec_ptr->recbufsize;
-
-       if (!rec_ptr->is_16bit)
-               *size >>= 1;
+       if (*size > buffer->size) {
+               *size = buffer->size;
+               buffer->pos = buffer->hw_pos;
+               buffer->bytestocopy = buffer->size;
+               DPF(1, "buffer overrun\n");
+       }
 
        return;
 }
 
-static void copy_s16_to_u8(u8 * dstbuf, s16 * srcbuf, u32 size)
+static void copy_block(u8 *dst, u8 * src, u32 str, u32 len, u8 cov)
 {
-       u16 sample;
-       u8 byte;
-
-       while (size--) {
-               sample = (*srcbuf) + 32767;
-               byte = (u8) (sample >> 8);
-               copy_to_user(dstbuf, &byte, 1);
-               dstbuf++;
-               srcbuf++;
+       if (cov == 1)
+               copy_to_user(dst, src + str, len);
+       else {
+               u8 byte;
+               u32 i;
+
+               src += 1 + 2 * str;
+
+               for (i = 0; i < len; i++) {
+                       byte = src[2 * i] ^ 0x80;
+                       copy_to_user(dst + i, &byte, 1);
+               }
        }
+
+       return;
 }
 
-/* transfer the data from the wave device.                    */
 void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 * data, u32 * size)
 {
-       struct wave_in *wave_in = wiinst->wave_in;
-       struct record *rec_ptr = wave_in->rec_ptr;
+       struct wavein_buffer *buffer = &wiinst->buffer;
        u32 sizetocopy, sizetocopy_now, start;
        unsigned long flags;
 
-       sizetocopy = min(rec_ptr->recbufsize * (rec_ptr->is_16bit + 1) / 2, *size);
+       sizetocopy = min(buffer->size, *size);
        *size = sizetocopy;
 
        if (!sizetocopy)
                return;
 
        spin_lock_irqsave(&wiinst->lock, flags);
+       start = buffer->pos;
+       buffer->pos += sizetocopy;
+       buffer->pos %= buffer->size;
+       buffer->bytestocopy -= sizetocopy;
+       sizetocopy_now = buffer->size - start;
 
-       sizetocopy_now = (rec_ptr->recbufsize - rec_ptr->recpos) * (rec_ptr->is_16bit + 1) / 2;
-
-       start = rec_ptr->recpos;
+       spin_unlock_irqrestore(&wiinst->lock, flags);
 
        if (sizetocopy > sizetocopy_now) {
                sizetocopy -= sizetocopy_now;
-               rec_ptr->recpos = sizetocopy * 2 / (rec_ptr->is_16bit + 1);
-
-               spin_unlock_irqrestore(&wiinst->lock, flags);
 
-               if (rec_ptr->is_16bit) {
-                       copy_to_user(data, rec_ptr->recbuffer + start, sizetocopy_now);
-                       copy_to_user(data + sizetocopy_now, rec_ptr->recbuffer, sizetocopy);
-               } else {
-                       copy_s16_to_u8(data, (s16 *) (rec_ptr->recbuffer + start), sizetocopy_now);
-                       copy_s16_to_u8(data + sizetocopy_now, (s16 *) rec_ptr->recbuffer, sizetocopy);
-               }
+               copy_block(data, buffer->addr, start, sizetocopy_now, buffer->cov);
+               copy_block(data + sizetocopy_now, buffer->addr, 0, sizetocopy, buffer->cov);
        } else {
-               if (sizetocopy == sizetocopy_now)
-                       rec_ptr->recpos = 0;
-               else
-                       rec_ptr->recpos += sizetocopy * 2 / (rec_ptr->is_16bit + 1);
-
-               spin_unlock_irqrestore(&wiinst->lock, flags);
-
-               if (rec_ptr->is_16bit)
-                       copy_to_user(data, rec_ptr->recbuffer + start, sizetocopy);
-               else
-                       copy_s16_to_u8(data, (s16 *) (rec_ptr->recbuffer + start), sizetocopy);
+               copy_block(data, buffer->addr, start, sizetocopy, buffer->cov);
        }
 
        return;
 }
 
-/* get the specified control value of the wave device. */
-
-int emu10k1_wavein_getcontrol(struct wave_in *wave_in, u32 ctrlid, u32 * value)
+void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
 {
-       switch (ctrlid) {
-       case WAVECURPOS:
-               /* There is no actual start yet */
-               if (wave_in->state == CARDWAVE_STATE_STOPPED) {
-                       *value = 0;
-               } else {
-                       /* value is in byte units */
-                       *value = sblive_readptr(wave_in->rec_ptr->card, wave_in->rec_ptr->bufidxreg, 0);
-               }
-
-               break;
+       u32 hw_pos;
+       u32 diff;
 
-       default:
-               return CTSTATUS_ERROR;
+       /* There is no actual start yet */
+       if (!(wiinst->state & WAVE_STATE_STARTED)) {
+               hw_pos = wiinst->buffer.hw_pos;
+       } else {
+               /* hw_pos in byte units */
+               hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
        }
 
-       return CTSTATUS_SUCCESS;
+       diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
+       wiinst->total_recorded += diff;
+       wiinst->buffer.bytestocopy += diff;
+
+       wiinst->buffer.hw_pos = hw_pos;
+
+       return;
 }
index 2d781033d7880a8dc71580e1524c904de925a489..f0c44057df23cf7c6b2627428048686b78be2d0a 100644 (file)
 #define _CARDWI_H
 
 #include "icardwav.h"
+#include "audio.h"
+#include "timer.h"
 
-struct wave_in 
-{
-       struct list_head list;
-
-       u32 state;
-       struct record *rec_ptr;
-       struct memhandle *memhandle;
-       struct emu_timer *timer;
-       u32 callbacksize;
-       struct wave_format wave_fmt;
+struct wavein_buffer {
+       u16 ossfragshift;
+        u32 fragment_size;
+        u32 numfrags;
+       u32 hw_pos;             /* hardware cursor position */
+       u32 pos;                /* software cursor position */
+       u32 bytestocopy;        /* bytes of recorded data available */
+       u32 size;
+       u32 sizereg;
+       u32 sizeregval;
+        u32 addrreg;
+        u32 idxreg;
+        u32 adcctl;
+       void *addr;
+       u8 cov;
+       dma_addr_t dma_handle;  
 };
 
 struct wiinst
 {
-       struct wave_in *wave_in;
-       struct wave_format wave_fmt;
-       u16 ossfragshift;
-       u32 fragment_size;
-       u32 numfrags;
+       u8 state;
+       struct emu_timer timer;
+       struct wave_format format;
+       struct wavein_buffer buffer;
        wait_queue_head_t wait_queue;
-       int mapped;
-       u32 total_recorded;
+       u8 mmapped;
+       u32 total_recorded;     /* total bytes read() from device */
        u32 blocks;
-       u32 curpos;
        spinlock_t lock;
        u8 recsrc;
+       u16 fxwc;
 };
 
-struct emu10k1_wavein 
-{
-       struct wave_in *ac97;
-       struct wave_in *mic;
-       struct wave_in *fx;
-
-       u8 recsrc;
-};
-
-
 #define WAVEIN_MAXBUFSIZE         65536
 #define WAVEIN_MINBUFSIZE        368
 
@@ -83,10 +80,10 @@ int emu10k1_wavein_open(struct emu10k1_wavedevice *);
 void emu10k1_wavein_close(struct emu10k1_wavedevice *);
 void emu10k1_wavein_start(struct emu10k1_wavedevice *);
 void emu10k1_wavein_stop(struct emu10k1_wavedevice *);
-void emu10k1_wavein_getxfersize(struct wave_in *, u32 *, u32 *);
+void emu10k1_wavein_getxfersize(struct wiinst *, u32 *);
 void emu10k1_wavein_xferdata(struct wiinst *, u8 *, u32 *);
-int emu10k1_wavein_setformat(struct emu10k1_wavedevice *);
-int emu10k1_wavein_getcontrol(struct wave_in *, u32, u32 *);
+int emu10k1_wavein_setformat(struct emu10k1_wavedevice *, struct wave_format *);
+void emu10k1_wavein_update(struct emu10k1_card *, struct wiinst *);
 
 
 #endif /* _CARDWI_H */
index 2423df032d1398b948669995b2275eedf0f71ffa..48d67b03a38361ae1c4123dea6053b0393764333 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     cardwo.c - PCM output HAL for emu10k1 driver
  **********************************************************************
  */
 
+#include <linux/poll.h>
 #include "hwaccess.h"
+#include "8010.h"
+#include "voicemgr.h"
 #include "cardwo.h"
 #include "audio.h"
 
-/* Volume calcs */
-
-static int set_volume_instance(struct emu10k1_waveout *card_waveout, struct wave_out *wave_out, struct voice_param *left)
+static u32 samplerate_to_linearpitch(u32 samplingrate)
 {
-       /* only applicable for playback */
-       u32 volL, volR, vol = 0;
-
-       volL = (wave_out->localvol & 0xffff);
-       volR = ((wave_out->localvol >> 16) & 0xffff);
-
-       if (wave_out->globalvolFactor) {
-               volL = ((u32) (((u16) card_waveout->globalvol & 0xffff) * (u16) volL)) / 0xffff;
-               volR = ((u32) (((u16) (card_waveout->globalvol >> 16) & 0xffff) * ((u16) volR))) / 0xffff;
-       }
-
-       /* BIG ASSUMPTION HERE THAT DEFAULT WAVE PAN/AUX IS 0xff/0xff */
-       /* New volume and pan */
-
-       if (volL == volR) {
-               vol = volL;
-               left->send_c = 0xff;
-               left->send_b = 0xff;
-       } else {
-               if (volL > volR) {
-                       vol = volL;
-                       left->send_c = 0xff;
-                       left->send_b = (char) ((volR * 255) / vol);
-               } else {
-                       vol = volR;
-                       left->send_b = 0xff;
-                       left->send_c = (char) ((volL * 255) / vol);
-               }
-       }
-
-       left->initial_attn = 0xff & sumVolumeToAttenuation(vol * 2);
-
-       return vol;
+       samplingrate = (samplingrate << 8) / 375;
+       return (samplingrate >> 1) + (samplingrate & 1);
 }
 
 static void query_format(struct wave_format *wave_fmt)
@@ -78,593 +47,404 @@ static void query_format(struct wave_format *wave_fmt)
        if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
                wave_fmt->channels = 2;
 
-       if (wave_fmt->samplingrate >= 0x2EE00)
-               wave_fmt->samplingrate = 0x2EE00;
+       if (wave_fmt->samplingrate >= 0x2ee00)
+               wave_fmt->samplingrate = 0x2ee00;
 
        if ((wave_fmt->bitsperchannel != 8) && (wave_fmt->bitsperchannel != 16))
                wave_fmt->bitsperchannel = 16;
 
+       wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
+       wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
+       wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
+
        return;
 }
 
-static int alloc_xferbuffer(struct emu10k1_card *card, struct wave_out *wave_out, u32 * size, void ***buffer)
+static int alloc_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer)
 {
-       u32 numpages, reqsize, pageindex, pagecount;
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
+       u32 pageindex, pagecount;
        unsigned long busaddx;
        int i;
 
-       reqsize = *size;
-       numpages = reqsize / PAGE_SIZE;
-
-       /* If size is not a multiple of PAGE_SIZE then we need to round up */
-       if (reqsize % PAGE_SIZE)
-               numpages += 1;
-
-       DPD(2, "requested pages is: %d\n", numpages);
-
-       wavexferbuf->numpages = numpages;
-
-       /* Only for playback, request for emu address space */
-       /* Support non page-aligned buffer, don't need interpolation page */
+       DPD(2, "requested pages is: %d\n", buffer->pages);
 
-       if ((wave_out->emupageindex = emu10k1_addxmgr_alloc(numpages * PAGE_SIZE, card)) < 0)
-               return CTSTATUS_ERROR;
-
-       if ((wave_out->pagetable = (void **) kmalloc(sizeof(void *) * numpages, GFP_KERNEL)) == NULL)
-               return CTSTATUS_ERROR;
+       if ((buffer->emupageindex = emu10k1_addxmgr_alloc(buffer->pages * PAGE_SIZE, card)) < 0)
+               return -1;
 
        /* Fill in virtual memory table */
-       for (pagecount = 0; pagecount < numpages; pagecount++) {
-               if ((wave_out->pagetable[pagecount] = (void *) __get_free_page(GFP_KERNEL)) == NULL) {
-                       wavexferbuf->numpages = pagecount;
-                       return CTSTATUS_ERROR;
+       for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
+               if ((buffer->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &buffer->dma_handle[pagecount])) == NULL) {
+                       buffer->pages = pagecount;
+                       return -1;
                }
 
-               DPD(2, "Virtual Addx: %p\n", wave_out->pagetable[pagecount]);
+               DPD(2, "Virtual Addx: %p\n", buffer->addr[pagecount]);
 
                for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-                       busaddx = virt_to_bus((u8 *) wave_out->pagetable[pagecount] + i * EMUPAGESIZE);
+                       busaddx = buffer->dma_handle[pagecount] + i * EMUPAGESIZE;
 
                        DPD(3, "Bus Addx: %lx\n", busaddx);
 
-                       pageindex = wave_out->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+                       pageindex = buffer->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
 
-                       ((u32 *) card->virtualpagetable->virtaddx)[pageindex] = ((u32) busaddx * 2) | pageindex;
+                       ((u32 *) card->virtualpagetable.addr)[pageindex] = (busaddx * 2) | pageindex;
                }
        }
 
-       *buffer = wave_out->pagetable;
-
-       return CTSTATUS_SUCCESS;
-}
-
-static int get_xferbuffer(struct emu10k1_card *card, struct wave_out *wave_out, u32 * size)
-{
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
-       void **buffer;
-
-       wavexferbuf->xferpos = 0;
-       wavexferbuf->silence_xferpos = 0;
-       wavexferbuf->stopposition = 0;
-       wavexferbuf->is_stereo = (wave_out->wave_fmt.channels == 2) ? 1 : 0;
-       wavexferbuf->is_16bit = (wave_out->wave_fmt.bitsperchannel == 16) ? 1 : 0;
-       wavexferbuf->bytespersample = (wavexferbuf->is_stereo + 1) * (wavexferbuf->is_16bit + 1);
-
-       if (alloc_xferbuffer(card, wave_out, size, &buffer) != CTSTATUS_SUCCESS)
-               return CTSTATUS_ERROR;
-
-       /* xferbufsize contains actual transfer buffer size */
-       wavexferbuf->xferbufsize = *size;
-       wavexferbuf->xferbuffer = buffer;
-
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
-static void dealloc_xferbuffer(struct emu10k1_card *card, struct wave_out *wave_out)
+static void free_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer)
 {
        u32 pagecount, pageindex;
        int i;
 
-       if (wave_out->pagetable != NULL) {
-               for (pagecount = 0; pagecount < wave_out->wavexferbuf->numpages; pagecount++) {
-                       free_page((unsigned long) wave_out->pagetable[pagecount]);
+       if (buffer->emupageindex < 0)
+               return;
+
+       for (pagecount = 0; pagecount < buffer->pages; pagecount++) {
+               pci_free_consistent(card->pci_dev, PAGE_SIZE, buffer->addr[pagecount], buffer->dma_handle[pagecount]);
 
-                       for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
-                               pageindex = wave_out->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
-                               ((u32 *) card->virtualpagetable->virtaddx)[pageindex] = (card->silentpage->busaddx * 2) | pageindex;
-                       }
+               for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) {
+                       pageindex = buffer->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i;
+                       ((u32 *) card->virtualpagetable.addr)[pageindex] = (card->silentpage.dma_handle * 2) | pageindex;
                }
-               kfree(wave_out->pagetable);
        }
 
-       emu10k1_addxmgr_free(card, wave_out->emupageindex);
+       emu10k1_addxmgr_free(card, buffer->emupageindex);
+       buffer->emupageindex = -1;
 
        return;
 }
 
-static int get_voice(struct emu10k1_card *card, struct wave_out *wave_out, int device)
+static int get_voice(struct emu10k1_card *card, struct woinst *woinst)
 {
-       struct emu10k1_waveout *card_waveout = card->waveout;
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
-       struct voice_allocdesc voice_allocdesc;
-       struct voice_param *left, *right;
-       u32 size;
-
+       struct emu_voice *voice = &woinst->voice;
        /* Allocate voices here, if no voices available, return error.
         * Init voice_allocdesc first.*/
 
-       voice_allocdesc.usage = VOICEMGR_USAGE_PLAYBACK;
-
-       voice_allocdesc.flags = 0;
-
-       if (device == 1)
-               voice_allocdesc.flags |= VOICEMGR_FLAGS_FXRT2;
-
-       if (wave_out->wave_fmt.channels == 1)
-               voice_allocdesc.flags |= VOICEMGR_FLAGS_MONO;
+       voice->usage = VOICE_USAGE_PLAYBACK;
 
-       if (wave_out->wave_fmt.bitsperchannel == 16)
-               voice_allocdesc.flags |= VOICEMGR_FLAGS_16BIT;
+       voice->flags = 0;
 
-       if ((wave_out->voice = emu10k1_voice_alloc(&card->voicemgr, &voice_allocdesc)) == NULL)
-               return CTSTATUS_ERROR;
+       if (woinst->format.channels == 2)
+               voice->flags |= VOICE_FLAGS_STEREO;
 
-       /* voice initialization */
+       if (woinst->format.bitsperchannel == 16)
+               voice->flags |= VOICE_FLAGS_16BIT;
 
-       left = &wave_out->voice->params;
+       if (emu10k1_voice_alloc(card, voice) < 0)
+               return -1;
 
        /* Calculate pitch */
-       left->initial_pitch = (u16) (srToPitch(wave_out->wave_fmt.samplingrate) >> 8);
+       voice->initial_pitch = (u16) (srToPitch(woinst->format.samplingrate) >> 8);
+       voice->pitch_target = samplerate_to_linearpitch(woinst->format.samplingrate);
 
-       DPD(2, "Initial pitch --> %x\n", left->initial_pitch);
+       DPD(2, "Initial pitch --> 0x%x\n", voice->initial_pitch);
 
-       /* Easy way out.. gotta calculate value */
-       left->pitch_target = 0;
-       left->volume_target = 0;
-       left->FC_target = 0;
+       voice->startloop = (woinst->buffer.emupageindex << 12) / woinst->format.bytespersample;
+       voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespersample;
+       voice->start = voice->startloop;
 
-       left->byampl_env_sustain = 0x7f;
-       left->byampl_env_decay = 0x7f;
+       if (voice->flags & VOICE_FLAGS_STEREO) {
+               voice->params[0].send_a = card->waveout.send_a[1];
+               voice->params[0].send_b = card->waveout.send_b[1];
+               voice->params[0].send_c = card->waveout.send_c[1];
+               voice->params[0].send_d = card->waveout.send_d[1];
 
-       if (wave_out->globalreverbFactor) {
-               u8 t = (card_waveout->globalreverb & 0xff) + (wave_out->localreverb & 0xff);
+               if (woinst->device)
+                       voice->params[0].send_routing = 0xd23c;
+               else
+                       voice->params[0].send_routing = card->waveout.send_routing[1];
 
-               left->send_a = (t > 255) ? 255 : t;
-       } else {
-               left->send_a = 0;
-       }
+               voice->params[0].volume_target = 0xffff;
+               voice->params[0].initial_fc = 0xff;
+               voice->params[0].initial_attn = 0x00;
+               voice->params[0].byampl_env_sustain = 0x7f;
+               voice->params[0].byampl_env_decay = 0x7f;
 
-       if (wave_out->globalchorusFactor) {
-               u8 t = (card_waveout->globalchorus & 0xff) + (wave_out->localchorus & 0xff);
+               voice->params[1].send_a = card->waveout.send_a[2];
+               voice->params[1].send_b = card->waveout.send_b[2];
+               voice->params[1].send_c = card->waveout.send_c[2];
+               voice->params[1].send_d = card->waveout.send_d[2];
+
+               if (woinst->device)
+                       voice->params[1].send_routing = 0xd23c;
+               else
+                       voice->params[1].send_routing = card->waveout.send_routing[2];
 
-               left->send_d = (t > 255) ? 255 : t;
+               voice->params[1].volume_target = 0xffff;
+               voice->params[1].initial_fc = 0xff;
+               voice->params[1].initial_attn = 0x00;
+               voice->params[1].byampl_env_sustain = 0x7f;
+               voice->params[1].byampl_env_decay = 0x7f;
        } else {
-               left->send_d = 0;
+               voice->params[0].send_a = card->waveout.send_a[0];
+               voice->params[0].send_b = card->waveout.send_b[0];
+               voice->params[0].send_c = card->waveout.send_c[0];
+               voice->params[0].send_d = card->waveout.send_d[0];
+
+               if (woinst->device)
+                        voice->params[0].send_routing = 0xd23c;
+                else
+                       voice->params[0].send_routing = card->waveout.send_routing[0];
+
+               voice->params[0].volume_target = 0xffff;
+               voice->params[0].initial_fc = 0xff;
+               voice->params[0].initial_attn = 0x00;
+               voice->params[0].byampl_env_sustain = 0x7f;
+               voice->params[0].byampl_env_decay = 0x7f;
        }
 
-       set_volume_instance(card_waveout, wave_out, left);
-
-       left->pan_target = left->send_c;
-       left->aux_target = left->send_b;
-
-       size = wavexferbuf->xferbufsize / wavexferbuf->bytespersample;
-       left->start = 2 * (wave_out->emupageindex << 11) / wavexferbuf->bytespersample;
-       left->end = left->start + size;
-       left->startloop = left->start;
-       left->endloop = left->end;
-
-       if (wave_out->voice->linked_voice) {
-               DPF(2, "is stereo\n");
-               right = &wave_out->voice->linked_voice->params;
-
-               right->initial_pitch = left->initial_pitch;
+       DPD(2, "voice: startloop=0x%x, endloop=0x%x\n", voice->startloop, voice->endloop);
 
-               /* Easy way out.. gotta calculate value */
-               right->pitch_target = 0;
-               right->volume_target = 0;
-               right->FC_target = 0;
+       emu10k1_voice_playback_setup(voice);
 
-               right->byampl_env_sustain = 0x7f;
-               right->byampl_env_decay = 0x7f;
-
-               right->send_d = left->send_d;
-               right->send_a = left->send_a;
-
-               /* Left output of right channel is always zero */
-               right->send_c = 0;
-
-               /* Update right channel aux */
-               right->pan_target = 0;
-               right->send_b = left->send_b;
-               right->aux_target = right->send_b;
-
-               /* Zero out right output of left channel */
-               left->send_b = 0;
-               left->aux_target = 0;
-
-               /* Update right channel attenuation */
-               right->initial_attn = left->initial_attn;
-
-               right->start = left->start;
-               right->end = left->end;
-               right->startloop = left->startloop;
-               right->endloop = left->endloop;
-
-       }
-
-       DPD(2, "voice: start=%x, end=%x, startloop=%x, endloop=%x\n", left->start, left->end, left->startloop, left->endloop);
-
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int emu10k1_waveout_open(struct emu10k1_wavedevice *wave_dev)
 {
        struct emu10k1_card *card = wave_dev->card;
        struct woinst *woinst = wave_dev->woinst;
-       struct wave_out *wave_out;
-       u32 bytespersec, delay;
-       u32 buffsize;
+       u32 delay;
 
        DPF(2, "emu10k1_waveout_open()\n");
 
-       if ((wave_out = (struct wave_out *) kmalloc(sizeof(struct wave_out), GFP_KERNEL)) == NULL) {
-               ERROR();
-               emu10k1_waveout_close(wave_dev);
-               return CTSTATUS_ERROR;
-       }
-
-       woinst->wave_out = wave_out;
-
-       /* Init channel object */
-       wave_out->state = CARDWAVE_STATE_STOPPED;
-       wave_out->wave_fmt = woinst->wave_fmt;
-       wave_out->voice = NULL;
-       wave_out->emupageindex = -1;
-       wave_out->wavexferbuf = NULL;
-       wave_out->pagetable = NULL;
-       wave_out->timer = NULL;
-
-       /* Assign default local volume */
-       /* FIXME: Should we be maxing the initial values like this? */
-       wave_out->localvol = 0xffffffff;
-       wave_out->localreverb = 0xffffffff;
-       wave_out->localchorus = 0xffffffff;
-       wave_out->globalvolFactor = 0xffff;
-       wave_out->globalreverbFactor = 0xffff;
-       wave_out->globalchorusFactor = 0xffff;
-
-       wave_out->setpos = 0;
-       wave_out->position = 0;
-
-       wave_out->fill_silence = 0;
-
-       if ((wave_out->wavexferbuf = (struct wave_xferbuf *) kmalloc(sizeof(struct wave_xferbuf), GFP_KERNEL)) == NULL) {
+       if (alloc_buffer(card, &woinst->buffer) < 0) {
                ERROR();
                emu10k1_waveout_close(wave_dev);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       buffsize = woinst->fragment_size * woinst->numfrags;
+       woinst->buffer.fill_silence = 0;
+       woinst->buffer.silence_bytes = 0;
+       woinst->buffer.silence_pos = 0;
+       woinst->buffer.hw_pos = 0;
+       woinst->buffer.bytestocopy = woinst->buffer.size;
 
-       if (get_xferbuffer(card, wave_out, &buffsize) != CTSTATUS_SUCCESS) {
+       if (get_voice(card, woinst) < 0) {
                ERROR();
                emu10k1_waveout_close(wave_dev);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       woinst->fragment_size = buffsize / woinst->numfrags;
-       wave_out->callbacksize = woinst->fragment_size;
+       delay = (48000 * woinst->buffer.fragment_size) / woinst->format.bytespersec;
 
-       if (get_voice(card, wave_out, woinst->device) != CTSTATUS_SUCCESS) {
-               ERROR();
-               emu10k1_waveout_close(wave_dev);
-               return CTSTATUS_ERROR;
-       }
+       emu10k1_timer_install(card, &woinst->timer, delay / 2);
 
-       bytespersec = wave_out->wave_fmt.channels * (wave_out->wave_fmt.bitsperchannel >> 3) * (wave_out->wave_fmt.samplingrate);
-       delay = (48000 * wave_out->callbacksize) / bytespersec;
+       woinst->state = WAVE_STATE_OPEN;
 
-       if ((wave_out->timer = emu10k1_timer_install(card, emu10k1_waveout_bh, (unsigned long) wave_dev, delay / 2)) == NULL) {
-               ERROR();
-               emu10k1_waveout_close(wave_dev);
-               return CTSTATUS_ERROR;
-       }
-
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 void emu10k1_waveout_close(struct emu10k1_wavedevice *wave_dev)
 {
        struct emu10k1_card *card = wave_dev->card;
-       struct wave_out *wave_out = wave_dev->woinst->wave_out;
+       struct woinst *woinst = wave_dev->woinst;
 
        DPF(2, "emu10k1_waveout_close()\n");
 
-       if (wave_out->state != CARDWAVE_STATE_STOPPED)
-               emu10k1_waveout_stop(wave_dev);
+       emu10k1_waveout_stop(wave_dev);
 
-       if (wave_out->timer != NULL)
-               emu10k1_timer_uninstall(card, wave_out->timer);
+       emu10k1_timer_uninstall(card, &woinst->timer);
 
-       if (wave_out->voice != NULL)
-               emu10k1_voice_free(&card->voicemgr, wave_out->voice);
+       emu10k1_voice_free(&woinst->voice);
 
-       if (wave_out->emupageindex >= 0)
-               dealloc_xferbuffer(card, wave_out);
+       free_buffer(card, &woinst->buffer);
 
-       if (wave_out->wavexferbuf != NULL)
-               kfree(wave_out->wavexferbuf);
-
-       kfree(wave_out);
-       wave_dev->woinst->wave_out = NULL;
+       woinst->state = WAVE_STATE_CLOSED;
 
        return;
 }
 
-int emu10k1_waveout_start(struct emu10k1_wavedevice *wave_dev)
+void emu10k1_waveout_start(struct emu10k1_wavedevice *wave_dev)
 {
        struct emu10k1_card *card = wave_dev->card;
-       struct wave_out *wave_out = wave_dev->woinst->wave_out;
-       u32 start, startPosition;
+       struct woinst *woinst = wave_dev->woinst;
 
        DPF(2, "emu10k1_waveout_start()\n");
-
-       /* If already started, return success */
-       if (wave_out->state == CARDWAVE_STATE_STARTED)
-               return CTSTATUS_SUCCESS;
-
-       if (wave_out->state == CARDWAVE_STATE_STOPPED && wave_out->setpos)
-               startPosition = wave_out->position / (wave_out->wavexferbuf->bytespersample);
-       else
-               startPosition = wave_out->wavexferbuf->stopposition;
-
-       start = wave_out->voice->params.start;
-       wave_out->voice->params.start += startPosition;
-
-       DPD(2, "CA is %x\n", wave_out->voice->params.start);
-
-       emu10k1_voice_playback_setup(wave_out->voice);
-
-       wave_out->voice->params.start = start;
-
        /* Actual start */
-       emu10k1_voice_start(wave_out->voice);
 
-       wave_out->state = CARDWAVE_STATE_STARTED;
-       wave_out->setpos = 0;
+       emu10k1_voice_start(&woinst->voice, woinst->total_played);
 
-       emu10k1_timer_enable(card, wave_out->timer);
+       emu10k1_timer_enable(card, &woinst->timer);
 
-       return CTSTATUS_SUCCESS;
+       woinst->state |= WAVE_STATE_STARTED;
+
+       return;
 }
 
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev)
+int emu10k1_waveout_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
 {
        struct emu10k1_card *card = wave_dev->card;
        struct woinst *woinst = wave_dev->woinst;
-       struct wave_out *wave_out = woinst->wave_out;
-       u32 bytespersec, delay;
+       u32 delay;
 
        DPF(2, "emu10k1_waveout_setformat()\n");
 
-       query_format(&woinst->wave_fmt);
+       if (woinst->state & WAVE_STATE_STARTED)
+               return -1;
 
-       if (wave_out == NULL)
-               return CTSTATUS_SUCCESS;
-
-       if (wave_out->state == CARDWAVE_STATE_STARTED) {
-               woinst->wave_fmt = wave_out->wave_fmt;
-               return CTSTATUS_SUCCESS;
-       }
+       query_format(format);
 
-       if ((wave_out->wave_fmt.samplingrate != woinst->wave_fmt.samplingrate)
-           || (wave_out->wave_fmt.bitsperchannel != woinst->wave_fmt.bitsperchannel)
-           || (wave_out->wave_fmt.channels != woinst->wave_fmt.channels)) {
-               struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
+       if (woinst->format.samplingrate != format->samplingrate ||
+           woinst->format.channels != format->channels ||
+           woinst->format.bitsperchannel != format->bitsperchannel) {
 
-               emu10k1_timer_uninstall(card, wave_out->timer);
+               woinst->format = *format;
 
-               emu10k1_voice_free(&card->voicemgr, wave_out->voice);
+               if (woinst->state == WAVE_STATE_CLOSED)
+                       return 0;
 
-               wave_out->wave_fmt = woinst->wave_fmt;
-               wave_out->timer = NULL;
+               emu10k1_timer_uninstall(card, &woinst->timer);
+               emu10k1_voice_free(&woinst->voice);
 
-               wavexferbuf->xferpos = 0;
-               wavexferbuf->silence_xferpos = 0;
-               wavexferbuf->stopposition = 0;
-               wavexferbuf->is_stereo = (wave_out->wave_fmt.channels == 2) ? 1 : 0;
-               wavexferbuf->is_16bit = (wave_out->wave_fmt.bitsperchannel == 16) ? 1 : 0;
-               wavexferbuf->bytespersample = (wavexferbuf->is_stereo + 1) * (wavexferbuf->is_16bit + 1);
-
-               if (get_voice(card, wave_out, woinst->device) != CTSTATUS_SUCCESS) {
+               if (get_voice(card, woinst) < 0) {
                        ERROR();
                        emu10k1_waveout_close(wave_dev);
-                       return CTSTATUS_ERROR;
+                       return -1;
                }
 
-               bytespersec = wave_out->wave_fmt.channels * (wave_out->wave_fmt.bitsperchannel >> 3) * (wave_out->wave_fmt.samplingrate);
-               delay = (48000 * wave_out->callbacksize) / bytespersec;
+               delay = (48000 * woinst->buffer.fragment_size) / woinst->format.bytespersec;
 
-               if ((wave_out->timer = emu10k1_timer_install(card, emu10k1_waveout_bh, (unsigned long) wave_dev, delay / 2)) == NULL) {
-                       ERROR();
-                       emu10k1_waveout_close(wave_dev);
-                       return CTSTATUS_ERROR;
-               }
+               emu10k1_timer_install(card, &woinst->timer, delay / 2);
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 void emu10k1_waveout_stop(struct emu10k1_wavedevice *wave_dev)
 {
        struct emu10k1_card *card = wave_dev->card;
-       struct wave_out *wave_out = wave_dev->woinst->wave_out;
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
-       u32 samples = 32;
-       u32 position;
+       struct woinst *woinst = wave_dev->woinst;
 
        DPF(2, "emu10k1_waveout_stop()\n");
 
-       if (wave_out->state == CARDWAVE_STATE_STOPPED)
+       if (!(woinst->state & WAVE_STATE_STARTED))
                return;
 
-       emu10k1_timer_disable(card, wave_out->timer);
+       emu10k1_timer_disable(card, &woinst->timer);
 
        /* Stop actual voice */
-       emu10k1_voice_stop(wave_out->voice);
-
-       /* Save the stop position */
-       emu10k1_voice_getcontrol(wave_out->voice, CCCA_CURRADDR, &wavexferbuf->stopposition);
-
-       wavexferbuf->stopposition -= wave_out->voice->params.start;
-
-       /* Refer to voicemgr.c, CA is not started at zero.  We need to take this into account. */
-       position = wavexferbuf->stopposition * wavexferbuf->bytespersample;
+       emu10k1_voice_stop(&woinst->voice);
 
-       if (!wavexferbuf->is_16bit)
-               samples <<= 1;
+       emu10k1_waveout_update(woinst);
 
-       if (wavexferbuf->is_stereo)
-               samples <<= 1;
-
-       samples -= 4;
-
-       if (position >= samples * (wavexferbuf->is_16bit + 1))
-               position -= samples * (wavexferbuf->is_16bit + 1);
-       else
-               position += wavexferbuf->xferbufsize - samples * (wavexferbuf->is_16bit + 1);
-
-       wavexferbuf->stopposition = position / wavexferbuf->bytespersample;
-
-       DPD(2, "position is %x\n", wavexferbuf->stopposition);
-
-       wave_out->state = CARDWAVE_STATE_STOPPED;
-       wave_out->setpos = 0;
-       wave_out->position = 0;
+       woinst->state &= ~WAVE_STATE_STARTED;
 
        return;
 }
 
-void emu10k1_waveout_getxfersize(struct wave_out *wave_out, u32 * size, u32 * pending, u32 * curpos)
+void emu10k1_waveout_getxfersize(struct woinst *woinst, u32 * size)
 {
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
-
-       /* Get position of current address, this is in no. of bytes in play buffer */
-       emu10k1_waveout_getcontrol(wave_out, WAVECURPOS, curpos);
-
-       if ((*curpos > wavexferbuf->silence_xferpos)
-           || ((*curpos == wavexferbuf->silence_xferpos)
-               && (wave_out->state == CARDWAVE_STATE_STARTED))
-           || ((*curpos == wavexferbuf->silence_xferpos) && (wavexferbuf->silence_xferpos != 0)
-               && (wave_out->state == CARDWAVE_STATE_STOPPED))) {
-               *size = *curpos - wavexferbuf->silence_xferpos;
-               *pending = wavexferbuf->xferbufsize - *size;
-       } else {
-               *pending = wavexferbuf->silence_xferpos - *curpos;
-               *size = wavexferbuf->xferbufsize - *pending;
+       struct waveout_buffer *buffer = &woinst->buffer;
+       int pending;
+
+       if (woinst->mmapped) {
+               *size = buffer->bytestocopy;
+               return;
        }
 
-       if (wavexferbuf->silence_xferpos != wavexferbuf->xferpos) {
-               if (*pending < wave_out->callbacksize) {
-                       wave_out->fill_silence = 2;
-                       *pending = 0;
-                       *size = wavexferbuf->xferbufsize;
-                       wavexferbuf->xferpos = *curpos;
-               } else {
-                       if (wave_out->fill_silence == 2) {
-                               *pending = 0;
-                               *size = wavexferbuf->xferbufsize;
-                               wavexferbuf->xferpos = *curpos;
-                       } else {
-                               *pending -= wave_out->callbacksize;
-                               *size += wave_out->callbacksize;
-                       }
-               }
+       pending = buffer->size - buffer->bytestocopy;
+
+       buffer->fill_silence = (pending < (signed) buffer->fragment_size) ? 1 : 0;
+
+       if (pending > (signed) buffer->silence_bytes) {
+               *size = buffer->bytestocopy + buffer->silence_bytes;
        } else {
-               if (*pending < wave_out->callbacksize)
-                       wave_out->fill_silence = 1;
-               else
-                       wave_out->fill_silence = 0;
+               *size = buffer->size;
+               buffer->silence_bytes = pending;
+               if (pending < 0) {
+                       buffer->silence_pos = buffer->hw_pos;
+                       buffer->silence_bytes = 0;
+                       buffer->bytestocopy = buffer->size;
+                       DPF(1, "buffer underrun\n");
+               }
        }
 
        return;
 }
 
-static void copy_block(u32 dst, u8 * src, u32 len, void **pt)
+static void copy_block(void **dst, u32 str, u8 *src, u32 len)
 {
        int i, j, k;
 
-       i = dst / PAGE_SIZE;
-       j = dst % PAGE_SIZE;
-       k = (len > PAGE_SIZE - j) ? PAGE_SIZE - j : len;
-       copy_from_user(pt[i] + j, src, k);
-       len -= k;
-       while (len >= PAGE_SIZE) {
-               copy_from_user(pt[++i], src + k, PAGE_SIZE);
-               k += PAGE_SIZE;
-               len -= PAGE_SIZE;
-       }
-       copy_from_user(pt[++i], src + k, len);
+       i = str / PAGE_SIZE;
+       j = str % PAGE_SIZE;
+
+       if (len > PAGE_SIZE - j) {
+               k = PAGE_SIZE - j;
+               copy_from_user(dst[i] + j, src, k);
+               len -= k;
+               while (len > PAGE_SIZE) {
+                       copy_from_user(dst[++i], src + k, PAGE_SIZE);
+                       k += PAGE_SIZE;
+                       len -= PAGE_SIZE;
+               }
+               copy_from_user(dst[++i], src + k, len);
+
+       } else
+               copy_from_user(dst[i] + j, src, len);
 
        return;
 }
 
-static void fill_block(u32 dst, u8 val, u32 len, void **pt)
+static void fill_block(void **dst, u32 str, u8 src, u32 len)
 {
        int i, j, k;
 
-       i = dst / PAGE_SIZE;
-       j = dst % PAGE_SIZE;
-       k = (len > PAGE_SIZE - j) ? PAGE_SIZE - j : len;
-       memset(pt[i] + j, val, k);
-       len -= k;
-       while (len >= PAGE_SIZE) {
-               memset(pt[++i], val, PAGE_SIZE);
-               len -= PAGE_SIZE;
-       }
-       memset(pt[++i], val, len);
+       i = str / PAGE_SIZE;
+       j = str % PAGE_SIZE;
+
+       if (len > PAGE_SIZE - j) {
+                k = PAGE_SIZE - j;
+                memset(dst[i] + j, src, k);
+                len -= k;
+                while (len > PAGE_SIZE) {
+                        memset(dst[++i], src, PAGE_SIZE);
+                        len -= PAGE_SIZE;
+                }
+                memset(dst[++i], src, len);
+
+        } else
+                memset(dst[i] + j, src, len);
 
        return;
 }
 
-void emu10k1_waveout_xferdata(struct woinst *woinst, u8 * data, u32 * size)
+void emu10k1_waveout_xferdata(struct woinst *woinst, u8 *data, u32 *size)
 {
-       struct wave_out *wave_out = woinst->wave_out;
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
+       struct waveout_buffer *buffer = &woinst->buffer;
        u32 sizetocopy, sizetocopy_now, start;
        unsigned long flags;
 
-       sizetocopy = min(wavexferbuf->xferbufsize, *size);
+       sizetocopy = min(buffer->size, *size);
        *size = sizetocopy;
 
        if (!sizetocopy)
                return;
 
        spin_lock_irqsave(&woinst->lock, flags);
+       start = (buffer->size + buffer->silence_pos - buffer->silence_bytes) % buffer->size;
 
-       sizetocopy_now = wavexferbuf->xferbufsize - wavexferbuf->xferpos;
+       if(sizetocopy > buffer->silence_bytes) {
+               buffer->silence_pos += sizetocopy - buffer->silence_bytes;
+               buffer->bytestocopy -= sizetocopy - buffer->silence_bytes;
+               buffer->silence_bytes = 0;
+       } else
+               buffer->silence_bytes -= sizetocopy;
 
-       start = wavexferbuf->xferpos;
+       sizetocopy_now = buffer->size - start;
+
+       spin_unlock_irqrestore(&woinst->lock, flags);
 
        if (sizetocopy > sizetocopy_now) {
                sizetocopy -= sizetocopy_now;
-               wavexferbuf->xferpos = sizetocopy;
-               wavexferbuf->silence_xferpos = wavexferbuf->xferpos;
-               spin_unlock_irqrestore(&woinst->lock, flags);
-
-               copy_block(start, data, sizetocopy_now, wavexferbuf->xferbuffer);
-               copy_block(0, data + sizetocopy_now, sizetocopy, wavexferbuf->xferbuffer);
+               copy_block(buffer->addr, start, data, sizetocopy_now);
+               copy_block(buffer->addr, 0, data + sizetocopy_now, sizetocopy);
        } else {
-               if (sizetocopy == sizetocopy_now)
-                       wavexferbuf->xferpos = 0;
-               else
-                       wavexferbuf->xferpos += sizetocopy;
-
-               wavexferbuf->silence_xferpos = wavexferbuf->xferpos;
-               spin_unlock_irqrestore(&woinst->lock, flags);
-
-               copy_block(start, data, sizetocopy, wavexferbuf->xferbuffer);
+               copy_block(buffer->addr, start, data, sizetocopy);
        }
 
        return;
@@ -672,84 +452,63 @@ void emu10k1_waveout_xferdata(struct woinst *woinst, u8 * data, u32 * size)
 
 void emu10k1_waveout_fillsilence(struct woinst *woinst)
 {
-       struct wave_out *wave_out = woinst->wave_out;
-       struct wave_xferbuf *wavexferbuf = wave_out->wavexferbuf;
+       struct waveout_buffer *buffer = &woinst->buffer;
        u16 filldata;
        u32 sizetocopy, sizetocopy_now, start;
        unsigned long flags;
 
-       sizetocopy = wave_out->callbacksize;
+       sizetocopy = woinst->buffer.fragment_size;
 
-       if (wave_out->wave_fmt.bitsperchannel == 8)
-               filldata = 0x8080;
-       else
+       if (woinst->format.bitsperchannel == 16)
                filldata = 0x0000;
+       else
+               filldata = 0x8080;
 
        spin_lock_irqsave(&woinst->lock, flags);
+       buffer->silence_bytes += sizetocopy;
+       buffer->bytestocopy -= sizetocopy;
+       buffer->silence_pos %= buffer->size;
+       start = buffer->silence_pos;
+       buffer->silence_pos += sizetocopy;
+       sizetocopy_now = buffer->size - start;
 
-       sizetocopy_now = wavexferbuf->xferbufsize - wavexferbuf->silence_xferpos;
-       start = wavexferbuf->silence_xferpos;
+       spin_unlock_irqrestore(&woinst->lock, flags);
 
        if (sizetocopy > sizetocopy_now) {
                sizetocopy -= sizetocopy_now;
-               wavexferbuf->silence_xferpos = sizetocopy;
-               spin_unlock_irqrestore(&woinst->lock, flags);
-               fill_block(start, filldata, sizetocopy_now, wavexferbuf->xferbuffer);
-               fill_block(0, filldata, sizetocopy, wavexferbuf->xferbuffer);
+               fill_block(buffer->addr, start, filldata, sizetocopy_now);
+               fill_block(buffer->addr, 0, filldata, sizetocopy);
        } else {
-               if (sizetocopy == sizetocopy_now)
-                       wavexferbuf->silence_xferpos = 0;
-               else
-                       wavexferbuf->silence_xferpos += sizetocopy;
-
-               spin_unlock_irqrestore(&woinst->lock, flags);
-
-               fill_block(start, filldata, sizetocopy, wavexferbuf->xferbuffer);
+               fill_block(buffer->addr, start, filldata, sizetocopy);
        }
 
        return;
 }
 
-/* get the specified control value of the wave device. */
-
-int emu10k1_waveout_getcontrol(struct wave_out *wave_out, u32 ctrl_id, u32 * value)
+void emu10k1_waveout_update(struct woinst *woinst)
 {
-       switch (ctrl_id) {
-       case WAVECURPOS:
-               /* There is no actual start yet */
-               if (wave_out->state == CARDWAVE_STATE_STOPPED) {
-                       if (wave_out->setpos)
-                               *value = wave_out->position;
-                       else
-                               *value = wave_out->wavexferbuf->stopposition * wave_out->wavexferbuf->bytespersample;
-               } else {
-                       emu10k1_voice_getcontrol(wave_out->voice, CCCA_CURRADDR, value);
-
-                       *value -= wave_out->voice->params.start;
-
-                       /* Get number of bytes in play buffer per channel.
-                        * If 8 bit mode is enabled, this needs to be changed. */
-                       {
-                               u32 samples = 64 * (wave_out->wavexferbuf->is_stereo + 1);
-
-                               *value *= wave_out->wavexferbuf->bytespersample;
-
-                               /* Refer to voicemgr.c, CA is not started at zero.
-                                * We need to take this into account. */
-
-                               samples -= 4 * (wave_out->wavexferbuf->is_16bit + 1);
-
-                               if (*value >= samples)
-                                       *value -= samples;
-                               else
-                                       *value += wave_out->wavexferbuf->xferbufsize - samples;
-                       }
-               }
+       u32 hw_pos;
+       u32 diff;
+
+       /* There is no actual start yet */
+       if (!(woinst->state & WAVE_STATE_STARTED)) {
+               hw_pos = woinst->buffer.hw_pos;
+       } else {
+               /* hw_pos in sample units */
+               hw_pos = sblive_readptr(woinst->voice.card, CCCA_CURRADDR, woinst->voice.num);
 
-               break;
-       default:
-               return CTSTATUS_ERROR;
+               if(hw_pos < woinst->voice.start)
+                       hw_pos += woinst->buffer.size / woinst->format.bytespersample - woinst->voice.start;
+               else
+                       hw_pos -= woinst->voice.start;
+
+               hw_pos *= woinst->format.bytespersample;
        }
 
-       return CTSTATUS_SUCCESS;
+       diff = (woinst->buffer.size + hw_pos - woinst->buffer.hw_pos) % woinst->buffer.size;
+       woinst->total_played += diff;
+       woinst->buffer.bytestocopy += diff;
+       woinst->buffer.hw_pos = hw_pos;
+
+       return;
 }
index 20391432a0cefc8d0dac06221597f517f581b73c..2e31846a24e6a877dd37aa6b365c40180f064ab7 100644 (file)
 #define _CARDWO_H
 
 #include "icardwav.h"
+#include "audio.h"
+#include "voicemgr.h"
+#include "timer.h"
 
-struct wave_xferbuf 
-{
-       u32     xferpos;
-       u32     silence_xferpos;
-       u32     xferbufsize;     /* transfer buffer size */
-       u32     numpages;        /* number of pages in transfer buffer */
-       void    **xferbuffer;    /* pointer to the transfer buffer */
-       int     is_stereo;
-       int     is_16bit;
-       int     bytespersample;
-       u32     stopposition;
-};
-
-struct wave_out
-{
-    u32             state;
-    struct emu_voice *voice;
-    int             emupageindex;
-    struct emu_timer *timer;
-    struct wave_xferbuf *wavexferbuf;
-    void           **pagetable;
-    u32             callbacksize;
-    u32             localvol;
-    u32             localreverb;
-    u32             localchorus;
-    u32             globalvolFactor;
-    u32             globalreverbFactor;
-    u32             globalchorusFactor;
-    int             setpos;
-    u32             position;
-    struct wave_format      wave_fmt;
-    int             fill_silence;
-};
+/* setting this to other than a power of two may break some applications */
+#define WAVEOUT_MAXBUFSIZE     MAXBUFSIZE
+#define WAVEOUT_MINBUFSIZE     64
 
-/* setting this to other than a power of two
-   may break some applications */
-#define WAVEOUT_MAXBUFSIZE          32768 
-#define WAVEOUT_MINBUFSIZE         64
+#define WAVEOUT_DEFAULTFRAGLEN 20 /* Time to play a fragment in ms (latency) */
+#define WAVEOUT_DEFAULTBUFLEN  500 /* Time to play the entire buffer in ms */
 
-#define WAVEOUT_DEFAULTFRAGLEN      100 /* Time to play a fragment in ms (latency) */
-#define WAVEOUT_DEFAULTBUFLEN       1000 /* Time to play the entire buffer in ms */
+#define WAVEOUT_MINFRAGSHIFT   6
 
-#define WAVEOUT_MINFRAGSHIFT   4
+struct waveout_buffer {
+       u16 ossfragshift;
+        u32 numfrags;
+       u32 fragment_size;      /* in bytes units */
+       u32 size;               /* in bytes units */
+       u32 pages;              /* buffer size in page units*/
+       int emupageindex;
+       void *addr[BUFMAXPAGES];
+       dma_addr_t dma_handle[BUFMAXPAGES];
+        u32 silence_pos;       /* software cursor position (including silence) */
+       u32 hw_pos;             /* hardware cursor position */
+       u32 bytestocopy;        /* free space on buffer (including silence) */
+       u8 fill_silence;
+       u32 silence_bytes;      /* silence bytes in buffer */
+};
 
 struct woinst 
 {
-        struct wave_out *wave_out;
-        struct wave_format wave_fmt;
-        u16 ossfragshift;
-        u32 fragment_size;
-        u32 numfrags;
+       u8 state;
+       struct emu_voice voice;
+       struct emu_timer timer;
+        struct wave_format format;
+       struct waveout_buffer buffer;
         wait_queue_head_t wait_queue;
-        int mapped;
-        u32 total_copied;
-        u32 total_played;
+        u8 mmapped;
+        u32 total_copied;      /* total number of bytes written() to the buffer (excluding silence) */
+        u32 total_played;      /* total number of bytes played including silence */
         u32 blocks;
-       u32 curpos;
-       u32 device;
+       u8 device;
        spinlock_t lock;
 };
 
-struct emu10k1_waveout
-{
-       u32 globalvol;
-       u32 mute;
-       u32 left;
-       u32 right;
-       u32 globalreverb;
-       u32 globalchorus;
-};
-
 int emu10k1_waveout_open(struct emu10k1_wavedevice *);
 void emu10k1_waveout_close(struct emu10k1_wavedevice *);
-int emu10k1_waveout_start(struct emu10k1_wavedevice *);
+void emu10k1_waveout_start(struct emu10k1_wavedevice *);
 void emu10k1_waveout_stop(struct emu10k1_wavedevice *);
-void emu10k1_waveout_getxfersize(struct wave_out *, u32 *, u32 *, u32 *);
+void emu10k1_waveout_getxfersize(struct woinst*, u32 *);
 void emu10k1_waveout_xferdata(struct woinst*, u8*, u32 *);
 void emu10k1_waveout_fillsilence(struct woinst*);
-int emu10k1_waveout_setformat(struct emu10k1_wavedevice*);
-int emu10k1_waveout_getcontrol(struct wave_out*, u32, u32 *);
+int emu10k1_waveout_setformat(struct emu10k1_wavedevice*, struct wave_format*);
+void emu10k1_waveout_update(struct woinst*);
 
 #endif /* _CARDWO_H */
diff --git a/drivers/sound/emu10k1/ecard.c b/drivers/sound/emu10k1/ecard.c
new file mode 100644 (file)
index 0000000..9d56e0b
--- /dev/null
@@ -0,0 +1,155 @@
+/*     
+ **********************************************************************
+ *     ecard.c - E-card initialization code
+ *     Copyright 1999, 2000 Creative Labs, Inc. 
+ * 
+ ********************************************************************** 
+ * 
+ *     Date                 Author          Summary of changes 
+ *     ----                 ------          ------------------ 
+ *     October 20, 1999     Bertrand Lee    base code release 
+ * 
+ ********************************************************************** 
+ * 
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version. 
+ * 
+ *     This program is distributed in the hope that it will be useful, 
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *     GNU General Public License for more details. 
+ * 
+ *     You should have received a copy of the GNU General Public 
+ *     License along with this program; if not, write to the Free 
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
+ *     USA. 
+ * 
+ ********************************************************************** 
+ */ 
+
+#include "ecard.h"
+#include "hwaccess.h"
+
+/* Private routines */
+static void ecard_setadcgain(struct emu10k1_card *, struct ecard_state *, u16);
+static void ecard_write(struct emu10k1_card *, u32);
+
+/**************************************************************************
+ * @func Set the gain of the ECARD's CS3310 Trim/gain controller.  The
+ * trim value consists of a 16bit value which is composed of two
+ * 8 bit gain/trim values, one for the left channel and one for the
+ * right channel.  The following table maps from the Gain/Attenuation
+ * value in decibels into the corresponding bit pattern for a single
+ * channel.
+ */
+
+static void ecard_setadcgain(struct emu10k1_card *card, struct ecard_state *ecard, u16 gain)
+{
+       u32 currbit;
+       ecard->adc_gain = gain;
+
+       /* Enable writing to the TRIM registers */
+       ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
+
+       /* Do it again to insure that we meet hold time requirements */
+       ecard_write(card, ecard->control_bits & ~EC_TRIM_CSN);
+
+       for (currbit = (1L << 15); currbit; currbit >>= 1) {
+
+               u32 value = ecard->control_bits & ~(EC_TRIM_CSN|EC_TRIM_SDATA);
+
+               if (gain & currbit)
+                     value |= EC_TRIM_SDATA;
+
+               /* Clock the bit */
+               ecard_write(card, value);
+               ecard_write(card, value | EC_TRIM_SCLK);
+               ecard_write(card, value);
+       }
+
+       ecard_write(card, ecard->control_bits);
+}
+
+/**************************************************************************
+ * @func Clock bits into the Ecard's control latch.  The Ecard uses a
+ *  control latch will is loaded bit-serially by toggling the Modem control
+ *  lines from function 2 on the E8010.  This function hides these details
+ *  and presents the illusion that we are actually writing to a distinct
+ *  register.
+ */
+static void ecard_write(struct emu10k1_card *card, u32 value)
+{
+       u16 count;
+       u32 data, hcvalue;
+
+       hcvalue = emu10k1_readfn0(card, HCFG) & ~(HOOKN_BIT|HANDN_BIT|PULSEN_BIT);
+
+       emu10k1_writefn0(card, HCFG, hcvalue);
+
+       for (count = 0 ; count < EC_NUM_CONTROL_BITS; count++) {
+       
+               /* Set up the value */
+               data = ((value & 0x1) ? PULSEN_BIT : 0);
+               value >>= 1;
+
+               emu10k1_writefn0(card, HCFG, hcvalue | data);
+
+               /* Clock the shift register */
+               emu10k1_writefn0(card, HCFG, hcvalue | data | HANDN_BIT);
+               emu10k1_writefn0(card, HCFG, hcvalue | data);
+       }
+
+       /* Latch the bits */
+       emu10k1_writefn0(card, HCFG, hcvalue | HOOKN_BIT);
+       emu10k1_writefn0(card, HCFG, hcvalue);
+}
+
+int __devinit emu10k1_ecard_init(struct emu10k1_card *card)
+{
+       u32 hcvalue;
+       struct ecard_state ecard;
+
+       /* Set up the initial settings */
+       ecard.mux0_setting = EC_DEFAULT_SPDIF0_SEL;
+       ecard.mux1_setting = EC_DEFAULT_SPDIF1_SEL;
+       ecard.mux2_setting = 0;
+       ecard.adc_gain = EC_DEFAULT_ADC_GAIN;
+       ecard.control_bits = EC_RAW_RUN_MODE | 
+                             EC_SPDIF0_SELECT(ecard.mux0_setting) |
+                            EC_SPDIF1_SELECT(ecard.mux1_setting);
+
+
+       /* Step 0: Set the codec type in the hardware control register 
+        * and enable audio output */
+       hcvalue = emu10k1_readfn0(card, HCFG);
+       emu10k1_writefn0(card, HCFG, hcvalue | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S);
+       emu10k1_readfn0(card, HCFG);
+
+       /* Step 1: Turn off the led and deassert TRIM_CS */
+       ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
+
+       /* Step 2: Calibrate the ADC and DAC */
+       ecard_write(card, EC_DACCAL | EC_LEDN | EC_TRIM_CSN);
+
+       /* Step 3: Wait for awhile; FIXME: Is this correct? */
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout(HZ);
+
+       /* Step 4: Switch off the DAC and ADC calibration.  Note
+        * That ADC_CAL is actually an inverted signal, so we assert
+        * it here to stop calibration.  */
+       ecard_write(card, EC_ADCCAL | EC_LEDN | EC_TRIM_CSN);
+
+       /* Step 4: Switch into run mode */
+       ecard_write(card, ecard.control_bits);
+
+       /* Step 5: Set the analog input gain */
+       ecard_setadcgain(card, &ecard, ecard.adc_gain);
+       
+       return 0;
+}
+
+
diff --git a/drivers/sound/emu10k1/ecard.h b/drivers/sound/emu10k1/ecard.h
new file mode 100644 (file)
index 0000000..0d55960
--- /dev/null
@@ -0,0 +1,113 @@
+/*     
+ **********************************************************************
+ *     ecard.h
+ *     Copyright 1999, 2000 Creative Labs, Inc. 
+ * 
+ ********************************************************************** 
+ * 
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version. 
+ * 
+ *     This program is distributed in the hope that it will be useful, 
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ *     GNU General Public License for more details. 
+ * 
+ *     You should have received a copy of the GNU General Public 
+ *     License along with this program; if not, write to the Free 
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
+ *     USA. 
+ * 
+ ********************************************************************** 
+ */ 
+
+#ifndef _ECARD_H
+#define _ECARD_H
+
+#include "8010.h"
+#include "hwaccess.h"
+#include <linux/init.h>
+
+/* In A1 Silicon, these bits are in the HC register */
+#define HOOKN_BIT   (1L << 12)
+#define HANDN_BIT   (1L << 11)
+#define PULSEN_BIT  (1L << 10)
+
+#define EC_GDI1 (1 << 13)
+#define EC_GDI0 (1 << 14)
+
+#define EC_NUM_CONTROL_BITS 20
+
+#define EC_AC3_DATA_SELN  0x0001L
+#define EC_EE_DATA_SEL    0x0002L
+#define EC_EE_CNTRL_SELN  0x0004L
+#define EC_EECLK          0x0008L
+#define EC_EECS           0x0010L
+#define EC_EESDO          0x0020L
+#define EC_TRIM_CSN      0x0040L
+#define EC_TRIM_SCLK     0x0080L
+#define EC_TRIM_SDATA    0x0100L
+#define EC_TRIM_MUTEN    0x0200L
+#define EC_ADCCAL        0x0400L
+#define EC_ADCRSTN       0x0800L
+#define EC_DACCAL        0x1000L
+#define EC_DACMUTEN      0x2000L
+#define EC_LEDN                  0x4000L
+
+#define EC_SPDIF0_SEL_SHIFT    15
+#define EC_SPDIF1_SEL_SHIFT    17      
+#define EC_SPDIF0_SEL_MASK     (0x3L << EC_SPDIF0_SEL_SHIFT)
+#define EC_SPDIF1_SEL_MASK     (0x7L << EC_SPDIF1_SEL_SHIFT)
+#define EC_SPDIF0_SELECT(_x) (((_x) << EC_SPDIF0_SEL_SHIFT) & EC_SPDIF0_SEL_MASK)
+#define EC_SPDIF1_SELECT(_x) (((_x) << EC_SPDIF1_SEL_SHIFT) & EC_SPDIF1_SEL_MASK)
+#define EC_CURRENT_PROM_VERSION 0x01 /* Self-explanatory.  This should
+                                      * be incremented any time the EEPROM's
+                                      * format is changed.  */
+
+#define EC_EEPROM_SIZE         0x40 /* ECARD EEPROM has 64 16-bit words */
+
+/* Addresses for special values stored in to EEPROM */
+#define EC_PROM_VERSION_ADDR   0x20    /* Address of the current prom version */
+#define EC_BOARDREV0_ADDR      0x21    /* LSW of board rev */
+#define EC_BOARDREV1_ADDR      0x22    /* MSW of board rev */ 
+
+#define EC_LAST_PROMFILE_ADDR  0x2f
+
+#define EC_SERIALNUM_ADD       0x30    /* First word of serial number.  The number
+                                         * can be up to 30 characters in length
+                                         * and is stored as a NULL-terminated
+                                         * ASCII string.  Any unused bytes must be
+                                         * filled with zeros */
+#define EC_CHECKSUM_ADDR       0x3f    /* Location at which checksum is stored */
+
+
+
+/* Most of this stuff is pretty self-evident.  According to the hardware 
+ * dudes, we need to leave the ADCCAL bit low in order to avoid a DC 
+ * offset problem.  Weird.
+ */
+#define EC_RAW_RUN_MODE        (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | EC_TRIM_CSN)
+
+
+#define EC_DEFAULT_ADC_GAIN   0xC4C4
+#define EC_DEFAULT_SPDIF0_SEL 0x0
+#define EC_DEFAULT_SPDIF1_SEL 0x4
+
+#define HC_EA 0x01L
+
+/* ECARD state structure.  This structure maintains the state
+ * for various portions of the the ECARD's onboard hardware.
+ */
+struct ecard_state {
+       u32 control_bits;
+       u16 adc_gain;
+       u16 mux0_setting;
+       u16 mux1_setting;
+       u16 mux2_setting;
+};
+
+int emu10k1_ecard_init(struct emu10k1_card *) __devinit;
+
+#endif /* _ECARD_H */
diff --git a/drivers/sound/emu10k1/efxmgr.c b/drivers/sound/emu10k1/efxmgr.c
deleted file mode 100644 (file)
index 1b4e01a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-
-/*     
- **********************************************************************
- *     sblive_fx.c
- *     Copyright 1999, 2000 Creative Labs, Inc. 
- * 
- ********************************************************************** 
- * 
- *     Date                 Author          Summary of changes 
- *     ----                 ------          ------------------ 
- *     October 20, 1999     Bertrand Lee    base code release 
- * 
- ********************************************************************** 
- * 
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version. 
- * 
- *     This program is distributed in the hope that it will be useful, 
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of 
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- *     GNU General Public License for more details. 
- * 
- *     You should have received a copy of the GNU General Public 
- *     License along with this program; if not, write to the Free 
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
- *     USA. 
- * 
- ********************************************************************** 
- */
-
-#include "hwaccess.h"
-#include "efxmgr.h"
index f0010d40e6d67d14014fe746828a9c050ffd1a83..20cb56464cc0850cf348a2e5e5c3f0cf63143805 100644 (file)
@@ -3,9 +3,11 @@
 
 #include <linux/wrapper.h>
 
-#define UP_INODE_SEM(a)
-#define DOWN_INODE_SEM(a)
+#define PCI_SET_DMA_MASK(pdev,mask)        (((pdev)->dma_mask) = (mask))
 
-#define GET_INODE_STRUCT()
+#ifndef PCI_GET_DRIVER_DATA
+  #define PCI_GET_DRIVER_DATA(pdev)             ((pdev)->driver_data)
+  #define PCI_SET_DRIVER_DATA(pdev,data)        (((pdev)->driver_data) = (data))
+#endif /* PCI_GET_DRIVER_DATA */
 
 #endif
index 94243c874558836ccece106708570b372139e496..d7d2d4caf7baaecf0ee1b85517fa68a0c47351b8 100644 (file)
@@ -44,14 +44,15 @@ int emu10k1_addxmgr_alloc(u32 size, struct emu10k1_card *card)
        /* Convert bytes to pages */
        numpages = (size / EMUPAGESIZE) + ((size % EMUPAGESIZE) ? 1 : 0);
 
-       while (index < (MAXPAGES - RESERVED - 1)) {
+       spin_lock_irqsave(&card->lock, flags);
+
+       while (index < (MAXPAGES - 1)) {
                if (pagetable[index] & 0x8000) {
                        /* This block of pages is in use, jump to the start of the next block. */
                        index += (pagetable[index] & 0x7fff);
                } else {
                        /* Found free block */
                        if (pagetable[index] >= numpages) {
-                               spin_lock_irqsave(&card->lock, flags);
 
                                /* Block is large enough */
 
@@ -72,6 +73,8 @@ int emu10k1_addxmgr_alloc(u32 size, struct emu10k1_card *card)
                }
        }
 
+       spin_unlock_irqrestore(&card->lock, flags);
+
        return -1;
 }
 
index fda2baa2210ce4ac194ad9146ede906032c52d4a..581467845b925e71166200fb85b3ac0a15aeb62e 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     hwaccess.c -- Hardware access layer
  **********************************************************************
  */
 
+#include <asm/io.h>
+
 #include "hwaccess.h"
+#include "8010.h"
 #include "icardmid.h"
 
 /*************************************************************************
@@ -86,7 +88,7 @@ u32 srToPitch(u32 sampleRate)
        };
 
        if (sampleRate == 0)
-               return (0);     /* Bail out if no leading "1" */
+               return 0;       /* Bail out if no leading "1" */
 
        sampleRate *= 11185;    /* Scale 48000 to 0x20002380 */
 
@@ -131,51 +133,58 @@ u8 sumVolumeToAttenuation(u32 value)
 /*******************************************
 * write/read PCI function 0 registers      *
 ********************************************/
-void sblive_writefn0(struct emu10k1_card *card, u8 reg, u32 data)
+void emu10k1_writefn0(struct emu10k1_card *card, u32 reg, u32 data)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&card->lock, flags);
-       outl(data, card->iobase + reg);
-       spin_unlock_irqrestore(&card->lock, flags);
-
-       return;
-}
-
-void sblive_wrtmskfn0(struct emu10k1_card *card, u8 reg, u32 mask, u32 data)
-{
-       unsigned long flags;
+       if (reg & 0xff000000) {
+               u32 mask;
+               u8 size, offset;
 
-       data &= mask;
+               size = (reg >> 24) & 0x3f;
+               offset = (reg >> 16) & 0x1f;
+               mask = ((1 << size) - 1) << offset;
+               data = (data << offset) & mask;
+               reg &= 0x7f;
 
-       spin_lock_irqsave(&card->lock, flags);
-       data |= inl(card->iobase + reg) & ~mask;
-       outl(data, card->iobase + reg);
-       spin_unlock_irqrestore(&card->lock, flags);
+               spin_lock_irqsave(&card->lock, flags);
+               data |= inl(card->iobase + reg) & ~mask;
+               outl(data, card->iobase + reg);
+               spin_unlock_irqrestore(&card->lock, flags);
+       } else {
+               spin_lock_irqsave(&card->lock, flags);
+               outl(data, card->iobase + reg);
+               spin_unlock_irqrestore(&card->lock, flags);
+       }
 
        return;
 }
 
-u32 sblive_readfn0(struct emu10k1_card * card, u8 reg)
+u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg)
 {
        u32 val;
        unsigned long flags;
 
-       spin_lock_irqsave(&card->lock, flags);
-       val = inl(card->iobase + reg);
-       spin_unlock_irqrestore(&card->lock, flags);
-       return val;
-}
+       if (reg & 0xff000000) {
+               u32 mask;
+               u8 size, offset;
 
-u32 sblive_rdmskfn0(struct emu10k1_card * card, u8 reg, u32 mask)
-{
-       u32 val;
-       unsigned long flags;
+               size = (reg >> 24) & 0x3f;
+               offset = (reg >> 16) & 0x1f;
+               mask = ((1 << size) - 1) << offset;
+               reg &= 0x7f;
 
-       spin_lock_irqsave(&card->lock, flags);
-       val = inl(card->iobase + reg);
-       spin_unlock_irqrestore(&card->lock, flags);
-       return val & mask;
+               spin_lock_irqsave(&card->lock, flags);
+               val = inl(card->iobase + reg);
+               spin_unlock_irqrestore(&card->lock, flags);
+
+               return (val & mask) >> offset;
+        } else {
+               spin_lock_irqsave(&card->lock, flags);
+               val = inl(card->iobase + reg);
+               spin_unlock_irqrestore(&card->lock, flags);
+               return val;
+       }
 }
 
 /************************************************************************
@@ -209,6 +218,37 @@ void sblive_writeptr(struct emu10k1_card *card, u32 reg, u32 channel, u32 data)
                outl(data, card->iobase + DATA);
                spin_unlock_irqrestore(&card->lock, flags);
        }
+}
+
+/* ... :  data, reg, ... , TAGLIST_END */
+void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...)
+{
+       va_list args;
+
+       unsigned long flags;
+        u32 reg;
+
+       va_start(args, channel);
+
+       spin_lock_irqsave(&card->lock, flags);
+       while ((reg = va_arg(args, u32)) != TAGLIST_END) {
+               u32 data = va_arg(args, u32);
+               u32 regptr = (((reg << 16) & PTR_ADDRESS_MASK)
+                             | (channel & PTR_CHANNELNUM_MASK));
+               outl(regptr, card->iobase + PTR);
+               if (reg & 0xff000000) {
+                       int size = (reg >> 24) & 0x3f;
+                        int offset = (reg >> 16) & 0x1f;
+                       u32 mask = ((1 << size) - 1) << offset;
+                       data = (data << offset) & mask;
+
+                       data |= inl(card->iobase + DATA) & ~mask;
+               }
+               outl(data, card->iobase + DATA);
+       }
+       spin_unlock_irqrestore(&card->lock, flags);
+
+       va_end(args);
 
        return;
 }
@@ -244,6 +284,34 @@ u32 sblive_readptr(struct emu10k1_card * card, u32 reg, u32 channel)
        }
 }
 
+void emu10k1_irq_enable(struct emu10k1_card *card, u32 irq_mask)
+{
+       u32 val;
+       unsigned long flags;
+
+       DPF(2,"emu10k1_irq_enable()\n");
+
+       spin_lock_irqsave(&card->lock, flags);
+        val = inl(card->iobase + INTE) | irq_mask;
+        outl(val, card->iobase + INTE);
+       spin_unlock_irqrestore(&card->lock, flags);
+       return;
+}
+
+void emu10k1_irq_disable(struct emu10k1_card *card, u32 irq_mask)
+{
+        u32 val;
+        unsigned long flags;
+
+        DPF(2,"emu10k1_irq_disable()\n");
+
+        spin_lock_irqsave(&card->lock, flags);
+        val = inl(card->iobase + INTE) & ~irq_mask;
+        outl(val, card->iobase + INTE);
+        spin_unlock_irqrestore(&card->lock, flags);
+        return;
+}
+
 void emu10k1_set_stop_on_loop(struct emu10k1_card *card, u32 voicenum)
 {
        /* Voice interrupt */
@@ -271,11 +339,11 @@ static void sblive_wcwait(struct emu10k1_card *card, u32 wait)
        volatile unsigned uCount;
        u32 newtime = 0, curtime;
 
-       curtime = READ_FN0(card, WC_SAMPLECOUNTER);
+       curtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
        while (wait--) {
                uCount = 0;
                while (uCount++ < TIMEOUT) {
-                       newtime = READ_FN0(card, WC_SAMPLECOUNTER);
+                       newtime = emu10k1_readfn0(card, WC_SAMPLECOUNTER);
                        if (newtime != curtime)
                                break;
                }
@@ -293,12 +361,12 @@ int sblive_readac97(struct emu10k1_card *card, u8 index, u16 * data)
 
        spin_lock_irqsave(&card->lock, flags);
 
-       outb(index, card->mixeraddx + 2);
-       *data = inw(card->mixeraddx);
+       outb(index, card->iobase + AC97ADDRESS);
+       *data = inw(card->iobase + AC97DATA);
 
        spin_unlock_irqrestore(&card->lock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int sblive_writeac97(struct emu10k1_card *card, u8 index, u16 data)
@@ -307,12 +375,12 @@ int sblive_writeac97(struct emu10k1_card *card, u8 index, u16 data)
 
        spin_lock_irqsave(&card->lock, flags);
 
-       outb(index, card->mixeraddx + 2);
-       outw(data, card->mixeraddx);
+       outb(index, card->iobase + AC97ADDRESS);
+       outw(data, card->iobase + AC97DATA);
 
        spin_unlock_irqrestore(&card->lock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int sblive_rmwac97(struct emu10k1_card *card, u8 index, u16 data, u16 mask)
@@ -322,16 +390,16 @@ int sblive_rmwac97(struct emu10k1_card *card, u8 index, u16 data, u16 mask)
 
        spin_lock_irqsave(&card->lock, flags);
 
-       outb(index, card->mixeraddx + 2);
-       temp = inw(card->mixeraddx);
+       outb(index, card->iobase + AC97ADDRESS);
+       temp = inw(card->iobase + AC97DATA);
        temp &= ~mask;
        data &= mask;
        temp |= data;
-       outw(temp, card->mixeraddx);
+       outw(temp, card->iobase + AC97DATA);
 
        spin_unlock_irqrestore(&card->lock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /*********************************************************
@@ -347,9 +415,9 @@ int emu10k1_mpu_write_data(struct emu10k1_card *card, u8 data)
 
        if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) {
                outb(data, card->iobase + MUDATA);
-               ret = CTSTATUS_SUCCESS;
+               ret = 0;
        } else
-               ret = CTSTATUS_BUSY;
+               ret = -1;
 
        spin_unlock_irqrestore(&card->lock, flags);
 
@@ -365,9 +433,9 @@ int emu10k1_mpu_read_data(struct emu10k1_card *card, u8 * data)
 
        if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) {
                *data = inb(card->iobase + MUDATA);
-               ret = CTSTATUS_SUCCESS;
+               ret = 0;
        } else
-               ret = CTSTATUS_NODATA;
+               ret = -1;
 
        spin_unlock_irqrestore(&card->lock, flags);
 
@@ -405,12 +473,12 @@ int emu10k1_mpu_reset(struct emu10k1_card *card)
                spin_unlock_irqrestore(&card->lock, flags);
 
                if (status == 0xfe)
-                       return CTSTATUS_SUCCESS;
+                       return 0;
                else
-                       return CTSTATUS_ERROR;
+                       return -1;
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int emu10k1_mpu_acquire(struct emu10k1_card *card)
@@ -418,7 +486,7 @@ int emu10k1_mpu_acquire(struct emu10k1_card *card)
        /* FIXME: This should be a macro */
        ++card->mpuacqcount;
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 int emu10k1_mpu_release(struct emu10k1_card *card)
@@ -426,5 +494,5 @@ int emu10k1_mpu_release(struct emu10k1_card *card)
        /* FIXME: this should be a macro */
        --card->mpuacqcount;
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
index 0dba188d3887c03fb0eaf041ba2779c6045f8524..769a06ab6c35a2474f73fe874363ff93880647c7 100644 (file)
 #ifndef _HWACCESS_H
 #define _HWACCESS_H
 
-#include <linux/version.h>
-#include <linux/kernel.h>
 #include <linux/fs.h>
-#include <linux/ioport.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
-#include <linux/interrupt.h>
 
-#include <asm/io.h>
-#include <asm/dma.h>
+#include "emu_wrapper.h"
 
-#include <emu_wrapper.h>
-
-enum GlobalErrorCode
-{
-       CTSTATUS_SUCCESS = 0x0000,
-       CTSTATUS_ERROR,
-       CTSTATUS_NOMEMORY,
-       CTSTATUS_INUSE,
-};
+#define EMUPAGESIZE     4096            /* don't change */
+#define NUM_G           64              /* use all channels */
+#define NUM_FXSENDS     4               /* don't change */
+/* setting this to other than a power of two may break some applications */
+#define MAXBUFSIZE     65536
+#define MAXPAGES       8192 
+#define BUFMAXPAGES     (MAXBUFSIZE / PAGE_SIZE)
 
 #define FLAGS_AVAILABLE     0x0001
 #define FLAGS_READY         0x0002
@@ -62,50 +54,57 @@ enum GlobalErrorCode
 
 struct memhandle
 {
-       unsigned long busaddx;
-       void *virtaddx;
-       u32 order;
+       dma_addr_t dma_handle;
+       void *addr;
+       u32 size;
 };
 
-struct memhandle *emu10k1_alloc_memphysical(u32);
-void emu10k1_free_memphysical(struct memhandle *);
-
 #define DEBUG_LEVEL 2
 
 #ifdef EMU10K1_DEBUG
 # define DPD(level,x,y...) do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ , y );} while(0)
 # define DPF(level,x)   do {if(level <= DEBUG_LEVEL) printk( KERN_NOTICE "emu10k1: %s: %d: " x , __FILE__ , __LINE__ );} while(0)
-#define ERROR() DPF(1,"error\n");
 #else
-# define DPD(level,x,y...) /* not debugging: nothing */
-# define DPF(level,x)
-#define ERROR()
+# define DPD(level,x,y...) do { } while (0) /* not debugging: nothing */
+# define DPF(level,x) do { } while (0)
 #endif /* EMU10K1_DEBUG */
 
-#include "8010.h"
-#include "voicemgr.h"
+#define ERROR() DPF(1,"error\n")
 
-int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
-void emu10k1_addxmgr_free(struct emu10k1_card *, int);
+/* DATA STRUCTURES */
 
-#include "timer.h"
-#include "irqmgr.h"
+struct emu10k1_waveout
+{
+       u16 send_routing[3];
+
+       u8 send_a[3];
+       u8 send_b[3];
+       u8 send_c[3];
+       u8 send_d[3];
+};
+
+struct emu10k1_wavein
+{
+        struct wiinst *ac97;
+        struct wiinst *mic;
+        struct wiinst *fx;
+
+        u8 recsrc;
+        u32 fxwc;
+};
 
-/* DATA STRUCTURES */
 
 struct emu10k1_card 
 {
        struct list_head list;
 
-       struct memhandle        *virtualpagetable;
-
-       struct memhandle        *tankmem;
-       u32 tmemsize;
-       struct memhandle        *silentpage;
+       struct memhandle        virtualpagetable;
+       struct memhandle        tankmem;
+       struct memhandle        silentpage;
 
        spinlock_t              lock;
 
-       struct voice_manager    voicemgr;
+       u8                      voicetable[NUM_G];
        u16                     emupagetable[MAXPAGES];
 
        struct list_head        timers;
@@ -114,22 +113,23 @@ struct emu10k1_card
 
        struct pci_dev          *pci_dev;
        unsigned long           iobase;
-        unsigned long           mixeraddx;
-       u32  irq; 
+       unsigned long           length;
+       unsigned short          model;
+       unsigned int irq; 
 
-       unsigned long   audio1_num;
-       unsigned long   audio2_num;
-       unsigned long   mixer_num;
-       unsigned long   midi_num;
+       int     audio_num;
+       int     audio1_num;
+       int     mixer_num;
+       int     midi_num;
 
-       struct emu10k1_waveout  *waveout;
-       struct emu10k1_wavein   *wavein;
+       struct emu10k1_waveout  waveout;
+       struct emu10k1_wavein   wavein;
        struct emu10k1_mpuout   *mpuout;
        struct emu10k1_mpuin    *mpuin;
 
        u16                     arrwVol[SOUND_MIXER_NRDEVICES + 1];
        /* array is used from the member 1 to save (-1) operation */
-       u32                     digmix[96];
+       u32                     digmix[9 * 6 * 2];
        unsigned int            modcnt;
        struct semaphore        open_sem;
        mode_t                  open_mode;
@@ -139,8 +139,13 @@ struct emu10k1_card
        u32         has_toslink;               // TOSLink detection
 
        u8 chiprev;                    /* Chip revision                */
+
+       int isaps;
 };
 
+int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *);
+void emu10k1_addxmgr_free(struct emu10k1_card *, int);
+
 #ifdef PRIVATE_PCM_VOLUME
 
 #define MAX_PCM_CHANNELS NUM_G 
@@ -154,16 +159,9 @@ struct sblive_pcm_volume_rec {
        int opened;             // counter - locks element
 };
 extern struct sblive_pcm_volume_rec sblive_pcm_volume[];
-
+extern u16 pcm_last_mixer;
 #endif
 
-
-#define ENABLE                         0xffffffff
-#define DISABLE                0x00000000
-
-#define ENV_ON                 0x80
-#define ENV_OFF                        0x00
-
 #define TIMEOUT                    16384
 
 u32 srToPitch(u32);
@@ -173,19 +171,17 @@ extern struct list_head emu10k1_devs;
 
 /* Hardware Abstraction Layer access functions */
 
-#define WRITE_FN0(a,b,c) sblive_wrtmskfn0((a),(u8)(b), ((1 << (((b) >> 24) & 0x3f)) - 1) << (((b) >> 16) & 0x1f), (c) << (((b) >> 16) & 0x1f))
-
-#define READ_FN0(a,b) sblive_rdmskfn0((a),(u8)(b),((1 << (((b) >> 24) & 0x3f)) - 1) << (((b) >> 16) & 0x1f)) >> (((b) >> 16) & 0x1f)
-
-void sblive_writefn0(struct emu10k1_card *, u8 , u32 );
-void sblive_wrtmskfn0(struct emu10k1_card *, u8 , u32 , u32 );
-
-u32 sblive_readfn0(struct emu10k1_card *, u8 );
-u32 sblive_rdmskfn0(struct emu10k1_card *, u8, u32 );
+void emu10k1_writefn0(struct emu10k1_card *, u32 , u32 );
+u32 emu10k1_readfn0(struct emu10k1_card *, u32 );
 
 void sblive_writeptr(struct emu10k1_card *, u32 , u32 , u32 );
+void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...);
+#define TAGLIST_END 0
+
 u32 sblive_readptr(struct emu10k1_card *, u32 , u32 );
 
+void emu10k1_irq_enable(struct emu10k1_card *, u32);
+void emu10k1_irq_disable(struct emu10k1_card *, u32);
 void emu10k1_set_stop_on_loop(struct emu10k1_card *, u32);
 void emu10k1_clear_stop_on_loop(struct emu10k1_card *, u32);
 
index a141e7396513e288ceace53ee73c447f43e018ca..8a8f999aaa1926eea9bd168bcf3de4d6201f2f47 100644 (file)
 #ifndef _ICARDWAV_H
 #define _ICARDWAV_H
 
-/* Enumeration for SetControl */
-enum
-{
-        WAVECURPOS = 0x10,
-};
-
 struct wave_format 
 {
-       u32 samplingrate;
-       u32 bitsperchannel;
-       u32 channels;           /* 1 = Mono, 2 = Stereo */
+       int samplingrate;
+       u8 bitsperchannel;
+       u8 channels;            /* 1 = Mono, 2 = Stereo */
+       u8 bytesperchannel;
+       u8 bytespersample;
+       int bytespersec;
 };
 
 /* emu10k1_wave states */
-#define CARDWAVE_STATE_STOPPED     0x0001
-#define CARDWAVE_STATE_STARTED     0x0002
+#define WAVE_STATE_OPEN                0x01    
+#define WAVE_STATE_STARTED     0x02
+#define WAVE_STATE_CLOSED      0x04
 
 #endif /* _ICARDWAV_H */
index 96bffcfe48789b45ded104cf6254cd196e0f2f7e..6a047ba02f7c2cd3285318f5b6ecad1af32227fe 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include "hwaccess.h"
+#include "8010.h"
 #include "cardmi.h"
 #include "cardmo.h"
 #include "irqmgr.h"
 void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct emu10k1_card *card = (struct emu10k1_card *) dev_id;
-       u32 irqstatus, ptr, tmp;
+       u32 irqstatus, tmp;
 
-       if (!(irqstatus = sblive_readfn0(card, IPR)))
+       if (!(irqstatus = emu10k1_readfn0(card, IPR)))
                return;
 
        DPD(4, "emu10k1_interrupt called, irq =  %u\n", irq);
 
-       /* Preserve PTR register */
-       ptr = sblive_readfn0(card, PTR);
-
        /*
         ** NOTE :
         ** We do a 'while loop' here cos on certain machines, with both
@@ -85,43 +83,10 @@ void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (irqstatus)
                        emu10k1_irq_disable(card, irqstatus);
 
-               sblive_writefn0(card, IPR, tmp);
-
-       } while ((irqstatus = sblive_readfn0(card, IPR)));
+               emu10k1_writefn0(card, IPR, tmp);
 
-       sblive_writefn0(card, PTR, ptr);
+       } while ((irqstatus = emu10k1_readfn0(card, IPR)));
 
        return;
 }
 
-/* Enables the specified irq service */
-
-int emu10k1_irq_enable(struct emu10k1_card *card, u32 irqtype)
-{
-       /*
-        * TODO :
-        * put protection here so that we don't accidentally
-        * screw-up another cardxxx objects irqs
-        */
-
-       DPD(4, "emu10k1_irq_enable %x\n", irqtype);
-       sblive_wrtmskfn0(card, INTE, irqtype, ENABLE);
-
-       return CTSTATUS_SUCCESS;
-}
-
-/* Disables the specified irq service */
-
-int emu10k1_irq_disable(struct emu10k1_card *card, u32 irqtype)
-{
-       /*
-        * TODO :
-        * put protection here so that we don't accidentally
-        * screw-up another cardxxx objects irqs
-        */
-
-       DPD(4, "emu10k1_irq_disable %x\n", irqtype);
-       sblive_wrtmskfn0(card, INTE, irqtype, DISABLE);
-
-       return CTSTATUS_SUCCESS;
-}
index 886a7374edd65b825765ba0ea428ee614548f4a2..76166f80453fc8cdae8b225f9d0a47be5f839712 100644 (file)
 #define IRQTYPE_SPDIF               (IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE)
 #define IRQTYPE_DSP                 IPR_FXDSP
 
-struct emu10k1_wavedevice
-{
-        struct emu10k1_card *card;
-        struct wiinst *wiinst;
-        struct woinst *woinst;
-        u16 enablebits;
-};
-
 void emu10k1_timer_irqhandler(struct emu10k1_card *);
 
-int emu10k1_irq_enable(struct emu10k1_card *, u32);
-int emu10k1_irq_disable(struct emu10k1_card *, u32);
-
 #endif /* _IRQ_H */
index acb65d7e56de5a1b22ba3957ae50c840d14c24f2..c8ddfb2b4067e63c4071ab2231facad557891267 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     main.c - Creative EMU10K1 audio driver
  *      0.4 Added rear-channel, SPDIF support.
  *     0.5 Source cleanup, SMP fixes, multiopen support, 64 bit arch fixes,
  *         moved bh's to tasklets, moved to the new PCI driver initialization style.
+ *     0.6 Make use of pci_alloc_consistent, improve compatibility layer for 2.2 kernels,
+ *         code reorganization and cleanup.
+ *      0.7 Support for the Emu-APS. Bug fixes for voice cache setup, mmaped sound + poll().
+ *         Support for setting external TRAM size.
+ *     
  **********************************************************************
  */
 
 /* These are only included once per module */
+#include <linux/version.h>
 #include <linux/module.h>
+#include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include "hwaccess.h"
+#include "8010.h"
 #include "efxmgr.h"
 #include "cardwo.h"
 #include "cardwi.h"
 #include "cardmo.h"
 #include "cardmi.h"
 #include "recmgr.h"
+#include "ecard.h"
 
-#define DRIVER_VERSION "0.5"
+#define DRIVER_VERSION "0.7"
 
 /* FIXME: is this right? */
+/* does the card support 32 bit bus master?*/
 #define EMU10K1_DMA_MASK                0xffffffff     /* DMA buffer mask for pci_alloc_consist */
 
 #ifndef PCI_VENDOR_ID_CREATIVE
@@ -70,8 +80,8 @@
 #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
 #endif
 
-#define EMU10K1_EXTENT 0x20    /* 32 byte I/O space */
-
+#define EMU_APS_SUBID  0x40011102
 enum {
        EMU10K1 = 0,
 };
@@ -80,7 +90,7 @@ static char *card_names[] __devinitdata = {
        "EMU10K1",
 };
 
-static struct pci_device_id emu10k1_pci_tbl[] __devinitdata = {
+static struct pci_device_id emu10k1_pci_tbl[] = {
        {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
         PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
        {0,}
@@ -99,32 +109,38 @@ extern struct file_operations emu10k1_midi_fops;
 extern void emu10k1_interrupt(int, void *, struct pt_regs *s);
 extern int emu10k1_mixer_wrch(struct emu10k1_card *, unsigned int, int);
 
-static int __devinit audio_init(struct emu10k1_card *card)
+static void __devinit audio_init(struct emu10k1_card *card)
 {
-       if ((card->waveout = kmalloc(sizeof(struct emu10k1_waveout), GFP_KERNEL)) == NULL) {
-               printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_waveout: out of memory\n");
-               return CTSTATUS_ERROR;
-       }
-       memset(card->waveout, 0, sizeof(struct emu10k1_waveout));
-
-       /* Assign default global volume, reverb, chorus */
-       card->waveout->globalvol = 0xffffffff;
-       card->waveout->left = 0xffff;
-       card->waveout->right = 0xffff;
-       card->waveout->mute = 0;
-       card->waveout->globalreverb = 0xffffffff;
-       card->waveout->globalchorus = 0xffffffff;
-
-       if ((card->wavein = kmalloc(sizeof(struct emu10k1_wavein), GFP_KERNEL))
-           == NULL) {
-               printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_wavein: out of memory\n");
-               return CTSTATUS_ERROR;
-       }
-       memset(card->wavein, 0, sizeof(struct emu10k1_wavein));
+       /* Assign default playback voice parameters */
+       /* mono voice */
+       card->waveout.send_a[0] = 0x00;
+       card->waveout.send_b[0] = 0xff;
+       card->waveout.send_c[0] = 0xff;
+       card->waveout.send_d[0] = 0x00;
+       card->waveout.send_routing[0] = 0xd01c;
+
+       /* stereo voice */
+       card->waveout.send_a[1] = 0x00;
+        card->waveout.send_b[1] = 0xff;
+        card->waveout.send_c[1] = 0x00;
+        card->waveout.send_d[1] = 0x00;
+        card->waveout.send_routing[1] = 0xd01c;
+
+       card->waveout.send_a[2] = 0x00;
+        card->waveout.send_b[2] = 0x00;
+        card->waveout.send_c[2] = 0xff;
+        card->waveout.send_d[2] = 0x00;
+        card->waveout.send_routing[2] = 0xd01c;
+
+       /* Assign default recording parameters */
+       if(card->isaps)
+               card->wavein.recsrc = WAVERECORD_FX;
+       else
+               card->wavein.recsrc = WAVERECORD_AC97;
+
+       card->wavein.fxwc = 0x0003;
 
-       card->wavein->recsrc = WAVERECORD_AC97;
-
-       return CTSTATUS_SUCCESS;
+       return;
 }
 
 static void __devinit mixer_init(struct emu10k1_card *card)
@@ -141,61 +157,64 @@ static void __devinit mixer_init(struct emu10k1_card *card)
                SOUND_MIXER_PHONEIN, 0x3232}, {
                SOUND_MIXER_MIC, 0x0000}, {
                SOUND_MIXER_LINE, 0x0000}, {
-               SOUND_MIXER_CD, 0x3232}, {
-               SOUND_MIXER_LINE1, 0x3232}, {
+               SOUND_MIXER_CD, 0x4b4b}, {
+               SOUND_MIXER_LINE1, 0x4b4b}, {
                SOUND_MIXER_LINE3, 0x3232}, {
                SOUND_MIXER_DIGITAL1, 0x6464}, {
                SOUND_MIXER_DIGITAL2, 0x6464}, {
                SOUND_MIXER_PCM, 0x6464}, {
-               SOUND_MIXER_RECLEV, 0x3232}, {
+               SOUND_MIXER_RECLEV, 0x0404}, {
                SOUND_MIXER_TREBLE, 0x3232}, {
                SOUND_MIXER_BASS, 0x3232}, {
-       SOUND_MIXER_LINE2, 0x4b4b}};
+               SOUND_MIXER_LINE2, 0x4b4b}};
 
-       int initdig[] = { 0, 1, 2, 3, 6, 7, 16, 17, 18, 19, 22, 23, 64, 65, 66, 67, 70, 71,
-               84, 85
+       int initdig[] = { 0, 1, 2, 3, 6, 7, 18, 19, 20, 21, 24, 25, 72, 73, 74, 75, 78, 79,
+               94, 95
        };
 
-       /* Reset */
-       sblive_writeac97(card, AC97_RESET, 0);
-
-#if 0
-       /* Check status word */
-       {
-               u16 reg;
-
-               sblive_readac97(card, AC97_RESET, &reg);
-               DPD(2, "RESET 0x%x\n", reg);
-               sblive_readac97(card, AC97_MASTERTONE, &reg);
-               DPD(2, "MASTER_TONE 0x%x\n", reg);
+       for (count = 0; count < sizeof(card->digmix) / sizeof(card->digmix[0]); count++) {
+               card->digmix[count] = 0x80000000;
+               sblive_writeptr(card, FXGPREGBASE + 0x10 + count, 0, 0);
        }
-#endif
 
-       /* Set default recording source to mic in */
-       sblive_writeac97(card, AC97_RECORDSELECT, 0);
+       card->modcnt = 0;       // Should this be here or in open() ?
 
-       /* Set default AC97 "PCM" volume to acceptable max */
-       //sblive_writeac97(card, AC97_PCMOUTVOLUME, 0);
-       //sblive_writeac97(card, AC97_LINE2, 0);
+       if (!card->isaps) {
 
-       /* Set default volumes for all mixer channels */
+               for (count = 0; count < sizeof(initdig) / sizeof(initdig[0]); count++) {
+                       card->digmix[initdig[count]] = 0x7fffffff;
+                       sblive_writeptr(card, FXGPREGBASE + 0x10 + initdig[count], 0, 0x7fffffff);
+               }
 
-       for (count = 0; count < sizeof(card->digmix) / sizeof(card->digmix[0]); count++) {
-               card->digmix[count] = 0x80000000;
-               sblive_writeptr(card, FXGPREGBASE + 0x10 + count, 0, 0);
-       }
+               /* Reset */
+               sblive_writeac97(card, AC97_RESET, 0);
+
+#if 0
+               /* Check status word */
+               {
+                       u16 reg;
+
+                       sblive_readac97(card, AC97_RESET, &reg);
+                       DPD(2, "RESET 0x%x\n", reg);
+                       sblive_readac97(card, AC97_MASTERTONE, &reg);
+                       DPD(2, "MASTER_TONE 0x%x\n", reg);
+               }
+#endif
 
-       for (count = 0; count < sizeof(initdig) / sizeof(initdig[0]); count++) {
-               card->digmix[initdig[count]] = 0x7fffffff;
-               sblive_writeptr(card, FXGPREGBASE + 0x10 + initdig[count], 0, 0x7fffffff);
+               /* Set default recording source to mic in */
+               sblive_writeac97(card, AC97_RECORDSELECT, 0);
+
+               /* Set default AC97 "PCM" volume to acceptable max */
+               //sblive_writeac97(card, AC97_PCMOUTVOLUME, 0);
+               //sblive_writeac97(card, AC97_LINE2, 0);
        }
 
+       /* Set default volumes for all mixer channels */
+
        for (count = 0; count < sizeof(initvol) / sizeof(initvol[0]); count++) {
                emu10k1_mixer_wrch(card, initvol[count].mixch, initvol[count].vol);
        }
 
-       card->modcnt = 0;       // Should this be here or in open() ?
-
        return;
 }
 
@@ -204,7 +223,7 @@ static int __devinit midi_init(struct emu10k1_card *card)
        if ((card->mpuout = kmalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL))
            == NULL) {
                printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        memset(card->mpuout, 0, sizeof(struct emu10k1_mpuout));
@@ -220,7 +239,7 @@ static int __devinit midi_init(struct emu10k1_card *card)
        if ((card->mpuin = kmalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL)) == NULL) {
                kfree(card->mpuout);
                printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        memset(card->mpuin, 0, sizeof(struct emu10k1_mpuin));
@@ -232,31 +251,20 @@ static int __devinit midi_init(struct emu10k1_card *card)
        spin_lock_init(&card->mpuin->lock);
 
        /* Reset the MPU port */
-       if (emu10k1_mpu_reset(card) != CTSTATUS_SUCCESS) {
+       if (emu10k1_mpu_reset(card) < 0) {
                ERROR();
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 static void __devinit voice_init(struct emu10k1_card *card)
 {
-       struct voice_manager *voicemgr = &card->voicemgr;
-       struct emu_voice *voice;
        int i;
 
-       voicemgr->card = card;
-       voicemgr->lock = SPIN_LOCK_UNLOCKED;
-
-       voice = voicemgr->voice;
-       for (i = 0; i < NUM_G; i++) {
-               voice->card = card;
-               voice->usage = VOICEMGR_USAGE_FREE;
-               voice->num = i;
-               voice->linked_voice = NULL;
-               voice++;
-       }
+       for (i = 0; i < NUM_G; i++)
+               card->voicetable[i] = VOICE_USAGE_FREE;
 
        return;
 }
@@ -280,21 +288,27 @@ static void __devinit addxmgr_init(struct emu10k1_card *card)
        /* Mark first page as used */
        /* This page is reserved by the driver */
        card->emupagetable[0] = 0x8001;
-       card->emupagetable[1] = MAXPAGES - RESERVED - 1;
+       card->emupagetable[1] = MAXPAGES - 1;
 
        return;
 }
 
 static void __devinit fx_init(struct emu10k1_card *card)
 {
-       int i, j, k, l;
+       int i, j, k;
+#ifdef TONE_CONTROL
+       int l;
+#endif 
        u32 pc = 0;
 
        for (i = 0; i < 512; i++)
                OP(6, 0x40, 0x40, 0x40, 0x40);
 
        for (i = 0; i < 256; i++)
-               sblive_writeptr(card, FXGPREGBASE + i, 0, 0);
+               sblive_writeptr_tag(card, 0,
+                                   FXGPREGBASE + i, 0,
+                                   TANKMEMADDRREGBASE + i, 0,
+                                   TAGLIST_END);
 
        pc = 0;
 
@@ -304,7 +318,7 @@ static void __devinit fx_init(struct emu10k1_card *card)
                OP(4, 0x101, 0x40, j + 2, 0x44);
 
                for (i = 0; i < 6; i++) {
-                       k = i * 16 + j;
+                       k = i * 18 + j;
                        OP(0, 0x102, 0x40, 0x110 + k, 0x100);
                        OP(0, 0x102, 0x102, 0x112 + k, 0x101);
                        OP(0, 0x102, 0x102, 0x114 + k, 0x10 + j);
@@ -313,25 +327,32 @@ static void __devinit fx_init(struct emu10k1_card *card)
                        OP(0, 0x102, 0x102, 0x11a + k, 0x16 + j);
                        OP(0, 0x102, 0x102, 0x11c + k, 0x18 + j);
                        OP(0, 0x102, 0x102, 0x11e + k, 0x1a + j);
-
-                       k = 0x190 + i * 8 + j * 4;
-                       OP(0, 0x40, 0x40, 0x102, 0x170 + j);
-                       OP(7, k + 1, k, k + 1, 0x174 + j);
-                       OP(7, k, 0x102, k, 0x172 + j);
-                       OP(7, k + 3, k + 2, k + 3, 0x178 + j);
-                       OP(0, k + 2, 0x56, k + 2, 0x176 + j);
+#ifdef TONE_CONTROL
+                       OP(0, 0x102, 0x102, 0x120 + k, 0x1c + j);
+
+                       k = 0x1a0 + i * 8 + j * 4;
+                       OP(0, 0x40, 0x40, 0x102, 0x180 + j);
+                       OP(7, k + 1, k, k + 1, 0x184 + j);
+                       OP(7, k, 0x102, k, 0x182 + j);
+                       OP(7, k + 3, k + 2, k + 3, 0x188 + j);
+                       OP(0, k + 2, 0x56, k + 2, 0x186 + j);
                        OP(6, k + 2, k + 2, k + 2, 0x40);
 
-                       l = 0x1c0 + i * 8 + j * 4;
-                       OP(0, 0x40, 0x40, k + 2, 0x180 + j);
-                       OP(7, l + 1, l, l + 1, 0x184 + j);
-                       OP(7, l, k + 2, l, 0x182 + j);
-                       OP(7, l + 3, l + 2, l + 3, 0x188 + j);
-                       OP(0, l + 2, 0x56, l + 2, 0x186 + j);
+                       l = 0x1d0 + i * 8 + j * 4;
+                       OP(0, 0x40, 0x40, k + 2, 0x190 + j);
+                       OP(7, l + 1, l, l + 1, 0x194 + j);
+                       OP(7, l, k + 2, l, 0x192 + j);
+                       OP(7, l + 3, l + 2, l + 3, 0x198 + j);
+                       OP(0, l + 2, 0x56, l + 2, 0x196 + j);
                        OP(4, l + 2, 0x40, l + 2, 0x46);
 
-                       OP(6, 0x20 + (i * 2) + j, l + 2, 0x40, 0x40);
-
+                       if ((i == 0) && !card->isaps)
+                               OP(4, 0x20 + (i * 2) + j, 0x40, l + 2, 0x50);   /* FIXME: Is this really needed? */
+                       else
+                               OP(6, 0x20 + (i * 2) + j, l + 2, 0x40, 0x40);
+#else
+                       OP(0, 0x20 + (i * 2) + j, 0x102, 0x120 + k, 0x1c + j);
+#endif
                }
        }
        sblive_writeptr(card, DBG, 0, 0);
@@ -342,63 +363,64 @@ static void __devinit fx_init(struct emu10k1_card *card)
 static int __devinit hw_init(struct emu10k1_card *card)
 {
        int nCh;
-
-#ifdef TANKMEM
-       u32 size = 0;
-#endif
-       u32 sizeIdx = 0;
-       u32 pagecount, tmp;
+       u32 pagecount; /* tmp */
 
        /* Disable audio and lock cache */
-       sblive_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE | HCFG_MUTEBUTTONENABLE);
+       emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
 
        /* Reset recording buffers */
-       sblive_writeptr(card, MICBS, 0, ADCBS_BUFSIZE_NONE);
-       sblive_writeptr(card, MICBA, 0, 0);
-       sblive_writeptr(card, FXBS, 0, ADCBS_BUFSIZE_NONE);
-       sblive_writeptr(card, FXBA, 0, 0);
-       sblive_writeptr(card, ADCBS, 0, ADCBS_BUFSIZE_NONE);
-       sblive_writeptr(card, ADCBA, 0, 0);
+       sblive_writeptr_tag(card, 0,
+                           MICBS, ADCBS_BUFSIZE_NONE,
+                           MICBA, 0,
+                           FXBS, ADCBS_BUFSIZE_NONE,
+                           FXBA, 0,
+                           ADCBS, ADCBS_BUFSIZE_NONE,
+                           ADCBA, 0,
+                           TAGLIST_END);
 
        /* Disable channel interrupt */
-       sblive_writefn0(card, INTE, DISABLE);
-       sblive_writeptr(card, CLIEL, 0, 0);
-       sblive_writeptr(card, CLIEH, 0, 0);
-       sblive_writeptr(card, SOLEL, 0, 0);
-       sblive_writeptr(card, SOLEH, 0, 0);
+       emu10k1_writefn0(card, INTE, 0);
+       sblive_writeptr_tag(card, 0,
+                           CLIEL, 0,
+                           CLIEH, 0,
+                           SOLEL, 0,
+                           SOLEH, 0,
+                           TAGLIST_END);
 
        /* Init envelope engine */
        for (nCh = 0; nCh < NUM_G; nCh++) {
-               sblive_writeptr(card, DCYSUSV, nCh, ENV_OFF);
-               sblive_writeptr(card, IP, nCh, 0);
-               sblive_writeptr(card, VTFT, nCh, 0xffff);
-               sblive_writeptr(card, CVCF, nCh, 0xffff);
-               sblive_writeptr(card, PTRX, nCh, 0);
-               sblive_writeptr(card, CPF, nCh, 0);
-               sblive_writeptr(card, CCR, nCh, 0);
-
-               sblive_writeptr(card, PSST, nCh, 0);
-               sblive_writeptr(card, DSL, nCh, 0x10);
-               sblive_writeptr(card, CCCA, nCh, 0);
-               sblive_writeptr(card, Z1, nCh, 0);
-               sblive_writeptr(card, Z2, nCh, 0);
-               sblive_writeptr(card, FXRT, nCh, 0xd01c0000);
-
-               sblive_writeptr(card, ATKHLDM, nCh, 0);
-               sblive_writeptr(card, DCYSUSM, nCh, 0);
-               sblive_writeptr(card, IFATN, nCh, 0xffff);
-               sblive_writeptr(card, PEFE, nCh, 0);
-               sblive_writeptr(card, FMMOD, nCh, 0);
-               sblive_writeptr(card, TREMFRQ, nCh, 24);        /* 1 Hz */
-               sblive_writeptr(card, FM2FRQ2, nCh, 24);        /* 1 Hz */
-               sblive_writeptr(card, TEMPENV, nCh, 0);
-
-               /*** These are last so OFF prevents writing ***/
-               sblive_writeptr(card, LFOVAL2, nCh, 0);
-               sblive_writeptr(card, LFOVAL1, nCh, 0);
-               sblive_writeptr(card, ATKHLDV, nCh, 0);
-               sblive_writeptr(card, ENVVOL, nCh, 0);
-               sblive_writeptr(card, ENVVAL, nCh, 0);
+               sblive_writeptr_tag(card, nCh,
+                                   DCYSUSV, 0,
+                                   IP, 0,
+                                   VTFT, 0xffff,
+                                   CVCF, 0xffff,
+                                   PTRX, 0,
+                                   CPF, 0,
+                                   CCR, 0,
+
+                                   PSST, 0,
+                                   DSL, 0x10,
+                                   CCCA, 0,
+                                   Z1, 0,
+                                   Z2, 0,
+                                   FXRT, 0xd01c0000,
+
+                                   ATKHLDM, 0,
+                                   DCYSUSM, 0,
+                                   IFATN, 0xffff,
+                                   PEFE, 0,
+                                   FMMOD, 0,
+                                   TREMFRQ, 24,        /* 1 Hz */
+                                   FM2FRQ2, 24,        /* 1 Hz */
+                                   TEMPENV, 0,
+
+                                   /*** These are last so OFF prevents writing ***/
+                                   LFOVAL2, 0,
+                                   LFOVAL1, 0,
+                                   ATKHLDV, 0,
+                                   ENVVOL, 0,
+                                   ENVVAL, 0,
+                                    TAGLIST_END);
        }
 
        /*
@@ -416,73 +438,57 @@ static int __devinit hw_init(struct emu10k1_card *card)
         ** P                 = 0     (Consumer)
         */
 
-       /* SPDIF0 */
-       sblive_writeptr(card, SPCS0, 0, SPCS_CLKACCY_1000PPM | 0x002000000 |
-                       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+       sblive_writeptr_tag(card, 0,
 
-       /* SPDIF1 */
-       sblive_writeptr(card, SPCS1, 0, SPCS_CLKACCY_1000PPM | 0x002000000 |
-                       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+                           /* SPDIF0 */
+                           SPCS0, (SPCS_CLKACCY_1000PPM | 0x002000000 |
+                                   SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
 
-       /* SPDIF2 & SPDIF3 */
-       sblive_writeptr(card, SPCS2, 0, SPCS_CLKACCY_1000PPM | 0x002000000 |
-                       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+                           /* SPDIF1 */
+                           SPCS1, (SPCS_CLKACCY_1000PPM | 0x002000000 |
+                                   SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
 
-       fx_init(card);          /* initialize effects engine */
+                           /* SPDIF2 & SPDIF3 */
+                           SPCS2, (SPCS_CLKACCY_1000PPM | 0x002000000 |
+                                   SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
 
-       card->tankmem = NULL;
+                           TAGLIST_END);
 
-#ifdef TANKMEM
-       size = TMEMSIZE;
-       sizeIdx = TMEMSIZEREG;
-       while (size > 16384) {
-               if ((card->tankmem = emu10k1_alloc_memphysical(size)) != NULL)
-                       break;
-
-               size /= 2;
-               sizeIdx -= 1;
-       }
+       fx_init(card);          /* initialize effects engine */
 
-       if (card->tankmem == NULL) {
-               card->tmemsize = 0;
-               return CTSTATUS_ERROR;
-       }
+       card->tankmem.size = 0;
 
-       card->tmemsize = size;
-#else                          /* !TANKMEM */
-       card->tmemsize = 0;
-#endif                         /* TANKMEM */
+       card->virtualpagetable.size = MAXPAGES * sizeof(u32);
 
-       if ((card->virtualpagetable = emu10k1_alloc_memphysical((MAXPAGES - RESERVED) * sizeof(u32))) == NULL) {
+       if ((card->virtualpagetable.addr = pci_alloc_consistent(card->pci_dev, card->virtualpagetable.size, &card->virtualpagetable.dma_handle)) ==
+           NULL) {
                ERROR();
-               emu10k1_free_memphysical(card->tankmem);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       if ((card->silentpage = emu10k1_alloc_memphysical(EMUPAGESIZE)) == NULL) {
-               ERROR();
-               emu10k1_free_memphysical(card->tankmem);
-               emu10k1_free_memphysical(card->virtualpagetable);
-               return CTSTATUS_ERROR;
-       } else
-               memset(card->silentpage->virtaddx, 0, EMUPAGESIZE);
+       card->silentpage.size = EMUPAGESIZE;
 
-       for (pagecount = 0; pagecount < (MAXPAGES - RESERVED); pagecount++)
+       if ((card->silentpage.addr = pci_alloc_consistent(card->pci_dev, card->silentpage.size, &card->silentpage.dma_handle)) == NULL) {
+               ERROR();
+               pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
+               return -1;
+       }
 
-               ((u32 *) card->virtualpagetable->virtaddx)[pagecount] = (card->silentpage->busaddx * 2) | pagecount;
+       for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
+               ((u32 *) card->virtualpagetable.addr)[pagecount] = (card->silentpage.dma_handle * 2) | pagecount;
 
        /* Init page table & tank memory base register */
-       sblive_writeptr(card, PTB, 0, card->virtualpagetable->busaddx);
-#ifdef TANKMEM
-       sblive_writeptr(card, TCB, 0, card->tankmem->busaddx);
-#else
-       sblive_writeptr(card, TCB, 0, 0);
-#endif
-       sblive_writeptr(card, TCBS, 0, sizeIdx);
+       sblive_writeptr_tag(card, 0,
+                           PTB, card->virtualpagetable.dma_handle,
+                           TCB, 0,
+                           TCBS, 0,
+                           TAGLIST_END);
 
        for (nCh = 0; nCh < NUM_G; nCh++) {
-               sblive_writeptr(card, MAPA, nCh, MAP_PTI_MASK | (card->silentpage->busaddx * 2));
-               sblive_writeptr(card, MAPB, nCh, MAP_PTI_MASK | (card->silentpage->busaddx * 2));
+               sblive_writeptr_tag(card, nCh,
+                                   MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+                                   MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+                                   TAGLIST_END);
        }
 
        /* Hokay, now enable the AUD bit */
@@ -497,12 +503,16 @@ static int __devinit hw_init(struct emu10k1_card *card)
        sblive_writeac97(card, AC97_MASTERVOLUME, 0);
        sblive_writeac97(card, AC97_PCMOUTVOLUME, 0);
 
-       sblive_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE | HCFG_AUTOMUTE | HCFG_JOYENABLE);
+       if(card->model == 0x20 || card->model == 0xc400 ||
+         (card->model == 0x21 && card->chiprev < 6))
+               emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
+       else
+               emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
 
-       /* TOSLink detection */
+       /* FIXME: TOSLink detection */
        card->has_toslink = 0;
 
-       tmp = sblive_readfn0(card, HCFG);
+/*     tmp = sblive_readfn0(card, HCFG);
        if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
                sblive_writefn0(card, HCFG, tmp | 0x800);
 
@@ -513,30 +523,23 @@ static int __devinit hw_init(struct emu10k1_card *card)
                        sblive_writefn0(card, HCFG, tmp);
                }
        }
-
-       return CTSTATUS_SUCCESS;
+*/
+       return 0;
 }
 
 static int __devinit emu10k1_init(struct emu10k1_card *card)
 {
        /* Init Card */
-       if (hw_init(card) != CTSTATUS_SUCCESS)
-               return CTSTATUS_ERROR;
+       if (hw_init(card) < 0)
+               return -1;
 
        voice_init(card);
        timer_init(card);
        addxmgr_init(card);
 
-       DPD(2, "  hw control register -> %x\n", sblive_readfn0(card, HCFG));
-
-       return CTSTATUS_SUCCESS;
-}
+       DPD(2, "  hw control register -> 0x%x\n", emu10k1_readfn0(card, HCFG));
 
-static void __devexit audio_exit(struct emu10k1_card *card)
-{
-       kfree(card->waveout);
-       kfree(card->wavein);
-       return;
+       return 0;
 }
 
 static void __devexit midi_exit(struct emu10k1_card *card)
@@ -550,50 +553,57 @@ static void __devexit midi_exit(struct emu10k1_card *card)
        return;
 }
 
-static void __devexit emu10k1_exit(struct emu10k1_card *card)
+static void __devinit emu10k1_exit(struct emu10k1_card *card)
 {
        int ch;
 
-       sblive_writefn0(card, INTE, DISABLE);
+       emu10k1_writefn0(card, INTE, 0);
 
        /** Shutdown the chip **/
        for (ch = 0; ch < NUM_G; ch++)
-               sblive_writeptr(card, DCYSUSV, ch, ENV_OFF);
+               sblive_writeptr(card, DCYSUSV, ch, 0);
 
        for (ch = 0; ch < NUM_G; ch++) {
-               sblive_writeptr(card, VTFT, ch, 0);
-               sblive_writeptr(card, CVCF, ch, 0);
-               sblive_writeptr(card, PTRX, ch, 0);
-               sblive_writeptr(card, CPF, ch, 0);
+               sblive_writeptr_tag(card, ch,
+                                   VTFT, 0,
+                                   CVCF, 0,
+                                   PTRX, 0,
+                                   CPF, 0,
+                                   TAGLIST_END);
        }
 
-       /* Reset recording buffers */
-       sblive_writeptr(card, MICBS, 0, ADCBS_BUFSIZE_NONE);
-       sblive_writeptr(card, MICBA, 0, 0);
-       sblive_writeptr(card, FXBS, 0, ADCBS_BUFSIZE_NONE);
-       sblive_writeptr(card, FXBA, 0, 0);
-       sblive_writeptr(card, FXWC, 0, 0);
-       sblive_writeptr(card, ADCBS, 0, ADCBS_BUFSIZE_NONE);
-       sblive_writeptr(card, ADCBA, 0, 0);
-       sblive_writeptr(card, TCBS, 0, TCBS_BUFFSIZE_16K);
-       sblive_writeptr(card, TCB, 0, 0);
-       sblive_writeptr(card, DBG, 0, 0x8000);
-
-       /* Disable channel interrupt */
-       sblive_writeptr(card, CLIEL, 0, 0);
-       sblive_writeptr(card, CLIEH, 0, 0);
-       sblive_writeptr(card, SOLEL, 0, 0);
-       sblive_writeptr(card, SOLEH, 0, 0);
-
        /* Disable audio and lock cache */
-       sblive_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE | HCFG_MUTEBUTTONENABLE);
-       sblive_writeptr(card, PTB, 0, 0);
+       emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
+
+       sblive_writeptr_tag(card, 0,
+                            PTB, 0,
+
+                           /* Reset recording buffers */
+                           MICBS, ADCBS_BUFSIZE_NONE,
+                           MICBA, 0,
+                           FXBS, ADCBS_BUFSIZE_NONE,
+                           FXBA, 0,
+                           FXWC, 0,
+                           ADCBS, ADCBS_BUFSIZE_NONE,
+                           ADCBA, 0,
+                           TCBS, 0,
+                           TCB, 0,
+                           DBG, 0x8000,
+
+                           /* Disable channel interrupt */
+                           CLIEL, 0,
+                           CLIEH, 0,
+                           SOLEL, 0,
+                           SOLEH, 0,
+                           TAGLIST_END);
+
+
+       pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
+       pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
+       
+       if(card->tankmem.size != 0)
+               pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
 
-       emu10k1_free_memphysical(card->silentpage);
-       emu10k1_free_memphysical(card->virtualpagetable);
-#ifdef TANKMEM
-       emu10k1_free_memphysical(card->tankmem);
-#endif
        return;
 }
 
@@ -601,6 +611,7 @@ static void __devexit emu10k1_exit(struct emu10k1_card *card)
 static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
 {
        struct emu10k1_card *card;
+       u32 subsysvid;
 
        if ((card = kmalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "emu10k1: out of memory\n");
@@ -608,7 +619,6 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
        }
        memset(card, 0, sizeof(struct emu10k1_card));
 
-#if LINUX_VERSION_CODE > 0x020320
        if (!pci_dma_supported(pci_dev, EMU10K1_DMA_MASK)) {
                printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n");
                kfree(card);
@@ -623,27 +633,17 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
        pci_set_master(pci_dev);
 
        card->iobase = pci_resource_start(pci_dev, 0);
+       card->length = pci_resource_len(pci_dev, 0); 
 
-       if (request_region(card->iobase, EMU10K1_EXTENT, card_names[pci_id->driver_data]) == NULL) {
+       if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
                printk(KERN_ERR "emu10k1: IO space in use\n");
                kfree(card);
                return -ENODEV;
        }
-       pci_dev->driver_data = card;
-       pci_dev->dma_mask = EMU10K1_DMA_MASK;
-#else
-       pci_set_master(pci_dev);
 
-       card->iobase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+       PCI_SET_DRIVER_DATA(pci_dev, card);
+       PCI_SET_DMA_MASK(pci_dev, EMU10K1_DMA_MASK);
 
-       if (check_region(card->iobase, EMU10K1_EXTENT)) {
-               printk(KERN_ERR "emu10k1: IO space in use\n");
-               kfree(card);
-               return -ENODEV;
-       }
-
-       request_region(card->iobase, EMU10K1_EXTENT, card_names[pci_id->driver_data]);
-#endif
        card->irq = pci_dev->irq;
        card->pci_dev = pci_dev;
 
@@ -654,22 +654,27 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
        }
 
        pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
+       pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
 
-       printk(KERN_INFO "emu10k1: %s rev %d found at IO 0x%04lx, IRQ %d\n", card_names[pci_id->driver_data], card->chiprev, card->iobase, card->irq);
+       printk(KERN_INFO "emu10k1: %s rev %d model 0x%x found, IO at 0x%04lx-0x%04lx, IRQ %d\n",
+               card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
+               card->iobase + card->length - 1, card->irq);
+
+       pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
+       card->isaps = (subsysvid == EMU_APS_SUBID);
 
        spin_lock_init(&card->lock);
-       card->mixeraddx = card->iobase + AC97DATA;
        init_MUTEX(&card->open_sem);
        card->open_mode = 0;
        init_waitqueue_head(&card->open_wait);
 
        /* Register devices */
-       if ((card->audio1_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
+       if ((card->audio_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
                printk(KERN_ERR "emu10k1: cannot register first audio device!\n");
                goto err_dev0;
        }
 
-       if ((card->audio2_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
+       if ((card->audio1_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
                printk(KERN_ERR "emu10k1: cannot register second audio device!\n");
                goto err_dev1;
        }
@@ -684,33 +689,27 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
                goto err_dev3;
        }
 
-       if (emu10k1_init(card) != CTSTATUS_SUCCESS) {
+       if (emu10k1_init(card) < 0) {
                printk(KERN_ERR "emu10k1: cannot initialize device!\n");
                goto err_emu10k1_init;
        }
 
-       if (audio_init(card) != CTSTATUS_SUCCESS) {
-               printk(KERN_ERR "emu10k1: cannot initialize audio!\n");
-               goto err_audio_init;
-       }
-
-       if (midi_init(card) != CTSTATUS_SUCCESS) {
+       if (midi_init(card) < 0) {
                printk(KERN_ERR "emu10k1: cannot initialize midi!\n");
                goto err_midi_init;
        }
 
+       audio_init(card);
        mixer_init(card);
 
-       DPD(2, "Hardware initialized. TRAM allocated: %u bytes\n", (unsigned int) card->tmemsize);
+       if (card->isaps)
+               emu10k1_ecard_init(card);
 
        list_add(&card->list, &emu10k1_devs);
 
        return 0;
 
       err_midi_init:
-       audio_exit(card);
-
-      err_audio_init:
        emu10k1_exit(card);
 
       err_emu10k1_init:
@@ -720,16 +719,16 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
        unregister_sound_mixer(card->mixer_num);
 
       err_dev2:
-       unregister_sound_dsp(card->audio2_num);
+       unregister_sound_dsp(card->audio1_num);
 
       err_dev1:
-       unregister_sound_dsp(card->audio1_num);
+       unregister_sound_dsp(card->audio_num);
 
       err_dev0:
        free_irq(card->irq, card);
 
       err_irq:
-       release_region(card->iobase, EMU10K1_EXTENT);
+       release_region(card->iobase, card->length);
        kfree(card);
 
        return -ENODEV;
@@ -737,26 +736,25 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
 
 static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
 {
-#if LINUX_VERSION_CODE > 0x020320
-       struct emu10k1_card *card = pci_dev->driver_data;
-#else
-       struct emu10k1_card *card = list_entry(emu10k1_devs.next, struct emu10k1_card, list);
-#endif
+       struct emu10k1_card *card = PCI_GET_DRIVER_DATA(pci_dev);
+
        midi_exit(card);
-       audio_exit(card);
        emu10k1_exit(card);
 
        unregister_sound_midi(card->midi_num);
+       
        unregister_sound_mixer(card->mixer_num);
-       unregister_sound_dsp(card->audio2_num);
+
        unregister_sound_dsp(card->audio1_num);
+       unregister_sound_dsp(card->audio_num);
 
        free_irq(card->irq, card);
-       release_region(card->iobase, EMU10K1_EXTENT);
+       release_region(card->iobase, card->length);
 
        list_del(&card->list);
 
        kfree(card);
+
        return;
 }
 
@@ -770,7 +768,6 @@ static struct pci_driver emu10k1_pci_driver = {
        remove:emu10k1_remove,
 };
 
-#if LINUX_VERSION_CODE > 0x020320
 static int __init emu10k1_init_module(void)
 {
        printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
@@ -781,44 +778,9 @@ static int __init emu10k1_init_module(void)
 static void __exit emu10k1_cleanup_module(void)
 {
        pci_unregister_driver(&emu10k1_pci_driver);
-       return;
-}
-
-#else
-
-static int __init emu10k1_init_module(void)
-{
-       struct pci_dev *dev = NULL;
-       const struct pci_device_id *pci_id = emu10k1_pci_driver.id_table;
-
-       printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
-       if (!pci_present())
-               return -ENODEV;
-
-       while (pci_id->vendor) {
-               while ((dev = pci_find_device(pci_id->vendor, pci_id->device, dev)))
-                       emu10k1_probe(dev, pci_id);
-
-               pci_id++;
-       }
-       return 0;
-}
-
-static void __exit emu10k1_cleanup_module(void)
-{
-       struct emu10k1_card *card;
-
-       while (!list_empty(&emu10k1_devs)) {
-               card = list_entry(emu10k1_devs.next, struct emu10k1_card, list);
-
-               emu10k1_remove(card->pci_dev);
-       }
 
        return;
 }
 
-#endif
-
 module_init(emu10k1_init_module);
 module_exit(emu10k1_cleanup_module);
index d7e0a4a8771a942ac481589d7b92f50a17a498c2..f94d3b6a480c92a75c8288e0f2ad2fbc1bb0c423 100644 (file)
@@ -32,6 +32,8 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
@@ -64,20 +66,20 @@ static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hd
        if ((midihdr->data = (u8 *) kmalloc(MIDIIN_BUFLEN, GFP_KERNEL)) == NULL) {
                ERROR();
                kfree(midihdr);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
-       if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) != CTSTATUS_SUCCESS) {
+       if (emu10k1_mpuin_add_buffer(midi_dev->card->mpuin, midihdr) < 0) {
                ERROR();
                kfree(midihdr->data);
                kfree(midihdr);
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        *midihdrptr = midihdr;
        list_add_tail(&midihdr->list, &midi_dev->mid_hdrs);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 static int emu10k1_midi_open(struct inode *inode, struct file *file)
@@ -138,20 +140,19 @@ static int emu10k1_midi_open(struct inode *inode, struct file *file)
 
                dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
 
-               if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo)
-                   != CTSTATUS_SUCCESS) {
+               if (emu10k1_mpuin_open(card, &dsCardMidiOpenInfo) < 0) {
                        ERROR();
                        kfree(midi_dev);
                        return -ENODEV;
                }
 
                /* Add two buffers to receive sysex buffer */
-               if (midiin_add_buffer(midi_dev, &midihdr1) != CTSTATUS_SUCCESS) {
+               if (midiin_add_buffer(midi_dev, &midihdr1) < 0) {
                        kfree(midi_dev);
                        return -ENODEV;
                }
 
-               if (midiin_add_buffer(midi_dev, &midihdr2) != CTSTATUS_SUCCESS) {
+               if (midiin_add_buffer(midi_dev, &midihdr2) < 0) {
                        list_del(&midihdr1->list);
                        kfree(midihdr1->data);
                        kfree(midihdr1);
@@ -165,8 +166,7 @@ static int emu10k1_midi_open(struct inode *inode, struct file *file)
 
                dsCardMidiOpenInfo.refdata = (unsigned long) midi_dev;
 
-               if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo)
-                   != CTSTATUS_SUCCESS) {
+               if (emu10k1_mpuout_open(card, &dsCardMidiOpenInfo) < 0) {
                        ERROR();
                        kfree(midi_dev);
                        return -ENODEV;
@@ -188,6 +188,7 @@ static int emu10k1_midi_release(struct inode *inode, struct file *file)
        struct emu10k1_card *card;
 
        lock_kernel();
+
        card = midi_dev->card;
        DPF(2, "emu10k1_midi_release()\n");
 
@@ -231,6 +232,7 @@ static int emu10k1_midi_release(struct inode *inode, struct file *file)
        card->open_mode &= ~((file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE));
        up(&card->open_sem);
        wake_up_interruptible(&card->open_wait);
+
        unlock_kernel();
 
        return 0;
@@ -252,8 +254,7 @@ static ssize_t emu10k1_midi_read(struct file *file, char *buffer, size_t count,
                return -EFAULT;
 
        if (midi_dev->mistate == MIDIIN_STATE_STOPPED) {
-               if (emu10k1_mpuin_start(midi_dev->card)
-                   != CTSTATUS_SUCCESS) {
+               if (emu10k1_mpuin_start(midi_dev->card) < 0) {
                        ERROR();
                        return -EINVAL;
                }
@@ -348,7 +349,7 @@ static ssize_t emu10k1_midi_write(struct file *file, const char *buffer, size_t
 
        spin_lock_irqsave(&midi_spinlock, flags);
 
-       if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) != CTSTATUS_SUCCESS) {
+       if (emu10k1_mpuout_add_buffer(midi_dev->card, midihdr) < 0) {
                ERROR();
                kfree(midihdr->data);
                kfree(midihdr);
@@ -422,20 +423,20 @@ int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned lon
                break;
 
        default:                /* Unknown message */
-               return CTSTATUS_ERROR;
+               return -1;
        }
 
        spin_unlock_irqrestore(&midi_spinlock, flags);
 
-       return CTSTATUS_SUCCESS;
+       return 0;
 }
 
 /* MIDI file operations */
 struct file_operations emu10k1_midi_fops = {
-       owner:THIS_MODULE,
-       read:emu10k1_midi_read,
-       write:emu10k1_midi_write,
-       poll:emu10k1_midi_poll,
-       open:emu10k1_midi_open,
-       release:emu10k1_midi_release,
+        owner:         THIS_MODULE,
+       read:           emu10k1_midi_read,
+       write:          emu10k1_midi_write,
+       poll:           emu10k1_midi_poll,
+       open:           emu10k1_midi_open,
+       release:        emu10k1_midi_release,
 };
index 62796146f49b0989fae97f0f9784b1e71e6f73cc..f28787f87b6ee78fb9bbd2e18d347b5e5cc3d860 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     mixer.c - /dev/mixer interface for emu10k1 driver
 
 #define __NO_VERSION__         /* Kernel version only defined once */
 #include <linux/module.h>
+#include <linux/version.h>
+#include <linux/bitops.h>
 #include <asm/uaccess.h>
 
 #include "hwaccess.h"
+#include "8010.h"
+#include "recmgr.h"
 
 #define AC97_PESSIMISTIC
 #undef OSS_DOCUMENTED_MIXER_SEMANTICS
 #define vol_to_sw_5(hwvol) (((31 - (hwvol)) * 100) / 31)
 #define vol_to_sw_4(hwvol) (((15 - (hwvol)) * 100) / 15)
 
+#define DM_MUTE 0x80000000
+
 #ifdef PRIVATE_PCM_VOLUME
 struct sblive_pcm_volume_rec sblive_pcm_volume[MAX_PCM_CHANNELS];
+u16 pcm_last_mixer = 0x6464;
 #endif
 
-/* --------------------------------------------------------------------- */
-
-/*
- * hweightN: returns the hamming weight (i.e. the number
- * of bits set) of a N-bit word
- */
-
-#ifdef hweight32
-#undef hweight32
-#endif
-
-extern __inline__ unsigned int hweight32(unsigned int w)
-{
-       unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
-
-       res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
-       res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
-       res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
-       return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
-}
-
 /* Mapping arrays */
 static const unsigned int recsrc[] = {
        SOUND_MASK_MIC,
@@ -84,10 +69,10 @@ static const unsigned int recsrc[] = {
        SOUND_MASK_VOLUME,
        SOUND_MASK_OGAIN,       /* Used to be PHONEOUT */
        SOUND_MASK_PHONEIN,
+#ifdef TONE_CONTROL
        SOUND_MASK_TREBLE,
        SOUND_MASK_BASS,
-       SOUND_MASK_MONITOR,
-       SOUND_MASK_PCM,
+#endif
 };
 
 static const unsigned char volreg[SOUND_MIXER_NRDEVICES] = {
@@ -115,7 +100,7 @@ static const unsigned char volreg[SOUND_MIXER_NRDEVICES] = {
        /* 4 bit mono */
        [SOUND_MIXER_IGAIN] = AC97_RECORDGAINMIC,
        /* test code */
-       [SOUND_MIXER_BASS] = AC97_GENERALPUPOSE,
+       [SOUND_MIXER_BASS] = AC97_GENERALPURPOSE,
        [SOUND_MIXER_TREBLE] = AC97_MASTERTONE,
        [SOUND_MIXER_LINE2] = AC97_PCMOUTVOLUME,
        [SOUND_MIXER_DIGITAL2] = AC97_MASTERVOLUME
@@ -133,13 +118,26 @@ static int mixer_rdch(struct emu10k1_card *card, unsigned int ch, int *arg)
        int j;
        int nL, nR;
 
+       switch (ch) {
+       case SOUND_MIXER_PCM:
+       case SOUND_MIXER_VOLUME:
+#ifdef TONE_CONTROL
+       case SOUND_MIXER_TREBLE:
+        case SOUND_MIXER_BASS:
+#endif
+                return put_user(0x0000, (int *) arg);
+       default:
+               break;
+       }
+
+       if(card->isaps)
+               return -EINVAL;
+
        switch (ch) {
        case SOUND_MIXER_LINE:
        case SOUND_MIXER_CD:
        case SOUND_MIXER_VIDEO:
        case SOUND_MIXER_LINE1:
-       case SOUND_MIXER_PCM:
-       case SOUND_MIXER_VOLUME:
                sblive_readac97(card, volreg[ch], &reg);
                nL = ((~(reg >> 8) & 0x1f) * 100) / 32;
                nR = (~(reg & 0x1f) * 100) / 32;
@@ -165,9 +163,6 @@ static int mixer_rdch(struct emu10k1_card *card, unsigned int ch, int *arg)
                nR = (~(reg & 0x1f) * 100) / 16;
                return put_user(reg & 0x8000 ? 0 : (nL << 8) | nR, (int *) arg);
 
-       case SOUND_MIXER_TREBLE:
-       case SOUND_MIXER_BASS:
-               return put_user(0x0000, (int *) arg);
        default:
                return -EINVAL;
        }
@@ -204,7 +199,9 @@ static const unsigned char volidx[SOUND_MIXER_NRDEVICES] = {
        [SOUND_MIXER_DIGITAL2] = 19
 };
 
-u32 bass_table[41][5] = {
+#ifdef TONE_CONTROL
+
+static const u32 bass_table[41][5] = {
        { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
        { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
        { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
@@ -248,7 +245,7 @@ u32 bass_table[41][5] = {
        { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
 };
 
-u32 treble_table[41][5] = {
+static const u32 treble_table[41][5] = {
        { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
        { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
        { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
@@ -299,8 +296,8 @@ static void set_bass(struct emu10k1_card *card, int l, int r)
        l = (l * 40 + 50) / 100;
        r = (r * 40 + 50) / 100;
        for (i = 0; i < 5; i++) {
-               sblive_writeptr(card, FXGPREGBASE + 0x70 + (i * 2), 0, bass_table[l][i]);
-               sblive_writeptr(card, FXGPREGBASE + 0x70 + (i * 2) + 1, 0, bass_table[r][i]);
+               sblive_writeptr(card, FXGPREGBASE + 0x80 + (i * 2), 0, bass_table[l][i]);
+               sblive_writeptr(card, FXGPREGBASE + 0x80 + (i * 2) + 1, 0, bass_table[r][i]);
        }
 }
 
@@ -311,12 +308,14 @@ static void set_treble(struct emu10k1_card *card, int l, int r)
        l = (l * 40 + 50) / 100;
        r = (r * 40 + 50) / 100;
        for (i = 0; i < 5; i++) {
-               sblive_writeptr(card, FXGPREGBASE + 0x80 + (i * 2), 0, treble_table[l][i]);
-               sblive_writeptr(card, FXGPREGBASE + 0x80 + (i * 2) + 1, 0, treble_table[r][i]);
+               sblive_writeptr(card, FXGPREGBASE + 0x90 + (i * 2), 0, treble_table[l][i]);
+               sblive_writeptr(card, FXGPREGBASE + 0x90 + (i * 2) + 1, 0, treble_table[r][i]);
        }
 }
 
-u32 db_table[101] = {
+#endif
+
+static const u32 db_table[101] = {
        0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540,
        0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8,
        0x0207567a, 0x021fd03d, 0x0239714c, 0x02544792, 0x027061a1,
@@ -340,6 +339,29 @@ u32 db_table[101] = {
        0x7fffffff,
 };
 
+static void aps_update_digital(struct emu10k1_card *card)
+{
+       int i, l1, r1, l2, r2;
+       
+       i = card->arrwVol[volidx[SOUND_MIXER_VOLUME]];
+       l1 = (i & 0xff);
+       r1 = ((i >> 8) & 0xff);
+
+       i = card->arrwVol[volidx[SOUND_MIXER_PCM]];
+       l2 = (i & 0xff);
+       r2 = ((i >> 8) & 0xff);
+       
+       for (i = 0; i < 108; i++) {
+               if (card->digmix[i] != DM_MUTE) {
+                       if ((i % 18 >= 0) && (i % 18 < 4))
+                               card->digmix[i] = ((i & 1) ? ((u64) db_table[r1] * (u64) db_table[r2]) : ((u64) db_table[l1] * (u64) db_table[l2])) >> 31;
+                       else
+                               card->digmix[i] = (i & 1) ? db_table[r1] : db_table[l1];
+                       sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, card->digmix[i]);
+               }
+       }
+}
+
 static void update_digital(struct emu10k1_card *card)
 {
        int i, k, l1, r1, l2, r2, l3, r3, l4, r4;
@@ -376,11 +398,11 @@ static void update_digital(struct emu10k1_card *card)
                l1 = i;
        }
 
-       for (i = 0; i < 16; i++) {
-               if (card->digmix[i] != 0x80000000) {
-                       if ((i >= 0) && (i < 4))
+       for (i = 0; i < 36; i++) {
+               if (card->digmix[i] != DM_MUTE) {
+                       if (((i >= 0) && (i < 4)) || ((i >= 18) && (i < 22)))
                                j = (i & 1) ? ((u64) db_table[r1] * (u64) db_table[r3]) : ((u64) db_table[l1] * (u64) db_table[l3]);
-                       else if ((i == 6) || (i == 7))
+                       else if ((i == 6) || (i == 7) || (i == 24) || (i == 25))
                                j = (i & 1) ? ((u64) db_table[r1] * (u64) db_table[r4]) : ((u64) db_table[l1] * (u64) db_table[l4]);
                        else
                                j = ((i & 1) ? db_table[r1] : db_table[l1]) << 31;
@@ -389,11 +411,11 @@ static void update_digital(struct emu10k1_card *card)
                }
        }
 
-       for (i = 64; i < 80; i++) {
-               if (card->digmix[i] != 0x80000000) {
-                       if ((i >= 64) && (i < 68))
+       for (i = 72; i < 90; i++) {
+               if (card->digmix[i] != DM_MUTE) {
+                       if ((i >= 72) && (i < 76))
                                j = (i & 1) ? ((u64) db_table[r2] * (u64) db_table[r3]) : ((u64) db_table[l2] * (u64) db_table[l3]);
-                       else if ((i == 70) || (i == 71))
+                       else if ((i == 78) || (i == 79))
                                j = (i & 1) ? ((u64) db_table[r2] * (u64) db_table[r4]) : ((u64) db_table[l2] * (u64) db_table[l4]);
                        else
                                j = ((i & 1) ? db_table[r2] : db_table[l2]) << 31;
@@ -402,18 +424,18 @@ static void update_digital(struct emu10k1_card *card)
                }
        }
 
-       for (i = 16; i <= 80; i += 16) {
-               if (i != 64) {
+       for (i = 36; i <= 90; i += 18) {
+               if (i != 72) {
                        for (k = 0; k < 4; k++)
-                               if (card->digmix[i + k] != 0x80000000) {
+                               if (card->digmix[i + k] != DM_MUTE) {
                                        card->digmix[i + k] = db_table[l3];
                                        sblive_writeptr(card, FXGPREGBASE + 0x10 + i + k, 0, card->digmix[i + k]);
                                }
-                       if (card->digmix[i + 6] != 0x80000000) {
+                       if (card->digmix[i + 6] != DM_MUTE) {
                                card->digmix[i + 6] = db_table[l4];
                                sblive_writeptr(card, FXGPREGBASE + 0x10 + i + 6, 0, card->digmix[i + 6]);
                        }
-                       if (card->digmix[i + 7] != 0x80000000) {
+                       if (card->digmix[i + 7] != DM_MUTE) {
                                card->digmix[i + 7] = db_table[r4];
                                sblive_writeptr(card, FXGPREGBASE + 0x10 + i + 7, 0, card->digmix[i + 7]);
                        }
@@ -428,9 +450,9 @@ static void update_digital(struct emu10k1_card *card)
 static int set_pcm_attn(struct emu10k1_card *card, int ch, int l)
 {
 #ifndef PCMLEVEL
-#define PCMLEVEL 140           // almost silence
+#define PCMLEVEL 110           /* almost silence */
 #endif
-       int vol = IFATN_ATTENUATION_MASK;       // silence
+       int vol = IFATN_ATTENUATION_MASK;       /* silence */
 
        if (l > 0)
                vol = (PCMLEVEL - (l * PCMLEVEL + 50) / 100);
@@ -454,29 +476,29 @@ static int update_pcm_attn(struct emu10k1_card *card, unsigned l1, unsigned r1)
 
        for (i = 0; i < MAX_PCM_CHANNELS; i++) {
                if (sblive_pcm_volume[i].files == current->files) {
-                       sblive_pcm_volume[i].mixer = mixer;
+                       sblive_pcm_volume[i].mixer = pcm_last_mixer = mixer;
                        if (sblive_pcm_volume[i].opened) {
                                if (sblive_pcm_volume[i].channel_r < NUM_G) {
+                                       sblive_pcm_volume[i].attn_r = set_pcm_attn(card, sblive_pcm_volume[i].channel_r, r1);
                                        if (sblive_pcm_volume[i].channel_l < NUM_G)
                                                sblive_pcm_volume[i].attn_l = set_pcm_attn(card, sblive_pcm_volume[i].channel_l, l1);
-                                       sblive_pcm_volume[i].attn_r = set_pcm_attn(card, sblive_pcm_volume[i].channel_r, r1);
                                } else {
-                                       // mono voice
+                                       /* mono voice */
                                        if (sblive_pcm_volume[i].channel_l < NUM_G)
                                                sblive_pcm_volume[i].attn_l =
                                                    set_pcm_attn(card, sblive_pcm_volume[i].channel_l, (l1 >= r1) ? l1 : r1);
-                                       // to correctly handle mono voice here we would need
-                                       // to go into stereo mode and move the voice to the right & left
-                                       // looks a bit overcomlicated...
+                                               /* to correctly handle mono voice here we would need
+                                                  to go into stereo mode and move the voice to the right & left
+                                                  looks a bit overcomplicated... */
                                }
-
                        }
+
                        return 1;
+
                }
        }
-       if (i == MAX_PCM_CHANNELS)
-               card->arrwVol[volidx[SOUND_MIXER_PCM]] = mixer;
 
+       card->arrwVol[volidx[SOUND_MIXER_PCM]] = mixer;
        return 0;
 }
 #endif
@@ -505,10 +527,11 @@ int emu10k1_mixer_wrch(struct emu10k1_card *card, unsigned int ch, int val)
 
        switch (ch) {
        case SOUND_MIXER_VOLUME:
-       case SOUND_MIXER_DIGITAL1:
-       case SOUND_MIXER_LINE3:
-               DPD(4, "SOUND_MIXER_%s:\n", (ch == SOUND_MIXER_VOLUME) ? "VOLUME" : (ch == SOUND_MIXER_DIGITAL1) ? "DIGITAL1" : "LINE3");
-               update_digital(card);
+               DPF(4, "SOUND_MIXER_VOLUME:\n");
+               if (card->isaps)
+                       aps_update_digital(card);
+               else
+                       update_digital(card);
                return 0;
        case SOUND_MIXER_PCM:
                DPF(4, "SOUND_MIXER_PCM\n");
@@ -516,6 +539,34 @@ int emu10k1_mixer_wrch(struct emu10k1_card *card, unsigned int ch, int val)
                if (update_pcm_attn(card, l1, r1))
                        return 0;
 #endif
+               if (card->isaps)
+                       aps_update_digital(card);
+               else
+                       update_digital(card);
+               return 0;
+#ifdef TONE_CONTROL
+       case SOUND_MIXER_TREBLE:
+                DPF(4, "SOUND_MIXER_TREBLE:\n");
+                set_treble(card, l1, r1);
+                return 0;
+
+        case SOUND_MIXER_BASS:
+                DPF(4, "SOUND_MIXER_BASS:\n");
+                set_bass(card, l1, r1);
+               return 0;
+#endif
+       default:
+               break;
+       }
+
+
+       if (card->isaps)
+               return -EINVAL;
+
+       switch (ch) {
+       case SOUND_MIXER_DIGITAL1:
+       case SOUND_MIXER_LINE3:
+               DPD(4, "SOUND_MIXER_%s:\n", (ch == SOUND_MIXER_DIGITAL1) ? "DIGITAL1" : "LINE3");
                update_digital(card);
                return 0;
        case SOUND_MIXER_DIGITAL2:
@@ -549,7 +600,7 @@ int emu10k1_mixer_wrch(struct emu10k1_card *card, unsigned int ch, int val)
                DPF(4, "SOUND_MIXER_MIC:\n");
                i = 0;
                if (l1 >= 30)
-                       // 20dB / (34.5dB + 12dB + 20dB) * 100 = 30
+                       /* 20dB / (34.5dB + 12dB + 20dB) * 100 = 30 */
                {
                        l1 -= 30;
                        i = 0x40;
@@ -572,16 +623,6 @@ int emu10k1_mixer_wrch(struct emu10k1_card *card, unsigned int ch, int val)
                sblive_writeac97(card, volreg[ch], wval);
                return 0;
 
-       case SOUND_MIXER_TREBLE:
-               DPF(4, "SOUND_MIXER_TREBLE:\n");
-               set_treble(card, l1, r1);
-               return 0;
-
-       case SOUND_MIXER_BASS:
-               DPF(4, "SOUND_MIXER_BASS:\n");
-               set_bass(card, l1, r1);
-               return 0;
-
        default:
                DPF(2, "Got unknown SOUND_MIXER ioctl\n");
                return -EINVAL;
@@ -597,6 +638,10 @@ static loff_t emu10k1_mixer_llseek(struct file *file, loff_t offset, int origin)
 /* Mixer file operations */
 
 /* FIXME: Do we need spinlocks in here? */
+/* WARNING! not all the ioctl's are supported by the emu-APS
+   (anything AC97 related). As a general rule keep the AC97 related ioctls
+   separate from the rest. This will make it easier to rewrite the mixer
+   using the kernel AC97 interface. */ 
 static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
        static const char id[] = "SBLive";
@@ -658,10 +703,201 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
                        return -EFAULT;
 
                for (i = 0; i < sizeof(card->digmix) / sizeof(card->digmix[0]); i++)
-                       sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, (card->digmix[i] & 0x80000000) ? 0 : card->digmix[i]);
+                       sblive_writeptr(card, FXGPREGBASE + 0x10 + i, 0, (card->digmix[i] & DM_MUTE) ? 0 : card->digmix[i]);
                return 0;
 
                break;
+       case SOUND_MIXER_PRIVATE3: {
+                       struct mixer_private_ioctl ctl;
+
+                       if (copy_from_user(&ctl, (void *) arg, sizeof(struct mixer_private_ioctl)))
+                               return -EFAULT;
+
+                       switch (ctl.cmd) {
+#ifdef EMU10K1_DEBUG
+                       case CMD_WRITEFN0:
+                               emu10k1_writefn0(card, ctl.val[0], ctl.val[1]);
+                               return 0;
+                               break;
+
+                       case CMD_WRITEPTR:
+                               if(ctl.val[1] >= 0x40)
+                                       return -EINVAL;
+
+                               if(ctl.val[0] > 0xff)
+                                       return -EINVAL;
+
+                               if((ctl.val[0] & 0x7ff) > 0x3f)
+                                       ctl.val[1] = 0x00;
+
+                               sblive_writeptr(card, ctl.val[0], ctl.val[1], ctl.val[2]);
+
+                               return 0;
+                               break;
+#endif
+                       case CMD_READFN0:
+                               ctl.val[2] = emu10k1_readfn0(card, ctl.val[0]);
+
+                               if (copy_to_user((void *) arg, &ctl, sizeof(struct mixer_private_ioctl)))
+                                       return -EFAULT;
+
+                               return 0;
+                               break;
+
+                       case CMD_READPTR:
+                               if(ctl.val[1] >= 0x40)
+                                       return -EINVAL;
+
+                               if((ctl.val[0] & 0x7ff) > 0xff)
+                                       return -EINVAL;
+
+                               if((ctl.val[0] & 0x7ff) > 0x3f)
+                                       ctl.val[1] = 0x00;
+
+                               ctl.val[2] = sblive_readptr(card, ctl.val[0], ctl.val[1]);
+
+                               if (copy_to_user((void *) arg, &ctl, sizeof(struct mixer_private_ioctl)))
+                                       return -EFAULT;
+
+                               return 0;
+                               break;
+
+                       case CMD_SETRECSRC:
+                               switch(ctl.val[0]){
+                               case WAVERECORD_AC97:
+                                       if(card->isaps)
+                                               return -EINVAL;
+                                       card->wavein.recsrc = WAVERECORD_AC97;
+                                       break;
+                               case WAVERECORD_MIC:    
+                                       card->wavein.recsrc = WAVERECORD_MIC;
+                                       break;
+                               case WAVERECORD_FX:
+                                       card->wavein.recsrc = WAVERECORD_FX;
+                                       card->wavein.fxwc = ctl.val[1] & 0xffff;
+                                       if(!card->wavein.fxwc)
+                                               return -EINVAL;
+                                       break;
+                               default:
+                                       return -EINVAL;
+                               }
+                               return 0;
+                               break;
+
+                       case CMD_GETRECSRC:
+                               ctl.val[0] = card->wavein.recsrc;
+                               ctl.val[1] = card->wavein.fxwc;
+                               if (copy_to_user((void *) arg, &ctl, sizeof(struct mixer_private_ioctl)))
+                                       return -EFAULT;
+
+                               return 0;
+                               break;
+
+                       case CMD_GETVOICEPARAM:
+
+                               ctl.val[0] = card->waveout.send_routing[0];
+                               ctl.val[1] = card->waveout.send_a[0] | card->waveout.send_b[0] << 8 |
+                                            card->waveout.send_c[0] << 16 | card->waveout.send_d[0] << 24;
+
+                               ctl.val[2] = card->waveout.send_routing[1]; 
+                               ctl.val[3] = card->waveout.send_a[1] | card->waveout.send_b[1] << 8 |
+                                            card->waveout.send_c[1] << 16 | card->waveout.send_d[1] << 24;
+
+                               ctl.val[4] = card->waveout.send_routing[2]; 
+                               ctl.val[5] = card->waveout.send_a[2] | card->waveout.send_b[2] << 8 |
+                                            card->waveout.send_c[2] << 16 | card->waveout.send_d[2] << 24;
+
+                               if (copy_to_user((void *) arg, &ctl, sizeof(struct mixer_private_ioctl)))
+                                       return -EFAULT;
+
+                               return 0;
+                               break;
+
+                       case CMD_SETVOICEPARAM:
+                               card->waveout.send_routing[0] = ctl.val[0] & 0xffff;
+                               card->waveout.send_a[0] = ctl.val[1] & 0xff;
+                               card->waveout.send_b[0] = (ctl.val[1] >> 8) & 0xff;
+                               card->waveout.send_c[0] = (ctl.val[1] >> 16) & 0xff;
+                               card->waveout.send_d[0] = (ctl.val[1] >> 24) & 0xff;
+
+                               card->waveout.send_routing[1] = ctl.val[2] & 0xffff;
+                               card->waveout.send_a[1] = ctl.val[3] & 0xff;
+                               card->waveout.send_b[1] = (ctl.val[3] >> 8) & 0xff;
+                               card->waveout.send_c[1] = (ctl.val[3] >> 16) & 0xff;
+                               card->waveout.send_d[1] = (ctl.val[3] >> 24) & 0xff;
+
+                               card->waveout.send_routing[2] = ctl.val[4] & 0xffff;
+                               card->waveout.send_a[2] = ctl.val[5] & 0xff;
+                               card->waveout.send_b[2] = (ctl.val[5] >> 8) & 0xff;
+                               card->waveout.send_c[2] = (ctl.val[5] >> 16) & 0xff;
+                               card->waveout.send_d[2] = (ctl.val[5] >> 24) & 0xff;
+
+                               return 0;
+                               break;
+
+                       default:
+                               return -EINVAL;
+                               break;
+                       }
+               }
+               break;
+
+       case SOUND_MIXER_PRIVATE4:{
+                       u32 size;
+                       int size_reg = 0;
+
+                       if (copy_from_user(&size, (void *) arg, sizeof(size)))
+                               return -EFAULT;
+
+                       DPD(2,"External tram size 0x%x\n", size);
+
+                       if(size > 0x1fffff)
+                               return -EINVAL;
+
+                       if (size != 0) {        
+                               size = (size - 1) >> 14;
+
+                               while (size) {
+                                       size >>= 1;
+                                       size_reg++;
+                               }
+
+                               size = 0x4000 << size_reg;
+                       }
+
+                       DPD(2,"External tram size 0x%x 0x%x\n", size, size_reg);
+
+                       if (size != card->tankmem.size) {
+                               if (card->tankmem.size > 0) {
+                                       emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 1);
+
+                                       sblive_writeptr_tag(card, 0, TCB, 0,
+                                                           TCBS, 0,
+                                                           TAGLIST_END);
+
+                                       pci_free_consistent(card->pci_dev, card->tankmem.size,
+                                                           card->tankmem.addr, card->tankmem.dma_handle);
+
+                                       card->tankmem.size = 0;
+                               }
+
+                               if (size != 0) {
+                                       if ((card->tankmem.addr = pci_alloc_consistent(card->pci_dev, size,
+                                            &card->tankmem.dma_handle)) == NULL)
+                                               return -ENOMEM;
+
+                                       card->tankmem.size = size;
+
+                                       sblive_writeptr_tag(card, 0, TCB, card->tankmem.dma_handle,
+                                                           TCBS, size_reg,
+                                                           TAGLIST_END);
+
+                                       emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0);
+                               }
+                       }
+                       return 0;
+               }
+               break;
 
        default:
                break;
@@ -672,56 +908,106 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
 
        if (_IOC_DIR(cmd) == _IOC_READ) {
                switch (_IOC_NR(cmd)) {
-               case SOUND_MIXER_RECSRC:        /* Arg contains a bit for each recording source */
-                       DPF(2, "SOUND_MIXER_READ_RECSRC\n");
-                       sblive_readac97(card, AC97_RECORDSELECT, &reg);
-                       return put_user(recsrc[reg & 7], (int *) arg);
-
-               case SOUND_MIXER_DEVMASK:       /* Arg contains a bit for each supported device */
-                       DPF(4, "SOUND_MIXER_READ_DEVMASK\n");
+                       case SOUND_MIXER_DEVMASK:       /* Arg contains a bit for each supported device */
+                        DPF(4, "SOUND_MIXER_READ_DEVMASK\n");
+                       if (card->isaps)
+#ifdef TONE_CONTROL
+                               return put_user(SOUND_MASK_PCM | SOUND_MASK_VOLUME |
+                                               SOUND_MASK_BASS | SOUND_MASK_TREBLE,
+                                               (int *) arg); 
+#else
+                               return put_user(SOUND_MASK_PCM | SOUND_MASK_VOLUME,
+                                               (int *) arg); 
+#endif
+               
+#ifdef TONE_CONTROL
+                       return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
+                                        SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
+                                        SOUND_MASK_PCM | SOUND_MASK_VOLUME |
+                                        SOUND_MASK_PHONEIN | SOUND_MASK_MIC |
+                                        SOUND_MASK_BASS | SOUND_MASK_TREBLE |
+                                        SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER |
+                                        SOUND_MASK_LINE3 | SOUND_MASK_DIGITAL1 | 
+                                        SOUND_MASK_DIGITAL2 | SOUND_MASK_LINE2, (int *) arg);
+#else
                        return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
+                                        SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
+                                        SOUND_MASK_PCM | SOUND_MASK_VOLUME |
+                                        SOUND_MASK_PHONEIN | SOUND_MASK_MIC |
+                                        SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER |
+                                        SOUND_MASK_LINE3 | SOUND_MASK_DIGITAL1 | 
+                                        SOUND_MASK_DIGITAL2 | SOUND_MASK_LINE2, (int *) arg);
+#endif
+
+                       case SOUND_MIXER_RECMASK:       /* Arg contains a bit for each supported recording source */
+                               DPF(2, "SOUND_MIXER_READ_RECMASK\n");
+                               if (card->isaps)
+                                       return put_user(0, (int *) arg);
+
+                               return put_user(SOUND_MASK_MIC | SOUND_MASK_CD |
+                                       SOUND_MASK_LINE1 | SOUND_MASK_LINE |
+                                       SOUND_MASK_VOLUME | SOUND_MASK_OGAIN |
+                                       SOUND_MASK_PHONEIN, (int *) arg);
+
+                       case SOUND_MIXER_STEREODEVS:    /* Mixer channels supporting stereo */
+                               DPF(2, "SOUND_MIXER_READ_STEREODEVS\n");
+
+                               if (card->isaps)
+#ifdef TONE_CONTROL
+                                       return put_user(SOUND_MASK_PCM | SOUND_MASK_VOLUME |
+                                                       SOUND_MASK_BASS | SOUND_MASK_TREBLE,
+                                                       (int *) arg);
+#else
+                                       return put_user(SOUND_MASK_PCM | SOUND_MASK_VOLUME,
+                                                       (int *) arg);
+#endif
+
+#ifdef TONE_CONTROL
+                               return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
                                        SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
                                        SOUND_MASK_PCM | SOUND_MASK_VOLUME |
-                                       SOUND_MASK_PHONEIN | SOUND_MASK_MIC |
                                        SOUND_MASK_BASS | SOUND_MASK_TREBLE |
-                                       SOUND_MASK_RECLEV | SOUND_MASK_SPEAKER |
-                                       SOUND_MASK_LINE3 | SOUND_MASK_DIGITAL1 | 
-                                       SOUND_MASK_DIGITAL2 | SOUND_MASK_LINE2, (int *) arg);
-               case SOUND_MIXER_RECMASK:       /* Arg contains a bit for each supported recording source */
-                       DPF(2, "SOUND_MIXER_READ_RECMASK\n");
-                       return put_user(SOUND_MASK_MIC | SOUND_MASK_CD |
-                                       SOUND_MASK_LINE1 | SOUND_MASK_LINE | 
-                                       SOUND_MASK_VOLUME | SOUND_MASK_OGAIN | 
-                                       SOUND_MASK_PHONEIN | SOUND_MASK_MONITOR | 
-                                       SOUND_MASK_PCM, (int *) arg);
-
-               case SOUND_MIXER_STEREODEVS:    /* Mixer channels supporting stereo */
-                       DPF(2, "SOUND_MIXER_READ_STEREODEVS\n");
-                       return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
+                                       SOUND_MASK_RECLEV | SOUND_MASK_LINE3 |
+                                       SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 |
+                                       SOUND_MASK_LINE2, (int *) arg);
+#else
+                               return put_user(SOUND_MASK_LINE | SOUND_MASK_CD |
                                        SOUND_MASK_OGAIN | SOUND_MASK_LINE1 |
                                        SOUND_MASK_PCM | SOUND_MASK_VOLUME |
-                                       SOUND_MASK_BASS | SOUND_MASK_TREBLE |
                                        SOUND_MASK_RECLEV | SOUND_MASK_LINE3 |
-                                       SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 | 
+                                       SOUND_MASK_DIGITAL1 | SOUND_MASK_DIGITAL2 |
                                        SOUND_MASK_LINE2, (int *) arg);
+#endif
 
-               case SOUND_MIXER_CAPS:
-                       DPF(2, "SOUND_MIXER_READ_CAPS\n");
-                       return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
-
+                       case SOUND_MIXER_CAPS:
+                               DPF(2, "SOUND_MIXER_READ_CAPS\n");
+                               return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
 #ifdef PRIVATE_PCM_VOLUME
-               case SOUND_MIXER_PCM:
-                       // needs to be before default: !!
-                       {
-                               int i;
-
-                               for (i = 0; i < MAX_PCM_CHANNELS; i++) {
-                                       if (sblive_pcm_volume[i].files == current->files) {
-                                               return put_user((int) sblive_pcm_volume[i].mixer, (int *) arg);
-                                       }
-                               }
-                       }
+                case SOUND_MIXER_PCM:
+                        /* needs to be before default: !!*/
+                        {
+                                int i;
+
+                                for (i = 0; i < MAX_PCM_CHANNELS; i++) {
+                                        if (sblive_pcm_volume[i].files == current->files) {
+                                                return put_user((int) sblive_pcm_volume[i].mixer, (int *) arg);
+                                        }
+                                }
+                        }
 #endif
+               default:
+                       break;
+               }
+
+               switch (_IOC_NR(cmd)) {
+               case SOUND_MIXER_RECSRC:        /* Arg contains a bit for each recording source */
+                       DPF(2, "SOUND_MIXER_READ_RECSRC\n");
+                       if (card->isaps)
+                               return put_user(0, (int *) arg);
+
+                       sblive_readac97(card, AC97_RECORDSELECT, &reg);
+                       return put_user(recsrc[reg & 7], (int *) arg);
+
                default:
                        i = _IOC_NR(cmd);
                        DPD(4, "SOUND_MIXER_READ(%d)\n", i);
@@ -737,6 +1023,7 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
 #endif                         /* OSS_DOCUMENTED_MIXER_SEMANTICS */
                }
        }
+
        /* End of _IOC_READ */
        if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE))
                return -EINVAL;
@@ -748,10 +1035,13 @@ static int emu10k1_mixer_ioctl(struct inode *inode, struct file *file, unsigned
        case SOUND_MIXER_RECSRC:        /* Arg contains a bit for each recording source */
                DPF(2, "SOUND_MIXER_WRITE_RECSRC\n");
 
+               if (card->isaps)
+                       return -EINVAL;
+
                get_user_ret(val, (int *) arg, -EFAULT);
                i = hweight32(val);
                if (i == 0)
-                       return 0;       /*val = mixer_recmask(s); */
+                       return 0;       /* val = mixer_recmask(s); */
                else if (i > 1) {
                        sblive_readac97(card, AC97_RECORDSELECT, &reg);
                        val &= ~recsrc[reg & 7];
@@ -809,14 +1099,14 @@ static int emu10k1_mixer_open(struct inode *inode, struct file *file)
 
 static int emu10k1_mixer_release(struct inode *inode, struct file *file)
 {
-       DPF(3, "emu10k1_mixer_release()\n");
+       DPF(4, "emu10k1_mixer_release()\n");
        return 0;
 }
 
 struct file_operations emu10k1_mixer_fops = {
-       owner:THIS_MODULE,
-       llseek:emu10k1_mixer_llseek,
-       ioctl:emu10k1_mixer_ioctl,
-       open:emu10k1_mixer_open,
-       release:emu10k1_mixer_release,
+        owner:         THIS_MODULE,
+       llseek:         emu10k1_mixer_llseek,
+       ioctl:          emu10k1_mixer_ioctl,
+       open:           emu10k1_mixer_open,
+       release:        emu10k1_mixer_release,
 };
diff --git a/drivers/sound/emu10k1/osutils.c b/drivers/sound/emu10k1/osutils.c
deleted file mode 100644 (file)
index c0f5f63..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-
-/*
- **********************************************************************
- *     osutils.c - OS Services layer for emu10k1 driver
- *     Copyright 1999, 2000 Creative Labs, Inc.
- *
- **********************************************************************
- *
- *     Date                 Author          Summary of changes
- *     ----                 ------          ------------------
- *     October 20, 1999     Bertrand Lee    base code release
- *     November 2, 1999     Alan Cox        cleaned up
- *
- **********************************************************************
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this program; if not, write to the Free
- *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *     USA.
- *
- **********************************************************************
- */
-
-#include "hwaccess.h"
-
-struct memhandle *emu10k1_alloc_memphysical(u32 size)
-{
-       struct memhandle *handle;
-       u32 reqpage, order;
-
-       if ((handle = (struct memhandle *) kmalloc(sizeof(struct memhandle), GFP_KERNEL)) == NULL)
-               return handle;
-
-       DPD(3, "kmalloc: [%p]\n", handle);
-
-       order = 0;
-       reqpage = size / PAGE_SIZE;
-
-       if (size % PAGE_SIZE)
-               reqpage++;
-
-       if (reqpage != 0) {
-               reqpage--;
-               while (reqpage > 0) {
-                       reqpage >>= 1;
-                       order++;
-               }
-       }
-
-       if ((handle->virtaddx = (void *) __get_free_pages(GFP_KERNEL, order)) == NULL) {
-               kfree(handle);
-
-               DPD(3, "kfree: [%p]\n", handle);
-               return (void *) NULL;
-       }
-
-       /* in linux, we can directly access physical address, don't need to do
-        * phys_to_virt.
-        * In linux kernel 2.0.36, virt_to_bus does nothing, get_free_pages
-        * returns physical address. But in kernel 2.2.1 upwards,
-        * get_free_pages returns virtual address, we need to convert it
-        * to physical address. Then this physical address can be used to
-        * program hardware registers. */
-       handle->busaddx = virt_to_bus(handle->virtaddx);
-       handle->order = order;
-
-       DPD(3, "__get_free_pages: [%p] %lx\n", handle->virtaddx, handle->busaddx);
-
-       return handle;
-}
-
-void emu10k1_free_memphysical(struct memhandle *handle)
-{
-       free_pages((unsigned long) handle->virtaddx, handle->order);
-       kfree(handle);
-
-       DPD(3, "free_pages: [%p]\n", handle->virtaddx);
-       DPD(3, "kfree: [%p]\n", handle);
-
-       return;
-}
index 18980ce4e6cd71694b8b56cc95f78097bfe2c221..81af4419e49225b3995a12823e2cf77afd64c441 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     recmgr.c -- Recording manager for emu10k1 driver
  **********************************************************************
  */
 
-#include "hwaccess.h"
+#include "8010.h"
 #include "recmgr.h"
 
-void emu10k1_start_record(struct record *rec_ptr)
+void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
 {
-       struct emu10k1_card *hw_ptr = rec_ptr->card;
-
        DPF(2, "emu10k1_start_record()\n");
-       DPD(2, "bus addx: %lx\n", rec_ptr->busaddx);
 
-       sblive_writeptr(hw_ptr, rec_ptr->bufaddrreg, 0, rec_ptr->busaddx);
-       sblive_writeptr(hw_ptr, rec_ptr->bufsizereg, 0, rec_ptr->bufsize);
+       sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval);
 
-       if (rec_ptr->adcctl)
-               sblive_writeptr(hw_ptr, ADCCR, 0, rec_ptr->adcctl);
+       if (buffer->adcctl)
+               sblive_writeptr(card, ADCCR, 0, buffer->adcctl);
 
        return;
 }
 
-void emu10k1_stop_record(struct record *rec_ptr)
+void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer)
 {
-       struct emu10k1_card *hw_ptr = rec_ptr->card;
-
        DPF(2, "emu10k1_stop_record()\n");
 
        /* Disable record transfer */
-       if (rec_ptr->adcctl)
-               sblive_writeptr(hw_ptr, ADCCR, 0, 0);
+       if (buffer->adcctl)
+               sblive_writeptr(card, ADCCR, 0, 0);
 
-       sblive_writeptr(hw_ptr, rec_ptr->bufsizereg, 0, ADCBS_BUFSIZE_NONE);
+       sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE);
 
        return;
 }
 
-void emu10k1_set_record_src(struct record *rec_ptr, u8 recsrc)
+void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst)
 {
+       struct wavein_buffer *buffer = &wiinst->buffer;
+
        DPF(2, "emu10k1_set_record_src()\n");
 
-       switch (recsrc) {
+       switch (wiinst->recsrc) {
 
        case WAVERECORD_AC97:
                DPF(2, "recording source: AC97\n");
-               rec_ptr->bufsizereg = ADCBS;
-               rec_ptr->bufaddrreg = ADCBA;
-               rec_ptr->bufidxreg = ADCIDX_IDX;
+               buffer->sizereg = ADCBS;
+               buffer->addrreg = ADCBA;
+               buffer->idxreg = ADCIDX_IDX;
 
-               switch (rec_ptr->samplingrate) {
+               switch (wiinst->format.samplingrate) {
                case 0xBB80:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_48;
+                       buffer->adcctl = ADCCR_SAMPLERATE_48;
                        break;
                case 0xAC44:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_44;
+                       buffer->adcctl = ADCCR_SAMPLERATE_44;
                        break;
                case 0x7D00:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_32;
+                       buffer->adcctl = ADCCR_SAMPLERATE_32;
                        break;
                case 0x5DC0:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_24;
+                       buffer->adcctl = ADCCR_SAMPLERATE_24;
                        break;
                case 0x5622:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_22;
+                       buffer->adcctl = ADCCR_SAMPLERATE_22;
                        break;
                case 0x3E80:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_16;
+                       buffer->adcctl = ADCCR_SAMPLERATE_16;
                        break;
                case 0x2B11:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_11;
+                       buffer->adcctl = ADCCR_SAMPLERATE_11;
                        break;
                case 0x1F40:
-                       rec_ptr->adcctl = ADCCR_SAMPLERATE_8;
+                       buffer->adcctl = ADCCR_SAMPLERATE_8;
                        break;
                default:
+                       BUG();
                        break;
                }
 
-               rec_ptr->adcctl |= ADCCR_LCHANENABLE;
+               buffer->adcctl |= ADCCR_LCHANENABLE;
 
-               if (rec_ptr->is_stereo)
-                       rec_ptr->adcctl |= ADCCR_RCHANENABLE;
-
-               //      rec_ptr->fxwc = 0;
+               if (wiinst->format.channels == 2)
+                       buffer->adcctl |= ADCCR_RCHANENABLE;
 
                break;
 
        case WAVERECORD_MIC:
                DPF(2, "recording source: MIC\n");
-               rec_ptr->bufsizereg = MICBS;
-               rec_ptr->bufaddrreg = MICBA;
-               rec_ptr->bufidxreg = MICIDX_IDX;
-               rec_ptr->adcctl = 0;
-               //      rec_ptr->fxwc = 0;
+               buffer->sizereg = MICBS;
+               buffer->addrreg = MICBA;
+               buffer->idxreg = MICIDX_IDX;
+               buffer->adcctl = 0;
                break;
 
        case WAVERECORD_FX:
                DPF(2, "recording source: FX\n");
-               rec_ptr->bufsizereg = FXBS;
-               rec_ptr->bufaddrreg = FXBA;
-               rec_ptr->bufidxreg = FXIDX_IDX;
-               rec_ptr->adcctl = 0;
-               //      rec_ptr->fxwc = 0x000ffff;
+               buffer->sizereg = FXBS;
+               buffer->addrreg = FXBA;
+               buffer->idxreg = FXIDX_IDX;
+               buffer->adcctl = 0;
+
+               sblive_writeptr(card, FXWC, 0, wiinst->fxwc);
                break;
        default:
+               BUG();
                break;
        }
 
+       DPD(2, "bus addx: %x\n", buffer->dma_handle);
+
+       sblive_writeptr(card, buffer->addrreg, 0, buffer->dma_handle);
+
        return;
 }
index 1fbde606b6969f0ad63fd9bab6470db913d6cd87..6ee3f7795a21e76913008f30e7aa598c191cdc3f 100644 (file)
 #ifndef _RECORDMGR_H
 #define _RECORDMGR_H
 
-struct record 
-{
-       struct emu10k1_card *card;
-       u8 *recbuffer;
-       u32 recpos;
-       int is_stereo;
-       int is_16bit;
-       u32 recbufsize;
-       u32 bufsize;
-       u32 bufsizereg;
-       u32 bufaddrreg;
-       u32 bufidxreg;
-       u32 adcctl;
-       unsigned long busaddx;
-       u32 samplingrate;
-};
+#include "hwaccess.h"
+#include "cardwi.h"
 
 /* Recording resources */
 #define WAVERECORD_AC97                0x01
 #define WAVERECORD_MIC         0x02
 #define WAVERECORD_FX          0x03
 
-void emu10k1_start_record(struct record *);
-void emu10k1_stop_record(struct record *);
-void emu10k1_set_record_src(struct record *, u8);
+void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *);
+void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *);
+void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst);
 
 
 #endif /* _RECORDMGR_H */
index 1614b464d00967621ac8389ce9b80fa28dc67efb..8167010bd7d5fa976b2a56614a9026c41da6eb7d 100644 (file)
@@ -29,6 +29,9 @@
 /* 4/3/2000    Implemented timer list using list.h          Rui Sousa */
 
 #include "hwaccess.h"
+#include "8010.h"
+#include "irqmgr.h"
+#include "timer.h"
 
 /* Try to schedule only once per fragment */
 
@@ -42,7 +45,7 @@ void emu10k1_timer_irqhandler(struct emu10k1_card *card)
        list_for_each(entry, &card->timers) {
                t = list_entry(entry, struct emu_timer, list);
 
-               if (t->active) {
+               if (t->state & TIMER_STATE_ACTIVE) {
                        t->count++;
                        if (t->count == t->count_max) {
                                t->count = 0;
@@ -56,22 +59,17 @@ void emu10k1_timer_irqhandler(struct emu10k1_card *card)
        return;
 }
 
-struct emu_timer *emu10k1_timer_install(struct emu10k1_card *card, void (*func) (unsigned long), unsigned long data, u32 delay)
+void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u32 delay)
 {
-       struct emu_timer *timer;
        struct emu_timer *t;
        struct list_head *entry;
        unsigned long flags;
 
-       if ((timer = (struct emu_timer *) kmalloc(sizeof(struct emu_timer), GFP_KERNEL)) == NULL)
-               return timer;
-
        if (delay < 5)
                delay = 5;
 
        timer->delay = delay;
-       tasklet_init(&timer->tasklet, func, data);
-       timer->active = 0;
+       timer->state = TIMER_STATE_INSTALLED;
 
        spin_lock_irqsave(&card->timer_lock, flags);
 
@@ -87,7 +85,7 @@ struct emu_timer *emu10k1_timer_install(struct emu10k1_card *card, void (*func)
                card->timer_delay = delay;
                delay = (delay < 1024 ? delay : 1024);
 
-               WRITE_FN0(card, TIMER_RATE, delay);
+               emu10k1_writefn0(card, TIMER_RATE, delay);
 
                list_for_each(entry, &card->timers) {
                        t = list_entry(entry, struct emu_timer, list);
@@ -103,7 +101,7 @@ struct emu_timer *emu10k1_timer_install(struct emu10k1_card *card, void (*func)
 
        spin_unlock_irqrestore(&card->timer_lock, flags);
 
-       return timer;
+       return;
 }
 
 void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
@@ -113,6 +111,9 @@ void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
        u32 delay = TIMER_STOPPED;
        unsigned long flags;
 
+       if (timer->state == TIMER_STATE_UNINSTALLED)
+               return;
+
        spin_lock_irqsave(&card->timer_lock, flags);
 
        list_del(&timer->list);
@@ -132,7 +133,7 @@ void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
                else {
                        delay = (delay < 1024 ? delay : 1024);
 
-                       WRITE_FN0(card, TIMER_RATE, delay);
+                       emu10k1_writefn0(card, TIMER_RATE, delay);
 
                        list_for_each(entry, &card->timers) {
                                t = list_entry(entry, struct emu_timer, list);
@@ -147,8 +148,7 @@ void emu10k1_timer_uninstall(struct emu10k1_card *card, struct emu_timer *timer)
 
        spin_unlock_irqrestore(&card->timer_lock, flags);
 
-       tasklet_unlock_wait(&timer->tasklet);
-       kfree(timer);
+       timer->state = TIMER_STATE_UNINSTALLED;
 
        return;
 }
@@ -158,7 +158,7 @@ void emu10k1_timer_enable(struct emu10k1_card *card, struct emu_timer *timer)
        unsigned long flags;
 
        spin_lock_irqsave(&card->timer_lock, flags);
-       timer->active = 1;
+       timer->state |= TIMER_STATE_ACTIVE;
        spin_unlock_irqrestore(&card->timer_lock, flags);
 
        return;
@@ -169,7 +169,7 @@ void emu10k1_timer_disable(struct emu10k1_card *card, struct emu_timer *timer)
        unsigned long flags;
 
        spin_lock_irqsave(&card->timer_lock, flags);
-       timer->active = 0;
+       timer->state &= ~TIMER_STATE_ACTIVE;
        spin_unlock_irqrestore(&card->timer_lock, flags);
 
        return;
index 39e1ee2c998727077b87238b02a958bd6c4b6596..979576a3c8899f3d4caf19562c4b4c1664a82b66 100644 (file)
 #ifndef _TIMER_H
 #define _TIMER_H
 
+#include <linux/interrupt.h>
+#include "hwaccess.h"
+
 struct emu_timer 
 {
        struct list_head list;
        struct tasklet_struct tasklet;
-       int active;
+       u8 state; 
        u32 count;                              /* current number of interrupts */
        u32 count_max;                          /* number of interrupts needed to schedule the bh */
        u32 delay;                              /* timer delay */
 };
 
-struct emu_timer *emu10k1_timer_install(struct emu10k1_card *, void (*)(unsigned long), unsigned long, u32);
+void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u32);
 void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *);
 void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *);
 void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *);
 
-#define TIMER_STOPPED 0xffffffff 
+#define TIMER_STOPPED                  0xffffffff 
+#define TIMER_STATE_INSTALLED          0x01
+#define TIMER_STATE_ACTIVE             0x02
+#define TIMER_STATE_UNINSTALLED        0x04
 
 #endif /* _TIMER_H */
index de94a453ecfe276ae2efc80069e4b846a1f08825..c61ffb92eb8f1b2acc3c125788ac291d42dca683 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     voicemgr.c - Voice manager for emu10k1 driver
  **********************************************************************
  */
 
-#include "hwaccess.h"
+#include "voicemgr.h"
+#include "8010.h"
 
-struct emu_voice *emu10k1_voice_alloc(struct voice_manager *voicemgr, struct voice_allocdesc *voiceallocdesc)
+int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice)
 {
-       struct emu10k1_card *card = voicemgr->card;
-       struct emu_voice *voice_tmp = voicemgr->voice;
-       struct emu_voice *voice = NULL;
+       u8 *voicetable = card->voicetable;
        int i;
        unsigned long flags;
 
        DPF(2, "emu10k1_voice_alloc()\n");
 
-       spin_lock_irqsave(&voicemgr->lock, flags);
+       spin_lock_irqsave(&card->lock, flags);
 
-       if (voiceallocdesc->flags & VOICEMGR_FLAGS_MONO) {
-               for (i = 0; i < NUM_G; i++)
-                       if (voice_tmp[i].usage == VOICEMGR_USAGE_FREE) {
-                               voice_tmp[i].flags = VOICEMGR_FLAGS_VOICEMASTER | voiceallocdesc->flags;
-                               voice_tmp[i].usage = voiceallocdesc->usage;
-                               voice = &voice_tmp[i];
+       if (voice->flags & VOICE_FLAGS_STEREO) {
+               for (i = 0; i < NUM_G; i += 2)
+                       if ((voicetable[i] == VOICE_USAGE_FREE) && (voicetable[i + 1] == VOICE_USAGE_FREE)) {
+                               voicetable[i] = voice->usage;
+                               voicetable[i + 1] = voice->usage;
                                break;
                        }
        } else {
-               for (i = 0; i < NUM_G; i += 2)
-                       if ((voice_tmp[i].usage == VOICEMGR_USAGE_FREE)
-                           && (voice_tmp[i + 1].usage == VOICEMGR_USAGE_FREE)) {
-                               voice_tmp[i].linked_voice = &voice_tmp[i + 1];
-                               voice_tmp[i].flags = VOICEMGR_FLAGS_VOICEMASTER | voiceallocdesc->flags;
-                               voice_tmp[i].usage = voiceallocdesc->usage;
-                               voice_tmp[i + 1].flags = VOICEMGR_FLAGS_STEREOSLAVE | voiceallocdesc->flags;
-                               voice_tmp[i + 1].usage = voiceallocdesc->usage;
-                               voice = &voice_tmp[i];
+               for (i = 0; i < NUM_G; i++)
+                       if (voicetable[i] == VOICE_USAGE_FREE) {
+                               voicetable[i] = voice->usage;
                                break;
                        }
        }
 
-       spin_unlock_irqrestore(&voicemgr->lock, flags);
+       spin_unlock_irqrestore(&card->lock, flags);
 
-       voice_tmp = voice;
+       if (i >= NUM_G)
+               return -1;
 
-       while (voice_tmp != NULL) {
+       voice->card = card;
+       voice->num = i;
 
-               DPD(2, " voice allocated -> %d\n", voice_tmp->num);
+#ifdef PRIVATE_PCM_VOLUME
 
-               sblive_writeptr(card, IFATN, voice_tmp->num, 0xffff);
-               sblive_writeptr(card, DCYSUSV, voice_tmp->num, ENV_OFF);
-               sblive_writeptr(card, VTFT, voice_tmp->num, 0xffff);
-               sblive_writeptr(card, PTRX, voice_tmp->num, 0);
+       for (i = 0; i < MAX_PCM_CHANNELS; i++) {
+               if (sblive_pcm_volume[i].files == current->files) {
+                       sblive_pcm_volume[i].channel_l = voice->num;
+                       DPD(2, "preset left: %d\n", voice->num);
+                       if (voice->flags & VOICE_FLAGS_STEREO) {
+                               sblive_pcm_volume[i].channel_r = voice->num + 1;
+                               DPD(2, "preset right: %d\n", voice->num + 1);
+                       }
+                       break;
+               }
+       }
+#endif
+
+       for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
+               DPD(2, " voice allocated -> %d\n", voice->num + i);
 
-               voice_tmp = voice_tmp->linked_voice;
+               sblive_writeptr_tag(card, voice->num + i, IFATN, 0xffff,
+                                                       DCYSUSV, 0,
+                                                       VTFT, 0x0000ffff,
+                                                       PTRX, 0,
+                                                       TAGLIST_END);
        }
 
-       return voice;
+       return 0;
 }
 
-void emu10k1_voice_free(struct voice_manager *voicemgr, struct emu_voice *voice)
+void emu10k1_voice_free(struct emu_voice *voice)
 {
        struct emu10k1_card *card = voice->card;
-       struct emu_voice *voice_tmp;
-       unsigned dcysusv;
-       u32 cra, sample;
        int i;
        unsigned long flags;
 
        DPF(2, "emu10k1_voice_free()\n");
 
-       voice_tmp = voice;
-
-       while (voice_tmp != NULL) {
-
-               DPD(2, " voice freed -> %d\n", voice_tmp->num);
+       if (voice->usage == VOICE_USAGE_FREE)
+               return;
 
-               sblive_writeptr(card, IFATN, voice_tmp->num, IFATN_FILTERCUTOFF_MASK | IFATN_ATTENUATION_MASK);
-               sblive_writeptr(card, IP, voice_tmp->num, 0);
+#ifdef PRIVATE_PCM_VOLUME
+       for (i = 0; i < MAX_PCM_CHANNELS; i++) {
+               if (sblive_pcm_volume[i].files == current->files) {
+                       if (voice->num == sblive_pcm_volume[i].channel_l)
+                               sblive_pcm_volume[i].channel_l = NUM_G;
+                       if ((voice->flags & VOICE_FLAGS_STEREO)
+                           && (voice->num + 1) == sblive_pcm_volume[i].channel_r) {
+                               sblive_pcm_volume[i].channel_r = NUM_G;
+                       }
+                       break;
+               }
+       }
+#endif
 
-               dcysusv = sblive_readptr(card, DCYSUSV, voice_tmp->num) & (DCYSUSV_PHASE1_MASK | DCYSUSV_SUSTAINLEVEL_MASK | DCYSUSV_DECAYTIME_MASK);
-               sblive_writeptr(card, DCYSUSV, voice_tmp->num, dcysusv | ENV_OFF);
+       for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
+               DPD(2, " voice released -> %d\n", voice->num + i);
 
-               sblive_writeptr(card, VTFT, voice_tmp->num, VTFT_FILTERTARGET_MASK);
-               sblive_writeptr(card, PTRX_PITCHTARGET, voice_tmp->num, 0);
-               sblive_writeptr(card, CVCF, voice_tmp->num, CVCF_CURRENTFILTER_MASK);
-               sblive_writeptr(card, CPF, voice_tmp->num, 0);
+               sblive_writeptr_tag(card, voice->num + i, DCYSUSV, 0, 
+                                                       VTFT, 0x0000ffff,
+                                                       PTRX_PITCHTARGET, 0,
+                                                       CVCF, 0x0000ffff,
+                                                       CPF, 0,
+                                                       TAGLIST_END);
+       }
 
-               sample = (voice_tmp->flags & VOICEMGR_FLAGS_16BIT) ? 0 : 0x80808080;
-               cra = sblive_readptr(card, CCR, voice_tmp->num) & CCR_READADDRESS_MASK;
-               sblive_writeptr(card, CCR, voice_tmp->num, cra);
-               cra = (cra >> 18) & 0xf;
-               sblive_writeptr(card, CD0 + cra, voice_tmp->num, sample);
-               cra = (cra + 0x1) & 0xf;
-               sblive_writeptr(card, CD0 + cra, voice_tmp->num, sample);
+       voice->usage = VOICE_USAGE_FREE;
 
-               for (i = 0; i < NUM_FXSENDS; i++)
-                       voice_tmp->sendhandle[i] = 0;
+       spin_lock_irqsave(&card->lock, flags);
 
-               voice_tmp->flags = 0;
+       card->voicetable[voice->num] = VOICE_USAGE_FREE;
 
-               spin_lock_irqsave(&voicemgr->lock, flags);
-               voice_tmp->usage = VOICEMGR_USAGE_FREE;
+       if (voice->flags & VOICE_FLAGS_STEREO)
+               card->voicetable[voice->num + 1] = VOICE_USAGE_FREE;
 
-               voice_tmp = voice_tmp->linked_voice;
-               voice->linked_voice = NULL;
-               spin_unlock_irqrestore(&voicemgr->lock, flags);
-       }
+       spin_unlock_irqrestore(&card->lock, flags);
 
        return;
 }
 
-/*       Sets up a voices for Wave Playback */
-
 void emu10k1_voice_playback_setup(struct emu_voice *voice)
 {
        struct emu10k1_card *card = voice->card;
-       u32 sample, cra = 0, start = 0;
+       u32 start;
+       int i;
 
        DPF(2, "emu10k1_voice_playback_setup()\n");
 
-       while (voice != NULL) {
-               sblive_writeptr(card, DCYSUSV, voice->num, ENV_OFF);
-               sblive_writeptr(card, VTFT, voice->num, VTFT_FILTERTARGET_MASK);
-               sblive_writeptr(card, CVCF, voice->num, CVCF_CURRENTFILTER_MASK);
-               sblive_writeptr(card, FXRT, voice->num, (voice->flags & VOICEMGR_FLAGS_FXRT2) ? 0xd23c0000 : 0xd01c0000);
-
-               /* Stop CA */
-               /* Assumption that PT is alreadt 0 so no harm overwriting */
-               sblive_writeptr(card, PTRX, voice->num, (voice->params.send_a << 8) | voice->params.send_b);
-
-               if (voice->flags & VOICEMGR_FLAGS_VOICEMASTER) {
-                       if (voice->linked_voice != NULL) {
-                               /* Set stereo bit */
-                               cra = 64;
-                               sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
-                               sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
-                       } else {
-                               cra = 32;
-                               sblive_writeptr(card, CPF, voice->num, 0);
-                       }
-
-                       if (voice->flags & VOICEMGR_FLAGS_16BIT)
-                               sample = 0;
-                       else {
-                               cra = cra * 2;
-                               sample = 0x80808080;
-                       }
-                       cra -= 4;
-
-                       if (voice->linked_voice != NULL) {
-                               /* CCR_READADDRESS_MASK */
-                               sblive_writeptr(card, CCR, voice->num, 0x3c << 16);
-                               sblive_writeptr(card, CCR, voice->num + 1, cra << 16);
-                               sblive_writeptr(card, CDE, voice->num + 1, sample);
-                               sblive_writeptr(card, CDF, voice->num + 1, sample);
-                               start = voice->params.start + cra / 2;
-                       } else {
-                               sblive_writeptr(card, CCR, voice->num, 0x1c << 16);     /* FIXME: Is 0x1c correct? */
-                               sblive_writeptr(card, CDE, voice->num, sample);
-                               sblive_writeptr(card, CDF, voice->num, sample);
-                               start = voice->params.start + cra;
-                       }
-
-                       if (start > voice->params.endloop) {
-                               start -= voice->params.endloop;
-
-                               if (voice->linked_voice != NULL)
-                                       cra = (cra << 25) | 0x1bc0000 | ((cra - start) << 9);
-                               else
-                                       cra = (cra << 25) | 0x11c0000 | ((cra - start) << 9);
-
-                               start += voice->params.startloop;
-
-                               if (start >= voice->params.endloop)
-                                       start = voice->params.endloop - 1;
-                       } else if (voice->linked_voice != NULL)
-                               cra = (cra << 25) | (0x3c << 16);
-                       else
-                               cra = (cra << 25) | (0x1c << 16);
-
-                       start |= CCCA_INTERPROM_0;
-               }
-
-               /* CSL, ST, CA */
-               sblive_writeptr(card, DSL, voice->num, voice->params.endloop | (voice->params.send_d << 24));
-               sblive_writeptr(card, PSST, voice->num, voice->params.startloop | (voice->params.send_c << 24));
+       if (voice->flags & VOICE_FLAGS_STEREO) {
+               /* Set stereo bit */
+               start = 28;
+               sblive_writeptr(card, CPF, voice->num, CPF_STEREO_MASK);
+               sblive_writeptr(card, CPF, voice->num + 1, CPF_STEREO_MASK);
+       } else {
+               start = 30;
+               sblive_writeptr(card, CPF, voice->num, 0);
+       }
 
-               if (voice->flags & VOICEMGR_FLAGS_16BIT)
-                       sblive_writeptr(card, CCCA, voice->num, start);
-               else
-                       sblive_writeptr(card, CCCA, voice->num, start | CCCA_8BITSELECT);
+       if(!(voice->flags & VOICE_FLAGS_16BIT))
+               start *= 2;
 
-               /* Clear filter delay memory */
-               sblive_writeptr(card, Z1, voice->num, 0);
-               sblive_writeptr(card, Z2, voice->num, 0);
+       voice->start += start;
 
-               /* Invalidate maps */
-               sblive_writeptr(card, MAPA, voice->num, MAP_PTI_MASK | (card->silentpage->busaddx * 2));
-               sblive_writeptr(card, MAPB, voice->num, MAP_PTI_MASK | (card->silentpage->busaddx * 2));
+       for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
+               sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16);
 
-               /* Fill cache */
-               if (voice->flags & VOICEMGR_FLAGS_VOICEMASTER)
-                       sblive_writeptr(card, CCR, voice->num, cra);
-
-               sblive_writeptr(card, ATKHLDV, voice->num, ATKHLDV_HOLDTIME_MASK | ATKHLDV_ATTACKTIME_MASK);
-               sblive_writeptr(card, LFOVAL1, voice->num, 0x8000);
-               sblive_writeptr(card, ATKHLDM, voice->num, 0);
-               sblive_writeptr(card, DCYSUSM, voice->num, DCYSUSM_DECAYTIME_MASK);
-               sblive_writeptr(card, LFOVAL2, voice->num, 0x8000);
-               sblive_writeptr(card, IP, voice->num, voice->params.initial_pitch);
-               sblive_writeptr(card, PEFE, voice->num, 0x7f);
-               sblive_writeptr(card, FMMOD, voice->num, 0);
-               sblive_writeptr(card, TREMFRQ, voice->num, 0);
-               sblive_writeptr(card, FM2FRQ2, voice->num, 0);
-               sblive_writeptr(card, ENVVAL, voice->num, 0xbfff);
-               sblive_writeptr(card, ENVVOL, voice->num, 0xbfff);
+               /* Stop CA */
+               /* Assumption that PT is already 0 so no harm overwriting */
+               sblive_writeptr(card, PTRX, voice->num + i, (voice->params[i].send_a << 8) | voice->params[i].send_b);
+
+               sblive_writeptr_tag(card, voice->num + i,
+                               /* CSL, ST, CA */
+                                   DSL, voice->endloop | (voice->params[i].send_d << 24),
+                                   PSST, voice->startloop | (voice->params[i].send_c << 24),
+                                   CCCA, (voice->start) | CCCA_INTERPROM_0 | ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT),
+                                   /* Clear filter delay memory */
+                                   Z1, 0,
+                                   Z2, 0,
+                                   /* Invalidate maps */
+                                   MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+                                   MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+                               /* modulation envelope */
+                                   CVCF, 0x0000ffff,
+                                   VTFT, 0x0000ffff,
+                                   ATKHLDM, 0,
+                                   DCYSUSM, 0x007f,
+                                   LFOVAL1, 0x8000,
+                                   LFOVAL2, 0x8000,
+                                   FMMOD, 0,
+                                   TREMFRQ, 0,
+                                   FM2FRQ2, 0,
+                                   ENVVAL, 0x8000,
+                               /* volume envelope */
+                                   ATKHLDV, 0x7f7f,
+                                   ENVVOL, 0x8000,
+                               /* filter envelope */
+                                   PEFE_FILTERAMOUNT, 0x7f,
+                               /* pitch envelope */
+                                   PEFE_PITCHAMOUNT, 0, TAGLIST_END);
 
 #ifdef PRIVATE_PCM_VOLUME
-               {
-                       int i;
-
-                       for (i = 0; i < MAX_PCM_CHANNELS; i++) {
-                               if (sblive_pcm_volume[i].channel_l == voice->num) {
-                                       voice->params.initial_attn = (sblive_pcm_volume[i].channel_r < NUM_G) ? sblive_pcm_volume[i].attn_l :
-                                           // test for mono channel (reverse logic is correct here!)
-                                           (sblive_pcm_volume[i].attn_r >
-                                            sblive_pcm_volume[i].attn_l) ? sblive_pcm_volume[i].attn_l : sblive_pcm_volume[i].attn_r;
-                                       DPD(2, "set left volume  %d\n", voice->params.initial_attn);
-                                       break;
-                               } else if (sblive_pcm_volume[i].channel_r == voice->num) {
-                                       voice->params.initial_attn = sblive_pcm_volume[i].attn_r;
-                                       DPD(2, "set right volume  %d\n", voice->params.initial_attn);
-                                       break;
-                               }
-                       }
-               }
+{
+int j;
+        for (j = 0; j < MAX_PCM_CHANNELS; j++) {
+                if (sblive_pcm_volume[j].channel_l == voice->num + i) {
+                        voice->params[i].initial_attn = (sblive_pcm_volume[j].channel_r < NUM_G) ? sblive_pcm_volume[i].attn_l :
+                // test for mono channel (reverse logic is correct here!)
+                                            (sblive_pcm_volume[j].attn_r >
+                                             sblive_pcm_volume[j].attn_l) ? sblive_pcm_volume[j].attn_l : sblive_pcm_volume[j].attn_r;
+                                        DPD(2, "set left volume %d\n", voice->params[i].initial_attn);
+                                        break;
+                                } else if (sblive_pcm_volume[j].channel_r == voice->num + i) {
+                                        voice->params[i].initial_attn = sblive_pcm_volume[j].attn_r;
+                                        DPD(2, "set right volume %d\n", voice->params[i].initial_attn);
+                                        break;
+                                }
+                        }
+                }
 #endif
-               sblive_writeptr(card, IFATN, voice->num, IFATN_FILTERCUTOFF_MASK | voice->params.initial_attn);
-
-               voice->params.FC_target = 0xffff;
-               voice->params.pitch_target = (u16) (IP_TO_CP(voice->params.initial_pitch) >> 16);
 
-               voice = voice->linked_voice;
+               voice->params[i].fc_target = 0xffff;
        }
 
        return;
 }
 
-void emu10k1_voice_start(struct emu_voice *voice)
+void emu10k1_voice_start(struct emu_voice *voice, int set)
 {
        struct emu10k1_card *card = voice->card;
+       int i;
 
        DPF(2, "emu10k1_voice_start()\n");
 
-       while (voice != NULL) {
-               sblive_writeptr(card, PTRX_PITCHTARGET, voice->num, voice->params.pitch_target);
-
-               if (voice->flags & VOICEMGR_FLAGS_VOICEMASTER)
-                       sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->params.pitch_target);
-
-               sblive_writeptr(card, VTFT, voice->num, ((u32) voice->params.volume_target << 16)
-                               | voice->params.FC_target);
-               sblive_writeptr(card, CVCF, voice->num, ((u32) voice->params.volume_target << 16)
-                               | voice->params.FC_target);
-               sblive_writeptr(card, DCYSUSV, voice->num, (voice->params.byampl_env_sustain << 8)
-                               | ENV_ON | voice->params.byampl_env_decay);
-
-               /* Using StopOnLoop for MIDI stops the playback
-                  too early, which may cause a DC level to be played
-                  until the note is released. */
-
-               if (voice->usage == VOICEMGR_USAGE_MIDI)
-                       emu10k1_clear_stop_on_loop(card, voice->num);
-               else {
-                       if (voice->params.startloop > voice->params.end)
-                               emu10k1_set_stop_on_loop(card, voice->num);
-                       else
-                               emu10k1_clear_stop_on_loop(card, voice->num);
+       if (!set) {
+               u32 cra, ccis, cs, sample;
+               if (voice->flags & VOICE_FLAGS_STEREO) {
+                       cra = 64;
+                       ccis = 28;
+                       cs = 4;
+               } else {
+                       cra = 64;
+                       ccis = 30;
+                       cs = 2;
                }
-               voice = voice->linked_voice;
-       }
 
-       return;
-}
+               if(voice->flags & VOICE_FLAGS_16BIT) {
+                       sample = 0x00000000;
+               } else {
+                       sample = 0x80808080;            
+                       ccis *= 2;
+               }
 
-void emu10k1_voice_stop(struct emu_voice *voice)
-{
-       struct emu10k1_card *card = voice->card;
+               for(i = 0; i < cs; i++)
+                       sblive_writeptr(card, CD0 + i, voice->num, sample);
 
-       DPF(2, "emu10k1_voice_stop()\n");
+               /* Reset cache */
+               sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, 0);
+               if (voice->flags & VOICE_FLAGS_STEREO)
+                       sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num + 1, 0);
+
+               sblive_writeptr(card, CCR_READADDRESS, voice->num, cra);
+
+               if (voice->flags & VOICE_FLAGS_STEREO)
+                       sblive_writeptr(card, CCR_READADDRESS, voice->num + 1, cra);
 
-       while (voice != NULL) {
-               sblive_writeptr(card, IFATN, voice->num, 0xffff);
-               sblive_writeptr(card, IP, voice->num, 0);
-               sblive_writeptr(card, VTFT, voice->num, 0xffff);
-               sblive_writeptr(card, PTRX_PITCHTARGET, voice->num, 0);
-               voice = voice->linked_voice;
+               /* Fill cache */
+               sblive_writeptr(card, CCR_CACHEINVALIDSIZE, voice->num, ccis);
        }
 
-       return;
-}
+       for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
+               sblive_writeptr_tag(card, voice->num + i,
+                                   IFATN, (voice->params[i].initial_fc << 8) | voice->params[i].initial_attn,
+                                   VTFT, (voice->params[i].volume_target << 16) | voice->params[i].fc_target,
+                                   CVCF, (voice->params[i].volume_target << 16) | voice->params[i].fc_target,
+                                   DCYSUSV, (voice->params[i].byampl_env_sustain << 8) | voice->params[i].byampl_env_decay,
+                                   TAGLIST_END);
 
-void emu10k1_voice_setcontrol(struct emu_voice *voice, struct voice_cntlset *setting, u32 numparam)
-{
-       struct emu10k1_card *card = voice->card;
-       int count;
+               emu10k1_clear_stop_on_loop(card, voice->num + i);
+
+               sblive_writeptr(card, PTRX_PITCHTARGET, voice->num + i, voice->pitch_target);
 
-       for (count = 0; count < numparam; count++)
-               sblive_writeptr(card, setting[count].paramID, voice->num, setting[count].value);
+               if (i == 0)
+                       sblive_writeptr(card, CPF_CURRENTPITCH, voice->num, voice->pitch_target);
+
+               sblive_writeptr(card, IP, voice->num + i, voice->initial_pitch);
+       }
 
        return;
 }
 
-void emu10k1_voice_getcontrol(struct emu_voice *voice, u32 controlid, u32 * value)
+void emu10k1_voice_stop(struct emu_voice *voice)
 {
        struct emu10k1_card *card = voice->card;
+       int i;
 
-       *value = sblive_readptr(card, controlid, voice->num);
+       DPF(2, "emu10k1_voice_stop()\n");
+
+       for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) {
+               sblive_writeptr_tag(card, voice->num + i,
+                                       PTRX_PITCHTARGET, 0,
+                                       CPF_CURRENTPITCH, 0,
+                                       IFATN, 0xffff,
+                                       VTFT, 0x0000ffff,
+                                       CVCF, 0x0000ffff,
+                                       IP, 0,
+                                       TAGLIST_END);
+       }
 
        return;
 }
+
index bef340d8b38b043f6524cecb1801824bafc51252..58ab55f2d9d7987e3efee6de2ed605d382a9bb05 100644 (file)
 
 #ifndef _VOICEMGR_H
 #define _VOICEMGR_H
+
+#include "hwaccess.h"
+
 /* struct emu_voice.usage flags */
-#define VOICEMGR_USAGE_FREE         0x00000000
-#define VOICEMGR_USAGE_MIDI         0x00000001
-#define VOICEMGR_USAGE_PLAYBACK     0x00000002
+#define VOICE_USAGE_FREE               0x01
+#define VOICE_USAGE_MIDI               0x02
+#define VOICE_USAGE_PLAYBACK           0x04
 
 /* struct emu_voice.flags flags */
-#define VOICEMGR_FLAGS_MONO         0x00000002
-#define VOICEMGR_FLAGS_16BIT        0x00000004
-#define VOICEMGR_FLAGS_STEREOSLAVE  0x00000008
-#define VOICEMGR_FLAGS_VOICEMASTER  0x80000000
-#define VOICEMGR_FLAGS_FXRT2        0x00000010
+#define VOICE_FLAGS_STEREO             0x02
+#define VOICE_FLAGS_16BIT              0x04
 
 struct voice_param
 {
-       /* Sound engine */
-       u32 start;
-       u32 startloop;
-       u32 endloop;
-       u32 end;
-
-       u16 current_pitch;
-       u16 pitch_target;
-
-       u16 current_volume;
-       u16 volume_target;
-
-       u16 current_FC;
-       u16 FC_target;
-
-       u8 pan_target;
-       u8 aux_target;
-
        /* FX bus amount send */
 
+       u32 send_routing;
+
        u32 send_a;
        u32 send_b;
        u32 send_c;
        u32 send_d;
 
-       /* Envelope engine */
-       u16 ampl_env_delay;
-       u8 byampl_env_attack;
-       u8 byampl_env_hold;
-       u8 byampl_env_decay;
-       u8 byampl_env_sustain;
-       u8 byampl_env_release;
-
-       u16 aux_env_delay;
-       u8 byaux_env_attack;
-       u8 byaux_env_hold;
-       u8 byaux_env_decay;
-       u8 byaux_env_sustain;
-       u8 byaux_env_release;
-
-       u16 mod_LFO_delay;      /* LFO1 */
-       u16 vib_LFO_delay;      /* LFO2 */
-       u8 mod_LFO_freq;        /* LFO1 */
-       u8 vib_LFO_freq;        /* LFO2 */
-
-       s8 aux_env_to_pitch;
-       s8 aux_env_to_FC;
-       s8 mod_LFO_to_pitch;
-       s8 vib_LFO_to_pitch;
-       s8 mod_LFO_to_FC;
-       s8 mod_LFO_to_volume;
-
-       u16 sample_pitch;
-       u16 initial_pitch;
-       u8 initial_attn;
-       u8 initial_FC;
-};
+       u32 initial_fc;
+       u32 fc_target;
 
-struct voice_allocdesc
-{
-       u32 usage;                      /* playback, Midi */
-       u32 flags;                      /* stereo/mono rec/playback 8/16 bit*/
+       u32 initial_attn;
+       u32 volume_target;
+
+       u32 byampl_env_sustain;
+       u32 byampl_env_decay;
 };
 
+
 struct emu_voice
 {
-       struct list_head list;
-
        struct emu10k1_card *card;
-       u32 usage;              /* Free, MIDI, playback */
-       u32 num;                /* Voice ID */
-       u32 flags;              /* Stereo/mono, rec/playback, 8/16 bit */
-
-       struct voice_param params;
-
-       struct emu_voice *linked_voice; /*for stereo voice*/
-
-       u32 sendhandle[NUM_FXSENDS];
-};
+       u8 usage;               /* Free, MIDI, playback */
+       u8 num;                 /* Voice ID */
+       u8 flags;               /* Stereo/mono, 8/16 bit */
 
-struct voice_manager
-{
-       struct emu10k1_card *card;
-       spinlock_t lock;
+        u32 startloop;
+        u32 endloop;
+       u32 start;
 
-       struct emu_voice voice[NUM_G];
-};
+       u32 initial_pitch;
+       u32 pitch_target;
 
-struct voice_cntlset
-{
-       u32 paramID;
-       u32 value;
+       struct voice_param params[2];
 };
 
-struct emu_voice *emu10k1_voice_alloc(struct voice_manager *, struct voice_allocdesc *);
-void emu10k1_voice_free(struct voice_manager *, struct emu_voice *);
+int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *);
+void emu10k1_voice_free(struct emu_voice *);
 void emu10k1_voice_playback_setup(struct emu_voice *);
-void emu10k1_voice_start(struct emu_voice *);
+void emu10k1_voice_start(struct emu_voice *, int);
 void emu10k1_voice_stop(struct emu_voice *);
-void emu10k1_voice_setcontrol(struct emu_voice *, struct voice_cntlset *, u32);
-void emu10k1_voice_getcontrol(struct emu_voice *, u32, u32 *);
 
 #endif /* _VOICEMGR_H */
index e802fa4cfe366b0deb7dc592795e9b46d2b189d1..9eac1e3d840f77befbaa1549f23429ffde32244a 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <asm/dec21285.h>
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/system.h>
 
 #include "sound_config.h"
index 5831dd1d9c3db517888e80b089523d9273ff96c7..756234fd8e5d34683c01b8354823a35129d72b1b 100644 (file)
@@ -19,6 +19,10 @@ O_OBJS               :=
 
 export-objs            := usb.o input.o
 
+# Objects which appear many times
+
+common-objs    := input.o
+
 # Multipart objects.
 
 list-multi             := usbcore.o
@@ -37,27 +41,6 @@ obj-m        :=
 obj-n  :=
 obj-   :=
 
-# Object files in subdirectories
-
-ifeq ($(CONFIG_USB_SERIAL),y)
-       SUB_DIRS += serial
-       obj-y += serial/usb-serial.o
-else
-       ifeq ($(CONFIG_USB_SERIAL),m)
-               MOD_IN_SUB_DIRS += serial
-       endif
-endif
-
-ifeq ($(CONFIG_USB_STORAGE),y)
-       SUB_DIRS += storage
-       obj-y += storage/usb-storage.o
-else
-       ifeq ($(CONFIG_USB_STORAGE),m)
-               MOD_IN_SUB_DIRS += storage
-       endif
-endif
-
-
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_USB)              += usbcore.o
@@ -92,6 +75,33 @@ obj-$(CONFIG_USB_DSBR)               += dsbr100.o
 obj-$(CONFIG_USB_MICROTEK)     += microtek.o
 obj-$(CONFIG_USB_BLUETOOTH)    += bluetooth.o
 
+# Object files in subdirectories
+
+ifeq ($(CONFIG_USB_SERIAL),y)
+       SUB_DIRS += serial
+       obj-y += serial/usb-serial.o
+else
+       ifeq ($(CONFIG_USB_SERIAL),m)
+               MOD_IN_SUB_DIRS += serial
+       endif
+endif
+
+ifeq ($(CONFIG_USB_STORAGE),y)
+       SUB_DIRS += storage
+       obj-y += storage/usb-storage.o
+else
+       ifeq ($(CONFIG_USB_STORAGE),m)
+               MOD_IN_SUB_DIRS += storage
+       endif
+endif
+
+# Remove duplicates.
+# The 'common-*' lists are intermediate lists used to filter out
+# duplicates.
+
+common-y       := $(filter $(obj-y),$(common-obj))
+obj-y          := $(filter-out $(common-y), $(obj-y)) $(common-y)
+
 # Extract lists of the multi-part drivers.
 # The 'int-*' lists are the intermediate files used to build the multi's.
 
@@ -111,8 +121,8 @@ obj-y               := $(filter-out $(list-multi), $(obj-y)) $(int-y)
 
 # Translate to Rules.make lists.
 
-O_OBJS         := $(sort $(filter-out $(export-objs), $(obj-y)))
-OX_OBJS                := $(sort $(filter     $(export-objs), $(obj-y)))
+O_OBJS         := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS                := $(filter     $(export-objs), $(obj-y))
 M_OBJS         := $(sort $(filter-out $(export-objs), $(obj-m)))
 MX_OBJS                := $(sort $(filter     $(export-objs), $(obj-m)))
 MI_OBJS                := $(sort $(filter-out $(export-objs), $(int-m)))
index 4ee29a70214211f5c4bd9e29b89375a7e15da6b4..fd239671b07c098f3f44e8caceee846e179e5927 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * bluetooth.c   Version 0.3
+ * bluetooth.c   Version 0.4
  *
  * Copyright (c) 2000 Greg Kroah-Hartman       <greg@kroah.com>
  * Copyright (c) 2000 Mark Douglas Corner      <mcorner@umich.edu>
@@ -7,6 +7,13 @@
  * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
  *
  *
+ * (07/11/2000) Version 0.4 gkh
+ *     Fixed bug in disconnect for when we call tty_hangup
+ *     Fixed bug in bluetooth_ctrl_msg where the bluetooth struct was not
+ *     getting attached to the control urb properly.
+ *     Fixed bug in bluetooth_write where we pay attention to the result
+ *     of bluetooth_ctrl_msg.
+ *
  * (08/03/2000) Version 0.3 gkh mdc
  *     Merged in Mark's changes to make the driver play nice with the Axis
  *     stack.
@@ -251,7 +258,7 @@ static int bluetooth_ctrl_msg (struct usb_bluetooth *bluetooth, int request, int
        dr->length = cpu_to_le16p(&len);
        
        FILL_CONTROL_URB (urb, bluetooth->dev, usb_sndctrlpipe(bluetooth->dev, 0),
-                         (unsigned char*)dr, buf, len, bluetooth_ctrl_callback, 0);
+                         (unsigned char*)dr, buf, len, bluetooth_ctrl_callback, bluetooth);
 
        /* send it down the pipe */
        status = usb_submit_urb(urb);
@@ -400,7 +407,10 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign
                        else
                                memcpy (new_buffer, buf+1, count-1);
 
-                       bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, new_buffer, count-1);
+                       if (bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, new_buffer, count-1) != 0) {
+                               kfree (new_buffer);
+                               return 0;
+                       }
 
                        /* need to free new_buffer somehow... FIXME */
                        return count;
@@ -1099,6 +1109,9 @@ static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr)
        int i;
 
        if (bluetooth) {
+               if ((bluetooth->active) && (bluetooth->tty))
+                       tty_hangup(bluetooth->tty);
+
                bluetooth->active = 0;
 
                if (bluetooth->read_urb) {
@@ -1117,9 +1130,6 @@ static void usb_bluetooth_disconnect(struct usb_device *dev, void *ptr)
 
                tty_unregister_devfs (&bluetooth_tty_driver, bluetooth->minor);
 
-               if (bluetooth->tty)
-                       tty_hangup(bluetooth->tty);
-
                for (i = 0; i < NUM_BULK_URBS; ++i) {
                        if (bluetooth->write_urb_pool[i]) {
                                usb_unlink_urb (bluetooth->write_urb_pool[i]);
index 5609ae1c274353c0fda2e707c49a5bc3974520fc..00bd135e8f5a8cf5330b0e818e1abc418ad21861 100644 (file)
@@ -733,8 +733,7 @@ static int proc_clearhalt(struct dev_state *ps, void *arg)
         else
                 pipe = usb_sndbulkpipe(ps->dev, ep & 0x7f);
 
-       usb_clear_halt(ps->dev, pipe);
-       return 0;
+       return usb_clear_halt(ps->dev, pipe);
 }
                
 
index c5c403b2b3515638fd6b8303aa8174ab7bb1b7d6..f168b1bfcfc05bb79a41b69ce8e17a5b1a56ed64 100644 (file)
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
 *
+*  (8/8/2000) pberger and borchers
+*    -- Fixed close so that 
+*       - it can timeout while waiting for transmit idle, if needed;
+*       - it ignores interrupts when flushing the port, turning
+*         of modem signalling, and so on;
+*       - it waits for the flush to really complete before returning.
+*    -- Read_bulk_callback and write_bulk_callback check for a closed
+*       port before using the tty struct or writing to the port.
+*    -- The two changes above fix the oops caused by interrupted closes.
+*    -- Added interruptible args to write_oob_command and set_modem_signals
+*       and added a timeout arg to transmit_idle; needed for fixes to
+*       close.
+*    -- Added code for rx_throttle and rx_unthrottle so that input flow
+*       control works.
+*    -- Added code to set overrun, parity, framing, and break errors
+*       (untested).
+*    -- Set USB_DISABLE_SPD flag for write bulk urbs, so no 0 length
+*       bulk writes are done.  These hung the Digi USB device.  The
+*       0 length bulk writes were a new feature of usb-uhci added in
+*       the 2.4.0-test6 kernels.
+*    -- Fixed mod inc race in open; do mod inc before sleeping to wait
+*       for a close to finish.
+*
+*  (7/31/2000) pberger
+*    -- Fixed bugs with hardware handshaking:
+*       - Added code to set/clear tty->hw_stopped in digi_read_oob_callback()
+*         and digi_set_termios()
+*    -- Added code in digi_set_termios() to
+*       - add conditional in code handling transition from B0 to only
+*         set RTS if RTS/CTS flow control is either not in use or if
+*         the port is not currently throttled.
+*       - handle turning off CRTSCTS.
+*
+*  (7/30/2000) borchers
+*    -- Added support for more than one Digi USB device by moving
+*       globals to a private structure in the pointed to from the
+*       usb_serial structure.
+*    -- Moved the modem change and transmit idle wait queues into
+*       the port private structure, so each port has its own queue
+*       rather than sharing global queues.
+*    -- Added support for break signals.
+*
+*  (7/25/2000) pberger
+*    -- Added USB-2 support.  Note: the USB-2 supports 3 devices: two
+*       serial and a parallel port.  The parallel port is implemented
+*       as a serial-to-parallel converter.  That is, the driver actually
+*       presents all three USB-2 interfaces as serial ports, but the third
+*       one physically connects to a parallel device.  Thus, for example,
+*       one could plug a parallel printer into the USB-2's third port,
+*       but from the kernel's (and userland's) point of view what's
+*       actually out there is a serial device.
+*
 *  (7/15/2000) borchers
 *    -- Fixed race in open when a close is in progress.
 *    -- Keep count of opens and dec the module use count for each
@@ -24,8 +76,8 @@
 *       callbacks, and no longer restart read chains if there is
 *       a status error or a sanity error.  This fixed the seg
 *       faults and other errors we used to get on disconnect.
-*    -- Port->active is once again a flag, not a count, as it was
-*       intended by usb-serial.  Since it was only a char it would
+*    -- Port->active is once again a flag as usb-serial intended it
+*       to be, not a count.  Since it was only a char it would
 *       have been limited to 256 simultaneous opens.  Now the open
 *       count is kept in the port private structure in dp_open_count.
 *    -- Added code for modularization of the digi_acceleport driver.
 *
 *  (6/4/2000) pberger and borchers
 *    -- Replaced separate calls to spin_unlock_irqrestore and
-*       interruptible_sleep_on_interruptible with a new function
+*       interruptible_sleep_on_timeout with a new function
 *       cond_wait_interruptible_timeout_irqrestore.  This eliminates
 *       the race condition where the wake up could happen after
 *       the unlock and before the sleep.
 *  - Following Documentation/DocBook/kernel-locking.pdf no spin locks
 *    are held when calling copy_to/from_user or printk.
 *    
-*  $Id: digi_acceleport.c,v 1.5 2000/07/18 04:52:43 root Exp $
+*  $Id: digi_acceleport.c,v 1.80 2000/08/09 06:36:18 root Exp $
 */
 
 #include <linux/config.h>
 
 /* Defines */
 
-/* port buffer length -- must be <= transfer buffer length - 2 */
+/* port output buffer length -- must be <= transfer buffer length - 2 */
 /* so we can be sure to send the full buffer in one urb */
-#define DIGI_PORT_BUF_LEN              8
+#define DIGI_OUT_BUF_SIZE              8
+
+/* port input buffer length -- must be >= transfer buffer length - 3 */
+/* so we can be sure to hold at least one full buffer from one urb */
+#define DIGI_IN_BUF_SIZE               64
 
 /* retry timeout while sleeping */
 #define DIGI_RETRY_TIMEOUT             (HZ/10)
 
 /* ids */
 #define DIGI_VENDOR_ID                 0x05c5
-#define DIGI_ID                                0x0004
+#define DIGI_2_ID                      0x0002  /* USB-2 */
+#define DIGI_4_ID                      0x0004  /* USB-4 */
 
 /* commands
  * "INB": can be used on the in-band endpoint
 
 /* Structures */
 
-typedef struct digi_private {
-       int dp_port_num;
+typedef struct digi_serial {
+       spinlock_t ds_serial_lock;
+       struct usb_serial_port *ds_oob_port;    /* out-of-band port */
+       int ds_oob_port_num;                    /* index of out-of-band port */
+       int ds_device_started;
+} digi_serial_t;
+
+typedef struct digi_port {
        spinlock_t dp_port_lock;
-       int dp_buf_len;
-       unsigned char dp_buf[DIGI_PORT_BUF_LEN];
+       int dp_port_num;
+       int dp_out_buf_len;
+       unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
+       int dp_in_buf_len;
+       unsigned char dp_in_buf[DIGI_IN_BUF_SIZE];
+       unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE];
        unsigned int dp_modem_signals;
+       wait_queue_head_t dp_modem_change_wait;
        int dp_open_count;                      /* inc on open, dec on close */
        int dp_transmit_idle;
+       wait_queue_head_t dp_transmit_idle_wait;
+       int dp_throttled;
+       int dp_throttle_restart;
+       wait_queue_head_t dp_flush_wait;
        int dp_in_close;                        /* close in progress */
        wait_queue_head_t dp_close_wait;        /* wait queue for close */
        struct tq_struct dp_wakeup_task;
-} digi_private_t;
+} digi_port_t;
 
 
 /* Local Function Declarations */
 
 static void digi_wakeup_write( struct usb_serial_port *port );
 static void digi_wakeup_write_lock( struct usb_serial_port *port );
-static int digi_write_oob_command( unsigned char *buf, int count );
+static int digi_write_oob_command( struct usb_serial_port *port,
+       unsigned char *buf, int count, int interruptible );
 static int digi_write_inb_command( struct usb_serial_port *port,
-       unsigned char *buf, int count ) __attribute__((unused));
+       unsigned char *buf, int count, unsigned long timeout );
 static int digi_set_modem_signals( struct usb_serial_port *port,
-       unsigned int modem_signals );
+       unsigned int modem_signals, int interruptible );
 static int digi_transmit_idle( struct usb_serial_port *port,
        unsigned long timeout );
 static void digi_rx_throttle (struct usb_serial_port *port);
@@ -386,25 +459,40 @@ static int digi_read_oob_callback( struct urb *urb );
 
 /* device info needed for the Digi serial converter */
 static u16 digi_vendor_id = DIGI_VENDOR_ID;
-static u16 digi_product_id = DIGI_ID;
-
-/* out of band port */
-static int oob_port_num;                       /* index of out-of-band port */
-static struct usb_serial_port *oob_port;       /* out-of-band port */
-static int device_startup = 0;
-
-spinlock_t startup_lock;                       /* used by startup_device */
-
-static wait_queue_head_t modem_change_wait;
-static wait_queue_head_t transmit_idle_wait;
+static u16 digi_product_2_id = DIGI_2_ID;      /* USB 2 */
+static u16 digi_product_4_id = DIGI_4_ID;      /* USB 4 */
 
+static struct usb_serial_device_type digi_acceleport_2_device = {
+       name:                           "Digi USB",
+       idVendor:                       &digi_vendor_id,
+       idProduct:                      &digi_product_2_id,
+       needs_interrupt_in:             DONT_CARE,
+       needs_bulk_in:                  MUST_HAVE,
+       needs_bulk_out:                 MUST_HAVE,
+       num_interrupt_in:               0,
+       num_bulk_in:                    4,
+       num_bulk_out:                   4,
+       num_ports:                      3,
+       open:                           digi_open,
+       close:                          digi_close,
+       write:                          digi_write,
+       write_room:                     digi_write_room,
+       write_bulk_callback:            digi_write_bulk_callback,
+       read_bulk_callback:             digi_read_bulk_callback,
+       chars_in_buffer:                digi_chars_in_buffer,
+       throttle:                       digi_rx_throttle,
+       unthrottle:                     digi_rx_unthrottle,
+       ioctl:                          digi_ioctl,
+       set_termios:                    digi_set_termios,
+       break_ctl:                      digi_break_ctl,
+       startup:                        digi_startup,
+       shutdown:                       digi_shutdown,
+};
 
-/* Globals */
-
-struct usb_serial_device_type digi_acceleport_device = {
+static struct usb_serial_device_type digi_acceleport_4_device = {
        name:                           "Digi USB",
        idVendor:                       &digi_vendor_id,
-       idProduct:                      &digi_product_id,
+       idProduct:                      &digi_product_4_id,
        needs_interrupt_in:             DONT_CARE,
        needs_bulk_in:                  MUST_HAVE,
        needs_bulk_out:                 MUST_HAVE,
@@ -479,7 +567,7 @@ static void digi_wakeup_write_lock( struct usb_serial_port *port )
 {
 
        unsigned long flags;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
 
 
        spin_lock_irqsave( &priv->dp_port_lock, flags );
@@ -515,20 +603,23 @@ static void digi_wakeup_write( struct usb_serial_port *port )
 *  Write commands on the out of band port.  Commands are 4
 *  bytes each, multiple commands can be sent at once, and
 *  no command will be split across USB packets.  Returns 0
-*  if successful, -EINTR if interrupted while sleeping, or
-*  a negative error returned by usb_submit_urb.
+*  if successful, -EINTR if interrupted while sleeping and
+*  the interruptible flag is true, or a negative error
+*  returned by usb_submit_urb.
 */
 
-static int digi_write_oob_command( unsigned char *buf, int count )
+static int digi_write_oob_command( struct usb_serial_port *port,
+       unsigned char *buf, int count, int interruptible )
 {
 
        int ret = 0;
        int len;
-       digi_private_t *oob_priv = (digi_private_t *)(oob_port->private);
+       struct usb_serial_port *oob_port = (struct usb_serial_port *)((digi_serial_t *)port->serial->private)->ds_oob_port;
+       digi_port_t *oob_priv = (digi_port_t *)oob_port->private;
        unsigned long flags = 0;
 
 
-dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_port_num, count );
+dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count );
 
        spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
 
@@ -538,7 +629,7 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_port_num, count );
                        cond_wait_interruptible_timeout_irqrestore(
                                &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
                                &oob_priv->dp_port_lock, flags );
-                       if( signal_pending(current) ) {
+                       if( interruptible && signal_pending(current) ) {
                                return( -EINTR );
                        }
                        spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
@@ -562,8 +653,8 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_port_num, count );
        spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
 
        if( ret ) {
-               dbg( "digi_write_oob_command: usb_submit_urb failed, ret=%d",
-               ret );
+               err( __FUNCTION__ ": usb_submit_urb failed, ret=%d",
+                       ret );
        }
 
        return( ret );
@@ -576,17 +667,20 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_port_num, count );
 *
 *  Write commands on the given port.  Commands are 4
 *  bytes each, multiple commands can be sent at once, and
-*  no command will be split across USB packets.  Returns 0
-*  if successful, or a negative error returned by digi_write.
+*  no command will be split across USB packets.  If timeout
+*  is non-zero, write in band command will return after
+*  waiting unsuccessfully for the URB status to clear for
+*  timeout ticks.  Returns 0 if successful, or a negative
+*  error returned by digi_write.
 */
 
 static int digi_write_inb_command( struct usb_serial_port *port,
-       unsigned char *buf, int count )
+       unsigned char *buf, int count, unsigned long timeout )
 {
 
        int ret = 0;
        int len;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        unsigned char *data = port->write_urb->transfer_buffer;
        unsigned long flags = 0;
 
@@ -594,11 +688,17 @@ static int digi_write_inb_command( struct usb_serial_port *port,
 dbg( "digi_write_inb_command: TOP: port=%d, count=%d", priv->dp_port_num,
 count );
 
+       if( timeout )
+               timeout += jiffies;
+       else
+               timeout = ULONG_MAX;
+
        spin_lock_irqsave( &priv->dp_port_lock, flags );
 
-       while( count > 0 ) {
+       while( count > 0 && ret == 0 ) {
 
-               while( port->write_urb->status == -EINPROGRESS ) {
+               while( port->write_urb->status == -EINPROGRESS
+               && jiffies < timeout ) {
                        cond_wait_interruptible_timeout_irqrestore(
                                &port->write_wait, DIGI_RETRY_TIMEOUT,
                                &priv->dp_port_lock, flags );
@@ -611,25 +711,26 @@ count );
                /* len must be a multiple of 4 and small enough to */
                /* guarantee the write will send buffered data first, */
                /* so commands are in order with data and not split */
-               len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len );
+               len = MIN( count, port->bulk_out_size-2-priv->dp_out_buf_len );
                if( len > 4 )
                        len &= ~3;
 
                /* write any buffered data first */
-               if( priv->dp_buf_len > 0 ) {
+               if( priv->dp_out_buf_len > 0 ) {
                        data[0] = DIGI_CMD_SEND_DATA;
-                       data[1] = priv->dp_buf_len;
-                       memcpy( data+2, priv->dp_buf, priv->dp_buf_len );
-                       memcpy( data+2+priv->dp_buf_len, buf, len );
+                       data[1] = priv->dp_out_buf_len;
+                       memcpy( data+2, priv->dp_out_buf,
+                               priv->dp_out_buf_len );
+                       memcpy( data+2+priv->dp_out_buf_len, buf, len );
                        port->write_urb->transfer_buffer_length
-                               = priv->dp_buf_len+2+len;
+                               = priv->dp_out_buf_len+2+len;
                } else {
                        memcpy( data, buf, len );
                        port->write_urb->transfer_buffer_length = len;
                }
 
                if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
-                       priv->dp_buf_len = 0;
+                       priv->dp_out_buf_len = 0;
                        count -= len;
                        buf += len;
                }
@@ -639,8 +740,8 @@ count );
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
        if( ret ) {
-               dbg( "digi_write_inb_command: usb_submit_urb failed, ret=%d",
-               ret );
+               err( __FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d",
+               ret, priv->dp_port_num );
        }
 
        return( ret );
@@ -659,13 +760,14 @@ count );
 */
 
 static int digi_set_modem_signals( struct usb_serial_port *port,
-       unsigned int modem_signals )
+       unsigned int modem_signals, int interruptible )
 {
 
        int ret;
+       digi_port_t *port_priv = (digi_port_t *)port->private;
+       struct usb_serial_port *oob_port = (struct usb_serial_port *)((digi_serial_t *)port->serial->private)->ds_oob_port;
+       digi_port_t *oob_priv = (digi_port_t *)oob_port->private;
        unsigned char *data = oob_port->write_urb->transfer_buffer;
-       digi_private_t *port_priv = (digi_private_t *)(port->private);
-       digi_private_t *oob_priv = (digi_private_t *)(oob_port->private);
        unsigned long flags = 0;
 
 
@@ -680,7 +782,7 @@ port_priv->dp_port_num, modem_signals );
                cond_wait_interruptible_timeout_irqrestore(
                        &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
                        &oob_priv->dp_port_lock, flags );
-               if( signal_pending(current) ) {
+               if( interruptible && signal_pending(current) ) {
                        return( -EINTR );
                }
                spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
@@ -711,7 +813,7 @@ port_priv->dp_port_num, modem_signals );
        spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
 
        if( ret ) {
-               dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d",
+               err( __FUNCTION__ ": usb_submit_urb failed, ret=%d",
                ret );
        }
 
@@ -738,7 +840,7 @@ static int digi_transmit_idle( struct usb_serial_port *port,
 
        int ret;
        unsigned char buf[2];
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        unsigned long flags = 0;
 
 
@@ -749,16 +851,16 @@ static int digi_transmit_idle( struct usb_serial_port *port,
        buf[0] = DIGI_CMD_TRANSMIT_IDLE;
        buf[1] = 0;
 
-       if( (ret=digi_write_inb_command( port, buf, 2 )) != 0 )
-               return( ret );
-
        timeout += jiffies;
 
+       if( (ret=digi_write_inb_command( port, buf, 2, timeout-jiffies )) != 0 )
+               return( ret );
+
        spin_lock_irqsave( &priv->dp_port_lock, flags );
 
        while( jiffies < timeout && !priv->dp_transmit_idle ) {
                cond_wait_interruptible_timeout_irqrestore(
-                       &transmit_idle_wait, DIGI_RETRY_TIMEOUT,
+                       &priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
                        &priv->dp_port_lock, flags );
                if( signal_pending(current) ) {
                        return( -EINTR );
@@ -777,21 +879,18 @@ static int digi_transmit_idle( struct usb_serial_port *port,
 static void digi_rx_throttle( struct usb_serial_port *port )
 {
 
-#ifdef DEBUG
-       digi_private_t *priv = (digi_private_t *)(port->private);
-#endif
+       unsigned long flags;
+       digi_port_t *priv = (digi_port_t *)(port->private);
 
 
 dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num );
 
-       /* stop receiving characters. We just turn off the URB request, and
-          let chars pile up in the device. If we're doing hardware
-          flowcontrol, the device will signal the other end when its buffer
-          fills up. If we're doing XON/XOFF, this would be a good time to
-          send an XOFF, although it might make sense to foist that off
-          upon the device too. */
-
-       // usb_unlink_urb(port->interrupt_in_urb);
+       /* stop receiving characters by not resubmitting the read urb */
+       spin_lock_irqsave( &priv->dp_port_lock, flags );
+       priv->dp_throttled = 1;
+       priv->dp_throttle_restart = 0;
+       priv->dp_in_buf_len = 0;
+       spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 }
 
@@ -799,16 +898,43 @@ dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num );
 static void digi_rx_unthrottle( struct usb_serial_port *port )
 {
 
-#ifdef DEBUG
-       digi_private_t *priv = (digi_private_t *)(port->private);
-#endif
+       int ret = 0;
+       int len;
+       unsigned long flags;
+       digi_port_t *priv = (digi_port_t *)(port->private);
+       struct tty_struct *tty = port->tty;
 
 
 dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
 
-       /* just restart the receive interrupt URB */
-       //if (usb_submit_urb(port->interrupt_in_urb))
-       //      dbg( "digi_rx_unthrottle: usb_submit_urb failed" );
+       spin_lock_irqsave( &priv->dp_port_lock, flags );
+
+       /* send any buffered chars from throttle time on to tty subsystem */
+       len = MIN( priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count );
+       if( len > 0 ) {
+               memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len );
+               memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len );
+               tty->flip.char_buf_ptr += len;
+               tty->flip.flag_buf_ptr += len;
+               tty->flip.count += len;
+               tty_flip_buffer_push( tty );
+       }
+
+       /* restart read chain */
+       if( priv->dp_throttle_restart )
+               ret = usb_submit_urb( port->read_urb );
+
+       /* turn throttle off */
+       priv->dp_throttled = 0;
+       priv->dp_in_buf_len = 0;
+       priv->dp_throttle_restart = 0;
+
+       spin_unlock_irqrestore( &priv->dp_port_lock, flags );
+
+       if( ret ) {
+               err( __FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d",
+                       ret, priv->dp_port_num );
+       }
 
 }
 
@@ -817,12 +943,13 @@ static void digi_set_termios( struct usb_serial_port *port,
        struct termios *old_termios )
 {
 
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        unsigned int iflag = port->tty->termios->c_iflag;
        unsigned int cflag = port->tty->termios->c_cflag;
        unsigned int old_iflag = old_termios->c_iflag;
        unsigned int old_cflag = old_termios->c_cflag;
        unsigned char buf[32];
+       unsigned int modem_signals;
        int arg,ret;
        int i = 0;
 
@@ -837,13 +964,18 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
                /* reassert DTR and (maybe) RTS on transition from B0 */
                if( (old_cflag&CBAUD) == B0 ) {
                        /* don't set RTS if using hardware flow control */
-                       /* and throttling input -- not implemented yet */
-                       digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS );
+                       /* and throttling input */
+                       modem_signals = TIOCM_DTR;
+                       if( !(port->tty->termios->c_cflag & CRTSCTS) ||
+                       !test_bit(TTY_THROTTLED, &port->tty->flags) ) {
+                               modem_signals |= TIOCM_RTS;
+                       }
+                       digi_set_modem_signals( port, modem_signals, 1 );
                }
 
                switch( (cflag&CBAUD) ) {
                        /* drop DTR and RTS on transition to B0 */
-               case B0: digi_set_modem_signals( port, 0 ); break;
+               case B0: digi_set_modem_signals( port, 0, 1 ); break;
                case B50: arg = DIGI_BAUD_50; break;
                case B75: arg = DIGI_BAUD_75; break;
                case B110: arg = DIGI_BAUD_110; break;
@@ -947,10 +1079,20 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
                else
                        arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
 
-               if( (cflag&CRTSCTS) )
+               if( (cflag&CRTSCTS) ) {
+
                        arg |= DIGI_INPUT_FLOW_CONTROL_RTS;
-               else
+
+                       /* On USB-4 it is necessary to assert RTS prior */
+                       /* to selecting RTS input flow control.  */
+                       buf[i++] = DIGI_CMD_SET_RTS_SIGNAL;
+                       buf[i++] = priv->dp_port_num;
+                       buf[i++] = DIGI_RTS_ACTIVE;
+                       buf[i++] = 0;
+
+               } else {
                        arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS;
+               }
 
                buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
                buf[i++] = priv->dp_port_num;
@@ -960,8 +1102,8 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
        }
 
        /* set output flow control */
-       /*if( (iflag&IXON) != (old_iflag&IXON)
-       || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) )*/ {
+       if( (iflag&IXON) != (old_iflag&IXON)
+       || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
 
                arg = 0;
 
@@ -970,10 +1112,12 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
                else
                        arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
 
-               if( (cflag&CRTSCTS) )
+               if( (cflag&CRTSCTS) ) {
                        arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS;
-               else
+               } else {
                        arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS;
+                       port->tty->hw_stopped = 0;
+               }
 
                buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
                buf[i++] = priv->dp_port_num;
@@ -997,7 +1141,7 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
 
        }
 
-       if( (ret=digi_write_oob_command( buf, i )) != 0 )
+       if( (ret=digi_write_oob_command( port, buf, i, 1 )) != 0 )
                dbg( "digi_set_termios: write oob failed, ret=%d", ret );
 
 }
@@ -1006,12 +1150,15 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
 static void digi_break_ctl( struct usb_serial_port *port, int break_state )
 {
 
-#ifdef DEBUG
-       digi_private_t *priv = (digi_private_t *)(port->private);
-#endif
+       unsigned char buf[4];
 
 
-dbg( "digi_break_ctl: TOP: port=%d", priv->dp_port_num );
+       buf[0] = DIGI_CMD_BREAK_CONTROL;
+       buf[1] = 2;                             /* length */
+       buf[2] = break_state ? 1 : 0;
+       buf[3] = 0;                             /* pad */
+
+       digi_write_inb_command( port, buf, 4, 0 );
 
 }
 
@@ -1020,7 +1167,7 @@ static int digi_ioctl( struct usb_serial_port *port, struct file *file,
        unsigned int cmd, unsigned long arg )
 {
 
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        unsigned int val;
        unsigned long flags = 0;
 
@@ -1048,7 +1195,7 @@ dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd );
                else if( cmd == TIOCMBIC )
                        val = priv->dp_modem_signals & ~val;
                spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-               return( digi_set_modem_signals( port, val ) );
+               return( digi_set_modem_signals( port, val, 1 ) );
 
        case TIOCMIWAIT:
                /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
@@ -1072,7 +1219,7 @@ static int digi_write( struct usb_serial_port *port, int from_user,
 {
 
        int ret,data_len,new_len;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        unsigned char *data = port->write_urb->transfer_buffer;
        unsigned char user_buf[64];     /* 64 bytes is max USB bulk packet */
        unsigned long flags = 0;
@@ -1098,9 +1245,10 @@ priv->dp_port_num, count, from_user, in_interrupt() );
                /* buffer data if count is 1 (probably put_char) if possible */
                if( count == 1 ) {
                        new_len = MIN( count,
-                               DIGI_PORT_BUF_LEN-priv->dp_buf_len );
-                       memcpy( priv->dp_buf+priv->dp_buf_len, buf, new_len );
-                       priv->dp_buf_len += new_len;
+                               DIGI_OUT_BUF_SIZE-priv->dp_out_buf_len );
+                       memcpy( priv->dp_out_buf+priv->dp_out_buf_len, buf,
+                               new_len );
+                       priv->dp_out_buf_len += new_len;
                } else {
                        new_len = 0;
                }
@@ -1113,8 +1261,8 @@ priv->dp_port_num, count, from_user, in_interrupt() );
 
        /* allow space for any buffered data and for new data, up to */
        /* transfer buffer size - 2 (for command and length bytes) */
-       new_len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len );
-       data_len = new_len + priv->dp_buf_len;
+       new_len = MIN( count, port->bulk_out_size-2-priv->dp_out_buf_len );
+       data_len = new_len + priv->dp_out_buf_len;
 
        if( data_len == 0 ) {
                spin_unlock_irqrestore( &priv->dp_port_lock, flags );
@@ -1127,22 +1275,24 @@ priv->dp_port_num, count, from_user, in_interrupt() );
        *data++ = data_len;
 
        /* copy in buffered data first */
-       memcpy( data, priv->dp_buf, priv->dp_buf_len );
-       data += priv->dp_buf_len;
+       memcpy( data, priv->dp_out_buf, priv->dp_out_buf_len );
+       data += priv->dp_out_buf_len;
 
        /* copy in new data */
        memcpy( data, from_user ? user_buf : buf, new_len );
 
        if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
                ret = new_len;
-               priv->dp_buf_len = 0;
+               priv->dp_out_buf_len = 0;
        }
 
        /* return length of new data written, or error */
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
        if( ret < 0 ) {
-               dbg( "digi_write: usb_submit_urb failed, ret=%d", ret );
+               err( __FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d",
+                       ret, priv->dp_port_num );
        }
+
 dbg( "digi_write: returning %d", ret );
        return( ret );
 
@@ -1154,21 +1304,27 @@ static void digi_write_bulk_callback( struct urb *urb )
 
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial;
-       digi_private_t *priv;
+       digi_port_t *priv;
        int ret = 0;
 
 
-dbg( "digi_write_bulk_callback: TOP" );
+dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
 
-       /* port sanity check */
-       if( port == NULL || (priv=(digi_private_t *)(port->private)) == NULL ) {
+       /* port and serial sanity check */
+       if( port == NULL || (priv=(digi_port_t *)(port->private)) == NULL ) {
                err( __FUNCTION__ ": port or port->private is NULL, status=%d",
                        urb->status );
                return;
        }
+       serial = port->serial;
+       if( serial == NULL || serial->private == NULL ) {
+               err( __FUNCTION__ ": serial or serial->private is NULL, status=%d", urb->status );
+               return;
+       }
 
        /* handle oob callback */
-       if( priv->dp_port_num == oob_port_num ) {
+       if( priv->dp_port_num
+       == ((digi_serial_t *)(serial->private))->ds_oob_port_num ) {
                dbg( "digi_write_bulk_callback: oob callback" );
                spin_lock( &priv->dp_port_lock );
                wake_up_interruptible( &port->write_wait );
@@ -1176,29 +1332,29 @@ dbg( "digi_write_bulk_callback: TOP" );
                return;
        }
 
-       /* sanity checks */
-       if( port_paranoia_check( port, "digi_write_bulk_callback" ) )
-               return;
-       serial = port->serial;
-       if( serial_paranoia_check( serial, "digi_write_bulk_callback" ) )
+       /* further sanity checks */
+       if( port_paranoia_check( port, __FUNCTION__ )
+       || serial_paranoia_check( serial, __FUNCTION__ ) )
                return;
 
-       /* try to send any buffered data on this port */
+       /* try to send any buffered data on this port, if it is open */
        spin_lock( &priv->dp_port_lock );
-       if( port->write_urb->status != -EINPROGRESS && priv->dp_buf_len > 0 ) {
+       if( priv->dp_open_count && port->write_urb->status != -EINPROGRESS
+       && priv->dp_out_buf_len > 0 ) {
 
                *((unsigned char *)(port->write_urb->transfer_buffer))
                        = (unsigned char)DIGI_CMD_SEND_DATA;
                *((unsigned char *)(port->write_urb->transfer_buffer)+1)
-                       = (unsigned char)priv->dp_buf_len;
+                       = (unsigned char)priv->dp_out_buf_len;
 
-               port->write_urb->transfer_buffer_length = priv->dp_buf_len+2;
+               port->write_urb->transfer_buffer_length
+                       = priv->dp_out_buf_len+2;
 
-               memcpy( port->write_urb->transfer_buffer+2, priv->dp_buf,
-                       priv->dp_buf_len );
+               memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
+                       priv->dp_out_buf_len );
 
                if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
-                       priv->dp_buf_len = 0;
+                       priv->dp_out_buf_len = 0;
                }
 
        }
@@ -1224,7 +1380,7 @@ static int digi_write_room( struct usb_serial_port *port )
 {
 
        int room;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        unsigned long flags = 0;
 
 
@@ -1233,7 +1389,7 @@ static int digi_write_room( struct usb_serial_port *port )
        if( port->write_urb->status == -EINPROGRESS )
                room = 0;
        else
-               room = port->bulk_out_size - 2 - priv->dp_buf_len;
+               room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
 
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
@@ -1246,7 +1402,7 @@ dbg( "digi_write_room: port=%d, room=%d", priv->dp_port_num, room );
 static int digi_chars_in_buffer( struct usb_serial_port *port )
 {
 
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
 
 
        if( port->write_urb->status == -EINPROGRESS ) {
@@ -1254,8 +1410,8 @@ dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_ou
                /* return( port->bulk_out_size - 2 ); */
                return( 256 );
        } else {
-dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, priv->dp_buf_len );
-               return( priv->dp_buf_len );
+dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, priv->dp_out_buf_len );
+               return( priv->dp_out_buf_len );
        }
 
 }
@@ -1266,7 +1422,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp )
 
        int ret;
        unsigned char buf[32];
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        struct termios not_termios;
        unsigned long flags = 0;
 
@@ -1285,12 +1441,18 @@ dbg( "digi_open: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, por
                return( -EAGAIN );
        }
 
+       /* inc module use count before sleeping to wait for closes */
+       ++priv->dp_open_count;
+       MOD_INC_USE_COUNT;
+
        /* wait for a close in progress to finish */
        while( priv->dp_in_close ) {
                cond_wait_interruptible_timeout_irqrestore(
                        &priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
                        &priv->dp_port_lock, flags );
                if( signal_pending(current) ) {
+                       --priv->dp_open_count;
+                       MOD_DEC_USE_COUNT;
                        return( -EINTR );
                }
                spin_lock_irqsave( &priv->dp_port_lock, flags );
@@ -1299,16 +1461,12 @@ dbg( "digi_open: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, por
        /* if port is already open, just return */
        /* be sure exactly one open proceeds */
        if( port->active ) {
-               ++priv->dp_open_count;
-               MOD_INC_USE_COUNT;
                spin_unlock_irqrestore( &priv->dp_port_lock, flags );
                return( 0 );
        }
 
-       /* open is certain */
+       /* first open, mark port as active */
        port->active = 1;
-       ++priv->dp_open_count;
-       MOD_INC_USE_COUNT;
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
  
        /* read modem signals automatically whenever they change */
@@ -1323,7 +1481,7 @@ dbg( "digi_open: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, por
        buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
        buf[7] = 0;
 
-       if( (ret=digi_write_oob_command( buf, 8 )) != 0 )
+       if( (ret=digi_write_oob_command( port, buf, 8, 1 )) != 0 )
                dbg( "digi_open: write oob failed, ret=%d", ret );
 
        /* set termios settings */
@@ -1332,7 +1490,7 @@ dbg( "digi_open: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, por
        digi_set_termios( port, &not_termios );
 
        /* set DTR and RTS */
-       digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS );
+       digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS, 1 );
 
        return( 0 );
 
@@ -1345,7 +1503,7 @@ static void digi_close( struct usb_serial_port *port, struct file *filp )
        int ret;
        unsigned char buf[32];
        struct tty_struct *tty = port->tty;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)port->private;
        unsigned long flags = 0;
 
 
@@ -1386,7 +1544,7 @@ dbg( "digi_close: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, po
        }
 
        /* drop DTR and RTS */
-       digi_set_modem_signals( port, 0 );
+       digi_set_modem_signals( port, 0, 0 );
 
        /* disable input flow control */
        buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
@@ -1406,29 +1564,24 @@ dbg( "digi_close: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, po
        buf[10] = DIGI_DISABLE;
        buf[11] = 0;
 
-       /* flush fifos */
-       buf[12] = DIGI_CMD_IFLUSH_FIFO;
+       /* disable receive */
+       buf[12] = DIGI_CMD_RECEIVE_ENABLE;
        buf[13] = priv->dp_port_num;
-       buf[14] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+       buf[14] = DIGI_DISABLE;
        buf[15] = 0;
 
-       /* disable receive */
-       buf[16] = DIGI_CMD_RECEIVE_ENABLE;
+       /* flush fifos */
+       buf[16] = DIGI_CMD_IFLUSH_FIFO;
        buf[17] = priv->dp_port_num;
-       buf[18] = DIGI_DISABLE;
+       buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
        buf[19] = 0;
 
-       if( (ret=digi_write_oob_command( buf, 20 )) != 0 )
+       if( (ret=digi_write_oob_command( port, buf, 20, 0 )) != 0 )
                dbg( "digi_close: write oob failed, ret=%d", ret );
 
        /* wait for final commands on oob port to complete */
-       while( oob_port->write_urb->status == -EINPROGRESS ) {
-               interruptible_sleep_on_timeout( &oob_port->write_wait,
-                       DIGI_RETRY_TIMEOUT );
-               if( signal_pending(current) ) {
-                       break;
-               }
-       }
+       interruptible_sleep_on_timeout( &priv->dp_flush_wait,
+               DIGI_CLOSE_TIMEOUT );
 
        /* shutdown any outstanding bulk writes */
        usb_unlink_urb (port->write_urb);
@@ -1458,23 +1611,31 @@ static int digi_startup_device( struct usb_serial *serial )
 {
 
        int i,ret = 0;
+       digi_serial_t *serial_priv = (digi_serial_t *)serial->private;
+       struct usb_serial_port *port;
 
 
        /* be sure this happens exactly once */
-       spin_lock( &startup_lock );
-       if( device_startup ) {
-               spin_unlock( &startup_lock );
+       spin_lock( &serial_priv->ds_serial_lock );
+       if( serial_priv->ds_device_started ) {
+               spin_unlock( &serial_priv->ds_serial_lock );
                return( 0 );
        }
-       device_startup = 1;
-       spin_unlock( &startup_lock );
+       serial_priv->ds_device_started = 1;
+       spin_unlock( &serial_priv->ds_serial_lock );
 
        /* start reading from each bulk in endpoint for the device */
-       for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
+       /* set USB_DISABLE_SPD flag for write bulk urbs */
+       for( i=0; i<serial->type->num_ports+1; i++ ) {
 
-               if( (ret=usb_submit_urb(serial->port[i].read_urb)) != 0 ) {
-                       dbg( "digi_startup_device: usb_submit_urb failed, port=%d, ret=%d",
-                               i, ret );
+               port = &serial->port[i];
+
+               port->write_urb->transfer_flags |= USB_DISABLE_SPD;
+
+               if( (ret=usb_submit_urb(port->read_urb)) != 0 ) {
+                       err(
+                       __FUNCTION__ ": usb_submit_urb failed, ret=%d, port=%d",
+                       ret, i );
                        break;
                }
 
@@ -1489,51 +1650,68 @@ static int digi_startup( struct usb_serial *serial )
 {
 
        int i;
-       digi_private_t *priv;
+       digi_port_t *priv;
+       digi_serial_t *serial_priv;
 
 
 dbg( "digi_startup: TOP" );
 
-       spin_lock_init( &startup_lock );
-       init_waitqueue_head( &modem_change_wait );
-       init_waitqueue_head( &transmit_idle_wait );
-
        /* allocate the private data structures for all ports */
        /* number of regular ports + 1 for the out-of-band port */
-       for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
+       for( i=0; i<serial->type->num_ports+1; i++ ) {
 
                serial->port[i].active = 0;
 
-               /* allocate private structure */
+               /* allocate port private structure */
                priv = serial->port[i].private =
-                       (digi_private_t *)kmalloc( sizeof(digi_private_t),
+                       (digi_port_t *)kmalloc( sizeof(digi_port_t),
                        GFP_KERNEL );
-               if( priv == (digi_private_t *)0 )
+               if( priv == (digi_port_t *)0 ) {
+                       while( --i >= 0 )
+                               kfree( serial->port[i].private );
                        return( 1 );                    /* error */
+               }
 
-               /* initialize private structure */
+               /* initialize port private structure */
+               spin_lock_init( &priv->dp_port_lock );
                priv->dp_port_num = i;
-               priv->dp_buf_len = 0;
+               priv->dp_out_buf_len = 0;
+               priv->dp_in_buf_len = 0;
                priv->dp_modem_signals = 0;
+               init_waitqueue_head( &priv->dp_modem_change_wait );
                priv->dp_open_count = 0;
                priv->dp_transmit_idle = 0;
+               init_waitqueue_head( &priv->dp_transmit_idle_wait );
+               priv->dp_throttled = 0;
+               priv->dp_throttle_restart = 0;
+               init_waitqueue_head( &priv->dp_flush_wait );
                priv->dp_in_close = 0;
                init_waitqueue_head( &priv->dp_close_wait );
                priv->dp_wakeup_task.next = NULL;
                priv->dp_wakeup_task.sync = 0;
                priv->dp_wakeup_task.routine = (void *)digi_wakeup_write_lock;
                priv->dp_wakeup_task.data = (void *)(&serial->port[i]);
-               spin_lock_init( &priv->dp_port_lock );
 
                /* initialize write wait queue for this port */
-               init_waitqueue_head(&serial->port[i].write_wait);
+               init_waitqueue_head( &serial->port[i].write_wait );
+
+       }
 
+       /* allocate serial private structure */
+       serial_priv = serial->private =
+               (digi_serial_t *)kmalloc( sizeof(digi_serial_t),
+               GFP_KERNEL );
+       if( serial_priv == (digi_serial_t *)0 ) {
+               for( i=0; i<serial->type->num_ports+1; i++ )
+                       kfree( serial->port[i].private );
+               return( 1 );                    /* error */
        }
 
-       /* initialize out of band port info */
-       oob_port_num = digi_acceleport_device.num_ports;
-       oob_port = &serial->port[oob_port_num];
-       device_startup = 0;
+       /* initialize serial private structure */
+       spin_lock_init( &serial_priv->ds_serial_lock );
+       serial_priv->ds_oob_port_num = serial->type->num_ports;
+       serial_priv->ds_oob_port = &serial->port[serial_priv->ds_oob_port_num];
+       serial_priv->ds_device_started = 0;
 
        return( 0 );
 
@@ -1544,22 +1722,20 @@ static void digi_shutdown( struct usb_serial *serial )
 {
 
        int i;
-       digi_private_t *priv;
+       digi_port_t *priv;
        unsigned long flags;
 
 
 dbg( "digi_shutdown: TOP, in_interrupt()=%d", in_interrupt() );
 
        /* stop reads and writes on all ports */
-       for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
+       for( i=0; i<serial->type->num_ports+1; i++ ) {
                usb_unlink_urb( serial->port[i].read_urb );
                usb_unlink_urb( serial->port[i].write_urb );
        }
 
-       device_startup = 0;
-
        /* dec module use count */
-       for( i=0; i<digi_acceleport_device.num_ports; i++ ) {
+       for( i=0; i<serial->type->num_ports; i++ ) {
                priv = serial->port[i].private;
                spin_lock_irqsave( &priv->dp_port_lock, flags );
                while( priv->dp_open_count > 0 ) {
@@ -1571,8 +1747,9 @@ dbg( "digi_shutdown: TOP, in_interrupt()=%d", in_interrupt() );
 
        /* free the private data structures for all ports */
        /* number of regular ports + 1 for the out-of-band port */
-       for( i=0; i<digi_acceleport_device.num_ports+1; i++ )
+       for( i=0; i<serial->type->num_ports+1; i++ )
                kfree( serial->port[i].private );
+       kfree( serial->private );
 
 }
 
@@ -1581,18 +1758,24 @@ static void digi_read_bulk_callback( struct urb *urb )
 {
 
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-       digi_private_t *priv;
+       digi_port_t *priv;
        int ret;
 
 
 dbg( "digi_read_bulk_callback: TOP" );
 
        /* port sanity check, do not resubmit if port is not valid */
-       if( port == NULL || (priv=(digi_private_t *)(port->private)) == NULL ) {
+       if( port == NULL || (priv=(digi_port_t *)(port->private)) == NULL ) {
                err( __FUNCTION__ ": port or port->private is NULL, status=%d",
                        urb->status );
                return;
        }
+       if( port->serial == NULL
+       || serial_paranoia_check( port->serial, __FUNCTION__ )
+       || port->serial->private == NULL ) {
+               err( __FUNCTION__ ": serial is bad or serial->private is NULL, status=%d", urb->status );
+               return;
+       }
 
        /* do not resubmit urb if it has any status error */
        if( urb->status ) {
@@ -1601,7 +1784,8 @@ dbg( "digi_read_bulk_callback: TOP" );
        }
 
        /* handle oob or inb callback, do not resubmit if error */
-       if( priv->dp_port_num == oob_port_num ) {
+       if( priv->dp_port_num
+       == ((digi_serial_t *)(port->serial->private))->ds_oob_port_num ) {
                if( digi_read_oob_callback( urb ) != 0 )
                        return;
        } else {
@@ -1623,45 +1807,110 @@ dbg( "digi_read_bulk_callback: TOP" );
 *
 *  Digi Read INB Callback handles reads on the in band ports, sending
 *  the data on to the tty subsystem.  When called we know port and
-*  port->private are not NULL.  It returns 0 if successful, and -1 if
-*  the sanity checks failed.
+*  port->private are not NULL and port->serial has been validated.
+*  It returns 0 if successful, 1 if successful but the port is
+*  throttled, and -1 if the sanity checks failed.
 */
 
 static int digi_read_inb_callback( struct urb *urb )
 {
 
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-       struct usb_serial *serial = port->serial;
        struct tty_struct *tty = port->tty;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        int opcode = ((unsigned char *)urb->transfer_buffer)[0];
        int len = ((unsigned char *)urb->transfer_buffer)[1];
        int status = ((unsigned char *)urb->transfer_buffer)[2];
        unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
-       int i;
+       int flag,throttled;
 
 
-       /* sanity checks */
-       if( port_paranoia_check( port, __FUNCTION__ )
-       || serial_paranoia_check( serial, __FUNCTION__ ) )
+       /* sanity check */
+       if( port_paranoia_check( port, __FUNCTION__ ) )
                return( -1 );
 
-       /* short packet check */
+       /* do not process callbacks on closed ports */
+       /* but do continue the read chain */
+       if( priv->dp_open_count == 0 )
+               return( 0 );
+
+       /* short/multiple packet check */
        if( urb->actual_length != len + 2 ) {
-               err( __FUNCTION__ ": INCOMPLETE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status );
+               err( __FUNCTION__ ": INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status );
                return( -1 );
        }
 
+       spin_lock( &priv->dp_port_lock );
+
+       /* check for throttle; if set, do not resubmit read urb */
+       /* indicate the read chain needs to be restarted on unthrottle */
+       throttled = priv->dp_throttled;
+       if( throttled )
+               priv->dp_throttle_restart = 1;
+
        /* receive data */
-       if( opcode == DIGI_CMD_RECEIVE_DATA && urb->actual_length > 3 ) {
-               len = MIN( len, urb->actual_length-3 );
-               for( i=0; i<len; ++i ) {
-                        tty_insert_flip_char(tty, data[i], 0);
-               }
-               tty_flip_buffer_push(tty);
+       if( opcode == DIGI_CMD_RECEIVE_DATA ) {
+
+               /* get flag from status */
+               flag = 0;
+
+               /* overrun is special, not associated with a char */
+               if( status & DIGI_OVERRUN_ERROR ) {
+                       tty_insert_flip_char( tty, 0, TTY_OVERRUN );
+               }
+
+               /* break takes precedence over parity, */
+               /* which takes precedence over framing errors */
+               if( status & DIGI_BREAK_ERROR ) {
+                       flag = TTY_BREAK;
+               } else if( status & DIGI_PARITY_ERROR ) {
+                       flag = TTY_PARITY;
+               } else if( status & DIGI_FRAMING_ERROR ) {
+                       flag = TTY_FRAME;
+               }
+
+               /* data length is len-1 (one byte of len is status) */
+               --len;
+
+               if( throttled ) {
+
+                       len = MIN( len,
+                               DIGI_IN_BUF_SIZE - priv->dp_in_buf_len );
+
+                       if( len > 0 ) {
+                               memcpy( priv->dp_in_buf + priv->dp_in_buf_len,
+                                       data, len );
+                               memset( priv->dp_in_flag_buf
+                                       + priv->dp_in_buf_len, flag, len );
+                               priv->dp_in_buf_len += len;
+                       }
+
+               } else {
+
+                       len = MIN( len, TTY_FLIPBUF_SIZE - tty->flip.count );
+
+                       if( len > 0 ) {
+                               memcpy( tty->flip.char_buf_ptr, data, len );
+                               memset( tty->flip.flag_buf_ptr, flag, len );
+                               tty->flip.char_buf_ptr += len;
+                               tty->flip.flag_buf_ptr += len;
+                               tty->flip.count += len;
+                               tty_flip_buffer_push( tty );
+                       }
+
+               }
+
        }
 
-       return( 0 );
+       spin_unlock( &priv->dp_port_lock );
+
+       if( opcode == DIGI_CMD_RECEIVE_DISABLE ) {
+               dbg( __FUNCTION__ ": got RECEIVE_DISABLE" );
+       } else if( opcode != DIGI_CMD_RECEIVE_DATA ) {
+               dbg( __FUNCTION__ ": unknown opcode: %d", opcode );
+       }
+
+       return( throttled ? 1 : 0 );
 
 }
 
@@ -1670,8 +1919,9 @@ static int digi_read_inb_callback( struct urb *urb )
 *  Digi Read OOB Callback
 *
 *  Digi Read OOB Callback handles reads on the out of band port.
-*  When called we know port and port->private are not NULL.  It
-*  returns 0 if successful, and -1 if the sanity checks failed.
+*  When called we know port and port->private are not NULL and
+*  the port->serial is valid.  It returns 0 if successful, and
+*  -1 if the sanity checks failed.
 */
 
 static int digi_read_oob_callback( struct urb *urb )
@@ -1679,19 +1929,13 @@ static int digi_read_oob_callback( struct urb *urb )
 
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial = port->serial;
-       digi_private_t *priv = (digi_private_t *)(port->private);
+       digi_port_t *priv = (digi_port_t *)(port->private);
        int opcode, line, status, val;
        int i;
 
 
-dbg( "digi_read_oob_callback: len=%d", urb->actual_length );
-
-       /* sanity check */
-       if( serial == NULL ) {
-               err( __FUNCTION__ ": port->serial is NULL, status=%d, port=%d",
-                       urb->status, priv->dp_port_num );
-               return( -1 );
-       }
+dbg( "digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num,
+urb->actual_length );
 
        /* handle each oob command */
        for( i=0; i<urb->actual_length-3; ) {
@@ -1701,25 +1945,39 @@ dbg( "digi_read_oob_callback: len=%d", urb->actual_length );
                status = ((unsigned char *)urb->transfer_buffer)[i++];
                val = ((unsigned char *)urb->transfer_buffer)[i++];
 
-dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", opcode, line, status, val );
+dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d",
+opcode, line, status, val );
 
-               if( status != 0 )
+               if( status != 0 || line >= serial->type->num_ports )
                        continue;
 
-               if( (priv=serial->port[line].private) == NULL ) {
-                       dbg( __FUNCTION__ ": port[%d].private is NULL!", line );
-                       continue;
-               }
+               port = &serial->port[line];
+
+               if( port_paranoia_check( port, __FUNCTION__ )
+               || (priv=port->private) == NULL )
+                       return( -1 );
 
                if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) {
 
                        spin_lock( &priv->dp_port_lock );
 
                        /* convert from digi flags to termiox flags */
-                       if( val & DIGI_READ_INPUT_SIGNALS_CTS )
+                       if( val & DIGI_READ_INPUT_SIGNALS_CTS ) {
                                priv->dp_modem_signals |= TIOCM_CTS;
-                       else
+                               /* port must be open to use tty struct */
+                               if( priv->dp_open_count
+                               && port->tty->termios->c_cflag & CRTSCTS ) {
+                                       port->tty->hw_stopped = 0;
+                                       digi_wakeup_write( port );
+                               }
+                       } else {
                                priv->dp_modem_signals &= ~TIOCM_CTS;
+                               /* port must be open to use tty struct */
+                               if( priv->dp_open_count
+                               && port->tty->termios->c_cflag & CRTSCTS ) {
+                                       port->tty->hw_stopped = 1;
+                               }
+                       }
                        if( val & DIGI_READ_INPUT_SIGNALS_DSR )
                                priv->dp_modem_signals |= TIOCM_DSR;
                        else
@@ -1733,16 +1991,20 @@ dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", opcode, li
                        else
                                priv->dp_modem_signals &= ~TIOCM_CD;
 
-                       wake_up_interruptible( &modem_change_wait );
+                       wake_up_interruptible( &priv->dp_modem_change_wait );
                        spin_unlock( &priv->dp_port_lock );
 
                } else if( opcode == DIGI_CMD_TRANSMIT_IDLE ) {
 
                        spin_lock( &priv->dp_port_lock );
                        priv->dp_transmit_idle = 1;
-                       wake_up_interruptible( &transmit_idle_wait );
+                       wake_up_interruptible( &priv->dp_transmit_idle_wait );
                        spin_unlock( &priv->dp_port_lock );
 
+               } else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {
+
+                       wake_up_interruptible( &priv->dp_flush_wait );
+
                }
 
        }
@@ -1754,20 +2016,23 @@ dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", opcode, li
 
 int digi_init (void)
 {
-       usb_serial_register (&digi_acceleport_device);
+       usb_serial_register (&digi_acceleport_2_device);
+       usb_serial_register (&digi_acceleport_4_device);
        return 0;
 }
 
 
 void digi_exit (void)
 {
-       usb_serial_deregister (&digi_acceleport_device);
+       usb_serial_deregister (&digi_acceleport_2_device);
+       usb_serial_deregister (&digi_acceleport_4_device);
 }
 
 
 module_init(digi_init);
 module_exit(digi_exit);
 
+
 MODULE_AUTHOR("Peter Berger <pberger@brimson.com>, Al Borchers <borchers@steinerpoint.com>");
 MODULE_DESCRIPTION("Digi AccelePort USB-4 Serial Converter driver");
 
index fe63007b8c68c71a4f90ea27bc071a3493027dcd..10d57076c45c93e71372645654463a82667ba51f 100644 (file)
@@ -11,6 +11,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (08/08/2000) gkh
+ *     Added open_count to port structure.
+ *
  * (07/23/2000) gkh
  *     Added bulk_out_endpointAddress to port structure.
  *
@@ -59,6 +62,7 @@ struct usb_serial_port {
        wait_queue_head_t       write_wait;
 
        struct tq_struct        tqueue;         /* task queue for line discipline waking up */
+       int                     open_count;     /* number of times this port has been opened */
        
        void *                  private;        /* data private to the specific port */
 };
index 568f2b5cd73b8932562fcf4b9bc47cbcf300bfea..bc0ea807a40b1608b4bbcacf0bb43d3ecd4291d7 100644 (file)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (08/08/2000) gkh
+ *     Fixed endian problem in visor_startup.
+ *     Fixed MOD_INC and MOD_DEC logic and the ability to open a port more 
+ *     than once.
+ * 
  * (07/23/2000) gkh
  *     Added pool of write urbs to speed up transfers to the visor.
  * 
@@ -71,6 +76,7 @@ static int  visor_write               (struct usb_serial_port *port, int from_user, const uns
 static void visor_throttle     (struct usb_serial_port *port);
 static void visor_unthrottle   (struct usb_serial_port *port);
 static int  visor_startup      (struct usb_serial *serial);
+static void visor_shutdown     (struct usb_serial *serial);
 static int  visor_ioctl                (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
 static void visor_set_termios  (struct usb_serial_port *port, struct termios *old_termios);
 static void visor_write_bulk_callback (struct urb *urb);
@@ -94,6 +100,7 @@ struct usb_serial_device_type handspring_device = {
        throttle:               visor_throttle,
        unthrottle:             visor_unthrottle,
        startup:                visor_startup,
+       shutdown:               visor_shutdown,
        ioctl:                  visor_ioctl,
        set_termios:            visor_set_termios,
        write:                  visor_write,
@@ -117,13 +124,18 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
                return -EINVAL;
        }
 
-       port->active = 1;
-
-       /*Start reading from the device*/
-       if (usb_submit_urb(port->read_urb))
-               dbg(__FUNCTION__  " - usb_submit_urb(read bulk) failed");
+       ++port->open_count;
+       MOD_INC_USE_COUNT;
+       
+       if (!port->active) {
+               port->active = 1;
 
-       return (0);
+               /*Start reading from the device*/
+               if (usb_submit_urb(port->read_urb))
+                       dbg(__FUNCTION__  " - usb_submit_urb(read bulk) failed");
+       }
+       
+       return 0;
 }
 
 
@@ -134,19 +146,24 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
        
        dbg(__FUNCTION__ " - port %d", port->number);
                         
-       if (!transfer_buffer) {
-               err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
-       } else {
-               /* send a shutdown message to the device */
-               usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
-                               0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
-               kfree (transfer_buffer);
-       }
+       --port->open_count;
+       MOD_DEC_USE_COUNT;
+
+       if (port->open_count <= 0) {
+               if (!transfer_buffer) {
+                       err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+               } else {
+                       /* send a shutdown message to the device */
+                       usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
+                                       0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
+                       kfree (transfer_buffer);
+               }
 
-       /* shutdown our bulk reads and writes */
-       usb_unlink_urb (port->write_urb);
-       usb_unlink_urb (port->read_urb);
-       port->active = 0;
+               /* shutdown our bulk read */
+               usb_unlink_urb (port->read_urb);
+               port->active = 0;
+               port->open_count = 0;
+       }
 }
 
 
@@ -282,6 +299,8 @@ static int  visor_startup (struct usb_serial *serial)
        } else {
                struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
                char *string;
+
+               le16_to_cpus(&connection_info->num_ports);
                info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
                for (i = 0; i < connection_info->num_ports; ++i) {
                        switch (connection_info->connections[i].port_function_id) {
@@ -322,6 +341,21 @@ static int  visor_startup (struct usb_serial *serial)
 }
 
 
+static void visor_shutdown (struct usb_serial *serial)
+{
+       int i;
+
+       dbg (__FUNCTION__);
+
+       /* stop reads and writes on all ports */
+       for (i=0; i < serial->num_ports; ++i) {
+               while (serial->port[i].open_count > 0) {
+                       visor_close (&serial->port[i], NULL);
+               }
+       }
+}
+
+
 static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
        dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
index 25d1d24cf8eca5b633efa7bded9297525f20f6bf..017a99dce29f4902b9ebac6109479c3d66e2839a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
+#include <linux/init.h>
 #include <linux/usb.h>
 
 /*
@@ -42,13 +43,11 @@ int dsbr100_init(void);
 int uhci_init(void);
 int ohci_hcd_init(void);
 
-#ifdef MODULE
-
 /*
  * Cleanup
  */
 
-void cleanup_module(void)
+static void __exit usb_exit(void)
 {
        usb_major_cleanup();
        usbdevfs_cleanup();
@@ -59,10 +58,7 @@ void cleanup_module(void)
  * Init
  */
 
-int init_module(void)
-#else
-int usb_init(void)
-#endif
+static int __init usb_init(void)
 {
        usb_major_init();
        usbdevfs_init();
@@ -99,3 +95,6 @@ int usb_init(void)
 #endif
        return 0;
 }
+
+module_init(usb_init);
+module_exit(usb_exit);
index 367f0d3f6a00aa0ef7b37ede327b4550fd6e6401..316394a840f18bc4ab7c238cbefc5a1d4b15b837 100644 (file)
@@ -76,7 +76,6 @@
        (OHCI_CTRL_CBSR & 0x3) \
        | OHCI_CTRL_BLE | OHCI_CTRL_CLE | OHCI_CTRL_IE | OHCI_CTRL_PLE
 
-static DECLARE_WAIT_QUEUE_HEAD (op_wakeup); 
 static LIST_HEAD (ohci_hcd_list);
 static spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
 
@@ -534,7 +533,6 @@ static int sohci_unlink_urb (urb_t * urb)
 {
        unsigned long flags;
        ohci_t * ohci;
-       DECLARE_WAITQUEUE (wait, current);
        
        if (!urb) /* just to be sure */ 
                return -EINVAL;
@@ -580,14 +578,18 @@ static int sohci_unlink_urb (urb_t * urb)
                        spin_unlock_irqrestore (&usb_ed_lock, flags);
 
                        if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
+                               DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
+                               DECLARE_WAITQUEUE (wait, current);
+
                                usb_dec_dev_use (urb->dev);     
-                               add_wait_queue (&op_wakeup, &wait);
-                               current->state = TASK_UNINTERRUPTIBLE;
                                /* wait until all TDs are deleted */
-                               if (!schedule_timeout (HZ / 10))
-                                       err("unlink URB timeout!");
-                               remove_wait_queue (&op_wakeup, &wait); 
+                               add_wait_queue (&unlink_wakeup, &wait);
+                               urb_priv->wait = &unlink_wakeup;
+                               current->state = TASK_UNINTERRUPTIBLE;
+                               schedule ();
+                               remove_wait_queue (&unlink_wakeup, &wait); 
                                urb->status = -ENOENT;
+                               urb_priv->wait = 0;
                        } else {
                                /* usb_dec_dev_use done in dl_del_list() */
                                urb->status = -EINPROGRESS;
@@ -634,7 +636,6 @@ static int sohci_free_dev (struct usb_device * usb_dev)
        unsigned long flags;
        int i, cnt = 0;
        ed_t * ed;
-       DECLARE_WAITQUEUE (wait, current);
        struct ohci_device * dev = usb_to_ohci (usb_dev);
        ohci_t * ohci = usb_dev->bus->hcpriv;
        
@@ -643,13 +644,20 @@ static int sohci_free_dev (struct usb_device * usb_dev)
        
        if (usb_dev->devnum >= 0) {
        
-               /* delete all TDs of all EDs */
+               /* driver disconnects should have unlinked all urbs
+                * (freeing all the TDs, unlinking EDs) but we need
+                * to defend against bugs that prevent that.
+                */
                spin_lock_irqsave (&usb_ed_lock, flags);        
                for(i = 0; i < NUM_EDS; i++) {
                        ed = &(dev->ed[i]);
                        if (ed->state != ED_NEW) {
-                               if (ed->state == ED_OPER)
+                               if (ed->state == ED_OPER) {
+                                       /* driver on that interface didn't unlink an urb */
+                                       dbg ("driver usb-%s dev %d ed 0x%x unfreed URB",
+                                               ohci->ohci_dev->slot_name, usb_dev->devnum, i);
                                        ep_unlink (ohci, ed);
+                               }
                                ep_rm_ed (usb_dev, ed);
                                ed->state = ED_DEL;
                                cnt++;
@@ -657,6 +665,9 @@ static int sohci_free_dev (struct usb_device * usb_dev)
                }
                spin_unlock_irqrestore (&usb_ed_lock, flags);
                
+               /* if the controller is running, tds for those unlinked
+                * urbs get freed by dl_del_list at the next SF interrupt
+                */
                if (cnt > 0) {
 
                        if (ohci->disabled) {
@@ -670,15 +681,21 @@ static int sohci_free_dev (struct usb_device * usb_dev)
                                warn ("TD leak, %d", cnt);
 
                        } else if (!in_interrupt ()) {
+                               DECLARE_WAIT_QUEUE_HEAD (freedev_wakeup); 
+                               DECLARE_WAITQUEUE (wait, current);
+
                                /* SF interrupt handler calls dl_del_list */
-                               add_wait_queue (&op_wakeup, &wait);
+                               add_wait_queue (&freedev_wakeup, &wait);
+                               dev->wait = &freedev_wakeup;
                                current->state = TASK_UNINTERRUPTIBLE;
-                               schedule_timeout (HZ / 10);
-                               remove_wait_queue (&op_wakeup, &wait);
+                               schedule ();
+                               remove_wait_queue (&freedev_wakeup, &wait);
 
                        } else {
-                               /* drivers mustn't expect this to work */
-                               err ("can't free tds, interrupt context");
+                               /* likely some interface's driver has a refcount bug */
+                               err ("bus %s devnum %d deletion in interrupt",
+                                       ohci->ohci_dev->slot_name, usb_dev->devnum);
+                               BUG ();
                        }
                }
        }
@@ -907,35 +924,34 @@ static int ep_unlink (ohci_t * ohci, ed_t * ed)
 #endif
                break;
                
-    case ISO:
-       if (ohci->ed_isotail == ed)
-                               ohci->ed_isotail = ed->ed_prev;
+       case ISO:
+               if (ohci->ed_isotail == ed)
+                       ohci->ed_isotail = ed->ed_prev;
                if (ed->hwNextED != 0) 
-                               ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
-                               
+                   ((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
+                                   
                if (ed->ed_prev != NULL) {
                        ed->ed_prev->hwNextED = ed->hwNextED;
                } else {
-                       for (i = 0; i < 32; i += inter) {
-                               inter = 1;
+                       for (i = 0; i < 32; i++) {
                                for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]); 
-                                       *ed_p != 0; 
-                                       ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) {
-                                               inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
-                                               if(((ed_t *) bus_to_virt (le32_to_cpup (ed_p))) == ed) {
-                                                       *ed_p = ed->hwNextED;           
-                                                       break;
-                                               }
-                               }
+                                               *ed_p != 0; 
+                                               ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) {
+                                       // inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
+                                       if(((ed_t *) bus_to_virt (le32_to_cpup (ed_p))) == ed) {
+                                               *ed_p = ed->hwNextED;           
+                                               break;
+                                       }
+                               }
                        }       
                }       
 #ifdef DEBUG
                ep_print_int_eds (ohci, "UNLINK_ISO");
 #endif
                break;
-    }
-    ed->state = ED_UNLINK;
-    return 0;
+       }
+       ed->state = ED_UNLINK;
+       return 0;
 }
 
 
@@ -1276,28 +1292,33 @@ static void dl_del_list (ohci_t  * ohci, unsigned int frame)
                                tdINFO = le32_to_cpup (&td->hwINFO);
                                if (TD_CC_GET (tdINFO) < 0xE) dl_transfer_length (td);
                                *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
-                               if(++ (urb_priv->td_cnt) == urb_priv->length) 
+                               /* URB is done; clean up */
+                               if (++(urb_priv->td_cnt) == urb_priv->length) {
+                                       void    *condition = urb_priv->wait; 
+
                                        urb_rm_priv (urb);
                                        if (urb->transfer_flags & USB_ASYNC_UNLINK) {
                                                usb_dec_dev_use (urb->dev);
                                                urb->status = -ECONNRESET;
                                                urb->complete (urb); 
-                                       } else {        
-                                               wake_up (&op_wakeup);
+                                       } else if (condition) { 
+                                               /* unblock sohci_unlink_urb */
+                                               wake_up (condition);
                                        }
+                               }
                        } else {
                                td_p = &td->hwNextTD;
                        }
-                       
                }
+
                if (ed->state & ED_DEL) { /* set by sohci_free_dev */
                        struct ohci_device * dev = usb_to_ohci (ohci->dev[edINFO & 0x7F]);
-                       OHCI_FREE (tdTailP); /* free dummy td */
+                       OHCI_FREE (tdTailP); /* free dummy td */
                        ed->hwINFO = cpu_to_le32 (OHCI_ED_SKIP); 
                        ed->state = ED_NEW; 
                        /* if all eds are removed wake up sohci_free_dev */
-                       if (!--dev->ed_cnt)
-                               wake_up (&op_wakeup);
+                       if (!--dev->ed_cnt && dev->wait)
+                               wake_up (dev->wait);
                }
                else {
                        ed->state &= ~ED_URB_DEL;
@@ -1839,6 +1860,7 @@ static int hc_start (ohci_t * ohci)
 
        /* start controller operations */
        ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+       ohci->disabled = 0;
        writel (ohci->hc_control, &ohci->regs->control);
  
        /* Choose the interrupts we care about now, others later on demand */
@@ -1850,25 +1872,28 @@ static int hc_start (ohci_t * ohci)
        writel ((readl(&ohci->regs->roothub.a) | RH_A_NPS) & ~RH_A_PSM,
                &ohci->regs->roothub.a);
        writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif /* OHCI_USE_NPS */
+
        // POTPGT delay is bits 24-31, in 2 ms units.
        mdelay ((readl(&ohci->regs->roothub.a) >> 23) & 0x1fe);
-#endif /* OHCI_USE_NPS */
  
        /* connect the virtual root hub */
        ohci->rh.devnum = 0;
        usb_dev = usb_alloc_dev (NULL, ohci->bus);
-       if (!usb_dev)
+       if (!usb_dev) {
+           ohci->disabled = 1;
            return -ENOMEM;
+       }
 
        dev = usb_to_ohci (usb_dev);
        ohci->bus->root_hub = usb_dev;
        usb_connect (usb_dev);
        if (usb_new_device (usb_dev) != 0) {
                usb_free_dev (usb_dev); 
+               ohci->disabled = 1;
                return -ENODEV;
        }
        
-       ohci->disabled = 0;
        return 0;
 }
 
@@ -1936,7 +1961,7 @@ static void hc_interrupt (int irq, void * __ohci, struct pt_regs * r)
 
 /* allocate OHCI */
 
-static ohci_t * __devinit hc_alloc_ohci (void * mem_base)
+static ohci_t * __devinit hc_alloc_ohci (struct pci_dev *dev, void * mem_base)
 {
        ohci_t * ohci;
        struct usb_bus * bus;
@@ -1947,9 +1972,16 @@ static ohci_t * __devinit hc_alloc_ohci (void * mem_base)
                
        memset (ohci, 0, sizeof (ohci_t));
        
+       ohci->disabled = 1;
        ohci->irq = -1;
        ohci->regs = mem_base;   
 
+       ohci->ohci_dev = dev;
+       dev->driver_data = ohci;
+       INIT_LIST_HEAD (&ohci->ohci_hcd_list);
+       list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
+
        bus = usb_alloc_bus (&sohci_device_operations);
        if (!bus) {
                kfree (ohci);
@@ -1958,8 +1990,7 @@ static ohci_t * __devinit hc_alloc_ohci (void * mem_base)
 
        ohci->bus = bus;
        bus->hcpriv = (void *) ohci;
-       ohci->disabled = 1;
+
        return ohci;
 } 
 
@@ -2008,6 +2039,7 @@ static int __devinit
 hc_found_ohci (struct pci_dev *dev, int irq, void * mem_base)
 {
        ohci_t * ohci;
+       u8 latency, limit;
        char buf[8], *bufp = buf;
 
 #ifndef __sparc__
@@ -2019,15 +2051,24 @@ hc_found_ohci (struct pci_dev *dev, int irq, void * mem_base)
                (unsigned long) mem_base, bufp);
        printk(KERN_INFO __FILE__ ": usb-%s, %s\n", dev->slot_name, dev->name);
     
-       ohci = hc_alloc_ohci (mem_base);
+       ohci = hc_alloc_ohci (dev, mem_base);
        if (!ohci) {
                return -ENOMEM;
        }
 
-       ohci->ohci_dev = dev;
-       dev->driver_data = ohci;
-       INIT_LIST_HEAD (&ohci->ohci_hcd_list);
-       list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
+       /* bad pci latencies can contribute to overruns */ 
+       pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+       if (latency) {
+               pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
+               if (limit && limit < latency) {
+                       dbg ("PCI latency reduced to max %d", limit);
+                       pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
+                       ohci->pci_latency = limit;
+               } else {
+                       /* it might already have been reduced */
+                       ohci->pci_latency = latency;
+               }
+       }
 
        if (hc_reset (ohci) < 0) {
                hc_release_ohci (ohci);
@@ -2042,7 +2083,7 @@ hc_found_ohci (struct pci_dev *dev, int irq, void * mem_base)
        
        if (request_irq (irq, hc_interrupt, SA_SHIRQ,
                        ohci_pci_driver.name, ohci) != 0) {
-               err ("request interrupt %d failed", irq);
+               err ("request interrupt %s failed", bufp);
                hc_release_ohci (ohci);
                return -EBUSY;
        }
@@ -2072,6 +2113,9 @@ static void hc_restart (ohci_t *ohci)
        int temp;
        int i;
 
+       if (ohci->pci_latency)
+               pci_write_config_byte (ohci->ohci_dev, PCI_LATENCY_TIMER, ohci->pci_latency);
+
        ohci->disabled = 1;
        if (ohci->bus->root_hub)
                usb_disconnect (&ohci->bus->root_hub);
@@ -2106,7 +2150,6 @@ static int __devinit
 ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
        unsigned long mem_resource, mem_len;
-       u8 latency, limit;
        void *mem_base;
 
        if (pci_enable_device(dev) < 0)
@@ -2128,14 +2171,6 @@ ohci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 
        /* controller writes into our memory */
        pci_set_master (dev);
-       pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
-       if (latency) {
-               pci_read_config_byte (dev, PCI_MAX_LAT, &limit);
-               if (limit && limit < latency) {
-                       dbg ("PCI latency reduced to max %d", limit);
-                       pci_write_config_byte (dev, PCI_LATENCY_TIMER, limit);
-               }
-       }
 
        return hc_found_ohci (dev, dev->irq, mem_base);
 } 
@@ -2157,6 +2192,9 @@ ohci_pci_remove (struct pci_dev *dev)
                ohci->disabled ? " (disabled)" : "",
                in_interrupt () ? " in interrupt" : ""
                );
+#ifdef DEBUG
+       ohci_dump (ohci, 1);
+#endif
 
        /* don't wake up sleeping controllers, or block in interrupt context */
        if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER || in_interrupt ()) {
@@ -2209,6 +2247,14 @@ ohci_pci_resume (struct pci_dev *dev)
        ohci_t          *ohci = (ohci_t *) dev->driver_data;
        int             temp;
 
+       /* guard against multiple resumes */
+       atomic_inc (&ohci->resume_count);
+       if (atomic_read (&ohci->resume_count) != 1) {
+               err ("concurrent PCI resumes for usb-%s", dev->slot_name);
+               atomic_dec (&ohci->resume_count);
+               return;
+       }
+
        /* did we suspend, or were we powered off? */
        ohci->hc_control = readl (&ohci->regs->control);
        temp = ohci->hc_control & OHCI_CTRL_HCFS;
@@ -2253,6 +2299,9 @@ ohci_pci_resume (struct pci_dev *dev)
        default:
                warn ("odd PCI resume for usb-%s", dev->slot_name);
        }
+
+       /* controller is operational, extra resumes are harmless */
+       atomic_dec (&ohci->resume_count);
 }
 
 #endif /* CONFIG_PM */
index e326f5ee66e984ef64119d13b4a2aee3065670fd..d286265e3ac57a9e5fc479a894916e05e5165466 100644 (file)
@@ -366,6 +366,7 @@ typedef struct ohci {
 
        int irq;
        int disabled;                   /* e.g. got a UE, we're hung */
+       atomic_t resume_count;          /* defending against multiple resumes */
 
        struct ohci_regs * regs;        /* OHCI controller's memory */
        struct list_head ohci_hcd_list; /* list of all ohci_hcd */
@@ -384,7 +385,10 @@ typedef struct ohci {
        struct usb_bus * bus;    
        struct usb_device * dev[128];
        struct virt_root_hub rh;
-       struct pci_dev *ohci_dev;
+
+       /* PCI device handle and settings */
+       struct pci_dev  *ohci_dev;
+       u8              pci_latency;
 } ohci_t;
 
 
index bd721cba20fe301ca7e9686265df82493a36b23d..14c6e649e44b1274ab54ab0d697ba4f7cf6e22ea 100644 (file)
@@ -12,7 +12,7 @@
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Randy Dunlap
  *
- * $Id: usb-uhci.c,v 1.236 2000/08/02 20:28:28 acher Exp $
+ * $Id: usb-uhci.c,v 1.237 2000/08/08 14:58:17 acher Exp $
  */
 
 #include <linux/config.h>
@@ -48,7 +48,7 @@
 /* This enables an extra UHCI slab for memory debugging */
 #define DEBUG_SLAB
 
-#define VERSTR "$Revision: 1.236 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.237 $ time " __TIME__ " " __DATE__
 
 #include <linux/usb.h>
 #include "usb-uhci.h"
@@ -888,7 +888,7 @@ _static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb)
                data += pktsze;
                len -= pktsze;
 
-               last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || (urb->transfer_flags & USB_DISABLE_SPD)));
+               last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_DISABLE_SPD)));
 
                if (last)
                        td->hw.td.status |= TD_CTRL_IOC;        // last one generates INT
index 5eb9970a294d87e6cc0e89c5732645b2645ba5fc..4ac946a3a273f45ab5c5cea03eecd30a9474b68a 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/malloc.h>
 #include <linux/init.h>
 #include <linux/fb.h>
-#include <linux/wrapper.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -1528,13 +1527,16 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
        virtual_end = PAGE_ALIGN(virtual_end);
 
        while (virtual_start < virtual_end) {
+               struct page *page;
+
                /*
                 * Clear page reserved bit,
                 * set count to 1, and free
                 * the page.
                 */
-               mem_map_unreserve(virt_to_page(virtual_start));
-               atomic_set(&virt_to_page(virtual_start)->count, 1);
+               page = virt_to_page(virtual_start);
+               ClearPageReserved(page);
+               atomic_set(&page->count, 1);
                free_page(virtual_start);
 
                virtual_start += PAGE_SIZE;
@@ -1629,7 +1631,7 @@ acornfb_init(void)
                for (page = current_par.screen_base; 
                     page < PAGE_ALIGN(current_par.screen_base + size);
                     page += PAGE_SIZE)
-                       mem_map_reserve(virt_to_page(page));
+                       SetPageReserved(virt_to_page(page));
                /* Hand back any excess pages that we allocated. */
                for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE)
                        free_page(page);
index df86a674e966f93c0b455686a5b16b4d094198b5..aa955b41c433f7a872a625c2df8d8ac07eaa779f 100644 (file)
 
 /*
  *   Code Status:
- *     4/1/99 - Driver appears to be working for Brutus 320x200x8bpp mode.  Other
- *               resolutions are working, but only the 8bpp mode is supported.
- *               Changes need to be made to the palette encode and decode routines
- *               to support 4 and 16 bpp modes.  
- *               Driver is not designed to be a module.  The FrameBuffer is statically
- *               allocated since dynamic allocation of a 300k buffer cannot be guaranteed. 
- *
- *     6/17/99 - FrameBuffer memory is now allocated at run-time when the
- *               driver is initialized.    
+ * 1999/04/01:
+ *     Driver appears to be working for Brutus 320x200x8bpp mode.  Other
+ *     resolutions are working, but only the 8bpp mode is supported.
+ *     Changes need to be made to the palette encode and decode routines
+ *     to support 4 and 16 bpp modes.  
+ *     Driver is not designed to be a module.  The FrameBuffer is statically
+ *     allocated since dynamic allocation of a 300k buffer cannot be 
+ *     guaranteed. 
+ * 
+ * 1999/06/17:
+ *     FrameBuffer memory is now allocated at run-time when the
+ *     driver is initialized.    
  *
+ * 2000/04/10:
+ *     Big cleanup for dynamic selection of machine type at run time.
+ *             Nicolas Pitre <nico@cam.org>
+ * 
+ * 2000/07/19:
+ *     Support for Bitsy aka Compaq iPAQ H3600 added.
+ *             Jamey Hicks <jamey@crl.dec.com>
+ * 
+ * 2000/08/07:
+ *     Resolved an issue caused by a change made to the Assabet's PLD 
+ *     earlier this year which broke the framebuffer driver for newer 
+ *     Phase 4 Assabets.  Some other parameters were changed to optimize for
+ *     the Sharp display.
+ *             Tak-Shing Chan <tchan.rd@idthk.com>
+ *             Jeff Sutherland <jsutherland@accelent.com>
+ * 
+ * 2000/08/09:
+ *     XP860 support added
+ *             Kunihiko IMAI <???>
  */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -41,6 +64,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 #include <asm/uaccess.h>
 #include <asm/proc/pgtable.h>
 
@@ -324,7 +348,7 @@ static int
 sa1100fb_encode_var(struct fb_var_screeninfo *var,
                     struct sa1100fb_par *par)
 {
-        // Don't know if really want to var on entry.
+        // Don't know if really want to zero var on entry.
         // Look at set_var to see.  If so, may need to add extra params to par     
 //     memset(var, 0, sizeof(struct fb_var_screeninfo));
  
@@ -347,15 +371,26 @@ sa1100fb_encode_var(struct fb_var_screeninfo *var,
                break;
        case 12:          // This case should differ for Active/Passive mode  
        case 16:
-               var->red.length    = 5;
-               var->green.length  = 6;
-               var->blue.length   = 5;
-               var->transp.length = 0;
-               var->red.offset    = 11;
-               var->green.offset  = 5;
-               var->blue.offset   = 0;
-               var->transp.offset = 0;
-               break;
+                if (machine_is_bitsy()) {
+                        var->red.length    = 4;
+                        var->blue.length   = 4;
+                        var->green.length  = 4;
+                        var->transp.length = 0;
+                        var->red.offset    = 12;
+                        var->green.offset  = 7;
+                        var->blue.offset   = 1;
+                        var->transp.offset = 0;
+                } else {
+                        var->red.length    = 5;
+                        var->blue.length   = 5;
+                        var->green.length  = 6;
+                        var->transp.length = 0;
+                        var->red.offset    = 11;
+                        var->green.offset  = 5;
+                        var->blue.offset   = 0;
+                        var->transp.offset = 0;
+                }
+                break;
        }
        return 0;
 }
@@ -425,10 +460,13 @@ sa1100fb_decode_var(struct fb_var_screeninfo *var,
 
        DPRINTK("p_palette_base = 0x%08lx\n",(u_long)par->p_palette_base);
        DPRINTK("v_palette_base = 0x%08lx\n",(u_long)par->v_palette_base);
+       DPRINTK("palette_size = 0x%08lx\n",(u_long)par->palette_size);
+       DPRINTK("palette_mem_size = 0x%08lx\n",(u_long)palette_mem_size);
        DPRINTK("p_screen_base  = 0x%08lx\n",(u_long)par->p_screen_base);
        DPRINTK("v_screen_base  = 0x%08lx\n",(u_long)par->v_screen_base);
        DPRINTK("VideoMemRegion = 0x%08lx\n",(u_long)VideoMemRegion);
        DPRINTK("VideoMemRegion_phys = 0x%08lx\n",(u_long)VideoMemRegion_phys);
+
        return 0;
 }
 
@@ -463,8 +501,6 @@ sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
        else
                display = &global_disp;     /* Default display settings */
 
-
-       DPRINTK("xres = %d, yres = %d\n",var->xres, var->yres);
        /* Decode var contents into a par structure, adjusting any */
        /* out of range values. */
        if ((err = sa1100fb_decode_var(var, &par)))
@@ -490,7 +526,6 @@ sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
                    (memcmp(&display->var.blue, &var->blue, sizeof(var->blue)))) 
                        chgvar = 1;
        }
-       DPRINTK("chgvar=%d\n", chgvar);
 
        display->var = *var;
        display->screen_base    = par.v_screen_base;
@@ -505,8 +540,6 @@ sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
        display->can_soft_blank = 1;
        display->inverse        = 0;
 
-        DPRINTK("display->var.bits_per_pixel=%d xres=%d yres=%d display->dispsw=%p\n", 
-                display->var.bits_per_pixel, var->xres, var->yres, display->dispsw);
        switch (display->var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB4
         case 4:
@@ -545,7 +578,6 @@ sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
                        cmap = &display->cmap;
                else
                        cmap = fb_default_cmap(current_par.palette_size);
-                DPRINTK("visual=%d palette_size=%d cmap=%p\n", current_par.visual, current_par.palette_size, cmap);
 
                fb_set_cmap(cmap, 1, sa1100fb_setcolreg, info);
        }
@@ -634,14 +666,18 @@ __init sa1100fb_init_fbinfo(void)
                init_var.blue.length    = 5;
                init_var.grayscale      = 0;
                init_var.sync           = 0;
+               init_var.pixclock       = 171521;
        } else if (machine_is_bitsy()) {
                current_par.max_xres    = 320;
                current_par.max_yres    = 240;
                current_par.max_bpp     = 16;
-               init_var.red.length        = 5;
-               init_var.green.length      = 6;
-               init_var.blue.length       = 5;
-               init_var.grayscale         = 0;
+               init_var.red.length     = 4;
+               init_var.green.length   = 4;
+               init_var.blue.length    = 4;
+               init_var.red.offset     = 12;
+               init_var.green.offset   = 7;
+               init_var.blue.offset    = 1;
+               init_var.grayscale      = 0;
        } else if (machine_is_brutus()) {
                current_par.max_xres    = 320;
                current_par.max_yres    = 240;
@@ -694,6 +730,23 @@ __init sa1100fb_init_fbinfo(void)
                init_var.vsync_len      = 1;
                init_var.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
                init_var.vmode          = 0;
+       } else if (machine_is_xp860()) {
+               current_par.max_xres    = 1024;
+               current_par.max_yres    = 768;
+
+               current_par.max_bpp     = 8;
+               init_var.red.length     = 4;
+               init_var.green          = init_var.red;
+               init_var.blue           = init_var.red;
+
+               init_var.hsync_len      = 4;
+               init_var.left_margin    = 3;
+               init_var.right_margin   = 2;
+
+               init_var.vsync_len      = 3;
+               init_var.upper_margin   = 2;
+               init_var.lower_margin   = 1;
+               
        }
 
        current_par.p_palette_base      = NULL;
@@ -769,7 +822,6 @@ __init sa1100fb_map_video_memory(void)
                                             L_PTE_YOUNG    |
                                             L_PTE_DIRTY    |
                                             L_PTE_WRITE);
-       memset(VideoMemRegion, 0xAA, ALLOCATED_FB_MEM_SIZE);
        return (VideoMemRegion == NULL ? -EINVAL : 0);
 }
 
@@ -804,6 +856,12 @@ static inline int get_pcd(unsigned int pixclock)
                /* the last multiplication by 1.2 is to handle */
                /* sync problems */
        }
+       if (machine_is_assabet()) {
+               pcd = frequency[PPCR & 0xf] / 1000;
+               pcd *= pixclock / 1000;
+               pcd = pcd / 1000000;
+               pcd++; /* make up for integer math truncations */
+       }
        return pcd;
 }
 
@@ -844,12 +902,12 @@ sa1100fb_activate_var(struct fb_var_screeninfo *var)
                        LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(6) + 
                        LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
                lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(2) + 
+                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + 
                        LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
                lcd_shadow.lccr3 = 
                        LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + 
                        LCCR3_HorSnchH + LCCR3_ACBsCntOff + 
-                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(38);
+                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
 
                /* Set board control register to handle new color depth */
                sa1100fb_assabet_set_truecolor(var->bits_per_pixel >= 16);
@@ -860,29 +918,33 @@ sa1100fb_activate_var(struct fb_var_screeninfo *var)
                                   LCCR0_DMADel(0);
                lcd_shadow.lccr1 = LCCR1_DisWdth( var->xres ) +
                                   LCCR1_HorSnchWdth( 4 ) +
-                                  LCCR1_BegLnDel( 0x1f ) +
-                                  LCCR1_EndLnDel( 0x1f );
-               lcd_shadow.lccr2 = LCCR2_DisHght( var->yres ) +
-                                  LCCR2_VrtSnchWdth( 1 )+
-                                  LCCR2_BegFrmDel( 0 ) +
-                                  LCCR2_EndFrmDel( 0 );
-               lcd_shadow.lccr3 = 15;
+                                  LCCR1_BegLnDel( 0xC ) +
+                                  LCCR1_EndLnDel( 0x11 );
+               lcd_shadow.lccr2 = LCCR2_DisHght( var->yres + 1 ) +
+                                  LCCR2_VrtSnchWdth( 3 )+
+                                  LCCR2_BegFrmDel( 10 ) +
+                                  LCCR2_EndFrmDel( 1 );
+               lcd_shadow.lccr3 = (/* PCD */ 0x10
+                                    | /* ACB */ 0
+                                    | /* API */ 0
+                                    | LCCR3_VrtSnchL
+                                    | LCCR3_HorSnchL);
        } else if (machine_is_brutus()) {
-               DPRINTK("Configuring  Brutus LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas + 
-                       LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + 
-                       LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(4) + 
-                       LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + 
-                       LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-               lcd_shadow.lccr3 = 
-                       LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + 
-                       LCCR3_HorSnchH + LCCR3_ACBsCntOff + 
-                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
+               DPRINTK("Configuring  Brutus LCD\n");
+               lcd_shadow.lccr0 = 
+                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas + 
+                       LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + 
+                       LCCR0_DMADel(0);
+               lcd_shadow.lccr1 = 
+                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(4) + 
+                       LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
+               lcd_shadow.lccr2 = 
+                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + 
+                       LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
+               lcd_shadow.lccr3 = 
+                       LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + 
+                       LCCR3_HorSnchH + LCCR3_ACBsCntOff + 
+                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
        } else if (machine_is_lart()) {
                DPRINTK("Configuring LART LCD\n");
                lcd_shadow.lccr0 = 
@@ -950,6 +1012,25 @@ sa1100fb_activate_var(struct fb_var_screeninfo *var)
                        ((current_var.sync & FB_SYNC_HOR_HIGH_ACT) ? LCCR3_HorSnchH : LCCR3_HorSnchL) +
                        ((current_var.sync & FB_SYNC_VERT_HIGH_ACT) ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
                */
+       } else if (machine_is_xp860()) {
+               DPRINTK("Configuring XP860 LCD\n");
+               lcd_shadow.lccr0 = 
+                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
+                       LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM +
+                       LCCR0_DMADel(0);
+               lcd_shadow.lccr1 = 
+                       LCCR1_DisWdth(var->xres) + 
+                       LCCR1_HorSnchWdth(var->hsync_len) +
+                       LCCR1_BegLnDel(var->left_margin) +
+                       LCCR1_EndLnDel(var->right_margin);
+               lcd_shadow.lccr2 = 
+                       LCCR2_DisHght(var->yres) + 
+                       LCCR2_VrtSnchWdth(var->vsync_len) +
+                       LCCR2_BegFrmDel(var->upper_margin) +
+                       LCCR2_EndFrmDel(var->lower_margin);
+               lcd_shadow.lccr3 = 
+                       LCCR3_PixClkDiv(6) +
+                       LCCR3_HorSnchL + LCCR3_VrtSnchL;
        }
 
        /* Restore interrupt status */
@@ -976,10 +1057,12 @@ sa1100fb_activate_var(struct fb_var_screeninfo *var)
 static void sa1100fb_inter_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
         if (LCSR & LCSR_LDD) {
+                int controller_state = current_par.controller_state;
                /* Disable Done Flag is set */
                LCCR0 |= LCCR0_LDM;           /* Mask LCD Disable Done Interrupt */
                current_par.controller_state = LCD_MODE_DISABLED;
-               if (current_par.controller_state == LCD_MODE_DISABLE_BEFORE_ENABLE) {
+               if (controller_state == LCD_MODE_DISABLE_BEFORE_ENABLE) {
+                       DPRINTK("sa1100fb_inter_handler: re-enabling LCD controller\n");
                        sa1100fb_enable_lcd_controller();
                }
        }
@@ -1010,7 +1093,8 @@ static void sa1100fb_disable_lcd_controller(void)
 #endif
        } else if (machine_is_bitsy()) {
 #ifdef CONFIG_SA1100_BITSY
-               clr_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON);
+                if (current_par.controller_state != LCD_MODE_DISABLE_BEFORE_ENABLE)
+                        clr_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON);
 #endif
        } else if (machine_is_penny()) {
 #ifdef CONFIG_SA1100_PENNY
@@ -1066,7 +1150,7 @@ static void sa1100fb_enable_lcd_controller(void)
 #endif
                } else if (machine_is_bitsy()) {
 #ifdef CONFIG_SA1100_BITSY
-                        set_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON)
+                  set_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON);
                        DPRINTK("DBAR1=%p\n", DBAR1);
                        DPRINTK("LCCR0=%x\n", LCCR0);
                        DPRINTK("LCCR1=%x\n", LCCR1);
@@ -1115,6 +1199,7 @@ sa1100fb_blank(int blank, struct fb_info *info)
                                  current_par.currcon, info); 
                sa1100fb_enable_lcd_controller();
        }
+       /* TODO: Bitsy support for blanking display */
 }
 
 
@@ -1164,7 +1249,7 @@ int __init sa1100fb_init(void)
                current_par.montype = 1;
 
        if (request_irq(IRQ_LCD, sa1100fb_inter_handler, SA_INTERRUPT, "SA1100 LCD", NULL) != 0) {
-               printk("sa1100fb: failed in request_irq\n");
+               printk(KERN_ERR "sa1100fb: failed in request_irq\n");
                return -EBUSY;
        }
        DPRINTK("sa1100fb: request_irq succeeded\n");
@@ -1185,6 +1270,9 @@ int __init sa1100fb_init(void)
 #endif
        } else if (machine_is_tifon()) {
                GPDR |= GPIO_GPIO(24);  /* set GPIO24 to output */
+       } else if (machine_is_xp860()) {
+               GPDR |= 0x3fc;
+               GAFR |= 0x3fc;
        }
 
        if (sa1100fb_set_var(&init_var, -1, &fb_info))
index b296dad7b1fd74ec316ad01bbf6a4d74f37c3d42..8c731615669a56f2fe446191fbb67ae2e9523ac0 100644 (file)
@@ -1781,15 +1781,12 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
  * for them to complete.  Clean up the buffer_heads afterwards.  
  */
 
-static int do_kio(int rw, int nr, struct buffer_head *bh[], int size)
+static int wait_kio(int rw, int nr, struct buffer_head *bh[], int size)
 {
        int iosize;
        int i;
        struct buffer_head *tmp;
 
-       if (rw == WRITE)
-               rw = WRITERAW;
-       ll_rw_block(rw, nr, bh);
 
        iosize = 0;
        spin_lock(&unused_list_lock);
@@ -1905,12 +1902,13 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
                                offset += size;
 
                                atomic_inc(&iobuf->io_count);
-       
+
+                               generic_make_request(rw, tmp);
                                /* 
-                                * Start the IO if we have got too much 
+                                * Wait for IO if we have got too much 
                                 */
                                if (bhind >= KIO_MAX_SECTORS) {
-                                       err = do_kio(rw, bhind, bh, size);
+                                       err = wait_kio(rw, bhind, bh, size);
                                        if (err >= 0)
                                                transferred += err;
                                        else
@@ -1928,7 +1926,7 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
 
        /* Is there any IO still left to submit? */
        if (bhind) {
-               err = do_kio(rw, bhind, bh, size);
+               err = wait_kio(rw, bhind, bh, size);
                if (err >= 0)
                        transferred += err;
                else
index 5f436f1e0c4d432304e06571847a6f3ad3da22ef..c0df3a68b6d3cfacee1dc62f7ba606091dfdf248 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -436,7 +436,7 @@ static inline int make_private_signals(void)
 
        if (atomic_read(&current->sig->count) <= 1)
                return 0;
-       newsig = kmalloc(sizeof(*newsig), GFP_KERNEL);
+       newsig = kmem_cache_alloc(sigact_cachep, GFP_KERNEL);
        if (newsig == NULL)
                return -ENOMEM;
        spin_lock_init(&newsig->siglock);
@@ -460,7 +460,7 @@ static inline void release_old_signals(struct signal_struct * oldsig)
        if (current->sig == oldsig)
                return;
        if (atomic_dec_and_test(&oldsig->count))
-               kfree(oldsig);
+               kmem_cache_free(sigact_cachep, oldsig);
 }
 
 /*
@@ -470,13 +470,13 @@ static inline void release_old_signals(struct signal_struct * oldsig)
 
 static inline void flush_old_files(struct files_struct * files)
 {
-       unsigned long j;
+       long j = -1;
 
-       j = 0;
        write_lock(&files->file_lock);
        for (;;) {
                unsigned long set, i;
 
+               j++;
                i = j * __NFDBITS;
                if (i >= files->max_fds || i >= files->max_fdset)
                        break;
@@ -484,7 +484,6 @@ static inline void flush_old_files(struct files_struct * files)
                if (!set)
                        continue;
                files->close_on_exec->fds_bits[j] = 0;
-               j++;
                write_unlock(&files->file_lock);
                for ( ; set ; i++,set >>= 1) {
                        if (set & 1) {
index 233a18fb31a0aa87d2d1fcb0e181317b3a2474f7..5f7a643d7bad583e9d51e81d9eb02cd007f464f9 100644 (file)
@@ -510,7 +510,8 @@ static int vfat_ioctl_fill(
        const char * name,
        int name_len,
        off_t offset,
-       ino_t ino)
+       ino_t ino,
+       unsigned int d_type)
 {
        struct dirent *d1 = (struct dirent *)buf;
        struct dirent *d2 = d1 + 1;
index f13f2fa7e6de0d782d22aea98dfa6787a62fe206..4d342db5fdf9e0647c73328d782b0a06be224bff 100644 (file)
@@ -187,7 +187,9 @@ struct code_page_directory
                                           in data block */
     secno code_page_data;              /* sector number of a code_page_data
                                           containing c.p. array */
-    unsigned index;                    /* index in c.p. array in that sector*/
+    unsigned short index;              /* index in c.p. array in that sector*/
+    unsigned short unknown;            /* some unknown value; usually 0;
+                                          2 in Japanese version */
   } array[31];                         /* unknown length */
 };
 
@@ -207,7 +209,7 @@ struct code_page_data
   struct {
     unsigned short ix;                 /* index */
     unsigned short code_page_number;   /* code page number */
-    unsigned short zero1;
+    unsigned short unknown;            /* the same as in cp directory */
     unsigned char map[128];            /* upcase table for chars 80..ff */
     unsigned short zero2;
   } code_page[3];
index a0e0feada348799b4ddd0face6318610304c8051..290844b4da06ba9ba0f59fbcf8f630cdb94b76cf 100644 (file)
@@ -59,6 +59,11 @@ char *hpfs_load_code_page(struct super_block *s, secno cps)
        cpds = cp->array[0].code_page_data;
        cpi = cp->array[0].index;
        brelse(bh);
+
+       if (cpi >= 3) {
+               printk("HPFS: Code page index out of array\n");
+               return NULL;
+       }
        
        if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL;
        if ((unsigned)cpd->offs[cpi] > 0x178) {
index f78a7b2954f8a380b2159410e23f21fccf53fb2e..91463a42b66df9c2b19a26974dadc263df39064d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ARM_A_OUT_H__
 #define __ARM_A_OUT_H__
 
-#include <linux/types.h>
+#include <asm/types.h>
 
 struct exec
 {
index 8d734d2bbe971175beac835b43432e41c4bec208..789f4cf6f399c8a499deb3ca8f62648494892e00 100644 (file)
@@ -82,7 +82,7 @@
  * RAM definitions
  */
 #define GET_MEMORY_END(p)      (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages))
-#define PARAMS_BASE            (PAGE_OFFSET + 0x7c000)
+#define PARAMS_OFFSET          0x7c000
 
 #else
 
index c24213b20be43e9af65c901f6061af78bb5af2c4..3a7c9a968bed7a05b452e671ecd32c4525c51a95 100644 (file)
@@ -12,6 +12,7 @@
  *  29-07-1998 RMK     Major re-work of IDE architecture specific code
  */
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
index 97b3c499e5802fc5919555e60a82c9210c800515..7a922e991ad414765376dfba4002a2a4390109a4 100644 (file)
  */
 #include <asm/ioc.h>
 
+#ifdef CONFIG_ARCH_ARC
+#define a_clf()        clf()
+#define a_stf()        stf()
+#else
+#define a_clf()        do { } while (0)
+#define a_stf()        do { } while (0)
+#endif
+
 #define fixup_irq(x) (x)
 
 static void arc_mask_irq_ack_a(unsigned int irq)
 {
        unsigned int temp;
 
+       a_clf();
        __asm__ __volatile__(
        "ldrb   %0, [%2]\n"
 "      bic     %0, %0, %1\n"
@@ -26,30 +35,35 @@ static void arc_mask_irq_ack_a(unsigned int irq)
        : "=&r" (temp)
        : "r" (1 << (irq & 7)), "r" (ioaddr(IOC_IRQMASKA)),
          "r" (ioaddr(IOC_IRQCLRA)));
+       a_stf();
 }
 
 static void arc_mask_irq_a(unsigned int irq)
 {
        unsigned int temp;
 
+       a_clf();
        __asm__ __volatile__(
        "ldrb   %0, [%2]\n"
 "      bic     %0, %0, %1\n"
 "      strb    %0, [%2]"
        : "=&r" (temp)
        : "r" (1 << (irq & 7)), "r" (ioaddr(IOC_IRQMASKA)));
+       a_stf();
 }
 
 static void arc_unmask_irq_a(unsigned int irq)
 {
        unsigned int temp;
 
+       a_clf();
        __asm__ __volatile__(
        "ldrb   %0, [%2]\n"
 "      orr     %0, %0, %1\n"
 "      strb    %0, [%2]"
        : "=&r" (temp)
        : "r" (1 << (irq & 7)), "r" (ioaddr(IOC_IRQMASKA)));
+       a_stf();
 }
 
 static void arc_mask_irq_b(unsigned int irq)
index 578f6f70b693c33a9fd78e0e2a3816f1a5ec03e4..d80ddd13f5ad7209780e784a470cfa01eb9d004b 100644 (file)
@@ -5,21 +5,6 @@
  */
 #include <linux/config.h>
 
-#ifdef CONFIG_ARCH_ARC
-
-#define cliIF()                                \
-       do {                            \
-         unsigned long temp;           \
-         __asm__ __volatile__(         \
-"      mov     %0, pc\n"               \
-"      orr %0, %0, #0x0c000000\n"      \
-"      teqp    %0, #0\n"               \
-         : "=r" (temp) \
-    : );       \
-  } while(0)
-
-#endif
-
 static void arch_idle(void)
 {
        while (!current->need_resched && !hlt_counter);
index 7bab998b971b818b27fcd67275f6c85f4a4b2860..1d6a8829d3271ca2954fdc0398f20423c2a8de94 100644 (file)
@@ -7,13 +7,15 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
+/* DMA is not yet implemented! It should be the same as acorn, copy over.. */
+
 /*
  * This is the maximum DMA address that can be DMAd to.
  * There should not be more than (0xd0000000 - 0xc0000000)
  * bytes of RAM.
  */
 #define MAX_DMA_ADDRESS                0xd0000000
-#define MAX_DMA_CHANNELS       1
+#define MAX_DMA_CHANNELS       0
 
 #define DMA_S0                 0
 
index 76978f79bfef24ad99d6422d67d89b39065aac2d..938389b203a3cd08d92317ad48cd62d9039011c3 100644 (file)
@@ -67,6 +67,8 @@
 #define IOEB_BASE              ((volatile unsigned char *)0xe0350050)
 #define PCIO_FLOPPYDMABASE     ((volatile unsigned char *)0xe002a000)
 #define PCIO_BASE              0xe0010000
+/* in/out bias for the ISA slot region */
+#define ISASLOT_IO             0x80400000
 
 /*
  * RAM definitions
@@ -77,8 +79,6 @@
                                                 p->u1.s.pages_in_bank[2] + \
                                                 p->u1.s.pages_in_bank[3]))
 
-#define PARAMS_BASE            0
-
 #define FLUSH_BASE_PHYS                0x00000000      /* ROM */
 
 #else
index 53daa0969571af90e3d551e85b4c6f22dba49089..d928d8596e1471ee875cd5c83f931bc6180b0ed6 100644 (file)
@@ -7,6 +7,7 @@
  *  29-07-1998 RMK     Major re-work of IDE architecture specific code
  */
 #include <asm/irq.h>
+#include <asm/arch/hardware.h>
 
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
@@ -15,7 +16,7 @@
 static __inline__ void
 ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
-       ide_ioreg_t reg = (ide_ioreg_t) data_port;
+       ide_ioreg_t reg = data_port;
        int i;
 
        memset(hw, 0, sizeof(*hw));
@@ -24,9 +25,14 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
                hw->io_ports[i] = reg;
                reg += 1;
        }
-       hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       if (irq)
+       if (ctrl_port) {
+               hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+       } else {
+               hw->io_ports[IDE_CONTROL_OFFSET] = data_port + 0x206;
+       }
+       if (irq != NULL)
                *irq = 0;
+       hw->io_ports[IDE_IRQ_OFFSET] = 0;
 }
 
 /*
@@ -36,4 +42,9 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 static __inline__ void
 ide_init_default_hwifs(void)
 {
+       hw_regs_t hw;
+   
+       ide_init_hwif_ports(&hw, ISASLOT_IO + 0x1f0, ISASLOT_IO + 0x3f6, NULL);
+       hw.irq = IRQ_ISA_14;
+       ide_register_hw(&hw, NULL);
 }
index 256b2a34ec06c3ccb30a1253ce4cda37e9d53588..4611f7975f46648ee8fd6e836451eee0c0e84f99 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __ASM_ARCH_SERIAL_H
 #define __ASM_ARCH_SERIAL_H
 
+#include <asm/arch/hardware.h>
+
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
      /* UART CLK        PORT  IRQ     FLAGS        */
 #define STD_SERIAL_PORT_DEFNS \
        { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS },     /* ttyS0 */     \
-       { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS },     /* ttyS1 */     \
-       { 0, BASE_BAUD, 0x804002e8,  41, STD_COM_FLAGS },       /* ttyS2 */     \
-       { 0, BASE_BAUD, 0x804003e8,  40, STD_COM_FLAGS },       /* ttyS3 */     \
+       { 0, BASE_BAUD, 0x2F8,  0, STD_COM_FLAGS },     /* ttyS1 */     \
+        /* ISA Slot Serial ports */ \
+       { 0, BASE_BAUD, ISASLOT_IO + 0x2e8,  41, STD_COM_FLAGS },       /* ttyS2 */     \
+       { 0, BASE_BAUD, ISASLOT_IO + 0x3e8,  40, STD_COM_FLAGS },       /* ttyS3 */     \
        { 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },     /* ttyS4 */     \
        { 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },     /* ttyS5 */     \
        { 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },     /* ttyS6 */     \
index e2c9276050627b5914b9a5d4916e66e11f8222ed..7851607fc2e689b790aabd9b45f4c86c85e2f56d 100644 (file)
@@ -8,7 +8,6 @@
  *  10-Oct-1996        RMK     Brought up to date with arch-sa110eval
  *  04-Dec-1997        RMK     Updated for new arch/arm/time.c
  */
-extern void ioctime_init(void);
 
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -33,8 +32,6 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  */
 extern __inline__ void setup_timer(void)
 {
-       ioctime_init();
-
        timer_irq.handler = timer_interrupt;
 
        setup_arm_irq(IRQ_TIMER, &timer_irq);
index 0585c831892c2357ae81de1673d540ebb6322b17..12ffdc98de289f81163520f2fcf5cefe1e6b6d84 100644 (file)
@@ -5,11 +5,12 @@
  */
 
 #define BASE 0x03010000
+#define SERBASE (BASE + (0x3f8 << 2))
 
 static __inline__ void putc(char c)
 {
-       while (!(*((volatile unsigned int *)(BASE + 0xbf4)) & 0x20));
-       *((volatile unsigned int *)(BASE + 0xbe0)) = c;
+       while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20));
+       *((volatile unsigned int *)(SERBASE)) = c;
 }
 
 /*
@@ -27,13 +28,13 @@ static void puts(const char *s)
 
 static __inline__ void arch_decomp_setup(void)
 {
-       int baud = 3686400 / (9600 * 16);
+       int baud = 3686400 / (9600 * 32);
 
-       *((volatile unsigned int *)(BASE + 0xBEC)) = 0x80;
-       *((volatile unsigned int *)(BASE + 0xBE0)) = baud & 0xff;
-       *((volatile unsigned int *)(BASE + 0xBE4)) = (baud & 0xff00) >> 8;
-       *((volatile unsigned int *)(BASE + 0xBEC)) = 3; /* 8 bits */
-       *((volatile unsigned int *)(BASE + 0xBF0)) = 3; /* DTR, RTS */
+       *((volatile unsigned int *)(SERBASE + 0xC)) = 0x80;
+       *((volatile unsigned int *)(SERBASE + 0x0)) = baud & 0xff;
+       *((volatile unsigned int *)(SERBASE + 0x4)) = (baud & 0xff00) >> 8;
+       *((volatile unsigned int *)(SERBASE + 0xC)) = 3; /* 8 bits */
+       *((volatile unsigned int *)(SERBASE + 0x10)) = 3; /* DTR, RTS */
 }
 
 /*
index 08723718cb116b574765dbd647a555975452be17..18ee0f968107dcd3917bce3d1726cda4a972fc66 100644 (file)
@@ -42,7 +42,7 @@
 
 #define UNCACHEABLE_ADDR       0xf3000000
 
-#define PARAMS_BASE            (PAGE_OFFSET + 0x400)
+#define PARAMS_OFFSET          0x400
 
 #endif
 
index 142a2ddbc9d708acd647f8f1dc2e5200418651cf..ae5817d9e499e4f28a730ad5535ba7f06e416004 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/config.h>
 #include <asm/arch/memory.h>
 
-#ifdef CONFIG_FOOTBRIDGE_HOST
+#ifdef CONFIG_ARCH_FOOTBRIDGE
 /*   Virtual      Physical     Size
  * 0xff800000  0x40000000      1MB     X-Bus
  * 0xff000000  0x7c000000      1MB     PCI I/O space
@@ -61,7 +61,9 @@
 #define PCIMEM_BASE            0xf0000000
 
 #elif defined(CONFIG_ARCH_CO285)
-
+/*
+ * This is the COEBSA285 cut-down mapping
+ */
 #define PCIMEM_SIZE            0x80000000
 #define PCIMEM_BASE            0x80000000
 
@@ -85,7 +87,7 @@
 
 #else
 
-#error Add your add-in architecture here
+#error "Undefined footbridge architecture"
 
 #endif
 
 #define XBUS_SWITCH_J17_9      ((*XBUS_SWITCH) & (1 << 6))
 
 #define PARAMS_OFFSET          0x0100
-#define PARAMS_BASE            (PAGE_OFFSET + PARAMS_OFFSET)
 
 #define FLUSH_BASE_PHYS                0x50000000
 #define UNCACHEABLE_ADDR       (ARMCSR_BASE + 0x108)
index b6f2639b563e3580f1dd445df545fcab7e80683a..791c00fae9e74988c668f46c36cbf3276174c81e 100644 (file)
 #include <asm/hardware.h>
 #include <asm/dec21285.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 
 /*
  * Footbridge IRQ translation table
  *  Converts from our IRQ numbers into FootBridge masks
  */
-static int dc21285_irq_mask[] = {
+static const int dc21285_irq_mask[] = {
        IRQ_MASK_UART_RX,       /*  0 */
        IRQ_MASK_UART_TX,       /*  1 */
        IRQ_MASK_TIMER1,        /*  2 */
@@ -45,8 +46,10 @@ static int isa_irq = -1;
 
 static inline int fixup_irq(unsigned int irq)
 {
+#ifdef PCIIACK_BASE
        if (irq == isa_irq)
                irq = *(unsigned char *)PCIIACK_BASE;
+#endif
 
        return irq;
 }
index 9ad99a4589a0c13e1c5b13ad9b72cb32a5f89f21..6a60fae42cdf28118bae38c4b70a43d76fb33622 100644 (file)
@@ -8,6 +8,7 @@
  *  20-Jan-1998        RMK     Started merge of EBSA286, CATS and NetWinder
  *  01-Feb-1999        PJB     ISA IRQs start at 0 not 16
  */
+#include <asm/mach-types.h>
 
 #define NR_IRQS                        36
 #define NR_DC21285_IRQS                16
index 691514e6b5fffc031f17be0d9223452e2b0bccab..f3c05b072fe35623efb5c6ba9930b8eff213f5df 100644 (file)
@@ -6,11 +6,10 @@
  * (C) 1998 Russell King
  * (C) 1998 Phil Blundell
  */
+#include <linux/ioport.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 
-extern int have_isa_bridge;
-
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
@@ -71,7 +70,7 @@ extern unsigned char pckbd_sysrq_xlate[128];
 #define SYSRQ_KEY      0x54
 
 /* resource allocation */
-#define kbd_request_region()
+#define kbd_request_region()   request_region(0x60, 16, "keyboard")
 #define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
                                             "keyboard", NULL)
 
index 18d7dacb00f075ebb7e7c9d71c89bb89bda83bf6..d9859cb76b5cacbed74cae86b43dc628bbd6a1d0 100644 (file)
 
 #include <linux/config.h>
 
-#if defined(CONFIG_FOOTBRIDGE_HOST)
-
+#if defined(CONFIG_FOOTBRIDGE_ADDIN)
 /*
- * Task size: 3GB
+ * If we may be using add-in footbridge mode, then we must
+ * use the out-of-line translation that makes use of the
+ * PCI BAR
  */
-#define TASK_SIZE              (0xc0000000UL)
-#define TASK_SIZE_26           (0x04000000UL)
+#ifndef __ASSEMBLY__
+extern unsigned long __virt_to_bus(unsigned long);
+extern unsigned long __bus_to_virt(unsigned long);
+#endif
 
-/*
- * Page offset: 3GB
- */
-#define PAGE_OFFSET            (0xc0000000UL)
-#define PHYS_OFFSET            (0x00000000UL)
+#elif defined(CONFIG_FOOTBRIDGE_HOST)
 
 #define __virt_to_bus__is_a_macro
 #define __virt_to_bus(x)       ((x) - 0xe0000000)
 #define __bus_to_virt__is_a_macro
 #define __bus_to_virt(x)       ((x) + 0xe0000000)
 
-#elif defined(CONFIG_FOOTBRIDGE_ADDIN)
+#else
 
-#if defined(CONFIG_ARCH_CO285)
+#error "Undefined footbridge mode"
 
-/*
- * Task size: 1.5GB
- */
-#define TASK_SIZE              (0x60000000UL)
-#define TASK_SIZE_26           (0x04000000UL)
+#endif
 
-/*
- * Page offset: 1.5GB
- */
+#if defined(CONFIG_ARCH_FOOTBRIDGE)
+
+/* Task size and page offset at 3GB */
+#define TASK_SIZE              (0xc0000000UL)
+#define PAGE_OFFSET            (0xc0000000UL)
+
+#elif defined(CONFIG_ARCH_CO285)
+
+/* Task size and page offset at 1.5GB */
+#define TASK_SIZE              (0x60000000UL)
 #define PAGE_OFFSET            (0x60000000UL)
-#define PHYS_OFFSET            (0x00000000UL)
 
 #else
 
-#error Add in your architecture here
+#error "Undefined footbridge architecture"
 
 #endif
 
-#ifndef __ASSEMBLY__
-extern unsigned long __virt_to_bus(unsigned long);
-extern unsigned long __bus_to_virt(unsigned long);
-#endif
-
-#endif
+#define TASK_SIZE_26           (0x04000000UL)
+#define PHYS_OFFSET            (0x00000000UL)
 
 /*
- * On Footbridge machines, the dram is contiguous.
- * On Host Footbridge, these conversions are constant.
- * On an add-in footbridge, these depend on register settings.
+ * The DRAM is always contiguous.
  */
 #define __virt_to_phys__is_a_macro
 #define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
index 4704e3de3c704be3b613896880fe1ca318d89bfc..dbbaf94442f373f42632f95ec7e9dfba4d54e51d 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/leds.h>
+#include <asm/mach-types.h>
 
 static void arch_idle(void)
 {
index cc28f3449217306e4a67d492e7b166942df66f18..2ae77bcb1dc1f41909a1a575f07b974f69fcbda8 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <asm/dec21285.h>
 #include <asm/leds.h>
-#include <asm/system.h>
+#include <asm/mach-types.h>
 
 static int rtc_base;
 
index d800cbc8d094ea95555d0e0cec9dbf9491692709..a9209af7b455c690ee5c6641d1ce2d2046522b0f 100644 (file)
@@ -41,7 +41,7 @@
 #define FLUSH_BASE_PHYS                0x40000000      /* ROM */
 #define FLUSH_BASE             0xdf000000
 
-#define PARAMS_BASE            (PAGE_OFFSET + 0x0100)
+#define PARAMS_OFFSET          (0x0100)
 #define Z_PARAMS_BASE          (RAM_START + PARAMS_OFFSET)
 
 #define PCIO_BASE              IO_BASE
index aff8aaf9cf989fbfbef0b0ad5e4ca9af378d4d84..61cec831ae285bb788bf4c46bbc75dbe0cca3c1b 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 2000 Steve Hill (sjhill@cotw.com)
  *
  * Changelog:
- *  29-03-2000 SJH     Created file placeholder
+ *  03-29-2000 SJH     Created file placeholder
  */
 #include <asm/irq.h>
 
index 787b621089f1641116b7c6e502cd0f375a8097a3..720282bbe78aa4377dfc88a279b181a09c438d37 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * linux/include/asm-arm/arch-l7200/io.h
  *
- * Copyright (C) 2000 Steven Hill (sjhill@cotw.com)
+ * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
  *
  * Modifications:
- *  21-03-2000 SJH     Created from linux/include/asm-arm/arch-nexuspci/io.h
+ *  03-21-2000 SJH     Created from linux/include/asm-arm/arch-nexuspci/io.h
  */
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
 #define IO_SPACE_LIMIT 0xffffffff
 
-/*
- * We use two different types of addressing - PC style addresses, and ARM
- * addresses.  PC style accesses the PC hardware with the normal PC IO
- * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
- * and are translated to the start of IO.  Note that all addresses are
- * shifted left!
- */
-#define __PORT_PCIO(x) (!((x) & 0x80000000))
-
-/*
- * Dynamic IO functions.
- */
-
-extern __inline__ void __outb (unsigned int value, unsigned int port)
-{
-       unsigned long temp;
-       __asm__ __volatile__(
-       "tst    %2, #0x80000000\n\t"
-       "mov    %0, %4\n\t"
-       "addeq  %0, %0, %3\n\t"
-       "strb   %1, [%0, %2, lsl #2]    @ outb"
-       : "=&r" (temp)
-       : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-       : "cc");
-}
-
-extern __inline__ void __outw (unsigned int value, unsigned int port)
-{
-       unsigned long temp;
-       __asm__ __volatile__(
-       "tst    %2, #0x80000000\n\t"
-       "mov    %0, %4\n\t"
-       "addeq  %0, %0, %3\n\t"
-       "str    %1, [%0, %2, lsl #2]    @ outw"
-       : "=&r" (temp)
-       : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-       : "cc");
-}
-
-extern __inline__ void __outl (unsigned int value, unsigned int port)
-{
-       unsigned long temp;
-       __asm__ __volatile__(
-       "tst    %2, #0x80000000\n\t"
-       "mov    %0, %4\n\t"
-       "addeq  %0, %0, %3\n\t"
-       "str    %1, [%0, %2, lsl #2]    @ outl"
-       : "=&r" (temp)
-       : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
-       : "cc");
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr)                                      \
-extern __inline__ unsigned sz __in##fnsuffix (unsigned int port)               \
-{                                                                              \
-       unsigned long temp, value;                                              \
-       __asm__ __volatile__(                                                   \
-       "tst    %2, #0x80000000\n\t"                                            \
-       "mov    %0, %4\n\t"                                                     \
-       "addeq  %0, %0, %3\n\t"                                                 \
-       "ldr" ##instr## "       %1, [%0, %2, lsl #2]    @ in"###fnsuffix        \
-       : "=&r" (temp), "=r" (value)                                            \
-       : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)                \
-       : "cc");                                                                \
-       return (unsigned sz)value;                                              \
-}
-
-extern __inline__ unsigned int __ioaddr (unsigned int port)                    \
-{                                                                              \
-       if (__PORT_PCIO(port))                                                  \
-               return (unsigned int)(PCIO_BASE + (port << 2));                 \
-       else                                                                    \
-               return (unsigned int)(IO_BASE + (port << 2));                   \
-}
-
-#define DECLARE_IO(sz,fnsuffix,instr)  \
-       DECLARE_DYN_IN(sz,fnsuffix,instr)
-
-DECLARE_IO(char,b,"b")
-DECLARE_IO(short,w,"")
-DECLARE_IO(int,l,"")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_IN
-
-/*
- * Constant address IO functions
- *
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
- */
-#define __outbc(value,port)                                                    \
-({                                                                             \
-       if (__PORT_PCIO((port)))                                                \
-               __asm__ __volatile__(                                           \
-               "strb   %0, [%1, %2]    @ outbc"                                \
-               : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));          \
-       else                                                                    \
-               __asm__ __volatile__(                                           \
-               "strb   %0, [%1, %2]    @ outbc"                                \
-               : : "r" (value), "r" (IO_BASE), "r" ((port) << 2));             \
-})
-
-#define __inbc(port)                                                           \
-({                                                                             \
-       unsigned char result;                                                   \
-       if (__PORT_PCIO((port)))                                                \
-               __asm__ __volatile__(                                           \
-               "ldrb   %0, [%1, %2]    @ inbc"                                 \
-               : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));         \
-       else                                                                    \
-               __asm__ __volatile__(                                           \
-               "ldrb   %0, [%1, %2]    @ inbc"                                 \
-               : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));            \
-       result;                                                                 \
-})
-
-#define __outwc(value,port)                                                    \
-({                                                                             \
-       unsigned long v = value;                                                \
-       if (__PORT_PCIO((port)))                                                \
-               __asm__ __volatile__(                                           \
-               "str    %0, [%1, %2]    @ outwc"                                \
-               : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));        \
-       else                                                                    \
-               __asm__ __volatile__(                                           \
-               "str    %0, [%1, %2]    @ outwc"                                \
-               : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));           \
-})
-
-#define __inwc(port)                                                           \
-({                                                                             \
-       unsigned short result;                                                  \
-       if (__PORT_PCIO((port)))                                                \
-               __asm__ __volatile__(                                           \
-               "ldr    %0, [%1, %2]    @ inwc"                                 \
-               : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));         \
-       else                                                                    \
-               __asm__ __volatile__(                                           \
-               "ldr    %0, [%1, %2]    @ inwc"                                 \
-               : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));            \
-       result & 0xffff;                                                        \
-})
-
-#define __outlc(value,port)                                                    \
-({                                                                             \
-       unsigned long v = value;                                                \
-       if (__PORT_PCIO((port)))                                                \
-               __asm__ __volatile__(                                           \
-               "str    %0, [%1, %2]    @ outlc"                                \
-               : : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));              \
-       else                                                                    \
-               __asm__ __volatile__(                                           \
-               "str    %0, [%1, %2]    @ outlc"                                \
-               : : "r" (v), "r" (IO_BASE), "r" ((port) << 2));                 \
-})
-
-#define __inlc(port)                                                           \
-({                                                                             \
-       unsigned long result;                                                   \
-       if (__PORT_PCIO((port)))                                                \
-               __asm__ __volatile__(                                           \
-               "ldr    %0, [%1, %2]    @ inlc"                                 \
-               : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));         \
-       else                                                                    \
-               __asm__ __volatile__(                                           \
-               "ldr    %0, [%1, %2]    @ inlc"                                 \
-               : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));            \
-       result;                                                                 \
-})
-
-#define __ioaddrc(port)                                                                \
-       (__PORT_PCIO((port)) ? PCIO_BASE + ((port) << 2) : IO_BASE + ((port) << 2))
-
-#define inb(p)         (__builtin_constant_p((p)) ? __inbc(p)    : __inb(p))
-#define inw(p)         (__builtin_constant_p((p)) ? __inwc(p)    : __inw(p))
-#define inl(p)         (__builtin_constant_p((p)) ? __inlc(p)    : __inl(p))
-#define outb(v,p)      (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
-#define outw(v,p)      (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
-#define outl(v,p)      (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
-#define __ioaddr(p)    (__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-
 /*
  * Translated address IO functions
  *
@@ -207,4 +25,18 @@ DECLARE_IO(int,l,"")
 #define outl_t(v,p)    (*(volatile unsigned long *)(p) = (v))
 #define inl_t(p)       (*(volatile unsigned long *)(p))
 
+/*
+ * FIXME - These are to allow for linking. On all the other
+ *         ARM platforms, the entire IO space is contiguous.
+ *         The 7200 has three separate IO spaces. The below
+ *         macros will eventually become more involved. Use
+ *         with caution and don't be surprised by kernel oopses!!!
+ */
+#define inb(p)         inb_t(p)
+#define inw(p)         inw_t(p)
+#define inl(p)         inl_t(p)
+#define outb(v,p)      outb_t(v,p)
+#define outw(v,p)      outw_t(v,p)
+#define outl(v,p)      outl_t(v,p)
+
 #endif
index f2aaabd5c56bc59b224cdef27cfb351ec3c22fb6..d07a1ddc1a49db9004cd3e1579d4b70f8acc3985 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/arch-l7200/memory.h
  *
- * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
+ * Copyright (c) 2000 Steve Hill (sjhill@cotw.com)
  * Copyright (c) 2000 Rob Scott (rscott@mtrob.fdns.net)
  *
  * Changelog:
@@ -9,8 +9,8 @@
  *  04-13-2000  RS      Changed bus macros for new addr
  *  05-03-2000  SJH     Removed bus macros and fixed virt_to_phys macro
  */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
 
 /*
  * Task size: 3GB
index c299629dd8c6d137ece4294a8537424ed51f37f6..0f5ecbab04e434323e427457f7eb3f2967647954 100644 (file)
@@ -1,21 +1,22 @@
 /*
  * linux/include/asm-arm/arch-l7200/system.h
  *
- * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
+ * Copyright (c) 2000 Steve Hill (sjhill@cotw.com)
  *
  * Changelog
  *  03-21-2000  SJH    Created
  *  04-26-2000  SJH    Fixed functions
  *  05-03-2000  SJH    Removed usage of obsolete 'iomd.h'
+ *  05-31-2000  SJH    Properly implemented 'arch_idle'
  */
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
 static void arch_idle(void)
 {
-        while (!current->need_resched && !hlt_counter)
-               { };
-/*                outb(0, IOMD_SUSMODE);*/
+        while (!current->need_resched && !hlt_counter) {
+               cpu_do_idle(IDLE_WAIT_SLOW);
+       }
 }
 
 extern inline void arch_reset(char mode)
index 077735e218ddbfe2a575b215022415e6afa29a18..1d4ef492b07115c3bd0759a474f966fd9dc24372 100644 (file)
@@ -54,8 +54,6 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  */
 extern __inline__ void setup_timer(void)
 {
-       xtime.tv_sec = RTC_RTCDR;
-
        RTC_RTCC = 0;                           /* Clear interrupt */
 
        timer_irq.handler = timer_interrupt;
index d2e56455b8697d29b9ee6f8347a927ab0402ad54..d7ac5f65e599b0062f2f53d6b1865b381d0e5495 100644 (file)
@@ -2,18 +2,43 @@
  * linux/include/asm-arm/arch-l7200/uncompress.h
  *
  * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *  05-01-2000 SJH     Created
+ *  05-13-2000 SJH     Filled in function bodies
+ *  07-26-2000 SJH     Removed hard coded buad rate
  */
 
+#include <asm/hardware.h>
+
+#define IO_UART  IO_START + 0x00044000
+
+#define __raw_writeb(v,p)      (*(volatile unsigned char *)(p) = (v))
+#define __raw_readb(p)         (*(volatile unsigned char *)(p))
+
 static __inline__ void putc(char c)
 {
+       while(__raw_readb(IO_UART + 0x18) & 0x20 ||
+               __raw_readb(IO_UART + 0x18) & 0x08);
+       __raw_writeb(c, IO_UART + 0x00);
 }
 
 static void puts(const char *s)
 {
+       while (*s) {
+               if (*s == 10) {                 /* If a LF, add CR */
+                       putc(10);
+                       putc(13);
+               }
+               putc(*(s++));
+       }
 }
 
 static __inline__ void arch_decomp_setup(void)
 {
+       __raw_writeb(0x00, IO_UART + 0x08);     /* Set HSB */
+       __raw_writeb(0x00, IO_UART + 0x20);     /* Disable IRQs */
+       __raw_writeb(0x01, IO_UART + 0x14);     /* Enable UART */
 }
 
 #define arch_decomp_wdog()
index ab71831400b38e130a919d6e150725d85f700fb8..ce1a27b1338426dbe310d12ef97a565f130240bf 100644 (file)
@@ -78,7 +78,6 @@
                                                 p->u1.s.pages_in_bank[2] + \
                                                 p->u1.s.pages_in_bank[3]))
 
-#define PARAMS_BASE            (PAGE_OFFSET + PARAMS_OFFSET)
 #define Z_PARAMS_BASE          (RAM_START + PARAMS_OFFSET)
 #define FLUSH_BASE_PHYS                0x00000000      /* ROM */
 
diff --git a/include/asm-arm/arch-sa1100/cerf.h b/include/asm-arm/arch-sa1100/cerf.h
new file mode 100644 (file)
index 0000000..95d58a1
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _INCLUDE_CERF_H_
+#define _INCLUDE_CERF_H_
+
+/* GPIOs for CF+ slot lines */
+#define GPIO_CF_IRQ            GPIO_GPIO (22)  /* 1111 MBGNT _OR_ CF IRQ   */
+#define GPIO_CF_CD             GPIO_GPIO (23)  /* 1111 MBREQ _OR_ CF CD    */
+#define GPIO_CF_BVD2           GPIO_GPIO (19)  /* Graphics IRQ _OR_ CF BVD */
+#define GPIO_CF_BVD1           GPIO_GPIO (20)  /* 1111 IRQ _OR_ CF BVD     */
+
+#define IRQ_GPIO_CF_IRQ                IRQ_GPIO22
+#define IRQ_GPIO_CF_CD         IRQ_GPIO23
+#define IRQ_GPIO_CF_BVD2       IRQ_GPIO19
+#define IRQ_GPIO_CF_BVD1       IRQ_GPIO20
+
+#endif
+
index 8f9a1315296e2f7041b3d9ede466ba0ffab46c45..a4a1b58844a7f19afe7e3fd01d07007e263d6fcf 100644 (file)
@@ -77,6 +77,10 @@ extern void set_GPIO_IRQ_edge( int gpio_mask, int edge_mask );
 #define machine_has_neponset() (0)
 #endif
 
+#ifdef CONFIG_SA1100_CERF
+#include "cerf.h"
+#endif
+
 #ifdef CONFIG_SA1100_EMPEG
 #include "empeg.h"
 #endif
index 63cdc68338b1846d5cbcf756988a0943d7450fed..ac21901400e4c02ec38e84f013e432c57e8af3cf 100644 (file)
@@ -7,10 +7,9 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_BLK_DEV_IDE
-
 #include <asm/irq.h>
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
 
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
@@ -116,9 +115,26 @@ ide_init_default_hwifs(void)
        ide_init_hwif_ports(&hw, 0xe00001f0, 0xe00003f6, NULL);
        hw.irq = IRQ_GPIO7;
        ide_register_hw(&hw, NULL);
+#endif
+    }
+    else if (machine_is_lart()) {
+#ifdef CONFIG_SA1100_LART
+        hw_regs_t hw;
+
+        /* Enable GPIO as interrupt line */
+        GPDR &= ~GPIO_GPIO1;
+        set_GPIO_IRQ_edge(GPIO_GPIO1, GPIO_RISING_EDGE);
+        
+        /* set PCMCIA interface timing */
+        MECR = 0x00060006;
+
+        /* init the interface */
+/*         ide_init_hwif_ports(&hw, 0xe00000000, 0xe00001000, NULL); */
+        ide_init_hwif_ports(&hw, 0xe00001000, 0xe00000000, NULL);
+        hw.irq = IRQ_GPIO1;
+        ide_register_hw(&hw, NULL);
 #endif
     }
 }
 
-#endif
 
index 6e24e97b1d1b3570b5f28ff88dd2b1b42f418d94..8c6b0e821f4428dc48dc5700898f5bcca1901e7c 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/config.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 
 #define fixup_irq(x)   (x)
 
index 7f9359782c0bf4e464bcd2ed98d5f5ee693c38fa..5f4648ee61226f537de193e2a968d9c5c0a2221e 100644 (file)
@@ -9,6 +9,8 @@
 #include "hardware.h"
 #include "serial_reg.h"
 
+#include <asm/mach-types.h>
+
 /* Assabet's Status Control "Register" */
 unsigned long SCR_value;
 
@@ -29,7 +31,7 @@ static void puts( const char *s )
                        serial_port = (unsigned long *)_Ser3UTCR0;
                else
                        serial_port = (unsigned long *)_Ser1UTCR0;
-       } else if (machine_is_brutus())
+       } else if (machine_is_brutus()||machine_is_nanoengine())
                serial_port = (unsigned long *)_Ser1UTCR0;
        else if (machine_is_empeg() || machine_is_bitsy() ||
                 machine_is_victor() || machine_is_lart())
index 523bd065f2f6dcc66c6287e8d22a62fccfe07efe..dcb47641e40f635685a0d1e418350be5fbe3e989 100644 (file)
@@ -11,8 +11,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-extern int have_isa_bridge;
-
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
index 9d122b4de24f6fc43c6bc37f17b123281864b249..c3e44c92164b2ea962caf1b0f7ae6a0d3a32bbfe 100644 (file)
@@ -7,5 +7,9 @@
  * Do not include any C declarations in this file - it is included by
  * assembler source.
  */
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
+#endif
+
 #include <asm/proc/ptrace.h>
 #include <asm/proc/assembler.h>
index ed2d9627be028e967b26b6637f4f177941e1b75d..78c65b59985c91b9266785542372aa7da4556a59 100644 (file)
@@ -4,7 +4,6 @@
 typedef unsigned int dmach_t;
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/memory.h>
index 697976d8969b2fe6adb62699e41a103b5fc2cc24..594552e84c1f465db39be63db51e04cd8334cf16 100644 (file)
 
 #include <asm/arch/hardware.h>
 
+#ifdef PARAMS_OFFSET
+#define PARAMS_BASE            ((PAGE_OFFSET) + (PARAMS_OFFSET))
+#else
+#define PARAMS_BASE            0
+#endif
+
 #endif
index 84a67f7679b95856156b74f0e8cc703e8a148f9a..7eebdb1c2db7f2939cfeeeb0d4df4c5cf1cea31b 100644 (file)
@@ -25,17 +25,20 @@ typedef enum {
        led_amber_on,
        led_amber_off,
        led_red_on,
-       led_red_off
+       led_red_off,
+       /*
+        * I want this between led_timer and led_start, but
+        * someone has decided to export this to user space
+        */
+       led_halted
 } led_event_t;
 
 /* Use this routine to handle LEDs */
 
 #ifdef CONFIG_LEDS
 extern void (*leds_event)(led_event_t);
-#define set_leds_event(r)      leds_event = r
 #else
 #define leds_event(e)
-#define set_leds_event(r)
 #endif
 
 #endif
index d6e3009430c1efaa1b162d983bf750da3982ad6d..7b81e0c4254398b123742fc380625d164da85053 100644 (file)
@@ -4,6 +4,7 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
+#include <asm/arch/irqs.h>
 #include <asm/io.h>
 
 #ifndef RTC_PORT
@@ -24,6 +25,4 @@ outb_p((addr),RTC_PORT(0)); \
 outb_p((val),RTC_PORT(1)); \
 })
 
-#define RTC_IRQ 8
-
 #endif /* _ASM_MC146818RTC_H */
index 4f24702a21b07343ad2cc43cbb7e18e24469a7a7..7201ff55875d607cdd3a3c611ef2d6ddcc3c888b 100644 (file)
@@ -91,8 +91,8 @@ extern __inline__ int get_order(unsigned long size)
 #define __va(x)                        ((void *)__phys_to_virt((unsigned long)(x)))
 
 #ifndef CONFIG_DISCONTIGMEM
-#define MAP_NR(addr)           ((__pa(addr) - PHYS_OFFSET) >> PAGE_SHIFT)
-#define virt_to_page(kaddr)    (mem_map + ((__pa(kaddr) - PHYS_OFFSET) >> PAGE_SHIFT))
+#define virt_to_page(kaddr)    (mem_map + (__pa(kaddr) >> PAGE_SHIFT) - \
+                                (PHYS_OFFSET >> PAGE_SHIFT))
 #define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
 #endif
 
index c0548236b712c9db1ebe9a0b36c2b84b0449e3ba..a16a0d54c294062902c7876544f9ddbcc5474095 100644 (file)
@@ -5,7 +5,6 @@
 #define _ASMARM_PGALLOC_H
 
 #include <linux/config.h>
-#include <linux/threads.h>
 
 #include <asm/processor.h>
 
index 850ea4139c42bd4bb90d9a0d476df121014083b1..65b39ad722cb8137faad241b7068eb22bce96e39 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/config.h>
 #include <asm/arch/memory.h>
 #include <asm/proc-fns.h>
-#include <asm/system.h>
 
 /*
  * PMD_SHIFT determines the size of the area a second-level page table can map
@@ -80,7 +79,8 @@ extern void __handle_bad_pmd_kernel(pmd_t *pmd);
 #define pte_clear(ptep)                set_pte((ptep), __pte(0))
 
 #ifndef CONFIG_DISCONTIGMEM
-#define pte_page(x)            (mem_map + (unsigned long)(((pte_val(pte) - PHYS_OFFSET) >> PAGE_SHIFT)))
+#define pte_page(x)            (mem_map + (pte_val((x)) >> PAGE_SHIFT) - \
+                                (PHYS_OFFSET >> PAGE_SHIFT))
 #else
 /*
  * I'm not happy with this - we needlessly convert a physical address
@@ -88,7 +88,7 @@ extern void __handle_bad_pmd_kernel(pmd_t *pmd);
  * which, if __va and __pa are expensive causes twice the expense for
  * zero gain. --rmk
  */
-#define pte_page(x)            (mem_map + MAP_NR(__va(pte_val(pte))))
+#define pte_page(x)            (mem_map + MAP_NR(__va(pte_val((x)))))
 #endif
 
 #define pmd_none(pmd)          (!pmd_val(pmd))
@@ -173,9 +173,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 #define module_map             vmalloc
 #define module_unmap           vfree
 
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define PageSkip(page)         (machine_is_riscpc() && test_bit(PG_skip, &(page)->flags))
-
 #define io_remap_page_range    remap_page_range
 
 #endif /* !__ASSEMBLY__ */
index d611ea4dd4e48ddcfa6afb566647d6458a7e3fb9..42b23aa89ef3a0983b90c9d1dfc0de0c9d688831 100644 (file)
@@ -6,10 +6,6 @@
  * This file contains arm architecture specific defines
  * for the different processors
  */
-#ifndef __ASSEMBLY__
-#error "Only include this from assembly code"
-#endif
-
 #define MODE_USR       USR26_MODE
 #define MODE_FIQ       FIQ26_MODE
 #define MODE_IRQ       IRQ26_MODE
 #define SVCMODE(tmpreg)\
        teqp    pc, $0x00000003;\
        mov     r0, r0
+
+
+/*
+ * Save the current IRQ state and disable IRQs
+ * Note that this macro assumes FIQs are enabled, and
+ * that the processor is in SVC mode.
+ */
+       .macro  save_and_disable_irqs, oldcpsr, temp
+  mov \oldcpsr, pc
+  orr \temp, \oldcpsr, #0x08000000
+  teqp \temp, #0
+  .endm
+
+/*
+ * Restore interrupt state previously stored in
+ * a register
+ * ** Actually do nothing on Arc - hope that the caller uses a MOVS PC soon
+ * after!
+ */
+       .macro  restore_irqs, oldcpsr
+  @ This be restore_irqs
+  .endm
index 75250fb3bf18d0fa7921ae4457059d167b1c8347..ca99bcf829234bdad911fe70700ab7a9e2e126fe 100644 (file)
@@ -10,6 +10,9 @@
 #define flush_icache_page(vma,page)            do { } while (0)
 #define flush_icache_range(start,end)          do { } while (0)
 
+/* DAG: ARM3 will flush cache on MEMC updates anyway? so don't bother */
+#define clean_cache_area(_start,_size) do { } while (0)
+
 /*
  * TLB flushing:
  *
diff --git a/include/asm-arm/proc-armo/locks.h b/include/asm-arm/proc-armo/locks.h
new file mode 100644 (file)
index 0000000..fcf0cab
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * linux/include/asm-arm/proc-armo/locks.h
+ *
+ * Copyright (C) 2000 Russell King
+ * Fixes for 26 bit machines, (C) 2000 Dave Gilbert
+ *
+ * Interrupt safe locking assembler. 
+ *
+ */
+#ifndef __ASM_PROC_LOCKS_H
+#define __ASM_PROC_LOCKS_H
+
+/* Decrements by 1, fails if value < 0 */
+#define __down_op(ptr,fail)                    \
+       ({                                      \
+       __asm__ __volatile__ (                  \
+       "@ atomic down operation\n"             \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+"      ldr     lr, [%0]\n"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      subs    lr, lr, #1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      orrmi   r0, r0, #0x80000000     @ set N\n" \
+"      teqp    r0, #0\n"                       \
+"      movmi   r0, %0\n"                       \
+"      blmi    " SYMBOL_NAME_STR(fail)         \
+       :                                       \
+       : "r" (ptr)                             \
+       : "r0", "lr", "cc");                    \
+       })
+
+#define __down_op_ret(ptr,fail)                        \
+       ({                                      \
+               unsigned int result;            \
+       __asm__ __volatile__ (                  \
+"      @ down_op_ret\n"                        \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+"      ldr     lr, [%1]\n"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      subs    lr, lr, #1\n"                   \
+"      str     lr, [%1]\n"                     \
+"      orrmi   r0, r0, #0x80000000     @ set N\n" \
+"      teqp    r0, #0\n"                       \
+"      movmi   r0, %1\n"                       \
+"      movpl   r0, #0\n"                       \
+"      blmi    " SYMBOL_NAME_STR(fail) "\n"    \
+"      mov     %0, r0"                         \
+       : "=&r" (result)                        \
+       : "r" (ptr)                             \
+       : "r0", "lr", "cc");                    \
+       result;                                 \
+       })
+
+#define __up_op(ptr,wake)                      \
+       ({                                      \
+       __asm__ __volatile__ (                  \
+       "@ up_op\n"                             \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+"      ldr     lr, [%0]\n"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      adds    lr, lr, #1\n"                   \
+"      str     lr, [%0]\n"                     \
+"      orrle   r0, r0, #0x80000000     @ set N - should this be mi ??? DAG ! \n" \
+"      teqp    r0, #0\n"                       \
+"      movmi   r0, %0\n"                       \
+"      blmi    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr)                             \
+       : "r0", "lr", "cc");                    \
+       })
+
+/*
+ * The value 0x01000000 supports up to 128 processors and
+ * lots of processes.  BIAS must be chosen such that sub'ing
+ * BIAS once per CPU will result in the long remaining
+ * negative.
+ */
+#define RW_LOCK_BIAS      0x01000000
+#define RW_LOCK_BIAS_STR "0x01000000"
+
+/* Decrements by RW_LOCK_BIAS rather than 1, fails if value != 0 */
+#define __down_op_write(ptr,fail)              \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ down_op_write\n"                     \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+"      and     r0, r0, #0x0c000003\n"          \
+\
+"      ldr     lr, [%0]\n"                     \
+"      subs    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+\
+" orreq r0, r0, #0x40000000 @ set Z \n"\
+"      teqp    r0, #0\n"                       \
+"      movne   r0, %0\n"                       \
+"      blne    " SYMBOL_NAME_STR(fail)         \
+       :                                       \
+       : "r" (ptr), "I" (RW_LOCK_BIAS)         \
+       : "r0", "lr", "cc");                    \
+       })
+
+/* Increments by RW_LOCK_BIAS, wakes if value >= 0 */
+#define __up_op_write(ptr,wake)                        \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ up_op_read\n"                        \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+\
+"      ldr     lr, [%0]\n"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      adds    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+\
+" orrcs r0, r0, #0x20000000 @ set C\n" \
+"      teqp    r0, #0\n"                       \
+"      movcs   r0, %0\n"                       \
+"      blcs    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr), "I" (RW_LOCK_BIAS)         \
+       : "r0", "lr", "cc");                    \
+       })
+
+#define __down_op_read(ptr,fail)               \
+       __down_op(ptr, fail)
+
+#define __up_op_read(ptr,wake)                 \
+       ({                                      \
+       __asm__ __volatile__(                   \
+       "@ up_op_read\n"                        \
+"      mov     r0, pc\n"                       \
+"      orr     lr, r0, #0x08000000\n"          \
+"      teqp    lr, #0\n"                       \
+\
+"      ldr     lr, [%0]\n"                     \
+"      and     r0, r0, #0x0c000003\n"          \
+"      adds    lr, lr, %1\n"                   \
+"      str     lr, [%0]\n"                     \
+\
+" orreq r0, r0, #0x40000000 @ Set Z \n" \
+"      teqp    r0, #0\n"                       \
+"      moveq   r0, %0\n"                       \
+"      bleq    " SYMBOL_NAME_STR(wake)         \
+       :                                       \
+       : "r" (ptr), "I" (1)                    \
+       : "r0", "lr", "cc");                    \
+       })
+
+#endif
index 36a3515e7a0db0fbbcd7659f2ff51b27fdfc3d66..42a6bc70a5aed7bf599005d682038976df406259 100644 (file)
@@ -77,6 +77,24 @@ extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int
          : "memory");                          \
        } while(0)
 
+#define __clf()        do {                            \
+       unsigned long temp;                     \
+       __asm__ __volatile__(                   \
+"      mov     %0, pc          @ clf\n"        \
+"      orr     %0, %0, #0x04000000\n"          \
+"      teqp    %0, #0\n"                       \
+       : "=r" (temp));                         \
+    } while(0)
+
+#define __stf()        do {                            \
+       unsigned long temp;                     \
+       __asm__ __volatile__(                   \
+"      mov     %0, pc          @ stf\n"        \
+"      bic     %0, %0, #0x04000000\n"          \
+"      teqp    %0, #0\n"                       \
+       : "=r" (temp));                         \
+    } while(0)
+
 /*
  * save current IRQ & FIQ state
  */
index 788a22b87e8208d58523f2f8c941530c513a4530..aaec7f9c7954ed5a969611a9699248d9d4fce982 100644 (file)
@@ -6,10 +6,6 @@
  * This file contains ARM processor specifics for
  * the ARM6 and better processors.
  */
-#ifndef __ASSEMBLY__
-#error "Only include this from assembly code"
-#endif
-
 #define MODE_USR       USR_MODE
 #define MODE_FIQ       FIQ_MODE
 #define MODE_IRQ       IRQ_MODE
@@ -35,9 +31,8 @@
        instr   regs
 
 /*
- * Save the current IRQ state and disable IRQs
- * Note that this macro assumes FIQs are enabled, and
- * that the processor is in SVC mode.
+ * Save the current IRQ state and disable IRQs.  Note that this macro
+ * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
        .macro  save_and_disable_irqs, oldcpsr, temp
        mrs     \oldcpsr, cpsr
@@ -46,8 +41,8 @@
        .endm
 
 /*
- * Restore interrupt state previously stored in
- * a register
+ * Restore interrupt state previously stored in a register.  We don't
+ * guarantee that this will preserve the flags.
  */
        .macro  restore_irqs, oldcpsr
        msr     cpsr_c, \oldcpsr
index 3c41d577b40b26a60c1d8a99d13188f8b74d0563..c5eb263aa9a86bf282a1f1551a617a8f57dd2a5d 100644 (file)
@@ -17,6 +17,6 @@
    there is no other ELF system currently supported by iBCS.
    @@ Could print a warning message to encourage users to upgrade.  */
 #define SET_PERSONALITY(ex,ibcs2) \
-       set_personality((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT)
+       set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT))
 
 #endif
index d9ef8ffd98d88037c799d291ffeafb4437bf59da..e05e6356f745f0117065594a883da3e53205c6d9 100644 (file)
@@ -78,6 +78,36 @@ extern unsigned long cr_alignment;   /* defined in entry-armv.S */
        : "memory");                                            \
        })
 
+/*
+ * Enable FIQs
+ */
+#define __stf()                                                        \
+       ({                                                      \
+               unsigned long temp;                             \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ stf\n"                \
+"      bic     %0, %0, #64\n"                                  \
+"      msr     cpsr_c, %0"                                     \
+       : "=r" (temp)                                           \
+       :                                                       \
+       : "memory");                                            \
+       })
+
+/*
+ * Disable FIQs
+ */
+#define __clf()                                                        \
+       ({                                                      \
+               unsigned long temp;                             \
+       __asm__ __volatile__(                                   \
+       "mrs    %0, cpsr                @ clf\n"                \
+"      orr     %0, %0, #64\n"                                  \
+"      msr     cpsr_c, %0"                                     \
+       : "=r" (temp)                                           \
+       :                                                       \
+       : "memory");                                            \
+       })
+
 /*
  * save current IRQ & FIQ state
  */
index 67afdd2ae57d3c1467ee8b9379f9a3b383755e49..af146abf96eb44c902d6e7bdf8136a99b93c075b 100644 (file)
@@ -41,7 +41,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "2:\n"                                                  \
        "       .section .fixup,\"ax\"\n"                       \
        "       .align  2\n"                                    \
-       "3:     mvn     %0, %3\n"                               \
+       "3:     mov     %0, %3\n"                               \
        "       b       2b\n"                                   \
        "       .previous\n"                                    \
        "       .section __ex_table,\"a\"\n"                    \
@@ -49,7 +49,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "       .long   1b, 3b\n"                               \
        "       .previous"                                      \
        : "=r" (err)                                            \
-       : "r" (x), "r" (addr), "i" (EFAULT), "0" (err))
+       : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
 
 #define __put_user_asm_half(x,addr,err)                                \
 ({                                                             \
@@ -60,7 +60,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "3:\n"                                                  \
        "       .section .fixup,\"ax\"\n"                       \
        "       .align  2\n"                                    \
-       "4:     mvn     %0, %5\n"                               \
+       "4:     mov     %0, %5\n"                               \
        "       b       3b\n"                                   \
        "       .previous\n"                                    \
        "       .section __ex_table,\"a\"\n"                    \
@@ -71,7 +71,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        : "=r" (err)                                            \
        : "r" (__temp), "r" (__temp >> 8),                      \
          "r" (addr), "r" ((int)(addr) + 1),                    \
-          "i" (EFAULT), "0" (err));                            \
+          "i" (-EFAULT), "0" (err));                           \
 })
 
 #define __put_user_asm_word(x,addr,err)                                \
@@ -80,7 +80,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "2:\n"                                                  \
        "       .section .fixup,\"ax\"\n"                       \
        "       .align  2\n"                                    \
-       "3:     mvn     %0, %3\n"                               \
+       "3:     mov     %0, %3\n"                               \
        "       b       2b\n"                                   \
        "       .previous\n"                                    \
        "       .section __ex_table,\"a\"\n"                    \
@@ -88,7 +88,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "       .long   1b, 3b\n"                               \
        "       .previous"                                      \
        : "=r" (err)                                            \
-       : "r" (x), "r" (addr), "i" (EFAULT), "0" (err))
+       : "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
 
 #define __get_user_asm_byte(x,addr,err)                                \
        __asm__ __volatile__(                                   \
@@ -96,7 +96,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "2:\n"                                                  \
        "       .section .fixup,\"ax\"\n"                       \
        "       .align  2\n"                                    \
-       "3:     mvn     %0, %3\n"                               \
+       "3:     mov     %0, %3\n"                               \
        "       mov     %1, #0\n"                               \
        "       b       2b\n"                                   \
        "       .previous\n"                                    \
@@ -105,7 +105,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "       .long   1b, 3b\n"                               \
        "       .previous"                                      \
        : "=r" (err), "=r" (x)                                  \
-       : "r" (addr), "i" (EFAULT), "0" (err))
+       : "r" (addr), "i" (-EFAULT), "0" (err))
 
 #define __get_user_asm_half(x,addr,err)                                \
 ({                                                             \
@@ -117,7 +117,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "3:\n"                                                  \
        "       .section .fixup,\"ax\"\n"                       \
        "       .align  2\n"                                    \
-       "4:     mvn     %0, %5\n"                               \
+       "4:     mov     %0, %5\n"                               \
        "       mov     %1, #0\n"                               \
        "       b       3b\n"                                   \
        "       .previous\n"                                    \
@@ -128,7 +128,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "       .previous"                                      \
        : "=r" (err), "=r" (x), "=&r" (__temp)                  \
        : "r" (addr), "r" ((int)(addr) + 1),                    \
-          "i" (EFAULT), "0" (err));                            \
+          "i" (-EFAULT), "0" (err));                           \
 })
 
 
@@ -138,7 +138,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "2:\n"                                                  \
        "       .section .fixup,\"ax\"\n"                       \
        "       .align  2\n"                                    \
-       "3:     mvn     %0, %3\n"                               \
+       "3:     mov     %0, %3\n"                               \
        "       mov     %1, #0\n"                               \
        "       b       2b\n"                                   \
        "       .previous\n"                                    \
@@ -147,7 +147,7 @@ extern __inline__ void set_fs (mm_segment_t fs)
        "       .long   1b, 3b\n"                               \
        "       .previous"                                      \
        : "=r" (err), "=r" (x)                                  \
-       : "r" (addr), "i" (EFAULT), "0" (err))
+       : "r" (addr), "i" (-EFAULT), "0" (err))
 
 extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n);
 #define __do_copy_from_user(to,from,n)                         \
index aea5122a05e6289627a312c7e909ef790d87b99d..8a26bc85d1e526eb5df9b6fcb214f3bfd2a665a1 100644 (file)
 
 #define RLIM_NLIMITS   10
 
+#ifdef __KERNEL__
+
 /*
  * SuS says limits have to be unsigned.
  * Which makes a ton more sense anyway.
  */
 #define RLIM_INFINITY  (~0UL)
 
-#ifdef __KERNEL__
-
-#define INIT_RLIMITS                                   \
-{                                                      \
-       { LONG_MAX, LONG_MAX },                         \
-       { LONG_MAX, LONG_MAX },                         \
-       { LONG_MAX, LONG_MAX },                         \
-       { _STK_LIM, _STK_LIM },                         \
-       {        0, LONG_MAX },                         \
-       { LONG_MAX, LONG_MAX },                         \
-       {        0,        0 },                         \
-       { INR_OPEN, INR_OPEN },                         \
-       { LONG_MAX, LONG_MAX },                         \
-       { LONG_MAX, LONG_MAX },                         \
+#define INIT_RLIMITS                           \
+{                                              \
+       { RLIM_INFINITY, RLIM_INFINITY },       \
+       { RLIM_INFINITY, RLIM_INFINITY },       \
+       { RLIM_INFINITY, RLIM_INFINITY },       \
+       { _STK_LIM,      RLIM_INFINITY },       \
+       { 0,             RLIM_INFINITY },       \
+       { RLIM_INFINITY, RLIM_INFINITY },       \
+       { 0,             0             },       \
+       { INR_OPEN,      INR_OPEN      },       \
+       { RLIM_INFINITY, RLIM_INFINITY },       \
+       { RLIM_INFINITY, RLIM_INFINITY },       \
 }
 
 #endif /* __KERNEL__ */
index c7f71bb14af2b73480fff3eea72f3c98081786fd..a1142be1a8fbb566dac98fe0d39d98f79f5f708f 100644 (file)
@@ -1,11 +1,10 @@
 #ifndef __ASM_ARM_SYSTEM_H
 #define __ASM_ARM_SYSTEM_H
 
-#include <linux/kernel.h>
-
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <linux/linkage.h>
 
 /* information about the system we're running on */
 extern unsigned int system_rev;
@@ -13,365 +12,14 @@ extern unsigned int system_serial_low;
 extern unsigned int system_serial_high;
 extern unsigned int mem_fclk_21285;
 
-/* The type of machine we're running on */
-extern unsigned int __machine_arch_type;
-
-/* see arch/arm/kernel/arch.c for a description of these */
-#define MACH_TYPE_EBSA110              0
-#define MACH_TYPE_RISCPC               1
-#define MACH_TYPE_NEXUSPCI             3
-#define MACH_TYPE_EBSA285              4
-#define MACH_TYPE_NETWINDER            5
-#define MACH_TYPE_CATS                 6
-#define MACH_TYPE_TBOX                 7
-#define MACH_TYPE_CO285                        8
-#define MACH_TYPE_CLPS7110             9
-#define MACH_TYPE_ARCHIMEDES           10
-#define MACH_TYPE_A5K                  11
-#define MACH_TYPE_ETOILE               12
-#define MACH_TYPE_LACIE_NAS            13
-#define MACH_TYPE_CLPS7500             14
-#define MACH_TYPE_SHARK                        15
-#define MACH_TYPE_BRUTUS               16
-#define MACH_TYPE_PERSONAL_SERVER      17
-#define MACH_TYPE_ITSY                 18
-#define MACH_TYPE_L7200                        19
-/* 20 is free - contact rmk@arm.linux.org.uk directly if you wish to use this number */
-#define MACH_TYPE_INTEGRATOR           21
-#define MACH_TYPE_BITSY                        22
-#define MACH_TYPE_IXP1200              23
-#define MACH_TYPE_THINCLIENT           24
-#define MACH_TYPE_ASSABET              25
-#define MACH_TYPE_VICTOR               26
-#define MACH_TYPE_LART                 27
-#define MACH_TYPE_RANGER               28
-#define MACH_TYPE_GRAPHICSCLIENT       29
-#define MACH_TYPE_XP860                        30
-
 /*
- * Sort out a definition for machine_arch_type
- * The rules are:
- * 1. If one architecture is selected, then all machine_is_xxx()
- *    are constant.
- * 2. If two or more architectures are selected, then the selected
- *    machine_is_xxx() are variable, and the unselected machine_is_xxx()
- *    are constant zero.
- *
- * In general, you should use machine_is_xxxx() in your code, not:
- *  -  switch (machine_arch_type) { }
- *  -  if (machine_arch_type = xxxx)
- *  -  __machine_arch_type
- *
- * Please note that these are kept in numeric order (ie, the same
- * order as the list above).
+ * This tells us if we have an ISA bridge
+ * present in a PCI system.
  */
-#ifdef CONFIG_ARCH_EBSA110
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_EBSA110
-# endif
-# define machine_is_ebsa110()  (machine_arch_type == MACH_TYPE_EBSA110)
-#else
-# define machine_is_ebsa110()  (0)
-#endif
-
-#ifdef CONFIG_ARCH_RPC
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_RISCPC
-# endif
-# define machine_is_riscpc()   (machine_arch_type == MACH_TYPE_RISCPC)
-#else
-# define machine_is_riscpc()   (0)
-#endif
-
-#ifdef CONFIG_ARCH_EBSA285
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_EBSA285
-# endif
-# define machine_is_ebsa285()  (machine_arch_type == MACH_TYPE_EBSA285)
-#else
-# define machine_is_ebsa285()  (0)
-#endif
-
-#ifdef CONFIG_ARCH_NETWINDER
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_NETWINDER
-# endif
-# define machine_is_netwinder()        (machine_arch_type == MACH_TYPE_NETWINDER)
-#else
-# define machine_is_netwinder()        (0)
-#endif
-
-#ifdef CONFIG_ARCH_CATS
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_CATS
-# endif
-# define machine_is_cats()     (machine_arch_type == MACH_TYPE_CATS)
-#else
-# define machine_is_cats()     (0)
-#endif
-
-#ifdef CONFIG_ARCH_CO285
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_CO285
-# endif
-# define machine_is_co285()    (machine_arch_type == MACH_TYPE_CO285)
-#else
-# define machine_is_co285()    (0)
-#endif
-
-#ifdef CONFIG_ARCH_ARC
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_ARCHIMEDES
-# endif
-# define machine_is_arc()      (machine_arch_type == MACH_TYPE_ARCHIMEDES)
-#else
-# define machine_is_arc()      (0)
-#endif
-
-#ifdef CONFIG_ARCH_A5K
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_A5K
-# endif
-# define machine_is_a5k()      (machine_arch_type == MACH_TYPE_A5K)
-#else
-# define machine_is_a5k()      (0)
-#endif
-
-#ifdef CONFIG_ARCH_CLPS7500
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_CLPS7500
-# endif
-# define machine_is_clps7500() (machine_arch_type == MACH_TYPE_CLPS7500)
-#else
-# define machine_is_clps7500() (0)
-#endif
-
-#ifdef CONFIG_ARCH_SHARK
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_SHARK
-# endif
-# define machine_is_shark()    (machine_arch_type == MACH_TYPE_SHARK)
-#else
-# define machine_is_shark()    (0)
-#endif
-
-#ifdef CONFIG_SA1100_BRUTUS
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_BRUTUS
-# endif
-# define machine_is_brutus()   (machine_arch_type == MACH_TYPE_BRUTUS)
-#else
-# define machine_is_brutus()   (0)
-#endif
-
-#ifdef CONFIG_ARCH_PERSONAL_SERVER
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_PERSONAL_SERVER
-# endif
-# define machine_is_personal_server()  (machine_arch_type == MACH_TYPE_PERSONAL_SERVER)
-#else
-# define machine_is_personal_server()  (0)
-#endif
-
-#ifdef CONFIG_SA1100_ITSY
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_ITSY
-# endif
-# define machine_is_itsy()     (machine_arch_type == MACH_TYPE_ITSY)
-#else
-# define machine_is_itsy()     (0)
-#endif
-
-#ifdef CONFIG_ARCH_L7200
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_L7200
-# endif
-# define machine_is_l7200()    (machine_arch_type == MACH_TYPE_L7200)
+#ifdef CONFIG_PCI
+extern int have_isa_bridge;
 #else
-# define machine_is_l7200()    (0)
-#endif
-
-#ifdef CONFIG_SA1100_BITSY
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_BITSY
-# endif
-# define machine_is_bitsy()    (machine_arch_type == MACH_TYPE_BITSY)
-#else
-# define machine_is_bitsy()    (0)
-#endif
-
-#ifdef CONFIG_SA1100_THINCLIENT
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_THINCLIENT
-# endif
-# define machine_is_thinclient()       (machine_arch_type == MACH_TYPE_THINCLIENT)
-#else
-# define machine_is_thinclient()       (0)
-#endif
-
-#ifdef CONFIG_SA1100_ASSABET
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_ASSABET
-# endif
-# define machine_is_assabet()  (machine_arch_type == MACH_TYPE_ASSABET)
-#else
-# define machine_is_assabet()  (0)
-#endif
-
-#ifdef CONFIG_SA1100_VICTOR
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_VICTOR
-# endif
-# define machine_is_victor()   (machine_arch_type == MACH_TYPE_VICTOR)
-#else
-# define machine_is_victor()   (0)
-#endif
-
-#ifdef CONFIG_SA1100_LART
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_LART
-# endif
-# define machine_is_lart()     (machine_arch_type == MACH_TYPE_LART)
-#else
-# define machine_is_lart()     (0)
-#endif
-
-#ifdef CONFIG_SA1100_GRAPHICSCLIENT
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_GRAPHICSCLIENT
-# endif
-# define machine_is_grpahicsclient() \
-                               (machine_arch_type == MACH_TYPE_GRAPHICSCLIENT)
-#else
-# define machine_is_graphicsclient() \
-                               (0)
-#endif
-
-#ifdef CONFIG_SA1100_XP860
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_XP860
-# endif
-# define machine_is_xp860()    (machine_arch_type == MACH_TYPE_XP860)
-#else
-# define machine_is_xp860()    (0)
-#endif
-
-/*
- * The following are currently unregistered
- */
-#ifdef CONFIG_SA1100_EMPEG
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_EMPEG
-# endif
-# define machine_is_empeg()    (machine_arch_type == MACH_TYPE_EMPEG)
-#else
-# define machine_is_empeg()    (0)
-#endif
-
-#ifdef CONFIG_SA1100_TIFON
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_TIFON
-# endif
-# define machine_is_tifon()    (machine_arch_type == MACH_TYPE_TIFON)
-#else
-# define machine_is_tifon()    (0)
-#endif
-
-#ifdef CONFIG_SA1100_PLEB
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_PLEB
-# endif
-# define machine_is_pleb()     (machine_arch_type == MACH_TYPE_PLEB)
-#else
-# define machine_is_pleb()     (0)
-#endif
-
-#ifdef CONFIG_SA1100_PENNY
-# ifdef machine_arch_type
-#  undef machine_arch_type
-#  define machine_arch_type    __machine_arch_type
-# else
-#  define machine_arch_type    MACH_TYPE_PENNY
-# endif
-# define machine_is_penny()    (machine_arch_type == MACH_TYPE_PENNY)
-#else
-# define machine_is_penny()    (0)
-#endif
-
-#ifndef machine_arch_type
-#define machine_arch_type      __machine_arch_type
+#define have_isa_bridge                (0)
 #endif
 
 #include <asm/proc-fns.h>
@@ -408,8 +56,6 @@ extern struct task_struct *__switch_to(struct task_struct *prev, struct task_str
                mb();                           \
        } while (0)
 
-#endif
-
 /* For spinlocks etc */
 #define local_irq_save(x)      __save_flags_cli(x)
 #define local_irq_restore(x)   __restore_flags(x)
@@ -422,10 +68,14 @@ extern struct task_struct *__switch_to(struct task_struct *prev, struct task_str
 
 #define cli()                  __cli()
 #define sti()                  __sti()
+#define clf()                  __clf()
+#define stf()                  __stf()
 #define save_flags(x)          __save_flags(x)
 #define restore_flags(x)       __restore_flags(x)
 #define save_flags_cli(x)      __save_flags_cli(x)
 
-#endif
+#endif /* CONFIG_SMP */
+
+#endif /* __KERNEL__ */
 
 #endif
index 9922760e490fbe40e5a949f23e63728374cb8e18..1981814234593c473ed6d1df5d9f8a925fb9049e 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __ASM_ARM_TERMBITS_H
 #define __ASM_ARM_TERMBITS_H
 
-#include <linux/posix_types.h>
-
 typedef unsigned char  cc_t;
 typedef unsigned int   speed_t;
 typedef unsigned int   tcflag_t;
index c45cea198fdb12c8e6700fbb8b226c41ba242cb9..6d589dd1d2a38809b28a3ff7176e8c128791bfa7 100644 (file)
@@ -68,8 +68,6 @@ struct termio {
 
 #ifdef __KERNEL__
 
-#include <linux/string.h>
-
 /*
  * Translate a "termio" structure into a "termios". Ugh.
  */
index 8bcfa707813c17bdf6b474fae76e845965c4d358..add086e5540639e81876820f44e55c8c06213b23 100644 (file)
@@ -46,7 +46,14 @@ extern __inline__ int verify_area(int type, const void * addr, unsigned long siz
 
 /*
  * Single-value transfer routines.  They automatically use the right
- * size if we just have the right pointer type.
+ * size if we just have the right pointer type.  Note that the functions
+ * which read from user space (*get_*) need to take care not to leak
+ * kernel data even if the calling code is buggy and fails to check
+ * the return value.  This means zeroing out the destination variable
+ * or buffer on error.  Normally this is done out of line by the
+ * fixup code, but there are a few places where it intrudes on the
+ * main code path.  When we only write to user space, there is no
+ * problem.
  *
  * The "__xxx" versions of the user access functions do not verify the
  * address space - it must have been done previously with a separate
@@ -54,24 +61,27 @@ extern __inline__ int verify_area(int type, const void * addr, unsigned long siz
  *
  * The "xxx_ret" versions return constant specified in the third
  * argument if something bad happens.
+ *
+ * The "xxx_error" versions set the third argument to EFAULT if an
+ * error occurs, and leave it unchanged on success.  Note that these
+ * versions are void (ie, don't return a value as such).
  */
 #define get_user(x,p)          __get_user_check((x),(p),sizeof(*(p)))
 #define __get_user(x,p)                __get_user_nocheck((x),(p),sizeof(*(p)))
+#define __get_user_error(x,p,e)        __get_user_nocheck_error((x),(p),sizeof(*(p)),(e))
 #define get_user_ret(x,p,r)    ({ if (get_user(x,p)) return r; })
 #define __get_user_ret(x,p,r)  ({ if (__get_user(x,p)) return r; })
 
 #define put_user(x,p)          __put_user_check((__typeof(*(p)))(x),(p),sizeof(*(p)))
 #define __put_user(x,p)                __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p)))
+#define __put_user_error(x,p,e)        __put_user_nocheck_error((x),(p),sizeof(*(p)),(e))
 #define put_user_ret(x,p,r)    ({ if (put_user(x,p)) return r; })
 #define __put_user_ret(x,p,r)  ({ if (__put_user(x,p)) return r; })
 
 static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
 {
-       char *end = (char *)to + n;
-       if (access_ok(VERIFY_READ, from, n)) {
+       if (access_ok(VERIFY_READ, from, n))
                __do_copy_from_user(to, from, n);
-               if (n) memset(end - n, 0, n);
-       }
        return n;
 }
 
@@ -147,26 +157,38 @@ extern __inline__ long strnlen_user(const char *s, long n)
 ({                                                                     \
        long __gu_err = -EFAULT, __gu_val = 0;                          \
        const __typeof__(*(ptr)) *__gu_addr = (ptr);                    \
-       if (access_ok(VERIFY_READ,__gu_addr,size))                      \
+       if (access_ok(VERIFY_READ,__gu_addr,size)) {                    \
+               __gu_err = 0;                                           \
                __get_user_size(__gu_val,__gu_addr,(size),__gu_err);    \
+       }                                                               \
        (x) = (__typeof__(*(ptr)))__gu_val;                             \
        __gu_err;                                                       \
 })
 
 #define __get_user_nocheck(x,ptr,size)                                 \
 ({                                                                     \
-       long __gu_err = 0, __gu_val = 0;                                \
+       long __gu_err = 0, __gu_val;                                    \
        __get_user_size(__gu_val,(ptr),(size),__gu_err);                \
        (x) = (__typeof__(*(ptr)))__gu_val;                             \
        __gu_err;                                                       \
 })
 
+#define __get_user_nocheck_error(x,ptr,size,err)                       \
+({                                                                     \
+       long __gu_val;                                                  \
+       __get_user_size(__gu_val,(ptr),(size),(err));                   \
+       (x) = (__typeof__(*(ptr)))__gu_val;                             \
+       (void) 0;                                                       \
+})
+
 #define __put_user_check(x,ptr,size)                                   \
 ({                                                                     \
        long __pu_err = -EFAULT;                                        \
        __typeof__(*(ptr)) *__pu_addr = (ptr);                          \
-       if (access_ok(VERIFY_WRITE,__pu_addr,size))                     \
+       if (access_ok(VERIFY_WRITE,__pu_addr,size)) {                   \
+               __pu_err = 0;                                           \
                __put_user_size((x),__pu_addr,(size),__pu_err);         \
+       }                                                               \
        __pu_err;                                                       \
 })
 
@@ -177,11 +199,16 @@ extern __inline__ long strnlen_user(const char *s, long n)
        __pu_err;                                                       \
 })
 
+#define __put_user_nocheck_error(x,ptr,size,err)                       \
+({                                                                     \
+       __put_user_size((x),(ptr),(size),err);                          \
+       (void) 0;                                                       \
+})
+
 extern long __get_user_bad(void);
 
 #define __get_user_size(x,ptr,size,retval)                             \
 do {                                                                   \
-       retval = 0;                                                     \
        switch (size) {                                                 \
        case 1: __get_user_asm_byte(x,ptr,retval);      break;          \
        case 2: __get_user_asm_half(x,ptr,retval);      break;          \
@@ -194,7 +221,6 @@ extern long __put_user_bad(void);
 
 #define __put_user_size(x,ptr,size,retval)                             \
 do {                                                                   \
-       retval = 0;                                                     \
        switch (size) {                                                 \
        case 1: __put_user_asm_byte(x,ptr,retval);      break;          \
        case 2: __put_user_asm_half(x,ptr,retval);      break;          \
index 2ff6723d86f120746d87f94f7309a69e14d9ac32..44aa2e3b1c5b20be59eac9ed89d3b12e07413394 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_ARM_UNALIGNED_H
 #define __ASM_ARM_UNALIGNED_H
 
-#include <linux/types.h>
+#include <asm/types.h>
 
 extern int __bug_unaligned_x(void *ptr);
 
index e49d3db8e28555605bd902e0180937f1fd9cf6a2..3e8b0f87915935565e78e684416159d265b59d1b 100644 (file)
@@ -2,7 +2,7 @@
 #define _ARM_USER_H
 
 #include <asm/page.h>
-#include <linux/ptrace.h>
+#include <asm/ptrace.h>
 /* Core file format: The core file is written in such a way that gdb
    can understand it and provide useful information to the user (under
    linux we use the 'trad-core' bfd).  There are quite a number of
index 14a87544dcf0f156304cd7dc4e8c0760fdc3def1..01c038774d3b204b5404067e9c71b57762b7dc58 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_PCI_H
 #define _ASM_IA64_PCI_H
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/types.h>
index 6771f0192ac4ce29ffdd15239a5cbe196405511f..fcf340ee002f66c5c0bb2a8ac13bf33024373651 100644 (file)
 
 #include <asm/bitops.h>
 #include <asm/mmu_context.h>
-#include <asm/processor.h>
 #include <asm/system.h>
 
 /*
index 2a373ed60af4ebbd5d11ea9b3d69fe99eed94dbf..3447659302cd4782227952c7c73fc4b690abd95f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.13 2000/07/06 01:41:45 davem Exp $ */
+/* $Id: fcntl.h,v 1.14 2000/08/12 20:49:49 jj Exp $ */
 #ifndef _SPARC_FCNTL_H
 #define _SPARC_FCNTL_H
 
 #define F_SETSIG       10      /*  for sockets. */
 #define F_GETSIG       11      /*  for sockets. */
 
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
 
@@ -62,4 +66,13 @@ struct flock {
        short __unused;
 };
 
+struct flock64 {
+       short l_type;
+       short l_whence;
+       loff_t l_start;
+       loff_t l_len;
+       pid_t l_pid;
+       short __unused;
+};
+
 #endif
index e6dac360b1f46165790ad24b079d3868b53de553..6dc3569429a274c39377edf606c1c110d08001da 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.67 2000/08/12 13:25:51 davem Exp $ */
+/* $Id: unistd.h,v 1.68 2000/08/12 20:49:49 jj Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
 /* #define __NR_putmsg          152    SunOS Specific                              */
 #define __NR_poll               153 /* Common                                      */
 #define __NR_getdents64                154 /* Linux specific                              */
-/* #define __NR_nfssvc          155    SunOS Specific                              */
+#define __NR_fstat64           155 /* Linux sparc32 Specific                      */
 /* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
 #define __NR_fstatfs            158 /* Common                                      */
index 00d73f44418c6d37266343d3d0414040f2b875e8..bd087fc215011483e6e8fd708ff7745a5e189a70 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.9 2000/08/12 13:25:53 davem Exp $ */
+/* $Id: fcntl.h,v 1.10 2000/08/12 20:49:49 jj Exp $ */
 #ifndef _SPARC64_FCNTL_H
 #define _SPARC64_FCNTL_H
 
 #define F_SETSIG       10      /*  for sockets. */
 #define F_GETSIG       11      /*  for sockets. */
 
+#ifdef __KERNEL__
+#define F_GETLK64      12
+#define F_SETLK64      13
+#define F_SETLKW64     14
+#endif
+
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC     1       /* actually anything with low bit set goes */
 
index 3218e00dd54bc9f9f14e14eb1bbb4d9f604aae66..44210c08efdc99f031e3f36ea38996d6467dbf1c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: openprom.h,v 1.7 1998/03/15 10:14:47 ecd Exp $ */
+/* $Id: openprom.h,v 1.8 2000/08/12 19:55:25 anton Exp $ */
 #ifndef __SPARC64_OPENPROM_H
 #define __SPARC64_OPENPROM_H
 
@@ -8,12 +8,6 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-/* Empirical constants... */
-#define KADB_DEBUGGER_BEGVM     0xffc00000    /* Where kern debugger is in virt-mem */
-#define        LINUX_OPPROM_BEGVM      0xffd00000
-#define        LINUX_OPPROM_ENDVM      0xfff00000
-#define        LINUX_OPPROM_MAGIC      0x10010407
-
 #ifndef __ASSEMBLY__
 /* V0 prom device operations. */
 struct linux_dev_v0_funcs {
index 9781003bd5ea3a28830cdb9fa58a75cf485873f6..e66e4abd6f98e7057f13ef65466884d948880950 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.45 2000/08/12 13:25:52 davem Exp $ */
+/* $Id: unistd.h,v 1.46 2000/08/12 20:49:49 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
 /* #define __NR_putmsg          152    SunOS Specific                              */
 #define __NR_poll               153 /* Common                                      */
 #define __NR_getdents64                154 /* Linux specific                              */
-/* #define __NR_nfssvc          155    SunOS Specific                              */
+/* #define __NR_fstat64         155    Linux sparc32 Specific                      */
 /* #define __NR_getdirentries   156    SunOS Specific                              */
 #define __NR_statfs             157 /* Common                                      */
 #define __NR_fstatfs            158 /* Common                                      */
index a350944506a5553817b86ba23d4deed0dceb4b45..166fa085baa2ab2acbe08e7690c37a714a6139c2 100644 (file)
@@ -50,8 +50,9 @@ enum chipset_type {
        VIA_VP3,
        VIA_MVP3,
        VIA_MVP4,
-       VIA_APOLLO_SUPER,
        VIA_APOLLO_PRO,
+       VIA_APOLLO_KX133,
+       VIA_APOLLO_KT133,
        SIS_GENERIC,
        AMD_GENERIC,
        AMD_IRONGATE,
index 4905550fd4afb3232638e31b954242e822967eef..3ce2c58bdeed8a9c74c57266d1934044cf7c9d0f 100644 (file)
@@ -71,8 +71,6 @@ extern int max_super_blocks, nr_super_blocks;
 #define READA 2                /* read-ahead  - don't block if no resources */
 #define SPECIAL 4      /* For non-blockdevice requests in request queue */
 
-#define WRITERAW 5     /* raw write - don't play with buffer lists */
-
 #define SEL_IN         1
 #define SEL_OUT                2
 #define SEL_EX         4
index 26a3d3ad5b59da588770aad6ad18360af19f882e..049815fb29c5998cdcfd11fea179a693de0718e0 100644 (file)
@@ -95,7 +95,6 @@ extern void sysctl_init(void);
 extern void signals_init(void);
 extern void bdev_init(void);
 extern int init_pcmcia_ds(void);
-extern int usb_init(void);
 
 extern void free_initmem(void);
 extern void filesystem_setup(void);
@@ -686,10 +685,6 @@ static void __init do_basic_setup(void)
 #ifdef CONFIG_ISAPNP
        isapnp_init();
 #endif
-#ifdef CONFIG_USB
-       usb_init();     /* Do this before doing initcalls, so that we can make
-                       usbcore initialize here, and all drivers initialize later */
-#endif
 #ifdef CONFIG_TC
        tc_init();
 #endif
index f4ecf6fcc8ad6f021d7c9e0ab100f9db03a74a79..7467dfaf0268f5c22534adc0c2a7135d0442f188 100644 (file)
@@ -51,7 +51,7 @@ match_sid(const struct sk_buff *skb, pid_t sid)
 
        read_lock(&tasklist_lock);
        for_each_task(p) {
-               struct file *files;
+               struct files_struct *files;
                if (p->session != sid)
                        continue;
 
index 8cf2b4a824e63b86e9861f893c1287c7f006e62f..6f4f716f8c15d00523c9378a8956f2ec2f82257a 100644 (file)
@@ -23,7 +23,6 @@ if [ "$CONFIG_NET" != "n" ]; then
    fi
 
    if [ "$CONFIG_IRDA" != "n" ]; then
-      source net/irda/compressors/Config.in
       source drivers/net/irda/Config.in
    fi
    endmenu
index bb8b98bca9be6ea68cf55704494a1cf8e865d25a..015630d2e106e407c0bd578bba444511b0c89966 100644 (file)
@@ -440,10 +440,10 @@ struct socket *sock_alloc(void)
        struct socket * sock;
 
        inode = get_empty_inode();
-       inode->i_sb = sock_mnt->mnt_sb;
        if (!inode)
                return NULL;
 
+       inode->i_sb = sock_mnt->mnt_sb;
        sock = socki_lookup(inode);
 
        inode->i_mode = S_IFSOCK|S_IRWXUGO;
@@ -1712,6 +1712,9 @@ void __init sock_init(void)
 
        proto_init();
 
+       register_filesystem(&sock_fs_type);
+       sock_mnt = kern_mount(&sock_fs_type);
+
        /*
         *      The netlink device handler may be needed early.
         */
@@ -1725,8 +1728,6 @@ void __init sock_init(void)
 #ifdef CONFIG_NETFILTER
        netfilter_init();
 #endif
-       register_filesystem(&sock_fs_type);
-       sock_mnt = kern_mount(&sock_fs_type);
 }
 
 int socket_get_info(char *buffer, char **start, off_t offset, int length)