]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.6 2.1.6
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:36 +0000 (15:12 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:36 +0000 (15:12 -0500)
401 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/networking/z8530drv.txt
MAINTAINERS
Makefile
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/time.c
arch/alpha/kernel/traps.c
arch/alpha/math-emu/fp-emul.c
arch/alpha/mm/fault.c
arch/alpha/mm/init.c
arch/i386/kernel/ksyms.c
arch/i386/kernel/ldt.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/sys_i386.c
arch/i386/kernel/time.c
arch/i386/kernel/traps.c
arch/i386/kernel/vm86.c
arch/i386/math-emu/README
arch/i386/math-emu/errors.c
arch/i386/math-emu/fpu_entry.c
arch/i386/math-emu/get_address.c
arch/i386/math-emu/load_store.c
arch/i386/math-emu/reg_ld_str.c
arch/i386/mm/fault.c
arch/i386/mm/init.c
drivers/block/floppy.c
drivers/block/hd.c
drivers/block/ide-cd.c
drivers/block/ide-tape.c
drivers/block/ide.c
drivers/block/loop.c
drivers/block/rd.c
drivers/block/umc8672.c
drivers/block/xd.c
drivers/cdrom/aztcd.c
drivers/cdrom/cdu31a.c
drivers/cdrom/gscd.c
drivers/cdrom/mcd.c
drivers/cdrom/sbpcd.c
drivers/cdrom/sjcd.c
drivers/cdrom/sonycd535.c
drivers/char/Makefile
drivers/char/README.scc
drivers/char/amigamouse.c
drivers/char/apm_bios.c
drivers/char/atarimouse.c
drivers/char/atixlmouse.c
drivers/char/baycom.c
drivers/char/busmouse.c
drivers/char/console.c
drivers/char/consolemap.c
drivers/char/cyclades.c
drivers/char/fbmem.c
drivers/char/lp.c
drivers/char/lp_m68k.c
drivers/char/mem.c
drivers/char/msbusmouse.c
drivers/char/n_tty.c
drivers/char/pcxx.c
drivers/char/psaux.c
drivers/char/pty.c
drivers/char/random.c
drivers/char/rtc.c
drivers/char/scc.c [deleted file]
drivers/char/selection.c
drivers/char/serial.c
drivers/char/stallion.c
drivers/char/tga.c
drivers/char/tpqic02.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/vc_screen.c
drivers/char/vesa_blank.c
drivers/char/vga.c
drivers/char/vt.c
drivers/char/wdt.c
drivers/isdn/isdn_common.c
drivers/isdn/isdn_net.c
drivers/isdn/isdn_ppp.c
drivers/isdn/isdn_tty.c
drivers/isdn/teles/callc.c
drivers/isdn/teles/card.c
drivers/isdn/teles/config.c
drivers/isdn/teles/llglue.c
drivers/isdn/teles/mod.c
drivers/isdn/teles/teles.h
drivers/net/3c59x.c
drivers/net/8390.c
drivers/net/Makefile
drivers/net/README.scc [new file with mode: 0644]
drivers/net/arcnet.c
drivers/net/bsd_comp.c
drivers/net/de4x5.c
drivers/net/depca.c
drivers/net/ewrk3.c
drivers/net/loopback.c
drivers/net/pi2.c
drivers/net/ppp.c
drivers/net/pt.c
drivers/net/scc.c [new file with mode: 0644]
drivers/net/slhc.c
drivers/net/slip.c
drivers/net/strip.c
drivers/net/z8530.h
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/Config.in
drivers/scsi/NCR5380.c
drivers/scsi/README.FlashPoint
drivers/scsi/aic7xxx.c
drivers/scsi/eata_dma.c
drivers/scsi/eata_dma.h
drivers/scsi/eata_generic.h
drivers/scsi/hosts.c
drivers/scsi/scsi.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/sd.c
drivers/scsi/sd_ioctl.c
drivers/scsi/seagate.c
drivers/scsi/sg.c
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/sound/.object_files [deleted file]
drivers/sound/.objects
drivers/sound/.version
drivers/sound/CHANGELOG
drivers/sound/Config.in
drivers/sound/Config.std
drivers/sound/Makefile
drivers/sound/Readme
drivers/sound/Readme.aedsp16
drivers/sound/Readme.cards
drivers/sound/Readme.linux
drivers/sound/ad1848.c
drivers/sound/ad1848_mixer.h
drivers/sound/adlib_card.c
drivers/sound/aedsp16.c
drivers/sound/audio.c
drivers/sound/configure.c
drivers/sound/cs4232.c
drivers/sound/dev_table.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/dmasound.c [deleted file]
drivers/sound/dmasound.h [deleted file]
drivers/sound/finetune.h
drivers/sound/gus_card.c
drivers/sound/gus_midi.c
drivers/sound/gus_vol.c
drivers/sound/gus_wave.c
drivers/sound/ics2101.c
drivers/sound/iwmem.h
drivers/sound/lowlevel/ChangeLog.awe [new file with mode: 0644]
drivers/sound/lowlevel/Config.tmpl
drivers/sound/lowlevel/Makefile
drivers/sound/lowlevel/README
drivers/sound/lowlevel/README.awe [new file with mode: 0644]
drivers/sound/lowlevel/aci.c
drivers/sound/lowlevel/awe_hw.h [new file with mode: 0644]
drivers/sound/lowlevel/awe_voice.h [new file with mode: 0644]
drivers/sound/lowlevel/awe_wave.c [new file with mode: 0644]
drivers/sound/lowlevel/init.c
drivers/sound/lowlevel/lowlevel.h [new file with mode: 0644]
drivers/sound/mad16.c
drivers/sound/maui.c
drivers/sound/midi_synth.c
drivers/sound/midibuf.c
drivers/sound/mpu401.c
drivers/sound/opl3.c
drivers/sound/opl3.h
drivers/sound/os.h
drivers/sound/pas2_card.c
drivers/sound/pas2_midi.c
drivers/sound/pas2_mixer.c
drivers/sound/pas2_pcm.c
drivers/sound/patmgr.c
drivers/sound/pss.c
drivers/sound/sb.h
drivers/sound/sb_audio.c
drivers/sound/sb_card.c
drivers/sound/sb_common.c
drivers/sound/sb_midi.c
drivers/sound/sb_mixer.c
drivers/sound/sb_mixer.h
drivers/sound/sequencer.c
drivers/sound/sound_calls.h
drivers/sound/sound_config.h
drivers/sound/sound_switch.c
drivers/sound/sound_timer.c
drivers/sound/soundcard.c
drivers/sound/soundvers.h
drivers/sound/sscape.c
drivers/sound/sys_timer.c
drivers/sound/trix.c
drivers/sound/uart401.c
drivers/sound/uart6850.c
fs/affs/dir.c
fs/affs/file.c
fs/affs/inode.c
fs/affs/namei.c
fs/affs/symlink.c
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/block_dev.c
fs/buffer.c
fs/dquot.c
fs/exec.c
fs/ext/dir.c
fs/ext/file.c
fs/ext/fsync.c
fs/ext/inode.c
fs/ext/namei.c
fs/ext/symlink.c
fs/ext2/dir.c
fs/ext2/file.c
fs/ext2/fsync.c
fs/ext2/inode.c
fs/ext2/ioctl.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext2/symlink.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/mmap.c
fs/fcntl.c
fs/hpfs/hpfs_fs.c
fs/ioctl.c
fs/isofs/dir.c
fs/isofs/inode.c
fs/isofs/namei.c
fs/isofs/symlink.c
fs/locks.c
fs/minix/dir.c
fs/minix/file.c
fs/minix/fsync.c
fs/minix/inode.c
fs/minix/namei.c
fs/minix/symlink.c
fs/msdos/namei.c
fs/namei.c
fs/ncpfs/dir.c
fs/ncpfs/file.c
fs/ncpfs/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/mmap.c
fs/ncpfs/sock.c
fs/nfs/bio.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfsroot.c
fs/nfs/proc.c
fs/nfs/rpcsock.c
fs/nfs/sock.c
fs/nfs/symlink.c
fs/noquot.c
fs/open.c
fs/pipe.c
fs/proc/array.c
fs/proc/base.c
fs/proc/fd.c
fs/proc/inode.c
fs/proc/kmsg.c
fs/proc/link.c
fs/proc/mem.c
fs/proc/net.c
fs/proc/root.c
fs/proc/scsi.c
fs/read_write.c
fs/readdir.c
fs/select.c
fs/smbfs/dir.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/ioctl.c
fs/smbfs/mmap.c
fs/smbfs/proc.c
fs/smbfs/sock.c
fs/stat.c
fs/super.c
fs/sysv/dir.c
fs/sysv/file.c
fs/sysv/inode.c
fs/sysv/symlink.c
fs/ufs/ufs_super.c
fs/ufs/ufs_symlink.c
fs/umsdos/dir.c
fs/umsdos/emd.c
fs/umsdos/file.c
fs/umsdos/inode.c
fs/umsdos/ioctl.c
fs/umsdos/rdir.c
fs/umsdos/symlink.c
fs/vfat/namei.c
fs/xiafs/dir.c
fs/xiafs/file.c
fs/xiafs/fsync.c
fs/xiafs/inode.c
fs/xiafs/namei.c
fs/xiafs/symlink.c
include/asm-alpha/segment.h
include/asm-alpha/uaccess.h [new file with mode: 0644]
include/asm-i386/elf.h
include/asm-i386/segment.h
include/asm-i386/string-486.h
include/asm-i386/uaccess.h [new file with mode: 0644]
include/linux/fs.h
include/linux/mm.h
include/linux/proc_fs.h
include/linux/raid0.h
include/linux/scc.h
include/linux/soundcard.h
include/linux/ultrasound.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
kernel/exit.c
kernel/fork.c
kernel/info.c
kernel/itimer.c
kernel/module.c
kernel/panic.c
kernel/printk.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/time.c
mm/filemap.c
mm/memory.c
mm/mlock.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/page_alloc.c
mm/page_io.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
net/802/tr.c
net/appletalk/aarp.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/ax25/ax25_in.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/bridge/br.c
net/core/datagram.c
net/core/dev.c
net/core/dev_mcast.c
net/core/iovec.c
net/core/skbuff.c
net/core/sock.c
net/ethernet/eth.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_fragment.c
net/ipv4/ip_fw.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipmr.c
net/ipv4/packet.c
net/ipv4/protocol.c
net/ipv4/rarp.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/ipv4/utils.c
net/ipx/af_ipx.c
net/netlink.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/netrom/nr_in.c
net/netrom/nr_out.c
net/netrom/nr_route.c
net/netrom/nr_subr.c
net/netrom/nr_timer.c
net/socket.c
net/unix/af_unix.c
net/unix/garbage.c
scripts/Menuconfig

diff --git a/CREDITS b/CREDITS
index 88ee58ac4cf9ed41efcb0fa32ff9d42cc99cdc94..4b1cd4fcef9d42a412eaca524368b7e25c12edfe 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -927,7 +927,7 @@ S: Fairfax, Virginia 22033
 S: USA
 
 N: William (Bill) Metzenthen
-E: billm@jacobi.maths.monash.edu.au
+E: billm@suburbia.net
 D: Author of the FPU emulator.
 D: Minor kernel hacker for other lost causes (Hercules mono, etc).
 S: 22 Parker Street
@@ -1118,6 +1118,12 @@ S: Rebmannsweg 34h
 S: 79539 Loerrach
 S: Germany
 
+N: Joerg Reuter
+E: jreuter@lykos.oche.de
+E: dl1bke@db0pra.ampr.org
+D: Generic Z8530 driver, AX.25 DAMA slave implementation
+D: Several AX.25 hacks
+
 N: William E. Roadcap
 E: roadcapw@cfw.com
 W: http://www.cfw.com/~roadcapw
index 9485b79b69ab9c8fadc9a4b3a5fcdf595295ae4f..b060c96330f88fa58f90a2f29eb23f818e4f4a76 100644 (file)
@@ -103,49 +103,67 @@ option is present.  Many older distributions (mainly Slackware) have
 this option in their lilo.config file.  Comment it out and re-run lilo
 if you need ramdisks.
 
+Module load errors
+==================
+
+   The 386 Linux kernel versions 2.1.0 and above have moved to address
+0xc0000000.  This means that syscalls that return an address in the
+kernel area will return a value that is a negative 32 bit number.
+Versions of libc prior to libc-5.4.8 will interpret the negative value
+as an error.  In particular, this prevents modules from loading.  You
+need at least libc-5.4.10 to load modules successfully again.
+
+
 The Linux C Library
 ===================
 
-   The latest stable Linux C Library release is 5.2.18.  If you upgrade
-to this from 5.0.9 or earlier, be sure to read the
-`release.libc-5.2.18' file, since GNU make and a few other fairly
-important utils can be broken by the upgrade.
-
-   The current (beta) Linux C Library release is 5.3.12. In this
-release there are some important changes that may cause troubles to
-buggy programs (programs that call free() on a pointer not returned by
-malloc() work with previous libc, but not with this release) so read the
-`release.libc-5.3.12' file carefully!  In the latest libc releases a
-dirent bug, which erroneously defined d->reclen to d->namlen if USE_GNU
-was defined, has been fixed.  Unfortunately, some GNU packages depend
-on this bug.  GNU make 3.xx is one of them.  To fix that you need to
-patch and recompile those programs (a patch for make is included in the
-file `release.libc-.5.3.9', and the address to obtain a precompiled
-binary is at the end of this file).
-
-   Also, the libc-5.3.x line has a known security hole relating to
-rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.
-
-   If you're getting an error message that is something to the effect of
+   Before upgrading your C library, be sure to carefully read the
+`release.libc-x.y.z' file. (x.y.z is the version number eg. 5.4.7)
+
+- GNU make, perl, and a few other important utils can be broken by the
+  upgrade.  A dirent bug, which erroneously defined d->reclen to
+  d->namlen if USE_GNU was defined, has been fixed.  Unfortunately,
+  some GNU packages depend on this bug.  GNU make 3.xx is one of them.
+  To fix that you need to patch and recompile those programs (a patch
+  for make is included in the file `release.libc-x.y.z', and the
+  address to obtain a precompiled binary is at the end of this file).
+
+- Upgrading libc can also break xterm support.  If it does, you need
+  to recompile xterm.
+
+- There have been some important changes to libc that may cause
+  trouble with buggy programs.  Programs that call free() on a pointer
+  not returned by malloc() work with older versions of libc, but not
+  with newer versions of libc.
+
+
+There are good reasons to upgrade your libc though!
+
+- If you use modules, you'll need libc-5.4.10 or later with version
+  2.1.x i386 kernels
+
+- The libc-5.3.x line before libc-5.3.12 have a known security hole
+  relating to rlogin.  Another security fix was done in libc-5.4.7.
+
+- If you're getting an error message that is something like
 
    `fcntl_setlk() called by process 123 with broken flock() emulation'
 
-   then you need to upgrade to at least libc-5.2.18 as well.  A proper
-(in other words, BSD-style ;-) flock system call was added to 2.0.x,
-and older libc's will now give this error.  It doesn't *really* matter,
-so you can just ignore it. If it really annoys you, upgrade libc (and
-recompile any static binaries you might have that are linked against
-the old libc).  If you're feeling lazy, just comment out
+  then you need to upgrade to at least libc-5.2.18.  A proper (in
+  other words, BSD-style ;-) flock system call was added to 2.0.x, and
+  older libc's will now give this error.  It doesn't *really* matter,
+  so you can just ignore it. If it really annoys you, upgrade libc
+  (and recompile any static binaries you might have that are linked
+  against the old libc).  If you're feeling lazy, just comment out
+
+  `printk(KERN_WARNING
+    "fcntl_setlk() called by process %d with broken flock() emulation\n",
+     current->pid);'
 
-   `                printk(KERN_WARNING
-"fcntl_setlk() called by process %d with broken flock()
-  emulation\n",                        current->pid);'
+  in linux/fs/locks.c and recompile.  If you're still running a.out,
+  there's an unofficial libc-4.7.6 to which you can upgrade to fix
+  this problem.
 
-   in linux/fs/locks.c and recompile.  If you're still running a.out,
-there's an unofficial libc-4.7.6 release out to which you can upgrade
-to fix this problem.  Libc is available from
-ftp://sunsite.unc.edu/pub/Linux/GCC/.
 
 GCC Signal 11 error
 ===================
@@ -416,11 +434,9 @@ Make
    If make no longer works, you need to read the release notes for the
 libc you upgraded to.  The latest libc and release notes can be found at
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC.  This is NOT an error due
-to the kernel, though many people have mistakenly thought it is.  When
-you upgrade to libc-5.3.9, you have to patch make to get it to work.
-All of this is documented in the release notes with libc.  Upgrading
-libc can also break xterm support.  If it does, you need to recompile
-xterm.
+to the kernel, though many people have mistakenly thought it was.  When
+you upgrade to libc-5.3.9 or later, from previous versions, you have
+to patch make to get it to work.
 
 Loop device
 ===========
@@ -605,15 +621,15 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2
 Linux C Library
 ===============
 
-The stable 5.2.18 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.2.18.bin.tar.gz
-Installation notes for 5.2.18:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
+The stable 5.4.7 release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.7.bin.tar.gz
+Installation notes for 5.4.7:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.7
 
-The latest 5.3.12 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.3.12.bin.tar.gz
-Installation notes for 5.3.12:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.3.12
+The latest release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/private/tofu/libc-x.y.z.bin.tar.gz
+Installation notes for x.y.z:
+ftp://sunsite.unc.edu/pub/Linux/GCC/private/tofu/release.libc-x.y.z
 
 Patched make sources:
 ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz
@@ -623,12 +639,16 @@ ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74-direntfix-elf.tgz
 Linux C++ Library
 =================
 
+ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.4.bin.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.3.bin.tar.gz
 Installation notes:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.4
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.3
-Use 2.7.13 with libc 5.2.18 and 2.7.14 with libc 5.3.12.
+Use libg++-2.7.2.1 with libc-5.4.4 and above,
+    libg++-2.7.1.4 with libc-5.3.5 to libc-5.4.3,
+    libg++-2.7.1.3 with libc 5.2.14 to libc-5.3.4
 
 Dynamic Linker
 ==============
@@ -713,4 +733,3 @@ Chris Ricker (gt1355b@prism.gatech.edu).  I generate this from a
 modified texinfo setup, so you don't need to bother generating a diff
 against the current version before you send the additional information
 to me.
-
index bda2615581dbf51446d525e5143bd2a3e6c01cac..90aee7f3eed79473fb8752718e3f7777441910a8 100644 (file)
@@ -1864,11 +1864,11 @@ CONFIG_WIC
   code which can be inserted in and removed from the running kernel
   whenever you want), say M here and read Documentation/modules.txt.
 
-Z8530 SCC kiss emulation driver for AX.25
+Z8530 SCC driver for AX.25
 CONFIG_SCC
   These cards are used to connect your Linux box to an amateur radio
   in order to communicate with other computers.  If you want to use
-  this, read Documentation/networking/z8530drv.txt and the HAM-HOWTO,
+  this, read Documentation/networking/z8530drv.txt and the AX.25-HOWTO,
   available via ftp (user: anonymous) at
   sunsite.unc.edu:/pub/Linux/docs/HOWTO.  If you want to compile this
   as a module ( = code which can be inserted in and removed from the
index f7df36efbfce4edb6be720bd58a7f11a84469cd5..67c842ee600eef0e3f3f07d05fad1ad521ffd593 100644 (file)
@@ -4,24 +4,22 @@ full package from:
 Internet:
 =========
 
-ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-2.0.dl1bke.real.tar.gz
+1. db0bm.automation.fh-aachen.de/incoming/dl1bke/z8530drv-utils-3.0.tar.gz
 
-[
-  if you can't find it there, try:
-  .../tcpip/linux/z8530drv-2.0.dl1bke.tar.gz
-
-]
+2. ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz
+   If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
 
 and various mirrors (i.e. nic.switch.ch)
 
----------------------------------------------------------------------------
+Please note that the information in this document may be hopelessly outdated.
+-----------------------------------------------------------------------------
 
 
         SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      
 
    ********************************************************************
 
-        (c) 1993,1995 by Joerg Reuter DL1BKE
+        (c) 1993,1996 by Joerg Reuter DL1BKE <jreuter@lykos.oche.de>
 
         portions (c) 1993 Guido ten Dolle PE1NNZ
 
@@ -37,7 +35,12 @@ To use the driver, 3 steps must be performed:
 
      1. if compiled as module: loading the module
      2. Setup of hardware, MODEM and KISS parameters with sccinit
-     3. Attachment of each channel in the packet software
+     3. Attach each channel to the Linux kernel AX.25 with "ifconfig"
+
+Unlike the versions below 2.4 this driver is a real network device
+driver. If you want to run xNOS instead of our fine kernel AX.25
+use a 2.x version (available from above sites) or read the
+AX.25-HOWTO on how to emulate a KISS TNC on network device drivers.
 
 
 1.1 Loading the module
@@ -54,15 +57,14 @@ please read 'man insmod' that comes with modutils.
 
 You should include the insmod in one of the /etc/rc.d/rc.* files,
 and don't forget to insert a call of sccinit after that. It
-will read  your
+will read your /etc/z8530drv.conf.
 
-
-1.2. /etc/z8530drv.rc
-=====================
+1.2. /etc/z8530drv.conf
+=======================
 
 To setup all parameters you must run /sbin/sccinit from one
-of your rc.*-files. This has to be done BEFORE the start of
-NET or axattach. Sccinit reads the file /etc/z8530drv.rc
+of your rc.*-files. This has to be done BEFORE you can
+"ifconfig" an interface. Sccinit reads the file /etc/z8530drv.conf
 and sets the hardware, MODEM and KISS parameters. A sample file is
 delivered with this package. Change it to your needs.
 
@@ -222,7 +224,7 @@ not appear. Example:
 
 gencfg 2 0x150 4 2 0 1 0x168 9 4915200 
 
-will print a skeleton z8530drv.rc for the OptoSCC to stdout.
+will print a skeleton z8530drv.conf for the OptoSCC to stdout.
 
 gencfg 2 0x300 2 4 5 -4 0 7 4915200 0x10
 
@@ -236,11 +238,11 @@ to edit scc_config.h...
 The channel definition is divided into three sub sections for each
 channel:
 
-An example for /dev/scc0:
+An example for scc0:
 
 # DEVICE
 
-device /dev/scc0       # the device for the following params
+device scc0    # the device for the following params
 
 # MODEM / BUFFERS
 
@@ -254,10 +256,6 @@ mode nrzi          # HDLC encoding mode
                        #       nrzi = 1k2 MODEM, G3RUH 9k6 MODEM
                        #       nrz  = DF9IC 9k6 MODEM
                        #
-rxbuffers 8            # number of rx buffers allocated
-                       #               (option, default is 4)
-txbuffers 16           # number of tx buffers allocated
-                       #               (option, default is 16)
 bufsize        384             # size of buffers. Note that this must include
                        # the AX.25 header, not only the data field!
                        # (optional, defaults to 384)
@@ -283,9 +281,10 @@ The order WITHIN these sections is unimportant. The order OF these
 sections IS important. The MODEM parameters are set with the first
 recognized KISS parameter...
 
-Please note that you can initialize the board only once after boot. 
-You can change all parameters but "mode" and "clock" later with the
-Sccparam program or through KISS. Just to avoid security holes... 
+Please note that you can initialize the board only once after boot
+(or insmod). You can change all parameters but "mode" and "clock" 
+later with the Sccparam program or through KISS. Just to avoid 
+security holes... 
 
 (1) this divider is usually mounted on the SCC-PBC (PA0HZP) or not
     present at all (BayCom). It feeds back the output of the DPLL 
@@ -293,71 +292,56 @@ Sccparam program or through KISS. Just to avoid security holes...
     installed will normally result in keying the transceiver until 
     maxkey expires --- of course without sending anything (useful).
 
-
 2. Attachment of a channel by your AX.25 software
 =================================================
 
-2.1 KA9Q NOS derivates
-======================
+2.1 Kernel AX.25
+================
 
-When the linux has startup, the SCC driver has been initialized,
-you can attach the channels in your packet software. This is done
-by open the scc devices by using the attach asy command.
-The SCC-drivers emulates the scc devices as serial asy ports,
-this means e.g. that the baudrate can be set in the attach command.
+To set up an AX.25 device you can simply type:
 
+       ifconfig scc0 44.128.1.1 hw ax25 dl0tha-7
 
-Example Wampes:
+This will create a network interface with the IP number 44.128.20.107 
+and the callsign "dl0tha". If you do not have any IP number (yet) you 
+can use any of the 44.128.0.0 network. Note that you do not need 
+axattach. The purpose of axattach (like slattach) is to create a KISS 
+network device linked to a TTY. Please read the documentation of the 
+ax25-utils and the AX.25-HOWTO to learn how to set the parameters of
+the kernel AX.25.
 
-#############################################################################################
-# Wampes device attach
-# NOTE: Interfacename and the device must be the same!!
-# Usage: attach asy 0 0 slip|vjslip|ax25ui|ax25i|nrs|kissui <label> 0 <mtu> <speed> [ip_addr]
-#
-attach asy 0 0 kissi  scc0 256 256 1200   # Attach SCC channel 1 in 1200 baud
-attach asy 0 0 kissi  scc1 256 256 1200   # Attach SCC channel 2 in 1200 baud
-attach asy 0 0 kissui scc2 256 256 38400  # Attach SCC channel 3 in 38400 baud
-attach asy 0 0 kissui scc3 256 256 9600   # Attach SCC channel 4 in 9600 baud
-#              ^^^^
-#              for WAMPES 921229 use here: ax25
-#
+2.2 NOS, NET and TFKISS
+=======================
 
-Example JNOS:
+Since the TTY driver (aka KISS TNC emulation) is gone you need
+to emulate the old behaviour. The cost using these programs is
+that you probably need to compile the kernel AX.25, regardless 
+if you actually use it or not. First setup your /etc/ax25/axports,
+for example:
 
-############################################
-# JNOS device attach
-#
-attach asy scc0 0 ax25 scc0 256 256 1200
-attach asy scc1 0 ax25 scc1 256 256 1200
-attach asy scc2 0 ax25 scc2 256 256 300
-attach asy scc3 0 ax25 scc3 256 256 4800
-#
-#
+       9k6     dl0tha-9  9600  255 4 9600 baud port (scc3)
+       axlink  dl0tha-15 38400 255 4 Link to NOS
 
+Now "ifconfig" the scc device:
 
-It allows AX.25 communication without a TNC.  Only a MODEM is
-needed. The parameters have the same meaning as in KISS mode.
-In fact, the AX.25 mode is emulating an extended KISS TNC, so
-the same commands can be used to set the parameters of the
-interface (see below).
+       ifconfig scc3 44.128.1.1 hw ax25 dl0tha-9
 
-To be able to run fullduplex using an SCC in AX.25 mode, an 
-external divider must be available, that divides the baudrate 
-generator clock available on the TRxC pin by 32, and puts the 
-resulting signal on the RTxC pint of the same channel of the SCC.  
-Such a divider is not necessary for normal CSMA packet radio 
-operation, but interrupt overhead is slightly reduced if you 
-still install it.  
+You can now axattach a pseudo-TTY:
 
-2.2 Kernel AX.25
-================
+       axattach /dev/ptys0 axlink
 
-Well, as said before: The driver emulates a KISS TNC, so you
-can simply run
+and start your NOS and attach /dev/ptys0 there. The problem is that
+NOS is reachable only via digipeating through the kernel AX.25
+(disasterous on a DAMA controlled channel). To solve this problem,
+configure "rxecho" to echo the incoming frames from "9k6" to "axlink"
+and outgoing frames from "axlink" to "9k6" and start:
 
-       axattach -s 1200 /dev/scc0 DL1BKE
+       rxecho
 
-to establish the link between kernel AX.25 and z8530drv.
+Or simply use "kissbridge" coming with z8530drv-utils:
+
+       ifconfig scc3 hw ax25 dl0tha-9
+       kissbridge scc3 /dev/ptys0
 
 
 3. Adjustment and Display of parameters
@@ -369,7 +353,7 @@ to establish the link between kernel AX.25 and z8530drv.
 Once a SCC channel has been attached, the parameter settings and 
 some statistic information can be shown using the param program:
 
-dl1bke-u:~$ sccstat /dev/scc0
+dl1bke-u:~$ sccstat scc0
 
 Parameters:
 
@@ -391,43 +375,35 @@ SLIP        : off
 
 Status:
 
-HDLC                  Z8530           Interrupts         Queues
+HDLC                  Z8530           Interrupts         Buffers
 -----------------------------------------------------------------------
-Sent       :     273  RxOver :     0  RxInts :   125074  RxQueue :    0
-Received   :    1095  TxUnder:     0  TxInts :     4684  TxQueue :    0
-RxErrors   :    1591                  ExInts :    11776  NoSpace :    0
-KissErrors :       0                  SpInts :     1503
+Sent       :     273  RxOver :     0  RxInts :   125074  Size    :  384
+Received   :    1095  TxUnder:     0  TxInts :     4684  NoSpace :    0
+RxErrors   :    1591                  ExInts :    11776
+TxErrors   :       0                  SpInts :     1503
 Tx State   :    idle
 
-Memory allocated:
-
-Buffer size:     384
-rx buffers :       4
-tx buffers :       8
-
 
 The status info shown is:
 
 Sent           - number of frames transmitted
 Received       - number of frames received
 RxErrors       - number of receive errors (CRC, ABORT)
-KissErrors     - number of KISS errors (should be zero...)
+TxErrors       - number of discarded Tx frames (due to various reasons) 
 Tx State       - status of the Tx interrupt handler: idle/busy/active/tail (2)
 RxOver         - number of receiver overruns
-TxUnder                - number of transmitter underruns     
+TxUnder                - number of transmitter underruns
 RxInts         - number of receiver interrupts
 TxInts         - number of transmitter interrupts
 EpInts         - number of receiver special condition interrupts
 SpInts         - number of external/status interrupts
-RxQueue                - number of received packets enqueued for this channel
-TxQueue                - number of packets enqueued for Tx
-NoSpace                - number of times the receiver buffer pool was found empty
-
+Size           - maximum size of an AX.25 frame (*with* AX.25 headers!)
+NoSpace                - number of times a buffer could not get allocated
 
 An overrun is abnormal. If lots of these occur, the product of
 baudrate and number of interfaces is too high for the processing
-power of you computer. If "Space" errors occur, specify a higher
-number of buffers in the "scc.h" file.
+power of you computer. NoSpace errors are unlikely caused by the
+driver or the kernel AX.25.
 
 
 3.2 Setting Parameters
@@ -436,11 +412,8 @@ number of buffers in the "scc.h" file.
 
 The setting of parameters of the emulated KISS TNC is done in the 
 same way in the SCC driver. You can change parameters by using
-the command param in NET or NOS
-
-     param <iface> <paramname> <value>
-
-or use the program "sccparam":
+the kissparms program from the ax25-utils package or use the program 
+"sccparam":
 
      sccparam <device> <paramname> <decimal-|hexadecimal value>
 
@@ -621,32 +594,25 @@ softdcd:
      Example: sccparam /dev/scc0 soft on
 
 
-slip:
-     use slip encoding instead of kiss
-
-     Example: sccparam /dev/scc1 slip on
-
-
-
 4. Problems 
 ===========
 
 If you have tx-problems with your BayCom USCC card please check
 the manufacturer of the 8530. SGS chips have a slightly
-different timing. Try Zilog... I have no information if this
-driver works with baudrates higher than 1200 baud. A solution is
-to write to register 8 instead to the data port, but this won't
-work with the ESCC chips *SIGH!*
+different timing. Try Zilog...  A solution is to write to register 8 
+instead to the data port, but this won't work with the ESCC chips. 
+*SIGH!*
+
+A very common problem is that the PTT locks until the maxkeyup timer
+expires, although interrupts and clock source are correct. In most
+cases #define SCC_DELAY solves the problems. For more hints read
+the (pseudo) FAQ and the documentation coming with z8530drv-utils.
 
 I got reports that the driver has problems on some 386-based systems.
 (i.e. Amstrad) Those systems have a bogus AT bus timing which will
 lead to delayed answers on interrupts. You can recognize these
 problems by looking at the output of Sccstat for the suspected
 port. See if it shows under- and overruns you own such a system.
-Perhaps it will help if you simplify the scc_isr() function a bit.
-You'll find a slightly faster version in the files scc_isr_intack
-or scc_isr_novec.
-
 
 Delayed processing of received data: This depends on
 
@@ -654,127 +620,24 @@ Delayed processing of received data: This depends on
 
 - kernel profiling compiled or not
 
-- the rather slow receiver in tty_io.c
-
 - a high interrupt load
 
 - a high load of the machine --- running X, Xmorph, XV and Povray,
   while compiling the kernel... hmm ... even with 32 MB RAM ...  ;-)
+  Or running a named for the whole .ampr.org. domain on an 8 MB
+  box...
 
-- NET's speed itself.
-
+- using information from rxecho or kissbridge.
 
 Kernel panics: please read to /linux/README and find out if it
 really occurred within the scc driver.
 
-If you can't solve a problem, send me
+If you cannot solve a problem, send me
 
 - a description of the problem,
 - information on your hardware (computer system, scc board, modem)
 - your kernel version
-- the output of sccstat /dev/scc# ("#" is the No. of the channel)
-- the settings of "speed", "clock" and "mode" for that channel
-  in /etc/z8530drv.rc
-- your scc_config.h
-
-
-And always remember: 
-The 1.1.* kernel series is for alpha tests -- use at your own risk ;-)
-The 1.2.* series should run reliable. This driver perhaps NOT!
-The 1.3.* kernel series is for alpha tests again... you get the idea!
-
-
-3. DRSI Boards
-==============
-
-I still can't test the DRSI board, but this configuration derived from
-the PE1CHL SCC driver configuration should work:
-
-An example of scc_config.h for 
-
-One DRSI board installed:
-=========================
-
-/* gencfg 1 0x300 0x10 2 0 1 0 7 4915200 */
-
-/* file generated by $Id: gencfg.c,v 1.2 1994/11/29 21:42:24 JReuter Exp JReuter $ */
-
-#include <linux/scc.h>
-
-int     Nchips      = 1;
-io_port Vector_Latch = 0x0;
-int     Ivec        = 7;
-long    Clock       = 4915200;
-char   Board        = PA0HZP;
-int    Option       = 0;
-io_port Special_Port = 0x0;
-
-io_port SCC_ctrl[MAXSCC * 2] =
-{0x302, 0x300, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
-io_port SCC_data[MAXSCC * 2] =
-{0x303, 0x301, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
-
-/* set to '1' if you have and want ESCC chip (8580/85180/85280) support */
-
-/*                                           Chip      */
-/*                                         ========    */
-int SCC_Enhanced[MAXSCC] =     {0,     /* ...one...    */
-                                0,     /* ...two...    */
-                                0,     /* ...three...  */
-                                0};    /* ...four...   */
-
-#define VERBOSE_BOOTMSG 1
-#undef  SCC_DELAY              /* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY             /* slow it even a bit more down */
-#undef  DONT_CHECK             /* don't look if the SCCs you specified are available */
-
-
-
-Two boards installed:
-=====================
-
-/* file generated by $Id: gencfg.c,v 1.2 1994/11/29 21:42:24 JReuter Exp JReuter $ */
-
-#include <linux/scc.h>
-
-int     Nchips      = 2;
-io_port Vector_Latch = 0x0;
-int     Ivec        = 7;
-long    Clock       = 4915200;
-char   Board        = PA0HZP;
-int    Option       = 0;
-io_port Special_Port = 0x0;
-
-io_port SCC_ctrl[MAXSCC * 2] =
-{0x302, 0x300, 0x312, 0x310, 0x0, 0x0, 0x0, 0x0};
-
-io_port SCC_data[MAXSCC * 2] =
-{0x303, 0x301, 0x313, 0x311, 0x0, 0x0, 0x0, 0x0};
-
-/* set to '1' if you have and want ESCC chip (8580/85180/85280) support */
-
-/*                                           Chip      */
-/*                                         ========    */
-int SCC_Enhanced[MAXSCC] =     {0,     /* ...one...    */
-                                0,     /* ...two...    */
-                                0,     /* ...three...  */
-                                0};    /* ...four...   */
-
-#define VERBOSE_BOOTMSG 1
-#undef  SCC_DELAY              /* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY             /* slow it even a bit more down */
-#undef  DONT_CHECK             /* don't look if the SCCs you specified are available */
-
-
-*****************
-
-You  m u s t  use "clock dpll" in /etc/z8530drv.rc for operation, 
-the on-board baudrate generator is not supported.
-
-*****************
-(mni tnx to Mike Bilow)
-
+- the output of cat /proc/net/z8530
 
 4. Thor RLC100
 ==============
@@ -788,4 +651,4 @@ in the Linux standard distribution and their support.
 
 Joerg Reuter   ampr-net: dl1bke@db0pra.ampr.org
                AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
-               Internet: jreuter@lykos.tng.oche.de
+               Internet: jreuter@lykos.oche.de
index 69ce1486114b32f36a3c66907326ad9f41c2bd9e..65dbd8e7fb24e81243e6075c860475a25a3810da 100644 (file)
@@ -123,6 +123,18 @@ M: jsn@cs.nott.ac.uk
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
 
+DAMA SLAVE for AX.25
+P: Joerg Reuter
+M: jreuter@lykos.oche.de
+L: linux-hams@vger.rutgers.edu
+S: Maintained
+
+Z8530 DRIVER FOR AX.25
+P: Joerg Reuter
+M: jreuter@lykos.oche.de
+L: linux-hams@vger.rutgers.edu
+S: Maintained
+
 BUSLOGIC SCSI DRIVER
 P:     Leonard N. Zubkoff
 M:     Leonard N. Zubkoff <lnz@dandelion.com>
@@ -341,6 +353,12 @@ M: emoenke@gwdg.de
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
+FPU EMULATOR
+P:     Bill Metzenthen
+M:     billm@suburbia.net
+W:     http://suburbia.net/~billm/floating-point/emulator/
+S:     Maintained
+
 CREDITS FILE
 P:     John A. Martin
 M:     jam@acm.org
index 78ec382a2c80989fe98f4d5294e899b194067e0e..f559827c224fcb606ff9b1fb10a5dc79d0ada929 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 5
+SUBLEVEL = 6
 
 ARCH = i386
 
index 858448cd64005d1e90b775ec7b4aa4f64a7fd1d1..003775d2efd98f0c9ba44c3d164da09f1a9b64a3 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <asm/fpu.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
index 371afdaa51409ae2ae21d6503fe37cf1b6ff15fa..a31ba17324feb27c6753cf2aacae6e25646e8d68 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/elfcore.h>
 
 #include <asm/reg.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
index e133d61e9d73bd4cb7602bd6c6c2a7829bbe27f8..d03744a68562201ac42ca22b87e15fabff21cd13 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/user.h>
 #include <linux/debugreg.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
index 7ffde4a197f642aa2548c261009ec75abd23d83d..f53d556e321f340ed7bfa6728e165c5476b5133a 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/delay.h>
 #include <linux/config.h>      /* CONFIG_ALPHA_LCA etc */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/hwrpb.h>
index 610cd2c8965837e105300cc36deba20522310e75..9e6ca449d52edd886b8462c905c47d58c0ff4b39 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
index 87b51e81f4c09920149cf1eb53b284e216891ffb..05dc250f19c4ae635d18ed08dd7d1df54ff6a565 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/hwrpb.h>
 
index 34db674c177542b7e2d33458ee7094189e7fbe8b..22172c2af845deba16c334de96ae6de813654ac6 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/tty.h>
 
 #include <asm/gentrap.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 void die_if_kernel(char * str, struct pt_regs * regs, long err)
index 66a8df574c88681a6053f2c7bec7dc1f397656a9..38df501fdb36911f7ffa642eb56f40a222d2e0ea 100644 (file)
@@ -3,7 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "ieee-math.h"
 
index 7dcf69a7d9772ffe4ca575ef37fcb4e3d7e85b3a..3fb73d12879181177c7fba272c04858dabe5d016 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 
index a6457543639e126329872382f3a880e93908838e..facb2f45ca38d83145a8ff5f5f8f6040d244a77c 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/swap.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
index 864b0ba88da602251ae9cf54023e36c154a360a0..a11f330af1c50fc9aab3d0fb8f589beff9ddcf05 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
index b9eae82965d08cb3a62078e1a5fc436d39f1810f..9e2f5e0cd1f8c2866b9a5ce499cc8aeb4e1605b6 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/ldt.h>
 
index c3d67a93603fb2bbe9732c15fb8eb756635fe5b8..a26a2c6a3ac5c039771364bfb02b07ec7a2211d8 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/delay.h>
 #include <linux/smp.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/io.h>
index 9977c3d2a46014e23a0d9d7d4b9daef0a459d5b6..5ea63609276140fab3017dc9bbdf658617b02f0c 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/user.h>
 #include <linux/debugreg.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
index c177e0ee3ee1ffd487babb65adb54bc93a2497d9..cde6354ee7362d23d8a0975904856df20acf9efe 100644 (file)
@@ -28,7 +28,7 @@
 #ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
 #endif
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 
index 56ee1f4f7fbfa53dbaf0806ad59e3c8292bf487b..c53a40e16afcecdb1feb5519c512ae38bd6e99aa 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
@@ -181,7 +181,8 @@ static void setup_frame(struct sigaction * sa,
 /* set up the "normal" stack seen by the signal handler (iBCS2) */
 #define __CODE ((unsigned long)(frame+24))
 #define CODE(x) ((unsigned long *) ((x)+__CODE))
-       put_user(__CODE,frame);
+       if (put_user(__CODE,frame))
+               do_exit(SIGSEGV);
        if (current->exec_domain && current->exec_domain->signal_invmap)
                put_user(current->exec_domain->signal_invmap[signr], frame+1);
        else
@@ -189,7 +190,7 @@ static void setup_frame(struct sigaction * sa,
        {
                unsigned int tmp = 0;
 #define PUT_SEG(seg, mem) \
-__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); *(mem) = tmp;
+__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); put_user(tmp,mem);
                PUT_SEG(gs, frame+2);
                PUT_SEG(fs, frame+3);
        }
index f457cf905f1e9023d5ee148da361002bde1f3f5e..619b372d8722a2f96f84745b111c3c0257f18fd1 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/ipc.h>
 
 /*
index fab5069dfe1bf0e0e3c04cb5a2b6f03976d55694..d2960d6e5f7cb2e95c7b5116abfc7f33483b7537 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
index 7d4f875be5825fb71f264dd2c46b10765b0aceac..b285161b5b5f7d3ba1baf31826be46418b6abd6b 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/mm.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 asmlinkage int system_call(void);
index 0c3c2acd7abec4c4b1f2a5b5c6cf56bcad15725b..6cceba36ca1484b8f11d76f989a5e7f77e161f23 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/ptrace.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
index 00b77898f46e1bca19fe8d8820c23ca11b52e45e..5158b4b81e804a5d29490ae7b974dfb14f72fb5b 100644 (file)
@@ -1,9 +1,9 @@
  +---------------------------------------------------------------------------+
  |  wm-FPU-emu   an FPU emulator for 80386 and 80486SX microprocessors.      |
  |                                                                           |
- | Copyright (C) 1992,1993,1994,1995                                         |
+ | Copyright (C) 1992,1993,1994,1995,1996                                    |
  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
- |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
+ |                       Australia.  E-mail billm@suburbia.net               |
  |                                                                           |
  |    This program is free software; you can redistribute it and/or modify   |
  |    it under the terms of the GNU General Public License version 2 as      |
@@ -42,11 +42,11 @@ but is very close.  See "Limitations" later in this file for a list of
 some differences.
 
 Please report bugs, etc to me at:
-       billm@jacobi.maths.monash.edu.au
+       billm@suburbia.net
 
 
 --Bill Metzenthen
-  October 1995
+  October 1996
 
 
 ----------------------- Internals of wm-FPU-emu -----------------------
index a744e5fa54188646468186073f40ef2674c3f31b..f76020d1f00ee3f5728e8fa67eca570256542e83 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/signal.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
index 39eb585d91f6099568a36c27441c6b4a6de3103c..07c32db9af0c9d2e8f6511ed4be7b9d5ce834653 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <linux/signal.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "fpu_emu.h"
index 0935b7a656e99f9bd7dbc1096a22d879cbfc8ce8..0749cdc70636d130f0894375dd735f161c64cbb6 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/head.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
index e154a707ef8461e1c9e97b19d872b9a311cbea57..cc288a9ab1083287ec40557e89c3700b4958d516 100644 (file)
@@ -18,7 +18,7 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
index 8e67f473af5e91de18699b93893d43fb26b7cf35..3e258a0c6086cefb4f03b70665b38f5f13e40959 100644 (file)
@@ -17,7 +17,7 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
index 02f8d029818d3a40f6b82b6287e2ff40f7c2ba08..9c7df1109c453f828b4eb9e798154f475383a2e5 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 extern void die_if_kernel(const char *,struct pt_regs *,long);
index 6ad218d813dc69d820629e967238802d2fe842bd..cf258d6de04e2246a15f3a189cc2ed6be6f125ec 100644 (file)
@@ -22,7 +22,7 @@
 #endif
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 
index 601f1f59207c48cdf36e5976af21c28cc3a1e765..9ae5eab73cf766133f869d47a96833d97f4e3f97 100644 (file)
@@ -161,7 +161,7 @@ struct old_floppy_raw_cmd {
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int use_virtual_dma=0; /* virtual DMA for Intel */
 static unsigned short virtual_dma_port=0x3f0;
index e68c6ab48907e3c4764bf333c8e673151570d703..2bd6d46fe572f71975b2b1ca2472196f161801b3 100644 (file)
@@ -39,7 +39,7 @@
 #define REALLY_SLOW_IO
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR HD_MAJOR
 #include <linux/blk.h>
index 9424ef6a28b358f9c8b6c1323fe602195099ba11..136f972c329cc782010c7654713b6791da64cfc0 100644 (file)
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 #include "ide.h"
index a95dea94e9f2138d95c5d7eec9f157a98a7a0598..3de8904180f2cd0217b982cd6f2e1693fdfbc80a 100644 (file)
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 /*
index b904b5e67169c1440633f0f69b72aeddd82df3f7..c00e3d7a79824e031f0571063b133ced8b86593f 100644 (file)
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_PCI
@@ -2272,11 +2272,13 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
        unsigned long capacity, check;
 
        id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
-       ide_input_data(drive, id, SECTOR_WORDS);        /* read 512 bytes of id info */
+       ide_input_data(drive, id, SECTOR_WORDS);/* read 512 bytes of id info */
        sti();
 
+#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO)
        /*
-        * EATA SCSI controllers do a hardware ATA emulation:  ignore them
+        * EATA SCSI controllers do a hardware ATA emulation:  
+        * Ignore them if there is a driver for them available.
         */
        if ((id->model[0] == 'P' && id->model[1] == 'M')
         || (id->model[0] == 'S' && id->model[1] == 'K')) {
@@ -2284,6 +2286,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
                drive->present = 0;
                return;
        }
+#endif
 
        /*
         *  WIN_IDENTIFY returns little-endian info,
index f998039533e1f8d3116e71a94a3a93824d67eab3..b07cfe49f603d2505890f8035b44326c77c9d84e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/errno.h>
 #include <linux/major.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_BLK_DEV_LOOP_DES
 #include <linux/des.h>
index 94ed024099ad08bb7df8baf37a27d0b79f32773b..f1bfa7403fa120cff0a65f15d819be5b3c509a79 100644 (file)
@@ -52,7 +52,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 extern void wait_for_keypress(void);
 
index 49eabc5d6f02bbb97beaa639e5b69e954d692515..3427f7077b30d7945ffa29ab9b129884a8c827d2 100644 (file)
@@ -28,7 +28,7 @@
  * Germany
  *
  * To enable UMC8672 support there must a lilo line like
- * append="hd=umc8672"...
+ * append="ide0=umc8672"...
  * To set the speed according to the abilities of the hardware there must be a
  * line like
  * #define UMC_DRIVE0 11
index c57dc2cdf2552b9fd62b4d563413bf4888a35563..c85ca6b58daf1a09f9a72e35a9e94a81e5e414e9 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
 #define MAJOR_NR XT_DISK_MAJOR
index 8138eee65b3d09fafc0bce5f0b51d88824d72420..5a8f5e7b70ff33a0f97467bc7511f8b0a4ac9263 100644 (file)
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR AZTECH_CDROM_MAJOR 
 
index d85d5b491f02c8b9a75aea9e322532c51795242b..de2608937a53dbed86209d65be0651488ab28951 100644 (file)
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
 #include <linux/cdrom.h>
@@ -1915,7 +1915,9 @@ find_track(int track)
    int num_tracks;
 
 
-   num_tracks = sony_toc.last_track_num - sony_toc.first_track_num + 1;
+   num_tracks = (  bcd_to_int(sony_toc.last_track_num)
+                 - bcd_to_int(sony_toc.first_track_num)
+                + 1);
    for (i = 0; i < num_tracks; i++)
    {
       if (sony_toc.tracks[i].track == track)
@@ -2486,8 +2488,8 @@ static int scd_ioctl(struct inode *inode,
          i=verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));
          if(i<0)
                return i;
-         loc_hdr.cdth_trk0 = sony_toc.first_track_num;
-         loc_hdr.cdth_trk1 = sony_toc.last_track_num;
+         loc_hdr.cdth_trk0 = bcd_to_int(sony_toc.first_track_num);
+         loc_hdr.cdth_trk1 = bcd_to_int(sony_toc.last_track_num);
          copy_to_user(hdr, &loc_hdr, sizeof(*hdr));
       }
       return 0;
@@ -2567,8 +2569,8 @@ static int scd_ioctl(struct inode *inode,
                return i;
          
          copy_from_user(&ti, (char *) arg, sizeof(ti));
-         if (   (ti.cdti_trk0 < sony_toc.first_track_num)
-             || (ti.cdti_trk0 > sony_toc.last_track_num)
+         if (   (ti.cdti_trk0 < bcd_to_int(sony_toc.first_track_num))
+             || (ti.cdti_trk0 > bcd_to_int(sony_toc.last_track_num))
              || (ti.cdti_trk1 < ti.cdti_trk0))
          {
             return -EINVAL;
@@ -2587,7 +2589,7 @@ static int scd_ioctl(struct inode *inode,
           * If we want to stop after the last track, use the lead-out
           * MSF to do that.
           */
-         if (ti.cdti_trk1 >= sony_toc.last_track_num)
+         if (ti.cdti_trk1 >= bcd_to_int(sony_toc.last_track_num))
          {
             log_to_msf(msf_to_log(sony_toc.lead_out_start_msf)-1,
                        &(params[4]));
index 092810dbc7d57232e6b3a069e930c652a8ab15a7..7495443719f19afac7834ab810085211fc8ad45f 100644 (file)
@@ -58,7 +58,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
 #include <linux/blk.h>
index f0ed24ea9b5477c269231747fb631de044f6a6a1..2b868e3faf1fc901d12487aa4be77035cdf5a536 100644 (file)
@@ -80,7 +80,7 @@
 /* #define REALLY_SLOW_IO  */
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR MITSUMI_CDROM_MAJOR
 #include <linux/blk.h>
index 4b36c3236b7a0bf21cd24cbfdc385f9049820c0a..df4341ffacd2794b567964214d86d8629d748955 100644 (file)
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <stdarg.h>
 #include <linux/sbpcd.h>
 #include <linux/config.h>
index 095d2b43ca0fb0b1cf14213cba5dbd4fa0a36de3..6f44f04154d070516c0ab7916b07a36ca2b043af 100644 (file)
@@ -68,7 +68,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MAJOR_NR SANYO_CDROM_MAJOR
 #include <linux/blk.h>
index aa2b70cccd600fd01429b1922e79c424f6fa3f78..b7e2060282279cfcee580c3096999a546f6a0fea 100644 (file)
 #define REALLY_SLOW_IO
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/cdrom.h>
 
index b8f8ed7d0695827710d7da5088c8d14ac8411920..dddceff15bd70c4cb3dd01a6eacb1461ec781250 100644 (file)
@@ -196,14 +196,6 @@ else
   endif
 endif
   
-ifeq ($(CONFIG_SCC),y)
-L_OBJS += scc.o
-else
-  ifeq ($(CONFIG_SCC),m)
-  M_OBJS += scc.o
-  endif
-endif  
-
 ifeq ($(CONFIG_BAYCOM),y)
 L_OBJS += baycom.o
 else
index 71b0c5e4148c985ac5bbabce47a99fcbb94a12af..8837d8a5dd08e7e9bd2efe30efde39eb0a0cb183 100644 (file)
@@ -1,24 +1,5 @@
+The z8530drv is now a network device driver, you can find it in
+       ../net/scc.c
 
-You will find subset of the documentation in
-
-                 linux/Documentation/networking/z8530drv.txt
-
-
-To use this driver you MUST have the full package from
-
-ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-2.01.dl1bke.real.tar.gz
-
-[
-  if you can't find it there, try:
-  .../tcpip/linux/z8530drv-2.01.dl1bke.tar.gz
-
-]
-
-and various mirrors (i.e. nic.switch.ch)
-
-The package includes the utilities necessary to initialize and
-control the driver.
-
-Joerg Reuter   ampr-net: dl1bke@db0pra.ampr.org
-               AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
-               Internet: jreuter@lykos.tng.oche.de
+A subset of the documentation is in
+       ../../Documentation/networking/z8530drv.txt
index f6448718e859ca466cb7817b6d7b097a6c03164f..bfb124859a9776813825812f23cce622dc004eba 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/random.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/amigamouse.h>
 #include <asm/amigahw.h>
index f6ada91812d23765c82ab9c920799158f675acfe..c680040af0984e529dda6de6f0a8b4e88e038589 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/types.h>
 #include <linux/stddef.h>
index b001c1c4ec0f250890b7328f6ada77bebc4a5386..d35fa5a494af87e6eb6e4b5ab3564642399b861f 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <asm/atarikb.h>
 #include <asm/atari_mouse.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
 static struct mouse_status mouse;
index 6501808d682509bdca4128de116c1651e7c0cab6..53e74f5884a1908990ef0d82b59ef8f9bb0734ce 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/random.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
index 964802d4513f9e5ac7cfa4e441058a87614934d6..e3a89e32eb80615b592faeba7fac4bd82ce9ca1a 100644 (file)
@@ -82,7 +82,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
index 7be14631274fdd64a9036ddc26b20a07af7e0511..91bcbb89243d835e0896bf119f13dcf62fdeeefd 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/ioport.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
index b948aa83c976ab80c1ea6ec54d39509bda1aa611..accc35015308042dc5d8b16d5d511de4e45d714d 100644 (file)
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include "kbd_kern.h"
index 0e368189f9864b2435b8a4a6693136e1e81f12b3..041a6a23e979ac9db8081bdbddb72f2a16a33075 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include "consolemap.h"
 
 static unsigned short translations[][256] = {
index bbee7c819fbf446b065ccabb4f2b2ceaf961f076..cc90ba4f6e49729f7c77cc7da41eadccfe1af333 100644 (file)
@@ -280,7 +280,7 @@ static char rcsid[] =
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include <linux/config.h>
index c7ef2badd9158e75862f3e9cfb059fd26d379dde..d0187a4a499caf94d3df506314dd68c7f5c81b0f 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/mman.h>
 #include <linux/tty.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
index 140910414e31733ea8d7620e9e01bafe89dc7a04..281226f69dcee7c2efebf9961f3ecd10657b465d 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /* the BIOS manuals say there can be up to 4 lpt devices
index 793ab21adc93c6be84e5aa43b8ddb0d4550678d5..1c634041bbc2afa9e4bbee909a8edb4765d3d83d 100644 (file)
@@ -57,7 +57,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 
index 0c36bb040bdbdc46e1efddabaf3e400246e10d12..1fb50fcc1c80aa349e49ebbb6ea819819c23e57d 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/mm.h>
 #include <linux/random.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
index 524e0420e286f3de056f9b6b5f2d7164dd755822..6d5819b0217923358e4d00933c52a1616cd836a1 100644 (file)
@@ -42,7 +42,7 @@
 #include <linux/random.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 
index 51d5e47570cf95cd7b61aa2c9280f31cf4927719..143d9e0a82de938bb84381540454b5a5b7863c32 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
index f54015331eb9b67effe2da3b302e6f546e18d1b5..fdb74ced7d347c1249e9942acbf1810fe39f4f02 100644 (file)
@@ -78,7 +78,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #define VERSION        "1.5.7"
index eaa8f56d50ff21f7dc383c003a542abb090c3a5b..a6ba7bdaa648bc0c3fe90909d1c1c521b1e52f54 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/random.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/config.h>
index 8a6c6dbbc1f5d921ed2594fa1eb42ac7af2a7c2c..7c74d4524d17b1315ba96f0f2255c1d35aa3e849 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
index fb4606ba2e68e8ae84c2cd3c410efb342199f517..64ffdf406d789febdf71c886f725797f0d0881c5 100644 (file)
 #include <linux/malloc.h>
 #include <linux/random.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 
index 2bc5a6f10d7074fd5757f1279aba3f31ac00bb1a..1e1ec7d859a03631a7774fa0a3bd9d54a716520e 100644 (file)
@@ -52,7 +52,7 @@
 #include <linux/mc146818rtc.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
@@ -66,11 +66,11 @@ static struct wait_queue *rtc_wait;
 
 static struct timer_list rtc_irq_timer;
 
-static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
-                       int origin);
+static long long rtc_llseek(struct inode *inode, struct file *file,
+                           loff_t offset, int origin);
 
-static int rtc_read(struct inode *inode, struct file *file,
-                       char *buf, int count);
+static long rtc_read(struct inode *inode, struct file *file,
+                       char *buf, unsigned long count);
 
 static int rtc_ioctl(struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg);
@@ -133,13 +133,14 @@ static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  *     Now all the various file operations that we export.
  */
 
-static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
-       int origin)
+static long long rtc_llseek(struct inode *inode, struct file *file,
+                           loff_t offset, int origin)
 {
        return -ESPIPE;
 }
 
-static int rtc_read(struct inode *inode, struct file *file, char *buf, int count)
+static long rtc_read(struct inode *inode, struct file *file, char *buf,
+                    unsigned long count)
 {
        struct wait_queue wait = { current, NULL };
        int retval;
@@ -507,7 +508,7 @@ static int rtc_select(struct inode *inode, struct file *file,
  */
 
 static struct file_operations rtc_fops = {
-       rtc_lseek,
+       rtc_llseek,
        rtc_read,
        NULL,           /* No write */
        NULL,           /* No readdir */
diff --git a/drivers/char/scc.c b/drivers/char/scc.c
deleted file mode 100644 (file)
index 66eb858..0000000
+++ /dev/null
@@ -1,2791 +0,0 @@
-#define RCS_ID "$Id: scc.c,v 1.41 1995/12/17 22:36:40 jreuter Exp jreuter $"
-
-#define BANNER "Z8530 SCC driver version 2.01.dl1bke (alpha) by DL1BKE\n"
-
-/*
-
-   ********************************************************************
-   *   SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      *
-   ********************************************************************
-
-
-   ********************************************************************
-
-       Copyright (c) 1993, 1995 Joerg Reuter DL1BKE
-
-       portions (c) 1993 Guido ten Dolle PE1NNZ
-
-   ********************************************************************
-   
-   The driver and the programs in the archive are UNDER CONSTRUCTION.
-   The code is likely to fail, and so your kernel could --- even 
-   a whole network. 
-
-   This driver is intended for Amateur Radio use. If you are running it
-   for commercial purposes, please drop me a note. I am nosy...
-
-   ...BUT:
-   ! You  m u s t  recognize the appropriate legislations of your country !
-   ! before you connect a radio to the SCC board and start to transmit or !
-   ! receive. The GPL allows you to use the  d r i v e r,  NOT the RADIO! !
-
-   For non-Amateur-Radio use please note that you might need a special
-   allowance/licence from the designer of the SCC Board and/or the
-   MODEM. 
-
-   This program is free software; you can redistribute it and/or modify 
-   it under the terms of the (modified) GNU General Public License 
-   delivered with the Linux kernel source.
-   
-   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 find a copy of the GNU General Public License in 
-   /usr/src/linux/COPYING; 
-   
-   ******************************************************************** 
-
-
-   ...If you find any portions of the code that are copyrighted to you,
-   and you don't want to see in here, please send me a private (!) 
-   message to my internet site. I will change it as soon as possible. 
-   Please don't flame to the tcp-group or anywhere else. Thanks!
-
-   Joerg Reuter        ampr-net: dl1bke@db0pra.ampr.org
-               AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
-               Internet: jreuter@lykos.tng.oche.de
-               
-               
-   Incomplete history of z8530drv:
-   -------------------------------
-
-   940913      - started to write the driver, rescued most of my own
-                 code (and Hans Alblas' memory buffer pool concept) from 
-                 an earlier project "sccdrv" which was initiated by 
-                 Guido ten Dolle. Not much of the old driver survived, 
-                 though. The first version I put my hands on was sccdrv1.3
-                 from August 1993. The memory buffer pool concept
-                 appeared in an unauthorized sccdrv version (1.5) from
-                 August 1994.
-
-   950131      - changed copyright notice to GPL without limitations.
-   
-     .
-     .
-     .
-      
-   950922      - using kernel timer chain
-   
-   951002      - splitting timer routine, adding support for throttle/
-                 unthrottle calls, removed typo in kiss decoder,
-                 corrected termios settings.
-                 
-   951011      - at last found one (the?) problem which caused the 
-                 driver to mess up buffers on heavy load pe1ayx was
-                 complaining about. Quite simple to reproduce:
-                 set a 9k6 port into audio loopback, add a route
-                 to 44.99.99.99 on that route and do a 
-                 ping -f 44.99.99.99
-                 
-   951013      - it still does not survive a flood ping...
-   
-   951107      - axattach w/o "-s" option (or setting an invalid 
-                 baudrate) does not produce "division by zero" faults 
-                 anymore.
-                 
-   951114      - rewrote memory management, took first steps to allow
-                 compilation as a module. Well, it looks like a whole
-                 new driver now. BTW: It  d o e s  survive the flood
-                 ping at last...
-                 
-   951116      - scc_config.h is gone -- the driver will be initialized
-                 through ioctl-commands. Use sccinit.c for this purpose.
-                 
-   951117      - Well --- what should I say: You can compile it as a
-                 module now. And I solved the problem with slip.c...
-                 
-   951120      - most ioctl() routines may be called w/o suser()
-                 permissions, check if you've set the permissions of
-                 /dev/scc* right! NOT 0666, you know it's evil ;-)
-                 
-   951217      - found silly bug in init_channel(), some bugfixes
-                 for the "standalone" module
-
-
-   Thanks to:
-   ----------
-   
-   PE1CHL Rob  - for a lot of good ideas from his SCC driver for DOS
-   PE1NNZ Guido - for his port of the original driver to Linux
-   KA9Q   Phil  - from whom we stole the mbuf-structure
-   PA3AYX Hans  - for some useful changes
-   DL8MBT Flori - for support
-   DG0FT  Rene  - for the BayCom USCC support
-   PA3AOU Harry - for ESCC testing, information supply and support
-   
-   PE1KOX Rob, DG1RTF Thomas, ON5QK Roland, G4XYW Andy, Linus,
-   EI9GL Paul,
-   
-   and all who sent me bug reports and ideas... 
-   
-   
-   NB -- if you find errors, change something, please let me know
-        first before you distribute it... And please don't touch
-        the version number. Just replace my callsign in
-        "v2.01.dl1bke" with your own. Just to avoid confusion...
-        
-   If you want to add your modification to the linux distribution
-   please (!) contact me first.
-         
-   Jörg Reuter DL1BKE
-  
-*/
-
-/* ----------------------------------------------------------------------- */
-
-#define DEBUG_BUFFERS  /* keep defined unless it is really stable... */
-
-#undef  SCC_DELAY      /* perhaps a 486DX2 is a *bit* too fast */
-#undef  SCC_LDELAY 5   /* slow it even a bit more down */
-#undef  DONT_CHECK     /* don't look if the SCCs you specified are available */
-
-#define MAXSCC          4       /* number of max. supported chips */
-#define RXBUFFERS       8       /* default number of RX buffers */
-#define TXBUFFERS       8       /* default number of TX buffers */
-#define BUFSIZE         384     /* must not exceed 4096-sizeof(mbuf) */
-#define TPS             25      /* scc_tx_timer():  Ticks Per Second */
-
-#define DEFAULT_CLOCK  4915200 /* default pclock if nothing is specified */
-
-/* ----------------------------------------------------------------------- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/tqueue.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/serial.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/scc.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/bitops.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <time.h>
-#include <linux/kernel.h>
-
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-#endif
-
-#ifndef Z8530_MAJOR
-#define Z8530_MAJOR 34
-#endif
-
-int scc_init(void);
-
-static struct mbuf * scc_enqueue_buffer(struct mbuf **queue, struct mbuf * buffer);
-static struct mbuf * scc_dequeue_buffer(struct mbuf **queue);
-static void alloc_buffer_pool(struct scc_channel *scc);
-static void free_buffer_pool(struct scc_channel *scc);
-static struct mbuf * scc_get_buffer(struct scc_channel *scc, char type);
-
-int scc_open(struct tty_struct *tty, struct file *filp);
-static void scc_close(struct tty_struct *tty, struct file *filp);
-int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static void scc_put_char(struct tty_struct *tty, unsigned char ch);
-static void scc_flush_chars(struct tty_struct *tty);
-static int scc_write_room(struct tty_struct *tty);
-static int scc_chars_in_buffer(struct tty_struct *tty);
-static void scc_flush_buffer(struct tty_struct *tty);
-static int scc_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void scc_set_termios(struct tty_struct *tty, struct termios *old_termios);
-static void scc_set_ldisc(struct tty_struct *tty);
-static void scc_throttle(struct tty_struct *tty);
-static void scc_unthrottle(struct tty_struct *tty);
-static void scc_start(struct tty_struct *tty);
-static void scc_stop(struct tty_struct *tty);
-
-static void z8530_init(void);
-
-static void scc_change_speed(struct scc_channel *scc);
-static void kiss_encode(struct scc_channel *scc);
-
-static void init_channel(struct scc_channel *scc);
-static void scc_key_trx (struct scc_channel *scc, char tx);
-static void scc_txint(register struct scc_channel *scc);
-static void scc_exint(register struct scc_channel *scc);
-static void scc_rxint(register struct scc_channel *scc);
-static void scc_spint(register struct scc_channel *scc);
-static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
-static void scc_tx_timer(unsigned long);
-static void scc_rx_timer(unsigned long);
-static void scc_init_timer(struct scc_channel *scc);
-
-/* from serial.c */
-
-static int baud_table[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 115200, 0 };
-
-
-struct tty_driver scc_driver;
-static int scc_refcount;
-static struct tty_struct *scc_table[2*MAXSCC];
-static struct termios scc_termios[2 * MAXSCC];
-static struct termios scc_termios_locked[2 * MAXSCC];
-
-struct irqflags { unsigned char used : 1; } Ivec[16];
-       
-struct scc_channel SCC_Info[2 * MAXSCC];         /* information per channel */
-io_port SCC_ctrl[2 * MAXSCC];                   /* Control ports */
-
-unsigned char Random = 0;              /* random number for p-persist */
-unsigned char Driver_Initialized = 0;
-int Nchips = 0;
-io_port Vector_Latch = 0;
-
-struct semaphore scc_sem = MUTEX;
-unsigned char scc_wbuf[BUFSIZE];
-
-static struct termios scc_std_termios;
-
-/* ******************************************************************** */
-/* *                   Port Access Functions                         * */
-/* ******************************************************************** */
-
-static inline unsigned char
-InReg(register io_port port, register unsigned char reg)
-{
-#ifdef SCC_LDELAY
-       register unsigned char r;
-       Outb(port, reg);
-       udelay(SCC_LDELAY);
-       r=Inb(port);
-       udelay(SCC_LDELAY);
-       return r;
-#else
-       Outb(port, reg);
-       return Inb(port);
-#endif
-}
-
-static inline void
-OutReg(register io_port port, register unsigned char reg, register unsigned char val)
-{
-#ifdef SCC_LDELAY
-       Outb(port, reg); udelay(SCC_LDELAY);
-       Outb(port, val); udelay(SCC_LDELAY);
-#else
-       Outb(port, reg);
-       Outb(port, val);
-#endif
-}
-
-static inline void
-wr(register struct scc_channel *scc, register unsigned char reg, register unsigned char val)
-{
-       OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
-}
-
-static inline void
-or(register struct scc_channel *scc, register unsigned char reg, register unsigned char val)
-{
-       OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
-}
-
-static inline void
-cl(register struct scc_channel *scc, register unsigned char reg, register unsigned char val)
-{
-       OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
-}
-
-/* ******************************************************************** */
-/* *                   Memory Buffer Management                        */
-/* ******************************************************************** */
-
-/*
- * The new buffer scheme uses a ring chain of buffers. This has the
- * advantage to access both, first and last element of the list, very
- * fast. It has the disadvantage to mess things up double if something
- * is wrong.
- *
- * Every scc channel has its own buffer pool now with an adjustable
- * number of buffers for transmit and receive buffers. The buffer
- * size remains the same for each AX.25 frame, but is (as a semi-
- * undocumented feature) adjustable within a range of 512 and 4096
- * to benefit experiments with higher frame lengths. If you need
- * larger frames... Well, you'd better choose a whole new concept
- * for that, like a DMA capable I/O card and a block device driver...
- *
- */
-
-/* ------ Management of buffer queues ------ */
-
-
-/* Insert a buffer at the "end" of the chain */
-
-static struct mbuf * 
-scc_enqueue_buffer(struct mbuf **queue, struct mbuf * buffer)
-{
-       unsigned long flags;
-       struct mbuf * anchor;
-       
-       save_flags(flags); cli();               /* do not disturb! */
-
-#ifdef DEBUG_BUFFERS                   
-       if (queue == NULLBUFP)                  /* called with illegal parameters, notify the user */
-
-       {
-               printk("z8530drv: Pointer to queue anchor is NULL pointer [enq]\n");
-               restore_flags(flags);
-               return NULLBUF;
-       }
-       
-       if (buffer == NULLBUF)
-       {
-               printk("z8530drv: can't enqueue a NULL pointer\n");
-               restore_flags(flags);
-               return NULLBUF;
-       }
-#endif
-
-       anchor = *queue;                        /* the anchor is the "start" of the chain */
-
-       if (anchor == NULLBUF)                  /* found an empty list */
-       {
-               *queue = buffer;                /* new anchor */
-               buffer->next = buffer->prev = NULLBUF;
-       } else  
-       if (anchor->prev == NULLBUF)            /* list has one member only */
-       {
-#ifdef DEBUG_BUFFERS
-               if (anchor->prev != NULLBUF)    /* oops?! */
-                       printk("weird --- anchor->prev is NULL but not anchor->next [enq]\n");
-#endif                 
-               anchor->next = anchor->prev = buffer;
-               buffer->next = buffer->prev = anchor;
-       } else
-#ifdef DEBUG_BUFFERS   
-       if (anchor->next == NULLBUF)            /* this has to be an error. Okay, make the best out of it */
-       {
-               printk("z8530drv: weird --- anchor->next is NULL but not anchor->prev [enq]\n");
-               anchor->next = anchor->prev = buffer;
-               buffer->next = buffer->prev = anchor;
-       } else
-#endif
-       {                                       /* every other case */
-               buffer->prev = anchor->prev;    /* self explaining, isn't it? */
-               buffer->next = anchor;
-               anchor->prev->next = buffer;
-               anchor->prev = buffer;
-       }
-       
-       restore_flags(flags);
-       return *queue;                          /* return "start" of chain */
-}
-
-
-
-/* Remove a buffer from the "start" of the chain an return it */
-
-static struct mbuf * 
-scc_dequeue_buffer(struct mbuf **queue)
-{
-       unsigned long flags;
-       struct mbuf *buffer;
-       
-       save_flags(flags); cli();
-
-#ifdef DEBUG_BUFFERS                   
-       if (queue == NULLBUFP)                  /* called with illegal parameter */
-
-       {
-               printk("z8530drv: Pointer to queue anchor is NULL pointer [deq]\n");
-               restore_flags(flags);
-               return NULLBUF;
-       }
-#endif
-
-       buffer = *queue;                        /* head of the chain */
-       
-       if (buffer != NULLBUF)                  /* not an empty list? */
-       {
-               if (buffer->prev != NULLBUF)    /* not last buffer? */
-               {
-#ifdef DEBUG_BUFFERS
-                       if (buffer->next == NULLBUF)
-                       {                       /* what?! */
-                               printk("z8530drv: weird --- buffer->next is NULL but not buffer->prev [deq]\n");
-                       } else
-#endif
-                       if (buffer->prev->next == buffer->prev->prev)
-                       {                       /* only one buffer remaining... */
-                               buffer->next->prev = NULLBUF;
-                               buffer->next->next = NULLBUF;
-                       } else {                /* the one remaining situation... */
-                               buffer->next->prev = buffer->prev;
-                               buffer->prev->next = buffer->next;
-                       }
-               } 
-#ifdef DEBUG_BUFFERS
-               else if (buffer->next != NULLBUF)
-                       printk("z8530drv: weird --- buffer->prev is NULL but not buffer->next [deq]\n");
-#endif
-               *queue = buffer->next;          /* new head of chain */
-               
-               buffer->next = NULLBUF;         /* for security only... */
-               buffer->prev = NULLBUF;
-               buffer->rw_ptr = buffer->data;
-       } 
-       
-       restore_flags(flags);
-       return buffer;                          /* give it away... */
-}
-
-/* ------ buffer pool management ------ */
-
-
-/* allocate buffer pool        for a channel */
-
-static void 
-alloc_buffer_pool(struct scc_channel *scc)
-{
-       int k;
-       struct mbuf * bptr;
-       int  buflen;
-       
-       buflen = sizeof(struct mbuf) + scc->stat.bufsize;
-       
-       if (scc->stat.bufsize <  336) scc->stat.bufsize = 336;
-       if (buflen > 4096)
-       {
-               scc->stat.bufsize = 4096-sizeof(struct mbuf);
-               buflen = 4096;
-       }
-       
-       if (scc->stat.rxbuffers < 4)  scc->stat.rxbuffers = 4;
-       if (scc->stat.txbuffers < 4)  scc->stat.txbuffers = 4;
-       
-
-       
-       /* allocate receive buffers for this channel */
-       
-       for (k = 0; k < scc->stat.rxbuffers ; k++)
-       {
-               /* allocate memory for the struct and the buffer */
-               
-               bptr = (struct mbuf *) kmalloc(buflen, GFP_ATOMIC);
-               
-               /* should not happen, but who knows? */
-               
-               if (bptr == NULLBUF)
-               {
-                       printk("z8530drv: %s: can't allocate memory for rx buffer pool", kdevname(scc->tty->device));
-                       break;
-               }
-               
-               /* clear memory */
-               
-               memset(bptr, 0, buflen);
-               
-               /* initialize structure */
-               
-               bptr->rw_ptr = bptr->data;
-               
-               /* and append the buffer to the pool */
-               
-               scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-       }
-       
-       /* now do the same for the transmit buffers */
-       
-       for (k = 0; k < scc->stat.txbuffers ; k++)
-       {
-               bptr = (struct mbuf *) kmalloc(buflen, GFP_ATOMIC);
-               
-               if (bptr == NULLBUF)
-               {
-                       printk("z8530drv: %s: can't allocate memory for tx buffer pool", kdevname(scc->tty->device));
-                       break;
-               }
-               
-               memset(bptr, 0, buflen);
-               
-               bptr->rw_ptr = bptr->data;
-               
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-       }
-}
-
-
-/* remove buffer pool */
-
-static void 
-free_buffer_pool(struct scc_channel *scc)
-{
-       struct mbuf * bptr;
-       unsigned long flags;
-       int cnt;
-       
-       /* this one is a bit tricky and probably dangerous. */
-               
-       save_flags(flags); cli();
-       
-       /* esp. to free the buffers currently in use by ISR */
-       
-       bptr = scc->rx_bp;
-       if (bptr != NULLBUF)
-       {
-               scc->rx_bp = NULLBUF;
-               scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-       }
-
-       bptr = scc->tx_bp;      
-       if (bptr != NULLBUF)
-       {
-               scc->tx_bp = NULLBUF;
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-       }
-       
-       bptr = scc->kiss_decode_bp;
-       if (bptr != NULLBUF)
-       {
-               scc->kiss_decode_bp = NULLBUF;
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-       }
-       
-       bptr = scc->kiss_encode_bp;
-       if (bptr != NULLBUF)
-       {
-               scc->kiss_encode_bp = NULLBUF;
-               scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-       }
-       
-       restore_flags(flags);
-       
-       
-       while (scc->rx_queue != NULLBUF)
-       {
-               bptr = scc_dequeue_buffer(&scc->rx_queue);
-               scc_enqueue_buffer(&scc->rx_buffer_pool, bptr);
-       }
-       
-       while (scc->tx_queue != NULLBUF)
-       {
-               bptr = scc_dequeue_buffer(&scc->tx_queue);
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bptr);
-       }
-       
-       /* you want to know why we move every buffer back to the
-          buffer pool? Well, good question... ;-) 
-        */
-       
-       cnt = 0;
-       
-       /* Probably because we just want a central position in the
-          code were we actually call free()?
-        */
-       
-       while (scc->rx_buffer_pool != NULLBUF)
-       {
-               bptr = scc_dequeue_buffer(&scc->rx_buffer_pool);
-               
-               if (bptr != NULLBUF)
-               {
-                       cnt++;
-                       kfree(bptr);
-               }
-       }
-
-       if (cnt < scc->stat.rxbuffers)          /* hmm... hmm... :-( */
-               printk("z8530drv: oops, deallocated only %d of %d rx buffers\n", cnt, scc->stat.rxbuffers);
-       if (cnt > scc->stat.rxbuffers)          /* WHAT?!! */
-               printk("z8530drv: oops, deallocated %d instead of %d rx buffers. Very strange.\n", cnt, scc->stat.rxbuffers);
-               
-       cnt = 0;
-       
-       while (scc->tx_buffer_pool != NULLBUF)
-       {
-               bptr = scc_dequeue_buffer(&scc->tx_buffer_pool);
-               
-               if (bptr != NULLBUF)
-               {
-                       cnt++;
-                       kfree(bptr);
-               }
-       }
-
-       if (cnt < scc->stat.txbuffers)
-               printk("z8530drv: oops, deallocated only %d of %d tx buffers\n", cnt, scc->stat.txbuffers);
-       if (cnt > scc->stat.txbuffers)
-               printk("z8530drv: oops, deallocated %d instead of %d tx buffers. Very strange.\n", cnt, scc->stat.txbuffers);
-}
-               
-               
-/* ------ rx/tx buffer management ------ */
-
-/* 
-   get a fresh buffer from the pool if possible; if not: get one from
-   the queue. We will remove the oldest frame from the queue and hope
-   it was a good idea... ;-)
-   
- */
-
-static struct mbuf * 
-scc_get_buffer(struct scc_channel *scc, char type)
-{
-       struct mbuf * bptr;
-       
-       if (type == BT_TRANSMIT)
-       {
-               bptr = scc_dequeue_buffer(&scc->tx_buffer_pool);
-               
-               /* no free buffers in the pool anymore? */
-               
-               if (bptr == NULLBUF)
-               {
-                       printk("z8530drv: scc_get_buffer(%s): tx buffer pool empty\n", kdevname(scc->tty->device));
-                       
-                       /* use the oldest from the queue instead */
-                       
-                       bptr = scc_dequeue_buffer(&scc->tx_queue);
-                       
-                       /* this should never, ever happen... */
-                       
-                       if (bptr == NULLBUF)
-                               printk("z8530drv: scc_get_buffer(): panic - even no buffer found in tx queue\n");
-               }
-       } else {
-               bptr = scc_dequeue_buffer(&scc->rx_buffer_pool);
-               
-               if (bptr == NULLBUF)
-               {
-                       printk("z8530drv: scc_get_buffer(%s): rx buffer pool empty\n", kdevname(scc->tty->device));
-                       
-                       bptr = scc_dequeue_buffer(&scc->rx_queue);
-                       
-                       if (bptr == NULLBUF)
-                               printk("z8530drv: scc_get_buffer(): panic - even no buffer found in rx queue\n");
-               }       
-       }
-       
-       if (bptr != NULLBUF)
-       {
-               bptr->rw_ptr = bptr->data;
-               bptr->cnt = 0;
-       }
-
-       return bptr;
-}
-
-
-/* ******************************************************************** */
-/* *                   Interrupt Service Routines                    * */
-/* ******************************************************************** */
-
-/* ----> interrupt service routine for the 8530 <---- */
-
-/* it's recommended to keep this function "inline" ;-) */
-
-static inline void
-scc_isr_dispatch(register struct scc_channel *scc, register int vector)
-{
-       switch (vector & VECTOR_MASK)
-       {
-               case TXINT: scc_txint(scc); break;
-               case EXINT: scc_exint(scc); break;
-               case RXINT: scc_rxint(scc); break;
-               case SPINT: scc_spint(scc); break;
-               default   : printk("scc_isr(): unknown interrupt status (addr %4.4x, state %2.2x)\n",scc->ctrl,vector);
-       }
-}
-
-
-
-
-
-/* If the card has a latch for the interrupt vector (like the PA0HZP card)
-   use it to get the number of the chip that generated the int.
-   If not: poll all defined chips.
- */
-
-static void
-scc_isr(int irq, void *dev_id, struct pt_regs *regs)
-{
-       register unsigned char vector;  
-       register struct scc_channel *scc;
-       register io_port q;
-       register io_port *p;
-       register int k;
-
-
-       cli();
-       
-       if (Vector_Latch)
-       {
-               while(1)                           /* forever...? */
-               { 
-                       Outb(Vector_Latch, 0);      /* Generate INTACK */
-        
-                       /* Read the vector */
-                       if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break; 
-                                               /* ...not forever! */
-          
-                       /* Extract channel number and status from vector. */
-                       /* Isolate channel number */
-                       /* Call handler */
-               
-                       if (vector & 0x01) break; 
-                
-                       scc=&SCC_Info[(((vector>>1)&0x7c)^0x04) >> 2];
-        
-                       if (!scc->tty) break;
-
-                       scc_isr_dispatch(scc, vector);
-                       
-                       Outb(scc->ctrl,0x38);              /* Reset Highest IUS" opcode to WR0 */
-               }  
-               
-               sti();  
-               return;
-       }
-       
-       
-       /* Find the SCC generating the interrupt by polling all attached SCCs
-        * reading RR3A (the interrupt pending register)
-        */
-
-       k = 0;
-       p = SCC_ctrl;
-       
-       while (k++ < Nchips)
-       {
-               if (!(q=*p++)) break;
-               
-               Outb(q,3);
-               
-               if (Inb(q))
-               {
-                       if (!(q=*p++)) break;
-                       
-                       Outb(q,2);
-                       vector=Inb(q);                  /* Read the vector */
-        
-                       /* Extract channel number and status from vector. */
-                       /* Isolate channel number */
-                       /* Call handler */
-        
-
-                       if (vector & 1) break; 
-        
-                       scc = &SCC_Info[(((vector >> 1) & 0x7c) ^ 0x04) >> 2];
-        
-                       if (!scc->tty) break;
-
-                       /* Isolate status info from vector, call handler */
-                       
-                       scc_isr_dispatch(scc, vector);
-
-                       k = 0;
-                       p = SCC_ctrl;
-
-               } else p++;
-       }    
-       
-       sti();
-}
-
-
-
-/* ----> four different interrupt handlers for Tx, Rx, changing of     */
-/*       DCD/CTS and Rx/Tx errors                                      */
-
-
-/* Transmitter interrupt handler */
-static void
-scc_txint(register struct scc_channel *scc)
-{
-       register struct mbuf *bp;
-
-       scc->stat.txints++;
-
-       bp = scc->tx_bp;
-       
-       if (bp == NULLBUF)
-       {
-               do 
-               {
-                       if (bp != NULLBUF)
-                               scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-
-                       bp = scc_dequeue_buffer(&scc->tx_queue);
-                       
-                       if (bp == NULLBUF)
-                       {
-                               scc->stat.tx_state = TXS_BUSY;
-                               scc->t_tail = scc->kiss.tailtime;
-                               
-                               Outb(scc->ctrl, RES_Tx_P);      /* clear int */
-                               return;
-                       }
-                       
-                       if ( scc->kiss.not_slip && (bp->cnt > 0) )
-                       {
-                               bp->rw_ptr++;
-                               bp->cnt--;
-                       }
-                       
-               } while (bp->cnt < 1);
-               
-               
-               Outb(scc->ctrl, RES_Tx_CRC);    /* reset CRC generator */
-               or(scc,R10,ABUNDER);            /* re-install underrun protection */
-               Outb(scc->data,*bp->rw_ptr);    /* send byte */
-               if (!scc->enhanced)             /* reset EOM latch */
-                       Outb(scc->ctrl, RES_EOM_L);
-               
-               scc->tx_bp = bp;
-               scc->stat.tx_state = TXS_ACTIVE; /* next byte... */
-       } else
-       if (bp->cnt <= 0)
-       {
-               if (--scc->stat.tx_queued < 0) scc->stat.tx_queued = 0;
-               
-               Outb(scc->ctrl, RES_Tx_P);      /* reset pending int */
-               cl(scc, R10, ABUNDER);          /* send CRC */
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-               scc->tx_bp = NULLBUF;
-               scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
-               return;
-       } else {
-               Outb(scc->data,*bp->rw_ptr);            
-       }
-       
-       bp->rw_ptr++;                   /* increment pointer */
-       bp->cnt--;                      /* decrease byte count */
-}
-
-static inline void
-flush_FIFO(register struct scc_channel *scc)
-{
-       register int k;
-       
-       for (k=0; k<3; k++)
-               Inb(scc->data);
-               
-       if(scc->rx_bp != NULLBUF)       /* did we receive something? */
-       {
-               scc->stat.rxerrs++;  /* then count it as an error */
-               scc_enqueue_buffer(&scc->rx_buffer_pool, scc->rx_bp);
-               
-               scc->rx_bp = NULLBUF;
-       }
-}
-
-
-/* External/Status interrupt handler */
-static void
-scc_exint(register struct scc_channel *scc)
-{
-       register unsigned char status,changes,chg_and_stat;
-
-       scc->stat.exints++;
-
-       status = InReg(scc->ctrl,R0);
-       changes = status ^ scc->status;
-       chg_and_stat = changes & status;
-       
-       /* ABORT: generated whenever DCD drops while receiving */
-
-       if (chg_and_stat & BRK_ABRT)            /* Received an ABORT */
-               flush_FIFO(scc);
-                       
-               
-       /* DCD: on = start to receive packet, off = ABORT condition */
-       /* (a successfully received packet generates a special condition int) */
-       
-       if(changes & DCD)                       /* DCD input changed state */
-       {
-               if(status & DCD)                /* DCD is now ON */
-               {
-                       if (scc->modem.clocksrc != CLK_EXTERNAL)
-                               OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
-                               
-                       or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
-               } else {                        /* DCD is now OFF */
-                       cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
-                       flush_FIFO(scc);
-               }
-       }
-
-#ifdef notdef
-       /* CTS: use external TxDelay (what's that good for?!) */
-       
-       if (chg_and_stat & CTS)                 /* CTS is now ON */
-       {                       
-               if (!Running(t_txdel) && scc->kiss.txdelay == 0) /* zero TXDELAY = wait for CTS */
-                       scc->t_txdel = 0;       /* kick it! */          
-               
-       }
-#endif
-       
-       if ( (status & TxEOM) && (scc->stat.tx_state == TXS_ACTIVE) )
-       {
-               scc->stat.tx_under++;     /* oops, an underrun! count 'em */
-               Outb(scc->ctrl, RES_Tx_P);
-               Outb(scc->ctrl, RES_EXT_INT);   /* reset ext/status interrupts */
-               scc->t_maxk = 1;
-               
-               if (scc->tx_bp != NULLBUF)
-               {
-                       scc_enqueue_buffer(&scc->tx_buffer_pool, scc->tx_bp);
-                       scc->tx_bp = NULLBUF;
-               }
-               
-               if (--scc->stat.tx_queued < 0) scc->stat.tx_queued = 0;
-               or(scc,R10,ABUNDER);
-       }
-               
-       if (status & ZCOUNT)               /* Oops? */
-       {
-               scc->stat.tx_under = 9999;  /* errr... yes. */
-               Outb(scc->ctrl, RES_Tx_P); /* just to be sure */
-               scc->t_maxk = 1;
-               
-               if (scc->tx_bp != NULLBUF)
-               {
-                       scc_enqueue_buffer(&scc->tx_buffer_pool, scc->tx_bp);
-                       scc->tx_bp = NULLBUF;
-               }
-
-               if (--scc->stat.tx_queued < 0) scc->stat.tx_queued = 0;
-               scc->kiss.tx_inhibit = 1;       /* don't try it again! */
-       }
-               
-       
-       scc->status = status;
-       Outb(scc->ctrl,RES_EXT_INT);
-}
-
-
-/* Receiver interrupt handler */
-static void
-scc_rxint(register struct scc_channel *scc)
-{
-       register struct mbuf *bp;
-
-       scc->stat.rxints++;
-
-       if( Running(t_maxk) && !(scc->kiss.fulldup))
-       {
-               Inb(scc->data);         /* discard char */
-               or(scc,R3,ENT_HM);      /* enter hunt mode for next flag */
-               return;
-       }
-
-       bp = scc->rx_bp;
-       
-       if (bp == NULLBUF)
-       {
-               bp = scc_get_buffer(scc, BT_RECEIVE);
-               if (bp == NULLBUF)
-               {
-                       printk("scc_rxint(): panic --- cannot get a buffer\n");
-                       Inb(scc->data);
-                       or(scc, R3, ENT_HM);
-                       scc->stat.nospace++;
-                       return;
-               }
-               
-               scc->rx_bp = bp;
-       }
-       
-       if (bp->cnt > scc->stat.bufsize)
-       {
-#ifdef notdef
-               printk("scc_rxint(): oops, received huge frame...\n");
-#endif
-               scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-               scc->rx_bp = NULLBUF;
-               Inb(scc->data);
-               or(scc, R3, ENT_HM);
-               return;
-       }
-               
-       /* now, we have a buffer. read character and store it */
-       *bp->rw_ptr = Inb(scc->data);
-       bp->rw_ptr++;
-       bp->cnt++;
-}
-
-/* kick rx_timer (try to send received frame or part of it ASAP) */
-
-/* of course we could define a "bottom half" routine to do the job,
-   but since its structures are saved in an array instead of a linked
-   list we would get in trouble if it clashes with another driver or
-   when we try to modularize the driver. IMHO we are fast enough
-   with a timer routine called on the next timer-INT... Your opinions?
- */
-
-static inline void
-kick_rx_timer(register struct scc_channel *scc)
-{
-       if (scc->rx_t.next)
-               del_timer(&(scc->rx_t));
-               
-       scc->rx_t.expires = jiffies + 1;
-       scc->rx_t.function = scc_rx_timer;
-       scc->rx_t.data = (unsigned long) scc;
-       add_timer(&scc->rx_t);
-}
-
-/* Receive Special Condition interrupt handler */
-static void
-scc_spint(register struct scc_channel *scc)
-{
-       register unsigned char status;
-       register struct mbuf *bp;
-
-       scc->stat.spints++;
-
-       status = InReg(scc->ctrl,R1);           /* read receiver status */
-       
-       Inb(scc->data);                         /* throw away Rx byte */
-       bp = scc->rx_bp;
-
-       if(status & Rx_OVR)                     /* receiver overrun */
-       {
-               scc->stat.rx_over++;             /* count them */
-               or(scc,R3,ENT_HM);               /* enter hunt mode for next flag */
-               
-               if (bp) scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-               scc->rx_bp = NULLBUF;
-       }
-       
-       if(status & END_FR && bp != NULLBUF)    /* end of frame */
-       {
-               /* CRC okay, frame ends on 8 bit boundary and received something ? */
-               
-               if (!(status & CRC_ERR) && (status & 0xe) == RES8 && bp->cnt)
-               {
-                       /* ignore last received byte (first of the CRC bytes) */
-                       bp->cnt--;
-                       
-                       scc_enqueue_buffer(&scc->rx_queue, bp);
-                       scc->rx_bp = NULLBUF;
-                       scc->stat.rxframes++;
-                       scc->stat.rx_queued++;
-                       kick_rx_timer(scc);
-               } else {                                /* a bad frame */
-                       scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-                       scc->rx_bp = NULLBUF;
-                       scc->stat.rxerrs++;
-               }
-       }
-       
-       Outb(scc->ctrl,ERR_RES);
-}
-
-
-/* ******************************************************************** */
-/* *                   Init Channel                                    */
-/* ******************************************************************** */
-
-
-/* ----> set SCC channel speed <---- */
-
-static inline void set_brg(register struct scc_channel *scc, unsigned int tc)
-{
-       unsigned long flags;
-
-       save_flags(flags); cli();       /* 2-step register accesses... */
-
-       cl(scc,R14,BRENABL);            /* disable baudrate generator */
-       wr(scc,R12,tc & 255);           /* brg rate LOW */
-       wr(scc,R13,tc >> 8);            /* brg rate HIGH */
-       or(scc,R14,BRENABL);            /* enable baudrate generator */
-
-       restore_flags(flags);
-}
-
-static inline void set_speed(register struct scc_channel *scc)
-{
-       if (scc->modem.speed > 0)       /* paranoia... */
-               set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);
-}
-
-
-/* ----> initialize a SCC channel <---- */
-
-static inline void init_brg(register struct scc_channel *scc)
-{
-       wr(scc, R14, BRSRC);                            /* BRG source = PCLK */
-       OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]);    /* DPLL source = BRG */
-       OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]);   /* DPLL NRZI mode */
-}
-
-/*
- * Initialization according to the Z8530 manual (SGS-Thomson's version):
- *
- * 1. Modes and constants
- *
- * WR9 11000000        chip reset
- * WR4 XXXXXXXX        Tx/Rx control, async or sync mode
- * WR1 0XX00X00        select W/REQ (optional)
- * WR2 XXXXXXXX        program interrupt vector
- * WR3 XXXXXXX0        select Rx control
- * WR5 XXXX0XXX        select Tx control
- * WR6 XXXXXXXX        sync character
- * WR7 XXXXXXXX        sync character
- * WR9 000X0XXX        select interrupt control
- * WR10        XXXXXXXX        miscellaneous control (optional)
- * WR11        XXXXXXXX        clock control
- * WR12        XXXXXXXX        time constant lower byte (optional)
- * WR13        XXXXXXXX        time constant upper byte (optional)
- * WR14        XXXXXXX0        miscellaneous control
- * WR14        XXXSSSSS        commands (optional)
- *
- * 2. Enables
- *
- * WR14        000SSSS1        baud rate enable
- * WR3 SSSSSSS1        Rx enable
- * WR5 SSSS1SSS        Tx enable
- * WR0 10000000        reset Tx CRG (optional)
- * WR1 XSS00S00        DMA enable (optional)
- *
- * 3. Interrupt status
- *
- * WR15        XXXXXXXX        enable external/status
- * WR0 00010000        reset external status
- * WR0 00010000        reset external status twice
- * WR1 SSSXXSXX        enable Rx, Tx and Ext/status
- * WR9 000SXSSS        enable master interrupt enable
- *
- * 1 = set to one, 0 = reset to zero
- * X = user defined, S = same as previous init
- *
- *
- * Note that the implementation differs in some points from above scheme.
- *
- */
-static void
-init_channel(register struct scc_channel *scc)
-{
-       unsigned long flags;
-       
-       if (scc->rx_t.next) del_timer(&(scc->rx_t));
-       if (scc->tx_t.next) del_timer(&(scc->tx_t));
-
-       save_flags(flags); cli();
-
-       wr(scc,R4,X1CLK|SDLC);          /* *1 clock, SDLC mode */
-       wr(scc,R1,0);                   /* no W/REQ operation */
-       wr(scc,R3,Rx8|RxCRC_ENAB);      /* RX 8 bits/char, CRC, disabled */     
-       wr(scc,R5,Tx8|DTR|TxCRC_ENAB);  /* TX 8 bits/char, disabled, DTR */
-       wr(scc,R6,0);                   /* SDLC address zero (not used) */
-       wr(scc,R7,FLAG);                /* SDLC flag value */
-       wr(scc,R9,VIS);                 /* vector includes status */
-       wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
-       wr(scc,R14, 0);
-
-
-/* set clock sources:
-
-   CLK_DPLL: normal halfduplex operation
-   
-               RxClk: use DPLL
-               TxClk: use DPLL
-               TRxC mode DPLL output
-               
-   CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)
-   
-               BayCom:                 others:
-               
-               TxClk = pin RTxC        TxClk = pin TRxC
-               RxClk = pin TRxC        RxClk = pin RTxC
-            
-
-   CLK_DIVIDER:
-               RxClk = use DPLL
-               TxClk = pin RTxC
-               
-               BayCom:                 others:
-               pin TRxC = DPLL         pin TRxC = BRG
-               (RxClk * 1)             (RxClk * 32)
-*/  
-
-               
-       switch(scc->modem.clocksrc)
-       {
-               case CLK_DPLL:
-                       wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-                       init_brg(scc);
-                       break;
-
-               case CLK_DIVIDER:
-                       wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);
-                       init_brg(scc);
-                       break;
-
-               case CLK_EXTERNAL:
-                       wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);
-                       OutReg(scc->ctrl, R14, DISDPLL);
-                       break;
-
-       }
-       
-       set_speed(scc);                 /* set baudrate */
-       
-       if(scc->enhanced)
-       {
-               or(scc,R15,SHDLCE|FIFOE);       /* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */
-               wr(scc,R7,AUTOEOM);
-       }
-
-       if((InReg(scc->ctrl,R0)) & DCD)         /* DCD is now ON */
-       {
-               if (scc->modem.clocksrc != CLK_EXTERNAL)
-                       or(scc,R14, SEARCH);
-                       
-               or(scc,R3,ENT_HM|RxENABLE);     /* enable the receiver, hunt mode */
-       }
-       
-       /* enable CTS (not for Baycom), ABORT & DCD interrupts */
-       wr(scc,R15,((scc->brand & BAYCOM) ? 0 : CTSIE)|BRKIE|DCDIE|TxUIE);
-       
-       Outb(scc->ctrl,RES_EXT_INT);    /* reset ext/status interrupts */
-       Outb(scc->ctrl,RES_EXT_INT);    /* must be done twice */
-
-       or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
-       
-       scc->status = InReg(scc->ctrl,R0);      /* read initial status */
-       
-       or(scc,R9,MIE);                 /* master interrupt enable */
-       
-       scc_init_timer(scc);
-                       
-       restore_flags(flags);
-}
-
-
-
-
-/* ******************************************************************** */
-/* *                   SCC timer functions                           * */
-/* ******************************************************************** */
-
-
-/* ----> scc_key_trx sets the time constant for the baudrate 
-         generator and keys the transmitter                 <---- */
-
-static void
-scc_key_trx(struct scc_channel *scc, char tx)
-{
-       unsigned int time_const;
-
-       if (scc->modem.speed < baud_table[1]) 
-               scc->modem.speed = 1200;
-               
-       if (scc->brand & PRIMUS)
-               Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));
-       
-       time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;
-       
-       if (scc->modem.clocksrc == CLK_DPLL)
-       {                               /* simplex operation */
-               if (tx)
-               {
-                       cl(scc,R3,RxENABLE|ENT_HM);     /* then switch off receiver */
-                       
-                       set_brg(scc, time_const);       /* reprogram baudrate generator */
-
-                       /* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
-                       wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
-                       
-                       or(scc,R5,RTS|TxENAB);          /* set the RTS line and enable TX */
-               } else {
-                       cl(scc,R5,RTS|TxENAB);
-                       
-                       set_brg(scc, time_const);       /* reprogram baudrate generator */
-                       
-                       /* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
-                       wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-                       
-                       or(scc,R3,RxENABLE|ENT_HM);
-               }
-       } else {
-               if (tx)
-                       or(scc,R5,RTS|TxENAB);          /* enable tx */
-               else
-                       cl(scc,R5,RTS|TxENAB);          /* disable tx */
-       }
-}
-
-
-/* ----> SCC timer interrupt handler and friends. Will be called every 1/TPS s <---- */
-
-static unsigned char Rand = 17;
-
-static inline int is_grouped(register struct scc_channel *scc)
-{
-       int k;
-       struct scc_channel *scc2;
-       unsigned char grp1, grp2;
-
-       grp1 = scc->kiss.group;
-       
-       for (k = 0; k < (Nchips * 2); k++)
-       {
-               scc2 = &SCC_Info[k];
-               grp2 = scc2->kiss.group;
-               
-               if (scc2 == scc || !(scc2->tty && grp2)) 
-                       return 0;
-               
-               if ((grp1 & 0x3f) == (grp2 & 0x3f))
-               {
-                       if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
-                               return 1;
-                       
-                       if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
-                               return 1;
-               }
-       }
-       return 0;
-}
-               
-
-static inline void dw_slot_timeout(register struct scc_channel *scc)
-{
-       scc->t_dwait = TIMER_STOPPED;
-       scc->t_slot = TIMER_STOPPED;
-       
-       if (!scc->kiss.fulldup)
-       {
-               Rand = Rand * 17 + 31;
-               
-               if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD))  || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
-               {
-                       if (scc->t_mbusy == TIMER_STOPPED)
-                               scc->t_mbusy = TPS * scc->kiss.maxdefer;
-                               
-                       scc->t_slot = scc->kiss.slottime;
-                       return ;
-                       
-               }
-       }
-       
-       if ( !(scc->wreg[R5] & RTS) )
-       {
-               scc->t_txdel = scc->kiss.txdelay;
-               scc_key_trx(scc, TX_ON);
-       } else {
-               scc->t_txdel = 0;
-       }
-}
-
-
-
-
-static inline void txdel_timeout(register struct scc_channel *scc)
-{
-       scc->t_txdel = TIMER_STOPPED;
-       
-       scc->t_maxk = TPS * scc->kiss.maxkeyup;
-       
-       if (scc->tx_bp == NULLBUF)
-               scc_txint(scc); 
-}
-       
-
-
-static inline void tail_timeout(register struct scc_channel *scc)
-{
-       scc->t_tail = TIMER_STOPPED;
-       
-       /* when fulldup is 0 or 1, switch off the transmitter.
-        * when frames are still queued (because of transmit time limit),
-        * restart the procedure to get the channel after MINTIME.
-        * when fulldup is 2, the transmitter remains keyed and we
-        * continue sending after waiting for waittime. IDLETIME is an 
-        * idle timeout in this case.
-        */ 
-        
-        if (scc->kiss.fulldup < 2)
-        {
-               if (scc->tx_bp)         /* we had a timeout? */
-               {
-                       scc->stat.tx_state = TXS_BUSY;
-                       scc->t_dwait = TPS * scc->kiss.mintime; /* try again */
-               }
-               
-               scc->stat.tx_state = TXS_IDLE;
-               scc->t_maxk = TIMER_STOPPED;
-               scc_key_trx(scc, TX_OFF);
-               return;
-        }
-        
-        if (scc->tx_bp)                        /* maxkeyup expired */ /* ?! */
-        {
-               scc->stat.tx_state = TXS_BUSY;
-               scc->t_txdel = TPS * scc->kiss.waittime;
-        }
-        else
-        
-               scc->t_idle = TPS * scc->kiss.idletime;
-}
-
-
-static inline void busy_timeout(register struct scc_channel *scc)
-{
-#ifdef THROW_AWAY_AFTER_BUSY_TIMEOUT
-       register struct mbuf *bp;               /* not tested */
-
-       while (bp = scc_dequeue_buffer(&scc->tx_queue))
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-               
-       scc->tx_queue = NULLBUF;
-       scc->stat.tx_state = TXS_IDLE;
-       
-#else
-       scc->t_txdel = scc->kiss.txdelay;       /* brute force ... */
-#endif
-       scc->t_mbusy = TIMER_STOPPED;
-       
-}
-
-
-static inline void maxk_idle_timeout(register struct scc_channel *scc)
-{
-       scc->t_maxk = TIMER_STOPPED;
-       scc->t_idle = TIMER_STOPPED;
-       
-       scc->stat.tx_state = TXS_BUSY;
-       scc->t_tail = scc->kiss.tailtime;
-}
-
-static void
-scc_tx_timer(unsigned long channel)
-{
-       register struct scc_channel *scc;
-       unsigned long flags;
-               
-
-       scc = (struct scc_channel *) channel;
-               
-       if (scc->tty && scc->init)
-       {               
-               save_flags(flags); cli();
-               
-               /* KISS-TNC emulation */
-               
-               if (Expired(t_dwait)) dw_slot_timeout(scc)      ; else
-               if (Expired(t_slot))  dw_slot_timeout(scc)      ; else
-               if (Expired(t_txdel)) txdel_timeout(scc)        ; else
-               if (Expired(t_tail))  tail_timeout(scc)         ;
-                       
-               /* watchdogs */
-               
-               if (Expired(t_mbusy)) busy_timeout(scc);
-               if (Expired(t_maxk))  maxk_idle_timeout(scc);
-               if (Expired(t_idle))  maxk_idle_timeout(scc);
-                       
-               restore_flags(flags);
-       }
-       
-       scc->tx_t.expires = jiffies + HZ/TPS;
-       add_timer(&scc->tx_t);
-}
-                       
-
-static void
-scc_rx_timer(unsigned long channel)
-{
-       register struct scc_channel *scc;
-       
-       scc = (struct scc_channel *) channel;
-       
-       if (scc->rx_queue && scc->throttled)
-       {
-               scc->rx_t.expires = jiffies + HZ/TPS;
-               add_timer(&scc->rx_t);
-               return;
-       }
-       
-       kiss_encode(scc);
-       
-       if (scc->rx_queue && !scc->throttled)
-       {
-
-               printk("z8530drv: warning: %s should be throttled\n", 
-                      kdevname(scc->tty->device));
-                              
-               scc->rx_t.expires = jiffies + HZ/TPS;
-               add_timer(&scc->rx_t);
-       }
-}
-
-static void
-scc_init_timer(struct scc_channel *scc)
-{
-       unsigned long flags;
-       
-       save_flags(flags); cli();
-       
-       Stop_Timer(t_dwait);
-       Stop_Timer(t_slot);
-       Stop_Timer(t_txdel);
-       Stop_Timer(t_tail);
-       Stop_Timer(t_mbusy);
-       Stop_Timer(t_maxk);
-       Stop_Timer(t_idle);
-       
-       scc->stat.tx_state = TXS_IDLE;
-       
-       if (scc->tx_t.next) 
-               del_timer(&scc->tx_t);
-       
-       scc->tx_t.data = (unsigned long) scc;
-       scc->tx_t.function = scc_tx_timer;
-       scc->tx_t.expires = jiffies + HZ/TPS;
-       add_timer(&scc->tx_t);
-       
-       scc->rx_t.data = (unsigned long) scc;
-       scc->rx_t.function = scc_rx_timer;
-       
-       restore_flags(flags);
-}
-
-
-/* ******************************************************************** */
-/* *                   KISS interpreter                              * */
-/* ******************************************************************** */
-
-
-/*
- * this will set the "kiss" parameters through kiss itself
- */
-static void
-kiss_set_param(struct scc_channel *scc,char cmd, unsigned int val)
-{
-
-#define  VAL val=val*TPS/100
-#define SVAL val? val:TIMER_STOPPED
-
-       switch(cmd){
-       case PARAM_TXDELAY:
-               scc->kiss.txdelay = VAL; break;
-       case PARAM_PERSIST:
-               scc->kiss.persist = val; break;
-       case PARAM_SLOTTIME:
-               scc->kiss.slottime = VAL; break;
-       case PARAM_TXTAIL:
-               scc->kiss.tailtime = VAL; break;
-       case PARAM_FULLDUP:
-               scc->kiss.fulldup = val; break;
-       case PARAM_WAIT:
-               scc->kiss.waittime = VAL; break;
-       case PARAM_MAXKEY:
-               scc->kiss.maxkeyup = SVAL; break;
-       case PARAM_MIN:
-               scc->kiss.mintime = SVAL; break;
-       case PARAM_IDLE:
-               scc->kiss.idletime = val; break;
-       case PARAM_MAXDEFER:
-               scc->kiss.maxdefer = SVAL; break;
-       case PARAM_GROUP:
-               scc->kiss.group = val;  break;
-       case PARAM_TX:
-               scc->kiss.tx_inhibit = val;
-       case PARAM_SOFTDCD:
-               scc->kiss.softdcd = val;
-       }
-       return;
-
-#undef  VAL
-#undef SVAL
-}
-
-
-/* interpret frame: strip CRC and decode KISS */
-
-static void kiss_interpret_frame(struct scc_channel * scc)
-{
-       unsigned char kisscmd;
-       unsigned long flags;
-       struct mbuf *bp;
-
-       bp = scc->kiss_decode_bp;
-       bp->rw_ptr = bp->data;
-       
-#ifdef DEBUG_BUFFERS
-       if (bp == NULLBUF)
-       {
-               printk("kiss_interpret_frame(): weird --- nothing to do.\n");
-               return;
-       }
-#endif
-       
-       if (bp->cnt < 2)
-       {
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-               scc->kiss_decode_bp = NULLBUF;
-               return;
-       }
-       
-       
-       
-       if (scc->kiss.not_slip)
-       {
-               kisscmd = *bp->rw_ptr;
-               bp->rw_ptr++;
-       } else {
-               kisscmd = 0;
-       }
-
-       if (kisscmd & 0xa0)
-       {
-               if (bp->cnt > 3) 
-                       bp->cnt -= 2;
-               else
-               {
-                       scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-                       scc->kiss_decode_bp = NULLBUF;
-                       return;
-               }
-       }
-       
-       
-       kisscmd &= 0x1f;
-       
-               
-       if (kisscmd)
-       {
-               kiss_set_param(scc, kisscmd, *bp->rw_ptr);
-               scc_enqueue_buffer(&scc->tx_buffer_pool, bp);
-               scc->kiss_decode_bp = NULLBUF;
-               return;
-       }
-
-       scc_enqueue_buffer(&scc->tx_queue, bp); /* enqueue frame */
-       
-       scc->stat.txframes++;
-       scc->stat.tx_queued++;
-       scc->kiss_decode_bp = NULLBUF;
-
-       save_flags(flags); cli();
-
-       if(scc->stat.tx_state == TXS_IDLE)
-       {                               /* when transmitter is idle */
-               scc->stat.tx_state = TXS_BUSY;
-               scc->t_dwait = (scc->kiss.fulldup? 0:scc->kiss.waittime);
-       }
-       
-       restore_flags(flags);
-}
-
-static inline void kiss_store_byte(struct scc_channel *scc, unsigned char ch)
-{
-       register struct mbuf *bp = scc->kiss_decode_bp;
-       
-       if (bp != NULLBUF)
-       {
-               if (bp->cnt > scc->stat.bufsize)
-                       printk("kiss_decode(): frame too long\n");
-               else
-               {
-                       *bp->rw_ptr = ch;
-                       bp->rw_ptr++;
-                       bp->cnt++;
-               }
-       }
-}
-
-static inline int kiss_decode(struct scc_channel *scc, unsigned char ch)
-{
-       switch (scc->stat.tx_kiss_state) 
-       {
-               case KISS_IDLE:
-                       if (ch == FEND)
-                       {
-                               scc->kiss_decode_bp = scc_get_buffer(scc, BT_TRANSMIT);
-                               if (scc->kiss_decode_bp == NULLBUF)
-                                       return 1;
-
-                               scc->stat.tx_kiss_state = KISS_DATA;
-                       } else scc->stat.txerrs++;
-                       break;
-                                       
-               case KISS_DATA:
-                       if (ch == FESC)
-                               scc->stat.tx_kiss_state = KISS_ESCAPE;
-                       else if (ch == FEND)
-                       {
-                               kiss_interpret_frame(scc);
-                               scc->stat.tx_kiss_state = KISS_IDLE;
-                       }
-                       else kiss_store_byte(scc, ch);
-                       break;
-                                       
-               case KISS_ESCAPE:
-                       if (ch == TFEND)
-                       {
-                               kiss_store_byte(scc, FEND);
-                               scc->stat.tx_kiss_state = KISS_DATA;
-                       }
-                       else if (ch == TFESC)
-                       {
-                               kiss_store_byte(scc, FESC);
-                               scc->stat.tx_kiss_state = KISS_DATA;
-                       }
-                       else
-                       {
-                               scc_enqueue_buffer(&scc->tx_buffer_pool, scc->kiss_decode_bp);
-                               scc->kiss_decode_bp = NULLBUF;
-                               scc->stat.txerrs++;
-                               scc->stat.tx_kiss_state = KISS_IDLE;
-                       }
-                       break;
-       } /* switch */
-       
-       return 0;
-       
-}
-
-/* ----> Encode received data and write it to the flip-buffer  <---- */
-
-static void
-kiss_encode(register struct scc_channel *scc)
-{
-       struct mbuf *bp;
-       struct tty_struct * tty = scc->tty;
-       unsigned char ch;
-
-       bp = scc->kiss_encode_bp;
-       
-       /* worst case: FEND 0 FESC TFEND -> 4 bytes */
-       
-       while(tty->flip.count < TTY_FLIPBUF_SIZE-4)
-       {
-               if (bp == NULLBUF)
-               {
-                       bp = scc_dequeue_buffer(&scc->rx_queue);
-                       scc->kiss_encode_bp = bp;
-                       
-                       if (bp == NULLBUF)
-                       {
-                               scc->stat.rx_kiss_state = KISS_IDLE;
-                               break;
-                       }
-               }
-               
-
-               if (bp->cnt <= 0)
-               {
-                       if (--scc->stat.rx_queued < 0)
-                               scc->stat.rx_queued = 0;
-                                       
-                       if (scc->stat.rx_kiss_state == KISS_RXFRAME)    /* new packet? */
-                       {
-                               tty_insert_flip_char(tty, FEND, 0);  /* send FEND for old frame */
-                               scc->stat.rx_kiss_state = KISS_IDLE; /* generate FEND for new frame */
-                       }
-                       
-                       scc_enqueue_buffer(&scc->rx_buffer_pool, bp);
-                       
-                       bp = scc->kiss_encode_bp = NULLBUF;
-                       continue;
-               }
-               
-
-               if (scc->stat.rx_kiss_state == KISS_IDLE)
-               {
-                       tty_insert_flip_char(tty, FEND, 0);
-                       
-                       if (scc->kiss.not_slip)
-                               tty_insert_flip_char(tty, 0, 0);
-                                       
-                       scc->stat.rx_kiss_state = KISS_RXFRAME;
-               }
-                               
-               switch(ch = *bp->rw_ptr)
-               {
-                       case FEND:
-                               tty_insert_flip_char(tty, FESC, 0);
-                               tty_insert_flip_char(tty, TFEND, 0);
-                               break;
-                       case FESC:
-                               tty_insert_flip_char(tty, FESC, 0);
-                               tty_insert_flip_char(tty, TFESC, 0);
-                               break;
-                       default:
-                               tty_insert_flip_char(tty, ch, 0);
-               }
-                       
-               bp->rw_ptr++;
-               bp->cnt--;
-       }
-               
-       queue_task(&tty->flip.tqueue, &tq_timer); /* kick it... */
-}
-
-
-/* ******************************************************************* */
-/* *           Init channel structures, special HW, etc...          * */
-/* ******************************************************************* */
-
-
-static void
-z8530_init(void)
-{
-       struct scc_channel *scc;
-       int chip, k;
-       unsigned long flags;
-       char *flag;
-
-
-       printk("Init Z8530 driver: %u channels, IRQ", Nchips*2);
-       
-       flag=" ";
-       for (k = 0; k < 16; k++)
-               if (Ivec[k].used) 
-               {
-                       printk("%s%d", flag, k);
-                       flag=",";
-               }
-       printk("\n");
-       
-
-       /* reset and pre-init all chips in the system */
-       for (chip = 0; chip < Nchips; chip++)
-       {
-               scc=&SCC_Info[2*chip];
-               if (!scc->ctrl) continue;
-                       
-               save_flags(flags); cli();       /* because of 2-step accesses */
-               
-               /* Special SCC cards */
-
-               if(scc->brand & EAGLE)                  /* this is an EAGLE card */
-                       Outb(scc->special,0x08);        /* enable interrupt on the board */
-                       
-               if(scc->brand & (PC100 | PRIMUS))       /* this is a PC100/EAGLE card */
-                       Outb(scc->special,scc->option); /* set the MODEM mode (0x22) */
-
-                       
-               /* Init SCC */
-
-               /* some general init we can do now */
-               
-               Outb(scc->ctrl, 0);
-               OutReg(scc->ctrl,R9,FHWRES);            /* force hardware reset */
-               udelay(100);                            /* give it 'a bit' more time than required */
-               wr(scc, R2, chip*16);                   /* interrupt vector */
-               wr(scc, R9, VIS);                       /* vector includes status */
-
-               restore_flags(flags);
-        }
-
-       Driver_Initialized = 1;
-}
-
-
-/* ******************************************************************** */
-/* *   Filesystem Routines: open, close, ioctl, settermios, etc      * */
-/* ******************************************************************** */
-
-
-
-/* scc_paranoia_check(): warn user if something went wrong             */
-
-static inline int scc_paranoia_check(struct scc_channel *scc, kdev_t device,
-                                    const char *routine)
-{
-#ifdef SCC_PARANOIA_CHECK
-
-static const char *badmagic = 
-       "Warning: bad magic number for Z8530 SCC struct (%s) in %s\n"; 
-static const char *badinfo =  
-       "Warning: Z8530 not found for (%s) in %s\n";
-       
-       if (!scc->init) 
-       {
-                       printk(badinfo, kdevname(device), routine);
-               return 1;
-       }
-       
-       if (scc->magic != SCC_MAGIC)
-       {
-               printk(badmagic, kdevname(device), routine);
-               return 1;
-       }
-#endif
-
-       return 0;
-}
-
-
-/* ----> this one is called whenever you open the device <---- */
-
-int scc_open(struct tty_struct *tty, struct file * filp)
-{
-       struct scc_channel *scc;
-       int chan;
-       
-       chan = MINOR(tty->device) - tty->driver.minor_start;
-       
-       if (Driver_Initialized)
-       {
-               if ( (chan < 0) || (chan >= (Nchips * 2)) )
-                       return -ENODEV;
-        } else {
-               tty->driver_data = &SCC_Info[0];
-               MOD_INC_USE_COUNT;
-               return 0;
-        }
-       scc = &SCC_Info[chan];
-       
-       tty->driver_data = scc;
-       tty->termios->c_cflag &= ~CBAUD;
-       
-       if (scc->magic != SCC_MAGIC)
-       {
-               printk("ERROR: scc_open(): bad magic number for device (%s)",
-                      kdevname(tty->device));
-               return -ENODEV;
-       }               
-       
-       MOD_INC_USE_COUNT;
-       
-       if(scc->tty != NULL)
-       {
-               scc->tty_opened++;
-               return 0;
-       }
-
-       scc->tty = tty;
-       alloc_buffer_pool(scc);
-       
-       if(!scc->init) return 0;
-       
-       scc->throttled = 0;
-
-       scc->stat.tx_kiss_state = KISS_IDLE;    /* don't change this... */
-       scc->stat.rx_kiss_state = KISS_IDLE;    /* ...or this */
-       init_channel(scc);
-       return 0;
-}
-
-
-/* ----> and this whenever you close the device <---- */
-
-static void
-scc_close(struct tty_struct *tty, struct file * filp)
-{
-       struct scc_channel *scc = tty->driver_data;
-       unsigned long flags;
-
-        if (!scc || (scc->magic != SCC_MAGIC))
-                return;
-                
-        MOD_DEC_USE_COUNT;
-       
-       if(scc->tty_opened)
-       {
-               scc->tty_opened--;
-               return;
-       }
-       
-       tty->driver_data = NULLBUF;
-       
-       if (!Driver_Initialized)
-               return;
-       
-       save_flags(flags); cli();
-       
-       Outb(scc->ctrl,0);              /* Make sure pointer is written */
-       wr(scc,R1,0);                   /* disable interrupts */
-       wr(scc,R3,0);
-       
-       scc->tty = NULL;
-       
-       del_timer(&scc->tx_t);
-       del_timer(&scc->rx_t);
-
-       free_buffer_pool(scc);
-       
-       restore_flags(flags);
-       
-       scc->throttled = 0;
-       tty->stopped = 0;
-}
-
-
-/*
- * change scc_speed
- */
-static void
-scc_change_speed(struct scc_channel * scc)
-{
-       long speed;
-       
-       if (scc->tty == NULL)
-               return;
-               
-
-       speed = baud_table[scc->tty->termios->c_cflag & CBAUD];
-       
-       if (speed > 0) scc->modem.speed = speed;
-       
-       if (scc->stat.tx_state == 0)    /* only switch baudrate on rx... ;-) */
-               set_speed(scc);
-}
-
-
-/* ----> ioctl-routine of the driver <---- */
-
-/* perform ioctl on SCC (sdlc) channel
- * this is used for AX.25 mode, and will set the "kiss" parameters
- */
-/* TIOCMGET    - get modem status      arg: (unsigned long *) arg
- * TIOCMBIS    - set PTT               arg: ---
- * TIOCMBIC    - reset PTT             arg: ---
- * TIOCMBIC    - set PTT               arg: ---
- * TIOCSCCINI  - initialize driver     arg: ---
- * TIOCCHANINI - initialize channel    arg: (struct scc_modem *) arg
- * TIOCGKISS   - get level 1 parameter arg: (struct ioctl_command *) arg
- * TIOCSKISS   - set level 1 parameter arg: (struct ioctl_command *) arg
- * TIOCSCCSTAT  - get driver status    arg: (struct scc_stat *) arg
- */
-
-static int
-scc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-       struct scc_channel * scc = tty->driver_data;
-       unsigned long flags, r;
-       unsigned int result;
-       unsigned int value;
-       struct ioctl_command kiss_cmd;
-       struct scc_mem_config memcfg;
-       struct scc_hw_config hwcfg;
-       int error, chan;
-
-        if (scc->magic != SCC_MAGIC) 
-        {
-               printk("ERROR: scc_ioctl(): bad magic number for device %s",
-                       kdevname(tty->device));
-                       
-                return -ENODEV;
-        }
-                                                        
-       r = NO_SUCH_PARAM;
-       
-       if (!Driver_Initialized)
-       {
-               if (cmd == TIOCSCCCFG)
-               {
-                       int found = 1;
-                       
-                       if (!suser()) return -EPERM;
-                       if (!arg) return -EFAULT;
-                       
-                       if (Nchips >= MAXSCC) 
-                               return -EINVAL;
-                       
-                       copy_from_user(&hwcfg, (void *) arg, sizeof(hwcfg));
-                       
-                       if (hwcfg.irq == 2) hwcfg.irq = 9;
-                       
-                       if (!Ivec[hwcfg.irq].used && hwcfg.irq)
-                       {
-                               if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL))
-                                       printk("z8530drv: Warning --- could not get IRQ %d\n", hwcfg.irq);
-                               else
-                                       Ivec[hwcfg.irq].used = 1;
-                       }
-                       
-                       if (hwcfg.vector_latch) 
-                               Vector_Latch = hwcfg.vector_latch;
-                               
-                       if (hwcfg.clock == 0)
-                               hwcfg.clock = DEFAULT_CLOCK;
-
-#ifndef DONT_CHECK
-                       save_flags(flags); cli();
-                       
-                       check_region(scc->ctrl, 1);
-                       Outb(hwcfg.ctrl_a, 0);
-                       udelay(5);
-                       OutReg(hwcfg.ctrl_a,R13,0x55);          /* is this chip really there? */
-                       udelay(5);
-                       
-                       if (InReg(hwcfg.ctrl_a,R13) != 0x55 )
-                               found = 0;
-                               
-                       restore_flags(flags);
-#endif
-
-                       if (found)
-                       {
-                               SCC_Info[2*Nchips  ].ctrl = hwcfg.ctrl_a;
-                               SCC_Info[2*Nchips  ].data = hwcfg.data_a;
-                               SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;
-                               SCC_Info[2*Nchips+1].data = hwcfg.data_b;
-                       
-                               SCC_ctrl[2*Nchips  ] = hwcfg.ctrl_a;
-                               SCC_ctrl[2*Nchips+1] = hwcfg.ctrl_b;
-                       }
-               
-                       for (chan = 0; chan < 2; chan++)
-                       {
-                               SCC_Info[2*Nchips+chan].special = hwcfg.special;
-                               SCC_Info[2*Nchips+chan].clock = hwcfg.clock;
-                               SCC_Info[2*Nchips+chan].brand = hwcfg.brand;
-                               SCC_Info[2*Nchips+chan].option = hwcfg.option;
-                               SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
-                       
-#ifdef DONT_CHECK
-                               printk("%s%i: data port = 0x%3.3x  control port = 0x%3.3x\n",
-                                       scc_driver.name, 2*Nchips+chan, 
-                                       SCC_Info[2*Nchips+chan].data, 
-                                       SCC_Info[2*Nchips+chan].ctrl);
-
-#else
-                               printk("%s%i: data port = 0x%3.3x  control port = 0x%3.3x -- %s\n",
-                                       scc_driver.name, 2*Nchips+chan, 
-                                       chan? hwcfg.data_b : hwcfg.data_a, 
-                                       chan? hwcfg.ctrl_b : hwcfg.ctrl_a,
-                                       found? "found" : "missing");
-#endif
-                               
-                               if (found)
-                               {
-                                       request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
-                                       request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
-                               }
-                       }
-                       
-                       if (found) Nchips++;
-                       
-                       return 0;
-               }
-               
-               if (cmd == TIOCSCCINI)
-               {
-                       if (!suser())
-                               return -EPERM;
-                               
-                       if (Nchips == 0)
-                               return -EINVAL;
-                       
-                       z8530_init();
-                       
-                       scc->tty=tty;
-                       alloc_buffer_pool(scc);
-                       return 0;
-               }
-               
-               return -EINVAL; /* confuse the user */
-       }
-       
-       if (!scc->init)
-       {
-               if (cmd == TIOCCHANINI)
-               {
-                       if (!arg)
-                               return -EFAULT;
-                               
-                       if (!suser())
-                               return -EPERM;
-                       
-                       copy_from_user(&scc->modem, (void *) arg, sizeof(struct scc_modem));
-                       
-                       /* default KISS Params */
-               
-                       if (scc->modem.speed < 4800)
-                       {
-                               scc->kiss.txdelay = 36*TPS/100;    /* 360 ms */
-                               scc->kiss.persist = 42;            /* 25% persistence */                        /* was 25 */
-                               scc->kiss.slottime = 16*TPS/100;   /* 160 ms */
-                               scc->kiss.tailtime = 4;            /* minimal reasonable value */
-                               scc->kiss.fulldup = 0;             /* CSMA */
-                               scc->kiss.waittime = 50*TPS/100;   /* 500 ms */
-                               scc->kiss.maxkeyup = 10;           /* 10 s */
-                               scc->kiss.mintime = 3;             /* 3 s */
-                               scc->kiss.idletime = 30;           /* 30 s */
-                               scc->kiss.maxdefer = 120;          /* 2 min */
-                               scc->kiss.not_slip = 1;            /* KISS mode */
-                               scc->kiss.softdcd = 0;             /* hardware dcd */
-                       } else {
-                               scc->kiss.txdelay = 10*TPS/100;    /* 100 ms */
-                               scc->kiss.persist = 64;            /* 25% persistence */                        /* was 25 */
-                               scc->kiss.slottime = 8*TPS/100;    /* 160 ms */
-                               scc->kiss.tailtime = 1;            /* minimal reasonable value */
-                               scc->kiss.fulldup = 0;             /* CSMA */
-                               scc->kiss.waittime = 50*TPS/100;   /* 500 ms */
-                               scc->kiss.maxkeyup = 7;            /* 7 s */
-                               scc->kiss.mintime = 3;             /* 3 s */
-                               scc->kiss.idletime = 30;           /* 30 s */
-                               scc->kiss.maxdefer = 120;          /* 2 min */
-                               scc->kiss.not_slip = 1;            /* KISS mode */
-                               scc->kiss.softdcd = 0;             /* hardware dcd */
-                       }
-                       
-                       scc->init = 1;                  
-                       
-                       return 0;
-               }
-               
-               return -EINVAL;
-       }
-
-       switch(cmd){
-       case TCSBRK:
-               return 0;
-       case TIOCMGET:
-               error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(unsigned int *));
-               if (error)
-                       return error;
-
-               save_flags(flags); cli();
-               
-               result =  ((scc->wreg[R5] & RTS) ? TIOCM_RTS : 0)
-                       | ((scc->wreg[R5] & DTR) ? TIOCM_DTR : 0)
-                       | ((InReg(scc->ctrl,R0) & DCD)  ? TIOCM_CAR : 0)
-                       | ((InReg(scc->ctrl,R0) & CTS)  ? TIOCM_CTS : 0);
-               
-               restore_flags(flags);
-                       
-               put_user(result,(unsigned int *) arg);
-               return 0;
-       case TIOCMBIS:
-       case TIOCMBIC:
-       case TIOCMSET:
-               switch (cmd) {
-               case TIOCMBIS:
-                       scc->wreg[R5] |= DTR;
-                       scc->wreg[R5] |= RTS;
-                       break;
-               case TIOCMBIC:
-                       scc->wreg[R5] &= ~DTR;
-                       scc->wreg[R5] &= ~RTS;
-                       break;
-               case TIOCMSET:
-                       value = get_user((unsigned int *) arg);
-                       
-                       if(value & TIOCM_DTR)
-                               scc->wreg[R5] |= DTR;
-                       else
-                               scc->wreg[R5] &= ~DTR;
-                       if(value & TIOCM_RTS)
-                               scc->wreg[R5] |= RTS;
-                       else
-                               scc->wreg[R5] &= ~RTS;
-                       break;
-               }
-               
-               save_flags(flags); cli();
-               
-               if(scc->stat.tx_state == TXS_IDLE && !Running(t_idle))
-                       maxk_idle_timeout(scc);
-                       
-               restore_flags(flags);
-               
-               return 0;
-               
-       case TCGETS:
-               error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct termios));
-               if (error)
-                       return error;
-               if (!arg) 
-                       return -EFAULT;
-                       
-               copy_to_user((void *) arg, scc->tty->termios, sizeof(struct termios));
-               return 0;
-               
-       case TCSETS:
-       case TCSETSF:           /* should flush first, but... */
-       case TCSETSW:           /* should wait 'till flush, but... */
-               if (!arg)
-                       return -EFAULT;
-               
-               copy_from_user(scc->tty->termios, (void *) arg, sizeof(struct termios));
-               scc_change_speed(scc);
-               return 0;
-               
-       case TIOCCHANMEM:
-               if (!arg)
-                       return -EFAULT;
-                       
-               copy_from_user(&memcfg, (void *) arg, sizeof(struct scc_mem_config));
-               
-               save_flags(flags); cli();
-               
-               free_buffer_pool(scc);
-               scc->stat.rxbuffers = memcfg.rxbuffers;
-               scc->stat.txbuffers = memcfg.txbuffers;
-               scc->stat.bufsize   = memcfg.bufsize;
-               alloc_buffer_pool(scc);
-               
-               restore_flags(flags);
-               return 0;
-               
-               
-       case TIOCSCCSTAT:
-               error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(struct scc_stat));
-               if (error)
-                       return error;
-               
-               if (!arg)
-                       return -EFAULT;
-                       
-               copy_to_user((void *) arg, &scc->stat, sizeof(struct scc_stat));
-               return 0;
-               
-#define TICKS (100/TPS)
-#define CAST(x) (unsigned long)(x)
-#define  Val   kiss_cmd.param
-#define  VAL   kiss_cmd.param*TPS/100
-#define SVAL   kiss_cmd.param? kiss_cmd.param:TIMER_STOPPED
-
-       case TIOCGKISS:
-               error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(struct ioctl_command));
-               if (error)
-                       return error;
-                       
-               if (!arg)
-                       return -EFAULT;
-                       
-               copy_from_user(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
-
-               switch (kiss_cmd.command)
-               {
-                       case PARAM_TXDELAY:     r = CAST(scc->kiss.txdelay*TICKS);      break;
-                       case PARAM_PERSIST:     r = CAST(scc->kiss.persist);            break;
-                       case PARAM_SLOTTIME:    r = CAST(scc->kiss.slottime*TICKS);     break;
-                       case PARAM_TXTAIL:      r = CAST(scc->kiss.tailtime*TICKS);     break;
-                       case PARAM_FULLDUP:     r = CAST(scc->kiss.fulldup);            break;
-                       case PARAM_SOFTDCD:     r = CAST(scc->kiss.softdcd);            break;
-                       case PARAM_DTR:         r = CAST((scc->wreg[R5] & DTR)? 1:0); break;
-                       case PARAM_RTS:         r = CAST((scc->wreg[R5] & RTS)? 1:0); break;
-                       case PARAM_SPEED:       r = CAST(scc->modem.speed);     break;
-                       case PARAM_GROUP:       r = CAST(scc->kiss.group);              break;
-                       case PARAM_IDLE:        r = CAST(scc->kiss.idletime);           break;
-                       case PARAM_MIN:         r = CAST(scc->kiss.mintime);            break;
-                       case PARAM_MAXKEY:      r = CAST(scc->kiss.maxkeyup);           break;
-                       case PARAM_WAIT:        r = CAST(scc->kiss.waittime);           break;
-                       case PARAM_MAXDEFER:    r = CAST(scc->kiss.maxdefer);           break;
-                       case PARAM_TX:          r = CAST(scc->kiss.tx_inhibit); break;
-                       case PARAM_SLIP:        r = CAST(!scc->kiss.not_slip);          break;
-                       default:                r = NO_SUCH_PARAM;
-               }
-               
-               kiss_cmd.param = r;
-               
-               copy_to_user((void *) arg, &kiss_cmd, sizeof(struct ioctl_command));
-               return 0;
-               break;
-               
-       case TIOCSKISS:
-               if (!arg)
-                       return -EFAULT;
-
-               copy_from_user(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
-               
-               switch (kiss_cmd.command)
-               {
-                       case PARAM_TXDELAY:     scc->kiss.txdelay=VAL;          break;
-                       case PARAM_PERSIST:     scc->kiss.persist=Val;          break;
-                       case PARAM_SLOTTIME:    scc->kiss.slottime=VAL;         break;
-                       case PARAM_TXTAIL:      scc->kiss.tailtime=VAL;         break;
-                       case PARAM_FULLDUP:     scc->kiss.fulldup=Val;          break;
-                       case PARAM_SOFTDCD:     scc->kiss.softdcd=Val;          break;
-                       case PARAM_DTR:         break; /* does someone need this? */
-                       case PARAM_RTS:         break; /* or this? */
-                       case PARAM_SPEED:       scc->modem.speed=Val;           break;
-                       case PARAM_GROUP:       scc->kiss.group=Val;            break;
-                       case PARAM_IDLE:        scc->kiss.idletime=Val;         break;
-                       case PARAM_MIN:         scc->kiss.mintime=SVAL;         break;
-                       case PARAM_MAXKEY:      scc->kiss.maxkeyup=SVAL;        break;
-                       case PARAM_WAIT:        scc->kiss.waittime=Val;         break;
-                       case PARAM_MAXDEFER:    scc->kiss.maxdefer=SVAL;        break;
-                       case PARAM_TX:          scc->kiss.tx_inhibit=Val;       break;
-                       case PARAM_SLIP:        scc->kiss.not_slip=!Val;        break;
-                       default:                return -ENOIOCTLCMD;
-               }
-               
-               return 0;
-               break;
-#undef TICKS
-#undef CAST
-#undef VAL
-#undef SVAL
-#undef Val
-               
-       default:
-               return -ENOIOCTLCMD;
-    }
-}
-
-
-/* ----> tx routine: decode KISS data and scc_enqueue it <---- */
-
-/* send raw frame to SCC. used for AX.25 */
-int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
-{
-       struct scc_channel * scc = tty->driver_data;
-       unsigned char *p;
-       unsigned long flags;
-       int cnt, cnt2;
-       
-       if (!tty) return count;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_write"))
-               return 0;
-
-       if (scc->kiss.tx_inhibit) return count;
-       
-       save_flags(flags); cli();
-       
-       cnt2 = count;
-       
-       while (cnt2)
-       {
-               cnt   = cnt2 > BUFSIZE? BUFSIZE:cnt2;
-               cnt2 -= cnt;
-               
-               if (from_user)
-               {
-                       down(&scc_sem);
-                       copy_from_user(scc_wbuf, buf, cnt);
-                       up(&scc_sem);
-               }
-               else
-                       memcpy(scc_wbuf, buf, cnt);
-               
-               /* Strange thing. The timeout of the slip driver is */
-               /* very small, thus we'll wake him up now.          */
-
-               if (cnt2 == 0)
-               {
-                       wake_up_interruptible(&tty->write_wait);
-               
-                       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                           tty->ldisc.write_wakeup)
-                               (tty->ldisc.write_wakeup)(tty);
-               } else 
-                       buf += cnt;
-                       
-               p=scc_wbuf;
-               
-               while(cnt--) 
-                 if (kiss_decode(scc, *p++))
-                 {
-                       scc->stat.nospace++;
-                       restore_flags(flags);
-                       return 0;
-                 }                     
-       } /* while cnt2 */
-
-       restore_flags(flags);
-               
-       return count;
-}
-                               
-
-/* put a single char into the buffer */
-
-static void scc_put_char(struct tty_struct * tty, unsigned char ch)
-{
-       struct scc_channel *scc = tty->driver_data;
-       unsigned char ch2;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_put_char"))
-               return;
-               
-       ch2 = ch;
-       scc_write(tty, 0, &ch2, 1);     /* that's all */
-}
-
-static void scc_flush_chars(struct tty_struct * tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       scc_paranoia_check(scc, tty->device, "scc_flush_chars"); /* just to annoy the user... */
-       
-       return; /* no flush needed */
-}
-
-
-static int scc_write_room(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_write_room"))
-               return 0;
-       
-       return BUFSIZE;
-}
-
-static int scc_chars_in_buffer(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc && scc->kiss_decode_bp)
-               return scc->kiss_decode_bp->cnt;
-       else
-               return 0;
-}
-
-static void scc_flush_buffer(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-
-       if (scc_paranoia_check(scc, tty->device, "scc_flush_buffer"))
-               return;
-       wake_up_interruptible(&tty->write_wait);
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-           tty->ldisc.write_wakeup)
-               (tty->ldisc.write_wakeup)(tty);
-}
-
-static void scc_throttle(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_throttle"))
-               return;
-
-#ifdef DEBUG           
-       printk("scc: scc_throttle() called for device %d\n", MINOR(tty->device));
-#endif
-       scc->throttled = 1;
-       
-       del_timer(&(scc->rx_t));
-       scc->rx_t.expires = jiffies + HZ/TPS;
-       add_timer(&scc->rx_t);
-}
-
-static void scc_unthrottle(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_unthrottle"))
-               return;
-               
-#ifdef DEBUG
-       printk("scc: scc_unthrottle() called for device %d\n", MINOR(tty->device));
-#endif         
-       scc->throttled = 0;
-       del_timer(&(scc->rx_t));
-       scc_tx_timer(scc->rx_t.data);
-}
-
-/* experimental, the easiest way to stop output is a fake scc_throttle */
-
-static void scc_start(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_start"))
-               return;
-               
-       scc_unthrottle(tty);
-}
-
-static void scc_stop(struct tty_struct *tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_stop"))
-               return;
-               
-       scc_throttle(tty);
-}
-
-static void
-scc_set_termios(struct tty_struct * tty, struct termios * old_termios)
-{
-       struct scc_channel *scc = tty->driver_data;
-       
-       if (scc_paranoia_check(scc, tty->device, "scc_set_termios"))
-               return;
-               
-       if (old_termios && (tty->termios->c_cflag == old_termios->c_cflag)) 
-               return;
-               
-       scc_change_speed(scc);
-}
-
-static void
-scc_set_ldisc(struct tty_struct * tty)
-{
-       struct scc_channel *scc = tty->driver_data;
-
-       if (scc_paranoia_check(scc, tty->device, "scc_set_ldisc"))
-               return;
-               
-       scc_change_speed(scc);
-}
-
-
-/* ******************************************************************** */
-/* *                   Init SCC driver                               * */
-/* ******************************************************************** */
-
-int  scc_init (void)
-{
-       int chip, chan, k;
-       
-       memset(&scc_std_termios, 0, sizeof(struct termios));
-        memset(&scc_driver, 0, sizeof(struct tty_driver));
-        scc_driver.magic = TTY_DRIVER_MAGIC;
-        scc_driver.name = "scc";
-        scc_driver.major = Z8530_MAJOR;
-        scc_driver.minor_start = 0;
-        scc_driver.num = MAXSCC*2;
-        scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
-        scc_driver.subtype = 1;                        /* not needed */
-        scc_driver.init_termios = scc_std_termios;
-        scc_driver.init_termios.c_cflag = B9600  | CREAD | CS8 | HUPCL | CLOCAL;
-        scc_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-        scc_driver.flags = TTY_DRIVER_REAL_RAW;
-        scc_driver.refcount = &scc_refcount;
-        scc_driver.table = scc_table;
-        scc_driver.termios = (struct termios **) scc_termios;
-        scc_driver.termios_locked = (struct termios **) scc_termios_locked;
-        scc_driver.open = scc_open;
-        scc_driver.close = scc_close;
-        scc_driver.write = scc_write;
-        scc_driver.start = scc_start;
-        scc_driver.stop = scc_stop;
-        
-        scc_driver.put_char = scc_put_char;
-        scc_driver.flush_chars = scc_flush_chars;        
-       scc_driver.write_room = scc_write_room;
-       scc_driver.chars_in_buffer = scc_chars_in_buffer;
-       scc_driver.flush_buffer = scc_flush_buffer;
-       
-       scc_driver.throttle = scc_throttle;
-       scc_driver.unthrottle = scc_unthrottle;
-        
-        scc_driver.ioctl = scc_ioctl;
-        scc_driver.set_termios = scc_set_termios;
-        scc_driver.set_ldisc = scc_set_ldisc;
-
-       printk(BANNER);
-        
-        if (tty_register_driver(&scc_driver))
-        {
-               printk("Failed to register Z8530 SCC driver\n");
-               return -EIO;
-       }
-       
-       /* pre-init channel information */
-       
-       for (chip = 0; chip < MAXSCC; chip++)
-       {
-               memset((char *) &SCC_Info[2*chip  ], 0, sizeof(struct scc_channel));
-               memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
-               
-               for (chan = 0; chan < 2; chan++)
-               {
-                       SCC_Info[2*chip+chan].magic    = SCC_MAGIC;
-                       SCC_Info[2*chip+chan].stat.rxbuffers = RXBUFFERS;
-                       SCC_Info[2*chip+chan].stat.txbuffers = TXBUFFERS;
-                       SCC_Info[2*chip+chan].stat.bufsize   = BUFSIZE;
-               }
-       }
-       
-       for (k = 0; k < 16; k++) Ivec[k].used = 0;
-
-       return 0;
-}
-
-/* ******************************************************************** */
-/* *                       Module support                            * */
-/* ******************************************************************** */
-
-
-#ifdef MODULE
-int init_module(void)
-{
-       int result = 0;
-       
-       result = scc_init();
-       
-       if (result == 0)
-               printk("Copyright 1993,1995 Joerg Reuter DL1BKE (jreuter@lykos.tng.oche.de)\n");
-               
-       return result;
-}
-
-void cleanup_module(void)
-{
-       long flags;
-       io_port ctrl;
-       int k, errno;
-       struct scc_channel *scc;
-       
-       save_flags(flags); cli();
-       if ( (errno = tty_unregister_driver(&scc_driver)) )
-       {
-               printk("Failed to unregister Z8530 SCC driver (%d)", -errno);
-               restore_flags(flags);
-               return;
-       }
-       
-       for (k = 0; k < Nchips; k++)
-               if ( (ctrl = SCC_ctrl[k*2]) )
-               {
-                       Outb(ctrl, 0);
-                       OutReg(ctrl,R9,FHWRES); /* force hardware reset */
-                       udelay(50);
-               }
-               
-       for (k = 0; k < Nchips*2; k++)
-       {
-               scc = &SCC_Info[k];
-               if (scc)
-               {
-                       release_region(scc->ctrl, 1);
-                       release_region(scc->data, 1);
-               }
-       }
-       
-       for (k=0; k < 16 ; k++)
-               if (Ivec[k].used) free_irq(k, NULL);
-               
-       restore_flags(flags);
-}
-#endif
index c719933ad042fa13d395f99751f535bed82bcc83..bb51de2f78d9a6cd4d1e61f75ff2bedf8f9eb936 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/malloc.h>
 #include <linux/types.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "vt_kern.h"
 #include "consolemap.h"
@@ -290,9 +290,9 @@ int paste_selection(struct tty_struct *tty)
        if (!bp || !c)
                return 0;
        do_unblank_screen();
-       current->state = TASK_INTERRUPTIBLE;
        add_wait_queue(&vt->paste_wait, &wait);
-       while (c) {
+       do {
+               current->state = TASK_INTERRUPTIBLE;
                if (test_bit(TTY_THROTTLED, &tty->flags)) {
                        schedule();
                        continue;
@@ -301,7 +301,8 @@ int paste_selection(struct tty_struct *tty)
                tty->ldisc.receive_buf(tty, bp, 0, l);
                c -= l;
                bp += l;
-       }
+       } while (c);
+       remove_wait_queue(&vt->paste_wait, &wait);
        current->state = TASK_RUNNING;
        return 0;
 }
index 5b86a1e20a20ce26f77d1a3530704ba1416378b0..6655f7b285a941ce497a5232f27e29712eb9d393 100644 (file)
@@ -45,7 +45,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 static char *serial_name = "Serial driver";
index fecb834be0d2d8e75ed39d080b5d4d7d5ff552c7..872afdd42bbefd53683ce23409d470e748dfbebd 100644 (file)
@@ -45,7 +45,7 @@
 #include <linux/config.h>      /* for CONFIG_PCI */
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
index 41d7405047ce81682409d9447ca712f9577383e1..ca2706dba4133e0277e0bf68415b3ff4156168bb 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include "kbd_kern.h"
index f2479390e7c1964a9a0215f5a01f9d12272840d8..e8bceaf0a09e497bf9be3300d0e45fcdeb100387 100644 (file)
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* We really shouldn't be using this define.. */
 #define IOCCMD_MASK 0x0000ffff
index 89dff1943966cf506d5a448c74b451ebcce862e2..a3ce2e356cb9b2f77133fca7300c54da5e67c8b4 100644 (file)
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
-#include <linux/scc.h>
-
 #include "kbd_kern.h"
 #include "vt_kern.h"
 #include "selection.h"
@@ -1714,7 +1712,7 @@ void do_SAK( struct tty_struct *tty)
                if (((*p)->tty == tty) ||
                    ((session > 0) && ((*p)->session == session)))
                        send_sig(SIGKILL, *p, 1);
-               else {
+               else if ((*p)->files) {
                        for (i=0; i < NR_OPEN; i++) {
                                filp = (*p)->files->fd[i];
                                if (filp && (filp->f_op == &tty_fops) &&
@@ -1928,9 +1926,6 @@ int tty_init(void)
 #ifdef CONFIG_SERIAL
        rs_init();
 #endif
-#ifdef CONFIG_SCC
-       scc_init();
-#endif
 #ifdef CONFIG_CYCLADES
        cy_init();
 #endif
index aa3c3efc959bc457acf3cc8bced098daf881c10f..55d6d21dc7dcde6a2d3109e6d84e7f831e08a5fc 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <asm/io.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #undef TTY_DEBUG_WAIT_UNTIL_SENT
index 0ed3eb74502d424319044e8d5cbc0271e56aaa93..b03118f783a8bc4d9f0a1d4f230fe8b9c5542b2c 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include "vt_kern.h"
 #include "selection.h"
 
index 02a269e2acc46b0f2f21e2bf1544d563fea72359..eb957180b827eed9abc38a534eee104bb18d0240 100644 (file)
@@ -43,7 +43,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/mm.h>
 
 extern unsigned short video_port_reg, video_port_val;
index 70a3dccde577ad40b06f17ac8d974c6490ff3e71..d9dbcd4b81feb9ad445d24b914e3776b6b230aba 100644 (file)
@@ -52,7 +52,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include "kbd_kern.h"
index 978bee056bff509e74740ea5ee4e2f00b4f1e295..1fc0a81b3c466c6781d4946cd58eb9a1bb6506d4 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/fs.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "kbd_kern.h"
 #include "vt_kern.h"
index 5b39a508adfcda2a8ab903ffc0ffd1e2a0b8a1fd..77d8d71cf9001c7a52fb1b4095f47076f9e9820f 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static int wdt_is_open=0;
index fb2264b8c0027f6600bc998f0d15fa85c7d5a3e4..623190a73107de709a4ec463612dc844c89f1e4b 100644 (file)
@@ -726,6 +726,8 @@ int isdn_getnum(char **p)
 /*
  * isdn_readbchan() tries to get data from the read-queue.
  * It MUST be called with interrupts off.
+ *  
+ * I hope I got the EFAULT error path right -AK.
  */
 int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
 {
@@ -736,6 +738,7 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
        int dflag;
         struct sk_buff *skb;
        u_char *cp;
+       int ret = 0; 
 
        if (!dev->drv[di])
                return 0;
@@ -749,6 +752,7 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
        cp = buf;
        count = 0;
        while (left) {
+                       ret = 0; 
                 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
                         break;
                 if (skb->lock)
@@ -765,15 +769,19 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
                         count_pull = count_put = 0;
                         while ((count_pull < skb->len) && (left-- > 0)) {
                                 if (dev->drv[di]->DLEflag & DLEmask) {
-                                        if (user)
-                                                put_fs_byte(DLE,cp++);
-                                        else
+                                                                           if (user) {
+                                                ret = put_user(DLE,cp);
+                                                                                               cp++; 
+                                                                                               if (ret) break; 
+                                        } else
                                                 *cp++ = DLE;
                                         dev->drv[di]->DLEflag &= ~DLEmask;
                                 } else {
-                                        if (user)
-                                                put_fs_byte(*p,cp++);
-                                        else
+                                                                           if (user) {
+                                                ret = put_user(*p,cp);
+                                                                                               if (ret) break;
+                                                                                               cp++; 
+                                        } else
                                                 *cp++ = *p;
                                         if (*p == DLE) {
                                                 dev->drv[di]->DLEflag |= DLEmask;
@@ -794,10 +802,12 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
                                 dflag = 0;
                         }
                         count_put = count_pull;
+                                               ret = 0; 
                         if (user)
-                                copy_to_user(cp, skb->data, count_put);
+                                ret = copy_to_user(cp, skb->data, count_put);
                         else
                                 memcpy(cp, skb->data, count_put);
+                                               count_put -= ret; 
                         cp += count_put;
                         left -= count_put;
                 }
@@ -821,11 +831,11 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
                          * but we pull off the data we got until now.
                          */
                        skb_pull(skb,count_pull);
-                        skb->lock = 0;
+                        skb->lock = 0; 
                 }
                dev->drv[di]->rcvcount[channel] -= count_put;
        }
-       return count;
+       return ret ? -EFAULT : count;
 }
 
 static __inline int isdn_minor2drv(int minor)
@@ -923,9 +933,10 @@ static int isdn_read(struct inode *inode, struct file *file, char *buf, int coun
                p = isdn_statstr();
                file->private_data = 0;
                if ((len = strlen(p)) <= count) {
-                       copy_to_user(buf, p, len);
+                       if (copy_to_user(buf, p, len))
+                               return -EFAULT;
                        file->f_pos += len;
-                       return len;
+                       return len; 
                }
                return 0;
        }
@@ -1072,35 +1083,25 @@ static int isdn_set_allcfg(char *src)
                return ret;
        save_flags(flags);
        cli();
-       if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(int)))) {
-               restore_flags(flags);
-               return ret;
-       }
-       copy_from_user((char *) &i, src, sizeof(int));
-        src += sizeof(int);
+       ret = get_user(i, src); 
+       if (ret) 
+               goto out; 
+    src += sizeof(int);
        while (i) {
                char *c;
                char *c2;
 
-               if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(cfg)))) {
-                       restore_flags(flags);
-                       return ret;
-               }
-               copy_from_user((char *) &cfg, src, sizeof(cfg));
+               if(copy_from_user((char *) &cfg, src, sizeof(cfg)))
+                       goto fault; 
                src += sizeof(cfg);
                if (!isdn_net_new(cfg.name, NULL)) {
                        restore_flags(flags);
                        return -EIO;
                }
-               if ((ret = isdn_net_setcfg(&cfg))) {
-                       restore_flags(flags);
-                       return ret;
-               }
-               if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(buf)))) {
-                       restore_flags(flags);
-                       return ret;
-               }
-               copy_from_user(buf, src, sizeof(buf));
+               if ((ret = isdn_net_setcfg(&cfg))) 
+                       goto out; 
+               if(copy_from_user(buf, src, sizeof(buf)))
+                       goto fault; 
                src += sizeof(buf);
                c = buf;
                while (*c) {
@@ -1109,20 +1110,15 @@ static int isdn_set_allcfg(char *src)
                        strcpy(phone.phone, c);
                        strcpy(phone.name, cfg.name);
                        phone.outgoing = 0;
-                       if ((ret = isdn_net_addphone(&phone))) {
-                               restore_flags(flags);
-                               return ret;
-                       }
+                       if ((ret = isdn_net_addphone(&phone))) 
+                               goto fault; 
                        if (c2)
                                c = c2;
                        else
                                c += strlen(c);
                }
-               if ((ret = verify_area(VERIFY_READ, (void *) src, sizeof(buf)))) {
-                       restore_flags(flags);
-                       return ret;
-               }
-               copy_from_user(buf, src, sizeof(buf));
+               if(copy_from_user(buf, src, sizeof(buf)))
+                       goto fault; 
                src += sizeof(buf);
                c = buf;
                while (*c) {
@@ -1131,10 +1127,8 @@ static int isdn_set_allcfg(char *src)
                        strcpy(phone.phone, c);
                        strcpy(phone.name, cfg.name);
                        phone.outgoing = 1;
-                       if ((ret = isdn_net_addphone(&phone))) {
-                               restore_flags(flags);
-                               return ret;
-                       }
+                       if ((ret = isdn_net_addphone(&phone))) 
+                               goto out; 
                        if (c2)
                                c = c2;
                        else
@@ -1142,8 +1136,12 @@ static int isdn_set_allcfg(char *src)
                }
                i--;
        }
+out:
        restore_flags(flags);
-       return 0;
+       return ret;
+fault:
+       restore_flags(flags);
+       return -EFAULT;
 }
 
 static int isdn_get_allcfg(char *dest)
@@ -1152,17 +1150,13 @@ static int isdn_get_allcfg(char *dest)
        isdn_net_ioctl_phone phone;
        isdn_net_dev *p;
        ulong flags;
-       int ret;
+       int ret = 0;
 
        /* Walk through netdev-chain */
        save_flags(flags);
        cli();
        p = dev->netdev;
        while (p) {
-               if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 10))) {
-                       restore_flags(flags);
-                       return ret;
-               }
                strcpy(cfg.eaz, p->local.msn);
                cfg.exclusive = p->local.exclusive;
                if (p->local.pre_device >= 0) {
@@ -1179,28 +1173,29 @@ static int isdn_get_allcfg(char *dest)
                cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
                cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0;
                cfg.ihup = (p->local.hupflags & 8) ? 1 : 0;
-               copy_to_user(dest, p->local.name, 10);
+               ret = 0; 
+               ret += copy_to_user(dest, p->local.name, 10);
                dest += 10;
-               copy_to_user(dest, (char *) &cfg, sizeof(cfg));
+               ret += copy_to_user(dest, (char *) &cfg, sizeof(cfg));
                dest += sizeof(cfg);
                strcpy(phone.name, p->local.name);
                phone.outgoing = 0;
-               if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-                       restore_flags(flags);
-                       return ret;
-               } else
+               if (ret)
+                       break; 
+               if ((ret = isdn_net_getphones(&phone, dest)) < 0) 
+                       break; 
+               else
                        dest += ret;
                strcpy(phone.name, p->local.name);
                phone.outgoing = 1;
-               if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-                       restore_flags(flags);
-                       return ret;
-               } else
+               if ((ret = isdn_net_getphones(&phone, dest)) < 0) 
+                       break; 
+               else
                        dest += ret;
                p = p->next;
        }
        restore_flags(flags);
-       return 0;
+       return ret;
 }
 
 static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1209,7 +1204,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
        isdn_ctrl c;
        int drvidx;
        int chidx;
-       int ret;
+       int ret = 0;
        char *s;
        char name[10];
        char bname[21];
@@ -1227,14 +1222,15 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         ulong *p = (ulong *)arg;
                                         int i;
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-                                                               sizeof(ulong)*ISDN_MAX_CHANNELS*2)))
-                                                return ret;
                                         for (i = 0;i<ISDN_MAX_CHANNELS;i++) {
-                                                put_fs_long(dev->ibytes[i],p++);
-                                                put_fs_long(dev->obytes[i],p++);
+                                                ret = put_user(dev->ibytes[i],p);
+                                                   if (ret) break; 
+                                                                                               p++; 
+                                                                                               ret = put_user(dev->obytes[i],p);
+                                                                                               p++; 
+                                                                                               if (ret) break; 
                                         }
-                                        return 0;
+                                        return ret;
                                 } else
                                         return -EINVAL;
                                 break;
@@ -1259,62 +1255,48 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                         case IIOCNETAIF:
                                 /* Add a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
+                                        if(copy_from_user(name, (char *) arg, sizeof(name)))
+                                                                                       return -EFAULT; 
                                         s = name;
                                 } else
                                         s = NULL;
                                 if ((s = isdn_net_new(s, NULL))) {
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
-                                                return ret;
-                                        copy_to_user((char *) arg, s, strlen(s) + 1);
-                                        return 0;
+                                                                           return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : ret; 
                                 } else
                                         return -ENODEV;
                         case IIOCNETASL:
                                 /* Add a slave to a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(bname))))
-                                                return ret;
-                                        copy_from_user(bname, (char *) arg, sizeof(bname));
+                                        if(copy_from_user(bname, (char *) arg, sizeof(bname)))
+                                                                                       return -EFAULT; 
                                 } else
                                         return -EINVAL;
                                 if ((s = isdn_net_newslave(bname))) {
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
-                                                return ret;
-                                        copy_to_user((char *) arg, s, strlen(s) + 1);
-                                        return 0;
+                                        return copy_to_user((char *) arg, s, strlen(s) + 1) ? -EFAULT : 0;
                                 } else
                                         return -ENODEV;
                         case IIOCNETDIF:
                                 /* Delete a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
-                                        return isdn_net_rm(name);
+                                        ret = copy_from_user(name, (char *) arg, sizeof(name));
+                                        return ret ? -EFAULT : isdn_net_rm(name);
                                 } else
                                         return -EINVAL;
                         case IIOCNETSCF:
                                 /* Set configurable parameters of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
-                                                return ret;
-                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
-                                        return isdn_net_setcfg(&cfg);
+                                        ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
+                                        return ret ? -EFAULT : isdn_net_setcfg(&cfg);
                                 } else
                                         return -EINVAL;
                         case IIOCNETGCF:
                                 /* Get configurable parameters of a network-interface */
-                                if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
-                                                return ret;
-                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
+                                if (arg) {                               
+                                        if(copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+                                                                                       return -EFAULT; 
                                         if (!(ret = isdn_net_getcfg(&cfg))) {
-                                                if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(cfg))))
-                                                        return ret;
-                                                copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg));
+                                                if(copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+                                                                                                       return -EFAULT; 
                                         }
                                         return ret;
                                 } else
@@ -1322,68 +1304,51 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                         case IIOCNETANM:
                                 /* Add a phone-number to a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
-                                                return ret;
-                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
-                                        return isdn_net_addphone(&phone);
+                                        ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+                                        return ret ? -EFAULT : isdn_net_addphone(&phone);
                                 } else
                                         return -EINVAL;
                         case IIOCNETGNM:
                                 /* Get list of phone-numbers of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
-                                                return ret;
-                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
-                                        return isdn_net_getphones(&phone, (char *) arg);
+                                        ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+                                        return ret ? -EFAULT : isdn_net_getphones(&phone, (char *) arg);
                                 } else
                                         return -EINVAL;
                         case IIOCNETDNM:
                                 /* Delete a phone-number of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
-                                                return ret;
-                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
-                                        return isdn_net_delphone(&phone);
+                                        ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
+                                        return ret ? -EFAULT : isdn_net_delphone(&phone);
                                 } else
                                         return -EINVAL;
                         case IIOCNETDIL:
                                 /* Force dialing of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
-                                        return isdn_net_force_dial(name);
+                                        ret = copy_from_user(name, (char *) arg, sizeof(name));
+                                        return ret ? -EFAULT : isdn_net_force_dial(name);
                                 } else
                                         return -EINVAL;
 #ifdef CONFIG_ISDN_PPP
                         case IIOCNETALN:
-                                if(arg) {
-                                        if ((ret = verify_area(VERIFY_READ,
-                                                               (void*)arg,
-                                                               sizeof(name))))
-                                                return ret;
-                                } else
-                                        return -EINVAL;
-                                copy_from_user(name,(char*)arg,sizeof(name));
-                                return isdn_ppp_dial_slave(name);
+                                                               if (arg) 
+                                        ret = copy_from_user(name,(char*)arg,sizeof(name));
+                                                               else
+                                                                           return -EINVAL; 
+                                return ret ? -EFAULT : isdn_ppp_dial_slave(name);
                         case IIOCNETDLN:
+                                                           
                                 if(arg) {
-                                        if ((ret = verify_area(VERIFY_READ,
-                                                               (void*)arg,
-                                                               sizeof(name))))
-                                                return ret;
+                                                                           ret = copy_from_user(name,(char*)arg,sizeof(name));
                                 } else
                                         return -EINVAL;
-                                copy_from_user(name,(char*)arg,sizeof(name));
-                                return isdn_ppp_hangup_slave(name);
+                                return ret ? -EFAULT : isdn_ppp_hangup_slave(name);
 #endif
                         case IIOCNETHUP:
                                 /* Force hangup of a network-interface */
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
-                                                return ret;
-                                        copy_from_user(name, (char *) arg, sizeof(name));
-                                        return isdn_net_force_hangup(name);
+                                        ret = copy_from_user(name, (char *) arg, sizeof(name));
+                                                                       return ret ? -EFAULT : isdn_net_force_hangup(name);
                                 } else
                                         return -EINVAL;
                                 break;
@@ -1405,12 +1370,10 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         int i;
                                         char *p;
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
-                                        copy_from_user((char *) &iocts, (char *) arg,
-                                                      sizeof(isdn_ioctl_struct));
-                                        if (strlen(iocts.drvid)) {
+                                        if(copy_from_user((char *) &iocts, (char *) arg,
+                                                      sizeof(isdn_ioctl_struct)))
+                                                                                       return -EFAULT; 
+                                                                               if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
                                                 drvidx = -1;
@@ -1450,17 +1413,14 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         char *p = (char *) arg;
                                         int i;
-                                        
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-                                                               (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
-                                                               * ISDN_MAX_CHANNELS)))
-                                                return ret;
-                                        
+                                                                   
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                copy_to_user(p, dev->mdm.info[i].emu.profile,
-                                                            ISDN_MODEM_ANZREG);
+                                                if(copy_to_user(p, dev->mdm.info[i].emu.profile,
+                                                            ISDN_MODEM_ANZREG))
+                                                                                                       return -EFAULT;
                                                 p += ISDN_MODEM_ANZREG;
-                                                copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
+                                                if(copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
+                                                                                                       return -EFAULT; 
                                                 p += ISDN_MSNLEN;
                                         }
                                         return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
@@ -1473,17 +1433,14 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         char *p = (char *) arg;
                                         int i;
                                         
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               (ISDN_MODEM_ANZREG + ISDN_MSNLEN)
-                                                               * ISDN_MAX_CHANNELS)))
-                                                return ret;
-                                        
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                copy_from_user(dev->mdm.info[i].emu.profile, p,
-                                                              ISDN_MODEM_ANZREG);
-                                                p += ISDN_MODEM_ANZREG;
-                                                copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
-                                                p += ISDN_MSNLEN;
+                                                if(copy_from_user(dev->mdm.info[i].emu.profile, p,
+                                                              ISDN_MODEM_ANZREG))
+                                                                                                       return -EFAULT; 
+                                                                                               p += ISDN_MODEM_ANZREG;
+                                                if(copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+                                                                                                       return -EFAULT; 
+                                                                                               p += ISDN_MSNLEN;
                                         }
                                         return 0;
                                 } else
@@ -1497,11 +1454,10 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         char *p;
                                         char nstring[255];
                                         
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
-                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
-                                        if (strlen(iocts.drvid)) {
+                                        ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                      
+                                                                               if (ret) return -EFAULT;
+                                                                               if (strlen(iocts.drvid)) {
                                                 drvidx = -1;
                                                 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
                                                         if (!(strcmp(dev->drvid[i], iocts.drvid))) {
@@ -1513,9 +1469,8 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         if (drvidx == -1)
                                                 return -ENODEV;
                                         if (cmd == IIOCSETMAP) {
-                                                if ((ret = verify_area(VERIFY_READ, (void *) iocts.arg, 255)))
-                                                        return ret;
-                                                copy_from_user(nstring, (char *) iocts.arg, 255);
+                                                ret = copy_from_user(nstring, (char *) iocts.arg, 255);
+                                                                                               if (ret) return -EFAULT; 
                                                 memset(dev->drv[drvidx]->msn2eaz, 0,
                                                        sizeof(dev->drv[drvidx]->msn2eaz));
                                                 p = strtok(nstring, ",");
@@ -1531,21 +1486,16 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                                      strlen(dev->drv[drvidx]->msn2eaz[i]) ?
                                                                      dev->drv[drvidx]->msn2eaz[i] : "-",
                                                                      (i < 9) ? "," : "\0");
-                                                if ((ret = verify_area(VERIFY_WRITE, (void *) iocts.arg,
-                                                                       strlen(nstring) + 1)))
-                                                        return ret;
-                                                copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1);
-                                        }
+                                                                                               if(copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1))
+                                                                                                       return -EFAULT; 
+                                                                               }
                                         return 0;
                                 } else
                                         return -EINVAL;
                         case IIOCDBGVAR:
                                 if (arg) {
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(ulong))))
-                                                return ret;
-                                        copy_to_user((char *) arg, (char *) &dev, sizeof(ulong));
-                                        return 0;
-                                } else
+                                        return copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)) ? -EFAULT : 0;
+                                                               } else
                                         return -EINVAL;
                                 break;
                         default:
@@ -1556,10 +1506,10 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         int i;
                                         char *p;
-                                        if ((ret = verify_area(VERIFY_READ, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
-                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+
+                                        ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                                                                               if (ret)
+                                                                                           return -EFAULT; 
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
@@ -1573,17 +1523,13 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                 drvidx = 0;
                                         if (drvidx == -1)
                                                 return -ENODEV;
-                                        if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-                                                               sizeof(isdn_ioctl_struct))))
-                                                return ret;
                                         c.driver = drvidx;
                                         c.command = ISDN_CMD_IOCTL;
                                         c.arg = cmd;
                                         memcpy(c.num, (char *) &iocts.arg, sizeof(ulong));
                                         ret = dev->drv[drvidx]->interface->command(&c);
                                         memcpy((char *) &iocts.arg, c.num, sizeof(ulong));
-                                        copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
-                                        return ret;
+                                        return copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)) ? -EFAULT : 0;
                                 } else
                                         return -EINVAL;
                }
@@ -1890,9 +1836,12 @@ int isdn_writebuf_stub(int drvidx, int chan, const u_char *buf, int len,
                 skb_reserve(skb, dev->drv[drvidx]->interface->hl_hdrlen);
                 skb->free = 1;
 
-                if (user)
-                        copy_from_user(skb_put(skb, len), buf, len);
-                else
+                if (user) {
+                                           if(copy_from_user(skb_put(skb, len), buf, len)) {
+                                                       kfree_skb(skb,FREE_WRITE);
+                                                       return -EFAULT; 
+                                               }
+                } else
                         memcpy(skb_put(skb, len), buf, len);
 
                 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx,
index f2bad4a18465a4375116542e1f39b46ab6263053..ad4e4c827d13968c64883550b07c99bcb8d7edbc 100644 (file)
@@ -170,14 +170,14 @@ isdn_net_open(struct device *dev)
                        p->start = 1;
                        p = (((isdn_net_local *) p->priv)->slave);
                }
-       }
+       }
 
-       isdn_MOD_INC_USE_COUNT();
-       return 0;
-}
+       isdn_MOD_INC_USE_COUNT(); 
+       return 0; 
+} 
 
-/*
- * Assign an ISDN-channel to a net-interface
+/* 
+ Assign an ISDN-channel to a net-interface 
  */
 static void
 isdn_net_bind_channel(isdn_net_local * lp, int idx)
@@ -2179,7 +2179,7 @@ int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
        int count = 0;
        isdn_net_phone *n;
        int flags;
-       int ret;
+       int ret = 0;
 
        if (!p)
                return -ENODEV;
@@ -2188,22 +2188,22 @@ int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
        inout &= 1;
         for (n = p->local.phone[inout]; n; n = n->next) {
                if (more) {
-                       put_fs_byte(' ', phones++);
+                       ret = put_user(((char)' '), phones);
+                       phones++; 
                        count++;
                }
-               if ((ret = verify_area(VERIFY_WRITE, (void *) phones, strlen(n->num) + 1))) {
+               if (ret || copy_to_user(phones, n->num, strlen(n->num) + 1)) {
                        restore_flags(flags);
-                       return ret;
+                       return -EFAULT;
                }
-               copy_to_user(phones, n->num, strlen(n->num) + 1);
                phones += strlen(n->num);
                count += strlen(n->num);
                more = 1;
        }
-        put_fs_byte(0,phones);
-        count++;
+    ret = put_user(((char)0),phones);  
+    count++;
        restore_flags(flags);
-       return count;
+       return ret ? -EFAULT : count;
 }
 
 /*
index 5a42490d9b0270a72a66681843371b5d036adb03..cfe209f6a7fe6d63a1885e28e939519728f83fcb 100644 (file)
@@ -345,15 +345,15 @@ void isdn_ppp_release(int min, struct file *file)
        is->state = 0;
 }
 
+#if 0 /* get_user() / put_user() in 2.1 replace them 1:1 */
 /*
  * get_arg .. ioctl helper
  */
 static int get_arg(void *b, unsigned long *val)
 {
        int r;
-       if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long))))
-                return r;
-       copy_from_user((void *) val, b, sizeof(unsigned long));
+       if (copy_from_user((void *) val, b, sizeof(unsigned long))) 
+               return -EFAULT; 
        return 0;
 }
 
@@ -368,6 +368,7 @@ static int set_arg(void *b, unsigned long val)
        copy_to_user(b, (void *) &val, sizeof(unsigned long));
        return 0;
 }
+#endif
 
 /*
  * ippp device ioctl 
@@ -377,6 +378,7 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
        unsigned long val;
        int r;
        struct ippp_struct *is;
+       unsigned long *argp = (unsigned long*)arg; 
 
        is = file->private_data;
 
@@ -389,7 +391,7 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
        switch (cmd) {
        case PPPIOCBUNDLE:
 #ifdef CONFIG_ISDN_MPP
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_user(val, arg)))
                        return r;
                printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
                         (int) min, (int) is->unit, (int) val);
@@ -399,24 +401,24 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
 #endif
                break;
        case PPPIOCGUNIT:       /* get ppp/isdn unit number */
-               if ((r = set_arg((void *) arg, is->unit)))
+               if ((r = put_user(is->unit, argp)))
                        return r;
                break;
        case PPPIOCGMPFLAGS:    /* get configuration flags */
-               if ((r = set_arg((void *) arg, is->mpppcfg)))
+               if ((r = put_user(is->mpppcfg, argp)))
                        return r;
                break;
        case PPPIOCSMPFLAGS:    /* set configuration flags */
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_user(val, argp)))
                        return r;
                is->mpppcfg = val;
                break;
        case PPPIOCGFLAGS:      /* get configuration flags */
-               if ((r = set_arg((void *) arg, is->pppcfg)))
+               if ((r = put_user(is->pppcfg ,argp)))
                        return r;
                break;
        case PPPIOCSFLAGS:      /* set configuration flags */
-               if ((r = get_arg((void *) arg, &val))) {
+               if ((r = get_user(val, argp))) {
                        return r;
                }
                if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) {
@@ -433,7 +435,7 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
                break;
 #endif
        case PPPIOCSMRU:        /* set receive unit size for PPP */
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_user(val, argp)))
                        return r;
                is->mru = val;
                break;
@@ -442,7 +444,7 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
        case PPPIOCSMPMTU:
                break;
        case PPPIOCSMAXCID:     /* set the maximum compression slot id */
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_user(val, argp)))
                        return r;
                val++;
                if(is->maxcid != val) {
@@ -465,11 +467,11 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
                }
                break;
        case PPPIOCGDEBUG:
-               if ((r = set_arg((void *) arg, is->debug)))
+               if ((r = put_user(is->debug, argp)))
                        return r;
                break;
        case PPPIOCSDEBUG:
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_user(val, argp)))
                        return r;
                is->debug = val;
                break;
@@ -594,9 +596,6 @@ int isdn_ppp_read(int min, struct file *file, char *buf, int count)
        if (!(is->state & IPPP_OPEN))
                return 0;
 
-       if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
-               return r;
-
        save_flags(flags);
        cli();
 
@@ -607,7 +606,8 @@ int isdn_ppp_read(int min, struct file *file, char *buf, int count)
        }
        if (b->len < count)
                count = b->len;
-       copy_to_user(buf, b->buf, count);
+       if (copy_to_user(buf, b->buf, count)) 
+               count = -EFAULT; /* ugly */
        kfree(b->buf);
        b->buf = NULL;
        is->first = b;
@@ -1447,11 +1447,7 @@ static int isdn_ppp_dev_ioctl_stats(int slot,struct ifreq *ifr,struct device *de
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
        int err;
 
-        res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
-        err = verify_area (VERIFY_WRITE, res,sizeof(struct ppp_stats));
-
-       if(err)
-               return err;
+       res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
 
        /* build a temporary stat struct and copy it to user space */
 
@@ -1475,9 +1471,7 @@ static int isdn_ppp_dev_ioctl_stats(int slot,struct ifreq *ifr,struct device *de
                }
 #endif
        }
-       copy_to_user (res, &t, sizeof (struct ppp_stats));
-       return 0;
-
+       return copy_to_user (res, &t, sizeof (struct ppp_stats)) ? -EFAULT : 0;
 }
 
 int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
@@ -1498,9 +1492,8 @@ int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
                case SIOCGPPPVER:
                        r = (char *) ifr->ifr_ifru.ifru_data;
                        len = strlen(PPP_VERSION) + 1;
-                       error = verify_area(VERIFY_WRITE, r, len);
-                       if (!error)
-                               copy_to_user(r, PPP_VERSION, len);
+                       if (copy_to_user(r, PPP_VERSION, len))
+                               error = -EFAULT; 
                        break;
                case SIOCGPPPSTATS:
                        error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
index 4444374adab26bbe952745ebbbcc98b1ae405ebc..28e47c11ec2b3bc6cf03645a6c1b01e2f4032dee 100644 (file)
@@ -1013,8 +1013,7 @@ static int isdn_tty_get_lsr_info(modem_info * info, uint * value)
        status = info->lsr;
        restore_flags(flags);
        result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-       put_user(result, (ulong *) value);
-       return 0;
+       return put_user(result, (ulong *) value);
 }
 
 
@@ -1035,14 +1034,18 @@ static int isdn_tty_get_modem_info(modem_info * info, uint * value)
            | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
            | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
            | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-       put_user(result, (ulong *) value);
-       return 0;
+       return put_user(result, (ulong *) value);
 }
 
 static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
 {
-       uint arg = get_user((uint *) value);
-        int pre_dtr;
+       uint arg;
+    int pre_dtr;
+       int error;
+
+       error = get_user(arg, ((uint *) value));
+       if (error)
+               return error;
 
        switch (cmd) {
                 case TIOCMBIS:
@@ -1140,19 +1143,17 @@ static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
 #endif
-                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
-                        if (error)
-                                return error;
-                        put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
+                        error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg);
+                                               if (error)
+                                                           return error;
                         return 0;
                 case TIOCSSOFTCAR:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
 #endif
-                        error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
-                        if (error)
-                                return error;
-                        arg = get_user((ulong *) arg);
+                        error = get_user(arg ,((ulong *) arg));
+                                               if (error)
+                                                           return error;
                         tty->termios->c_cflag =
                                 ((tty->termios->c_cflag & ~CLOCAL) |
                                  (arg ? CLOCAL : 0));
@@ -1161,26 +1162,16 @@ static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
 #endif
-                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-                        if (error)
-                                return error;
                         return isdn_tty_get_modem_info(info, (uint *) arg);
                 case TIOCMBIS:
                 case TIOCMBIC:
                 case TIOCMSET:
-                        error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint));
-                        if (error)
-                                return error;
                         return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
                 case TIOCSERGETLSR:    /* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                         printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
 #endif
-                        error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
-                        if (error)
-                                return error;
-                        else
-                                return isdn_tty_get_lsr_info(info, (uint *) arg);
+                        return isdn_tty_get_lsr_info(info, (uint *) arg);
                         
                 default:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
@@ -2670,7 +2661,7 @@ static int isdn_tty_edit_at(const char *p, int count, modem_info * info, int use
 
        for (cnt = count; cnt > 0; p++, cnt--) {
                if (user)
-                       c = get_user(p);
+                   get_user(c, p);
                else
                        c = *p;
                total++;
index d46c283632f3abd7c66810e5d027471f55fd4ccf..660db962c9092484a316c1d5dd87f892f6c81af9 100644 (file)
@@ -1450,9 +1450,10 @@ teles_writebuf(int id, int chan, const u_char * buf, int count, int user)
 
         ptr += i;
 
-        if (user)
-                memcpy_fromfs(ptr, buf, count);
-        else
+        if (user) {
+                if (copy_from_user(ptr, buf, count))
+                                       return -EFAULT;
+               } else
                 memcpy(ptr, buf, count);
         ibh->datasize = count + i;
 
index c90bcd00bc5ae0d120711c362b6d09fd86da085a..c0595e86264b30e3f9b527915e86c867135e2540 100644 (file)
@@ -64,6 +64,8 @@
 #include <linux/tqueue.h>
 #include <linux/interrupt.h>
 
+#include <asm/io.h>
+
 #undef DCHAN_VERBOSE
 
 extern void     tei_handler(struct PStack *st, byte pr,
@@ -75,9 +77,9 @@ extern int      nrcards;
 #define bytein(addr) inb_p(addr)
 
 static inline   byte
-readisac_0(byte * cardm, byte offset)
+readisac_0(unsigned int cardm, byte offset)
 {
-       return *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
+       return readb(cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
 }
 
 static inline   byte
@@ -90,9 +92,9 @@ readisac_3(int iobase, byte offset)
         ((mbase)?readisac_0(mbase,ofs):readisac_3(ibase,ofs))
 
 static inline void
-writeisac_0(byte * cardm, byte offset, byte value)
+writeisac_0(unsigned int cardm, byte offset, byte value)
 {
-       *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset) = value;
+       writeb(value, cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
 }
 
 static inline void
@@ -117,9 +119,9 @@ writeisac_s(int iobase, byte offset, byte * src, int count)
 }
 
 static inline   byte
-readhscx_0(byte * base, byte hscx, byte offset)
+readhscx_0(unsigned int base, byte hscx, byte offset)
 {
-       return *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
+       return readb(base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
                          ((hscx & 1) ? 0x40 : 0) + offset);
 }
 
@@ -133,10 +135,10 @@ readhscx_3(int iobase, byte hscx, byte offset)
         ((mbase)?readhscx_0(mbase,hscx,ofs):readhscx_3(ibase,hscx,ofs))
 
 static inline void
-writehscx_0(byte * base, byte hscx, byte offset, byte data)
+writehscx_0(unsigned int base, byte hscx, byte offset, byte data)
 {
-       *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
-                  ((hscx & 1) ? 0x40 : 0) + offset) = data;
+       writeb(data, base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
+                  ((hscx & 1) ? 0x40 : 0) + offset);
 }
 
 static inline void
@@ -199,7 +201,7 @@ writehscx_s(int iobase, byte hscx, byte offset, byte * src, int count)
 #define HSCX_MASK 0x20
 
 static inline void
-waitforCEC_0(byte * base, byte hscx)
+waitforCEC_0(unsigned int base, byte hscx)
 {
        long            to = 10;
 
@@ -225,7 +227,7 @@ waitforCEC_3(int iobase, byte hscx)
 }
 
 static inline void
-waitforXFW_0(byte * base, byte hscx)
+waitforXFW_0(unsigned int base, byte hscx)
 {
        long            to = 20;
 
@@ -251,7 +253,7 @@ waitforXFW_3(int iobase, byte hscx)
 }
 
 static inline void
-writehscxCMDR_0(byte * base, byte hscx, byte data)
+writehscxCMDR_0(unsigned int base, byte hscx, byte data)
 {
        long            flags;
 
@@ -1059,7 +1061,7 @@ restart_ph(struct IsdnCardState *sp)
 }
 
 static void
-initisac(byte * cardmem, int iobase)
+initisac(unsigned int cardmem, int iobase)
 {
         if (cardmem) {
                 writeisac_0(cardmem, ISAC_MASK, 0xff);
@@ -1093,17 +1095,17 @@ checkcard(int cardnr)
        struct IsdnCard *card = cards + cardnr;
 
         if (card->membase)
-                if ((unsigned long)card->membase < 0x10000) {
-                        (unsigned long)card->membase <<= 4;
+                if (card->membase < 0x10000) {
+                        card->membase <<= 4;
                         printk(KERN_INFO
-                               "Teles membase configured DOSish, assuming 0x%lx\n",
-                               (unsigned long)card->membase);
+                               "Teles membase configured DOSish, assuming 0x%x\n",
+                               card->membase);
                 }
         if (!card->iobase) {
                 if (card->membase) {
                         printk(KERN_NOTICE
-                               "Teles 8 assumed, mem: %lx irq: %d proto: %s\n",
-                               (long) card->membase, card->interrupt,
+                               "Teles 8 assumed, mem: %x irq: %d proto: %s\n",
+                               card->membase, card->interrupt,
                                (card->protocol == ISDN_PTYPE_1TR6) ?
                                "1TR6" : "EDSS1");
                         printk(KERN_INFO "HSCX version A:%x B:%x\n",
@@ -1186,7 +1188,7 @@ checkcard(int cardnr)
                         break;
                 }
                 if (card->membase) {
-                        cfval |= (((unsigned int) card->membase >> 9) & 0xF0);
+                        cfval |= (card->membase >> 9) & 0xF0;
                 }   
                 if (bytein(card->iobase + 0) != 0x51) {
                         printk(KERN_INFO "XXX Byte at %x is %x\n",
@@ -1232,8 +1234,8 @@ checkcard(int cardnr)
                 
                 if (card->membase)
                         printk(KERN_NOTICE
-                               "Teles 16.0 found, io: %x mem: %lx irq: %d proto: %s\n",
-                               card->iobase, (long) card->membase,
+                               "Teles 16.0 found, io: %x mem: %x irq: %d proto: %s\n",
+                               card->iobase, card->membase,
                                card->interrupt,
                                (card->protocol == ISDN_PTYPE_1TR6) ?
                                "1TR6" : "EDSS1");
@@ -1253,12 +1255,12 @@ checkcard(int cardnr)
         if (card->membase) {
                 cli();
                 timout = jiffies + (HZ / 5) + 1;
-                *(byte *) (card->membase + 0x80) = 0;
+                writeb(0, card->membase + 0x80);
                 sti();
                 while (jiffies <= timout);
                 
                 cli();
-                *(byte *) (card->membase + 0x80) = 1;
+                writeb(1, card->membase + 0x80);
                 timout = jiffies + (HZ / 5) + 1;
                 sti();
                 while (jiffies <= timout);
index 1a9d2d87322fe687b61bd7aaaa5a8357a4992c86..86d29afa5fe6e5ea803839f1a152385fdcfef079 100644 (file)
 
 struct IsdnCard cards[] =
 {
-       {(byte *) 0xd0000, 15, 0xd80, ISDN_PTYPE_EURO, NULL},   /* example */
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
-       {NULL, 0, 0, 0, NULL},
+       {0xd0000, 15, 0xd80, ISDN_PTYPE_EURO, NULL},    /* example */
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
+       {0, 0, 0, 0, NULL},
 };
index ce022f7a0e06714e57c3811093dff673de6f24c2..81a0a1e00bef6c4e14f6374289a02c738b1fb73f 100644 (file)
@@ -46,9 +46,10 @@ teles_readstatus(byte * buf, int len, int user, int id, int channel)
        byte           *p;
 
        for (p = buf, count = 0; count < len; p++, count++) {
-               if (user)
-                       put_fs_byte(*teles_status_read++, p);
-               else
+               if (user) {
+                       put_user(*teles_status_read, p);
+                       teles_status_read++; 
+               } else
                        *p++ = *teles_status_read++;
                if (teles_status_read > teles_status_end)
                        teles_status_read = teles_status_buf;
index 821ac8ee3495575efb04df6b08df64c8d9b75a68..0b12d9c92ea87cecaf86cfa51cc2878569253a55 100644 (file)
@@ -14,7 +14,7 @@ extern char   *teles_id;
 int             nrcards;
 
 typedef struct {
-       byte           *membase;
+       unsigned int    membase;
        int             interrupt;
        unsigned int    iobase;
        unsigned int    protocol;
@@ -73,7 +73,7 @@ void teles_setup(char *str, int *ints)
                         j++; argc--;
                 }
                 if (argc) {
-                        io[i].membase   = (byte *)ints[j];
+                        io[i].membase   = ints[j];
                         j++; argc--;
                 }
                 if (argc) {
index 15ce659761d793e2a034016d1946e6febe88c11e..502169a6b47ff9b0596ad4de9c5be562bf220443 100644 (file)
@@ -14,8 +14,6 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
-#include <asm/segment.h>
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -28,6 +26,9 @@
 #include <linux/isdnif.h>
 #include <linux/tty.h>
 
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
 #define PH_ACTIVATE   1
 #define PH_DATA       2
 #define PH_DEACTIVATE 3
@@ -306,7 +307,7 @@ struct PStack {
 };
 
 struct HscxState {
-       byte           *membase;
+       unsigned int    membase;
        int             iobase;
        int             inuse, init, active;
        struct BufPool  sbufpool, rbufpool, smallpool;
@@ -329,7 +330,7 @@ struct IsdnCardState {
 #ifdef DEBUG_MAGIC
        int             magic;
 #endif
-       byte           *membase;
+       unsigned int    membase;
        int             iobase;
        struct BufPool  sbufpool, rbufpool, smallpool;
        struct PStack  *stlist;
@@ -351,7 +352,7 @@ struct IsdnCardState {
 };
 
 struct IsdnCard {
-       byte           *membase;
+       unsigned int    membase;
        int             interrupt;
        unsigned int    iobase;
        int             protocol;       /* EDSS1 or 1TR6 */
index c0adaaa64df90ee0d420456c3cb76955964a9fea..36b58bff9e77cfbe789422804ac5dbcf07b0cfe4 100644 (file)
@@ -315,7 +315,7 @@ init_module(void)
 
        root_vortex_dev = NULL;
        cards_found = vortex_scan(0);
-       return cards_found < 0 ? cards_found : 0;
+       return cards_found ? 0 : -ENODEV;
 }
 
 #else
index 9864106bafb8a7f1c8a46b3417a95f56d31e431f..e9c56d6c8e4111005062bdb348e7bf3272960b02 100644 (file)
@@ -48,7 +48,7 @@ static const char *version =
 #include <linux/ptrace.h>
 #include <linux/string.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
index e1fca14c470e5cd138ee5069a4316571380e902d..8083084b22a5f0787e53af33764e598116f620dd 100644 (file)
@@ -416,6 +416,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_SCC),y)
+L_OBJS += scc.o
+else
+  ifeq ($(CONFIG_SCC),m)
+  M_OBJS += scc.o
+  endif
+endif
+
 ifeq ($(CONFIG_PI),y)
 L_OBJS += pi2.o
 endif
diff --git a/drivers/net/README.scc b/drivers/net/README.scc
new file mode 100644 (file)
index 0000000..b3eb344
--- /dev/null
@@ -0,0 +1,23 @@
+
+You will find subset of the documentation in
+
+                 linux/Documentation/networking/z8530drv.txt
+
+To use this driver you MUST have the full package from:
+
+Internet:
+=========
+
+1. db0bm.automation.fh-aachen.de/incoming/dl1bke/z8530drv-utils-3.0.tar.gz
+
+2. ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-utils-3.0.tar.gz
+   If you can't find it there, try .../tcpip/linux/z8530drv-utils-3.0.tar.gz
+
+and various mirrors (i.e. nic.switch.ch)
+
+The package includes the utilities necessary to initialize and
+control the driver.
+
+Joerg Reuter   ampr-net: dl1bke@db0pra.ampr.org
+               AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
+               Internet: jreuter@lykos.oche.de
index 626dff2345d27049b414c22a557602c9314d0921..2e18e2d5b069087e909604c67a7433913285ba42 100644 (file)
          
        **********************
        
+       v2.56 (96/10/18)
+         - Turned arc0e/arc0s startup messages back on by default, as most
+           people will probably not notice the additional devices
+           otherwise, and experience more protocol confusion than
+           necessary.
+         - Fixed a tiny but noticeable bug in the packet debugging routines
+           (thanks Tomasz)
+
        v2.55 (96/08/05)
          - A couple more messages moved to D_EXTRA.
          - SLOW_XMIT_COPY off by default.
 */
 
 static const char *version =
- "arcnet.c: v2.55 96/08/05 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.56 96/10/18 Avery Pennarun <apenwarr@foxnet.net>\n";
 
  
 
@@ -708,8 +716,7 @@ void arcnet_dump_skb(struct device *dev,struct sk_buff *skb,char *desc)
         {
                if (i%16==0)
                        printk("\n" KERN_DEBUG "[%04X] ",i);
-               else
-                               printk("%02X ",((u_char *)skb->data)[i]);
+                       printk("%02X ",((u_char *)skb->data)[i]);
        }
         printk("\n");
         restore_flags(flags);
@@ -731,8 +738,7 @@ void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,char *desc)
        {
                if (i%16==0)
                        printk("\n" KERN_DEBUG "[%04X] ",i);
-               else
-                       printk("%02X ",buffer[i]);
+               printk("%02X ",buffer[i]);
        }
        printk("\n");
        restore_flags(flags);
@@ -754,6 +760,8 @@ void arcnet_dump_packet(struct device *dev,u_char *buffer,int ext,char *desc)
  * NOTE: the list of possible ports/shmems is static, so it is retained
  * across calls to arcnet_probe.  So, if more than one ARCnet probe is made,
  * values that were discarded once will not even be tried again.
+ *
+ * FIXME: grab all devices in one shot and eliminate the big static array.
  */
 int arcnet_probe(struct device *dev)
 {
@@ -775,9 +783,8 @@ int arcnet_probe(struct device *dev)
                        ports[(count-0x200)/16] = count;
                for (count=0xA0000; count<=0xFF800; count+=2048)
                        shmems[(count-0xA0000)/2048] = count;
-       }
-       else
                init_once=1;
+       }
 
        BUGLVL(D_NORMAL) printk(version);
 
@@ -1370,7 +1377,7 @@ arcnet_open(struct device *dev)
        
        /* The RFC1201 driver is the default - just store */
        lp->adev=dev;
-       BUGMSG(D_EXTRA,"ARCnet RFC1201 protocol initialized.\n");
+       BUGMSG(D_NORMAL,"ARCnet RFC1201 protocol initialized.\n");
 
 #ifdef CONFIG_ARCNET_ETH       
        /* Initialize the ethernet-encap protocol driver */
@@ -1388,7 +1395,7 @@ arcnet_open(struct device *dev)
        lp->edev->init=arcnetE_init;
        register_netdev(lp->edev);
 #else
-       BUGMSG(D_EXTRA,"Ethernet-Encap protocol not available (disabled).\n");
+       BUGMSG(D_NORMAL,"Ethernet-Encap protocol not available (disabled).\n");
 #endif
 
 #ifdef CONFIG_ARCNET_1051
@@ -1400,7 +1407,7 @@ arcnet_open(struct device *dev)
        lp->sdev->init=arcnetS_init;
        register_netdev(lp->sdev);
 #else
-       BUGMSG(D_EXTRA,"RFC1051 protocol not available (disabled).\n");
+       BUGMSG(D_NORMAL,"RFC1051 protocol not available (disabled).\n");
 #endif
 
        /* we're started */
@@ -2781,7 +2788,7 @@ static int arcnetE_init(struct device *dev)
        dev->stop=arcnetE_open_close;
        dev->hard_start_xmit=arcnetE_send_packet;
 
-       BUGMSG(D_EXTRA,"ARCnet Ethernet-Encap protocol initialized.\n");
+       BUGMSG(D_NORMAL,"ARCnet Ethernet-Encap protocol initialized.\n");
                        
        return 0;
 }
@@ -2961,7 +2968,7 @@ static int arcnetS_init(struct device *dev)
        dev->hard_start_xmit=arcnetS_send_packet;
        dev->hard_header=arcnetS_header;
        dev->rebuild_header=arcnetS_rebuild_header;
-       BUGMSG(D_EXTRA,"ARCnet RFC1051 (NetBSD, AmiTCP) protocol initialized.\n");
+       BUGMSG(D_NORMAL,"ARCnet RFC1051 (NetBSD, AmiTCP) protocol initialized.\n");
 
        return 0;
 }
@@ -3241,10 +3248,10 @@ static struct device thiscard = {
        
        
 static int io=0x0;     /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
-static int irqnum=0;   /* or use the insmod io= irqnum= shmem= options */
+static int irqnum=0;   /* or use the insmod io= irq= shmem= options */
 static int irq=0;
 static int shmem=0;
-static char *device = NULL;
+static char *device = NULL;    /* use eg. device="arc1" to change name */
 
 int
 init_module(void)
@@ -3304,15 +3311,3 @@ cleanup_module(void)
 }
 
 #endif /* MODULE */
-
-
-\f
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c arcnet.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 8
- * End:
- */
-
index 0087c9c7cd0c2bee462c0ce573d3f039faab8076..1e1c194f09fbbe91802db25e10509c6313399bd9 100644 (file)
@@ -76,7 +76,7 @@
 
 #include <asm/system.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
 #include <linux/if.h>
index b307b2b5e9e0b4d5bec80d864836aa8e72270c2f..9a40201816f7ed85fcf38967cab7ff73fc1913b0 100644 (file)
@@ -234,7 +234,7 @@ static const char *version = "de4x5.c:v0.441 96/9/9 davies@wanton.lkg.dec.com\n"
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 7d8043623416f0c53eb87e3cef4a6118efd16c3b..19d5caaa2d0ba195794cf77ff802f0247e29b045 100644 (file)
@@ -221,7 +221,7 @@ static const char *version = "depca.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n"
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
index ea5d4ae9e86c1a236d7babd1187e1d90623a064c..cbfb2aa716f10ac13ba008f2743a51a559fa660e 100644 (file)
@@ -154,7 +154,7 @@ static const char *version = "ewrk3.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n"
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 7c3e1cad4a2087b2914438aadf81ee9f54d4aedc..443f67ec001081fd513f23b214d4311d5e77b97e 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/in.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/inet.h>
index ee4392fcf939a9fa7e3c8313f93d09e9427d9e0c..cc05dd2cf1501770c37d57458adf32e635edda30 100644 (file)
@@ -109,7 +109,7 @@ static const char *version =
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index a562a5e80a4997cb92241faacce56b0c0eca5220..65de51ed5466e0e000d9dabae5cbdda126037668 100644 (file)
@@ -76,7 +76,7 @@
 #include <linux/signal.h>      /* used in new tty drivers */
 #include <asm/system.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
index f08e3aeb61ccee4e5d76302b387e10c078577e07..da40c907cebf1906d4c9e4a8784c5146785fb084 100644 (file)
@@ -79,7 +79,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff --git a/drivers/net/scc.c b/drivers/net/scc.c
new file mode 100644 (file)
index 0000000..3bef372
--- /dev/null
@@ -0,0 +1,2287 @@
+#define RCS_ID "$Id: scc.c,v 1.63 1996/10/09 16:45:47 jreuter Exp jreuter $"
+
+#define VERSION "3.0"
+#define BANNER  "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
+
+/*
+ * Please use z8530drv-utils-3.0 with this version.
+ *            ------------------
+ */
+
+/*
+   ********************************************************************
+   *   SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      *
+   ********************************************************************
+
+
+   ********************************************************************
+
+       Copyright (c) 1993, 1996 Joerg Reuter DL1BKE
+
+       portions (c) 1993 Guido ten Dolle PE1NNZ
+
+   ********************************************************************
+   
+   The driver and the programs in the archive are UNDER CONSTRUCTION.
+   The code is likely to fail, and so your kernel could --- even 
+   a whole network. 
+
+   This driver is intended for Amateur Radio use. If you are running it
+   for commercial purposes, please drop me a note. I am nosy...
+
+   ...BUT:
+   ! You  m u s t  recognize the appropriate legislations of your country !
+   ! before you connect a radio to the SCC board and start to transmit or !
+   ! receive. The GPL allows you to use the  d r i v e r,  NOT the RADIO! !
+
+   For non-Amateur-Radio use please note that you might need a special
+   allowance/licence from the designer of the SCC Board and/or the
+   MODEM. 
+
+   This program is free software; you can redistribute it and/or modify 
+   it under the terms of the (modified) GNU General Public License 
+   delivered with the Linux kernel source.
+   
+   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 find a copy of the GNU General Public License in 
+   /usr/src/linux/COPYING; 
+   
+   ******************************************************************** 
+
+               
+   Incomplete history of z8530drv:
+   -------------------------------
+
+   940913      - started to write the driver, rescued most of my own
+                 code (and Hans Alblas' memory buffer pool concept) from 
+                 an earlier project "sccdrv" which was initiated by 
+                 Guido ten Dolle. Not much of the old driver survived, 
+                 though. The first version I put my hands on was sccdrv1.3
+                 from August 1993. The memory buffer pool concept
+                 appeared in an unauthorized sccdrv version (1.5) from
+                 August 1994.
+
+   950131      - changed copyright notice to GPL without limitations.
+   
+     .
+     . <SNIP>
+     .
+                 
+   961005      - New semester, new driver... 
+
+                 * KISS TNC emulator removed (TTY driver)
+                 * Source moved to drivers/net/
+                 * Includes Z8530 defines from drivers/net/z8530.h
+                 * Uses sk_buffer memory management
+                 * Doesn't have own queues anymore
+                 * Reduced overhead of /proc/net/z8530drv output
+                 * Streamlined quite a lot things
+                 * Invents brand new bugs... ;-)
+
+                 The move to version number 3.0 reflects theses changes.
+                 You can use version 2.4 if you need a KISS TNC emulator.
+
+   Thanks to all who contributed to this driver with ideas and bug
+   reports!
+   
+   NB -- if you find errors, change something, please let me know
+        first before you distribute it... And please don't touch
+        the version number. Just replace my callsign in
+        "v3.0.dl1bke" with your own. Just to avoid confusion...
+
+   If you want to add your modification to the linux distribution
+   please (!) contact me first.
+   
+   New versions of the driver will be announced on the linux-hams
+   mailing list on vger.rutgers.edu. To subscribe send an e-mail
+   to majordomo@vger.rutgers.edu with the following line in
+   the body of the mail:
+   
+          subscribe linux-hams
+          
+   The content of the "Subject" field will be ignored.
+
+   vy 73,
+   Joerg Reuter        ampr-net: dl1bke@db0pra.ampr.org
+               AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
+               Internet: jreuter@lykos.oche.de  
+*/
+
+/* ----------------------------------------------------------------------- */
+
+#undef  SCC_DELAY      /* perhaps your ISA bus is a *bit* too fast? */
+#undef  SCC_LDELAY 1   /* slow it even a bit more down */
+#undef  DONT_CHECK     /* don't look if the SCCs you specified are available */
+
+#define MAXSCC          4       /* number of max. supported chips */
+#define BUFSIZE         384     /* must not exceed 4096 */
+#undef  DISABLE_ALL_INTS       /* use cli()/sti() in ISR instead of */
+                               /* enable_irq()/disable_irq()        */
+#undef SCC_DEBUG
+
+#define DEFAULT_CLOCK  4915200 /* default pclock if nothing is specified */
+
+/* ----------------------------------------------------------------------- */
+
+#include <linux/module.h>
+#include <linux/config.h>
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/socket.h>
+
+#include <linux/scc.h>
+#include "z8530.h"
+
+#include <net/ax25.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+#endif
+
+int scc_init(void);
+
+static void t_dwait(unsigned long);
+static void t_txdelay(unsigned long);
+static void t_tail(unsigned long);
+static void t_busy(unsigned long);
+static void t_maxkeyup(unsigned long);
+static void t_idle(unsigned long);
+static void scc_tx_done(struct scc_channel *);
+static void scc_start_tx_timer(struct scc_channel *, void (*)(unsigned long), unsigned long);
+static void scc_start_maxkeyup(struct scc_channel *);
+static void scc_start_defer(struct scc_channel *);
+
+static void z8530_init(void);
+
+static void init_channel(struct scc_channel *scc);
+static void scc_key_trx (struct scc_channel *scc, char tx);
+static void scc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static void scc_init_timer(struct scc_channel *scc);
+
+static int scc_net_setup(struct scc_channel *scc, unsigned char *name);
+static int scc_net_init(struct device *dev);
+static int scc_net_open(struct device *dev);
+static int scc_net_close(struct device *dev);
+static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
+static int scc_net_tx(struct sk_buff *skb, struct device *dev);
+static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static int scc_net_set_mac_address(struct device *dev, void *addr);
+static int scc_net_rebuild_header(void *buff, struct device *dev, unsigned long raddr, struct sk_buff *skb);
+static int scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);
+static struct enet_statistics * scc_net_get_stats(struct device *dev);
+
+static unsigned char *SCC_DriverName = "scc";
+
+static struct irqflags { unsigned char used : 1; } Ivec[16];
+       
+static struct scc_channel SCC_Info[2 * MAXSCC];        /* information per channel */
+
+static struct scc_ctrl {
+       io_port chan_A;
+       io_port chan_B;
+       int irq;
+} SCC_ctrl[MAXSCC+1];
+
+static unsigned char Driver_Initialized = 0;
+static int Nchips = 0;
+static io_port Vector_Latch = 0;
+
+
+/* ******************************************************************** */
+/* *                   Port Access Functions                         * */
+/* ******************************************************************** */
+
+/* These provide interrupt save 2-step access to the Z8530 registers */
+
+static __inline__ unsigned char
+InReg(io_port port, unsigned char reg)
+{
+       unsigned long flags;
+       unsigned char r;
+       
+       save_flags(flags);
+       cli();
+#ifdef SCC_LDELAY
+       Outb(port, reg);
+       udelay(SCC_LDELAY);
+       r=Inb(port);
+       udelay(SCC_LDELAY);
+#else
+       Outb(port, reg);
+       r=Inb(port);
+#endif
+       restore_flags(flags);
+       return r;
+}
+
+static __inline__ void
+OutReg(io_port port, unsigned char reg, unsigned char val)
+{
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+#ifdef SCC_LDELAY
+       Outb(port, reg); udelay(SCC_LDELAY);
+       Outb(port, val); udelay(SCC_LDELAY);
+#else
+       Outb(port, reg);
+       Outb(port, val);
+#endif
+       restore_flags(flags);
+}
+
+static __inline__ void
+wr(struct scc_channel *scc, unsigned char reg, unsigned char val)
+{
+       OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
+}
+
+static __inline__ void
+or(struct scc_channel *scc, unsigned char reg, unsigned char val)
+{
+       OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
+}
+
+static __inline__ void
+cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
+{
+       OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
+}
+
+#ifdef DISABLE_ALL_INTS
+static __inline__ void scc_cli(int irq)
+{ cli(); }
+static __inline__ void scc_sti(int irq)
+{ sti(); }
+#else
+static __inline__ void scc_cli(int irq)
+{ disable_irq(irq); }
+static __inline__ void scc_sti(int irq)
+{ enable_irq(irq); }
+#endif
+
+/* ******************************************************************** */
+/* *                   Some useful macros                            * */
+/* ******************************************************************** */
+
+
+static __inline__ void
+scc_lock_dev(struct scc_channel *scc)
+{
+       scc->dev->tbusy = 1;
+}
+
+static __inline__ void
+scc_unlock_dev(struct scc_channel *scc)
+{
+       scc->tx_next_buff = NULL;
+       scc->dev->tbusy = 0;
+}
+
+static __inline__ void
+scc_discard_buffers(struct scc_channel *scc)
+{
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+       
+       if (scc->tx_buff != NULL)
+       {
+               dev_kfree_skb(scc->tx_buff, FREE_WRITE);
+               scc->tx_buff = NULL;
+       }
+       
+       if (scc->tx_next_buff != NULL)
+       {
+               dev_kfree_skb(scc->tx_next_buff, FREE_WRITE);
+               scc->tx_next_buff = NULL;
+       }
+       
+       restore_flags(flags);
+}
+
+
+
+/* ******************************************************************** */
+/* *                   Interrupt Service Routines                    * */
+/* ******************************************************************** */
+
+
+/* ----> subroutines for the interrupt handlers <---- */
+
+static __inline__ void
+scc_notify(struct scc_channel *scc, int event)
+{
+       struct sk_buff *skb;
+       char *bp;
+       
+        if (scc->kiss.fulldup != KISS_DUPLEX_OPTIMA)
+               return;
+
+       skb = dev_alloc_skb(2);
+       if (skb != NULL)
+       {
+               skb->free = 1;
+               bp = skb_put(skb, 2);
+               *bp++ = PARAM_HWEVENT;
+               *bp++ = event;
+               scc_net_rx(scc, skb);
+       } else
+               scc->stat.nospace++;
+}
+
+static __inline__ void
+flush_rx_FIFO(struct scc_channel *scc)
+{
+       int k;
+       
+       for (k=0; k<3; k++)
+               Inb(scc->data);
+               
+       if(scc->rx_buff != NULL)                /* did we receive something? */
+       {
+               scc->stat.rxerrs++;  /* then count it as an error */
+               kfree_skb(scc->rx_buff, FREE_READ);
+               scc->rx_buff = NULL;
+       }
+}
+
+
+/* ----> four different interrupt handlers for Tx, Rx, changing of     */
+/*       DCD/CTS and Rx/Tx errors                                      */
+
+/* Transmitter interrupt handler */
+static __inline__ void
+scc_txint(struct scc_channel *scc)
+{
+       struct sk_buff *skb;
+
+       scc->stat.txints++;
+       skb = scc->tx_buff;
+       
+       /* send first octet */
+       
+       if (skb == NULL)
+       {
+               skb = scc->tx_next_buff;
+               scc->tx_buff = skb;
+
+               if (skb == NULL)
+               {
+                       scc_tx_done(scc);
+                       Outb(scc->ctrl, RES_Tx_P);
+                       return;
+               }
+               
+               if (skb->len == 0)              /* Paranoia... */
+               {
+                       dev_kfree_skb(skb, FREE_WRITE);
+                       scc->tx_buff = NULL;
+                       scc_tx_done(scc);
+                       Outb(scc->ctrl, RES_Tx_P);
+                       return;
+               }
+               
+               scc_unlock_dev(scc);
+
+               scc->stat.tx_state = TXS_ACTIVE;
+
+               OutReg(scc->ctrl, R0, RES_Tx_CRC);
+                                               /* reset CRC generator */
+               or(scc,R10,ABUNDER);            /* re-install underrun protection */
+               Outb(scc->data,*skb->data);     /* send byte */
+               skb_pull(skb, 1);
+
+               if (!scc->enhanced)             /* reset EOM latch */
+                       Outb(scc->ctrl,RES_EOM_L);
+               return;
+       }
+       
+       /* End Of Frame... */
+       
+       if (skb->len == 0)
+       {
+               Outb(scc->ctrl, RES_Tx_P);      /* reset pending int */
+               cl(scc, R10, ABUNDER);          /* send CRC */
+               dev_kfree_skb(skb, FREE_WRITE);
+               scc->tx_buff = NULL;
+               scc->stat.tx_state = TXS_NEWFRAME; /* next frame... */
+               return;
+       } 
+       
+       /* send octet */
+       
+       Outb(scc->data,*skb->data);             
+       skb_pull(skb, 1);
+}
+
+
+/* External/Status interrupt handler */
+static __inline__ void
+scc_exint(struct scc_channel *scc)
+{
+       unsigned char status,changes,chg_and_stat;
+
+       scc->stat.exints++;
+
+       status = InReg(scc->ctrl,R0);
+       changes = status ^ scc->status;
+       chg_and_stat = changes & status;
+       
+       /* ABORT: generated whenever DCD drops while receiving */
+
+       if (chg_and_stat & BRK_ABRT)            /* Received an ABORT */
+               flush_rx_FIFO(scc);
+
+
+       /* DCD: on = start to receive packet, off = ABORT condition */
+       /* (a successfully received packet generates a special condition int) */
+       
+       if(changes & DCD)                       /* DCD input changed state */
+       {
+               if(status & DCD)                /* DCD is now ON */
+               {
+                       if (scc->modem.clocksrc != CLK_EXTERNAL)
+                               OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
+                               
+                       or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
+               } else {                        /* DCD is now OFF */
+                       cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
+                       flush_rx_FIFO(scc);
+               }
+               
+               if (!scc->kiss.softdcd)
+                       scc_notify(scc, (status & DCD)? HWEV_DCD_ON:HWEV_DCD_OFF);
+       }
+       
+       /* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
+       
+       if (changes & SYNC_HUNT)
+       {
+               if (scc->kiss.softdcd)
+                       scc_notify(scc, (status & SYNC_HUNT)? HWEV_DCD_OFF:HWEV_DCD_ON);
+               else
+                       cl(scc,R15,SYNCIE);     /* oops, we were too lazy to disable this? */
+       }
+
+#ifdef notdef
+       /* CTS: use external TxDelay (what's that good for?!)
+        * Anyway: If we _could_ use it (BayCom USCC uses CTS for
+        * own purposes) we _should_ use the "autoenable" feature
+        * of the Z8530 and not this interrupt...
+        */
+        
+       if (chg_and_stat & CTS)                 /* CTS is now ON */
+       {
+               if (scc->kiss.txdelay == 0)     /* zero TXDELAY = wait for CTS */
+                       scc_start_tx_timer(scc, t_txdelay, 0);
+       }
+#endif
+       
+       if (scc->stat.tx_state == TXS_ACTIVE && (status & TxEOM))
+       {
+               scc->stat.tx_under++;     /* oops, an underrun! count 'em */
+               Outb(scc->ctrl, RES_EXT_INT);   /* reset ext/status interrupts */
+
+               if (scc->tx_buff != NULL)
+               {
+                       dev_kfree_skb(scc->tx_buff, FREE_WRITE);
+                       scc->tx_buff = NULL;
+               }
+               
+               or(scc,R10,ABUNDER);
+               scc_start_tx_timer(scc, t_txdelay, 1);  /* restart transmission */
+       }
+               
+       scc->status = status;
+       Outb(scc->ctrl,RES_EXT_INT);
+}
+
+
+/* Receiver interrupt handler */
+static __inline__ void
+scc_rxint(struct scc_channel *scc)
+{
+       struct sk_buff *skb;
+
+       scc->stat.rxints++;
+
+       if((scc->wreg[5] & RTS) && scc->kiss.fulldup == KISS_DUPLEX_HALF)
+       {
+               Inb(scc->data);         /* discard char */
+               or(scc,R3,ENT_HM);      /* enter hunt mode for next flag */
+               return;
+       }
+
+       skb = scc->rx_buff;
+       
+       if (skb == NULL)
+       {
+               skb = dev_alloc_skb(scc->stat.bufsize);
+               if (skb == NULL)
+               {
+                       scc->dev_stat.rx_dropped++;
+                       scc->stat.nospace++;
+                       Inb(scc->data);
+                       or(scc, R3, ENT_HM);
+                       return;
+               }
+               
+               skb->free = 1;
+               scc->rx_buff = skb;
+               
+               *(skb_put(skb, 1)) = 0; /* KISS data */
+       }
+       
+       if (skb->len >= scc->stat.bufsize)
+       {
+#ifdef notdef
+               printk(KERN_DEBUG "z8530drv: oops, scc_rxint() received huge frame...\n");
+#endif
+               kfree_skb(skb, FREE_READ);
+               scc->rx_buff = NULL;
+               Inb(scc->data);
+               or(scc, R3, ENT_HM);
+               return;
+       }
+
+       *(skb_put(skb, 1)) = Inb(scc->data);
+}
+
+
+/* Receive Special Condition interrupt handler */
+static __inline__ void
+scc_spint(struct scc_channel *scc)
+{
+       unsigned char status;
+       struct sk_buff *skb;
+
+       scc->stat.spints++;
+
+       status = InReg(scc->ctrl,R1);           /* read receiver status */
+       
+       Inb(scc->data);                         /* throw away Rx byte */
+       skb = scc->rx_buff;
+
+       if(status & Rx_OVR)                     /* receiver overrun */
+       {
+               scc->stat.rx_over++;             /* count them */
+               or(scc,R3,ENT_HM);               /* enter hunt mode for next flag */
+               
+               if (skb != NULL) 
+                       kfree_skb(skb, FREE_READ);
+               scc->rx_buff = NULL;
+       }
+
+       if(status & END_FR && skb != NULL)      /* end of frame */
+       {
+               /* CRC okay, frame ends on 8 bit boundary and received something ? */
+               
+               if (!(status & CRC_ERR) && (status & 0xe) == RES8 && skb->len > 0)
+               {
+                       /* ignore last received byte (first of the CRC bytes) */
+                       skb_trim(skb, skb->len-1);
+                       scc_net_rx(scc, skb);
+                       scc->rx_buff = NULL;
+                       scc->stat.rxframes++;
+               } else {                                /* a bad frame */
+                       kfree_skb(skb, FREE_READ);
+                       scc->rx_buff = NULL;
+                       scc->stat.rxerrs++;
+               }
+       } 
+
+       Outb(scc->ctrl,ERR_RES);
+}
+
+
+/* ----> interrupt service routine for the Z8530 <---- */
+
+static void
+scc_isr_dispatch(struct scc_channel *scc, int vector)
+{
+       switch (vector & VECTOR_MASK)
+       {
+               case TXINT: scc_txint(scc); break;
+               case EXINT: scc_exint(scc); break;
+               case RXINT: scc_rxint(scc); break;
+               case SPINT: scc_spint(scc); break;
+       }
+}
+
+/* If the card has a latch for the interrupt vector (like the PA0HZP card)
+   use it to get the number of the chip that generated the int.
+   If not: poll all defined chips.
+ */
+
+#define SCC_IRQTIMEOUT 30000
+
+static void
+scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned char vector;   
+       struct scc_channel *scc;
+       struct scc_ctrl *ctrl;
+       int k;
+       
+       scc_cli(irq);
+
+       if (Vector_Latch)
+       {
+               for(k=0; k < SCC_IRQTIMEOUT; k++)
+               {
+                       Outb(Vector_Latch, 0);      /* Generate INTACK */
+        
+                       /* Read the vector */
+                       if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break; 
+                       if (vector & 0x01) break;
+                
+                       scc=&SCC_Info[vector >> 3 ^ 0x01];
+                       if (!scc->dev) break;
+
+                       scc_isr_dispatch(scc, vector);
+
+                       OutReg(scc->ctrl,R0,RES_H_IUS);              /* Reset Highest IUS */
+               }  
+               scc_sti(irq);
+
+               if (k == SCC_IRQTIMEOUT)
+                       printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
+
+               return;
+       }
+
+       /* Find the SCC generating the interrupt by polling all attached SCCs
+        * reading RR3A (the interrupt pending register)
+        */
+
+       ctrl = SCC_ctrl;
+       while (ctrl->chan_A)
+       {
+               if (ctrl->irq != irq)
+               {
+                       ctrl++;
+                       continue;
+               }
+
+               scc = NULL;
+               for (k = 0; InReg(ctrl->chan_A,R3) && k < SCC_IRQTIMEOUT; k++)
+               {
+                       vector=InReg(ctrl->chan_B,R2);  /* Read the vector */
+                       if (vector & 0x01) break; 
+
+                       scc = &SCC_Info[vector >> 3 ^ 0x01];
+                       if (!scc->dev) break;
+
+                       scc_isr_dispatch(scc, vector);
+               }
+
+               if (k == SCC_IRQTIMEOUT)
+               {
+                       printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?!\n");
+                       break;
+               }
+
+               /* This looks wierd and it is. At least the BayCom USCC doesn't
+                * use the Interrupt Daisy Chain, thus we'll have to start
+                * all over again to be sure not to miss an interrupt from 
+                * (any of) the other chip(s)...
+                * Honestly, the situation *is* braindamaged...
+                */
+
+               if (scc != NULL)
+               {
+                       OutReg(scc->ctrl,R0,RES_H_IUS);
+                       ctrl = SCC_ctrl; 
+               } else
+                       ctrl++;
+       }
+       
+       scc_sti(irq);
+}
+
+
+
+/* ******************************************************************** */
+/* *                   Init Channel                                    */
+/* ******************************************************************** */
+
+
+/* ----> set SCC channel speed <---- */
+
+static __inline__ void 
+set_brg(struct scc_channel *scc, unsigned int tc)
+{
+       cl(scc,R14,BRENABL);            /* disable baudrate generator */
+       wr(scc,R12,tc & 255);           /* brg rate LOW */
+       wr(scc,R13,tc >> 8);            /* brg rate HIGH */
+       or(scc,R14,BRENABL);            /* enable baudrate generator */
+}
+
+static __inline__ void 
+set_speed(struct scc_channel *scc)
+{
+       disable_irq(scc->irq);
+
+       if (scc->modem.speed > 0)       /* paranoia... */
+               set_brg(scc, (unsigned) (scc->clock / (scc->modem.speed * 64)) - 2);
+
+       enable_irq(scc->irq);
+}
+
+
+/* ----> initialize a SCC channel <---- */
+
+static __inline__ void 
+init_brg(struct scc_channel *scc)
+{
+       wr(scc, R14, BRSRC);                            /* BRG source = PCLK */
+       OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]);    /* DPLL source = BRG */
+       OutReg(scc->ctrl, R14, SNRZI|scc->wreg[R14]);   /* DPLL NRZI mode */
+}
+
+/*
+ * Initialization according to the Z8530 manual (SGS-Thomson's version):
+ *
+ * 1. Modes and constants
+ *
+ * WR9 11000000        chip reset
+ * WR4 XXXXXXXX        Tx/Rx control, async or sync mode
+ * WR1 0XX00X00        select W/REQ (optional)
+ * WR2 XXXXXXXX        program interrupt vector
+ * WR3 XXXXXXX0        select Rx control
+ * WR5 XXXX0XXX        select Tx control
+ * WR6 XXXXXXXX        sync character
+ * WR7 XXXXXXXX        sync character
+ * WR9 000X0XXX        select interrupt control
+ * WR10        XXXXXXXX        miscellaneous control (optional)
+ * WR11        XXXXXXXX        clock control
+ * WR12        XXXXXXXX        time constant lower byte (optional)
+ * WR13        XXXXXXXX        time constant upper byte (optional)
+ * WR14        XXXXXXX0        miscellaneous control
+ * WR14        XXXSSSSS        commands (optional)
+ *
+ * 2. Enables
+ *
+ * WR14        000SSSS1        baud rate enable
+ * WR3 SSSSSSS1        Rx enable
+ * WR5 SSSS1SSS        Tx enable
+ * WR0 10000000        reset Tx CRG (optional)
+ * WR1 XSS00S00        DMA enable (optional)
+ *
+ * 3. Interrupt status
+ *
+ * WR15        XXXXXXXX        enable external/status
+ * WR0 00010000        reset external status
+ * WR0 00010000        reset external status twice
+ * WR1 SSSXXSXX        enable Rx, Tx and Ext/status
+ * WR9 000SXSSS        enable master interrupt enable
+ *
+ * 1 = set to one, 0 = reset to zero
+ * X = user defined, S = same as previous init
+ *
+ *
+ * Note that the implementation differs in some points from above scheme.
+ *
+ */
+static void
+init_channel(struct scc_channel *scc)
+{
+       disable_irq(scc->irq);
+       
+       if (scc->tx_t.next)    del_timer(&scc->tx_t);
+       if (scc->tx_wdog.next) del_timer(&scc->tx_wdog);
+
+       wr(scc,R4,X1CLK|SDLC);          /* *1 clock, SDLC mode */
+       wr(scc,R1,0);                   /* no W/REQ operation */
+       wr(scc,R3,Rx8|RxCRC_ENAB);      /* RX 8 bits/char, CRC, disabled */     
+       wr(scc,R5,Tx8|DTR|TxCRC_ENAB);  /* TX 8 bits/char, disabled, DTR */
+       wr(scc,R6,0);                   /* SDLC address zero (not used) */
+       wr(scc,R7,FLAG);                /* SDLC flag value */
+       wr(scc,R9,VIS);                 /* vector includes status */
+       wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
+       wr(scc,R14, 0);
+
+
+/* set clock sources:
+
+   CLK_DPLL: normal halfduplex operation
+   
+               RxClk: use DPLL
+               TxClk: use DPLL
+               TRxC mode DPLL output
+               
+   CLK_EXTERNAL: external clocking (G3RUH or DF9IC modem)
+   
+               BayCom:                 others:
+               
+               TxClk = pin RTxC        TxClk = pin TRxC
+               RxClk = pin TRxC        RxClk = pin RTxC
+            
+
+   CLK_DIVIDER:
+               RxClk = use DPLL
+               TxClk = pin RTxC
+               
+               BayCom:                 others:
+               pin TRxC = DPLL         pin TRxC = BRG
+               (RxClk * 1)             (RxClk * 32)
+*/  
+
+               
+       switch(scc->modem.clocksrc)
+       {
+               case CLK_DPLL:
+                       wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
+                       init_brg(scc);
+                       break;
+
+               case CLK_DIVIDER:
+                       wr(scc, R11, ((scc->brand & BAYCOM)? TRxCDP : TRxCBR) | RCDPLL|TCRTxCP|TRxCOI);
+                       init_brg(scc);
+                       break;
+
+               case CLK_EXTERNAL:
+                       wr(scc, R11, (scc->brand & BAYCOM)? RCTRxCP|TCRTxCP : RCRTxCP|TCTRxCP);
+                       OutReg(scc->ctrl, R14, DISDPLL);
+                       break;
+
+       }
+       
+       set_speed(scc);                 /* set baudrate */
+       
+       if(scc->enhanced)
+       {
+               or(scc,R15,SHDLCE|FIFOE);       /* enable FIFO, SDLC/HDLC Enhancements (From now R7 is R7') */
+               wr(scc,R7,AUTOEOM);
+       }
+
+       if((InReg(scc->ctrl,R0)) & DCD)         /* DCD is now ON */
+       {
+               if (scc->modem.clocksrc != CLK_EXTERNAL)
+                       or(scc,R14, SEARCH);
+                       
+               or(scc,R3,ENT_HM|RxENABLE);     /* enable the receiver, hunt mode */
+       }
+       
+       /* enable ABORT, DCD & SYNC/HUNT interrupts */
+
+       wr(scc,R15, BRKIE|TxUIE|DCDIE);
+       if (scc->kiss.softdcd)
+               or(scc,R15, SYNCIE);
+
+       Outb(scc->ctrl,RES_EXT_INT);    /* reset ext/status interrupts */
+       Outb(scc->ctrl,RES_EXT_INT);    /* must be done twice */
+
+       or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
+       
+       scc->status = InReg(scc->ctrl,R0);      /* read initial status */
+       
+       or(scc,R9,MIE);                 /* master interrupt enable */
+       
+       scc_init_timer(scc);
+                       
+       enable_irq(scc->irq);
+}
+
+
+
+
+/* ******************************************************************** */
+/* *                   SCC timer functions                           * */
+/* ******************************************************************** */
+
+
+/* ----> scc_key_trx sets the time constant for the baudrate 
+         generator and keys the transmitter                 <---- */
+
+static void
+scc_key_trx(struct scc_channel *scc, char tx)
+{
+       unsigned int time_const;
+               
+       if (scc->brand & PRIMUS)
+               Outb(scc->ctrl + 4, scc->option | (tx? 0x80 : 0));
+
+       if (scc->modem.speed < 300) 
+               scc->modem.speed = 1200;
+
+       time_const = (unsigned) (scc->clock / (scc->modem.speed * (tx? 2:64))) - 2;
+
+       disable_irq(scc->irq);
+
+       if (tx)
+       {
+               or(scc, R1, TxINT_ENAB);        /* t_maxkeyup may have reset these */
+               or(scc, R15, TxUIE);
+       }
+
+       if (scc->modem.clocksrc == CLK_DPLL)
+       {                               /* force simplex operation */
+               if (tx)
+               {
+                       cl(scc, R3, RxENABLE|ENT_HM);   /* switch off receiver */
+                       cl(scc, R15, DCDIE);            /* No DCD changes, please */
+                       set_brg(scc, time_const);       /* reprogram baudrate generator */
+
+                       /* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
+                       wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
+                       
+                       or(scc,R5,RTS|TxENAB);          /* set the RTS line and enable TX */
+               } else {
+                       cl(scc,R5,RTS|TxENAB);
+                       
+                       set_brg(scc, time_const);       /* reprogram baudrate generator */
+                       
+                       /* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
+                       wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
+                       
+                       or(scc,R3,RxENABLE|ENT_HM);
+                       or(scc,R15, DCDIE);
+               }
+       } else {
+               if (tx)
+               {
+                       if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+                       {
+                               cl(scc, R3, RxENABLE);
+                               cl(scc, R15, DCDIE);
+                       }
+                               
+                               
+                       or(scc,R5,RTS|TxENAB);          /* enable tx */
+               } else {
+                       cl(scc,R5,RTS|TxENAB);          /* disable tx */
+                       
+                       if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+                       {
+                               or(scc, R3, RxENABLE|ENT_HM);
+                               or(scc, R15, DCDIE);
+                       }
+               }
+       }
+
+       enable_irq(scc->irq);
+}
+
+
+/* ----> SCC timer interrupt handler and friends. <---- */
+
+static void 
+scc_start_tx_timer(struct scc_channel *scc, void (*handler)(unsigned long), unsigned long when)
+{
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+
+       if (scc->tx_t.next) 
+               del_timer(&scc->tx_t);
+
+       if (when == 0)
+       {
+               handler((unsigned long) scc);
+       } else 
+       if (when != TIMER_OFF)
+       {
+               scc->tx_t.data = (unsigned long) scc;
+               scc->tx_t.function = handler;
+               scc->tx_t.expires = jiffies + (when*HZ)/100;
+               add_timer(&scc->tx_t);
+       }
+       
+       restore_flags(flags);   
+}
+
+static void
+scc_start_defer(struct scc_channel *scc)
+{
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+
+       if (scc->tx_wdog.next)
+               del_timer(&scc->tx_wdog);
+       
+       if (scc->kiss.maxdefer != 0 && scc->kiss.maxdefer != TIMER_OFF)
+       {
+               scc->tx_wdog.data = (unsigned long) scc;
+               scc->tx_wdog.function = t_busy;
+               scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxdefer;
+               add_timer(&scc->tx_wdog);
+       }
+       restore_flags(flags);
+}
+
+static void
+scc_start_maxkeyup(struct scc_channel *scc)
+{
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+
+       if (scc->tx_wdog.next)
+               del_timer(&scc->tx_wdog);
+       
+       if (scc->kiss.maxkeyup != 0 && scc->kiss.maxkeyup != TIMER_OFF)
+       {
+               scc->tx_wdog.data = (unsigned long) scc;
+               scc->tx_wdog.function = t_maxkeyup;
+               scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
+               add_timer(&scc->tx_wdog);
+       }
+       
+       restore_flags(flags);
+}
+
+/* 
+ * This is called from scc_txint() when there are no more frames to send.
+ * Not exactly a timer function, but it is a close friend of the family...
+ */
+
+static void
+scc_tx_done(struct scc_channel *scc)
+{
+       /* 
+        * trx remains keyed in fulldup mode 2 until t_idle expires.
+        */
+                                
+       switch (scc->kiss.fulldup)
+       {
+               case KISS_DUPLEX_LINK:
+                       scc->stat.tx_state = TXS_IDLE2;
+                       if (scc->kiss.idletime != TIMER_OFF)
+                       scc_start_tx_timer(scc, t_idle, scc->kiss.idletime*100);
+                       break;
+               case KISS_DUPLEX_OPTIMA:
+                       scc_notify(scc, HWEV_ALL_SENT);
+                       break;
+               default:
+                       scc->stat.tx_state = TXS_BUSY;
+                       scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
+       }
+
+       scc_unlock_dev(scc);
+}
+
+
+static unsigned char Rand = 17;
+
+static __inline__ int 
+is_grouped(struct scc_channel *scc)
+{
+       int k;
+       struct scc_channel *scc2;
+       unsigned char grp1, grp2;
+
+       grp1 = scc->kiss.group;
+       
+       for (k = 0; k < (Nchips * 2); k++)
+       {
+               scc2 = &SCC_Info[k];
+               grp2 = scc2->kiss.group;
+               
+               if (scc2 == scc || !(scc2->dev && grp2))
+                       continue;
+               
+               if ((grp1 & 0x3f) == (grp2 & 0x3f))
+               {
+                       if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
+                               return 1;
+                       
+                       if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
+                               return 1;
+               }
+       }
+       return 0;
+}
+
+/* DWAIT and SLOTTIME expired
+ *
+ * fulldup == 0:  DCD is active or Rand > P-persistence: start t_busy timer
+ *                else key trx and start txdelay
+ * fulldup == 1:  key trx and start txdelay
+ * fulldup == 2:  mintime expired, reset status or key trx and start txdelay
+ */
+
+static void 
+t_dwait(unsigned long channel)
+{
+       struct scc_channel *scc = (struct scc_channel *) channel;
+       
+       if (scc->stat.tx_state == TXS_WAIT)     /* maxkeyup or idle timeout */
+       {
+               if (scc->tx_next_buff == NULL)  /* nothing to send */
+               {
+                       scc->stat.tx_state = TXS_IDLE;
+                       scc_unlock_dev(scc);    /* t_maxkeyup locked it. */
+                       return;
+               }
+
+               scc->stat.tx_state = TXS_BUSY;
+       }
+
+       if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+       {
+               Rand = Rand * 17 + 31;
+               
+               if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD))  || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
+               {
+                       scc_start_defer(scc);
+                       scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);
+                       return ;
+               }
+       }
+
+       if ( !(scc->wreg[R5] & RTS) )
+       {
+               scc_key_trx(scc, TX_ON);
+               scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
+       } else {
+               scc_start_tx_timer(scc, t_txdelay, 0);
+       }
+}
+
+
+/* TXDELAY expired
+ *
+ * kick transmission by a fake scc_txint(scc), start 'maxkeyup' watchdog.
+ */
+
+static void 
+t_txdelay(unsigned long channel)
+{
+       struct scc_channel *scc = (struct scc_channel *) channel;
+
+       scc_start_maxkeyup(scc);
+
+       if (scc->tx_buff == NULL)
+       {
+               disable_irq(scc->irq);
+               scc_txint(scc); 
+               enable_irq(scc->irq);
+       }
+}
+       
+
+/* TAILTIME expired
+ *
+ * switch off transmitter. If we were stopped by Maxkeyup restart
+ * transmission after 'mintime' seconds
+ */
+
+static void 
+t_tail(unsigned long channel)
+{
+       struct scc_channel *scc = (struct scc_channel *) channel;
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+       if (scc->tx_wdog.next)
+               del_timer(&scc->tx_wdog);
+               
+       scc_key_trx(scc, TX_OFF);
+
+       restore_flags(flags);
+
+       if (scc->stat.tx_state == TXS_TIMEOUT)          /* we had a timeout? */
+       {
+               scc->stat.tx_state = TXS_WAIT;
+
+               if (scc->kiss.mintime != TIMER_OFF)     /* try it again */
+                       scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
+               else
+                       scc_start_tx_timer(scc, t_dwait, 0);
+               return;
+       }
+       
+       scc->stat.tx_state = TXS_IDLE;
+       scc_unlock_dev(scc);
+}
+
+
+/* BUSY timeout
+ *
+ * throw away send buffers if DCD remains active too long.
+ */
+
+static void 
+t_busy(unsigned long channel)
+{
+       struct scc_channel *scc = (struct scc_channel *) channel;
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+       
+       if (scc->tx_t.next)
+               del_timer(&scc->tx_t);
+
+       restore_flags(flags);
+       
+       scc_lock_dev(scc);
+
+       scc_discard_buffers(scc);
+
+       scc->stat.txerrs++;
+       scc->stat.tx_state = TXS_IDLE;
+       
+       scc_unlock_dev(scc);
+}
+
+/* MAXKEYUP timeout
+ *
+ * this is our watchdog.
+ */
+
+static void 
+t_maxkeyup(unsigned long channel)
+{
+       struct scc_channel *scc = (struct scc_channel *) channel;
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+
+       /* 
+        * let things settle down before we start to
+        * accept new data.
+        */
+
+       scc_lock_dev(scc);
+       scc_discard_buffers(scc);
+
+       if (scc->tx_t.next)
+               del_timer(&scc->tx_t);
+
+       cl(scc, R1, TxINT_ENAB);        /* force an ABORT, but don't */
+       cl(scc, R15, TxUIE);            /* count it. */
+       OutReg(scc->ctrl, R0, RES_Tx_P);
+
+       restore_flags(flags);
+
+       scc->stat.txerrs++;
+       scc->stat.tx_state = TXS_TIMEOUT;
+       scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
+}
+
+/* IDLE timeout
+ *
+ * in fulldup mode 2 it keys down the transmitter after 'idle' seconds
+ * of inactivity. We will not restart transmission before 'mintime'
+ * expires.
+ */
+
+static void 
+t_idle(unsigned long channel)
+{
+       struct scc_channel *scc = (struct scc_channel *) channel;
+       unsigned long flags;
+       
+       save_flags(flags);
+       cli();
+       
+       if (scc->tx_wdog.next)
+               del_timer(&scc->tx_wdog);
+
+       restore_flags(flags);
+       
+       scc_key_trx(scc, TX_OFF);
+
+       if (scc->kiss.mintime != TIMER_OFF)
+               scc_start_tx_timer(scc, t_dwait, scc->kiss.mintime*100);
+       scc->stat.tx_state = TXS_WAIT;
+}
+
+static void
+scc_init_timer(struct scc_channel *scc)
+{
+       unsigned long flags;
+       
+       save_flags(flags); 
+       cli();
+       
+       scc->stat.tx_state = TXS_IDLE;
+
+       restore_flags(flags);
+}
+
+
+/* ******************************************************************** */
+/* *                   Set/get L1 parameters                         * */
+/* ******************************************************************** */
+
+
+/*
+ * this will set the "hardware" parameters through KISS commands or ioctl()
+ */
+
+#define CAST(x) (unsigned long)(x)
+
+static unsigned int
+scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)
+{
+       int dcd;
+
+       switch (cmd)
+       {
+               case PARAM_TXDELAY:     scc->kiss.txdelay=arg;          break;
+               case PARAM_PERSIST:     scc->kiss.persist=arg;          break;
+               case PARAM_SLOTTIME:    scc->kiss.slottime=arg;         break;
+               case PARAM_TXTAIL:      scc->kiss.tailtime=arg;         break;
+               case PARAM_FULLDUP:     scc->kiss.fulldup=arg;          break;
+               case PARAM_DTR:         break; /* does someone need this? */
+               case PARAM_GROUP:       scc->kiss.group=arg;            break;
+               case PARAM_IDLE:        scc->kiss.idletime=arg;         break;
+               case PARAM_MIN:         scc->kiss.mintime=arg;          break;
+               case PARAM_MAXKEY:      scc->kiss.maxkeyup=arg;         break;
+               case PARAM_WAIT:        scc->kiss.waittime=arg;         break;
+               case PARAM_MAXDEFER:    scc->kiss.maxdefer=arg;         break;
+               case PARAM_TX:          scc->kiss.tx_inhibit=arg;       break;
+
+               case PARAM_SOFTDCD:     
+                       scc->kiss.softdcd=arg;
+                       if (arg)
+                               or(scc, R15, SYNCIE);
+                       else
+                               cl(scc, R15, SYNCIE);
+                       break;
+                               
+               case PARAM_SPEED:
+                       if (arg < 256)
+                               scc->modem.speed=arg*100;
+                       else
+                               scc->modem.speed=arg;
+
+                       if (scc->stat.tx_state == 0)    /* only switch baudrate on rx... ;-) */
+                               set_speed(scc);
+                       break;
+                       
+               case PARAM_RTS: 
+                       if ( !(scc->wreg[R5] & RTS) )
+                       {
+                               if (arg != TX_OFF)
+                                       scc_key_trx(scc, TX_ON);
+                                       scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay);
+                       } else {
+                               if (arg == TX_OFF)
+                               {
+                                       scc->stat.tx_state = TXS_BUSY;
+                                       scc_start_tx_timer(scc, t_tail, scc->kiss.tailtime);
+                               }
+                       }
+                       break;
+                       
+               case PARAM_HWEVENT:
+                       dcd = (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD));
+                       scc_notify(scc, dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
+                       break;
+
+               default:                return -EINVAL;
+       }
+       
+       return 0;
+}
+
+
+static unsigned long
+scc_get_param(struct scc_channel *scc, unsigned int cmd)
+{
+       switch (cmd)
+       {
+               case PARAM_TXDELAY:     return CAST(scc->kiss.txdelay);
+               case PARAM_PERSIST:     return CAST(scc->kiss.persist);
+               case PARAM_SLOTTIME:    return CAST(scc->kiss.slottime);
+               case PARAM_TXTAIL:      return CAST(scc->kiss.tailtime);
+               case PARAM_FULLDUP:     return CAST(scc->kiss.fulldup);
+               case PARAM_SOFTDCD:     return CAST(scc->kiss.softdcd);
+               case PARAM_DTR:         return CAST((scc->wreg[R5] & DTR)? 1:0);
+               case PARAM_RTS:         return CAST((scc->wreg[R5] & RTS)? 1:0);
+               case PARAM_SPEED:       return CAST(scc->modem.speed);
+               case PARAM_GROUP:       return CAST(scc->kiss.group);
+               case PARAM_IDLE:        return CAST(scc->kiss.idletime);
+               case PARAM_MIN:         return CAST(scc->kiss.mintime);
+               case PARAM_MAXKEY:      return CAST(scc->kiss.maxkeyup);
+               case PARAM_WAIT:        return CAST(scc->kiss.waittime);
+               case PARAM_MAXDEFER:    return CAST(scc->kiss.maxdefer);
+               case PARAM_TX:          return CAST(scc->kiss.tx_inhibit);
+               default:                return NO_SUCH_PARAM;
+       }
+
+}
+
+#undef CAST
+#undef SVAL
+
+/* ******************************************************************* */
+/* *           Init channel structures, special HW, etc...          * */
+/* ******************************************************************* */
+
+/*
+ * Reset the Z8530s and setup special hardware
+ */
+
+static void
+z8530_init(void)
+{
+       struct scc_channel *scc;
+       int chip, k;
+       unsigned long flags;
+       char *flag;
+
+
+       printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
+       
+       flag=" ";
+       for (k = 0; k < 16; k++)
+               if (Ivec[k].used) 
+               {
+                       printk("%s%d", flag, k);
+                       flag=",";
+               }
+       printk("\n");
+
+
+       /* reset and pre-init all chips in the system */
+       for (chip = 0; chip < Nchips; chip++)
+       {
+               scc=&SCC_Info[2*chip];
+               if (!scc->ctrl) continue;
+
+               /* Special SCC cards */
+
+               if(scc->brand & EAGLE)                  /* this is an EAGLE card */
+                       Outb(scc->special,0x08);        /* enable interrupt on the board */
+                       
+               if(scc->brand & (PC100 | PRIMUS))       /* this is a PC100/PRIMUS card */
+                       Outb(scc->special,scc->option); /* set the MODEM mode (0x22) */
+
+                       
+               /* Reset and pre-init Z8530 */
+
+               save_flags(flags);
+               cli();
+               
+               Outb(scc->ctrl, 0);
+               OutReg(scc->ctrl,R9,FHWRES);            /* force hardware reset */
+               udelay(100);                            /* give it 'a bit' more time than required */
+               wr(scc, R2, chip*16);                   /* interrupt vector */
+               wr(scc, R9, VIS);                       /* vector includes status */
+               
+               restore_flags(flags);
+        }
+
+       Driver_Initialized = 1;
+}
+
+/*
+ * Allocate device structure, err, instance, and register driver
+ */
+
+static int 
+scc_net_setup(struct scc_channel *scc, unsigned char *name)
+{
+       unsigned char *buf;
+       struct device *dev;
+
+       if (dev_get(name) != NULL)
+       {
+               printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);
+               return -EEXIST;
+       }
+
+       if ((scc->dev = (struct device *) kmalloc(sizeof(struct device), GFP_KERNEL)) == NULL)
+               return -ENOMEM;
+
+       dev = scc->dev;
+       memset(dev, 0, sizeof(struct device));
+
+       buf = (unsigned char *) kmalloc(10, GFP_KERNEL);
+       strcpy(buf, name);
+
+       dev->priv = (void *) scc;
+       dev->name = buf;
+       dev->init = scc_net_init;
+
+       if (register_netdev(dev) != 0)
+       {
+               kfree(dev);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+
+
+/* ******************************************************************** */
+/* *                       Network driver methods                    * */
+/* ******************************************************************** */
+
+static unsigned char ax25_bcast[AX25_ADDR_LEN] =
+{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
+static unsigned char ax25_nocall[AX25_ADDR_LEN] =
+{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
+
+/* ----> Initialize device <----- */
+
+static int 
+scc_net_init(struct device *dev)
+{
+       int k;
+
+       for (k=0; k < DEV_NUMBUFFS; k++)
+               skb_queue_head_init(&dev->buffs[k]);
+       dev->tx_queue_len    = 16;      /* should be enough... */
+
+       dev->open            = scc_net_open;
+       dev->stop            = scc_net_close;
+
+       dev->hard_start_xmit = scc_net_tx;
+       dev->hard_header     = scc_net_header;
+       dev->rebuild_header  = scc_net_rebuild_header;
+       dev->set_mac_address = scc_net_set_mac_address;
+       dev->get_stats       = scc_net_get_stats;
+       dev->do_ioctl        = scc_net_ioctl;
+
+       memcpy(dev->broadcast, ax25_bcast,  AX25_ADDR_LEN);
+       memcpy(dev->dev_addr,  ax25_nocall, AX25_ADDR_LEN);
+       dev->flags      = 0;
+       dev->family     = AF_INET;
+       dev->pa_addr    = 0;
+       dev->pa_brdaddr = 0;
+       dev->pa_mask    = 0;
+       dev->pa_alen    = 4;
+
+       dev->type = ARPHRD_AX25;
+       dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
+       dev->mtu = AX25_DEF_PACLEN;
+       dev->addr_len = AX25_ADDR_LEN;
+
+       return 0;
+}
+
+/* ----> open network device <---- */
+
+static int 
+scc_net_open(struct device *dev)
+{
+       struct scc_channel *scc = (struct scc_channel *) dev->priv;
+
+       if (scc == NULL || scc->magic != SCC_MAGIC)
+               return -ENODEV;
+
+       if (!scc->init)
+               return -EINVAL;
+
+       MOD_INC_USE_COUNT;
+       
+       scc->tx_buff = scc->tx_next_buff = NULL;
+       init_channel(scc);
+
+       dev->tbusy = 0;
+       dev->start = 1;
+
+       return 0;
+}
+
+/* ----> close network device <---- */
+
+static int 
+scc_net_close(struct device *dev)
+{
+       struct scc_channel *scc = (struct scc_channel *) dev->priv;
+       unsigned long flags;
+
+       if (scc == NULL || scc->magic != SCC_MAGIC)
+               return -ENODEV;
+
+       MOD_DEC_USE_COUNT;
+
+       save_flags(flags); 
+       cli();
+       
+       Outb(scc->ctrl,0);              /* Make sure pointer is written */
+       wr(scc,R1,0);                   /* disable interrupts */
+       wr(scc,R3,0);
+
+       del_timer(&scc->tx_t);
+       del_timer(&scc->tx_wdog);
+
+       restore_flags(flags);
+       
+       scc_discard_buffers(scc);
+
+       dev->tbusy = 1;
+       dev->start = 0;
+
+       return 0;
+}
+
+/* ----> receive frame, called from scc_rxint() <---- */
+
+static void 
+scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
+{
+       if (skb->len == 0)
+       {
+               kfree_skb(skb, FREE_READ);
+               return;
+       }
+               
+       scc->dev_stat.rx_packets++;
+
+       skb->dev      = scc->dev;
+       skb->protocol = htons(ETH_P_AX25);
+       skb->mac.raw  = skb->data;
+       
+       netif_rx(skb);
+       return;
+}
+
+/* ----> transmit frame <---- */
+
+static int 
+scc_net_tx(struct sk_buff *skb, struct device *dev)
+{
+       struct scc_channel *scc = (struct scc_channel *) dev->priv;
+       unsigned long flags;
+       char kisscmd;
+       long ticks;
+       
+       if (dev->tbusy)
+       {
+               ticks = (signed) (jiffies - dev->trans_start);
+
+               if (ticks < scc->kiss.maxdefer*HZ || scc == NULL)
+                       return 1;
+
+               /* 
+                * Throw away transmission queue. 
+                */
+
+               if (scc->tx_wdog.next)
+                       del_timer(&scc->tx_wdog);
+               t_busy((unsigned long) scc);
+                dev->trans_start = jiffies;
+        }
+        
+       if (skb == NULL)
+       {
+               dev_tint(dev);
+               return 0;
+       }
+       
+       if (scc == NULL || scc->magic != SCC_MAGIC)
+       {
+               dev_kfree_skb(skb, FREE_WRITE);
+               return 0;
+       }
+
+       if (skb->len > scc->stat.bufsize || skb->len < 2)
+       {
+               scc->dev_stat.tx_dropped++;     /* bogus frame */
+               dev_kfree_skb(skb, FREE_WRITE);
+               return 0;
+       }
+       
+       scc->dev_stat.tx_packets++;
+       scc->stat.txframes++;
+       
+       kisscmd = *skb->data & 0x1f;
+       skb_pull(skb, 1);
+
+       if (kisscmd)
+       {
+               scc_set_param(scc, kisscmd, *skb->data);
+               dev_kfree_skb(skb, FREE_WRITE);
+               return 0;
+       }
+
+       save_flags(flags);
+       cli();
+       
+       scc_lock_dev(scc);
+       
+       if (scc->tx_next_buff != NULL)
+       {
+               printk(KERN_ERR "z8530drv: race condition, discarding frame\n");
+               dev_kfree_skb(skb, FREE_WRITE);
+               scc_lock_dev(scc);
+               restore_flags(flags);
+               return 0;
+       }
+       
+       dev->trans_start = jiffies;
+       scc->tx_next_buff = skb;
+
+       /*
+        * Start transmission if the trx state is idle or
+        * t_idle hasn't expired yet. Use dwait/persistance/slottime
+        * algorithm for normal halfduplex operation.
+        */
+
+       if(scc->stat.tx_state == TXS_IDLE || scc->stat.tx_state == TXS_IDLE2)
+       {
+               scc->stat.tx_state = TXS_BUSY;
+               if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+                       scc_start_tx_timer(scc, t_dwait, scc->kiss.waittime);
+               else
+                       scc_start_tx_timer(scc, t_dwait, 0);
+       }
+
+       restore_flags(flags);
+
+       return 0;
+}
+
+/* ----> ioctl functions <---- */
+
+/*
+ * SIOCSCCCFG          - configure driver      arg: (struct scc_hw_config *) arg
+ * SIOCSCCINI          - initialize driver     arg: ---
+ * SIOCSCCCHANINI      - initialize channel    arg: (struct scc_modem *) arg
+ * SIOCSCCSMEM         - set memory            arg: (struct scc_mem_config *) arg
+ * SIOCSCCGKISS                - get level 1 parameter arg: (struct scc_kiss_cmd *) arg
+ * SIOCSCCSKISS                - set level 1 parameter arg: (struct scc_kiss_cmd *) arg
+ * SIOCSCCGSTAT                - get driver status     arg: (struct scc_stat *) arg
+ */
+
+static int
+scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+       struct scc_kiss_cmd kiss_cmd;
+       struct scc_mem_config memcfg;
+       struct scc_hw_config hwcfg;
+       unsigned char device_name[10];
+       struct scc_channel *scc;
+       int chan;
+       void *arg;
+       
+       scc = (struct scc_channel *) dev->priv;
+       if (scc == NULL || scc->magic != SCC_MAGIC)
+               return -EINVAL;
+               
+       arg = (void *) ifr->ifr_data;
+       
+       if (!Driver_Initialized)
+       {
+               if (cmd == SIOCSCCCFG)
+               {
+                       int found = 1;
+
+                       if (!suser()) return -EPERM;
+                       if (!arg) return -EFAULT;
+
+                       if (Nchips >= MAXSCC) 
+                               return -EINVAL;
+
+                       if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))
+                               return -EFAULT;
+
+                       if (hwcfg.irq == 2) hwcfg.irq = 9;
+
+                       if (!Ivec[hwcfg.irq].used && hwcfg.irq)
+                       {
+                               if (request_irq(hwcfg.irq, scc_isr, SA_INTERRUPT, "AX.25 SCC", NULL))
+                                       printk(KERN_WARNING "z8530drv: warning, cannot get IRQ %d\n", hwcfg.irq);
+                               else
+                                       Ivec[hwcfg.irq].used = 1;
+                       }
+
+                       if (hwcfg.vector_latch) 
+                               Vector_Latch = hwcfg.vector_latch;
+
+                       if (hwcfg.clock == 0)
+                               hwcfg.clock = DEFAULT_CLOCK;
+
+#ifndef DONT_CHECK
+                       disable_irq(hwcfg.irq);
+
+                       check_region(scc->ctrl, 1);
+                       Outb(hwcfg.ctrl_a, 0);
+                       udelay(5);
+                       OutReg(hwcfg.ctrl_a,R13,0x55);          /* is this chip really there? */
+                       udelay(5);
+
+                       if (InReg(hwcfg.ctrl_a,R13) != 0x55)
+                               found = 0;
+
+                       enable_irq(hwcfg.irq);
+#endif
+
+                       if (found)
+                       {
+                               SCC_Info[2*Nchips  ].ctrl = hwcfg.ctrl_a;
+                               SCC_Info[2*Nchips  ].data = hwcfg.data_a;
+                               SCC_Info[2*Nchips  ].irq  = hwcfg.irq;
+                               SCC_Info[2*Nchips+1].ctrl = hwcfg.ctrl_b;
+                               SCC_Info[2*Nchips+1].data = hwcfg.data_b;
+                               SCC_Info[2*Nchips+1].irq  = hwcfg.irq;
+                       
+                               SCC_ctrl[Nchips].chan_A = hwcfg.ctrl_a;
+                               SCC_ctrl[Nchips].chan_B = hwcfg.ctrl_b;
+                               SCC_ctrl[Nchips].irq    = hwcfg.irq;
+                       }
+
+
+                       for (chan = 0; chan < 2; chan++)
+                       {
+                               sprintf(device_name, "%s%i", SCC_DriverName, 2*Nchips+chan);
+
+                               SCC_Info[2*Nchips+chan].special = hwcfg.special;
+                               SCC_Info[2*Nchips+chan].clock = hwcfg.clock;
+                               SCC_Info[2*Nchips+chan].brand = hwcfg.brand;
+                               SCC_Info[2*Nchips+chan].option = hwcfg.option;
+                               SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
+
+#ifdef DONT_CHECK
+                               printk(KERN_INFO "%s: data port = 0x%3.3x  control port = 0x%3.3x\n",
+                                       device_name, 
+                                       SCC_Info[2*Nchips+chan].data, 
+                                       SCC_Info[2*Nchips+chan].ctrl);
+
+#else
+                               printk(KERN_INFO "%s: data port = 0x%3.3lx  control port = 0x%3.3lx -- %s\n",
+                                       device_name,
+                                       chan? hwcfg.data_b : hwcfg.data_a, 
+                                       chan? hwcfg.ctrl_b : hwcfg.ctrl_a,
+                                       found? "found" : "missing");
+#endif
+
+                               if (found)
+                               {
+                                       request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
+                                       request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
+                                       if (Nchips+chan != 0)
+                                               scc_net_setup(&SCC_Info[2*Nchips+chan], device_name);
+                               }
+                       }
+                       
+                       if (found) Nchips++;
+                       
+                       return 0;
+               }
+               
+               if (cmd == SIOCSCCINI)
+               {
+                       if (!suser())
+                               return -EPERM;
+                               
+                       if (Nchips == 0)
+                               return -EINVAL;
+
+                       z8530_init();
+                       return 0;
+               }
+               
+               return -EINVAL; /* confuse the user */
+       }
+       
+       if (!scc->init)
+       {
+               if (cmd == SIOCSCCCHANINI)
+               {
+                       if (!suser()) return -EPERM;
+                       if (!arg) return -EINVAL;
+                       
+                       scc->stat.bufsize   = BUFSIZE;
+
+                       if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))
+                               return -EINVAL;
+                       
+                       /* default KISS Params */
+               
+                       if (scc->modem.speed < 4800)
+                       {
+                               scc->kiss.txdelay = 36;         /* 360 ms */
+                               scc->kiss.persist = 42;         /* 25% persistence */                   /* was 25 */
+                               scc->kiss.slottime = 16;        /* 160 ms */
+                               scc->kiss.tailtime = 4;         /* minimal reasonable value */
+                               scc->kiss.fulldup = 0;          /* CSMA */
+                               scc->kiss.waittime = 50;        /* 500 ms */
+                               scc->kiss.maxkeyup = 10;        /* 10 s */
+                               scc->kiss.mintime = 3;          /* 3 s */
+                               scc->kiss.idletime = 30;        /* 30 s */
+                               scc->kiss.maxdefer = 120;       /* 2 min */
+                               scc->kiss.softdcd = 0;          /* hardware dcd */
+                       } else {
+                               scc->kiss.txdelay = 10;         /* 100 ms */
+                               scc->kiss.persist = 64;         /* 25% persistence */                   /* was 25 */
+                               scc->kiss.slottime = 8;         /* 160 ms */
+                               scc->kiss.tailtime = 1;         /* minimal reasonable value */
+                               scc->kiss.fulldup = 0;          /* CSMA */
+                               scc->kiss.waittime = 50;        /* 500 ms */
+                               scc->kiss.maxkeyup = 7;         /* 7 s */
+                               scc->kiss.mintime = 3;          /* 3 s */
+                               scc->kiss.idletime = 30;        /* 30 s */
+                               scc->kiss.maxdefer = 120;       /* 2 min */
+                               scc->kiss.softdcd = 0;          /* hardware dcd */
+                       }
+                       
+                       scc->tx_buff = scc->tx_next_buff = NULL;
+                       scc->init = 1;
+                       
+                       return 0;
+               }
+               
+               return -EINVAL;
+       }
+       
+       switch(cmd)
+       {
+               case SIOCSCCRESERVED:
+                       return -ENOIOCTLCMD;
+
+               case SIOCSCCSMEM:
+                       if (!suser()) return -EPERM;
+                       if (!arg || copy_from_user(&memcfg, arg, sizeof(memcfg)))
+                               return -EINVAL;
+                       scc->stat.bufsize   = memcfg.bufsize;
+                       return 0;
+               
+               case SIOCSCCGSTAT:
+                       if (!arg || copy_to_user(arg, &scc->stat, sizeof(scc->stat)))
+                               return -EINVAL;
+                       return 0;
+               
+               case SIOCSCCGKISS:
+                       if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
+                               return -EINVAL;
+                       kiss_cmd.param = scc_get_param(scc, kiss_cmd.command);
+                       if (copy_to_user(arg, &kiss_cmd, sizeof(kiss_cmd)))
+                               return -EINVAL;
+                       return 0;
+               
+               case SIOCSCCSKISS:
+                       if (!suser()) return -EPERM;
+                       if (!arg || copy_from_user(&kiss_cmd, arg, sizeof(kiss_cmd)))
+                               return -EINVAL;
+                       return scc_set_param(scc, kiss_cmd.command, kiss_cmd.param);
+
+               default:
+                       return -ENOIOCTLCMD;
+               
+       }
+       
+       return -EINVAL;
+}
+
+/* ----> set interface callsign <---- */
+
+static int 
+scc_net_set_mac_address(struct device *dev, void *addr)
+{
+       struct sockaddr *sa = (struct sockaddr *) addr;
+       memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+       return 0;
+}
+
+/* ----> rebuild header <---- */
+
+static int 
+scc_net_rebuild_header(void *buff, struct device *dev, unsigned long raddr, struct sk_buff *skb)
+{
+    return ax25_rebuild_header(buff, dev, raddr, skb);
+}
+
+/* ----> "hard" header <---- */
+
+static int 
+scc_net_header(struct sk_buff *skb, struct device *dev, unsigned short type, 
+              void *daddr, void *saddr, unsigned len)
+{
+    return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+}
+
+/* ----> get statistics <---- */
+
+static struct enet_statistics *
+scc_net_get_stats(struct device *dev)
+{
+       struct scc_channel *scc = (struct scc_channel *) dev->priv;
+       
+       if (scc == NULL || scc->magic != SCC_MAGIC)
+               return NULL;
+               
+       scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;
+       scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;
+       scc->dev_stat.rx_fifo_errors = scc->stat.rx_over;
+       scc->dev_stat.tx_fifo_errors = scc->stat.tx_under;
+
+       return &scc->dev_stat;
+}
+
+/* ******************************************************************** */
+/* *           dump statistics to /proc/net/z8530drv                 * */
+/* ******************************************************************** */
+
+
+static int 
+scc_net_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+       struct scc_channel *scc;
+       struct scc_kiss *kiss;
+       struct scc_stat *stat;
+       int len = 0;
+       off_t pos = 0;
+       off_t begin = 0;
+       int k;
+
+       len += sprintf(buffer, "z8530drv-"VERSION"\n");
+
+       if (!Driver_Initialized)
+       {
+               len += sprintf(buffer+len, "not initialized\n");
+               goto done;
+       }
+
+       if (!Nchips)
+       {
+               len += sprintf(buffer+len, "chips missing\n");
+               goto done;
+       }
+
+       for (k = 0; k < Nchips*2; k++)
+       {
+               scc = &SCC_Info[k];
+               stat = &scc->stat;
+               kiss = &scc->kiss;
+
+               if (!scc->init)
+                       continue;
+
+               /* dev  data ctrl irq clock brand enh vector special option 
+                *      baud nrz clocksrc softdcd bufsize
+                *      rxints txints exints spints
+                *      rcvd rxerrs over / xmit txerrs under / nospace bufsize
+                *      txd pers slot tail ful wait min maxk idl defr txof grp
+                *      W ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
+                *      R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
+                */
+
+               len += sprintf(buffer+len, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx %3.3lx %d\n",
+                               scc->dev->name,
+                               scc->data, scc->ctrl, scc->irq, scc->clock, scc->brand,
+                               scc->enhanced, Vector_Latch, scc->special,
+                               scc->option);
+               len += sprintf(buffer+len, "\t%lu %d %d %d %d\n",
+                               scc->modem.speed, scc->modem.nrz,
+                               scc->modem.clocksrc, kiss->softdcd,
+                               stat->bufsize);
+               len += sprintf(buffer+len, "\t%lu %lu %lu %lu\n",
+                               stat->rxints, stat->txints, stat->exints, stat->spints);
+               len += sprintf(buffer+len, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
+                               stat->rxframes, stat->rxerrs, stat->rx_over,
+                               stat->txframes, stat->txerrs, stat->tx_under,
+                               stat->nospace,  stat->tx_state);
+
+#define K(x) kiss->x
+               len += sprintf(buffer+len, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
+                               K(txdelay), K(persist), K(slottime), K(tailtime),
+                               K(fulldup), K(waittime), K(mintime), K(maxkeyup),
+                               K(idletime), K(maxdefer), K(tx_inhibit), K(group));
+#undef K
+#ifdef SCC_DEBUG
+               {
+                       int reg;
+
+               len += sprintf(buffer+len, "\tW ");
+                       for (reg = 0; reg < 16; reg++)
+                               len += sprintf(buffer+len, "%2.2x ", scc->wreg[reg]);
+                       len += sprintf(buffer+len, "\n");
+                       
+               len += sprintf(buffer+len, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
+                       for (reg = 3; reg < 8; reg++)
+                               len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
+                       len += sprintf(buffer+len, "XX ");
+                       for (reg = 9; reg < 16; reg++)
+                               len += sprintf(buffer+len, "%2.2x ", InReg(scc->ctrl, reg));
+                       len += sprintf(buffer+len, "\n");
+               }
+#endif
+               len += sprintf(buffer+len, "\n");
+
+                pos = begin + len;
+
+                if (pos < offset) {
+                        len   = 0;
+                        begin = pos;
+                }
+
+                if (pos > offset + length)
+                        break;
+       }
+
+done:
+
+        *start = buffer + (offset - begin);
+        len   -= (offset - begin);
+
+        if (len > length) len = length;
+
+        return len;
+}
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry scc_proc_dir_entry = 
+{ 
+  PROC_NET_Z8530, 8, "z8530drv", S_IFREG | S_IRUGO, 1, 0, 0, 0, 
+  &proc_net_inode_operations, scc_net_get_info 
+};
+
+#define scc_net_procfs_init()   proc_net_register(&scc_proc_dir_entry);
+#define scc_net_procfs_remove() proc_net_unregister(PROC_NET_Z8530);
+#else
+#define scc_net_procfs_init()
+#define scc_net_procfs_remove()
+#endif
+
+  
+/* ******************************************************************** */
+/* *                   Init SCC driver                               * */
+/* ******************************************************************** */
+
+int scc_init (void)
+{
+       int chip, chan, k, result;
+       char devname[10];
+       
+       printk(KERN_INFO BANNER);
+       
+       memset(&SCC_ctrl, 0, sizeof(SCC_ctrl));
+       
+       /* pre-init channel information */
+       
+       for (chip = 0; chip < MAXSCC; chip++)
+       {
+               memset((char *) &SCC_Info[2*chip  ], 0, sizeof(struct scc_channel));
+               memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
+               
+               for (chan = 0; chan < 2; chan++)
+                       SCC_Info[2*chip+chan].magic = SCC_MAGIC;
+       }
+
+       for (k = 0; k < 16; k++) Ivec[k].used = 0;
+
+       sprintf(devname,"%s0", SCC_DriverName);
+       
+       result = scc_net_setup(SCC_Info, devname);
+       if (result)
+       {
+               printk(KERN_ERR "z8530drv: cannot initialize module\n");
+               return result;
+       }
+
+       scc_net_procfs_init();
+
+       return 0;
+}
+
+/* ******************************************************************** */
+/* *                       Module support                            * */
+/* ******************************************************************** */
+
+
+#ifdef MODULE
+int init_module(void)
+{
+       int result = 0;
+       
+       result = scc_init();
+
+       if (result == 0)
+               printk(KERN_INFO "Copyright 1993,1996 Joerg Reuter DL1BKE (jreuter@lykos.tng.oche.de)\n");
+               
+       return result;
+}
+
+void cleanup_module(void)
+{
+       long flags;
+       io_port ctrl;
+       int k;
+       struct scc_channel *scc;
+       
+       save_flags(flags); 
+       cli();
+
+       if (Nchips == 0)
+               unregister_netdev(SCC_Info[0].dev);
+
+       for (k = 0; k < Nchips; k++)
+               if ( (ctrl = SCC_ctrl[k].chan_A) )
+               {
+                       Outb(ctrl, 0);
+                       OutReg(ctrl,R9,FHWRES); /* force hardware reset */
+                       udelay(50);
+               }
+               
+       for (k = 0; k < Nchips*2; k++)
+       {
+               scc = &SCC_Info[k];
+               if (scc)
+               {
+                       release_region(scc->ctrl, 1);
+                       release_region(scc->data, 1);
+                       if (scc->dev)
+                       {
+                               unregister_netdev(scc->dev);
+                               kfree(scc->dev);
+                       }
+               }
+       }
+       
+       for (k=0; k < 16 ; k++)
+               if (Ivec[k].used) free_irq(k, NULL);
+               
+       restore_flags(flags);
+
+       scc_net_procfs_remove();
+}
+#endif
index 1026e888a5de538f1cb8e47cbebc4516f275283b..3071c2323a4da98e88eb0525ace242cd4c811589 100644 (file)
@@ -75,7 +75,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/mm.h>
 #include <net/checksum.h>
 #include <net/slhc_vj.h>
index 02c1d0d9d71d4f258d690e9aa4ebdf206f15796b..0194afea88c483b935dd4228fcd5a49ee78ac5cc 100644 (file)
@@ -57,7 +57,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <linux/string.h>
 #include <linux/mm.h>
index 1d4cc12aea216a367774c99ae122f7af95eeebc8..a09e0b9ae2e13ae563b3284a2724fbce323849f2 100644 (file)
@@ -75,7 +75,7 @@
 
 #include <stdlib.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 /*
index bfa7339af376d088495fa2e69f168f1b7ef0ad93..3d4a918d7d7bf7567a5a7b4a35bb006fe3ca680c 100644 (file)
 /* Read Register 13 (upper byte of baud rate generator constant) */
 
 /* Read Register 15 (value of WR 15) */
+
+/* 8580/85180/85280 Enhanced SCC register definitions */
+
+/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */
+#define AUTOTXF        0x01            /* Auto Tx Flag */
+#define AUTOEOM 0x02           /* Auto EOM Latch Reset */
+#define AUTORTS        0x04            /* Auto RTS */
+#define TXDNRZI 0x08           /* TxD Pulled High in SDLC NRZI mode */
+#define FASTDTR 0x10           /* Fast DTR/REQ Mode */
+#define CRCCBCR        0x20            /* CRC Check Bytes Completely Received */
+#define EXTRDEN        0x40            /* Extended Read Enabled */
+
+/* Write Register 15 (external/status interrupt control) */
+#define SHDLCE 1               /* SDLC/HDLC Enhancements Enable */
+#define FIFOE  4               /* FIFO Enable */
+
+/* Read Register 6 (frame status FIFO) */
+#define BCLSB  0xff            /* LSB of 14 bits count */
+
+/* Read Register 7 (frame status FIFO) */
+#define BCMSB  0x3f            /* MSB of 14 bits count */
+#define FDA    0x40            /* FIFO Data Available Status */
+#define FOY    0x80            /* FIFO Overflow Status */
index 6b48f603140295c46d7610cab2b6bdf69a4ff707..5e057cb993a9398ad0e5733c54b14c1d69643f39 100644 (file)
@@ -25,7 +25,7 @@
 
 
 #define BusLogic_DriverVersion         "2.0.6"
-#define BusLogic_DriverDate            "17 July 1996"
+#define BusLogic_DriverDate            "19 October 1996"
 
 
 #include <linux/module.h>
index bc855fccc1a37bb5677080ccd9d2cc7e9827aa23..be29070c5e60b93f6656d5ad4814b22282be346a 100644 (file)
@@ -1066,11 +1066,10 @@ void BusLogic_StartMailboxCommand(BusLogic_HostAdapter_T *HostAdapter)
 
 static inline void BusLogic_Delay(int Seconds)
 {
-  unsigned long TimeoutJiffies = jiffies + Seconds * HZ;
   unsigned long ProcessorFlags;
   save_flags(ProcessorFlags);
   sti();
-  while (jiffies < TimeoutJiffies) barrier();
+  while (--Seconds >= 0) udelay(1000000);
   restore_flags(ProcessorFlags);
 }
 
index 01b9039ebbb9a430a9460471ce40968610d5c5c6..424c73987a8595dda99d74d1d53415985144ebb8 100644 (file)
@@ -24,9 +24,9 @@ dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
 dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
 dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
 dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI
-dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
 dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
+dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
 dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
index 5a5a5a20d9ec5d78530398a4307702e3570d3822..51c39e3938c075650c1ceee4d24a7a564f269298 100644 (file)
@@ -734,7 +734,7 @@ static void NCR5380_print_options (struct Scsi_Host *instance) {
  */
 
 static void NCR5380_print_status (struct Scsi_Host *instance) {
-   char pr_bfr[256];
+   static char pr_bfr[512];
    char *start;
    int len;
 
@@ -767,7 +767,7 @@ static void NCR5380_print_status (struct Scsi_Host *instance) {
 */
 
 #undef SPRINTF
-#define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
+#define SPRINTF(args...) do { if(pos < buffer + length-80) pos += sprintf(pos, ## args); } while(0)
 static
 char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
 static
index 174d897fb38d8a81104ceea5df9c044bd5007f03..3c86573e0c76e8b1f7dc7842e58aa12d57f2dbf8 100644 (file)
@@ -1,4 +1,67 @@
+The BusLogic FlashPoint SCSI host adapters are now supported on Linux 2.0.x.
+See http://www.dandelion.com/Linux/ for the beta test BusLogic driver which
+includes FlashPoint support.  The upgrade program described below will remain
+available through the end of 1996.
 
+
+
+         MYLEX INTRODUCES LINUX OPERATING SYSTEM SUPPORT FOR ITS
+             BUSLOGIC FLASHPOINT LINE OF SCSI HOST ADAPTERS
+
+
+FREMONT, CA, -- October 8, 1996 -- Mylex Corporation has expanded Linux
+operating system support to its BusLogic brand of FlashPoint Ultra SCSI
+host adapters.  All of BusLogic's other SCSI host adapters, including the
+MultiMaster line, currently support the Linux operating system.  Linux
+drivers and information will be available on October 15th at
+http://www.dandelion.com/Linux/.
+
+"Mylex is committed to supporting the Linux community," says Peter Shambora,
+vice president of marketing for Mylex.  "We have supported Linux driver
+development and provided technical support for our host adapters for several
+years, and are pleased to now make our FlashPoint products available to this
+user base."
+
+The Linux Operating System
+
+Linux is a freely-distributed implementation of UNIX for Intel x86, Sun
+SPARC, SGI MIPS, Motorola 68k, Digital Alpha AXP and Motorola PowerPC
+machines.  It supports a wide range of software, including the X Window
+System, Emacs, and TCP/IP networking.  Further information is available at
+http://www.linux.org and http://www.ssc.com/linux.
+
+FlashPoint Host Adapters
+
+The FlashPoint family of Ultra SCSI host adapters, designed for workstation
+and file server environments, are available in narrow, wide, dual channel,
+and dual channel wide versions.  These adapters feature SeqEngine
+automation technology, which minimizes SCSI command overhead and reduces
+the number of interrupts generated to the CPU.
+
+About Mylex
+
+Mylex Corporation (NASDAQ/NM SYMBOL: MYLX), founded in 1983, is a leading
+producer of RAID technology and network management products.  The company
+produces high performance disk array (RAID) controllers, and complementary
+computer products for network servers, mass storage systems, workstations
+and system boards.  Through its wide range of RAID controllers and its
+BusLogic line of Ultra SCSI host adapter products, Mylex provides enabling
+intelligent I/O technologies that increase network management control,
+enhance CPU utilization, optimize I/O performance, and ensure data security
+and availability.  Products are sold globally through a network of OEMs,
+major distributors, VARs, and system integrators.  Mylex Corporation is
+headquartered at 34551 Ardenwood Blvd., Fremont, CA.
+
+                                  ####
+
+Contact:
+
+Peter Shambora
+Vice President of Marketing
+Mylex Corp.
+510/796-6100
+peters@mylex.com
+\f
                               ANNOUNCEMENT
               BusLogic FlashPoint LT/BT-948 Upgrade Program
                              1 February 1996
index 195eaa1f501b05404821cf389bda1104b0347e5f..f0982dc8a6ad7c539fdc3f7c5acaa1c4eb96ded9 100644 (file)
@@ -1,3 +1,5 @@
+#define EXPERIMENTAL_FLAGS 0
+
 /*+M*************************************************************************
  * Adaptec AIC7xxx device driver for Linux.
  *
@@ -4314,7 +4316,7 @@ aic7xxx_register(Scsi_Host_Template *template,
   p->flags = config->flags;
   p->chan_num = config->chan_num;
   p->scb_link = &(p->scb_usage);
-#ifdef AIC7XXX_SHARE_SCBS
+#if defined(CONFIG_PCI) && defined(AIC7XXX_SHARE_SCBS)
   if ((p->chan_num == 0) && ((p->type == AIC_7873) | (p->type == AIC_7883)))
   {
     shared_3985_scbs = &(p->scb_usage);
@@ -4410,7 +4412,7 @@ aic7xxx_register(Scsi_Host_Template *template,
     outb(config->scsi_id_b, SCSIID + base);
     scsi_conf = inb(SCSICONF + base + 1) & (ENSPCHK | STIMESEL);
     outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base);
-#if 1
+#if EXPERIMENTAL_FLAGS
     outb(ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1 + base);
 #else
     outb(ENSELTIMO, SIMODE1 + base);
@@ -4432,7 +4434,7 @@ aic7xxx_register(Scsi_Host_Template *template,
   outb(config->scsi_id, SCSIID + base);
   scsi_conf = inb(SCSICONF + base) & (ENSPCHK | STIMESEL);
   outb(scsi_conf | ENSTIMER | ACTNEGEN | STPWEN, SXFRCTL1 + base);
-#if 1
+#if EXPERIMENTAL_FLAGS
   outb(ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1 + base);
 #else
   outb(ENSELTIMO, SIMODE1 + base);
index 9fe17304eb498516ed499a42bad0a629f4145807..41b91acb02cad25d4c3ba0ffb53a29648e9c0ef9 100644 (file)
@@ -58,7 +58,7 @@
  * Jagdis who did a lot of testing and found quite a number *
  * of bugs during the development.                          *
  ************************************************************
- *  last change: 96/08/13                 OS: Linux 2.0.12  *
+ *  last change: 96/10/21                 OS: Linux 2.0.23  *
  ************************************************************/
 
 /* Look in eata_dma.h for configuration and revision information */
@@ -295,12 +295,9 @@ void eata_int_handler(int irq, void *dev_id, struct pt_regs * regs)
            sp->EOC = FALSE; /* Clean out this flag */
 
            if (ccb->status == LOCKED || ccb->status == RESET) {
-               ccb->status = FREE;
-               eata_stat = inb(base + HA_RSTATUS);
-               printk("eata_dma: int_handler, reseted command returned,"
-                      " freeing reseted queueslot\n");
+               printk("eata_dma: int_handler, reseted command pid %ld returned"
+                     "\n", cmd->pid);
               DBG(DBG_INTR && DBG_DELAY, DELAY(1));
-              break;
            }
            
            eata_stat = inb(base + HA_RSTATUS); 
@@ -467,23 +464,33 @@ int eata_queue(Scsi_Cmnd * cmd, void (* done) (Scsi_Cmnd *))
     struct Scsi_Host *sh;
     struct eata_ccb *ccb;
     struct scatterlist *sl;
+
     
     save_flags(flags);
     cli();
+
+#if 0
+    for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) {
+      if(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) {
+            printk("eata_dma: scsi%d interrupt pending in eata_queue.\n"
+                  "          Calling interrupt handler.\n", sh->host_no);
+            eata_int_handler(sh->irq, 0, 0);
+      }
+    }
+#endif
     
     queue_counter++;
 
     hd = HD(cmd);
     sh = cmd->host;
     
-#if 1
     if (cmd->cmnd[0] == REQUEST_SENSE && cmd->sense_buffer[0] != 0) {
         DBG(DBG_REQSENSE, printk(KERN_DEBUG "Tried to REQUEST SENSE\n"));
        cmd->result = DID_OK << 16;
        done(cmd);
+
        return(0);
     }
-#endif
 
     /* check for free slot */
     for (y = hd->last_ccb + 1, x = 0; x < sh->can_queue; x++, y++) { 
@@ -678,7 +685,6 @@ int eata_reset(Scsi_Cmnd * cmd, unsigned int resetflags)
                           " reason %x\n", cmd->pid, cmd->target, cmd->lun, 
                           cmd->abort_reason));
        
-    /* Some interrupt controllers seem to loose interrupts */
     for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->next) {
         if(inb((uint)sh->base + HA_RAUXSTAT) & HA_AIRQ) {
             printk("eata_dma: scsi%d interrupt pending in eata_reset.\n"
@@ -686,6 +692,7 @@ int eata_reset(Scsi_Cmnd * cmd, unsigned int resetflags)
             eata_int_handler(sh->irq, 0, 0);
       }
     }
+
     if (HD(cmd)->state == RESET) {
        printk("eata_reset: exit, already in reset.\n");
        restore_flags(flags);
@@ -766,9 +773,9 @@ int eata_reset(Scsi_Cmnd * cmd, unsigned int resetflags)
     restore_flags(flags);
     
     if (success) {
-       DBG(DBG_ABNORM, printk("eata_reset: exit, success.\n"));
+       DBG(DBG_ABNORM, printk("eata_reset: exit, pending.\n"));
        DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));
-       return (SCSI_RESET_SUCCESS);
+       return (SCSI_RESET_PENDING);
     } else {
        DBG(DBG_ABNORM, printk("eata_reset: exit, wakeup.\n"));
        DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));
@@ -852,8 +859,9 @@ static void eata_select_queue_depths(struct Scsi_Host *host,
                    device->queue_depth = (TYPE_OTHER_QUEUE * factor) / 10;
                    break;
                }
-           } else /* ISA forces us to limit the QS because of bounce buffers*/
-               device->queue_depth = 2; /* I know this is cruel */
+           } else /* ISA forces us to limit the queue depth because of the 
+                   * bounce buffer memory overhead. I know this is cruel */
+               device->queue_depth = 2; 
 
            /* 
             * It showed that we need to set an upper limit of commands 
@@ -863,6 +871,8 @@ static void eata_select_queue_depths(struct Scsi_Host *host,
             */
            if(device->queue_depth > UPPER_DEVICE_QUEUE_LIMIT)
                device->queue_depth = UPPER_DEVICE_QUEUE_LIMIT;
+           if(device->queue_depth == 0) 
+               device->queue_depth = 1;
 
            printk(KERN_INFO "scsi%d: queue depth for target %d on channel %d "
                   "set to %d\n", host->host_no, device->id, device->channel,
index 3beb2d96a640b63d2bdb9968ca51e2a4cd40ee4f..a23931bf9a3094496596ccf04e75de1c545d7478 100644 (file)
@@ -4,7 +4,7 @@
 *             mike@i-Connect.Net                        *
 *             neuffer@mail.uni-mainz.de                 *
 *********************************************************
-* last change: 96/08/14                                 *
+* last change: 96/10/14                                 *
 ********************************************************/
 
 #ifndef _EATA_DMA_H
@@ -17,7 +17,7 @@
 
 #define VER_MAJOR 2
 #define VER_MINOR 5
-#define VER_SUB   "9a"
+#define VER_SUB   "9b"
 
 
 /************************************************************************
index 8f1a0ed8c9d00df5b467a5f5ea4a0627e4850fbc..c884def02a2ffd3344fdbd473be9b390cd8bffd2 100644 (file)
@@ -68,7 +68,7 @@
 #define SG_SIZE                 64 
 #define SG_SIZE_BIG     252           /* max. 8096 elements, 64k */
 
-#define UPPER_DEVICE_QUEUE_LIMIT 24    /* The limit we have to set for the 
+#define UPPER_DEVICE_QUEUE_LIMIT 64    /* The limit we have to set for the 
                                        * device queue to keep the broken 
                                        * midlevel SCSI code from producing
                                        * bogus timeouts
index a77fe820f8c71f47de260297cf8aafe92e62319f..0fa74718cf38c8d35623a0b0243c9672f6f0907c 100644 (file)
@@ -224,6 +224,12 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #ifdef CONFIG_SCSI_ADVANSYS
        ADVANSYS,
 #endif
+#ifdef CONFIG_SCSI_EATA_DMA
+    EATA_DMA,
+#endif
+#ifdef CONFIG_SCSI_EATA_PIO
+    EATA_PIO,
+#endif
 /* BusLogic must come before aha1542.c */
 #ifdef CONFIG_SCSI_BUSLOGIC
     BUSLOGIC,
@@ -282,12 +288,6 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #ifdef CONFIG_SCSI_NCR53C8XX
     NCR53C8XX,
 #endif
-#ifdef CONFIG_SCSI_EATA_DMA
-    EATA_DMA,
-#endif
-#ifdef CONFIG_SCSI_EATA_PIO
-    EATA_PIO,
-#endif
 #ifdef CONFIG_SCSI_7000FASST
     WD7000,
 #endif
index f92909efaea53709135f58a2ff9b9804947b611e..dc0d8df427c34c25a0ada7aec5b25f0eb3c9703d 100644 (file)
@@ -17,8 +17,8 @@
  *  add scatter-gather, multiple outstanding request, and other
  *  enhancements.
  *
- *  Native multichannel and wide scsi support added 
- *  by Michael Neuffer neuffer@goofy.zdv.uni-mainz.de
+ *  Native multichannel, wide scsi, /proc/scsi and hot plugging 
+ *  support added by Michael Neuffer <mike@i-connect.net>
  *
  *  Added request_module("scsi_hostadapter") for kerneld:
  *  (Put an "alias scsi_hostadapter your_hostadapter" in /etc/conf.modules)
@@ -47,6 +47,7 @@
 #include <linux/stat.h>
 #include <linux/blk.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -275,6 +276,7 @@ static struct dev_info device_list[] =
  */
 {"SONY","CD-ROM CDU-8001","*", BLIST_BORKEN},
 {"TEXEL","CD-ROM","1.06", BLIST_BORKEN},
+{"IOMEGA","Io20S         *F","*", BLIST_KEY},
 {"INSITE","Floptical   F*8I","*", BLIST_KEY},
 {"INSITE","I325VM","*", BLIST_KEY},
 {"NRC","MBR-7","*", BLIST_FORCELUN | BLIST_SINGLELUN},
@@ -1219,17 +1221,19 @@ inline void internal_cmnd (Scsi_Cmnd * SCpnt)
      */
     timeout = host->last_reset + MIN_RESET_DELAY;
     if (jiffies < timeout) {
-        /*
-         * NOTE: This may be executed from within an interrupt
-         * handler!  This is bad, but for now, it'll do.  The irq
-         * level of the interrupt handler has been masked out by the
-         * platform dependent interrupt handling code already, so the
-         * sti() here will not cause another call to the SCSI host's
-         * interrupt handler (assuming there is one irq-level per
-         * host).
-         */
-        sti();
-        while (jiffies < timeout) barrier();
+       int ticks_remaining = timeout - jiffies;
+       /*
+        * NOTE: This may be executed from within an interrupt
+        * handler!  This is bad, but for now, it'll do.  The irq
+        * level of the interrupt handler has been masked out by the
+        * platform dependent interrupt handling code already, so the
+        * sti() here will not cause another call to the SCSI host's
+        * interrupt handler (assuming there is one irq-level per
+        * host).
+        */
+       sti();
+       while (--ticks_remaining >= 0) udelay(1000000/HZ);
+       host->last_reset = jiffies - MIN_RESET_DELAY;
     }
     restore_flags(flags);
     
@@ -3065,7 +3069,11 @@ static int scsi_register_host(Scsi_Host_Template * tpnt)
         */
        
        for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
-           if(shpnt->hostt == tpnt) scan_scsis(shpnt,0,0,0,0);
+           if(shpnt->hostt == tpnt) {
+             scan_scsis(shpnt,0,0,0,0);
+             if (shpnt->select_queue_depths != NULL)
+                 (shpnt->select_queue_depths)(shpnt, scsi_devices);
+           }
        
        for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
            if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();
index 4c722e6463bb83116b1c37ccf9712b53515fa5b9..8b63abed2d3bdde55ec0745c6ac35953a928b829 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/module.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
index 06cef903b0b07531c3ebe8a5b261a10428505b81..5bc6731ef6c7423e140a1b46fa6789afc65691c7 100644 (file)
@@ -512,7 +512,7 @@ static void do_sd_request (void)
 
        if (flag++ == 0)
            SCpnt = allocate_device(&CURRENT,
-                                   rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0); 
+                          rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0); 
        else SCpnt = NULL;
        
        /*
@@ -537,7 +537,8 @@ static void do_sd_request (void)
            cli();
            req = CURRENT;
            while(req){
-               SCpnt = request_queueable(req, rscsi_disks[DEVICE_NR(req->rq_dev)].device);
+               SCpnt = request_queueable(req, 
+                                   rscsi_disks[DEVICE_NR(req->rq_dev)].device);
                if(SCpnt) break;
                req1 = req;
                req = req->next;
index bff43d9fdfebf07ba0ffab86eface4fd8dfe7a1b..78c1ba0d65923d137911c24b174edce9e5aa1c86 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/hdreg.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/blk.h>
 #include "scsi.h"
index 7f56ba9c584cc66cd396f0efec4e4f4439bc1cf4..c163d1dba36c6f641047a86a241ed5d68b1c6d76 100644 (file)
@@ -1633,7 +1633,7 @@ int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
        return SCSI_RESET_WAKEUP;
        }
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include "sd.h"
 #include <scsi/scsi_ioctl.h>
 
index 656c7e66acc7dace50f94780c7bcde5cf875a324..3e1382fc18deb142d6162b19a6917984edb6ddbf 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/blk.h>
index e46db02714c84816acbe8cb771799b4d8da0a5db..82884f403776ad71087d7547172c04acf7d95aa5 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 
index 9160583d4fbac2a0ab0ea5f46c7812ac78e0ccb0..3c6e475c6fa9ae01e1cfd1d651f9aa945546fdf8 100644 (file)
@@ -11,7 +11,7 @@
   Copyright 1992 - 1996 Kai Makisara
                 email Kai.Makisara@metla.fi
 
-  Last modified: Tue Oct  1 22:53:51 1996 by makisara@kai.makisara.fi
+  Last modified: Tue Oct 22 20:59:52 1996 by root@kai.makisara.fi
   Some small formal changes - aeb, 950809
 */
 
@@ -26,7 +26,7 @@
 #include <linux/mtio.h>
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 #include <asm/system.h>
 
@@ -888,10 +888,12 @@ out:
 
 \f
 /* Write command */
-       static int
-st_write(struct inode * inode, struct file * filp, const char * buf, int count)
+       static long
+st_write(struct inode * inode, struct file * filp, const char * buf,
+        unsigned long count)
 {
-    int total, do_count, blks, retval, transfer;
+    long total;
+    int do_count, blks, retval, transfer;
     int write_threshold;
     int doing_write = 0;
     static unsigned char cmd[10];
@@ -1166,10 +1168,10 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
 
 \f
 /* Read command */
-       static int
-st_read(struct inode * inode, struct file * filp, char * buf, int count)
+       static long
+st_read(struct inode * inode, struct file * filp, char * buf, unsigned long count)
 {
-    int total;
+    long total;
     int transfer, blks, bytes;
     static unsigned char cmd[10];
     Scsi_Cmnd * SCpnt = NULL;
@@ -1310,7 +1312,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                  (STp->buffer)->buffer_bytes = (blks - transfer) * STp->block_size;
 #if DEBUG
                  if (debugging)
-                   printk(ST_DEB_MSG "st%d: ILI but enough data received %d %d.\n",
+                   printk(ST_DEB_MSG "st%d: ILI but enough data received %ld %d.\n",
                           dev, count - total, (STp->buffer)->buffer_bytes);
 #endif
                  if (count - total > (STp->buffer)->buffer_bytes)
@@ -1332,7 +1334,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
 #if DEBUG
                if (debugging)
                  printk(ST_DEB_MSG
-                   "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
+                   "st%d: EOF detected (%d bytes read, transferred %ld bytes).\n",
                         dev, (STp->buffer)->buffer_bytes, total);
 #endif
              }
@@ -2314,6 +2316,7 @@ set_location(struct inode * inode, unsigned int block, int partition,
       return (-EBUSY);
 
     STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
+    STp->eof = ST_NOEOF;
     if ((STp->buffer)->last_result_fatal != 0) {
       result = (-EIO);
       if (STp->can_partitions &&
diff --git a/drivers/sound/.object_files b/drivers/sound/.object_files
deleted file mode 100644 (file)
index 92ba4da..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-audio.o
-dmabuf.o
-opl3.o
-sequencer.o
-midibuf.o
-sb_card.o
-pas2_card.o
-adlib_card.o
-pas2_pcm.o
-pas2_mixer.o
-pas2_midi.o
-gus_card.o
-gus_wave.o
-mpu401.o
-gus_midi.o
-gus_vol.o
-patmgr.o
-sb_mixer.o
-sb_common.o
-midi_synth.o
-uart6850.o
-uart401.o
-sound_timer.o
-sb_midi.o
-sb_audio.o
-sys_timer.o
-ics2101.o
-ad1848.o
-pss.o
-sscape.o
-trix.o
-aedsp16.o
-mad16.o
-cs4232.o
-maui.o
index 2a7c4461c51f1e0dd435518828929c5e6c9b890e..df5184e6de0157ffa632e26aabd9052a4d3428e1 100644 (file)
@@ -24,7 +24,7 @@ ifdef CONFIG_AUDIO
        OBJS := $(OBJS)  dmabuf.o
 endif
 
-ifdef CONFIG_GUS
+ifdef CONFIG_GUSHW
        OBJS := $(OBJS)  gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
 endif
 
@@ -76,7 +76,7 @@ ifdef CONFIG_SEQUENCER
        OBJS := $(OBJS)  sound_timer.o
 endif
 
-ifdef CONFIG_SSCAPE
+ifdef CONFIG_SSCAPEHW
        OBJS := $(OBJS)  sscape.o
 endif
 
@@ -95,3 +95,4 @@ endif
 ifdef CONFIG_UART401
        OBJS := $(OBJS)  uart401.o
 endif
+
index 81e5a00da1b58aa459590f6d062c0d2d4dc3557a..08b3451796cc902725362b9c52dbf9eb3a8641c7 100644 (file)
@@ -1,2 +1,2 @@
-3.5.5-beta1
-0x030504
+3.7-beta6
+0x030701
index ccb6032dee1f9e048197261cda38155ad8f53015..e383ff1d986d86b631fcf632afae4203b5124ec3 100644 (file)
@@ -1,5 +1,9 @@
-Changelog for version 3.5.4
----------------------------
+Changelog for version 3.7-beta5
+-------------------------------
+
+Since 3.5
+- Changes almost everywhere.
+- Support for OPTi 82C924 based soundcards.
 
 Since 3.5.4-beta8
 - Fixed a bug in handling of non-fragment sized writes in 16 bit/stereo mode
index 22cba705d75939b4bd16b45380855bb018e2e251..e28aabb2baa16c3ca7fbf03e354cb2550804f55a 100644 (file)
@@ -14,4 +14,5 @@ bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
 
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
+   bool 'AWE32 synth' CONFIG_AWE32_SYNTH
 fi
index b1bc3607904bd99befe4226407f4ba54ee59935f..e28aabb2baa16c3ca7fbf03e354cb2550804f55a 100644 (file)
@@ -2,10 +2,10 @@
 # Sound driver configuration
 #
 #--------
-# There is another config script which is compatible with rest of
+# There is another confic script which is compatible with rest of
 # the kernel. It can be activated by running 'make mkscript' in this
 # directory. Please note that this is an _experimental_ feature which
-# doesn't work with all cards (PSS, SM Wave, AudioTrix Pro, Maui).
+# doesn't work with all cards (PSS, SM Wave, AudioTriX Pro, Maui).
 #--------
 #
 $MAKE -C drivers/sound config || exit 1
@@ -14,4 +14,5 @@ bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
 
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
+   bool 'AWE32 synth' CONFIG_AWE32_SYNTH
 fi
index d5dfa70aedc0f584bd701717800a431b334b30b9..fb0ab87e33976c4427513321072ef640ba5c5f19 100644 (file)
@@ -21,8 +21,6 @@ endif
 ifeq (.defines,$(wildcard .defines))
 include .defines
 include .objects
-else
-OBJS   = `cat .object_files`
 endif
 
 ifndef TOPDIR
@@ -72,7 +70,7 @@ sound.a: $(OBJS)
 
 clean:
        rm -f core core.* *.o *.a tmp_make *~ x y z *%
-       rm -f configure sound_stub.c objects/*.o 
+       rm -f configure
        cd lowlevel;make clean
 
 indent:
@@ -80,7 +78,7 @@ indent:
 
 local.h: 
        $(MAKE) clean
-       $(MAKE) setup-$(TARGET_OS)
+       $(MAKE) setup
        $(MAKE) oldconfig
        $(MAKE) dep
        @echo
@@ -93,7 +91,7 @@ local.h:
        @echo
 
 config: configure
-       @$(MAKE) setup-$(TARGET_OS)
+       @$(MAKE) setup
        @./configure > local.h
        @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
        @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
@@ -101,7 +99,7 @@ config: configure
 #      @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
        @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-oldconfig: setup-$(TARGET_OS) configure
+oldconfig: setup configure
        @./configure -o > local.h
        @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h
        @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h
@@ -109,7 +107,7 @@ oldconfig: setup-$(TARGET_OS) configure
 #      @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
        @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-kernelconfig: setup-$(TARGET_OS)
+kernelconfig: setup
        rm -f configure
        $(HOSTCC) -o configure configure.c
        ./configure fixedlocal > local.h
@@ -120,7 +118,7 @@ kernelconfig: setup-$(TARGET_OS)
 #      @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null
        @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h
 
-mkscript: setup-$(TARGET_OS)
+mkscript: setup
        rm -f configure
        $(HOSTCC) -o configure configure.c
        ./configure script > Config.in
@@ -136,9 +134,9 @@ configure: configure.c
        @cat .blurb
 
 dep:
-       $(CPP) -M *.c > .depend
+       $(CPP) -M $(CFLAGS) -I. *.c > .depend
 
-setup-linux:
+setup:
        @echo Compiling Sound Driver v $(VERSION) for Linux
 
 sound.o: local.h $(FIXEDOBJS) sound.a
@@ -152,6 +150,9 @@ modules: local.h sound.o
 lowlevel/lowlevel.o: dummy
                cd lowlevel;make
 
+contrib:
+               cd lowlevel;make clean;make module CFLAGS="$(CFLAGS)"
+
 ifdef USE_DEPEND
 #
 # include a dependency file if one exists
index 19dbc96bd30637bd9551a94576603fcbebb712d9..16f7746cb5eac205a4c45c3ca2a47c24c7240226 100644 (file)
@@ -1,8 +1,8 @@
-USS Lite version 3.5.4 release notes
-------------------------------------
+OSS Lite version 3.7-beta release notes
+---------------------------------------
 
 Most up to date information about this driver is available from 
-http://www.4front-tech.com/usslite or http://personal.eunet.fi/pp/voxware
+http://www.4front-tech.com/ossfree or http://personal.eunet.fi/pp/voxware
 (European mirror).
 
 
@@ -16,15 +16,12 @@ New Programmer's Guide is currently under work (June/July 96). Please
 check http://www.4front-tech.com/pguide for more info.
 
    ====================================================
--  THIS VERSION ____REQUIRES____ Linux 1.3.70 OR LATER.
+-  THIS VERSION ____REQUIRES____ Linux 2.1.5 OR LATER.
    ====================================================
 
-It's very likely that this driver version is incompatible with
-Linux versions later than 2.0.x.
-
 Packages "snd-util-3.5.tar.gz" and "snd-data-0.1.tar.Z"
 contain useful utilities to be used with this driver.
-See http://www.4front-tech.com/usslite/getting.html for
+See http://www.4front-tech.com/ossfree/getting.html for
 download instructions.
 
 If you are looking for the installation instructions, please
@@ -35,7 +32,7 @@ Supported soundcards
 
 See Readme.cards.
 
-Please check http://www.4front-tech.com/usslite if you don't find
+Please check http://www.4front-tech.com/ossfree if you don't find
 your soundcard there.
 
 Contributors
@@ -73,6 +70,8 @@ contributors. (I could have forgotten some names.)
        Gregor Hoffleit Mozart support (initial version)
        Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support
        James Hightower Spotting a tiny but important bug in CS423x support.
+       Denis Sablic    OPTi 82C924 spesific enhancements (non PnP mode)
+       Tim MacKenzie   Full duplex support for OPTi 82C930.
        
        Please look at lowlevel/README for more contributors.
 
@@ -113,7 +112,7 @@ If you have some problems
 =========================
 
 Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
-Also look at the home page (http://www.4front-tech.com/usslite). It may
+Also look at the home page (http://www.4front-tech.com/ossfree). It may
 contain info about some recent bug fixes.
 
 It's likely that you have some problems when trying to use the sound driver
@@ -168,7 +167,7 @@ Hannu
 
 Hannu Savolainen
 hannu@voxware.pp.fi, hannu@4front-tech.com     
-(Please check http://www.4front-tech.com/usslite before mailing me).
+(Please check http://www.4front-tech.com/ossfree before mailing me).
 
 Snail mail:    Hannu Savolainen
                Hiekkalaiturintie 3 A 8
index 13575eb220072a1e1cc388034e3d2725567a0967..b205a9d0ff56f039b01f19f721e1b14a3202610e 100644 (file)
@@ -1,6 +1,6 @@
-Information about Audio Excel DSP 16 can be found in the source
+Informations about Audio Excel DSP 16 can be found in the source
 file aedsp16.c
 Please, read the head of the source before using it. It contain useful
-information.
+informations.
 
     Riccardo
index 528c256adadaa15883636d07f5a34dad74acd851..25fd775de5964b8be0aca13864a26b4b0c00b84d 100644 (file)
@@ -1,9 +1,15 @@
-Configuring version 3.5.4 (for Linux) with some most common soundcards
-======================================================================
+Configuring version 3.7 (for Linux) with some most common soundcards
+====================================================================
+
+This document describes configuring soundcards with freeware version of
+Open Sound Systems (OSS/Free). Information about the commercial version
+(OSS/Linux) and it's configuration is available from 
+http://www.4front-tech.com/linux.html. Information presented here is
+not valid for OSS/Linux.
 
 IMPORTANT!     This document covers only cards that were "known" when
                this driver version was released. Please look at
-               http://www.4front-tech.com/usslite for info about
+               http://www.4front-tech.com/ossfree for info about
                cards introduced recently.
 
                The following covers mainly the "old" configuration
@@ -22,45 +28,15 @@ IMPORTANT!  This document covers only cards that were "known" when
 Cards that are not (fully) supported by this driver
 ---------------------------------------------------
 
-There are many soundcards which don't work with this driver
-version (v3.5). Support for some of them is expected to be
-available during/after summer 1996 (in version 3.6). Please check
-http://www.4front-tech.com/usslite for latest news. Please don't
-mail me and ask about these cards. The unsupported cards are:
-
-       - All PnP soundcards (SB PnP, GUS PnP, Soundscape PnP etc.)
-               Schedule for availability of PnP soundcard support in
-               USS/Lite depends on progress made by kernel PnP team
-               (probably in Linux 2.1.xx versions). With Linux 2.0.x
-               versions there are two ways to get PnP soundcards to work:
-               - Use isapnptools, DOS, Win95 or PnP aware BIOS to wake up the
-               card before starting the sound driver. See "Configuring PnP 
-               soundcards" below for some hints.
-               - Support for SB PnP and GUS PnP is present in USS/Linux (the
-               commercial version of this driver).
-       - Mwave soundcards and motherboards
-               (Version 3.6 or 3.7. Depends on how fast I get
-               suitable documents for Mwave).
-       - Emu8k (SB 32/AWE)
-               (Probably not _before_ summer 97. I know the unofficial
-               AWE programmers guide so don't send me more copies of it).
-       - Diamond Edge 3D
-               (ASAP. In practice this may take relatively long time).
-       - Compaq Deskpro
-               (Version 3.5.4-beta6 (already released))
-       - Sound Galaxy Washington/Waverider
-               (Audio features already in USS/Linux (USS/Lite soon). 
-               Can't promise the waverider synth since
-               availability of chip specs is uncertain).
-       - Yamaha OPL4 (on cards having _RAM_ for samples)
-               (Late 96?. Works as OPL3 with current driver versions)
+See http://www.4front-tech.com/ossfree for information about soundcards 
+to be supported in future. 
 
 How to use sound without recompiling kernel and/or sound driver
 ---------------------------------------------------------------
 
 There is commercial sound driver which should be released during Apr 96.
 It comes in precompiled form and doesn't require recompiling of kernel. See
-http://www.4Front-tech.com/uss.html for more info.
+http://www.4Front-tech.com/oss.html for more info.
 
 Configuring PnP cards
 ---------------------
@@ -75,9 +51,9 @@ motherboards) is also based on PnP technology but there is a "native" driver
 available for it (see information about CS4232 later in this document).
 
 PnP soundcards (as well as most other PnP ISA cards) are not supported
-by version 3.5 of this driver (Linux 1.3.xx and Linux 2.0.x). Proper
-support for them should be released during spring 9
-(see http://www.4front-tech.com/usslite for latest info).
+by this version of the driver . Proper
+support for them should be released during spring 97 once kernel level
+PnP support is available.
 
 There is a method to get most of the PnP cards to work. The basic method
 is the following:
@@ -99,6 +75,7 @@ before running it.
 Some machines have BIOS utility for setting PnP resources. This is a good
 way to configure some cards. In this case you don't need to boot DOS/Win95
 prior starting Linux.
+
 Another way to initialize PnP cards without DOS/Win95 is a Linux based
 PnP isolation tool. When writing this there is a pre alpha test version
 of such tool available from ftp://ftp.demon.co.uk/pub/unix/linux/utils. The
@@ -106,11 +83,9 @@ file is called isapnptools-*. Please note that this tool is just a temporary
 solution which may be incompatible with future kernel versions having proper
 support for PnP cards. There are bugs in setting DMA channels in earlier
 versions of isapnptools so at least version 1.6 is required with soundcards.
-You can find latest version of isapnptools from
-ftp://ftp.demon.co.uk/pub/unix/linux/utils/
 
-These two methods don't work with GUS PnP which requires some additional
-initialization (cards DOS/Win95 driver does it). 
+Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers.
+See http://www.4front-tech.com/linux.html for more info.
 
 Read this before trying to configure the driver
 -----------------------------------------------
@@ -138,25 +113,35 @@ Sound Blasters
        SB 1.0 to 2.0
        SB Pro
        SB 16
-       NOTE!   The ASP chip and the EMU synth of AWE32 are not supported 
-               since their manufacturer doesn't release information about
-               the card. However, both SB16ASP and AWE32 work with
-               the driver just like a SB16. Also see the comment about some
-               unsupported cards at the end of this file.
-               (The OPL3 FM chip of SB32/AWE works but you cannot hear it).
+       SB32/AWE
+               Configure SB32/AWE just like SB16. See lowlevel/README.awe
+               for information about using the wave table synth.
        SB16 compatible cards by other manufacturers than Creative.
-               You have been fooled since there are no SB16 compatible
+               You have been fooled since there are _no_ SB16 compatible
                cards on the market (Feb 96). It's likely that your card
                is compatible just with SB Pro but there is also a non-SB-
                compatible 16 bit mode. Usually it's MSS/WSS but it could also
-               be a proprietary one like MV Jazz16 or ESS ES688.
+               be a proprietary one like MV Jazz16 or ESS ES688. OPTi
+               MAD16 chips are very common in so called "SB 16 bit cards".
+       "Supposed to be SB compatible" cards.
+               Forget the SB compatibility and check for other alternatives
+               first. The only cards that work with the SB driver in
+               Linux have been made by Creative Technology (there is at least
+               one chip on the card with "CREATIVE" printed on it). The
+               only other SB compatible chips are ESS and Jazz16 chips
+               (maybe ALSxxx chips too but they propably don't work).
+
+               Practically all soundcards have some kind of SB emulation mode
+               in addition to their native (16 bit) mode. In most cases this
+               (8 bit only) SB compatible mode doesn't work with Linux. However
+               in most cases the native 16 bit mode is supported by Linux.
 
 Gravis Ultrasound (GUS)
        GUS
        GUS + the 16 bit option
        GUS MAX
        GUS ACE (No MIDI port and audio recording)
-       GUS PnP (Partially supported)
+       GUS PnP (in GUS MAX compatible mode)
 
 MPU-401        and compatibles
        The driver works both with the full (intelligent mode) MPU-401
@@ -230,8 +215,8 @@ Ensoniq SoundScape and compatibles
        NOTE! The new PnP SoundScape is not supported yet.
 
 MAD16 and Mozart based cards
-       The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929) 
-       and OPTi 82C930 interface
+       The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929),
+       OPTi 82C924 (non PnP mode) and OPTi 82C930 interface
        chips are used in many different soundcards, including some
        cards by Reveal miro and Turtle Beach (Tropez). The purpose of these
        chips is to connect other audio components to the PC bus. The
@@ -240,16 +225,14 @@ MAD16 and Mozart based cards
 
 Audio Excel DSP16 
        Support for this card was written by Riccardo Faccetti
-       (riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info.
-       (This driver is not functional in version 3.5 of this driver. A
-       patch should be made available during April 96 (sunsite.unc.edu)).
+       (riccardo@cdc8g5.cdc.polimi.it). The AEDSP16 driver included in
+       this source distribution is not fully functional. A patch is
+       available from sunsite.unc.edu/pub/Linux/kernel/sound.
        
 Crystal CS4232 based cards such as AcerMagic S23, TB Tropez _Plus_ and 
        many PC motherboards (Compaq, HP, Intel, ...)
        CS4232 is a PnP multimedia chip which contains a CS3231A codec,
        SB and MPU401 emulations. There is support for OPL3 too.
-       This is a temporary driver which uses the chip in non PnP mode
-       (The final driver should be included in version 3.6 of the driver).
        Unfortunately the MPU401 mode doesn't work (I don't know how to
        initialize it). 
 
@@ -454,7 +437,8 @@ select some options automatically as well.
        - Answer 'y' if you have the AudioTrix Pro.
   "Support for MAD16 and/or Mozart based cards",
        - Answer y if your card has a Mozart (OAK OTI-601) or MAD16
-         (OPTi 82C928, 82C929 or 82C930) audio interface chip. These chips are
+         (OPTi 82C928, 82C929, 82C924 or 82C930) audio interface chip. 
+         These chips are
          currently quite common so it's possible that many no-name cards
          have one of them. In addition the MAD16 chip is used in some
          cards made by known manufacturers such as Turtle Beach (Tropez),
@@ -463,15 +447,11 @@ select some options automatically as well.
        - This enables TB Maui specific initialization. Works with TB Maui
        and TB Tropez (may not work with Tropez Plus).
 
-  "Audio Excel DSP 16 initialization support",
-       - Don't know much about this card. Look at aedsp16.c for more info.
 
 Then the configuration program asks some y/n questions about the higher
 level services. It's recommended to answer 'y' to each of these questions.
 Answer 'n' only if you know you will not need the option.
 
-  "/dev/dsp and /dev/audio supports (usually required)",
-       - Answering 'n' disables /dev/dsp and /dev/audio. Answer 'y'.
   "MIDI interface support",
        - Answering 'n' disables /dev/midi## devices and access to any
          MIDI ports using /dev/sequencer and /dev/music. This option
@@ -705,7 +685,10 @@ when using the (future) binary distribution version of the driver.
 Ensoniq SoundScape
 ------------------
 
-NOTE!  The new PnP SoundScape is not supported yet.
+NOTE!  The new PnP SoundScape is not supported yet. Soundscape compatible
+       cards made by Reveal don't work with Linux. They use older revision
+       of the Soundscape chipset which is not fully compatible with
+       newer cards made by Ensoniq.
 
 The SoundScape driver handles initialization of MSS and MPU supports
 itself so you don't need to enable other drivers than SoundScape
@@ -719,7 +702,7 @@ itself so you don't need to enable other drivers than SoundScape
 !!!!!      purposes. It WAS required to change /dev/dsp (a symlink) to !!!!
 !!!!!      point to /dev/dsp1.                                         !!!!
 !!!!!                                                                   !!!!
-!!!!!      This is not required with USS versions 3.5-beta6 and later  !!!!
+!!!!!      This is not required with OSS versions 3.5-beta6 and later  !!!!
 !!!!!      since there is now just one audio device file. Please       !!!!
 !!!!!      change /dev/dsp to point back to /dev/dsp0 if you are       !!!!
 !!!!!      upgrading from an earlier driver version using              !!!!
@@ -757,6 +740,10 @@ an old card and you will need to use sndscape.co1. For other cards use
 soundscape.co0. New Soundscape revisions such as Elite and PnP use
 code files with higher numbers (.co2, .co3, etc.).
 
+NOTE!  Ensoniq Soundscape VIVO is not compatible with other Soundscape cards.
+       Currently it's possible to use it in Linux only with OSS/Linux
+       drivers.
+
 Check /var/adm/messages after running ssinit. The driver prints
 the board version after downloading the microcode file. That version
 number must match the number in the name of the microcode file (extension).
@@ -801,6 +788,10 @@ MAD16 cards having a CS4231 codec support full duplex mode. This mode
 can be enabled by configuring the card to use two DMA channels. Possible
 DMA channel pairs are: 0&1, 1&0 and 3&0.
 
+NOTE! Cards having an OPTi 82C924 chip work with OSS/Free only in
+non-PnP mode (usually jumper selectable). The PnP mode is supported only
+by OSS/Linux.
+
 MV Jazz (ProSonic)
 ------------------
 
@@ -855,10 +846,6 @@ is powered on. These cards actually behave just like they have jumpers
 for all of the settings. Configure driver for MSS, MPU, SB/SB Pro  and OPL3 
 supports with these cards. 
 
-The config program asks if you want support for the mixer of
-SG NX Pro. Answer 'y' to these questions if you have one of the above 8 or
-16 bit Aztech cards.
-
 There are some new Sound Galaxies in the market. I have no experience with
 them so read the card's manual carefully.
 
@@ -992,14 +979,12 @@ required in maintaining the driver (some changes need to be done
 to all low level drivers and be tested too, maybe with multiple
 operating systems). For this reason I have made a decision to not support
 obsolete cards. It's possible that someone else makes a separately 
-distributed driver (diffs) for the card. Version v3.6 will be much more
-modular so making separately distributed drivers will be easier with it.
-(The bad news is that v3.6 will not be available before summer -96).
+distributed driver (diffs) for the card. 
 
 Writing a driver for a new card is not possible if there are no 
 programming information available about the card. If you don't
 find your new card from this file, look from the home page 
-(http://www.4front-tech.com/usslite). Then please contact
+(http://www.4front-tech.com/ossfree). Then please contact
 manufacturer of the card and ask if they have (or are willing to)
 released technical details of the card. Do this before contacting me. I
 can only answer 'no' if there are no programming information available.
@@ -1015,12 +1000,12 @@ Some companies don't give low level technical information about their
 products to public or at least their require signing a NDA. It's not
 possible to implement a freeware driver for them. However it's possible
 that support for such cards become available in the commercial version
-of this driver (see http://www.4Front-tech.com/uss.html for more info).
+of this driver (see http://www.4Front-tech.com/oss.html for more info).
 
 There are some common audio chipsets that are not supported yet. For example
 Sierra Aria and IBM Mwave. It's possible that these architectures
 get some support in future but I can't make any promises. Just look
-at the home page (http://www.4front-tech.com/usslite/new_cards.html)
+at the home page (http://www.4front-tech.com/ossfree/new_cards.html)
 for latest info.
 
 Information about unsupported soundcards and chipsets is welcome as well
@@ -1032,9 +1017,9 @@ Hannu Savolainen
 hannu@voxware.pp.fi
 
 Personal home page:       http://personal.eunet.fi/pp/voxware/hannu.html
-www home page of USS/Lite: http://www.4front-tech.com/usslite
+www home page of OSS/Free: http://www.4front-tech.com/ossfree
   European/Finnish mirror: http://personal.eunet.fi/pp/voxware
 
-www home page of commercial
-Open Sound System drivers: http://www.4front-tech.com/uss.html
+www home page of commercial OSS
+(Open Sound System) drivers: http://www.4front-tech.com/oss.html
 
index 3f41060276f0bb247c54befc70f5a87e766db4ee..35c977bef926b00201a75b98790121da076acad9 100644 (file)
@@ -67,7 +67,7 @@ Readme.cards for info about configuring the driver with your card. Also
 check for possible boot (insmod) time error messages in /var/adm/messages.
 
 - Other messages or problems
-Please check http://www.4front-tech.com/usslite for more info.
+Please check http://www.4front-tech.com/osslite for more info.
 
 Hannu Savolainen
 hannu@voxware.pp.fi
index b329ff9d366de8487b3a61c79532668bef81b0e2..5556718f432c87897ee14949dde79b0eb9633f3f 100644 (file)
@@ -17,7 +17,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -36,6 +36,7 @@ typedef struct
   {
     int             base;
     int             irq;
+    int             dma1, dma2;
     int             dual_dma;  /* 1, when two DMA channels allocated */
     unsigned char   MCE_bit;
     unsigned char   saved_regs[16];
@@ -46,6 +47,7 @@ typedef struct
     int             channels;
     int             audio_format;
     unsigned char   format_bits;
+    int             audio_flags;
 
     int             xfer_count;
     int             audio_mode;
@@ -63,14 +65,15 @@ typedef struct
 
     /* Mixer parameters */
     int             recmask;
-    int             supported_devices;
-    int             supported_rec_devices;
-    unsigned short  levels[32];
+    int             supported_devices, orig_devices;
+    int             supported_rec_devices, orig_rec_devices;
+    int            *levels;
+    short           mixer_reroute[32];
     int             dev_no;
     volatile unsigned long timer_ticks;
     int             timer_running;
     int             irq_ok;
-    int            *osp;
+    mixer_ents     *mix_devices;
   }
 
 ad1848_info;
@@ -86,12 +89,12 @@ static int      ad_format_mask[8 /*devc->model */ ] =
 {
   0,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
   AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,    /* AD1845 */
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM,
-  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_U16_LE | AFMT_IMA_ADPCM
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+  AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM
 };
 
 static ad1848_info dev_info[MAX_AUDIO_DEV];
@@ -128,7 +131,7 @@ ad_read (ad1848_info * devc, int reg)
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
+  outb (((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr (devc));
   x = inb (io_Indexed_Data (devc));
   /*  printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
   restore_flags (flags);
@@ -148,8 +151,8 @@ ad_write (ad1848_info * devc, int reg, int data)
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (reg & 0xff) | devc->MCE_bit, io_Index_Addr (devc));
-  outb ((unsigned char) (data & 0xff), io_Indexed_Data (devc));
+  outb (((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr (devc));
+  outb (((unsigned char) (data & 0xff)), io_Indexed_Data (devc));
   /* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
   restore_flags (flags);
 }
@@ -204,6 +207,7 @@ ad_mute (ad1848_info * devc)
 /*
  * Let's have some delay
  */
+
   for (i = 0; i < 1000; i++)
     inb (devc->base);
 }
@@ -220,7 +224,7 @@ ad_unmute (ad1848_info * devc)
     inb (devc->base);
 
   /*
-     * Restore back old volume registers (unmute)
+   * Restore back old volume registers (unmute)
    */
   for (i = 6; i < 8; i++)
     {
@@ -249,7 +253,7 @@ ad_enter_MCE (ad1848_info * devc)
       return;
     }
 
-  outb (devc->MCE_bit, io_Index_Addr (devc));
+  outb ((devc->MCE_bit), io_Index_Addr (devc));
   restore_flags (flags);
 }
 
@@ -268,7 +272,7 @@ ad_leave_MCE (ad1848_info * devc)
 
   devc->MCE_bit = 0x00;
   prev = inb (io_Index_Addr (devc));
-  outb (0x00, io_Index_Addr (devc));   /* Clear the MCE bit */
+  outb ((0x00), io_Index_Addr (devc)); /* Clear the MCE bit */
 
   if ((prev & 0x40) == 0)      /* Not in MCE mode */
     {
@@ -276,7 +280,7 @@ ad_leave_MCE (ad1848_info * devc)
       return;
     }
 
-  outb (0x00, io_Index_Addr (devc));   /* Clear the MCE bit */
+  outb ((0x00), io_Index_Addr (devc)); /* Clear the MCE bit */
   wait_for_calibration (devc);
   restore_flags (flags);
 }
@@ -290,6 +294,15 @@ ad1848_set_recmask (ad1848_info * devc, int mask)
 
   mask &= devc->supported_rec_devices;
 
+  /* Rename the mixer bits if necessary */
+  for (i = 0; i < 32; i++)
+    if (devc->mixer_reroute[i] != i)
+      if (mask & (1 << i))
+       {
+         mask &= ~(1 << i);
+         mask |= (1 << devc->mixer_reroute[i]);
+       }
+
   n = 0;
   for (i = 0; i < 32; i++)     /* Count selected device bits */
     if (mask & (1 << i))
@@ -339,21 +352,30 @@ ad1848_set_recmask (ad1848_info * devc, int mask)
   ad_write (devc, 0, (ad_read (devc, 0) & 0x3f) | recdev);
   ad_write (devc, 1, (ad_read (devc, 1) & 0x3f) | recdev);
 
+  /* Rename the mixer bits back if necessary */
+  for (i = 0; i < 32; i++)
+    if (devc->mixer_reroute[i] != i)
+      if (mask & (1 << devc->mixer_reroute[i]))
+       {
+         mask &= ~(1 << devc->mixer_reroute[i]);
+         mask |= (1 << i);
+       }
+
   devc->recmask = mask;
   return mask;
 }
 
 static void
-change_bits (unsigned char *regval, int dev, int chn, int newval)
+change_bits (ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
 {
   unsigned char   mask;
   int             shift;
 
-  if (mix_devices[dev][chn].polarity == 1)     /* Reverse */
+  if (devc->mix_devices[dev][chn].polarity == 1)       /* Reverse */
     newval = 100 - newval;
 
-  mask = (1 << mix_devices[dev][chn].nbits) - 1;
-  shift = mix_devices[dev][chn].bitpos;
+  mask = (1 << devc->mix_devices[dev][chn].nbits) - 1;
+  shift = devc->mix_devices[dev][chn].bitpos;
   newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
 
   *regval &= ~(mask << shift); /* Clear bits */
@@ -364,7 +386,9 @@ static int
 ad1848_mixer_get (ad1848_info * devc, int dev)
 {
   if (!((1 << dev) & devc->supported_devices))
-    return -(EINVAL);
+    return -EINVAL;
+
+  dev = devc->mixer_reroute[dev];
 
   return devc->levels[dev];
 }
@@ -379,12 +403,20 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
   int             regoffs;
   unsigned char   val;
 
+  if (dev > 31)
+    return -EINVAL;
+
+  if (!(devc->supported_devices & (1 << dev)))
+    return -EINVAL;
+
+  dev = devc->mixer_reroute[dev];
+
   if (left > 100)
     left = 100;
   if (right > 100)
     right = 100;
 
-  if (mix_devices[dev][RIGHT_CHN].nbits == 0)  /* Mono control */
+  if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)    /* Mono control */
     right = left;
 
   retvol = left | (right << 8);
@@ -397,14 +429,8 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
   left = mix_cvt[left];
   right = mix_cvt[right];
 
-  if (dev > 31)
-    return -(EINVAL);
-
-  if (!(devc->supported_devices & (1 << dev)))
-    return -(EINVAL);
-
-  if (mix_devices[dev][LEFT_CHN].nbits == 0)
-    return -(EINVAL);
+  if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
+    return -EINVAL;
 
   devc->levels[dev] = retvol;
 
@@ -412,9 +438,9 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
      * Set the left channel
    */
 
-  regoffs = mix_devices[dev][LEFT_CHN].regno;
+  regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
   val = ad_read (devc, regoffs);
-  change_bits (&val, dev, LEFT_CHN, left);
+  change_bits (devc, &val, dev, LEFT_CHN, left);
   ad_write (devc, regoffs, val);
   devc->saved_regs[regoffs] = val;
 
@@ -422,12 +448,12 @@ ad1848_mixer_set (ad1848_info * devc, int dev, int value)
      * Set the right channel
    */
 
-  if (mix_devices[dev][RIGHT_CHN].nbits == 0)
+  if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
     return retvol;             /* Was just a mono channel */
 
-  regoffs = mix_devices[dev][RIGHT_CHN].regno;
+  regoffs = devc->mix_devices[dev][RIGHT_CHN].regno;
   val = ad_read (devc, regoffs);
-  change_bits (&val, dev, RIGHT_CHN, right);
+  change_bits (devc, &val, dev, RIGHT_CHN, right);
   ad_write (devc, regoffs, val);
   devc->saved_regs[regoffs] = val;
 
@@ -438,17 +464,33 @@ static void
 ad1848_mixer_reset (ad1848_info * devc)
 {
   int             i;
+  char            name[32];
+
+  devc->mix_devices = &(ad1848_mix_devices[0]);
+
+  sprintf (name, "%s_%d", devc->chip_name, nr_ad1848_devs);
+
+  for (i = 0; i < 32; i++)
+    devc->mixer_reroute[i] = i;
 
   switch (devc->model)
     {
     case MD_4231:
     case MD_4231A:
-    case MD_C930:
-    case MD_IWAVE:
     case MD_1845:
       devc->supported_devices = MODE2_MIXER_DEVICES;
       break;
 
+    case MD_C930:
+      devc->supported_devices = C930_MIXER_DEVICES;
+      devc->mix_devices = &(c930_mix_devices[0]);
+      break;
+
+    case MD_IWAVE:
+      devc->supported_devices = MODE3_MIXER_DEVICES;
+      devc->mix_devices = &(iwave_mix_devices[0]);
+      break;
+
     case MD_4232:
       devc->supported_devices = MODE3_MIXER_DEVICES;
       break;
@@ -458,10 +500,14 @@ ad1848_mixer_reset (ad1848_info * devc)
     }
 
   devc->supported_rec_devices = MODE1_REC_DEVICES;
+  devc->orig_devices = devc->supported_devices;
+  devc->orig_rec_devices = devc->supported_rec_devices;
+
+  devc->levels = load_mixer_volumes (name, default_mixer_levels, 1);
 
   for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
     if (devc->supported_devices & (1 << i))
-      ad1848_mixer_set (devc, i, default_mixer_levels[i]);
+      ad1848_mixer_set (devc, i, devc->levels[i]);
   ad1848_set_recmask (devc, SOUND_MASK_MIC);
 }
 
@@ -472,16 +518,19 @@ ad1848_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
+      int             val;
 
       if (_IOC_DIR (cmd) & _IOC_WRITE)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
-           return snd_ioctl_return ((int *) arg, ad1848_set_recmask (devc, get_user ((int *) arg)));
+           get_user (val, (int *) arg);
+           return ioctl_out (arg, ad1848_set_recmask (devc, val));
            break;
 
          default:
-           return snd_ioctl_return ((int *) arg, ad1848_mixer_set (devc, cmd & 0xff, get_user ((int *) arg)));
+           get_user (val, (int *) arg);
+           return ioctl_out (arg, ad1848_mixer_set (devc, cmd & 0xff, val));
          }
       else
        switch (cmd & 0xff)     /*
@@ -490,31 +539,34 @@ ad1848_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
          {
 
          case SOUND_MIXER_RECSRC:
-           return snd_ioctl_return ((int *) arg, devc->recmask);
+           return ioctl_out (arg, devc->recmask);
            break;
 
          case SOUND_MIXER_DEVMASK:
-           return snd_ioctl_return ((int *) arg, devc->supported_devices);
+           return ioctl_out (arg, devc->supported_devices);
            break;
 
          case SOUND_MIXER_STEREODEVS:
-           return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
+           if (devc->model == MD_C930)
+             return ioctl_out (arg, devc->supported_devices);
+           else
+             return ioctl_out (arg, devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
            break;
 
          case SOUND_MIXER_RECMASK:
-           return snd_ioctl_return ((int *) arg, devc->supported_rec_devices);
+           return ioctl_out (arg, devc->supported_rec_devices);
            break;
 
          case SOUND_MIXER_CAPS:
-           return snd_ioctl_return ((int *) arg, SOUND_CAP_EXCL_INPUT);
+           return ioctl_out (arg, SOUND_CAP_EXCL_INPUT);
            break;
 
          default:
-           return snd_ioctl_return ((int *) arg, ad1848_mixer_get (devc, cmd & 0xff));
+           return ioctl_out (arg, ad1848_mixer_get (devc, cmd & 0xff));
          }
     }
   else
-    return -(EINVAL);
+    return -EINVAL;
 }
 
 static int
@@ -560,7 +612,7 @@ ad1848_set_speed (int dev, int arg)
 
   n = sizeof (speed_table) / sizeof (speed_struct);
 
-  if (arg == 0)
+  if (arg <= 0)
     return devc->speed;
 
   if (devc->model == MD_1845)  /* AD1845 has different timer than others */
@@ -730,7 +782,7 @@ ad1848_open (int dev, int mode)
   unsigned long   flags;
 
   if (dev < 0 || dev >= num_audiodevs)
-    return -(ENXIO);
+    return -ENXIO;
 
   devc = (ad1848_info *) audio_devs[dev]->devc;
 
@@ -740,7 +792,7 @@ ad1848_open (int dev, int mode)
   if (devc->opened)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   devc->dual_dma = 0;
@@ -788,7 +840,7 @@ ad1848_close (int dev)
 static int
 ad1848_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -828,8 +880,7 @@ ad1848_output_block (int dev, unsigned long buf, int count, int intrflag, int dm
   save_flags (flags);
   cli ();
 
-  /* ad_write (devc, 9, ad_read (devc, 9) & ~ 0x01); / * Playback disable */
-  ad1848_halt (dev);
+  ad1848_halt_output (dev);
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
 
   ad_write (devc, 15, (unsigned char) (cnt & 0xff));
@@ -880,8 +931,7 @@ ad1848_start_input (int dev, unsigned long buf, int count, int intrflag, int dma
 
   if (dma_restart)
     {
-      /* ad1848_halt (dev); */
-      ad_write (devc, 9, ad_read (devc, 9) & ~0x02);   /* Capture disable */
+      ad1848_halt_input (dev);
       DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
     }
 
@@ -911,6 +961,25 @@ ad1848_prepare_for_output (int dev, int bsize, int bcount)
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
   ad_mute (devc);
+  {
+/*
+ * This code fragment ensures that the playback FIFO is empty before
+ * setting the codec for playback. Enabling playback for a moment should
+ * be enough to do that.
+ */
+    int             tmout;
+
+    ad_write (devc, 9, ad_read (devc, 9) | 0x01);      /* Enable playback */
+    disable_dma (audio_devs[dev]->dmachan1);
+    for (tmout = 0; tmout < 1000000; tmout++)
+      if (ad_read (devc, 11) & 0x10)   /* DRQ active */
+       if (tmout > 10000)
+         break;
+    ad_write (devc, 9, ad_read (devc, 9) & ~0x01);     /* Stop playback */
+
+    enable_dma (audio_devs[dev]->dmachan1);
+    devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+  }
 
   return ad1848_prepare_for_IO (dev, bsize, bcount);
 }
@@ -943,13 +1012,6 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
 
   old_fs = ad_read (devc, 8);
 
-  if (devc->model != MD_4232)
-    if (fs == old_fs)          /* No change */
-      {
-       restore_flags (flags);
-       devc->xfer_count = 0;
-       return 0;
-      }
 
   ad_enter_MCE (devc);         /* Enables changes to the format select reg */
 
@@ -963,9 +1025,12 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
   /*
    * Write to I8 starts resynchronization. Wait until it completes.
    */
-  timeout = 10000;
-  while (timeout > 0 && inb (devc->base) == 0x80)
-    timeout--;
+  timeout = 0;
+  while (timeout < 100 && inb (devc->base) != 0x80)
+    timeout++;
+  timeout = 0;
+  while (timeout < 10000 && inb (devc->base) == 0x80)
+    timeout++;
 
   /*
      * If mode >= 2 (CS4231), set I28 also. It's the capture format register.
@@ -975,12 +1040,15 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
       ad_write (devc, 28, fs);
 
       /*
-         * Write to I28 starts resynchronization. Wait until it completes.
+       * Write to I28 starts resynchronization. Wait until it completes.
        */
-      timeout = 10000;
-      while (timeout > 0 && inb (devc->base) == 0x80)
-       timeout--;
+      timeout = 0;
+      while (timeout < 100 && inb (devc->base) != 0x80)
+       timeout++;
 
+      timeout = 0;
+      while (timeout < 10000 && inb (devc->base) == 0x80)
+       timeout++;
     }
 
   if (devc->model == MD_4232)
@@ -1020,6 +1088,7 @@ ad1848_halt (int dev)
 
   if (bits & 0x02)
     ad1848_halt_input (dev);
+  devc->audio_mode = 0;
 }
 
 static void
@@ -1028,31 +1097,31 @@ ad1848_halt_input (int dev)
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
 
+  if (!(ad_read (devc, 9) & 0x02))
+    return;                    /* Capture not enabled */
+
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
 
-  if (devc->model == MD_4232)  /* Use applied black magic */
-    {
-      int             tmout;
+  {
+    int             tmout;
 
-      disable_dma (audio_devs[dev]->dmachan1);
+    disable_dma (audio_devs[dev]->dmachan1);
 
-      for (tmout = 0; tmout < 100000; tmout++)
-       if (ad_read (devc, 11) & 0x10)
-         break;
-      ad_write (devc, 9, ad_read (devc, 9) & ~0x01);   /* Stop playback */
+    for (tmout = 0; tmout < 100000; tmout++)
+      if (ad_read (devc, 11) & 0x10)
+       break;
+    ad_write (devc, 9, ad_read (devc, 9) & ~0x02);     /* Stop capture */
 
-      enable_dma (audio_devs[dev]->dmachan1);
-      restore_flags (flags);
-      return;
-    }
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x02);       /* Stop capture */
+    enable_dma (audio_devs[dev]->dmachan1);
+    devc->audio_mode &= ~PCM_ENABLE_INPUT;
+  }
 
 
-  outb (0, io_Status (devc));  /* Clear interrupt status */
-  outb (0, io_Status (devc));  /* Clear interrupt status */
+  outb ((0), io_Status (devc));        /* Clear interrupt status */
+  outb ((0), io_Status (devc));        /* Clear interrupt status */
 
   devc->audio_mode &= ~PCM_ENABLE_INPUT;
 
@@ -1065,30 +1134,30 @@ ad1848_halt_output (int dev)
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
 
+  if (!(ad_read (devc, 9) & 0x01))
+    return;                    /* Playback not enabled */
+
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
-  if (devc->model == MD_4232)  /* Use applied black magic */
-    {
-      int             tmout;
+  {
+    int             tmout;
 
-      disable_dma (audio_devs[dev]->dmachan1);
+    disable_dma (audio_devs[dev]->dmachan1);
 
-      for (tmout = 0; tmout < 100000; tmout++)
-       if (ad_read (devc, 11) & 0x10)
-         break;
-      ad_write (devc, 9, ad_read (devc, 9) & ~0x01);   /* Stop playback */
+    for (tmout = 0; tmout < 100000; tmout++)
+      if (ad_read (devc, 11) & 0x10)
+       break;
+    ad_write (devc, 9, ad_read (devc, 9) & ~0x01);     /* Stop playback */
 
-      enable_dma (audio_devs[dev]->dmachan1);
-      restore_flags (flags);
-      return;
-    }
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x01);       /* Stop playback */
+    enable_dma (audio_devs[dev]->dmachan1);
+    devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+  }
 
 
-  outb (0, io_Status (devc));  /* Clear interrupt status */
-  outb (0, io_Status (devc));  /* Clear interrupt status */
+  outb ((0), io_Status (devc));        /* Clear interrupt status */
+  outb ((0), io_Status (devc));        /* Clear interrupt status */
 
   devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
 
@@ -1112,20 +1181,20 @@ ad1848_trigger (int dev, int state)
   if (state & PCM_ENABLE_OUTPUT)
     tmp |= 0x01;
 
-  if (!(state & PCM_ENABLE_OUTPUT) && old & 0x01);
   ad_mute (devc);
 
   ad_write (devc, 9, tmp);
 
-  if (state & PCM_ENABLE_OUTPUT && !(old & 0x01));
   ad_unmute (devc);
 
   restore_flags (flags);
 }
 
-int
-ad1848_detect (int io_base, int *ad_flags, int *osp)
+void
+ad1848_init_hw (ad1848_info * devc)
 {
+  int             i;
+
   /*
    * Initial values for the indirect registers of CS4248/AD1848.
    */
@@ -1139,6 +1208,64 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   };
 
+
+  for (i = 0; i < 16; i++)
+    ad_write (devc, i, init_values[i]);
+
+
+  ad_mute (devc);              /* Initialize some variables */
+  ad_unmute (devc);            /* Leave it unmuted now */
+
+  if (devc->model > MD_1848)
+    {
+      ad_write (devc, 12, ad_read (devc, 12) | 0x40);  /* Mode2 = enabled */
+
+      if (devc->model == MD_IWAVE)
+       ad_write (devc, 12, 0x6c);      /* Select codec mode 3 */
+
+      for (i = 16; i < 32; i++)
+       ad_write (devc, i, init_values[i]);
+
+    }
+
+  if (devc->model > MD_1848)
+    {
+      if (devc->audio_flags & DMA_DUPLEX)
+       ad_write (devc, 9, ad_read (devc, 9) & ~0x04);  /* Dual DMA mode */
+      else
+       ad_write (devc, 9, ad_read (devc, 9) | 0x04);   /* Single DMA mode */
+
+      if (devc->model == MD_1845)
+       ad_write (devc, 27, ad_read (devc, 27) | 0x08);         /* Alternate freq select enabled */
+
+      if (devc->model == MD_IWAVE)
+       {                       /* Some magic Interwave specific initialization */
+         ad_write (devc, 12, 0x6c);    /* Select codec mode 3 */
+         ad_write (devc, 17, 0xc2);    /* Alternate feature enable */
+       }
+    }
+  else
+    {
+      devc->audio_flags &= ~DMA_DUPLEX;
+      ad_write (devc, 9, ad_read (devc, 9) | 0x04);    /* Single DMA mode */
+    }
+
+  outb ((0), io_Status (devc));        /* Clear pending interrupts */
+
+  /*
+   * Toggle the MCE bit. It completes the initialization phase.
+   */
+
+  ad_enter_MCE (devc);         /* In case the bit was off */
+  ad_leave_MCE (devc);
+
+  ad1848_mixer_reset (devc);
+}
+
+int
+ad1848_detect (int io_base, int *ad_flags, int *osp)
+{
+
   unsigned char   tmp;
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
   unsigned char   tmp1 = 0xff, tmp2 = 0xff;
@@ -1153,8 +1280,10 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
   if (ad_flags)
     {
       if (*ad_flags == 0x12345678)
-       interwave = 1;
-      *ad_flags = 0;
+       {
+         interwave = 1;
+         *ad_flags = 0;
+       }
     }
 
   if (nr_ad1848_devs >= MAX_AUDIO_DEV)
@@ -1176,7 +1305,7 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
   devc->opened = 0;
   devc->chip_name = "AD1848";
   devc->model = MD_1848;       /* AD1848 or CS4248 */
-  devc->osp = osp;
+  devc->levels = NULL;
   devc->debug_flag = 0;
 
   /*
@@ -1190,6 +1319,20 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
    */
 
   DDB (printk ("ad1848_detect() - step A\n"));
+
+/*
+ * Wait for the device to stop initialization
+ */
+  /* outb(( 0x0b),  devc->base); */
+
+  for (i = 0; i < 10000000; i++)
+    {
+      unsigned char   x = inb (devc->base);
+
+      if (x == 0xff || !(x & 0x80))
+       break;
+    }
+
   if ((inb (devc->base) & 0x80) != 0x00)       /* Not a AD1848 */
     {
       DDB (printk ("ad1848 detect error - step A (%02x)\n",
@@ -1284,7 +1427,14 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
    */
 
   DDB (printk ("ad1848_detect() - step G\n"));
-  ad_write (devc, 12, 0x40);   /* Set mode2, clear 0x80 */
+
+  if (ad_flags && *ad_flags == 400)
+    *ad_flags = 0;
+  else
+    ad_write (devc, 12, 0x40); /* Set mode2, clear 0x80 */
+
+  if (ad_flags)
+    *ad_flags = 0;
 
   tmp1 = ad_read (devc, 12);
   if (tmp1 & 0x80)
@@ -1419,22 +1569,6 @@ ad1848_detect (int io_base, int *ad_flags, int *osp)
   if (devc->model == MD_1848 && ad1847_flag)
     devc->chip_name = "AD1847";
 
-  for (i = 0; i < 16; i++)
-    ad_write (devc, i, init_values[i]);
-
-  ad_mute (devc);              /* Initialize some variables */
-  ad_unmute (devc);            /* Leave it unmuted now */
-
-  if (devc->model > MD_1848)
-    {
-      ad_write (devc, 12, ad_read (devc, 12) | 0x40);  /* Mode2 = enabled */
-
-      if (devc->model == MD_IWAVE)
-       ad_write (devc, 12, 0x6c);      /* Select codec mode 3 */
-
-      for (i = 16; i < 32; i++)
-       ad_write (devc, i, init_values[i]);
-    }
 
   return 1;
 }
@@ -1454,7 +1588,6 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
 
   ad1848_info    *devc = &dev_info[nr_ad1848_devs];
 
-  int             audio_flags = DMA_AUTOMODE;
 
 
   request_region (devc->base, 4, devc->chip_name);
@@ -1462,37 +1595,9 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
   devc->irq = (irq > 0) ? irq : 0;
   devc->opened = 0;
   devc->timer_ticks = 0;
-  devc->osp = osp;
-
-  if (devc->model > MD_1848)
-    {
-      if (dma_capture == dma_playback || dma_capture == -1 || dma_playback == -1)
-       {
-         ad_write (devc, 9, ad_read (devc, 9) | 0x04);         /* Single DMA mode */
-         audio_flags &= ~DMA_DUPLEX;
-       }
-      else
-       {
-         ad_write (devc, 9, ad_read (devc, 9) & ~0x04);        /* Dual DMA mode */
-         audio_flags |= DMA_DUPLEX;
-       }
-
-      if (devc->model == MD_1845)
-       ad_write (devc, 27, ad_read (devc, 27) | 0x08);         /* Alternate freq select enabled */
-
-      if (devc->model == MD_IWAVE)
-       {                       /* Some magic Interwave specific initialization */
-         ad_write (devc, 12, 0x6c);    /* Select codec mode 3 */
-         ad_write (devc, 17, 0xc2);    /* Alternate feature enable */
-       }
-    }
-  else
-    {
-      audio_flags &= ~DMA_DUPLEX;
-      ad_write (devc, 9, ad_read (devc, 9) | 0x04);    /* Single DMA mode */
-    }
-
-  outb (0, io_Status (devc));  /* Clear pending interrupts */
+  devc->dma1 = dma_playback;
+  devc->dma2 = dma_capture;
+  devc->audio_flags = DMA_AUTOMODE;
 
   if (name != NULL && name[0] != 0)
     sprintf (dev_name,
@@ -1504,14 +1609,22 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
   conf_printf2 (dev_name,
                devc->base, devc->irq, dma_playback, dma_capture);
 
-  if (devc->model == MD_1848)
-    audio_flags |= DMA_HARDSTOP;
+  if (devc->model == MD_1848 || devc->model == MD_C930)
+    devc->audio_flags |= DMA_HARDSTOP;
+
+  if (devc->model > MD_1848)
+    {
+      if (devc->dma1 == devc->dma2 || devc->dma2 == -1 || devc->dma1 == -1)
+       devc->audio_flags &= ~DMA_DUPLEX;
+      else
+       devc->audio_flags |= DMA_DUPLEX;
+    }
 
   if ((my_dev = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
                                        dev_name,
                                        &ad1848_audio_driver,
                                        sizeof (struct audio_driver),
-                                       audio_flags,
+                                       devc->audio_flags,
                                        ad_format_mask[devc->model],
                                        devc,
                                        dma_playback,
@@ -1520,17 +1633,21 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
       return;
     }
 
+  nr_ad1848_devs++;
+
+  ad1848_init_hw (devc);
+
   if (irq > 0)
     {
       irq2dev[irq] = devc->dev_no = my_dev;
       if (snd_set_irq_handler (devc->irq, ad1848_interrupt,
                               "SoundPort",
-                              devc->osp) < 0)
+                              NULL) < 0)
        {
          printk ("ad1848: IRQ in use\n");
        }
 
-      if (devc->model != MD_1848)
+      if (devc->model != MD_1848 && devc->model != MD_C930)
        {
          int             x;
          unsigned char   tmp = ad_read (devc, 16);
@@ -1547,17 +1664,20 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
          if (devc->timer_ticks == 0)
            printk ("ad1848: Interrupt test failed (IRQ%d)\n", devc->irq);
          else
-           devc->irq_ok = 1;
+           {
+             DDB (printk ("Interrupt test OK\n"));
+             devc->irq_ok = 1;
+           }
        }
       else
        devc->irq_ok = 1;       /* Couldn't test. assume it's OK */
     }
   else if (irq < 0)
     irq2dev[-irq] = devc->dev_no = my_dev;
-  nr_ad1848_devs++;
 
 #ifdef CONFIG_SEQUENCER
-  if (devc->model != MD_1848 && devc->model != MD_1845 && devc->irq_ok)
+  if (devc->model != MD_1848 &&
+      devc->model != MD_C930 && devc->irq_ok)
     ad1848_tmr_install (my_dev);
 #endif
 
@@ -1571,14 +1691,6 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
          printk ("ad1848.c: Can't allocate DMA%d\n", dma_capture);
     }
 
-  /*
-     * Toggle the MCE bit. It completes the initialization phase.
-   */
-
-  ad_enter_MCE (devc);         /* In case the bit was off */
-  ad_leave_MCE (devc);
-  ad1848_mixer_reset (devc);
-
   if (sound_install_mixer (MIXER_DRIVER_VERSION,
                           dev_name,
                           &ad1848_mixer_operations,
@@ -1589,6 +1701,59 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
     }
 }
 
+void
+ad1848_control (int cmd, int arg)
+{
+  ad1848_info    *devc;
+
+  if (nr_ad1848_devs < 1)
+    return;
+
+  devc = &dev_info[nr_ad1848_devs - 1];
+
+  switch (cmd)
+    {
+    case AD1848_SET_XTAL:      /* Change clock frequency of AD1845 (only ) */
+      if (devc->model != MD_1845)
+       return;
+      ad_enter_MCE (devc);
+      ad_write (devc, 29, (ad_read (devc, 29) & 0x1f) | (arg << 5));
+      ad_leave_MCE (devc);
+      break;
+
+    case AD1848_MIXER_REROUTE:
+      {
+       int             o = (arg >> 8) & 0xff;
+       int             n = arg & 0xff;
+
+       if (n == SOUND_MIXER_NONE)
+         {                     /* Just hide this control */
+           ad1848_mixer_set (devc, o, 0);      /* Shut up it */
+           devc->supported_devices &= ~(1 << o);
+           devc->supported_rec_devices &= ~(1 << o);
+           return;
+         }
+
+       /* Make the mixer control identified by o to appear as n */
+
+       if (o < 0 || o > SOUND_MIXER_NRDEVICES)
+         return;
+       if (n < 0 || n > SOUND_MIXER_NRDEVICES)
+         return;
+       if (!(devc->supported_devices & (1 << o)))
+         return;               /* Not supported */
+
+       devc->mixer_reroute[n] = o;     /* Rename the control */
+       devc->supported_devices &= ~(1 << o);
+       devc->supported_devices |= (1 << n);
+       if (devc->supported_rec_devices & (1 << o))
+         devc->supported_rec_devices |= (1 << n);
+       devc->supported_rec_devices &= ~(1 << o);
+      }
+      break;
+    }
+}
+
 void
 ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
 {
@@ -1629,6 +1794,7 @@ ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
   ad1848_info    *devc;
   int             dev;
   int             alt_stat = 0xff;
+  unsigned char   c930_stat = 0;
 
   if (irq < 0 || irq > 15)
     {
@@ -1655,6 +1821,8 @@ ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
   else
     devc = (ad1848_info *) audio_devs[dev]->devc;
 
+interrupt_again:               /* Jump back here if int status doesn't reset */
+
   status = inb (io_Status (devc));
 
   if (status == 0x80)
@@ -1662,8 +1830,25 @@ ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
 
   if (status & 0x01)
     {
+      if (devc->model == MD_C930)
+       {                       /* 82C930 has interrupt status register in MAD16 register MC11 */
+         unsigned long   flags;
 
-      if (devc->model != MD_1848)
+         save_flags (flags);
+         cli ();
+
+         alt_stat = 0;
+
+         outb ((11), 0xe0e);
+         c930_stat = inb (0xe0f);
+
+         if (c930_stat & 0x04)
+           alt_stat |= 0x10;   /* Playback intr */
+         if (c930_stat & 0x08)
+           alt_stat |= 0x20;   /* Playback intr */
+         restore_flags (flags);
+       }
+      else if (devc->model != MD_1848)
        alt_stat = ad_read (devc, 24);
 
       if (devc->opened && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
@@ -1687,10 +1872,30 @@ ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
        }
     }
 
-  if (devc->model != MD_1848)
+  if (devc->model == MD_C930)
+    {                          /* 82C930 has interrupt status register in MAD16 register MC11 */
+      unsigned long   flags;
+
+      save_flags (flags);
+      cli ();
+
+      outb ((11), 0xe0e);
+      outb ((~c930_stat), 0xe0f);
+      restore_flags (flags);
+    }
+  else if (devc->model != MD_1848)
     ad_write (devc, 24, ad_read (devc, 24) & ~alt_stat);       /* Selective ack */
   else
-    outb (0, io_Status (devc));        /* Clear interrupt status */
+    outb ((0), io_Status (devc));      /* Clear interrupt status */
+
+/*
+ * Sometimes playback or capture interrupts occur while a timer interrupt
+ * is being handled. The interrupt will not be retriggered if we don't
+ * handle it now. Check if an interrupt is still pending and restart
+ * the handler in this case.
+ */
+  if (inb (io_Status (devc)) & 0x01)
+    goto interrupt_again;
 }
 
 /*
@@ -1733,7 +1938,7 @@ init_deskpro (struct address_info *hw_config)
       return 0;
     }
 
-  outb (tmp | 0x04, 0xc44);    /* Select bank 1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank 1 */
   if (inb (0xc44) != 0x04)
     {
       DDB (printk ("init_deskpro: Invalid bank1 signature in port 0xc44\n"));
@@ -1774,9 +1979,9 @@ init_deskpro (struct address_info *hw_config)
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc44 (before): ");
-  outb (tmp & ~0x04, 0xc44);
+  outb ((tmp & ~0x04), 0xc44);
   printk ("%02x ", inb (0xc44));
-  outb (tmp | 0x04, 0xc44);
+  outb ((tmp | 0x04), 0xc44);
   printk ("%02x\n", inb (0xc44));
 #endif
 
@@ -1802,14 +2007,14 @@ init_deskpro (struct address_info *hw_config)
                   hw_config->io_base));
       return 0;
     }
-  outb (tmp & ~0x04, 0xc44);   /* Write to bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Write to bank=0 */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc44 (after): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc44));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc44));
 #endif
 
@@ -1826,23 +2031,23 @@ init_deskpro (struct address_info *hw_config)
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc45 (before): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc45));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc45));
 #endif
 
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
-  outb (0x88, 0xc45);          /* FM base 7:0 = 0x88 */
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
-  outb (0x10, 0xc45);          /* MSS ID = 0x10 (MSS port returns 0x04) */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
+  outb ((0x88), 0xc45);                /* FM base 7:0 = 0x88 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
+  outb ((0x10), 0xc45);                /* MSS ID = 0x10 (MSS port returns 0x04) */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc45 (after): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc45));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc45));
 #endif
 
@@ -1857,23 +2062,23 @@ init_deskpro (struct address_info *hw_config)
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc46 (before): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc46));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc46));
 #endif
 
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
-  outb (0x03, 0xc46);          /* FM base 15:8 = 0x03 */
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
-  outb (0x11, 0xc46);          /* ASIC ID = 0x11 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
+  outb ((0x03), 0xc46);                /* FM base 15:8 = 0x03 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
+  outb ((0x11), 0xc46);                /* ASIC ID = 0x11 */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc46 (after): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc46));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc46));
 #endif
 
@@ -1887,23 +2092,23 @@ init_deskpro (struct address_info *hw_config)
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc47 (before): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc47));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc47));
 #endif
 
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
-  outb (0x7c, 0xc47);          /* FM decode enable bits = 0x7c */
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
-  outb (0x00, 0xc47);          /* Reserved bank1 = 0x00 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
+  outb ((0x7c), 0xc47);                /* FM decode enable bits = 0x7c */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
+  outb ((0x00), 0xc47);                /* Reserved bank1 = 0x00 */
 
 #ifdef DEBUGXL
   /* Debug printing */
   printk ("Port 0xc47 (after): ");
-  outb (tmp & ~0x04, 0xc44);   /* Select bank=0 */
+  outb ((tmp & ~0x04), 0xc44); /* Select bank=0 */
   printk ("%02x ", inb (0xc47));
-  outb (tmp | 0x04, 0xc44);    /* Select bank=1 */
+  outb ((tmp | 0x04), 0xc44);  /* Select bank=1 */
   printk ("%02x\n", inb (0xc47));
 #endif
 
@@ -1915,7 +2120,7 @@ init_deskpro (struct address_info *hw_config)
   printk ("Port 0xc6f (before) = %02x\n", inb (0xc6f));
 #endif
 
-  outb (0x80, 0xc6f);
+  outb ((0x80), 0xc6f);
 
 #ifdef DEBUGXL
   printk ("Port 0xc6f (after) = %02x\n", inb (0xc6f));
@@ -2034,8 +2239,6 @@ attach_ms_sound (struct address_info *hw_config)
   int             dma = hw_config->dma;
   int             dma2 = hw_config->dma2;
 
-  if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, hw_config->osp))
-    return;
 
   if (hw_config->card_subtype == 1)    /* Has no IRQ/DMA registers */
     {
@@ -2055,9 +2258,9 @@ attach_ms_sound (struct address_info *hw_config)
   if (bits == -1)
     return;
 
-  outb (bits | 0x40, config_port);
+  outb ((bits | 0x40), config_port);
   if ((inb (version_port) & 0x40) == 0)
-    printk ("[IRQ Conflict?]");
+    printk ("[MSS: IRQ Conflict?]");
 
 /*
  * Handle the capture DMA channel
@@ -2090,7 +2293,7 @@ attach_ms_sound (struct address_info *hw_config)
   else
     dma2 = dma;
 
-  outb (bits | dma_bits[dma] | dma2_bit, config_port); /* Write IRQ+DMA setup */
+  outb ((bits | dma_bits[dma] | dma2_bit), config_port);       /* Write IRQ+DMA setup */
 
   ad1848_init ("MSS audio codec", hw_config->io_base + 4,
               hw_config->irq,
index 073c14d95bbce1c3b48c11e88b1740435b82e257..809b858bb39951cd0bfa2508fb0c8568766b0370 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
                                         SOUND_MASK_IGAIN | \
                                         SOUND_MASK_PCM | SOUND_MASK_IMIX)
 
-#define MODE2_MIXER_DEVICES            (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_MIC | \
+#define MODE2_MIXER_DEVICES            (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \
+                                        SOUND_MASK_MIC | \
                                         SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \
                                         SOUND_MASK_IGAIN | \
                                         SOUND_MASK_PCM | SOUND_MASK_IMIX)
 
 #define MODE3_MIXER_DEVICES            (MODE2_MIXER_DEVICES | SOUND_MASK_VOLUME)
 
+/* OPTi 82C930 has no IMIX level control, but it can still be selected as an
+ * input
+ */
+#define C930_MIXER_DEVICES     (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | \
+                                SOUND_MASK_MIC | SOUND_MASK_VOLUME | \
+                                SOUND_MASK_LINE3 | \
+                                SOUND_MASK_IGAIN | SOUND_MASK_PCM)
+
 struct mixer_def {
        unsigned int regno: 7;
        unsigned int polarity:1;        /* 0=normal, 1=reversed */
@@ -55,6 +64,7 @@ static char mix_cvt[101] = {
 };
 
 typedef struct mixer_def mixer_ent;
+typedef mixer_ent mixer_ents[2];
 
 /*
  * Most of the mixer entries work in backwards. Setting the polarity field
@@ -68,7 +78,7 @@ typedef struct mixer_def mixer_ent;
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)        \
        {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
 
-mixer_ent mix_devices[32][2] = {
+mixer_ents ad1848_mix_devices[32] = {
 MIX_ENT(SOUND_MIXER_VOLUME,    27, 1, 0, 4,    29, 1, 0, 4),
 MIX_ENT(SOUND_MIXER_BASS,       0, 0, 0, 0,     0, 0, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,     0, 0, 0, 0,     0, 0, 0, 0),
@@ -88,14 +98,59 @@ MIX_ENT(SOUND_MIXER_LINE2,   4, 1, 0, 5,     5, 1, 0, 5),
 MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 0, 5,    19, 1, 0, 5)
 };
 
-static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
+mixer_ents iwave_mix_devices[32] = {
+MIX_ENT(SOUND_MIXER_VOLUME,    25, 1, 0, 5,    27, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_BASS,       0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,     0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,      4, 1, 0, 5,     5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_PCM,        6, 1, 0, 6,     7, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER,   26, 1, 0, 4,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,      18, 1, 0, 5,    19, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_MIC,        0, 0, 5, 1,     1, 0, 5, 1),
+MIX_ENT(SOUND_MIXER_CD,                 2, 1, 0, 5,     3, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_IMIX,      13, 1, 2, 6,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,     0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,     0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN,      0, 0, 0, 4,     1, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_OGAIN,      0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 0, 5,     3, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE2,      4, 1, 0, 5,     5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 0, 5,    19, 1, 0, 5)
+};
+
+/* OPTi 82C930 has somewhat different port addresses.
+ * Note: VOLUME == SPEAKER, SYNTH == LINE2, LINE == LINE3, CD == LINE1
+ * VOLUME, SYNTH, LINE, CD are not enabled above.
+ * MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
+ */
+mixer_ents c930_mix_devices[32] = {
+MIX_ENT(SOUND_MIXER_VOLUME,    22, 1, 0, 5,    23, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_BASS,       0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,     0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,      4, 1, 0, 5,     5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_PCM,        6, 1, 0, 6,     7, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER,   22, 1, 0, 5,     23, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE,      18, 1, 1, 4,    19, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_MIC,        20, 1, 0, 4,    21, 1, 0, 4),
+MIX_ENT(SOUND_MIXER_CD,                 2, 1, 1, 4,     3, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_IMIX,      0, 0, 0, 0,      0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,     0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,     0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN,      0, 0, 0, 4,     1, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_OGAIN,      0, 0, 0, 0,     0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 1, 4,     3, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_LINE2,      4, 1, 1, 4,     5, 1, 1, 4),
+MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 1, 4,    19, 1, 1, 4)
+};
+
+static int default_mixer_levels[32] =
 {
   0x3232,                      /* Master Volume */
   0x3232,                      /* Bass */
   0x3232,                      /* Treble */
   0x4b4b,                      /* FM */
   0x3232,                      /* PCM */
-  0x4b4b,                      /* PC Speaker */
+  0x1515,                      /* PC Speaker */
   0x2020,                      /* Ext Line */
   0x1010,                      /* Mic */
   0x4b4b,                      /* CD */
index 692f43fdb62936e4e7c42ef9e4000e360d2e7db4..a99891f930eff286c0585d75e6dc0b4bdd4eaec0 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -32,7 +32,8 @@ probe_adlib (struct address_info *hw_config)
 
   if (check_region (hw_config->io_base, 4))
     {
-      printk ("\n\nopl3.c: I/O port %x already in use\n\n", hw_config->io_base);
+      DDB (printk ("opl3.c: I/O port %x already in use\n",
+                  hw_config->io_base));
       return 0;
     }
 
index 78f32ecc1501d79cbcc1e7e78542d6e55232d834..6449ac80a4aaca8aafaabc2dc0e41c5d5e52b0ba 100644 (file)
@@ -349,7 +349,7 @@ static struct orVals orDMA[] =
 };
 
 /*
- * Buffers to store audio card information
+ * Buffers to store audio card informations
  */
 static char     AudioExcelName[CARDNAMELEN + 1];
 static char     AudioExcelVersion[CARDVERLEN + 1];
@@ -403,9 +403,9 @@ ResetBoard (int port)
   /*
      * Reset DSP
    */
-  outb (1, (port + DSP_RESET));
+  outb ((1), (port + DSP_RESET));
   tenmicrosec ();
-  outb (0, (port + DSP_RESET));
+  outb ((0), (port + DSP_RESET));
   tenmicrosec ();
   tenmicrosec ();
   return CheckDSPOkay (port);
@@ -425,7 +425,7 @@ WriteDSPCommand (int port, int cmd)
        */
       if (!(ret & 0x80))
        {
-         outb (cmd, port + DSP_COMMAND);
+         outb ((cmd), port + DSP_COMMAND);
          return 0;
        }
     }
@@ -706,7 +706,7 @@ InitAEDSP16_SBPRO (struct address_info *hw_config)
      * can allow me to release the requested region.
    */
   if (!(ae_init & INIT_MPU401))
-    request_region (hw_config->io_base, 0x0f, "AEDSP16 (SBPro)");
+    request_region (hw_config->io_base, 0x0f, "aedsp16 (sbpro)");
 #endif
 
   ae_init |= INIT_SBPRO;
@@ -774,11 +774,11 @@ InitAEDSP16_MSS (struct address_info *hw_config)
      * can allow me to release the requested region. So when unloading
      * and then reloading it, we are going to have some nice Oops!
    */
-  request_region (hw_config->io_base, 0x08, "AEDSP16 (MSS)");
+  request_region (hw_config->io_base, 0x08, "aedsp16 (mss)");
 #endif
 
   if (!(ae_init & INIT_MPU401))
-    request_region (AEDSP16_BASE, 0x0f, "AEDSP16 (SBPro)");
+    request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
 
   ae_init |= INIT_MSS;
   return 0;
@@ -837,11 +837,11 @@ InitAEDSP16_MPU401 (struct address_info *hw_config)
      * request any region because there is not a uninit routine that
      * can allow me to release the requested region.
    */
-  request_region (hw_config->io_base, 0x02, "AEDSP16 (mpu401)");
+  request_region (hw_config->io_base, 0x02, "aedsp16 (mpu401)");
 #endif
 
   if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
-    request_region (AEDSP16_BASE, 0x0f, "AEDSP16 (SBPro)");
+    request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
 
   ae_init |= INIT_MPU401;
   return 0;
index 45f2bedf4a6b10675333bf2633d70e9e3c889618..4ce28d0d10edc38713cc1f94c8475c74c36f623a 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -31,11 +31,13 @@ static int      dev_nblock[MAX_AUDIO_DEV];  /* 1 if in nonblocking mode */
 #define                AM_WRITE        1
 #define        AM_READ         2
 
+
 static int      audio_format[MAX_AUDIO_DEV];
 static int      local_conversion[MAX_AUDIO_DEV];
 
+#define CNV_MU_LAW     0x00000001
 static int
-set_format (int dev, long fmt)
+set_format (int dev, int fmt)
 {
   if (fmt != AFMT_QUERY)
     {
@@ -46,12 +48,12 @@ set_format (int dev, long fmt)
        if (fmt == AFMT_MU_LAW)
          {
            fmt = AFMT_U8;
-           local_conversion[dev] = AFMT_MU_LAW;
+           local_conversion[dev] = CNV_MU_LAW;
          }
        else
          fmt = AFMT_U8;        /* This is always supported */
 
-      audio_format[dev] = DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) fmt, 1);
+      audio_format[dev] = audio_devs[dev]->d->set_bits (dev, fmt);
     }
 
   if (local_conversion[dev])   /* This shadows the HW format */
@@ -64,7 +66,7 @@ int
 audio_open (int dev, struct fileinfo *file)
 {
   int             ret;
-  long            bits;
+  int             bits;
   int             dev_type = dev & 0x0f;
   int             mode = file->mode & O_ACCMODE;
 
@@ -75,6 +77,9 @@ audio_open (int dev, struct fileinfo *file)
   else
     bits = 8;
 
+  if (dev < 0 || dev >= num_audiodevs)
+    return -ENXIO;
+
   if ((ret = DMAbuf_open (dev, mode)) < 0)
     return ret;
 
@@ -90,11 +95,8 @@ audio_open (int dev, struct fileinfo *file)
 
   local_conversion[dev] = 0;
 
-  if (DMAbuf_ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1) != bits)
+  if (audio_devs[dev]->d->set_bits (dev, bits) != bits)
     {
-      printk ("audio: Can't set number of bits on device %d\n", dev);
-      audio_release (dev, file);
-      return -(ENXIO);
     }
 
   if (dev_type == SND_DEV_AUDIO)
@@ -107,6 +109,7 @@ audio_open (int dev, struct fileinfo *file)
   audio_mode[dev] = AM_NONE;
   dev_nblock[dev] = 0;
 
+
   return ret;
 }
 
@@ -119,6 +122,13 @@ sync_output (int dev)
 
   if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
     {
+      int             i, n = buf_size & 3;
+
+      if (n)                   /* Not 4 byte aligned */
+       {
+         for (i = 0; i < n; i++)
+           dma_buf[buf_ptr++] = dmap->neutral_byte;
+       }
       DMAbuf_start_output (dev, buf_no, buf_ptr);
     }
 
@@ -130,11 +140,10 @@ sync_output (int dev)
 
   for (i = dmap->qlen + 1; i < dmap->nbufs; i++)
     {
+      p = (p + 1) % dmap->nbufs;
       memset (dmap->raw_buf + p * dmap->fragment_size,
              dmap->neutral_byte,
              dmap->fragment_size);
-
-      p = (p + 1) % dmap->nbufs;
     }
 
   dmap->flags |= DMA_CLEAN;
@@ -225,7 +234,7 @@ audio_write (int dev, struct fileinfo *file, const char *buf, int count)
                                            dev_nblock[dev])) < 0)
            {
              /* Handle nonblocking mode */
-             if (dev_nblock[dev] && buf_no == -(EAGAIN))
+             if (dev_nblock[dev] && buf_no == -EAGAIN)
                return p;       /* No more space. Return # of accepted bytes */
              return buf_no;
            }
@@ -236,17 +245,18 @@ audio_write (int dev, struct fileinfo *file, const char *buf, int count)
       if (l > (buf_size - buf_ptr))
        l = (buf_size - buf_ptr);
 
-      if (!audio_devs[dev]->d->copy_from_user)
+
+      if (!audio_devs[dev]->d->copy_user)
        {                       /*
                                 * No device specific copy routine
                                 */
          copy_from_user (&dma_buf[buf_ptr], &(buf)[p], l);
        }
       else
-       audio_devs[dev]->d->copy_from_user (dev,
-                                           dma_buf, buf_ptr, buf, p, l);
+       audio_devs[dev]->d->copy_user (dev,
+                                      dma_buf, buf_ptr, buf, p, l);
 
-      if (local_conversion[dev] == AFMT_MU_LAW)
+      if (local_conversion[dev] & CNV_MU_LAW)
        {
          /*
           * This just allows interrupts while the conversion is running
@@ -303,7 +313,7 @@ audio_read (int dev, struct fileinfo *file, char *buf, int count)
        {
          /* Nonblocking mode handling. Return current # of bytes */
 
-         if (dev_nblock[dev] && buf_no == -(EAGAIN))
+         if (dev_nblock[dev] && buf_no == -EAGAIN)
            return p;
 
          return buf_no;
@@ -316,7 +326,7 @@ audio_read (int dev, struct fileinfo *file, char *buf, int count)
        * Insert any local processing here.
        */
 
-      if (local_conversion[dev] == AFMT_MU_LAW)
+      if (local_conversion[dev] & CNV_MU_LAW)
        {
          /*
           * This just allows interrupts while the conversion is running
@@ -326,7 +336,11 @@ audio_read (int dev, struct fileinfo *file, char *buf, int count)
          translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
        }
 
-      copy_to_user (&(buf)[p], dmabuf, l);
+      {
+       char           *fixit = dmabuf;
+
+       copy_to_user (&(buf)[p], fixit, l);
+      };
 
       DMAbuf_rmchars (dev, buf_no, l);
 
@@ -341,6 +355,9 @@ int
 audio_ioctl (int dev, struct fileinfo *file,
             unsigned int cmd, caddr_t arg)
 {
+  int             val;
+
+/* printk("audio_ioctl(%x, %x)\n", cmd, arg); */
 
   dev = dev >> 4;
 
@@ -351,7 +368,7 @@ audio_ioctl (int dev, struct fileinfo *file,
       else
        printk ("/dev/dsp%d: No coprocessor for this device\n", dev);
 
-      return -(ENXIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
@@ -361,33 +378,39 @@ audio_ioctl (int dev, struct fileinfo *file,
          return 0;
 
        sync_output (dev);
-       return DMAbuf_ioctl (dev, cmd, arg, 0);
+       DMAbuf_sync (dev);
+       DMAbuf_reset (dev);
+       return 0;
        break;
 
       case SNDCTL_DSP_POST:
        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
          return 0;
+       audio_devs[dev]->dmap_out->flags |= DMA_POST;
        sync_output (dev);
+       DMAbuf_ioctl (dev, SNDCTL_DSP_POST, 0, 1);
        return 0;
        break;
 
       case SNDCTL_DSP_RESET:
        audio_mode[dev] = AM_NONE;
-       return DMAbuf_ioctl (dev, cmd, arg, 0);
+       DMAbuf_reset (dev);
+       return 0;
        break;
 
       case SNDCTL_DSP_GETFMTS:
-       return snd_ioctl_return ((int *) arg, audio_devs[dev]->format_mask | AFMT_MU_LAW);
+       return ioctl_out (arg, audio_devs[dev]->format_mask);
        break;
 
       case SNDCTL_DSP_SETFMT:
-       return snd_ioctl_return ((int *) arg, set_format (dev, get_user ((int *) arg)));
+       get_user (val, (int *) arg);
+       return ioctl_out (arg, set_format (dev, val));
 
       case SNDCTL_DSP_GETISPACE:
        if (!(audio_devs[dev]->open_mode & OPEN_READ))
          return 0;
        if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
-         return -(EBUSY);
+         return -EBUSY;
 
        {
          audio_buf_info  info;
@@ -397,7 +420,11 @@ audio_ioctl (int dev, struct fileinfo *file,
          if (err < 0)
            return err;
 
-         copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+         {
+           char           *fixit = (char *) &info;
+
+           copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+         };
          return 0;
        }
 
@@ -405,7 +432,7 @@ audio_ioctl (int dev, struct fileinfo *file,
        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
          return -EPERM;
        if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
-         return -(EBUSY);
+         return -EBUSY;
 
        {
          audio_buf_info  info;
@@ -420,7 +447,11 @@ audio_ioctl (int dev, struct fileinfo *file,
          if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
            info.bytes -= buf_ptr;
 
-         copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+         {
+           char           *fixit = (char *) &info;
+
+           copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+         };
          return 0;
        }
 
@@ -447,18 +478,64 @@ audio_ioctl (int dev, struct fileinfo *file,
 
          info |= DSP_CAP_MMAP;
 
-         copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+         {
+           char           *fixit = (char *) &info;
+
+           copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+         };
          return 0;
        }
        break;
 
+      case SOUND_PCM_WRITE_RATE:
+       get_user (val, (int *) arg);
+       return ioctl_out (arg, audio_devs[dev]->d->set_speed (dev, val));
+
+      case SOUND_PCM_READ_RATE:
+       return ioctl_out (arg, audio_devs[dev]->d->set_speed (dev, 0));
+
+      case SNDCTL_DSP_STEREO:
+       {
+         int             n;
+
+         get_user (n, (int *) arg);
+         if (n > 1)
+           {
+             printk ("sound: SNDCTL_DSP_STEREO called with invalid argument %d\n",
+                     n);
+             return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, n));
+           }
+
+         if (n < 0)
+           return -EINVAL;
+
+         return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, n + 1) - 1);
+       }
+
+      case SOUND_PCM_WRITE_CHANNELS:
+       get_user (val, (int *) arg);
+       return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, val));
+
+      case SOUND_PCM_READ_CHANNELS:
+       return ioctl_out (arg, audio_devs[dev]->d->set_channels (dev, 0));
+
+      case SOUND_PCM_READ_BITS:
+       return ioctl_out (arg, audio_devs[dev]->d->set_bits (dev, 0));
+
+      case SNDCTL_DSP_SETDUPLEX:
+       if (audio_devs[dev]->flags & DMA_DUPLEX)
+         return 0;
+       else
+         return -EIO;
+       break;
+
       default:
        return DMAbuf_ioctl (dev, cmd, arg, 0);
       }
 }
 
 void
-audio_init (void)
+audio_init_devices (void)
 {
   /*
      * NOTE! This routine could be called several times during boot.
@@ -466,7 +543,7 @@ audio_init (void)
 }
 
 int
-audio_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+audio_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   char           *dma_buf;
   int             buf_no, buf_ptr, buf_size;
index 2a64fd8d2b24fbd6f1ae58c8a529b3cf14f6d2ab..765f948bc9a10ff8effcaf262983d96e88c3790a 100644 (file)
@@ -1,16 +1,16 @@
 /*
  *     PnP soundcard support is not included in this version.
  *
- *       AEDSP16 will not work without significant changes.
+ *     There is a separately distributed patch available for AEDSP16.
  */
-#define DISABLED_OPTIONS       (B(OPT_SPNP)|B(OPT_AEDSP16)|B(OPT_UNUSED1)|B(OPT_UNUSED2))
+#define DISABLED_OPTIONS       (B(OPT_SPNP)|B(OPT_AEDSP16)|B(OPT_UNUSED1)|B(OPT_UNUSED2)|B(OPT_UNUSED3)|B(OPT_UNUSED4)|B(OPT_UNUSED5))
 /*
  * sound/configure.c  - Configuration program for the Linux Sound Driver
  */
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 #define OPT_UNUSED1    16
 #define OPT_UNUSED2    17
 #define OPT_AEDSP16     18
-#define OPT_AUDIO      19
-#define OPT_MIDI_AUTO  20
-#define OPT_MIDI       21
+#define OPT_UNUSED3    19
+#define OPT_UNUSED4    20
+#define OPT_UNUSED5    21
 #define OPT_YM3812_AUTO        22
 #define OPT_YM3812     23
 #define OPT_LAST       23      /* Last defined OPT number */
 
-#define DUMMY_OPTS (B(OPT_MIDI_AUTO)|B(OPT_YM3812_AUTO))
+#define DUMMY_OPTS (B(OPT_YM3812_AUTO))
 
-#define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_GUS)| \
+#define ANY_DEVS (B(OPT_SB)|B(OPT_PAS)|B(OPT_GUS)| \
                  B(OPT_MPU401)|B(OPT_PSS)|B(OPT_GUS16)|B(OPT_GUSMAX)| \
                  B(OPT_MSS)|B(OPT_SSCAPE)|B(OPT_UART6850)|B(OPT_TRIX)| \
-                 B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI)|B(OPT_ADLIB))
-#define AUDIO_CARDS (B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_GUS) | \
-               B (OPT_MSS) | B (OPT_GUS16) | B (OPT_GUSMAX) | B (OPT_TRIX) | \
-               B (OPT_SSCAPE)| B(OPT_MAD16) | B(OPT_CS4232))
+                 B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI)|B(OPT_ADLIB)| \
+                 B(OPT_SPNP))
 #define MPU_DEVS (B(OPT_PSS)|\
                  B(OPT_CS4232)|B(OPT_SPNP)|B(OPT_MAUI)|B(OPT_SSCAPE))
-#define UART401_DEVS (SBDSP_DEVS|B(OPT_TRIX)|B(OPT_MAD16))
-#define MIDI_CARDS (MPU_DEVS | UART401_DEVS | \
-                   B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_MPU401) | \
-                   B (OPT_GUS) | B (OPT_TRIX) | B (OPT_SSCAPE)|B(OPT_MAD16) | \
-                   B (OPT_CS4232)|B(OPT_MAUI))
+#define UART401_DEVS (SBDSP_DEVS|B(OPT_TRIX)|B(OPT_MAD16)|B(OPT_SPNP))
+#define NON_AUDIO_CARDS (B(OPT_ADLIB)|B(OPT_MPU401)|B(OPT_UART6850)|B(OPT_MAUI))
+#define AUDIO_CARDS (ANY_DEVS & ~NON_AUDIO_CARDS)
+#define MIDI_CARDS (ANY_DEVS & ~(B(OPT_ADLIB)|B(OPT_MSS)))
 #define AD1848_DEVS (B(OPT_GUS16)|B(OPT_MSS)|B(OPT_PSS)|B(OPT_GUSMAX)|\
                     B(OPT_SSCAPE)|B(OPT_TRIX)|B(OPT_MAD16)|B(OPT_CS4232)|\
                     B(OPT_SPNP))
 #define SBDSP_DEVS (B(OPT_SB)|B(OPT_SPNP)|B(OPT_MAD16)|B(OPT_TRIX))
-#define SEQUENCER_DEVS (OPT_MIDI|OPT_YM3812|OPT_ADLIB|OPT_GUS|OPT_MAUI|MIDI_CARDS)
+#define SEQUENCER_DEVS (MIDI_CARDS|B(OPT_YM3812)|B(OPT_ADLIB)|B(OPT_GUS)|B(OPT_MAUI))
 /*
  * Options that have been disabled for some reason (incompletely implemented
  * and/or tested). Don't remove from this list before looking at file
@@ -138,9 +135,9 @@ hw_entry        hw_table[] =
   {B (OPT_SB), B (OPT_PAS), "UNUSED1", 1, 0, 1},
   {B (OPT_SB) | B (OPT_UNUSED1), B (OPT_PAS), "UNUSED2", 1, 0, 1},
   {B (OPT_UNUSED1) | B (OPT_MSS) | B (OPT_MPU401), 0, "AEDSP16", 1, 0, 0},
-  {AUDIO_CARDS, 0, "AUDIO", 1, 0, 1},
-  {B (OPT_MPU401) | B (OPT_MAUI), 0, "MIDI_AUTO", 0, OPT_MIDI, 0},
-  {MIDI_CARDS, 0, "MIDI", 1, 0, 1},
+  {AUDIO_CARDS, 0, "UNUSED3", 1, 0, 1},
+  {B (OPT_MPU401) | B (OPT_MAUI), 0, "UNUSED4", 0, 0, 0},
+  {MIDI_CARDS, 0, "UNUSED5", 1, 0, 1},
   {B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812, 0},
   {B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_ADLIB) | B (OPT_MSS) | B (OPT_PSS), B (OPT_YM3812_AUTO), "YM3812", 1, 0, 1}
 };
@@ -167,9 +164,9 @@ char           *questions[] =
   "*** Unused option 1 ***",
   "*** Unused option 2 ***",
   "Audio Excel DSP 16 initialization support",
-  "/dev/dsp and /dev/audio support",
-  "This should not be asked",
-  "MIDI interface support",
+  "*** Unused option 3 ***",
+  "*** Unused option 4 ***",
+  "*** Unused option 5 ***",
   "This should not be asked",
   "FM synthesizer (YM3812/OPL-3) support",
   "Is the sky really falling"
@@ -288,10 +285,26 @@ extra_options[] =
     "UART401", UART401_DEVS
   }
   ,
+  {
+    "GUSHW", B (OPT_GUS) | B (OPT_SPNP)
+  }
+  ,
+  {
+    "SSCAPEHW", B (OPT_SSCAPE) | B (OPT_SPNP)
+  }
+  ,
   {
     "SEQUENCER", SEQUENCER_DEVS
   }
   ,
+  {
+    "AUDIO", AUDIO_CARDS
+  }
+  ,
+  {
+    "MIDI", MIDI_CARDS
+  }
+  ,
   {
     NULL, 0
   }
@@ -409,6 +422,32 @@ play_it_again_Sam:
 #define FMT_HEX 1
 #define FMT_INT 2
 
+void
+show_comment (int mask, char *txt)
+{
+  int             i;
+
+  if (dump_only)
+    {
+
+      for (i = 0; i < OPT_LAST; i++)
+       if (mask == B (i))
+         {
+           printf ("\n\nif [ \"$CONFIG_%s\" = \"y\" ]; then\n",
+                   hw_table[i].macro);
+           printf ("comment '%s'\n", txt);
+           printf ("fi\n");
+         }
+    }
+  else
+    {
+      if (!(mask & selected_options))
+       return;
+
+      fprintf (stderr, "%s\n", txt);
+    }
+}
+
 void
 ask_int_choice (int mask, char *macro,
                char *question,
@@ -682,14 +721,11 @@ use_old_config (char *filename)
   printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n", selected_options);
   fprintf (stderr, "Old configuration copied.\n");
 
-#if defined(linux) || defined(Solaris)
   build_defines ();
-#endif
   old_config_used = 1;
   return 1;
 }
 
-#if defined(linux) || defined(Solaris)
 void
 build_defines (void)
 {
@@ -723,7 +759,6 @@ build_defines (void)
   fprintf (optf, "\n");
   fclose (optf);
 }
-#endif
 
 void
 ask_parameters (void)
@@ -735,13 +770,11 @@ ask_parameters (void)
    * IRQ and DMA settings
    */
 
-#if 0  /* Disable this broken question. */
   ask_int_choice (B (OPT_AEDSP16), "AEDSP16_BASE",
                  "I/O base for Audio Excel DSP 16",
                  FMT_HEX,
                  0x220,
                  "220 or 240");
-#endif
 
   ask_int_choice (B (OPT_SB), "SBC_BASE",
                  "I/O base for SB",
@@ -762,7 +795,7 @@ ask_parameters (void)
                  "0, 1 or 3");
 
   ask_int_choice (B (OPT_SB), "SB_DMA2",
-               "Sound Blaster 16 bit DMA (_REQUIRED_for SB16, Jazz16, SMW)",
+                 "Sound Blaster 16 bit DMA (SB16, Jazz16, SMW)",
                  FMT_INT,
                  5,
                  "5, 6 or 7 (use 1 for 8 bit cards)");
@@ -770,14 +803,19 @@ ask_parameters (void)
   ask_int_choice (B (OPT_SB), "SB_MPU_BASE",
                  "MPU401 I/O base of SB16, Jazz16 and ES1688",
                  FMT_HEX,
-                 0,
+                 0x330,
                  "Check from manual of the card");
 
+  show_comment (B (OPT_SB),
+          "MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.");
+  show_comment (B (OPT_SB),
+               "Enter -1 to the following question if you have something else such as SB16/32.");
+
   ask_int_choice (B (OPT_SB), "SB_MPU_IRQ",
                  "SB MPU401 IRQ (Jazz16, SM Wave and ES1688)",
                  FMT_INT,
                  -1,
-                 "Use -1 with SB16");
+                 "Check from manual of the card");
 
   ask_int_choice (B (OPT_PAS), "PAS_IRQ",
                  "PAS16 IRQ",
@@ -867,6 +905,10 @@ ask_parameters (void)
                  9,
                  "Check from manual of the card");
 
+  if (dump_only)
+    show_comment (B (OPT_MAUI),
+       "ERROR! You have to use old sound configuration method with Maui.");
+
   ask_int_choice (B (OPT_MAUI), "MAUI_BASE",
                  "I/O base for Maui",
                  FMT_HEX,
@@ -891,6 +933,10 @@ ask_parameters (void)
                  -1,
                  "(Unknown)");
 
+  if (dump_only)
+    show_comment (B (OPT_PSS),
+    "ERROR! You have to use old sound configuration method with PSS cards.");
+
   ask_int_choice (B (OPT_PSS), "PSS_BASE",
                  "PSS I/O base",
                  FMT_HEX,
@@ -990,6 +1036,10 @@ ask_parameters (void)
 
     }
 
+  if (dump_only)
+    show_comment (B (OPT_MAUI),
+    "ERROR! You have to use old sound configuration method with AudioTrix.");
+
   ask_int_choice (B (OPT_TRIX), "TRIX_BASE",
                  "AudioTrix audio I/O base",
                  FMT_HEX,
@@ -1115,11 +1165,6 @@ ask_parameters (void)
                  FMT_INT,
                  9,
                  "5, 7, 9 or 10");
-  ask_int_choice (B (OPT_AUDIO), "DSP_BUFFSIZE",
-                 "Audio DMA buffer size",
-                 FMT_INT,
-                 65536,
-                 "4096, 16384, 32768 or 65536");
 }
 
 void
@@ -1367,7 +1412,7 @@ main (int argc, char *argv[])
        {
 
          if (think_positively (
-           "Do you want support for the Audio Excel Sound Blaster Pro mode",
+          "Do you want support for the Audio Excel Sound Blaster Pro mode",
                                 1,
                                 "Enable this option if you want the Audio Excel sound card to operate\n"
                                 "in Sound Blaster Pro mode.\n"))
@@ -1445,7 +1490,7 @@ main (int argc, char *argv[])
 
       if (think_positively ("Do you want to include TRXPRO.HEX in your kernel",
                            1,
-       "The MediaTrix AudioTrix Pro has an on-board microcontroller which\n"
+       "The MediaTrix AudioTrix Pro has an on-board microcontroller which\n"
                            "needs to be initialized by downloading the code from the file TRXPRO.HEX\n"
                            "in the DOS driver directory. If you don't have the TRXPRO.HEX file handy\n"
                            "you may skip this step. However, the SB and MPU-401 modes of AudioTrix\n"
@@ -1541,10 +1586,6 @@ main (int argc, char *argv[])
   printf ("#define SELECTED_SOUND_OPTIONS\t0x%08lx\n", selected_options);
   fprintf (stderr, "\nThe sound driver is now configured.\n");
 
-#if defined(SCO) || defined(ISC) || defined(SYSV)
-  fprintf (stderr, "Remember to update the System file\n");
-#endif
-
   if (!old_config_used)
     {
       char            str[255];
index 989f0e5508867f66743d29fadc2416a315832f20..2e7e9acc643cc0f2f99bb28ce8710d6e36d29835 100644 (file)
@@ -11,7 +11,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -30,7 +30,7 @@ static int     *osp;
 static void 
 CS_OUT (unsigned char a)
 {
-  outb (a, KEY_PORT);
+  outb ((a), KEY_PORT);
 }
 #define CS_OUT2(a, b)          {CS_OUT(a);CS_OUT(b);}
 #define CS_OUT3(a, b, c)       {CS_OUT(a);CS_OUT(b);CS_OUT(c);}
@@ -71,11 +71,10 @@ probe_cs4232 (struct address_info *hw_config)
   int             base = hw_config->io_base, irq = hw_config->irq;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
 
-  static wait_handle *cs_sleeper = NULL;
+  static struct wait_queue *cs_sleeper = NULL;
   static volatile struct snd_wait cs_sleep_flag =
   {0};
 
-  osp = hw_config->osp;
 
 /*
  * Verify that the I/O port range is free.
@@ -105,7 +104,7 @@ probe_cs4232 (struct address_info *hw_config)
 
   for (n = 0; n < 4; n++)
     {
-      cs_sleep_flag.flags = WK_NONE;
+      cs_sleep_flag.opts = WK_NONE;
 /*
  * Wake up the card by sending a 32 byte Crystal key to the key port.
  */
@@ -117,17 +116,17 @@ probe_cs4232 (struct address_info *hw_config)
        unsigned long   tlimit;
 
        if (HZ / 10)
-         current_set_timeout (tlimit = jiffies + (HZ / 10));
+         current->timeout = tlimit = jiffies + (HZ / 10);
        else
          tlimit = (unsigned long) -1;
-       cs_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&cs_sleeper);
-       if (!(cs_sleep_flag.flags & WK_WAKEUP))
+       cs_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&cs_sleeper);
+       if (!(cs_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             cs_sleep_flag.flags |= WK_TIMEOUT;
+             cs_sleep_flag.opts |= WK_TIMEOUT;
          }
-       cs_sleep_flag.flags &= ~WK_SLEEP;
+       cs_sleep_flag.opts &= ~WK_SLEEP;
       };                       /* Delay */
 
 /*
@@ -165,17 +164,17 @@ probe_cs4232 (struct address_info *hw_config)
        unsigned long   tlimit;
 
        if (HZ / 10)
-         current_set_timeout (tlimit = jiffies + (HZ / 10));
+         current->timeout = tlimit = jiffies + (HZ / 10);
        else
          tlimit = (unsigned long) -1;
-       cs_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&cs_sleeper);
-       if (!(cs_sleep_flag.flags & WK_WAKEUP))
+       cs_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&cs_sleeper);
+       if (!(cs_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             cs_sleep_flag.flags |= WK_TIMEOUT;
+             cs_sleep_flag.opts |= WK_TIMEOUT;
          }
-       cs_sleep_flag.flags &= ~WK_SLEEP;
+       cs_sleep_flag.opts &= ~WK_SLEEP;
       };                       /* Delay */
 
 /*
@@ -202,17 +201,17 @@ probe_cs4232 (struct address_info *hw_config)
        unsigned long   tlimit;
 
        if (HZ / 5)
-         current_set_timeout (tlimit = jiffies + (HZ / 5));
+         current->timeout = tlimit = jiffies + (HZ / 5);
        else
          tlimit = (unsigned long) -1;
-       cs_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&cs_sleeper);
-       if (!(cs_sleep_flag.flags & WK_WAKEUP))
+       cs_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&cs_sleeper);
+       if (!(cs_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             cs_sleep_flag.flags |= WK_TIMEOUT;
+             cs_sleep_flag.opts |= WK_TIMEOUT;
          }
-       cs_sleep_flag.flags &= ~WK_SLEEP;
+       cs_sleep_flag.opts &= ~WK_SLEEP;
       };                       /* Delay */
 
 /*
@@ -227,17 +226,17 @@ probe_cs4232 (struct address_info *hw_config)
        unsigned long   tlimit;
 
        if (HZ)
-         current_set_timeout (tlimit = jiffies + (HZ));
+         current->timeout = tlimit = jiffies + (HZ);
        else
          tlimit = (unsigned long) -1;
-       cs_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&cs_sleeper);
-       if (!(cs_sleep_flag.flags & WK_WAKEUP))
+       cs_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&cs_sleeper);
+       if (!(cs_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             cs_sleep_flag.flags |= WK_TIMEOUT;
+             cs_sleep_flag.opts |= WK_TIMEOUT;
          }
-       cs_sleep_flag.flags &= ~WK_SLEEP;
+       cs_sleep_flag.opts &= ~WK_SLEEP;
       };                       /* Longer delay */
     }
 
@@ -249,6 +248,7 @@ attach_cs4232 (struct address_info *hw_config)
 {
   int             base = hw_config->io_base, irq = hw_config->irq;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+  int             old_num_mixers = num_mixers;
 
   if (dma2 == -1)
     dma2 = dma1;
@@ -260,6 +260,13 @@ attach_cs4232 (struct address_info *hw_config)
               0,
               hw_config->osp);
 
+  if (num_mixers > old_num_mixers)
+    {                          /* Assume the mixer map is as suggested in the CS4232 databook */
+      AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
+      AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+      AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);   /* FM synth */
+    }
+
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
   if (mpu_base != 0 && mpu_irq != 0)
     {
@@ -275,7 +282,6 @@ attach_cs4232 (struct address_info *hw_config)
       hw_config2.driver_use_1 = 0;
       hw_config2.driver_use_2 = 0;
       hw_config2.card_subtype = 0;
-      hw_config2.osp = hw_config->osp;
 
       if (probe_mpu401 (&hw_config2))
        {
@@ -320,7 +326,6 @@ unload_cs4232 (struct address_info *hw_config)
       hw_config2.driver_use_1 = 0;
       hw_config2.driver_use_2 = 0;
       hw_config2.card_subtype = 0;
-      hw_config2.osp = hw_config->osp;
 
       unload_mpu401 (&hw_config2);
     }
index 3a835eeee2e50cb04ac8a643ea1ddcdd0ca9d575..080ec3641e8ab275f8a25bea15e02d1be123931a 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -44,7 +44,7 @@ start_services (void)
   if (num_audiodevs)           /* Audio devices present */
     {
       DMAbuf_init ();
-      audio_init ();
+      audio_init_devices ();
     }
 #endif
 
@@ -70,6 +70,14 @@ start_cards (void)
   if (trace_init)
     printk ("Sound initialization started\n");
 
+#ifdef CONFIG_LOWLEVEL_SOUND
+  {
+    extern void     sound_preinit_lowlevel_drivers (void);
+
+    sound_preinit_lowlevel_drivers ();
+  }
+#endif
+
 /*
  * Check the number of cards actually defined in the table
  */
@@ -105,6 +113,14 @@ start_cards (void)
                                                 */
       }
 
+#ifdef CONFIG_LOWLEVEL_SOUND
+  {
+    extern void     sound_init_lowlevel_drivers (void);
+
+    sound_init_lowlevel_drivers ();
+  }
+#endif
+
   if (trace_init)
     printk ("Sound initialization complete\n");
 }
@@ -112,7 +128,7 @@ start_cards (void)
 void
 sndtable_init (void)
 {
-  return start_cards ();
+  start_cards ();
 }
 
 void
@@ -147,7 +163,7 @@ sound_unload_driver (int type)
 
   unsigned long   flags;
 
-  DDB (printk ("unload driver %d: ", type));
+  DEB (printk ("unload driver %d: ", type));
 
   for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
     if (snd_installed_cards[i].card_type == type)
@@ -156,7 +172,7 @@ sound_unload_driver (int type)
          {
            if ((drv = snd_find_driver (type)) != -1)
              {
-               DDB (printk (" card %d", i));
+               DEB (printk (" card %d", i));
                if (sound_drivers[drv].unload)
                  {
                    sound_drivers[drv].unload (&snd_installed_cards[i].config);
@@ -165,7 +181,7 @@ sound_unload_driver (int type)
              }
          }
       }
-  DDB (printk ("\n"));
+  DEB (printk ("\n"));
 
   save_flags (flags);
   cli ();
@@ -179,12 +195,10 @@ sndtable_probe (int unit, struct address_info *hw_config)
 {
   int             sel = -1;
 
-  DDB (printk ("sndtable_probe(%d)\n", unit));
+  DEB (printk ("sndtable_probe(%d)\n", unit));
 
   if (!unit)
-    return TRUE;
-
-  sound_started = 1;
+    return 1;
 
 
   if (sel == -1 && num_sound_cards < max_sound_cards)
@@ -211,15 +225,14 @@ sndtable_probe (int unit, struct address_info *hw_config)
       snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1;
       snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2;
       snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype;
-      snd_installed_cards[sel].config.osp = hw_config->osp;
 
       if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1)
        {
          snd_installed_cards[sel].enabled = 0;
-         DDB (printk ("Failed to find driver\n"));
-         return FALSE;
+         DEB (printk ("Failed to find driver\n"));
+         return 0;
        }
-      DDB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
+      DEB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
 
       hw_config->card_subtype =
        snd_installed_cards[sel].config.card_subtype =
@@ -227,99 +240,32 @@ sndtable_probe (int unit, struct address_info *hw_config)
 
       if (sound_drivers[drv].probe (hw_config))
        {
-         DDB (printk ("Hardware probed OK\n"));
-         return TRUE;
+         DEB (printk ("Hardware probed OK\n"));
+         return 1;
        }
 
-      DDB (printk ("Failed to find hardware\n"));
+      DEB (printk ("Failed to find hardware\n"));
       snd_installed_cards[sel].enabled = 0;    /*
                                                 * Mark as not detected
                                                 */
-      return FALSE;
+      return 0;
     }
 
-  return FALSE;
+  return 0;
 }
 
-int
-sndtable_start_card (int unit, struct address_info *hw_config)
-{
-  int             sel = -1;
-
-  DDB (printk ("sndtable_probe(%d)\n", unit));
-
-  if (!unit)
-    return TRUE;
-
-  sound_started = 1;
-
-  if (sel == -1 && num_sound_cards < max_sound_cards)
-    {
-      int             i;
-
-      i = sel = (num_sound_cards++);
-
-      snd_installed_cards[sel].card_type = unit;
-      snd_installed_cards[sel].enabled = 1;
-    }
-
-  if (sel != -1)
-    {
-      int             drv;
-
-      snd_installed_cards[sel].for_driver_use = NULL;
-      snd_installed_cards[sel].config.io_base = hw_config->io_base;
-      snd_installed_cards[sel].config.irq = hw_config->irq;
-      snd_installed_cards[sel].config.dma = hw_config->dma;
-      snd_installed_cards[sel].config.dma2 = hw_config->dma2;
-      snd_installed_cards[sel].config.name = hw_config->name;
-      snd_installed_cards[sel].config.always_detect = hw_config->always_detect;
-      snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1;
-      snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2;
-      snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype;
-      snd_installed_cards[sel].config.osp = hw_config->osp;
-
-      if ((drv = snd_find_driver (snd_installed_cards[sel].card_type)) == -1)
-       {
-         snd_installed_cards[sel].enabled = 0;
-         DDB (printk ("Failed to find driver\n"));
-         return FALSE;
-       }
-      DDB (printk ("Driver name '%s'\n", sound_drivers[drv].name));
-
-      hw_config->card_subtype =
-       snd_installed_cards[sel].config.card_subtype =
-       sound_drivers[drv].card_subtype;
-
-      if (sound_drivers[drv].probe (hw_config))
-       {
-         DDB (printk ("Hardware probed OK\n"));
-         sound_drivers[drv].attach (hw_config);
-         start_services ();
-         return TRUE;
-       }
-
-      DDB (printk ("Failed to find hardware\n"));
-      snd_installed_cards[sel].enabled = 0;    /*
-                                                * Mark as not detected
-                                                */
-      return FALSE;
-    }
-
-  return FALSE;
-}
 
 int
 sndtable_init_card (int unit, struct address_info *hw_config)
 {
   int             i, n = num_sound_cards;
 
-  DDB (printk ("sndtable_init_card(%d) entered\n", unit));
+  DEB (printk ("sndtable_init_card(%d) entered\n", unit));
 
   if (!unit)
     {
       sndtable_init ();
-      return TRUE;
+      return 1;
     }
 
   for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
@@ -336,7 +282,6 @@ sndtable_init_card (int unit, struct address_info *hw_config)
        snd_installed_cards[i].config.driver_use_1 = hw_config->driver_use_1;
        snd_installed_cards[i].config.driver_use_2 = hw_config->driver_use_2;
        snd_installed_cards[i].config.card_subtype = hw_config->card_subtype;
-       snd_installed_cards[i].config.osp = hw_config->osp;
 
        if ((drv = snd_find_driver (snd_installed_cards[i].card_type)) == -1)
          snd_installed_cards[i].enabled = 0;   /*
@@ -345,18 +290,18 @@ sndtable_init_card (int unit, struct address_info *hw_config)
        else
          {
 
-           DDB (printk ("Located card - calling attach routine\n"));
+           DEB (printk ("Located card - calling attach routine\n"));
            sound_drivers[drv].attach (hw_config);
 
-           DDB (printk ("attach routine finished\n"));
+           DEB (printk ("attach routine finished\n"));
          }
        start_services ();
-       return TRUE;
+       return 1;
       }
 
-  DDB (printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
+  DEB (printk ("sndtable_init_card: No card defined with type=%d, num cards: %d\n",
               unit, num_sound_cards));
-  return FALSE;
+  return 0;
 }
 
 int
@@ -449,7 +394,6 @@ sound_setup (char *str, int *ints)
          snd_installed_cards[ptr].config.driver_use_1 = 0;
          snd_installed_cards[ptr].config.driver_use_2 = 0;
          snd_installed_cards[ptr].config.card_subtype = 0;
-         snd_installed_cards[ptr].config.osp = NULL;
        }
     }
 }
@@ -486,6 +430,7 @@ sound_install_audiodrv (int vers,
                        int dma1,
                        int dma2)
 {
+#ifdef CONFIG_AUDIO
   struct audio_driver *d;
   struct audio_operations *op;
   int             l, num;
@@ -493,14 +438,14 @@ sound_install_audiodrv (int vers,
   if (num_audiodevs >= MAX_AUDIO_DEV)
     {
       printk ("Sound: Too many audio drivers\n");
-      return -(EIO);
+      return -EIO;
     }
 
   if (vers != AUDIO_DRIVER_VERSION ||
       driver_size > sizeof (struct audio_driver))
     {
       printk ("Sound: Incompatible audio driver for %s\n", name);
-      return -(EIO);
+      return -EIO;
     }
 
 
@@ -516,7 +461,7 @@ sound_install_audiodrv (int vers,
   if (d == NULL || op == NULL)
     {
       printk ("Sound: Can't allocate driver for (%s)\n", name);
-      return -(ENOSPC);
+      return -ENOSPC;
     }
 
   memset ((char *) op, 0, sizeof (struct audio_operations));
@@ -546,11 +491,12 @@ sound_install_audiodrv (int vers,
   audio_devs[num_audiodevs] = op;
   num = num_audiodevs++;
 
-#ifdef CONFIG_AUDIO
   DMAbuf_init ();
-  audio_init ();
-#endif
+  audio_init_devices ();
   return num;
+#else
+  return -EINVAL;
+#endif
 }
 
 int 
@@ -566,14 +512,14 @@ sound_install_mixer (int vers,
   if (num_mixers >= MAX_MIXER_DEV)
     {
       printk ("Sound: Too many mixer drivers\n");
-      return -(EIO);
+      return -EIO;
     }
 
   if (vers != MIXER_DRIVER_VERSION ||
       driver_size > sizeof (struct mixer_operations))
     {
       printk ("Sound: Incompatible mixer driver for %s\n", name);
-      return -(EIO);
+      return -EIO;
     }
 
 
@@ -584,7 +530,7 @@ sound_install_mixer (int vers,
   if (op == NULL)
     {
       printk ("Sound: Can't allocate mixer driver for (%s)\n", name);
-      return -(ENOSPC);
+      return -ENOSPC;
     }
 
   memset ((char *) op, 0, sizeof (struct mixer_operations));
index 3ce91d341e5f42ebe26618524130df24c6de69f2..84dd114863aba6b091bcef45282858826244b236 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -22,6 +22,7 @@
  * Numbers 1000 to N are reserved for driver's internal use.
  */
 #define SNDCARD_DESKPROXL              27      /* Compaq Deskpro XL */
+#define SNDCARD_SBPNP                  29
 
 /*
  *     NOTE!   NOTE!   NOTE!   NOTE!
@@ -50,12 +51,6 @@ struct card_info {
        void *for_driver_use;
 };
 
-typedef struct pnp_sounddev
-{
-       int id;
-       void (*setup)(void *dev);
-       char *driver_name;
-}pnp_sounddev;
 
 /*
  * Device specific parameters (used only by dmabuf.c)
@@ -90,6 +85,7 @@ struct dma_buffparms {
 #define DMA_ALLOC_DONE 0x00000020
 #define DMA_SYNCING    0x00000040
 #define DMA_CLEAN      0x00000080
+#define DMA_POST       0x00000100
 
        int      open_mode;
 
@@ -112,6 +108,7 @@ struct dma_buffparms {
 
        int      underrun_count;
        int      byte_counter;
+       int      data_rate; /* Bytes/second */
 
        int      mapping_flags;
 #define                        DMA_MAP_MAPPED          0x00000001
@@ -126,7 +123,7 @@ struct dma_buffparms {
  * in the recent soundcards.
  */
 typedef struct coproc_operations {
-               char name[32];
+               char name[64];
                int (*open) (void *devc, int sub_device);
                void (*close) (void *devc, int sub_device);
                int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local);
@@ -148,7 +145,7 @@ struct audio_driver {
        void (*reset) (int dev);
        void (*halt_xfer) (int dev);
        int (*local_qlen)(int dev);
-        void (*copy_from_user)(int dev, char *localbuf, int localoffs,
+        void (*copy_user)(int dev, char *localbuf, int localoffs,
                                const char *userbuf, int useroffs, int len);
        void (*halt_input) (int dev);
        void (*halt_output) (int dev);
@@ -159,7 +156,7 @@ struct audio_driver {
 };
 
 struct audio_operations {
-        char name[32];
+        char name[64];
        int flags;
 #define NOTHING_SPECIAL        0x00
 #define NEEDS_RESTART          0x01
@@ -167,6 +164,7 @@ struct audio_operations {
 #define DMA_DUPLEX             0x04
 #define DMA_PSEUDO_AUTOMODE    0x08
 #define DMA_HARDSTOP           0x10
+#define DMA_NODMA              0x20
        int  format_mask;       /* Bitmask for supported audio formats */
        void *devc;             /* Driver specific info */
        struct audio_driver *d;
@@ -181,12 +179,15 @@ struct audio_operations {
        int min_fragment;       /* 0 == unlimited */
 };
 
+int *load_mixer_volumes(char *name, int *levels, int present);
+
 struct mixer_operations {
        char id[16];
-       char name[32];
+       char name[64];
        int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
        
        void *devc;
+       int modify_counter;
 };
 
 struct synth_operations {
@@ -242,7 +243,7 @@ struct midi_operations {
                );
        void (*close) (int dev);
        int (*ioctl) (int dev, unsigned int cmd, caddr_t arg);
-       int (*putc) (int dev, unsigned char data);
+       int (*outputc) (int dev, unsigned char data);
        int (*start_read) (int dev);
        int (*end_read) (int dev);
        void (*kick)(int dev);
@@ -273,6 +274,7 @@ struct sound_timer_operations {
 };
 
 #ifdef _DEV_TABLE_C_   
+
        struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0;
        struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0;
        struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0;
@@ -301,8 +303,6 @@ struct sound_timer_operations {
 #endif
 #ifdef CONFIG_MSS
                {"MSS", 0, SNDCARD_MSS, "MS Sound System",      attach_ms_sound, probe_ms_sound, unload_ms_sound},
-       /* MSS without IRQ/DMA config registers (for DEC Alphas) */
-               {"PCXBJ", 1, SNDCARD_PSEUDO_MSS,        "MS Sound System (AXP)",        attach_ms_sound, probe_ms_sound, unload_ms_sound},
        /* Compaq Deskpro XL */
                {"DESKPROXL", 2, SNDCARD_DESKPROXL,     "Compaq Deskpro XL",    attach_ms_sound, probe_ms_sound, unload_ms_sound},
 #endif
@@ -314,35 +314,48 @@ struct sound_timer_operations {
                {"CS4232", 0, SNDCARD_CS4232,   "CS4232",               attach_cs4232, probe_cs4232, unload_cs4232},
                {"CS4232MPU", 0, SNDCARD_CS4232_MPU,    "CS4232 MIDI",          attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu},
 #endif
-#ifdef CONFIG_YM3812
+#if defined(CONFIG_YM3812)
                {"OPL3", 0, SNDCARD_ADLIB,      "OPL-2/OPL-3 FM",               attach_adlib_card, probe_adlib, unload_adlib},
 #endif
 #ifdef CONFIG_PAS
                {"PAS16", 0, SNDCARD_PAS,       "ProAudioSpectrum",     attach_pas_card, probe_pas, unload_pas},
 #endif
-#if defined(CONFIG_MPU401) && defined(CONFIG_MIDI)
+#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
                {"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401",  attach_mpu401, probe_mpu401, unload_mpu401},
 #endif
+#if (defined(CONFIG_UART401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+       {"UART401", 0, SNDCARD_UART401,"MPU-401 (UART)", 
+               attach_uart401, probe_uart401, unload_uart401},
+#endif
 #if defined(CONFIG_MAUI)
                {"MAUI", 0, SNDCARD_MAUI,"TB Maui",     attach_maui, probe_maui, unload_maui},
 #endif
 #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI)
                {"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi",      attach_uart6850, probe_uart6850, unload_uart6850},
 #endif
-#ifdef CONFIG_SB
+
+
+
+
+#ifdef CONFIG_SBDSP
                {"SBLAST", 0, SNDCARD_SB,       "Sound Blaster",                attach_sb_card, probe_sb, unload_sb},
-#ifdef CONFIG_MIDI
+               {"SBPNP", 6, SNDCARD_SBPNP,     "Sound Blaster PnP",            attach_sb_card, probe_sb, unload_sb},
+
+#      ifdef CONFIG_MIDI
                {"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU-401",     attach_sbmpu, probe_sbmpu, unload_sbmpu},
+#      endif
 #endif
-#endif
+
+
+
 #ifdef CONFIG_GUS16
                {"GUS16", 0, SNDCARD_GUS16,     "Ultrasound 16-bit opt.",       attach_gus_db16, probe_gus_db16, unload_gus_db16},
 #endif
-#ifdef CONFIG_GUS
+#ifdef CONFIG_GUSHW
                {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound",    attach_gus_card, probe_gus, unload_gus},
                {"GUSPNP", 1, SNDCARD_GUSPNP,   "GUS PnP",      attach_gus_card, probe_gus, unload_gus},
 #endif
-#ifdef CONFIG_SSCAPE
+#ifdef CONFIG_SSCAPEHW
                {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq SoundScape",     attach_sscape, probe_sscape, unload_sscape},
                {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS,    "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound},
 #endif
@@ -351,6 +364,7 @@ struct sound_timer_operations {
                {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTrix (SB mode)",       attach_trix_sb, probe_trix_sb, unload_trix_sb},
                {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTrix MIDI",  attach_trix_mpu, probe_trix_mpu, unload_trix_mpu},
 #endif
+
                {NULL, 0, 0,            "*?*",                  NULL, NULL, NULL}
        };
 
@@ -479,11 +493,6 @@ struct sound_timer_operations {
 #ifdef CONFIG_YM3812
                {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
-/* Define some expansion space */
-               {0, {0}, 0},
-               {0, {0}, 0},
-               {0, {0}, 0},
-               {0, {0}, 0},
                {0, {0}, 0}
        };
 
@@ -498,11 +507,12 @@ struct sound_timer_operations {
        int max_sound_cards = 20;
 #endif
 
-#   ifdef MODULE
+#if defined(MODULE) || (!defined(linux) && !defined(_AIX))
        int trace_init = 0;
 #   else
        int trace_init = 1;
 #   endif
+
 #else
        extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs;
        extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers;
@@ -531,9 +541,8 @@ int sndtable_identify_card(char *name);
 void sound_setup (char *str, int *ints);
 
 int sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan);
-void sound_free_dmap (int dev, struct dma_buffparms *dmap);
+void sound_free_dmap (int dev, struct dma_buffparms *dmap, int chn);
 extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info);
-void install_pnp_sounddrv(struct pnp_sounddev *drv);
 int sndtable_probe (int unit, struct address_info *hw_config);
 int sndtable_init_card (int unit, struct address_info *hw_config);
 int sndtable_start_card (int unit, struct address_info *hw_config);
@@ -543,8 +552,8 @@ int sound_start_dma (       int dev, struct dma_buffparms *dmap, int chan,
                        int count, int dma_mode, int autoinit);
 void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan);
 
-#define AUDIO_DRIVER_VERSION   1
-#define MIXER_DRIVER_VERSION   1
+#define AUDIO_DRIVER_VERSION   2
+#define MIXER_DRIVER_VERSION   2
 int sound_install_audiodrv(int vers,
                           char *name,
                           struct audio_driver *driver,
index 12bfbf4fc7cb3c361b0a9148cc30aee8b12ebedd..bca21d0232ce2ad1c0113f832e5ed0c31f60cb9a 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 
 #include "sound_config.h"
 
-#if defined(CONFIG_AUDIO) || defined(CONFIG_GUS)
+#if defined(CONFIG_AUDIO) || defined(CONFIG_GUSHW)
 
-static wait_handle *in_sleeper[MAX_AUDIO_DEV] =
+static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] =
 {NULL};
 static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] =
 {
   {0}};
-static wait_handle *out_sleeper[MAX_AUDIO_DEV] =
+static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] =
 {NULL};
 static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] =
 {
@@ -57,30 +57,31 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
   unsigned        i, n;
   unsigned        sr, nc, sz, bsz;
 
-  if (dmap->fragment_size == 0)
-    {                          /* Compute the fragment size using the default algorithm */
+  sr = dsp_dev->d->set_speed (dev, 0);
+  nc = dsp_dev->d->set_channels (dev, 0);
+  sz = dsp_dev->d->set_bits (dev, 0);
 
-      sr = dsp_dev->d->set_speed (dev, 0);
-      nc = dsp_dev->d->set_channels (dev, 0);
-      sz = dsp_dev->d->set_bits (dev, 0);
+  if (sz == 8)
+    dmap->neutral_byte = NEUTRAL8;
+  else
+    dmap->neutral_byte = NEUTRAL16;
 
-      if (sz == 8)
-       dmap->neutral_byte = NEUTRAL8;
-      else
-       dmap->neutral_byte = NEUTRAL16;
+  if (sr < 1 || nc < 1 || sz < 1)
+    {
+      printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
+             dev, sr, nc, sz);
+      sr = DSP_DEFAULT_SPEED;
+      nc = 1;
+      sz = 8;
+    }
 
-      if (sr < 1 || nc < 1 || sz < 1)
-       {
-         printk ("Warning: Invalid PCM parameters[%d] sr=%d, nc=%d, sz=%d\n",
-                 dev, sr, nc, sz);
-         sr = DSP_DEFAULT_SPEED;
-         nc = 1;
-         sz = 8;
-       }
+  sz = sr * nc * sz;
 
-      sz = sr * nc * sz;
+  sz /= 8;                     /* #bits -> #bytes */
+  dmap->data_rate = sz;
 
-      sz /= 8;                 /* #bits -> #bytes */
+  if (dmap->fragment_size == 0)
+    {                          /* Compute the fragment size using the default algorithm */
 
       /*
          * Compute a buffer size for time not exceeding 1 second.
@@ -103,11 +104,12 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
 
       if (dmap->subdivision == 0)      /* Not already set */
        {
-         dmap->subdivision = 1;        /* Init to the default value */
-#ifndef V35A9_COMPATIBLE
-         if (recording)
-           dmap->subdivision = 4;      /* Use shorter fragments when recording */
-#endif
+         dmap->subdivision = 4;        /* Init to the default value */
+
+         if ((bsz / dmap->subdivision) > 4096)
+           dmap->subdivision *= 2;
+         if ((bsz / dmap->subdivision) < 4096)
+           dmap->subdivision = 1;
        }
 
       bsz /= dmap->subdivision;
@@ -138,8 +140,16 @@ reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording)
     n = MAX_SUB_BUFFERS;
   if (n > dmap->max_fragments)
     n = dmap->max_fragments;
+
+  if (n < 2)
+    {
+      n = 2;
+      bsz /= 2;
+    }
+
   dmap->nbufs = n;
   dmap->bytes_in_use = n * bsz;
+  dmap->fragment_size = bsz;
 
   if (dmap->raw_buf)
     memset (dmap->raw_buf,
@@ -159,11 +169,11 @@ dma_init_buffers (int dev, struct dma_buffparms *dmap)
 {
   if (dmap == audio_devs[dev]->dmap_out)
     {
-      out_sleep_flag[dev].flags = WK_NONE;
+      out_sleep_flag[dev].opts = WK_NONE;
     }
   else
     {
-      in_sleep_flag[dev].flags = WK_NONE;
+      in_sleep_flag[dev].opts = WK_NONE;
     }
 
   dmap->flags = DMA_BUSY;      /* Other flags off */
@@ -174,6 +184,7 @@ dma_init_buffers (int dev, struct dma_buffparms *dmap)
   dmap->dma_mode = DMODE_NONE;
   dmap->mapping_flags = 0;
   dmap->neutral_byte = NEUTRAL8;
+  dmap->data_rate = 8000;
   dmap->cfrag = -1;
   dmap->closing = 0;
 }
@@ -182,7 +193,7 @@ static int
 open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan)
 {
   if (dmap->flags & DMA_BUSY)
-    return -(EBUSY);
+    return -EBUSY;
 
   {
     int             err;
@@ -192,12 +203,12 @@ open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan)
   }
 
   if (dmap->raw_buf == NULL)
-    return -(ENOSPC);          /* Memory allocation failed during boot */
+    return -ENOSPC;            /* Memory allocation failed during boot */
 
   if (sound_open_dma (chan, audio_devs[dev]->name))
     {
       printk ("Unable to grab(2) DMA%d for the audio driver\n", chan);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   dmap->open_mode = mode;
@@ -206,6 +217,7 @@ open_dmap (int dev, int mode, struct dma_buffparms *dmap, int chan)
   dmap->max_fragments = 65536; /* Just a large value */
   dmap->byte_counter = 0;
 
+
   dma_init_buffers (dev, dmap);
 
   return 0;
@@ -221,19 +233,19 @@ close_dmap (int dev, struct dma_buffparms *dmap, int chan)
   dmap->flags &= ~DMA_BUSY;
 
   disable_dma (chan);
-  sound_free_dmap (dev, dmap);
+  sound_free_dmap (dev, dmap, chan);
 }
 
 static unsigned int
 default_set_bits (int dev, unsigned int bits)
 {
-  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) (long) bits, 1);
+  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SETFMT, (caddr_t) bits, 1);
 }
 
 static int
 default_set_speed (int dev, int speed)
 {
-  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SPEED, (caddr_t) (long) speed, 1);
+  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_SPEED, (caddr_t) speed, 1);
 }
 
 static short
@@ -241,7 +253,7 @@ default_set_channels (int dev, short channels)
 {
   int             c = channels;
 
-  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_CHANNELS, (caddr_t) (long) c, 1);
+  return audio_devs[dev]->d->ioctl (dev, SNDCTL_DSP_CHANNELS, (caddr_t) c, 1);
 }
 
 static void
@@ -265,13 +277,13 @@ DMAbuf_open (int dev, int mode)
   if (dev >= num_audiodevs)
     {
       /*  printk ("PCM device %d not installed.\n", dev); */
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (!audio_devs[dev])
     {
       /* printk ("PCM device %d not initialized\n", dev); */
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (!(audio_devs[dev]->flags & DMA_DUPLEX))
@@ -296,7 +308,8 @@ DMAbuf_open (int dev, int mode)
 
   audio_devs[dev]->enable_bits = mode;
   if (mode & OPEN_READ &&
-      audio_devs[dev]->flags & DMA_DUPLEX && dmap_out != dmap_in)
+      audio_devs[dev]->flags & DMA_DUPLEX &&
+      dmap_out != dmap_in)
     if ((retval = open_dmap (dev, mode, dmap_in, audio_devs[dev]->dmachan2)) < 0)
       {
        audio_devs[dev]->d->close (dev);
@@ -305,8 +318,8 @@ DMAbuf_open (int dev, int mode)
       }
   audio_devs[dev]->open_mode = mode;
   audio_devs[dev]->go = 1;
-  in_sleep_flag[dev].flags = WK_NONE;
-  out_sleep_flag[dev].flags = WK_NONE;
+  in_sleep_flag[dev].opts = WK_NONE;
+  out_sleep_flag[dev].opts = WK_NONE;
 
   audio_devs[dev]->d->set_bits (dev, 8);
   audio_devs[dev]->d->set_channels (dev, 1);
@@ -315,8 +328,8 @@ DMAbuf_open (int dev, int mode)
   return 0;
 }
 
-static void
-dma_reset (int dev)
+void
+DMAbuf_reset (int dev)
 {
   unsigned long   flags;
 
@@ -336,14 +349,70 @@ static void
 dma_reset_output (int dev)
 {
   unsigned long   flags;
+  int             tmout;
+
+  struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
+  if (dmap->dma_mode != DMODE_OUTPUT)
+    return;
+
+  if (!(dmap->flags & DMA_STARTED))    /* DMA is not active */
+    return;
 
+/*
+ * First wait until the current fragment has been played completely
+ */
   save_flags (flags);
   cli ();
+
+  tmout =
+    (dmap->fragment_size * HZ) / dmap->data_rate;
+
+  tmout += HZ / 10;            /* Some safety distance */
+
+  if (tmout < (HZ / 2))
+    tmout = HZ / 2;
+  if (tmout > 20 * HZ)
+    tmout = 20 * HZ;
+
+  audio_devs[dev]->dmap_out->flags |= DMA_SYNCING;
+
+  audio_devs[dev]->dmap_out->underrun_count = 0;
+  if (!(current->signal & ~current->blocked)
+      && audio_devs[dev]->dmap_out->qlen
+      && audio_devs[dev]->dmap_out->underrun_count == 0)
+    {
+
+      {
+       unsigned long   tlimit;
+
+       if (tmout)
+         current->timeout = tlimit = jiffies + (tmout);
+       else
+         tlimit = (unsigned long) -1;
+       out_sleep_flag[dev].opts = WK_SLEEP;
+       interruptible_sleep_on (&out_sleeper[dev]);
+       if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
+         {
+           if (jiffies >= tlimit)
+             out_sleep_flag[dev].opts |= WK_TIMEOUT;
+         }
+       out_sleep_flag[dev].opts &= ~WK_SLEEP;
+      };
+    }
+  audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
+  audio_devs[dev]->dmap_out->flags |= DMA_RESTART;
+
+/*
+ * Finally shut the device off
+ */
+
   if (!(audio_devs[dev]->flags & DMA_DUPLEX) ||
       !audio_devs[dev]->d->halt_output)
     audio_devs[dev]->d->reset (dev);
   else
     audio_devs[dev]->d->halt_output (dev);
+  audio_devs[dev]->dmap_out->flags &= ~DMA_STARTED;
   restore_flags (flags);
 
   dma_init_buffers (dev, audio_devs[dev]->dmap_out);
@@ -362,29 +431,75 @@ dma_reset_input (int dev)
     audio_devs[dev]->d->reset (dev);
   else
     audio_devs[dev]->d->halt_input (dev);
+  audio_devs[dev]->dmap_in->flags &= ~DMA_STARTED;
   restore_flags (flags);
 
   dma_init_buffers (dev, audio_devs[dev]->dmap_in);
   reorganize_buffers (dev, audio_devs[dev]->dmap_in, 1);
 }
 
-static int
-dma_sync (int dev)
+static void
+launch_output (int dev, struct dma_buffparms *dmap)
+{
+  dmap->flags |= DMA_ACTIVE;
+
+  if (dmap->dma_mode == DMODE_NONE || dmap->flags & DMA_RESTART)
+    {
+      reorganize_buffers (dev, audio_devs[dev]->dmap_out, 0);
+      audio_devs[dev]->d->prepare_for_output (dev,
+                                         dmap->fragment_size, dmap->nbufs);
+    }
+
+  dmap->dma_mode |= DMODE_OUTPUT;
+
+  audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +
+                                   dmap->qhead * dmap->fragment_size,
+                                   dmap->counts[dmap->qhead], 0,
+                                !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
+                                   !(dmap->flags & DMA_STARTED));
+  dmap->flags |= DMA_STARTED;
+  if (audio_devs[dev]->d->trigger)
+    audio_devs[dev]->d->trigger (dev,
+                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+}
+
+int
+DMAbuf_sync (int dev)
 {
   unsigned long   flags;
+  int             tmout;
 
   if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT))
     return 0;
 
   if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)
     {
+
+      struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+
       save_flags (flags);
       cli ();
 
+      tmout =
+       (dmap->fragment_size * HZ) / dmap->data_rate;
+
+      tmout += HZ / 10;                /* Some safety distance */
+
+      if (tmout < (HZ / 2))
+       tmout = HZ / 2;
+      if (tmout > 20 * HZ)
+       tmout = 20 * HZ;
+
+      ;
+      if (dmap->qlen > 0)
+       if (!(dmap->flags & DMA_ACTIVE))
+         launch_output (dev, dmap);
+      ;
+
       audio_devs[dev]->dmap_out->flags |= DMA_SYNCING;
 
       audio_devs[dev]->dmap_out->underrun_count = 0;
-      while (!current_got_fatal_signal ()
+      while (!(current->signal & ~current->blocked)
             && audio_devs[dev]->dmap_out->qlen
             && audio_devs[dev]->dmap_out->underrun_count == 0)
        {
@@ -392,29 +507,29 @@ dma_sync (int dev)
          {
            unsigned long   tlimit;
 
-           if (HZ)
-             current_set_timeout (tlimit = jiffies + (HZ));
+           if (tmout)
+             current->timeout = tlimit = jiffies + (tmout);
            else
              tlimit = (unsigned long) -1;
-           out_sleep_flag[dev].flags = WK_SLEEP;
-           module_interruptible_sleep_on (&out_sleeper[dev]);
-           if (!(out_sleep_flag[dev].flags & WK_WAKEUP))
+           out_sleep_flag[dev].opts = WK_SLEEP;
+           interruptible_sleep_on (&out_sleeper[dev]);
+           if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
              {
                if (jiffies >= tlimit)
-                 out_sleep_flag[dev].flags |= WK_TIMEOUT;
+                 out_sleep_flag[dev].opts |= WK_TIMEOUT;
              }
-           out_sleep_flag[dev].flags &= ~WK_SLEEP;
+           out_sleep_flag[dev].opts &= ~WK_SLEEP;
          };
-         if ((out_sleep_flag[dev].flags & WK_TIMEOUT))
+         if ((out_sleep_flag[dev].opts & WK_TIMEOUT))
            {
              audio_devs[dev]->dmap_out->flags &= ~DMA_SYNCING;
              restore_flags (flags);
              return audio_devs[dev]->dmap_out->qlen;
            }
        }
-      audio_devs[dev]->dmap_out->flags &= ~DMA_SYNCING;
+      audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
+      audio_devs[dev]->dmap_out->flags |= DMA_RESTART;
       restore_flags (flags);
-
       /*
        * Some devices such as GUS have huge amount of on board RAM for the
        * audio data. We have to wait until the device has finished playing.
@@ -424,30 +539,31 @@ dma_sync (int dev)
       cli ();
       if (audio_devs[dev]->d->local_qlen)      /* Device has hidden buffers */
        {
-         while (!(current_got_fatal_signal ())
+         while (!((current->signal & ~current->blocked))
                 && audio_devs[dev]->d->local_qlen (dev))
            {
 
              {
                unsigned long   tlimit;
 
-               if (HZ)
-                 current_set_timeout (tlimit = jiffies + (HZ));
+               if (tmout)
+                 current->timeout = tlimit = jiffies + (tmout);
                else
                  tlimit = (unsigned long) -1;
-               out_sleep_flag[dev].flags = WK_SLEEP;
-               module_interruptible_sleep_on (&out_sleeper[dev]);
-               if (!(out_sleep_flag[dev].flags & WK_WAKEUP))
+               out_sleep_flag[dev].opts = WK_SLEEP;
+               interruptible_sleep_on (&out_sleeper[dev]);
+               if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
                  {
                    if (jiffies >= tlimit)
-                     out_sleep_flag[dev].flags |= WK_TIMEOUT;
+                     out_sleep_flag[dev].opts |= WK_TIMEOUT;
                  }
-               out_sleep_flag[dev].flags &= ~WK_SLEEP;
+               out_sleep_flag[dev].opts &= ~WK_SLEEP;
              };
            }
        }
       restore_flags (flags);
     }
+  audio_devs[dev]->dmap_out->dma_mode = DMODE_NONE;
   return audio_devs[dev]->dmap_out->qlen;
 }
 
@@ -459,10 +575,10 @@ DMAbuf_release (int dev, int mode)
   audio_devs[dev]->dmap_out->closing = 1;
   audio_devs[dev]->dmap_in->closing = 1;
 
-  if (!(current_got_fatal_signal ())
+  if (!((current->signal & ~current->blocked))
       && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT))
     {
-      dma_sync (dev);
+      DMAbuf_sync (dev);
     }
 
   if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)
@@ -505,18 +621,17 @@ activate_recording (int dev, struct dma_buffparms *dmap)
 
   if (dmap->dma_mode == DMODE_OUTPUT)  /* Direction change */
     {
-      dma_sync (dev);
-      dma_reset (dev);
+      DMAbuf_sync (dev);
+      DMAbuf_reset (dev);
       dmap->dma_mode = DMODE_NONE;
     }
 
-  if (!(dmap->flags & DMA_ALLOC_DONE))
-    reorganize_buffers (dev, dmap, 1);
 
   if (prepare || !dmap->dma_mode)
     {
       int             err;
 
+      reorganize_buffers (dev, dmap, 1);
       if ((err = audio_devs[dev]->d->prepare_for_input (dev,
                                     dmap->fragment_size, dmap->nbufs)) < 0)
        {
@@ -552,12 +667,19 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
   if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't read from mmapped device (1)\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
   else if (!dmap->qlen)
     {
       int             tmout;
 
+      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) ||
+         !audio_devs[dev]->go)
+       {
+         restore_flags (flags);
+         return -EAGAIN;
+       }
+
       if ((err = activate_recording (dev, dmap)) < 0)
        {
          restore_flags (flags);
@@ -569,39 +691,42 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
       if (dontblock)
        {
          restore_flags (flags);
-         return -(EAGAIN);
-       }
-
-      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) &
-         audio_devs[dev]->go)
-       {
-         restore_flags (flags);
-         return -(EAGAIN);
+         return -EAGAIN;
        }
 
       if (!audio_devs[dev]->go)
        tmout = 0;
       else
-       tmout = 10 * HZ;
+       {
+         tmout =
+           (dmap->fragment_size * HZ) / dmap->data_rate;
+
+         tmout += HZ / 10;     /* Some safety distance */
+
+         if (tmout < (HZ / 2))
+           tmout = HZ / 2;
+         if (tmout > 20 * HZ)
+           tmout = 20 * HZ;
+       }
 
 
       {
        unsigned long   tlimit;
 
        if (tmout)
-         current_set_timeout (tlimit = jiffies + (tmout));
+         current->timeout = tlimit = jiffies + (tmout);
        else
          tlimit = (unsigned long) -1;
-       in_sleep_flag[dev].flags = WK_SLEEP;
-       module_interruptible_sleep_on (&in_sleeper[dev]);
-       if (!(in_sleep_flag[dev].flags & WK_WAKEUP))
+       in_sleep_flag[dev].opts = WK_SLEEP;
+       interruptible_sleep_on (&in_sleeper[dev]);
+       if (!(in_sleep_flag[dev].opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             in_sleep_flag[dev].flags |= WK_TIMEOUT;
+             in_sleep_flag[dev].opts |= WK_TIMEOUT;
          }
-       in_sleep_flag[dev].flags &= ~WK_SLEEP;
+       in_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
-      if ((in_sleep_flag[dev].flags & WK_TIMEOUT))
+      if ((in_sleep_flag[dev].opts & WK_TIMEOUT))
        {
          printk ("Sound: DMA (input) timed out - IRQ/DRQ config error?\n");
          err = EIO;
@@ -614,7 +739,7 @@ DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
   restore_flags (flags);
 
   if (!dmap->qlen)
-    return -(err);
+    return -err;
 
   *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]];
   *len = dmap->fragment_size - dmap->counts[dmap->qhead];
@@ -632,7 +757,7 @@ DMAbuf_rmchars (int dev, int buff_no, int c)
   if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't read from mmapped device (2)\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
   else if (p >= dmap->fragment_size)
     {                          /* This buffer is completely empty */
@@ -657,21 +782,21 @@ dma_subdivide (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
       fact = dmap->subdivision;
       if (fact == 0)
        fact = 1;
-      return snd_ioctl_return ((int *) arg, fact);
+      return ioctl_out (arg, fact);
     }
 
   if (dmap->subdivision != 0 ||
       dmap->fragment_size)     /* Too late to change */
-    return -(EINVAL);
+    return -EINVAL;
 
   if (fact > MAX_REALTIME_FACTOR)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (fact != 1 && fact != 2 && fact != 4 && fact != 8 && fact != 16)
-    return -(EINVAL);
+    return -EINVAL;
 
   dmap->subdivision = fact;
-  return snd_ioctl_return ((int *) arg, fact);
+  return ioctl_out (arg, fact);
 }
 
 static int
@@ -680,11 +805,11 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
   int             bytes, count;
 
   if (fact == 0)
-    return -(EIO);
+    return -EIO;
 
   if (dmap->subdivision != 0 ||
       dmap->fragment_size)     /* Too late to change */
-    return -(EINVAL);
+    return -EINVAL;
 
   bytes = fact & 0xffff;
   count = (fact >> 16) & 0x7fff;
@@ -693,10 +818,10 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
     count = MAX_SUB_BUFFERS;
 
   if (bytes < 4 || bytes > 17) /* <16 || > 512k */
-    return -(EINVAL);
+    return -EINVAL;
 
   if (count < 2)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (audio_devs[dev]->min_fragment > 0)
     if (bytes < audio_devs[dev]->min_fragment)
@@ -719,7 +844,7 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
 
   dmap->subdivision = 1;       /* Disable SNDCTL_DSP_SUBDIVIDE */
   if (arg)
-    return snd_ioctl_return ((int *) arg, bytes | (count << 16));
+    return ioctl_out (arg, bytes | (count << 16));
   else
     return 0;
 }
@@ -727,6 +852,10 @@ dma_set_fragment (int dev, struct dma_buffparms *dmap, caddr_t arg, int fact)
 static int
 get_buffer_pointer (int dev, int chan, struct dma_buffparms *dmap)
 {
+/*
+ * Try to approximate the active byte position of the DMA pointer within the
+ * buffer area as well as possible.
+ */
   int             pos;
   unsigned long   flags;
 
@@ -739,20 +868,19 @@ get_buffer_pointer (int dev, int chan, struct dma_buffparms *dmap)
       clear_dma_ff (chan);
       disable_dma (chan);
       pos = get_dma_residue (chan);
+      if (chan > 3)            /* Word count */
+       pos *= 2;
+      pos = dmap->bytes_in_use - pos;
+      if (pos < 0)
+       pos = 0;
+      if (pos > dmap->bytes_in_use)
+       pos = dmap->bytes_in_use;
       enable_dma (chan);
     }
   restore_flags (flags);
   /* printk ("%04x ", pos); */
 
-  if (audio_devs[dev]->flags & DMA_AUTOMODE)
-    return dmap->bytes_in_use - pos;
-  else
-    {
-      pos = dmap->fragment_size - pos;
-      if (pos < 0)
-       return 0;
-      return pos;
-    }
+  return pos;
 }
 
 
@@ -761,56 +889,9 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
   struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
   struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
-  long            larg = (long) arg;
 
   switch (cmd)
     {
-    case SOUND_PCM_WRITE_RATE:
-      if (local)
-       return audio_devs[dev]->d->set_speed (dev, larg);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_speed (dev, get_user ((int *) arg)));
-
-    case SOUND_PCM_READ_RATE:
-      if (local)
-       return audio_devs[dev]->d->set_speed (dev, 0);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_speed (dev, 0));
-
-    case SNDCTL_DSP_STEREO:
-      if (local)
-       return audio_devs[dev]->d->set_channels (dev, larg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, get_user ((int *) arg) + 1) - 1);
-
-    case SOUND_PCM_WRITE_CHANNELS:
-      if (local)
-       return audio_devs[dev]->d->set_channels (dev, (short) larg);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, get_user ((int *) arg)));
-
-    case SOUND_PCM_READ_CHANNELS:
-      if (local)
-       return audio_devs[dev]->d->set_channels (dev, 0);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_channels (dev, 0));
-
-    case SNDCTL_DSP_SAMPLESIZE:
-      if (local)
-       return audio_devs[dev]->d->set_bits (dev, larg);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_bits (dev, get_user ((int *) arg)));
-
-    case SOUND_PCM_READ_BITS:
-      if (local)
-       return audio_devs[dev]->d->set_bits (dev, 0);
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->d->set_bits (dev, 0));
-
-    case SNDCTL_DSP_RESET:
-      dma_reset (dev);
-      return 0;
-      break;
-
-    case SNDCTL_DSP_SYNC:
-      dma_sync (dev);
-      dma_reset (dev);
-      return 0;
-      break;
-
     case SNDCTL_DSP_GETBLKSIZE:
       if (!(dmap_out->flags & DMA_ALLOC_DONE))
        {
@@ -822,14 +903,19 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
                                (audio_devs[dev]->open_mode == OPEN_READ));
        }
 
-      return snd_ioctl_return ((int *) arg, dmap_out->fragment_size);
+      if (local)
+       return dmap_out->fragment_size;
+      else
+       return ioctl_out (arg, dmap_out->fragment_size);
       break;
 
     case SNDCTL_DSP_SUBDIVIDE:
       {
-       int             fact = get_user ((int *) arg);
+       int             fact;
        int             ret;
 
+       get_user (fact, (int *) arg);
+
        ret = dma_subdivide (dev, dmap_out, arg, fact);
        if (ret < 0)
          return ret;
@@ -842,18 +928,12 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
       }
       break;
 
-    case SNDCTL_DSP_SETDUPLEX:
-      if (audio_devs[dev]->flags & DMA_DUPLEX)
-       return 0;
-      else
-       return -(EIO);
-      break;
-
     case SNDCTL_DSP_SETFRAGMENT:
       {
-       int             fact = get_user ((int *) arg);
+       int             fact;
        int             ret;
 
+       get_user (fact, (int *) arg);
        ret = dma_set_fragment (dev, dmap_out, arg, fact);
        if (ret < 0)
          return ret;
@@ -869,7 +949,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
     case SNDCTL_DSP_GETISPACE:
     case SNDCTL_DSP_GETOSPACE:
       if (!local)
-       return -(EINVAL);
+       return -EINVAL;
       else
        {
          struct dma_buffparms *dmap = dmap_out;
@@ -878,13 +958,13 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 
          if (cmd == SNDCTL_DSP_GETISPACE &&
              !(audio_devs[dev]->open_mode & OPEN_READ))
-           return -(EINVAL);
+           return -EINVAL;
 
          if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX)
            dmap = dmap_in;
 
          if (dmap->mapping_flags & DMA_MAP_MAPPED)
-           return -(EINVAL);
+           return -EINVAL;
 
          if (!(dmap->flags & DMA_ALLOC_DONE))
            reorganize_buffers (dev, dmap, (cmd == SNDCTL_DSP_GETISPACE));
@@ -930,17 +1010,20 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
       {
        unsigned long   flags;
 
-       int             bits = get_user ((int *) arg) & audio_devs[dev]->open_mode;
+       int             bits;
        int             changed;
 
+       get_user (bits, (int *) arg);
+       bits &= audio_devs[dev]->open_mode;
+
        if (audio_devs[dev]->d->trigger == NULL)
-         return -(EINVAL);
+         return -EINVAL;
 
        if (!(audio_devs[dev]->flags & DMA_DUPLEX))
          if ((bits & PCM_ENABLE_INPUT) && (bits & PCM_ENABLE_OUTPUT))
            {
              printk ("Sound: Device doesn't have full duplex capability\n");
-             return -(EINVAL);
+             return -EINVAL;
            }
 
        save_flags (flags);
@@ -951,36 +1034,31 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
          {
            int             err;
 
-           if (!(dmap_in->flags & DMA_ALLOC_DONE))
-             {
-               reorganize_buffers (dev, dmap_in, 1);
-             }
+           reorganize_buffers (dev, dmap_in, 1);
 
            if ((err = audio_devs[dev]->d->prepare_for_input (dev,
                               dmap_in->fragment_size, dmap_in->nbufs)) < 0)
-             return -(err);
+             return -err;
 
            audio_devs[dev]->enable_bits = bits;
            activate_recording (dev, dmap_in);
          }
 
+
        if ((changed & bits) & PCM_ENABLE_OUTPUT &&
            dmap_out->mapping_flags & DMA_MAP_MAPPED &&
            audio_devs[dev]->go)
          {
-           int             err;
 
            if (!(dmap_out->flags & DMA_ALLOC_DONE))
              {
                reorganize_buffers (dev, dmap_out, 0);
              }
 
-           if ((err = audio_devs[dev]->d->prepare_for_output (dev,
-                            dmap_out->fragment_size, dmap_out->nbufs)) < 0)
-             return -(err);
-
+           ;
            dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size;
-           DMAbuf_start_output (dev, 0, dmap_out->fragment_size);
+           launch_output (dev, dmap_out);
+           ;
          }
 
        audio_devs[dev]->enable_bits = bits;
@@ -991,13 +1069,13 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
        restore_flags (flags);
       }
     case SNDCTL_DSP_GETTRIGGER:
-      return snd_ioctl_return ((int *) arg, audio_devs[dev]->enable_bits);
+      return ioctl_out (arg, audio_devs[dev]->enable_bits);
       break;
 
     case SNDCTL_DSP_SETSYNCRO:
 
       if (!audio_devs[dev]->d->trigger)
-       return -(EINVAL);
+       return -EINVAL;
 
       audio_devs[dev]->d->trigger (dev, 0);
       audio_devs[dev]->go = 0;
@@ -1010,7 +1088,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
        unsigned long   flags;
 
        if (!(audio_devs[dev]->open_mode & OPEN_READ))
-         return -(EINVAL);
+         return -EINVAL;
 
        save_flags (flags);
        cli ();
@@ -1018,7 +1096,11 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
        info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan2, audio_devs[dev]->dmap_in);
        info.blocks = audio_devs[dev]->dmap_in->qlen;
        info.bytes += info.ptr;
-       copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+       {
+         char           *fixit = (char *) &info;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+       };
 
        if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
          audio_devs[dev]->dmap_in->qlen = 0;   /* Acknowledge interrupts */
@@ -1033,7 +1115,7 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
        unsigned long   flags;
 
        if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
-         return -(EINVAL);
+         return -EINVAL;
 
        save_flags (flags);
        cli ();
@@ -1041,7 +1123,11 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
        info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan1, audio_devs[dev]->dmap_out);
        info.blocks = audio_devs[dev]->dmap_out->qlen;
        info.bytes += info.ptr;
-       copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+       {
+         char           *fixit = (char *) &info;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+       };
 
        if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
          audio_devs[dev]->dmap_out->qlen = 0;  /* Acknowledge interrupts */
@@ -1051,6 +1137,15 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
       break;
 
 
+    case SNDCTL_DSP_POST:
+      ;
+      if (audio_devs[dev]->dmap_out->qlen > 0)
+       if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE))
+         launch_output (dev, audio_devs[dev]->dmap_out);
+      ;
+      return 0;
+      break;
+
     default:
       return audio_devs[dev]->d->ioctl (dev, cmd, arg, local);
     }
@@ -1062,6 +1157,21 @@ DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
  * one or more audio devices at desired moment.
  */
 
+void
+DMAbuf_start_device (int dev)
+{
+  if (audio_devs[dev]->open_mode != 0)
+    if (!audio_devs[dev]->go)
+      {
+       /* OK to start the device */
+       audio_devs[dev]->go = 1;
+
+       if (audio_devs[dev]->d->trigger)
+         audio_devs[dev]->d->trigger (dev,
+                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
+      }
+}
+
 void
 DMAbuf_start_devices (unsigned int devmask)
 {
@@ -1069,16 +1179,7 @@ DMAbuf_start_devices (unsigned int devmask)
 
   for (dev = 0; dev < num_audiodevs; dev++)
     if (devmask & (1 << dev))
-      if (audio_devs[dev]->open_mode != 0)
-       if (!audio_devs[dev]->go)
-         {
-           /* OK to start the device */
-           audio_devs[dev]->go = 1;
-
-           if (audio_devs[dev]->d->trigger)
-             audio_devs[dev]->d->trigger (dev,
-                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
-         }
+      DMAbuf_start_device (dev);
 }
 
 static int
@@ -1087,12 +1188,18 @@ space_in_queue (int dev)
   int             len, max, tmp;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
 
-  if (dmap->qlen >= dmap->nbufs)       /* No space at all */
+  /* Don't allow touching pages too close to the playing ones */
+  int             lim = dmap->nbufs - 1;
+
+  if (lim < 2)
+    lim = 2;
+
+  if (dmap->qlen >= lim)       /* No space at all */
     return 0;
 
   /*
-     * Verify that there are no more pending buffers than the limit
-     * defined by the process.
+   * Verify that there are no more pending buffers than the limit
+   * defined by the process.
    */
 
   max = dmap->max_fragments;
@@ -1103,7 +1210,7 @@ space_in_queue (int dev)
       tmp = audio_devs[dev]->d->local_qlen (dev);
       if (tmp && len)
        tmp--;                  /*
-                                  * This buffer has been counted twice
+                                * This buffer has been counted twice
                                 */
       len += tmp;
     }
@@ -1125,29 +1232,28 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
   if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
     {
       printk ("Sound: Can't write to mmapped device (3)\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (dmap->dma_mode == DMODE_INPUT)   /* Direction change */
     {
-      dma_reset (dev);
+      DMAbuf_reset (dev);
       dmap->dma_mode = DMODE_NONE;
     }
   else if (dmap->flags & DMA_RESTART)  /* Restart buffering */
     {
-      dma_sync (dev);
+      DMAbuf_sync (dev);
       dma_reset_output (dev);
+      dmap->dma_mode = DMODE_NONE;
     }
 
   dmap->flags &= ~(DMA_RESTART | DMA_EMPTY);
 
-  if (!(dmap->flags & DMA_ALLOC_DONE))
-    reorganize_buffers (dev, dmap, 0);
-
   if (!dmap->dma_mode)
     {
       int             err;
 
+      reorganize_buffers (dev, dmap, 0);
       dmap->dma_mode = DMODE_OUTPUT;
       if ((err = audio_devs[dev]->d->prepare_for_output (dev,
                                     dmap->fragment_size, dmap->nbufs)) < 0)
@@ -1166,14 +1272,13 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
       if (dontblock)
        {
          restore_flags (flags);
-         return -(EAGAIN);
+         return -EAGAIN;
        }
 
-      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT) &&
-         audio_devs[dev]->go)
+      if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT))
        {
          restore_flags (flags);
-         return -(EAGAIN);
+         return -EAGAIN;
        }
 
       /*
@@ -1182,26 +1287,36 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
       if (!audio_devs[dev]->go)
        tmout = 0;
       else
-       tmout = 10 * HZ;
+       {
+         tmout =
+           (dmap->fragment_size * HZ) / dmap->data_rate;
+
+         tmout += HZ / 10;     /* Some safety distance */
+
+         if (tmout < (HZ / 2))
+           tmout = HZ / 2;
+         if (tmout > 20 * HZ)
+           tmout = 20 * HZ;
+       }
 
 
       {
        unsigned long   tlimit;
 
        if (tmout)
-         current_set_timeout (tlimit = jiffies + (tmout));
+         current->timeout = tlimit = jiffies + (tmout);
        else
          tlimit = (unsigned long) -1;
-       out_sleep_flag[dev].flags = WK_SLEEP;
-       module_interruptible_sleep_on (&out_sleeper[dev]);
-       if (!(out_sleep_flag[dev].flags & WK_WAKEUP))
+       out_sleep_flag[dev].opts = WK_SLEEP;
+       interruptible_sleep_on (&out_sleeper[dev]);
+       if (!(out_sleep_flag[dev].opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             out_sleep_flag[dev].flags |= WK_TIMEOUT;
+             out_sleep_flag[dev].opts |= WK_TIMEOUT;
          }
-       out_sleep_flag[dev].flags &= ~WK_SLEEP;
+       out_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
-      if ((out_sleep_flag[dev].flags & WK_TIMEOUT))
+      if ((out_sleep_flag[dev].opts & WK_TIMEOUT))
        {
          printk ("Sound: DMA (output) timed out - IRQ/DRQ config error?\n");
          err = EIO;
@@ -1213,7 +1328,7 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
            dmap->flags &= ~DMA_RESTART;
          audio_devs[dev]->d->reset (dev);
        }
-      else if (current_got_fatal_signal ())
+      else if ((current->signal & ~current->blocked))
        {
          err = EINTR;
          abort = 1;
@@ -1223,7 +1338,7 @@ DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
 
   if (!space_in_queue (dev))
     {
-      return -(err);           /* Caught a signal ? */
+      return -err;             /* Caught a signal ? */
     }
 
   *buf = dmap->raw_buf + dmap->qtail * dmap->fragment_size;
@@ -1267,6 +1382,11 @@ DMAbuf_start_output (int dev, int buff_no, int l)
 {
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
   int             restart = 0;
+  int             post = dmap->flags & DMA_POST;
+
+  ;
+
+  dmap->flags &= ~DMA_POST;
 
   dmap->cfrag = -1;
   if (dmap->flags & DMA_RESTART)
@@ -1287,16 +1407,17 @@ DMAbuf_start_output (int dev, int buff_no, int l)
     {
 
       dmap->qlen++;
-      if (dmap->qlen <= 0 || dmap->qlen > dmap->nbufs)
-       printk ("\nSound: Audio queue2 corrupted for dev%d (%d/%d)\n",
-               dev, dmap->qlen, dmap->nbufs);
 
       dmap->counts[dmap->qtail] = l;
       if (l < dmap->fragment_size)
        {
          int             p = dmap->fragment_size * dmap->qtail;
 
+#if defined(PPC) || defined(sparc) || defined(HPPA)
+         dmap->neutral_byte = dmap->raw_buf[p + l - 2];
+#else
          dmap->neutral_byte = dmap->raw_buf[p + l - 1];
+#endif
 
          memset (dmap->raw_buf + p + l,
                  dmap->neutral_byte,
@@ -1306,35 +1427,20 @@ DMAbuf_start_output (int dev, int buff_no, int l)
        dmap->neutral_byte =
          dmap->raw_buf[dmap->fragment_size * dmap->qtail - 1];
 
-      if ((l != dmap->fragment_size) &&
-         ((audio_devs[dev]->flags & DMA_AUTOMODE) &&
-          audio_devs[dev]->flags & NEEDS_RESTART))
-       dmap->flags |= DMA_RESTART;
-      else
-       dmap->flags &= ~DMA_RESTART;
-
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
     }
 
-  if (!(dmap->flags & DMA_ACTIVE))
-    {
-      dmap->flags |= DMA_ACTIVE;
-
-      if (restart)
-       audio_devs[dev]->d->prepare_for_output (dev,
-                                         dmap->fragment_size, dmap->nbufs);
-
-      audio_devs[dev]->d->output_block (dev, dmap->raw_buf_phys +
-                                       dmap->qhead * dmap->fragment_size,
-                                       dmap->counts[dmap->qhead], 0,
-                                !(audio_devs[dev]->flags & DMA_AUTOMODE) ||
-                                       !(dmap->flags & DMA_STARTED));
-      dmap->flags |= DMA_STARTED;
-      if (audio_devs[dev]->d->trigger)
-       audio_devs[dev]->d->trigger (dev,
-                       audio_devs[dev]->enable_bits * audio_devs[dev]->go);
-    }
+  /* Delay playback until there are at least two fragments (to prevent hiccup) */
+  if (dmap->qlen > 1 || post ||
+      (dmap->qlen > 0 && dmap->nbufs <= 2) ||
+      (dmap->qlen > 0 && dmap->flags & DMA_SYNCING) ||
+      restart || l != dmap->fragment_size)
+    if (!(dmap->flags & DMA_ACTIVE))
+      {
+       launch_output (dev, dmap);
+      }
 
+  ;
   return 0;
 }
 
@@ -1343,7 +1449,6 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
 {
   int             chan;
   struct dma_buffparms *dmap;
-  unsigned long   flags;
 
   if (dma_mode == DMA_MODE_WRITE)
     {
@@ -1356,12 +1461,20 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
       dmap = audio_devs[dev]->dmap_in;
     }
 
-  if (dmap->raw_buf_phys == 0)
+  if (dmap->raw_buf == NULL)
     {
       printk ("sound: DMA buffer == NULL\n");
       return 0;
     }
 
+  /* Handle cards with non automode DMA in new way */
+  if (physaddr != dmap->raw_buf_phys)  /* Not fragment 0 */
+    return count;
+  count = dmap->bytes_in_use;
+
+  if (chan < 0)
+    return 0;
+
   /*
    * The count must be one less than the actual size. This is handled by
    * set_dma_addr()
@@ -1372,6 +1485,8 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
                                 * Auto restart mode. Transfer the whole *
                                 * buffer
                                 */
+      unsigned long   flags;
+
       save_flags (flags);
       cli ();
       disable_dma (chan);
@@ -1384,6 +1499,8 @@ DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
     }
   else
     {
+      unsigned long   flags;
+
       save_flags (flags);
       cli ();
       disable_dma (chan);
@@ -1421,34 +1538,11 @@ DMAbuf_init (void)
       }
 }
 
-static void
-polish_buffers (struct dma_buffparms *dmap)
-{
-  int             i;
-  int             p, l;
-
-  i = dmap->qhead;
-
-  p = dmap->fragment_size * i;
-
-  if (i == dmap->cfrag)
-    {
-      l = dmap->fragment_size - dmap->counts[i];
-    }
-  else
-    l = dmap->fragment_size;
-
-  if (l)
-    {
-      memset (dmap->raw_buf + p,
-             dmap->neutral_byte,
-             l);
-    }
-}
-
 static void
 force_restart (int dev, struct dma_buffparms *dmap)
 {
+  unsigned long   flags;
+
   if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
       audio_devs[dev]->d->halt_output)
     audio_devs[dev]->d->halt_output (dev);
@@ -1456,10 +1550,19 @@ force_restart (int dev, struct dma_buffparms *dmap)
     audio_devs[dev]->d->halt_xfer (dev);
 
   dmap->flags &= ~(DMA_ACTIVE | DMA_STARTED);
-  if (audio_devs[dev]->flags & DMA_AUTOMODE)
-    dmap->flags |= DMA_RESTART;
-  else
-    dmap->flags &= ~DMA_RESTART;
+  dmap->flags |= DMA_RESTART;
+  dmap->qlen = dmap->qhead = dmap->qtail = 0;
+
+  save_flags (flags);
+  cli ();
+  if ((out_sleep_flag[dev].opts & WK_SLEEP))
+    {
+      {
+       out_sleep_flag[dev].opts = WK_WAKEUP;
+       wake_up (&out_sleeper[dev]);
+      };
+    }
+  restore_flags (flags);
 }
 
 void
@@ -1479,10 +1582,9 @@ DMAbuf_outputintr (int dev, int event_type)
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
   int             this_fragment;
 
-  dmap->byte_counter += dmap->counts[dmap->qhead];
-
 #ifdef OS_DMA_INTR
-  sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
+  if (audio_devs[dev]->dmachan1 >= 0)
+    sound_dma_intr (dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1);
 #endif
 
   if (dmap->raw_buf == NULL)
@@ -1495,6 +1597,8 @@ DMAbuf_outputintr (int dev, int event_type)
     {
       /* mmapped access */
       dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+      if (dmap->qhead == 0)    /* Wrapped */
+       dmap->byte_counter += dmap->bytes_in_use;
       dmap->qlen++;            /* Yes increment it (don't decrement) */
       dmap->flags &= ~DMA_ACTIVE;
       dmap->counts[dmap->qhead] = dmap->fragment_size;
@@ -1517,46 +1621,27 @@ DMAbuf_outputintr (int dev, int event_type)
        {
          printk ("\nSound: Audio queue3 corrupted for dev%d (%d/%d)\n",
                  dev, dmap->qlen, dmap->nbufs);
+         force_restart (dev, dmap);
          return;
        }
 
+      save_flags (flags);
+      cli ();
+
       dmap->qlen--;
       this_fragment = dmap->qhead;
       dmap->qhead = (dmap->qhead + 1) % dmap->nbufs;
+
+      if (dmap->qhead == 0)    /* Wrapped */
+       dmap->byte_counter += dmap->bytes_in_use;
       dmap->flags &= ~DMA_ACTIVE;
 
       if (event_type == 1 && dmap->qlen < 1)
        {
          dmap->underrun_count++;
 
-         if ((!(dmap->flags & DMA_CLEAN) &&
-              (audio_devs[dev]->dmap_out->flags & DMA_SYNCING ||
-               dmap->underrun_count > 5 || dmap->flags & DMA_EMPTY)) ||
-             audio_devs[dev]->flags & DMA_HARDSTOP)
-
-           {
-             dmap->qlen = 0;
-             force_restart (dev, dmap);
-           }
-         else
-           /* Ignore underrun. Just move the tail pointer forward and go */
-         if (dmap->closing)
-           {
-             polish_buffers (dmap);
-             audio_devs[dev]->d->halt_xfer (dev);
-           }
-         else
-           {
-             dmap->qlen++;
-             dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
-
-             if (!(dmap->flags & DMA_EMPTY))
-               polish_buffers (dmap);
-
-             dmap->cfrag = -1;
-             dmap->flags |= DMA_EMPTY;
-             dmap->counts[dmap->qtail] = dmap->fragment_size;
-           }
+         dmap->qlen = 0;
+         force_restart (dev, dmap);
        }
 
       if (dmap->qlen)
@@ -1586,15 +1671,17 @@ DMAbuf_outputintr (int dev, int event_type)
            }
          dmap->flags |= DMA_ACTIVE;
        }
+
+      restore_flags (flags);
     }                          /* event_type != 2 */
 
   save_flags (flags);
   cli ();
-  if ((out_sleep_flag[dev].flags & WK_SLEEP))
+  if ((out_sleep_flag[dev].opts & WK_SLEEP))
     {
       {
-       out_sleep_flag[dev].flags = WK_WAKEUP;
-       module_wake_up (&out_sleeper[dev]);
+       out_sleep_flag[dev].opts = WK_WAKEUP;
+       wake_up (&out_sleeper[dev]);
       };
     }
   restore_flags (flags);
@@ -1606,10 +1693,9 @@ DMAbuf_inputintr (int dev)
   unsigned long   flags;
   struct dma_buffparms *dmap = audio_devs[dev]->dmap_in;
 
-  dmap->byte_counter += dmap->fragment_size;
-
 #ifdef OS_DMA_INTR
-  sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
+  if (audio_devs[dev]->dmachan2 >= 0)
+    sound_dma_intr (dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmachan2);
 #endif
 
   if (dmap->raw_buf == NULL)
@@ -1621,6 +1707,8 @@ DMAbuf_inputintr (int dev)
   if (dmap->mapping_flags & DMA_MAP_MAPPED)
     {
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      if (dmap->qtail == 0)    /* Wrapped */
+       dmap->byte_counter += dmap->bytes_in_use;
       dmap->qlen++;
 
       if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
@@ -1638,7 +1726,7 @@ DMAbuf_inputintr (int dev)
     }
   else if (dmap->qlen == (dmap->nbufs - 1))
     {
-      printk ("Sound: Recording overrun\n");
+      /* printk ("Sound: Recording overrun\n"); */
       dmap->underrun_count++;
 
       if (audio_devs[dev]->flags & DMA_AUTOMODE)
@@ -1664,6 +1752,8 @@ DMAbuf_inputintr (int dev)
        printk ("\nSound: Audio queue4 corrupted for dev%d (%d/%d)\n",
                dev, dmap->qlen, dmap->nbufs);
       dmap->qtail = (dmap->qtail + 1) % dmap->nbufs;
+      if (dmap->qtail == 0)    /* Wrapped */
+       dmap->byte_counter += dmap->bytes_in_use;
     }
 
   if (!(audio_devs[dev]->flags & DMA_AUTOMODE))
@@ -1681,11 +1771,11 @@ DMAbuf_inputintr (int dev)
 
   save_flags (flags);
   cli ();
-  if ((in_sleep_flag[dev].flags & WK_SLEEP))
+  if ((in_sleep_flag[dev].opts & WK_SLEEP))
     {
       {
-       in_sleep_flag[dev].flags = WK_WAKEUP;
-       module_wake_up (&in_sleeper[dev]);
+       in_sleep_flag[dev].opts = WK_WAKEUP;
+       wake_up (&in_sleeper[dev]);
       };
     }
   restore_flags (flags);
@@ -1702,19 +1792,22 @@ DMAbuf_open_dma (int dev)
   int             err;
   unsigned long   flags;
 
-  if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, audio_devs[dev]->dmachan1)) < 0)
+  if ((err = open_dmap (dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, chan)) < 0)
     {
-      return -(EBUSY);
+      return -EBUSY;
     }
   dma_init_buffers (dev, audio_devs[dev]->dmap_out);
   audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE;
   audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->buffsize;
 
-  save_flags (flags);
-  cli ();
-  disable_dma (chan);
-  clear_dma_ff (chan);
-  restore_flags (flags);
+  if (chan >= 0)
+    {
+      save_flags (flags);
+      cli ();
+      disable_dma (chan);
+      clear_dma_ff (chan);
+      restore_flags (flags);
+    }
 
   return 0;
 }
@@ -1732,7 +1825,7 @@ DMAbuf_reset_dma (int dev)
 }
 
 int
-DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   struct dma_buffparms *dmap;
   unsigned long   flags;
@@ -1740,6 +1833,9 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle
   switch (sel_type)
     {
     case SEL_IN:
+      if (!(audio_devs[dev]->open_mode))
+       return 0;
+
       dmap = audio_devs[dev]->dmap_in;
 
       if (dmap->mapping_flags & DMA_MAP_MAPPED)
@@ -1750,16 +1846,17 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle
          save_flags (flags);
          cli ();
 
-         in_sleep_flag[dev].flags = WK_SLEEP;
-         module_select_wait (&in_sleeper[dev], wait);
+         in_sleep_flag[dev].opts = WK_SLEEP;
+         select_wait (&in_sleeper[dev], wait);
          restore_flags (flags);
          return 0;
        }
 
       if (dmap->dma_mode != DMODE_INPUT)
        {
-         if ((audio_devs[dev]->flags & DMA_DUPLEX) && !dmap->qlen &&
+         if (dmap->dma_mode == DMODE_NONE &&
              audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT &&
+             !dmap->qlen &&
              audio_devs[dev]->go)
            {
              unsigned long   flags;
@@ -1777,8 +1874,8 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle
          save_flags (flags);
          cli ();
 
-         in_sleep_flag[dev].flags = WK_SLEEP;
-         module_select_wait (&in_sleeper[dev], wait);
+         in_sleep_flag[dev].opts = WK_SLEEP;
+         select_wait (&in_sleeper[dev], wait);
          restore_flags (flags);
          return 0;
        }
@@ -1796,8 +1893,8 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle
          save_flags (flags);
          cli ();
 
-         out_sleep_flag[dev].flags = WK_SLEEP;
-         module_select_wait (&out_sleeper[dev], wait);
+         out_sleep_flag[dev].opts = WK_SLEEP;
+         select_wait (&out_sleeper[dev], wait);
          restore_flags (flags);
          return 0;
        }
@@ -1817,8 +1914,8 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle
          save_flags (flags);
          cli ();
 
-         out_sleep_flag[dev].flags = WK_SLEEP;
-         module_select_wait (&out_sleeper[dev], wait);
+         out_sleep_flag[dev].opts = WK_SLEEP;
+         select_wait (&out_sleeper[dev], wait);
          restore_flags (flags);
          return 0;
        }
@@ -1841,7 +1938,7 @@ DMAbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle
 int
 DMAbuf_open (int dev, int mode)
 {
-  return -(ENXIO);
+  return -ENXIO;
 }
 
 int
@@ -1853,31 +1950,31 @@ DMAbuf_release (int dev, int mode)
 int
 DMAbuf_getwrbuffer (int dev, char **buf, int *size, int dontblock)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_getrdbuffer (int dev, char **buf, int *len, int dontblock)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_rmchars (int dev, int buff_no, int c)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_start_output (int dev, int buff_no, int l)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 void
@@ -1888,13 +1985,13 @@ DMAbuf_init (void)
 int
 DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode)
 {
-  return -(EIO);
+  return -EIO;
 }
 
 int
 DMAbuf_open_dma (int dev)
 {
-  return -(ENXIO);
+  return -ENXIO;
 }
 
 void
diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c
deleted file mode 100644 (file)
index 2a2e6b8..0000000
+++ /dev/null
@@ -1,3252 +0,0 @@
-
-/* linux/drivers/sound/dmasound.c */
-
-/*
-
-VoxWare compatible Atari TT DMA sound driver for 680x0 Linux
-
-(c) 1995 by Michael Schlueter & Michael Marte
-
-Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS
-interface and the u-law to signed byte conversion.
-
-Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue,
-/dev/mixer, /dev/sndstat and complemented the VFS interface. He would like
-to thank:
-Michael Schlueter for initial ideas and documentation on the MFP and
-the DMA sound hardware.
-Therapy? for their CD 'Troublegum' which really made me rock.
-
-/dev/sndstat is based on code by Hannu Savolainen, the author of the
-VoxWare family of drivers.
-
-This file is subject to the terms and conditions of the GNU General Public
-License.  See the file COPYING in the main directory of this archive
-for more details.
-
-History:
-1995/8/25      first release
-
-1995/9/02      ++roman: fixed atari_stram_alloc() call, the timer programming
-                       and several race conditions
-
-1995/9/14      ++roman: After some discussion with Michael Schlueter, revised
-                       the interrupt disabling
-                       Slightly speeded up U8->S8 translation by using long
-                       operations where possible
-                       Added 4:3 interpolation for /dev/audio
-
-1995/9/20      ++TeSche: Fixed a bug in sq_write and changed /dev/audio
-                       converting to play at 12517Hz instead of 6258Hz.
-
-1995/9/23      ++TeSche: Changed sq_interrupt() and sq_play() to pre-program
-                       the DMA for another frame while there's still one
-                       running. This allows the IRQ response to be
-                       arbitrarily delayed and playing will still continue.
-
-1995/10/14     ++Guenther_Kelleter@ac3.maus.de, ++TeSche: better support for
-                       Falcon audio (the Falcon doesn't raise an IRQ at the
-                       end of a frame, but at the beginning instead!). uses
-                       'if (codec_dma)' in lots of places to simply switch
-                       between Falcon and TT code.
-
-1995/11/06     ++TeSche: started introducing a hardware abstraction scheme
-                       (may perhaps also serve for Amigas?), can now play
-                       samples at almost all frequencies by means of a more
-                       generalized expand routine, takes a good deal of care
-                       to cut data only at sample sizes, buffer size is now
-                       a kernel runtime option, implemented fsync() & several
-                       minor improvements
-               ++Guenther: useful hints and bug fixes, cross-checked it for
-                       Falcons
-
-1996/3/9       ++geert: support added for Amiga, A-law, 16-bit little endian.
-                       Unification to drivers/sound/dmasound.c.
-1996/4/6       ++Martin Mitchell: updated to 1.3 kernel.
-*/
-
-
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/major.h>
-#include <linux/config.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_ATARI
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#endif /* CONFIG_AMIGA */
-
-#include "dmasound.h"
-#include <linux/soundcard.h>
-
-
-#ifdef CONFIG_ATARI
-extern void atari_microwire_cmd(int cmd);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-   /*
-    *  The minimum period for audio depends on total (for OCS/ECS/AGA)
-    *  (Imported from arch/m68k/amiga/amisound.c)
-    */
-
-extern volatile u_short amiga_audio_min_period;
-
-
-   /*
-    *  amiga_mksound() should be able to restore the period after beeping
-    *  (Imported from arch/m68k/amiga/amisound.c)
-    */
-
-extern u_short amiga_audio_period;
-
-
-   /*
-    *  Audio DMA masks
-    */
-
-#define AMI_AUDIO_OFF  (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
-#define AMI_AUDIO_8    (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
-#define AMI_AUDIO_14   (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
-
-#endif /* CONFIG_AMIGA */
-
-
-/*** Some declarations *******************************************************/
-
-
-#define DMASND_TT              1
-#define DMASND_FALCON          2
-#define DMASND_AMIGA           3
-
-#define MAX_CATCH_RADIUS       10
-#define MIN_BUFFERS            4
-#define MIN_BUFSIZE            4
-#define MAX_BUFSIZE            128     /* Limit for Amiga */
-
-static int catchRadius = 0, numBufs = 4, bufSize = 32;
-
-
-#define arraysize(x)   (sizeof(x)/sizeof(*(x)))
-#define min(x, y)      ((x) < (y) ? (x) : (y))
-#define le2be16(x)     (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
-#define le2be16dbl(x)  (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
-
-#define IOCTL_IN(arg)          get_user((int *)(arg))
-#define IOCTL_OUT(arg, ret)    ioctl_return((int *)arg, ret)
-
-
-/*** Some low level helpers **************************************************/
-
-
-/* 8 bit mu-law */
-
-static char ulaw2dma8[] = {
-    -126,   -122,   -118,   -114,   -110,   -106,   -102,    -98,
-     -94,    -90,    -86,    -82,    -78,    -74,    -70,    -66,
-     -63,    -61,    -59,    -57,    -55,    -53,    -51,    -49,
-     -47,    -45,    -43,    -41,    -39,    -37,    -35,    -33,
-     -31,    -30,    -29,    -28,    -27,    -26,    -25,    -24,
-     -23,    -22,    -21,    -20,    -19,    -18,    -17,    -16,
-     -16,    -15,    -15,    -14,    -14,    -13,    -13,    -12,
-     -12,    -11,    -11,    -10,    -10,     -9,     -9,     -8,
-      -8,     -8,     -7,     -7,     -7,     -7,     -6,     -6,
-      -6,     -6,     -5,     -5,     -5,     -5,     -4,     -4,
-      -4,     -4,     -4,     -4,     -3,     -3,     -3,     -3,
-      -3,     -3,     -3,     -3,     -2,     -2,     -2,     -2,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,      0,
-     125,    121,    117,    113,    109,    105,    101,     97,
-      93,     89,     85,     81,     77,     73,     69,     65,
-      62,     60,     58,     56,     54,     52,     50,     48,
-      46,     44,     42,     40,     38,     36,     34,     32,
-      30,     29,     28,     27,     26,     25,     24,     23,
-      22,     21,     20,     19,     18,     17,     16,     15,
-      15,     14,     14,     13,     13,     12,     12,     11,
-      11,     10,     10,      9,      9,      8,      8,      7,
-       7,      7,      6,      6,      6,      6,      5,      5,
-       5,      5,      4,      4,      4,      4,      3,      3,
-       3,      3,      3,      3,      2,      2,      2,      2,
-       2,      2,      2,      2,      1,      1,      1,      1,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0
-};
-
-/* 8 bit A-law */
-
-static char alaw2dma8[] = {
-     -22,    -21,    -24,    -23,    -18,    -17,    -20,    -19,
-     -30,    -29,    -32,    -31,    -26,    -25,    -28,    -27,
-     -11,    -11,    -12,    -12,     -9,     -9,    -10,    -10,
-     -15,    -15,    -16,    -16,    -13,    -13,    -14,    -14,
-     -86,    -82,    -94,    -90,    -70,    -66,    -78,    -74,
-    -118,   -114,   -126,   -122,   -102,    -98,   -110,   -106,
-     -43,    -41,    -47,    -45,    -35,    -33,    -39,    -37,
-     -59,    -57,    -63,    -61,    -51,    -49,    -55,    -53,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -6,     -6,     -6,     -6,     -5,     -5,     -5,     -5,
-      -8,     -8,     -8,     -8,     -7,     -7,     -7,     -7,
-      -3,     -3,     -3,     -3,     -3,     -3,     -3,     -3,
-      -4,     -4,     -4,     -4,     -4,     -4,     -4,     -4,
-      21,     20,     23,     22,     17,     16,     19,     18,
-      29,     28,     31,     30,     25,     24,     27,     26,
-      10,     10,     11,     11,      8,      8,      9,      9,
-      14,     14,     15,     15,     12,     12,     13,     13,
-      86,     82,     94,     90,     70,     66,     78,     74,
-     118,    114,    126,    122,    102,     98,    110,    106,
-      43,     41,     47,     45,     35,     33,     39,     37,
-      59,     57,     63,     61,     51,     49,     55,     53,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       5,      5,      5,      5,      4,      4,      4,      4,
-       7,      7,      7,      7,      6,      6,      6,      6,
-       2,      2,      2,      2,      2,      2,      2,      2,
-       3,      3,      3,      3,      3,      3,      3,      3
-};
-
-
-#ifdef HAS_16BIT_TABLES
-
-/* 16 bit mu-law */
-
-static char ulaw2dma16[] = {
-    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
-    -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
-    -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
-    -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
-     -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
-     -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
-     -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
-     -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
-     -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
-     -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
-      -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
-      -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
-      -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
-      -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
-      -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
-       -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
-     32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
-     23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
-     15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
-     11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
-      7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
-      5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
-      3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
-      2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
-      1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
-      1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
-       876,    844,    812,    780,    748,    716,    684,    652,
-       620,    588,    556,    524,    492,    460,    428,    396,
-       372,    356,    340,    324,    308,    292,    276,    260,
-       244,    228,    212,    196,    180,    164,    148,    132,
-       120,    112,    104,     96,     88,     80,     72,     64,
-        56,     48,     40,     32,     24,     16,      8,      0,
-};
-
-/* 16 bit A-law */
-
-static char alaw2dma16[] = {
-     -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
-     -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
-     -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
-     -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
-    -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
-    -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
-    -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
-    -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
-      -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
-      -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
-       -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
-      -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
-     -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
-     -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
-      -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
-      -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
-      5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
-      7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
-      2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
-      3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
-     22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
-     30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
-     11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
-     15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
-       344,    328,    376,    360,    280,    264,    312,    296,
-       472,    456,    504,    488,    408,    392,    440,    424,
-        88,     72,    120,    104,     24,      8,     56,     40,
-       216,    200,    248,    232,    152,    136,    184,    168,
-      1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
-      1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
-       688,    656,    752,    720,    560,    528,    624,    592,
-       944,    912,   1008,    976,    816,    784,    880,    848,
-};
-#endif /* HAS_16BIT_TABLES */
-
-
-#ifdef HAS_14BIT_TABLES
-
-/* 14 bit mu-law (LSB) */
-
-static char alaw2dma14l[] = {
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-         1,      1,      1,      1,      1,      1,      1,      1,
-         1,      1,      1,      1,      1,      1,      1,      1,
-        49,     17,     49,     17,     49,     17,     49,     17,
-        49,     17,     49,     17,     49,     17,     49,     17,
-        41,     57,      9,     25,     41,     57,      9,     25,
-        41,     57,      9,     25,     41,     57,      9,     25,
-        37,     45,     53,     61,      5,     13,     21,     29,
-        37,     45,     53,     61,      5,     13,     21,     29,
-        35,     39,     43,     47,     51,     55,     59,     63,
-         3,      7,     11,     15,     19,     23,     27,     31,
-        34,     36,     38,     40,     42,     44,     46,     48,
-        50,     52,     54,     56,     58,     60,     62,      0,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        63,     63,     63,     63,     63,     63,     63,     63,
-        63,     63,     63,     63,     63,     63,     63,     63,
-        15,     47,     15,     47,     15,     47,     15,     47,
-        15,     47,     15,     47,     15,     47,     15,     47,
-        23,      7,     55,     39,     23,      7,     55,     39,
-        23,      7,     55,     39,     23,      7,     55,     39,
-        27,     19,     11,      3,     59,     51,     43,     35,
-        27,     19,     11,      3,     59,     51,     43,     35,
-        29,     25,     21,     17,     13,      9,      5,      1,
-        61,     57,     53,     49,     45,     41,     37,     33,
-        30,     28,     26,     24,     22,     20,     18,     16,
-        14,     12,     10,      8,      6,      4,      2,      0
-};
-
-/* 14 bit A-law (LSB) */
-
-static char alaw2dma14l[] = {
-        32,     32,     32,     32,     32,     32,     32,     32,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        16,     48,     16,     48,     16,     48,     16,     48,
-        16,     48,     16,     48,     16,     48,     16,     48,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-        42,     46,     34,     38,     58,     62,     50,     54,
-        10,     14,      2,      6,     26,     30,     18,     22,
-        42,     46,     34,     38,     58,     62,     50,     54,
-        10,     14,      2,      6,     26,     30,     18,     22,
-        40,     56,      8,     24,     40,     56,      8,     24,
-        40,     56,      8,     24,     40,     56,      8,     24,
-        20,     28,      4,     12,     52,     60,     36,     44,
-        20,     28,      4,     12,     52,     60,     36,     44,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        48,     16,     48,     16,     48,     16,     48,     16,
-        48,     16,     48,     16,     48,     16,     48,     16,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-        22,     18,     30,     26,      6,      2,     14,     10,
-        54,     50,     62,     58,     38,     34,     46,     42,
-        22,     18,     30,     26,      6,      2,     14,     10,
-        54,     50,     62,     58,     38,     34,     46,     42,
-        24,      8,     56,     40,     24,      8,     56,     40,
-        24,      8,     56,     40,     24,      8,     56,     40,
-        44,     36,     60,     52,     12,      4,     28,     20,
-        44,     36,     60,     52,     12,      4,     28,     20
-};
-#endif /* HAS_14BIT_TABLES */
-
-
-/*** Translations ************************************************************/
-
-
-#ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft);
-static long ata_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft);
-static long ata_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft);
-static long ata_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ata_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ata_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ata_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ata_ctx_law(const u_char *userPtr, long userCount, u_char frame[],
-                       long *frameUsed, long frameLeft);
-static long ata_ctx_s8(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft);
-static long ata_ctx_u8(const u_char *userPtr, long userCount, u_char frame[],
-                       long *frameUsed, long frameLeft);
-static long ata_ctx_s16be(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft);
-static long ata_ctx_u16be(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft);
-static long ata_ctx_s16le(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft);
-static long ata_ctx_u16le(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft);
-static long ami_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft);
-static long ami_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft);
-static long ami_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ami_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ami_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-static long ami_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft);
-#endif /* CONFIG_AMIGA */
-
-
-/*** Machine definitions *****************************************************/
-
-
-typedef struct {
-    int type;
-    void *(*dma_alloc)(unsigned int, int);
-    void (*dma_free)(void *, unsigned int);
-    int (*irqinit)(void);
-    void (*init)(void);
-    void (*silence)(void);
-    int (*setFormat)(int);
-    int (*setVolume)(int);
-    int (*setBass)(int);
-    int (*setTreble)(int);
-    void (*play)(void);
-} MACHINE;
-
-
-/*** Low level stuff *********************************************************/
-
-
-typedef struct {
-    int format;                /* AFMT_* */
-    int stereo;                /* 0 = mono, 1 = stereo */
-    int size;          /* 8/16 bit*/
-    int speed;         /* speed */
-} SETTINGS;
-
-typedef struct {
-    long (*ct_ulaw)(const u_char *, long, u_char *, long *, long);
-    long (*ct_alaw)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s8)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u8)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s16be)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u16be)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s16le)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u16le)(const u_char *, long, u_char *, long *, long);
-} TRANS;
-
-struct sound_settings {
-    MACHINE mach;      /* machine dependent things */
-    SETTINGS hard;     /* hardware settings */
-    SETTINGS soft;     /* software settings */
-    SETTINGS dsp;      /* /dev/dsp default settings */
-    TRANS *trans;      /* supported translations */
-    int volume_left;   /* volume (range is machine dependent) */
-    int volume_right;
-    int bass;          /* tone (range is machine dependent) */
-    int treble;
-    int minDev;                /* minor device number currently open */
-#ifdef CONFIG_ATARI
-    int bal;           /* balance factor for expanding (not volume!) */
-    u_long data;       /* data for expanding */
-#endif /* CONFIG_ATARI */
-};
-
-static struct sound_settings sound;
-
-
-#ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags);
-static void AtaFree(void *, unsigned int size);
-static int AtaIrqInit(void);
-static int AtaSetBass(int bass);
-static int AtaSetTreble(int treble);
-static void TTSilence(void);
-static void TTInit(void);
-static int TTSetFormat(int format);
-static int TTSetVolume(int volume);
-static void FalconSilence(void);
-static void FalconInit(void);
-static int FalconSetFormat(int format);
-static int FalconSetVolume(int volume);
-static void ata_sq_play_next_frame(int index);
-static void AtaPlay(void);
-static void ata_sq_interrupt(int irq, struct pt_regs *fp, void *dummy);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags);
-static void AmiFree(void *, unsigned int);
-static int AmiIrqInit(void);
-static void AmiSilence(void);
-static void AmiInit(void);
-static int AmiSetFormat(int format);
-static int AmiSetVolume(int volume);
-static int AmiSetTreble(int treble);
-static void ami_sq_play_next_frame(int index);
-static void AmiPlay(void);
-static void ami_sq_interrupt(int irq, struct pt_regs *fp, void *dummy);
-#endif /* CONFIG_AMIGA */
-
-
-/*** Mid level stuff *********************************************************/
-
-
-static void sound_silence(void);
-static void sound_init(void);
-static int sound_set_format(int format);
-static int sound_set_speed(int speed);
-static int sound_set_stereo(int stereo);
-static int sound_set_volume(int volume);
-#ifdef CONFIG_ATARI
-static int sound_set_bass(int bass);
-#endif /* CONFIG_ATARI */
-static int sound_set_treble(int treble);
-static long sound_copy_translate(const u_char *userPtr, long userCount,
-                                u_char frame[], long *frameUsed,
-                                long frameLeft);
-
-
-/*
- * /dev/mixer abstraction
- */
-
-struct sound_mixer {
-    int busy;
-};
-
-static struct sound_mixer mixer;
-
-static void mixer_init(void);
-static int mixer_open(int open_mode);
-static int mixer_release(void);
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-                      u_long arg);
-
-
-/*
- * Sound queue stuff, the heart of the driver
- */
-
-struct sound_queue {
-    int max_count, block_size;
-    char **buffers;
-
-    /* it shouldn't be necessary to declare any of these volatile */
-    int front, rear, count;
-    int rear_size;
-    /*
-     * The use of the playing field depends on the hardware
-     *
-     * Atari: The number of frames that are loaded/playing
-     *
-     * Amiga: Bit 0 is set: a frame is loaded
-     *        Bit 1 is set: a frame is playing
-     */
-    int playing;
-    struct wait_queue *write_queue, *open_queue, *sync_queue;
-    int open_mode;
-    int busy, syncing;
-#ifdef CONFIG_ATARI
-    int ignore_int;            /* ++TeSche: used for Falcon */
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-    int block_size_half, block_size_quarter;
-#endif /* CONFIG_AMIGA */
-};
-
-static struct sound_queue sq;
-
-#define sq_block_address(i)    (sq.buffers[i])
-#define SIGNAL_RECEIVED        (current->signal & ~current->blocked)
-#define NON_BLOCKING(open_mode)        (open_mode & O_NONBLOCK)
-#define ONE_SECOND     HZ      /* in jiffies (100ths of a second) */
-#define NO_TIME_LIMIT  0xffffffff
-#define SLEEP(queue, time_limit) \
-       current->timeout = jiffies+(time_limit); \
-       interruptible_sleep_on(&queue);
-#define WAKE_UP(queue) (wake_up_interruptible(&queue))
-
-static void sq_init(int numBufs, int bufSize, char **buffers);
-static void sq_play(void);
-static int sq_write(const char *src, int uLeft);
-static int sq_open(int open_mode);
-static void sq_reset(void);
-static int sq_sync(void);
-static int sq_release(void);
-
-
-/*
- * /dev/sndstat
- */
-
-struct sound_state {
-    int busy;
-    char buf[512];
-    int len, ptr;
-};
-
-static struct sound_state state;
-
-static void state_init(void);
-static int state_open(int open_mode);
-static int state_release(void);
-static int state_read(char *dest, int count);
-
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file);
-static int sound_fsync(struct inode *inode, struct file *filp);
-static void sound_release(struct inode *inode, struct file *file);
-static int sound_lseek(struct inode *inode, struct file *file, off_t offset,
-                      int orig);
-static int sound_read(struct inode *inode, struct file *file, char *buf,
-                     int count);
-static int sound_write(struct inode *inode, struct file *file, const char *buf,
-                      int count);
-static int ioctl_return(int *addr, int value);
-static int unknown_minor_dev(char *fname, int dev);
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-                      u_long arg);
-
-
-/*** Config & Setup **********************************************************/
-
-
-void soundcard_init(void);
-void dmasound_setup(char *str, int *ints);
-void sound_setup(char *str, int *ints);                /* ++Martin: stub for now */
-
-
-/*** Translations ************************************************************/
-
-
-/* ++TeSche: radically changed for new expanding purposes...
- *
- * These two routines now deal with copying/expanding/translating the samples
- * from user space into our buffer at the right frequency. They take care about
- * how much data there's actually to read, how much buffer space there is and
- * to convert samples into the right frequency/encoding. They will only work on
- * complete samples so it may happen they leave some bytes in the input stream
- * if the user didn't write a multiple of the current sample size. They both
- * return the number of bytes they've used from both streams so you may detect
- * such a situation. Luckily all programs should be able to cope with that.
- *
- * I think I've optimized anything as far as one can do in plain C, all
- * variables should fit in registers and the loops are really short. There's
- * one loop for every possible situation. Writing a more generalized and thus
- * parameterized loop would only produce slower code. Feel free to optimize
- * this in assembler if you like. :)
- *
- * I think these routines belong here because they're not yet really hardware
- * independent, especially the fact that the Falcon can play 16bit samples
- * only in stereo is hardcoded in both of them!
- *
- * ++geert: split in even more functions (one per format)
- */
-
-#ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    long count, used;
-    u_char *p = &frame[*frameUsed];
-
-    count = min(userCount, frameLeft);
-    if (sound.soft.stereo)
-       count &= ~1;
-    used = count;
-    while (count > 0) {
-       *p++ = table[get_user(userPtr++)];
-       count--;
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft)
-{
-    long count, used;
-    void *p = &frame[*frameUsed];
-
-    count = min(userCount, frameLeft);
-    if (sound.soft.stereo)
-       count &= ~1;
-    used = count;
-    copy_from_user(p, userPtr, count);
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-       u_char *p = &frame[*frameUsed];
-       count = min(userCount, frameLeft);
-       used = count;
-       while (count > 0) {
-           *p++ = get_user(userPtr++) ^ 0x80;
-           count--;
-       }
-    } else {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>1;
-       used = count*2;
-       while (count > 0) {
-           *p++ = get_user(((u_short *)userPtr)++) ^ 0x8080;
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           *p++ = data;
-           *p++ = data;
-           count--;
-       }
-       *frameUsed += used*2;
-    } else {
-       void *p = (u_short *)&frame[*frameUsed];
-       count = min(userCount, frameLeft) & ~3;
-       used = count;
-       copy_from_user(p, userPtr, count);
-       *frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-           *p++ = data;
-           *p++ = data;
-           count--;
-       }
-       *frameUsed += used*2;
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>2;
-       used = count*4;
-       while (count > 0) {
-           *p++ = get_user(((u_int *)userPtr)++) ^ 0x80008000;
-           count--;
-       }
-       *frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    count = frameLeft;
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data);
-           *p++ = data;
-           *p++ = data;
-           count--;
-       }
-       *frameUsed += used*2;
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>2;
-       used = count*4;
-       while (count > 0) {
-           data = get_user(((u_int *)userPtr)++);
-           data = le2be16dbl(data);
-           *p++ = data;
-           count--;
-       }
-       *frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    count = frameLeft;
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data) ^ 0x8000;
-           *p++ = data;
-           *p++ = data;
-       }
-       *frameUsed += used*2;
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       count = min(userCount, frameLeft)>>2;
-       used = count;
-       while (count > 0) {
-           data = get_user(((u_int *)userPtr)++);
-           data = le2be16dbl(data) ^ 0x80008000;
-           *p++ = data;
-           count--;
-       }
-       *frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ctx_law(const u_char *userPtr, long userCount, u_char frame[],
-                       long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_char *p = &frame[*frameUsed];
-       while (frameLeft) {
-           if (bal < 0) {
-               if (!userCount)
-                   break;
-               data = table[get_user(userPtr++)];
-               userCount--;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft--;
-           bal -= sSpeed;
-       }
-    } else {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 2) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = table[get_user(userPtr++)] << 8;
-               data |= table[get_user(userPtr++)];
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 2;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s8(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_char *p = &frame[*frameUsed];
-       while (frameLeft) {
-           if (bal < 0) {
-               if (!userCount)
-                   break;
-               data = get_user(userPtr++);
-               userCount--;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft--;
-           bal -= sSpeed;
-       }
-    } else {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 2) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = get_user(((u_short *)userPtr)++);
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 2;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u8(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_char *p = &frame[*frameUsed];
-       while (frameLeft) {
-           if (bal < 0) {
-               if (!userCount)
-                   break;
-               data = get_user(userPtr++) ^ 0x80;
-               userCount--;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft--;
-           bal -= sSpeed;
-       }
-    } else {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 2) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = get_user(((u_short *)userPtr)++) ^ 0x8080;
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 2;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s16be(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = get_user(((u_short *)userPtr)++);
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 4)
-                   break;
-               data = get_user(((u_int *)userPtr)++);
-               userCount -= 4;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u16be(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 4)
-                   break;
-               data = get_user(((u_int *)userPtr)++) ^ 0x80008000;
-               userCount -= 4;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s16le(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = get_user(((u_short *)userPtr)++);
-               data = le2be16(data);
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 4)
-                   break;
-               data = get_user(((u_int *)userPtr)++);
-               data = le2be16dbl(data);
-               userCount -= 4;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u16le(const u_char *userPtr, long userCount, u_char frame[],
-                         long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-       u_short *p = (u_short *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 2)
-                   break;
-               data = get_user(((u_short *)userPtr)++);
-               data = le2be16(data) ^ 0x8000;
-               userCount -= 2;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    } else {
-       u_long *p = (u_long *)&frame[*frameUsed];
-       while (frameLeft >= 4) {
-           if (bal < 0) {
-               if (userCount < 4)
-                   break;
-               data = get_user(((u_int *)userPtr)++);
-               data = le2be16dbl(data) ^ 0x80008000;
-               userCount -= 4;
-               bal += hSpeed;
-           }
-           *p++ = data;
-           frameLeft -= 4;
-           bal -= sSpeed;
-       }
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-#endif /* CONFIG_ATARI */
-
-
-#ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-                      long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    long count, used;
-
-    if (!sound.soft.stereo) {
-       u_char *p = &frame[*frameUsed];
-       count = min(userCount, frameLeft) & ~1;
-       used = count;
-       while (count > 0) {
-           *p++ = table[get_user(userPtr++)];
-           count--;
-       }
-    } else {
-       u_char *left = &frame[*frameUsed>>1];
-       u_char *right = left+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           *left++ = table[get_user(userPtr++)];
-           *right++ = table[get_user(userPtr++)];
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-       void *p = &frame[*frameUsed];
-       count = min(userCount, frameLeft) & ~1;
-       used = count;
-       copy_from_user(p, userPtr, count);
-    } else {
-       u_char *left = &frame[*frameUsed>>1];
-       u_char *right = left+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           *left++ = get_user(userPtr++);
-           *right++ = get_user(userPtr++);
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-                     long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-       char *p = &frame[*frameUsed];
-       count = min(userCount, frameLeft) & ~1;
-       used = count;
-       while (count > 0) {
-           *p++ = get_user(userPtr++) ^ 0x80;
-           count--;
-       }
-    } else {
-       u_char *left = &frame[*frameUsed>>1];
-       u_char *right = left+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           *left++ = get_user(userPtr++) ^ 0x80;
-           *right++ = get_user(userPtr++) ^ 0x80;
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-       u_char *high = &frame[*frameUsed>>1];
-       u_char *low = high+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           *high = data>>8;
-           *low = (data>>2) & 0x3f;
-           count--;
-       }
-    } else {
-       u_char *lefth = &frame[*frameUsed>>2];
-       u_char *leftl = lefth+sq.block_size_quarter;
-       u_char *righth = lefth+sq.block_size_half;
-       u_char *rightl = righth+sq.block_size_quarter;
-       count = min(userCount, frameLeft)>>2 & ~1;
-       used = count*4;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           *lefth = data>>8;
-           *leftl = (data>>2) & 0x3f;
-           data = get_user(((u_short *)userPtr)++);
-           *righth = data>>8;
-           *rightl = (data>>2) & 0x3f;
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-       u_char *high = &frame[*frameUsed>>1];
-       u_char *low = high+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-           *high = data>>8;
-           *low = (data>>2) & 0x3f;
-           count--;
-       }
-    } else {
-       u_char *lefth = &frame[*frameUsed>>2];
-       u_char *leftl = lefth+sq.block_size_quarter;
-       u_char *righth = lefth+sq.block_size_half;
-       u_char *rightl = righth+sq.block_size_quarter;
-       count = min(userCount, frameLeft)>>2 & ~1;
-       used = count*4;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-           *lefth = data>>8;
-           *leftl = (data>>2) & 0x3f;
-           data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-           *righth = data>>8;
-           *rightl = (data>>2) & 0x3f;
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-       u_char *high = &frame[*frameUsed>>1];
-       u_char *low = high+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data);
-           *high = data>>8;
-           *low = (data>>2) & 0x3f;
-           count--;
-       }
-    } else {
-       u_char *lefth = &frame[*frameUsed>>2];
-       u_char *leftl = lefth+sq.block_size_quarter;
-       u_char *righth = lefth+sq.block_size_half;
-       u_char *rightl = righth+sq.block_size_quarter;
-       count = min(userCount, frameLeft)>>2 & ~1;
-       used = count*4;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data);
-           *lefth = data>>8;
-           *leftl = (data>>2) & 0x3f;
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data);
-           *righth = data>>8;
-           *rightl = (data>>2) & 0x3f;
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-                        long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-       u_char *high = &frame[*frameUsed>>1];
-       u_char *low = high+sq.block_size_half;
-       count = min(userCount, frameLeft)>>1 & ~1;
-       used = count*2;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data) ^ 0x8000;
-           *high = data>>8;
-           *low = (data>>2) & 0x3f;
-           count--;
-       }
-    } else {
-       u_char *lefth = &frame[*frameUsed>>2];
-       u_char *leftl = lefth+sq.block_size_quarter;
-       u_char *righth = lefth+sq.block_size_half;
-       u_char *rightl = righth+sq.block_size_quarter;
-       count = min(userCount, frameLeft)>>2 & ~1;
-       used = count*4;
-       while (count > 0) {
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data) ^ 0x8000;
-           *lefth = data>>8;
-           *leftl = (data>>2) & 0x3f;
-           data = get_user(((u_short *)userPtr)++);
-           data = le2be16(data) ^ 0x8000;
-           *righth = data>>8;
-           *rightl = (data>>2) & 0x3f;
-           count--;
-       }
-    }
-    *frameUsed += used;
-    return(used);
-}
-#endif /* CONFIG_AMIGA */
-
-
-#ifdef CONFIG_ATARI
-static TRANS transTTNormal = {
-    ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL
-};
-
-static TRANS transTTExpanding = {
-    ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL
-};
-
-static TRANS transFalconNormal = {
-    ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be,
-    ata_ct_s16le, ata_ct_u16le
-};
-
-static TRANS transFalconExpanding = {
-    ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be,
-    ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le
-};
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static TRANS transAmiga = {
-    ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be,
-    ami_ct_s16le, ami_ct_u16le
-};
-#endif /* CONFIG_AMIGA */
-
-
-/*** Low level stuff *********************************************************/
-
-
-#ifdef CONFIG_ATARI
-
-/*
- * Atari (TT/Falcon)
- */
-
-static void *AtaAlloc(unsigned int size, int flags)
-{
-    int order;
-    unsigned int a_size;
-    order = 0;
-    a_size = PAGE_SIZE;
-    while (a_size < size) {
-       order++;
-       a_size <<= 1;
-    }
-    return (void *) __get_dma_pages(flags, order);
-}
-
-static void AtaFree(void *obj, unsigned int size)
-{
-    int order;
-    unsigned int a_size;
-    order = 0;
-    a_size = PAGE_SIZE;
-    while (a_size < size) {
-       order++;
-       a_size <<= 1;
-    }
-    free_pages ((unsigned long) obj, order);
-}
-
-static int AtaIrqInit(void)
-{
-    /* Set up timer A. Timer A
-    will receive a signal upon end of playing from the sound
-    hardware. Furthermore Timer A is able to count events
-    and will cause an interrupt after a programmed number
-    of events. So all we need to keep the music playing is
-    to provide the sound hardware with new data upon
-    an interrupt from timer A. */
-    mfp.tim_ct_a = 0;          /* ++roman: Stop timer before programming! */
-    mfp.tim_dt_a = 1;          /* Cause interrupt after first event. */
-    mfp.tim_ct_a = 8;          /* Turn on event counting. */
-    /* Register interrupt handler. */
-    add_isr(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, NULL, "DMA sound");
-    mfp.int_en_a |= 0x20;      /* Turn interrupt on. */
-    mfp.int_mk_a |= 0x20;
-    return(1);
-}
-
-
-#define TONE_VOXWARE_TO_DB(v) \
-       (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)
-#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
-
-
-static int AtaSetBass(int bass)
-{
-    sound.bass = TONE_VOXWARE_TO_DB(bass);
-    atari_microwire_cmd(MW_LM1992_BASS(sound.bass));
-    return(TONE_DB_TO_VOXWARE(sound.bass));
-}
-
-
-static int AtaSetTreble(int treble)
-{
-    sound.treble = TONE_VOXWARE_TO_DB(treble);
-    atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble));
-    return(TONE_DB_TO_VOXWARE(sound.treble));
-}
-
-
-
-/*
- * TT
- */
-
-
-static void TTSilence(void)
-{
-    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-    atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
-}
-
-
-static void TTInit(void)
-{
-    int mode, i, idx;
-    const int freq[4] = {50066, 25033, 12517, 6258};
-
-    /* search a frequency that fits into the allowed error range */
-
-    idx = -1;
-    for (i = 0; i < arraysize(freq); i++)
-       /* this isn't as much useful for a TT than for a Falcon, but
-        * then it doesn't hurt very much to implement it for a TT too.
-        */
-       if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
-           idx = i;
-    if (idx > -1) {
-       sound.soft.speed = freq[idx];
-       sound.trans = &transTTNormal;
-    } else
-       sound.trans = &transTTExpanding;
-
-    TTSilence();
-    sound.hard = sound.soft;
-
-    if (sound.hard.speed > 50066) {
-       /* we would need to squeeze the sound, but we won't do that */
-       sound.hard.speed = 50066;
-       mode = DMASND_MODE_50KHZ;
-       sound.trans = &transTTNormal;
-    } else if (sound.hard.speed > 25033) {
-       sound.hard.speed = 50066;
-       mode = DMASND_MODE_50KHZ;
-    } else if (sound.hard.speed > 12517) {
-       sound.hard.speed = 25033;
-       mode = DMASND_MODE_25KHZ;
-    } else if (sound.hard.speed > 6258) {
-       sound.hard.speed = 12517;
-       mode = DMASND_MODE_12KHZ;
-    } else {
-       sound.hard.speed = 6258;
-       mode = DMASND_MODE_6KHZ;
-    }
-
-    tt_dmasnd.mode = (sound.hard.stereo ?
-                     DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-                    DMASND_MODE_8BIT | mode;
-
-    sound.bal = -sound.soft.speed;
-}
-
-
-static int TTSetFormat(int format)
-{
-    /* TT sound DMA supports only 8bit modes */
-
-    switch (format) {
-       case AFMT_QUERY:
-           return(sound.soft.format);
-       case AFMT_MU_LAW:
-       case AFMT_A_LAW:
-       case AFMT_S8:
-       case AFMT_U8:
-           break;
-       default:
-           format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = 8;
-    if (sound.minDev == SND_DEV_DSP) {
-       sound.dsp.format = format;
-       sound.dsp.size = 8;
-    }
-    TTInit();
-
-    return(format);
-}
-
-
-#define VOLUME_VOXWARE_TO_DB(v) \
-       (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)
-#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)
-
-
-static int TTSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
-    atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left));
-    sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
-    atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right));
-    return(VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-          (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8));
-}
-
-
-
-/*
- * Falcon
- */
-
-
-static void FalconSilence(void)
-{
-    /* stop playback, set sample rate 50kHz for PSG sound */
-    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-    tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
-    tt_dmasnd.int_div = 0; /* STE compatible divider */
-    tt_dmasnd.int_ctrl = 0x0;
-    tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
-    tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
-    tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
-    tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
-}
-
-
-static void FalconInit(void)
-{
-    int divider, i, idx;
-    const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
-
-    /* search a frequency that fits into the allowed error range */
-
-    idx = -1;
-    for (i = 0; i < arraysize(freq); i++)
-       /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
-        * be playable without expanding, but that now a kernel runtime
-        * option
-        */
-       if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
-           idx = i;
-    if (idx > -1) {
-       sound.soft.speed = freq[idx];
-       sound.trans = &transFalconNormal;
-    } else
-       sound.trans = &transFalconExpanding;
-
-    FalconSilence();
-    sound.hard = sound.soft;
-
-    if (sound.hard.size == 16) {
-       /* the Falcon can play 16bit samples only in stereo */
-       sound.hard.stereo = 1;
-    }
-
-    if (sound.hard.speed > 49170) {
-       /* we would need to squeeze the sound, but we won't do that */
-       sound.hard.speed = 49170;
-       divider = 1;
-       sound.trans = &transFalconNormal;
-    } else if (sound.hard.speed > 32780) {
-       sound.hard.speed = 49170;
-       divider = 1;
-    } else if (sound.hard.speed > 24585) {
-       sound.hard.speed = 32780;
-       divider = 2;
-    } else if (sound.hard.speed > 19668) {
-       sound.hard.speed = 24585;
-       divider = 3;
-    } else if (sound.hard.speed > 16390) {
-       sound.hard.speed = 19668;
-       divider = 4;
-    } else if (sound.hard.speed > 12292) {
-       sound.hard.speed = 16390;
-       divider = 5;
-    } else if (sound.hard.speed > 9834) {
-       sound.hard.speed = 12292;
-       divider = 7;
-    } else if (sound.hard.speed > 8195) {
-       sound.hard.speed = 9834;
-       divider = 9;
-    } else {
-       sound.hard.speed = 8195;
-       divider = 11;
-    }
-    tt_dmasnd.int_div = divider;
-
-    /* Setup Falcon sound DMA for playback */
-    tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
-    tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
-    tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
-    tt_dmasnd.cbar_dst = 0x0000;
-    tt_dmasnd.rec_track_select = 0;
-    tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
-    tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
-
-    tt_dmasnd.mode = (sound.hard.stereo ?
-                     DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-                    ((sound.hard.size == 8) ?
-                      DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
-                    DMASND_MODE_6KHZ;
-
-    sound.bal = -sound.soft.speed;
-}
-
-
-static int FalconSetFormat(int format)
-{
-    int size;
-    /* Falcon sound DMA supports 8bit and 16bit modes */
-
-    switch (format) {
-       case AFMT_QUERY:
-           return(sound.soft.format);
-       case AFMT_MU_LAW:
-       case AFMT_A_LAW:
-       case AFMT_U8:
-       case AFMT_S8:
-           size = 8;
-           break;
-       case AFMT_S16_BE:
-       case AFMT_U16_BE:
-       case AFMT_S16_LE:
-       case AFMT_U16_LE:
-           size = 16;
-           break;
-       default: /* :-) */
-           size = 8;
-           format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = size;
-    if (sound.minDev == SND_DEV_DSP) {
-       sound.dsp.format = format;
-       sound.dsp.size = sound.soft.size;
-    }
-
-    FalconInit();
-
-    return(format);
-}
-
-
-/* This is for the Falcon output *attenuation* in 1.5dB steps,
- * i.e. output level from 0 to -22.5dB in -1.5dB steps.
- */
-#define VOLUME_VOXWARE_TO_ATT(v) \
-       ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)
-#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
-
-
-static int FalconSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
-    sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
-    tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4;
-    return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-          VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8);
-}
-
-
-static void ata_sq_play_next_frame(int index)
-{
-    char *start, *end;
-
-    /* used by AtaPlay() if all doubts whether there really is something
-     * to be played are already wiped out.
-     */
-    start = sq_block_address(sq.front);
-    end = start+((sq.count == index) ? sq.rear_size : sq.block_size);
-    /* end might not be a legal virtual address. */
-    DMASNDSetEnd(VTOP(end - 1) + 1);
-    DMASNDSetBase(VTOP(start));
-       /* Since only an even number of samples per frame can
-       be played, we might lose one byte here. (TO DO) */
-    sq.front = (sq.front+1) % sq.max_count;
-    sq.playing++;
-    tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
-}
-
-
-static void AtaPlay(void)
-{
-    /* ++TeSche: Note that sq.playing is no longer just a flag but holds
-     * the number of frames the DMA is currently programmed for instead,
-     * may be 0, 1 (currently being played) or 2 (pre-programmed).
-     *
-     * Changes done to sq.count and sq.playing are a bit more subtle again
-     * so now I must admit I also prefer disabling the irq here rather
-     * than considering all possible situations. But the point is that
-     * disabling the irq doesn't have any bad influence on this version of
-     * the driver as we benefit from having pre-programmed the DMA
-     * wherever possible: There's no need to reload the DMA at the exact
-     * time of an interrupt but only at some time while the pre-programmed
-     * frame is playing!
-     */
-    atari_disable_irq(IRQ_MFP_TIMA);
-
-    if (sq.playing == 2 ||     /* DMA is 'full' */
-       sq.count <= 0) {        /* nothing to do */
-       atari_enable_irq(IRQ_MFP_TIMA);
-       return;
-    }
-
-    if (sq.playing == 0) {
-       /* looks like there's nothing 'in' the DMA yet, so try
-        * to put two frames into it (at least one is available).
-        */
-       if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) {
-           /* hmmm, the only existing frame is not
-            * yet filled and we're not syncing?
-            */
-           atari_enable_irq(IRQ_MFP_TIMA);
-           return;
-       }
-       ata_sq_play_next_frame(1);
-       if (sq.count == 1) {
-           /* no more frames */
-           atari_enable_irq(IRQ_MFP_TIMA);
-           return;
-       }
-       if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
-           /* hmmm, there were two frames, but the second
-            * one is not yet filled and we're not syncing?
-            */
-           atari_enable_irq(IRQ_MFP_TIMA);
-           return;
-       }
-       ata_sq_play_next_frame(2);
-    } else {
-       /* there's already a frame being played so we may only stuff
-        * one new into the DMA, but even if this may be the last
-        * frame existing the previous one is still on sq.count.
-        */
-       if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
-           /* hmmm, the only existing frame is not
-            * yet filled and we're not syncing?
-            */
-           atari_enable_irq(IRQ_MFP_TIMA);
-           return;
-       }
-       ata_sq_play_next_frame(2);
-    }
-    atari_enable_irq(IRQ_MFP_TIMA);
-}
-
-
-static void ata_sq_interrupt(int irq, struct pt_regs *fp, void *dummy)
-{
-#if 0
-    /* ++TeSche: if you should want to test this... */
-    static int cnt = 0;
-    if (sq.playing == 2)
-       if (++cnt == 10) {
-           /* simulate losing an interrupt */
-           cnt = 0;
-           return;
-       }
-#endif
-
-    if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) {
-       /* ++TeSche: Falcon only: ignore first irq because it comes
-        * immediately after starting a frame. after that, irqs come
-        * (almost) like on the TT.
-        */
-       sq.ignore_int = 0;
-       return;
-    }
-
-    if (!sq.playing) {
-       /* playing was interrupted and sq_reset() has already cleared
-        * the sq variables, so better don't do anything here.
-        */
-       WAKE_UP(sq.sync_queue);
-       return;
-    }
-
-    /* Probably ;) one frame is finished. Well, in fact it may be that a
-     * pre-programmed one is also finished because there has been a long
-     * delay in interrupt delivery and we've completely lost one, but
-     * there's no way to detect such a situation. In such a case the last
-     * frame will be played more than once and the situation will recover
-     * as soon as the irq gets through.
-     */
-    sq.count--;
-    sq.playing--;
-
-    if (!sq.playing) {
-       tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-       sq.ignore_int = 1;
-    }
-
-    WAKE_UP(sq.write_queue);
-       /* At least one block of the queue is free now
-       so wake up a writing process blocked because
-       of a full queue. */
-
-    if ((sq.playing != 1) || (sq.count != 1))
-       /* We must be a bit carefully here: sq.count indicates the
-        * number of buffers used and not the number of frames to
-        * be played. If sq.count==1 and sq.playing==1 that means
-        * the only remaining frame was already programmed earlier
-        * (and is currently running) so we mustn't call AtaPlay()
-        * here, otherwise we'll play one frame too much.
-        */
-       AtaPlay();
-
-    if (!sq.playing) WAKE_UP(sq.sync_queue);
-       /* We are not playing after AtaPlay(), so there
-       is nothing to play any more. Wake up a process
-       waiting for audio output to drain. */
-}
-#endif /* CONFIG_ATARI */
-
-
-#ifdef CONFIG_AMIGA
-
-/*
- * Amiga
- */
-
-
-static void *AmiAlloc(unsigned int size, int flags)
-{
-    return(amiga_chip_alloc((long)size));
-}
-
-static void AmiFree(void *obj, unsigned int size)
-{
-    amiga_chip_free (obj);
-}
-
-static int AmiIrqInit(void)
-{
-    /* turn off DMA for audio channels */
-    custom.dmacon = AMI_AUDIO_OFF;
-
-    /* Register interrupt handler. */
-    if (!add_isr(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, NULL, "DMA sound"))
-       panic("Couldn't add audio interrupt");
-    return(1);
-}
-
-
-static void AmiSilence(void)
-{
-    /* turn off DMA for audio channels */
-    custom.dmacon = AMI_AUDIO_OFF;
-}
-
-
-static void AmiInit(void)
-{
-    int period, i;
-
-    AmiSilence();
-
-    if (sound.soft.speed)
-       period = amiga_colorclock/sound.soft.speed-1;
-    else
-       period = amiga_audio_min_period;
-    sound.hard = sound.soft;
-    sound.trans = &transAmiga;
-
-    if (period < amiga_audio_min_period) {
-       /* we would need to squeeze the sound, but we won't do that */
-       period = amiga_audio_min_period;
-       sound.hard.speed = amiga_colorclock/(period+1);
-    } else if (period > 65535) {
-       period = 65535;
-       sound.hard.speed = amiga_colorclock/(period+1);
-    }
-    for (i = 0; i < 4; i++)
-       custom.aud[i].audper = period;
-    amiga_audio_period = period;
-}
-
-
-static int AmiSetFormat(int format)
-{
-    int size;
-
-    /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
-
-    switch (format) {
-       case AFMT_QUERY:
-           return(sound.soft.format);
-       case AFMT_MU_LAW:
-       case AFMT_A_LAW:
-       case AFMT_U8:
-       case AFMT_S8:
-           size = 8;
-           break;
-       case AFMT_S16_BE:
-       case AFMT_U16_BE:
-       case AFMT_S16_LE:
-       case AFMT_U16_LE:
-           size = 16;
-           break;
-       default: /* :-) */
-           size = 8;
-           format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = size;
-    if (sound.minDev == SND_DEV_DSP) {
-       sound.dsp.format = format;
-       sound.dsp.size = sound.soft.size;
-    }
-    AmiInit();
-
-    return(format);
-}
-
-
-#define VOLUME_VOXWARE_TO_AMI(v) \
-       (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
-#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
-
-static int AmiSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
-    custom.aud[0].audvol = sound.volume_left;
-    sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
-    custom.aud[1].audvol = sound.volume_right;
-    return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-          (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
-}
-
-static int AmiSetTreble(int treble)
-{
-    sound.treble = treble;
-    if (treble > 50)
-       ciaa.pra |= 0x02;
-    else
-       ciaa.pra &= ~0x02;
-    return(treble);
-}
-
-
-#define AMI_PLAY_LOADED                1
-#define AMI_PLAY_PLAYING       2
-#define AMI_PLAY_MASK          3
-
-
-static void ami_sq_play_next_frame(int index)
-{
-    u_char *start, *ch0, *ch1, *ch2, *ch3;
-    u_long size;
-
-    /* used by AmiPlay() if all doubts whether there really is something
-     * to be played are already wiped out.
-     */
-    start = sq_block_address(sq.front);
-    size = (sq.count == index ? sq.rear_size : sq.block_size)>>1;
-
-    if (sound.hard.stereo) {
-       ch0 = start;
-       ch1 = start+sq.block_size_half;
-       size >>= 1;
-    } else {
-       ch0 = start;
-       ch1 = start;
-    }
-    if (sound.hard.size == 8) {
-       custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
-       custom.aud[0].audlen = size;
-       custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
-       custom.aud[1].audlen = size;
-       custom.dmacon = AMI_AUDIO_8;
-    } else {
-       size >>= 1;
-       custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
-       custom.aud[0].audlen = size;
-       custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
-       custom.aud[1].audlen = size;
-       if (sound.volume_left == 64 && sound.volume_right == 64) {
-           /* We can play pseudo 14-bit only with the maximum volume */
-           ch3 = ch0+sq.block_size_quarter;
-           ch2 = ch1+sq.block_size_quarter;
-           custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
-           custom.aud[2].audlen = size;
-           custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
-           custom.aud[3].audlen = size;
-           custom.dmacon = AMI_AUDIO_14;
-       } else
-           custom.dmacon = AMI_AUDIO_8;
-    }
-    sq.front = (sq.front+1) % sq.max_count;
-    sq.playing |= AMI_PLAY_LOADED;
-}
-
-
-static void AmiPlay(void)
-{
-    int minframes = 1;
-
-    custom.intena = IF_AUD0;
-
-    if (sq.playing & AMI_PLAY_LOADED) {
-       /* There's already a frame loaded */
-       custom.intena = IF_SETCLR | IF_AUD0;
-       return;
-    }
-
-    if (sq.playing & AMI_PLAY_PLAYING)
-       /* Increase threshold: frame 1 is already being played */
-       minframes = 2;
-
-    if (sq.count < minframes) {
-       /* Nothing to do */
-       custom.intena = IF_SETCLR | IF_AUD0;
-       return;
-    }
-
-    if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) {
-       /* hmmm, the only existing frame is not
-        * yet filled and we're not syncing?
-        */
-       custom.intena = IF_SETCLR | IF_AUD0;
-       return;
-    }
-
-    ami_sq_play_next_frame(minframes);
-
-    custom.intena = IF_SETCLR | IF_AUD0;
-}
-
-
-static void ami_sq_interrupt(int irq, struct pt_regs *fp, void *dummy)
-{
-    int minframes = 1;
-
-    if (!sq.playing) {
-       /* Playing was interrupted and sq_reset() has already cleared
-        * the sq variables, so better don't do anything here.
-        */
-       WAKE_UP(sq.sync_queue);
-       return;
-    }
-
-    if (sq.playing & AMI_PLAY_PLAYING) {
-       /* We've just finished a frame */
-       sq.count--;
-       WAKE_UP(sq.write_queue);
-    }
-
-    if (sq.playing & AMI_PLAY_LOADED)
-       /* Increase threshold: frame 1 is already being played */
-       minframes = 2;
-
-    /* Shift the flags */
-    sq.playing = (sq.playing<<1) & AMI_PLAY_MASK;
-
-    if (!sq.playing)
-       /* No frame is playing, disable audio DMA */
-       custom.dmacon = AMI_AUDIO_OFF;
-
-    if (sq.count >= minframes)
-       /* Try to play the next frame */
-       AmiPlay();
-
-    if (!sq.playing)
-       /* Nothing to play anymore.
-          Wake up a process waiting for audio output to drain. */
-       WAKE_UP(sq.sync_queue);
-}
-#endif /* CONFIG_AMIGA */
-
-
-/*** Machine definitions *****************************************************/
-
-
-#ifdef CONFIG_ATARI
-static MACHINE machTT = {
-    DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, TTInit, TTSilence, TTSetFormat,
-    TTSetVolume, AtaSetBass, AtaSetTreble, AtaPlay
-};
-
-static MACHINE machFalcon = {
-    DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, FalconInit, FalconSilence,
-    FalconSetFormat, FalconSetVolume, AtaSetBass, AtaSetTreble, AtaPlay
-};
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static MACHINE machAmiga = {
-    DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, AmiInit, AmiSilence,
-    AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble, AmiPlay
-};
-#endif /* CONFIG_AMIGA */
-
-
-/*** Mid level stuff *********************************************************/
-
-
-static void sound_silence(void)
-{
-    /* update hardware settings one more */
-    (*sound.mach.init)();
-
-    (*sound.mach.silence)();
-}
-
-
-static void sound_init(void)
-{
-    (*sound.mach.init)();
-}
-
-
-static int sound_set_format(int format)
-{
-    return(*sound.mach.setFormat)(format);
-}
-
-
-static int sound_set_speed(int speed)
-{
-    if (speed < 0)
-       return(sound.soft.speed);
-
-    sound.soft.speed = speed;
-    (*sound.mach.init)();
-    if (sound.minDev == SND_DEV_DSP)
-       sound.dsp.speed = sound.soft.speed;
-
-    return(sound.soft.speed);
-}
-
-
-static int sound_set_stereo(int stereo)
-{
-    if (stereo < 0)
-       return(sound.soft.stereo);
-
-    stereo = !!stereo;    /* should be 0 or 1 now */
-
-    sound.soft.stereo = stereo;
-    if (sound.minDev == SND_DEV_DSP)
-       sound.dsp.stereo = stereo;
-    (*sound.mach.init)();
-
-    return(stereo);
-}
-
-
-static int sound_set_volume(int volume)
-{
-    return(*sound.mach.setVolume)(volume);
-}
-
-
-#ifdef CONFIG_ATARI
-static int sound_set_bass(int bass)
-{
-    return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50);
-}
-#endif /* CONFIG_ATARI */
-
-
-static int sound_set_treble(int treble)
-{
-    return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50);
-}
-
-
-static long sound_copy_translate(const u_char *userPtr, long userCount,
-                                u_char frame[], long *frameUsed,
-                                long frameLeft)
-{
-    long (*ct_func)(const u_char *, long, u_char *, long *, long) = NULL;
-
-    switch (sound.soft.format) {
-       case AFMT_MU_LAW:
-           ct_func = sound.trans->ct_ulaw;
-           break;
-       case AFMT_A_LAW:
-           ct_func = sound.trans->ct_alaw;
-           break;
-       case AFMT_S8:
-           ct_func = sound.trans->ct_s8;
-           break;
-       case AFMT_U8:
-           ct_func = sound.trans->ct_u8;
-           break;
-       case AFMT_S16_BE:
-           ct_func = sound.trans->ct_s16be;
-           break;
-       case AFMT_U16_BE:
-           ct_func = sound.trans->ct_u16be;
-           break;
-       case AFMT_S16_LE:
-           ct_func = sound.trans->ct_s16le;
-           break;
-       case AFMT_U16_LE:
-           ct_func = sound.trans->ct_u16le;
-           break;
-    }
-    if (ct_func)
-       return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft));
-    else
-       return(0);
-}
-
-
-/*
- * /dev/mixer abstraction
- */
-
-
-#define RECLEVEL_VOXWARE_TO_GAIN(v) \
-       ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
-#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
-
-
-static void mixer_init(void)
-{
-    mixer.busy = 0;
-    sound.treble = 0;
-    sound.bass = 0;
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-       case DMASND_TT:
-           atari_microwire_cmd(MW_LM1992_VOLUME(0));
-           sound.volume_left = 0;
-           atari_microwire_cmd(MW_LM1992_BALLEFT(0));
-           sound.volume_right = 0;
-           atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
-           atari_microwire_cmd(MW_LM1992_TREBLE(0));
-           atari_microwire_cmd(MW_LM1992_BASS(0));
-           break;
-       case DMASND_FALCON:
-           sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
-           sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
-           break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-       case DMASND_AMIGA:
-           sound.volume_left = 64;
-           sound.volume_right = 64;
-           custom.aud[0].audvol = sound.volume_left;
-           custom.aud[3].audvol = 1;                   /* For pseudo 14bit */
-           custom.aud[1].audvol = sound.volume_right;
-           custom.aud[2].audvol = 1;                   /* For pseudo 14bit */
-           sound.treble = 50;
-           break;
-#endif /* CONFIG_AMIGA */
-    }
-}
-
-
-static int mixer_open(int open_mode)
-{
-    if (mixer.busy)
-       return(-EBUSY);
-    mixer.busy = 1;
-    return(0);
-}
-
-
-static int mixer_release(void)
-{
-    mixer.busy = 0;
-    return(0);
-}
-
-
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-                      u_long arg)
-{
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-       case DMASND_FALCON:
-           switch (cmd) {
-               case SOUND_MIXER_READ_DEVMASK:
-                   return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
-               case SOUND_MIXER_READ_RECMASK:
-                   return(IOCTL_OUT(arg, SOUND_MASK_MIC));
-               case SOUND_MIXER_READ_STEREODEVS:
-                   return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC));
-               case SOUND_MIXER_READ_CAPS:
-                   return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT));
-               case SOUND_MIXER_READ_VOLUME:
-                   return(IOCTL_OUT(arg,
-                       VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-                       VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8));
-               case SOUND_MIXER_WRITE_MIC:
-                   tt_dmasnd.input_gain =
-                       RECLEVEL_VOXWARE_TO_GAIN(IOCTL_IN(arg) & 0xff) << 4 |
-                       RECLEVEL_VOXWARE_TO_GAIN(IOCTL_IN(arg) >> 8 & 0xff);
-                   /* fall thru, return set value */
-               case SOUND_MIXER_READ_MIC:
-                   return(IOCTL_OUT(arg,
-                       RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
-                       RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8));
-               case SOUND_MIXER_READ_SPEAKER:
-                   {
-                       int porta;
-                       cli();
-                       sound_ym.rd_data_reg_sel = 14;
-                       porta = sound_ym.rd_data_reg_sel;
-                       sti();
-                       return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-                   }
-               case SOUND_MIXER_WRITE_VOLUME:
-                   return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-               case SOUND_MIXER_WRITE_SPEAKER:
-                   {
-                       int porta;
-                       cli();
-                       sound_ym.rd_data_reg_sel = 14;
-                       porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-                               (IOCTL_IN(arg) < 50 ? 0x40 : 0);
-                       sound_ym.wd_data = porta;
-                       sti();
-                       return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-                   }
-           }
-           break;
-
-       case DMASND_TT:
-           switch (cmd) {
-               case SOUND_MIXER_READ_DEVMASK:
-                   return(IOCTL_OUT(arg,
-                       SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
-                       ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT ?
-                           SOUND_MASK_SPEAKER : 0)));
-               case SOUND_MIXER_READ_RECMASK:
-                   return(IOCTL_OUT(arg, 0));
-               case SOUND_MIXER_READ_STEREODEVS:
-                   return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
-               case SOUND_MIXER_READ_VOLUME:
-                   return(IOCTL_OUT(arg,
-                       VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-                       (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)));
-               case SOUND_MIXER_READ_BASS:
-                   return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)));
-               case SOUND_MIXER_READ_TREBLE:
-                   return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)));
-               case SOUND_MIXER_READ_SPEAKER:
-                   {
-                       int porta;
-                       if ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT) {
-                           cli();
-                           sound_ym.rd_data_reg_sel = 14;
-                           porta = sound_ym.rd_data_reg_sel;
-                           sti();
-                           return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-                       } else
-                           return(-EINVAL);
-                   }
-               case SOUND_MIXER_WRITE_VOLUME:
-                   return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-               case SOUND_MIXER_WRITE_BASS:
-                   return(IOCTL_OUT(arg, sound_set_bass(IOCTL_IN(arg))));
-               case SOUND_MIXER_WRITE_TREBLE:
-                   return(IOCTL_OUT(arg, sound_set_treble(IOCTL_IN(arg))));
-               case SOUND_MIXER_WRITE_SPEAKER:
-                   if ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT) {
-                       int porta;
-                       cli();
-                       sound_ym.rd_data_reg_sel = 14;
-                       porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-                               (IOCTL_IN(arg) < 50 ? 0x40 : 0);
-                       sound_ym.wd_data = porta;
-                       sti();
-                       return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-                   } else
-                       return(-EINVAL);
-           }
-           break;
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-       case DMASND_AMIGA:
-           switch (cmd) {
-               case SOUND_MIXER_READ_DEVMASK:
-                   return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE));
-               case SOUND_MIXER_READ_RECMASK:
-                   return(IOCTL_OUT(arg, 0));
-               case SOUND_MIXER_READ_STEREODEVS:
-                   return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
-               case SOUND_MIXER_READ_VOLUME:
-                   return(IOCTL_OUT(arg,
-                       VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-                       VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
-               case SOUND_MIXER_WRITE_VOLUME:
-                   return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-               case SOUND_MIXER_READ_TREBLE:
-                   return(IOCTL_OUT(arg, sound.treble));
-               case SOUND_MIXER_WRITE_TREBLE:
-                   return(IOCTL_OUT(arg, sound_set_treble(IOCTL_IN(arg))));
-           }
-           break;
-#endif /* CONFIG_AMIGA */
-    }
-
-    return(-EINVAL);
-}
-
-
-
-/*
- * Sound queue stuff, the heart of the driver
- */
-
-
-static void sq_init(int numBufs, int bufSize, char **buffers)
-{
-    sq.max_count = numBufs;
-    sq.block_size = bufSize;
-    sq.buffers = buffers;
-
-    sq.front = sq.count = 0;
-    sq.rear = -1;
-    sq.write_queue = sq.open_queue = sq.sync_queue = 0;
-    sq.busy = 0;
-    sq.syncing = 0;
-
-    sq.playing = 0;
-
-#ifdef CONFIG_ATARI
-    sq.ignore_int = 0;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-    sq.block_size_half = sq.block_size>>1;
-    sq.block_size_quarter = sq.block_size_half>>1;
-#endif /* CONFIG_AMIGA */
-
-    sound_silence();
-
-    /* whatever you like as startup mode for /dev/dsp,
-     * (/dev/audio hasn't got a startup mode). note that
-     * once changed a new open() will *not* restore these!
-     */
-    sound.dsp.format = AFMT_S8;
-    sound.dsp.stereo = 0;
-    sound.dsp.size = 8;
-
-    /* set minimum rate possible without expanding */
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-       case DMASND_TT:
-           sound.dsp.speed = 6258;
-           break;
-       case DMASND_FALCON:
-           sound.dsp.speed = 8195;
-           break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-       case DMASND_AMIGA:
-           sound.dsp.speed = 8000;
-           break;
-#endif /* CONFIG_AMIGA */
-    }
-
-    /* before the first open to /dev/dsp this wouldn't be set */
-    sound.soft = sound.dsp;
-}
-
-
-static void sq_play(void)
-{
-    (*sound.mach.play)();
-}
-
-
-/* ++TeSche: radically changed this one too */
-
-static int sq_write(const char *src, int uLeft)
-{
-    int uWritten = 0;
-    u_char *dest;
-    long uUsed, bUsed, bLeft;
-
-    /* ++TeSche: Is something like this necessary?
-     * Hey, that's an honest question! Or does any other part of the
-     * filesystem already checks this situation? I really don't know.
-     */
-    if (uLeft < 1)
-       return(0);
-
-    /* The interrupt doesn't start to play the last, incomplete frame.
-     * Thus we can append to it without disabling the interrupts! (Note
-     * also that sq.rear isn't affected by the interrupt.)
-     */
-
-    if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
-       dest = sq_block_address(sq.rear);
-       bUsed = sq.rear_size;
-       uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
-       src += uUsed;
-       uWritten += uUsed;
-       uLeft -= uUsed;
-       sq.rear_size = bUsed;
-    }
-
-    do {
-       if (sq.count == sq.max_count) {
-           sq_play();
-           if (NON_BLOCKING(sq.open_mode))
-               return(uWritten > 0 ? uWritten : -EAGAIN);
-           SLEEP(sq.write_queue, ONE_SECOND);
-           if (SIGNAL_RECEIVED)
-               return(uWritten > 0 ? uWritten : -EINTR);
-       }
-
-       /* Here, we can avoid disabling the interrupt by first
-        * copying and translating the data, and then updating
-        * the sq variables. Until this is done, the interrupt
-        * won't see the new frame and we can work on it
-        * undisturbed.
-        */
-
-       dest = sq_block_address((sq.rear+1) % sq.max_count);
-       bUsed = 0;
-       bLeft = sq.block_size;
-       uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
-       src += uUsed;
-       uWritten += uUsed;
-       uLeft -= uUsed;
-       if (bUsed) {
-           sq.rear = (sq.rear+1) % sq.max_count;
-           sq.rear_size = bUsed;
-           sq.count++;
-       }
-    } while (bUsed);   /* uUsed may have been 0 */
-
-    sq_play();
-
-    return(uWritten);
-}
-
-
-static int sq_open(int open_mode)
-{
-    if (sq.busy) {
-       if (NON_BLOCKING(open_mode))
-           return(-EBUSY);
-       while (sq.busy) {
-           SLEEP(sq.open_queue, ONE_SECOND);
-           if (SIGNAL_RECEIVED)
-               return(-EINTR);
-       }
-    }
-    sq.open_mode = open_mode;
-    sq.busy = 1;
-#ifdef CONFIG_ATARI
-    sq.ignore_int = 1;
-#endif /* CONFIG_ATARI */
-    return(0);
-}
-
-
-static void sq_reset(void)
-{
-    sound_silence();
-    sq.playing = 0;
-    sq.count = 0;
-    sq.front = (sq.rear+1) % sq.max_count;
-}
-
-
-static int sq_sync(void)
-{
-    int rc = 0;
-
-    sq.syncing = 1;
-    sq_play(); /* there may be an incomplete frame waiting */
-
-    while (sq.playing) {
-       SLEEP(sq.sync_queue, ONE_SECOND);
-       if (SIGNAL_RECEIVED) {
-           /* While waiting for audio output to drain, an interrupt occurred.
-              Stop audio output immediately and clear the queue. */
-           sq_reset();
-           rc = -EINTR;
-           break;
-       }
-    }
-
-    sq.syncing = 0;
-    return(rc);
-}
-
-
-static int sq_release(void)
-{
-    int rc = 0;
-    if (sq.busy) {
-       rc = sq_sync();
-       sq.busy = 0;
-       WAKE_UP(sq.open_queue);
-       /* Wake up a process waiting for the queue being released.
-          Note: There may be several processes waiting for a call to open()
-                returning. */
-    }
-    return(rc);
-}
-
-
-
-/*
- * /dev/sndstat
- */
-
-
-static void state_init(void)
-{
-    state.busy = 0;
-}
-
-
-/* state.buf should not overflow! */
-
-static int state_open(int open_mode)
-{
-    char *buffer = state.buf, *mach = "";
-    int len = 0;
-
-    if (state.busy)
-       return(-EBUSY);
-
-    state.ptr = 0;
-    state.busy = 1;
-
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-       case DMASND_TT:
-       case DMASND_FALCON:
-           mach = "Atari ";
-           break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-       case DMASND_AMIGA:
-           mach = "Amiga ";
-           break;
-#endif /* CONFIG_AMIGA */
-    }
-    len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
-
-    len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
-    switch (sound.soft.format) {
-       case AFMT_MU_LAW:
-           len += sprintf(buffer+len, " (mu-law)");
-           break;
-       case AFMT_A_LAW:
-           len += sprintf(buffer+len, " (A-law)");
-           break;
-       case AFMT_U8:
-           len += sprintf(buffer+len, " (unsigned 8 bit)");
-           break;
-       case AFMT_S8:
-           len += sprintf(buffer+len, " (signed 8 bit)");
-           break;
-       case AFMT_S16_BE:
-           len += sprintf(buffer+len, " (signed 16 bit big)");
-           break;
-       case AFMT_U16_BE:
-           len += sprintf(buffer+len, " (unsigned 16 bit big)");
-           break;
-       case AFMT_S16_LE:
-           len += sprintf(buffer+len, " (signed 16 bit little)");
-           break;
-       case AFMT_U16_LE:
-           len += sprintf(buffer+len, " (unsigned 16 bit little)");
-           break;
-    }
-    len += sprintf(buffer+len, "\n");
-    len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
-                  sound.soft.speed, sound.hard.speed);
-    len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
-                  sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-       case DMASND_TT:
-           len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n",
-                          sound.volume_left);
-           len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n",
-                          sound.volume_right);
-           len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n",
-                          sound.bass);
-           len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n",
-                          sound.treble);
-           break;
-       case DMASND_FALCON:
-           len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n",
-                          sound.volume_left);
-           len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n",
-                          sound.volume_right);
-           break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-       case DMASND_AMIGA:
-           len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
-                          sound.volume_left);
-           len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
-                          sound.volume_right);
-           break;
-#endif /* CONFIG_AMIGA */
-    }
-    len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d\n",
-                  sq.block_size, sq.max_count);
-    len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
-                  sq.rear_size);
-    len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n",
-                  sq.playing, sq.syncing);
-    state.len = len;
-    return(0);
-}
-
-
-static int state_release(void)
-{
-    state.busy = 0;
-    return(0);
-}
-
-
-static int state_read(char *dest, int count)
-{
-    int n = state.len-state.ptr;
-    if (n > count)
-       n = count;
-    if (n <= 0)
-       return(0);
-    copy_to_user(dest, &state.buf[state.ptr], n);
-    state.ptr += n;
-    return(n);
-}
-
-
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file)
-{
-    int dev = MINOR(inode->i_rdev) & 0x0f;
-
-    switch (dev) {
-       case SND_DEV_STATUS:
-           return(state_open(file->f_flags));
-       case SND_DEV_CTL:
-           return(mixer_open(file->f_flags));
-       case SND_DEV_DSP:
-       case SND_DEV_AUDIO:
-           {
-               int rc = sq_open(file->f_flags);
-               if (rc == 0) {
-                   sound.minDev = dev;
-                   sound.soft = sound.dsp;
-                   sound_init();
-                   if (dev == SND_DEV_AUDIO) {
-                       sound_set_speed(8000);
-                       sound_set_stereo(0);
-                       sound_set_format(AFMT_MU_LAW);
-                   }
-               }
-               return(rc);
-           }
-       default:
-           return(-ENXIO);
-    }
-}
-
-
-static int sound_fsync(struct inode *inode, struct file *filp)
-{
-    int dev = MINOR(inode->i_rdev) & 0x0f;
-
-    switch (dev) {
-       case SND_DEV_STATUS:
-       case SND_DEV_CTL:
-           return(0);
-       case SND_DEV_DSP:
-       case SND_DEV_AUDIO:
-           return(sq_sync());
-       default:
-           return(unknown_minor_dev("sound_fsync", dev));
-    }
-}
-
-
-static void sound_release(struct inode *inode, struct file *file)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-       case SND_DEV_STATUS: state_release(); return;
-       case SND_DEV_CTL: mixer_release(); return;
-       case SND_DEV_DSP:
-       case SND_DEV_AUDIO:
-           sq_release(); sound.soft = sound.dsp; sound_silence();
-           return;
-       default:
-           unknown_minor_dev("sound_release", dev);
-    }
-}
-
-
-static int sound_lseek(struct inode *inode, struct file *file, off_t offset,
-                      int orig)
-{
-    return(-EPERM);
-}
-
-
-static int sound_read(struct inode *inode, struct file *file, char *buf,
-                     int count)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-       case SND_DEV_STATUS:
-           return(state_read(buf, count));
-       case SND_DEV_CTL:
-       case SND_DEV_DSP:
-       case SND_DEV_AUDIO:
-           return(-EPERM);
-       default:
-           return(unknown_minor_dev("sound_read", dev));
-    }
-}
-
-
-static int sound_write(struct inode *inode, struct file *file, const char *buf,
-                      int count)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-       case SND_DEV_STATUS:
-       case SND_DEV_CTL:
-           return(-EPERM);
-       case SND_DEV_DSP:
-       case SND_DEV_AUDIO:
-           return(sq_write(buf, count));
-       default:
-           return(unknown_minor_dev("sound_write", dev));
-    }
-}
-
-
-static int ioctl_return(int *addr, int value)
-{
-    int error;
-
-    if (value < 0)
-       return(value);
-
-    error = verify_area(VERIFY_WRITE, addr, sizeof(int));
-    if (error)
-       return(error);
-
-    put_user(value, addr);
-    return(0);
-}
-
-
-static int unknown_minor_dev(char *fname, int dev)
-{
-    /* printk("%s: Unknown minor device %d\n", fname, dev); */
-    return(-ENXIO);
-}
-
-
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-                      u_long arg)
-{
-    int dev = MINOR(inode->i_rdev);
-    u_long fmt;
-
-    switch (dev & 0x0f) {
-       case SND_DEV_STATUS:
-           return(-EPERM);
-       case SND_DEV_CTL:
-           return(mixer_ioctl(inode, file, cmd, arg));
-       case SND_DEV_AUDIO:
-       case SND_DEV_DSP:
-           switch (cmd) {
-               case SNDCTL_DSP_RESET:
-                   sq_reset();
-                   return(0);
-               case SNDCTL_DSP_POST:
-               case SNDCTL_DSP_SYNC:
-                   return(sound_fsync(inode, file));
-
-               /* ++TeSche: before changing any of these it's probably wise to
-                * wait until sound playing has settled down
-                */
-               case SNDCTL_DSP_SPEED:
-                   sound_fsync(inode, file);
-                   return(IOCTL_OUT(arg, sound_set_speed(IOCTL_IN(arg))));
-               case SNDCTL_DSP_STEREO:
-                   sound_fsync(inode, file);
-                   return(IOCTL_OUT(arg, sound_set_stereo(IOCTL_IN(arg))));
-               case SOUND_PCM_WRITE_CHANNELS:
-                   sound_fsync(inode, file);
-                   return(IOCTL_OUT(arg, sound_set_stereo(IOCTL_IN(arg)-1)+1));
-               case SNDCTL_DSP_SETFMT:
-                   sound_fsync(inode, file);
-                   return(IOCTL_OUT(arg, sound_set_format(IOCTL_IN(arg))));
-               case SNDCTL_DSP_GETFMTS:
-                   fmt = 0;
-                   if (sound.trans) {
-                       if (sound.trans->ct_ulaw)
-                           fmt |= AFMT_MU_LAW;
-                       if (sound.trans->ct_alaw)
-                           fmt |= AFMT_A_LAW;
-                       if (sound.trans->ct_s8)
-                           fmt |= AFMT_S8;
-                       if (sound.trans->ct_u8)
-                           fmt |= AFMT_U8;
-                       if (sound.trans->ct_s16be)
-                           fmt |= AFMT_S16_BE;
-                       if (sound.trans->ct_u16be)
-                           fmt |= AFMT_U16_BE;
-                       if (sound.trans->ct_s16le)
-                           fmt |= AFMT_S16_LE;
-                       if (sound.trans->ct_u16le)
-                           fmt |= AFMT_U16_LE;
-                   }
-                   return(IOCTL_OUT(arg, fmt));
-               case SNDCTL_DSP_GETBLKSIZE:
-                   return(IOCTL_OUT(arg, 10240));
-               case SNDCTL_DSP_SUBDIVIDE:
-               case SNDCTL_DSP_SETFRAGMENT:
-                   break;
-
-               default:
-                   return(mixer_ioctl(inode, file, cmd, arg));
-           }
-           break;
-
-       default:
-           return(unknown_minor_dev("sound_ioctl", dev));
-    }
-    return(-EINVAL);
-}
-
-
-static struct file_operations sound_fops =
-{
-    sound_lseek,
-    sound_read,
-    sound_write,
-    NULL,
-    NULL,                      /* select */
-    sound_ioctl,
-    NULL,
-    sound_open,
-    sound_release,
-    sound_fsync
-};
-
-
-
-/*** Config & Setup **********************************************************/
-
-
-void soundcard_init(void)
-{
-    int has_sound = 0;
-    char **buffers;
-    int i;
-
-    switch (boot_info.machtype) {
-#ifdef CONFIG_ATARI
-       case MACH_ATARI:
-           if (ATARIHW_PRESENT(PCM_8BIT)) {
-               if (ATARIHW_PRESENT(CODEC))
-                   sound.mach = machFalcon;
-               else if (ATARIHW_PRESENT(MICROWIRE))
-                   sound.mach = machTT;
-               else
-                   break;
-               if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
-                   has_sound = 1;
-               else
-                   printk("DMA sound driver: Timer A interrupt already in use\n");
-           }
-           break;
-
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-       case MACH_AMIGA:
-           if (AMIGAHW_PRESENT(AMI_AUDIO)) {
-               sound.mach = machAmiga;
-               has_sound = 1;
-           }
-           break;
-#endif /* CONFIG_AMIGA */
-    }
-    if (!has_sound)
-       return;
-
-    /* Set up sound queue, /dev/audio and /dev/dsp. */
-    buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
-    if (!buffers) {
-    out_of_memory:
-       printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
-       return;
-    }
-    for (i = 0; i < numBufs; i++) {
-       buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
-       if (!buffers[i]) {
-           while (i--)
-               sound.mach.dma_free (buffers[i], bufSize << 10);
-           kfree (buffers);
-           goto out_of_memory;
-        }
-    }
-
-    /* Register driver with the VFS. */
-    register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
-
-    sq_init(numBufs, bufSize << 10, buffers);
-
-    /* Set up /dev/sndstat. */
-    state_init();
-
-    /* Set up /dev/mixer. */
-    mixer_init();
-
-    if (!sound.mach.irqinit()) {
-       printk("DMA sound driver: Interrupt initialization failed\n");
-       return;
-    }
-
-    printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
-          bufSize);
-
-    return;
-}
-
-void sound_setup(char *str, int *ints)
-{
-    /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
-}
-
-void dmasound_setup(char *str, int *ints)
-{
-    /* check the bootstrap parameter for "dmasound=" */
-
-    switch (ints[0]) {
-       case 3:
-           if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
-               printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
-           else
-               catchRadius = ints[3];
-           /* fall through */
-       case 2:
-           if (ints[1] < MIN_BUFFERS)
-               printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs);
-           else
-               numBufs = ints[1];
-           if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
-               printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize);
-           else
-               bufSize = ints[2];
-           break;
-       case 0:
-           break;
-       default:
-           printk("dmasound_setup: illegal number of arguments\n");
-    }
-}
diff --git a/drivers/sound/dmasound.h b/drivers/sound/dmasound.h
deleted file mode 100644 (file)
index fec3ad8..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-
-/* linux/drivers/sound/dmasound.h */
-
-/*
- * Minor numbers for the sound driver.
- *
- * Unfortunately Creative called the codec chip of SB as a DSP. For this
- * reason the /dev/dsp is reserved for digitized audio use. There is a
- * device for true DSP processors but it will be called something else.
- * In v3.0 it's /dev/sndproc but this could be a temporary solution.
- */
-
-#define SND_NDEVS      256     /* Number of supported devices */
-#define SND_DEV_CTL    0       /* Control port /dev/mixer */
-#define SND_DEV_SEQ    1       /* Sequencer output /dev/sequencer (FM
-                                  synthesizer and MIDI output) */
-#define SND_DEV_MIDIN  2       /* Raw midi access */
-#define SND_DEV_DSP    3       /* Digitized voice /dev/dsp */
-#define SND_DEV_AUDIO  4       /* Sparc compatible /dev/audio */
-#define SND_DEV_DSP16  5       /* Like /dev/dsp but 16 bits/sample */
-#define SND_DEV_STATUS 6       /* /dev/sndstat */
-/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
-#define SND_DEV_SEQ2   8       /* /dev/sequencer, level 2 interface */
-#define SND_DEV_SNDPROC 9      /* /dev/sndproc for programmable devices */
-#define SND_DEV_PSS    SND_DEV_SNDPROC
-
-#define DSP_DEFAULT_SPEED      8000
-
-#define ON             1
-#define OFF            0
-
-#define MAX_AUDIO_DEV  5
-#define MAX_MIXER_DEV  2
-#define MAX_SYNTH_DEV  3
-#define MAX_MIDI_DEV   6
-#define MAX_TIMER_DEV  3
index e967015fd2923174e0bc1159a76646f658358d74..fe6d497a7143313b9c33727b78493bfd4ff1bb92 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
index 29805b7d5ec0c47d5898d42a278c81c1b3201820..3c0ac10de9c47dca7d9417dc87e6aa2b4063b2a2 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,7 +15,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
 
 #include "gus_hw.h"
 
@@ -27,75 +27,31 @@ extern int      gus_pcm_volume;
 extern int      have_gus_max;
 int             gus_pnp_flag = 0;
 
-int            *gus_osp;
-
 void
 attach_gus_card (struct address_info *hw_config)
 {
-  int             io_addr;
-
-  gus_osp = hw_config->osp;
   snd_set_irq_handler (hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp);
 
-  if (gus_wave_detect (hw_config->io_base))    /*
-                                                * Try first the default
-                                                */
-    {
-      gus_wave_init (hw_config);
+  gus_wave_init (hw_config);
 
-      request_region (hw_config->io_base, 16, "GUS");
-      request_region (hw_config->io_base + 0x100, 12, "GUS");  /* 0x10c-> is MAX */
-
-      if (sound_alloc_dma (hw_config->dma, "GUS"))
-       printk ("gus_card.c: Can't allocate DMA channel\n");
-      if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-       if (sound_alloc_dma (hw_config->dma2, "GUS(2)"))
-         printk ("gus_card.c: Can't allocate DMA channel2\n");
-#ifdef CONFIG_MIDI
-      gus_midi_init ();
-#endif
-      return;
-    }
-
-#ifndef EXCLUDE_GUS_IODETECT
-
-  /*
-   * Look at the possible base addresses (0x2X0, X=1, 2, 3, 4, 5, 6)
-   */
+  request_region (hw_config->io_base, 16, "GUS");
+  request_region (hw_config->io_base + 0x100, 12, "GUS");      /* 0x10c-> is MAX */
 
-  for (io_addr = 0x210; io_addr <= 0x260; io_addr += 0x10)
-    if (io_addr != hw_config->io_base) /*
-                                        * Already tested
-                                        */
-      if (gus_wave_detect (io_addr))
-       {
-         hw_config->io_base = io_addr;
-
-         printk (" WARNING! GUS found at %x, config was %x ", io_addr, hw_config->io_base);
-         gus_wave_init (hw_config);
-         request_region (io_addr, 16, "GUS");
-         request_region (io_addr + 0x100, 12, "GUS");  /* 0x10c-> is MAX */
-         if (sound_alloc_dma (hw_config->dma, "GUS"))
-           printk ("gus_card.c: Can't allocate DMA channel\n");
-         if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-           if (sound_alloc_dma (hw_config->dma2, "GUS"))
-             printk ("gus_card.c: Can't allocate DMA channel2\n");
+  if (sound_alloc_dma (hw_config->dma, "GUS"))
+    printk ("gus_card.c: Can't allocate DMA channel\n");
+  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
+    if (sound_alloc_dma (hw_config->dma2, "GUS(2)"))
+      printk ("gus_card.c: Can't allocate DMA channel2\n");
 #ifdef CONFIG_MIDI
-         gus_midi_init ();
+  gus_midi_init ();
 #endif
-         return;
-       }
-
-#endif
-
 }
 
 int
 probe_gus (struct address_info *hw_config)
 {
-  int             io_addr, irq;
-
-  gus_osp = hw_config->osp;
+  int             irq;
+  int             io_addr;
 
   if (hw_config->card_subtype == 1)
     gus_pnp_flag = 1;
@@ -226,7 +182,7 @@ probe_gus_db16 (struct address_info *hw_config)
 void
 attach_gus_db16 (struct address_info *hw_config)
 {
-#ifdef CONFIG_GUS
+#ifdef CONFIG_GUSHW
   gus_pcm_volume = 100;
   gus_wave_volume = 90;
 #endif
index 5bea9c00f87fb204cecf5fa17bc80acc090c5498..89fb3be2caa2d406ea1da12872e9bee075d14cb5 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -17,7 +17,7 @@
 
 #include "gus_hw.h"
 
-#if defined(CONFIG_GUS) && defined(CONFIG_MIDI)
+#if defined(CONFIG_GUSHW) && defined(CONFIG_MIDI)
 
 static int      midi_busy = 0, input_opened = 0;
 static int      my_dev;
@@ -48,10 +48,10 @@ gus_midi_open (int dev, int mode,
   if (midi_busy)
     {
       printk ("GUS: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
-  outb (MIDI_RESET, u_MidiControl);
+  outb ((MIDI_RESET), u_MidiControl);
   gus_delay ();
 
   gus_midi_control = 0;
@@ -64,7 +64,7 @@ gus_midi_open (int dev, int mode,
     }
 
 
-  outb (gus_midi_control, u_MidiControl);      /* Enable */
+  outb ((gus_midi_control), u_MidiControl);    /* Enable */
 
   midi_busy = 1;
   qlen = qhead = qtail = output_used = 0;
@@ -87,7 +87,7 @@ dump_to_midi (unsigned char midi_byte)
   if (GUS_MIDI_STATUS () & MIDI_XMIT_EMPTY)
     {
       ok = 1;
-      outb (midi_byte, u_MidiData);
+      outb ((midi_byte), u_MidiData);
     }
   else
     {
@@ -95,7 +95,7 @@ dump_to_midi (unsigned char midi_byte)
        * Enable Midi xmit interrupts (again)
        */
       gus_midi_control |= MIDI_ENABLE_XMIT;
-      outb (gus_midi_control, u_MidiControl);
+      outb ((gus_midi_control), u_MidiControl);
     }
 
   restore_flags (flags);
@@ -109,7 +109,7 @@ gus_midi_close (int dev)
    * Reset FIFO pointers, disable intrs
    */
 
-  outb (MIDI_RESET, u_MidiControl);
+  outb ((MIDI_RESET), u_MidiControl);
   midi_busy = 0;
 }
 
@@ -180,7 +180,7 @@ gus_midi_end_read (int dev)
 static int
 gus_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -242,7 +242,7 @@ gus_midi_init (void)
       return;
     }
 
-  outb (MIDI_RESET, u_MidiControl);
+  outb ((MIDI_RESET), u_MidiControl);
 
   std_midi_synth.midi_dev = my_dev = num_midis;
   midi_devs[num_midis++] = &gus_midi_operations;
@@ -282,8 +282,8 @@ gus_midi_interrupt (int dummy)
               * Disable Midi output interrupts, since no data in the buffer
               */
              gus_midi_control &= ~MIDI_ENABLE_XMIT;
-             outb (gus_midi_control, u_MidiControl);
-             outb (gus_midi_control, u_MidiControl);
+             outb ((gus_midi_control), u_MidiControl);
+             outb ((gus_midi_control), u_MidiControl);
            }
        }
 
index e9e352812e2a835709d35125fad0f5441ede5fec..9b00b4e2197e06f0e770aea326adb48d1d74b1d0 100644 (file)
@@ -4,14 +4,14 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 #include <linux/config.h>
 
 #include "sound_config.h"
-#ifdef CONFIG_GUS
+#ifdef CONFIG_GUSHW
 #include "gus_linearvol.h"
 
 #define GUS_VOLUME     gus_wave_volume
index 6d6ccae7fbfd470d985c21625c8fe6112543b088..7166556382fe0defe967d2d7a207d3016247664e 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -19,7 +19,9 @@
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
 
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
+
+#define GUS_BANK_SIZE (256*1024)
 
 #define MAX_SAMPLE     150
 #define MAX_PATCH      256
@@ -103,7 +105,7 @@ static int      gus_audio_speed;
 static int      gus_audio_channels;
 static int      gus_audio_bits;
 
-static wait_handle *dram_sleeper = NULL;
+static struct wait_queue *dram_sleeper = NULL;
 static volatile struct snd_wait dram_sleep_flag =
 {0};
 
@@ -130,6 +132,7 @@ struct voice_info voices[32];
 
 static int      freq_div_table[] =
 {
+  44100,
   44100,                       /* 14 */
   41160,                       /* 15 */
   38587,                       /* 16 */
@@ -214,13 +217,13 @@ gus_poke (long addr, unsigned char data)
 
   save_flags (flags);
   cli ();
-  outb (0x43, u_Command);
-  outb (addr & 0xff, u_DataLo);
-  outb ((addr >> 8) & 0xff, u_DataHi);
+  outb ((0x43), u_Command);
+  outb ((addr & 0xff), u_DataLo);
+  outb (((addr >> 8) & 0xff), u_DataHi);
 
-  outb (0x44, u_Command);
-  outb ((addr >> 16) & 0xff, u_DataHi);
-  outb (data, u_DRAMIO);
+  outb ((0x44), u_Command);
+  outb (((addr >> 16) & 0xff), u_DataHi);
+  outb ((data), u_DRAMIO);
   restore_flags (flags);
 }
 
@@ -232,12 +235,12 @@ gus_peek (long addr)
 
   save_flags (flags);
   cli ();
-  outb (0x43, u_Command);
-  outb (addr & 0xff, u_DataLo);
-  outb ((addr >> 8) & 0xff, u_DataHi);
+  outb ((0x43), u_Command);
+  outb ((addr & 0xff), u_DataLo);
+  outb (((addr >> 8) & 0xff), u_DataHi);
 
-  outb (0x44, u_Command);
-  outb ((addr >> 16) & 0xff, u_DataHi);
+  outb ((0x44), u_Command);
+  outb (((addr >> 16) & 0xff), u_DataHi);
   tmp = inb (u_DRAMIO);
   restore_flags (flags);
 
@@ -252,8 +255,8 @@ gus_write8 (int reg, unsigned int data)
   save_flags (flags);
   cli ();
 
-  outb (reg, u_Command);
-  outb ((unsigned char) (data & 0xff), u_DataHi);
+  outb ((reg), u_Command);
+  outb (((unsigned char) (data & 0xff)), u_DataHi);
 
   restore_flags (flags);
 }
@@ -266,7 +269,7 @@ gus_read8 (int reg)
 
   save_flags (flags);
   cli ();
-  outb (reg | 0x80, u_Command);
+  outb ((reg | 0x80), u_Command);
   val = inb (u_DataHi);
   restore_flags (flags);
 
@@ -281,7 +284,7 @@ gus_look8 (int reg)
 
   save_flags (flags);
   cli ();
-  outb (reg, u_Command);
+  outb ((reg), u_Command);
   val = inb (u_DataHi);
   restore_flags (flags);
 
@@ -296,10 +299,10 @@ gus_write16 (int reg, unsigned int data)
   save_flags (flags);
   cli ();
 
-  outb (reg, u_Command);
+  outb ((reg), u_Command);
 
-  outb ((unsigned char) (data & 0xff), u_DataLo);
-  outb ((unsigned char) ((data >> 8) & 0xff), u_DataHi);
+  outb (((unsigned char) (data & 0xff)), u_DataLo);
+  outb (((unsigned char) ((data >> 8) & 0xff)), u_DataHi);
 
   restore_flags (flags);
 }
@@ -313,7 +316,7 @@ gus_read16 (int reg)
   save_flags (flags);
   cli ();
 
-  outb (reg | 0x80, u_Command);
+  outb ((reg | 0x80), u_Command);
 
   lo = inb (u_DataLo);
   hi = inb (u_DataHi);
@@ -332,7 +335,7 @@ gus_look16 (int reg)
   save_flags (flags);
   cli ();
 
-  outb (reg, u_Command);
+  outb ((reg), u_Command);
 
   lo = inb (u_DataLo);
   hi = inb (u_DataHi);
@@ -379,7 +382,7 @@ gus_select_voice (int voice)
   if (voice < 0 || voice > 31)
     return;
 
-  outb (voice, u_Voice);
+  outb ((voice), u_Voice);
 }
 
 static void
@@ -746,14 +749,14 @@ gus_initialize (void)
    * Set up for Digital ASIC
    */
 
-  outb (0x05, gus_base + 0x0f);
+  outb ((0x05), gus_base + 0x0f);
 
   mix_image |= 0x02;           /* Disable line out (for a moment) */
-  outb (mix_image, u_Mixer);
+  outb ((mix_image), u_Mixer);
 
-  outb (0x00, u_IRQDMAControl);
+  outb ((0x00), u_IRQDMAControl);
 
-  outb (0x00, gus_base + 0x0f);
+  outb ((0x00), gus_base + 0x0f);
 
   /*
    * Now set up the DMA and IRQ interface
@@ -810,27 +813,27 @@ gus_initialize (void)
    * Doing it first time
    */
 
-  outb (mix_image, u_Mixer);   /* Select DMA control */
-  outb (dma_image | 0x80, u_IRQDMAControl);    /* Set DMA address */
+  outb ((mix_image), u_Mixer); /* Select DMA control */
+  outb ((dma_image | 0x80), u_IRQDMAControl);  /* Set DMA address */
 
-  outb (mix_image | 0x40, u_Mixer);    /* Select IRQ control */
-  outb (irq_image, u_IRQDMAControl);   /* Set IRQ address */
+  outb ((mix_image | 0x40), u_Mixer);  /* Select IRQ control */
+  outb ((irq_image), u_IRQDMAControl); /* Set IRQ address */
 
   /*
    * Doing it second time
    */
 
-  outb (mix_image, u_Mixer);   /* Select DMA control */
-  outb (dma_image, u_IRQDMAControl);   /* Set DMA address */
+  outb ((mix_image), u_Mixer); /* Select DMA control */
+  outb ((dma_image), u_IRQDMAControl); /* Set DMA address */
 
-  outb (mix_image | 0x40, u_Mixer);    /* Select IRQ control */
-  outb (irq_image, u_IRQDMAControl);   /* Set IRQ address */
+  outb ((mix_image | 0x40), u_Mixer);  /* Select IRQ control */
+  outb ((irq_image), u_IRQDMAControl); /* Set IRQ address */
 
   gus_select_voice (0);                /* This disables writes to IRQ/DMA reg */
 
   mix_image &= ~0x02;          /* Enable line out */
   mix_image |= 0x08;           /* Enable IRQ */
-  outb (mix_image, u_Mixer);   /*
+  outb ((mix_image), u_Mixer); /*
                                   * Turn mixer channels on
                                   * Note! Mic in is left off.
                                 */
@@ -849,6 +852,7 @@ gus_initialize (void)
   restore_flags (flags);
 }
 
+
 static void
 pnp_mem_init (void)
 {
@@ -928,6 +932,7 @@ pnp_mem_init (void)
       printk ("Sound: An Interwave audio chip detected but no DRAM\n");
       printk ("Sound: Unable to work with this card.\n");
       gus_write8 (0x19, gus_read8 (0x19) & ~0x01);
+      gus_mem_size = 0;
       return;
     }
 /*
@@ -1026,6 +1031,7 @@ gus_wave_detect (int baseaddr)
 {
   unsigned long   i, max_mem = 1024L;
   unsigned long   loc;
+  unsigned char   val;
 
   gus_base = baseaddr;
 
@@ -1037,6 +1043,24 @@ gus_wave_detect (int baseaddr)
   gus_delay ();
   gus_delay ();
 
+#ifdef GUSPNP_AUTODETECT
+  val = gus_look8 (0x5b);      /* Version number register */
+  gus_write8 (0x5b, ~val);     /* Invert all bits */
+
+  if ((gus_look8 (0x5b) & 0xf0) == (val & 0xf0))       /* No change */
+    if ((gus_look8 (0x5b) & 0x0f) == ((~val) & 0x0f))  /* Change */
+      {
+       DDB (printk ("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
+       gus_pnp_flag = 1;
+      }
+    else
+      {
+       DDB (printk ("Not an Interwave chip (%x)\n", gus_look8 (0x5b)));
+       gus_pnp_flag = 0;
+      }
+  gus_write8 (0x5b, val);      /* Restore all bits */
+#endif
+
   if (gus_pnp_flag)
     pnp_mem_init ();
 
@@ -1083,7 +1107,11 @@ guswave_ioctl (int dev,
     {
     case SNDCTL_SYNTH_INFO:
       gus_info.nr_voices = nr_voices;
-      copy_to_user (&((char *) arg)[0], &gus_info, sizeof (gus_info));
+      {
+       char           *fixit = (char *) &gus_info;
+
+       copy_to_user (&((char *) arg)[0], fixit, sizeof (gus_info));
+      };
       return 0;
       break;
 
@@ -1097,10 +1125,10 @@ guswave_ioctl (int dev,
       break;
 
     case SNDCTL_SYNTH_MEMAVL:
-      return gus_mem_size - free_mem_ptr - 32;
+      return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -1110,10 +1138,10 @@ guswave_set_instr (int dev, int voice, int instr_no)
   int             sample_no;
 
   if (instr_no < 0 || instr_no > MAX_PATCH)
-    return -(EINVAL);
+    instr_no = 0;              /* Default to acoustic piano */
 
   if (voice < 0 || voice > 31)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
     {
@@ -1127,14 +1155,14 @@ guswave_set_instr (int dev, int voice, int instr_no)
   if (sample_no == NOT_SAMPLE)
     {
       printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
-      return -(EINVAL);                /* Patch not defined */
+      return -EINVAL;          /* Patch not defined */
     }
 
   if (sample_ptrs[sample_no] == -1)    /* Sample not loaded */
     {
       printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n",
              sample_no, instr_no, voice);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   sample_map[voice] = sample_no;
@@ -1388,7 +1416,7 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
   if (voice < 0 || voice > 31)
     {
       printk ("GUS: Invalid voice\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (note_num == 255)
@@ -1406,12 +1434,12 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
 
   if ((patch = patch_map[voice]) == -1)
     {
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if ((samplep = patch_table[patch]) == NOT_SAMPLE)
     {
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   note_freq = note_to_freq (note_num);
@@ -1492,8 +1520,8 @@ guswave_start_note2 (int dev, int voice, int note_num, int volume)
   if (samples[sample].mode & WAVE_16_BITS)
     {
       mode |= 0x04;            /* 16 bits */
-      if ((sample_ptrs[sample] >> 18) !=
-         ((sample_ptrs[sample] + samples[sample].len) >> 18))
+      if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
+         ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
        printk ("GUS: Sample address error\n");
     }
 
@@ -1660,7 +1688,7 @@ guswave_open (int dev, int mode)
   int             err;
 
   if (gus_busy)
-    return -(EBUSY);
+    return -EBUSY;
 
   voice_alloc->timestamp = 0;
 
@@ -1672,7 +1700,7 @@ guswave_open (int dev, int mode)
   else
     gus_no_dma = 0;
 
-  dram_sleep_flag.flags = WK_NONE;
+  dram_sleep_flag.opts = WK_NONE;
   gus_busy = 1;
   active_device = GUS_DEV_WAVE;
 
@@ -1710,21 +1738,24 @@ guswave_load_patch (int dev, int format, const char *addr,
   if (format != GUS_PATCH)
     {
       printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (count < sizeof_patch)
     {
       printk ("GUS Error: Patch header too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   count -= sizeof_patch;
 
+  if (gus_mem_size == 0)
+    return -ENOSPC;
+
   if (free_sample >= MAX_SAMPLE)
     {
       printk ("GUS: Sample table full\n");
-      return -(ENOSPC);
+      return -ENOSPC;
     }
 
   /*
@@ -1739,7 +1770,7 @@ guswave_load_patch (int dev, int format, const char *addr,
   if (instr < 0 || instr > MAX_PATCH)
     {
       printk ("GUS: Invalid patch number %d\n", instr);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (count < patch.len)
@@ -1752,7 +1783,7 @@ guswave_load_patch (int dev, int format, const char *addr,
   if (patch.len <= 0 || patch.len > gus_mem_size)
     {
       printk ("GUS: Invalid sample length %d\n", (int) patch.len);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (patch.mode & WAVE_LOOPING)
@@ -1760,20 +1791,18 @@ guswave_load_patch (int dev, int format, const char *addr,
       if (patch.loop_start < 0 || patch.loop_start >= patch.len)
        {
          printk ("GUS: Invalid loop start\n");
-         return -(EINVAL);
+         return -EINVAL;
        }
 
       if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
        {
          printk ("GUS: Invalid loop end\n");
-         return -(EINVAL);
+         return -EINVAL;
        }
     }
 
   free_mem_ptr = (free_mem_ptr + 31) & ~31;    /* 32 byte alignment */
 
-#define GUS_BANK_SIZE (256*1024)
-
   if (patch.mode & WAVE_16_BITS)
     {
       /*
@@ -1782,7 +1811,7 @@ guswave_load_patch (int dev, int format, const char *addr,
       if (patch.len >= GUS_BANK_SIZE)
        {
          printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
-         return -(ENOSPC);
+         return -ENOSPC;
        }
 
       if ((free_mem_ptr / GUS_BANK_SIZE) !=
@@ -1792,14 +1821,14 @@ guswave_load_patch (int dev, int format, const char *addr,
          ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
 
          if ((tmp_mem + patch.len) > gus_mem_size)
-           return -(ENOSPC);
+           return -ENOSPC;
 
          free_mem_ptr = tmp_mem;       /* This leaves unusable memory */
        }
     }
 
   if ((free_mem_ptr + patch.len) > gus_mem_size)
-    return -(ENOSPC);
+    return -ENOSPC;
 
   sample_ptrs[free_sample] = free_mem_ptr;
 
@@ -1839,14 +1868,14 @@ guswave_load_patch (int dev, int format, const char *addr,
        blk_sz = left;
 
       /*
-       * DMA cannot cross 256k bank boundaries. Check for that.
+       * DMA cannot cross bank (256k) boundaries. Check for that.
        */
       blk_end = target + blk_sz;
 
-      if ((target >> 18) != (blk_end >> 18))
+      if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
        {                       /* Split the block */
 
-         blk_end &= ~(256 * 1024 - 1);
+         blk_end &= ~(GUS_BANK_SIZE - 1);
          blk_sz = blk_end - target;
        }
 
@@ -1858,10 +1887,9 @@ guswave_load_patch (int dev, int format, const char *addr,
          long            i;
          unsigned char   data;
 
-
          for (i = 0; i < blk_sz; i++)
            {
-             data = get_fs_byte (&((addr)[sizeof_patch + i]));
+             get_user (data, (unsigned char *) &((addr)[sizeof_patch + i]));
              if (patch.mode & WAVE_UNSIGNED)
 
                if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
@@ -1878,7 +1906,7 @@ guswave_load_patch (int dev, int format, const char *addr,
          if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
            {
              printk ("GUS: DMA buffer == NULL\n");
-             return -(EINVAL);
+             return -ENOSPC;
            }
 
          /*
@@ -1923,7 +1951,7 @@ guswave_load_patch (int dev, int format, const char *addr,
          if (audio_devs[gus_devnum]->dmachan1 > 3)
            dma_command |= 0x04;        /* 16 bit DMA _channel_ */
 
-         gus_write8 (0x41, dma_command);       /* Lets bo luteet (=bugs) */
+         gus_write8 (0x41, dma_command);       /* Lets go luteet (=bugs) */
 
          /*
           * Sleep here until the DRAM DMA done interrupt is served
@@ -1935,19 +1963,19 @@ guswave_load_patch (int dev, int format, const char *addr,
            unsigned long   tlimit;
 
            if (HZ)
-             current_set_timeout (tlimit = jiffies + (HZ));
+             current->timeout = tlimit = jiffies + (HZ);
            else
              tlimit = (unsigned long) -1;
-           dram_sleep_flag.flags = WK_SLEEP;
-           module_interruptible_sleep_on (&dram_sleeper);
-           if (!(dram_sleep_flag.flags & WK_WAKEUP))
+           dram_sleep_flag.opts = WK_SLEEP;
+           interruptible_sleep_on (&dram_sleeper);
+           if (!(dram_sleep_flag.opts & WK_WAKEUP))
              {
                if (jiffies >= tlimit)
-                 dram_sleep_flag.flags |= WK_TIMEOUT;
+                 dram_sleep_flag.opts |= WK_TIMEOUT;
              }
-           dram_sleep_flag.flags &= ~WK_SLEEP;
+           dram_sleep_flag.opts &= ~WK_SLEEP;
          };
-         if ((dram_sleep_flag.flags & WK_TIMEOUT))
+         if ((dram_sleep_flag.opts & WK_TIMEOUT))
            printk ("GUS: DMA Transfer timed out\n");
          restore_flags (flags);
        }
@@ -2190,59 +2218,99 @@ gus_audio_set_bits (int bits)
 static int
 gus_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
+  int             val;
+
   switch (cmd)
     {
     case SOUND_PCM_WRITE_RATE:
       if (local)
        return gus_audio_set_speed ((int) arg);
-      return snd_ioctl_return ((int *) arg, gus_audio_set_speed (get_user ((int *) arg)));
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_speed (val));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
        return gus_audio_speed;
-      return snd_ioctl_return ((int *) arg, gus_audio_speed);
+      return ioctl_out (arg, gus_audio_speed);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
        return gus_audio_set_channels ((int) arg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, gus_audio_set_channels (get_user ((int *) arg) + 1) - 1);
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_channels (val + 1) - 1);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
        return gus_audio_set_channels ((int) arg);
-      return snd_ioctl_return ((int *) arg, gus_audio_set_channels (get_user ((int *) arg)));
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_channels (val));
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
        return gus_audio_channels;
-      return snd_ioctl_return ((int *) arg, gus_audio_channels);
+      return ioctl_out (arg, gus_audio_channels);
       break;
 
     case SNDCTL_DSP_SETFMT:
       if (local)
        return gus_audio_set_bits ((int) arg);
-      return snd_ioctl_return ((int *) arg, gus_audio_set_bits (get_user ((int *) arg)));
+      get_user (val, (int *) arg);
+      return ioctl_out (arg, gus_audio_set_bits (val));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
        return gus_audio_bits;
-      return snd_ioctl_return ((int *) arg, gus_audio_bits);
+      return ioctl_out (arg, gus_audio_bits);
 
     case SOUND_PCM_WRITE_FILTER:       /* NOT POSSIBLE */
-      return snd_ioctl_return ((int *) arg, -(EINVAL));
+      return ioctl_out (arg, -EINVAL);
       break;
 
     case SOUND_PCM_READ_FILTER:
-      return snd_ioctl_return ((int *) arg, -(EINVAL));
+      return ioctl_out (arg, -EINVAL);
+      break;
+
+/* This is just a temporary hack used for reading the ROM patch set. */
+
+    case SNDCTL_PMGR_ACCESS:
+      {
+       copr_msg       *buf;
+       int             i, pos;
+
+       buf = (copr_msg *) vmalloc (sizeof (copr_msg));
+       if (buf == NULL)
+         return -ENOSPC;
+
+       copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+       pos = buf->len;
+
+       gus_write8 (0x53, gus_look8 (0x53) | 0x02);     /* Select ROM I/O access */
+
+       for (i = 0; i < 2048; i++)
+         {
+           buf->data[i] = gus_peek (pos + i);
+         }
+       gus_write8 (0x53, gus_look8 (0x53) & ~0x02);    /* Select DRAM I/O access */
+       buf->len = 2048;        /* feed back number of WORDs sent */
+       {
+         char           *fixit = (char *) buf;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+       };
+       vfree (buf);
+
+       return 0;
+      }
       break;
 
     }
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -2255,16 +2323,17 @@ gus_audio_reset (int dev)
     }
 }
 
+
 static int
 gus_audio_open (int dev, int mode)
 {
   if (gus_busy)
-    return -(EBUSY);
+    return -EBUSY;
 
   if (gus_pnp_flag && mode & OPEN_READ)
     {
       printk ("Sound: This audio device doesn't have recording capability\n");
-      return -(EIO);
+      return -EIO;
     }
   gus_initialize ();
 
@@ -2588,7 +2657,7 @@ gus_audio_prepare_for_input (int dev, int bsize, int bcount)
   if (gus_audio_bits != 8)
     {
       printk ("GUS Error: 16 bit recording not supported\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -2653,9 +2722,9 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
 
       for (i = 0; i < len; i++)
        {
-         *out_left++ = get_fs_byte (&((userbuf)[in_left]));
+         get_user (*out_left++, (unsigned char *) &((userbuf)[in_left]));
          in_left += 2;
-         *out_right++ = get_fs_byte (&((userbuf)[in_right]));
+         get_user (*out_right++, (unsigned char *) &((userbuf)[in_right]));
          in_right += 2;
        }
     }
@@ -2674,9 +2743,9 @@ gus_copy_from_user (int dev, char *localbuf, int localoffs,
 
       for (i = 0; i < len; i++)
        {
-         *out_left++ = get_fs_word (&((userbuf)[in_left]));
+         get_user (*out_left++, (unsigned short *) &((userbuf)[in_left]));
          in_left += 4;
-         *out_right++ = get_fs_word (&((userbuf)[in_right]));
+         get_user (*out_right++, (unsigned short *) &((userbuf)[in_right]));
          in_right += 4;
        }
     }
@@ -2798,7 +2867,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        struct patch_info *pat;
 
        if (ptr < 0 || ptr >= free_sample)
-         return -(EINVAL);
+         return -EINVAL;
 
        memcpy (rec->data.data8, (char *) &samples[ptr],
                sizeof (struct patch_info));
@@ -2818,12 +2887,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        struct patch_info *pat;
 
        if (ptr < 0 || ptr >= free_sample)
-         return -(EINVAL);
+         return -EINVAL;
 
        pat = (struct patch_info *) rec->data.data8;
 
        if (pat->len > samples[ptr].len)        /* Cannot expand sample */
-         return -(EINVAL);
+         return -EINVAL;
 
        pat->key = samples[ptr].key;    /* Ensure the link is correct */
 
@@ -2843,10 +2912,10 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        int             l = rec->parm3;
 
        if (sample < 0 || sample >= free_sample)
-         return -(EINVAL);
+         return -EINVAL;
 
        if (offs < 0 || offs >= samples[sample].len)
-         return -(EINVAL);     /* Invalid offset */
+         return -EINVAL;       /* Invalid offset */
 
        n = samples[sample].len - offs;         /* Num of bytes left */
 
@@ -2857,12 +2926,12 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          l = sizeof (rec->data.data8);
 
        if (l <= 0)
-         return -(EINVAL);     /*
+         return -EINVAL;       /*
                                   * Was there a bug?
                                 */
 
        offs += sample_ptrs[sample];    /*
-                                        * Begin offsets + offset to DRAM
+                                        * Begin offset + offset to DRAM
                                         */
 
        for (n = 0; n < l; n++)
@@ -2884,10 +2953,10 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
        int             l = rec->parm3;
 
        if (sample < 0 || sample >= free_sample)
-         return -(EINVAL);
+         return -EINVAL;
 
        if (offs < 0 || offs >= samples[sample].len)
-         return -(EINVAL);     /*
+         return -EINVAL;       /*
                                   * Invalid offset
                                 */
 
@@ -2902,7 +2971,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
          l = sizeof (rec->data.data8);
 
        if (l <= 0)
-         return -(EINVAL);     /*
+         return -EINVAL;       /*
                                   * Was there a bug?
                                 */
 
@@ -2920,7 +2989,7 @@ guswave_patchmgr (int dev, struct patmgr_info *rec)
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -3030,7 +3099,7 @@ set_input_volumes (void)
 
   mix_image &= ~0x07;
   mix_image |= mask & 0x07;
-  outb (mix_image, u_Mixer);
+  outb ((mix_image), u_Mixer);
 
   restore_flags (flags);
 }
@@ -3046,16 +3115,20 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
-           gus_recmask = get_user ((int *) arg) & MIX_DEVS;
+           get_user (gus_recmask, (int *) arg);
+           gus_recmask &= MIX_DEVS;
            if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
              gus_recmask = SOUND_MASK_MIC;
            /* Note! Input volumes are updated during next open for recording */
-           return snd_ioctl_return ((int *) arg, gus_recmask);
+           return ioctl_out (arg, gus_recmask);
            break;
 
          case SOUND_MIXER_MIC:
            {
-             int             vol = get_user ((int *) arg) & 0xff;
+             int             vol;
+
+             get_user (vol, (int *) arg);
+             vol &= 0xff;
 
              if (vol < 0)
                vol = 0;
@@ -3063,13 +3136,16 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
                vol = 100;
              gus_mic_vol = vol;
              set_input_volumes ();
-             return snd_ioctl_return ((int *) arg, vol | (vol << 8));
+             return ioctl_out (arg, vol | (vol << 8));
            }
            break;
 
          case SOUND_MIXER_LINE:
            {
-             int             vol = get_user ((int *) arg) & 0xff;
+             int             vol;
+
+             get_user (vol, (int *) arg);
+             vol &= 0xff;
 
              if (vol < 0)
                vol = 0;
@@ -3077,25 +3153,27 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
                vol = 100;
              gus_line_vol = vol;
              set_input_volumes ();
-             return snd_ioctl_return ((int *) arg, vol | (vol << 8));
+             return ioctl_out (arg, vol | (vol << 8));
            }
            break;
 
          case SOUND_MIXER_PCM:
-           gus_pcm_volume = get_user ((int *) arg) & 0xff;
+           get_user (gus_pcm_volume, (int *) arg);
+           gus_pcm_volume &= 0xff;
            if (gus_pcm_volume < 0)
              gus_pcm_volume = 0;
            if (gus_pcm_volume > 100)
              gus_pcm_volume = 100;
            gus_audio_update_volume ();
-           return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
+           return ioctl_out (arg, gus_pcm_volume | (gus_pcm_volume << 8));
            break;
 
          case SOUND_MIXER_SYNTH:
            {
              int             voice;
 
-             gus_wave_volume = get_user ((int *) arg) & 0xff;
+             get_user (gus_wave_volume, (int *) arg);
+             gus_wave_volume &= 0xff;
 
              if (gus_wave_volume < 0)
                gus_wave_volume = 0;
@@ -3106,12 +3184,12 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
                for (voice = 0; voice < nr_voices; voice++)
                  dynamic_volume_change (voice);        /* Apply the new vol */
 
-             return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
+             return ioctl_out (arg, gus_wave_volume | (gus_wave_volume << 8));
            }
            break;
 
          default:
-           return -(EINVAL);
+           return -EINVAL;
          }
       else
        switch (cmd & 0xff)     /*
@@ -3120,47 +3198,47 @@ gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
          {
 
          case SOUND_MIXER_RECSRC:
-           return snd_ioctl_return ((int *) arg, gus_recmask);
+           return ioctl_out (arg, gus_recmask);
            break;
 
          case SOUND_MIXER_DEVMASK:
-           return snd_ioctl_return ((int *) arg, MIX_DEVS);
+           return ioctl_out (arg, MIX_DEVS);
            break;
 
          case SOUND_MIXER_STEREODEVS:
-           return snd_ioctl_return ((int *) arg, 0);
+           return ioctl_out (arg, 0);
            break;
 
          case SOUND_MIXER_RECMASK:
-           return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+           return ioctl_out (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
            break;
 
          case SOUND_MIXER_CAPS:
-           return snd_ioctl_return ((int *) arg, 0);
+           return ioctl_out (arg, 0);
            break;
 
          case SOUND_MIXER_MIC:
-           return snd_ioctl_return ((int *) arg, gus_mic_vol | (gus_mic_vol << 8));
+           return ioctl_out (arg, gus_mic_vol | (gus_mic_vol << 8));
            break;
 
          case SOUND_MIXER_LINE:
-           return snd_ioctl_return ((int *) arg, gus_line_vol | (gus_line_vol << 8));
+           return ioctl_out (arg, gus_line_vol | (gus_line_vol << 8));
            break;
 
          case SOUND_MIXER_PCM:
-           return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
+           return ioctl_out (arg, gus_pcm_volume | (gus_pcm_volume << 8));
            break;
 
          case SOUND_MIXER_SYNTH:
-           return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
+           return ioctl_out (arg, gus_wave_volume | (gus_wave_volume << 8));
            break;
 
          default:
-           return -(EINVAL);
+           return -EINVAL;
          }
     }
   else
-    return -(EINVAL);
+    return -EINVAL;
 }
 
 static struct mixer_operations gus_mixer_operations =
@@ -3187,7 +3265,7 @@ gus_default_mixer_init (void)
  */
       mix_image &= ~0x07;
       mix_image |= 0x04;       /* All channels enabled */
-      outb (mix_image, u_Mixer);
+      outb ((mix_image), u_Mixer);
     }
 }
 
@@ -3197,6 +3275,7 @@ gus_wave_init (struct address_info *hw_config)
   unsigned long   flags;
   unsigned char   val;
   char           *model_num = "2.4";
+  char            tmp[64], tmp2[64];
   int             gus_type = 0x24;     /* 2.4 */
 
   int             irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
@@ -3227,27 +3306,9 @@ gus_wave_init (struct address_info *hw_config)
      *  Versions < 3.6 don't have the digital ASIC. Try to probe it first.
    */
 
-#ifdef GUSPNP_AUTODETECT
-  val = gus_look8 (0x5b);      /* Version number register */
-  gus_write8 (0x5b, ~val);     /* Invert all bits */
-
-  if ((gus_look8 (0x5b) & 0xf0) == (val & 0xf0))       /* No change */
-    if ((gus_look8 (0x5b) & 0x0f) == ((~val) & 0x0f))  /* Change */
-      {
-       DDB (printk ("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
-       gus_pnp_flag = 1;
-      }
-    else
-      {
-       DDB (printk ("Not an Interwave chip\n"));
-       gus_pnp_flag = 0;
-      }
-  gus_write8 (0x5b, val);      /* Restore all bits */
-#endif
-
   save_flags (flags);
   cli ();
-  outb (0x20, gus_base + 0x0f);
+  outb ((0x20), gus_base + 0x0f);
   val = inb (gus_base + 0x0f);
   restore_flags (flags);
 
@@ -3306,12 +3367,16 @@ gus_wave_init (struct address_info *hw_config)
 
            max_config |= (gus_base >> 4) & 0x0f;       /* Extract the X from 2X0 */
 
-           outb (max_config, gus_base + 0x106);        /* UltraMax control */
+           outb ((max_config), gus_base + 0x106);      /* UltraMax control */
          }
 
          if (ad1848_detect (gus_base + 0x10c, &ad_flags, hw_config->osp))
            {
              char           *name = "GUS MAX";
+             int             old_num_mixers = num_mixers;
+
+             if (gus_pnp_flag)
+               name = "GUS PnP";
 
              gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
              gus_wave_volume = 90;
@@ -3325,6 +3390,13 @@ gus_wave_init (struct address_info *hw_config)
                           gus_dma,     /* Capture DMA */
                           1,   /* Share DMA channels with GF1 */
                           hw_config->osp);
+
+             if (num_mixers > old_num_mixers)
+               {               /* GUS has it's own mixer map */
+                 AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_SYNTH);
+                 AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+                 AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+               }
            }
          else
            printk ("[Where's the CS4231?]");
@@ -3343,15 +3415,19 @@ gus_wave_init (struct address_info *hw_config)
 
   if (hw_config->name)
     {
-      char            tmp[20];
 
-      strncpy (tmp, hw_config->name, 20);
-      tmp[19] = 0;
-      sprintf (gus_info.name, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
-      gus_info.name[sizeof (gus_info.name) - 1] = 0;
+      strncpy (tmp, hw_config->name, 45);
+      tmp[45] = 0;
+      sprintf (tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
+      tmp2[sizeof (tmp2) - 1] = 0;
+    }
+  else if (gus_pnp_flag)
+    {
+      sprintf (tmp2, "Gravis UltraSound PnP (%dk)",
+              (int) gus_mem_size / 1024);
     }
   else
-    sprintf (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+    sprintf (tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
 
 
   samples = (struct patch_info *) (sound_mem_blocks[sound_nblocks] = vmalloc ((MAX_SAMPLE + 1) * sizeof (*samples)));
@@ -3363,7 +3439,9 @@ gus_wave_init (struct address_info *hw_config)
       return;
     }
 
-  conf_printf (gus_info.name, hw_config);
+  conf_printf (tmp2, hw_config);
+  strncpy (gus_info.name, tmp2, sizeof (tmp2));
+  gus_info.name[sizeof (tmp2) - 1] = 0;
 
   if (num_synths >= MAX_SYNTH_DEV)
     printk ("GUS Error: Too many synthesizers\n");
@@ -3380,20 +3458,21 @@ gus_wave_init (struct address_info *hw_config)
 
   gus_initialize ();
 
-  if (num_audiodevs < MAX_AUDIO_DEV)
-    {
-      audio_devs[gus_devnum = num_audiodevs++] = &gus_audio_operations;
-      audio_devs[gus_devnum]->dmachan1 = dma;
-      audio_devs[gus_devnum]->dmachan2 = dma2;
-      audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
-      audio_devs[gus_devnum]->min_fragment = 9;
-      audio_devs[gus_devnum]->mixer_dev = num_mixers;  /* Next mixer# */
-      audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
-      if (dma2 != dma && dma2 != -1)
-       audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
-    }
-  else
-    printk ("GUS: Too many PCM devices available\n");
+  if (gus_mem_size > 0)
+    if (num_audiodevs < MAX_AUDIO_DEV)
+      {
+       audio_devs[gus_devnum = num_audiodevs++] = &gus_audio_operations;
+       audio_devs[gus_devnum]->dmachan1 = dma;
+       audio_devs[gus_devnum]->dmachan2 = dma2;
+       audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
+       audio_devs[gus_devnum]->min_fragment = 9;
+       audio_devs[gus_devnum]->mixer_dev = num_mixers;         /* Next mixer# */
+       audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
+       if (dma2 != dma && dma2 != -1)
+         audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
+      }
+    else
+      printk ("GUS: Too many audio devices available\n");
 
   /*
      *  Mixer dependent initialization.
@@ -3648,10 +3727,10 @@ guswave_dma_irq (void)
     switch (active_device)
       {
       case GUS_DEV_WAVE:
-       if ((dram_sleep_flag.flags & WK_SLEEP))
+       if ((dram_sleep_flag.opts & WK_SLEEP))
          {
-           dram_sleep_flag.flags = WK_WAKEUP;
-           module_wake_up (&dram_sleeper);
+           dram_sleep_flag.opts = WK_WAKEUP;
+           wake_up (&dram_sleeper);
          };
        break;
 
@@ -3702,12 +3781,12 @@ gus_timer_command (unsigned int addr, unsigned int val)
 {
   int             i;
 
-  outb ((unsigned char) (addr & 0xff), select_addr);
+  outb (((unsigned char) (addr & 0xff)), select_addr);
 
   for (i = 0; i < 2; i++)
     inb (select_addr);
 
-  outb ((unsigned char) (val & 0xff), data_addr);
+  outb (((unsigned char) (val & 0xff)), data_addr);
 
   for (i = 0; i < 2; i++)
     inb (select_addr);
index c8cbb8329ed4f4ed924d5eb4803dacd2b9a38b54..ab04953a451b0ed3f7ed81945d7c4d3e6f1cb1d5 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -14,7 +14,7 @@
 
 
 #include "sound_config.h"
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
 
 #include <linux/ultrasound.h>
 #include "gus_hw.h"
@@ -85,10 +85,10 @@ write_mix (int dev, int chn, int vol)
 
   save_flags (flags);
   cli ();
-  outb (ctrl_addr, u_MixSelect);
-  outb (selector[dev], u_MixData);
-  outb (attn_addr, u_MixSelect);
-  outb ((unsigned char) vol, u_MixData);
+  outb ((ctrl_addr), u_MixSelect);
+  outb ((selector[dev]), u_MixData);
+  outb ((attn_addr), u_MixSelect);
+  outb (((unsigned char) vol), u_MixData);
   restore_flags (flags);
 }
 
@@ -128,27 +128,27 @@ ics2101_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
            break;
 
          case SOUND_MIXER_MIC:
-           return snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_user ((int *) arg)));
+           return ioctl_out (arg, set_volumes (DEV_MIC, ioctl_in (arg)));
            break;
 
          case SOUND_MIXER_CD:
-           return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_user ((int *) arg)));
+           return ioctl_out (arg, set_volumes (DEV_CD, ioctl_in (arg)));
            break;
 
          case SOUND_MIXER_LINE:
-           return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_user ((int *) arg)));
+           return ioctl_out (arg, set_volumes (DEV_LINE, ioctl_in (arg)));
            break;
 
          case SOUND_MIXER_SYNTH:
-           return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_user ((int *) arg)));
+           return ioctl_out (arg, set_volumes (DEV_GF1, ioctl_in (arg)));
            break;
 
          case SOUND_MIXER_VOLUME:
-           return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_user ((int *) arg)));
+           return ioctl_out (arg, set_volumes (DEV_VOL, ioctl_in (arg)));
            break;
 
          default:
-           return -(EINVAL);
+           return -EINVAL;
          }
       else
        switch (cmd & 0xff)     /*
@@ -161,47 +161,47 @@ ics2101_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
            break;
 
          case SOUND_MIXER_DEVMASK:
-           return snd_ioctl_return ((int *) arg, MIX_DEVS);
+           return ioctl_out (arg, MIX_DEVS);
            break;
 
          case SOUND_MIXER_STEREODEVS:
-           return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
+           return ioctl_out (arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
            break;
 
          case SOUND_MIXER_RECMASK:
-           return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+           return ioctl_out (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
            break;
 
          case SOUND_MIXER_CAPS:
-           return snd_ioctl_return ((int *) arg, 0);
+           return ioctl_out (arg, 0);
            break;
 
          case SOUND_MIXER_MIC:
-           return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]);
+           return ioctl_out (arg, volumes[DEV_MIC]);
            break;
 
          case SOUND_MIXER_LINE:
-           return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]);
+           return ioctl_out (arg, volumes[DEV_LINE]);
            break;
 
          case SOUND_MIXER_CD:
-           return snd_ioctl_return ((int *) arg, volumes[DEV_CD]);
+           return ioctl_out (arg, volumes[DEV_CD]);
            break;
 
          case SOUND_MIXER_VOLUME:
-           return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]);
+           return ioctl_out (arg, volumes[DEV_VOL]);
            break;
 
          case SOUND_MIXER_SYNTH:
-           return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]);
+           return ioctl_out (arg, volumes[DEV_GF1]);
            break;
 
          default:
-           return -(EINVAL);
+           return -EINVAL;
          }
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static struct mixer_operations ics2101_mixer_operations =
index c3d29dceb2bf91987276dec8d693bfcdce63bd43..ae5afa5c85bd42285a6200976aa5096eb0a563ce 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
diff --git a/drivers/sound/lowlevel/ChangeLog.awe b/drivers/sound/lowlevel/ChangeLog.awe
new file mode 100644 (file)
index 0000000..d8d69e7
--- /dev/null
@@ -0,0 +1,66 @@
+ver.0.2.0
+       - Includes FreeBSD port
+       - Can load GUS compatible patches
+       - Change values of hardware control parameters for compatibility
+         with GUS driver
+       - Accept 8bit or unsigned wave data
+       - Accept no blank loop data
+       - Add sample mode flags in sample_info
+
+ver.0.1.6
+       - Add voice effects control
+       - Fix awe_voice.h for word alignment
+
+ver.0.1.5c
+       - Fix FM(OPL) playback problem
+
+ver.0.1.5b
+       - Fix pitch calculation for fixed midi key
+
+ver.0.1.5a
+       - Fix bugs in removing samples from linked list.
+
+ver.0.1.5
+       - Add checksum verification for sample uploading
+         (not compatible from older sample_info structure)
+       - Fix sample offset pointers to (actual value - 1)
+       - Add sequencer command to initialize awe32
+
+ver.0.1.4c
+       - Fix card detection and memory check function to avoid system crash
+         at booting
+
+ver.0.1.4b
+       - Add release sustain mode
+       - Initialize FM each time after loading samples
+
+ver.0.1.4a
+       - Fix AWE card detection code
+       - Correct FM initialize position 
+       - Add non-releasing mode on voice info
+
+ver.0.1.4
+       - Add AWE card and DRAM detection codes
+       - Add FM initialization code
+       - Modify volume control
+       - Remove linear volume mode
+       - Change memory management; not using malloc dynamically
+       - Add remove-samples command
+       - Use internal id implicitly at loading samples
+
+ver.0.1.3
+       - Fix a bug on patch uploading to RAM
+
+ver.0.1.2
+       - Divide to separated packages
+       - Fix disagreed macro conditions
+       - Fix unresolved function bugs
+       - Integrate VoxWare and USS-Lite driver source (awe_voice.c)
+         and remove awe_card.c
+
+ver.0.1.1
+       - Fix wrong sample numbers in sbktext
+       - Fix txt2sfx bug
+       - Fix pan parameter calculation
+       - Append USS-Lite/Linux2.0 driver
+
index f5428e6408cea041e445971b6ef43093699669b1..0f175d1bb7d0f22140f939d0d11b9ec9e6e51123 100644 (file)
@@ -2,4 +2,5 @@ bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND
 
 if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    bool 'ACI mixer (miroPCM12)' CONFIG_ACI_MIXER
+   bool 'AWE32 synth' CONFIG_AWE32_SYNTH
 fi
index 13a2bf1fd79d26e01c5b821fbc9083d37b8d29be..13bb1b95ae5cf0d4673d220e64cdbc330bba24ae 100644 (file)
@@ -1,18 +1,33 @@
 all:   lowlevel.o
 
+ALLOBJS = init.o aci.o awe_wave.o
 OBJS = init.o
 
 ifdef CONFIG_LOWLEVEL_SOUND
 ifdef CONFIG_ACI_MIXER
 OBJS := $(OBJS) aci.o
 endif
+ifdef CONFIG_AWE32_SYNTH
+OBJS := $(OBJS) awe_wave.o
+endif
 endif
 
 lowlevel.o:    $(OBJS)
        $(LD) -r -o lowlevel.o $(OBJS)
 
+module: manual_config.h
+       rm -f lowlevel.o
+       make CFLAGS="$(CFLAGS) -DLOWLEVEL_MODULE" $(ALLOBJS)
+       $(LD) -r -o lowlevel.o $(ALLOBJS)
+       touch module
+
+manual_config.h:
+       @echo You should create `pwd`/manual_config.h.
+       @echo See `pwd`/README for more info.
+       @exit 1
+
 clean:
-       rm -f core x y z *~ *.o
+       rm -f core x y z *~ *.o module
 
 ifdef HOSTCC
 include $(TOPDIR)/Rules.make
index de1eb5720514c9d6cd82c3635d3d75afbc46f0f9..86c93b55bc213d362d39dcedbf2431a15e4e73a1 100644 (file)
@@ -1,13 +1,17 @@
 Additional low level sound drivers for Linux
---------------------------------------------
+============================================
 
 This directory contains additional low level sound drivers which
-are not part of USS/Lite (UNIX Sound System). These drivers are
-maintained by their authors.
+are not part of USS/Lite (Open Sound System). These drivers are
+maintained by their authors (not by Hannu Savolainen).
 
-If you like to write a low level sound driver, please contact
+If you like to write a new low level sound driver, please contact
 Hannu Savolainen (hannu@voxware.pp.fi) for more info.
 
 The following low level drivers are included:
 
-- ACI MIXER for miroPCM12 by Markus Kuhn. See aci.readme for more info.
+- ACI MIXER for miroPCM12 by Markus Kuhn
+(mskuhn@cip.informatik.uni-erlangen.de).
+- SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai
+(iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more
+info.
diff --git a/drivers/sound/lowlevel/README.awe b/drivers/sound/lowlevel/README.awe
new file mode 100644 (file)
index 0000000..c962fa7
--- /dev/null
@@ -0,0 +1,69 @@
+================================================================
+       AWE32 Sound Driver for Linux / FreeBSD
+               version 0.2.0; Oct. 16, 1996
+================================================================
+
+* GENERAL NOTES
+
+This is a sound driver extension for SB-AWE32 cards to enable the
+wave synth operations.  The driver is provided for both Linux 1.2.x
+and 2.0.x kernels, and also FreeBSD.  Follow the corresponding
+instruction in the installation document if you use old sound drivers.
+
+This driver was written by Takashi Iwai (iwai@dragon.mm.t.u-tokyo.ac.jp)  
+who also maintains the code.  Please forward any questions, bug fixes
+and suggestions directly to me (_NOT_ to Linus Torvalds or Hannu
+Savolainen).
+
+
+* CAUTION
+
+- In the v0.2.0, parameters of hardware control are changed to have a
+compatibility with GUS driver.  If you have older awesfx and drvmidi
+utilities, please get new versions and install them again.
+
+- The SFX file after v0.1.5 is no more compatible from 0.1.4x.
+Please remake the obsolete SFX files again by txt2sfx utility.
+
+
+* USING THE DRIVER
+
+To load SoundFont files, sfxload utility is required.
+All AWE32 driver and utilities can be downloaded from:
+       http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
+
+Follow the instruction in awesfx package to make patched GM and
+GS presets.  Then, load the SFX file on driver by sfxload utility.
+
+       % sfxload -i gm.sfx
+
+Now you can hear midi musics by supported midi players
+(awemidi-0.1.x.tar.gz or patch file to playmidi-2.3).
+
+       % drvmidi foo.mid
+
+Enjoy.
+
+
+* ACKNOWLEDGMENTS
+
+Thanks to Witold Jachimczyk (witek@xfactor.wpi.edu) for many advices
+to programming of AWE32.  Many codes are brought from his AWE32-native 
+MOD player, ALMP.
+The port of awedrv0.1.6 to FreeBSD is done by Randall Hopper
+(rhh@ct.picker.com).
+I also thank linux-awe-ml members for their efforts
+to reboot their system many times :-)
+
+
+* BUGS & TODO'S
+
+- Some instruments are inaudible, eg. glockenspiel and sinewaves.
+- No stereo sample can be used.
+- More smart patch management
+- More smart DRAM memory control
+- Dynamic buffer allocation
+- etc, etc, etc.
+
+
+Takashi Iwai <iwai@dragon.mm.t.u-tokyo.ac.jp>
index effec81e36db36309577a75054158b16d73a35bb..cad3c7e067398c72de8aeeea168822dd4b70f7b6 100644 (file)
@@ -35,7 +35,7 @@
  * This mixer driver identifies itself to applications as "ACI" in
  * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
  *
- * Proprietary mixer features that go beyond the standard USS mixer
+ * Proprietary mixer features that go beyond the standard OSS mixer
  * interface are:
  * 
  * Full duplex solo configuration:
@@ -58,7 +58,9 @@
  *
  */
 
+#include "lowlevel.h"
 #include "../sound_config.h"
+#include "lowlevel.h"
 #ifdef CONFIG_ACI_MIXER
 
 #undef  DEBUG             /* if defined, produce a verbose report via syslog */
diff --git a/drivers/sound/lowlevel/awe_hw.h b/drivers/sound/lowlevel/awe_hw.h
new file mode 100644 (file)
index 0000000..3f6d385
--- /dev/null
@@ -0,0 +1,89 @@
+/*================================================================
+ * AWE32 access routines
+ *================================================================*/
+
+#ifndef AWE_HW_H_DEF
+#define AWE_HW_H_DEF
+
+/*
+ * user configuration:
+ * if auto detection can't work properly, define the following values
+ * for your machine.
+ */
+/*#define AWE_DEFAULT_BASE_ADDR        0x620*/ /* base port address */
+/*#define AWE_DEFAULT_MEM_SIZE 512*/   /* kbytes */
+
+
+/*
+ * maximum size of sample table:
+ * if your data overflow, increase the following values.
+ */
+#define AWE_MAX_SAMPLES                400
+#define AWE_MAX_INFOS          900     /* GS presets has 801 infos! */
+
+
+/*
+ * Emu-8000 control registers
+ * name(channel)       reg, port
+ */
+
+#define awe_cmd_idx(reg,ch)    (((reg)<< 5) | (ch))
+
+#define Data0    0x620 /* doubleword r/w */
+#define Data1    0xA20 /* doubleword r/w */
+#define Data2    0xA22 /* word r/w */
+#define Data3    0xE20 /* word r/w */
+#define Pointer  0xE22 /* register pointer r/w */
+
+#define AWE_CPF(ch)    awe_cmd_idx(0,ch), Data0        /* DW: current pitch and fractional address */
+#define AWE_PTRX(ch)   awe_cmd_idx(1,ch), Data0        /* DW: pitch target and reverb send */
+#define AWE_CVCF(ch)   awe_cmd_idx(2,ch), Data0        /* DW: current volume and filter cutoff */
+#define AWE_VTFT(ch)   awe_cmd_idx(3,ch), Data0        /* DW: volume and filter cutoff targets */
+#define AWE_PSST(ch)   awe_cmd_idx(6,ch), Data0        /* DW: pan send and loop start address */
+#define AWE_CSL(ch)    awe_cmd_idx(7,ch), Data0        /* DW: chorus send and loop end address */
+#define AWE_CCCA(ch)   awe_cmd_idx(0,ch), Data1        /* DW: Q, control bits, and current address */
+#define AWE_HWCF4      awe_cmd_idx(1,9),  Data1        /* DW: config dw 4 */
+#define AWE_HWCF5      awe_cmd_idx(1,10), Data1        /* DW: config dw 5 */
+#define AWE_HWCF6      awe_cmd_idx(1,13), Data1        /* DW: config dw 6 */
+#define AWE_SMALR      awe_cmd_idx(1,20), Data1        /* DW: sound memory address for left read */
+#define AWE_SMARR      awe_cmd_idx(1,21), Data1        /* DW:    for right read */
+#define AWE_SMALW      awe_cmd_idx(1,22), Data1        /* DW: sound memory address for left write */
+#define AWE_SMARW      awe_cmd_idx(1,23), Data1        /* DW:    for right write */
+#define AWE_SMLD       awe_cmd_idx(1,26), Data1        /* W: sound memory left data */
+#define AWE_SMRD       awe_cmd_idx(1,26), Data2        /* W:    right data */
+#define AWE_WC         awe_cmd_idx(1,27), Data2        /* W: sample counter */
+#define AWE_WC_Cmd     awe_cmd_idx(1,27)
+#define AWE_WC_Port    Data2
+#define AWE_HWCF1      awe_cmd_idx(1,29), Data1        /* W: config w 1 */
+#define AWE_HWCF2      awe_cmd_idx(1,30), Data1        /* W: config w 2 */
+#define AWE_HWCF3      awe_cmd_idx(1,31), Data1        /* W: config w 3 */
+#define AWE_INIT1(ch)  awe_cmd_idx(2,ch), Data1        /* W: init array 1 */
+#define AWE_INIT2(ch)  awe_cmd_idx(2,ch), Data2        /* W: init array 2 */
+#define AWE_INIT3(ch)  awe_cmd_idx(3,ch), Data1        /* W: init array 3 */
+#define AWE_INIT4(ch)  awe_cmd_idx(3,ch), Data2        /* W: init array 4 */
+#define AWE_ENVVOL(ch) awe_cmd_idx(4,ch), Data1        /* W: volume envelope delay */
+#define AWE_DCYSUSV(ch)        awe_cmd_idx(5,ch), Data1        /* W: volume envelope sustain and decay */
+#define AWE_ENVVAL(ch) awe_cmd_idx(6,ch), Data1        /* W: modulation envelope delay */
+#define AWE_DCYSUS(ch) awe_cmd_idx(7,ch), Data1        /* W: modulation envelope sustain and decay */
+#define AWE_ATKHLDV(ch)        awe_cmd_idx(4,ch), Data2        /* W: volume envelope attack and hold */
+#define AWE_LFO1VAL(ch)        awe_cmd_idx(5,ch), Data2        /* W: LFO#1 Delay */
+#define AWE_ATKHLD(ch) awe_cmd_idx(6,ch), Data2        /* W: modulation envelope attack and hold */
+#define AWE_LFO2VAL(ch)        awe_cmd_idx(7,ch), Data2        /* W: LFO#2 Delay */
+#define AWE_IP(ch)     awe_cmd_idx(0,ch), Data3        /* W: initial pitch */
+#define AWE_IFATN(ch)  awe_cmd_idx(1,ch), Data3        /* W: initial filter cutoff and attenuation */
+#define AWE_PEFE(ch)   awe_cmd_idx(2,ch), Data3        /* W: pitch and filter envelope heights */
+#define AWE_FMMOD(ch)  awe_cmd_idx(3,ch), Data3        /* W: vibrato and filter modulation freq */
+#define AWE_TREMFRQ(ch)        awe_cmd_idx(4,ch), Data3        /* W: LFO#1 tremolo amount and freq */
+#define AWE_FM2FRQ2(ch)        awe_cmd_idx(5,ch), Data3        /* W: LFO#2 vibrato amount and freq */
+
+/*  used during detection (returns ROM version ?)                    */
+#define AWE_U1         0xE0, Data3       /* (R)(W) used in initialization */
+#define AWE_U2(ch)     0xC0+(ch), Data3  /* (W)(W) used in init envelope  */
+
+
+#define AWE_MAX_VOICES         32
+#define AWE_NORMAL_VOICES      30      /*30&31 are reserved for DRAM refresh*/
+
+#define AWE_DRAM_OFFSET                0x200000
+
+#endif
diff --git a/drivers/sound/lowlevel/awe_voice.h b/drivers/sound/lowlevel/awe_voice.h
new file mode 100644 (file)
index 0000000..0aa0ed7
--- /dev/null
@@ -0,0 +1,242 @@
+#ifndef AWE_VOICE_H
+#define AWE_VOICE_H
+/*================================================================
+ * awe_voice.h -- voice information for AWE32 wave table synth
+ *     ver.0.2.0; Oct. 16, 1996
+ *     copyright (c) 1996  by Takashi Iwai
+ *================================================================*/
+
+#ifndef SAMPLE_TYPE_AWE32
+#define SAMPLE_TYPE_AWE32      0x20
+#endif
+
+#ifndef _PATCHKEY
+#define _PATCHKEY(id) ((id<<8)|0xfd)
+#endif
+
+/*----------------------------------------------------------------
+ * patch information record
+ *----------------------------------------------------------------*/
+
+/* patch interface header: 16 bytes */
+typedef struct awe_patch_info {
+       short key;                      /* use AWE_PATCH here */
+#define AWE_PATCH      _PATCHKEY(0x07)
+
+       short device_no;                /* synthesizer number */
+       unsigned short sf_id;           /* file id (should be zero) */
+       short sf_version;               /* patch version (not referred) */
+       long len;                       /* data length (without this header) */
+
+       short type;                     /* following data type */
+#define AWE_LOAD_INFO          0
+#define AWE_LOAD_DATA          1
+
+       short reserved;                 /* word alignment data */
+       char data[0];                   /* patch data follows here */
+} awe_patch_info;
+
+
+/*----------------------------------------------------------------
+ * raw voice information record
+ *----------------------------------------------------------------*/
+
+/* wave table envelope & effect parameters to control EMU8000 */
+typedef struct _awe_voice_parm {
+       unsigned short moddelay;        /* modulation delay (0x8000) */
+       unsigned short modatkhld;       /* modulation attack & hold time (0x7f7f) */
+       unsigned short moddcysus;       /* modulation decay & sustain (0x7f7f) */
+       unsigned short modrelease;      /* modulation release time (0x807f) */
+       short modkeyhold, modkeydecay;  /* envelope change per key (not used) */
+       unsigned short voldelay;        /* volume delay (0x8000) */
+       unsigned short volatkhld;       /* volume attack & hold time (0x7f7f) */
+       unsigned short voldcysus;       /* volume decay & sustain (0x7f7f) */
+       unsigned short volrelease;      /* volume release time (0x807f) */
+       short volkeyhold, volkeydecay;  /* envelope change per key (not used) */
+       unsigned short lfo1delay;       /* LFO1 delay (0x8000) */
+       unsigned short lfo2delay;       /* LFO2 delay (0x8000) */
+       unsigned short pefe;            /* modulation pitch & cutoff (0x0000) */
+       unsigned short fmmod;           /* LFO1 pitch & cutoff (0x0000) */
+       unsigned short tremfrq;         /* LFO1 volume & freq (0x0000) */
+       unsigned short fm2frq2;         /* LFO2 pitch & freq (0x0000) */
+       unsigned char cutoff;           /* initial cutoff (0xff) */
+       unsigned char filterQ;          /* initial filter Q [0-15] (0x0) */
+       unsigned char chorus;           /* chorus send (0x00) */
+       unsigned char reverb;           /* reverb send (0x00) */
+       unsigned short reserved[4];     /* not used */
+} awe_voice_parm;
+
+/* wave table parameters: 92 bytes */
+typedef struct _awe_voice_info {
+       unsigned short sf_id;           /* file id (should be zero) */
+       unsigned short sample;          /* sample id */
+       long start, end;                /* sample offset correction */
+       long loopstart, loopend;        /* loop offset correction */
+       short rate_offset;              /* sample rate pitch offset */
+       unsigned short mode;            /* sample mode */
+#define AWE_MODE_ROMSOUND              0x8000
+#define AWE_MODE_STEREO                        1
+#define AWE_MODE_LOOPING               2
+#define AWE_MODE_NORELEASE             4       /* obsolete */
+#define AWE_MODE_INIT_PARM             8
+
+       short root;                     /* midi root key */
+       short tune;                     /* pitch tuning (in cents) */
+       char low, high;                 /* key note range */
+       char vellow, velhigh;           /* velocity range */
+       char fixkey, fixvel;            /* fixed key, velocity */
+       char pan, fixpan;               /* panning, fixed panning */
+       short exclusiveClass;           /* exclusive class (0 = none) */
+       unsigned char amplitude;        /* sample volume (127 max) */
+       unsigned char attenuation;      /* attenuation (0.375dB) */
+       short scaleTuning;              /* pitch scale tuning(%), normally 100 */
+       awe_voice_parm parm;            /* voice envelope parameters */
+       short index;                    /* internal index (set by driver) */
+} awe_voice_info;
+
+/* instrument info header: 4 bytes */
+typedef struct _awe_voice_rec {
+       unsigned char bank;             /* midi bank number */
+       unsigned char instr;            /* midi preset number */
+       short nvoices;                  /* number of voices */
+       awe_voice_info info[0];         /* voice information follows here */
+} awe_voice_rec;
+
+
+/*----------------------------------------------------------------
+ * sample wave information
+ *----------------------------------------------------------------*/
+
+/* wave table sample header: 32 bytes */
+typedef struct awe_sample_info {
+       unsigned short sf_id;           /* file id (should be zero) */
+       unsigned short sample;          /* sample id */
+       long start, end;                /* start & end offset */
+       long loopstart, loopend;        /* loop start & end offset */
+       long size;                      /* size (0 = ROM) */
+       short checksum_flag;            /* use check sum = 1 */
+       unsigned short mode_flags;      /* mode flags */
+#define AWE_SAMPLE_8BITS       1       /* wave data is 8bits */
+#define AWE_SAMPLE_UNSIGNED    2       /* wave data is unsigned */
+#define AWE_SAMPLE_NO_BLANK    4       /* no blank loop is attached */
+#define AWE_SAMPLE_SINGLESHOT  8       /* single-shot w/o loop */
+#define AWE_SAMPLE_BIDIR_LOOP  16      /* bidirectional looping */
+#define AWE_SAMPLE_STEREO_LEFT 32      /* stereo left sound */
+#define AWE_SAMPLE_STEREO_RIGHT        64      /* stereo right sound */
+       unsigned long checksum;         /* check sum */
+       unsigned short data[0];         /* sample data follows here */
+} awe_sample_info;
+
+
+/*----------------------------------------------------------------
+ * awe hardware controls
+ *----------------------------------------------------------------*/
+
+#define _AWE_DEBUG_MODE                        0x00
+#define _AWE_REVERB_MODE               0x01
+#define _AWE_CHORUS_MODE               0x02
+#define _AWE_REMOVE_LAST_SAMPLES       0x03
+#define _AWE_INITIALIZE_CHIP           0x04
+#define _AWE_SEND_EFFECT               0x05
+#define _AWE_TERMINATE_CHANNEL         0x06
+#define _AWE_TERMINATE_ALL             0x07
+#define _AWE_INITIAL_VOLUME            0x08
+#define _AWE_SET_GUS_BANK              0x09
+
+#define _AWE_MODE_FLAG                 0x80
+#define _AWE_COOKED_FLAG               0x40    /* not supported */
+#define _AWE_MODE_VALUE_MASK           0x3F
+
+#define _AWE_CMD(chn, voice, cmd, p1, p2) \
+{_SEQ_NEEDBUF(8); _seqbuf[_seqbufptr] = SEQ_PRIVATE;\
+ _seqbuf[_seqbufptr+1] = chn;\
+ _seqbuf[_seqbufptr+2] = _AWE_MODE_FLAG|(cmd);\
+ _seqbuf[_seqbufptr+3] = voice;\
+ *(unsigned short*)&_seqbuf[_seqbufptr+4] = p1;\
+ *(unsigned short*)&_seqbuf[_seqbufptr+6] = p2;\
+ _SEQ_ADVBUF(8);}
+
+#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
+#define AWE_REVERB_MODE(dev,p1)        _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
+#define AWE_CHORUS_MODE(dev,p1)        _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
+#define AWE_REMOVE_LAST_SAMPLES(dev) _AWE_CMD(dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
+#define AWE_INITIALIZE_CHIP(dev) _AWE_CMD(dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
+#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
+#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
+#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
+#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
+#define AWE_SET_GUS_BANK(dev,bank) _AWE_CMD(dev, 0, _AWE_SET_GUS_BANK, bank, 0)
+
+/* reverb mode */
+#define        AWE_REVERB_ROOM1        0
+#define AWE_REVERB_ROOM2       1
+#define        AWE_REVERB_ROOM3        2
+#define        AWE_REVERB_HALL1        3
+#define        AWE_REVERB_HALL2        4
+#define        AWE_REVERB_PLATE        5
+#define        AWE_REVERB_DELAY        6
+#define        AWE_REVERB_PANNINGDELAY 7
+
+/* chorus mode */
+#define AWE_CHORUS_1           0
+#define        AWE_CHORUS_2            1
+#define        AWE_CHORUS_3            2
+#define        AWE_CHORUS_4            3
+#define        AWE_CHORUS_FEEDBACK     4
+#define        AWE_CHORUS_FLANGER      5
+#define        AWE_CHORUS_SHORTDELAY   6
+#define        AWE_CHORUS_SHORTDELAY2  7
+
+/* effects */
+enum {
+
+/* modulation envelope parameters */
+/* 0*/ AWE_FX_ENV1_DELAY,      /* WORD: ENVVAL */
+/* 1*/ AWE_FX_ENV1_ATTACK,     /* BYTE: up ATKHLD */
+/* 2*/ AWE_FX_ENV1_HOLD,       /* BYTE: lw ATKHLD */
+/* 3*/ AWE_FX_ENV1_DECAY,      /* BYTE: lw DCYSUS */
+/* 4*/ AWE_FX_ENV1_RELEASE,    /* BYTE: lw DCYSUS */
+/* 5*/ AWE_FX_ENV1_SUSTAIN,    /* BYTE: up DCYSUS */
+/* 6*/ AWE_FX_ENV1_PITCH,      /* BYTE: up PEFE */
+/* 7*/ AWE_FX_ENV1_CUTOFF,     /* BYTE: lw PEFE */
+
+/* volume envelope parameters */
+/* 8*/ AWE_FX_ENV2_DELAY,      /* WORD: ENVVOL */
+/* 9*/ AWE_FX_ENV2_ATTACK,     /* BYTE: up ATKHLDV */
+/*10*/ AWE_FX_ENV2_HOLD,       /* BYTE: lw ATKHLDV */
+/*11*/ AWE_FX_ENV2_DECAY,      /* BYTE: lw DCYSUSV */
+/*12*/ AWE_FX_ENV2_RELEASE,    /* BYTE: lw DCYSUSV */
+/*13*/ AWE_FX_ENV2_SUSTAIN,    /* BYTE: up DCYSUSV */
+       
+/* LFO1 (tremolo & vibrato) parameters */
+/*14*/ AWE_FX_LFO1_DELAY,      /* WORD: LFO1VAL */
+/*15*/ AWE_FX_LFO1_FREQ,       /* BYTE: lo TREMFRQ */
+/*16*/ AWE_FX_LFO1_VOLUME,     /* BYTE: up TREMFRQ */
+/*17*/ AWE_FX_LFO1_PITCH,      /* BYTE: up FMMOD */
+/*18*/ AWE_FX_LFO1_CUTOFF,     /* BYTE: lo FMMOD */
+
+/* LFO2 (vibrato) parameters */
+/*19*/ AWE_FX_LFO2_DELAY,      /* WORD: LFO2VAL */
+/*20*/ AWE_FX_LFO2_FREQ,       /* BYTE: lo FM2FRQ2 */
+/*21*/ AWE_FX_LFO2_PITCH,      /* BYTE: up FM2FRQ2 */
+
+/* Other overall effect parameters */
+/*22*/ AWE_FX_INIT_PITCH,      /* SHORT: pitch offset */
+/*23*/ AWE_FX_CHORUS,          /* BYTE: chorus effects send (0-255) */
+/*24*/ AWE_FX_REVERB,          /* BYTE: reverb effects send (0-255) */
+/*25*/ AWE_FX_CUTOFF,          /* BYTE: up IFATN */
+/*26*/ AWE_FX_FILTERQ,         /* BYTE: up CCCA */
+
+/* Sample / loop offset changes */
+/*27*/ AWE_FX_SAMPLE_START,    /* SHORT: offset */
+/*28*/ AWE_FX_LOOP_START,      /* SHORT: offset */
+/*29*/ AWE_FX_LOOP_END,        /* SHORT: offset */
+/*30*/ AWE_FX_COARSE_SAMPLE_START,     /* SHORT: upper word offset */
+/*31*/ AWE_FX_COARSE_LOOP_START,       /* SHORT: upper word offset */
+/*32*/ AWE_FX_COARSE_LOOP_END,         /* SHORT: upper word offset */
+
+       AWE_FX_END,
+};
+
+
+#endif /* AWE_VOICE_H */
diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c
new file mode 100644 (file)
index 0000000..e44d5a2
--- /dev/null
@@ -0,0 +1,3242 @@
+/*================================================================
+ * awe_wave.c -- driver for AWE32 wave table synth
+ *     version 0.2.0; Oct. 16, 1996
+ *     copyright (c) 1996  by Takashi Iwai
+ *================================================================*/
+
+/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD),
+ * uncomment the following line
+ */
+/* #define AWE_OBSOLETE_VOXWARE */
+
+#include "lowlevel.h"
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include "sound_config.h"
+#if !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#include "../sound_config.h"
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*----------------------------------------------------------------*
+ * compile condition
+ *----------------------------------------------------------------*/
+
+/* initialize FM passthrough even without extended RAM */
+/*#define AWE_ALWAYS_INIT_FM*/
+
+/* debug on */
+#define AWE_DEBUG_ON
+
+/* verify checksum for uploading samples */
+#define AWE_CHECKSUM_DATA
+#define AWE_CHECKSUM_MEMORY
+
+/* disable interruption during sequencer operation */
+/*#define AWE_NEED_DISABLE_INTR*/
+
+/*----------------------------------------------------------------*/
+
+#ifdef CONFIG_AWE32_SYNTH
+
+#include "awe_hw.h"
+#include "awe_voice.h"
+
+#ifdef AWE_OBSOLETE_VOXWARE
+#include "tuning.h"
+#else
+#include "../tuning.h"
+#endif
+
+#ifdef linux
+#  include <linux/ultrasound.h>
+#elif defined(__FreeBSD__)
+#  include <machine/ultrasound.h>
+#endif
+
+
+/*----------------------------------------------------------------
+ * debug message
+ *----------------------------------------------------------------*/
+
+#ifdef AWE_DEBUG_ON
+static int debug_mode = 0;
+#define DEBUG(LVL,XXX) {if (debug_mode > LVL) { XXX; }}
+#define ERRMSG(XXX)    {if (debug_mode) { XXX; }}
+#define FATALERR(XXX)  XXX
+#else
+#define DEBUG(LVL,XXX) /**/
+#define ERRMSG(XXX)    XXX
+#define FATALERR(XXX)  XXX
+#endif
+
+/*----------------------------------------------------------------
+ * bank and voice record
+ *----------------------------------------------------------------*/
+
+/* bank record */
+typedef struct _awe_voice_list {
+       unsigned char bank, instr;
+       awe_voice_info v;
+       struct _awe_voice_list *next_instr;
+       struct _awe_voice_list *next_bank;
+} awe_voice_list;
+
+/* sample and information table */
+static awe_sample_info *samples;
+static awe_voice_list *infos;
+
+#define AWE_MAX_PRESETS                256
+#define AWE_DEFAULT_BANK       0
+
+/* preset table index */
+static awe_voice_list *preset_table[AWE_MAX_PRESETS];
+
+/*----------------------------------------------------------------
+ * voice table
+ *----------------------------------------------------------------*/
+
+#define AWE_FX_BYTES   ((AWE_FX_END+7)/8)
+
+typedef struct _voice_info {
+       int state;              /* status (on = 1, off = 0) */
+       int note;               /* midi key (0-127) */
+       int velocity;           /* midi velocity (0-127) */
+       int bender;             /* midi pitchbend (-8192 - 8192) */
+       int bender_range;       /* midi bender range (x100) */
+       int panning;            /* panning (0-127) */
+       int main_vol;           /* channel volume (0-127) */
+       int expression_vol;     /* midi expression (0-127) */
+
+       /* EMU8000 parameters */
+       int apitch;             /* pitch parameter */
+       int avol;               /* volume parameter */
+
+       /* instrument parameters */
+       int bank;               /* current tone bank */
+       int instr;              /* current program */
+       awe_voice_list *vrec;
+       awe_voice_info *sample;
+
+       /* channel effects */
+       unsigned char fx_flags[AWE_FX_BYTES];
+       short fx[AWE_FX_END];
+} voice_info;
+
+static voice_info voices[AWE_MAX_VOICES];
+
+
+/*----------------------------------------------------------------
+ * global variables
+ *----------------------------------------------------------------*/
+
+/* awe32 base address (overwritten at initialization) */
+static int awe_base = 0;
+/* memory byte size (overwritten at initialization) */
+static long awe_mem_size = 0;
+
+/* maximum channels for playing */
+static int awe_max_voices = AWE_MAX_VOICES;
+
+static long free_mem_ptr = 0;          /* free word byte size */
+static int free_info = 0;              /* free info tables */
+static int last_info = 0;              /* last loaded info index */
+static int free_sample = 0;            /* free sample tables */
+static int last_sample = 0;            /* last loaded sample index */
+static int loaded_once = 0;            /* samples are loaded after init? */
+static unsigned short current_sf_id = 0;       /* internal id */
+
+static int reverb_mode = 0;            /* reverb mode */
+static int chorus_mode = 0;            /* chorus mode */
+static unsigned short init_atten = 32;  /* 12dB */
+
+static int awe_present = 0;            /* awe device present? */
+static int awe_busy = 0;               /* awe device opened? */
+
+static int awe_gus_bank = AWE_DEFAULT_BANK;    /* GUS default bank number */
+
+
+static struct synth_info awe_info = {
+       "AWE32 Synth",          /* name */
+       0,                      /* device */
+       SYNTH_TYPE_SAMPLE,      /* synth_type */
+       SAMPLE_TYPE_AWE32,      /* synth_subtype */
+       0,                      /* perc_mode (obsolete) */
+       AWE_MAX_VOICES,         /* nr_voices */
+       0,                      /* nr_drums (obsolete) */
+       AWE_MAX_INFOS           /* instr_bank_size */
+};
+
+
+static struct voice_alloc_info *voice_alloc;   /* set at initialization */
+
+
+/*----------------------------------------------------------------
+ * function prototypes
+ *----------------------------------------------------------------*/
+
+#ifndef AWE_OBSOLETE_VOXWARE
+static int awe_check_port(void);
+static void awe_request_region(void);
+static void awe_release_region(void);
+#endif
+
+static void awe_reset_samples(void);
+/* emu8000 chip i/o access */
+static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);
+static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data);
+static unsigned short awe_peek(unsigned short cmd, unsigned short port);
+static unsigned long awe_peek_dw(unsigned short cmd, unsigned short port);
+static void awe_wait(unsigned short delay);
+
+/* initialize emu8000 chip */
+static void awe_initialize(void);
+
+/* set voice parameters */
+static void awe_init_voice_info(awe_voice_info *vp);
+static void awe_init_voice_parm(awe_voice_parm *pp);
+static int freq_to_note(int freq);
+static int calc_rate_offset(int Hz);
+/*static int calc_parm_delay(int msec);*/
+static int calc_parm_hold(int msec);
+static int calc_parm_attack(int msec);
+static int calc_parm_decay(int msec);
+static int calc_parm_search(int msec, short *table);
+
+/* turn on/off note */
+static void awe_note_on(int voice);
+static void awe_note_off(int voice);
+static void awe_terminate(int voice);
+static void awe_exclusive_off(int voice);
+
+/* calculate voice parameters */
+static void awe_set_pitch(int voice);
+static void awe_set_volume(int voice);
+static void awe_set_pan(int voice, int forced);
+static void awe_fx_fmmod(int voice);
+static void awe_fx_tremfrq(int voice);
+static void awe_fx_fm2frq2(int voice);
+static void awe_fx_cutoff(int voice);
+static void awe_fx_initpitch(int voice);
+static void awe_calc_pitch(int voice);
+static void awe_calc_pitch_from_freq(int voice, int freq);
+static void awe_calc_volume(int voice);
+static void awe_voice_init(int voice, int inst_only);
+
+/* sequencer interface */
+static int awe_open(int dev, int mode);
+static void awe_close(int dev);
+static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg);
+static int awe_kill_note(int dev, int voice, int note, int velocity);
+static int awe_start_note(int dev, int v, int note_num, int volume);
+static int awe_set_instr(int dev, int voice, int instr_no);
+static void awe_reset(int dev);
+static void awe_hw_control(int dev, unsigned char *event);
+static int awe_load_patch(int dev, int format, const char *addr,
+                         int offs, int count, int pmgr_flag);
+static void awe_aftertouch(int dev, int voice, int pressure);
+static void awe_controller(int dev, int voice, int ctrl_num, int value);
+static void awe_panning(int dev, int voice, int value);
+static void awe_volume_method(int dev, int mode);
+static int awe_patchmgr(int dev, struct patmgr_info *rec);
+static void awe_bender(int dev, int voice, int value);
+static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);
+static void awe_setup_voice(int dev, int voice, int chn);
+
+/* hardware controls */
+static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
+static void awe_hw_awe_control(int dev, int cmd, unsigned char *event);
+
+/* voice search */
+static awe_voice_info *awe_search_voice(int voice, int note);
+static awe_voice_list *awe_search_instr(int bank, int preset);
+
+/* load / remove patches */
+static void awe_check_loaded(void);
+static int awe_load_info(awe_patch_info *patch, const char *addr);
+static int awe_load_data(awe_patch_info *patch, const char *addr);
+static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
+static int awe_write_wave_data(const char *addr, long offset, int size);
+static awe_voice_list *awe_get_removed_list(awe_voice_list *curp);
+static void awe_remove_samples(void);
+static short awe_set_sample(awe_voice_info *vp);
+
+/* lowlevel functions */
+static void awe_init_audio(void);
+static void awe_init_dma(void);
+static void awe_init_array(void);
+static void awe_send_array(unsigned short *data);
+static void awe_tweak(void);
+static void awe_init_fm(void);
+static int awe_open_dram_for_write(int offset);
+static int awe_open_dram_for_read(int offset);
+static void awe_open_dram_for_check(void);
+static void awe_close_dram(void);
+static void awe_close_dram_for_read(void);
+static void awe_write_dram(unsigned short c);
+static int awe_detect(void);
+static int awe_check_dram(void);
+static void awe_set_chorus_mode(int mode);
+static void awe_set_reverb_mode(int mode);
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#define awe_check_port()       0       /* always false */
+#define awe_request_region()   /* nothing */
+#define awe_release_region()   /* nothing */
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+/* the following macros are osbolete */
+
+#define PERMANENT_MALLOC(type,var,size,memptr) \
+       var = (type)(sound_mem_blocks[sound_nblocks++] = vmalloc(size))
+#define RET_ERROR(err)                 -err
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+#ifdef AWE_NEED_DISABLE_INTR
+#define DECL_INTR_FLAGS(x)     unsigned long x
+#else
+#undef DISABLE_INTR
+#undef RESTORE_INTR
+#define DECL_INTR_FLAGS(x) /**/
+#define DISABLE_INTR(x) /**/
+#define RESTORE_INTR(x) /**/
+#endif
+
+
+/* macros for Linux and FreeBSD compatibility */
+
+#undef OUTW
+#undef COPY_FROM_USER
+#undef GET_BYTE_FROM_USER
+#undef GET_SHORT_FROM_USER
+#undef IOCTL_TO_USER
+  
+#ifdef linux
+#  define NO_DATA_ERR                 ENODATA
+#  define OUTW(data, addr)            outw(data, addr)
+#  define COPY_FROM_USER(target, source, offs, count) \
+              copy_from_user( ((caddr_t)(target)),(source)+(offs),(count) )
+#  define GET_BYTE_FROM_USER(target, addr, offs)      \
+               get_user(target, (unsigned char*)&((addr)[offs]))
+#  define GET_SHORT_FROM_USER(target, addr, offs)     \
+               get_user(target, (unsigned short*)&((addr)[offs]))
+#  define IOCTL_TO_USER(target, offs, source, count)  \
+              copy_to_user  ( ((caddr_t)(target)),(source)+(offs),(count) )
+#  define BZERO(target,len)                           \
+              memset( (caddr_t)target, '\0', len )
+#elif defined(__FreeBSD__)
+#  define NO_DATA_ERR                 EINVAL
+#  define OUTW(data, addr)            outw(addr, data)
+#  define COPY_FROM_USER(target, source, offs, count) \
+              uiomove( ((caddr_t)(target)),(count),((struct uio *)(source)) )
+#  define GET_BYTE_FROM_USER(target, addr, offs)      \
+              uiomove( ((char*)&(target)), 1, ((struct uio *)(addr)) )
+#  define GET_SHORT_FROM_USER(target, addr, offs)     \
+              uiomove( ((char*)&(target)), 2, ((struct uio *)(addr)) )
+#  define IOCTL_TO_USER(target, offs, source, count)  \
+              memcpy( &((target)[offs]), (source), (count) )
+#  define BZERO(target,len)                           \
+              bzero( (caddr_t)target, len )
+#endif
+
+
+/*----------------------------------------------------------------
+ * synth operation table
+ *----------------------------------------------------------------*/
+
+static struct synth_operations awe_operations =
+{
+       &awe_info,
+       0,
+       SYNTH_TYPE_SAMPLE,
+       SAMPLE_TYPE_AWE32,
+       awe_open,
+       awe_close,
+       awe_ioctl,
+       awe_kill_note,
+       awe_start_note,
+       awe_set_instr,
+       awe_reset,
+       awe_hw_control,
+       awe_load_patch,
+       awe_aftertouch,
+       awe_controller,
+       awe_panning,
+       awe_volume_method,
+       awe_patchmgr,
+       awe_bender,
+       awe_alloc,
+       awe_setup_voice
+};
+
+
+
+/*================================================================
+ * attach / unload interface
+ *================================================================*/
+
+#ifdef AWE_OBSOLETE_VOXWARE
+long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
+#else
+int attach_awe(void)
+#endif
+{
+       /* check presence of AWE32 card */
+       if (! awe_detect()) {
+               printk("AWE32: not detected\n");
+               return 0;
+       }
+
+       /* check AWE32 ports are available */
+       if (awe_check_port()) {
+               printk("AWE32: I/O area already used.\n");
+               return 0;
+       }
+
+       /* allocate sample tables */
+       PERMANENT_MALLOC(awe_sample_info *, samples,
+                        AWE_MAX_SAMPLES * sizeof(awe_sample_info), mem_start);
+       PERMANENT_MALLOC(awe_voice_list *, infos,
+                        AWE_MAX_INFOS * sizeof(awe_voice_list), mem_start);
+       if (samples == NULL || infos == NULL) {
+               printk("AWE32: can't allocate sample tables\n");
+               return 0;
+       }
+
+       if (num_synths >= MAX_SYNTH_DEV)
+               printk("AWE32 Error: too many synthesizers\n");
+       else {
+               voice_alloc = &awe_operations.alloc;
+               voice_alloc->max_voice = awe_max_voices;
+               synth_devs[num_synths++] = &awe_operations;
+       }
+
+       /* reserve I/O ports for awedrv */
+       awe_request_region();
+
+       /* clear all samples */
+       awe_reset_samples();
+
+       /* intialize AWE32 hardware */
+       awe_initialize();
+
+       printk("<AWE32 SynthCard (%dk)>\n", (int)awe_mem_size/1024);
+       sprintf(awe_info.name, "AWE32 Synth (%dk)", (int)awe_mem_size/1024);
+
+       /* set reverb & chorus modes */
+       awe_set_reverb_mode(reverb_mode);
+       awe_set_chorus_mode(chorus_mode);
+
+       awe_present = 1;
+
+#ifdef AWE_OBSOLETE_VOXWARE
+       return mem_start;
+#else
+       return 1;
+#endif
+}
+
+
+void unload_awe(void)
+{
+       if (awe_present) {
+               awe_reset_samples();
+               awe_release_region();
+       }
+}
+
+
+#ifdef AWE_OBSOLETE_VOXWARE
+int probe_awe_obsolete(struct address_info *hw_config)
+{
+       return 1;
+       /*return awe_detect();*/
+}
+
+#endif
+
+/*================================================================
+ * clear sample tables 
+ *================================================================*/
+
+static void
+awe_reset_samples(void)
+{
+       int i;
+
+       /* free all bank tables */
+       for (i = 0; i < AWE_MAX_PRESETS; i++) {
+               preset_table[i] = NULL;
+       }
+
+       free_mem_ptr = 0;
+       last_sample = free_sample = 0;
+       last_info = free_info = 0;
+       current_sf_id = 0;
+       loaded_once = 0;
+}
+
+
+/*================================================================
+ * EMU register access
+ *================================================================*/
+
+/* select a given AWE32 pointer */
+#define awe_set_cmd(cmd)       OUTW(cmd, awe_base + 0x802)
+#define awe_port(port)         (awe_base - 0x620 + port)
+
+/* write 16bit data */
+static void
+awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
+{
+       awe_set_cmd(cmd);
+       OUTW(data, awe_port(port));
+}
+
+/* write 32bit data */
+static void
+awe_poke_dw(unsigned short cmd, unsigned short port, unsigned long data)
+{
+       awe_set_cmd(cmd);
+       OUTW(data, awe_port(port));             /* write lower 16 bits */
+       OUTW(data >> 16, awe_port(port)+2);     /* write higher 16 bits */
+}
+
+/* read 16bit data */
+static unsigned short
+awe_peek(unsigned short cmd, unsigned short port)
+{
+       unsigned short k;
+       awe_set_cmd(cmd);
+       k = inw(awe_port(port));
+       return k;
+}
+
+/* read 32bit data */
+static unsigned long
+awe_peek_dw(unsigned short cmd, unsigned short port)
+{
+       unsigned long k1, k2;
+       awe_set_cmd(cmd);
+       k1 = inw(awe_port(port));
+       k2 = inw(awe_port(port)+2);
+       k1 |= k2 << 16;
+       return k1;
+}
+
+/* wait delay number of AWE32 44100Hz clocks */
+static void
+awe_wait(unsigned short delay)
+{
+       unsigned short clock, target;
+       unsigned short port = awe_port(AWE_WC_Port);
+       int counter;
+  
+       /* sample counter */
+       awe_set_cmd(AWE_WC_Cmd);
+       clock = (unsigned short)inw(port);
+       target = clock + delay;
+       counter = 0;
+       if (target < clock) {
+               for (; (unsigned short)inw(port) > target; counter++)
+                       if (counter > 65536)
+                               break;
+       }
+       for (; (unsigned short)inw(port) < target; counter++)
+               if (counter > 65536)
+                       break;
+}
+
+
+#ifndef AWE_OBSOLETE_VOXWARE
+
+/*================================================================
+ * port check / request
+ *  0x620-622, 0xA20-A22, 0xE20-E22
+ *================================================================*/
+
+static int
+awe_check_port(void)
+{
+       return (check_region(awe_port(Data0), 3) ||
+               check_region(awe_port(Data1), 3) ||
+               check_region(awe_port(Data3), 3));
+}
+
+static void
+awe_request_region(void)
+{
+       request_region(awe_port(Data0), 3, "sound driver (AWE32)");
+       request_region(awe_port(Data1), 3, "sound driver (AWE32)");
+       request_region(awe_port(Data3), 3, "sound driver (AWE32)");
+}
+
+static void
+awe_release_region(void)
+{
+       release_region(awe_port(Data0), 3);
+       release_region(awe_port(Data1), 3);
+       release_region(awe_port(Data3), 3);
+}
+
+#endif /* !AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * AWE32 initialization
+ *================================================================*/
+static void
+awe_initialize(void)
+{
+       unsigned short data;
+       DECL_INTR_FLAGS(flags);
+
+       DEBUG(0,printk("AWE32: initializing..\n"));
+       DISABLE_INTR(flags);
+
+       /* check for an error condition */
+       data = awe_peek(AWE_U1);
+       if (!(data & 0x000F) == 0x000C) {
+               FATALERR(printk("AWE32: can't initialize AWE32\n"));
+       }
+
+       /* initialize hardware configuration */
+       awe_poke(AWE_HWCF1, 0x0059);
+       awe_poke(AWE_HWCF2, 0x0020);
+
+       /* disable audio output */
+       awe_poke(AWE_HWCF3, 0x0000);
+
+       /* initialize audio channels */
+       awe_init_audio();
+
+       /* initialize init array */
+       awe_init_dma();
+       awe_init_array();
+
+       /* check DRAM memory size */
+       awe_mem_size = awe_check_dram();
+
+       /* initialize the FM section of the AWE32 */
+       awe_init_fm();
+
+       /* set up voice envelopes */
+       awe_tweak();
+
+       /* enable audio */
+       awe_poke(AWE_HWCF3, 0x0004);
+
+       data = awe_peek(AWE_HWCF2);
+       if (~data & 0x40) {
+               FATALERR(printk("AWE32: Unable to initialize AWE32.\n"));
+       }
+
+       RESTORE_INTR(flags);
+}
+
+
+/*================================================================
+ * AWE32 voice parameters
+ *================================================================*/
+
+/* initialize voice_info record */
+static void
+awe_init_voice_info(awe_voice_info *vp)
+{
+       vp->sf_id = 0;
+       vp->sample = 0;
+       vp->rate_offset = 0;
+
+       vp->start = 0;
+       vp->end = 0;
+       vp->loopstart = 0;
+       vp->loopend = 0;
+       vp->mode = 0;
+       vp->root = 60;
+       vp->tune = 0;
+       vp->low = 0;
+       vp->high = 127;
+       vp->vellow = 0;
+       vp->velhigh = 127;
+
+       vp->fixkey = -1;
+       vp->fixvel = -1;
+       vp->fixpan = -1;
+       vp->pan = -1;
+
+       vp->exclusiveClass = 0;
+       vp->amplitude = 127;
+       vp->attenuation = 0;
+       vp->scaleTuning = 100;
+
+       awe_init_voice_parm(&vp->parm);
+}
+
+/* initialize voice_parm record:
+ * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
+ * Vibrato and Tremolo effects are zero.
+ * Cutoff is maximum.
+ * Chorus and Reverb effects are zero.
+ */
+static void
+awe_init_voice_parm(awe_voice_parm *pp)
+{
+       pp->moddelay = 0x8000;
+       pp->modatkhld = 0x7f7f;
+       pp->moddcysus = 0x7f7f;
+       pp->modrelease = 0x807f;
+       pp->modkeyhold = 0;
+       pp->modkeydecay = 0;
+
+       pp->voldelay = 0x8000;
+       pp->volatkhld = 0x7f7f;
+       pp->voldcysus = 0x7f7f;
+       pp->volrelease = 0x807f;
+       pp->volkeyhold = 0;
+       pp->volkeydecay = 0;
+
+       pp->lfo1delay = 0x8000;
+       pp->lfo2delay = 0x8000;
+       pp->pefe = 0;
+
+       pp->fmmod = 0;
+       pp->tremfrq = 0;
+       pp->fm2frq2 = 0;
+
+       pp->cutoff = 0xff;
+       pp->filterQ = 0;
+
+       pp->chorus = 0;
+       pp->reverb = 0;
+}      
+
+
+/* convert frequency mHz to abstract cents (= midi key * 100) */
+static int
+freq_to_note(int mHz)
+{
+       /* abscents = log(mHz/8176) / log(2) * 1200 */
+       unsigned long max_val = (unsigned long)0xffffffff / 10000;
+       int i, times;
+       unsigned long base;
+       unsigned long freq;
+       int note, tune;
+
+       if (mHz == 0)
+               return 0;
+       if (mHz < 0)
+               return 12799; /* maximum */
+
+       freq = mHz;
+       note = 0;
+       for (base = 8176 * 2; freq >= base; base *= 2) {
+               note += 12;
+               if (note >= 128) /* over maximum */
+                       return 12799;
+       }
+       base /= 2;
+
+       /* to avoid overflow... */
+       times = 10000;
+       while (freq > max_val) {
+               max_val *= 10;
+               times /= 10;
+               base /= 10;
+       }
+
+       freq = freq * times / base;
+       for (i = 0; i < 12; i++) {
+               if (freq < semitone_tuning[i+1])
+                       break;
+               note++;
+       }
+
+       tune = 0;
+       freq = freq * 10000 / semitone_tuning[i];
+       for (i = 0; i < 100; i++) {
+               if (freq < cent_tuning[i+1])
+                       break;
+               tune++;
+       }
+
+       return note * 100 + tune;
+}
+
+
+/* convert Hz to AWE32 rate offset:
+ * sample pitch offset for the specified sample rate
+ * rate=44100 is no offset, each 4096 is 1 octave (twice).
+ * eg, when rate is 22050, this offset becomes -4096.
+ */
+static int
+calc_rate_offset(int Hz)
+{
+       /* offset = log(Hz / 44100) / log(2) * 4096 */
+       int freq, base, i;
+
+       /* maybe smaller than max (44100Hz) */
+       if (Hz <= 0 || Hz >= 44100) return 0;
+
+       base = 0;
+       for (freq = Hz * 2; freq < 44100; freq *= 2)
+               base++;
+       base *= 1200;
+
+       freq = 44100 * 10000 / (freq/2);
+       for (i = 0; i < 12; i++) {
+               if (freq < semitone_tuning[i+1])
+                       break;
+               base += 100;
+       }
+       freq = freq * 10000 / semitone_tuning[i];
+       for (i = 0; i < 100; i++) {
+               if (freq < cent_tuning[i+1])
+                       break;
+               base++;
+       }
+       return -base * 4096 / 1200;
+}
+
+
+/*----------------------------------------------------------------
+ * convert envelope time parameter to AWE32 raw parameter
+ *----------------------------------------------------------------*/
+
+/* attack & decay/release time table (mHz) */
+static short attack_time_tbl[128] = {
+32767, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742,
+ 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371,
+ 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188,
+ 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94,
+ 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47,
+ 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23,
+ 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11,
+ 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 0,
+};
+
+static short decay_time_tbl[128] = {
+32767, 3651, 3508, 3371, 3239, 3113, 2991, 2874, 2761, 2653, 2550, 2450, 2354, 2262, 2174, 2089,
+ 2007, 1928, 1853, 1781, 1711, 1644, 1580, 1518, 1459, 1401, 1347, 1294, 1243, 1195, 1148, 1103,
+ 1060, 1018, 979, 940, 904, 868, 834, 802, 770, 740, 711, 683, 657, 631, 606, 582,
+ 560, 538, 517, 496, 477, 458, 440, 423, 407, 391, 375, 361, 347, 333, 320, 307,
+ 295, 284, 273, 262, 252, 242, 232, 223, 215, 206, 198, 190, 183, 176, 169, 162,
+ 156, 150, 144, 138, 133, 128, 123, 118, 113, 109, 104, 100, 96, 93, 89, 85,
+ 82, 79, 76, 73, 70, 67, 64, 62, 60, 57, 55, 53, 51, 49, 47, 45,
+ 43, 41, 40, 38, 37, 35, 34, 32, 31, 30, 29, 28, 27, 25, 24, 0,
+};
+
+/*
+static int
+calc_parm_delay(int msec)
+{
+       return (0x8000 - msec * 1000 / 725);
+}
+*/
+
+static int
+calc_parm_hold(int msec)
+{
+       int val = 0x7f - (unsigned char)(msec / 92);
+       if (val < 1) val = 1;
+       if (val > 127) val = 127;
+       return val;
+}
+
+static int
+calc_parm_attack(int msec)
+{
+       return calc_parm_search(msec, attack_time_tbl);
+}
+
+static int
+calc_parm_decay(int msec)
+{
+       return calc_parm_search(msec, decay_time_tbl);
+}
+
+static int
+calc_parm_search(int msec, short *table)
+{
+       int left = 0, right = 127, mid;
+       while (left < right) {
+               mid = (left + right) / 2;
+               if (msec < (int)table[mid])
+                       left = mid + 1;
+               else
+                       right = mid;
+       }
+       return left;
+}
+
+
+/*================================================================
+ * effects table
+ *================================================================*/
+
+/* set an effect value */
+#define FX_SET(v,type,value) \
+(voices[v].fx_flags[(type)/8] |= (1<<((type)%8)),\
+ voices[v].fx[type] = (value))
+/* check the effect value is set */
+#define FX_ON(v,type)  (voices[v].fx_flags[(type)/8] & (1<<((type)%8)))
+
+#if 0
+#define FX_BYTE(v,type,value)\
+       (FX_ON(v,type) ? (unsigned char)voices[v].fx[type] :\
+        (unsigned char)(value))
+#define FX_WORD(v,type,value)\
+       (FX_ON(v,type) ? (unsigned short)voices[v].fx[type] :\
+        (unsigned short)(value))
+
+#else
+
+/* get byte effect value */
+static unsigned char FX_BYTE(int v, int type, unsigned char value)
+{
+       unsigned char tmp;
+       if (FX_ON(v,type))
+               tmp = (unsigned char)voices[v].fx[type];
+       else
+               tmp = value;
+       DEBUG(4,printk("AWE32: [-- byte(%d) = %x]\n", type, tmp));
+       return tmp;
+}
+
+/* get word effect value */
+static unsigned short FX_WORD(int v, int type, unsigned short value)
+{
+       unsigned short tmp;
+       if (FX_ON(v,type))
+               tmp = (unsigned short)voices[v].fx[type];
+       else
+               tmp = value;
+       DEBUG(4,printk("AWE32: [-- word(%d) = %x]\n", type, tmp));
+       return tmp;
+}
+
+#endif
+
+/* get word (upper=type1/lower=type2) effect value */
+static unsigned short FX_COMB(int v, int type1, int type2, unsigned short value)
+{
+       unsigned short tmp;
+       if (FX_ON(v, type1))
+               tmp = (unsigned short)(voices[v].fx[type1]) << 8;
+       else
+               tmp = value & 0xff00;
+       if (FX_ON(v, type2))
+               tmp |= (unsigned short)(voices[v].fx[type2]) & 0xff;
+       else
+               tmp |= value & 0xff;
+       DEBUG(4,printk("AWE32: [-- comb(%d/%d) = %x]\n", type1, type2, tmp));
+       return tmp;
+}
+
+/* address offset */
+static long
+FX_OFFSET(int voice, int lo, int hi)
+{
+       awe_voice_info *vp;
+       long addr;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return 0;
+
+       addr = 0;
+       if (FX_ON(voice, hi)) {
+               addr = (short)voices[voice].fx[hi];
+               addr = addr << 15;
+       }
+       if (FX_ON(voice, lo))
+               addr += (short)voices[voice].fx[lo];
+       if (!(vp->mode & (AWE_SAMPLE_8BITS<<6)))
+               addr /= 2;
+       return addr;
+}
+
+
+typedef void (*fx_affect_func)(int voice);
+static fx_affect_func fx_realtime[] = {
+       /* env1: delay, attack, hold, decay, release, sustain, pitch, cutoff*/
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+       /* env2: delay, attack, hold, decay, release, sustain */
+       NULL, NULL, NULL, NULL, NULL, NULL,
+       /* lfo1: delay, freq, volume, pitch, cutoff */
+       NULL, awe_fx_tremfrq, awe_fx_tremfrq, awe_fx_fmmod, awe_fx_fmmod,
+       /* lfo2: delay, freq, pitch */
+       NULL, awe_fx_fm2frq2, awe_fx_fm2frq2,
+       /* global: initpitch, chorus, reverb, cutoff, filterQ */
+       awe_fx_initpitch, NULL, NULL, awe_fx_cutoff, NULL,
+       /* sample: start, loopstart, loopend */
+       NULL, NULL, NULL,
+};
+
+
+/*================================================================
+ * turn on/off sample
+ *================================================================*/
+
+static void
+awe_note_on(int voice)
+{
+       unsigned long temp;
+       long addr;
+       unsigned short tmp2;
+       awe_voice_info *vp;
+
+       /* A voice sample must assigned before calling */
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+
+       /* channel to be silent and idle */
+       awe_poke(AWE_DCYSUSV(voice), 0x0080);
+       awe_poke(AWE_VTFT(voice), 0);
+       awe_poke(AWE_CVCF(voice), 0);
+       awe_poke(AWE_PTRX(voice), 0);
+       awe_poke(AWE_CPF(voice), 0);
+
+       /* modulation & volume envelope */
+       awe_poke(AWE_ENVVAL(voice),
+                FX_WORD(voice, AWE_FX_ENV1_DELAY, vp->parm.moddelay));
+       awe_poke(AWE_ATKHLD(voice),
+                FX_COMB(voice, AWE_FX_ENV1_ATTACK, AWE_FX_ENV1_HOLD,
+                        vp->parm.modatkhld));
+       awe_poke(AWE_DCYSUS(voice),
+                FX_COMB(voice, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
+                         vp->parm.moddcysus));
+       awe_poke(AWE_ENVVOL(voice),
+                FX_WORD(voice, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
+       awe_poke(AWE_ATKHLDV(voice),
+                FX_COMB(voice, AWE_FX_ENV2_ATTACK, AWE_FX_ENV2_HOLD,
+                        vp->parm.volatkhld));
+       /* decay/sustain parameter for volume envelope must be set at last */
+
+       /* pitch offset */
+       awe_poke(AWE_IP(voice), voices[voice].apitch);
+       DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));
+
+       /* cutoff and volume */
+       tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+       tmp2 = (tmp2 << 8) | voices[voice].avol;
+       awe_poke(AWE_IFATN(voice), tmp2);
+
+       /* modulation envelope heights */
+       awe_poke(AWE_PEFE(voice),
+                FX_COMB(voice, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,
+                        vp->parm.pefe));
+
+       /* lfo1/2 delay */
+       awe_poke(AWE_LFO1VAL(voice),
+                FX_WORD(voice, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));
+       awe_poke(AWE_LFO2VAL(voice),
+                FX_WORD(voice, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));
+
+       /* lfo1 pitch & cutoff shift */
+       awe_poke(AWE_FMMOD(voice),
+                FX_COMB(voice, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
+                        vp->parm.fmmod));
+       /* lfo1 volume & freq */
+       awe_poke(AWE_TREMFRQ(voice),
+                FX_COMB(voice, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
+                        vp->parm.tremfrq));
+       /* lfo2 pitch & freq */
+       awe_poke(AWE_FM2FRQ2(voice),
+                FX_COMB(voice, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
+                        vp->parm.fm2frq2));
+
+       /* pan & loop start */
+        awe_set_pan(voice, 1);
+
+       /* chorus & loop end (chorus 8bit, MSB) */
+       addr = vp->loopend - 1;
+       addr += FX_OFFSET(voice, AWE_FX_LOOP_END,
+                         AWE_FX_COARSE_LOOP_END);
+       temp = FX_BYTE(voice, AWE_FX_CHORUS, vp->parm.chorus);
+       temp = (temp <<24) | (unsigned long)addr;
+       awe_poke_dw(AWE_CSL(voice), temp);
+
+       /* Q & current address (Q 4bit value, MSB) */
+       addr = vp->start - 1;
+       addr += FX_OFFSET(voice, AWE_FX_SAMPLE_START,
+                         AWE_FX_COARSE_SAMPLE_START);
+       temp = FX_BYTE(voice, AWE_FX_FILTERQ, vp->parm.filterQ);
+       temp = (temp<<28) | (unsigned long)addr;
+       awe_poke_dw(AWE_CCCA(voice), temp);
+
+       /* reset volume */
+       awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF);
+       awe_poke_dw(AWE_CVCF(voice), 0x0000FFFF);
+
+       /* turn on envelope */
+       awe_poke(AWE_DCYSUSV(voice),
+                FX_COMB(voice, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,
+                         vp->parm.voldcysus));
+       /* set chorus */
+       temp = FX_BYTE(voice, AWE_FX_REVERB, vp->parm.reverb);
+       temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8);
+       awe_poke_dw(AWE_PTRX(voice), temp);
+       awe_poke_dw(AWE_CPF(voice), 0x40000000);
+
+       DEBUG(3,printk("AWE32: [-- start=%x loop=%x]\n",
+                      (int)vp->start, (int)vp->loopstart));
+}
+
+/* turn off the voice */
+static void
+awe_note_off(int voice)
+{
+       awe_voice_info *vp;
+       unsigned short tmp;
+       if ((vp = voices[voice].sample) == NULL || !voices[voice].state)
+               return;
+       if (FX_ON(voice, AWE_FX_ENV1_RELEASE))
+               tmp = 0x8000 | voices[voice].fx[AWE_FX_ENV1_RELEASE];
+       else
+               tmp = vp->parm.modrelease;
+       awe_poke(AWE_DCYSUS(voice), tmp);
+       if (FX_ON(voice, AWE_FX_ENV2_RELEASE))
+               tmp = 0x8000 | voices[voice].fx[AWE_FX_ENV2_RELEASE];
+       else
+               tmp = vp->parm.volrelease;
+       awe_poke(AWE_DCYSUSV(voice), tmp);
+}
+
+/* force to terminate the voice (no releasing echo) */
+static void
+awe_terminate(int voice)
+{
+       awe_poke(AWE_DCYSUSV(voice), 0x807F);
+}
+
+
+/* turn off other voices with the same exclusive class (for drums) */
+static void
+awe_exclusive_off(int voice)
+{
+       int i, excls;
+
+       if (voices[voice].sample == NULL) /* no sample */
+               return;
+       excls = voices[voice].sample->exclusiveClass;
+       if (excls == 0) /* not exclusive */
+               return;
+
+       /* turn off voices with the same class */
+       for (i = 0; i < awe_max_voices; i++) {
+               if (i != voice && voices[voice].state &&
+                   voices[i].sample &&
+                   voices[i].sample->exclusiveClass == excls) {
+                       DEBUG(4,printk("AWE32: [exoff(%d)]\n", i));
+                       awe_note_off(i);
+                       awe_voice_init(i, 1);
+               }
+       }
+}
+
+
+/*================================================================
+ * change the parameters of an audible voice
+ *================================================================*/
+
+/* change pitch */
+static void
+awe_set_pitch(int voice)
+{
+       if (!voices[voice].state) return;
+       awe_poke(AWE_IP(voice), voices[voice].apitch);
+}
+
+/* change volume */
+static void
+awe_set_volume(int voice)
+{
+       awe_voice_info *vp;
+       unsigned short tmp2;
+       if (!voices[voice].state) return;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+       tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+       tmp2 = (tmp2 << 8) | voices[voice].avol;
+       awe_poke(AWE_IFATN(voice), tmp2);
+}
+
+/* change pan; this could make a click noise.. */
+static void
+awe_set_pan(int voice, int forced)
+{
+       unsigned long temp;
+       long addr;
+       awe_voice_info *vp;
+
+       if (!voices[voice].state && !forced) return;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+
+       /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
+       if (vp->fixpan > 0)     /* 0-127 */
+               temp = 255 - (int)vp->fixpan * 2;
+       else {
+               int pos = 0;
+               if (vp->pan >= 0) /* 0-127 */
+                       pos = (int)vp->pan * 2 - 128;
+               pos += voices[voice].panning; /* -128 - 127 */
+               pos = 127 - pos;
+               if (pos < 0)
+                       temp = 0;
+               else if (pos > 255)
+                       temp = 255;
+               else
+                       temp = pos;
+       }
+       addr = vp->loopstart - 1;
+       addr += FX_OFFSET(voice, AWE_FX_LOOP_START,
+                         AWE_FX_COARSE_LOOP_START);
+       temp = (temp<<24) | (unsigned long)addr;
+       awe_poke_dw(AWE_PSST(voice), temp);
+}
+
+/* effects change during playing */
+static void
+awe_fx_fmmod(int voice)
+{
+       awe_voice_info *vp;
+       if (!voices[voice].state) return;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+       awe_poke(AWE_FMMOD(voice),
+                FX_COMB(voice, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
+                        vp->parm.fmmod));
+}
+
+static void
+awe_fx_tremfrq(int voice)
+{
+       awe_voice_info *vp;
+       if (!voices[voice].state) return;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+       awe_poke(AWE_TREMFRQ(voice),
+                FX_COMB(voice, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
+                        vp->parm.tremfrq));
+}
+
+static void
+awe_fx_fm2frq2(int voice)
+{
+       awe_voice_info *vp;
+       if (!voices[voice].state) return;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+       awe_poke(AWE_FM2FRQ2(voice),
+                FX_COMB(voice, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
+                        vp->parm.fm2frq2));
+}
+
+static void
+awe_fx_cutoff(int voice)
+{
+       unsigned short tmp2;
+       awe_voice_info *vp;
+       if (!voices[voice].state) return;
+       if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+               return;
+       tmp2 = FX_BYTE(voice, AWE_FX_CUTOFF, vp->parm.cutoff);
+       tmp2 = (tmp2 << 8) | voices[voice].avol;
+       awe_poke(AWE_IFATN(voice), tmp2);
+}
+
+static void
+awe_fx_initpitch(int voice)
+{
+       if (!voices[voice].state) return;
+       if (FX_ON(voice, AWE_FX_INIT_PITCH)) {
+               DEBUG(3,printk("AWE32: initpitch ok\n"));
+       } else {
+               DEBUG(3,printk("AWE32: BAD initpitch %d\n", AWE_FX_INIT_PITCH));
+       }
+       awe_calc_pitch(voice);
+       awe_poke(AWE_IP(voice), voices[voice].apitch);
+}
+
+
+/*================================================================
+ * calculate pitch offset
+ *----------------------------------------------------------------
+ * 0xE000 is no pitch offset at 44100Hz sample.
+ * Every 4096 is one octave.
+ *================================================================*/
+
+static void
+awe_calc_pitch(int voice)
+{
+       voice_info *vp = &voices[voice];
+       awe_voice_info *ap;
+       int offset;
+
+       /* search voice information */
+       if ((ap = vp->sample) == NULL)
+                       return;
+       if (ap->index < 0) {
+               if (awe_set_sample(ap) < 0)
+                       return;
+       }
+
+       /* calculate offset */
+       if (ap->fixkey >= 0) {
+               DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune));
+               offset = (ap->fixkey - ap->root) * 4096 / 12;
+       } else {
+               DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune));
+               offset = (vp->note - ap->root) * 4096 / 12;
+               DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset));
+       }
+       offset += ap->tune * 4096 / 1200;
+       DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset));
+       if (vp->bender != 0) {
+               DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, vp->bender));
+               /* (819200: 1 semitone) ==> (4096: 12 semitones) */
+               offset += vp->bender * vp->bender_range / 2400;
+       }
+       offset = (offset * ap->scaleTuning) / 100;
+       DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset));
+
+       /* add initial pitch correction */
+       if (FX_ON(voice, AWE_FX_INIT_PITCH)) {
+               DEBUG(3,printk("AWE32: fx_pitch(%d) %d\n", voice, vp->fx[AWE_FX_INIT_PITCH]));
+               offset += vp->fx[AWE_FX_INIT_PITCH];
+       }
+
+       /* 0xe000: root pitch */
+       vp->apitch = 0xe000 + ap->rate_offset + offset;
+       DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset));
+       if (vp->apitch > 0xffff)
+               vp->apitch = 0xffff;
+       if (vp->apitch < 0)
+               vp->apitch = 0;
+}
+
+
+static void
+awe_calc_pitch_from_freq(int voice, int freq)
+{
+       voice_info *vp = &voices[voice];
+       awe_voice_info *ap;
+       int offset;
+       int note;
+
+       /* search voice information */
+       if ((ap = vp->sample) == NULL)
+               return;
+       if (ap->index < 0) {
+               if (awe_set_sample(ap) < 0)
+                       return;
+       }
+       note = freq_to_note(freq);
+       offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200;
+       offset = (offset * ap->scaleTuning) / 100;
+       if (FX_ON(voice, AWE_FX_INIT_PITCH))
+               offset += vp->fx[AWE_FX_INIT_PITCH];
+       vp->apitch = 0xe000 + ap->rate_offset + offset;
+       if (vp->apitch > 0xffff)
+               vp->apitch = 0xffff;
+       if (vp->apitch < 0)
+               vp->apitch = 0;
+}
+
+/*================================================================
+ * calculate volume attenuation
+ *----------------------------------------------------------------
+ * Voice volume is controlled by volume attenuation parameter.
+ * So volume becomes maximum when avol is 0 (no attenuation), and
+ * minimum when 255 (-96dB or silence).
+ *================================================================*/
+
+static int vol_table[128] = {
+       255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
+       47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
+       31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
+       22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
+       15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
+       10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
+       6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
+       2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
+};
+
+static void
+awe_calc_volume(int voice)
+{
+       voice_info *vp = &voices[voice];
+       awe_voice_info *ap;
+       int vol;
+
+       /* search voice information */
+       if ((ap = vp->sample) == NULL)
+               return;
+
+       ap = vp->sample;
+       if (ap->index < 0) {
+               if (awe_set_sample(ap) < 0)
+                       return;
+       }
+       
+       if (vp->velocity < ap->vellow)
+               vp->velocity = ap->vellow;
+       else if (vp->velocity > ap->velhigh)
+               vp->velocity = ap->velhigh;
+
+       /* 0 - 127 */
+       vol = (vp->velocity * vp->main_vol * vp->expression_vol) / (127*127);
+       vol = vol * ap->amplitude / 127;
+       if (vol < 0) vol = 0;
+       if (vol > 127) vol = 127;
+
+       /* calc to attenuation */
+       vol = vol_table[vol];
+       vol = vol + (int)ap->attenuation + init_atten;
+       if (vol > 255) vol = 255;
+
+       vp->avol = vol;
+       DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));
+}
+
+
+/*================================================================
+ * synth operation routines
+ *================================================================*/
+
+/* initialize the voice */
+static void
+awe_voice_init(int voice, int inst_only)
+{
+       if (! inst_only) {
+               /* clear voice parameters */
+               voices[voice].note = -1;
+               voices[voice].velocity = 0;
+               voices[voice].panning = 0; /* zero center */
+               voices[voice].bender = 0; /* zero tune skew */
+               voices[voice].bender_range = 200; /* sense * 100 */
+               voices[voice].main_vol = 127;
+               voices[voice].expression_vol = 127;
+               voices[voice].bank = AWE_DEFAULT_BANK;
+               voices[voice].instr = -1;
+               voices[voice].vrec = NULL;
+               voices[voice].sample = NULL;
+       }
+
+       /* clear voice mapping */
+       voices[voice].state = 0;
+       voice_alloc->map[voice] = 0;
+
+       /* emu8000 parameters */
+       voices[voice].apitch = 0;
+       voices[voice].avol = 255;
+
+       /* clear effects */
+       BZERO(voices[voice].fx_flags, sizeof(voices[voice].fx_flags));
+}
+
+
+/*----------------------------------------------------------------
+ * device open / close
+ *----------------------------------------------------------------*/
+
+/* open device:
+ *   reset status of all voices, and clear sample position flag
+ */
+static int
+awe_open(int dev, int mode)
+{
+       if (awe_busy)
+               return RET_ERROR(EBUSY);
+
+       awe_busy = 1;
+       awe_reset(dev);
+
+       /* clear sample position flag */
+       loaded_once = 0;
+
+       /* set GUS bank to default */
+       awe_gus_bank = AWE_DEFAULT_BANK;
+       return 0;
+}
+
+
+/* close device:
+ *   reset all voices again (terminate sounds)
+ */
+static void
+awe_close(int dev)
+{
+       awe_reset(dev);
+       awe_busy = 0;
+}
+
+
+/* sequencer I/O control:
+ */
+static int
+awe_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+       switch (cmd) {
+       case SNDCTL_SYNTH_INFO:
+               awe_info.nr_voices = awe_max_voices;
+               IOCTL_TO_USER((char*)arg, 0, &awe_info, sizeof(awe_info));
+               return 0;
+               break;
+
+       case SNDCTL_SEQ_RESETSAMPLES:
+               awe_reset_samples();
+               awe_reset(dev); /* better to reset emu8k chip... */
+               return 0;
+               break;
+
+       case SNDCTL_SEQ_PERCMODE:
+               /* what's this? */
+               return 0;
+               break;
+
+       case SNDCTL_SYNTH_MEMAVL:
+               DEBUG(0,printk("AWE32: [ioctl memavl = %d]\n", (int)free_mem_ptr));
+               return awe_mem_size - free_mem_ptr*2;
+
+       default:
+               ERRMSG(printk("AWE32: unsupported ioctl %d\n", cmd));
+               return RET_ERROR(EINVAL);
+       }
+}
+
+
+/* kill a voice:
+ *   not terminate, just release the voice.
+ */
+static int
+awe_kill_note(int dev, int voice, int note, int velocity)
+{
+       awe_voice_info *vp;
+       DECL_INTR_FLAGS(flags);
+
+       DEBUG(2,printk("AWE32: [off(%d)]\n", voice));
+       if (voice < 0 || voice >= awe_max_voices)
+                     return RET_ERROR(EINVAL);
+       if ((vp = voices[voice].sample) == NULL)
+               return 0;
+       
+       if (!(vp->mode & AWE_MODE_NORELEASE)) {
+               DISABLE_INTR(flags);
+               awe_note_off(voice);
+               RESTORE_INTR(flags);
+       }
+       awe_voice_init(voice, 1);
+       return 0;
+}
+
+
+/* search the note with the specified key range */
+static awe_voice_info *
+awe_search_voice(int voice, int note)
+{
+       awe_voice_list *rec;
+       int maxc;
+
+       for (rec = voices[voice].vrec, maxc = AWE_MAX_INFOS;
+            rec && maxc; rec = rec->next_instr, maxc--) {
+               if (rec->v.low <= note && note <= rec->v.high)
+                       return &rec->v;
+       }
+       return NULL;
+}
+
+/* start a voice:
+ *   if note is 255, identical with aftertouch function.
+ *   Otherwise, start a voice with specified not and volume.
+ */
+static int
+awe_start_note(int dev, int v, int note_num, int volume)
+{
+       DECL_INTR_FLAGS(flags);
+
+       DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", v, note_num, volume));
+       if (v < 0 || v >= awe_max_voices)
+                     return RET_ERROR(EINVAL);
+       /* an instrument must be set before starting a note */
+       if (voices[v].vrec == NULL) {
+               DEBUG(1,printk("AWE32: [-- vrec is null]\n"));
+               return 0;
+       }
+
+       if (note_num == 255) {
+               /* dynamic volume change; sample is already assigned */
+               if (! voices[v].state || voices[v].sample == NULL)
+                       return 0;
+               /* calculate volume parameter */
+               voices[v].velocity = volume;
+               awe_calc_volume(v);
+               DISABLE_INTR(flags);
+               awe_set_volume(v);
+               RESTORE_INTR(flags);
+               return 0;
+       }
+       /* assign a sample with the corresponding note */
+       if ((voices[v].sample = awe_search_voice(v, note_num)) == NULL) {
+               DEBUG(1,printk("AWE32: [-- sample is null]\n"));
+               return 0;
+       }
+       /* calculate pitch & volume parameters */
+       voices[v].note = note_num;
+       voices[v].velocity = volume;
+       awe_calc_pitch(v);
+       awe_calc_volume(v);
+
+       DISABLE_INTR(flags);
+       /* turn off other voices (for drums) */
+       awe_exclusive_off(v);
+       /* turn on the voice */
+       awe_note_on(v);
+       voices[v].state = 1;    /* flag up */
+       RESTORE_INTR(flags);
+
+       return 0;
+}
+
+
+/* search instrument from preset table with the specified bank */
+static awe_voice_list *
+awe_search_instr(int bank, int preset)
+{
+       awe_voice_list *p;
+       int maxc;
+
+       for (maxc = AWE_MAX_INFOS, p = preset_table[preset];
+            p && maxc; p = p->next_bank, maxc--) {
+               if (p->bank == bank)
+                       return p;
+       }
+       return NULL;
+}
+
+
+/* assign the instrument to a voice */
+static int
+awe_set_instr(int dev, int voice, int instr_no)
+{
+       awe_voice_list *rec;
+
+       if (voice < 0 || voice >= awe_max_voices)
+               return RET_ERROR(EINVAL);
+
+       if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS)
+               return RET_ERROR(EINVAL);
+
+       if ((rec = awe_search_instr(voices[voice].bank, instr_no)) == NULL) {
+               /* if bank is not defined, use the default bank 0 */
+               if (voices[voice].bank != AWE_DEFAULT_BANK &&
+                   (rec = awe_search_instr(AWE_DEFAULT_BANK, instr_no)) == NULL) {
+                       DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
+                       return 0;
+               }
+       }
+
+       voices[voice].instr = instr_no;
+       voices[voice].vrec = rec;
+       voices[voice].sample = NULL;  /* not set yet */
+
+       return 0;
+}
+
+
+/* reset all voices; terminate sounds and initialize parameters */
+static void
+awe_reset(int dev)
+{
+       int i;
+       /* don't turn off voice 31 and 32.  they are used also for FM voices */
+       for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+               awe_terminate(i);
+               awe_voice_init(i, 0);
+       }
+       awe_init_fm();
+       awe_tweak();
+}
+
+
+/* hardware specific control:
+ *   GUS specific and AWE32 specific controls are available.
+ */
+static void
+awe_hw_control(int dev, unsigned char *event)
+{
+       int cmd = event[2];
+       if (cmd & _AWE_MODE_FLAG)
+               awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
+       else
+               awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
+}
+
+/* GUS compatible controls */
+static void
+awe_hw_gus_control(int dev, int cmd, unsigned char *event)
+{
+       int voice;
+       unsigned short p1;
+       short p2;
+       int plong;
+       DECL_INTR_FLAGS(flags);
+
+       voice = event[3];
+       p1 = *(unsigned short *) &event[4];
+       p2 = *(short *) &event[6];
+       plong = *(int*) &event[4];
+
+       switch (cmd) {
+       case _GUS_NUMVOICES:
+               if (p1 >= awe_max_voices)
+                       printk("AWE32: num_voices: voices out of range %d\n", p1);
+               break;
+       case _GUS_VOICESAMPLE:
+               if (voice < awe_max_voices)
+                       awe_set_instr(dev, voice, p1);
+               break;
+
+       case _GUS_VOICEON:
+               if (voice < awe_max_voices) {
+                       DISABLE_INTR(flags);
+                       awe_note_on(voice);
+                       RESTORE_INTR(flags);
+               }
+               break;
+               
+       case _GUS_VOICEOFF:
+               if (voice < awe_max_voices) {
+                       DISABLE_INTR(flags);
+                       awe_note_off(voice);
+                       RESTORE_INTR(flags);
+               }
+               break;
+               
+       case _GUS_VOICEMODE:
+               /* not supported */
+               break;
+
+       case _GUS_VOICEBALA:
+               /* -128 to 127 */
+               if (voice < awe_max_voices)
+                       awe_panning(dev, voice, (short)p1);
+               break;
+
+       case _GUS_VOICEFREQ:
+               if (voice < awe_max_voices)
+                       awe_calc_pitch_from_freq(voice, plong);
+               break;
+               
+       case _GUS_VOICEVOL:
+       case _GUS_VOICEVOL2:
+               /* not supported yet */
+               break;
+
+       case _GUS_RAMPRANGE:
+       case _GUS_RAMPRATE:
+       case _GUS_RAMPMODE:
+       case _GUS_RAMPON:
+       case _GUS_RAMPOFF:
+               /* volume ramping not supported */
+               break;
+
+       case _GUS_VOLUME_SCALE:
+               break;
+
+       case _GUS_VOICE_POS:
+               if (voice < awe_max_voices) {
+                       FX_SET(voice, AWE_FX_SAMPLE_START, (short)(plong & 0x7fff));
+                       FX_SET(voice, AWE_FX_COARSE_SAMPLE_START, (plong >> 15) & 0xffff);
+               }
+               break;
+       }
+}
+
+
+/* AWE32 specific controls */
+static void
+awe_hw_awe_control(int dev, int cmd, unsigned char *event)
+{
+       int voice;
+       unsigned short p1;
+       short p2;
+       int chn;
+
+       chn = event[1];
+       voice = event[3];
+       p1 = *(unsigned short *) &event[4];
+       p2 = *(short *) &event[6];
+       
+
+#ifdef AWE_DEBUG_ON
+       switch (cmd) {
+       case _AWE_DEBUG_MODE:
+               debug_mode = p1;
+               printk("AWE32: debug mode = %d\n", debug_mode);
+               break;
+#endif
+       case _AWE_REVERB_MODE:
+               if (p1 <= 7) {
+                       reverb_mode = p1;
+                       DEBUG(0,printk("AWE32: reverb mode %d\n", reverb_mode));
+                       awe_set_reverb_mode(reverb_mode);
+               }
+               break;
+
+       case _AWE_CHORUS_MODE:
+               if (p1 <= 7) {
+                       chorus_mode = p1;
+                       DEBUG(0,printk("AWE32: chorus mode %d\n", chorus_mode));
+                       awe_set_chorus_mode(chorus_mode);
+               }
+               break;
+                     
+       case _AWE_REMOVE_LAST_SAMPLES:
+               DEBUG(0,printk("AWE32: remove last samples\n"));
+               awe_remove_samples();
+               break;
+
+       case _AWE_INITIALIZE_CHIP:
+               awe_initialize();
+               break;
+
+       case _AWE_SEND_EFFECT:
+               if (voice < awe_max_voices && p1 < AWE_FX_END) {
+                       FX_SET(voice, p1, p2);
+                       DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, voices[voice].fx[p1]));
+                       if (fx_realtime[p1]) {
+                               DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice));
+                               fx_realtime[p1](voice);
+                       }
+               }
+               break;
+
+       case _AWE_TERMINATE_CHANNEL:
+               if (voice < awe_max_voices) {
+                       DEBUG(0,printk("AWE32: terminate (%d)\n", voice));
+                       awe_terminate(voice);
+                       awe_voice_init(voice, 1);
+               }
+               break;
+
+       case _AWE_TERMINATE_ALL:
+               DEBUG(0,printk("AWE32: terminate all\n"));
+               awe_reset(0);
+               break;
+
+       case _AWE_INITIAL_VOLUME:
+               DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
+               init_atten = p1;
+               break;
+
+       case _AWE_SET_GUS_BANK:
+               DEBUG(0,printk("AWE32: set gus bank %d\n", p1));
+               awe_gus_bank = p1;
+               break;
+               
+       default:
+               DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice));
+               break;
+       }
+}
+
+
+/*----------------------------------------------------------------
+ * load a sound patch:
+ *   three types of patches are accepted: AWE, GUS, and SYSEX.
+ *----------------------------------------------------------------*/
+
+static int
+awe_load_patch(int dev, int format, const char *addr,
+              int offs, int count, int pmgr_flag)
+{
+       awe_patch_info patch;
+       int rc = 0;
+
+       if (format == GUS_PATCH) {
+               return awe_load_guspatch(addr, offs, count, pmgr_flag);
+       } else if (format == SYSEX_PATCH) {
+               /* no system exclusive message supported yet */
+               return 0;
+       } else if (format != AWE_PATCH) {
+               FATALERR(printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format));
+               return RET_ERROR(EINVAL);
+       }
+       
+       if (count < sizeof(awe_patch_info)) {
+               FATALERR(printk("AWE32 Error: Patch header too short\n"));
+               return RET_ERROR(EINVAL);
+       }
+       COPY_FROM_USER(((char*)&patch) + offs, addr, offs, 
+                      sizeof(awe_patch_info) - offs);
+
+       count -= sizeof(awe_patch_info);
+       if (count < patch.len) {
+               FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",
+                      count, (int)patch.len));
+               patch.len = count;
+       }
+       
+       switch (patch.type) {
+       case AWE_LOAD_INFO:
+               rc = awe_load_info(&patch, addr);
+               break;
+
+       case AWE_LOAD_DATA:
+               rc = awe_load_data(&patch, addr);
+               /*
+               if (!pmgr_flag && rc == 0)
+                       pmgr_inform(dev, PM_E_PATCH_LOADED, instr, free_sample, 0, 0);
+               */
+               break;
+
+       default:
+               FATALERR(printk("AWE32 Error: unknown patch format type %d\n",
+                      patch.type));
+               rc = RET_ERROR(EINVAL);
+       }
+
+       return rc;
+}
+
+
+/* load voice information data */
+static int
+awe_load_info(awe_patch_info *patch, const char *addr)
+{
+       awe_voice_list *rec, *curp;
+       long offset;
+       short i, nvoices;
+       unsigned char bank, instr;
+       int total_size;
+
+       if (patch->len < sizeof(awe_voice_rec)) {
+               FATALERR(printk("AWE32 Error: invalid patch info length\n"));
+               return RET_ERROR(EINVAL);
+       }
+
+       offset = sizeof(awe_patch_info);
+       GET_BYTE_FROM_USER(bank, addr, offset); offset++;
+       GET_BYTE_FROM_USER(instr, addr, offset); offset++;
+       GET_SHORT_FROM_USER(nvoices, addr, offset); offset+=2;
+
+       if (nvoices <= 0 || nvoices >= 100) {
+               FATALERR(printk("AWE32 Error: Illegal voice number %d\n", nvoices));
+               return RET_ERROR(EINVAL);
+       }
+       if (free_info + nvoices > AWE_MAX_INFOS) {
+               ERRMSG(printk("AWE32 Error: Too many voice informations\n"));
+               return RET_ERROR(ENOSPC);
+       }
+
+       total_size = sizeof(awe_voice_rec) + sizeof(awe_voice_info) * nvoices;
+       if (patch->len < total_size) {
+               ERRMSG(printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n",
+                      (int)patch->len, nvoices));
+               return RET_ERROR(EINVAL);
+       }
+
+       curp = awe_search_instr(bank, instr);
+       for (i = 0; i < nvoices; i++) {
+               rec = &infos[free_info + i];
+
+               rec->bank = bank;
+               rec->instr = instr;
+               if (i < nvoices - 1)
+                       rec->next_instr = rec + 1;
+               else
+                       rec->next_instr = curp;
+               rec->next_bank = NULL;
+
+               /* copy awe_voice_info parameters */
+               COPY_FROM_USER(&rec->v, addr, offset, sizeof(awe_voice_info));
+               offset += sizeof(awe_voice_info);
+               rec->v.sf_id = current_sf_id;
+               if (rec->v.mode & AWE_MODE_INIT_PARM)
+                       awe_init_voice_parm(&rec->v.parm);
+               awe_set_sample(&rec->v);
+       }
+
+       /* prepend to top of the list */
+       infos[free_info].next_bank = preset_table[instr];
+       preset_table[instr] = &infos[free_info];
+       free_info += nvoices;
+
+       return 0;
+}
+
+
+/* load wave sample data */
+static int
+awe_load_data(awe_patch_info *patch, const char *addr)
+{
+       long offset;
+       int size;
+       int rc;
+
+       if (free_sample >= AWE_MAX_SAMPLES) {
+               ERRMSG(printk("AWE32 Error: Sample table full\n"));
+               return RET_ERROR(ENOSPC);
+       }
+
+       size = (patch->len - sizeof(awe_sample_info)) / 2;
+       offset = sizeof(awe_patch_info);
+       COPY_FROM_USER(&samples[free_sample], addr, offset,
+                      sizeof(awe_sample_info));
+       offset += sizeof(awe_sample_info);
+       if (size != samples[free_sample].size) {
+               ERRMSG(printk("AWE32 Warning: sample size differed (%d != %d)\n",
+                      (int)samples[free_sample].size, (int)size));
+               samples[free_sample].size = size;
+       }
+       if (samples[free_sample].size > 0)
+               if ((rc = awe_write_wave_data(addr, offset, size)) != 0)
+                       return rc;
+
+       awe_check_loaded();
+       samples[free_sample].sf_id = current_sf_id;
+
+       free_sample++;
+       return 0;
+}
+
+/* check the other samples are already loaded */
+static void
+awe_check_loaded(void)
+{
+       if (!loaded_once) {
+               /* it's the first time */
+               last_sample = free_sample;
+               last_info = free_info;
+               current_sf_id++;
+               loaded_once = 1;
+       }
+}
+
+
+#define BLANK_LOOP_START       8
+#define BLANK_LOOP_END         40
+#define BLANK_LOOP_SIZE                48
+
+/* loading onto memory */
+static int 
+awe_write_wave_data(const char *addr, long offset, int size)
+{
+       awe_sample_info *sp = &samples[free_sample];
+       int i, truesize;
+       int rc;
+       unsigned long csum1, csum2;
+       DECL_INTR_FLAGS(flags);
+
+       /* be sure loop points start < end */
+       if (sp->loopstart > sp->loopend) {
+               long tmp = sp->loopstart;
+               sp->loopstart = sp->loopend;
+               sp->loopend = tmp;
+       }
+
+       /* compute true data size to be loaded */
+       truesize = size;
+       if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)
+               truesize += sp->loopend - sp->loopstart;
+       if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)
+               truesize += BLANK_LOOP_SIZE;
+       if (size > 0 && free_mem_ptr + truesize >= awe_mem_size/2) {
+               ERRMSG(printk("AWE32 Error: Sample memory full\n"));
+               return RET_ERROR(ENOSPC);
+       }
+
+       /* recalculate address offset */
+       sp->end -= sp->start;
+       sp->loopstart -= sp->start;
+       sp->loopend -= sp->start;
+       sp->size = truesize;
+
+       sp->start = free_mem_ptr + AWE_DRAM_OFFSET;
+       sp->end += free_mem_ptr + AWE_DRAM_OFFSET;
+       sp->loopstart += free_mem_ptr + AWE_DRAM_OFFSET;
+       sp->loopend += free_mem_ptr + AWE_DRAM_OFFSET;
+
+       DISABLE_INTR(flags);
+       if ((rc = awe_open_dram_for_write(free_mem_ptr)) != 0) {
+               RESTORE_INTR(flags);
+               return rc;
+       }
+
+       csum1 = 0;
+       for (i = 0; i < size; i++) {
+               unsigned char cc;
+               unsigned short c;
+               if (sp->mode_flags & AWE_SAMPLE_8BITS) {
+                       GET_BYTE_FROM_USER(cc, addr, offset); offset++;
+                       c = cc << 8; /* convert 8bit -> 16bit */
+               } else {
+                       GET_SHORT_FROM_USER(c, addr, offset); offset += 2;
+               }
+               if (sp->mode_flags & AWE_SAMPLE_UNSIGNED)
+                       c ^= 0x8000; /* unsigned -> signed */
+               csum1 += c;
+               awe_write_dram(c);
+               if (i == sp->loopend &&
+                   (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)) {
+                       int looplen = sp->loopend - sp->loopstart;
+                       /* copy reverse loop */
+                       int k;
+                       for (k = 0; k < looplen; k++) {
+                               if (sp->mode_flags & AWE_SAMPLE_8BITS) {
+                                       GET_BYTE_FROM_USER(cc, addr, offset-k);
+                                       c = cc << 8;
+                               } else {
+                                       GET_SHORT_FROM_USER(c, addr, offset-k*2);
+                               }
+                               if (sp->mode_flags & AWE_SAMPLE_UNSIGNED)
+                                       c ^= 0x8000;
+                               awe_write_dram(c);
+                       }
+               }
+       }
+
+       /* if no blank loop is attached in the sample, add it */
+       if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) {
+               for (i = 0; i < BLANK_LOOP_SIZE; i++)
+                       awe_write_dram(0);
+               if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) {
+                       sp->loopstart = sp->end + BLANK_LOOP_START;
+                       sp->loopend = sp->end + BLANK_LOOP_END;
+               }
+               sp->size += BLANK_LOOP_SIZE;
+       }
+
+       awe_close_dram();
+       RESTORE_INTR(flags);
+       if (sp->checksum_flag) {
+#ifdef AWE_CHECKSUM_DATA
+               if (sp->checksum_flag != 2 && csum1 != sp->checksum) {
+                       ERRMSG(printk("AWE32: [%d] checksum mismatch on data %x:%x\n",
+                              free_sample,
+                              (int)samples[free_sample].checksum,
+                              (int)csum1));
+                       return RET_ERROR(NO_DATA_ERR);
+               }
+#endif /* AWE_CHECKSUM_DATA */
+#ifdef AWE_CHECKSUM_MEMORY
+               DISABLE_INTR(flags);
+               if (awe_open_dram_for_read(free_mem_ptr) == 0) {
+                       csum2 = 0;
+                       for (i = 0; i < size; i++) {
+                               unsigned short c;
+                               c = awe_peek(AWE_SMLD);
+                               csum2 += c;
+                       }
+                       awe_close_dram_for_read();
+                       if (csum2 != samples[free_sample].checksum) {
+                               RESTORE_INTR(flags);
+                               ERRMSG(printk("AWE32: [%d] checksum mismatch on DRAM %x:%x\n",
+                                             free_sample,
+                                             (int)samples[free_sample].checksum,
+                                             (int)csum2));
+                               return RET_ERROR(NO_DATA_ERR);
+                       }
+               }
+               RESTORE_INTR(flags);
+#endif /* AWE_CHECKSUM_MEMORY */
+       }
+       free_mem_ptr += sp->size;
+
+       /* re-initialize FM passthrough */
+       DISABLE_INTR(flags);
+       awe_init_fm();
+       awe_tweak();
+       RESTORE_INTR(flags);
+
+       return 0;
+}
+
+
+/* calculate GUS envelope time:
+ * is this correct?  i have no idea..
+ */
+static int
+calc_gus_envelope_time(int rate, int start, int end)
+{
+       int r, p, t;
+       r = (3 - ((rate >> 6) & 3)) * 3;
+       p = rate & 0x3f;
+       t = end - start;
+       if (t < 0) t = -t;
+       if (13 > r)
+               t = t << (13 - r);
+       else
+               t = t >> (r - 13);
+       return (t * 10) / (p * 441);
+}
+
+#define calc_gus_sustain(val)  (0x7f - vol_table[(val)/2])
+#define calc_gus_attenuation(val)      vol_table[(val)/2]
+
+/* load GUS patch */
+static int
+awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag)
+{
+       struct patch_info patch;
+       awe_voice_list *rec, *curp;
+       long sizeof_patch;
+       int note;
+       int rc;
+
+       sizeof_patch = (long)&patch.data[0] - (long)&patch; /* header size */
+       if (free_sample >= AWE_MAX_SAMPLES) {
+               ERRMSG(printk("AWE32 Error: Sample table full\n"));
+               return RET_ERROR(ENOSPC);
+       }
+       if (free_info >= AWE_MAX_INFOS) {
+               ERRMSG(printk("AWE32 Error: Too many voice informations\n"));
+               return RET_ERROR(ENOSPC);
+       }
+       if (size < sizeof_patch) {
+               ERRMSG(printk("AWE32 Error: Patch header too short\n"));
+               return RET_ERROR(EINVAL);
+       }
+       COPY_FROM_USER(((char*)&patch) + offs, addr, offs, sizeof_patch - offs);
+       size -= sizeof_patch;
+       if (size < patch.len) {
+               FATALERR(printk("AWE32 Warning: Patch record too short (%d<%d)\n",
+                      size, (int)patch.len));
+               patch.len = size;
+       }
+
+       samples[free_sample].sf_id = 0;
+       samples[free_sample].sample = free_sample;
+       samples[free_sample].start = 0;
+       samples[free_sample].end = patch.len;
+       samples[free_sample].loopstart = patch.loop_start;
+       samples[free_sample].loopend = patch.loop_end;
+       samples[free_sample].size = patch.len;
+
+       /* set up mode flags */
+       samples[free_sample].mode_flags = 0;
+       if (!(patch.mode & WAVE_16_BITS))
+               samples[free_sample].mode_flags |= AWE_SAMPLE_8BITS;
+       if (patch.mode & WAVE_UNSIGNED)
+               samples[free_sample].mode_flags |= AWE_SAMPLE_UNSIGNED;
+       samples[free_sample].mode_flags |= AWE_SAMPLE_NO_BLANK;
+       if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP)))
+               samples[free_sample].mode_flags |= AWE_SAMPLE_SINGLESHOT;
+       if (patch.mode & WAVE_BIDIR_LOOP)
+               samples[free_sample].mode_flags |= AWE_SAMPLE_BIDIR_LOOP;
+
+       DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no,
+                      samples[free_sample].mode_flags));
+       if (patch.mode & WAVE_16_BITS) {
+               /* convert to word offsets */
+               samples[free_sample].size /= 2;
+               samples[free_sample].end /= 2;
+               samples[free_sample].loopstart /= 2;
+               samples[free_sample].loopend /= 2;
+       }
+       samples[free_sample].checksum_flag = 0;
+       samples[free_sample].checksum = 0;
+
+       if ((rc = awe_write_wave_data(addr, sizeof_patch,
+                                     samples[free_sample].size)) != 0)
+               return rc;
+
+       awe_check_loaded();
+       samples[free_sample].sf_id = current_sf_id;
+       free_sample++;
+
+       /* set up voice info */
+       rec = &infos[free_info];
+       awe_init_voice_info(&rec->v);
+       rec->v.sf_id = current_sf_id;
+       rec->v.sample = free_sample - 1; /* the last sample */
+       rec->v.rate_offset = calc_rate_offset(patch.base_freq);
+       note = freq_to_note(patch.base_note);
+       rec->v.root = note / 100;
+       rec->v.tune = -(note % 100);
+       rec->v.low = freq_to_note(patch.low_note) / 100;
+       rec->v.high = freq_to_note(patch.high_note) / 100;
+       DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%d-%d)]\n",
+                      rec->v.rate_offset, note,
+                      rec->v.low, rec->v.high,
+             patch.low_note, patch.high_note));
+       /* panning position; -128 - 127 => 0-127 */
+       rec->v.pan = (patch.panning + 128) / 2;
+
+       /* detuning is ignored */
+       /* 6points volume envelope */
+       if (patch.mode & WAVE_ENVELOPES) {
+               int attack, hold, decay, release;
+               attack = calc_gus_envelope_time
+                       (patch.env_rate[0], 0, patch.env_offset[0]);
+               hold = calc_gus_envelope_time
+                       (patch.env_rate[1], patch.env_offset[0],
+                        patch.env_offset[1]);
+               decay = calc_gus_envelope_time
+                       (patch.env_rate[2], patch.env_offset[1],
+                        patch.env_offset[2]);
+               release = calc_gus_envelope_time
+                       (patch.env_rate[3], patch.env_offset[1],
+                        patch.env_offset[4]);
+               release += calc_gus_envelope_time
+                       (patch.env_rate[4], patch.env_offset[3],
+                        patch.env_offset[4]);
+               release += calc_gus_envelope_time
+                       (patch.env_rate[5], patch.env_offset[4],
+                        patch.env_offset[5]);
+               rec->v.parm.volatkhld = (calc_parm_attack(attack) << 8) |
+                       calc_parm_hold(hold);
+               rec->v.parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
+                       calc_parm_decay(decay);
+               rec->v.parm.volrelease = 0x8000 | calc_parm_decay(release);
+               DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release));
+               rec->v.attenuation = calc_gus_attenuation(patch.env_offset[0]);
+       }
+
+       /* tremolo effect */
+       if (patch.mode & WAVE_TREMOLO) {
+               int rate = (patch.tremolo_rate * 1000 / 38) / 42;
+               rec->v.parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
+               DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n",
+                              patch.tremolo_rate, patch.tremolo_depth,
+                              rec->v.parm.tremfrq));
+       }
+       /* vibrato effect */
+       if (patch.mode & WAVE_VIBRATO) {
+               int rate = (patch.vibrato_rate * 1000 / 38) / 42;
+               rec->v.parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
+               DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n",
+                              patch.tremolo_rate, patch.tremolo_depth,
+                              rec->v.parm.tremfrq));
+       }
+       
+       /* scale_freq, scale_factor, volume, and fractions not implemented */
+
+       /* set the voice index */
+       awe_set_sample(&rec->v);
+
+       /* prepend to top of the list */
+       curp = awe_search_instr(awe_gus_bank, patch.instr_no);
+       rec->bank = awe_gus_bank;
+       rec->instr = patch.instr_no;
+       rec->next_instr = curp;
+       rec->next_bank = preset_table[rec->instr];
+       preset_table[rec->instr] = rec;
+       free_info++;
+
+       return 0;
+}
+
+
+/* remove samples with current sf_id from instrument list */
+static awe_voice_list *
+awe_get_removed_list(awe_voice_list *curp)
+{
+       awe_voice_list *lastp, **prevp;
+       int maxc;
+       lastp = curp;
+       prevp = &lastp;
+       for (maxc = AWE_MAX_INFOS;
+            curp && maxc; curp = curp->next_instr, maxc--) {
+               if (curp->v.sf_id == current_sf_id)
+                       *prevp = curp->next_instr;
+               else
+                       prevp = &curp->next_instr;
+       }
+       return lastp;
+}
+
+
+/* remove last loaded samples */
+static void
+awe_remove_samples(void)
+{
+       awe_voice_list **prevp, *p, *nextp;
+       int maxc;
+       int i;
+
+       if (last_sample == free_sample && last_info == free_info)
+               return;
+
+       /* remove the records from preset table */
+       for (i = 0; i < AWE_MAX_PRESETS; i++) {
+               prevp = &preset_table[i];
+               for (maxc = AWE_MAX_INFOS, p = preset_table[i];
+                    p && maxc; p = nextp, maxc--) {
+                       nextp = p->next_bank;
+                       p = awe_get_removed_list(p);
+                       if (p == NULL)
+                               *prevp = nextp;
+                       else {
+                               *prevp = p;
+                               prevp = &p->next_bank;
+                       }
+               }
+       }
+
+       for (i = last_sample; i < free_sample; i++)
+               free_mem_ptr -= samples[i].size;
+
+       free_sample = last_sample;
+       free_info = last_info;
+       current_sf_id--;
+       loaded_once = 0;
+}
+
+
+/* search the specified sample */
+static short
+awe_set_sample(awe_voice_info *vp)
+{
+       int i;
+       for (i = 0; i < free_sample; i++) {
+               if (samples[i].sf_id == vp->sf_id &&
+                   samples[i].sample == vp->sample) {
+                       /* set the actual sample offsets */
+                       vp->start += samples[i].start;
+                       vp->end += samples[i].end;
+                       vp->loopstart += samples[i].loopstart;
+                       vp->loopend += samples[i].loopend;
+                       /* copy mode flags */
+                       vp->mode |= (samples[i].mode_flags << 6);
+                       /* set index */
+                       vp->index = i;
+                       return i;
+               }
+       }
+       return -1;
+}
+
+
+/* voice pressure change */
+static void
+awe_aftertouch(int dev, int voice, int pressure)
+{
+       DECL_INTR_FLAGS(flags);
+
+       DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure));
+       if (voice < 0 || voice >= awe_max_voices)
+               return;
+       voices[voice].velocity = pressure;
+       awe_calc_volume(voice);
+       DISABLE_INTR(flags);
+       awe_set_volume(voice);
+       RESTORE_INTR(flags);
+}
+
+
+/* voice control change */
+static void
+awe_controller(int dev, int voice, int ctrl_num, int value)
+{
+       DECL_INTR_FLAGS(flags);
+
+       if (voice < 0 || voice >= awe_max_voices)
+               return;
+
+       switch (ctrl_num) {
+       case CTL_BANK_SELECT:
+               DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
+               voices[voice].bank = value;
+               break;
+
+       case CTRL_PITCH_BENDER:
+               DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value));
+               /* zero centered */
+               voices[voice].bender = value;
+               awe_calc_pitch(voice);
+               DISABLE_INTR(flags);
+               awe_set_pitch(voice);
+               RESTORE_INTR(flags);
+               break;
+
+       case CTRL_PITCH_BENDER_RANGE:
+               DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value));
+               /* sense x 100 */
+               voices[voice].bender_range = value;
+               /* no audible pitch change yet.. */
+               break;
+
+       case CTL_EXPRESSION:
+               value /= 128;
+       case CTRL_EXPRESSION:
+               DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value));
+               /* 0 - 127 */
+               voices[voice].expression_vol = value;
+               awe_calc_volume(voice);
+               DISABLE_INTR(flags);
+               awe_set_volume(voice);
+               RESTORE_INTR(flags);
+               break;
+
+       case CTL_PAN:
+               DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
+               /* (0-127) -> signed 8bit */
+               voices[voice].panning = value * 2 - 128;
+               DISABLE_INTR(flags);
+               awe_set_pan(voice, 0);
+               RESTORE_INTR(flags);
+               break;
+
+       case CTL_MAIN_VOLUME:
+               value = (value * 127) / 16383;
+       case CTRL_MAIN_VOLUME:
+               DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value));
+               /* 0 - 127 */
+               voices[voice].main_vol = value;
+               awe_calc_volume(voice);
+               DISABLE_INTR(flags);
+               awe_set_volume(voice);
+               RESTORE_INTR(flags);
+               break;
+
+       case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */
+               DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value));
+               FX_SET(voice, AWE_FX_REVERB, value * 2);
+               break;          
+
+       case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */
+               DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value));
+               FX_SET(voice, AWE_FX_CHORUS, value * 2);
+               break;          
+
+
+       default:
+               DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n",
+                          voice, ctrl_num, value));
+               break;
+       }
+}
+
+
+/* voice pan change (value = -128 - 127) */
+static void
+awe_panning(int dev, int voice, int value)
+{
+       DECL_INTR_FLAGS(flags);
+       if (voice >= 0 || voice < awe_max_voices) {
+               voices[voice].panning = value;
+               DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, voices[voice].panning));
+               DISABLE_INTR(flags);
+               awe_set_pan(voice, 0);
+               RESTORE_INTR(flags);
+       }
+}
+
+
+/* volume mode change */
+static void
+awe_volume_method(int dev, int mode)
+{
+       /* not impremented */
+       DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode));
+}
+
+
+/* patch manager */
+static int
+awe_patchmgr(int dev, struct patmgr_info *rec)
+{
+       FATALERR(printk("AWE32 Warning: patch manager control not supported\n"));
+       return 0;
+}
+
+
+/* pitch wheel change: 0-16384 */
+static void
+awe_bender(int dev, int voice, int value)
+{
+       DECL_INTR_FLAGS(flags);
+
+       if (voice < 0 || voice >= awe_max_voices)
+               return;
+       /* convert to zero centered value */
+       voices[voice].bender = value - 8192;
+       DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, voices[voice].bender));
+       awe_calc_pitch(voice);
+       DISABLE_INTR(flags);
+       awe_set_pitch(voice);
+       RESTORE_INTR(flags);
+}
+
+
+/* search an empty voice; used by sequencer2 */
+static int
+awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
+{
+       int i, p, best = -1, best_time = 0x7fffffff;
+
+       p = alloc->ptr;
+       /* First look for a completely stopped voice */
+
+       for (i = 0; i < alloc->max_voice; i++) {
+               if (alloc->map[p] == 0) {
+                       alloc->ptr = p;
+                       return p;
+               }
+               if (alloc->alloc_times[p] < best_time) {
+                       best = p;
+                       best_time = alloc->alloc_times[p];
+               }
+               p = (p + 1) % alloc->max_voice;
+       }
+
+       /* Then look for a releasing voice */
+       for (i = 0; i < alloc->max_voice; i++) {
+               if (alloc->map[p] == 0xffff) {
+                       alloc->ptr = p;
+                       return p;
+               }
+               p = (p + 1) % alloc->max_voice;
+       }
+
+       if (best >= 0)
+               p = best;
+
+       /* terminate the voice */
+       if (voices[p].state)
+               awe_terminate(p);
+
+       alloc->ptr = p;
+       return p;
+}
+
+
+/* set up voice; used by sequencer2 */
+static void
+awe_setup_voice(int dev, int voice, int chn)
+{
+       struct channel_info *info;
+       if (synth_devs[dev] == NULL ||
+           (info = &synth_devs[dev]->chn_info[chn]) == NULL)
+               return;
+       if (voice < 0 || voice >= awe_max_voices)
+               return;
+
+       DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn));
+       voices[voice].expression_vol = info->controllers[CTL_EXPRESSION];
+       voices[voice].main_vol =
+               (info->controllers[CTL_MAIN_VOLUME] * 100) / 128; /* 0 - 127 */
+       voices[voice].panning =
+               info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */
+       voices[voice].bender = info->bender_value; /* zero center */
+       voices[voice].bank = info->controllers[CTL_BANK_SELECT];
+       awe_set_instr(dev, voice, info->pgm_num);
+}
+
+
+/*================================================================
+ * initialization of AWE32
+ *================================================================*/
+
+/* intiailize audio channels */
+static void
+awe_init_audio(void)
+{
+       int ch;
+
+       /* turn off envelope engines */
+       for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+               awe_poke(AWE_DCYSUSV(ch), 0x0080);
+       }
+  
+       for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+               awe_poke(AWE_ENVVOL(ch), 0);
+               awe_poke(AWE_ENVVAL(ch), 0);
+               awe_poke(AWE_DCYSUS(ch), 0);
+               awe_poke(AWE_ATKHLDV(ch), 0);
+               awe_poke(AWE_LFO1VAL(ch), 0);
+               awe_poke(AWE_ATKHLD(ch), 0);
+               awe_poke(AWE_LFO2VAL(ch), 0);
+               awe_poke(AWE_IP(ch), 0);
+               awe_poke(AWE_IFATN(ch), 0);
+               awe_poke(AWE_PEFE(ch), 0);
+               awe_poke(AWE_FMMOD(ch), 0);
+               awe_poke(AWE_TREMFRQ(ch), 0);
+               awe_poke(AWE_FM2FRQ2(ch), 0);
+               awe_poke_dw(AWE_PTRX(ch), 0);
+               awe_poke_dw(AWE_VTFT(ch), 0);
+               awe_poke_dw(AWE_PSST(ch), 0);
+               awe_poke_dw(AWE_CSL(ch), 0);
+               awe_poke_dw(AWE_CCCA(ch), 0);
+       }
+
+       for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+               awe_poke_dw(AWE_CPF(ch), 0);
+               awe_poke_dw(AWE_CVCF(ch), 0);
+       }
+}
+
+
+/* initialize DMA address */
+static void
+awe_init_dma(void)
+{
+       awe_poke_dw(AWE_SMALR, 0x00000000);
+       awe_poke_dw(AWE_SMARR, 0x00000000);
+       awe_poke_dw(AWE_SMALW, 0x00000000);
+       awe_poke_dw(AWE_SMARW, 0x00000000);
+}
+
+
+/* initialization arrays */
+
+static unsigned short init1[128] = {
+       0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
+       0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
+       0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
+       0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
+
+       0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
+       0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
+       0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
+       0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
+
+       0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
+       0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
+       0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
+       0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
+
+       0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
+       0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
+       0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
+       0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
+};
+
+static unsigned short init2[128] = {
+       0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
+       0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
+       0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
+       0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
+
+       0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
+       0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
+       0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
+       0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
+
+       0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
+       0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
+       0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
+       0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
+       0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
+       0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
+       0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
+       0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
+};
+
+static unsigned short init3[128] = {
+       0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
+       0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
+       0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
+       0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
+
+       0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
+       0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
+       0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
+       0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
+
+       0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
+       0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
+       0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
+       0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
+
+       0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
+       0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
+       0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
+       0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
+};
+
+static unsigned short init4[128] = {
+       0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
+       0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
+       0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
+       0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
+
+       0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
+       0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
+       0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
+       0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
+
+       0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
+       0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
+       0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
+       0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
+
+       0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
+       0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
+       0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
+       0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
+};
+
+
+/* send initialization arrays to start up */
+static void
+awe_init_array(void)
+{
+       awe_send_array(init1);
+       awe_wait(1024);
+       awe_send_array(init2);
+       awe_send_array(init3);
+       awe_poke_dw(AWE_HWCF4, 0);
+       awe_poke_dw(AWE_HWCF5, 0x83);
+       awe_poke_dw(AWE_HWCF6, 0x8000);
+       awe_send_array(init4);
+}
+
+/* send an initialization array */
+static void
+awe_send_array(unsigned short *data)
+{
+       int i;
+       unsigned short *p;
+
+       p = data;
+       for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+               awe_poke(AWE_INIT1(i), *p);
+       for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+               awe_poke(AWE_INIT2(i), *p);
+       for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+               awe_poke(AWE_INIT3(i), *p);
+       for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+               awe_poke(AWE_INIT4(i), *p);
+}
+
+
+/*
+ * set up awe32 channels to some known state.
+ */
+
+static void
+awe_tweak(void)
+{
+       int i;
+
+       /* Set the envelope engine parameters to the "default" values for
+          simply playing back unarticulated audio at 44.1kHz.  Set all
+          of the channels: */
+
+       for (i = 0; i < AWE_MAX_VOICES; i++) {
+               awe_poke(AWE_ENVVOL(i)   , 0x8000);
+               awe_poke(AWE_ENVVAL(i)   , 0x8000);
+               awe_poke(AWE_DCYSUS(i)   , 0x7F7F);
+               awe_poke(AWE_ATKHLDV(i)  , 0x7F7F);
+               awe_poke(AWE_LFO1VAL(i)  , 0x8000);
+               awe_poke(AWE_ATKHLD(i)   , 0x7F7F);
+               awe_poke(AWE_LFO2VAL(i)  , 0x8000);
+               awe_poke(AWE_IP(i)       , 0xE000);
+               awe_poke(AWE_IFATN(i)    , 0xFF00);
+               awe_poke(AWE_PEFE(i)     , 0x0000);
+               awe_poke(AWE_FMMOD(i)    , 0x0000);
+               awe_poke(AWE_TREMFRQ(i)  , 0x0010);
+               awe_poke(AWE_FM2FRQ2(i)  , 0x0010);
+       }
+}
+
+
+/*
+ *  initializes the FM section of AWE32
+ */
+
+static void
+awe_init_fm(void)
+{
+#ifndef AWE_ALWAYS_INIT_FM
+       /* if no extended memory is on board.. */
+       if (awe_mem_size <= 0)
+               return;
+#endif
+       DEBUG(0,printk("AWE32: initializing FM\n"));
+
+       /* Initialize the last two channels for DRAM refresh and producing
+          the reverb and chorus effects for Yamaha OPL-3 synthesizer */
+
+       awe_poke(   AWE_DCYSUSV(30)   , 0x0080);
+       awe_poke_dw(AWE_PSST(30)      , 0xFFFFFFE0);
+       awe_poke_dw(AWE_CSL(30)       , 0xFFFFFFE8);
+       awe_poke_dw(AWE_PTRX(30)      , 0x00FFFF00);
+       awe_poke_dw(AWE_CPF(30)       , 0x00000000);
+       awe_poke_dw(AWE_CCCA(30)      , 0x00FFFFE3);
+
+       awe_poke(   AWE_DCYSUSV(31)   , 0x0080);
+       awe_poke_dw(AWE_PSST(31)      , 0x00FFFFE0);
+       awe_poke_dw(AWE_CSL(31)       , 0xFFFFFFE8);
+       awe_poke_dw(AWE_PTRX(31)      , 0x00FFFF00);
+       awe_poke_dw(AWE_CPF(31)       , 0x00000000);
+       awe_poke_dw(AWE_CCCA(31)      , 0x00FFFFE3);
+
+       /* Timing loop */
+
+       /* PTRX is 32 bit long but do not write to the MS byte */
+       awe_poke(AWE_PTRX(30)      , 0x0000);
+
+       while(! (inw(awe_base-0x620+Pointer) & 0x1000));
+       while(   inw(awe_base-0x620+Pointer) & 0x1000);
+
+       /* now write the MS byte of PTRX */
+       OUTW(0x4828, awe_base-0x620+Data0+0x002);
+
+       awe_poke(   AWE_IFATN(28)     , 0x0000);
+       awe_poke_dw(AWE_VTFT(30)      , 0x8000FFFF);
+       awe_poke_dw(AWE_VTFT(31)      , 0x8000FFFF);
+
+       /* change maximum channels to 30 */
+       awe_max_voices = AWE_NORMAL_VOICES;
+       awe_info.nr_voices = awe_max_voices;
+       voice_alloc->max_voice = awe_max_voices;
+}
+
+/*
+ *  AWE32 DRAM access routines
+ */
+
+/* open DRAM write accessing mode */
+static int
+awe_open_dram_for_write(int offset)
+{
+       int i;
+
+       /* use all channels for DMA transfer */
+       for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+               awe_poke(AWE_DCYSUSV(i), 0x80);
+               awe_poke_dw(AWE_VTFT(i), 0);
+               awe_poke_dw(AWE_CVCF(i), 0);
+               awe_poke_dw(AWE_PTRX(i), 0x40000000);
+               awe_poke_dw(AWE_CPF(i), 0x40000000);
+               awe_poke_dw(AWE_PSST(i), 0);
+               awe_poke_dw(AWE_CSL(i), 0);
+               awe_poke_dw(AWE_CCCA(i), 0x06000000);
+       }
+       /* point channels 31 & 32 to ROM samples for DRAM refresh */
+       awe_poke_dw(AWE_VTFT(30), 0);
+       awe_poke_dw(AWE_PSST(30), 0x1d8);
+       awe_poke_dw(AWE_CSL(30), 0x1e0);
+       awe_poke_dw(AWE_CCCA(30), 0x1d8);
+       awe_poke_dw(AWE_VTFT(31), 0);
+       awe_poke_dw(AWE_PSST(31), 0x1d8);
+       awe_poke_dw(AWE_CSL(31), 0x1e0);
+       awe_poke_dw(AWE_CCCA(31), 0x1d8);
+
+       /* if full bit is on, not ready to write on */
+       if (awe_peek_dw(AWE_SMALW) & 0x80000000) {
+               for (i = 0; i < AWE_NORMAL_VOICES; i++)
+                       awe_poke_dw(AWE_CCCA(i), 0);
+               return RET_ERROR(ENOSPC);
+       }
+
+       /* set address to write */
+       awe_poke_dw(AWE_SMALW, offset + AWE_DRAM_OFFSET);
+
+       return 0;
+}
+
+/* open DRAM for RAM size detection */
+static void
+awe_open_dram_for_check(void)
+{
+       int k;
+       unsigned long scratch;
+
+       awe_poke(AWE_HWCF2 , 0x0020);
+
+       for (k = 0; k < AWE_NORMAL_VOICES; k++) {
+               awe_poke(AWE_DCYSUSV(k), 0x0080);
+               awe_poke_dw(AWE_VTFT(k), 0x00000000);
+               awe_poke_dw(AWE_CVCF(k), 0x00000000);
+               awe_poke_dw(AWE_PTRX(k), 0x40000000);
+               awe_poke_dw(AWE_CPF(k), 0x40000000);
+               awe_poke_dw(AWE_PSST(k), 0x00000000);
+               awe_poke_dw(AWE_CSL(k), 0x00000000);
+               scratch = (((k&1) << 9) + 0x400);
+               scratch = scratch << 16;
+               awe_poke_dw(AWE_CCCA(k), scratch);
+       }
+}
+
+
+/* close dram access */
+static void
+awe_close_dram(void)
+{
+       int i;
+       /* wait until FULL bit in SMAxW register be false */
+       for (i = 0; i < 10000; i++) {
+               if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
+                       break;
+               awe_wait(10);
+       }
+
+       for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+               awe_poke_dw(AWE_CCCA(i), 0);
+               awe_poke(AWE_DCYSUSV(i), 0x807F);
+       }
+}
+
+
+#ifdef AWE_CHECKSUM_MEMORY
+/* open DRAM read accessing mode */
+static int
+awe_open_dram_for_read(int offset)
+{
+       int i;
+
+       /* use all channels for DMA transfer */
+       for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+               awe_poke(AWE_DCYSUSV(i), 0x80);
+               awe_poke_dw(AWE_VTFT(i), 0);
+               awe_poke_dw(AWE_CVCF(i), 0);
+               awe_poke_dw(AWE_PTRX(i), 0x40000000);
+               awe_poke_dw(AWE_CPF(i), 0x40000000);
+               awe_poke_dw(AWE_PSST(i), 0);
+               awe_poke_dw(AWE_CSL(i), 0);
+               awe_poke_dw(AWE_CCCA(i), 0x04000000);
+       }
+       /* point channels 31 & 32 to ROM samples for DRAM refresh */
+       awe_poke_dw(AWE_VTFT(30), 0);
+       awe_poke_dw(AWE_PSST(30), 0x1d8);
+       awe_poke_dw(AWE_CSL(30), 0x1e0);
+       awe_poke_dw(AWE_CCCA(30), 0x1d8);
+       awe_poke_dw(AWE_VTFT(31), 0);
+       awe_poke_dw(AWE_PSST(31), 0x1d8);
+       awe_poke_dw(AWE_CSL(31), 0x1e0);
+       awe_poke_dw(AWE_CCCA(31), 0x1d8);
+
+       /* if empty flag is on, not ready to read */
+       if (awe_peek_dw(AWE_SMALR) & 0x80000000) {
+               for (i = 0; i < AWE_NORMAL_VOICES; i++)
+                       awe_poke_dw(AWE_CCCA(i), 0);
+               return RET_ERROR(ENOSPC);
+       }
+
+       /* set address to read */
+       awe_poke_dw(AWE_SMALR, offset + AWE_DRAM_OFFSET);
+       /* drop stale data */
+       awe_peek(AWE_SMLD);
+       return 0;
+}
+
+/* close dram access for read */
+static void
+awe_close_dram_for_read(void)
+{
+       int i;
+       /* wait until FULL bit in SMAxW register be false */
+       for (i = 0; i < 10000; i++) {
+               if (!(awe_peek_dw(AWE_SMALR) & 0x80000000))
+                       break;
+               awe_wait(10);
+       }
+       for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+               awe_poke_dw(AWE_CCCA(i), 0);
+               awe_poke(AWE_DCYSUSV(i), 0x807F);
+       }
+}
+#endif /* AWE_CHECKSUM_MEMORY */
+
+
+/* write a word data */
+static void
+awe_write_dram(unsigned short c)
+{
+       int k;
+       /* wait until FULL bit in SMAxW register be false */
+       for (k = 0; k < 10000; k++) {
+               if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
+                       break;
+               awe_wait(10);
+       }
+       awe_poke(AWE_SMLD, c);
+}
+
+/*================================================================
+ * detect presence of AWE32 and check memory size
+ *================================================================*/
+
+static int
+awe_detect(void)
+{
+#ifdef AWE_DEFAULT_BASE_ADDR
+       awe_base = AWE_DEFAULT_BASE_ADDR;
+       if (((awe_peek(AWE_U1) & 0x000F) == 0x000C) &&
+           ((awe_peek(AWE_HWCF1) & 0x007E) == 0x0058) &&
+           ((awe_peek(AWE_HWCF2) & 0x0003) == 0x0003))
+               return 1;
+#endif
+       if (awe_base == 0) {
+               for (awe_base = 0x620; awe_base <= 0x680; awe_base += 0x20) {
+                       if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
+                               continue;
+                       if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
+                               continue;
+                       if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
+                               continue;
+                       DEBUG(0,printk("AWE32 found at %x\n", awe_base));
+                       return 1;
+               }
+       }
+       FATALERR(printk("AWE32 not found\n"));
+       awe_base = 0;
+       return 0;
+}
+
+
+/*================================================================
+ * check dram size on AWE board
+ *================================================================*/
+static int
+awe_check_dram(void)
+{
+       awe_open_dram_for_check();
+
+       awe_poke_dw(AWE_SMALW    , 0x00200000);     /* DRAM start address */
+       awe_poke(   AWE_SMLD     , 0x1234);
+       awe_poke(   AWE_SMLD     , 0x7777);
+
+       awe_mem_size = 0;
+       while (awe_mem_size < 28*1024) {     /* 28 MB is max onboard memory */
+               awe_wait(2);
+               awe_poke_dw(AWE_SMALR, 0x00200000); /* Address for reading */
+               awe_peek(AWE_SMLD);             /* Discard stale data  */
+               if (awe_peek(AWE_SMLD) != 0x1234)
+                       break;
+               if (awe_peek(AWE_SMLD) != 0x7777)
+                       break;
+               awe_mem_size += 32;
+               /* Address for writing */
+               awe_poke_dw(AWE_SMALW, 0x00200000+awe_mem_size*512L);
+               awe_poke(AWE_SMLD, 0xFFFF);
+       }
+       awe_close_dram();
+
+       DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", (int)awe_mem_size));
+#ifdef AWE_DEFAULT_MEM_SIZE
+       if (awe_mem_size == 0)
+               awe_mem_size = AWE_DEFAULT_MEM_SIZE;
+#endif
+       /* convert to Kbytes */
+       awe_mem_size *= 1024;
+       return awe_mem_size;
+}
+
+
+/*================================================================
+ * chorus and reverb controls
+ *================================================================*/
+
+static unsigned short ChorusEffects[24] =
+{
+  0xE600,0x03F6,0xBC2C,0xE608,0x031A,0xBC6E,0xE610,0x031A,
+  0xBC84,0xE620,0x0269,0xBC6E,0xE680,0x04D3,0xBCA6,0xE6E0,
+  0x044E,0xBC37,0xE600,0x0B06,0xBC00,0xE6C0,0x0B06,0xBC00
+};
+
+static unsigned long ChorusEffects2[] =
+{
+  0x0000 ,0x006D,0x8000,0x0000,0x0000 ,0x017C,0x8000,0x0000,
+  0x0000 ,0x0083,0x8000,0x0000,0x0000 ,0x017C,0x8000,0x0000,
+  0x0000 ,0x005B,0x8000,0x0000,0x0000 ,0x0026,0x8000,0x0000,
+  0x6E000,0x0083,0x8000,0x0000,0x6E000,0x0083,0x8000,0x0000
+};
+
+static unsigned short ChorusCommand[14] =
+{
+  0x69,0xA20,0x6C,0xA20,0x63,0xA22,0x29,
+  0xA20,0x2A,0xA20,0x2D,0xA20,0x2E,0xA20
+};
+
+static unsigned short ReverbEffects[224] =
+{
+  /* Room 1 */
+  0xB488,0xA450,0x9550,0x84B5,0x383A,0x3EB5,0x72F4,
+  0x72A4,0x7254,0x7204,0x7204,0x7204,0x4416,0x4516,
+  0xA490,0xA590,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Room 2 */
+  0xB488,0xA458,0x9558,0x84B5,0x383A,0x3EB5,0x7284,
+  0x7254,0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,
+  0xA440,0xA540,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Room 3 */
+  0xB488,0xA460,0x9560,0x84B5,0x383A,0x3EB5,0x7284,
+  0x7254,0x7224,0x7224,0x7254,0x7284,0x4416,0x4516,
+  0xA490,0xA590,0x842C,0x852C,0x842C,0x852C,0x842B,
+  0x852B,0x842B,0x852B,0x842A,0x852A,0x842A,0x852A,
+  /* Hall 1 */
+  0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7284,
+  0x7254,0x7224,0x7224,0x7254,0x7284,0x4448,0x4548,
+  0xA440,0xA540,0x842B,0x852B,0x842B,0x852B,0x842A,
+  0x852A,0x842A,0x852A,0x8429,0x8529,0x8429,0x8529,
+  /* Hall 2 */
+  0xB488,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7254,
+  0x7234,0x7224,0x7254,0x7264,0x7294,0x44C3,0x45C3,
+  0xA404,0xA504,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Plate */
+  0xB4FF,0xA470,0x9570,0x84B5,0x383A,0x3EB5,0x7234,
+  0x7234,0x7234,0x7234,0x7234,0x7234,0x4448,0x4548,
+  0xA440,0xA540,0x842A,0x852A,0x842A,0x852A,0x8429,
+  0x8529,0x8429,0x8529,0x8428,0x8528,0x8428,0x8528,
+  /* Delay */
+  0xB4FF,0xA470,0x9500,0x84B5,0x333A,0x39B5,0x7204,
+  0x7204,0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,
+  0xA4FF,0xA5FF,0x8420,0x8520,0x8420,0x8520,0x8420,
+  0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520,
+  /* Panning Delay */
+  0xB4FF,0xA490,0x9590,0x8474,0x333A,0x39B5,0x7204,
+  0x7204,0x7204,0x7204,0x7204,0x72F4,0x4400,0x4500,
+  0xA4FF,0xA5FF,0x8420,0x8520,0x8420,0x8520,0x8420,
+  0x8520,0x8420,0x8520,0x8420,0x8520,0x8420,0x8520
+};
+
+static unsigned short ReverbCommand[56] =
+{
+  0x43,0xA20,0x45,0xA20,0x7F,0xA22,0x47,0xA20,
+  0x54,0xA22,0x56,0xA22,0x4F,0xA20,0x57,0xA20,
+  0x5F,0xA20,0x47,0xA22,0x4F,0xA22,0x57,0xA22,
+  0x5D,0xA22,0x5F,0xA22,0x61,0xA20,0x63,0xA20,
+  0x49,0xA20,0x4B,0xA20,0x51,0xA20,0x53,0xA20,
+  0x59,0xA20,0x5B,0xA20,0x41,0xA22,0x43,0xA22,
+  0x49,0xA22,0x4B,0xA22,0x51,0xA22,0x53,0xA22
+};
+
+static void awe_set_chorus_mode(int effect)
+{
+       int k;
+       DECL_INTR_FLAGS(flags);
+
+       DISABLE_INTR(flags);
+       for (k = 0; k < 3; k++)
+               awe_poke(ChorusCommand[k*2],
+                        ChorusCommand[k*2+1],
+                        ChorusEffects[k+effect*3]);
+       for (k = 0; k < 4; k++)
+               awe_poke_dw(ChorusCommand[6+k*2],
+                           ChorusCommand[6+k*2+1],
+                           ChorusEffects2[k+effect*4]);
+       RESTORE_INTR(flags);
+}
+
+static void awe_set_reverb_mode(int effect)
+{
+       int k;
+       DECL_INTR_FLAGS(flags);
+
+       DISABLE_INTR(flags);
+       for (k = 0; k < 28; k++)
+               awe_poke(ReverbCommand[k*2],
+                        ReverbCommand[k*2+1],
+                        ReverbEffects[k+effect*28]);
+       RESTORE_INTR(flags);
+}
+
+#endif /* CONFIG_AWE32_SYNTH */
index 3adb52aa99c530d6a3bcb7eb8277b01be3acfe97..9f924b16a140e582aa0187d30374ad789583b783 100644 (file)
@@ -2,11 +2,31 @@
  * lowlevel/init.c - Calls initialization code for configured drivers.
  */
 
+#include "lowlevel.h"
 #include <linux/config.h>
+#include "../soundvers.h"
 
 #ifdef CONFIG_LOWLEVEL_SOUND
+
+#ifdef LOWLEVEL_MODULE
+char *lowlevel_version = SOUND_VERSION_STRING;
+#endif
+
 extern int attach_aci(void);
 extern void unload_aci(void);
+extern int attach_awe(void);
+extern void unload_awe(void);
+
+/*
+ * There are two places where you can insert initialization calls of
+ * low level drivers. sound_init_lowlevel_drivers() is called after
+ * the sound driver has been initialized (the normal case)
+ * while sound_preinit_lowlevel_drivers() is called before that.
+ */
+void
+sound_preinit_lowlevel_drivers(void)
+{
+}
 
 void
 sound_init_lowlevel_drivers(void)
@@ -14,6 +34,10 @@ sound_init_lowlevel_drivers(void)
 #ifdef CONFIG_ACI_MIXER
    attach_aci();
 #endif
+
+#ifdef CONFIG_AWE32_SYNTH
+   attach_awe();
+#endif
 }
 
 void
@@ -22,5 +46,9 @@ sound_unload_lowlevel_drivers(void)
 #ifdef CONFIG_ACI_MIXER
    unload_aci();
 #endif
+
+#ifdef CONFIG_AWE32_SYNTH
+   unload_awe();
+#endif
 }
 #endif
diff --git a/drivers/sound/lowlevel/lowlevel.h b/drivers/sound/lowlevel/lowlevel.h
new file mode 100644 (file)
index 0000000..bb0f6c7
--- /dev/null
@@ -0,0 +1,5 @@
+#ifdef LOWLEVEL_MODULE
+#define MODVERSIONS
+#include <linux/modversions.h>
+#include "manual_config.h"
+#endif
index 2191c8fbd14904195602ddb885094eb6e793355c..4cdb3d3045111ddaf0e9ec94da81993308b00509 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -16,6 +16,7 @@
  *      OAK OTI-601D    Mozart
  *      OPTi 82C929     MAD16 Pro
  *      OPTi 82C930
+ *      OPTi 82C924     (in non PnP mode)
  *
  * These audio interface chips don't produce sound themselves. They just
  * connect some other components (OPL-[234] and a WSS compatible codec)
@@ -47,7 +48,7 @@
  *
  *      CD-ROM port: 0x00=340, 0x40=330, 0x80=360 or 0xc0=320
  *      OPL4 select: 0x20=OPL4, 0x00=OPL3
- *      CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0a=IRQ3, 0x10=IRQ9,
+ *      CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0c=IRQ3, 0x10=IRQ9,
  *                  0x14=IRQ10 and 0x18=IRQ11.
  *
  *      CD-ROM DMA (Sony or Panasonic): 0x00=DMA3, 0x01=DMA2, 0x02=DMA1 or 0x03=disabled
@@ -69,6 +70,7 @@ static int      already_initialized = 0;
 #define MOZART 2
 #define C929   3
 #define C930   4
+#define C924    5
 
 /*
  *    Registers
@@ -118,21 +120,25 @@ mad_read (int port)
     {
     case C928:
     case MOZART:
-      outb (0xE2, PASSWD_REG);
+      outb ((0xE2), PASSWD_REG);
       break;
 
     case C929:
-      outb (0xE3, PASSWD_REG);
+      outb ((0xE3), PASSWD_REG);
       break;
 
     case C930:
-      /* outb( 0xE4,  PASSWD_REG); */
+      /* outb(( 0xE4),  PASSWD_REG); */
+      break;
+
+    case C924:
+      outb ((0xE5), PASSWD_REG);
       break;
     }
 
   if (board_type == C930)
     {
-      outb (port - MC0_PORT, 0xe0e);   /* Write to index reg */
+      outb ((port - MC0_PORT), 0xe0e); /* Write to index reg */
       tmp = inb (0xe0f);       /* Read from data reg */
     }
   else
@@ -154,25 +160,29 @@ mad_write (int port, int value)
     {
     case C928:
     case MOZART:
-      outb (0xE2, PASSWD_REG);
+      outb ((0xE2), PASSWD_REG);
       break;
 
     case C929:
-      outb (0xE3, PASSWD_REG);
+      outb ((0xE3), PASSWD_REG);
       break;
 
     case C930:
-      /* outb( 0xE4,  PASSWD_REG); */
+      /* outb(( 0xE4),  PASSWD_REG); */
+      break;
+
+    case C924:
+      outb ((0xE5), PASSWD_REG);
       break;
     }
 
   if (board_type == C930)
     {
-      outb (port - MC0_PORT, 0xe0e);   /* Write to index reg */
-      outb ((unsigned char) (value & 0xff), 0xe0f);
+      outb ((port - MC0_PORT), 0xe0e); /* Write to index reg */
+      outb (((unsigned char) (value & 0xff)), 0xe0f);
     }
   else
-    outb ((unsigned char) (value & 0xff), port);
+    outb (((unsigned char) (value & 0xff)), port);
   restore_flags (flags);
 }
 
@@ -354,106 +364,115 @@ init_c930 (struct address_info *hw_config)
   /* MC2 is CD configuration. Don't touch it. */
 
   mad_write (MC3_PORT, 0);     /* Disable SB mode IRQ and DMA */
-
   mad_write (MC4_PORT, 0x52);  /* ??? */
-  mad_write (MC5_PORT, 0x3D);  /* Init it into mode2 */
+  mad_write (MC5_PORT, 0x3C);  /* Init it into mode2 */
   mad_write (MC6_PORT, 0x02);  /* Enable WSS, Disable MPU and SB */
   mad_write (MC7_PORT, 0xCB);
   mad_write (MC10_PORT, 0x11);
 
-  if (!wss_init (hw_config))
-    return 0;
-
-/*
- * A temporary kludge which drops the device back to mode1.
- * This removes problems with interrupts but disables full duplex.
- * A better solution should be introduced later.
- */
-  mad_write (MC5_PORT, 0x1D);  /* Disable mode2 */
   return wss_init (hw_config);
 }
 
-int
-probe_mad16 (struct address_info *hw_config)
+static int
+chip_detect (void)
 {
   int             i;
-  static int      valid_ports[] =
-  {0x530, 0xe80, 0xf40, 0x604};
-  unsigned char   tmp;
-  unsigned char   cs4231_mode = 0;
-
-  int             ad_flags = 0;
-
-  if (already_initialized)
-    return 0;
-
-  mad16_osp = hw_config->osp;
-/*
- *    Check that all ports return 0xff (bus float) when no password
- *      is written to the password register.
- */
-
-  DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
-
 
 /*
  *    Then try to detect with the old password
  */
-  board_type = C928;
+  board_type = C924;
 
-  DDB (printk ("Detect using password = 0xE2\n"));
+  DDB (printk ("Detect using password = 0xE5\n"));
 
   if (!detect_mad16 ())                /* No luck. Try different model */
     {
-      board_type = C929;
+      board_type = C928;
 
-      DDB (printk ("Detect using password = 0xE3\n"));
+      DDB (printk ("Detect using password = 0xE2\n"));
 
       if (!detect_mad16 ())
        {
-         if (inb (PASSWD_REG) != 0xff)
-           return 0;
+         board_type = C929;
+
+         DDB (printk ("Detect using password = 0xE3\n"));
+
+         if (!detect_mad16 ())
+           {
+             if (inb (PASSWD_REG) != 0xff)
+               return 0;
 
 /*
  * First relocate MC# registers to 0xe0e/0xe0f, disable password 
  */
 
-         outb (0xE4, PASSWD_REG);
-         outb (0x80, PASSWD_REG);
+             outb ((0xE4), PASSWD_REG);
+             outb ((0x80), PASSWD_REG);
 
-         board_type = C930;
+             board_type = C930;
 
-         DDB (printk ("Detect using password = 0xE4\n"));
+             DDB (printk ("Detect using password = 0xE4\n"));
 
-         for (i = 0xf8d; i <= 0xf93; i++)
-           DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
+             for (i = 0xf8d; i <= 0xf93; i++)
+               DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
 
-         if (!detect_mad16 ())
-           return 0;
+             if (!detect_mad16 ())
+               return 0;
 
-         DDB (printk ("mad16.c: 82C930 detected\n"));
-         return init_c930 (hw_config);
+             DDB (printk ("mad16.c: 82C930 detected\n"));
+           }
+         else
+           {
+             DDB (printk ("mad16.c: 82C929 detected\n"));
+           }
        }
       else
        {
-         DDB (printk ("mad16.c: 82C929 detected\n"));
+         unsigned char   model;
+
+         if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
+           {
+             DDB (printk ("mad16.c: Mozart detected\n"));
+             board_type = MOZART;
+           }
+         else
+           {
+             DDB (printk ("mad16.c: 82C928 detected???\n"));
+             board_type = C928;
+           }
        }
     }
-  else
-    {
-      unsigned char   model;
 
-      if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
-       {
-         DDB (printk ("mad16.c: Mozart detected\n"));
-         board_type = MOZART;
-       }
-      else
-       {
-         DDB (printk ("mad16.c: 82C928 detected???\n"));
-         board_type = C928;
-       }
-    }
+  return 1;
+}
+
+int
+probe_mad16 (struct address_info *hw_config)
+{
+  int             i;
+  static int      valid_ports[] =
+  {0x530, 0xe80, 0xf40, 0x604};
+  unsigned char   tmp;
+  unsigned char   cs4231_mode = 0;
+
+  int             ad_flags = 0;
+
+  if (already_initialized)
+    return 0;
+
+  mad16_osp = hw_config->osp;
+/*
+ *    Check that all ports return 0xff (bus float) when no password
+ *      is written to the password register.
+ */
+
+  DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
+  if (!chip_detect ())
+    return 0;
+
+  if (board_type == C930)
+    return init_c930 (hw_config);
+
 
   for (i = 0xf8d; i <= 0xf93; i++)
     DDB (printk ("port %03x = %02x\n", i, mad_read (i)));
@@ -462,7 +481,7 @@ probe_mad16 (struct address_info *hw_config)
  * Set the WSS address
  */
 
-  tmp = 0x80;                  /* Enable WSS, Disable SB */
+  tmp = (mad_read (MC1_PORT) & 0x0f) | 0x80;   /* Enable WSS, Disable SB */
 
   for (i = 0; i < 5; i++)
     {
@@ -484,6 +503,7 @@ probe_mad16 (struct address_info *hw_config)
  */
 
 #ifdef MAD16_CONF
+  tmp &= ~0x0f;
   tmp |= ((MAD16_CONF) & 0x0f);        /* CD-ROM and joystick bits */
 #endif
   mad_write (MC1_PORT, tmp);
@@ -491,7 +511,7 @@ probe_mad16 (struct address_info *hw_config)
 #if defined(MAD16_CONF) && defined(MAD16_CDSEL)
   tmp = MAD16_CDSEL;
 #else
-  tmp = 0x03;
+  tmp = mad_read (MC2_PORT);
 #endif
 
 #ifdef MAD16_OPL4
@@ -501,6 +521,13 @@ probe_mad16 (struct address_info *hw_config)
   mad_write (MC2_PORT, tmp);
   mad_write (MC3_PORT, 0xf0);  /* Disable SB */
 
+  if (board_type == C924)      /* Specific C924 init values */
+    {
+      mad_write (MC4_PORT, 0xA0);
+      mad_write (MC5_PORT, 0x05);
+      mad_write (MC6_PORT, 0x03);
+    }
+
   if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
     return 0;
 
@@ -554,12 +581,14 @@ attach_mad16 (struct address_info *hw_config)
   /*
      * Set the IRQ and DMA addresses.
    */
+  if (board_type == C930)
+    interrupt_bits[5] = 0x28;  /* Also IRQ5 is possible on C930 */
 
   bits = interrupt_bits[hw_config->irq];
   if (bits == -1)
     return;
 
-  outb (bits | 0x40, config_port);
+  outb ((bits | 0x40), config_port);
   if ((inb (version_port) & 0x40) == 0)
     printk ("[IRQ Conflict?]");
 
@@ -594,7 +623,7 @@ attach_mad16 (struct address_info *hw_config)
   else
     dma2 = dma;
 
-  outb (bits | dma_bits[dma] | dma2_bit, config_port); /* Write IRQ+DMA setup */
+  outb ((bits | dma_bits[dma] | dma2_bit), config_port);       /* Write IRQ+DMA setup */
 
   ad1848_init ("MAD16 WSS", hw_config->io_base + 4,
               hw_config->irq,
@@ -766,10 +795,12 @@ unload_mad16_mpu (struct address_info *hw_config)
     }
 #endif
 
-#if (defined(CONFIG_UART401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
   unload_uart401 (hw_config);
 #endif
 }
 
+
+
 /* That's all folks */
 #endif
index 43670af12f2b0e0fdfc6a9e95655e17c5210ee8e..8c6e1ef8026546d0618f4948dc0134289239eb19 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -47,7 +47,7 @@ static int      maui_osLen = 0;
 
 #endif
 
-static wait_handle *maui_sleeper = NULL;
+static struct wait_queue *maui_sleeper = NULL;
 static volatile struct snd_wait maui_sleep_flag =
 {0};
 
@@ -84,20 +84,22 @@ maui_wait (int mask)
        unsigned long   tlimit;
 
        if (HZ / 10)
-         current_set_timeout (tlimit = jiffies + (HZ / 10));
+         current->timeout = tlimit = jiffies + (HZ / 10);
        else
          tlimit = (unsigned long) -1;
-       maui_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&maui_sleeper);
-       if (!(maui_sleep_flag.flags & WK_WAKEUP))
+       maui_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&maui_sleeper);
+       if (!(maui_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             maui_sleep_flag.flags |= WK_TIMEOUT;
+             maui_sleep_flag.opts |= WK_TIMEOUT;
          }
-       maui_sleep_flag.flags &= ~WK_SLEEP;
+       maui_sleep_flag.opts &= ~WK_SLEEP;
       };
-      if (current_got_fatal_signal ())
-       return 0;
+      if ((current->signal & ~current->blocked))
+       {
+         return 0;
+       }
     }
 
   return 0;
@@ -117,7 +119,7 @@ maui_write (unsigned char data)
 {
   if (maui_wait (STAT_TX_AVAIL))
     {
-      outb (data, HOST_DATA_PORT);
+      outb ((data), HOST_DATA_PORT);
       return 1;
     }
   printk ("Maui: Write timeout\n");
@@ -228,29 +230,29 @@ maui_init (int irq)
       return 0;
     }
 
-  outb (0x00, HOST_CTRL_PORT); /* Reset */
+  outb ((0x00), HOST_CTRL_PORT);       /* Reset */
 
-  outb (bits, HOST_DATA_PORT); /* Set the IRQ bits */
-  outb (bits | 0x80, HOST_DATA_PORT);  /* Set the IRQ bits again? */
+  outb ((bits), HOST_DATA_PORT);       /* Set the IRQ bits */
+  outb ((bits | 0x80), HOST_DATA_PORT);                /* Set the IRQ bits again? */
 
-  outb (0x80, HOST_CTRL_PORT); /* Leave reset */
-  outb (0x80, HOST_CTRL_PORT); /* Leave reset */
+  outb ((0x80), HOST_CTRL_PORT);       /* Leave reset */
+  outb ((0x80), HOST_CTRL_PORT);       /* Leave reset */
 
-  outb (0xD0, HOST_CTRL_PORT); /* Cause interrupt */
+  outb ((0xD0), HOST_CTRL_PORT);       /* Cause interrupt */
 
   for (i = 0; i < 1000000 && !irq_ok; i++);
 
   if (!irq_ok)
     return 0;
 
-  outb (0x80, HOST_CTRL_PORT); /* Leave reset */
+  outb ((0x80), HOST_CTRL_PORT);       /* Leave reset */
 
   printk ("Turtle Beach Maui initialization\n");
 
   if (!download_code ())
     return 0;
 
-  outb (0xE0, HOST_CTRL_PORT); /* Normal operation */
+  outb ((0xE0), HOST_CTRL_PORT);       /* Normal operation */
 
   /* Select mpu401 mode */
 
@@ -305,7 +307,7 @@ maui_load_patch (int dev, int format, const char *addr,
   if (count < hdr_size)
     {
       printk ("Maui error: Patch header too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   count -= hdr_size;
@@ -331,12 +333,12 @@ maui_load_patch (int dev, int format, const char *addr,
     {
       unsigned char   data;
 
-      data = get_fs_byte (&((addr)[hdr_size + i]));
+      get_user (data, (unsigned char *) &((addr)[hdr_size + i]));
       if (i == 0 && !(data & 0x80))
-       return -(EINVAL);
+       return -EINVAL;
 
       if (maui_write (data) == -1)
-       return -(EIO);
+       return -EIO;
     }
 
   if ((i = maui_read ()) != 0x80)
@@ -344,7 +346,7 @@ maui_load_patch (int dev, int format, const char *addr,
       if (i != -1)
        printk ("Maui: Error status %02x\n", i);
 
-      return -(EIO);
+      return -EIO;
     }
 
   return 0;
@@ -365,7 +367,7 @@ probe_maui (struct address_info *hw_config)
   if (snd_set_irq_handler (hw_config->irq, mauiintr, "Maui", maui_osp) < 0)
     return 0;
 
-  maui_sleep_flag.flags = WK_NONE;
+  maui_sleep_flag.opts = WK_NONE;
 /*
  * Initialize the processor if necessary
  */
index 2f946b49a14ca12d055aca859fa9e80773d5b6ed..64cde661a97aafe94ba0313591b3beb1ba719bf6 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -22,7 +22,7 @@
 
 #define _MIDI_SYNTH_C_
 
-static wait_handle *sysex_sleeper = NULL;
+static struct wait_queue *sysex_sleeper = NULL;
 static volatile struct snd_wait sysex_sleep_flag =
 {0};
 
@@ -99,8 +99,8 @@ midi_outc (int midi_dev, int data)
 {
   int             timeout;
 
-  for (timeout = 0; timeout < 32000; timeout++)
-    if (midi_devs[midi_dev]->putc (midi_dev, (unsigned char) (data & 0xff)))
+  for (timeout = 0; timeout < 3200; timeout++)
+    if (midi_devs[midi_dev]->outputc (midi_dev, (unsigned char) (data & 0xff)))
       {
        if (data & 0x80)        /*
                                 * Status byte
@@ -248,7 +248,7 @@ leave_sysex (int dev)
 
   sysex_state[dev] = 0;
 
-  while (!midi_devs[orig_dev]->putc (orig_dev, 0xf7) &&
+  while (!midi_devs[orig_dev]->outputc (orig_dev, 0xf7) &&
         timeout < 1000)
     timeout++;
 
@@ -275,7 +275,10 @@ midi_synth_ioctl (int dev,
     {
 
     case SNDCTL_SYNTH_INFO:
-      copy_to_user (&((char *) arg)[0], synth_devs[dev]->info, sizeof (struct synth_info));
+      {
+       char           *fixit = (char *) synth_devs[dev]->info;
+       copy_to_user (&((char *) arg)[0], fixit, sizeof (struct synth_info));
+      };
 
       return 0;
       break;
@@ -285,7 +288,7 @@ midi_synth_ioctl (int dev,
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -363,7 +366,7 @@ midi_synth_set_instr (int dev, int channel, int instr_no)
   int             orig_dev = synth_devs[dev]->midi_dev;
 
   if (instr_no < 0 || instr_no > 127)
-    return 0;
+    instr_no = 0;
   if (channel < 0 || channel > 15)
     return 0;
 
@@ -437,7 +440,7 @@ midi_synth_open (int dev, int mode)
   struct midi_input_info *inc;
 
   if (orig_dev < 0 || orig_dev > num_midis)
-    return -(ENXIO);
+    return -ENXIO;
 
   midi2synth[orig_dev] = dev;
   sysex_state[dev] = 0;
@@ -458,7 +461,7 @@ midi_synth_open (int dev, int mode)
   inc->m_prev_status = 0x00;
   restore_flags (flags);
 
-  sysex_sleep_flag.flags = WK_NONE;
+  sysex_sleep_flag.opts = WK_NONE;
 
   return 1;
 }
@@ -473,7 +476,7 @@ midi_synth_close (int dev)
   /*
    * Shut up the synths by sending just single active sensing message.
    */
-  midi_devs[orig_dev]->putc (orig_dev, 0xfe);
+  midi_devs[orig_dev]->outputc (orig_dev, 0xfe);
 
   midi_devs[orig_dev]->close (orig_dev);
 }
@@ -503,13 +506,13 @@ midi_synth_load_patch (int dev, int format, const char *addr,
   if (format != SYSEX_PATCH)
     {
       printk ("MIDI Error: Invalid patch format (key) 0x%x\n", format);
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   if (count < hdr_size)
     {
       printk ("MIDI Error: Patch header too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   count -= hdr_size;
@@ -531,13 +534,13 @@ midi_synth_load_patch (int dev, int format, const char *addr,
   left = sysex.len;
   src_offs = 0;
 
-  sysex_sleep_flag.flags = WK_NONE;
+  sysex_sleep_flag.opts = WK_NONE;
 
-  for (i = 0; i < left && !current_got_fatal_signal (); i++)
+  for (i = 0; i < left && !(current->signal & ~current->blocked); i++)
     {
       unsigned char   data;
 
-      data = get_fs_byte (&((addr)[hdr_size + i]));
+      get_user (data, (unsigned char *) &((addr)[hdr_size + i]));
 
       eox_seen = (i > 0 && data & 0x80);       /* End of sysex */
 
@@ -549,28 +552,28 @@ midi_synth_load_patch (int dev, int format, const char *addr,
          if (data != 0xf0)
            {
              printk ("Error: Sysex start missing\n");
-             return -(EINVAL);
+             return -EINVAL;
            }
        }
 
-      while (!midi_devs[orig_dev]->putc (orig_dev, (unsigned char) (data & 0xff)) &&
-            !current_got_fatal_signal ())
+      while (!midi_devs[orig_dev]->outputc (orig_dev, (unsigned char) (data & 0xff)) &&
+            !(current->signal & ~current->blocked))
 
        {
          unsigned long   tlimit;
 
          if (1)
-           current_set_timeout (tlimit = jiffies + (1));
+           current->timeout = tlimit = jiffies + (1);
          else
            tlimit = (unsigned long) -1;
-         sysex_sleep_flag.flags = WK_SLEEP;
-         module_interruptible_sleep_on (&sysex_sleeper);
-         if (!(sysex_sleep_flag.flags & WK_WAKEUP))
+         sysex_sleep_flag.opts = WK_SLEEP;
+         interruptible_sleep_on (&sysex_sleeper);
+         if (!(sysex_sleep_flag.opts & WK_WAKEUP))
            {
              if (jiffies >= tlimit)
-               sysex_sleep_flag.flags |= WK_TIMEOUT;
+               sysex_sleep_flag.opts |= WK_TIMEOUT;
            }
-         sysex_sleep_flag.flags &= ~WK_SLEEP;
+         sysex_sleep_flag.opts &= ~WK_SLEEP;
        };                      /* Wait for timeout */
 
       if (!first_byte && data & 0x80)
@@ -652,7 +655,7 @@ midi_synth_controller (int dev, int channel, int ctrl_num, int value)
 int
 midi_synth_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 void
@@ -725,7 +728,7 @@ midi_synth_send_sysex (int dev, unsigned char *bytes, int len)
            }
        }
 
-      if (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]))
+      if (!midi_devs[orig_dev]->outputc (orig_dev, bytes[i]))
        {
 /*
  * Hardware level buffer is full. Abort the sysex message.
@@ -736,7 +739,7 @@ midi_synth_send_sysex (int dev, unsigned char *bytes, int len)
          bytes[i] = 0xf7;
          sysex_state[dev] = 0;
 
-         while (!midi_devs[orig_dev]->putc (orig_dev, bytes[i]) &&
+         while (!midi_devs[orig_dev]->outputc (orig_dev, bytes[i]) &&
                 timeout < 1000)
            timeout++;
        }
index d088c80a83defce96270d8a5104f995a1cbe1598..a5619b9a8c5284d3df665f24fa5e1e60a0b51246 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 
 #define MAX_QUEUE_SIZE 4000
 
-static wait_handle *midi_sleeper[MAX_MIDI_DEV] =
+static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] =
 {NULL};
 static volatile struct snd_wait midi_sleep_flag[MAX_MIDI_DEV] =
 {
   {0}};
-static wait_handle *input_sleeper[MAX_MIDI_DEV] =
+static struct wait_queue *input_sleeper[MAX_MIDI_DEV] =
 {NULL};
 static volatile struct snd_wait input_sleep_flag[MAX_MIDI_DEV] =
 {
@@ -67,7 +67,7 @@ static volatile int open_devs = 0;
        if (SPACE_AVAIL(q)) \
        { \
          unsigned long flags; \
-         save_flags(flags);cli(); \
+         save_flags( flags);cli(); \
          q->queue[q->tail] = (data); \
          q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \
          restore_flags(flags); \
@@ -77,7 +77,7 @@ static volatile int open_devs = 0;
        if (DATA_AVAIL(q)) \
        { \
          unsigned long flags; \
-         save_flags(flags);cli(); \
+         save_flags( flags);cli(); \
          data = q->queue[q->head]; \
          q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \
          restore_flags(flags); \
@@ -92,24 +92,24 @@ drain_midi_queue (int dev)
    */
 
   if (midi_devs[dev]->buffer_status != NULL)
-    while (!current_got_fatal_signal () &&
+    while (!(current->signal & ~current->blocked) &&
           midi_devs[dev]->buffer_status (dev))
 
       {
        unsigned long   tlimit;
 
        if (HZ / 10)
-         current_set_timeout (tlimit = jiffies + (HZ / 10));
+         current->timeout = tlimit = jiffies + (HZ / 10);
        else
          tlimit = (unsigned long) -1;
-       midi_sleep_flag[dev].flags = WK_SLEEP;
-       module_interruptible_sleep_on (&midi_sleeper[dev]);
-       if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
+       midi_sleep_flag[dev].opts = WK_SLEEP;
+       interruptible_sleep_on (&midi_sleeper[dev]);
+       if (!(midi_sleep_flag[dev].opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             midi_sleep_flag[dev].flags |= WK_TIMEOUT;
+             midi_sleep_flag[dev].opts |= WK_TIMEOUT;
          }
-       midi_sleep_flag[dev].flags &= ~WK_SLEEP;
+       midi_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
 }
 
@@ -129,10 +129,10 @@ midi_input_intr (int dev, unsigned char data)
   if (SPACE_AVAIL (midi_in_buf[dev]))
     {
       QUEUE_BYTE (midi_in_buf[dev], data);
-      if ((input_sleep_flag[dev].flags & WK_SLEEP))
+      if ((input_sleep_flag[dev].opts & WK_SLEEP))
        {
-         input_sleep_flag[dev].flags = WK_WAKEUP;
-         module_wake_up (&input_sleeper[dev]);
+         input_sleep_flag[dev].opts = WK_WAKEUP;
+         wake_up (&input_sleeper[dev]);
        };
     }
 
@@ -159,19 +159,25 @@ midi_poll (unsigned long dummy)
       for (dev = 0; dev < num_midis; dev++)
        if (midi_out_buf[dev] != NULL)
          {
-           while (DATA_AVAIL (midi_out_buf[dev]) &&
-                  midi_devs[dev]->putc (dev,
-                        midi_out_buf[dev]->queue[midi_out_buf[dev]->head]))
+           int             ok = 1;
+
+           while (DATA_AVAIL (midi_out_buf[dev]) && ok)
              {
+               int             c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
+
+               restore_flags (flags);  /* Give some time to others */
+               ok = midi_devs[dev]->outputc (dev, c);
+               save_flags (flags);
+               cli ();
                midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
                midi_out_buf[dev]->len--;
              }
 
            if (DATA_AVAIL (midi_out_buf[dev]) < 100 &&
-               (midi_sleep_flag[dev].flags & WK_SLEEP))
+               (midi_sleep_flag[dev].opts & WK_SLEEP))
              {
-               midi_sleep_flag[dev].flags = WK_WAKEUP;
-               module_wake_up (&midi_sleeper[dev]);
+               midi_sleep_flag[dev].opts = WK_WAKEUP;
+               wake_up (&midi_sleeper[dev]);
              };
          }
 
@@ -202,7 +208,7 @@ MIDIbuf_open (int dev, struct fileinfo *file)
   if (dev < 0 || dev >= num_midis)
     {
       printk ("Sound: Nonexistent MIDI interface %d\n", dev);
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   /*
@@ -223,7 +229,7 @@ MIDIbuf_open (int dev, struct fileinfo *file)
     {
       printk ("midi: Can't allocate buffer\n");
       midi_devs[dev]->close (dev);
-      return -(EIO);
+      return -EIO;
     }
   midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0;
 
@@ -235,13 +241,13 @@ MIDIbuf_open (int dev, struct fileinfo *file)
       midi_devs[dev]->close (dev);
       vfree (midi_in_buf[dev]);
       midi_in_buf[dev] = NULL;
-      return -(EIO);
+      return -EIO;
     }
   midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
   open_devs++;
 
-  midi_sleep_flag[dev].flags = WK_NONE;
-  input_sleep_flag[dev].flags = WK_NONE;
+  midi_sleep_flag[dev].opts = WK_NONE;
+  input_sleep_flag[dev].opts = WK_NONE;
 
   if (open_devs < 2)           /* This was first open */
     {
@@ -277,29 +283,29 @@ MIDIbuf_release (int dev, struct fileinfo *file)
 
   if (mode != OPEN_READ)
     {
-      midi_devs[dev]->putc (dev, 0xfe);                /*
+      midi_devs[dev]->outputc (dev, 0xfe);     /*
                                                   * Active sensing to shut the
                                                   * devices
                                                 */
 
-      while (!current_got_fatal_signal () &&
+      while (!(current->signal & ~current->blocked) &&
             DATA_AVAIL (midi_out_buf[dev]))
 
        {
          unsigned long   tlimit;
 
          if (0)
-           current_set_timeout (tlimit = jiffies + (0));
+           current->timeout = tlimit = jiffies + (0);
          else
            tlimit = (unsigned long) -1;
-         midi_sleep_flag[dev].flags = WK_SLEEP;
-         module_interruptible_sleep_on (&midi_sleeper[dev]);
-         if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
+         midi_sleep_flag[dev].opts = WK_SLEEP;
+         interruptible_sleep_on (&midi_sleeper[dev]);
+         if (!(midi_sleep_flag[dev].opts & WK_WAKEUP))
            {
              if (jiffies >= tlimit)
-               midi_sleep_flag[dev].flags |= WK_TIMEOUT;
+               midi_sleep_flag[dev].opts |= WK_TIMEOUT;
            }
-         midi_sleep_flag[dev].flags &= ~WK_SLEEP;
+         midi_sleep_flag[dev].opts &= ~WK_SLEEP;
        };                      /*
                                   * Sync
                                 */
@@ -352,22 +358,22 @@ MIDIbuf_write (int dev, struct fileinfo *file, const char *buf, int count)
            unsigned long   tlimit;
 
            if (0)
-             current_set_timeout (tlimit = jiffies + (0));
+             current->timeout = tlimit = jiffies + (0);
            else
              tlimit = (unsigned long) -1;
-           midi_sleep_flag[dev].flags = WK_SLEEP;
-           module_interruptible_sleep_on (&midi_sleeper[dev]);
-           if (!(midi_sleep_flag[dev].flags & WK_WAKEUP))
+           midi_sleep_flag[dev].opts = WK_SLEEP;
+           interruptible_sleep_on (&midi_sleeper[dev]);
+           if (!(midi_sleep_flag[dev].opts & WK_WAKEUP))
              {
                if (jiffies >= tlimit)
-                 midi_sleep_flag[dev].flags |= WK_TIMEOUT;
+                 midi_sleep_flag[dev].opts |= WK_TIMEOUT;
              }
-           midi_sleep_flag[dev].flags &= ~WK_SLEEP;
+           midi_sleep_flag[dev].opts &= ~WK_SLEEP;
          };
-         if (current_got_fatal_signal ())
+         if ((current->signal & ~current->blocked))
            {
              restore_flags (flags);
-             return -(EINTR);
+             return -EINTR;
            }
 
          n = SPACE_AVAIL (midi_out_buf[dev]);
@@ -411,20 +417,20 @@ MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count)
        unsigned long   tlimit;
 
        if (parms[dev].prech_timeout)
-         current_set_timeout (tlimit = jiffies + (parms[dev].prech_timeout));
+         current->timeout = tlimit = jiffies + (parms[dev].prech_timeout);
        else
          tlimit = (unsigned long) -1;
-       input_sleep_flag[dev].flags = WK_SLEEP;
-       module_interruptible_sleep_on (&input_sleeper[dev]);
-       if (!(input_sleep_flag[dev].flags & WK_WAKEUP))
+       input_sleep_flag[dev].opts = WK_SLEEP;
+       interruptible_sleep_on (&input_sleeper[dev]);
+       if (!(input_sleep_flag[dev].opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             input_sleep_flag[dev].flags |= WK_TIMEOUT;
+             input_sleep_flag[dev].opts |= WK_TIMEOUT;
          }
-       input_sleep_flag[dev].flags &= ~WK_SLEEP;
+       input_sleep_flag[dev].opts &= ~WK_SLEEP;
       };
-      if (current_got_fatal_signal ())
-       c = -(EINTR);           /*
+      if ((current->signal & ~current->blocked))
+       c = -EINTR;             /*
                                   * The user is getting restless
                                 */
     }
@@ -441,7 +447,11 @@ MIDIbuf_read (int dev, struct fileinfo *file, char *buf, int count)
       while (c < n)
        {
          REMOVE_BYTE (midi_in_buf[dev], tmp_data);
-         copy_to_user (&(buf)[c], (char *) &tmp_data, 1);
+         {
+           char           *fixit = (char *) &tmp_data;
+
+           copy_to_user (&(buf)[c], fixit, 1);
+         };
          c++;
        }
     }
@@ -466,20 +476,20 @@ MIDIbuf_ioctl (int dev, struct fileinfo *file,
       else
        printk ("/dev/midi%d: No coprocessor for this device\n", dev);
 
-      return -(ENXIO);
+      return -ENXIO;
     }
   else
     switch (cmd)
       {
 
       case SNDCTL_MIDI_PRETIME:
-       val = (int) get_user ((int *) arg);
+       get_user (val, (int *) arg);
        if (val < 0)
          val = 0;
 
        val = (HZ * val) / 10;
        parms[dev].prech_timeout = val;
-       return snd_ioctl_return ((int *) arg, val);
+       return ioctl_out (arg, val);
        break;
 
       default:
@@ -488,7 +498,7 @@ MIDIbuf_ioctl (int dev, struct fileinfo *file,
 }
 
 int
-MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   dev = dev >> 4;
 
@@ -498,8 +508,8 @@ MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handl
       if (!DATA_AVAIL (midi_in_buf[dev]))
        {
 
-         input_sleep_flag[dev].flags = WK_SLEEP;
-         module_select_wait (&input_sleeper[dev], wait);
+         input_sleep_flag[dev].opts = WK_SLEEP;
+         select_wait (&input_sleeper[dev], wait);
          return 0;
        }
       return 1;
@@ -509,8 +519,8 @@ MIDIbuf_select (int dev, struct fileinfo *file, int sel_type, select_table_handl
       if (SPACE_AVAIL (midi_out_buf[dev]))
        {
 
-         midi_sleep_flag[dev].flags = WK_SLEEP;
-         module_select_wait (&midi_sleeper[dev], wait);
+         midi_sleep_flag[dev].opts = WK_SLEEP;
+         select_wait (&midi_sleeper[dev], wait);
          return 0;
        }
       return 1;
index 5f1c5e5e73a61fe742d03020184f2c6e55a984bf..132d63e20ac652ef45c32b7a49ab36736bdfbdc5 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -23,6 +23,7 @@
 
 static int      init_sequence[20];     /* NOTE! pos 0 = len, start pos 1. */
 
+
 #ifdef CONFIG_SEQUENCER
 static int      timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL;
 
@@ -82,7 +83,7 @@ mpu401_status (struct mpu_config *devc)
 static void 
 write_command (struct mpu_config *devc, unsigned char cmd)
 {
-  outb (cmd, COMDPORT (devc->base));
+  outb ((cmd), COMDPORT (devc->base));
 }
 static int 
 read_data (struct mpu_config *devc)
@@ -93,7 +94,7 @@ read_data (struct mpu_config *devc)
 static void 
 write_data (struct mpu_config *devc, unsigned char byte)
 {
-  outb (byte, DATAPORT (devc->base));
+  outb ((byte), DATAPORT (devc->base));
 }
 
 #define        OUTPUT_READY    0x40
@@ -492,14 +493,14 @@ mpu401_open (int dev, int mode,
   struct mpu_config *devc;
 
   if (dev < 0 || dev >= num_midis)
-    return -(ENXIO);
+    return -ENXIO;
 
   devc = &dev_conf[dev];
 
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -514,7 +515,7 @@ mpu401_open (int dev, int mode,
       if (mpu401_status (devc) == 0xff)                /* Bus float */
        {
          printk ("MPU-401: Device not initialized properly\n");
-         return -(EIO);
+         return -EIO;
        }
       reset_mpu401 (devc);
     }
@@ -608,7 +609,7 @@ mpu401_command (int dev, mpu_command_rec * cmd)
                                 */
     {
       printk ("MPU-401 commands not possible in the UART mode\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   /*
@@ -627,7 +628,7 @@ retry:
   if (timeout-- <= 0)
     {
       printk ("MPU-401: Command (0x%x) timeout\n", (int) cmd->cmd);
-      return -(EIO);
+      return -EIO;
     }
 
   save_flags (flags);
@@ -661,7 +662,7 @@ retry:
     {
       restore_flags (flags);
       /*       printk ("MPU: No ACK to command (0x%x)\n", (int) cmd->cmd); */
-      return -(EIO);
+      return -EIO;
     }
 
   if (cmd->nr_args)
@@ -673,7 +674,7 @@ retry:
          {
            restore_flags (flags);
            printk ("MPU: Command (0x%x), parm send failed.\n", (int) cmd->cmd);
-           return -(EIO);
+           return -EIO;
          }
       }
 
@@ -695,7 +696,7 @@ retry:
          {
            restore_flags (flags);
            /* printk ("MPU: No response(%d) to command (0x%x)\n", i, (int) cmd->cmd);  */
-           return -(EIO);
+           return -EIO;
          }
       }
 
@@ -788,9 +789,9 @@ mpu401_ioctl (int dev, unsigned cmd, caddr_t arg)
       if (!(devc->capabilities & MPU_CAP_INTLG))       /* No intelligent mode */
        {
          printk ("MPU-401: Intelligent mode not supported by the HW\n");
-         return -(EINVAL);
+         return -EINVAL;
        }
-      set_uart_mode (dev, devc, !get_user ((int *) arg));
+      set_uart_mode (dev, devc, !ioctl_in (arg));
       return 0;
       break;
 
@@ -804,13 +805,17 @@ mpu401_ioctl (int dev, unsigned cmd, caddr_t arg)
        if ((ret = mpu401_command (dev, &rec)) < 0)
          return ret;
 
-       copy_to_user (&((char *) arg)[0], (char *) &rec, sizeof (rec));
+       {
+         char           *fixit = (char *) &rec;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (rec));
+       };
        return 0;
       }
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -837,7 +842,7 @@ mpu_synth_ioctl (int dev,
   midi_dev = synth_devs[dev]->midi_dev;
 
   if (midi_dev < 0 || midi_dev > num_midis)
-    return -(ENXIO);
+    return -ENXIO;
 
   devc = &dev_conf[midi_dev];
 
@@ -845,7 +850,10 @@ mpu_synth_ioctl (int dev,
     {
 
     case SNDCTL_SYNTH_INFO:
-      copy_to_user (&((char *) arg)[0], &mpu_synth_info[midi_dev], sizeof (struct synth_info));
+      {
+       char           *fixit = (char *) &mpu_synth_info[midi_dev];
+       copy_to_user (&((char *) arg)[0], fixit, sizeof (struct synth_info));
+      };
 
       return 0;
       break;
@@ -855,7 +863,7 @@ mpu_synth_ioctl (int dev,
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 }
 
@@ -869,7 +877,7 @@ mpu_synth_open (int dev, int mode)
 
   if (midi_dev < 0 || midi_dev > num_midis)
     {
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   devc = &dev_conf[midi_dev];
@@ -886,7 +894,7 @@ mpu_synth_open (int dev, int mode)
       if (mpu401_status (devc) == 0xff)                /* Bus float */
        {
          printk ("MPU-401: Device not initialized properly\n");
-         return -(EIO);
+         return -EIO;
        }
       reset_mpu401 (devc);
     }
@@ -894,7 +902,7 @@ mpu_synth_open (int dev, int mode)
   if (devc->opened)
     {
       printk ("MPU-401: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   devc->mode = MODE_SYNTH;
@@ -1464,7 +1472,7 @@ mpu_timer_open (int dev, int mode)
   int             midi_dev = sound_timer_devs[dev]->devlink;
 
   if (timer_open)
-    return -(EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 50;
@@ -1590,7 +1598,10 @@ mpu_timer_ioctl (int dev,
     {
     case SNDCTL_TMR_SOURCE:
       {
-       int             parm = (int) get_user ((int *) arg) & timer_caps;
+       int             parm;
+
+       get_user (parm, (int *) arg);
+       parm &= timer_caps;
 
        if (parm != 0)
          {
@@ -1602,7 +1613,7 @@ mpu_timer_ioctl (int dev,
              mpu_cmd (midi_dev, 0x3d, 0);      /* Use SMPTE sync */
          }
 
-       return snd_ioctl_return ((int *) arg, timer_mode);
+       return ioctl_out (arg, timer_mode);
       }
       break;
 
@@ -1628,18 +1639,18 @@ mpu_timer_ioctl (int dev,
 
     case SNDCTL_TMR_TIMEBASE:
       {
-       int             val = (int) get_user ((int *) arg);
+       int             val = (int) ioctl_in (arg);
 
        if (val)
          set_timebase (midi_dev, val);
 
-       return snd_ioctl_return ((int *) arg, curr_timebase);
+       return ioctl_out (arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-       int             val = (int) get_user ((int *) arg);
+       int             val = (int) ioctl_in (arg);
        int             ret;
 
        if (val)
@@ -1657,19 +1668,23 @@ mpu_timer_ioctl (int dev,
            curr_tempo = val;
          }
 
-       return snd_ioctl_return ((int *) arg, curr_tempo);
+       return ioctl_out (arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (get_user ((int *) arg) != 0) /* Can't change */
-       return -(EINVAL);
+      if (ioctl_in (arg) != 0) /* Can't change */
+       return -EINVAL;
+
+      return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      break;
 
-      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
+    case SNDCTL_SEQ_GETTIME:
+      return ioctl_out (arg, curr_ticks);
       break;
 
     case SNDCTL_TMR_METRONOME:
-      metronome_mode = (int) get_user ((int *) arg);
+      metronome_mode = (int) ioctl_in (arg);
       setup_metronome (midi_dev);
       return 0;
       break;
@@ -1677,7 +1692,7 @@ mpu_timer_ioctl (int dev,
     default:;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
index 1f76d2d855a96c09a099d183a68927cd6f01b379..c501cc7c06830365a2cd3e9f174150a97534a8a3 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -38,6 +38,7 @@ struct voice_info
     unsigned long   current_freq;
     int             volume;
     int             mode;
+    int             panning;   /* 0xffff means not set */
   };
 
 typedef struct opl_devinfo
@@ -123,7 +124,7 @@ opl3_ioctl (int dev,
        if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
          {
            printk ("FM Error: Invalid instrument number %d\n", ins.channel);
-           return -(EINVAL);
+           return -EINVAL;
          }
 
        pmgr_inform (dev, PM_E_PATCH_LOADED, ins.channel, 0, 0, 0);
@@ -134,7 +135,11 @@ opl3_ioctl (int dev,
     case SNDCTL_SYNTH_INFO:
       devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice;
 
-      copy_to_user (&((char *) arg)[0], &devc->fm_info, sizeof (devc->fm_info));
+      {
+       char           *fixit = (char *) &devc->fm_info;
+
+       copy_to_user (&((char *) arg)[0], fixit, sizeof (devc->fm_info));
+      };
       return 0;
       break;
 
@@ -149,7 +154,7 @@ opl3_ioctl (int dev,
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
 }
@@ -168,7 +173,7 @@ opl3_detect (int ioaddr, int *osp)
    * Note2! The chip is initialized if detected.
    */
 
-  unsigned char   stat1, stat2, signature;
+  unsigned char   stat1, signature;
   int             i;
 
   if (devc != NULL)
@@ -196,51 +201,12 @@ opl3_detect (int ioaddr, int *osp)
 
   signature = stat1 = inb (ioaddr);    /* Status register */
 
-  if ((stat1 & 0xE0) != 0x00)
+  if (signature != 0x00 && signature != 0x06 && signature != 0x02)
     {
-      return 0;                        /*
-                                * Should be 0x00
-                                */
-    }
-
-  opl3_command (ioaddr, TIMER1_REGISTER, 0xff);                /* Set timer1 to 0xff */
-
-  opl3_command (ioaddr, TIMER_CONTROL_REGISTER,
-               TIMER2_MASK | TIMER1_START);    /*
-                                                * Unmask and start timer 1
-                                                */
-
-  /*
-   * Now we have to delay at least 80 usec
-   */
-
-  for (i = 0; i < 50; i++)
-    tenmicrosec (devc->osp);
-
-  stat2 = inb (ioaddr);                /*
-                                  * Read status after timers have expired
-                                */
-
-  /*
-   * Stop the timers
-   */
-
-  /* Reset timers 1 and 2 */
-  opl3_command (ioaddr, TIMER_CONTROL_REGISTER, TIMER1_MASK | TIMER2_MASK);
-  /* Reset the IRQ of the FM chip */
-  opl3_command (ioaddr, TIMER_CONTROL_REGISTER, IRQ_RESET);
-
-  if ((stat2 & 0xE0) != 0xc0)
-    {
-      return 0;                        /*
-                                * There is no YM3812
-                                */
+      DDB (printk ("OPL3 not detected %x\n", signature));
+      return 0;
     }
 
-  /*
-   * There is a FM chip in this address. Detect the type (OPL2 to OPL4)
-   */
-
   if (signature == 0x06 && !force_opl3_mode)   /* OPL2 */
     {
       detected_model = 2;
@@ -269,7 +235,7 @@ opl3_detect (int ioaddr, int *osp)
        {
          int             tmp;
 
-         outb (0x02, ioaddr - 8);      /* Select OPL4 ID register */
+         outb ((0x02), ioaddr - 8);    /* Select OPL4 ID register */
          tenmicrosec (devc->osp);
          tmp = inb (ioaddr - 7);       /* Read it */
          tenmicrosec (devc->osp);
@@ -278,9 +244,9 @@ opl3_detect (int ioaddr, int *osp)
            {
              detected_model = 4;
 
-             outb (0xF8, ioaddr - 8);  /* Select OPL4 FM mixer control */
+             outb ((0xF8), ioaddr - 8);        /* Select OPL4 FM mixer control */
              tenmicrosec (devc->osp);
-             outb (0x1B, ioaddr - 7);  /* Write value */
+             outb ((0x1B), ioaddr - 7);        /* Write value */
              tenmicrosec (devc->osp);
            }
          else
@@ -297,7 +263,7 @@ opl3_detect (int ioaddr, int *osp)
                                                 */
 
   opl3_command (ioaddr, TEST_REGISTER, ENABLE_WAVE_SELECT);
-  opl3_command (ioaddr, PERCUSSION_REGISTER, 0x00);    /*
+  opl3_command (ioaddr, PERCOSSION_REGISTER, 0x00);    /*
                                                         * Melodic mode.
                                                         */
 
@@ -326,9 +292,8 @@ opl3_kill_note (int devno, int voice, int note, int velocity)
   devc->voc[voice].keyon_byte = 0;
   devc->voc[voice].bender = 0;
   devc->voc[voice].volume = 64;
-  devc->voc[voice].bender_range = 200; /*
-                                        * 200 cents = 2 semitones
-                                        */
+  devc->voc[voice].panning = 0xffff;   /* Not set */
+  devc->voc[voice].bender_range = 200;
   devc->voc[voice].orig_freq = 0;
   devc->voc[voice].current_freq = 0;
   devc->voc[voice].mode = 0;
@@ -362,7 +327,7 @@ opl3_set_instr (int dev, int voice, int instr_no)
     return 0;
 
   if (instr_no < 0 || instr_no >= SBFM_MAXINSTR)
-    return 0;
+    instr_no = 0;              /* Acoustic piano (usually) */
 
   devc->act_i[voice] = &devc->i_map[instr_no];
   return 0;
@@ -512,7 +477,7 @@ static int
 opl3_start_note (int dev, int voice, int note, int volume)
 {
   unsigned char   data, fpc;
-  int             block, fnum, freq, voice_mode;
+  int             block, fnum, freq, voice_mode, pan;
   struct sbi_instrument *instr;
   struct physical_voice_info *map;
 
@@ -520,6 +485,7 @@ opl3_start_note (int dev, int voice, int note, int volume)
     return 0;
 
   map = &pv_map[devc->lv_map[voice]];
+  pan = devc->voc[voice].panning;
 
   if (map->voice_mode == 0)
     return 0;
@@ -626,6 +592,19 @@ opl3_start_note (int dev, int voice, int note, int volume)
    * Set Feedback/Connection
    */
   fpc = instr->operators[10];
+
+  if (pan != 0xffff)
+    {
+      fpc &= ~STEREO_BITS;
+
+      if (pan < -64)
+       fpc |= VOICE_TO_LEFT;
+      else if (pan > 64)
+       fpc |= VOICE_TO_RIGHT;
+      else
+       fpc |= (VOICE_TO_LEFT | VOICE_TO_RIGHT);
+    }
+
   if (!(fpc & 0x30))
     fpc |= 0x30;               /*
                                 * Ensure that at least one chn is enabled
@@ -761,7 +740,7 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
    * register. The OPL-3 survives with just two INBs
    */
 
-  outb ((unsigned char) (addr & 0xff), io_addr);
+  outb (((unsigned char) (addr & 0xff)), io_addr);
 
   if (!devc->model != 2)
     tenmicrosec (devc->osp);
@@ -769,7 +748,7 @@ opl3_command (int io_addr, unsigned int addr, unsigned int val)
     for (i = 0; i < 2; i++)
       inb (io_addr);
 
-  outb ((unsigned char) (val & 0xff), io_addr + 1);
+  outb (((unsigned char) (val & 0xff)), io_addr + 1);
 
   if (devc->model != 2)
     {
@@ -827,7 +806,7 @@ opl3_open (int dev, int mode)
   int             i;
 
   if (devc->busy)
-    return -(EBUSY);
+    return -EBUSY;
   devc->busy = 1;
 
   devc->v_alloc->max_voice = devc->nr_voice = (devc->model == 2) ? 18 : 9;
@@ -873,7 +852,7 @@ opl3_load_patch (int dev, int format, const char *addr,
   if (count < sizeof (ins))
     {
       printk ("FM Error: Patch record too short\n");
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   copy_from_user (&((char *) &ins)[offs], &(addr)[offs], sizeof (ins) - offs);
@@ -881,7 +860,7 @@ opl3_load_patch (int dev, int format, const char *addr,
   if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
     {
       printk ("FM Error: Invalid instrument number %d\n", ins.channel);
-      return -(EINVAL);
+      return -EINVAL;
     }
   ins.key = format;
 
@@ -889,8 +868,9 @@ opl3_load_patch (int dev, int format, const char *addr,
 }
 
 static void
-opl3_panning (int dev, int voice, int pressure)
+opl3_panning (int dev, int voice, int value)
 {
+  devc->voc[voice].panning = value;
 }
 
 static void
@@ -1004,14 +984,7 @@ bend_pitch (int dev, int voice, int value)
                                 */
   opl3_command (map->ioaddr, FNUM_LOW + map->voice_num, data);
 
-  data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);    /*
-                                                                * *
-                                                                * KEYON|OCTAVE|MS
-                                                                *
-                                                                * * bits * *
-                                                                * of * f-num
-                                                                *
-                                                                */
+  data = 0x20 | ((block & 0x7) << 2) | ((fnum >> 8) & 0x3);
   devc->voc[voice].keyon_byte = data;
   opl3_command (map->ioaddr, KEYON_BLOCK + map->voice_num, data);
 }
@@ -1035,13 +1008,17 @@ opl3_controller (int dev, int voice, int ctrl_num, int value)
     case CTL_MAIN_VOLUME:
       devc->voc[voice].volume = value / 128;
       break;
+
+    case CTL_PAN:
+      devc->voc[voice].panning = (value * 2) - 128;
+      break;
     }
 }
 
 static int
 opl3_patchmgr (int dev, struct patmgr_info *rec)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -1132,6 +1109,7 @@ opl3_setup_voice (int dev, int voice, int chn)
   devc->voc[voice].bender = info->bender_value;
   devc->voc[voice].volume =
     info->controllers[CTL_MAIN_VOLUME];
+  devc->voc[voice].panning = (info->controllers[CTL_PAN] * 2) - 128;
 }
 
 static struct synth_operations opl3_operations =
index a3813964982bc3e6e008fc80e803db8b14104d3d..ae1234b442dac279cb3d20479742125e9b41bdaf 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 #define   COMPOSITE_SINE_WAVE_MODE     0x80            /* Don't use with OPL-3? */
 #define   KEYBOARD_SPLIT               0x40
 
-#define PERCUSSION_REGISTER                    0xbd    /* Left side only */
+#define PERCOSSION_REGISTER                    0xbd    /* Left side only */
 #define   TREMOLO_DEPTH                        0x80
 #define   VIBRATO_DEPTH                        0x40
-#define          PERCUSSION_ENABLE             0x20
+#define          PERCOSSION_ENABLE             0x20
 #define   BASSDRUM_ON                  0x10
 #define   SNAREDRUM_ON                 0x08
 #define   TOMTOM_ON                    0x04
index 448bc5e9b52f7b694d9f9ff669d07037b8a39cb9..04a79fbbd5633d5b561d7a288df79bc6fcffbac7 100644 (file)
@@ -1,8 +1,3 @@
-
-#define ALLOW_SELECT
-#undef NO_INLINE_ASM
-#define SHORT_BANNERS
-
 #ifdef MODULE
 #define __NO_VERSION__
 #include <linux/module.h>
@@ -20,7 +15,7 @@
 #include <linux/sched.h>
 #include <linux/ctype.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/dma.h>
 #include <linux/wait.h>
@@ -38,7 +33,7 @@
 #define TRUE   1
 
 struct snd_wait {
-         int flags;
+         int opts;
        };
 
 extern int sound_alloc_dma(int chn, char *deviceID);
@@ -46,11 +41,5 @@ extern int sound_open_dma(int chn, char *deviceID);
 extern void sound_free_dma(int chn);
 extern void sound_close_dma(int chn);
 
-#define RUNTIME_DMA_ALLOC
-
 extern caddr_t sound_mem_blocks[1024];
 extern int sound_nblocks;
-
-#undef PSEUDO_DMA_AUTOINIT
-#define ALLOW_BUFFER_MAPPING
-
index 1d324d8720985e99d3a3e0d6ebcaf76e25bd82b9..be5a169ca1c314aa7b318b4b5c2caf6e1450221a 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <linux/config.h>
-
 #include "sound_config.h"
 
 #if defined(CONFIG_PAS)
@@ -30,7 +29,6 @@ static int      pas_intr_mask = 0;
 static int      pas_irq = 0;
 static int      pas_sb_base = 0;
 
-int            *pas_osp;
 
 char            pas_model;
 static char    *pas_model_names[] =
@@ -52,7 +50,7 @@ pas_read (int ioaddr)
 void
 pas_write (unsigned char data, int ioaddr)
 {
-  outb (data, ioaddr ^ translate_code);
+  outb ((data), ioaddr ^ translate_code);
 }
 
 /******************* Begin of the Interrupt Handler ********************/
@@ -203,8 +201,8 @@ config_pas_hw (struct address_info *hw_config)
      * as per Media Vision.  Only define this if your PAS doesn't work correctly.
    */
 #ifdef SYMPHONY_PAS
-  outb (0x05, 0xa8);
-  outb (0x60, 0xa9);
+  outb ((0x05), 0xa8);
+  outb ((0x60), 0xa9);
 #endif
 
 #ifdef BROKEN_BUS_CLOCK
@@ -282,8 +280,8 @@ detect_pas_hw (struct address_info *hw_config)
    * you have something on base port 0x388. SO be forewarned.
    */
 
-  outb (0xBC, 0x9A01);         /* Activate first board */
-  outb (hw_config->io_base >> 2, 0x9A01);      /* Set base address */
+  outb ((0xBC), 0x9A01);       /* Activate first board */
+  outb ((hw_config->io_base >> 2), 0x9A01);    /* Set base address */
   translate_code = 0x388 ^ hw_config->io_base;
   pas_write (1, 0xBF88);       /* Select one wait states */
 
@@ -318,7 +316,6 @@ void
 attach_pas_card (struct address_info *hw_config)
 {
   pas_irq = hw_config->irq;
-  pas_osp = hw_config->osp;
 
   if (detect_pas_hw (hw_config))
     {
@@ -359,7 +356,6 @@ attach_pas_card (struct address_info *hw_config)
 int
 probe_pas (struct address_info *hw_config)
 {
-  pas_osp = hw_config->osp;
   return detect_pas_hw (hw_config);
 }
 
index b1d4315921f0c43d572ba2deb87d4d67269bbb5c..974443c9611cd5254b821916541ce55704ea9a76 100644 (file)
@@ -4,15 +4,13 @@
  * The low level driver for the PAS Midi Interface.
  */
 
-#include <linux/config.h>
-
 #include "sound_config.h"
+#include <linux/config.h>
 
 #if defined(CONFIG_PAS) && defined(CONFIG_MIDI)
 
 static int      midi_busy = 0, input_opened = 0;
 static int      my_dev;
-static volatile int ofifo_bytes = 0;
 
 static unsigned char tmp_queue[256];
 static volatile int qlen;
@@ -34,7 +32,7 @@ pas_midi_open (int dev, int mode,
   if (midi_busy)
     {
       printk ("PAS2: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   /*
@@ -59,29 +57,22 @@ pas_midi_open (int dev, int mode,
 
   if (mode == OPEN_READ || mode == OPEN_READWRITE)
     {
-      ctrl |= 0x04;            /*
-                                  * Enable input
-                                */
+      ctrl |= 0x04;            /* Enable input */
       input_opened = 1;
     }
 
   if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
     {
-      ctrl |= 0x08 |           /*
-                                  * Enable output
-                                */
-       0x10;
+      ctrl |= 0x08 | 0x10;     /* Enable output */
     }
 
-  pas_write (ctrl,
-            0x178b);
+  pas_write (ctrl, 0x178b);
 
   /*
    * Acknowledge any pending interrupts
    */
 
   pas_write (0xff, 0x1B88);
-  ofifo_bytes = 0;
 
   restore_flags (flags);
 
@@ -110,18 +101,19 @@ dump_to_midi (unsigned char midi_byte)
 
   fifo_space = ((x = pas_read (0x1B89)) >> 4) & 0x0f;
 
-  if (fifo_space == 15 || (fifo_space < 2 && ofifo_bytes > 13))                /*
-                                                                          * Fifo
-                                                                          * full
-                                                                        */
+/*
+ * The MIDI FIFO space register and it's documentation is nonunderstandable.
+ * There seem to be no way to differentiate between buffer full and buffer
+ * empty situations. For this reason we don't never write the buffer
+ * completely full. In this way we can assume that 0 (or is it 15)
+ * means that the buffer is empty.
+ */
+
+  if (fifo_space < 2 && fifo_space != 0)       /* Full (almost) */
     {
-      return 0;                        /*
-                                * Upper layer will call again
-                                */
+      return 0;                        /* Ask upper layers to retry after some time */
     }
 
-  ofifo_bytes++;
-
   pas_write (midi_byte, 0x178A);
 
   return 1;
@@ -154,18 +146,14 @@ pas_midi_out (int dev, unsigned char midi_byte)
 
   if (!qlen)
     if (dump_to_midi (midi_byte))
-      return 1;                        /*
-                                * OK
-                                */
+      return 1;
 
   /*
    * Put to the local queue
    */
 
   if (qlen >= 256)
-    return 0;                  /*
-                                * Local queue full
-                                */
+    return 0;                  /* Local queue full */
 
   save_flags (flags);
   cli ();
@@ -194,13 +182,12 @@ pas_midi_end_read (int dev)
 static int
 pas_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
 pas_midi_kick (int dev)
 {
-  ofifo_bytes = 0;
 }
 
 static int
@@ -225,9 +212,7 @@ static struct midi_operations pas_midi_operations =
   pas_midi_start_read,
   pas_midi_end_read,
   pas_midi_kick,
-  NULL,                                /*
-                                * command
-                                */
+  NULL,
   pas_buffer_status,
   NULL
 };
@@ -254,13 +239,9 @@ pas_midi_interrupt (void)
 
   stat = pas_read (0x1B88);
 
-  if (stat & 0x04)             /*
-                                  * Input byte available
-                                */
+  if (stat & 0x04)             /* Input data available */
     {
-      incount = pas_read (0x1B89) & 0x0f;      /*
-                                                  * Input FIFO count
-                                                */
+      incount = pas_read (0x1B89) & 0x0f;      /* Input FIFO size */
       if (!incount)
        incount = 16;
 
@@ -270,22 +251,11 @@ pas_midi_interrupt (void)
            midi_input_intr (my_dev, pas_read (0x178A));
          }
        else
-         pas_read (0x178A);    /*
-                                * Flush
-                                */
+         pas_read (0x178A);    /* Flush */
     }
 
   if (stat & (0x08 | 0x10))
     {
-      if (!(stat & 0x08))
-       {
-         ofifo_bytes = 8;
-       }
-      else
-       {
-         ofifo_bytes = 0;
-       }
-
       save_flags (flags);
       cli ();
 
@@ -301,13 +271,10 @@ pas_midi_interrupt (void)
 
   if (stat & 0x40)
     {
-      printk ("MIDI output overrun %x,%x,%d \n", pas_read (0x1B89), stat, ofifo_bytes);
-      ofifo_bytes = 100;
+      printk ("MIDI output overrun %x,%x\n", pas_read (0x1B89), stat);
     }
 
-  pas_write (stat, 0x1B88);    /*
-                                  * Acknowledge interrupts
-                                */
+  pas_write (stat, 0x1B88);    /* Acknowledge interrupts */
 }
 
 #endif
index bcc9326ea9bb16916b048ee03a4e0137b9511fff..0e05d9b8bd3e571737f5f1068b3b2c405240a35d 100644 (file)
@@ -5,9 +5,8 @@
  *
  * Mixer routines for the Pro Audio Spectrum cards.
  */
-   
-#include <linux/config.h>
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #if defined(CONFIG_PAS)
@@ -31,8 +30,9 @@ static int      mode_control = 0;
                                         SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \
                                         SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV)
 
+static int     *levels;
 
-static unsigned short levels[SOUND_MIXER_NRDEVICES] =
+static int      default_levels[32] =
 {
   0x3232,                      /* Master Volume */
   0x3232,                      /* Bass */
@@ -62,7 +62,7 @@ mix_write (unsigned char data, int ioaddr)
   if (pas_model == 4)
     {
       outw (data | (data << 8), (ioaddr ^ translate_code) - 1);
-      outb (0x80, 0);
+      outb ((0x80), 0);
     }
   else
     pas_write (data, ioaddr);
@@ -190,7 +190,7 @@ pas_mixer_set (int whichDev, unsigned int level)
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   return (levels[whichDev]);
@@ -218,14 +218,16 @@ pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 
   if (cmd == SOUND_MIXER_PRIVATE1)     /* Set loudness bit */
     {
-      int             level = get_user ((int *) arg);
+      int             level;
+
+      get_user (level, (int *) arg);
 
       if (level == -1)         /* Return current settings */
        {
          if (mode_control & 0x04)
-           return snd_ioctl_return ((int *) arg, 1);
+           return ioctl_out (arg, 1);
          else
-           return snd_ioctl_return ((int *) arg, 0);
+           return ioctl_out (arg, 0);
        }
       else
        {
@@ -233,20 +235,22 @@ pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
          if (level)
            mode_control |= 0x04;
          set_mode (mode_control);
-         return snd_ioctl_return ((int *) arg, !!level);       /* 0 or 1 */
+         return ioctl_out (arg, !!level);      /* 0 or 1 */
        }
     }
 
 
   if (cmd == SOUND_MIXER_PRIVATE2)     /* Set enhance bit */
     {
-      int             level = get_user ((int *) arg);
+      int             level;
+
+      get_user (level, (int *) arg);
 
       if (level == -1)         /* Return current settings */
        {
          if (!(mode_control & 0x03))
-           return snd_ioctl_return ((int *) arg, 0);
-         return snd_ioctl_return ((int *) arg, ((mode_control & 0x03) + 1) * 20);
+           return ioctl_out (arg, 0);
+         return ioctl_out (arg, ((mode_control & 0x03) + 1) * 20);
        }
       else
        {
@@ -269,13 +273,13 @@ pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 
   if (cmd == SOUND_MIXER_PRIVATE3)     /* Set mute bit */
     {
-      int             level = get_user ((int *) arg);
+      int             level;
+
+      get_user (level, (int *) arg);
 
       if (level == -1)         /* Return current settings */
        {
-         return snd_ioctl_return ((int *) arg,
-                                  !(pas_read (0x0B8A) &
-                                    0x20));
+         return ioctl_out (arg, !(pas_read (0x0B8A) & 0x20));
        }
       else
        {
@@ -293,7 +297,7 @@ pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
   if (((cmd >> 8) & 0xff) == 'M')
     {
       if (_IOC_DIR (cmd) & _IOC_WRITE)
-       return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_user ((int *) arg)));
+       return ioctl_out (arg, pas_mixer_set (cmd & 0xff, ioctl_in (arg)));
       else
        {                       /*
                                 * Read parameters
@@ -303,32 +307,32 @@ pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
            {
 
            case SOUND_MIXER_RECSRC:
-             return snd_ioctl_return ((int *) arg, rec_devices);
+             return ioctl_out (arg, rec_devices);
              break;
 
            case SOUND_MIXER_STEREODEVS:
-             return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
+             return ioctl_out (arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
              break;
 
            case SOUND_MIXER_DEVMASK:
-             return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES);
+             return ioctl_out (arg, SUPPORTED_MIXER_DEVICES);
              break;
 
            case SOUND_MIXER_RECMASK:
-             return snd_ioctl_return ((int *) arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
+             return ioctl_out (arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
              break;
 
            case SOUND_MIXER_CAPS:
-             return snd_ioctl_return ((int *) arg, 0);         /* No special capabilities */
+             return ioctl_out (arg, 0);        /* No special capabilities */
              break;
 
 
            default:
-             return snd_ioctl_return ((int *) arg, levels[cmd & 0xff]);
+             return ioctl_out (arg, levels[cmd & 0xff]);
            }
        }
     }
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static struct mixer_operations pas_mixer_operations =
@@ -341,6 +345,8 @@ static struct mixer_operations pas_mixer_operations =
 int
 pas_init_mixer (void)
 {
+  levels = load_mixer_volumes ("PAS16_1", default_levels, 1);
+
   pas_mixer_reset ();
 
   if (num_mixers < MAX_MIXER_DEV)
index a107d2c3d8a5dda3b06ae72eb88de24e8ea81dcd..11639299f27ea99d73a2330e3d72449ce7b91626 100644 (file)
@@ -4,9 +4,8 @@
  *
  * The low level driver for the Pro Audio Spectrum ADC/DAC.
  */
-   
-#include <linux/config.h>
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #if defined(CONFIG_PAS) && defined(CONFIG_AUDIO)
@@ -42,7 +41,7 @@ pcm_set_speed (int arg)
   unsigned long   flags;
 
   if (arg == 0)
-     return pcm_speed;
+    return pcm_speed;
 
   if (arg > 44100)
     arg = 44100;
@@ -131,7 +130,7 @@ int
 pcm_set_bits (int arg)
 {
   if (arg == 0)
-     return pcm_bits;
+    return pcm_bits;
 
   if ((arg & pcm_bitsok) != arg)
     return pcm_bits;
@@ -156,61 +155,61 @@ pas_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
     case SOUND_PCM_WRITE_RATE:
       if (local)
        return pcm_set_speed ((int) arg);
-      return snd_ioctl_return ((int *) arg, pcm_set_speed (get_user ((int *) arg)));
+      return ioctl_out (arg, pcm_set_speed (ioctl_in (arg)));
       break;
 
     case SOUND_PCM_READ_RATE:
       if (local)
        return pcm_speed;
-      return snd_ioctl_return ((int *) arg, pcm_speed);
+      return ioctl_out (arg, pcm_speed);
       break;
 
     case SNDCTL_DSP_STEREO:
       if (local)
        return pcm_set_channels ((int) arg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, pcm_set_channels (get_user ((int *) arg) + 1) - 1);
+      return ioctl_out (arg, pcm_set_channels (ioctl_in (arg) + 1) - 1);
       break;
 
     case SOUND_PCM_WRITE_CHANNELS:
       if (local)
        return pcm_set_channels ((int) arg);
-      return snd_ioctl_return ((int *) arg, pcm_set_channels (get_user ((int *) arg)));
+      return ioctl_out (arg, pcm_set_channels (ioctl_in (arg)));
       break;
 
     case SOUND_PCM_READ_CHANNELS:
       if (local)
        return pcm_channels;
-      return snd_ioctl_return ((int *) arg, pcm_channels);
+      return ioctl_out (arg, pcm_channels);
       break;
 
     case SNDCTL_DSP_SETFMT:
       if (local)
        return pcm_set_bits ((int) arg);
-      return snd_ioctl_return ((int *) arg, pcm_set_bits (get_user ((int *) arg)));
+      return ioctl_out (arg, pcm_set_bits (ioctl_in (arg)));
       break;
 
     case SOUND_PCM_READ_BITS:
       if (local)
        return pcm_bits;
-      return snd_ioctl_return ((int *) arg, pcm_bits);
+      return ioctl_out (arg, pcm_bits);
 
     case SOUND_PCM_WRITE_FILTER:       /*
                                         * NOT YET IMPLEMENTED
                                         */
-      if (get_user ((int *) arg) > 1)
-       return -(EINVAL);
-      pcm_filter = get_user ((int *) arg);
+      if (ioctl_in (arg) > 1)
+       return -EINVAL;
+      pcm_filter = ioctl_in (arg);
       break;
 
     case SOUND_PCM_READ_FILTER:
-      return snd_ioctl_return ((int *) arg, pcm_filter);
+      return ioctl_out (arg, pcm_filter);
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -234,7 +233,7 @@ pas_audio_open (int dev, int mode)
   if (pcm_busy)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   pcm_busy = 1;
index 700adfbbaeef5d59f3e528abf5ad80b945c10c1e..95c49dc31aef91948c41ed5c9ec4aa4439929e59 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -18,7 +18,7 @@
 
 #if defined(CONFIG_SEQUENCER)
 
-static wait_handle *server_procs[MAX_SYNTH_DEV] =
+static struct wait_queue *server_procs[MAX_SYNTH_DEV] =
 {NULL};
 static volatile struct snd_wait server_wait_flag[MAX_SYNTH_DEV] =
 {
@@ -35,7 +35,7 @@ static int      pmgr_opened[MAX_SYNTH_DEV] =
 #define A_TO_S 1
 #define S_TO_A         2
 
-static wait_handle *appl_proc = NULL;
+static struct wait_queue *appl_proc = NULL;
 static volatile struct snd_wait appl_wait_flag =
 {0};
 
@@ -43,13 +43,13 @@ int
 pmgr_open (int dev)
 {
   if (dev < 0 || dev >= num_synths)
-    return -(ENXIO);
+    return -ENXIO;
 
   if (pmgr_opened[dev])
-    return -(EBUSY);
+    return -EBUSY;
   pmgr_opened[dev] = 1;
 
-  server_wait_flag[dev].flags = WK_NONE;
+  server_wait_flag[dev].opts = WK_NONE;
 
   return 0;
 }
@@ -64,12 +64,12 @@ pmgr_release (int dev)
     {
 
       mbox[dev]->key = PM_ERROR;
-      mbox[dev]->parm1 = -(EIO);
+      mbox[dev]->parm1 = -EIO;
 
-      if ((appl_wait_flag.flags & WK_SLEEP))
+      if ((appl_wait_flag.opts & WK_SLEEP))
        {
-         appl_wait_flag.flags = WK_WAKEUP;
-         module_wake_up (&appl_proc);
+         appl_wait_flag.opts = WK_WAKEUP;
+         wake_up (&appl_proc);
        };
     }
 
@@ -85,26 +85,30 @@ pmgr_read (int dev, struct fileinfo *file, char *buf, int count)
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid read count\n", dev);
-      return -(EIO);
+      return -EIO;
     }
 
-  while (!ok && !current_got_fatal_signal ())
+  while (!ok && !(current->signal & ~current->blocked))
     {
       save_flags (flags);
       cli ();
 
       while (!(mbox[dev] && msg_direction[dev] == A_TO_S) &&
-            !current_got_fatal_signal ())
+            !(current->signal & ~current->blocked))
        {
 
-         server_wait_flag[dev].flags = WK_SLEEP;
-         module_interruptible_sleep_on (&server_procs[dev]);
-         server_wait_flag[dev].flags &= ~WK_SLEEP;;
+         server_wait_flag[dev].opts = WK_SLEEP;
+         interruptible_sleep_on (&server_procs[dev]);
+         server_wait_flag[dev].opts &= ~WK_SLEEP;;
        }
 
       if (mbox[dev] && msg_direction[dev] == A_TO_S)
        {
-         copy_to_user (&(buf)[0], (char *) mbox[dev], count);
+         {
+           char           *fixit = (char *) mbox[dev];
+
+           copy_to_user (&(buf)[0], fixit, count);
+         };
          msg_direction[dev] = 0;
          ok = 1;
        }
@@ -114,7 +118,7 @@ pmgr_read (int dev, struct fileinfo *file, char *buf, int count)
     }
 
   if (!ok)
-    return -(EINTR);
+    return -EINTR;
   return count;
 }
 
@@ -126,7 +130,7 @@ pmgr_write (int dev, struct fileinfo *file, const char *buf, int count)
   if (count < 4)
     {
       printk ("PATMGR%d: Write count < 4\n", dev);
-      return -(EIO);
+      return -EIO;
     }
 
   copy_from_user ((char *) mbox[dev], &(buf)[0], 4);
@@ -137,7 +141,7 @@ pmgr_write (int dev, struct fileinfo *file, const char *buf, int count)
 
       tmp_dev = ((unsigned short *) mbox[dev])[2];
       if (tmp_dev != dev)
-       return -(ENXIO);
+       return -ENXIO;
 
       return synth_devs[dev]->load_patch (dev, *(unsigned short *) mbox[dev],
                                          buf, 4, count, 1);
@@ -146,7 +150,7 @@ pmgr_write (int dev, struct fileinfo *file, const char *buf, int count)
   if (count != sizeof (struct patmgr_info))
     {
       printk ("PATMGR%d: Invalid write count\n", dev);
-      return -(EIO);
+      return -EIO;
     }
 
   /*
@@ -162,11 +166,11 @@ pmgr_write (int dev, struct fileinfo *file, const char *buf, int count)
       copy_from_user (&((char *) mbox[dev])[4], &(buf)[4], count - 4);
       msg_direction[dev] = S_TO_A;
 
-      if ((appl_wait_flag.flags & WK_SLEEP))
+      if ((appl_wait_flag.opts & WK_SLEEP))
        {
          {
-           appl_wait_flag.flags = WK_WAKEUP;
-           module_wake_up (&appl_proc);
+           appl_wait_flag.opts = WK_WAKEUP;
+           wake_up (&appl_proc);
          };
        }
     }
@@ -193,23 +197,23 @@ pmgr_access (int dev, struct patmgr_info *rec)
       mbox[dev] = rec;
       msg_direction[dev] = A_TO_S;
 
-      if ((server_wait_flag[dev].flags & WK_SLEEP))
+      if ((server_wait_flag[dev].opts & WK_SLEEP))
        {
          {
-           server_wait_flag[dev].flags = WK_WAKEUP;
-           module_wake_up (&server_procs[dev]);
+           server_wait_flag[dev].opts = WK_WAKEUP;
+           wake_up (&server_procs[dev]);
          };
        }
 
 
-      appl_wait_flag.flags = WK_SLEEP;
-      module_interruptible_sleep_on (&appl_proc);
-      appl_wait_flag.flags &= ~WK_SLEEP;;
+      appl_wait_flag.opts = WK_SLEEP;
+      interruptible_sleep_on (&appl_proc);
+      appl_wait_flag.opts &= ~WK_SLEEP;;
 
       if (msg_direction[dev] != S_TO_A)
        {
          rec->key = PM_ERROR;
-         rec->parm1 = -(EIO);
+         rec->parm1 = -EIO;
        }
       else if (rec->key == PM_ERROR)
        {
@@ -263,18 +267,18 @@ pmgr_inform (int dev, int event, unsigned long p1, unsigned long p2,
       mbox[dev]->parm3 = p3;
       msg_direction[dev] = A_TO_S;
 
-      if ((server_wait_flag[dev].flags & WK_SLEEP))
+      if ((server_wait_flag[dev].opts & WK_SLEEP))
        {
          {
-           server_wait_flag[dev].flags = WK_WAKEUP;
-           module_wake_up (&server_procs[dev]);
+           server_wait_flag[dev].opts = WK_WAKEUP;
+           wake_up (&server_procs[dev]);
          };
        }
 
 
-      appl_wait_flag.flags = WK_SLEEP;
-      module_interruptible_sleep_on (&appl_proc);
-      appl_wait_flag.flags &= ~WK_SLEEP;;
+      appl_wait_flag.opts = WK_SLEEP;
+      interruptible_sleep_on (&appl_proc);
+      appl_wait_flag.opts &= ~WK_SLEEP;;
       mbox[dev] = NULL;
       msg_direction[dev] = 0;
     }
index 86104338f7dd4bf3d7b049c623935bbf315ac84f..f7b36e50110133b8e2e56265cc07c090b50ad678 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -74,6 +74,31 @@ static pss_confdata *devc = &pss_data;
 static int      pss_initialized = 0;
 static int      nonstandard_microcode = 0;
 
+static void
+pss_write (int data)
+{
+  int             i, limit;
+
+  limit = jiffies + 10;                /* The timeout is 0.1 seconds */
+  /*
+   * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
+   * called while interrupts are disabled. This means that the timer is
+   * disabled also. However the timeout situation is a abnormal condition.
+   * Normally the DSP should be ready to accept commands after just couple of
+   * loops.
+   */
+
+  for (i = 0; i < 5000000 && jiffies < limit; i++)
+    {
+      if (inw (devc->base + PSS_STATUS) & PSS_WRITE_EMPTY)
+       {
+         outw (devc->base + PSS_DATA, data);
+         return;
+       }
+    }
+  printk ("PSS: DSP Command (%04x) Timeout.\n", data);
+}
+
 int
 probe_pss (struct address_info *hw_config)
 {
@@ -354,6 +379,22 @@ attach_pss (struct address_info *hw_config)
   conf_printf (tmp, hw_config);
 }
 
+static void
+pss_init_speaker (void)
+{
+/* Don't ask what are these commands. I really don't know */
+  pss_write (0x0010);
+  pss_write (0x0000 | 252);    /* Left master volume */
+  pss_write (0x0010);
+  pss_write (0x0100 | 252);    /* Right master volume */
+  pss_write (0x0010);
+  pss_write (0x0200 | 246);    /* Bass */
+  pss_write (0x0010);
+  pss_write (0x0300 | 246);    /* Treble */
+  pss_write (0x0010);
+  pss_write (0x0800 | 0x00ce); /* Stereo switch? */
+}
+
 int
 probe_pss_mpu (struct address_info *hw_config)
 {
@@ -392,6 +433,8 @@ probe_pss_mpu (struct address_info *hw_config)
       return 0;
     }
 
+  pss_init_speaker ();
+
 /*
  * Finally wait until the DSP algorithm has initialized itself and
  * deactivates receive interrupt.
@@ -422,14 +465,14 @@ pss_coproc_open (void *dev_info, int sub_device)
       if (pss_synthLen == 0)
        {
          printk ("PSS: MIDI synth microcode not available.\n");
-         return -(EIO);
+         return -EIO;
        }
 
       if (nonstandard_microcode)
        if (!pss_download_boot (devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
          {
            printk ("PSS: Unable to load MIDI synth microcode to DSP.\n");
-           return -(EIO);
+           return -EIO;
          }
       nonstandard_microcode = 0;
       break;
@@ -460,12 +503,12 @@ static int
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!pss_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("PSS: Unable to load microcode block to DSP.\n");
-      return -(EIO);
+      return -EIO;
     }
   nonstandard_microcode = 1;   /* The MIDI microcode has been overwritten */
 
@@ -491,7 +534,7 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
 
        buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
        if (buf == NULL)
-         return -(ENOSPC);
+         return -ENOSPC;
 
        copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
        err = download_boot_block (dev_info, buf);
@@ -509,7 +552,7 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
 
        buf = (copr_msg *) vmalloc (sizeof (copr_msg));
        if (buf == NULL)
-         return -(ENOSPC);
+         return -ENOSPC;
 
        copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 
@@ -524,9 +567,13 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
              {
                restore_flags (flags);
                buf->len = i;   /* feed back number of WORDs sent */
-               copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+               {
+                 char           *fixit = (char *) buf;
+
+                 copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+               };
                vfree (buf);
-               return -(EIO);
+               return -EIO;
              }
          }
 
@@ -548,7 +595,7 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
 
        buf = (copr_msg *) vmalloc (sizeof (copr_msg));
        if (buf == NULL)
-         return -(ENOSPC);
+         return -ENOSPC;
 
 
        data = (unsigned short *) buf->data;
@@ -562,14 +609,18 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
            if (!pss_get_dspword (devc, data++))
              {
                if (i == 0)
-                 err = -(EIO);
+                 err = -EIO;
                break;
              }
          }
 
        restore_flags (flags);
 
-       copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+       {
+         char           *fixit = (char *) buf;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+       };
        vfree (buf);
 
        return err;
@@ -590,25 +641,29 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
        if (!pss_put_dspword (devc, 0x00d0))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        if (!pss_get_dspword (devc, &tmp))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        buf.parm1 = tmp;
        restore_flags (flags);
 
-       copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+       {
+         char           *fixit = (char *) &buf;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (buf));
+       };
        return 0;
       }
       break;
@@ -626,20 +681,20 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
        if (!pss_put_dspword (devc, 0x00d1))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        tmp = (unsigned int) buf.parm2 & 0xffff;
        if (!pss_put_dspword (devc, tmp))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        restore_flags (flags);
@@ -660,27 +715,27 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
        if (!pss_put_dspword (devc, 0x00d3))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        tmp = (unsigned int) buf.parm2 & 0x00ff;
        if (!pss_put_dspword (devc, tmp))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff;
        if (!pss_put_dspword (devc, tmp))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        restore_flags (flags);
@@ -701,19 +756,19 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
        if (!pss_put_dspword (devc, 0x00d2))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        if (!pss_put_dspword (devc, (unsigned short) (buf.parm1 & 0xffff)))
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        if (!pss_get_dspword (devc, &tmp))      /* Read MSB */
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        buf.parm1 = tmp << 8;
@@ -721,23 +776,27 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
        if (!pss_get_dspword (devc, &tmp))      /* Read LSB */
          {
            restore_flags (flags);
-           return -(EIO);
+           return -EIO;
          }
 
        buf.parm1 |= tmp & 0x00ff;
 
        restore_flags (flags);
 
-       copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
+       {
+         char           *fixit = (char *) &buf;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (buf));
+       };
        return 0;
       }
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static coproc_operations pss_coproc_operations =
@@ -769,7 +828,7 @@ attach_pss_mpu (struct address_info *hw_config)
 int
 probe_pss_mss (struct address_info *hw_config)
 {
-  int             timeout;
+  volatile int    timeout;
 
   if (!pss_initialized)
     return 0;
@@ -808,7 +867,11 @@ probe_pss_mss (struct address_info *hw_config)
        timeout < 100000 && (inb (hw_config->io_base + 3) & 0x3f) != 0x04;
        timeout++);
 
-  outb (0x0b, hw_config->io_base + 4); /* Required by some cards */
+  outb ((0x0b), hw_config->io_base + 4);       /* Required by some cards */
+
+  for (timeout = 0;
+       timeout < 100000;
+       timeout++);
   return probe_ms_sound (hw_config);
 }
 
index 40a415c14b374b381925a83e61daf3d7bb0aa586..fc43428779696598f908a71269e8971a22898f9b 100644 (file)
@@ -36,6 +36,7 @@
 #define MDL_SB201      3       /* SB2.01 */
 #define MDL_SBPRO      4       /* SB Pro */
 #define MDL_SB16       5       /* SB16/32/AWE */
+#define MDL_SBPNP      6       /* SB16/32/AWE PnP */
 #define MDL_JAZZ       10      /* Media Vision Jazz16 */
 #define MDL_SMW                11      /* Logitech SoundMan Wave (Jazz16) */
 #define MDL_ESS                12      /* ESS ES688 and ES1688 */
@@ -83,11 +84,12 @@ typedef struct sb_devc {
           volatile int intr_active, irq_mode;
 
        /* Mixer fields */
-          unsigned short levels[SOUND_MIXER_NRDEVICES];
+          int *levels;
           mixer_tab *iomap;
           int mixer_caps, recmask, supported_devices;
           int supported_rec_devices;
           int my_mixerdev;
+          int sbmixnum;
 
        /* Audio fields */
           unsigned long trg_buf;
index 47ba13e3478af57fc3a9a2ffaf1d077cecca83aa..650ce75ef54dcc551e00212d566f6b79bd40d1f4 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -29,13 +29,13 @@ sb_audio_open (int dev, int mode)
   if (devc == NULL)
     {
       printk ("SB: Incomplete initialization\n");
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (devc->caps & SB_NO_RECORDING && mode & OPEN_READ)
     {
       printk ("SB: Recording is not possible with this device\n");
-      return -(EPERM);
+      return -EPERM;
     }
 
   save_flags (flags);
@@ -43,14 +43,14 @@ sb_audio_open (int dev, int mode)
   if (devc->opened)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   if (devc->dma16 != -1 && devc->dma16 != devc->dma8)
     {
       if (sound_open_dma (devc->dma16, "Sound Blaster 16 bit"))
        {
-         return -(EBUSY);
+         return -EBUSY;
        }
     }
   devc->opened = mode;
@@ -541,7 +541,8 @@ sbpro_audio_set_channels (int dev, short channels)
     if (channels != devc->channels)
       {
        devc->channels = channels;
-       sbpro_audio_set_speed (dev, devc->speed);
+       if (devc->model == MDL_SBPRO)
+         sbpro_audio_set_speed (dev, devc->speed);
       }
   return devc->channels;
 }
@@ -578,6 +579,37 @@ jazz16_audio_set_speed (int dev, int speed)
  * ESS specific routines
  */
 
+static int
+ess_audio_set_speed (int dev, int speed)
+{
+  sb_devc        *devc = audio_devs[dev]->devc;
+  int             divider;
+
+  if (speed > 0)
+    {
+      if (speed < 5000)
+       speed = 4000;
+
+      if (speed > 48000)
+       speed = 48000;
+
+      if (speed > 22000)
+       {
+         divider = (795500 + speed / 2) / speed;
+         speed = (795500 + divider / 2) / divider;
+       }
+      else
+       {
+         divider = (397700 + speed / 2) / speed;
+         speed = (397700 + divider / 2) / divider;
+       }
+
+      devc->speed = speed;
+    }
+
+  return devc->speed;
+}
+
 static void
 ess_speed (sb_devc * devc)
 {
@@ -965,7 +997,7 @@ sb16_audio_trigger (int dev, int bits)
 static int
 sb_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -1122,7 +1154,7 @@ static struct audio_driver ess_audio_driver =     /* ESS ES688/1688 */
   NULL,
   NULL,
   ess_audio_trigger,
-  sb16_audio_set_speed,
+  ess_audio_set_speed,
   sb16_audio_set_bits,
   sbpro_audio_set_channels
 };
index f1a1276abc33258d501e37c06397558d4765c06d..7f87dd34a5503e3981391b19b43cf756b51c5def 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
index b5dda6f51181237b011f600a7fa1e937dfbced4a..dc6d0e7e75104d3325489f5f2fbff008a40e9df1 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -41,7 +41,7 @@ static int      jazz16_base = 0;      /* Not detected */
 static unsigned char jazz16_bits = 0;  /* I/O relocation bits */
 
 /*
- * Logitech SoundMan Wave specific initialization code
+ * Logitech Soundman Wave specific initialization code
  */
 
 #ifdef SMW_MIDI0001_INCLUDED
@@ -65,7 +65,7 @@ sb_dsp_command (sb_devc * devc, unsigned char val)
   /*
    * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes
    * called while interrupts are disabled. This means that the timer is
-   * disabled also. However the timeout situation is an abnormal condition.
+   * disabled also. However the timeout situation is a abnormal condition.
    * Normally the DSP should be ready to accept commands after just couple of
    * loops.
    */
@@ -74,7 +74,7 @@ sb_dsp_command (sb_devc * devc, unsigned char val)
     {
       if ((inb (DSP_STATUS) & 0x80) == 0)
        {
-         outb (val, DSP_COMMAND);
+         outb ((val), DSP_COMMAND);
          return 1;
        }
     }
@@ -192,12 +192,12 @@ sb_dsp_reset (sb_devc * devc)
   int             loopc;
 
   if (devc->model == MDL_ESS)
-    outb (3, DSP_RESET);       /* Reset FIFO too */
+    outb ((3), DSP_RESET);     /* Reset FIFO too */
   else
-    outb (1, DSP_RESET);
+    outb ((1), DSP_RESET);
 
   tenmicrosec (devc->osp);
-  outb (0, DSP_RESET);
+  outb ((0), DSP_RESET);
   tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
@@ -261,28 +261,31 @@ sb16_set_dma_hw (sb_devc * devc)
   return 1;
 }
 
+#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
 static void
-sb16_set_mpu_port(sb_devc *devc, struct address_info *hw_config)
+sb16_set_mpu_port (sb_devc * devc, struct address_info *hw_config)
 {
 /*
- * This routine initializes new MIDI port setup register of SB Vibra.
+ * This routine initializes new MIDI port setup register of SB Vibra (CT2502).
  */
-       unsigned char bits = sb_getmixer(devc, 0x84) & ~0x06;
-       switch (hw_config->io_base)
-       {
-       case 0x300:
-               sb_setmixer (devc, 0x84, bits | 0x04);
-               break;
+  unsigned char   bits = sb_getmixer (devc, 0x84) & ~0x06;
 
-       case 0x330:
-               sb_setmixer (devc, 0x84, bits | 0x00);
-               break;
+  switch (hw_config->io_base)
+    {
+    case 0x300:
+      sb_setmixer (devc, 0x84, bits | 0x04);
+      break;
 
-       default:
-               sb_setmixer (devc, 0x84, bits | 0x02); /* Disable MPU */
-               printk("SB16: Invalid MIDI I/O port %x\n", hw_config->io_base);
-       }
+    case 0x330:
+      sb_setmixer (devc, 0x84, bits | 0x00);
+      break;
+
+    default:
+      sb_setmixer (devc, 0x84, bits | 0x02);   /* Disable MPU */
+      printk ("SB16: Invalid MIDI I/O port %x\n", hw_config->io_base);
+    }
 }
+#endif
 
 static int
 sb16_set_irq_hw (sb_devc * devc, int level)
@@ -304,6 +307,8 @@ sb16_set_irq_hw (sb_devc * devc, int level)
       ival = 8;
       break;
     default:
+      if (devc->type == MDL_SBPNP)
+       return 1;
       printk ("SB16 IRQ%d is not possible\n", level);
       return 0;
     }
@@ -345,9 +350,9 @@ relocate_Jazz16 (sb_devc * devc, struct address_info *hw_config)
  */
   save_flags (flags);
   cli ();
-  outb (0xAF, 0x201);
-  outb (0x50, 0x201);
-  outb (bits, 0x201);
+  outb ((0xAF), 0x201);
+  outb ((0x50), 0x201);
+  outb ((bits), 0x201);
   restore_flags (flags);
 }
 
@@ -425,6 +430,7 @@ init_Jazz16 (sb_devc * devc, struct address_info *hw_config)
   return 1;
 }
 
+
 static int
 ess_init (sb_devc * devc, struct address_info *hw_config)
 {
@@ -466,9 +472,14 @@ ess_init (sb_devc * devc, struct address_info *hw_config)
     }
   else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
     {
+      char           *chip = "ES688";
+
+      if ((ess_minor & 0x0f) >= 8)
+       chip = "ES1688";
+
       sprintf (name,
-              "ESS ES1688 AudioDrive (rev %d)",
-              ess_minor & 0x0f);
+              "ESS %s AudioDrive (rev %d)",
+              chip, ess_minor & 0x0f);
     }
   else
     strcpy (name, "Jazz16");
@@ -570,7 +581,6 @@ sb_dsp_detect (struct address_info *hw_config)
 
   memset ((char *) &sb_info, 0, sizeof (sb_info));     /* Zero everything */
 
-  devc->osp = hw_config->osp;
   devc->type = hw_config->card_subtype;
 
   devc->base = hw_config->io_base;
@@ -592,6 +602,7 @@ sb_dsp_detect (struct address_info *hw_config)
     if (devc->major == 0 || (devc->major == 3 && devc->minor == 1))
       relocate_Jazz16 (devc, hw_config);
 
+
   if (!sb_dsp_reset (devc))
     {
       DDB (printk ("SB reset failed\n"));
@@ -642,16 +653,14 @@ void
 sb_dsp_init (struct address_info *hw_config)
 {
   sb_devc        *devc;
-  char            name[100];
-
-#ifndef NO_SB_IRQ_TEST
   int             n;
-#endif
+  char            name[100];
 
 /*
  * Check if we had detected a SB device earlier
  */
   DDB (printk ("sb_dsp_init(%x) entered\n", hw_config->io_base));
+  name[0] = 0;
 
   if (detected_devc == NULL)
     {
@@ -674,61 +683,64 @@ sb_dsp_init (struct address_info *hw_config)
   devc->dev = num_audiodevs;
   devc->caps = hw_config->driver_use_1;
 
-  if (snd_set_irq_handler (hw_config->irq,
-                          sbintr, "sound blaster", devc->osp) < 0)
-    {
-      printk ("SB: Can't allocate IRQ%d\n", hw_config->irq);
-      irq2devc[hw_config->irq] = NULL;
-      return;
-    }
+  if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) &&
+      hw_config->irq > 0)
+    {                          /* IRQ setup */
+      if (snd_set_irq_handler (hw_config->irq,
+                              sbintr, "soundblaster", devc->osp) < 0)
+       {
+         printk ("SB: Can't allocate IRQ%d\n", hw_config->irq);
+         return;
+       }
 
-  irq2devc[hw_config->irq] = devc;
-  devc->irq_ok = 0;
+      irq2devc[hw_config->irq] = devc;
+      devc->irq_ok = 0;
 
-  if (devc->major == 4)
-    if (!sb16_set_irq_hw (devc, devc->irq))    /* Unsupported IRQ */
-      {
-       snd_release_irq (devc->irq);
-       return;
-      }
-
-  if ((devc->type == 0 || devc->type == MDL_ESS) &&
-      devc->major == 3 && devc->minor == 1)
-    {                          /* Handle various chipsets which claim they are SB Pro compatible */
-      if ((devc->type != 0 && devc->type != MDL_ESS) ||
-         !ess_init (devc, hw_config))
-       if ((devc->type != 0 && devc->type != MDL_JAZZ &&
-            devc->type != MDL_SMW) || !init_Jazz16 (devc, hw_config))
+      if (devc->major == 4)
+       if (!sb16_set_irq_hw (devc, devc->irq))         /* Unsupported IRQ */
          {
-           DDB (printk ("This is a genuine SB Pro\n"));
+           snd_release_irq (devc->irq);
+           irq2devc[hw_config->irq] = NULL;
+           return;
          }
-    }
 
-#ifndef NO_SB_IRQ_TEST
-  if (devc->major != 4 || devc->minor > 11) /* Not Sb16 v4.5 or v4.11 */
-  {
-    for (n = 0; n < 3 && devc->irq_ok == 0; n++)
-    if (sb_dsp_command (devc, 0xf2))   /* Cause interrupt immediately */
-      {
-       int             i;
+      if ((devc->type == 0 || devc->type == MDL_ESS) &&
+         devc->major == 3 && devc->minor == 1)
+       {                       /* Handle various chipsets which claim they are SB Pro compatible */
+         if ((devc->type != 0 && devc->type != MDL_ESS) ||
+             !ess_init (devc, hw_config))
+           if ((devc->type != 0 && devc->type != MDL_JAZZ &&
+                devc->type != MDL_SMW) || !init_Jazz16 (devc, hw_config))
+             {
+               DDB (printk ("This is a genuine SB Pro\n"));
+             }
+       }
 
-       for (i = 0; !devc->irq_ok && i < 10000; i++);
-      }
+      if (devc->major == 4 && devc->minor <= 11)       /* Won't work */
+       devc->irq_ok = 1;
+      else
+       {
+         for (n = 0; n < 3 && devc->irq_ok == 0; n++)
+           if (sb_dsp_command (devc, 0xf2))    /* Cause interrupt immediately */
+             {
+               int             i;
 
-  if (!devc->irq_ok)
-    {
-      printk ("sb: Interrupt test on IRQ%d failed - device disabled\n", devc->irq);
-      snd_release_irq (devc->irq);
-      return;
-    }
-  else
-    {
-      DDB (printk ("IRQ test OK (IRQ%d)\n", devc->irq));
+               for (i = 0; !devc->irq_ok && i < 10000; i++);
+             }
+
+         if (!devc->irq_ok)
+           {
+             printk ("sb: Interrupt test on IRQ%d failed - Propable IRQ conflict\n", devc->irq);
+           }
+         else
+           {
+             DDB (printk ("IRQ test OK (IRQ%d)\n", devc->irq));
+           }
+
+       }                       /* IRQ setup */
     }
-  }
-#endif
 
-  request_region (hw_config->io_base, 16, "sound blaster");
+  request_region (hw_config->io_base, 16, "soundblaster");
 
   switch (devc->major)
     {
@@ -788,14 +800,14 @@ sb_dsp_init (struct address_info *hw_config)
   hw_config->card_subtype = devc->model;
   last_devc = devc;            /* For SB MPU detection */
 
-  if (!(devc->caps & SB_NO_AUDIO))
+  if (!(devc->caps & SB_NO_AUDIO) && devc->dma8 >= 0)
     {
-      if (sound_alloc_dma (devc->dma8, "Sound Blaster8"))
+      if (sound_alloc_dma (devc->dma8, "SoundBlaster8"))
        {
          printk ("SB: Can't allocate 8 bit DMA channel %d\n", devc->dma8);
        }
       if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)
-       if (sound_alloc_dma (devc->dma16, "Sound Blaster16"))
+       if (sound_alloc_dma (devc->dma16, "SoundBlaster16"))
          {
            printk ("SB: Can't allocate 16 bit DMA channel %d\n", devc->dma16);
          }
@@ -822,11 +834,15 @@ sb_dsp_unload (struct address_info *hw_config)
   if (irq < 0)
     irq *= -1;
 
-  devc = irq2devc[irq];
+  if (irq > 2 && irq < 16)
+    devc = irq2devc[irq];
+  else
+    devc = NULL;
 
   if (devc && devc->base == hw_config->io_base)
     {
       release_region (devc->base, 16);
+
       if (!(devc->caps & SB_NO_AUDIO))
        {
          sound_free_dma (devc->dma8);
@@ -835,9 +851,15 @@ sb_dsp_unload (struct address_info *hw_config)
            sound_free_dma (devc->dma16);
        }
 
-      snd_release_irq (devc->irq);
-      irq2devc[devc->irq] = NULL;
+      if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) &&
+         devc->irq > 0)
+       {
+         snd_release_irq (devc->irq);
+         irq2devc[devc->irq] = NULL;
+       }
     }
+  else
+    release_region (hw_config->io_base, 16);
 }
 
 /*
@@ -851,10 +873,12 @@ sb_setmixer (sb_devc * devc, unsigned int port, unsigned int value)
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (port & 0xff), MIXER_ADDR);
+  outb (((unsigned char) (port & 0xff)), MIXER_ADDR);
 
   tenmicrosec (devc->osp);
-  outb ((unsigned char) (value & 0xff), MIXER_DATA);
+  tenmicrosec (devc->osp);
+  outb (((unsigned char) (value & 0xff)), MIXER_DATA);
+  tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
   restore_flags (flags);
 }
@@ -867,8 +891,9 @@ sb_getmixer (sb_devc * devc, unsigned int port)
 
   save_flags (flags);
   cli ();
-  outb ((unsigned char) (port & 0xff), MIXER_ADDR);
+  outb (((unsigned char) (port & 0xff)), MIXER_ADDR);
 
+  tenmicrosec (devc->osp);
   tenmicrosec (devc->osp);
   val = inb (MIXER_DATA);
   tenmicrosec (devc->osp);
@@ -890,9 +915,9 @@ smw_putmem (sb_devc * devc, int base, int addr, unsigned char val)
   save_flags (flags);
   cli ();
 
-  outb (addr & 0xff, base + 1);        /* Low address bits */
-  outb (addr >> 8, base + 2);  /* High address bits */
-  outb (val, base);            /* Data */
+  outb ((addr & 0xff), base + 1);      /* Low address bits */
+  outb ((addr >> 8), base + 2);        /* High address bits */
+  outb ((val), base);          /* Data */
 
   restore_flags (flags);
 }
@@ -906,8 +931,8 @@ smw_getmem (sb_devc * devc, int base, int addr)
   save_flags (flags);
   cli ();
 
-  outb (addr & 0xff, base + 1);        /* Low address bits */
-  outb (addr >> 8, base + 2);  /* High address bits */
+  outb ((addr & 0xff), base + 1);      /* Low address bits */
+  outb ((addr >> 8), base + 2);        /* High address bits */
   val = inb (base);            /* Data */
 
   restore_flags (flags);
@@ -928,13 +953,13 @@ smw_midi_init (sb_devc * devc, struct address_info *hw_config)
    */
 
   control = inb (mpu_base + 7);
-  outb (control | 3, mpu_base + 7);    /* Set last two bits to 1 (?) */
-  outb ((control & 0xfe) | 2, mpu_base + 7);   /* xxxxxxx0 resets the mc */
+  outb ((control | 3), mpu_base + 7);  /* Set last two bits to 1 (?) */
+  outb (((control & 0xfe) | 2), mpu_base + 7); /* xxxxxxx0 resets the mc */
 
   for (i = 0; i < 300; i++)    /* Wait at least 1ms */
     tenmicrosec (devc->osp);
 
-  outb (control & 0xfc, mpu_base + 7); /* xxxxxx00 enables RAM */
+  outb ((control & 0xfc), mpu_base + 7);       /* xxxxxx00 enables RAM */
 
   /*
      *  Detect microcontroller by probing the 8k RAM area
@@ -1012,7 +1037,7 @@ smw_midi_init (sb_devc * devc, struct address_info *hw_config)
   /* control |= 0x20;      Uncomment this if you want to use IRQ7 */
 #endif
 
-  outb (control | 0x03, mpu_base + 7); /* xxxxxx11 restarts */
+  outb ((control | 0x03), mpu_base + 7);       /* xxxxxx11 restarts */
   hw_config->name = "SoundMan Wave";
   return 1;
 }
@@ -1125,9 +1150,9 @@ init_Jazz16_midi (sb_devc * devc, struct address_info *hw_config)
  */
   save_flags (flags);
   cli ();
-  outb (0xAF, 0x201);
-  outb (0x50, 0x201);
-  outb (bits, 0x201);
+  outb ((0xAF), 0x201);
+  outb ((0x50), 0x201);
+  outb ((bits), 0x201);
   restore_flags (flags);
 
   hw_config->name = "Jazz16";
@@ -1167,7 +1192,7 @@ probe_sbmpu (struct address_info *hw_config)
   last_devc = 0;
 
   if (hw_config->io_base <= 0)
-     return 0;
+    return 0;
 
   if (check_region (hw_config->io_base, 4))
     {
@@ -1185,7 +1210,8 @@ probe_sbmpu (struct address_info *hw_config)
        }
       hw_config->name = "Sound Blaster 16";
       hw_config->irq = -devc->irq;
-      sb16_set_mpu_port(devc, hw_config);
+      if (devc->minor > 12)    /* What is Vibra's version??? */
+       sb16_set_mpu_port (devc, hw_config);
       break;
 
     case MDL_ESS:
index 9d129ccb37ad28ba9856267963f1a6a1ffffc4bf..12ec822bf1493570ee8569f9803368bad8edd0f7 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -40,14 +40,14 @@ sb_midi_open (int dev, int mode,
   unsigned long   flags;
 
   if (devc == NULL)
-    return -(ENXIO);
+    return -ENXIO;
 
   save_flags (flags);
   cli ();
   if (devc->opened)
     {
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
   devc->opened = 1;
   restore_flags (flags);
@@ -59,7 +59,7 @@ sb_midi_open (int dev, int mode,
   if (!sb_dsp_command (devc, 0x35))    /* Start MIDI UART mode */
     {
       devc->opened = 0;
-      return -(EIO);
+      return -EIO;
     }
 
   devc->intr_active = 1;
@@ -97,7 +97,7 @@ sb_midi_out (int dev, unsigned char midi_byte)
   sb_devc        *devc = midi_devs[dev]->devc;
 
   if (devc == NULL)
-    return -(ENXIO);
+    return -ENXIO;
 
   sb_dsp_command (devc, midi_byte);
 
@@ -116,7 +116,7 @@ sb_midi_end_read (int dev)
   sb_devc        *devc = midi_devs[dev]->devc;
 
   if (devc == NULL)
-    return -(ENXIO);
+    return -ENXIO;
 
   sb_dsp_reset (devc);
   devc->intr_active = 0;
@@ -126,7 +126,7 @@ sb_midi_end_read (int dev)
 static int
 sb_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EPERM);
+  return -EPERM;
 }
 
 void
index 7590efff9952be6d291b1cd1aeb2ced1e57501af..ae562fd6909be15d99257353c66c12e4cd958a7d 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -22,6 +22,8 @@
 #include "sb.h"
 #include "sb_mixer.h"
 
+static int      sbmixnum = 1;
+
 void            sb_mixer_reset (sb_devc * devc);
 
 void
@@ -69,7 +71,7 @@ static int
 sb_mixer_get (sb_devc * devc, int dev)
 {
   if (!((1 << dev) & devc->supported_devices))
-    return -(EINVAL);
+    return -EINVAL;
 
   return devc->levels[dev];
 }
@@ -107,10 +109,10 @@ smw_mixer_set (sb_devc * devc, int dev, int value)
     right = 100;
 
   if (dev > 31)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!(devc->supported_devices & (1 << dev))) /* Not supported */
-    return -(EINVAL);
+    return -EINVAL;
 
   switch (dev)
     {
@@ -137,7 +139,7 @@ smw_mixer_set (sb_devc * devc, int dev, int value)
     default:
       reg = smw_mix_regs[dev];
       if (reg == 0)
-       return -(EINVAL);
+       return -EINVAL;
       sb_setmixer (devc, reg, (24 - (24 * left / 100)) | 0x20);                /* 24=mute, 0=max */
       sb_setmixer (devc, reg + 1, (24 - (24 * right / 100)) | 0x40);
     }
@@ -164,17 +166,17 @@ sb_mixer_set (sb_devc * devc, int dev, int value)
     right = 100;
 
   if (dev > 31)
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!(devc->supported_devices & (1 << dev))) /*
                                                 * Not supported
                                                 */
-    return -(EINVAL);
+    return -EINVAL;
 
   regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
 
   if (regoffs == 0)
-    return -(EINVAL);
+    return -EINVAL;
 
   val = sb_getmixer (devc, regoffs);
   change_bits (devc, &val, dev, LEFT_CHN, left);
@@ -300,6 +302,7 @@ static int
 sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
   sb_devc        *devc = mixer_devs[dev]->devc;
+  int             val;
 
   if (((cmd >> 8) & 0xff) == 'M')
     {
@@ -307,46 +310,48 @@ sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
        switch (cmd & 0xff)
          {
          case SOUND_MIXER_RECSRC:
-           return snd_ioctl_return ((int *) arg, set_recmask (devc, get_user ((int *) arg)));
+           get_user (val, (int *) arg);
+           return ioctl_out (arg, set_recmask (devc, val));
            break;
 
          default:
 
-           return snd_ioctl_return ((int *) arg, sb_mixer_set (devc, cmd & 0xff, get_user ((int *) arg)));
+           get_user (val, (int *) arg);
+           return ioctl_out (arg, sb_mixer_set (devc, cmd & 0xff, val));
          }
       else
        switch (cmd & 0xff)
          {
 
          case SOUND_MIXER_RECSRC:
-           return snd_ioctl_return ((int *) arg, devc->recmask);
+           return ioctl_out (arg, devc->recmask);
            break;
 
          case SOUND_MIXER_DEVMASK:
-           return snd_ioctl_return ((int *) arg, devc->supported_devices);
+           return ioctl_out (arg, devc->supported_devices);
            break;
 
          case SOUND_MIXER_STEREODEVS:
            if (devc->model == MDL_JAZZ || devc->model == MDL_SMW)
-             return snd_ioctl_return ((int *) arg, devc->supported_devices);
+             return ioctl_out (arg, devc->supported_devices);
            else
-             return snd_ioctl_return ((int *) arg, devc->supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
+             return ioctl_out (arg, devc->supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX));
            break;
 
          case SOUND_MIXER_RECMASK:
-           return snd_ioctl_return ((int *) arg, devc->supported_rec_devices);
+           return ioctl_out (arg, devc->supported_rec_devices);
            break;
 
          case SOUND_MIXER_CAPS:
-           return snd_ioctl_return ((int *) arg, devc->mixer_caps);
+           return ioctl_out (arg, devc->mixer_caps);
            break;
 
          default:
-           return snd_ioctl_return ((int *) arg, sb_mixer_get (devc, cmd & 0xff));
+           return ioctl_out (arg, sb_mixer_get (devc, cmd & 0xff));
          }
     }
   else
-    return -(EINVAL);
+    return -EINVAL;
 }
 
 static struct mixer_operations sb_mixer_operations =
@@ -359,10 +364,16 @@ static struct mixer_operations sb_mixer_operations =
 void
 sb_mixer_reset (sb_devc * devc)
 {
+  char            name[32];
   int             i;
 
+  sprintf (name, "SB_%d", devc->sbmixnum);
+
+  devc->levels = load_mixer_volumes (name, default_levels, 1);
+
   for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
     sb_mixer_set (devc, i, devc->levels[i]);
+
   set_recmask (devc, SOUND_MASK_MIC);
 }
 
@@ -371,6 +382,9 @@ sb_mixer_init (sb_devc * devc)
 {
   int             mixer_type = 0;
 
+  devc->sbmixnum = sbmixnum++;
+  devc->levels = NULL;
+
   sb_setmixer (devc, 0x00, 0); /* Reset mixer */
 
   if (!(mixer_type = detect_mixer (devc)))
@@ -431,7 +445,6 @@ sb_mixer_init (sb_devc * devc)
          sizeof (struct mixer_operations));
 
   mixer_devs[num_mixers]->devc = devc;
-  memcpy ((char *) devc->levels, (char *) &default_levels, sizeof (default_levels));
 
   sb_mixer_reset (devc);
   devc->my_mixerdev = num_mixers++;
index 7635916c7dcadf02cbda5585330a5c63f7c10564..ccd3bb264df5c069973146f124189491afbe15cc 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -43,7 +43,8 @@
 #define SB16_MIXER_DEVICES             (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
                                         SOUND_MASK_CD | \
                                         SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
-                                        SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE)
+                                        SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+                                       SOUND_MASK_IMIX)
 
 /*
  * Mixer registers
@@ -160,7 +161,7 @@ MIX_ENT(SOUND_MIXER_SPEAKER,        0x3b, 7, 2, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_LINE,      0x38, 7, 5, 0x39, 7, 5),
 MIX_ENT(SOUND_MIXER_MIC,       0x3a, 7, 5, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_CD,                0x36, 7, 5, 0x37, 7, 5),
-MIX_ENT(SOUND_MIXER_IMIX,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IMIX,      0x3c, 0, 1, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_ALTPCM,    0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_RECLEV,    0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
 MIX_ENT(SOUND_MIXER_IGAIN,     0x3f, 7, 2, 0x40, 7, 2),
@@ -171,7 +172,7 @@ MIX_ENT(SOUND_MIXER_OGAIN,  0x41, 7, 2, 0x42, 7, 2)
                             higher than with SB Pro. This improves the
                             sound quality */
 
-static unsigned short default_levels[SOUND_MIXER_NRDEVICES] =
+static int default_levels[32] =
 {
   0x2020,                      /* Master Volume */
   0x4b4b,                      /* Bass */
@@ -194,7 +195,7 @@ static unsigned short default_levels[SOUND_MIXER_NRDEVICES] =
 
 #else  /* If the user selected just plain SB Pro */
 
-static unsigned short default_levels[SOUND_MIXER_NRDEVICES] =
+static int default_levels[32] =
 {
   0x5a5a,                      /* Master Volume */
   0x4b4b,                      /* Bass */
@@ -205,7 +206,7 @@ static unsigned short default_levels[SOUND_MIXER_NRDEVICES] =
   0x4b4b,                      /* Ext Line */
   0x1010,                      /* Mic */
   0x4b4b,                      /* CD */
-  0x4b4b,                      /* Recording monitor */
+  0x0000,                      /* Recording monitor */
   0x4b4b,                      /* SB PCM */
   0x4b4b,                      /* Recording level */
   0x4b4b,                      /* Input gain */
index 6a1e626eb9a1a61a6e222ff564c69853f8150675..6b4717c8e23514865556495cd9cc8b946e7b5b23 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -42,10 +42,10 @@ static int      max_synthdev = 0;
 #define SEQ_2  2
 static int      seq_mode = SEQ_1;
 
-static wait_handle *seq_sleeper = NULL;
+static struct wait_queue *seq_sleeper = NULL;
 static volatile struct snd_wait seq_sleep_flag =
 {0};
-static wait_handle *midi_sleeper = NULL;
+static struct wait_queue *midi_sleeper = NULL;
 static volatile struct snd_wait midi_sleep_flag =
 {0};
 
@@ -108,7 +108,7 @@ sequencer_read (int dev, struct fileinfo *file, char *buf, int count)
           1 : 0))
        {
          restore_flags (flags);
-         return -(EAGAIN);
+         return -EAGAIN;
        }
 
 
@@ -116,17 +116,17 @@ sequencer_read (int dev, struct fileinfo *file, char *buf, int count)
        unsigned long   tlimit;
 
        if (pre_event_timeout)
-         current_set_timeout (tlimit = jiffies + (pre_event_timeout));
+         current->timeout = tlimit = jiffies + (pre_event_timeout);
        else
          tlimit = (unsigned long) -1;
-       midi_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&midi_sleeper);
-       if (!(midi_sleep_flag.flags & WK_WAKEUP))
+       midi_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&midi_sleeper);
+       if (!(midi_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             midi_sleep_flag.flags |= WK_TIMEOUT;
+             midi_sleep_flag.opts |= WK_TIMEOUT;
          }
-       midi_sleep_flag.flags &= ~WK_SLEEP;
+       midi_sleep_flag.opts &= ~WK_SLEEP;
       };
 
       if (!iqlen)
@@ -139,7 +139,11 @@ sequencer_read (int dev, struct fileinfo *file, char *buf, int count)
   while (iqlen && c >= ev_len)
     {
 
-      copy_to_user (&(buf)[p], (char *) &iqueue[iqhead * IEV_SZ], ev_len);
+      {
+       char           *fixit = (char *) &iqueue[iqhead * IEV_SZ];
+
+       copy_to_user (&(buf)[p], fixit, ev_len);
+      };
       p += ev_len;
       c -= ev_len;
 
@@ -182,11 +186,11 @@ seq_copy_to_input (unsigned char *event_rec, int len)
   iqlen++;
   iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;
 
-  if ((midi_sleep_flag.flags & WK_SLEEP))
+  if ((midi_sleep_flag.opts & WK_SLEEP))
     {
       {
-       midi_sleep_flag.flags = WK_WAKEUP;
-       module_wake_up (&midi_sleeper);
+       midi_sleep_flag.opts = WK_WAKEUP;
+       wake_up (&midi_sleeper);
       };
     }
   restore_flags (flags);
@@ -258,7 +262,7 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
   DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count));
 
   if (mode == OPEN_READ)
-    return -(EIO);
+    return -EIO;
 
   if (dev)
     return pmgr_write (dev - 1, file, buf, count);
@@ -276,10 +280,10 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
 
          dev = *(unsigned short *) &event_rec[2];
          if (dev < 0 || dev >= max_synthdev)
-           return -(ENXIO);
+           return -ENXIO;
 
          if (!(synth_open_mask & (1 << dev)))
-           return -(ENXIO);
+           return -ENXIO;
 
          err = synth_devs[dev]->load_patch (dev, *(short *) &event_rec[0], buf, p + 4, c, 0);
          if (err < 0)
@@ -293,7 +297,7 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
          if (seq_mode == SEQ_2 && ev_code == SEQ_EXTENDED)
            {
              printk ("Sequencer: Invalid level 2 event %x\n", ev_code);
-             return -(EINVAL);
+             return -EINVAL;
            }
 
          ev_size = 8;
@@ -313,7 +317,7 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
          if (seq_mode == SEQ_2)
            {
              printk ("Sequencer: 4 byte event in level 2 mode\n");
-             return -(EINVAL);
+             return -EINVAL;
            }
          ev_size = 4;
        }
@@ -329,7 +333,7 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
              if (dev >= max_mididev)
                {
                  printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);
-                 return -(ENXIO);
+                 return -ENXIO;
                }
 
              mode = file->mode & O_ACCMODE;
@@ -357,7 +361,7 @@ sequencer_write (int dev, struct fileinfo *file, const char *buf, int count)
 
          if (!processed && (file->flags & (O_NONBLOCK) ?
                             1 : 0))
-           return -(EAGAIN);
+           return -EAGAIN;
          else
            return processed;
        }
@@ -388,15 +392,15 @@ seq_queue (unsigned char *note, char nonblock)
                                 * Give chance to drain the queue
                                 */
 
-  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !(seq_sleep_flag.flags & WK_SLEEP))
+  if (!nonblock && qlen >= SEQ_MAX_QUEUE && !(seq_sleep_flag.opts & WK_SLEEP))
     {
       /*
        * Sleep until there is enough space on the queue
        */
 
-      seq_sleep_flag.flags = WK_SLEEP;
-      module_interruptible_sleep_on (&seq_sleeper);
-      seq_sleep_flag.flags &= ~WK_SLEEP;;
+      seq_sleep_flag.opts = WK_SLEEP;
+      interruptible_sleep_on (&seq_sleeper);
+      seq_sleep_flag.opts &= ~WK_SLEEP;;
     }
 
   if (qlen >= SEQ_MAX_QUEUE)
@@ -419,10 +423,10 @@ extended_event (unsigned char *q)
   int             dev = q[2];
 
   if (dev < 0 || dev >= max_synthdev)
-    return -(ENXIO);
+    return -ENXIO;
 
   if (!(synth_open_mask & (1 << dev)))
-    return -(ENXIO);
+    return -ENXIO;
 
   switch (q[1])
     {
@@ -459,7 +463,7 @@ extended_event (unsigned char *q)
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
   return 0;
@@ -549,7 +553,7 @@ seq_chn_voice_event (unsigned char *event_rec)
          if (chn == 9)
            {
              synth_devs[dev]->set_instr (dev, voice, 128 + note);
-              synth_devs[dev]->chn_info[chn].pgm_num = 128 + note;
+             synth_devs[dev]->chn_info[chn].pgm_num = 128 + note;
              note = 60;        /* Middle C */
 
            }
@@ -695,11 +699,11 @@ seq_timing_event (unsigned char *event_rec)
 
              save_flags (flags);
              cli ();
-             if ((seq_sleep_flag.flags & WK_SLEEP))
+             if ((seq_sleep_flag.opts & WK_SLEEP))
                {
                  {
-                   seq_sleep_flag.flags = WK_WAKEUP;
-                   module_wake_up (&seq_sleeper);
+                   seq_sleep_flag.opts = WK_WAKEUP;
+                   wake_up (&seq_sleeper);
                  };
                }
              restore_flags (flags);
@@ -723,10 +727,10 @@ seq_timing_event (unsigned char *event_rec)
        {
          long            time;
 
-         seq_playing = 1;
          time = parm;
          prev_event_time = time;
 
+         seq_playing = 1;
          request_sound_timer (time);
 
          if ((SEQ_MAX_QUEUE - qlen) >= output_threshold)
@@ -735,11 +739,11 @@ seq_timing_event (unsigned char *event_rec)
 
              save_flags (flags);
              cli ();
-             if ((seq_sleep_flag.flags & WK_SLEEP))
+             if ((seq_sleep_flag.opts & WK_SLEEP))
                {
                  {
-                   seq_sleep_flag.flags = WK_WAKEUP;
-                   module_wake_up (&seq_sleeper);
+                   seq_sleep_flag.opts = WK_WAKEUP;
+                   wake_up (&seq_sleeper);
                  };
                }
              restore_flags (flags);
@@ -871,11 +875,11 @@ play_event (unsigned char *q)
 
              save_flags (flags);
              cli ();
-             if ((seq_sleep_flag.flags & WK_SLEEP))
+             if ((seq_sleep_flag.opts & WK_SLEEP))
                {
                  {
-                   seq_sleep_flag.flags = WK_WAKEUP;
-                   module_wake_up (&seq_sleeper);
+                   seq_sleep_flag.opts = WK_WAKEUP;
+                   wake_up (&seq_sleeper);
                  };
                }
              restore_flags (flags);
@@ -914,7 +918,7 @@ play_event (unsigned char *q)
          if (dev < 0 || dev >= num_midis)
            break;
 
-         if (!midi_devs[dev]->putc (dev, q[1]))
+         if (!midi_devs[dev]->outputc (dev, q[1]))
            {
              /*
                 * Output FIFO is full. Wait one timer cycle and try again.
@@ -1010,11 +1014,11 @@ seq_startplay (void)
 
       save_flags (flags);
       cli ();
-      if ((seq_sleep_flag.flags & WK_SLEEP))
+      if ((seq_sleep_flag.opts & WK_SLEEP))
        {
          {
-           seq_sleep_flag.flags = WK_WAKEUP;
-           module_wake_up (&seq_sleeper);
+           seq_sleep_flag.opts = WK_WAKEUP;
+           wake_up (&seq_sleeper);
          };
        }
       restore_flags (flags);
@@ -1080,22 +1084,21 @@ sequencer_open (int dev, struct fileinfo *file)
   if (!sequencer_ok)
     {
       printk ("Soundcard: Sequencer not initialized\n");
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   if (dev)                     /* Patch manager device */
     {
       printk ("Patch manager interface is currently broken. Sorry\n");
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   save_flags (flags);
   cli ();
   if (sequencer_busy)
     {
-      printk ("Sequencer busy\n");
       restore_flags (flags);
-      return -(EBUSY);
+      return -EBUSY;
     }
   sequencer_busy = 1;
   restore_flags (flags);
@@ -1135,21 +1138,21 @@ sequencer_open (int dev, struct fileinfo *file)
        {
          printk ("sequencer: No timer for level 2\n");
          sequencer_busy = 0;
-         return -(ENXIO);
+         return -ENXIO;
        }
       setup_mode2 ();
     }
 
-  if (seq_mode == SEQ_1 && (mode == OPEN_READ || mode == OPEN_READWRITE))
+  if (seq_mode == SEQ_1 && mode == OPEN_READ)
     if (!max_mididev)
       {
        printk ("Sequencer: No Midi devices. Input not possible\n");
        sequencer_busy = 0;
-       return -(ENXIO);
+       return -ENXIO;
       }
 
   if (!max_synthdev && !max_mididev)
-    return -(ENXIO);
+    return -ENXIO;
 
   synth_open_mask = 0;
 
@@ -1202,8 +1205,8 @@ sequencer_open (int dev, struct fileinfo *file)
       tmr->open (tmr_no, seq_mode);
     }
 
-  seq_sleep_flag.flags = WK_NONE;
-  midi_sleep_flag.flags = WK_NONE;
+  seq_sleep_flag.opts = WK_NONE;
+  midi_sleep_flag.opts = WK_NONE;
   output_threshold = SEQ_MAX_QUEUE / 2;
 
   for (i = 0; i < num_synths; i++)
@@ -1224,7 +1227,7 @@ seq_drain_midi_queues (void)
 
   n = 1;
 
-  while (!current_got_fatal_signal () && n)
+  while (!(current->signal & ~current->blocked) && n)
     {
       n = 0;
 
@@ -1244,17 +1247,17 @@ seq_drain_midi_queues (void)
            unsigned long   tlimit;
 
            if (HZ / 10)
-             current_set_timeout (tlimit = jiffies + (HZ / 10));
+             current->timeout = tlimit = jiffies + (HZ / 10);
            else
              tlimit = (unsigned long) -1;
-           seq_sleep_flag.flags = WK_SLEEP;
-           module_interruptible_sleep_on (&seq_sleeper);
-           if (!(seq_sleep_flag.flags & WK_WAKEUP))
+           seq_sleep_flag.opts = WK_SLEEP;
+           interruptible_sleep_on (&seq_sleeper);
+           if (!(seq_sleep_flag.opts & WK_WAKEUP))
              {
                if (jiffies >= tlimit)
-                 seq_sleep_flag.flags |= WK_TIMEOUT;
+                 seq_sleep_flag.opts |= WK_TIMEOUT;
              }
-           seq_sleep_flag.flags &= ~WK_SLEEP;
+           seq_sleep_flag.opts &= ~WK_SLEEP;
          };
        }
     }
@@ -1286,7 +1289,7 @@ sequencer_release (int dev, struct fileinfo *file)
 
   if (mode != OPEN_READ && !(file->flags & (O_NONBLOCK) ?
                             1 : 0))
-    while (!current_got_fatal_signal () && qlen)
+    while (!(current->signal & ~current->blocked) && qlen > 0)
       {
        seq_sync ();
       }
@@ -1302,24 +1305,28 @@ sequencer_release (int dev, struct fileinfo *file)
                                 */
 
   for (i = 0; i < max_synthdev; i++)
-    if (synth_open_mask & (1 << i))    /*
+    {
+      if (synth_open_mask & (1 << i))  /*
                                         * Actually opened
                                         */
-      if (synth_devs[i])
-       {
-         synth_devs[i]->close (i);
+       if (synth_devs[i])
+         {
+           synth_devs[i]->close (i);
 
-         if (synth_devs[i]->midi_dev)
-           midi_opened[synth_devs[i]->midi_dev] = 0;
-       }
+           if (synth_devs[i]->midi_dev)
+             midi_opened[synth_devs[i]->midi_dev] = 0;
+         }
+    }
 
   for (i = 0; i < num_synths; i++)
     if (pmgr_present[i])
       pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
 
   for (i = 0; i < max_mididev; i++)
-    if (midi_opened[i])
-      midi_devs[i]->close (i);
+    {
+      if (midi_opened[i])
+       midi_devs[i]->close (i);
+    }
 
   if (seq_mode == SEQ_2)
     tmr->close (tmr_no);
@@ -1332,29 +1339,29 @@ seq_sync (void)
 {
   unsigned long   flags;
 
-  if (qlen && !seq_playing && !current_got_fatal_signal ())
+  if (qlen && !seq_playing && !(current->signal & ~current->blocked))
     seq_startplay ();
 
   save_flags (flags);
   cli ();
-  if (qlen && !(seq_sleep_flag.flags & WK_SLEEP))
+  if (qlen > 0)
     {
 
       {
        unsigned long   tlimit;
 
        if (HZ)
-         current_set_timeout (tlimit = jiffies + (HZ));
+         current->timeout = tlimit = jiffies + (HZ);
        else
          tlimit = (unsigned long) -1;
-       seq_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&seq_sleeper);
-       if (!(seq_sleep_flag.flags & WK_WAKEUP))
+       seq_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&seq_sleeper);
+       if (!(seq_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             seq_sleep_flag.flags |= WK_TIMEOUT;
+             seq_sleep_flag.opts |= WK_TIMEOUT;
          }
-       seq_sleep_flag.flags &= ~WK_SLEEP;
+       seq_sleep_flag.opts &= ~WK_SLEEP;
       };
     }
   restore_flags (flags);
@@ -1382,24 +1389,24 @@ midi_outc (int dev, unsigned char data)
 
   save_flags (flags);
   cli ();
-  while (n && !midi_devs[dev]->putc (dev, data))
+  while (n && !midi_devs[dev]->outputc (dev, data))
     {
 
       {
        unsigned long   tlimit;
 
        if (4)
-         current_set_timeout (tlimit = jiffies + (4));
+         current->timeout = tlimit = jiffies + (4);
        else
          tlimit = (unsigned long) -1;
-       seq_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&seq_sleeper);
-       if (!(seq_sleep_flag.flags & WK_WAKEUP))
+       seq_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&seq_sleeper);
+       if (!(seq_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             seq_sleep_flag.flags |= WK_TIMEOUT;
+             seq_sleep_flag.opts |= WK_TIMEOUT;
          }
-       seq_sleep_flag.flags &= ~WK_SLEEP;
+       seq_sleep_flag.opts &= ~WK_SLEEP;
       };
       n--;
     }
@@ -1478,12 +1485,12 @@ seq_reset (void)
 
   save_flags (flags);
   cli ();
-  if ((seq_sleep_flag.flags & WK_SLEEP))
+  if ((seq_sleep_flag.opts & WK_SLEEP))
     {
       /*      printk ("Sequencer Warning: Unexpected sleeping process - Waking up\n"); */
       {
-       seq_sleep_flag.flags = WK_WAKEUP;
-       module_wake_up (&seq_sleeper);
+       seq_sleep_flag.opts = WK_WAKEUP;
+       wake_up (&seq_sleeper);
       };
     }
   restore_flags (flags);
@@ -1531,28 +1538,28 @@ sequencer_ioctl (int dev, struct fileinfo *file,
     case SNDCTL_TMR_METRONOME:
     case SNDCTL_TMR_SOURCE:
       if (dev)                 /* Patch manager */
-       return -(EIO);
+       return -EIO;
 
       if (seq_mode != SEQ_2)
-       return -(EINVAL);
+       return -EINVAL;
       return tmr->ioctl (tmr_no, cmd, arg);
       break;
 
     case SNDCTL_TMR_SELECT:
       if (dev)                 /* Patch manager */
-       return -(EIO);
+       return -EIO;
 
       if (seq_mode != SEQ_2)
-       return -(EINVAL);
-      pending_timer = get_user ((int *) arg);
+       return -EINVAL;
+      get_user (pending_timer, (int *) arg);
 
       if (pending_timer < 0 || pending_timer >= num_sound_timers)
        {
          pending_timer = -1;
-         return -(EINVAL);
+         return -EINVAL;
        }
 
-      return snd_ioctl_return ((int *) arg, pending_timer);
+      return ioctl_out (arg, pending_timer);
       break;
 
     case SNDCTL_SEQ_PANIC:
@@ -1563,14 +1570,14 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (dev)                 /*
                                 * Patch manager
                                 */
-       return -(EIO);
+       return -EIO;
 
       if (mode == OPEN_READ)
        return 0;
-      while (qlen && !current_got_fatal_signal ())
+      while (qlen > 0 && !(current->signal & ~current->blocked))
        seq_sync ();
       if (qlen)
-       return -(EINTR);
+       return -EINTR;
       else
        return 0;
       break;
@@ -1579,7 +1586,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (dev)                 /*
                                 * Patch manager
                                 */
-       return -(EIO);
+       return -EIO;
 
       seq_reset ();
       return 0;
@@ -1589,11 +1596,11 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (dev)                 /*
                                 * Patch manager
                                 */
-       return -(EIO);
+       return -EIO;
 
-      midi_dev = get_user ((int *) arg);
+      get_user (midi_dev, (int *) arg);
       if (midi_dev >= max_mididev)
-       return -(ENXIO);
+       return -ENXIO;
 
       if (!midi_opened[midi_dev])
        {
@@ -1615,23 +1622,30 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (dev)                 /*
                                 * Patch manager
                                 */
-       return -(EIO);
+       return -EIO;
 
       if (mode == OPEN_WRITE)
        return 0;
-      return snd_ioctl_return ((int *) arg, iqlen);
+      return ioctl_out (arg, iqlen);
       break;
 
     case SNDCTL_SEQ_GETOUTCOUNT:
 
       if (mode == OPEN_READ)
        return 0;
-      return snd_ioctl_return ((int *) arg, SEQ_MAX_QUEUE - qlen);
+      return ioctl_out (arg, SEQ_MAX_QUEUE - qlen);
+      break;
+
+    case SNDCTL_SEQ_GETTIME:
+      if (seq_mode == SEQ_2)
+       return tmr->ioctl (tmr_no, cmd, arg);
+
+      return ioctl_out (arg, jiffies - seq_time);
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
       if (dev)                 /* Patch manager */
-       return -(EIO);
+       return -EIO;
 
       /*
        * If *arg == 0, just return the current rate
@@ -1639,25 +1653,25 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (seq_mode == SEQ_2)
        return tmr->ioctl (tmr_no, cmd, arg);
 
-      if (get_user ((int *) arg) != 0)
-       return -(EINVAL);
+      if (ioctl_in (arg) != 0)
+       return -EINVAL;
 
-      return snd_ioctl_return ((int *) arg, HZ);
+      return ioctl_out (arg, HZ);
       break;
 
     case SNDCTL_SEQ_RESETSAMPLES:
       {
        int             err;
 
-       dev = get_user ((int *) arg);
+       get_user (dev, (int *) arg);
        if (dev < 0 || dev >= num_synths)
          {
-           return -(ENXIO);
+           return -ENXIO;
          }
 
        if (!(synth_open_mask & (1 << dev)) && !orig_dev)
          {
-           return -(EBUSY);
+           return -EBUSY;
          }
 
        if (!orig_dev && pmgr_present[dev])
@@ -1669,36 +1683,38 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       break;
 
     case SNDCTL_SEQ_NRSYNTHS:
-      return snd_ioctl_return ((int *) arg, max_synthdev);
+      return ioctl_out (arg, max_synthdev);
       break;
 
     case SNDCTL_SEQ_NRMIDIS:
-      return snd_ioctl_return ((int *) arg, max_mididev);
+      return ioctl_out (arg, max_mididev);
       break;
 
     case SNDCTL_SYNTH_MEMAVL:
       {
-       int             dev = get_user ((int *) arg);
+       int             dev;
+
+       get_user (dev, (int *) arg);
 
        if (dev < 0 || dev >= num_synths)
-         return -(ENXIO);
+         return -ENXIO;
 
        if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-         return -(EBUSY);
+         return -EBUSY;
 
-       return snd_ioctl_return ((int *) arg, synth_devs[dev]->ioctl (dev, cmd, arg));
+       return ioctl_out (arg, synth_devs[dev]->ioctl (dev, cmd, arg));
       }
       break;
 
     case SNDCTL_FM_4OP_ENABLE:
       {
-       int             dev = get_user ((int *) arg);
+       int             dev = ioctl_in (arg);
 
        if (dev < 0 || dev >= num_synths)
-         return -(ENXIO);
+         return -ENXIO;
 
        if (!(synth_open_mask & (1 << dev)))
-         return -(ENXIO);
+         return -ENXIO;
 
        synth_devs[dev]->ioctl (dev, cmd, arg);
        return 0;
@@ -1714,10 +1730,10 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        dev = inf.device;
 
        if (dev < 0 || dev >= max_synthdev)
-         return -(ENXIO);
+         return -ENXIO;
 
        if (!(synth_open_mask & (1 << dev)) && !orig_dev)
-         return -(EBUSY);
+         return -EBUSY;
 
        return synth_devs[dev]->ioctl (dev, cmd, arg);
       }
@@ -1743,14 +1759,20 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       {
        struct midi_info inf;
        int             dev;
+       char           *pp;
 
        copy_from_user ((char *) &inf, &((char *) arg)[0], sizeof (inf));
        dev = inf.device;
 
        if (dev < 0 || dev >= max_mididev)
-         return -(ENXIO);
+         return -ENXIO;
+
+       pp = (char *) &midi_devs[dev]->info;
+       {
+         char           *fixit = pp;
 
-       copy_to_user (&((char *) arg)[0], (char *) &(midi_devs[dev]->info), sizeof (inf));
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (inf));
+       };
        return 0;
       }
       break;
@@ -1763,7 +1785,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        if ((inf = (struct patmgr_info *) vmalloc (sizeof (*inf))) == NULL)
          {
            printk ("patmgr: Can't allocate memory for a message\n");
-           return -(EIO);
+           return -EIO;
          }
 
        copy_from_user ((char *) inf, &((char *) arg)[0], sizeof (*inf));
@@ -1772,13 +1794,13 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        if (dev < 0 || dev >= num_synths)
          {
            vfree (inf);
-           return -(ENXIO);
+           return -ENXIO;
          }
 
        if (!synth_devs[dev]->pmgr_interface)
          {
            vfree (inf);
-           return -(ENXIO);
+           return -ENXIO;
          }
 
        if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1)
@@ -1787,7 +1809,11 @@ sequencer_ioctl (int dev, struct fileinfo *file,
            return err;
          }
 
-       copy_to_user (&((char *) arg)[0], (char *) inf, sizeof (*inf));
+       {
+         char           *fixit = (char *) inf;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (*inf));
+       };
        vfree (inf);
        return 0;
       }
@@ -1801,7 +1827,7 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        if ((inf = (struct patmgr_info *) vmalloc (sizeof (*inf))) == NULL)
          {
            printk ("patmgr: Can't allocate memory for a message\n");
-           return -(EIO);
+           return -EIO;
          }
 
        copy_from_user ((char *) inf, &((char *) arg)[0], sizeof (*inf));
@@ -1810,13 +1836,13 @@ sequencer_ioctl (int dev, struct fileinfo *file,
        if (dev < 0 || dev >= num_synths)
          {
            vfree (inf);
-           return -(ENXIO);
+           return -ENXIO;
          }
 
        if (!pmgr_present[dev])
          {
            vfree (inf);
-           return -(ESRCH);
+           return -ESRCH;
          }
 
        if ((err = pmgr_access (dev, inf)) < 0)
@@ -1825,7 +1851,11 @@ sequencer_ioctl (int dev, struct fileinfo *file,
            return err;
          }
 
-       copy_to_user (&((char *) arg)[0], (char *) inf, sizeof (*inf));
+       {
+         char           *fixit = (char *) inf;
+
+         copy_to_user (&((char *) arg)[0], fixit, sizeof (*inf));
+       };
        vfree (inf);
        return 0;
       }
@@ -1833,12 +1863,12 @@ sequencer_ioctl (int dev, struct fileinfo *file,
 
     case SNDCTL_SEQ_THRESHOLD:
       {
-       int             tmp = get_user ((int *) arg);
+       int             tmp = ioctl_in (arg);
 
        if (dev)                /*
                                 * Patch manager
                                 */
-         return -(EIO);
+         return -EIO;
 
        if (tmp < 1)
          tmp = 1;
@@ -1851,14 +1881,14 @@ sequencer_ioctl (int dev, struct fileinfo *file,
 
     case SNDCTL_MIDI_PRETIME:
       {
-       int             val = get_user ((int *) arg);
+       int             val = ioctl_in (arg);
 
        if (val < 0)
          val = 0;
 
        val = (HZ * val) / 10;
        pre_event_timeout = val;
-       return snd_ioctl_return ((int *) arg, val);
+       return ioctl_out (arg, val);
       }
       break;
 
@@ -1866,24 +1896,24 @@ sequencer_ioctl (int dev, struct fileinfo *file,
       if (dev)                 /*
                                 * Patch manager
                                 */
-       return -(EIO);
+       return -EIO;
 
       if (mode == OPEN_READ)
-       return -(EIO);
+       return -EIO;
 
       if (!synth_devs[0])
-       return -(ENXIO);
+       return -ENXIO;
       if (!(synth_open_mask & (1 << 0)))
-       return -(ENXIO);
+       return -ENXIO;
       return synth_devs[0]->ioctl (0, cmd, arg);
       break;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 int
-sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table_handle * wait)
+sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
 {
   unsigned long   flags;
 
@@ -1897,8 +1927,8 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table_han
       if (!iqlen)
        {
 
-         midi_sleep_flag.flags = WK_SLEEP;
-         module_select_wait (&midi_sleeper, wait);
+         midi_sleep_flag.opts = WK_SLEEP;
+         select_wait (&midi_sleeper, wait);
          restore_flags (flags);
          return 0;
        }
@@ -1912,8 +1942,8 @@ sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table_han
       if ((SEQ_MAX_QUEUE - qlen) < output_threshold)
        {
 
-         seq_sleep_flag.flags = WK_SLEEP;
-         module_select_wait (&seq_sleeper, wait);
+         seq_sleep_flag.opts = WK_SLEEP;
+         select_wait (&seq_sleeper, wait);
          restore_flags (flags);
          return 0;
        }
index 16207733862d0d88c989c717a5ede0aefa1eaf34..ad51adf671a7671aaac67a071e030c97427257d2 100644 (file)
@@ -18,8 +18,11 @@ void DMAbuf_close_dma (int dev);
 void DMAbuf_reset_dma (int dev);
 void DMAbuf_inputintr(int dev);
 void DMAbuf_outputintr(int dev, int underflow_flag);
-int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
+void DMAbuf_start_device(int dev);
 void DMAbuf_start_devices(unsigned int devmask);
+void DMAbuf_reset (int dev);
+int DMAbuf_sync (int dev);
 
 /*
  *     System calls for /dev/dsp and /dev/audio
@@ -31,10 +34,9 @@ int audio_open (int dev, struct fileinfo *file);
 void audio_release (int dev, struct fileinfo *file);
 int audio_ioctl (int dev, struct fileinfo *file,
           unsigned int cmd, caddr_t arg);
-int audio_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-void audio_init (void);
+void audio_init_devices (void);
 
-int audio_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int audio_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
 
 /*
  *     System calls for the /dev/sequencer
@@ -54,7 +56,7 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range);
 void seq_input_event(unsigned char *event, int len);
 void seq_copy_to_input (unsigned char *event, int len);
 
-int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int sequencer_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
 
 /*
  *     System calls for the /dev/midi
@@ -70,7 +72,7 @@ int MIDIbuf_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
 void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count);
 void MIDIbuf_init(void);
 
-int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table_handle * wait);
+int MIDIbuf_select(int dev, struct fileinfo *file, int sel_type, select_table * wait);
 
 /*
  *
@@ -89,6 +91,8 @@ void sound_dma_malloc(int dev);
 void sound_dma_free(int dev);
 void conf_printf(char *name, struct address_info *hw_config);
 void conf_printf2(char *name, int base, int irq, int dma, int dma2);
+int ioctl_in(caddr_t arg);
+int ioctl_out(caddr_t arg, int result);
 
 /*     From sound_switch.c     */
 int sound_read_sw (int dev, struct fileinfo *file, char *buf, int count);
@@ -202,6 +206,12 @@ int ad1848_detect (int io_base, int *flags, int *osp);
 #define AD_F_CS4231    0x0001  /* Returned if a CS4232 (or compatible) detected */
 #define AD_F_CS4248    0x0001  /* Returned if a CS4248 (or compatible) detected */
 
+void    ad1848_control(int cmd, int arg);
+#define                AD1848_SET_XTAL         1
+#define                AD1848_MIXER_REROUTE    2
+#define AD1848_REROUTE(oldctl, newctl) \
+               ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
+
 void     ad1848_interrupt (int irq, void *dev_id, struct pt_regs * dummy);
 void attach_ms_sound(struct address_info * hw_config);
 int probe_ms_sound(struct address_info *hw_config);
@@ -223,15 +233,6 @@ void attach_sscape (struct address_info *hw_config);
 int probe_ss_ms_sound (struct address_info *hw_config);
 void attach_ss_ms_sound(struct address_info * hw_config);
 
-int pss_read (int dev, struct fileinfo *file, char *buf, int count);
-int pss_write (int dev, struct fileinfo *file, char *buf, int count);
-int pss_open (int dev, struct fileinfo *file);
-void pss_release (int dev, struct fileinfo *file);
-int pss_ioctl (int dev, struct fileinfo *file,
-          unsigned int cmd, caddr_t arg);
-int pss_lseek (int dev, struct fileinfo *file, off_t offset, int orig);
-void pss_init(void);
-
 /* From aedsp16.c */
 int InitAEDSP16_SBPRO(struct address_info *hw_config);
 int InitAEDSP16_MSS(struct address_info *hw_config);
@@ -291,6 +292,3 @@ void attach_cs4232_mpu (struct address_info *hw_config);
 void attach_maui(struct address_info * hw_config);
 int probe_maui(struct address_info *hw_config);
 
-/*     From sound_pnp.c */
-void sound_pnp_init(int *osp);
-void sound_pnp_disconnect(void);
index 75aec488ffb081e5ade1e32561ca9e17e75ab02d..29cf2161f02fa31dcc81fca05dad872db778380d 100644 (file)
@@ -5,7 +5,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 #include "os.h"
 #include "soundvers.h"
 
-#if defined(ISC) || defined(SCO) || defined(SVR42)
-#define GENERIC_SYSV
-#endif
-
 
 
 
 #define MAX_REALTIME_FACTOR    4
 #endif
 
-/************* PCM DMA buffer sizes *******************/
-
-/* If you are using high playback or recording speeds, the default buffer size
-   is too small. DSP_BUFFSIZE must be 64k or less.
-
-   A rule of thumb is 64k for PAS16, 32k for PAS+, 16k for SB Pro and
-   4k for SB.
-
-   If you change the DSP_BUFFSIZE, don't modify this file.
-   Use the make config command instead. */
-
-#ifndef DSP_BUFFSIZE
-#define DSP_BUFFSIZE           (4096)
-#endif
+/*
+ * Use always 64k buffer size. There is no reason to use shorter.
+ */
+#undef DSP_BUFFSIZE
+#define DSP_BUFFSIZE           (16*1024)
 
 #ifndef DSP_BUFFCOUNT
 #define DSP_BUFFCOUNT          1       /* 1 is recommended. */
@@ -128,7 +115,7 @@ struct address_info {
        int driver_use_1;       /* Driver defined field 1 */
        int driver_use_2;       /* Driver defined field 2 */
        int *osp;       /* OS specific info */
-       int card_subtype;       /* Driver specific. Usually 0 */
+       int card_subtype;       /* Driver spesific. Usually 0 */
 };
 
 #define SYNTH_MAX_VOICES       32
@@ -170,7 +157,7 @@ struct channel_info {
 #endif
 
 #ifndef DDB
-#define DDB(x)
+#define DDB(x) {}
 #endif
 
 #define TIMER_ARMED    121234
index e1607d1d048b937bbaa7e5c57be8279c028b51cd..ce9a19c226088fc40f14dfaa5c975f5cf051f871 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
 
 #include "sound_config.h"
 
-struct sbc_device
-  {
-    int             usecount;
-  };
-
 static int      in_use = 0;    /* Total # of open devices */
 
+/*
+ * Table for configurable mixer volume handling
+ */
+static mixer_vol_table mixer_vols[MAX_MIXER_DEV];
+static int      num_mixer_volumes = 0;
+
 /*
  * /dev/sndstatus -device
  */
@@ -29,6 +30,92 @@ static char    *status_buf = NULL;
 static int      status_len, status_ptr;
 static int      status_busy = 0;
 
+int
+               *
+load_mixer_volumes (char *name, int *levels, int present)
+{
+  int             i, n;
+
+  for (i = 0; i < num_mixer_volumes; i++)
+    if (strcmp (name, mixer_vols[i].name) == 0)
+      {
+       if (present)
+         mixer_vols[i].num = i;
+       return mixer_vols[i].levels;
+      }
+
+  if (num_mixer_volumes >= MAX_MIXER_DEV)
+    {
+      printk ("Sound: Too many mixers (%s)\n", name);
+      return levels;
+    }
+
+  n = num_mixer_volumes++;
+
+  strcpy (mixer_vols[n].name, name);
+
+  if (present)
+    mixer_vols[n].num = n;
+  else
+    mixer_vols[n].num = -1;
+
+  for (i = 0; i < 32; i++)
+    mixer_vols[n].levels[i] = levels[i];
+  return mixer_vols[n].levels;
+}
+
+static int
+set_mixer_levels (caddr_t arg)
+{
+  mixer_vol_table *buf = NULL;
+  int             err = 0;
+
+  if ((buf = (mixer_vol_table *) vmalloc (sizeof (mixer_vol_table))) == NULL)
+    return -ENOSPC;
+
+  copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+  load_mixer_volumes (buf->name, buf->levels, 0);
+
+  {
+    char           *fixit = (char *) buf;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+  };
+  vfree (buf);
+
+  return err;
+}
+
+static int
+get_mixer_levels (caddr_t arg)
+{
+  mixer_vol_table *buf = NULL;
+  int             n, err = 0;
+
+  if ((buf = (mixer_vol_table *) vmalloc (sizeof (mixer_vol_table))) == NULL)
+    return -ENOSPC;
+
+  copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+  n = buf->num;
+  if (n < 0 || n >= num_mixer_volumes)
+    err = -EINVAL;
+  else
+    {
+      memcpy ((char *) buf, (char *) &mixer_vols[n], sizeof (*buf));
+    }
+
+  {
+    char           *fixit = (char *) buf;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+  };
+  vfree (buf);
+
+  return err;
+}
+
 static int
 put_status (char *s)
 {
@@ -111,6 +198,7 @@ init_status (void)
   put_status (system_utsname.machine);
   put_status ("\n");
 
+
   if (!put_status ("Config options: "))
     return;
   if (!put_status_int (SELECTED_SOUND_OPTIONS, 16))
@@ -135,6 +223,7 @@ init_status (void)
          return;
       }
 
+
   if (!put_status ("\nCard config: \n"))
     return;
 
@@ -269,6 +358,7 @@ init_status (void)
     }
 #endif
 
+#ifdef CONFIG_MIDI
   if (!put_status ("\nTimers:\n"))
     return;
 
@@ -283,6 +373,7 @@ init_status (void)
       if (!put_status ("\n"))
        return;
     }
+#endif
 
   if (!put_status ("\nMixers:\n"))
     return;
@@ -316,7 +407,11 @@ read_status (char *buf, int count)
   if (l <= 0)
     return 0;
 
-  copy_to_user (&(buf)[0], &status_buf[status_ptr], l);
+  {
+    char           *fixit = &status_buf[status_ptr];
+
+    copy_to_user (&(buf)[0], fixit, l);
+  };
   status_ptr += l;
 
   return l;
@@ -353,11 +448,10 @@ sound_read_sw (int dev, struct fileinfo *file, char *buf, int count)
       return MIDIbuf_read (dev, file, buf, count);
 #endif
 
-    default:
-      printk ("Sound: Undefined minor device %d\n", dev);
+    default:;
     }
 
-  return -(EPERM);
+  return -EINVAL;
 }
 
 int
@@ -366,6 +460,7 @@ sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count)
 
   DEB (printk ("sound_write_sw(dev=%d, count=%d)\n", dev, count));
 
+
   switch (dev & 0x0f)
     {
 
@@ -391,7 +486,7 @@ sound_write_sw (int dev, struct fileinfo *file, const char *buf, int count)
 
     }
 
-  return -(EPERM);
+  return -EINVAL;
 }
 
 int
@@ -404,24 +499,25 @@ sound_open_sw (int dev, struct fileinfo *file)
   if ((dev >= SND_NDEVS) || (dev < 0))
     {
       printk ("Invalid minor device %d\n", dev);
-      return -(ENXIO);
+      return -ENXIO;
     }
 
+
   switch (dev & 0x0f)
     {
     case SND_DEV_STATUS:
       if (status_busy)
-       return -(EBUSY);
+       return -EBUSY;
       status_busy = 1;
       if ((status_buf = (char *) vmalloc (4000)) == NULL)
-       return -(EIO);
+       return -EIO;
       status_len = status_ptr = 0;
       init_status ();
       break;
 
     case SND_DEV_CTL:
       if ((dev & 0xf0) && ((dev & 0xf0) >> 4) >= num_mixers)
-       return -(ENXIO);
+       return -ENXIO;
       return 0;
       break;
 
@@ -451,7 +547,7 @@ sound_open_sw (int dev, struct fileinfo *file)
 
     default:
       printk ("Invalid minor device %d\n", dev);
-      return -(ENXIO);
+      return -ENXIO;
     }
 
   in_use++;
@@ -510,21 +606,64 @@ get_mixer_info (int dev, caddr_t arg)
   mixer_info      info;
 
   if (dev < 0 || dev >= num_mixers)
-    return -(ENXIO);
+    return -ENXIO;
+
+  strcpy (info.id, mixer_devs[dev]->id);
+  strcpy (info.name, mixer_devs[dev]->name);
+  info.modify_counter = mixer_devs[dev]->modify_counter;
+
+  {
+    char           *fixit = (char *) &info;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+  };
+  return 0;
+}
+
+static int
+get_old_mixer_info (int dev, caddr_t arg)
+{
+  _old_mixer_info info;
+
+  if (dev < 0 || dev >= num_mixers)
+    return -ENXIO;
 
   strcpy (info.id, mixer_devs[dev]->id);
   strcpy (info.name, mixer_devs[dev]->name);
 
-  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
+  {
+    char           *fixit = (char *) &info;
+
+    copy_to_user (&((char *) arg)[0], fixit, sizeof (info));
+  };
   return 0;
 }
 
+static int
+sound_mixer_ioctl (int mixdev,
+                  unsigned int cmd, caddr_t arg)
+{
+  if (cmd == SOUND_MIXER_INFO)
+    return get_mixer_info (mixdev, arg);
+  if (cmd == SOUND_OLD_MIXER_INFO)
+    return get_old_mixer_info (mixdev, arg);
+
+  if (_IOC_DIR (cmd) & _IOC_WRITE)
+    mixer_devs[mixdev]->modify_counter++;
+
+  return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
+}
+
 int
 sound_ioctl_sw (int dev, struct fileinfo *file,
                unsigned int cmd, caddr_t arg)
 {
   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 
+  if (cmd == OSS_GETVERSION)
+    return ioctl_out (arg, SOUND_VERSION);
+
+
   if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)    /* Mixer ioctl */
     if ((dev & 0x0f) != SND_DEV_CTL)
       {
@@ -539,17 +678,13 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
          case SND_DEV_AUDIO:
            mixdev = audio_devs[dev >> 4]->mixer_dev;
            if (mixdev < 0 || mixdev >= num_mixers)
-             return -(ENXIO);
-           if (cmd == SOUND_MIXER_INFO)
-             return get_mixer_info (mixdev, arg);
-           return mixer_devs[mixdev]->ioctl (mixdev, cmd, arg);
+             return -ENXIO;
+           return sound_mixer_ioctl (mixdev, cmd, arg);
            break;
 #endif
 
          default:
-           if (cmd == SOUND_MIXER_INFO)
-             return get_mixer_info (0, arg);
-           return mixer_devs[0]->ioctl (0, cmd, arg);
+           return sound_mixer_ioctl (dev, cmd, arg);
          }
       }
 
@@ -557,18 +692,20 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
     {
 
     case SND_DEV_CTL:
+      if (cmd == SOUND_MIXER_GETLEVELS)
+       return get_mixer_levels (arg);
+      if (cmd == SOUND_MIXER_SETLEVELS)
+       return set_mixer_levels (arg);
 
       if (!num_mixers)
-       return -(ENXIO);
+       return -ENXIO;
 
       dev = dev >> 4;
 
       if (dev >= num_mixers)
-       return -(ENXIO);
+       return -ENXIO;
 
-      if (cmd == SOUND_MIXER_INFO)
-       return get_mixer_info (dev, arg);
-      return mixer_devs[dev]->ioctl (dev, cmd, arg);
+      return sound_mixer_ioctl (dev, cmd, arg);
       break;
 
 #ifdef CONFIG_SEQUENCER
@@ -594,5 +731,5 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
 
     }
 
-  return -(EPERM);
+  return -EINVAL;
 }
index fdc5cb26b472ffb1b73c59972a03c34b8023ce33..6195c132f48766e035ed4223e0f8f1bf167daaf9 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -94,7 +94,7 @@ static int
 timer_open (int dev, int mode)
 {
   if (opened)
-    return -(EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 60;
@@ -193,7 +193,7 @@ timer_ioctl (int dev,
   switch (cmd)
     {
     case SNDCTL_TMR_SOURCE:
-      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
+      return ioctl_out (arg, TMR_INTERNAL);
       break;
 
     case SNDCTL_TMR_START:
@@ -214,7 +214,9 @@ timer_ioctl (int dev,
 
     case SNDCTL_TMR_TIMEBASE:
       {
-       int             val = get_user ((int *) arg);
+       int             val;
+
+       get_user (val, (int *) arg);
 
        if (val)
          {
@@ -225,13 +227,15 @@ timer_ioctl (int dev,
            curr_timebase = val;
          }
 
-       return snd_ioctl_return ((int *) arg, curr_timebase);
+       return ioctl_out (arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-       int             val = get_user ((int *) arg);
+       int             val;
+
+       get_user (val, (int *) arg);
 
        if (val)
          {
@@ -246,15 +250,19 @@ timer_ioctl (int dev,
            reprogram_timer ();
          }
 
-       return snd_ioctl_return ((int *) arg, curr_tempo);
+       return ioctl_out (arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (get_user ((int *) arg) != 0) /* Can't change */
-       return -(EINVAL);
+      if (ioctl_in (arg) != 0) /* Can't change */
+       return -EINVAL;
+
+      return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      break;
 
-      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
+    case SNDCTL_SEQ_GETTIME:
+      return ioctl_out (arg, curr_ticks);
       break;
 
     case SNDCTL_TMR_METRONOME:
@@ -264,7 +272,7 @@ timer_ioctl (int dev,
     default:;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
index 2b51654b39c540b81040d259a651dca7af33064b..43b0c7a8bb587e086cf407f405bfdb6bbdf19681 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -18,7 +18,7 @@
 #include <linux/major.h>
 
 
-int            *sound_global_osp = NULL;
+int            *sound_osp = NULL;
 static int      chrdev_registered = 0;
 static int      sound_major = SOUND_MAJOR;
 
@@ -42,48 +42,64 @@ static char     dma_alloc_map[8] =
 #define DMA_MAP_BUSY           2
 
 
+int
+ioctl_in (caddr_t arg)
+{
+  int             xx;
+
+  get_user (xx, (int *) arg);
+  return xx;
+}
+
+int
+ioctl_out (caddr_t arg, int result)
+{
+  put_user (result, (int *) arg);
+  return 0;
+}
+
 int
 snd_ioctl_return (int *addr, int value)
 {
   if (value < 0)
     return value;
 
-  put_user (value, addr);
+  put_user (value, (int *) &((addr)[0]));
   return 0;
 }
 
 static long
-sound_read (inode_handle * inode, file_handle * file, char *buf, unsigned long count)
+sound_read (struct inode *inode, struct file *file, char *buf, unsigned long count)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   return sound_read_sw (dev, &files[dev], buf, count);
 }
 
 static long
-sound_write (inode_handle * inode, file_handle * file, const char *buf, unsigned long count)
+sound_write (struct inode *inode, struct file *file, const char *buf, unsigned long count)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   return sound_write_sw (dev, &files[dev], buf, count);
 }
 
 static long long
-sound_lseek (inode_handle * inode, file_handle * file, long long offset, int orig)
+sound_lseek (struct inode *inode, struct file *file, long long offset, int orig)
 {
-  return -(EPERM);
+  return -EPERM;
 }
 
 static int
-sound_open (inode_handle * inode, file_handle * file)
+sound_open (struct inode *inode, struct file *file)
 {
   int             dev, retval;
   struct fileinfo tmp_file;
@@ -91,19 +107,19 @@ sound_open (inode_handle * inode, file_handle * file)
   if (is_unloading)
     {
       printk ("Sound: Driver partially removed. Can't open device\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
     {
-      printk ("Sound Card Error: The soundcard system has not been configured\n");
-      return -(ENXIO);
+      printk ("SoundCard Error: The soundcard system has not been configured\n");
+      return -ENXIO;
     }
 
   tmp_file.mode = 0;
-  tmp_file.flags = file_get_flags (file);
+  tmp_file.flags = file->f_flags;
 
   if ((tmp_file.flags & O_ACCMODE) == O_RDWR)
     tmp_file.mode = OPEN_READWRITE;
@@ -124,13 +140,13 @@ sound_open (inode_handle * inode, file_handle * file)
 }
 
 static void
-sound_release (inode_handle * inode, file_handle * file)
+sound_release (struct inode *inode, struct file *file)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   sound_release_sw (dev, &files[dev]);
 #ifdef MODULE
@@ -139,14 +155,14 @@ sound_release (inode_handle * inode, file_handle * file)
 }
 
 static int
-sound_ioctl (inode_handle * inode, file_handle * file,
+sound_ioctl (struct inode *inode, struct file *file,
             unsigned int cmd, unsigned long arg)
 {
   int             dev, err;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   if (_IOC_DIR (cmd) != _IOC_NONE)
     {
@@ -177,13 +193,13 @@ sound_ioctl (inode_handle * inode, file_handle * file,
 }
 
 static int
-sound_select (inode_handle * inode, file_handle * file, int sel_type, select_table_handle * wait)
+sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
 {
   int             dev;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 
@@ -218,15 +234,15 @@ sound_select (inode_handle * inode, file_handle * file, int sel_type, select_tab
 }
 
 static int
-sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
+sound_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
 {
   int             dev, dev_class;
   unsigned long   size;
   struct dma_buffparms *dmap = NULL;
 
-  dev = MINOR (inode_get_rdev (inode));
+  dev = MINOR (inode->i_rdev);
 
-  files[dev].flags = file_get_flags (file);
+  files[dev].flags = file->f_flags;
 
   dev_class = dev & 0x0f;
   dev >>= 4;
@@ -237,17 +253,17 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
       return -EINVAL;
     }
 
-  if ((vma_get_flags (vma) & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
+  if ((vma->vm_flags & (VM_READ | VM_WRITE)) == (VM_READ | VM_WRITE))
     {
       printk ("Sound: Cannot do read/write mmap()\n");
       return -EINVAL;
     }
 
-  if (vma_get_flags (vma) & VM_READ)
+  if (vma->vm_flags & VM_READ)
     {
       dmap = audio_devs[dev]->dmap_in;
     }
-  else if (vma_get_flags (vma) & VM_WRITE)
+  else if (vma->vm_flags & VM_WRITE)
     {
       dmap = audio_devs[dev]->dmap_out;
     }
@@ -275,13 +291,13 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
       return -EIO;
     }
 
-  if (vma_get_offset (vma) != 0)
+  if (vma->vm_offset != 0)
     {
       printk ("Sound: mmap() offset must be 0.\n");
       return -EINVAL;
     }
 
-  size = vma_get_end (vma) - vma_get_start (vma);
+  size = vma->vm_end - vma->vm_start;
 
   if (size != dmap->bytes_in_use)
     {
@@ -289,13 +305,13 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
              size, dmap->bytes_in_use);
     }
 
-  if (remap_page_range (vma_get_start (vma), virt_to_phys(dmap->raw_buf),
-                       vma_get_end (vma) - vma_get_start (vma),
-                       vma_get_page_prot (vma)))
+  if (remap_page_range (vma->vm_start, virt_to_phys (dmap->raw_buf),
+                       vma->vm_end - vma->vm_start,
+                       vma->vm_page_prot))
     return -EAGAIN;
 
-  vma_set_inode (vma, inode);
-  inode_inc_count (inode);
+  vma->vm_inode = inode;
+  inode->i_count++;
 
   dmap->mapping_flags |= DMA_MAP_MAPPED;
 
@@ -305,7 +321,7 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
   return 0;
 }
 
-static struct file_operation_handle sound_fops =
+static struct file_operations sound_fops =
 {
   sound_lseek,
   sound_read,
@@ -322,7 +338,7 @@ void
 soundcard_init (void)
 {
 #ifndef MODULE
-  module_register_chrdev (sound_major, "sound", &sound_fops);
+  register_chrdev (sound_major, "sound", &sound_fops);
   chrdev_registered = 1;
 #endif
 
@@ -331,15 +347,6 @@ soundcard_init (void)
   sndtable_init ();            /* Initialize call tables and detect cards */
 
 
-
-#ifdef CONFIG_LOWLEVEL_SOUND
-  {
-    extern void     sound_init_lowlevel_drivers (void);
-
-    sound_init_lowlevel_drivers ();
-  }
-#endif
-
   if (sndtable_get_cardcount () == 0)
     return;                    /* No cards detected */
 
@@ -347,7 +354,7 @@ soundcard_init (void)
   if (num_audiodevs)           /* Audio devices present */
     {
       DMAbuf_init ();
-      audio_init ();
+      audio_init_devices ();
     }
 #endif
 
@@ -396,7 +403,7 @@ init_module (void)
   int             ints[21];
   int             i;
 
-  if (connect_wrapper (WRAPPER_VERSION) < 0)
+  if (0 < 0)
     {
       printk ("Sound: Incompatible kernel (wrapper) version\n");
       return -EINVAL;
@@ -413,7 +420,7 @@ init_module (void)
   if (i)
     sound_setup ("sound=", ints);
 
-  err = module_register_chrdev (sound_major, "sound", &sound_fops);
+  err = register_chrdev (sound_major, "sound", &sound_fops);
   if (err)
     {
       printk ("sound: driver already loaded/included in kernel\n");
@@ -443,7 +450,7 @@ cleanup_module (void)
     }
 
   if (chrdev_registered)
-    module_unregister_chrdev (sound_major, "sound");
+    unregister_chrdev (sound_major, "sound");
 
 #ifdef CONFIG_SEQUENCER
   sound_stop_timer ();
@@ -491,7 +498,6 @@ snd_set_irq_handler (int interrupt_level, void (*iproc) (int, void *, struct pt_
 
   save_flags (flags);
   cli ();
-
   retcode = request_irq (interrupt_level, iproc, 0 /* SA_INTERRUPT */ , name, NULL);
   if (retcode < 0)
     {
@@ -595,14 +601,25 @@ request_sound_timer (int count)
   extern unsigned long seq_time;
 
   if (count < 0)
-    count = jiffies + (-count);
-  else
-    count += seq_time;
+    {
+
+      {
+       seq_timer.expires = (-count) + jiffies;
+       add_timer (&seq_timer);
+      };
+      return;
+    }
+
+  count += seq_time;
+
+  count -= jiffies;
+
+  if (count < 1)
+    count = 1;
 
-  ;
 
   {
-    seq_timer.expires = ((count - jiffies)) + jiffies;
+    seq_timer.expires = (count) + jiffies;
     add_timer (&seq_timer);
   };
 }
@@ -668,14 +685,14 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
 
       audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz);
 
-      if ((start_addr = (char *) __get_dma_pages (GFP_ATOMIC, sz)) == NULL)
+      if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL)
        audio_devs[dev]->buffsize /= 2;
     }
 
   if (start_addr == NULL)
     {
       printk ("Sound error: Couldn't allocate DMA buffer\n");
-      return -(ENOMEM);
+      return -ENOMEM;
     }
   else
     {
@@ -696,7 +713,7 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
                   "sound: Got invalid address 0x%lx for %ldb DMA-buffer\n",
                   (long) start_addr,
                   audio_devs[dev]->buffsize);
-         return -(EFAULT);
+         return -EFAULT;
        }
     }
   dmap->raw_buf = start_addr;
@@ -704,14 +721,14 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
 
   for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
     {
-      mem_map_reserve (i);
+      set_bit (PG_reserved, &mem_map[i].flags);;
     }
 
   return 0;
 }
 
 void
-sound_free_dmap (int dev, struct dma_buffparms *dmap)
+sound_free_dmap (int dev, struct dma_buffparms *dmap, int chan)
 {
   int             sz, size, i;
   unsigned long   start_addr, end_addr;
@@ -731,7 +748,7 @@ sound_free_dmap (int dev, struct dma_buffparms *dmap)
 
   for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
     {
-      mem_map_unreserve (i);
+      clear_bit (PG_reserved, &mem_map[i].flags);;
     }
 
   free_pages ((unsigned long) dmap->raw_buf, sz);
@@ -743,7 +760,7 @@ sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc * info)
 {
   printk ("Entered sound_map_buffer()\n");
   printk ("Exited sound_map_buffer()\n");
-  return -(EINVAL);
+  return -EINVAL;
 }
 #endif
 
index 1e6db53217c44be7a70388f39ebc13bb25e00a11..5a8c4c8cd1e64f9098d42a65b287a968b334908d 100644 (file)
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.5.4-960630"
-#define SOUND_INTERNAL_VERSION 0x030504
+#define SOUND_VERSION_STRING "3.7-beta6-961029"
+#define SOUND_INTERNAL_VERSION 0x030701
index 40ad714581d184ee827cb07648e48b4490d9ee0e..0cf0ed26ec72ae89523e12b25f8967c16ff887c4 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -15,7 +15,7 @@
 
 #include "sound_config.h"
 
-#if defined(CONFIG_SSCAPE)
+#if defined(CONFIG_SSCAPEHW)
 
 #include "coproc.h"
 
@@ -88,7 +88,7 @@ static struct sscape_info dev_info =
 {0};
 static struct sscape_info *devc = &dev_info;
 
-static wait_handle *sscape_sleeper = NULL;
+static struct wait_queue *sscape_sleeper = NULL;
 static volatile struct snd_wait sscape_sleep_flag =
 {0};
 
@@ -117,7 +117,7 @@ sscape_read (struct sscape_info *devc, int reg)
 
   save_flags (flags);
   cli ();
-  outb (reg, PORT (ODIE_ADDR));
+  outb ((reg), PORT (ODIE_ADDR));
   val = inb (PORT (ODIE_DATA));
   restore_flags (flags);
   return val;
@@ -130,21 +130,21 @@ sscape_write (struct sscape_info *devc, int reg, int data)
 
   save_flags (flags);
   cli ();
-  outb (reg, PORT (ODIE_ADDR));
-  outb (data, PORT (ODIE_DATA));
+  outb ((reg), PORT (ODIE_ADDR));
+  outb ((data), PORT (ODIE_DATA));
   restore_flags (flags);
 }
 
 static void
 host_open (struct sscape_info *devc)
 {
-  outb (0x00, PORT (HOST_CTRL));       /* Put the board to the host mode */
+  outb ((0x00), PORT (HOST_CTRL));     /* Put the board to the host mode */
 }
 
 static void
 host_close (struct sscape_info *devc)
 {
-  outb (0x03, PORT (HOST_CTRL));       /* Put the board to the MIDI mode */
+  outb ((0x03), PORT (HOST_CTRL));     /* Put the board to the MIDI mode */
 }
 
 static int
@@ -172,7 +172,7 @@ host_write (struct sscape_info *devc, unsigned char *data, int count)
          return 0;
        }
 
-      outb (data[i], PORT (HOST_DATA));
+      outb ((data[i]), PORT (HOST_DATA));
     }
 
 
@@ -291,11 +291,11 @@ sscapeintr (int irq, void *dev_id, struct pt_regs *dummy)
   static int      debug = 0;
 
   bits = sscape_read (devc, GA_INTSTAT_REG);
-  if ((sscape_sleep_flag.flags & WK_SLEEP))
+  if ((sscape_sleep_flag.opts & WK_SLEEP))
     {
       {
-       sscape_sleep_flag.flags = WK_WAKEUP;
-       module_wake_up (&sscape_sleeper);
+       sscape_sleep_flag.opts = WK_WAKEUP;
+       wake_up (&sscape_sleeper);
       };
     }
 
@@ -387,10 +387,10 @@ sscape_coproc_open (void *dev_info, int sub_device)
     {
       set_mt32 (devc, 0);
       if (!verify_mpu (devc))
-       return -(EIO);
+       return -EIO;
     }
 
-  sscape_sleep_flag.flags = WK_NONE;
+  sscape_sleep_flag.opts = WK_NONE;
   return 0;
 }
 
@@ -407,7 +407,7 @@ sscape_coproc_close (void *dev_info, int sub_device)
       sscape_write (devc, GA_DMAA_REG, 0x20);  /* DMA channel disabled */
       devc->dma_allocated = 0;
     }
-  sscape_sleep_flag.flags = WK_NONE;
+  sscape_sleep_flag.opts = WK_NONE;
   restore_flags (flags);
 
   return;
@@ -436,10 +436,6 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
       save_flags (flags);
       cli ();
       codec_dma_bits = sscape_read (devc, GA_CDCFG_REG);
-#if 0
-      sscape_write (devc, GA_CDCFG_REG,
-                   codec_dma_bits & ~0x08);    /* Disable codec DMA */
-#endif
 
       if (devc->dma_allocated == 0)
        {
@@ -473,7 +469,7 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
   /*
    * Wait until transfer completes.
    */
-  sscape_sleep_flag.flags = WK_NONE;
+  sscape_sleep_flag.opts = WK_NONE;
   done = 0;
   timeout_val = 100;
   while (!done && timeout_val-- > 0)
@@ -485,17 +481,17 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
        unsigned long   tlimit;
 
        if (1)
-         current_set_timeout (tlimit = jiffies + (1));
+         current->timeout = tlimit = jiffies + (1);
        else
          tlimit = (unsigned long) -1;
-       sscape_sleep_flag.flags = WK_SLEEP;
-       module_interruptible_sleep_on (&sscape_sleeper);
-       if (!(sscape_sleep_flag.flags & WK_WAKEUP))
+       sscape_sleep_flag.opts = WK_SLEEP;
+       interruptible_sleep_on (&sscape_sleeper);
+       if (!(sscape_sleep_flag.opts & WK_WAKEUP))
          {
            if (jiffies >= tlimit)
-             sscape_sleep_flag.flags |= WK_TIMEOUT;
+             sscape_sleep_flag.opts |= WK_TIMEOUT;
          }
-       sscape_sleep_flag.flags &= ~WK_SLEEP;
+       sscape_sleep_flag.opts &= ~WK_SLEEP;
       };
       clear_dma_ff (devc->dma);
       if ((resid = get_dma_residue (devc->dma)) == 0)
@@ -513,8 +509,8 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
       /*
          * Take the board out of reset
        */
-      outb (0x00, PORT (HOST_CTRL));
-      outb (0x00, PORT (MIDI_CTRL));
+      outb ((0x00), PORT (HOST_CTRL));
+      outb ((0x00), PORT (MIDI_CTRL));
 
       temp = sscape_read (devc, GA_HMCTL_REG);
       temp |= 0x40;
@@ -530,25 +526,31 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
       timeout_val = 5 * HZ;
       while (!done && timeout_val-- > 0)
        {
+         unsigned char   x;
+
 
          {
            unsigned long   tlimit;
 
            if (1)
-             current_set_timeout (tlimit = jiffies + (1));
+             current->timeout = tlimit = jiffies + (1);
            else
              tlimit = (unsigned long) -1;
-           sscape_sleep_flag.flags = WK_SLEEP;
-           module_interruptible_sleep_on (&sscape_sleeper);
-           if (!(sscape_sleep_flag.flags & WK_WAKEUP))
+           sscape_sleep_flag.opts = WK_SLEEP;
+           interruptible_sleep_on (&sscape_sleeper);
+           if (!(sscape_sleep_flag.opts & WK_WAKEUP))
              {
                if (jiffies >= tlimit)
-                 sscape_sleep_flag.flags |= WK_TIMEOUT;
+                 sscape_sleep_flag.opts |= WK_TIMEOUT;
              }
-           sscape_sleep_flag.flags &= ~WK_SLEEP;
+           sscape_sleep_flag.opts &= ~WK_SLEEP;
          };
-         if (inb (PORT (HOST_DATA)) == 0xff)   /* OBP startup acknowledge */
-           done = 1;
+         x = inb (PORT (HOST_DATA));
+         if (x == 0xff || x == 0xfe)   /* OBP startup acknowledge */
+           {
+             printk ("Soundscape: Acknowledge = %x\n", x);
+             done = 1;
+           }
        }
       sscape_write (devc, GA_CDCFG_REG, codec_dma_bits);
 
@@ -570,17 +572,17 @@ sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size,
            unsigned long   tlimit;
 
            if (1)
-             current_set_timeout (tlimit = jiffies + (1));
+             current->timeout = tlimit = jiffies + (1);
            else
              tlimit = (unsigned long) -1;
-           sscape_sleep_flag.flags = WK_SLEEP;
-           module_interruptible_sleep_on (&sscape_sleeper);
-           if (!(sscape_sleep_flag.flags & WK_WAKEUP))
+           sscape_sleep_flag.opts = WK_SLEEP;
+           interruptible_sleep_on (&sscape_sleeper);
+           if (!(sscape_sleep_flag.opts & WK_WAKEUP))
              {
                if (jiffies >= tlimit)
-                 sscape_sleep_flag.flags |= WK_TIMEOUT;
+                 sscape_sleep_flag.opts |= WK_TIMEOUT;
              }
-           sscape_sleep_flag.flags &= ~WK_SLEEP;
+           sscape_sleep_flag.opts &= ~WK_SLEEP;
          };
          if (inb (PORT (HOST_DATA)) == 0xfe)   /* Host startup acknowledge */
            done = 1;
@@ -620,12 +622,12 @@ static int
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return -(EINVAL);
+    return -EINVAL;
 
   if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
-      return -(EIO);
+      return -EIO;
     }
 
   return 0;
@@ -649,7 +651,7 @@ sscape_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
 
        buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
        if (buf == NULL)
-         return -(ENOSPC);
+         return -ENOSPC;
        copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
        err = download_boot_block (dev_info, buf);
        vfree (buf);
@@ -658,7 +660,7 @@ sscape_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
       break;
 
     default:
-      return -(EINVAL);
+      return -EINVAL;
     }
 
 }
@@ -760,7 +762,8 @@ attach_sscape (struct address_info *hw_config)
                      (sscape_read (devc, i) & 0xc0));
        break;
 
-      case 6:                  /* CD-ROM config. Don't touch. */
+      case 6:                  /* CD-ROM config (WSS codec actually) */
+       sscape_write (devc, i, regs[i]);
        break;
 
       case 9:                  /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
@@ -815,11 +818,11 @@ probe_sscape (struct address_info *hw_config)
 {
   unsigned char   save;
 
-  devc->failed = 1;
   devc->base = hw_config->io_base;
   devc->irq = hw_config->irq;
   devc->dma = hw_config->dma;
-  devc->osp = hw_config->osp;
+
+  devc->failed = 1;
 
   if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
     return 0;
@@ -830,17 +833,26 @@ probe_sscape (struct address_info *hw_config)
      * First 4 bits
    */
   if ((save = inb (PORT (ODIE_ADDR))) & 0xf0)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error A\n"));
+      return 0;
+    }
 
-  outb (0x00, PORT (ODIE_ADDR));
+  outb ((0x00), PORT (ODIE_ADDR));
   if (inb (PORT (ODIE_ADDR)) != 0x00)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error B\n"));
+      return 0;
+    }
 
-  outb (0xff, PORT (ODIE_ADDR));
+  outb ((0xff), PORT (ODIE_ADDR));
   if (inb (PORT (ODIE_ADDR)) != 0x0f)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error C\n"));
+      return 0;
+    }
 
-  outb (save, PORT (ODIE_ADDR));
+  outb ((save), PORT (ODIE_ADDR));
 
   /*
      * Now verify that some indirect registers return zero on some bits.
@@ -848,13 +860,22 @@ probe_sscape (struct address_info *hw_config)
    */
 
   if (sscape_read (devc, 0) & 0x0c)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error D (%x)\n", sscape_read (devc, 0)));
+      return 0;
+    }
 
   if (sscape_read (devc, 1) & 0x0f)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error E\n"));
+      return 0;
+    }
 
   if (sscape_read (devc, 5) & 0x0f)
-    return 0;
+    {
+      DDB (printk ("soundscape: Detect error F\n"));
+      return 0;
+    }
 
 #ifdef SSCAPE_DEBUG1
   /*
@@ -896,7 +917,10 @@ probe_ss_ms_sound (struct address_info *hw_config)
   int             i, irq_bits = 0xff;
 
   if (devc->failed)
-    return 0;
+    {
+      printk ("Soundscape: Card not detected\n");
+      return 0;
+    }
 
   if (devc->ok == 0)
     {
@@ -916,6 +940,7 @@ probe_ss_ms_sound (struct address_info *hw_config)
       return 0;
     }
 
+
   return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
 }
 
index b87f0dbbe34d18c6af6bfc12579e4b00831cad30..8904e9fd01816f014dbed8df5363acc3953fc1b4 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -90,7 +90,7 @@ static int
 def_tmr_open (int dev, int mode)
 {
   if (opened)
-    return -(EBUSY);
+    return -EBUSY;
 
   tmr_reset ();
   curr_tempo = 60;
@@ -192,7 +192,7 @@ def_tmr_ioctl (int dev,
   switch (cmd)
     {
     case SNDCTL_TMR_SOURCE:
-      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
+      return ioctl_out (arg, TMR_INTERNAL);
       break;
 
     case SNDCTL_TMR_START:
@@ -213,7 +213,9 @@ def_tmr_ioctl (int dev,
 
     case SNDCTL_TMR_TIMEBASE:
       {
-       int             val = get_user ((int *) arg);
+       int             val;
+
+       get_user (val, (int *) arg);
 
        if (val)
          {
@@ -224,13 +226,15 @@ def_tmr_ioctl (int dev,
            curr_timebase = val;
          }
 
-       return snd_ioctl_return ((int *) arg, curr_timebase);
+       return ioctl_out (arg, curr_timebase);
       }
       break;
 
     case SNDCTL_TMR_TEMPO:
       {
-       int             val = get_user ((int *) arg);
+       int             val;
+
+       get_user (val, (int *) arg);
 
        if (val)
          {
@@ -244,15 +248,19 @@ def_tmr_ioctl (int dev,
            curr_tempo = val;
          }
 
-       return snd_ioctl_return ((int *) arg, curr_tempo);
+       return ioctl_out (arg, curr_tempo);
       }
       break;
 
     case SNDCTL_SEQ_CTRLRATE:
-      if (get_user ((int *) arg) != 0) /* Can't change */
-       return -(EINVAL);
+      if (ioctl_in (arg) != 0) /* Can't change */
+       return -EINVAL;
+
+      return ioctl_out (arg, ((curr_tempo * curr_timebase) + 30) / 60);
+      break;
 
-      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
+    case SNDCTL_SEQ_GETTIME:
+      return ioctl_out (arg, curr_ticks);
       break;
 
     case SNDCTL_TMR_METRONOME:
@@ -262,7 +270,7 @@ def_tmr_ioctl (int dev,
     default:;
     }
 
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
index 15f36e7e5a8717d319ddbc794d74b476518b47c3..974c476b839a02dabca88aed6916bc12eefdd284 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -37,15 +37,15 @@ static int     *trix_osp = NULL;
 static unsigned char
 trix_read (int addr)
 {
-  outb ((unsigned char) addr, 0x390);  /* MT-0002-PC ASIC address */
+  outb (((unsigned char) addr), 0x390);                /* MT-0002-PC ASIC address */
   return inb (0x391);          /* MT-0002-PC ASIC data */
 }
 
 static void
 trix_write (int addr, int data)
 {
-  outb ((unsigned char) addr, 0x390);  /* MT-0002-PC ASIC address */
-  outb ((unsigned char) data, 0x391);  /* MT-0002-PC ASIC data */
+  outb (((unsigned char) addr), 0x390);                /* MT-0002-PC ASIC address */
+  outb (((unsigned char) data), 0x391);                /* MT-0002-PC ASIC data */
 }
 
 static void
@@ -57,22 +57,22 @@ download_boot (int base)
     return;
 
   trix_write (0xf8, 0x00);     /* ??????? */
-  outb (0x01, base + 6);       /* Clear the internal data pointer */
-  outb (0x00, base + 6);       /* Restart */
+  outb ((0x01), base + 6);     /* Clear the internal data pointer */
+  outb ((0x00), base + 6);     /* Restart */
 
   /*
      *  Write the boot code to the RAM upload/download register.
      *  Each write increments the internal data pointer.
    */
-  outb (0x01, base + 6);       /* Clear the internal data pointer */
-  outb (0x1A, 0x390);          /* Select RAM download/upload port */
+  outb ((0x01), base + 6);     /* Clear the internal data pointer */
+  outb ((0x1A), 0x390);                /* Select RAM download/upload port */
 
   for (i = 0; i < n; i++)
-    outb (trix_boot[i], 0x391);
+    outb ((trix_boot[i]), 0x391);
   for (i = n; i < 10016; i++)  /* Clear up to first 16 bytes of data RAM */
-    outb (0x00, 0x391);
-  outb (0x00, base + 6);       /* Reset */
-  outb (0x50, 0x390);          /* ?????? */
+    outb ((0x00), 0x391);
+  outb ((0x00), base + 6);     /* Reset */
+  outb ((0x50), 0x390);                /* ?????? */
 
 }
 
@@ -175,7 +175,7 @@ probe_trix_wss (struct address_info *hw_config)
       return 0;
     }
 
-  if (hw_config->dma2 != -1)
+  if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
     if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
       {
        printk ("AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
@@ -218,6 +218,7 @@ attach_trix_wss (struct address_info *hw_config)
 
   int             config_port = hw_config->io_base + 0;
   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
+  int             old_num_mixers = num_mixers;
 
   trix_osp = hw_config->osp;
 
@@ -238,7 +239,7 @@ attach_trix_wss (struct address_info *hw_config)
       return;
     }
 
-  outb (bits | 0x40, config_port);
+  outb ((bits | 0x40), config_port);
 
   if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
     {
@@ -256,7 +257,7 @@ attach_trix_wss (struct address_info *hw_config)
       trix_write (0x14, tmp | 0x80 | (dma2 << 4));
     }
 
-  outb (bits, config_port);    /* Write IRQ+DMA setup */
+  outb ((bits), config_port);  /* Write IRQ+DMA setup */
 
   ad1848_init ("AudioTrix Pro", hw_config->io_base + 4,
               hw_config->irq,
@@ -265,6 +266,14 @@ attach_trix_wss (struct address_info *hw_config)
               0,
               hw_config->osp);
   request_region (hw_config->io_base, 4, "MSS config");
+
+  if (num_mixers > old_num_mixers)     /* Mixer got installed */
+    {
+      AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_LINE);    /* Line in */
+      AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+      AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);   /* OPL4 */
+      AD1848_REROUTE (SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);                /* SB */
+    }
 }
 
 int
@@ -316,7 +325,7 @@ probe_trix_sb (struct address_info *hw_config)
 
   hw_config->name = "AudioTrix SB";
 #ifdef CONFIG_SBDSP
-  return probe_sb (hw_config);
+  return sb_dsp_detect (hw_config);
 #else
   return 0;
 #endif
@@ -327,7 +336,7 @@ attach_trix_sb (struct address_info *hw_config)
 {
 #ifdef CONFIG_SBDSP
   hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
-  attach_sb_card (hw_config);
+  sb_dsp_init (hw_config);
 #endif
 }
 
@@ -443,7 +452,7 @@ void
 unload_trix_sb (struct address_info *hw_config)
 {
 #ifdef CONFIG_SBDSP
-  unload_sb (hw_config);
+  sb_dsp_unload (hw_config);
 #endif
 }
 
index 443c46adb470890f80699d5f04b1979d1bc366ab..1d6abfb5c4ab646e3e38603e4aca003fa8c8cb19 100644 (file)
@@ -6,7 +6,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -23,7 +23,7 @@ typedef struct uart401_devc
     int             irq;
     int            *osp;
     void            (*midi_input_intr) (int dev, unsigned char data);
-    int             opened;
+    int             opened, disabled;
     volatile unsigned char input_byte;
     int             my_dev;
     int             share_irq;
@@ -48,7 +48,7 @@ uart401_status (uart401_devc * devc)
 static void 
 uart401_cmd (uart401_devc * devc, unsigned char cmd)
 {
-  outb (cmd, COMDPORT);
+  outb ((cmd), COMDPORT);
 }
 static int 
 uart401_read (uart401_devc * devc)
@@ -58,7 +58,7 @@ uart401_read (uart401_devc * devc)
 static void 
 uart401_write (uart401_devc * devc, unsigned char byte)
 {
-  outb (byte, DATAPORT);
+  outb ((byte), DATAPORT);
 }
 
 #define        OUTPUT_READY    0x40
@@ -68,6 +68,7 @@ uart401_write (uart401_devc * devc, unsigned char byte)
 #define        UART_MODE_ON    0x3F
 
 static int      reset_uart401 (uart401_devc * devc);
+static void     enter_uart_mode (uart401_devc * devc);
 
 static void
 uart401_input_loop (uart401_devc * devc)
@@ -110,7 +111,7 @@ uart401_open (int dev, int mode,
 
   if (devc->opened)
     {
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   while (input_avail (devc))
@@ -118,6 +119,8 @@ uart401_open (int dev, int mode,
 
   devc->midi_input_intr = input;
   devc->opened = mode;
+  enter_uart_mode (devc);
+  devc->disabled = 0;
 
   return 0;
 }
@@ -127,6 +130,7 @@ uart401_close (int dev)
 {
   uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
 
+  reset_uart401 (devc);
   devc->opened = 0;
 }
 
@@ -137,6 +141,8 @@ uart401_out (int dev, unsigned char midi_byte)
   unsigned long   flags;
   uart401_devc   *devc = (uart401_devc *) midi_devs[dev]->devc;
 
+  if (devc->disabled)
+    return 1;
   /*
    * Test for input since pending input seems to block the output.
    */
@@ -158,8 +164,11 @@ uart401_out (int dev, unsigned char midi_byte)
 
   if (!output_ready (devc))
     {
-      printk ("MPU-401: Timeout\n");
-      return 0;
+      printk ("MPU-401: Timeout - Device not responding\n");
+      devc->disabled = 1;
+      reset_uart401 (devc);
+      enter_uart_mode (devc);
+      return 1;
     }
 
   uart401_write (devc, midi_byte);
@@ -181,7 +190,7 @@ uart401_end_read (int dev)
 static int
 uart401_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
@@ -347,8 +356,6 @@ reset_uart401 (uart401_devc * devc)
 
   ok = 0;
 
-  /* save_flags(flags);cli(); */
-
   for (n = 0; n < 2 && !ok; n++)
     {
       for (timeout = 30000; timeout < 0 && !output_ready (devc); timeout--);
@@ -370,13 +377,19 @@ reset_uart401 (uart401_devc * devc)
 
     }
 
+
+  if (ok)
+    {
+      DDB (printk ("Reset UART401 OK\n"));
+    }
+  else
+    DDB (printk ("Reset UART401 failed - No hardware detected.\n"));
+
   if (ok)
     uart401_input_loop (devc); /*
                                 * Flush input before enabling interrupts
                                 */
 
-  /* restore_flags(flags); */
-
   return ok;
 }
 
@@ -388,6 +401,8 @@ probe_uart401 (struct address_info *hw_config)
   static uart401_devc hw_info;
   uart401_devc   *devc = &hw_info;
 
+  DDB (printk ("Entered probe_uart401()\n"));
+
   detected_devc = NULL;
 
   if (check_region (hw_config->io_base, 4))
@@ -428,7 +443,6 @@ unload_uart401 (struct address_info *hw_config)
     return;
 
   reset_uart401 (devc);
-
   release_region (hw_config->io_base, 4);
 
   if (!devc->share_irq)
index bea0738a78e15bc2ba20f0fe37429e32a73d3a5d..f86b1389543735c53986b7589528884cfbaa048e 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
@@ -36,7 +36,7 @@ uart6850_status (void)
 static void 
 uart6850_cmd (unsigned char cmd)
 {
-  outb (cmd, COMDPORT);
+  outb ((cmd), COMDPORT);
 }
 static int 
 uart6850_read (void)
@@ -46,7 +46,7 @@ uart6850_read (void)
 static void 
 uart6850_write (unsigned char byte)
 {
-  outb (byte, DATAPORT);
+  outb ((byte), DATAPORT);
 }
 
 #define        OUTPUT_READY    0x02    /* Mask for data ready Bit */
@@ -138,7 +138,7 @@ uart6850_open (int dev, int mode,
   if (uart6850_opened)
     {
       printk ("Midi6850: Midi busy\n");
-      return -(EBUSY);
+      return -EBUSY;
     }
 
   ;
@@ -222,7 +222,7 @@ uart6850_end_read (int dev)
 static int
 uart6850_ioctl (int dev, unsigned cmd, caddr_t arg)
 {
-  return -(EINVAL);
+  return -EINVAL;
 }
 
 static void
index ad6a642f8e669207405410efef6e76217153ee46..bb2e93f42b2c053a8fe888d76b20b045569f4f70 100644 (file)
@@ -13,7 +13,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
index ecdc2a13e8591cd85e05eb96c0090c916f54a986..d12b39234b320e472ef4205cd3488664cf7ab2e9 100644 (file)
@@ -12,7 +12,7 @@
  *  affs regular file handling primitives
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/sched.h>
 #include <linux/affs_fs.h>
index 07456e499a92e21621790c6829f968adfe3132ae..e76d03ffaa82fdfbe111a5e5a9b6a33555beb4f8 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/major.h>
 #include <linux/blkdev.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 extern int *blk_size[];
 extern struct timezone sys_tz;
index 23f98bfc8090e9de238d5a27edca902f3598bdb9..0f4bced4398a9b7fc1d52dd864098ce00163e33f 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/fcntl.h>
 #include <linux/locks.h>
 #include <linux/amigaffs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 
index fe790ef5c04d69f5276b98d4df5ae3f4498278e3..734df0780e477f37a72f65a99c2d79391ad3721d 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/stat.h>
 #include <linux/affs_fs.h>
 #include <linux/amigaffs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 
index bef32136f83dc790929cf0cd93058a9376b44d52..cb535656a40719b6484c312057359860749b314b 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/personality.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
index 338a9f6604583046b1e2288eaa15381024c94f28..8087c84ae42a5f2239a2873c032580bf7e86703b 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/personality.h>
 #include <linux/elfcore.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 #include <linux/config.h>
@@ -98,65 +98,68 @@ unsigned long * create_elf_tables(char *p, int argc, int envc,
                                  unsigned long interp_load_addr, int ibcs)
 {
        char **argv, **envp;
-       unsigned long *dlinfo;
        unsigned long *sp;
 
        /*
         * Force 16 byte alignment here for generality.
         */
        sp = (unsigned long *) (~15UL & (unsigned long) p);
-       sp -= exec ? DLINFO_ITEMS*2 : 2;
-       dlinfo = sp;
+
+       /*
+        * Put the ELF interpreter info on the stack
+        */
+#define NEW_AUX_ENT(nr, id, val) \
+         __put_user ((id), sp+(nr*2)); \
+         __put_user ((val), sp+(nr*2+1)); \
+
+       sp -= 2;
+       NEW_AUX_ENT(0, AT_NULL, 0);
+
+       if (exec) {
+               sp -= 11*2;
+
+         NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
+         NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
+         NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
+         NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE);
+         NEW_AUX_ENT (4, AT_BASE, interp_load_addr);
+         NEW_AUX_ENT (5, AT_FLAGS, 0);
+         NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry);
+         NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid);
+         NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid);
+         NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid);
+         NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid);
+       }
+#undef NEW_AUX_ENT
+
        sp -= envc+1;
        envp = (char **) sp;
        sp -= argc+1;
        argv = (char **) sp;
        if (!ibcs) {
-               put_user((unsigned long) envp,--sp);
-               put_user((unsigned long) argv,--sp);
+               __put_user((unsigned long) envp,--sp);
+               __put_user((unsigned long) argv,--sp);
        }
 
-#define NEW_AUX_ENT(id, val) \
-         put_user ((id), dlinfo++); \
-         put_user ((val), dlinfo++)
-
-       if (exec) { /* Put this here for an ELF program interpreter */
-         struct elf_phdr * eppnt;
-         eppnt = (struct elf_phdr *) exec->e_phoff;
-
-         NEW_AUX_ENT (AT_PHDR, load_addr + exec->e_phoff);
-         NEW_AUX_ENT (AT_PHENT, sizeof (struct elf_phdr));
-         NEW_AUX_ENT (AT_PHNUM, exec->e_phnum);
-         NEW_AUX_ENT (AT_PAGESZ, PAGE_SIZE);
-         NEW_AUX_ENT (AT_BASE, interp_load_addr);
-         NEW_AUX_ENT (AT_FLAGS, 0);
-         NEW_AUX_ENT (AT_ENTRY, (unsigned long) exec->e_entry);
-         NEW_AUX_ENT (AT_UID, (unsigned long) current->uid);
-         NEW_AUX_ENT (AT_EUID, (unsigned long) current->euid);
-         NEW_AUX_ENT (AT_GID, (unsigned long) current->gid);
-         NEW_AUX_ENT (AT_EGID, (unsigned long) current->egid);
-       }
-       NEW_AUX_ENT (AT_NULL, 0);
-#undef NEW_AUX_ENT
-       put_user((unsigned long)argc,--sp);
+       __put_user((unsigned long)argc,--sp);
        current->mm->arg_start = (unsigned long) p;
        while (argc-->0) {
                char c;
-               put_user(p,argv++);
+               __put_user(p,argv++);
                do {
                        get_user(c,p++);
                } while (c);
        }
-       put_user(NULL, argv);
+       __put_user(NULL, argv);
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
        while (envc-->0) {
                char c;
-               put_user(p,envp++);
+               __put_user(p,envp++);
                do {
                        get_user(c,p++);
                } while (c);
        }
-       put_user(NULL, envp);
+       __put_user(NULL, envp);
        current->mm->env_end = (unsigned long) p;
        return sp;
 }
index 54c7857d5be33f66e00644d2c6e806302396cfe4..4d802f4e3cd0de765e91038170f7f3bfe1ba8cfd 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 extern int *blk_size[];
index 4c19eb8f8559bda34d284357d47c1806c0605978..c7f915c105399e6c3ec0b396b7f91544cd6061e2 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/vmalloc.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #define NR_SIZES 5
index 305bbdb5ecefe5a9cf0777edc46e37d6c584df64..2c8778995155eb811249d5ef8d09292bd672f4aa 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/malloc.h>
 #include <linux/mount.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define __DQUOT_VERSION__      "dquot_5.6.0"
 
index e99fe1dd938e812426bd408567cd9ca4b089c413..7e75f0cffef66485f5d7a52b68a957c32df42c44 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -40,7 +40,7 @@
 #include <linux/personality.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 #include <linux/config.h>
index 945dfb2136635171f0086e8912454435b59b8990..c6b04d26c8e34bc03039c8fbf289d93971f92d01 100644 (file)
@@ -12,7 +12,7 @@
  *  ext directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
index 3e0a1edbf6721018116aaaa4deb72b9b1752c227..6e298aa607051b2bfdd6a889a2b06f9f258c9d1a 100644 (file)
@@ -12,7 +12,7 @@
  *  ext regular file handling primitives
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/sched.h>
index fa8e2188fb2e15e9958c40f3e55bcb9f00b32599..c2385aac58036b8c3a6398f8c109e5fb916f56f5 100644 (file)
@@ -11,7 +11,7 @@
  *  extfs fsync primitive
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
index 13f3ac8078a1211a7dbd4d8a8b315503958a99a6..7ca1cd1725c80881eda9200561b1839ca03be2c8 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/locks.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 void ext_put_inode(struct inode *inode)
 {
index 7d537f91bdd3382f5c8b6ed78ed7252a9313b1c8..0bbb771fbef7f9c434eebd248ba899d07e72fef2 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * comment out this line if you want names > EXT_NAME_LEN chars to be
index c410205c74f90c25952b0dac97c2e12b1055bf65..6dd04439d44f5c1ad319ac4e88cd1d5a9ee315b2 100644 (file)
@@ -12,7 +12,7 @@
  *  ext symlink handling code
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
index 9153984f0b22a2b0626ac25c7835633563b7b54a..195fbf395b67947fec514d09e3618ca791a88472 100644 (file)
@@ -15,7 +15,7 @@
  *  ext2 directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index decacbb9a0a2b5605f292aa38971627f421927e5..e42badbede17b2d3961792bb4312988194a2def8 100644 (file)
@@ -15,7 +15,7 @@
  *  ext2 fs regular file handling primitives
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
index ad14d604ce1172dcab4f6386771311c46161a8c7..e9c1e286af7a9db7afc0789dd0972c1fc450ccdd 100644 (file)
@@ -12,7 +12,7 @@
  *  ext2fs fsync primitive
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
index 6d36f11c1b46ca056edd7cbd490d3dc422633c5e..85f17d02d5ea082b6b45ee94d8e9271b8f73a84d 100644 (file)
@@ -15,7 +15,7 @@
  *  Goal-directed block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
index 9390313af1f3f2bad854732501a283867bcbfda1..8235a63016b3f6b821abfd9ee6fc3dd7ee55ae2a 100644 (file)
@@ -7,7 +7,7 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index 048ea2f5c9991b6181d87b5f89ac907ea0971a64..2249eb1b86fd891d1d7c1b8984de60d777678bad 100644 (file)
@@ -13,7 +13,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index 3684297038d246111de6dccf2fc233d679256b9a..e9e5b90d52c1dfeb439641d3178990c02636ccec 100644 (file)
@@ -18,7 +18,7 @@
 #include <stdarg.h>
 
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
index 151642c3c1fdb0946563ac1b4ab7b34fbbe33ba8..461e038c2e5ea427869eab90e409e60d2b328014 100644 (file)
@@ -15,7 +15,7 @@
  *  ext2 symlink handling code
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
index c54782641d551057e0d5a4e10744e47b81ebfdd4..6938b7b9e6790a30e6bcb428f6a662b5a258732b 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/dirent.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "msbuffer.h"
 #include "tables.h"
index 584b75d6e1f1c0313a2d7a196409418b71f3a2cf..b9162f7d904d52f3411e3ec8027617f72e45fb49 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/string.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include "msbuffer.h"
index c8d6adeb23069ea85a05b6eacfc4b5b5bc833e65..f79192f0d501d6783eed746b710024798b0dbeb8 100644 (file)
@@ -22,7 +22,7 @@
 #include "msbuffer.h"
 #include "tables.h"
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 
index 779710c38a4b3f361797087c411b120ae709be77..7896a4cfe544272b842d994eaff4eae182b425e7 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/malloc.h>
 #include <linux/msdos_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
index b5dde216d920be7a225eaa87bc5d93d7653ecc6b..99a1638e1415f34ed76cde6c8b9993abd8be2711 100644 (file)
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -14,6 +12,7 @@
 #include <linux/string.h>
 
 #include <asm/bitops.h>
+#include <asm/uaccess.h>
 
 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 
index f69bb7e4775ef2831971fd4fd878babee5a2caaa..3d70172f516e9f711c040afc410262b60d05ffa0 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <asm/bitops.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "hpfs.h"
 #include "hpfs_caps.h"
index 29189e2459cf2a66412895b5537eacf5b21cba19..32dd02225596fecb0eaaefdd9ec48a86e611ee0f 100644 (file)
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
@@ -14,6 +12,8 @@
 #include <linux/termios.h>
 #include <linux/fcntl.h> /* for f_flags values */
 
+#include <asm/uaccess.h>
+
 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 {
        int error;
index 32b09355830bce3dfec4da8a870e8d9dfe6e3350..ea193d7b4e61d5118a67f8b3e8cc0b15f07df5ba 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/sched.h>
 #include <linux/locks.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
 
index 237aed1e1114d9d6532ee6c86b450c866a769988..086872bf24348dc0d0466439eca0fc381177e81c 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/cdrom.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * We have no support for "multi volume" CDs, but more and more disks carry
index 34e32270d3c035fe4503a3081c4bb51c5fbf88a1..8cdadf83684eefe02d4b0b7e5849255d04676ae2 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/malloc.h>
 
 #include <linux/errno.h>
index f37b4ce8942fd48993a6c7a2734962cbe6b2fea5..59489dc4b67b7b8ad393cad959ab21fb0a994d4c 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int isofs_readlink(struct inode *, char *, int);
 static int isofs_follow_link(struct inode *, struct inode *, int, int, struct inode **);
index 5ab22715665e10954274242d7e249df6c8b992d4..50f3709c747b46555585b479f32f7368ad97e758 100644 (file)
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define OFFSET_MAX     ((off_t)0x7fffffff)     /* FIXME: move elsewhere? */
 
index b779e483a5db93d64be1eaab084104fc747a4b5c..851d1f7da04951999f21090f2a0163a1c3643abf 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static long minix_dir_read(struct inode * inode, struct file * filp,
        char * buf, unsigned long count)
index af99d323456ebf132f59caf91a5374757db1d9bf..009bd09ed9a91f69203bc51fb5d8188bf253064e 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define        NBUF    32
index 44e9fb2a5186bc75a05c83f3d6538d876499d831..9510d63648c66e6984633d1d12f3e9d40eb8e128 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define blocksize BLOCK_SIZE
index 0e0d7f492e37b841aaf7d5e8222bdf7c3e47860f..e6fe65f48d6db5ead9000f5bb81b44a76b8e6172 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/locks.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 void minix_put_inode(struct inode *inode)
index 4e6b264f126057725418b1270d591422af73ca3d..c55d77fbcdf45dd96c0d156d522f0381ba01db84 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * comment out this line if you want names > info->s_namelen chars to be
index 87bb3570e800553a79cfd13b537d6c17ce5edef7..9a340ec9b2f021f49c9c1d99c81547f8dab14476 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/minix_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int minix_readlink(struct inode *, char *, int);
 static int minix_follow_link(struct inode *, struct inode *, int, int, struct inode **);
index 0e5d3ceda43a5ecab975e3ce1ef0522a4dada602..e34e5de5b1f7215b9b507bc0e0b7778876bf86a2 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "../fat/msbuffer.h"
 
index fc0a000bb1987784bda62f65824ca085ef775c33..176c1c8393996058f8c04fd2ba81139459cf3d56 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
index 3596c4c33987ab0f8a6c3e2177721863a6e3af2e..ede71765f13dbbd5fb5f514a7619d53732aaaa58 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/ncp_fs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include "ncplib_kernel.h"
index 0b8f7cf7a981c59d00b0c1ae49c6cd680dc9d4da..12b646f91a5efb0afcd439feef0a189e38b00ef6 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/sched.h>
index d6f11c0cb16d6348b2cb3078013da3e3d2826bc9..55a0c4aae1f1330acb6320709658250fe9044c15 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/config.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/sched.h>
 #include <linux/ncp_fs.h>
index 17187f63c41b946fee77254f2505338104f756d0..e7d8aa7db07eba566e4519787ea227c4c3af9490 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ncp_fs.h>
index 798c706f6a182f6af371612100e2b18631d86d95..c7b828dc64beb126c483a06d4a9aff0fe5c961f3 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/ncp_fs.h>
 
 #include "ncplib_kernel.h"
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static inline int min(int a, int b)
index 0a4695c3ceecd9e9c02bd1c9a006e01044324ece..b8017a9d2d98139980a35e566f8ffe5be8a50405 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/socket.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/in.h>
 #include <linux/net.h>
 #include <linux/mm.h>
index 0b7533ec6be449dae69c4fb022035b7c4c710925..178f8cc28d50519c58f0954f8b9455912575754d 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/malloc.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #undef DEBUG_BIO
index 708519827cff56d856a97234967b10f3d87a72e5..8f16dc7996f087a57448b1e85a35b7fd8ae81862 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>       /* for fs functions */
+#include <asm/uaccess.h>       /* for fs functions */
 
 static int nfs_dir_open(struct inode * inode, struct file * file);
 static long nfs_dir_read(struct inode *, struct file *, char *, unsigned long);
index 8e7dc8c0cbbe219de2cc964cf9e99e2371056226..e6b02185cbf2179a2681e8e4a49b2fd4a964164d 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/malloc.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static int nfs_file_mmap(struct inode *, struct file *, struct vm_area_struct *);
index 6c62f419e1fe766c9af69c74f7cbbedd055df938..e47227011c403681fc56dbc49e2b497191f56d50 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/smp_lock.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* This is for kernel_thread */
 #define __KERNEL_SYSCALLS__
index 8b2dc39e04ec02055e6f071b0b807cdc10396333..8de01295d294e60656234768911bdb45230b3315 100644 (file)
@@ -92,7 +92,7 @@
 #include <net/route.h>
 #include <net/sock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* Range of privileged ports */
 #define STARTPORT      600
index f06f57a6fd547a0882e24d2c4adcde1fa90241ba..207021883f3314d8bc5508ef778b8f4b84168e3e 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/in.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef NFS_PROC_DEBUG
 
index 3a875f212d2250b72eabbdb3ac08943e38de8c5d..f627237d5f9e91cf640f031d3930eed39a2d3b4f 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/udp.h>
 #include <net/sock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define msleep(sec)    { current->timeout = sec * HZ / 1000; \
                          current->state = TASK_INTERRUPTIBLE; \
index 702fb4b1e428b5859e6e240be1de786bd0866c35..745a336394c21872d29c3fa7973c6262f4c73a3c 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/mm.h>
 #include <linux/rpcsock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
index 5421da3c683b5bf801aaed866c2a8486a263904b..e628e0182a5ab4252d9d6b1d02a13f8e70e968c3 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/malloc.h>
 #include <linux/string.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int nfs_readlink(struct inode *, char *, int);
 static int nfs_follow_link(struct inode *, struct inode *, int, int,
index 1e4c8e311c53644c5923c0d165877d3e6548396e..124c467b5336da288052436751ca3a33c771e061 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/malloc.h>
 #include <linux/mount.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifndef min
 #define min(a,b) ((a) < (b)) ? (a) : (b)
index be059d41744b26fe9318c3e8b1fb9fea340422d9..8ab0614a70df7b014ebfbe89d842ba164c41f058 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -19,7 +19,7 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
index 758770baf381648d40f4fa260dc0edf19d11d766..2f3c30916dbba2ce09b3fa1228431695c843a60a 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -14,6 +12,8 @@
 #include <linux/termios.h>
 #include <linux/mm.h>
 
+#include <asm/uaccess.h>
+
 /*
  * Define this if you want SunOS compatibility wrt braindead
  * select behaviour on FIFO's.
index ee7870918af76bd89a411fbee63b10d66932054c..d720f561578db7903f32f92981fc4456ae46b05f 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
index dc781cbb526d42bc33b9a629819fa2b18651edcf..2b6eece4a831b6c49b862f8ab4879b827c0996fe 100644 (file)
@@ -6,7 +6,7 @@
  *  proc base directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
index 98a3b926616d878f41a13d48fa23b8684f4c85a5..8d42018445890250d4a56cba4a5d5e3cae1d0191 100644 (file)
@@ -6,7 +6,7 @@
  *  proc fd directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
index 7be47de160045d738f07b74db48da4d8c9e90d56..73eb4a3937961fa52b5d358f6a7cd5ac2cac1bda 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/limits.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static void proc_put_inode(struct inode *inode)
 {
index 8b58cb13be193a5d7da104752a47a161b2a4df79..add112153990b98e7b6708320d876c91d3f3e076 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 extern unsigned long log_size;
index 44e59576ece87a567d795411c2373f5ca1be2d4b..cd79cce0734ba49bfe30d571b62ce04715688ac8 100644 (file)
@@ -6,7 +6,7 @@
  *  /proc link-file handling code
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
index 2094763b8cd3dd97156d46a840d00c05c690c28c..0a0ac25e9abf8514a2975f670fa241402b84a85a 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/mm.h>
 
 #include <asm/page.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
index 3cc8e6c967d04e770fbfb563252fa78667deb00d..7f11b86968c693194903fba84a58f0b3589c3e02 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/fcntl.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PROC_BLOCK_SIZE        (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 
index acbc9693eb1ec17ff9fc76ba01cdad2767b457aa..70150f5871e4a284d697f02f4e7bc3de7b561541 100644 (file)
@@ -6,7 +6,7 @@
  *  proc root directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
index b74ba73d656293078f0f4dac66fddba4ca8de849..447314eab3afb4a6092c2eafe50622dec1453939 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* forward references */
 static long proc_readscsi(struct inode * inode, struct file * file,
index bf53907738a5264623ec64acd08de998a3b7c1de..6c28b8f5961f3a1fc0ed634322b0c5bf4b70426f 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 #include <linux/uio.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static long long default_llseek(struct inode *inode,
        struct file *file,
index 38271eb3a0b570677cfcadb357d69201d56dcb67..e81415644cd53cf3b763d9a470fc55f1ebc1db08 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * Traditional linux readdir() handling..
index 4ccc605ca9282e4716f42d7b4eab8e65d9ab6349..5ffb84f8614d69f016121f7d9c1d148c2d79f95e 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/personality.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
index abe477fbd67f7d99c16a217b995a09e508a563b7..aa945bb4431b91be012b27192e070e3ba3b0a82d 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/malloc.h>
 #include <linux/mm.h>
 #include <linux/smb_fs.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
index 9a9bb552c7c6d79c21cd8c3ac149d2bee5cd9514..754180e1f3f16c4025ef51b7ab390c7a224d38b1 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/sched.h>
index 490f4144ad1d986339f7496d929c0f8ea5e39a40..695d92c466d81d66ebb9ad52952bf382905b6e7d 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <linux/sched.h>
 #include <linux/smb_fs.h>
index 045f99b521cb381c6d1c8fe4f84c7b1b36fabee6..b62a6e06dc7ce29d946dd4fe68f5d87ef06846e3 100644 (file)
@@ -5,7 +5,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/smb_fs.h>
index 1baec2a0ba5c8d0d8932f5fc2381ea796c495a91..d790c4bce9f536ccf19e687493bcdbfba4e1572c 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/smb_fs.h>
 #include <linux/fcntl.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
index edbee623f980e63dd2a404525e301dbde439f484..6d146e9e5025ec8167ebbd52b924b5acdfa16126 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/malloc.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/string.h>
 
 #define ARCH i386
index 603fe80c2c98511b88c6e213d0d3ad65e916cd2f..38998ce5453b17fc5f0b4cbf321a86fef0547fdb 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/socket.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/in.h>
 #include <linux/net.h>
 #include <linux/mm.h>
index 4a5c180f29c04def21219bb7c783b2eeb6181771..3ea223e58457195df0a10f9a0cee4bda33893aae 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifndef __alpha__
 
index cd18b0440d015a743c45abccf09e0d4bacb20f77..3665858b575bcbfae9b20d1d58b3c02b0aeccdb4 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/fd.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #ifdef CONFIG_KERNELD
index 8cece496ee00a0e2bacf3bacb94d078f42f546d1..52515b4f9ba5ad75055524df1dce1cc78c553809 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static long sysv_dir_read(struct inode * inode, struct file * filp,
        char * buf, unsigned long count)
index 839ffef79fe02d7477bde3971d39dc3630481a41..6029051d8a4d26e4c1f4bb737aba518f60b0462b 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/locks.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define        NBUF    32
 
index 1a3830f6b934c9f1470727c9e7f1911cbdf196b2..4e14cb35ede84628b59dd3e74cad13d0d37384e9 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/string.h>
 #include <linux/locks.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 void sysv_put_inode(struct inode *inode)
 {
index 85524a6483d90941103b719118cc6f488de81daa..9a33d9fab88704fcc66d3c7e7a4cff97f10ac493 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/sysv_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int sysv_readlink(struct inode *, char *, int);
 static int sysv_follow_link(struct inode *, struct inode *, int, int, struct inode **);
index 0f769728bdf5dbe9851ee3628bcbcc80d9aa5262..11657c704d86da5f7f3d636e03215ea4092d0bc8 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/ufs_fs.h>
 #include <linux/locks.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 int ufs_need_swab = 0;
 
index 6ac977caf5a690c098407d5df79b929bb30fc1b9..35322983ee3f5ccbfc4537c801a94eaf2525ebb5 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/ufs_fs.h>
 #include <linux/sched.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int
 ufs_readlink(struct inode * inode, char * buffer, int buflen)
index 0abc12d36054c56c649fea0562a0953f076955ef..9e0abf55af80671236ff95f9d87ad2fc72620fea 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
index 74baeb27dab8be5d773a83cb625751aaec2b7d30..6295d0a9846046d0d8aa33ec9ee33efb3b0dbeb5 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
index 075d4abc8d366b3bf0f94b342a4601941171ce01..d01ef6f87136926e566345947aaf61f699ac86b1 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define PRINTK(x)
index 34f80b7fe2a6c100718e8f44588568b10ae842f9..8157edca6cdc373210c8f0a6c1d35d73c488fc4c 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/umsdos_fs.h>
index b900f24822bc8a45dd483ce580b13dea66959344..a4d4108b8509c1fabc5188866193e352e8f49713 100644 (file)
@@ -6,7 +6,7 @@
  *  Extended MS-DOS ioctl directory handling functions
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
index bf393835bef4df0afae6b9d8fd7e986ca2679e00..da07c0d6198d82d1dc81e19c2438cd36bb99f50e 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
index e69acf2e2a5c3af1fa361c88b55124689f9528f1..7bbcc0ef0b1daeca7f201c4fc32afc1c80b3bb0c 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/umsdos_fs.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #define PRINTK(x)
index 77576ac1bc1853ad9ddb4d7934b7606478d3ef36..f0d5817717bc9548e891fc9907ba227151b83b5a 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "../fat/msbuffer.h"
 #include "../fat/tables.h"
index 148420e86a930adae62d6a53f356dffe076284cc..856d3cdcdf9d1551023ea1f44620100b05ece9d8 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/xia_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "xiafs_mac.h"
 
index b8eaac01567810bebcd087fda1e955bfbb2a257d..822b4b520618fb175fb26e2de7bc08bd06e868bf 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/locks.h>
 #include <linux/pagemap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include "xiafs_mac.h"
index e9e5505d779327bbacd926dd68ed079c36f3f27f..f491e3d8eadf2ce0248a65f58c70c71f0cd4fc86 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/fs.h>
 #include <linux/xia_fs.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include "xiafs_mac.h"
index cc4ddd87a7b936d89d656195f8247767c4e2fe84..48b31e9724eb8c849b12d3041becb836461a05cf 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "xiafs_mac.h"
 
index 06365b9c2ba1c628ac1905316687ee82fa75c56a..b23c4bf7132c34a6a4081338127000116054d561 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include "xiafs_mac.h"
 
index 2a58e8ee19138b99f50b1c2f5f53138a08a55c2f..1803ae45762384f167e1b0298c47a90f8f712fac 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/xia_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 static int 
 xiafs_readlink(struct inode *, char *, int);
index 7c57cc01a0b01af2b14cfa48453ad51dd84e86a8..0453d97daae7b4399ac1fae0ad7e194143f9b70d 100644 (file)
@@ -1,300 +1,6 @@
-#ifndef _ASM_SEGMENT_H
-#define _ASM_SEGMENT_H
+#ifndef __ALPHA_SEGMENT_H
+#define __ALPHA_SEGMENT_H
 
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- *
- * For historical reasons, these macros are grossly misnamed.
- */
+/* Only here because we have some old header files that expect it.. */
 
-#define KERNEL_DS      0
-#define USER_DS                1
-
-#define get_fs()  (current->tss.flags & 0x1)
-#define set_fs(x) (current->tss.flags = (current->tss.flags & ~0x1) | ((x) & 0x1))
-
-static inline unsigned long get_ds(void)
-{
-       return 0;
-}
-
-/*
- * Is a address valid? This does a straighforward calculation rather
- * than tests.
- *
- * Address valid if:
- *  - "addr" doesn't have any high-bits set
- *  - AND "size" doesn't have any high-bits set
- *  - AND "addr+size" doesn't have any high-bits set
- *  - OR we are in kernel mode.
- */
-#define __access_ok(addr,size,mask) \
-       (((mask)&((addr | size | (addr+size)) >> 42))==0)
-#define __access_mask (-(long)get_fs())
-
-#define access_ok(type,addr,size) \
-       __access_ok(((unsigned long)(addr)),(size),__access_mask)
-
-/*
- * These are the main single-value transfer routines.  They automatically
- * use the right size if we just have the right pointer type.
- *
- * As the alpha uses the same address space for kernel and user
- * data, we can just do these as direct assignments.  (Of course, the
- * exception handling means that it's no longer "just"...)
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof/typeof is ok)
- * (b) require any knowledge of processes at this stage
- */
-#define put_user(x,ptr)        __put_user((x),(ptr),sizeof(*(ptr)),__access_mask)
-#define get_user(x,ptr) __get_user((x),(ptr),sizeof(*(ptr)),__access_mask)
-
-#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
-#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
-
-/*
- * Not pretty? What do you mean not "not pretty"?
- */
-extern void __copy_user(void);
-
-#define __copy_tofrom_user(to,from,n,v)                                            \
-({                                                                         \
-       register void * __cu_to __asm__("$6") = (to);                       \
-       register const void * __cu_from __asm__("$7") = (from);             \
-       register long __cu_len __asm__("$0") = (n);                         \
-       if (__access_ok(((long)(v)),__cu_len,__access_mask)) {              \
-               register void * __cu_ex __asm__("$8");                      \
-               __cu_ex = &current->tss.ex;                                 \
-               __asm__ __volatile__(                                       \
-                       "jsr $28,(%7),__copy_user"                          \
-                       : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) \
-                       : "0" (__cu_len), "1" (__cu_from), "2" (__cu_to),   \
-                         "r" (__cu_ex), "r" (__copy_user)                  \
-                       : "$1","$2","$3","$4","$5","$28","memory");         \
-       }                                                                   \
-       __cu_len;                                                           \
-})
-
-extern void __get_user_unknown(void);
-
-#define __get_user(x,ptr,size,mask)                            \
-({                                                             \
-       long __gu_err = -EFAULT, __gu_val = 0;                  \
-       const __typeof__(*(ptr)) *__gu_addr = (ptr);            \
-       if (__access_ok((long)__gu_addr,size,mask)) {           \
-               long __gu_ex_count = current->tss.ex.count;     \
-               switch (size) {                                 \
-               case 1: __get_user_8; break;                    \
-               case 2: __get_user_16; break;                   \
-               case 4: __get_user_32; break;                   \
-               case 8: __get_user_64; break;                   \
-               default: __get_user_unknown(); break;           \
-               }                                               \
-       }                                                       \
-       (x) = (__typeof__(*(ptr))) __gu_val;                    \
-       __gu_err;                                               \
-})
-
-#define __get_user_64                                                     \
-       __asm__("/* Inline __get_user_64 */\n\t"                           \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "br 2f\n"               /* exception! */                   \
-               "1:\t"                                                     \
-               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
-               "ldq %1,%2\n\t"         /* actual data load */             \
-               "stq %4,%3\n\t"         /* restore exception count */      \
-               "clr %0\n"              /* no exception: error = 0 */      \
-               "2:\t/* End __get_user_64 */"                              \
-               : "=r"(__gu_err), "=r"(__gu_val)                           \
-               : "m"(*__gu_addr), "m"(current->tss.ex.count),             \
-                 "r"(__gu_ex_count), "r"(__gu_ex_count+1),                \
-                 "0"(__gu_err), "1"(__gu_val)                             \
-               : "$28")
-
-#define __get_user_32                                                     \
-       __asm__("/* Inline __get_user_32 */\n\t"                           \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "br 2f\n"               /* exception! */                   \
-               "1:\t"                                                     \
-               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
-               "ldl %1,%2\n\t"         /* actual data load */             \
-               "stq %4,%3\n\t"         /* restore exception count */      \
-               "clr %0\n"              /* no exception: error = 0 */      \
-               "2:\t/* End __get_user_32 */"                              \
-               : "=r"(__gu_err), "=r"(__gu_val)                           \
-               : "m"(*__gu_addr), "m"(current->tss.ex.count),             \
-                 "r"(__gu_ex_count), "r"(__gu_ex_count+1),                \
-                 "0"(__gu_err), "1"(__gu_val)                             \
-               : "$28")
-
-#define __get_user_16                                                     \
-       __asm__("/* Inline __get_user_16 */\n\t"                           \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "br 2f\n"               /* exception! */                   \
-               "1:\t"                                                     \
-               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
-               "ldq_u %1,%2\n\t"       /* actual data load */             \
-               "stq %5,%4\n\t"         /* restore exception count */      \
-               "clr %0\n\t"            /* no exception: error = 0 */      \
-               "extwl %1,%3,%1\n"      /* extract the short */            \
-               "2:\t/* End __get_user_16 */"                              \
-               : "=r"(__gu_err), "=r"(__gu_val)                           \
-               : "m"(*__gu_addr), "r"(__gu_addr),                         \
-                 "m"(current->tss.ex.count), "r"(__gu_ex_count),          \
-                 "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)       \
-               : "$28")
-
-#define __get_user_8                                                      \
-       __asm__("/* Inline __get_user_8 */\n\t"                            \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "br 2f\n"               /* exception! */                   \
-               "1:\t"                                                     \
-               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
-               "ldq_u %1,%2\n\t"       /* actual data load */             \
-               "stq %5,%4\n\t"         /* restore exception count */      \
-               "clr %0\n\t"            /* no exception: error = 0 */      \
-               "extbl %1,%3,%1\n"      /* extract the byte */             \
-               "2:\t/* End __get_user_8 */"                               \
-               : "=r"(__gu_err), "=r"(__gu_val)                           \
-               : "m"(*__gu_addr), "r"(__gu_addr),                         \
-                 "m"(current->tss.ex.count), "r"(__gu_ex_count),          \
-                 "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)       \
-               : "$28")
-
-extern void __put_user_unknown(void);
-
-#define __put_user(x,ptr,size,mask)                            \
-({                                                             \
-       long __pu_err = -EFAULT;                                \
-       __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
-        __typeof__(*(ptr)) __pu_val = (x);                     \
-       if (__access_ok((long)__pu_addr,size,mask)) {           \
-               long __pu_ex_count = current->tss.ex.count;     \
-               switch (size) {                                 \
-               case 1: __put_user_8; break;                    \
-               case 2: __put_user_16; break;                   \
-               case 4: __put_user_32; break;                   \
-               case 8: __put_user_64; break;                   \
-               default: __put_user_unknown(); break;           \
-               }                                               \
-       }                                                       \
-       __pu_err;                                               \
-})
-
-#define __put_user_64                                                     \
-       __asm__("/* Inline __put_user_64 */\n\t"                           \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "br 2f\n"               /* exception! */                   \
-               "1:\t"                                                     \
-               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
-               "stq %2,%1\n\t"         /* actual data store */            \
-               "stq %4,%3\n\t"         /* restore exception count */      \
-               "clr %0\n"              /* no exception: error = 0 */      \
-               "2:\t/* End __put_user_64 */"                              \
-               : "=r"(__pu_err), "=m"(*__pu_addr)                         \
-               : "r"(__pu_val), "m"(current->tss.ex.count),               \
-                 "r"(__pu_ex_count), "r"(__pu_ex_count+1),                \
-                 "0"(__pu_err)                                            \
-               : "$28")
-
-#define __put_user_32                                                     \
-       __asm__("/* Inline __put_user_32 */\n\t"                           \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "br 2f\n"               /* exception! */                   \
-               "1:\t"                                                     \
-               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
-               "stl %2,%1\n\t"         /* actual data store */            \
-               "stq %4,%3\n\t"         /* restore exception count */      \
-               "clr %0\n"              /* no exception: error = 0 */      \
-               "2:\t/* End __put_user_32 */"                              \
-               : "=r"(__pu_err), "=m"(*__pu_addr)                         \
-               : "r"(__pu_val), "m"(current->tss.ex.count),               \
-                 "r"(__pu_ex_count), "r"(__pu_ex_count+1),                \
-                 "0"(__pu_err)                                            \
-               : "$28")
-
-#define __put_user_16                                                     \
-       __asm__("/* Inline __put_user_16 */\n\t"                           \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "lda %0,%7\n\t"         /* exception! error = -EFAULT */   \
-               "br 2f\n"                                                  \
-               "1:\t"                                                     \
-               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
-               "ldq_u %0,%1\n\t"       /* masked data store */            \
-               "inswl %2,%3,%2\n\t"                                       \
-               "mskwl %0,%3,%0\n\t"                                       \
-               "or %0,%2,%2\n\t"                                          \
-               "stq_u %2,%1\n\t"                                          \
-               "stq %5,%4\n\t"         /* restore exception count */      \
-               "clr %0\n"              /* no exception: error = 0 */      \
-               "2:\t/* End __put_user_16 */"                              \
-               : "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)         \
-               : "r"(__pu_addr), "m"(current->tss.ex.count),              \
-                 "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
-                 "2"(__pu_val)                                            \
-               : "$28")
-
-#define __put_user_8                                                      \
-       __asm__("/* Inline __put_user_8 */\n\t"                            \
-               "br $28,1f\n\t"         /* set up exception address */     \
-               "lda %0,%7\n\t"         /* exception! error = -EFAULT */   \
-               "br 2f\n"                                                  \
-               "1:\t"                                                     \
-               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
-               "ldq_u %0,%1\n\t"       /* masked data store */            \
-               "insbl %2,%3,%2\n\t"                                       \
-               "mskbl %0,%3,%0\n\t"                                       \
-               "or %0,%2,%2\n\t"                                          \
-               "stq_u %2,%1\n\t"                                          \
-               "stq %5,%4\n\t"         /* restore exception count */      \
-               "clr %0\n"              /* no exception: error = 0 */      \
-               "2:\t/* End __put_user_8 */"                               \
-               : "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)         \
-               : "r"(__pu_addr), "m"(current->tss.ex.count),              \
-                 "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
-                 "2"(__pu_val)                                            \
-               : "$28")
-
-
-extern void __clear_user(void);
-
-#define clear_user(to,n)                                               \
-({                                                                     \
-       register void * __cl_to __asm__("$6") = (to);                   \
-       register long __cl_len __asm__("$0") = (n);                     \
-       if (__access_ok(((long)__cl_to),__cl_len,__access_mask)) {      \
-               register void * __cl_ex __asm__("$7");                  \
-               __cl_ex = &current->tss.ex;                             \
-               __asm__ __volatile__(                                   \
-                       "jsr $28,(%2),__clear_user"                     \
-                       : "=r"(__cl_len), "=r"(__cl_to)                 \
-                       : "r"(__clear_user), "r"(__cl_ex),              \
-                         "0"(__cl_len), "1"(__cl_to)                   \
-                       : "$1","$2","$3","$4","$5","$28","memory");     \
-       }                                                               \
-       __cl_len;                                                       \
-})
-
-
-/* Returns: -EFAULT if exception before terminator, N if the entire
-   buffer filled, else strlen.  */
-
-struct exception_struct;
-extern long __strncpy_from_user(char *__to, const char *__from,
-                               long __to_len, struct exception_struct *);
-
-#define strncpy_from_user(to,from,n)                                         \
-({                                                                           \
-       char * __sfu_to = (to);                                               \
-       const char * __sfu_from = (from);                                     \
-       long __sfu_len = (n), __sfu_ret = -EFAULT;                            \
-       if (__access_ok(((long)__sfu_from),__sfu_len,__access_mask)) {        \
-               __sfu_ret = __strncpy_from_user(__sfu_to,__sfu_from,          \
-                                               __sfu_len, &current->tss.ex); \
-       __sfu_ret;                                                            \
-})
-
-#endif /* _ASM_SEGMENT_H */
+#endif
diff --git a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h
new file mode 100644 (file)
index 0000000..4bc459a
--- /dev/null
@@ -0,0 +1,348 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define KERNEL_DS      0
+#define USER_DS                1
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+#define get_fs()  (current->tss.flags & 0x1)
+#define set_fs(x) (current->tss.flags = (current->tss.flags & ~0x1) | ((x) & 0x1))
+
+static inline unsigned long get_ds(void)
+{
+       return 0;
+}
+
+/*
+ * Is a address valid? This does a straighforward calculation rather
+ * than tests.
+ *
+ * Address valid if:
+ *  - "addr" doesn't have any high-bits set
+ *  - AND "size" doesn't have any high-bits set
+ *  - AND "addr+size" doesn't have any high-bits set
+ *  - OR we are in kernel mode.
+ */
+#define __access_ok(addr,size,mask) \
+       (((mask)&((addr | size | (addr+size)) >> 42))==0)
+#define __access_mask (-(long)get_fs())
+
+#define access_ok(type,addr,size) \
+       __access_ok(((unsigned long)(addr)),(size),__access_mask)
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * As the alpha uses the same address space for kernel and user
+ * data, we can just do these as direct assignments.  (Of course, the
+ * exception handling means that it's no longer "just"...)
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof/typeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)        __put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
+#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
+
+/*
+ * Not pretty? What do you mean not "not pretty"?
+ */
+extern void __copy_user(void);
+
+#define __copy_tofrom_user(to,from,n,v)                                            \
+({                                                                         \
+       register void * __cu_to __asm__("$6") = (to);                       \
+       register const void * __cu_from __asm__("$7") = (from);             \
+       register long __cu_len __asm__("$0") = (n);                         \
+       if (__access_ok(((long)(v)),__cu_len,__access_mask)) {              \
+               register void * __cu_ex __asm__("$8");                      \
+               __cu_ex = &current->tss.ex;                                 \
+               __asm__ __volatile__(                                       \
+                       "jsr $28,(%7),__copy_user"                          \
+                       : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) \
+                       : "0" (__cu_len), "1" (__cu_from), "2" (__cu_to),   \
+                         "r" (__cu_ex), "r" (__copy_user)                  \
+                       : "$1","$2","$3","$4","$5","$28","memory");         \
+       }                                                                   \
+       __cu_len;                                                           \
+})
+
+extern void __get_user_unknown(void);
+
+#define __get_user_nocheck(x,ptr,size)                         \
+({                                                             \
+       long __gu_err = -EFAULT, __gu_val = 0;                  \
+       const __typeof__(*(ptr)) *__gu_addr = (ptr);            \
+       long __gu_ex_count = current->tss.ex.count;             \
+       switch (size) {                                         \
+       case 1: __get_user_8; break;                            \
+       case 2: __get_user_16; break;                           \
+       case 4: __get_user_32; break;                           \
+       case 8: __get_user_64; break;                           \
+       default: __get_user_unknown(); break;                   \
+       }                                                       \
+       (x) = (__typeof__(*(ptr))) __gu_val;                    \
+       __gu_err;                                               \
+})
+
+#define __get_user_check(x,ptr,size,mask)                      \
+({                                                             \
+       long __gu_err = -EFAULT, __gu_val = 0;                  \
+       const __typeof__(*(ptr)) *__gu_addr = (ptr);            \
+       if (__access_ok((long)__gu_addr,size,mask)) {           \
+               long __gu_ex_count = current->tss.ex.count;     \
+               switch (size) {                                 \
+               case 1: __get_user_8; break;                    \
+               case 2: __get_user_16; break;                   \
+               case 4: __get_user_32; break;                   \
+               case 8: __get_user_64; break;                   \
+               default: __get_user_unknown(); break;           \
+               }                                               \
+       }                                                       \
+       (x) = (__typeof__(*(ptr))) __gu_val;                    \
+       __gu_err;                                               \
+})
+
+#define __get_user_64                                                     \
+       __asm__("/* Inline __get_user_64 */\n\t"                           \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "br 2f\n"               /* exception! */                   \
+               "1:\t"                                                     \
+               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
+               "ldq %1,%2\n\t"         /* actual data load */             \
+               "stq %4,%3\n\t"         /* restore exception count */      \
+               "clr %0\n"              /* no exception: error = 0 */      \
+               "2:\t/* End __get_user_64 */"                              \
+               : "=r"(__gu_err), "=r"(__gu_val)                           \
+               : "m"(*__gu_addr), "m"(current->tss.ex.count),             \
+                 "r"(__gu_ex_count), "r"(__gu_ex_count+1),                \
+                 "0"(__gu_err), "1"(__gu_val)                             \
+               : "$28")
+
+#define __get_user_32                                                     \
+       __asm__("/* Inline __get_user_32 */\n\t"                           \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "br 2f\n"               /* exception! */                   \
+               "1:\t"                                                     \
+               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
+               "ldl %1,%2\n\t"         /* actual data load */             \
+               "stq %4,%3\n\t"         /* restore exception count */      \
+               "clr %0\n"              /* no exception: error = 0 */      \
+               "2:\t/* End __get_user_32 */"                              \
+               : "=r"(__gu_err), "=r"(__gu_val)                           \
+               : "m"(*__gu_addr), "m"(current->tss.ex.count),             \
+                 "r"(__gu_ex_count), "r"(__gu_ex_count+1),                \
+                 "0"(__gu_err), "1"(__gu_val)                             \
+               : "$28")
+
+#define __get_user_16                                                     \
+       __asm__("/* Inline __get_user_16 */\n\t"                           \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "br 2f\n"               /* exception! */                   \
+               "1:\t"                                                     \
+               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
+               "ldq_u %1,%2\n\t"       /* actual data load */             \
+               "stq %5,%4\n\t"         /* restore exception count */      \
+               "clr %0\n\t"            /* no exception: error = 0 */      \
+               "extwl %1,%3,%1\n"      /* extract the short */            \
+               "2:\t/* End __get_user_16 */"                              \
+               : "=r"(__gu_err), "=r"(__gu_val)                           \
+               : "m"(*__gu_addr), "r"(__gu_addr),                         \
+                 "m"(current->tss.ex.count), "r"(__gu_ex_count),          \
+                 "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)       \
+               : "$28")
+
+#define __get_user_8                                                      \
+       __asm__("/* Inline __get_user_8 */\n\t"                            \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "br 2f\n"               /* exception! */                   \
+               "1:\t"                                                     \
+               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
+               "ldq_u %1,%2\n\t"       /* actual data load */             \
+               "stq %5,%4\n\t"         /* restore exception count */      \
+               "clr %0\n\t"            /* no exception: error = 0 */      \
+               "extbl %1,%3,%1\n"      /* extract the byte */             \
+               "2:\t/* End __get_user_8 */"                               \
+               : "=r"(__gu_err), "=r"(__gu_val)                           \
+               : "m"(*__gu_addr), "r"(__gu_addr),                         \
+                 "m"(current->tss.ex.count), "r"(__gu_ex_count),          \
+                 "r"(__gu_ex_count+1), "0"(__gu_err), "1"(__gu_val)       \
+               : "$28")
+
+extern void __put_user_unknown(void);
+
+#define __put_user_nocheck(x,ptr,size)                         \
+({                                                             \
+       long __pu_err = -EFAULT;                                \
+       __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
+        __typeof__(*(ptr)) __pu_val = (x);                     \
+       long __pu_ex_count = current->tss.ex.count;             \
+       switch (size) {                                         \
+       case 1: __put_user_8; break;                            \
+       case 2: __put_user_16; break;                           \
+       case 4: __put_user_32; break;                           \
+       case 8: __put_user_64; break;                           \
+       default: __put_user_unknown(); break;                   \
+       }                                                       \
+       __pu_err;                                               \
+})
+
+#define __put_user_check(x,ptr,size,mask)                      \
+({                                                             \
+       long __pu_err = -EFAULT;                                \
+       __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
+        __typeof__(*(ptr)) __pu_val = (x);                     \
+       if (__access_ok((long)__pu_addr,size,mask)) {           \
+               long __pu_ex_count = current->tss.ex.count;     \
+               switch (size) {                                 \
+               case 1: __put_user_8; break;                    \
+               case 2: __put_user_16; break;                   \
+               case 4: __put_user_32; break;                   \
+               case 8: __put_user_64; break;                   \
+               default: __put_user_unknown(); break;           \
+               }                                               \
+       }                                                       \
+       __pu_err;                                               \
+})
+
+#define __put_user_64                                                     \
+       __asm__("/* Inline __put_user_64 */\n\t"                           \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "br 2f\n"               /* exception! */                   \
+               "1:\t"                                                     \
+               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
+               "stq %2,%1\n\t"         /* actual data store */            \
+               "stq %4,%3\n\t"         /* restore exception count */      \
+               "clr %0\n"              /* no exception: error = 0 */      \
+               "2:\t/* End __put_user_64 */"                              \
+               : "=r"(__pu_err), "=m"(*__pu_addr)                         \
+               : "r"(__pu_val), "m"(current->tss.ex.count),               \
+                 "r"(__pu_ex_count), "r"(__pu_ex_count+1),                \
+                 "0"(__pu_err)                                            \
+               : "$28")
+
+#define __put_user_32                                                     \
+       __asm__("/* Inline __put_user_32 */\n\t"                           \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "br 2f\n"               /* exception! */                   \
+               "1:\t"                                                     \
+               "stq %5,%3\n\t"         /* store inc'ed exception count */ \
+               "stl %2,%1\n\t"         /* actual data store */            \
+               "stq %4,%3\n\t"         /* restore exception count */      \
+               "clr %0\n"              /* no exception: error = 0 */      \
+               "2:\t/* End __put_user_32 */"                              \
+               : "=r"(__pu_err), "=m"(*__pu_addr)                         \
+               : "r"(__pu_val), "m"(current->tss.ex.count),               \
+                 "r"(__pu_ex_count), "r"(__pu_ex_count+1),                \
+                 "0"(__pu_err)                                            \
+               : "$28")
+
+#define __put_user_16                                                     \
+       __asm__("/* Inline __put_user_16 */\n\t"                           \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "lda %0,%7\n\t"         /* exception! error = -EFAULT */   \
+               "br 2f\n"                                                  \
+               "1:\t"                                                     \
+               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
+               "ldq_u %0,%1\n\t"       /* masked data store */            \
+               "inswl %2,%3,%2\n\t"                                       \
+               "mskwl %0,%3,%0\n\t"                                       \
+               "or %0,%2,%2\n\t"                                          \
+               "stq_u %2,%1\n\t"                                          \
+               "stq %5,%4\n\t"         /* restore exception count */      \
+               "clr %0\n"              /* no exception: error = 0 */      \
+               "2:\t/* End __put_user_16 */"                              \
+               : "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)         \
+               : "r"(__pu_addr), "m"(current->tss.ex.count),              \
+                 "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
+                 "2"(__pu_val)                                            \
+               : "$28")
+
+#define __put_user_8                                                      \
+       __asm__("/* Inline __put_user_8 */\n\t"                            \
+               "br $28,1f\n\t"         /* set up exception address */     \
+               "lda %0,%7\n\t"         /* exception! error = -EFAULT */   \
+               "br 2f\n"                                                  \
+               "1:\t"                                                     \
+               "stq %6,%4\n\t"         /* store inc'ed exception count */ \
+               "ldq_u %0,%1\n\t"       /* masked data store */            \
+               "insbl %2,%3,%2\n\t"                                       \
+               "mskbl %0,%3,%0\n\t"                                       \
+               "or %0,%2,%2\n\t"                                          \
+               "stq_u %2,%1\n\t"                                          \
+               "stq %5,%4\n\t"         /* restore exception count */      \
+               "clr %0\n"              /* no exception: error = 0 */      \
+               "2:\t/* End __put_user_8 */"                               \
+               : "=r"(__pu_err), "=m"(*__pu_addr), "=r"(__pu_val)         \
+               : "r"(__pu_addr), "m"(current->tss.ex.count),              \
+                 "r"(__pu_ex_count), "r"(__pu_ex_count+1), "i"(-EFAULT),  \
+                 "2"(__pu_val)                                            \
+               : "$28")
+
+
+extern void __clear_user(void);
+
+#define clear_user(to,n)                                               \
+({                                                                     \
+       register void * __cl_to __asm__("$6") = (to);                   \
+       register long __cl_len __asm__("$0") = (n);                     \
+       if (__access_ok(((long)__cl_to),__cl_len,__access_mask)) {      \
+               register void * __cl_ex __asm__("$7");                  \
+               __cl_ex = &current->tss.ex;                             \
+               __asm__ __volatile__(                                   \
+                       "jsr $28,(%2),__clear_user"                     \
+                       : "=r"(__cl_len), "=r"(__cl_to)                 \
+                       : "r"(__clear_user), "r"(__cl_ex),              \
+                         "0"(__cl_len), "1"(__cl_to)                   \
+                       : "$1","$2","$3","$4","$5","$28","memory");     \
+       }                                                               \
+       __cl_len;                                                       \
+})
+
+
+/* Returns: -EFAULT if exception before terminator, N if the entire
+   buffer filled, else strlen.  */
+
+struct exception_struct;
+extern long __strncpy_from_user(char *__to, const char *__from,
+                               long __to_len, struct exception_struct *);
+
+#define strncpy_from_user(to,from,n)                                         \
+({                                                                           \
+       char * __sfu_to = (to);                                               \
+       const char * __sfu_from = (from);                                     \
+       long __sfu_len = (n), __sfu_ret = -EFAULT;                            \
+       if (__access_ok(((long)__sfu_from),__sfu_len,__access_mask)) {        \
+               __sfu_ret = __strncpy_from_user(__sfu_to,__sfu_from,          \
+                                               __sfu_len, &current->tss.ex); \
+       __sfu_ret;                                                            \
+})
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+       return access_ok(type,addr,size)?0:-EFAULT;
+}
+
+#endif /* _ASM_SEGMENT_H */
index f9cb929bc35d46d966c165a48020365fbdaae678..71009ec5c3b32f7a644cdb470c4bfec388f188f9 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <asm/ptrace.h>
+#include <asm/user.h>
 
 typedef unsigned long elf_greg_t;
 
index acfbef61b031f700902c527d78315c8136a80fa8..d5f1ef6de9e9659723d7d321e05cf0441ed9d540 100644 (file)
@@ -7,217 +7,4 @@
 #define USER_CS                0x23
 #define USER_DS                0x2B
 
-#ifndef __ASSEMBLY__
-
-#include <linux/string.h>
-
-/*
- * The fs value determines whether argument validity checking should be
- * performed or not.  If get_fs() == USER_DS, checking is performed, with
- * get_fs() == KERNEL_DS, checking is bypassed.
- * 
- * For historical reasons, these macros are grossly misnamed.
- */
-      
-#define get_fs()       (current->tss.segment)
-#define set_fs(x)      (current->tss.segment = (x))
-#define get_ds()       (KERNEL_DS)
-
-#define __user_ok(addr,size) \
-((size <= 0xC0000000) && (addr <= 0xC0000000 - size))
-#define __kernel_ok \
-(get_fs() == KERNEL_DS)
-
-extern int __verify_write(const void *, unsigned long);
-
-#if CPU > 386
-#define __access_ok(type,addr,size) \
-(__kernel_ok || __user_ok(addr,size))
-#else
-#define __access_ok(type,addr,size) \
-(__kernel_ok || (__user_ok(addr,size) && \
-  ((type) == VERIFY_READ || wp_works_ok || __verify_write((void *)(addr),(size)))))
-#endif /* CPU */
-
-#define access_ok(type,addr,size) \
-__access_ok((type),(unsigned long)(addr),(size))
-
-/*
- * Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- *
- * This gets kind of ugly. We want to return _two_ values in "get_user()"
- * and yet we don't want to do any pointers, because that is too much
- * of a performance impact. Thus we have a few rather ugly macros here,
- * and hide all the uglyness from the user.
- */
-#define put_user(x,ptr) ({ \
-unsigned long __pu_addr = (unsigned long)(ptr); \
-__put_user((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
-
-#define get_user(x,ptr) ({ \
-unsigned long __gu_addr = (unsigned long)(ptr); \
-__get_user((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
-
-struct __large_struct { unsigned long buf[100]; };
-#define __m(x) (*(struct __large_struct *)(x))
-
-#define __put_user(x,addr,size) ({ \
-int __pu_ret = -EFAULT; \
-if (access_ok(VERIFY_WRITE,addr,size)) { \
-switch (size) { \
-case 1: __put_user_8(x,addr,__pu_ret); break; \
-case 2: __put_user_16(x,addr,__pu_ret); break; \
-case 4: __put_user_32(x,addr,__pu_ret); break; \
-default: __pu_ret = __put_user_bad(); break; \
-} } __pu_ret; })
-
-#define __put_user_asm(x,addr,ret,bwl,reg,rtype) \
-__asm__ __volatile__( \
-       "movl $1f,%0\n\t" \
-       "incl %3\n\t" \
-       "mov" #bwl " %" reg "1,%2\n\t" \
-       "xorl %0,%0\n\t" \
-       "decl %3\n1:" \
-:"=d" (ret) \
-:#rtype (x), "m" (__m(addr)),"m" (current->tss.ex.count), "0" (ret))
-
-#define __put_user_8(x,addr,ret) \
-__put_user_asm(x,addr,ret,b,"b","iq")
-#define __put_user_16(x,addr,ret) \
-__put_user_asm(x,addr,ret,w,"w","ir")
-#define __put_user_32(x,addr,ret) \
-__put_user_asm(x,addr,ret,l,"","ir")
-
-extern int __put_user_bad(void);
-
-#define __get_user(x,addr,size,type) ({ \
-int __gu_ret = -EFAULT; \
-unsigned long __gu_val = 0; \
-if (access_ok(VERIFY_WRITE,addr,size)) { \
-switch (size) { \
-case 1: __get_user_8(__gu_val,addr,__gu_ret); break; \
-case 2: __get_user_16(__gu_val,addr,__gu_ret); break; \
-case 4: __get_user_32(__gu_val,addr,__gu_ret); break; \
-default: __gu_ret = __get_user_bad(); break; \
-} } x = (type) __gu_val; __gu_ret; })
-
-#define __get_user_asm(x,addr,ret,bwl,reg,rtype) \
-__asm__ __volatile__( \
-       "movl $1f,%0\n\t" \
-       "incl %3\n\t" \
-       "mov" #bwl " %2,%" reg "1\n\t" \
-       "xorl %0,%0\n\t" \
-       "decl %3\n1:" \
-:"=d" (ret), #rtype (x) \
-:"m" (__m(addr)),"m" (current->tss.ex.count), "0" (ret), "1" (x))
-
-#define __get_user_8(x,addr,ret) \
-__get_user_asm(x,addr,ret,b,"b","=q")
-#define __get_user_16(x,addr,ret) \
-__get_user_asm(x,addr,ret,w,"w","=r")
-#define __get_user_32(x,addr,ret) \
-__get_user_asm(x,addr,ret,l,"","=r")
-
-extern int __get_user_bad(void);
-
-#define __copy_user(to,from,size) \
-__asm__ __volatile__( \
-       "movl $3f,%0\n\t" \
-       "incl %2\n\t" \
-       "rep; movsl\n\t" \
-       "testb $2,%b3\n\t" \
-       "je 1f\n\t" \
-       "movsw\n\t" \
-       "subb $2,%b3\n" \
-       "1:\t" \
-       "testb $1,%b3\n\t" \
-       "je 2f\n\t" \
-       "movsb\n\t" \
-       "decb %b3\n" \
-       "2:\t" \
-       "decl %2\n" \
-       "3:\tlea 0(%3,%1,4),%0" \
-       :"=d" (size) \
-       :"c" (size >> 2), "m" (current->tss.ex), "q" (size & 3), \
-        "D" (to), "S" (from), "0" (size) \
-       :"cx","di","si","memory");
-
-#define copy_to_user(to,from,n) ({ \
-unsigned long __cu_to = (unsigned long) (to); \
-unsigned long __cu_size = (unsigned long) (n); \
-if (__cu_size && __access_ok(VERIFY_WRITE, __cu_to, __cu_size)) \
-__copy_user(__cu_to,from,__cu_size); \
-__cu_size; })
-
-#define copy_from_user(to,from,n) ({ \
-unsigned long __cu_from = (unsigned long) (from); \
-unsigned long __cu_size = (unsigned long) (n); \
-if (__cu_size && __access_ok(VERIFY_READ, __cu_from, __cu_size)) \
-__copy_user(to,__cu_from,__cu_size); \
-__cu_size; })
-
-#define __clear_user(addr,size) \
-__asm__ __volatile__( \
-       "movl $3f,%0\n\t" \
-       "incl %2\n\t" \
-       "rep; stosl\n\t" \
-       "testl $2,%3\n\t" \
-       "je 1f\n\t" \
-       "stosw\n\t" \
-       "subl $2,%3\n" \
-       "1:\t" \
-       "testl $1,%3\n\t" \
-       "je 2f\n\t" \
-       "stosb\n\t" \
-       "decl %3\n" \
-       "2:\t" \
-       "decl %2\n" \
-       "3:\tlea 0(%3,%1,4),%0" \
-       :"=d" (size) \
-       :"c" (size >> 2), "m" (current->tss.ex), "r" (size & 3), \
-        "D" (addr), "0" (size), "a" (0) \
-       :"cx","di","memory");
-
-#define clear_user(addr,n) ({ \
-void * __cl_addr = (addr); \
-unsigned long __cl_size = (n); \
-if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
-__clear_user(__cl_addr, __cl_size); \
-__cl_size; })
-
-#define __strncpy_from_user(dst,src,count,res) \
-__asm__ __volatile__( \
-       "cld\n\t" \
-       "movl $3f,%0\n\t" \
-       "incl %2\n" \
-       "1:\tdecl %1\n\t" \
-       "js 2f\n\t" \
-       "lodsb\n\t" \
-       "stosb\n\t" \
-       "testb %%al,%%al\n\t" \
-       "jne 1b\n" \
-       "2:\t" \
-       "incl %1\n\t" \
-       "xorl %0,%0\n\t" \
-       "decl %2\n" \
-       "3:" \
-       :"=d" (res), "=r" (count) \
-       :"m" (current->tss.ex), "1" (count), "S" (src),"D" (dst),"0" (res) \
-       :"si","di","ax","cx","memory")
-
-#define strncpy_from_user(dest,src,count) ({ \
-const void * __sc_src = (src); \
-unsigned long __sc_count = (count); \
-long __sc_res = -EFAULT; \
-if (__access_ok(VERIFY_READ, ((unsigned long)(__sc_src)), __sc_count)) { \
-       unsigned long __sc_residue = __sc_count; \
-       __strncpy_from_user(dest,__sc_src,__sc_count,__sc_res); \
-       if (!__sc_res) __sc_res = __sc_residue - __sc_count; \
-} __sc_res; })
-
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_SEGMENT_H */
+#endif
index 992bfca60bb6a3bf13269cbd74b272cbd6d16d0a..50657fb357f095aee53238aa6361087a600c5991 100644 (file)
@@ -497,6 +497,7 @@ __asm__ __volatile__ (
        "std\n\t"
        "rep\n\t"
        "movsb\n\t"
+       "cld"
        : /* no output */
        :"c" (n), "S" (n-1+(const char *)src), "D" (n-1+(char *)tmp)
        :"cx","si","di","memory");
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
new file mode 100644 (file)
index 0000000..576c7bf
--- /dev/null
@@ -0,0 +1,336 @@
+#ifndef __i386_UACCESS_H
+#define __i386_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+
+#include <asm/segment.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ * 
+ * For historical reasons, these macros are grossly misnamed.
+ */
+      
+#define get_fs()       (current->tss.segment)
+#define set_fs(x)      (current->tss.segment = (x))
+#define get_ds()       (KERNEL_DS)
+
+#define __user_ok(addr,size) \
+((size <= 0xC0000000UL) && (addr <= 0xC0000000UL - size))
+#define __kernel_ok \
+(get_fs() == KERNEL_DS)
+
+extern int __verify_write(const void *, unsigned long);
+
+#if CPU > 386
+#define __access_ok(type,addr,size) \
+(__kernel_ok || __user_ok(addr,size))
+#else
+#define __access_ok(type,addr,size) \
+(__kernel_ok || (__user_ok(addr,size) && \
+  ((type) == VERIFY_READ || wp_works_ok || __verify_write((void *)(addr),(size)))))
+#endif /* CPU */
+
+#define access_ok(type,addr,size) \
+__access_ok((type),(unsigned long)(addr),(size))
+
+/*
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ */
+#define put_user(x,ptr) \
+__do_put_user((unsigned long)((__typeof__(*(ptr)))(x)),(ptr),(sizeof(*(ptr))))
+#define __put_user(x,ptr) \
+__do_put_user_nocheck((unsigned long)((__typeof__(*(ptr)))(x)),(ptr),(sizeof(*(ptr))))
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __put_user_asm(x,addr,ret,bwl,reg,rtype) \
+__asm__ __volatile__( \
+       "movl $1f,%0\n\t" \
+       "incl %3\n\t" \
+       "mov" #bwl " %" reg "1,%2\n\t" \
+       "xorl %0,%0\n\t" \
+       "decl %3\n1:" \
+:"=&d" (ret) \
+:#rtype (x), "m" (__m(addr)),"m" (current->tss.ex.count))
+
+extern int __put_user_bad(void);
+
+#define __put_user_size(x,ptr,size,retval) \
+switch (size) { \
+case 1: __put_user_asm(x,ptr,retval,b,"b","iq"); break; \
+case 2: __put_user_asm(x,ptr,retval,w,"w","ir"); break; \
+case 4: __put_user_asm(x,ptr,retval,l,"","ir"); break; \
+default: retval = __put_user_bad(); }
+
+static inline int __do_put_user(unsigned long x, void * ptr, int size)
+{
+       int retval = -EFAULT;
+       if (access_ok(VERIFY_WRITE, ptr, size))
+               __put_user_size(x,ptr,size,retval);
+       return retval;
+}
+
+#define __do_put_user_nocheck(x, ptr, size) \
+({ int retval; __put_user_size(x,ptr,size,retval); retval; })
+
+#define get_user(x,ptr) \
+__do_get_user((x),(unsigned long)(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
+
+#define __get_user(x,ptr) \
+__do_get_user_nocheck((x),(unsigned long)(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
+
+#define __do_get_user(x,ptr,size,type) ({ \
+unsigned long __gu_addr = ptr; \
+int __gu_ret = -EFAULT; \
+unsigned long __gu_val = 0; \
+if (access_ok(VERIFY_READ,__gu_addr,size)) { \
+switch (size) { \
+case 1: __do_get_user_8(__gu_val,__gu_addr,__gu_ret); break; \
+case 2: __do_get_user_16(__gu_val,__gu_addr,__gu_ret); break; \
+case 4: __do_get_user_32(__gu_val,__gu_addr,__gu_ret); break; \
+default: __gu_ret = __do_get_user_bad(); break; \
+} } x = (type) __gu_val; __gu_ret; })
+
+#define __do_get_user_nocheck(x,ptr,size,type) ({ \
+int __gu_ret; \
+unsigned long __gu_val; \
+switch (size) { \
+case 1: __do_get_user_8(__gu_val,ptr,__gu_ret); break; \
+case 2: __do_get_user_16(__gu_val,ptr,__gu_ret); break; \
+case 4: __do_get_user_32(__gu_val,ptr,__gu_ret); break; \
+default: __gu_ret = __do_get_user_bad(); __gu_val = 0; break; \
+} x = (type) __gu_val; __gu_ret; })
+
+#define __do_get_user_asm(x,addr,ret,bwl,reg,rtype) \
+__asm__ __volatile__( \
+       "movl $1f,%0\n\t" \
+       "incl %3\n\t" \
+       "mov" #bwl " %2,%" reg "1\n\t" \
+       "xorl %0,%0\n\t" \
+       "decl %3\n1:" \
+:"=&d" (ret), #rtype (x) \
+:"m" (__m(addr)),"m" (current->tss.ex.count))
+
+#define __do_get_user_8(x,addr,ret) \
+__do_get_user_asm(x,addr,ret,b,"b","=&q")
+#define __do_get_user_16(x,addr,ret) \
+__do_get_user_asm(x,addr,ret,w,"w","=&r")
+#define __do_get_user_32(x,addr,ret) \
+__do_get_user_asm(x,addr,ret,l,"","=&r")
+
+extern int __do_get_user_bad(void);
+
+#define __copy_user(to,from,size) \
+__asm__ __volatile__( \
+       "shrl $2,%1\n\t" \
+       "movl $3f,%0\n\t" \
+       "incl %3\n\t" \
+       "rep; movsl\n\t" \
+       "testl $2,%2\n\t" \
+       "je 1f\n\t" \
+       "movsw\n\t" \
+       "subl $2,%2\n" \
+       "1:\t" \
+       "testl $1,%2\n\t" \
+       "je 2f\n\t" \
+       "movsb\n\t" \
+       "decl %2\n" \
+       "2:\t" \
+       "decl %3\n" \
+       "3:\tlea 0(%2,%1,4),%0" \
+       :"=&d" (size) \
+       :"c" (size), "r" (size & 3), "m" (current->tss.ex), \
+        "D" (to), "S" (from) \
+       :"cx","di","si","memory");
+
+static inline unsigned long __constant_copy_user(void * to, const void * from, unsigned long size)
+{
+       unsigned long result;
+
+       switch (size & 3) {
+       default:
+               __asm__ __volatile__(
+                       "movl $1f,%0\n\t"
+                       "incl %1\n\t"
+                       "rep ; movsl\n\t"
+                       "decl %1\n"
+                       "1:\tlea 0(,%%ecx,4),%0"
+                       :"=&d" (result)
+                       :"m" (current->tss.ex),
+                        "S" (from),"D" (to),"c" (size/4)
+                       :"cx","di","si","memory");
+               break;
+       case 1:
+               __asm__ __volatile__(
+                       "movl $1f,%0\n\t"
+                       "incl %3\n\t"
+                       "rep ; movsl\n\t"
+                       "movsb\n\t"
+                       "decl %1\n\t"
+                       "decl %3\n"
+                       "1:\tlea 0(%1,%%ecx,4),%0"
+                       :"=&d" (result)
+                       :"ab" (1),"m" (current->tss.ex),
+                        "S" (from),"D" (to), "c" (size/4)
+                       :"cx","di","si","memory");
+               break;
+       case 2:
+               __asm__ __volatile__(
+                       "movl $1f,%0\n\t"
+                       "incl %2\n\t"
+                       "rep ; movsl\n\t"
+                       "movsw\n\t"
+                       "subl $2,%1\n\t"
+                       "decl %2\n"
+                       "1:\tlea 0(%1,%%ecx,4),%0"
+                       :"=&d" (result)
+                       :"ab" (2),"m" (current->tss.ex),
+                        "S" (from),"D" (to),"c" (size/4)
+                       :"cx","di","si","memory");
+               break;
+       case 3:
+               __asm__ __volatile__(
+                       "movl $1f,%0\n\t"
+                       "incl %2\n\t"
+                       "rep ; movsl\n\t"
+                       "movsw\n\t"
+                       "subl $2,%1\n\t"
+                       "movsb\n\t"
+                       "decl %1\n\t"
+                       "decl %2\n"
+                       "1:\tlea 0(%1,%%ecx,4),%0"
+                       :"=&d" (result)
+                       :"ab" (3),"m" (current->tss.ex),
+                        "S" (from),"D" (to),"c" (size/4)
+                       :"cx","di","si","memory");
+               break;
+       }
+       return result;
+}
+
+static inline unsigned long __generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               __copy_user(to,from,n);
+       return n;
+}
+
+static inline unsigned long __constant_copy_to_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_WRITE, to, n))
+               n = __constant_copy_user(to,from,n);
+       return n;
+}
+
+static inline unsigned long __generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_READ, from, n))
+               __copy_user(to,from,n);
+       return n;
+}
+
+static inline unsigned long __constant_copy_from_user(void *to, const void *from, unsigned long n)
+{
+       if (access_ok(VERIFY_READ, from, n))
+               n = __constant_copy_user(to,from,n);
+       return n;
+}
+
+#define copy_to_user(to,from,n) \
+(__builtin_constant_p(n) ? \
+ __constant_copy_to_user((to),(from),(n)) : \
+ __generic_copy_to_user((to),(from),(n)))
+
+#define copy_from_user(to,from,n) \
+(__builtin_constant_p(n) ? \
+ __constant_copy_from_user((to),(from),(n)) : \
+ __generic_copy_from_user((to),(from),(n)))
+
+#define __clear_user(addr,size) \
+__asm__ __volatile__( \
+       "movl $3f,%0\n\t" \
+       "incl %2\n\t" \
+       "rep; stosl\n\t" \
+       "testl $2,%3\n\t" \
+       "je 1f\n\t" \
+       "stosw\n\t" \
+       "subl $2,%3\n" \
+       "1:\t" \
+       "testl $1,%3\n\t" \
+       "je 2f\n\t" \
+       "stosb\n\t" \
+       "decl %3\n" \
+       "2:\t" \
+       "decl %2\n" \
+       "3:\tlea 0(%3,%1,4),%0" \
+       :"=&d" (size) \
+       :"c" (size >> 2), "m" (current->tss.ex), "r" (size & 3), \
+        "D" (addr), "a" (0) \
+       :"cx","di","memory");
+
+#define clear_user(addr,n) ({ \
+void * __cl_addr = (addr); \
+unsigned long __cl_size = (n); \
+if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
+__clear_user(__cl_addr, __cl_size); \
+__cl_size; })
+
+#define __strncpy_from_user(dst,src,count,res) \
+__asm__ __volatile__( \
+       "cld\n\t" \
+       "movl $3f,%0\n\t" \
+       "incl %2\n" \
+       "1:\tdecl %1\n\t" \
+       "js 2f\n\t" \
+       "lodsb\n\t" \
+       "stosb\n\t" \
+       "testb %%al,%%al\n\t" \
+       "jne 1b\n" \
+       "2:\t" \
+       "incl %1\n\t" \
+       "xorl %0,%0\n\t" \
+       "decl %2\n" \
+       "3:" \
+       :"=&d" (res), "=r" (count) \
+       :"m" (current->tss.ex), "1" (count), "S" (src),"D" (dst) \
+       :"si","di","ax","memory")
+
+#define strncpy_from_user(dest,src,count) ({ \
+const void * __sc_src = (src); \
+unsigned long __sc_count = (count); \
+long __sc_res = -EFAULT; \
+if (__access_ok(VERIFY_READ, ((unsigned long)(__sc_src)), __sc_count)) { \
+       unsigned long __sc_residue = __sc_count; \
+       __strncpy_from_user(dest,__sc_src,__sc_count,__sc_res); \
+       if (!__sc_res) __sc_res = __sc_residue - __sc_count; \
+} __sc_res; })
+
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+       return access_ok(type,addr,size)?0:-EFAULT;
+}
+
+#endif /* __i386_UACCESS_H */
index 703baa153d5b81a41222a8d93b54fb2f37f138e2..b99eaa7973f0eb1ac63a58b5190950f9cc9e33f9 100644 (file)
@@ -16,8 +16,6 @@
 #include <linux/kdev_t.h>
 #include <linux/ioctl.h>
 
-#include <asm/semaphore.h>
-
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but I'll fix
  * that later. Anyway, now the file code is no longer dependent
@@ -123,6 +121,7 @@ extern int max_files, nr_files;
 
 #ifdef __KERNEL__
 
+#include <asm/semaphore.h>
 #include <asm/bitops.h>
 
 extern void buffer_init(void);
index 89c748f2b4d6789eef571767e163bea214eb6de9..12c1de0ecc8d10441eeeeffad4404c8a37399ec1 100644 (file)
@@ -14,15 +14,6 @@ extern void * high_memory;
 
 #include <asm/page.h>
 #include <asm/atomic.h>
-#include <asm/segment.h>
-
-#define VERIFY_READ 0
-#define VERIFY_WRITE 1
-
-extern inline int verify_area(int type, const void * addr, unsigned long size)
-{
-       return access_ok(type,addr,size)?0:-EFAULT;
-}
 
 /*
  * Linux kernel virtual memory manager primitives.
index caccf16c238b5a2a6a903b3dee0fe6038d5710b6..b944826603398e7319e87e6d9e1f09906b7f63d8 100644 (file)
@@ -104,6 +104,7 @@ enum net_directory_inos {
        PROC_NET_IP_MASQ_APP,
        PROC_NET_STRIP_STATUS,
        PROC_NET_STRIP_TRACE,
+       PROC_NET_Z8530,
        PROC_NET_LAST
 };
 
index 2e3e69baacb7177c5cf759cbce8aeb2e507328fc..e1ae51c028c5d9a29b7e71c9e7c8c995fa6c5559 100644 (file)
@@ -1,32 +1,3 @@
-
-#ifndef _RAID0_H
-#define _RAID0_H
-
-struct strip_zone
-{
-  int zone_offset;             /* Zone offset in md_dev */
-  int dev_offset;              /* Zone offset in real dev */
-  int size;                    /* Zone size */
-  int nb_dev;                  /* Number of devices attached to the zone */
-  struct real_dev *dev[MAX_REAL]; /* Devices attached to the zone */
-};
-
-struct raid0_hash
-{
-  struct strip_zone *zone0, *zone1;
-};
-
-struct raid0_data
-{
-  struct raid0_hash *hash_table; /* Dynamically allocated */
-  struct strip_zone *strip_zone; /* This one too */
-  int nr_strip_zones;
-  struct strip_zone *smallest;
-  int nr_zones;
-};
-
-#endif
-
 #ifndef _RAID0_H
 #define _RAID0_H
 
index 0ad094599d4466275a8f7abba133be55ed2f89a1..bda966f520ae13abf4a4ad6a16e18c5f6b913901 100644 (file)
@@ -1,8 +1,10 @@
-/* $Id: scc.h,v 1.15 1995/11/16 20:19:26 jreuter Exp jreuter $ */
+/* $Id: scc.h,v 1.26 1996/10/09 16:35:56 jreuter Exp jreuter $ */
 
 #ifndef        _SCC_H
 #define        _SCC_H
 
+#include <linux/if_ether.h>
+
 /* selection of hardware types */
 
 #define PA0HZP         0x00    /* hardware type for PA0HZP SCC card and compatible */
 
 #define SCC_PARANOIA_CHECK     /* tell the user if something is going wrong */
 
-/* ioctl() commands */
-
-#define TIOCSCCCFG     0x2200          /* set hardware parameters */
-#define TIOCSCCINI     0x2201          /* init driver */
-#define TIOCCHANINI    0x2202          /* init channel */
-
-#define TIOCCHANMEM    0x2210          /* adjust buffer pools */
-
-#define TIOCGKISS      0x2282          /* get kiss parameter */
-#define TIOCSKISS      0x2283          /* set kiss parameter */
-
-#define TIOCSCCSTAT    0x2284          /* get scc status */
+/* DEV ioctl() commands */
 
+#define SIOCSCCRESERVED (SIOCDEVPRIVATE+0)
+#define SIOCSCCCFG     (SIOCDEVPRIVATE+1)
+#define SIOCSCCINI     (SIOCDEVPRIVATE+2)
+#define SIOCSCCCHANINI (SIOCDEVPRIVATE+3)
+#define SIOCSCCSMEM    (SIOCDEVPRIVATE+4)
+#define SIOCSCCGKISS   (SIOCDEVPRIVATE+5)
+#define SIOCSCCSKISS   (SIOCDEVPRIVATE+6)
+#define SIOCSCCGSTAT   (SIOCDEVPRIVATE+7)
 
 /* magic number */
 
 #define SCC_MAGIC      0x8530          /* ;-) */
 
-/* KISS protocol flags */
-#define FEND   192
-#define FESC   219
-#define TFEND  220
-#define TFESC  221
-
 /* KISS state machine */
 
 #define        KISS_IDLE       0
 #define PARAM_WAIT      16
 #define PARAM_MAXDEFER 17
 #define PARAM_TX        18
-#define PARAM_SLIP     19
+#define PARAM_HWEVENT  31
 #define PARAM_RETURN   255     /* reset kiss mode */
 
+/* fulldup parameter */
+
+#define KISS_DUPLEX_HALF       0       /* normal CSMA operation */
+#define KISS_DUPLEX_FULL       1       /* fullduplex, key down trx after transmission */
+#define KISS_DUPLEX_LINK       2       /* fullduplex, key down trx after 'idletime' sec */
+#define KISS_DUPLEX_OPTIMA     3       /* fullduplex, let the protocol layer control the hw */
+
+/* misc. parameters */
+
 #define TIMER_OFF      65535U  /* to switch off timers */
 #define NO_SUCH_PARAM  65534U  /* param not implemented */
 
+/* HWEVENT parameter */
+
+#define HWEV_DCD_ON    0
+#define HWEV_DCD_OFF   1
+#define HWEV_ALL_SENT  2
+
 /* channel grouping */
 
 #define RXGROUP                0x100   /* if set, only tx when all channels clear */
 #define TXS_BUSY       1       /* waiting for permission to send / tailtime */
 #define TXS_ACTIVE     2       /* Transmitter on, sending data */
 #define TXS_NEWFRAME   3       /* reset CRC and send (next) frame */
+#define TXS_IDLE2      4       /* Transmitter on, no data pending */
+#define TXS_WAIT       5       /* Waiting for Mintime to expire */
+#define TXS_TIMEOUT    6       /* We had a transmission timeout */
 
 #define TX_ON          1       /* command for scc_key_trx() */
 #define TX_OFF         0       /* dto */
 
-/* Buffer management */
-
-#define BT_RECEIVE  1          /* buffer allocated by receive */
-#define BT_TRANSMIT 2          /* buffer allocated by transmit */
-
-#define NULLBUF  (struct mbuf *)0
-#define NULLBUFP (struct mbuf **)0
+/* Vector masks in RR2B */
 
+#define VECTOR_MASK    0x06
+#define TXINT          0x00
+#define EXINT          0x02
+#define RXINT          0x04
+#define SPINT          0x06
 
-typedef unsigned short io_port;        /* type definition for an 'io port address' */
-typedef unsigned short ioaddr;  /* old def */
+typedef unsigned long io_port; /* type definition for an 'io port address' */
 
 #ifdef SCC_DELAY
 #define Inb(port)      inb_p(port)
@@ -115,42 +124,25 @@ typedef unsigned short ioaddr;  /* old def */
 #define Outb(port, val)        outb(val, port)
 #endif
 
-/* some nasty macros (esp. Expired) */
-
-#define TIMER_STOPPED 65535U
-#define Running(k) (scc->k != TIMER_STOPPED)
-#define Expired(k) (scc->k != TIMER_STOPPED) && (!(scc->k) || (--(scc->k) == 0))
-#define Stop_Timer(k) scc->k = TIMER_STOPPED
-
-
-/* Basic message buffer structure */
+#define TIMER_OFF 65535U
 
-struct mbuf {
-       struct mbuf *next;      /* Link to next buffer */
-       struct mbuf *prev;      /* Link to previous buffer */
-       
-       int cnt;                /* Number of bytes stored in buffer */
-       unsigned char *rw_ptr;  /* read-write pointer */
-       unsigned char data[0];  /* anchor for allocated buffer */
-};
-       
 /* SCC channel control structure for KISS */
 
 struct scc_kiss {
        unsigned char txdelay;          /* Transmit Delay 10 ms/cnt */
        unsigned char persist;          /* Persistence (0-255) as a % */
        unsigned char slottime;         /* Delay to wait on persistence hit */
-       unsigned char tailtime;         /* Delay after XMTR OFF */
+       unsigned char tailtime;         /* Delay after last byte written */
        unsigned char fulldup;          /* Full Duplex mode 0=CSMA 1=DUP 2=ALWAYS KEYED */
        unsigned char waittime;         /* Waittime before any transmit attempt */
        unsigned int  maxkeyup;         /* Maximum time to transmit (seconds) */
-       unsigned char mintime;          /* Minimal offtime after MAXKEYUP timeout */
+       unsigned char mintime;          /* Minimal offtime after MAXKEYUP timeout (seconds) */
        unsigned int  idletime;         /* Maximum idle time in ALWAYS KEYED mode (seconds) */
        unsigned int  maxdefer;         /* Timer for CSMA channel busy limit */
        unsigned char tx_inhibit;       /* Transmit is not allowed when set */  
-       unsigned char group;            /* group ID for AX.25 TX interlocking */
-       unsigned char not_slip;         /* set to zero: use SLIP instead of KISS */
-       unsigned char softdcd;          /* use DPLL instead of DCD pin for carrier detect */
+       unsigned char group;            /* Group ID for AX.25 TX interlocking */
+       unsigned char mode;             /* 'normal' or 'hwctrl' mode (unused) */
+       unsigned char softdcd;          /* Use DPLL instead of DCD pin for carrier detect */
 };
 
 
@@ -172,15 +164,9 @@ struct scc_stat {
        unsigned int tx_under;  /* Transmitter Underruns */
 
        unsigned int tx_state;  /* Transmitter state */
-       
-       char tx_kiss_state;     /* state of the kiss interpreter */
-       char rx_kiss_state;     /* state of the kiss encoder */
-       
        int tx_queued;          /* tx frames enqueued */
-       int rx_queued;          /* rx frames enqueued */
-       
-       unsigned int rxbuffers; /* allocated rx_buffers */
-       unsigned int txbuffers; /* allocated tx_buffers */
+
+       unsigned int maxqueue;  /* allocated tx_buffers */
        unsigned int bufsize;   /* used buffersize */
 };
 
@@ -191,13 +177,11 @@ struct scc_modem {
        char nrz;               /* NRZ instead of NRZI */       
 };
 
-struct ioctl_command {
+struct scc_kiss_cmd {
        int      command;       /* one of the KISS-Commands defined above */
        unsigned param;         /* KISS-Param */
 };
 
-/* currently unused */
-
 struct scc_hw_config {
        io_port data_a;         /* data port channel A */
        io_port ctrl_a;         /* control port channel A */
@@ -209,363 +193,57 @@ struct scc_hw_config {
        int     irq;            /* irq */
        long    clock;          /* clock */
        char    option;         /* command for function port */
-       
+
        char brand;             /* hardware type */
        char escc;              /* use ext. features of a 8580/85180/85280 */
 };
 
+/* (#) only one INTACK latch allowed. */
+
+
 struct scc_mem_config {
-       unsigned int rxbuffers;
-       unsigned int txbuffers;
+       unsigned int dummy;
        unsigned int bufsize;
 };
 
-/* (#) only one INTACK latch allowed. */
-       
 
 /* SCC channel structure */
 
 struct scc_channel {
-       int magic;              /* magic word */
+       int magic;                      /* magic word */
        
-       int init;               /* channel exists? */
-       struct tty_struct *tty; /* link to tty control structure */
-       char tty_opened;        /* No. of open() calls... */
-       char throttled;         /* driver is throttled  */
-               
-       char brand;             /* manufacturer of the board */
-       long clock;             /* used clock */
+       int init;                       /* channel exists? */
+
+       struct device *dev;             /* link to device control structure */
+       struct enet_statistics dev_stat;/* device statistics */
+
+       char brand;                     /* manufacturer of the board */
+       long clock;                     /* used clock */
        
-       io_port ctrl;           /* I/O address of CONTROL register */
-       io_port data;           /* I/O address of DATA register */
-       io_port special;        /* I/O address of special function port */
+       io_port ctrl;                   /* I/O address of CONTROL register */
+       io_port data;                   /* I/O address of DATA register */
+       io_port special;                /* I/O address of special function port */
+       int irq;                        /* Number of Interrupt */
        
        char option;
-       char enhanced;          /* Enhanced SCC support */
+       char enhanced;                  /* Enhanced SCC support */
 
-       unsigned char wreg[16]; /* Copy of last written value in WRx */
-       unsigned char status;   /* Copy of R0 at last external interrupt */
+       unsigned char wreg[16];         /* Copy of last written value in WRx */
+       unsigned char status;           /* Copy of R0 at last external interrupt */
 
-        struct scc_kiss kiss;  /* control structure for KISS params */
-        struct scc_stat stat;  /* statistical information */
-        struct scc_modem modem; /* modem information */
+        struct scc_kiss kiss;          /* control structure for KISS params */
+        struct scc_stat stat;          /* statistical information */
+        struct scc_modem modem;        /* modem information */
         
-        struct mbuf *rx_buffer_pool; /* free buffers for rx/tx frames are */
-        struct mbuf *tx_buffer_pool; /* linked in these ring chains */
-        
-        struct mbuf *rx_queue; /* chain of received frames */
-        struct mbuf *tx_queue; /* chain of frames due to transmit */
-        struct mbuf *rx_bp;    /* pointer to frame currently received */
-        struct mbuf *tx_bp;    /* pointer to frame currently transmitted */
-        
-        struct mbuf *kiss_decode_bp; /* frame we are receiving from tty */
-        struct mbuf *kiss_encode_bp; /* frame we are sending to tty */
-       
+        struct sk_buff *tx_next_buff;  /* next tx buffer */
+        struct sk_buff *rx_buff;       /* pointer to frame currently received */
+        struct sk_buff *tx_buff;       /* pointer to frame currently transmitted */
+
        /* Timer */
-       
-       struct timer_list tx_t; /* tx timer for this channel */
-       struct timer_list rx_t; /* rx timer */
 
-       /* rx timer counters */
-       
-       unsigned int t_dwait;   /* wait time (DWAIT) */
-       unsigned int t_slot;    /* channel sample frequency */
-       unsigned int t_txdel;   /* TX delay */
-       unsigned int t_tail;    /* tail time */
-       unsigned int t_maxk;    /* max. key up */
-       unsigned int t_min;     /* minimal key up */
-       unsigned int t_idle;    /* */
-       unsigned int t_mbusy;   /* time until defer if channel busy */          
+       struct timer_list tx_t;         /* tx timer for this channel */
+       struct timer_list tx_wdog;      /* tx watchdogs */
 };
 
-
-/* 8530 Serial Communications Controller Register definitions */
-#define        FLAG    0x7e
-
-/* Write Register 0 */
-#define        R0      0               /* Register selects */
-#define        R1      1
-#define        R2      2
-#define        R3      3
-#define        R4      4
-#define        R5      5
-#define        R6      6
-#define        R7      7
-#define        R8      8
-#define        R9      9
-#define        R10     10
-#define        R11     11
-#define        R12     12
-#define        R13     13
-#define        R14     14
-#define        R15     15
-
-#define        NULLCODE        0       /* Null Code */
-#define        POINT_HIGH      0x8     /* Select upper half of registers */
-#define        RES_EXT_INT     0x10    /* Reset Ext. Status Interrupts */
-#define        SEND_ABORT      0x18    /* HDLC Abort */
-#define        RES_RxINT_FC    0x20    /* Reset RxINT on First Character */
-#define        RES_Tx_P        0x28    /* Reset TxINT Pending */
-#define        ERR_RES         0x30    /* Error Reset */
-#define        RES_H_IUS       0x38    /* Reset highest IUS */
-
-#define        RES_Rx_CRC      0x40    /* Reset Rx CRC Checker */
-#define        RES_Tx_CRC      0x80    /* Reset Tx CRC Checker */
-#define        RES_EOM_L       0xC0    /* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define        EXT_INT_ENAB    0x1     /* Ext Int Enable */
-#define        TxINT_ENAB      0x2     /* Tx Int Enable */
-#define        PAR_SPEC        0x4     /* Parity is special condition */
-
-#define        RxINT_DISAB     0       /* Rx Int Disable */
-#define        RxINT_FCERR     0x8     /* Rx Int on First Character Only or Error */
-#define        INT_ALL_Rx      0x10    /* Int on all Rx Characters or error */
-#define        INT_ERR_Rx      0x18    /* Int on error only */
-
-#define        WT_RDY_RT       0x20    /* Wait/Ready on R/T */
-#define        WT_FN_RDYFN     0x40    /* Wait/FN/Ready FN */
-#define        WT_RDY_ENAB     0x80    /* Wait/Ready Enable */
-
-/* Write Register 2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define        RxENABLE        0x1     /* Rx Enable */
-#define        SYNC_L_INH      0x2     /* Sync Character Load Inhibit */
-#define        ADD_SM          0x4     /* Address Search Mode (SDLC) */
-#define        RxCRC_ENAB      0x8     /* Rx CRC Enable */
-#define        ENT_HM          0x10    /* Enter Hunt Mode */
-#define        AUTO_ENAB       0x20    /* Auto Enables */
-#define        Rx5             0x0     /* Rx 5 Bits/Character */
-#define        Rx7             0x40    /* Rx 7 Bits/Character */
-#define        Rx6             0x80    /* Rx 6 Bits/Character */
-#define        Rx8             0xc0    /* Rx 8 Bits/Character */
-
-/* Write Register 4 */
-
-#define        PAR_ENA         0x1     /* Parity Enable */
-#define        PAR_EVEN        0x2     /* Parity Even/Odd* */
-
-#define        SYNC_ENAB       0       /* Sync Modes Enable */
-#define        SB1             0x4     /* 1 stop bit/char */
-#define        SB15            0x8     /* 1.5 stop bits/char */
-#define        SB2             0xc     /* 2 stop bits/char */
-
-#define        MONSYNC         0       /* 8 Bit Sync character */
-#define        BISYNC          0x10    /* 16 bit sync character */
-#define        SDLC            0x20    /* SDLC Mode (01111110 Sync Flag) */
-#define        EXTSYNC         0x30    /* External Sync Mode */
-
-#define        X1CLK           0x0     /* x1 clock mode */
-#define        X16CLK          0x40    /* x16 clock mode */
-#define        X32CLK          0x80    /* x32 clock mode */
-#define        X64CLK          0xC0    /* x64 clock mode */
-
-/* Write Register 5 */
-
-#define        TxCRC_ENAB      0x1     /* Tx CRC Enable */
-#define        RTS             0x2     /* RTS */
-#define        SDLC_CRC        0x4     /* SDLC/CRC-16 */
-#define        TxENAB          0x8     /* Tx Enable */
-#define        SND_BRK         0x10    /* Send Break */
-#define        Tx5             0x0     /* Tx 5 bits (or less)/character */
-#define        Tx7             0x20    /* Tx 7 bits/character */
-#define        Tx6             0x40    /* Tx 6 bits/character */
-#define        Tx8             0x60    /* Tx 8 bits/character */
-#define        DTR             0x80    /* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define        VIS     1       /* Vector Includes Status */
-#define        NV      2       /* No Vector */
-#define        DLC     4       /* Disable Lower Chain */
-#define        MIE     8       /* Master Interrupt Enable */
-#define        STATHI  0x10    /* Status high */
-#define        NORESET 0       /* No reset on write to R9 */
-#define        CHRB    0x40    /* Reset channel B */
-#define        CHRA    0x80    /* Reset channel A */
-#define        FHWRES  0xc0    /* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define        BIT6    1       /* 6 bit/8bit sync */
-#define        LOOPMODE 2      /* SDLC Loop mode */
-#define        ABUNDER 4       /* Abort/flag on SDLC xmit underrun */
-#define        MARKIDLE 8      /* Mark/flag on idle */
-#define        GAOP    0x10    /* Go active on poll */
-#define        NRZ     0       /* NRZ mode */
-#define        NRZI    0x20    /* NRZI mode */
-#define        FM1     0x40    /* FM1 (transition = 1) */
-#define        FM0     0x60    /* FM0 (transition = 0) */
-#define        CRCPS   0x80    /* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define        TRxCXT  0       /* TRxC = Xtal output */
-#define        TRxCTC  1       /* TRxC = Transmit clock */
-#define        TRxCBR  2       /* TRxC = BR Generator Output */
-#define        TRxCDP  3       /* TRxC = DPLL output */
-#define        TRxCOI  4       /* TRxC O/I */
-#define        TCRTxCP 0       /* Transmit clock = RTxC pin */
-#define        TCTRxCP 8       /* Transmit clock = TRxC pin */
-#define        TCBR    0x10    /* Transmit clock = BR Generator output */
-#define        TCDPLL  0x18    /* Transmit clock = DPLL output */
-#define        RCRTxCP 0       /* Receive clock = RTxC pin */
-#define        RCTRxCP 0x20    /* Receive clock = TRxC pin */
-#define        RCBR    0x40    /* Receive clock = BR Generator output */
-#define        RCDPLL  0x60    /* Receive clock = DPLL output */
-#define        RTxCX   0x80    /* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define        BRENABL 1       /* Baud rate generator enable */
-#define        BRSRC   2       /* Baud rate generator source */
-#define        DTRREQ  4       /* DTR/Request function */
-#define        AUTOECHO 8      /* Auto Echo */
-#define        LOOPBAK 0x10    /* Local loopback */
-#define        SEARCH  0x20    /* Enter search mode */
-#define        RMC     0x40    /* Reset missing clock */
-#define        DISDPLL 0x60    /* Disable DPLL */
-#define        SSBR    0x80    /* Set DPLL source = BR generator */
-#define        SSRTxC  0xa0    /* Set DPLL source = RTxC */
-#define        SFMM    0xc0    /* Set FM mode */
-#define        SNRZI   0xe0    /* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define        ZCIE    2       /* Zero count IE */
-#define        DCDIE   8       /* DCD IE */
-#define        SYNCIE  0x10    /* Sync/hunt IE */
-#define        CTSIE   0x20    /* CTS IE */
-#define        TxUIE   0x40    /* Tx Underrun/EOM IE */
-#define        BRKIE   0x80    /* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define        Rx_CH_AV        0x1     /* Rx Character Available */
-#define        ZCOUNT          0x2     /* Zero count */
-#define        Tx_BUF_EMP      0x4     /* Tx Buffer empty */
-#define        DCD             0x8     /* DCD */
-#define        SYNC_HUNT       0x10    /* Sync/hunt */
-#define        CTS             0x20    /* CTS */
-#define        TxEOM           0x40    /* Tx underrun */
-#define        BRK_ABRT        0x80    /* Break/Abort */
-
-/* Read Register 1 */
-#define        ALL_SNT         0x1     /* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define        RES3            0x8     /* 0/3 */
-#define        RES4            0x4     /* 0/4 */
-#define        RES5            0xc     /* 0/5 */
-#define        RES6            0x2     /* 0/6 */
-#define        RES7            0xa     /* 0/7 */
-#define        RES8            0x6     /* 0/8 */
-#define        RES18           0xe     /* 1/8 */
-#define        RES28           0x0     /* 2/8 */
-/* Special Rx Condition Interrupts */
-#define        PAR_ERR         0x10    /* Parity error */
-#define        Rx_OVR          0x20    /* Rx Overrun Error */
-#define        CRC_ERR         0x40    /* CRC/Framing Error */
-#define        END_FR          0x80    /* End of Frame (SDLC) */
-
-/* Read Register 2 (channel B only) - Interrupt vector */
-
-#define VECTOR_MASK    0x06
-
-#define TXINT   0x00
-#define EXINT   0x02
-#define RXINT   0x04
-#define SPINT   0x06
-
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define        CHBEXT  0x1             /* Channel B Ext/Stat IP */
-#define        CHBTxIP 0x2             /* Channel B Tx IP */
-#define        CHBRxIP 0x4             /* Channel B Rx IP */
-#define        CHAEXT  0x8             /* Channel A Ext/Stat IP */
-#define        CHATxIP 0x10            /* Channel A Tx IP */
-#define        CHARxIP 0x20            /* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10  (misc status bits) */
-#define        ONLOOP  2               /* On loop */
-#define        LOOPSEND 0x10           /* Loop sending */
-#define        CLK2MIS 0x40            /* Two clocks missing */
-#define        CLK1MIS 0x80            /* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
-
-
-/* 8536 register definitions */
-
-#define CIO_MICR       0x00    /* Master interrupt control register */
-#define CIO_MCCR       0x01    /* Master configuration control register */
-#define CIO_CTMS1      0x1c    /* Counter/timer mode specification #1 */
-#define CIO_CTMS2      0x1d    /* Counter/timer mode specification #2 */
-#define CIO_CTMS3      0x1e    /* Counter/timer mode specification #3 */
-#define CIO_IVR        0x04    /* Interrupt vector register */
-
-#define CIO_CSR1       0x0a    /* Command and status register CTC #1 */
-#define CIO_CSR2       0x0b    /* Command and status register CTC #2 */
-#define CIO_CSR3       0x0c    /* Command and status register CTC #3 */
-
-#define CIO_CT1MSB     0x16    /* CTC #1 Timer constant - MSB */
-#define CIO_CT1LSB     0x17    /* CTC #1 Timer constant - LSB */
-#define CIO_CT2MSB     0x18    /* CTC #2 Timer constant - MSB */
-#define CIO_CT2LSB     0x19    /* CTC #2 Timer constant - LSB */
-#define CIO_CT3MSB     0x1a    /* CTC #3 Timer constant - MSB */
-#define CIO_CT3LSB     0x1b    /* CTC #3 Timer constant - LSB */
-#define CIO_PDCA       0x23    /* Port A data direction control */
-#define CIO_PDCB       0x2b    /* Port B data direction control */
-
-#define CIO_GCB        0x04    /* CTC Gate command bit */
-#define CIO_TCB        0x02    /* CTC Trigger command bit */
-#define CIO_IE         0xc0    /* CTC Interrupt enable (set) */
-#define CIO_CIP        0x20    /* CTC Clear interrupt pending */
-#define CIO_IP         0x20    /* CTC Interrupt pending */
-
-
-/* 8580/85180/85280 Enhanced SCC register definitions */
-
-/* Write Register 7' (SDLC/HDLC Programmable Enhancements) */
-#define AUTOTXF        0x01            /* Auto Tx Flag */
-#define AUTOEOM 0x02           /* Auto EOM Latch Reset */
-#define AUTORTS        0x04            /* Auto RTS */
-#define TXDNRZI 0x08           /* TxD Pulled High in SDLC NRZI mode */
-#define FASTDTR 0x10           /* Fast DTR/REQ Mode */
-#define CRCCBCR        0x20            /* CRC Check Bytes Completely Received */
-#define EXTRDEN        0x40            /* Extended Read Enabled */
-
-/* Write Register 15 (external/status interrupt control) */
-#define SHDLCE 1               /* SDLC/HDLC Enhancements Enable */
-#define FIFOE  4               /* FIFO Enable */
-
-/* Read Register 6 (frame status FIFO) */
-#define BCLSB  0xff            /* LSB of 14 bits count */
-
-/* Read Register 7 (frame status FIFO) */
-#define BCMSB  0x3f            /* MSB of 14 bits count */
-#define FDA    0x40            /* FIFO Data Available Status */
-#define FOY    0x80            /* FIFO Overflow Status */
-
-#endif /* _SCC_H */
-
-/* global functions */
-
-#ifdef PREV_LINUX_1_3_33
-extern long scc_init(long kmem_start);
-#else
-extern int scc_init(void);
+int scc_init(void);
 #endif
index dee4875d1b7513ccbdb81a3f6e6b2c72d16516b3..6254c2440cde004a33c9e8dec0bef7aa8e9c04b5 100644 (file)
  * SUCH DAMAGE.
  */
 
-#define SOUND_VERSION  350
-#define UNIX_SOUND_SYSTEM
 
+/*
+ * OSS interface version. With versions earlier than 3.6 this value is
+ * an integer with value less than 361. In versions 3.6 and later
+ * it's a six digit hexadecimal value. For example value
+ * of 0x030600 represents OSS version 3.6.0.
+ * Use ioctl(fd, OSS_GETVERSION, &int) to get the version number of
+ * the currently active driver.
+ */
+#define SOUND_VERSION  0x030700
+#define OPEN_SOUND_SYSTEM
+
+/* In Linux we need to be prepared for cross compiling */
 #include <linux/ioctl.h>
 
 /*
  * IOCTL Commands for /dev/sequencer
  */
 
-#ifndef _IOWR
-/*     @(#)ioctlp.h */
+#ifndef _SIOWR
+#if defined(_IOWR) && !defined(sun)
+/* Use already defined ioctl defines if they exist (except with Sun) */
+#define        SIOCPARM_MASK   IOCPARM_MASK
+#define        SIOC_VOID       IOC_VOID
+#define        SIOC_OUT        IOC_OUT
+#define        SIOC_IN         IOC_IN
+#define        SIOC_INOUT      IOC_INOUT
+#define        _SIO            _IO
+#define        _SIOR           _IOR
+#define        _SIOW           _IOW
+#define        _SIOWR          _IOWR
+#else
 
 /* Ioctl's have the command encoded in the lower word,
  * and the size of any in or out parameters in the upper
  * to encode the in/out status of the parameter; for now
  * we restrict parameters to at most 128 bytes.
  */
-/* #define     IOCTYPE         (0xff<<8) */
-#define        IOCPARM_MASK    0x7f            /* parameters must be < 128 bytes */
-#define        IOC_VOID        0x00000000      /* no parameters */
-#define        IOC_OUT         0x20000000      /* copy out parameters */
-#define        IOC_IN          0x40000000      /* copy in parameters */
-#define        IOC_INOUT       (IOC_IN|IOC_OUT)
+/* #define     SIOCTYPE                (0xff<<8) */
+#define        SIOCPARM_MASK   0x1fff          /* parameters must be < 8192 bytes */
+#define        SIOC_VOID       0x00000000      /* no parameters */
+#define        SIOC_OUT        0x20000000      /* copy out parameters */
+#define        SIOC_IN         0x40000000      /* copy in parameters */
+#define        SIOC_INOUT      (SIOC_IN|SIOC_OUT)
 /* the 0x20000000 is so we can distinguish new ioctl's from old */
-#define        _IO(x,y)        ((int)(IOC_VOID|(x<<8)|y))
-#define        _IOR(x,y,t)     ((int)(IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y))
-#define        _IOW(x,y,t)     ((int)(IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y))
-/* this should be _IORW, but stdio got there first */
-#define        _IOWR(x,y,t)    ((int)(IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y))
-#endif  /* !_IOWR */
-
-#define SNDCTL_SEQ_RESET               _IO  ('Q', 0)
-#define SNDCTL_SEQ_SYNC                        _IO  ('Q', 1)
-#define SNDCTL_SYNTH_INFO              _IOWR('Q', 2, struct synth_info)
-#define SNDCTL_SEQ_CTRLRATE            _IOWR('Q', 3, int)      /* Set/get timer resolution (HZ) */
-#define SNDCTL_SEQ_GETOUTCOUNT         _IOR ('Q', 4, int)
-#define SNDCTL_SEQ_GETINCOUNT          _IOR ('Q', 5, int)
-#define SNDCTL_SEQ_PERCMODE            _IOW ('Q', 6, int)
-#define SNDCTL_FM_LOAD_INSTR           _IOW ('Q', 7, struct sbi_instrument)    /* Valid for FM only */
-#define SNDCTL_SEQ_TESTMIDI            _IOW ('Q', 8, int)
-#define SNDCTL_SEQ_RESETSAMPLES                _IOW ('Q', 9, int)
-#define SNDCTL_SEQ_NRSYNTHS            _IOR ('Q',10, int)
-#define SNDCTL_SEQ_NRMIDIS             _IOR ('Q',11, int)
-#define SNDCTL_MIDI_INFO               _IOWR('Q',12, struct midi_info)
-#define SNDCTL_SEQ_THRESHOLD           _IOW ('Q',13, int)
+#define        _SIO(x,y)       ((int)(SIOC_VOID|(x<<8)|y))
+#define        _SIOR(x,y,t)    ((int)(SIOC_OUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#define        _SIOW(x,y,t)    ((int)(SIOC_IN|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+/* this should be _SIORW, but stdio got there first */
+#define        _SIOWR(x,y,t)   ((int)(SIOC_INOUT|((sizeof(t)&SIOCPARM_MASK)<<16)|(x<<8)|y))
+#  endif /* _IOWR */
+#endif  /* !_SIOWR */
+
+#define SNDCTL_SEQ_RESET               _SIO  ('Q', 0)
+#define SNDCTL_SEQ_SYNC                        _SIO  ('Q', 1)
+#define SNDCTL_SYNTH_INFO              _SIOWR('Q', 2, struct synth_info)
+#define SNDCTL_SEQ_CTRLRATE            _SIOWR('Q', 3, int)     /* Set/get timer resolution (HZ) */
+#define SNDCTL_SEQ_GETOUTCOUNT         _SIOR ('Q', 4, int)
+#define SNDCTL_SEQ_GETINCOUNT          _SIOR ('Q', 5, int)
+#define SNDCTL_SEQ_PERCMODE            _SIOW ('Q', 6, int)
+#define SNDCTL_FM_LOAD_INSTR           _SIOW ('Q', 7, struct sbi_instrument)   /* Valid for FM only */
+#define SNDCTL_SEQ_TESTMIDI            _SIOW ('Q', 8, int)
+#define SNDCTL_SEQ_RESETSAMPLES                _SIOW ('Q', 9, int)
+#define SNDCTL_SEQ_NRSYNTHS            _SIOR ('Q',10, int)
+#define SNDCTL_SEQ_NRMIDIS             _SIOR ('Q',11, int)
+#define SNDCTL_MIDI_INFO               _SIOWR('Q',12, struct midi_info)
+#define SNDCTL_SEQ_THRESHOLD           _SIOW ('Q',13, int)
 #define SNDCTL_SEQ_TRESHOLD            SNDCTL_SEQ_THRESHOLD    /* there was once a typo */
-#define SNDCTL_SYNTH_MEMAVL            _IOWR('Q',14, int)      /* in=dev#, out=memsize */
-#define SNDCTL_FM_4OP_ENABLE           _IOW ('Q',15, int)      /* in=dev# */
-#define SNDCTL_PMGR_ACCESS             _IOWR('Q',16, struct patmgr_info)
-#define SNDCTL_SEQ_PANIC               _IO  ('Q',17)
-#define SNDCTL_SEQ_OUTOFBAND           _IOW ('Q',18, struct seq_event_rec)
+#define SNDCTL_SYNTH_MEMAVL            _SIOWR('Q',14, int)     /* in=dev#, out=memsize */
+#define SNDCTL_FM_4OP_ENABLE           _SIOW ('Q',15, int)     /* in=dev# */
+#define SNDCTL_PMGR_ACCESS             _SIOWR('Q',16, struct patmgr_info)
+#define SNDCTL_SEQ_PANIC               _SIO  ('Q',17)
+#define SNDCTL_SEQ_OUTOFBAND           _SIOW ('Q',18, struct seq_event_rec)
+#define SNDCTL_SEQ_GETTIME             _SIOR ('Q',19, int)
 
        struct seq_event_rec {
                        unsigned char arr[8];
                };
 
-#define SNDCTL_TMR_TIMEBASE            _IOWR('T', 1, int)
-#define SNDCTL_TMR_START               _IO  ('T', 2)
-#define SNDCTL_TMR_STOP                        _IO  ('T', 3)
-#define SNDCTL_TMR_CONTINUE            _IO  ('T', 4)
-#define SNDCTL_TMR_TEMPO               _IOWR('T', 5, int)
-#define SNDCTL_TMR_SOURCE              _IOWR('T', 6, int)
+#define SNDCTL_TMR_TIMEBASE            _SIOWR('T', 1, int)
+#define SNDCTL_TMR_START               _SIO  ('T', 2)
+#define SNDCTL_TMR_STOP                        _SIO  ('T', 3)
+#define SNDCTL_TMR_CONTINUE            _SIO  ('T', 4)
+#define SNDCTL_TMR_TEMPO               _SIOWR('T', 5, int)
+#define SNDCTL_TMR_SOURCE              _SIOWR('T', 6, int)
 #      define TMR_INTERNAL             0x00000001
 #      define TMR_EXTERNAL             0x00000002
 #              define TMR_MODE_MIDI    0x00000010
 #              define TMR_MODE_FSK     0x00000020
 #              define TMR_MODE_CLS     0x00000040
 #              define TMR_MODE_SMPTE   0x00000080
-#define SNDCTL_TMR_METRONOME           _IOW ('T', 7, int)
-#define SNDCTL_TMR_SELECT              _IOW ('T', 8, int)
+#define SNDCTL_TMR_METRONOME           _SIOW ('T', 7, int)
+#define SNDCTL_TMR_SELECT              _SIOW ('T', 8, int)
 
 /*
- *     Endian aware patch key generation algorithm.
+ * Some big endian/little endian handling macros
  */
 
-#if defined(_AIX) || defined(AIX)
+#if defined(_AIX) || defined(AIX) || defined(sparc) || defined(HPPA) || defined(PPC)
+/* Big endian machines */
 #  define _PATCHKEY(id) (0xfd00|id)
+#  define AFMT_S16_NE AFMT_S16_BE
 #else
 #  define _PATCHKEY(id) ((id<<8)|0xfd)
+#  define AFMT_S16_NE AFMT_S16_LE
 #endif
 
 /*
@@ -248,7 +274,7 @@ struct sysex_info {
 #define                PS_MGR_OK               2       /* Patch manager supported */
 #define                PS_MANAGED              3       /* Patch manager running */
 
-#define SNDCTL_PMGR_IFACE              _IOWR('P', 1, struct patmgr_info)
+#define SNDCTL_PMGR_IFACE              _SIOWR('P', 1, struct patmgr_info)
 
 /*
  * The patmgr_info is a fixed size structure which is used for two
@@ -540,30 +566,30 @@ typedef struct {
                unsigned char data[30];
        } mpu_command_rec;
 
-#define SNDCTL_MIDI_PRETIME            _IOWR('m', 0, int)
-#define SNDCTL_MIDI_MPUMODE            _IOWR('m', 1, int)
-#define SNDCTL_MIDI_MPUCMD             _IOWR('m', 2, mpu_command_rec)
+#define SNDCTL_MIDI_PRETIME            _SIOWR('m', 0, int)
+#define SNDCTL_MIDI_MPUMODE            _SIOWR('m', 1, int)
+#define SNDCTL_MIDI_MPUCMD             _SIOWR('m', 2, mpu_command_rec)
 
 /********************************************
  * IOCTL commands for /dev/dsp and /dev/audio
  */
 
-#define SNDCTL_DSP_RESET               _IO  ('P', 0)
-#define SNDCTL_DSP_SYNC                        _IO  ('P', 1)
-#define SNDCTL_DSP_SPEED               _IOWR('P', 2, int)
-#define SNDCTL_DSP_STEREO              _IOWR('P', 3, int)
-#define SNDCTL_DSP_GETBLKSIZE          _IOWR('P', 4, int)
+#define SNDCTL_DSP_RESET               _SIO  ('P', 0)
+#define SNDCTL_DSP_SYNC                        _SIO  ('P', 1)
+#define SNDCTL_DSP_SPEED               _SIOWR('P', 2, int)
+#define SNDCTL_DSP_STEREO              _SIOWR('P', 3, int)
+#define SNDCTL_DSP_GETBLKSIZE          _SIOWR('P', 4, int)
 #define SNDCTL_DSP_SAMPLESIZE          SNDCTL_DSP_SETFMT
-#define SNDCTL_DSP_CHANNELS            _IOWR('P', 6, int)
+#define SNDCTL_DSP_CHANNELS            _SIOWR('P', 6, int)
 #define SOUND_PCM_WRITE_CHANNELS       SNDCTL_DSP_CHANNELS
-#define SOUND_PCM_WRITE_FILTER         _IOWR('P', 7, int)
-#define SNDCTL_DSP_POST                        _IO  ('P', 8)
-#define SNDCTL_DSP_SUBDIVIDE           _IOWR('P', 9, int)
-#define SNDCTL_DSP_SETFRAGMENT         _IOWR('P',10, int)
+#define SOUND_PCM_WRITE_FILTER         _SIOWR('P', 7, int)
+#define SNDCTL_DSP_POST                        _SIO  ('P', 8)
+#define SNDCTL_DSP_SUBDIVIDE           _SIOWR('P', 9, int)
+#define SNDCTL_DSP_SETFRAGMENT         _SIOWR('P',10, int)
 
 /*     Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */
-#define SNDCTL_DSP_GETFMTS             _IOR ('P',11, int) /* Returns a mask */
-#define SNDCTL_DSP_SETFMT              _IOWR('P',5, int) /* Selects ONE fmt*/
+#define SNDCTL_DSP_GETFMTS             _SIOR ('P',11, int) /* Returns a mask */
+#define SNDCTL_DSP_SETFMT              _SIOWR('P',5, int) /* Selects ONE fmt*/
 #      define AFMT_QUERY               0x00000000      /* Return current fmt */
 #      define AFMT_MU_LAW              0x00000001
 #      define AFMT_A_LAW               0x00000002
@@ -588,10 +614,10 @@ typedef struct audio_buf_info {
                        /* Note! 'bytes' could be more than fragments*fragsize */
                } audio_buf_info;
 
-#define SNDCTL_DSP_GETOSPACE           _IOR ('P',12, audio_buf_info)
-#define SNDCTL_DSP_GETISPACE           _IOR ('P',13, audio_buf_info)
-#define SNDCTL_DSP_NONBLOCK            _IO  ('P',14)
-#define SNDCTL_DSP_GETCAPS             _IOR ('P',15, int)
+#define SNDCTL_DSP_GETOSPACE           _SIOR ('P',12, audio_buf_info)
+#define SNDCTL_DSP_GETISPACE           _SIOR ('P',13, audio_buf_info)
+#define SNDCTL_DSP_NONBLOCK            _SIO  ('P',14)
+#define SNDCTL_DSP_GETCAPS             _SIOR ('P',15, int)
 #      define DSP_CAP_REVISION         0x000000ff      /* Bits for revision level (0 to 255) */
 #      define DSP_CAP_DUPLEX           0x00000100      /* Full duplex record/playback */
 #      define DSP_CAP_REALTIME         0x00000200      /* Real time capability */
@@ -605,8 +631,8 @@ typedef struct audio_buf_info {
 #      define DSP_CAP_TRIGGER          0x00001000      /* Supports SETTRIGGER */
 #      define DSP_CAP_MMAP             0x00002000      /* Supports mmap() */
 
-#define SNDCTL_DSP_GETTRIGGER          _IOR ('P',16, int)
-#define SNDCTL_DSP_SETTRIGGER          _IOW ('P',16, int)
+#define SNDCTL_DSP_GETTRIGGER          _SIOR ('P',16, int)
+#define SNDCTL_DSP_SETTRIGGER          _SIOW ('P',16, int)
 #      define PCM_ENABLE_INPUT         0x00000001
 #      define PCM_ENABLE_OUTPUT        0x00000002
 
@@ -616,22 +642,22 @@ typedef struct count_info {
                int ptr;        /* Current DMA pointer value */
        } count_info;
 
-#define SNDCTL_DSP_GETIPTR             _IOR ('P',17, count_info)
-#define SNDCTL_DSP_GETOPTR             _IOR ('P',18, count_info)
+#define SNDCTL_DSP_GETIPTR             _SIOR ('P',17, count_info)
+#define SNDCTL_DSP_GETOPTR             _SIOR ('P',18, count_info)
 
 typedef struct buffmem_desc {
                unsigned *buffer;
                int size;
        } buffmem_desc;
-#define SNDCTL_DSP_MAPINBUF            _IOR ('P', 19, buffmem_desc)
-#define SNDCTL_DSP_MAPOUTBUF           _IOR ('P', 20, buffmem_desc)
-#define SNDCTL_DSP_SETSYNCRO           _IO  ('P', 21)
-#define SNDCTL_DSP_SETDUPLEX           _IO  ('P', 22)
+#define SNDCTL_DSP_MAPINBUF            _SIOR ('P', 19, buffmem_desc)
+#define SNDCTL_DSP_MAPOUTBUF           _SIOR ('P', 20, buffmem_desc)
+#define SNDCTL_DSP_SETSYNCRO           _SIO  ('P', 21)
+#define SNDCTL_DSP_SETDUPLEX           _SIO  ('P', 22)
 
-#define SOUND_PCM_READ_RATE            _IOR ('P', 2, int)
-#define SOUND_PCM_READ_CHANNELS                _IOR ('P', 6, int)
-#define SOUND_PCM_READ_BITS            _IOR ('P', 5, int)
-#define SOUND_PCM_READ_FILTER          _IOR ('P', 7, int)
+#define SOUND_PCM_READ_RATE            _SIOR ('P', 2, int)
+#define SOUND_PCM_READ_CHANNELS                _SIOR ('P', 6, int)
+#define SOUND_PCM_READ_BITS            _SIOR ('P', 5, int)
+#define SOUND_PCM_READ_FILTER          _SIOR ('P', 7, int)
 
 /* Some alias names */
 #define SOUND_PCM_WRITE_BITS           SNDCTL_DSP_SETFMT
@@ -685,16 +711,16 @@ typedef struct copr_msg {
                unsigned char data[4000];
        } copr_msg;
 
-#define SNDCTL_COPR_RESET             _IO  ('C',  0)
-#define SNDCTL_COPR_LOAD             _IOWR('C',  1, copr_buffer)
-#define SNDCTL_COPR_RDATA            _IOWR('C',  2, copr_debug_buf)
-#define SNDCTL_COPR_RCODE            _IOWR('C',  3, copr_debug_buf)
-#define SNDCTL_COPR_WDATA            _IOW ('C',  4, copr_debug_buf)
-#define SNDCTL_COPR_WCODE            _IOW ('C',  5, copr_debug_buf)
-#define SNDCTL_COPR_RUN                      _IOWR('C',  6, copr_debug_buf)
-#define SNDCTL_COPR_HALT             _IOWR('C',  7, copr_debug_buf)
-#define SNDCTL_COPR_SENDMSG          _IOWR('C',  8, copr_msg)
-#define SNDCTL_COPR_RCVMSG           _IOR ('C',  9, copr_msg)
+#define SNDCTL_COPR_RESET             _SIO  ('C',  0)
+#define SNDCTL_COPR_LOAD             _SIOWR('C',  1, copr_buffer)
+#define SNDCTL_COPR_RDATA            _SIOWR('C',  2, copr_debug_buf)
+#define SNDCTL_COPR_RCODE            _SIOWR('C',  3, copr_debug_buf)
+#define SNDCTL_COPR_WDATA            _SIOW ('C',  4, copr_debug_buf)
+#define SNDCTL_COPR_WCODE            _SIOW ('C',  5, copr_debug_buf)
+#define SNDCTL_COPR_RUN                      _SIOWR('C',  6, copr_debug_buf)
+#define SNDCTL_COPR_HALT             _SIOWR('C',  7, copr_debug_buf)
+#define SNDCTL_COPR_SENDMSG          _SIOWR('C',  8, copr_msg)
+#define SNDCTL_COPR_RCVMSG           _SIOR ('C',  9, copr_msg)
 
 /*********************************************
  * IOCTL commands for /dev/mixer
@@ -740,15 +766,15 @@ typedef struct copr_msg {
 #define SOUND_ONOFF_MAX                30
 
 /* Note!       Number 31 cannot be used since the sign bit is reserved */
-
+#define SOUND_MIXER_NONE       31
 
 /*
  * The following unsupported macros are no longer functional.
  * Use SOUND_MIXER_PRIVATE# macros in future.
  */
-#define SOUND_MIXER_ENHANCE    31
-#define SOUND_MIXER_MUTE       31
-#define SOUND_MIXER_LOUD       31
+#define SOUND_MIXER_ENHANCE    SOUND_MIXER_NONE
+#define SOUND_MIXER_MUTE       SOUND_MIXER_NONE
+#define SOUND_MIXER_LOUD       SOUND_MIXER_NONE
 
 
 #define SOUND_DEVICE_LABELS    {"Vol  ", "Bass ", "Trebl", "Synth", "Pcm  ", "Spkr ", "Line ", \
@@ -793,7 +819,7 @@ typedef struct copr_msg {
 #define SOUND_MASK_ENHANCE     (1 << SOUND_MIXER_ENHANCE)
 #define SOUND_MASK_LOUD                (1 << SOUND_MIXER_LOUD)
 
-#define MIXER_READ(dev)                _IOR('M', dev, int)
+#define MIXER_READ(dev)                _SIOR('M', dev, int)
 #define SOUND_MIXER_READ_VOLUME                MIXER_READ(SOUND_MIXER_VOLUME)
 #define SOUND_MIXER_READ_BASS          MIXER_READ(SOUND_MIXER_BASS)
 #define SOUND_MIXER_READ_TREBLE                MIXER_READ(SOUND_MIXER_TREBLE)
@@ -823,7 +849,7 @@ typedef struct copr_msg {
 #define SOUND_MIXER_READ_STEREODEVS    MIXER_READ(SOUND_MIXER_STEREODEVS)
 #define SOUND_MIXER_READ_CAPS          MIXER_READ(SOUND_MIXER_CAPS)
 
-#define MIXER_WRITE(dev)               _IOWR('M', dev, int)
+#define MIXER_WRITE(dev)               _SIOWR('M', dev, int)
 #define SOUND_MIXER_WRITE_VOLUME       MIXER_WRITE(SOUND_MIXER_VOLUME)
 #define SOUND_MIXER_WRITE_BASS         MIXER_WRITE(SOUND_MIXER_BASS)
 #define SOUND_MIXER_WRITE_TREBLE       MIXER_WRITE(SOUND_MIXER_TREBLE)
@@ -853,9 +879,18 @@ typedef struct mixer_info
 {
   char id[16];
   char name[32];
+  int  modify_counter;
+  int fillers[10];
 } mixer_info;
 
-#define SOUND_MIXER_INFO               _IOR ('M', 101, mixer_info)
+typedef struct _old_mixer_info /* Obsolete */
+{
+  char id[16];
+  char name[32];
+} _old_mixer_info;
+
+#define SOUND_MIXER_INFO               _SIOR ('M', 101, mixer_info)
+#define SOUND_OLD_MIXER_INFO           _SIOR ('M', 101, _old_mixer_info)
 
 /*
  * A mechanism for accessing "proprietary" mixer features. This method
@@ -865,17 +900,42 @@ typedef struct mixer_info
  */
 typedef unsigned char mixer_record[128];
 
-#define SOUND_MIXER_ACCESS             _IOWR('M', 102, mixer_record)
+#define SOUND_MIXER_ACCESS             _SIOWR('M', 102, mixer_record)
 
 /*
  * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers.
  * These features can be used when accessing device specific features.
  */
-#define SOUND_MIXER_PRIVATE1           _IOWR('M', 111, int)
-#define SOUND_MIXER_PRIVATE2           _IOWR('M', 112, int)
-#define SOUND_MIXER_PRIVATE3           _IOWR('M', 113, int)
-#define SOUND_MIXER_PRIVATE4           _IOWR('M', 114, int)
-#define SOUND_MIXER_PRIVATE5           _IOWR('M', 115, int)
+#define SOUND_MIXER_PRIVATE1           _SIOWR('M', 111, int)
+#define SOUND_MIXER_PRIVATE2           _SIOWR('M', 112, int)
+#define SOUND_MIXER_PRIVATE3           _SIOWR('M', 113, int)
+#define SOUND_MIXER_PRIVATE4           _SIOWR('M', 114, int)
+#define SOUND_MIXER_PRIVATE5           _SIOWR('M', 115, int)
+
+/*
+ * SOUND_MIXER_GETLEVELS and SOUND_MIXER_SETLEVELS calls can be used
+ * for querying current mixer settings from the driver and for loading
+ * default volume settings _prior_ activating the mixer (loading
+ * doesn't affect current state of the mixer hardware). These calls
+ * are for internal use only.
+ */
+
+typedef struct mixer_vol_table {
+  int num;     /* Index to volume table */
+  char name[32];
+  int levels[32];
+} mixer_vol_table;
+
+#define SOUND_MIXER_GETLEVELS          _SIOWR('M', 116, mixer_vol_table)
+#define SOUND_MIXER_SETLEVELS          _SIOWR('M', 117, mixer_vol_table)
+
+/* 
+ * An ioctl for identifying the driver version. It will return value
+ * of the SOUND_VERSION macro used when compiling the driver.
+ * This call was introduced in OSS version 3.6 and it will not work
+ * with earlier versions (returns EINVAL).
+ */
+#define OSS_GETVERSION                 _SIOR ('M', 118, int)
 
 /*
  * Level 2 event types for /dev/sequencer
index 2e1ef2fcdea3427e587155e810f5100ee1fbb783..9021ae9192b7d16e149d189040652591cec4e7ed 100644 (file)
@@ -8,7 +8,7 @@
 /*
  * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
index 9a55a52b636a94ea353cb2aca715a7f738eaba92..0ed1eb6a6ba08f0550c416d786c917c76c36aa8d 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -16,7 +16,7 @@
 #include <linux/kerneld.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 extern int ipcperms (struct ipc_perm *ipcp, short msgflg);
 
index 2724a535802d90f58ac7e679e68fbcf817f9ff20..fb79d6004d34e65bf3703af9ed5dce2bf12d58e7 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -32,7 +32,6 @@
  */
 
 #include <linux/errno.h>
-#include <asm/segment.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/sem.h>
@@ -40,6 +39,8 @@
 #include <linux/stat.h>
 #include <linux/malloc.h>
 
+#include <asm/uaccess.h>
+
 extern int ipcperms (struct ipc_perm *ipcp, short semflg);
 static int newary (key_t, int, int);
 static int findkey (key_t key);
index 126944b0f490e6d16d0def4ff6708410e339f377..e12a1f30a2b3c30676aa95ec0dd66195017d0cd4 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -14,7 +14,7 @@
 #include <linux/malloc.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
index 89a7c3359b9f4361bb211ba3ce59b0bbeaa73418..e81afc36f6a88158b27abcb923ecf99075487e5b 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
-#include <asm/segment.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/sem.h>
@@ -13,6 +12,8 @@
 #include <linux/shm.h>
 #include <linux/stat.h>
 
+#include <asm/uaccess.h>
+
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 
 extern void sem_init (void), msg_init (void), shm_init (void);
index f233851fd56aad9f024ad0726a503a8505161ef8..6353a7743461e4159d6f49553de1c7f651c903d1 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 extern void sem_exit (void);
index ee5cdd5a8e3d4571e11ced1b90a591ad9bd698ad..07726e9d7fc89d2917ff0973ef4328332a47508a 100644 (file)
@@ -21,9 +21,9 @@
 #include <linux/malloc.h>
 #include <linux/smp.h>
 
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/uaccess.h>
 
 int nr_tasks=1;
 int nr_running=1;
index a602c4139b3dfd3650a6af876c7a67e180e0c73b..e6dc55734aaf5454be5857bad6117c39e18ec48a 100644 (file)
@@ -6,8 +6,6 @@
 
 /* This implements the sysinfo() system call */
 
-#include <asm/segment.h>
-
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/unistd.h>
@@ -15,6 +13,8 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 
+#include <asm/uaccess.h>
+
 asmlinkage int sys_sysinfo(struct sysinfo *info)
 {
        int error;
index f108334d9f79df55e1287c9ca1bd5b4151c75088..44bd8150f4f30eae59b2cee9800706c81ef35eaf 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  * change timeval to jiffies, trying to avoid the 
index 966b9f621e3c45c1e1f41ac5af28edbfd30ab69e..f83666193eabcceaca519edd1e7be25ef66dfdcb 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <asm/segment.h>
 #include <linux/mm.h>          /* defines GFP_KERNEL */
 #include <linux/string.h>
 #include <linux/module.h>
@@ -8,6 +7,8 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 #include <linux/config.h>
+
+#include <asm/uaccess.h>
 /*
  * Originally by Anonymous (as far as I know...)
  * Linux version by Bas Laarhoven <bas@vimec.nl>
index 78459e8383da1c8a11ca22d3cee9e95f931e968f..a0446d37381afd1247459c18a6ad3a9deb577604 100644 (file)
@@ -59,7 +59,7 @@ NORET_TYPE void panic(const char * fmt, ...)
 }
 
 /*
- * GCC 2.5.8 doesn't always optimize correctly; see include/asm/segment.h
+ * GCC 2.5.8 doesn't always optimize correctly; see include/asm/uaccess.h
  */
 
 int bad_user_access_length(void)
index da8ffca4c919b1a5c8e97cb20fdfbd410a8aefeb..ed39d4fab9e4ca72664545898b9dcfbb5b008c02 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <stdarg.h>
 
-#include <asm/segment.h>
 #include <asm/system.h>
 
 #include <linux/errno.h>
@@ -23,6 +22,8 @@
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 
+#include <asm/uaccess.h>
+
 #define LOG_BUF_LEN    8192
 
 static char buf[1024];
index 9415733bb3b40a7246d4872b3fd94bb4b209cbe6..3560a6d46a550a3111e960e6bb659a25b5dcf0d9 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 
index 27275b85bfdacdd9f589559da43f01625bdbf5f9..99f82331ebdd6fe18dff7967679b5bc9a11e06f7 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/unistd.h>
 #include <linux/mm.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #define _S(nr) (1<<((nr)-1))
 
index 60ee4baa2a2066aabfd3b599dd210261f8c10390..2017b81d6c39638dbe86effcda04c51f95d3d91f 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/apm_bios.h>
 #endif
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 /*
@@ -776,18 +776,7 @@ asmlinkage int sys_newuname(struct new_utsname * name)
 asmlinkage int sys_uname(struct old_utsname * name)
 {
        int error = -EFAULT;;
-       if (!name &&
-           !copy_to_user(&name->sysname,&system_utsname.sysname,
-               sizeof (system_utsname.sysname)) &&
-           !copy_to_user(&name->nodename,&system_utsname.nodename,
-               sizeof (system_utsname.nodename)) &&
-           !copy_to_user(&name->release,&system_utsname.release,
-               sizeof (system_utsname.release)) &&
-           !copy_to_user(&name->version,&system_utsname.version,
-               sizeof (system_utsname.version)) &&
-           !copy_to_user(&name->machine,&system_utsname.machine,
-               sizeof (system_utsname.machine))
-       )
+       if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
                error = 0;
        return error;
 }
index 5897096e2d188b5e130192134d1d5d004b8826ce..9b71940ac5661662a8f4db90981180b475376097 100644 (file)
 #include <linux/malloc.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-
 #include <linux/utsname.h>
 #include <linux/swapctl.h>
 
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
 /* External variables not in a header file. */
 extern int panic_timeout;
 
index 491f5e14fa92a2b79cadc5424fa05f1c4587ddc6..7eb9e2a8f63d875076a0ac7151f8b95793ffe28a 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/mm.h>
 #include <linux/timex.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /* 
  * The timezone where the local system is located.  Used as a default by some
index fdbe3cc458b458e82a8d2377665ae942ab7b8227..8f6c56440dbf1439f5b3e5c16d18f9fb73820f40 100644 (file)
@@ -23,9 +23,9 @@
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
+#include <asm/uaccess.h>
 
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
index 2c12d01f7b7f6fce0db1e4e19ca69faa37e35e00..f662bffbb638c25f85c598cf27737ac704f8e9e6 100644 (file)
@@ -46,7 +46,7 @@
 #include <linux/swap.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/string.h>
 
index 64b29434b71ded6274f65cebb97a8beb3d626ddf..65b9e54077af065928db069914d708c0301fc0da 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
index 292662b6a8ba7031ebd6b77f0d5d11aecb2be7de..75a7d2ad7286166a2c3794bea1e9f912b8f42aae 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -15,7 +15,7 @@
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
index 330e2c854c877f2625ce306da7f4b52d99bd142e..5aa7794a429682d75830d5adc5aac63d5b7c4dde 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
index 97064b2ea22284a7deafa636e4beec1eb43d53b1..56da75cfea84fee59a250527f4d480be55b1f99b 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/malloc.h>
 #include <linux/swap.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
index 6fc0470361ca3bc2c538c58f3e936df1993e0975..f6f1bbd706e7ae08d44bb58b971f2c27998386e0 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
index 14f645b7bff3afa3d393d9a1cc589b2f20abe6e9..9980c52b74eb53589a318ce47e2afa5d812ff6d6 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
index 75f028093a28dad656b28e560a9ea6f7f5352bbf..7076ec2f64e85ee9045ceb1063e29371d2fb1842 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -26,7 +26,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
index 99cc76957524c15fb764ee81b57d58d36e4e2715..0441807217385a56115943165a4c3812159afe78 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for cop_to/from_user */
+#include <asm/uaccess.h> /* for cop_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
index 146b42ca288a3f5447d983d130f502b3da2877ea..7012a4eda94231e38486784a043d94af9b41074d 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
index 26dcb59e1982e38719fd3366aadf44c8943ac73a..142e6d2566e86fa111f3cc711efbdaeca1a2aba9 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static struct vm_struct * vmlist = NULL;
index b062254f9b4128bfddbc19169e0a72e3ab4d3991..d14a82f0b0cd4187d2f18176fbe06bc782edcd76 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for copy_to/from_user */
+#include <asm/uaccess.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
index b17ac538a3d20af0d97c0d5e80cd1cf8fbc5aba9..c12a66d83f18f63ef8b1d644ac27f5a3a1aba0d9 100644 (file)
@@ -1,4 +1,4 @@
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 3deceee2afdb03e35096a55910beed711917d5fa..4b8d4fb7e4d5b73f2a6f17310c132bc49dce0733 100644 (file)
@@ -23,7 +23,7 @@
  *             Inside Appletalk (2nd Ed).
  */
  
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
index f23ab32e7137b11ddc3ba82072c0ddbe3ce5bd28..bdada63034046a9237bfa825c90949cbd4f41eca 100644 (file)
@@ -35,7 +35,7 @@
  
 #include <linux/config.h>
 #include <linux/module.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
@@ -1024,10 +1024,9 @@ static int atalk_setsockopt(struct socket *sock, int level, int optname, char *o
        if(optval==NULL)
                return(-EINVAL);
 
-       err=verify_area(VERIFY_READ,optval,sizeof(int));
-       if(err)
+       err = get_user(opt, (int *)optval);
+       if (err)
                return err;
-       opt=get_fs_long((unsigned long *)optval);
        
        switch(level)
        {
index 4c900407dbfefcdfc13267758307d4944d385bf8..11c09fb8fbf1185378f1ce6fd4837ad15390bfe0 100644 (file)
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
index bcd2aa975b3eeadd7cdcdfef75860390ac30be75..be5f16e3a46dedcc4b6bc73322c084e2c7d97d2a 100644 (file)
@@ -54,7 +54,7 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/ip.h>                    /* For ip_rcv */
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index f0f748e26b439f83ffd0b81dd088f55498d60b2c..a85fd7324229abbb588c93cd5cf8222bc6ab86b7 100644 (file)
@@ -48,7 +48,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index 801f435575fc50b1bdee1c2bfb5df51ad1f7bb83..fec63682bdd8e81b986081f7761e41f917671640 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index e87aedc2f51ee72ae4e1a9c41f492ad509b1a721..0c37cbc423b007a9801bc13e3844ec4e0de85838 100644 (file)
@@ -51,7 +51,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index 335755fbe52bfdcc3a4160c0dc2b7533f78ac745..2362d8e8d1e48dbcf01f7303b32f75509d9e3fcd 100644 (file)
@@ -38,7 +38,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index c2f86e13aebeaa43f6ff50c1e1833064a03343eb..587adf636cf42c9ba96655f6158bf49c79a366e4 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <net/br.h>
 
index 7f9aff0da543f08f8fa6bf812d24546b8104501f..b0f341656298574c9156103a93c8191bd1fe1781 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
index 20af844ed284f636e8ae0bdb9c476779e86c91bb..8be8425724403f4ab9209896635d31800e2cb1b7 100644 (file)
@@ -50,7 +50,7 @@
  *
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/config.h>
@@ -1366,6 +1366,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
 extern int lance_init(void);
 extern int ni65_init(void);
 extern int pi_init(void);
+extern int scc_init(void);
 extern void sdla_setup(void);
 extern void dlci_setup(void);
 
@@ -1407,6 +1408,9 @@ int net_dev_init(void)
 #if defined(CONFIG_PI)
        pi_init();
 #endif 
+#if defined(CONFIG_SCC)
+       scc_init();
+#endif
 #if defined(CONFIG_PT)
        pt_init();
 #endif
index 6756bc856c226914b2209afe4809e3084138a5f3..183d3fc3bf009ef0c5c8b306787fd13affc7d1fd 100644 (file)
@@ -20,7 +20,7 @@
  *     2 of the License, or (at your option) any later version.
  */
  
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
index 2a69ab6cc2f0df8d7a23998fbf9283bc68df8059..9059ca6b329591c056e2aea4a4bfa4e0137b52f9 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/net.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 
 extern inline int min(int x, int y)
index 6af7c270a298a8afcf5c33825c102946da9928d7..f9c613f186fef373a50192d3d141bb4a8de0c90b 100644 (file)
@@ -52,7 +52,7 @@
 #include <net/udp.h>
 #include <net/sock.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 /*
index d57778332f5f6d966629c665a3902754f3539774..db9fbbbf335d9c1f96e7abf9e4b60e0ed7bb17c3 100644 (file)
@@ -97,7 +97,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/inet.h>
index 61eb8f02b1451452367c515e1a79a5ec37527de3..e4a80d3886e5fa9e8e26796132a06b9ee2cdd596 100644 (file)
@@ -36,7 +36,7 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  */
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index f2092cc4fb62504900b6b29361f9d8b74c62d966..8dd763eac5f2eb3b3a023407cc3a934248b9969b 100644 (file)
@@ -75,7 +75,7 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 #include <linux/inet.h>
index 106c2460795b24611b6974ffff3bbdda5d96b2ff..ffd685219e9519783aae96d98fdcbdec52c1e045 100644 (file)
 #endif
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #include <stdarg.h>
 
index b10f205960cbf8bf542e29484f96f80de29fca8e..0c2d70caea2b76c2543b970a4c9b4d7f443c3f6f 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <linux/config.h>      /* For CONFIG_IP_CLASSLESS */
  
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
index e5c3a7fb0ddffc1c07f750346ec0d37679cc9e0f..e2b46fb927975117dc8c5858ccd7ddce1f361db2 100644 (file)
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <net/checksum.h>
 
 #define min(a,b)       ((a)<(b)?(a):(b))
index 627b05dfe719d3e01760742fabc893bc73daa0a4..f8f4e2ec2f42d9c74e070a30006d8b7b60e9efb5 100644 (file)
@@ -64,7 +64,7 @@
  */
 
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 887371b04c8e4fe54ff0e831e3e7b404926f74db..c6c33e03bcea7052f1406888e10ed51b1aaeb5ca 100644 (file)
@@ -366,7 +366,7 @@ static struct sk_buff *ip_glue(struct ipq *qp)
                {
                        NETDEBUG(printk("Invalid fragment list: Fragment over size.\n"));
                        ip_free(qp);
-                       frag_kfree_skb(skb,FREE_WRITE);
+                       kfree_skb(skb,FREE_WRITE);
                        ip_statistics.IpReasmFails++;
                        return NULL;
                }
@@ -466,6 +466,18 @@ struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device
                        return NULL;
                }
        }
+       
+       /*
+        *      Attempt to construct an oversize packet.
+        */
+        
+       if(ntohs(iph->tot_len)+(int)offset>65535)
+       {
+               skb->sk = NULL;
+               frag_kfree_skb(skb, FREE_READ);
+               ip_statistics.IpReasmFails++;
+               return NULL;
+       }       
 
        /*
         *      Determine the position of this fragment.
index f2ed0760db315f23b965e32e2c0c1535e7e78c68..b687b650e172921fc88ef1d161e2ed251075b9b6 100644 (file)
@@ -79,7 +79,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -149,7 +149,9 @@ struct ip_fw *ip_acct_chain;
 
 static struct ip_fw **chains[] =
        {&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain};
+#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */
 
+#ifdef CONFIG_IP_FIREWALL
 int ip_fw_fwd_policy=IP_FW_F_ACCEPT;
 int ip_fw_in_policy=IP_FW_F_ACCEPT;
 int ip_fw_out_policy=IP_FW_F_ACCEPT;
index d11c646adbdc69949d93af9f09aabc28fe5b5c79..3e286c4d7a91ea26b0f2f000ccfd9fd9ed7eadf4 100644 (file)
  *             2 of the License, or (at your option) any later version.
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 4034846d44180c1e05595fbe42bc8e3148097962..31e0d2ea9ceaf7ce7b7a5ec802d41515ae3ff9a9 100644 (file)
@@ -28,7 +28,7 @@
  *                                     output firewall rules)
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 195afcb7301a36880aee997327b555101df250c7..e196948a82dc5248399e5dc49636f81adde59285 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/mroute.h>
 #include <net/route.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #ifdef CONFIG_IP_MULTICAST
 
index 1a6500eb94e0989736f48451daebf015951510d7..46197a96ca895c04d34f6541cdde426c12d86521 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <linux/config.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
index de9844c26f51ab9c9aba1d47a66d42c4f6a119b3..ab17ffa8fb7518120ef20b9437a8537fa774cf6c 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 /*
  *     We really ought to have a single public _inline_ min function!
index 1d515383b2df4c08c83a3e2fc3a3f56deb39e525..2773fa326f4a15a1d3d60855e7dd81a2e22314ae 100644 (file)
@@ -23,7 +23,7 @@
  *             2 of the License, or (at your option) any later version.
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 31e8a9e4d7460798a35f40031ce1053c5ff11bed..af6b01db65068645e5fa680a97df584549e116c2 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/config.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <stdarg.h>
 #include <linux/inet.h>
 #include <linux/etherdevice.h>
index 2f7683c72eb71ea476fd1e61e3d1fd110a9e2942..036e283523f3ae3a01eca44209711e1ea356c859 100644 (file)
@@ -39,7 +39,7 @@
  
 #include <linux/config.h> 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
index bc814447e884bb4932c9cef98e537bc7b206953c..d575016846075f0f0fde5f2229100d368613e271 100644 (file)
@@ -50,7 +50,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
index b277cd3434073c54cebdbf1eb4c29f704b9b1f2e..0a8af9c887c7de9d77b4e71abdfbc64d3a702b80 100644 (file)
 #include <net/icmp.h>
 #include <net/tcp.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 unsigned long seq_offset;
 struct tcp_mib tcp_statistics;
index 2f706bf7f1e26a463840ae7b0e7e776c758ce575..831fe5a5e5997583aaa973a8d0370c0141b652e3 100644 (file)
@@ -84,7 +84,7 @@
 */
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/fcntl.h>
index 7aa870f38d60313d53431c666985650a6f880954..cbce01b689ed9a794c237868beaebebe4107a04f 100644 (file)
@@ -21,7 +21,7 @@
  *             2 of the License, or (at your option) any later version.
  */
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index 75310e8c0d3a2f7bfdc48d1f350f5e6ed9571b8c..855bac7176ac572648c56696c30e792948d6cd57 100644 (file)
@@ -77,7 +77,7 @@
 #include <linux/inet.h>
 #include <linux/route.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
@@ -1035,18 +1035,15 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
 static int 
 ipxitf_ioctl_real(unsigned int cmd, void *arg)
 {
-       int err;
        switch(cmd)
        {
-               case SIOCSIFADDR:
-               {
+               case SIOCSIFADDR: {
                        struct ifreq ifr;
                        struct sockaddr_ipx *sipx;
                        ipx_interface_definition f;
-                       err=verify_area(VERIFY_READ,arg,sizeof(ifr));
-                       if(err)
-                               return err;
-                       copy_from_user(&ifr,arg,sizeof(ifr));
+
+                       if (copy_from_user(&ifr,arg,sizeof(ifr)))
+                               return -EFAULT;
                        sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
                        if(sipx->sipx_family!=AF_IPX)
                                return -EINVAL;
@@ -1060,16 +1057,14 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
                        else
                                return ipxitf_create(&f);
                }
-               case SIOCGIFADDR:
-               {
+               case SIOCGIFADDR: {
                        struct ifreq ifr;
                        struct sockaddr_ipx *sipx;
                        ipx_interface *ipxif;
                        struct device *dev;
-                       err=verify_area(VERIFY_WRITE,arg,sizeof(ifr));
-                       if(err)
-                               return err;
-                       copy_from_user(&ifr,arg,sizeof(ifr));
+
+                       if (copy_from_user(&ifr,arg,sizeof(ifr)))
+                               return -EFAULT;
                        sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
                        dev=dev_get(ifr.ifr_name);
                        if(!dev)
@@ -1080,19 +1075,24 @@ ipxitf_ioctl_real(unsigned int cmd, void *arg)
                        sipx->sipx_family=AF_IPX;
                        sipx->sipx_network=ipxif->if_netnum;
                        memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
-                       copy_to_user(arg,&ifr,sizeof(ifr));
+                       if (copy_to_user(arg,&ifr,sizeof(ifr)))
+                               return -EFAULT;
                        return 0;
                }
-               case SIOCAIPXITFCRT:
-                       err=verify_area(VERIFY_READ,arg,sizeof(char));
-                       if(err)
+               case SIOCAIPXITFCRT: {
+                       int err, val;
+                       err = get_user(val, (unsigned char *) arg);
+                       if (err)
                                return err;
-                       return ipxcfg_set_auto_create(get_fs_byte(arg));
-               case SIOCAIPXPRISLT:
-                       err=verify_area(VERIFY_READ,arg,sizeof(char));
-                       if(err)
+                       return ipxcfg_set_auto_create(val);
+               }
+               case SIOCAIPXPRISLT: {
+                       int err, val;
+                       err = get_user(val, (unsigned char *) arg);
+                       if (err)
                                return err;
-                       return ipxcfg_set_auto_select(get_fs_byte(arg));
+                       return ipxcfg_set_auto_select(val);
+               }
                default:
                        return -EINVAL;
        }
@@ -1620,13 +1620,12 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname, char *opt
        
        sk=(ipx_socket *)sock->data;
        
-       if(optval==NULL)
+       if (optval==NULL)
                return(-EINVAL);
 
-       err=verify_area(VERIFY_READ,optval,sizeof(int));
-       if(err)
+       err = get_user(opt, (unsigned int *)optval);
+       if (err)
                return err;
-       opt=get_fs_long((unsigned long *)optval);
        
        switch(level)
        {
index fff0248b4a25b065f30b66b70a4433bbaa60aa98..a2794eb71af7257494cc6db542f78dc8bdb8281d 100644 (file)
@@ -27,7 +27,7 @@
 #include <net/netlink.h>
 
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 
 static int (*netlink_handler[MAX_LINKS])(struct sk_buff *skb);
index 39b12fb289f66ef2b073ea07ad27cc643929df4c..a178b015bd386c32afde0e61d14fde08ea94936e 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
index eaab1bdd670f779cd836422eb766b4883cab5769..a5610830af1c9e69bdf74c95c559a34164880952 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/if_ether.h>    /* For the statistics structure. */
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/inet.h>
index a4a73545362414229ffb4201eb49e57f4c65d22e..17b381310bc5e64457b0a3718266893262163a56 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/ip.h>                    /* For ip_rcv */
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index 288cda0d86c7e9aabc1ef502574db94318e94e17..90d29841707c5ff6a94ac7b910f39d1e9165df55 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index c2f6f2a58e41cba8a222f57079889e3cea7a7ec7..18dc4b85a9756f78dc4bc0f1d453f765ffc79d75 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
index 12ea151eee89216a3ddad8e2604f8a9c06fd4c18..c8fce6fd80d43b3801a43d539cf010f54a1815ad 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index 8fd9fdd4f4a658767c5669ea836ecd1b7d1ebd4a..a6dfa1cb5bc335d4cbafe961e0456cad4751e95b 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
index 96402c6b1fbcd6427a0f0dfec27f23ee42708a91..d4e0dcb60b7cdff2baa7af7f34c37aefe9957271 100644 (file)
@@ -74,7 +74,7 @@
 #include <net/netlink.h>
 
 #include <asm/system.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 
 #if defined(CONFIG_MODULES) && defined(CONFIG_NET)
 extern void export_net_symbols(void);
index 685a34b2fa5110e79cbc84dcda39a5ba8068eae0..fc5ececae627cab57dba284274d0129f7c341894 100644 (file)
@@ -63,7 +63,7 @@
 #include <linux/in.h>
 #include <linux/fs.h>
 #include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <net/sock.h>
index 3b7e114dda3dc7d8569d149e662a4d888d7dc2c8..c53c4d4e6cc1c1c016dfb7263a90b66a78a464c8 100644 (file)
@@ -49,7 +49,7 @@
 #include <linux/in.h>
 #include <linux/fs.h>
 #include <linux/malloc.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <net/sock.h>
index 79e342bf1566ac4dd07a3d6c4531863c1799f4a5..2f0f8c765ddb86b0195470630213de397512f95d 100644 (file)
@@ -860,11 +860,11 @@ EOM
 
 #
 # Load config options from a file.
-# Converts all "# OPTION is not set" lines to "OPTION=" lines
+# Converts all "# OPTION is not set" lines to "OPTION=n" lines
 #
 function load_config_file () {
        awk '
-         /# .* is not set.*/ { printf("%s=\n", $2) }
+         /# .* is not set.*/ { printf("%s=n\n", $2) }
        ! /# .* is not set.*/ { print }
        ' $1 >.tmpconfig
 
@@ -1119,12 +1119,12 @@ inputbox_instructions_hex="\
 Please enter a hexadecimal value. \
 Use the <TAB> key to move from the input field to the buttons below it."
 
-backtitle="Linux Kernel Configuration"
-
 DIALOG="./scripts/lxdialog/lxdialog"
 
 kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}"
 
+backtitle="Linux Kernel v$kernel_version Configuration"
+
 trap "cleanup ; rm -f .menuconfig ; exit 1" 1 2 15
 
 
@@ -1146,7 +1146,7 @@ then
   echo "#"
   echo "# Using defaults found in" $DEFAULTS
   echo "#"
-  . $DEFAULTS
+  load_config_file $DEFAULTS
 else
   echo "#"
   echo "# No defaults found"