]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.94 2.1.94
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:08 +0000 (15:15 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:08 +0000 (15:15 -0500)
204 files changed:
CREDITS
Documentation/Configure.help
Documentation/filesystems/umsdos.txt
Documentation/joystick.txt
Documentation/networking/6pack.txt [new file with mode: 0644]
Documentation/sound/AWE32 [new file with mode: 0644]
Documentation/sound/MAD16 [new file with mode: 0644]
Documentation/sound/Opti [new file with mode: 0644]
Documentation/sound/mwave [new file with mode: 0644]
MAINTAINERS
Makefile
Rules.make
arch/alpha/boot/bootp.c
arch/alpha/config.in
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/bios32.c
arch/alpha/kernel/head.S
arch/alpha/kernel/mcpcia.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/smc37c669.c
arch/alpha/kernel/smp.c
arch/alpha/lib/memcpy.c
arch/arm/config.in
arch/arm/defconfig
arch/arm/kernel/armksyms.c
arch/arm/kernel/calls.S
arch/arm/kernel/irq.c
arch/arm/mm/fault-armo.c
arch/arm/mm/fault-armv.c
arch/arm/mm/init.c
arch/i386/.kernel_offset.lds [deleted file]
arch/i386/Makefile
arch/i386/config.in
arch/i386/kernel/bios32.c
arch/i386/kernel/head.S
arch/i386/kernel/irq.c
arch/i386/kernel/mca.c
arch/i386/math-emu/poly.h
arch/i386/mm/init.c
arch/i386/vmlinux.lds
arch/m68k/amiga/amiga_ksyms.c
arch/m68k/atari/atari_ksyms.c
arch/m68k/mac/ksyms.c
drivers/acorn/block/Config.in
drivers/acorn/block/mfmhd.c
drivers/acorn/net/ether1.c
drivers/acorn/net/ether3.c
drivers/acorn/net/etherh.c
drivers/acorn/scsi/cumana_1.c
drivers/acorn/scsi/cumana_1.h
drivers/acorn/scsi/cumana_2.c
drivers/acorn/scsi/ecoscsi.c
drivers/acorn/scsi/ecoscsi.h
drivers/acorn/scsi/fas216.c
drivers/acorn/scsi/fas216.h
drivers/acorn/scsi/oak.c
drivers/acorn/scsi/oak.h
drivers/acorn/scsi/powertec.h
drivers/block/ide-proc.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/bt848.h
drivers/char/bttv.c
drivers/char/bttv.h
drivers/char/bw-qcam.c
drivers/char/c-qcam.c
drivers/char/console.c
drivers/char/hfmodem/gentbl.c
drivers/char/i2c.c [new file with mode: 0644]
drivers/char/i2c.h [new file with mode: 0644]
drivers/char/joystick.c
drivers/char/lp.c
drivers/char/msp3400.c [new file with mode: 0644]
drivers/char/msp3400.h [new file with mode: 0644]
drivers/char/pms.c
drivers/char/pty.c
drivers/char/tuner.c [new file with mode: 0644]
drivers/char/tuner.h
drivers/char/videodev.c
drivers/isdn/hisax/niccy.c
drivers/isdn/isdnloop/isdnloop.c
drivers/isdn/isdnloop/isdnloop.h
drivers/misc/parport_procfs.c
drivers/net/Config.in
drivers/net/Makefile
drivers/net/Space.c
drivers/net/de4x5.c
drivers/net/epic100.c [new file with mode: 0644]
drivers/net/hamradio/6pack.c [new file with mode: 0644]
drivers/net/hamradio/6pack.h [new file with mode: 0644]
drivers/net/hamradio/Config.in
drivers/net/hamradio/Makefile
drivers/net/hamradio/soundmodem/gentbl.c
drivers/net/sdla_fr.c
drivers/net/sdla_ppp.c
drivers/net/sdla_x25.c
drivers/scsi/mvme16x.c
drivers/sound/Config.in
drivers/sound/Defines
drivers/sound/Makefile
drivers/sound/README.C931 [deleted file]
drivers/sound/ad1848.c
drivers/sound/ad1848_mixer.h
drivers/sound/adlib_card.c
drivers/sound/audio.c
drivers/sound/cs4232.c
drivers/sound/dev_table.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/dmasound.c
drivers/sound/gus_card.c
drivers/sound/gus_wave.c
drivers/sound/local.h.master
drivers/sound/mad16.c
drivers/sound/maui.c
drivers/sound/midibuf.c
drivers/sound/opl3sa.c
drivers/sound/os.h
drivers/sound/pas2_card.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/softoss.c
drivers/sound/softoss_rs.c
drivers/sound/sound_calls.h
drivers/sound/sound_firmware.c
drivers/sound/sound_syms.c
drivers/sound/soundcard.c
drivers/sound/trix.c
drivers/sound/uart401.c
drivers/sound/uart6850.c
drivers/sound/vidc.c [new file with mode: 0644]
drivers/sound/vidc.h [new file with mode: 0644]
drivers/sound/vidc_audio.c [new file with mode: 0644]
drivers/sound/vidc_fill.S [new file with mode: 0644]
drivers/sound/vidc_mixer.c [new file with mode: 0644]
drivers/sound/vidc_synth.c [new file with mode: 0644]
drivers/video/cyberfb.c
drivers/video/fbcon-afb.c
drivers/video/fbcon-cfb16.c
drivers/video/fbcon-cfb2.c
drivers/video/fbcon-cfb24.c
drivers/video/fbcon-cfb32.c
drivers/video/fbcon-cfb4.c
drivers/video/fbcon-cfb8.c
drivers/video/fbcon-mac.c
drivers/video/fbcon-mfb.c
drivers/video/skeletonfb.c
fs/buffer.c
fs/devpts/root.c
fs/ext2/file.c
fs/sysv/inode.c
fs/umsdos/README-WIP.txt
fs/umsdos/dir.c
fs/umsdos/emd.c
fs/umsdos/file.c
fs/umsdos/inode.c
fs/umsdos/ioctl.c
fs/umsdos/namei.c
fs/umsdos/rdir.c
include/asm-alpha/lca.h
include/asm-alpha/string.h
include/asm-alpha/termios.h
include/asm-alpha/unistd.h
include/asm-arm/proc-armo/pgtable.h
include/asm-arm/proc-armv/pgtable.h
include/asm-arm/proc-armv/processor.h
include/asm-arm/stat.h
include/asm-arm/termios.h
include/asm-arm/unistd.h
include/asm-arm/xstat.h [new file with mode: 0644]
include/asm-i386/page.h
include/asm-i386/termios.h
include/asm-i386/unistd.h
include/asm-m68k/termios.h
include/asm-m68k/unistd.h
include/asm-mips/termios.h
include/asm-mips/unistd.h
include/asm-sparc/termios.h
include/asm-sparc/unistd.h
include/asm-sparc64/termios.h
include/asm-sparc64/unistd.h
include/linux/binfmts.h
include/linux/joystick.h
include/linux/mm.h
include/linux/pci.h
include/linux/swap.h
include/linux/umsdos_fs.h
include/linux/umsdos_fs.p
include/linux/videodev.h
include/linux/videotext.h [new file with mode: 0644]
include/net/ip.h
init/main.c
kernel/kmod.c
mm/page_io.c
mm/simp.c
mm/swapfile.c
net/ipv4/tcp_ipv4.c

diff --git a/CREDITS b/CREDITS
index 82b2c2092163465848bf3f35bf617d0f57778b2f..fd6f99e2f3de08c35d826e5695a70529983fb672 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -895,6 +895,10 @@ N: Rudolf Koenig
 E: rfkoenig@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
+N: Andreas Koensgen
+E: ajk@iehk.rwth-aachen.de
+D: 6pack driver for AX.25
+
 N: Andi Kleen
 E: ak@muc.de
 D: network hacker, syncookies
@@ -1254,6 +1258,14 @@ S: Dragonvagen 1 A 13
 S: FIN-00330 Helsingfors
 S: Finland
 
+N: Matija Nalis
+E: mnalis@jagor.srce.hr
+E: mnalis@voyager.hr
+D: Maintainer of the Umsdos file system
+S: Listopadska 7
+S: 10000 Zagreb
+S: Croatia
+
 N: Jonathan Naylor
 E: g4klx@g4klx.demon.co.uk
 E: g4klx@amsat.org
@@ -1407,7 +1419,7 @@ S: Germany
 
 N: Joerg Reuter
 E: jreuter@poboxes.com
-W: http://www.rat.de/jr/
+W: http://poboxes.com/jreuter/
 W: http://qsl.net/dl1bke/
 D: Generic Z8530 driver, AX.25 DAMA slave implementation
 D: Several AX.25 hacks
@@ -1866,6 +1878,14 @@ S: Hernesaarenkatu 15 A 2
 S: Fin-00150 Helsinki
 S: Finland
 
+N: Jonathan Woithe
+E: jwoithe@physics.adelaide.edu.au
+W: http://www.physics.adelaide.edu.au/~jwoithe
+D: ALS-007 soundcard extensions to Sound Blaster driver
+S: 4/36 Trevelyan St
+S: Wayville SA 5034
+S: Australia
+
 N: Roger E. Wolff
 E: R.E.Wolff@BitWizard.nl
 D: Written kmalloc/kfree
index 9b762c0139bcbb323ae310f5855c26ac515bea4e..fe121bc669360f9e39009394b70de5368f7e084e 100644 (file)
@@ -1089,7 +1089,7 @@ CONFIG_BINFMT_ELF
   want to say Y here. Information about ELF is on the WWW at
   http://www.sjc.ox.ac.uk/users/barlow/elf-howto.html (To browse the
   WWW, you need to have access to a machine on the Internet that has a
-  programs like lynx or netscape).  If you find that after upgrading
+  program like lynx or netscape).  If you find that after upgrading
   from Linux kernel 1.2 and saying Y here, you still can't run any ELF
   binaries (they just crash), then you'll have to install the newest
   ELF runtime libraries, including ld.so (check the file
@@ -1208,7 +1208,7 @@ CONFIG_M386
   the line "SMP=1" is not commented out and read Documentation/smp and
   Documentation/IO-APIC.txt and the SMP-FAQ on the WWW at
   http://www.irisa.fr/prive/mentre/smp-faq/ (to browse the WWW, you
-  need to have access to a machine on the Internet that has a programs
+  need to have access to a machine on the Internet that has a program
   like lynx or netscape). People using multiprocessor machines should
   also say Y to "Enhanced Real Time Clock Support", below.
   If you want to compile a kernel that should work on both single
@@ -1243,7 +1243,7 @@ CONFIG_PARPORT
   extensive information about drivers for many devices attaching to
   the parallel port see http://www.torque.net/linux-pp.html on the WWW
   (To browse the WWW, you need to have access to a machine on the
-  Internet that has a programs like lynx or netscape). It is possible
+  Internet that has a program like lynx or netscape). It is possible
   to share a single parallel port among several devices and it is safe
   to compile all the corresponding drivers into the kernel. If you
   want to compile parallel port support as a module ( = code which can
@@ -1295,72 +1295,6 @@ CONFIG_PNP_PARPORT
   themselves when requested.  Say Y to enable this feature, or M to
   compile it as a module (parport_ieee1284.o).  If in doubt, say N.
 
-Plug and Play subsystem (EXPERIMENTAL)
-CONFIG_PNP_DRV
-  This enables support for the new Plug-and-Play (or PnP) Linux
-  subsystems. This support is required for PnP ISA support, and for PnP
-  Legacy support. User-mode utilities for this support may be found at
-  http://www.lpsg.demon.co.uk/pnp-linux.html.
-
-PnP resource management
-CONFIG_KERNEL_PNP_RESOURCE
-  This option will cause the new PnP generic resource management
-  routines to be used instead of the old routines request_xxx and
-  free_xxx. Emulation routines are put in place to support the old
-  calling style. This code support masks for IO decoding (required for
-  Plug and Play devices). There is no need to enable this option unless
-  you want to - these features will still be used where they are needed.
-  However, enabling it will reduce your kernel size slightly, and also
-  allow you to test this code more extensively.
-
-Support for boot-loaded PnP configuration (RECOMMENDED)
-CONFIG_PNP_BLDCONFIG
-  This will enable support for preloading data about the configuration
-  of any Plug-and-Play devices in the system into the kernel at boot
-  time, which means that any devices required at boot can be configured
-  at this time manually. Say Y unless you have a reason not to.
-
-PnP ISA support
-CONFIG_PNP_ISA
-  This option is required to allow the Linux PnP subsystem to handle
-  Plug and Play ISA devices. This includes full support for PnP ISA,
-  including the I/O range check feature.
-
-PnP ISA backwards-compatibility support
-CONFIG_PNP_ISA_COMPAT
-  This option will enable partial backwards compatibility with drivers
-  written using older versions (up to the last 0.2.x) of the PnP driver
-  written by Tom Lees <tom@lpsg.demon.co.uk>.
-
-PnP Legacy device support
-CONFIG_PNP_LEGACY
-  Before PnP ISA was standardized, several "jumperless", or
-  "soft-configurable" boards were finding their way onto the market.
-  These cards used somewhat proprietary mechanisms for configuring
-  IRQs, DMAs, IO addresses, and memory ranges. These devices (mainly
-  network cards, but also some sound cards) can be configured as any
-  other PnP device can by saying Y here, if appropriate drivers
-  for these devices are available.
-
-PnP sysctl support (RECOMMENDED)
-CONFIG_PNP_SYSCTL
-  This option enables support for the user-mode interface to the
-  kernel-mode PnP systems. It requires that you said Y to "Sysctl
-  support" above.  The only reason you might want to switch this off
-  is if you aren't going to use user-mode utilities to configure PnP,
-  and you want to save a couple of kilobytes of kernel space. Answer Y
-  unless you know what you are doing. User-mode utilities and a
-  library for accessing this interface may be found at
-  http://www.lpsg.demon.co.uk/pnp-linux.html.
-
-PnP auto-configures all devices on startup
-CONFIG_PNP_BOOTINIT
-  This option will allow the PnP subsystem to automatically configure
-  all the PnP devices it finds upon system startup (or at least
-  attempt to). This is useful if you have older drivers which do not use
-  the Linux-PnP system to configure PnP devices, and which you need
-  to be configured by PnP before you can use them.
-
 Enable loadable module support
 CONFIG_MODULES
   Kernel modules are small pieces of compiled code which can be
@@ -3560,6 +3494,14 @@ CONFIG_MKISS
   whenever you want), say M here and read
   Documentation/modules.txt. The module will be called mkiss.o.
 
+Serial port 6PACK driver for AX.25
+CONFIG_6PACK
+6pack is a protocol that attaches a TNC connected to a serial interface
+to be used as a network device. 6pack can be used as an alternative to KISS,
+but has some extended functionality. Note that this driver is still
+experimental and might cause problems. For details about the features
+and the usage of the driver, read Documentation/networking/6pack.txt.
+
 PLIP (parallel port) support
 CONFIG_PLIP
   PLIP (Parallel Line Internet Protocol) is used to create a
@@ -6700,7 +6642,7 @@ CONFIG_RTC
   fashion. (They should also Documentation/smp and
   Documentation/IO-APIC.txt and the SMP-FAQ on the WWW at
   http://www.irisa.fr/prive/mentre/smp-faq/ (to browse the WWW, you
-  need to have access to a machine on the Internet that has a programs
+  need to have access to a machine on the Internet that has a program
   like lynx or netscape)).
   If you think you have a use for such a device (such as periodic data
   sampling), then say Y here, and go read the file
@@ -6801,6 +6743,16 @@ CONFIG_SB_MWAVE
   why they still haven't released any documentation.
   [http://204.200.238.31/cgi-bin/link.pl?co=i&cl=/ts/ibm/contact.html]
 
+Are you using the IBM Mwave "emulation" of SB ?
+CONFIG_SB_MWAVE
+  The IBM Mwave can do whats loosely describable as emulation of an 8bit
+  soundblaster if you load the right firmware from DOS warm boot and pray
+  and your machine happens to like you. Say Y if you are doing this as the
+  IRQ test normally fails on the mwave emulation. If you'd like real MWAVE
+  support phone IBM (425-556-8822) and ask them why they still haven't 
+  released any documentation.
+  [http://204.200.238.31/cgi-bin/link.pl?co=i&cl=/ts/ibm/contact.html]
+
 Generic OPL2/OPL3 FM synthesizer support
 CONFIG_ADLIB
   Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
@@ -6898,6 +6850,15 @@ CONFIG_MAD16
   manufacturers such as Turtle Beach (Tropez), Reveal (some models)
   and Diamond (latest ones).
 
+Support MIDI in older MAD16 based cards (requires SB)
+CONFIG_MAD16_OLDCARD
+  Answer Y (or M) if you have an older card based on the C928
+  or Mozart chipset and you want to have  MIDI support. If you
+  enable this option you also need to enable support for SoundBlaster.
+
+ If you answer Y here you will
+  also need to enable the SoundBlaster driver.
+
 Support for Crystal CS4232 based (PnP) cards
 CONFIG_CS4232
   Say Y here if you have a card based on the Crystal CS4232 chip set,
@@ -7855,6 +7816,11 @@ CONFIG_VIDEO_BT848
   want). If you want to compile it as a module, say M here and read
   Documentation/modules.txt.
 
+SAA5249 Teletext processor
+CONFIG_VIDEO_SAA5249
+  Support for I2C bus based teletext using the SAA5249 chip. At the moment
+  this is only useful on some european WinTV cards.
+
 Quickcam BW Video For Linux
 CONFIG_VIDEO_BWQCAM
   Say Y have if you the black and white version of the QuickCam
index 320dac6ca5ef57f20ad2e7d33d7fc02042a7d3d4..9e658b166abcec68aa96dc574ac1c3214f2be2ad 100644 (file)
@@ -1,7 +1,13 @@
+Firstly, let me say that UMSDOS is going through some major code changes,
+and has some KNOWN BUGS (and quite a few unknown :-). Please read
+fs/umsdos/README-WIP.txt for more information on current status. Thanks.
+
+----------------------------------------------------------------------------
 Very short explanation for the impatient!!!
 
 Umsdos is a file system driver that run on top the MSDOS fs driver.
 It is written by Jacques Gelinas (jacques@solucorp.qc.ca)
+and is currently maintained by Matija Nalis (mnalis@jagor.srce.hr)
 
 Umsdos is not a file system per se, but a twist to make a boring
 one into a useful one.
index ec525b182e7d71f2ca579d5d87f652392603d61a..00b620e052a1feecbda05d0b6daf7e6fb55fb33a 100644 (file)
@@ -41,7 +41,13 @@ used.
 select `M' for this driver in the kernel configuration and insert the
 module:
 
-insmod js.o js=0xXX,0xYY
+insmod joystick.o js=0xXX,0xYY
+
+  To enable autoloading/-unloading of the joystick module, you have to add
+these lines to /etc/conf.modules:
+
+alias char-major-15 joystick
+options joystick js=0xXX,0xYY
 
   To enable the user space programs to read the joystick device, you have to
 create the device files using mknod (man mknod for more info):
diff --git a/Documentation/networking/6pack.txt b/Documentation/networking/6pack.txt
new file mode 100644 (file)
index 0000000..11339d3
--- /dev/null
@@ -0,0 +1,175 @@
+This is the 6pack-mini-HOWTO, written by
+
+Andreas Könsgen DG3KQ
+Internet: ajk@iehk.rwth-aachen.de
+AMPR-net: dg3kq@db0pra.ampr.org
+AX.25:    dg3kq@db0ach.#nrw.deu.eu
+
+Last update: April 7, 1998
+
+1. What is 6pack, and what are the advantages to KISS?
+
+6pack is a transmission protocol for the data exchange between the PC and
+the TNC over a serial line. It can be used as an alternative to KISS.
+
+6pack has two major advantages:
+- The PC is given the full control over the radio
+  channel. Special control data is exchanged between the PC and the TNC so
+  that the PC knows at any time if the TNC is receiving data, if an TNC
+  buffer underrun or overrun has occured, if the PTT is
+  set and so on. This control data is processed at a higher priority than
+  normal data, so a data stream can be interrupted at any time to issue an
+  important event. This helps to improve the channel access and timing algorithms
+  as everything is computed in the PC. It would even be possible to experiment with
+  something completely different than the known CSMA and DAMA channel access
+  methods.
+  This kind of real-time control is especially important to supply several
+  TNCs that are connected between each other and the PC by a daisy chain
+  (however, this feature is not supported yet by the Linux 6pack driver).
+
+- Each packet transferred over the serial line is supplied with a checksum,
+  so it is easy to detect errors due to problems on the serial line.
+  Received packets that are corrupt are not passed on to the AX.25 layer.
+  Damaged packets that the TNC has received from the PC are not transmitted.
+
+More details about 6pack are described in the file 6pack.ps that is located
+in the doc directory of the AX.25 utilities package.
+
+2. Who has developed the 6pack protocol?
+
+The 6pack protocol has been developed by Ekki Plicht DF4OR, Henning Rech
+DF9IC and Gunter Jost DK7WJ. A driver for 6pack, written by Gunter Jost and
+Matthias Welwarsky DG2FEF, comes along with the PC version of FlexNet.
+They have also written a firmware for TNCs to perform the 6pack
+protocol (see section 4 below).
+
+3. Where can I get the latest version of 6pack for LinuX?
+
+At the moment, the 6pack stuff can obtained via anonymous ftp from
+db0bm.automation.fh-aachen.de. In the directory /incoming/dg3kq,
+there is a file named 6pack.tgz.
+
+4. Preparing the TNC for 6pack operation
+
+To be able to use 6pack, a special firmware for the TNC is needed. The EPROM
+of a newly bought TNC does not contain 6pack, so you will have to
+program an EPROM yourself. The image file for 6pack EPROMs should be
+available on any packet radio box where PC/FlexNet can be found. The name of
+the file is 6pack.bin. This file is copyrighted and maintainend by the FlexNet
+team. It can be used under the terms of the license that comes along
+with PC/FlexNet. Please do not ask me about the internals of this file as I
+don't know anything about it. I used a textual description of the 6pack
+protocol to program the Linux driver.
+
+TNCs contain a 64kByte EPROM, the lower half of which is used for
+TheFirmware/KISS. The upper half is either empty or is sometimes
+programmed with a software called TAPR. In the latter case, the TNC
+is supplied with a DIP switch so you can easily change between the
+two systems. When programming a new EPROM, one of the systems is replaced
+by 6pack. It is useful to replace TAPR, as this software is rarely used
+nowadays. If your TNC is not equipped with the switch mentioned above, you
+can build in one yourself that switches over the highest address pin
+of the EPROM between HIGH and LOW level. After having inserted the new EPROM
+and switched to 6pack, apply power to the TNC for a first test. The connect
+and the status LED are lit for about a second if the firmware initialises
+the TNC correctly.
+
+5. Building and installing the 6pack driver
+
+The driver has been tested with kernel version 2.1.90. Using with older
+kernels may lead to a compilation error because the interface to a kernel
+function has been changed in the 2.1.8x kernels.
+
+How to turn on 6pack support:
+
+- In the linux kernel configuration program, select the code maturity level
+  options menu and turn on the prompting for development drivers.
+
+- Select the amateur radio support menu and turn on the serial port 6pack
+  driver.
+
+- Compile and install the kernel and the modules.
+
+To use the driver, the kissattach program delivered with the AX.25 utilities
+has to be modified.
+
+- Do a cd to the directory that keeps the kissattach sources. Edit the
+  kissattach.c file. At the top, insert the following lines:
+
+  #ifndef N_6PACK
+  #define N_6PACK (N_AX25+1)
+  #endif
+
+  Then find the line
+   
+  int disc = N_AX25;
+
+  and replace N_AX25 by N_6PACK.
+
+- Recompile kissattach. Rename it to spattach to avoid confusions.
+
+Installing the driver:
+
+- Do an insmod 6pack. Look at your
+  /var/log/messages file to check if the module has printed its initialization message.
+
+- Do a spattach as you would launch kissattach when starting a KISS port.
+  Check if the kernel prints the message '6pack: TNC found'. 
+
+- From here, everything should work as if you were setting up a KISS port.
+  The only difference is that the network device that represents
+  the 6pack port is called sp instead of sl or ax. So, sp0 would be the
+  first 6pack port.
+
+Although the driver has been tested on various platforms, I still declare it
+ALPHA. BE CAREFUL! Sync your disks before insmoding the 6pack module
+and spattaching. Watch out if your computer behaves strangely. Read section
+6 of this file about known problems.
+
+Note that the connect and status LEDs of the TNC are controlled in a
+different way than they are when the TNC is used with PC/FlexNet. When using
+FlexNet, the connect LED is on if there is a connection; the status LED is
+on if there is data in the buffer of the PC's AX.25 engine that has to be
+transmitted. Under LinuX, the 6pack layer is beyond the AX.25 layer,
+so the 6pack driver doesn't know anything about connects or data that
+has not yet been transmitted. Therefore the LEDs are controlled
+as they are in KISS mode: The connect LED is turned on if data is transferred
+from the PC to the TNC over the serial line, the status LED if data is
+sent to the PC.
+
+6. Known problems
+
+When testing the driver with 2.0.3x kernels and
+operating with data rates on the radio channel of 9600 Baud or higher,
+the driver may, on certain systems, sometimes print the message '6pack:
+bad checksum', which is due to data loss if the other station sends two
+or more subsequent packets. I have been told that this is due tu a problem
+with the serial driver of 2.0.3x kernels. I don't know yet if the problem
+still exists with 2.1.x kernels, as I have heard that the serial driver
+code has been changed with 2.1.x.
+
+When shutting down the sp interface with ifconfig, the kernel crashes if
+there is still an AX.25 connection left over which an IP connection was
+running, even if that IP connection is already closed. The problem does not
+occur when there is a bare AX.25 connection still running. I don't know if
+this is a problem of the 6pack driver or something else in the kernel.
+
+The driver has been tested as a module, not yet as a kernel-builtin driver.
+
+The 6pack protocol supports daisy-chaining of TNCs in a token ring, which is
+connected to one serial port of the PC. This feature is not implemented
+and at least at the moment I won't be able to do it because I do not have
+the opportunity to build a TNC daisy-chain and test it.
+
+Some of the comments in the source code are inaccurate. They are left from
+the SLIP/KISS driver, from which the 6pack driver has been derived.
+I haven't modified or removed them yet -- sorry! The code itself needs
+some cleaning and optimizing. This will be done in a later release.
+
+If you encounter a bug or if you have a question or suggestion concerning the
+driver, feel free to mail me, using the adresses given at the beginning of
+this file.
+
+Have fun!
+
+Andreas
diff --git a/Documentation/sound/AWE32 b/Documentation/sound/AWE32
new file mode 100644 (file)
index 0000000..d85a7ad
--- /dev/null
@@ -0,0 +1,63 @@
+From: Nicola Bernardelli <nbern@mail.protos.it>
+
+     In order to load SB-AWE related drivers on recent kernels (tested
+with 2.1.86 and 2.1.88) with modularized sound support these lines can
+be issued (of course with the suitable values for the parameters)
+after PNP setup:
+
+insmod  sound.o
+insmod  uart401.o
+insmod  sb.o io=0x220 irq=5 dma=1 dma16=5 mpu_io=0x330
+insmod  awe_wave.o
+
+     Alternatively, in order to also have automatic load on demand
+(not of the awe support, which would anyway most likely also require a
+call to sfxload), these lines can be added to /etc/conf.modules, of
+course with the suitable values for the parameters):
+
+alias char-major-14 sb
+post-install sb modprobe "-k" "adlib_card"
+options sb io=0x220 irq=5 dma=1 dma16=5 mpu_io=0x330
+options adlib_card io=0x388     # FM synthetiser
+
+and then these two commands can be issued:
+
+modprobe sb
+insmod awe_wave
+
+------------------------------------------------------------------------------
+
+After picking up the second approach, you may want to put these lines
+on an ossfreeOn script:
+
+ -----
+#!/bin/sh
+
+modprobe sb
+insmod awe_wave
+
+# A call to 'aumix -L' (attention to what the home dir is at boot
+# time, you may put a link /.aumixrc -> /home/<sounduser>/.aumixrc) to
+# restore mixer device levels and a call to 'sfxload <path to
+# soundfont bank>' may be added in a customized ossfreeSetup script:
+
+if [ -x /usr/local/sbin/ossfreeSetup ] ; then
+  /usr/local/sbin/ossfreeSetup
+fi
+ -----
+
+And these lines in an ossfreeOff script:
+
+ -----
+#!/bin/sh
+
+# NOT set -e, maybe not all of them are currently loaded.
+
+rmmod awe_wave 
+rmmod adlib_card
+rmmod opl3
+rmmod sb
+rmmod uart401
+rmmod sound
+ -----
+
diff --git a/Documentation/sound/MAD16 b/Documentation/sound/MAD16
new file mode 100644 (file)
index 0000000..319b1e1
--- /dev/null
@@ -0,0 +1,25 @@
+From: Shaw Carruthers <shaw@shawc.demon.co.uk>
+
+I have been using mad16 sound for some time now with no problems, current
+kernel 2.1.89
+
+lsmod shows:
+
+mad16                   5176   0 
+sb                     22044   0  [mad16]
+uart401                 5576   0  [mad16 sb]
+ad1848                 14176   1  [mad16]
+sound                  61928   0  [mad16 sb uart401 ad1848]
+
+.config has:
+
+CONFIG_SOUND=m
+CONFIG_ADLIB=m
+CONFIG_MAD16=m
+CONFIG_YM3812=m
+
+modules.conf has:
+
+alias char-major-14 mad16
+options sb mad16=1
+options mad16 io=0x530 irq=7 dma=0 dma16=1  && /usr/local/bin/aumix -w 15 -p 20 -m 0 -1 0 -2 0 -3 0 -i 0
diff --git a/Documentation/sound/Opti b/Documentation/sound/Opti
new file mode 100644 (file)
index 0000000..90d4245
--- /dev/null
@@ -0,0 +1,216 @@
+Support for the OPTi 82C931 chip
+--------------------------------
+Note: parts of this README file apply also to other
+cards that use the mad16 driver.
+
+Some items in this README file are based on features
+added to the sound driver after Linux-2.1.91 was out.
+By the time of writing this I do not know which official
+kernel release will include these features.
+Please do not report inconsistencies on older Linux
+kernels.
+
+The OPTi 82C931 is supported in its non PnP mode.
+Usually you do not need to set jumpers etc... The sound driver
+will check the card status and if it is required it will
+force the card into a mode in which it can be programmed.
+
+If you have another OS installed on your computer it is recommended
+that Linux and the other OS use the same resources.
+
+Also, it is recommended that resources specified in /etc/conf.modules
+and resources specified in /etc/isapnp.conf agree.
+
+Compiling the sound driver
+--------------------------
+I highly recommend that you build a modularized sound driver.
+This document does not cover sound-driver which is built in
+the kernel.
+
+Sound card support should be enabled as a module (chose m).
+Answer 'm' for  these items:
+  Generic OPL2/OPL3 FM synthesizer support                     (CONFIG_ADLIB)
+  Microsoft Sound System support                               (CONFIG_MSS)
+  Support for OPTi MAD16 and/or Mozart based cards             (CONFIG_MAD16)
+  FM synthesizer (YM3812/OPL-3) support                                (CONFIG_YM3812)
+
+The configuration menu may ask for addresses, irq lines or dma
+channels. If the card is used as a module the module loading
+options will override these values.
+
+For the OPTi 931 you can answer 'n' to:
+  Support MIDI in older MAD16 based cards (requires SB)                (CONFIG_MAD16_OLDCARD)
+If you do need MIDI support in a Mozart or C928 based card you
+need to answer 'm' to the above question. In that case you will
+also need to answer 'm' to:
+  '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' (CONFIG_SB)
+
+Go on and compile your kernel and modules. Install the modules. Run depmod -a.
+
+Using isapnptools
+-----------------
+In most systems with a PnP bios you do not need to use isapnp. The
+initialization provided by the bios is sufficient for the driver
+to pick up the card and continue initialization.
+
+If that fails, or if you have other PnP cards, you need to use isapnp
+to initialize the card.
+This was tested with isapnptools-1.11 but I recommend that you use
+isapnptools-1.13 (or newer). Run pnpdump to dump the information
+about your PnP cards. Then edit the resulting file and select
+the options of your choice. This file is normally installed as
+/etc/isapnp.conf.
+
+The driver had one limitation WRT io port resources.
+IO3 base should be 0x0E0C. Isapnp allows other io ports but this
+address is hard-coded into the driver.
+
+Using kmod and autoloading the sound driver
+-------------------------------------------
+Comment: as of linux-2.1.90 kmod is replacing kerneld.
+The config file '/etc/conf.modules' is used as before.
+
+This is the sound part of my /etc/conf.modules file.
+Following that I will explain each line.
+
+alias mixer0 mad16
+alias audio0 mad16
+alias midi0  mad16
+alias synth0 opl3
+options sb mad16=1
+options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0
+options opl3 io=0x388
+post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
+
+Explain:
+
+alias mixer0 mad16
+alias audio0 mad16
+alias midi0  mad16
+alias synth0 opl3
+
+When any sound device is opened the kernel requests auto-loading
+of char-major-14. There is a built-in alias that translates this
+request to loading the main sound module. The main sound module
+contains only common code which is needed by all the sound drivers,
+and the driver for /dev/sndstat.
+
+The sound module in it's turn will request loading of a sub-driver
+for mixer, audio, midi or synthesizer device. The first 3 are
+supported by the mad16 driver. The synth device is supported
+by the opl3 driver.
+
+There is currently no way to autoload the sound device driver
+if more than one card is installed.
+
+options sb mad16=1
+
+This is left for historical reason. If you enable the
+config option 'Support MIDI in older MAD16 based cards (requires SB)'
+or if you use an older mad16 driver it will force loading of the
+SoundBlaster driver. This option tells the SB driver not to look
+for a SB card but to wait for the mad16 driver.
+
+options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0
+options opl3 io=0x388
+
+post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6
+
+This sets resources and options for the mad16 and opl3 drivers.
+I use 2 dma channels (only one is required) to enable full duplex.
+joystick=1 enables the joystick port. cdtype=0 disables the cd port.
+You can also set mpu_io and mpu_irq in the mad16 options for the
+uart401 driver.
+
+This tells modprobe to run /sbin/ad1848_mixer_reroute after
+mad16 is successfully loaded and initialized. The source
+for ad1848_mixer_reroute is appended to the end of this readme
+file. It is impossible for the sound driver to know the actual
+connections to the mixer. The 3 inputs intended for cd, synth
+and line-in are mapped to the generic inputs line1, line2 and
+line3. This program reroutes these mixer channels to their
+right names (note the right mapping depends on the actual sound
+card that you use).
+The numeric parameters mean:
+ 14=line1 8=cd    - reroute line1 to the CD input.
+ 15=line2 3=synth - reroute line2 to the synthesizer input.
+ 16=line3 6=line  - reroute line3 to the line input.
+For reference on other input names look at the file
+/usr/include/linux/soundcard.h.
+
+Using a joystick
+-----------------
+You must enable a joystick in the mad16 options. (also
+in /etc/isapnp.conf if you use it).
+Tested with regular analog joysticks.
+
+A CDROM drive connected to the sound card
+-----------------------------------------
+The 82C931 chip has support only for secondary ATAPI cdrom.
+(cdtype=8). Loading the mad16 driver resets the C931 chip
+and if a cdrom was already mounted it may cause a complete
+system hang. Do not use the sound card if you have an alternative.
+If you do use the sound card it is important that you load
+the mad16 driver (use "modprobe mad16" to prevent auto-unloading)
+before the cdrom is accessed the first time.
+
+Using the sound driver built-in the kernel may help here. but...
+Most new systems have a PnP bios and also two IDE controllers.
+The IDE controller on the sound card may be needed only on older
+systems (which have only one IDE controller) but these systems
+also do not have a PnP bios - requiring isapnptoosl and a modularized
+driver.
+
+Known problems
+--------------
+1. See the section on "A CDROM drive connected to the sound card".
+
+2. On my system the codec cannot capture companded sound samples.
+   (eg., recording from /dev/audio). When any companded capture is
+   requested I get a stereo-16 bit samples instead. Playback of
+   companded samples work well. Apparently this problem is not common
+   to all C931 based cards. I do not know how to identify cards that
+   have this problem.
+
+Source for ad1848_mixer_reroute.c
+---------------------------------
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/soundcard.h>
+
+static char *mixer_names[SOUND_MIXER_NRDEVICES] =
+       SOUND_DEVICE_LABELS;
+
+int
+main(int argc, char **argv) {
+       int val, from, to;
+       int i, fd;
+
+       fd = open("/dev/mixer", O_RDWR);
+       if(fd < 0) {
+               perror("/dev/mixer");
+               return 1;
+       }
+
+       for(i = 2; i < argc; i += 2) {
+               from = atoi(argv[i-1]);
+               to = atoi(argv[i]);
+
+               if(to == SOUND_MIXER_NONE)
+                       fprintf(stderr, "%s: turning off mixer %s\n",
+                               argv[0], mixer_names[to]);
+               else
+                       fprintf(stderr, "%s: rerouting mixer %s to %s\n",
+                               argv[0], mixer_names[from], mixer_names[to]);
+
+               val = from << 8 | to;
+
+               if(ioctl(fd, SOUND_MIXER_PRIVATE2, &val)) {
+                       perror("AD1848 mixer reroute");
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
diff --git a/Documentation/sound/mwave b/Documentation/sound/mwave
new file mode 100644 (file)
index 0000000..ad2a229
--- /dev/null
@@ -0,0 +1,192 @@
+       How to try and survive an IBM Mwave under Linux SB drivers
+
+
+* IBM refuse to provide documentation. If anyone can ever find out what
+  MWD50430.EXE actually does to load firmware then this comedy could go
+  away.
+
+* If you'd like to ask IBM why they don't release Mwave information.
+  phone IBM (425-556-8822) and ask them why they still haven't 
+  released any documentation.
+  [http://204.200.238.31/cgi-bin/link.pl?co=i&cl=/ts/ibm/contact.html]
+
+----------------------------------------------------------------------------
+
+OK, First thing - the IRQ problem IS a problem, whether the test is bypassed or
+not. And it is NOT a linux problem - it is an MWAVE problem that is fixed with
+the latest MWAVE patches. So, in other words, DON'T bypass the test for MWAVES!!
+
+My config is Win 95 on HDA1, swap on HDA2, RH 5 on HDA3.
+
+The steps, then:
+
+    Boot to Linux. 
+    Mount Win95 file system (assume mount mount = /dos95)
+    mkdir /dos95/linux
+    mkdir /dos95/linux/boot
+    mkdir /dos95/linux/boot/parms
+
+    Copy the kernel, any initrd image, and loadlin to /dos95/linux/boot
+
+    Reboot to win 95
+
+    Edit C:/msdos.sys and add/change the following:
+
+        Logo=0
+        BootGUI=0
+
+        [Note msdos.sys IS a text file but it needs to be 'unhidden' and make
+         read-writable before it can be eddited]
+
+    Edit Config .sys to have multiple config menus. I have one for win95, and
+    five for linux. Like this:
+------------
+[menu]
+menuitem=W95, Windows 95
+menuitem=LINTP, Linux - ThinkPad
+menuitem=LINTP3, Linux - ThinkPad Console
+menuitem=LINDOC, Linux - Docked
+menuitem=LINDOC3, Linux - Docked Console
+menuitem=LIN1, Linux - Single User Mode
+REM menudefault=W95,10
+
+[W95]
+
+[LINTP]
+
+[LINDOC]
+
+[LINTP3]
+
+[LINDOC3]
+
+[LIN1]
+
+[COMMON]
+FILES=30
+REM Please read README.TXT in C:\MWW subdirectory before changing the DOS= statement.
+DOS=HIGH,UMB
+DEVICE=C:\MWW\MANAGER\MWD50430.EXE
+SHELL=c:\command.com /e:2048
+-------------------
+
+The important things are the SHELL and DEVICE statements
+
+    Then change Autoexec.bat. Basically everything in there originally should be
+    done ONLY when Win95 is booted. Then you add new things specifically for
+    Linux.  Mine is as follows
+
+---------------
+@ECHO OFF
+if "%CONFIG%" == "W95" goto W95
+
+REM
+REM Linux stuff
+REM
+SET MWPATH=C:\MWW\DLL;C:\MWW\MWGAMES;C:\MWW\DSP
+SET BLASTER=A220 I5 D1
+SET MWROOT=C:\MWW
+SET LIBPATH=C:\MWW\DLL
+SET PATH=C:\WINDOWS;C:\MWW\DLL;
+CALL MWAVE START NOSHOW
+c:\linux\boot\loadlin.exe @c:\linux\boot\parms\%CONFIG%.par
+
+:W95
+REM
+REM Windows 95 stuff
+REM
+c:\toolkit\guard
+SET MSINPUT=C:\MSINPUT
+SET MWPATH=C:\MWW\DLL;C:\MWW\MWGAMES;C:\MWW\DSP
+REM The following is used by DOS games to recognize Sound Blaster hardware.
+REM If hardware settings are changed, please change this line as well.
+REM See the Mwave README file for instructions.
+SET BLASTER=A220 I5 D1
+SET MWROOT=C:\MWW
+SET LIBPATH=C:\MWW\DLL
+SET PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;E:\ORAWIN95\BIN;f:\msdev\bin;e:\v30\bin.dbg;v:\devt\v30\bin;c:\JavaSDK\Bin;C:\MWW\DLL;
+SET INCLUDE=f:\MSDEV\INCLUDE;F:\MSDEV\MFC\INCLUDE
+SET LIB=F:\MSDEV\LIB;F:\MSDEV\MFC\LIB
+win
+
+------------------------
+
+Now build a file in c:\linux\boot\parms for each linux config that you have.
+
+For example, my LINDOC3 config is for a docked Thinkpad at runlevel 3 with no
+initrd image, and has a parm file named LINDOC3.PAR in c:\linux\boot\parms:
+
+-----------------------
+#   LOADLIN @param_file image=other_image root=/dev/other
+#
+#      Linux Console in docking station
+#
+c:\linux\boot\zImage.krn         # first value must be the filename of the Linux-kernel
+root=/dev/hda3                    # the device which gets mounted as root FS
+ro                                      # Other kernel agruments go here
+apm=off
+doc=yes
+3
+-----------------------
+
+the doc=yes parm is an environment variable that my init scripts use, it is not
+a kernel argument.
+
+However, the apm=off parm IS a kernel argument!!!!!!! APM, at least in my setup,
+causes the kernel to crash when loaded via loadlin (but NOT when loaded via
+LILO). The APM stuff COULD be forced out of the kernel via the kernel compile
+options. BUT I, instead, got hold of an unofficial patch to the APM drivers that
+allows them to be dynamically deactivated via kernel arguments. Whatever you
+chose to document, APM, it seems, MUST be off for setups like mine.
+
+Now check the C:\MWW\MWCONFIG.REF looks like this:
+
+----------------------
+[NativeDOS]
+Default=SB1.5
+SBInputSource=CD
+SYNTH=FM
+QSound=OFF
+Reverb=OFF
+Chorus=OFF
+ReverbDepth=5
+ChorusDepth=5
+SBInputVolume=5
+SBMainVolume=10
+SBWaveVolume=10
+SBSynthVolume=10
+WaveTableVolume=10
+AudioPowerDriver=ON
+
+[FastCFG]
+Show=No
+HideOption=Off
+-----------------------------
+
+OR the Default= line COULD be
+
+Default=SBPRO
+
+Reboot to Win95 and choose Linux. When booted, use sndconfig to configure the  
+sound modules and VOILA - ThinkPad sound with Linux.
+
+Now the gottchas - You can either have CD sound OR Mixers but not both. Thats a
+problem with the SB1.5(CD sound) or SBPRO(Mixers) settings. No-one knows why
+this is!
+
+And, for some reason MPEG3 files, when played through mpg123, sound like they
+are playing at 1/8th speed - not very useful!!!!!!!!!!!! If you have ANY insight
+on why this second thing might be happening I would be grateful.
+
+===========================================================
+    _/      _/_/_/_/
+   _/_/  _/_/     _/
+  _/ _/_/ _/_/_/_/      Martin John Bartlett
+ _/  _/  _/     _/      (martin@nitram.demon.co.uk)
+_/      _/_/_/_/
+       _/
+_/    _/
+ _/_/
+===========================================================
+
+
index b8198cbf3dba8bafb46319fa98834ba26a854a68..ff3cf95e2e3a1a665b8fc989e62311b216a6b1fb 100644 (file)
@@ -76,6 +76,12 @@ M:   Philip.Blundell@pobox.com
 L:     linux-net@vger.rutgers.edu
 S:     Maintained
 
+6PACK NETWORK DRIVER FOR AX.25
+P:     Andreas Koensgen
+M:     ajk@iehk.rwth-aachen.de
+L:     linux-hams@vger.rutgers.edu
+S:     Maintained
+
 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
 P:     Paul Gortmaker
 M      gpg109@rsphy1.anu.edu.au
@@ -157,7 +163,7 @@ S:  Supported
 DAMA SLAVE for AX.25
 P:     Joerg Reuter
 M:     jreuter@poboxes.com
-W:     http://www.rat.de/jr/
+W:     http://poboxes.com/jreuter/
 W:     http://qsl.net/dl1bke/
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
@@ -313,6 +319,7 @@ S:  Maintained
 JOYSTICK DRIVER
 P:     Vojtech Pavlik
 M:     vojtech@atrey.karlin.mff.cuni.cz
+L:     linux-joystick@atrey.karlin.mff.cuni.cz
 S:     Maintained
 
 KERNEL AUTOMOUNTER (AUTOFS)
@@ -461,9 +468,9 @@ S:  Maintained
 PNP SUPPORT
 P:     Tom Lees
 M:     tom@lpsg.demon.co.uk
-L:     pnp-list@lpsg.demon.co.uk
-L:     pnp-list@redhat.com (maybe)
-W:     http://www.lpsg.demon.co.uk/pnp-linux.html
+L:     pnp-users@ferret.lmh.ox.ac.uk
+L:     pnp-devel@ferret.lmh.ox.ac.uk
+W:     http://www-jcr.lmh.ox.ac.uk/~pnp/
 S:     Maintained
 
 PPP PROTOCOL DRIVERS AND COMPRESSORS
@@ -516,7 +523,7 @@ S:  Maintained
 
 SOUND
 P:     Alan Cox 
-M:     Alan Cox@linux.org
+M:     Alan.Cox@linux.org
 S:     Maintained
 
 SPARC:
@@ -613,7 +620,7 @@ S:  Maintained
 Z8530 DRIVER FOR AX.25
 P:     Joerg Reuter
 M:     jreuter@poboxes.com
-W:     http://www.rat.de/jr/
+W:     http://poboxes.com/jreuter/
 W:     http://qsl.net/dl1bke/
 L:     linux-hams@vger.rutgers.edu
 S:     Maintained
index 774ac07cda406dd0e3e51fc409c31d802a26d474..9234795620d5084c3a2186a720754b7a906babbe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 93
+SUBLEVEL = 94
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
index 63181e223532cdc09e06dd6e0355054926bd69ba..bcd55b4760793d125e7406122dda55390c1a1f48 100644 (file)
@@ -176,9 +176,21 @@ ifneq "$(strip $(SYMTAB_OBJS))" ""
 MODINCL = $(TOPDIR)/include/linux/modules
 
 # The -w option (enable warnings) for genksyms will return here in 2.1
+# So where has it gone ???
+#
+# Added the SMP seperator to stop module accidents between uniproc/smp
+# intel boxes - AC - from bits by Michael Chastain
+#
+
+ifdef SMP
+       genksyms_smp_prefix := -p smp_
+else
+       genksyms_smp_prefix := 
+endif
+
 $(MODINCL)/%.ver: %.c
        $(CC) $(CFLAGS) -E -D__GENKSYMS__ $<\
-       | $(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp
+       | $(GENKSYMS) $(genksyms_smp_prefix) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) > $@.tmp
        mv $@.tmp $@
        
 $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)): $(TOPDIR)/include/linux/autoconf.h
index 24f10799f7cfe49e5c57fe2e537e1f2c8023819a..a1dc6d81897b78eaa5e9d7b597bbdeff2c3e0cdc 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/string.h>
 #include <linux/version.h>
 #include <linux/mm.h>
-#include <linux/config.h>
 
 #include <asm/system.h>
 #include <asm/console.h>
index 25aedbfc048e8f8bf753313f64dbe1f5097fa657..7169a58ff2327ec1cace9e750921fb53d128ecdb 100644 (file)
@@ -12,7 +12,6 @@ unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
 unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS
 unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
 unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
-unset CONFIG_ALPHA_SRM CONFIG_ALPHA_SRM_SETUP
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
index 132175541e6d2294f35a67358f8d4e4a1066bc0f..c220ccdc667125fcb4095bda9e60cda8798b0ad7 100644 (file)
@@ -27,7 +27,6 @@
 #define __KERNEL_SYSCALLS__
 #include <asm/unistd.h>
 
-extern void bcopy (const char *src, char *dst, int len);
 extern struct hwrpb_struct *hwrpb;
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
@@ -134,7 +133,6 @@ EXPORT_SYMBOL(__strlen_user);
  * interface isn't gonna change any time soon now, so it's OK
  * to leave it out of version control.
  */
-# undef bcopy
 # undef memcpy
 # undef memset
 EXPORT_SYMBOL_NOVERS(__divl);
@@ -147,7 +145,3 @@ EXPORT_SYMBOL_NOVERS(__remq);
 EXPORT_SYMBOL_NOVERS(__remqu);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memset);
-
-#if CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
-#endif
index b7dfd3135da0bd110cec81352f30cb59cb47ad3c..76f87bffd4f67b55e332533fbe3ab7270f72b257 100644 (file)
@@ -560,15 +560,13 @@ int pcibios_present(void)
 }
 
 
-unsigned long pcibios_init(unsigned long mem_start,
-                          unsigned long mem_end)
+void __init
+pcibios_init(void)
 {
        printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
-
 #if !PCI_MODIFY
        printk("...NOT modifying existing (SRM) PCI configuration\n");
 #endif
-       return mem_start;
 }
 
 /*
@@ -1951,20 +1949,20 @@ static inline void sio_fixup(void)
 extern void tga_console_init(void);
 #endif /* CONFIG_TGA_CONSOLE */
 
-unsigned long __init
-pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
+void __init
+pcibios_fixup(void)
 {
          struct pci_bus *cur;
 
 #ifdef CONFIG_ALPHA_MCPCIA
        /* must do massive setup for multiple PCI busses here... */
        DBG_DEVS(("pcibios_fixup: calling mcpcia_fixup()...\n"));
-       mem_start = mcpcia_fixup(mem_start, mem_end);
+       mcpcia_fixup();
 #endif /* MCPCIA */
 
 #ifdef CONFIG_ALPHA_TSUNAMI
        /* must do massive setup for multiple PCI busses here... */
-       /*      mem_start = tsunami_fixup(mem_start, mem_end); */
+       /* tsunami_fixup(); */
 #endif /* TSUNAMI */
 
 #if PCI_MODIFY && !defined(CONFIG_ALPHA_RUFFIAN)
@@ -2030,8 +2028,6 @@ pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
        tga_console_init();
 #endif
 #endif
-
-       return mem_start;
 }
 
 
index f7baa07433d4b4227cb886b43b5bea09ca697bb3..a6bcd616dbe52a4121add6d32bcc28ce9954c06e 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #define __ASSEMBLY__
-#include <linux/config.h>
 #include <asm/system.h>
 
 #define halt call_pal PAL_halt
index 8d61cfe7e76d0f04e4ea93ec76d7a477b0dec647..6a9dab59abb08a0e134e57b76b31313e4af49d38 100644 (file)
@@ -962,8 +962,7 @@ static void mcpcia_probe(struct linux_hose_info *hose,
        }
 }
 
-unsigned long mcpcia_fixup(unsigned long memory_start,
-                          unsigned long memory_end)
+void mcpcia_fixup(void)
 {
        struct linux_hose_info *hose;
 
@@ -974,7 +973,5 @@ unsigned long mcpcia_fixup(unsigned long memory_start,
        for (hose = mcpcia_root; hose; hose = hose->next) {
                mcpcia_probe(hose, &memory_start);
        }
-
-       return memory_start;
 }
 #endif /* CONFIG_ALPHA_MCPCIA */
index c69b11eabacda8a99c7eaaa5fe97e4b139a7f995..bcab8667fbd81c8806da93228bfb126df4cef88c 100644 (file)
@@ -395,7 +395,7 @@ int get_cpuinfo(char *buffer)
                       "BogoMIPS\t\t: %lu.%02lu\n"
                       "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
                       "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
-                      "platform string\t: %s\n"
+                      "platform string\t\t: %s\n"
 #ifdef __SMP__
                       "%s"
 #endif
index 052a6f1a76f4a75d55a8c7e12ec321d63ac0b06b..bcc4ed2127fbaf82322eb8da5e3a0f6b731159cb 100644 (file)
@@ -994,7 +994,7 @@ static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
 ** and standard ISA IRQs.
 **
 */
-static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata; 
+static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata = 0
 
 /*
 ** The following definition is for the default IRQ 
@@ -1020,7 +1020,7 @@ __initdata =
 ** ISA DMA channels.
 **
 */
-static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata
+static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata = 0;
 
 /*
 ** The following definition is the default DRQ
index 8654474fabbb4e302a050f795aa4a266082e510f..fed91a1c1c87c757dda11933b5b326524ec33199 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
index bcfac1020825c4af65ba499dfcd3144e534257b4..dc708c73e28b0375f0f7872b12c0fd0334431e1a 100644 (file)
@@ -104,7 +104,7 @@ static inline void __memcpy_aligned(unsigned long d, unsigned long s, long n)
        DO_REST_ALIGNED(d,s,n);
 }
 
-void * __memcpy(void * dest, const void *src, size_t n)
+void * memcpy(void * dest, const void *src, size_t n)
 {
        if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) {
                __memcpy_aligned((unsigned long) dest, (unsigned long) src, n);
@@ -114,22 +114,5 @@ void * __memcpy(void * dest, const void *src, size_t n)
        return dest;
 }
 
-/*
- * Broken compiler uses "bcopy" to do internal
- * assignments. Silly OSF/1 BSDism.
- */
-char * bcopy(const char * src, char * dest, size_t n)
-{
-       __memcpy(dest, src, n);
-       return dest;
-}
-
-/*
- * gcc-2.7.1 and newer generate calls to memset and memcpy.  So we
- * need to define that here:
- */
-#ifdef __ELF__
- asm (".weak memcpy; memcpy = __memcpy");
-#else
- asm (".weakext memcpy, __memcpy");
-#endif
+/* For backward modules compatibility, define __memcpy.  */
+asm("__memcpy = memcpy; .globl __memcpy");
index a02f294ba332161e48180ec01ce30836545c3a3f..b95c2f16ee12b114637a72af432d3166d75b2606 100644 (file)
@@ -105,6 +105,17 @@ fi
 # fi
 # endmenu
 
+# Conditionally compile in the Uniform CD-ROM driver
+if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" ]; then
+  define_bool CONFIG_CDROM y
+else
+  if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" ]; then
+    define_bool CONFIG_CDROM m
+  else
+    define_bool CONFIG_CDROM n
+  fi
+fi
+
 source fs/Config.in
 
 source fs/nls/Config.in
index 3953955d40d960cddee9a88e207eaf3fbd4f273a..48358557b3a5f5b1bacfe4943a5ee0e4b23c1364 100644 (file)
@@ -169,6 +169,7 @@ CONFIG_PPP=m
 CONFIG_ETHER1=m
 CONFIG_ETHER3=m
 CONFIG_ETHERH=m
+CONFIG_CDROM=y
 
 #
 # Filesystems
index 20c62e2e6d5b15c8a7023e66e9daa9a1ac5e7b77..0079d809520906bc2052d079550e308bf2ec605b 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/dma.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <asm/irq.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
@@ -77,6 +78,10 @@ EXPORT_SYMBOL(ecard_address);
 /* processor dependencies */
 EXPORT_SYMBOL(processor);
 
+/* irq */
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+
 /* io */
 EXPORT_SYMBOL(outswb);
 EXPORT_SYMBOL(outsw);
index 0d02eb85a61b0034a81dd629970a5b6b2ebf367b..8a248c728dc2061cd2c0e7cb69e9c03c819f5573 100644 (file)
@@ -5,7 +5,7 @@
  */
 #ifndef NR_SYSCALLS
 #define NR_syscalls 256
-#define NR_SYSCALLS 182
+#define NR_SYSCALLS 184
 #else
 
 /* 0 */                .long   SYMBOL_NAME(sys_setup)
                .long   SYMBOL_NAME(sys_rt_sigsuspend_wrapper)
 /* 180 */      .long   SYMBOL_NAME(sys_pread)
                .long   SYMBOL_NAME(sys_pwrite)
-               .space  (NR_syscalls - 182) * 4
+               .long   SYMBOL_NAME(sys_xstat)
+               .long   SYMBOL_NAME(sys_xmknod)
+               .space  (NR_syscalls - 184) * 4
 #endif
index e0fb7540a8b206ca1203c85bd5a3e1604a373b23..2e665312d0e3cea67492d31dc359664e8714518f 100644 (file)
@@ -98,7 +98,7 @@ int get_irq_list(char *buf)
                if (!action)
                        continue;
                p += sprintf(p, "%3d: %10u   %s",
-                            i, kstat.interrupts[i], action->name);
+                            i, kstat.irqs[0][i], action->name);
                for (action = action->next; action; action = action->next) {
                        p += sprintf(p, ", %s", action->name);
                }
@@ -126,7 +126,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 
        cpu = smp_processor_id();
        irq_enter(cpu, irq);
-       kstat.interrupts[irq]++;
+       kstat.irqs[0][irq]++;
 
        /* Return with this interrupt masked if no action */
        status = 0;
index a0fd65df2c4f66200843d3e05e1cc9f358ed34b4..6e1024c30f6e8b9d03ee399203f34aff5ed6b0d3 100644 (file)
 #define FAULT_CODE_WRITE       0x02
 #define FAULT_CODE_USER                0x01
 
+struct pgtable_cache_struct quicklists;
+
+void __bad_pte(pmd_t *pmd)
+{
+       printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+       set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+}
+
+pgd_t *get_pgd_slow(void)
+{
+       pgd_t *pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
+       pgd_t *init;
+       
+       if (pgd) {
+               init = pgd_offset(&init_mm, 0);
+               memzero (pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+               memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+       }
+       return pgd;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+       pte_t *pte;
+
+       pte = (pte_t *) kmalloc (PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
+       if (pmd_none(*pmd)) {
+               if (pte) {
+                       memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+                       set_pmd(pmd, mk_pmd(pte));
+                       return pte + offset;
+               }
+               set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+               return NULL;
+       }
+       kfree (pte);
+       if (pmd_bad(*pmd)) {
+               __bad_pte(pmd);
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + offset;
+}
+
 extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
 
 static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
index 2925761fb5f4acd3c203ebddc8e26594d7616519..02cde532ff706d176bb9cff369e2d53ea1861ecd 100644 (file)
 #define FAULT_CODE_READ                0x02
 #define FAULT_CODE_USER                0x01
 
+struct pgtable_cache_struct quicklists;
+
+void __bad_pte(pmd_t *pmd)
+{
+       printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+       set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+}
+
+void __bad_pte_kernel(pmd_t *pmd)
+{
+       printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+       set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+}
+
+pgd_t *get_pgd_slow(void)
+{
+       /*
+        * need to get a 16k page for level 1
+        */
+       pgd_t *pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,2);
+       pgd_t *init;
+       
+       if (pgd) {
+               init = pgd_offset(&init_mm, 0);
+               memzero ((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+               memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+       }
+       return pgd;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+       pte_t *pte;
+
+       pte = (pte_t *) get_small_page(GFP_KERNEL);
+       if (pmd_none(*pmd)) {
+               if (pte) {
+                       memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+                       set_pmd(pmd, mk_user_pmd(pte));
+                       return pte + offset;
+               }
+               set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+               return NULL;
+       }
+       free_small_page ((unsigned long) pte);
+       if (pmd_bad(*pmd)) {
+               __bad_pte(pmd);
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
+{
+       pte_t *pte;
+
+       pte = (pte_t *) get_small_page(GFP_KERNEL);
+       if (pmd_none(*pmd)) {
+               if (pte) {
+                       memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+                       set_pmd(pmd, mk_kernel_pmd(pte));
+                       return pte + offset;
+               }
+               set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+               return NULL;
+       }
+       free_small_page ((unsigned long) pte);
+       if (pmd_bad(*pmd)) {
+               __bad_pte_kernel(pmd);
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + offset;
+}
+
 extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
 
 static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
index b9e777a32decddc94fcaf3b55b7e9d3ace5197d4..4bc17c8c15e64d15028bdbdb298c3599cb37f378 100644 (file)
@@ -30,7 +30,6 @@
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
 extern char _etext, _stext, _edata, __bss_start, _end;
 extern char __init_begin, __init_end;
 
diff --git a/arch/i386/.kernel_offset.lds b/arch/i386/.kernel_offset.lds
deleted file mode 100644 (file)
index 9cfd927..0000000
+++ /dev/null
@@ -1 +0,0 @@
-__kernel_offset__ = (0x1000-1024)*1024*1024;
index e1b258f6c5a3dccb90718c96aa4051be4fc08f10..98bde850fca6a9807f29f54292aa1e83a349a8db 100644 (file)
@@ -58,9 +58,6 @@ SUBDIRS := $(SUBDIRS) arch/i386/math-emu
 DRIVERS := $(DRIVERS) arch/i386/math-emu/math.a
 endif
 
-memsize: dummy
-       @echo "__kernel_offset__ = (0x1000-$(CONFIG_MAX_MEMSIZE))*1024*1024;" > arch/i386/.kernel_offset.lds
-
 arch/i386/kernel: dummy
        $(MAKE) linuxsubdirs SUBDIRS=arch/i386/kernel
 
@@ -69,31 +66,30 @@ arch/i386/mm: dummy
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
-zImage: memsize vmlinux
+zImage: vmlinux
        @$(MAKEBOOT) zImage
 
-bzImage: memsize vmlinux
+bzImage: vmlinux
        @$(MAKEBOOT) bzImage
 
 compressed: zImage
 
-zlilo: memsize vmlinux
+zlilo: vmlinux
        @$(MAKEBOOT) BOOTIMAGE=zImage zlilo
 
-bzlilo: memsize vmlinux
+bzlilo: vmlinux
        @$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
 
-zdisk: memsize vmlinux
+zdisk: vmlinux
        @$(MAKEBOOT) BOOTIMAGE=zImage zdisk
 
-bzdisk: memsize vmlinux
+bzdisk: vmlinux
        @$(MAKEBOOT) BOOTIMAGE=bzImage zdisk
 
-install: memsize vmlinux
+install: vmlinux
        @$(MAKEBOOT) BOOTIMAGE=bzImage install
 
 archclean:
-       rm -f .kernel_offset.lds
        @$(MAKEBOOT) clean
 
 archdep:
index ee530401d0de8ae48dfa6dff42140cb2e9c41368..3f3f3a20da23117973754d937fbc968e22aaf8b2 100644 (file)
@@ -17,7 +17,6 @@ choice 'Processor family' \
         Pentium/K5/5x86/6x86   CONFIG_M586     \
         PPro/K6/6x86MX         CONFIG_M686" Pentium
 bool 'Math emulation' CONFIG_MATH_EMULATION
-int ' Max physical memory in MB' CONFIG_MAX_MEMSIZE 1024
 endmenu
 
 mainmenu_option next_comment
index 3e89085e344d7cafadf0cf4987b546c097a2380f..9ad83ddb17bdb451d980eb1b0431bb4c3a00a77e 100644 (file)
@@ -125,42 +125,7 @@ int pcibios_present(void)
 int pcibios_read_config_byte (unsigned char bus,
        unsigned char device_fn, unsigned char where, unsigned char *value)
 {
-       int res;
-
-       res = access_pci->read_config_byte(bus, device_fn, where, value);
-
-#ifdef __SMP__
-/*
- * IOAPICs can take PCI IRQs directly, lets first check the mptable:
- *
- * This can go away once nobody probes the irq this way,
- * but uses the PCI tables instead.
- */
-       if (where == PCI_INTERRUPT_LINE) {
-               int irq;
-               char pin;
-
-               /*
-                * get the PCI IRQ INT _physical pin_ for this device
-                */
-               access_pci->read_config_byte(bus, device_fn,
-                                               PCI_INTERRUPT_PIN, &pin);
-               /*
-                * subtle, PCI pins are numbered starting from 1 ...
-                */
-               pin--;
-
-               irq = IO_APIC_get_PCI_irq_vector (bus,PCI_SLOT(device_fn),pin);
-               if (irq != -1)
-                       *value = (unsigned char) irq;
-
-               printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
-                       bus,PCI_SLOT(device_fn), pin, irq);
-
-       }
-#endif
-
-       return res;
+       return access_pci->read_config_byte(bus, device_fn, where, value);
 }
 
 int pcibios_read_config_word (unsigned char bus,
index 3d80cdebc420a3f822b4a2bffb656d9cb88b983f..86031f37f5c562b57d766d28d93e906f85552cdf 100644 (file)
@@ -619,9 +619,6 @@ ENTRY(idt_table)
        .fill 256,8,0           # idt is uninitialized
 
 /*
- * This gdt setup gives the kernel a CONFIG_MAX_MEMSIZE sized address space at
- * virtual address PAGE_OFFSET.
- *
  * This contains up to 8192 quadwords depending on NR_TASKS - 64kB of
  * gdt entries.  Ugh. 
  *
index 95ce9fb1419cd4e562a4b60e1fc28a736e270ee9..0408fea355ab0ffac863b2ae3ce07393f47559be 100644 (file)
@@ -70,7 +70,9 @@ spinlock_t irq_controller_lock;
 
 static unsigned int irq_events [NR_IRQS] = { -1, };
 static int disabled_irq [NR_IRQS] = { 0, };
+#ifdef __SMP__
 static int ipi_pending [NR_IRQS] = { 0, };
+#endif
 
 /*
  * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
index de6de8f145187e1bf3dc71aab27c53195897f1d8..ae67822bcfdc47bad940cc22b2b1491ff0e764ea 100644 (file)
@@ -62,7 +62,7 @@ static struct MCA_info* mca_info = 0;
 /*--------------------------------------------------------------------*/
 
 #ifdef CONFIG_PROC_FS
-static long mca_do_proc_init( long memory_start, long memory_end );
+static void mca_do_proc_init( void );
 static int mca_default_procfn( char* buf, int slot );
 
 static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *);
@@ -79,7 +79,7 @@ static struct inode_operations proc_mca_inode_operations = {
 
 /*--------------------------------------------------------------------*/
 
-__initfunc(long mca_init(long memory_start, long memory_end))
+__initfunc(void mca_init(void))
 {
        unsigned int  i, j;
        int foundscsi = 0;
@@ -96,21 +96,14 @@ __initfunc(long mca_init(long memory_start, long memory_end))
         */
        
        if (!MCA_bus)
-               return memory_start;
+               return;
        cli();
 
        /*
         *      Allocate MCA_info structure (at address divisible by 8)
         */ 
 
-       if( ((memory_start+7)&(~7)) > memory_end ) 
-       {
-               /* uh oh */
-               return memory_start;
-       }
-
-       mca_info = (struct MCA_info*) ((memory_start+7)&(~7));
-       memory_start = ((long)mca_info) + sizeof(struct MCA_info);
+       mca_info = kmalloc(sizeof(struct MCA_info), GFP_ATOMIC);
 
        /*
         *      Make sure adapter setup is off
@@ -194,10 +187,8 @@ __initfunc(long mca_init(long memory_start, long memory_end))
        request_region(0x100,0x08,"POS (MCA)");
 
 #ifdef CONFIG_PROC_FS
-       memory_start = mca_do_proc_init( memory_start, memory_end );
+       mca_do_proc_init();
 #endif
-
-       return memory_start;
 }
 
 /*--------------------------------------------------------------------*/
@@ -418,12 +409,12 @@ int  get_mca_info(char *buf)
 
 
 /*--------------------------------------------------------------------*/
-__initfunc(long mca_do_proc_init( long memory_start, long memory_end ))
+__initfunc(void mca_do_proc_init( void ))
 {
        int i = 0;
        struct proc_dir_entry* node = 0;
 
-       if( mca_info == 0 ) return memory_start;        /* never happens */
+       if( mca_info == 0 ) return;     /* never happens */
 
        proc_register( &proc_mca, &(struct proc_dir_entry) {
                PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
@@ -439,11 +430,7 @@ __initfunc(long mca_do_proc_init( long memory_start, long memory_end ))
                mca_info->slot[i].dev = 0;
 
                if( ! mca_isadapter( i ) ) continue;
-               if( memory_start + sizeof(struct proc_dir_entry) > memory_end ) {
-                       continue;
-               }
-               node = (struct proc_dir_entry*) memory_start;
-               memory_start += sizeof(struct proc_dir_entry);
+               node = kmalloc(sizeof(struct proc_dir_entry), GFP_ATOMIC);
 
                if( i < MCA_MAX_SLOT_NR ) {
                        node->low_ino = PROC_MCA_SLOT + i;
@@ -464,7 +451,6 @@ __initfunc(long mca_do_proc_init( long memory_start, long memory_end ))
                proc_register( &proc_mca, node );
        }
 
-       return memory_start;
 } /* mca_do_proc_init() */
 
 /*--------------------------------------------------------------------*/
index 397cb9e3e7a7765cdf6dbbcd531636dafccdd08a..37ddfa0ef2842497054c8611b505e8055c79b950 100644 (file)
@@ -83,7 +83,7 @@ extern inline void add_Xsig_Xsig(Xsig *dest, const Xsig *x2)
 /* Note: the constraints in the asm statement didn't always work properly
    with gcc 2.5.8.  Changing from using edi to using ecx got around the
    problem, but keep fingers crossed! */
-extern inline int add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
+extern inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
 {
   asm volatile ("movl %2,%%ecx; movl %3,%%esi;
                  movl (%%esi),%%eax; addl %%eax,(%%ecx);
index 4b5f7bf19adcb25732e6bf5100171509755c040a..b96a4bc2f19539f2518ee3bee3d633115edebcc0 100644 (file)
@@ -293,8 +293,6 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
        }
 
        local_flush_tlb();
-       printk("IO APIC ID: %d\n", *(int *)0xFEC00000);
-       printk("APIC ID: %d\n", *(int *)0xFEE00000);
 }
 #endif
        local_flush_tlb();
index 0284015adb8121eefe76d9c013345b0b5a4a1acc..3812c81dba9534e0c5ffc671e7647b70d0c206df 100644 (file)
@@ -1,13 +1,12 @@
 /* ld script to make i386 Linux kernel
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
-INCLUDE arch/i386/.kernel_offset.lds
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
 ENTRY(_start)
 SECTIONS
 {
-  . = __kernel_offset__ + 0x100000;
+  . = 0xC0000000 + 0x100000;
   _text = .;                   /* Text and read-only data */
   .text : {
        *(.text)
index 9206b8e92c2a48b41043011325c9fa2cfec599ca..2b9c131d7941ca54c26c3ac1670084246fa4a342 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/zorro.h>
index bd22bf672face03c03e6af1220e501f40baa6ed3..c548893709d6b0252a57e16c4d1b9ac3863b88ee 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <asm/ptrace.h>
index c1cc4fcd0cd1e5419e77f7b3f1e2eb3cb7603571..05373b04e0929fc87b5c280cbc8b30dcef610da8 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/module.h>
 #include <asm/ptrace.h>
 #include <asm/traps.h>
index 2502b34603b2b996a61f20ebe645b232e09729ec..fe37a903e64425dfe374b3a78484849ac1a9124f 100644 (file)
@@ -16,6 +16,4 @@ if [ "$CONFIG_BLK_DEV_MFM" != "n" ]; then
   bool '   Autodetect hard drive geometry' CONFIG_BLK_DEV_MFM_AUTODETECT
 fi
 
-bool 'ADFS partition support' CONFIG_BLK_DEV_PART
-
 endmenu
index c2c49f3c96ac4329b313b4cdb347362694eeae4e..82c7e7bf585c5273f24d24c0b4d79d6dcb732c5c 100644 (file)
@@ -85,6 +85,8 @@
  *             card slots if someone tries this)!
  *
  * 17/1/97:RMK:        Upgraded to 2.1 kernels.
+ *
+ *  4/3/98:RMK:        Changed major number to 21.
  */
 
 /*
 #include <linux/major.h>
 #include <linux/ioport.h>
 
+#define MAJOR_NR       MFM_ACORN_MAJOR
+#include <linux/blk.h>
+
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq-no.h>
 #include <asm/hardware.h>
 #include <asm/ecard.h>
 
-#define MFM_DISK_MAJOR 13
-#undef  XT_DISK_MAJOR
-#define XT_DISK_MAJOR  -1
-#define MAJOR_NR       MFM_DISK_MAJOR
-#include "blk.h"
-
 /*
  * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
  */
@@ -232,9 +231,6 @@ static void mfm_specify (void);
 static void issue_request(int dev, unsigned int block, unsigned int nsect,
                          struct request *req);
 
-#define mfm_init xd_init
-#define mfm_setup xd_setup
-
 static unsigned int mfm_addr;          /* Controller address */
 static unsigned int mfm_IRQPollLoc;    /* Address to read for IRQ information */
 static unsigned int mfm_irqenable;     /* Podule IRQ enable location */
index 3034d9cc82c735b3c398d76b87a3a33af04e3c0b..f57cb7ffef6a6a6c7f234b861b5f65ddfbb95807 100644 (file)
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/errno.h>
-
+#include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
 #include <asm/ecard.h>
 
 #define __ETHER1_C
@@ -58,9 +58,6 @@
 
 static unsigned int net_debug = NET_DEBUG;
 
-#define        struct ether1_priv *priv = (struct ether1_priv *)dev->priv \
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv
-
 #define BUFFER_SIZE    0x10000
 #define TX_AREA_START  0x00100
 #define TX_AREA_END    0x05000
@@ -87,7 +84,8 @@ static const card_ids ether1_cids[] = {
 #define ether1_inw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
 #define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
 
-static inline unsigned short ether1_inw_p (struct device *dev, int addr, int svflgs)
+static inline unsigned short
+ether1_inw_p (struct device *dev, int addr, int svflgs)
 {
        unsigned long flags;
        unsigned short ret;
@@ -102,7 +100,8 @@ static inline unsigned short ether1_inw_p (struct device *dev, int addr, int svf
        return ret;
 }
 
-static inline void ether1_outw_p (struct device *dev, unsigned short val, int addr, int svflgs)
+static inline void
+ether1_outw_p (struct device *dev, unsigned short val, int addr, int svflgs)
 {
        unsigned long flags;
 
@@ -124,8 +123,8 @@ static inline void ether1_outw_p (struct device *dev, unsigned short val, int ad
  * This routine is essentially an optimised memcpy from the card's
  * onboard RAM to kernel memory.
  */
-static inline void *ether1_inswb (unsigned int addr, void *data, unsigned int len)
+static inline void *
+ether1_inswb (unsigned int addr, void *data, unsigned int len)
 {
        int used;
 
@@ -161,13 +160,14 @@ static inline void *ether1_inswb (unsigned int addr, void *data, unsigned int le
 2:             adds    %3, %3, #1
                ldreqb  %0, [%1]
                streqb  %0, [%2]"
-               : "=&r" (used), "=&r" (addr), "=&r" (data), "=&r" (len)
-               :                "1"  (addr), "2"   (data), "3"   (len));
+       : "=&r" (used), "=&r" (addr), "=&r" (data), "=&r" (len)
+       :                "1"  (addr), "2"   (data), "3"   (len));
 
        return data;
 }
 
-static inline void *ether1_outswb (unsigned int addr, void *data, unsigned int len)
+static inline void *
+ether1_outswb (unsigned int addr, void *data, unsigned int len)
 {
        int used;
 
@@ -203,28 +203,26 @@ static inline void *ether1_outswb (unsigned int addr, void *data, unsigned int l
 2:             adds    %3, %3, #1
                ldreqb  %0, [%2]
                streqb  %0, [%1]"
-               : "=&r" (used), "=&r" (addr), "=&r" (data), "=&r" (len)
-               :                "1"  (addr), "2"   (data), "3"   (len));
+       : "=&r" (used), "=&r" (addr), "=&r" (data), "=&r" (len)
+       :                "1"  (addr), "2"   (data), "3"   (len));
 
        return data;
 }
 
 
-static void ether1_writebuffer (struct device *dev, void *data, unsigned int start, unsigned int length)
+static void
+ether1_writebuffer (struct device *dev, void *data, unsigned int start, unsigned int length)
 {
        unsigned int page, thislen, offset;
+
        offset = start & 4095;
 
-       for (page = start >> 12; length; page++) 
-       {
+       for (page = start >> 12; length; page++) {
                outb (page, REG_PAGE);
-               if (offset + length > 4096) 
-               {
-                   length -= 4096 - offset;
-                   thislen = 4096 - offset;
-               }
-               else
-               {
+               if (offset + length > 4096) {
+                       length -= 4096 - offset;
+                       thislen = 4096 - offset;
+               } else {
                        thislen = length;
                        length = 0;
                }
@@ -234,23 +232,20 @@ static void ether1_writebuffer (struct device *dev, void *data, unsigned int sta
        }
 }
 
-static void ether1_readbuffer (struct device *dev, void *data, unsigned int start, unsigned int length)
+static void
+ether1_readbuffer (struct device *dev, void *data, unsigned int start, unsigned int length)
 {
        unsigned int page, thislen, offset;
 
        offset = start & 4095;
 
-       for (page = start >> 12; length; page++) 
-       {
+       for (page = start >> 12; length; page++) {
                outb (page, REG_PAGE);
-               if (offset + length > 4096) 
-               {
+               if (offset + length > 4096) {
                        length -= 4096 - offset;
                        thislen = 4096 - offset;
-               }
-               else
-               {
-                       thislen = length;
+               } else {
+                       thislen = length;
                        length = 0;
                }
 
@@ -259,7 +254,8 @@ static void ether1_readbuffer (struct device *dev, void *data, unsigned int star
        }
 }
 
-static int ether1_ramtest (struct device *dev, unsigned char byte)
+__initfunc(static int
+ether1_ramtest (struct device *dev, unsigned char byte))
 {
        unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
        int i, ret = BUFFER_SIZE;
@@ -275,12 +271,9 @@ static int ether1_ramtest (struct device *dev, unsigned char byte)
        memset (buffer, byte ^ 0xff, BUFFER_SIZE);
        ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE);
 
-       for (i = 0; i < BUFFER_SIZE; i++) 
-       {
-               if (buffer[i] != byte) 
-               {
-                       if (max_errors >= 0 && bad != buffer[i]) 
-                       {
+       for (i = 0; i < BUFFER_SIZE; i++) {
+               if (buffer[i] != byte) {
+                       if (max_errors >= 0 && bad != buffer[i]) {
                                if (bad != -1)
                                        printk ("\n");
                                printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X",
@@ -290,12 +283,9 @@ static int ether1_ramtest (struct device *dev, unsigned char byte)
                                bad = buffer[i];
                                bad_start = i;
                        }
-               }
-               else
-               {
-                       if (bad != -1) 
-                       {
-                               if (bad_start == i - 1)
+               } else {
+                       if (bad != -1) {
+                               if (bad_start == i - 1)
                                        printk ("\n");
                                else
                                        printk (" - 0x%04X\n", i - 1);
@@ -311,13 +301,15 @@ static int ether1_ramtest (struct device *dev, unsigned char byte)
        return ret;
 }
 
-static int ether1_reset (struct device *dev)
+static int
+ether1_reset (struct device *dev)
 {
        outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
        return BUS_16;
 }
 
-static int ether1_init_2 (struct device *dev)
+__initfunc(static int
+ether1_init_2 (struct device *dev))
 {
        int i;
        dev->mem_start = 0;
@@ -328,7 +320,7 @@ static int ether1_init_2 (struct device *dev)
                i = ether1_ramtest (dev, 0x1e);
 
        if (i <= 0)
-               return -ENODEV;
+               return -ENODEV;
 
        dev->mem_end = i;
        return 0;
@@ -340,12 +332,9 @@ static int ether1_init_2 (struct device *dev)
  */
 
 /* at 0x0100 */
-
 #define NOP_ADDR       (TX_AREA_START)
 #define NOP_SIZE       (0x06)
-
-static nop_t  init_nop  = 
-{
+static nop_t  init_nop  = {
        0,
        CMD_NOP,
        NOP_ADDR
@@ -364,8 +353,7 @@ static tdr_t  init_tdr      = {
 /* at 0x002e */
 #define MC_ADDR                (0x002e)
 #define MC_SIZE                (0x0c)
-static mc_t   init_mc   = 
-{
+static mc_t   init_mc   = {
        0,
        CMD_SETMULTICAST,
        TDR_ADDR,
@@ -447,7 +435,7 @@ static rfd_t  init_rfd      = {
 };
 
 #define RBD_SIZE       (0x0a)
-static rbd_t  init_rbd = {     
+static rbd_t  init_rbd = {
        0,
        0,
        0,
@@ -458,7 +446,8 @@ static rbd_t  init_rbd      = {
 #define TX_SIZE                (0x08)
 #define TBD_SIZE       (0x08)
 
-static int ether1_init_for_open (struct device *dev)
+static int
+ether1_init_for_open (struct device *dev)
 {
        struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        int i, status, addr, next, next2;
@@ -479,8 +468,7 @@ static int ether1_init_for_open (struct device *dev)
        ether1_writebuffer (dev, &init_tdr,  TDR_ADDR,  TDR_SIZE);
        ether1_writebuffer (dev, &init_nop,  NOP_ADDR,  NOP_SIZE);
 
-       if (ether1_inw (dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) 
-       {
+       if (ether1_inw (dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
                printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n",
                        dev->name);
                return 1;
@@ -492,21 +480,16 @@ static int ether1_init_for_open (struct device *dev)
         * First rfd is linked to scp, first rbd is linked to first
         * rfd.  Last rbd has a suspend command.
         */
-       
        addr = RX_AREA_START;
-
-       do 
-       {
+       do {
                next = addr + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
                next2 = next + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10;
 
-               if (next2 >= RX_AREA_END) 
-               {
+               if (next2 >= RX_AREA_END) {
                        next = RX_AREA_START;
                        init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND;
                        priv->rx_tail = addr;
-               }
-               else
+               } else
                        init_rfd.rfd_command = 0;
                if (addr == RX_AREA_START)
                        init_rfd.rfd_rbdoffset = addr + RFD_SIZE;
@@ -519,8 +502,7 @@ static int ether1_init_for_open (struct device *dev)
                ether1_writebuffer (dev, &init_rfd, addr, RFD_SIZE);
                ether1_writebuffer (dev, &init_rbd, addr + RFD_SIZE, RBD_SIZE);
                addr = next;
-       }
-       while (next2 < RX_AREA_END);
+       } while (next2 < RX_AREA_END);
 
        priv->tx_link = NOP_ADDR;
        priv->tx_head = NOP_ADDR + NOP_SIZE;
@@ -536,10 +518,8 @@ static int ether1_init_for_open (struct device *dev)
 
        /* 586 should now unset iscp.busy */
        i = jiffies + HZ/2;
-       while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) 
-       {
-               if (jiffies > i) 
-               {
+       while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
+               if (jiffies > i) {
                        printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
                        return 1;
                }
@@ -547,32 +527,30 @@ static int ether1_init_for_open (struct device *dev)
 
        /* check status of commands that we issued */
        i += HZ/10;
-       while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) 
-       {
-               if (jiffies-i<0)
+       while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
+                       & STAT_COMPLETE) == 0) {
+               if (jiffies > i)
                        break;
        }
 
-       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) 
-       {
+       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
                printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status);
                printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-               ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-               ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-               ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-               ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+                       ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+                       ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+                       ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+                       ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
                failures += 1;
        }
 
        i += HZ/10;
-       while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) 
-       {
-               if (jiffies-i<0)
+       while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
+                       & STAT_COMPLETE) == 0) {
+               if (jiffies > i)
                        break;
        }
 
-       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) 
-       {
+       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
                printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status);
                printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
                        ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
@@ -583,14 +561,13 @@ static int ether1_init_for_open (struct device *dev)
        }
 
        i += HZ/10;
-       while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) 
-       {
-               if (jiffies-i < 0)
+       while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
+                       & STAT_COMPLETE) == 0) {
+               if (jiffies > i)
                        break;
        }
 
-       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) 
-       {
+       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
                printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status);
                printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
                        ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
@@ -601,33 +578,29 @@ static int ether1_init_for_open (struct device *dev)
        }
 
        i += HZ;
-       while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS)) & STAT_COMPLETE) == 0) 
-       {
-               if (jiffies-i <0)
+       while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
+                       & STAT_COMPLETE) == 0) {
+               if (jiffies > i)
                        break;
        }
 
-       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) 
-       {
+       if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
                printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name);
                printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
                        ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
                        ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
                        ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
                        ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
-       }
-       else 
-       {
+       } else {
                status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
                if (status & TDR_XCVRPROB)
                        printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name);
-               else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) 
-               {
+               else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) {
 #ifdef FANCY
                        printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d.%d us away\n", dev->name,
                                status & TDR_SHORT ? "short" : "open", (status & TDR_TIME) / 10,
                                (status & TDR_TIME) % 10);
-#else  
+#else
                        printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d clks away\n", dev->name,
                                status & TDR_SHORT ? "short" : "open", (status & TDR_TIME));
 #endif
@@ -639,7 +612,8 @@ static int ether1_init_for_open (struct device *dev)
        return failures ? 1 : 0;
 }
 
-static int ether1_probe1 (struct device *dev)
+__initfunc(static int
+ether1_probe1 (struct device *dev))
 {
        static unsigned int version_printed = 0;
        struct ether1_priv *priv;
@@ -649,13 +623,12 @@ static int ether1_probe1 (struct device *dev)
                dev->priv = kmalloc (sizeof (struct ether1_priv), GFP_KERNEL);
 
        if (!dev->priv)
-               return 1;
+               return 1;
 
        priv = (struct ether1_priv *)dev->priv;
        memset (priv, 0, sizeof (struct ether1_priv));
 
-       if ((priv->bus_type = ether1_reset (dev)) == 0) 
-       {
+       if ((priv->bus_type = ether1_reset (dev)) == 0) {
                kfree (dev->priv);
                return 1;
        }
@@ -672,15 +645,14 @@ static int ether1_probe1 (struct device *dev)
        for (i = 0; i < 6; i++)
                printk (i==0?" %02x":i==5?":%02x\n":":%02x", dev->dev_addr[i]);
 
-       if (ether1_init_2 (dev)) 
-       {
+       if (ether1_init_2 (dev)) {
                kfree (dev->priv);
                return 1;
        }
 
-       dev->open           = ether1_open;
-       dev->stop           = ether1_close;
-       dev->hard_start_xmit= ether1_sendpacket;
+       dev->open                   = ether1_open;
+       dev->stop                   = ether1_close;
+       dev->hard_start_xmit    = ether1_sendpacket;
        dev->get_stats      = ether1_getstats;
        dev->set_multicast_list = ether1_setmulticastlist;
 
@@ -688,8 +660,7 @@ static int ether1_probe1 (struct device *dev)
        ether_setup (dev);
 
 #ifndef CLAIM_IRQ_AT_OPEN
-       if (request_irq (dev->irq, ether1_interrupt, 0, "ether1", dev)) 
-       {
+       if (request_irq (dev->irq, ether1_interrupt, 0, "ether1", dev)) {
                kfree (dev->priv);
                return -EAGAIN;
        }
@@ -699,7 +670,8 @@ static int ether1_probe1 (struct device *dev)
     
 /* ------------------------------------------------------------------------- */
 
-static void ether1_addr (struct device *dev)
+__initfunc(static void
+ether1_addr (struct device *dev))
 {
        int i;
     
@@ -707,7 +679,8 @@ static void ether1_addr (struct device *dev)
                dev->dev_addr[i] = inb (IDPROM_ADDRESS + i);
 }
 
-int ether1_probe (struct device *dev)
+__initfunc(int
+ether1_probe (struct device *dev))
 {
 #ifndef MODULE
        struct expansion_card *ec;
@@ -723,6 +696,7 @@ int ether1_probe (struct device *dev)
        dev->irq       = ec->irq;
 
        ecard_claim (ec);
+
 #endif
        ether1_addr (dev);
 
@@ -733,36 +707,36 @@ int ether1_probe (struct device *dev)
 
 /* ------------------------------------------------------------------------- */
 
-static int ether1_txalloc (struct device *dev, int size)
+static int
+ether1_txalloc (struct device *dev, int size)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        int start, tail;
 
        size = (size + 1) & ~1;
        tail = priv->tx_tail;
 
-       if (priv->tx_head + size > TX_AREA_END) 
-       {
+       if (priv->tx_head + size > TX_AREA_END) {
                if (tail > priv->tx_head)
                        return -1;
                start = TX_AREA_START;
                if (start + size > tail)
                        return -1;
                priv->tx_head = start + size;
-       }
-       else
-       {
+       } else {
                if (priv->tx_head < tail && (priv->tx_head + size) > tail)
                        return -1;
                start = priv->tx_head;
                priv->tx_head += size;
        }
+
        return start;
 }
 
-static void ether1_restart (struct device *dev, char *reason)
+static void
+ether1_restart (struct device *dev, char *reason)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        priv->stats.tx_errors ++;
 
        if (reason)
@@ -781,9 +755,10 @@ static void ether1_restart (struct device *dev, char *reason)
        dev->start = 1;
 }
 
-static int ether1_open (struct device *dev)
+static int
+ether1_open (struct device *dev)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 #ifdef CLAIM_IRQ_AT_OPEN
        if (request_irq (dev->irq, ether1_interrupt, 0, "ether1", dev))
                return -EAGAIN;
@@ -792,8 +767,7 @@ static int ether1_open (struct device *dev)
 
        memset (&priv->stats, 0, sizeof (struct enet_statistics));
 
-       if (ether1_init_for_open (dev)) 
-       {
+       if (ether1_init_for_open (dev)) {
 #ifdef CLAIM_IRQ_AT_OPEN
                free_irq (dev->irq, dev);
 #endif
@@ -808,15 +782,15 @@ static int ether1_open (struct device *dev)
        return 0;
 }
 
-static int ether1_sendpacket (struct sk_buff *skb, struct device *dev)
+static int
+ether1_sendpacket (struct sk_buff *skb, struct device *dev)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 
        if (priv->restart)
                ether1_restart (dev, NULL);
 
-       if (dev->tbusy) 
-       {
+       if (dev->tbusy) {
                /*
                 * If we get here, some higher level has decided that we are broken.
                 * There should really be a "kick me" function call instead.
@@ -835,11 +809,9 @@ static int ether1_sendpacket (struct sk_buff *skb, struct device *dev)
         * Block a timer-based transmit from overlapping.  This could better be
         * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
         */
-        
        if (test_and_set_bit (0, (void *)&dev->tbusy) != 0)
                printk (KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
-       else 
-       {
+       else {
                int len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
                int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
                unsigned long flags;
@@ -890,14 +862,15 @@ static int ether1_sendpacket (struct sk_buff *skb, struct device *dev)
                if (tst != -1)
                        dev->tbusy = 0;
        }
-       dev_kfree_skb (skb, FREE_WRITE);
+       dev_kfree_skb (skb);
 
        return 0;
 }
 
-static void ether1_xmit_done (struct device *dev)
+static void
+ether1_xmit_done (struct device *dev)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        nop_t nop;
        int caddr, tst;
 
@@ -906,57 +879,52 @@ static void ether1_xmit_done (struct device *dev)
 again:
        ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
 
-       switch (nop.nop_command & CMD_MASK) 
-       {
-               case CMD_TDR:
-                       /* special case */
-                       if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) != (unsigned short)I82586_NULL) 
-                       {
-                               ether1_outw (dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
-                               scb_command, NORMALIRQS);
-                               outb (CTRL_CA, REG_CONTROL);
-                       }
-                       priv->tx_tail = NOP_ADDR;
-                       return;
+       switch (nop.nop_command & CMD_MASK) {
+       case CMD_TDR:
+               /* special case */
+               if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+                               != (unsigned short)I82586_NULL) {
+                       ether1_outw(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
+                                   scb_command, NORMALIRQS);
+                       outb (CTRL_CA, REG_CONTROL);
+               }
+               priv->tx_tail = NOP_ADDR;
+               return;
 
-               case CMD_NOP:
-                       if (nop.nop_link == caddr)
-                       {
-                               if (priv->initialising == 0)
-                                       printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
-                               else
-                                       priv->initialising = 0;
-                               return;
-                       }
-                       if (caddr == nop.nop_link)
-                               return;
-                       caddr = nop.nop_link;
-                       goto again;
-
-               case CMD_TX:
-                       if (nop.nop_status & STAT_COMPLETE)
-                               break;
-                       printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
-                       priv->restart = 1;
+       case CMD_NOP:
+               if (nop.nop_link == caddr) {
+                       if (priv->initialising == 0)
+                               printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
+                       else
+                               priv->initialising = 0;
                        return;
-
-               default:
-                       printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
-                               nop.nop_command & CMD_MASK, caddr);
-                       priv->restart = 1;
+               }
+               if (caddr == nop.nop_link)
                        return;
+               caddr = nop.nop_link;
+               goto again;
+
+       case CMD_TX:
+               if (nop.nop_status & STAT_COMPLETE)
+                       break;
+               printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
+               priv->restart = 1;
+               return;
+
+       default:
+               printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
+                       nop.nop_command & CMD_MASK, caddr);
+               priv->restart = 1;
+               return;
        }
 
-       while (nop.nop_status & STAT_COMPLETE) 
-       {
-               if (nop.nop_status & STAT_OK) 
-               {
+       while (nop.nop_status & STAT_COMPLETE) {
+               if (nop.nop_status & STAT_OK) {
                        priv->stats.tx_packets ++;
                        priv->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
-               }
-               else
-               {
+               } else {
                        priv->stats.tx_errors ++;
+
                        if (nop.nop_status & STAT_COLLAFTERTX)
                                priv->stats.collisions ++;
                        if (nop.nop_status & STAT_NOCARRIER)
@@ -968,16 +936,15 @@ again:
                        if (nop.nop_status & STAT_COLLEXCESSIVE)
                                priv->stats.collisions += 16;
                }
-               if (nop.nop_link == caddr) 
-               {
+
+               if (nop.nop_link == caddr) {
                        printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name);
                        break;
                }
 
                caddr = nop.nop_link;
                ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
-               if ((nop.nop_command & CMD_MASK) != CMD_NOP) 
-               {
+               if ((nop.nop_command & CMD_MASK) != CMD_NOP) {
                        printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name);
                        break;
                }
@@ -987,8 +954,7 @@ again:
 
                caddr = nop.nop_link;
                ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
-               if ((nop.nop_command & CMD_MASK) != CMD_TX) 
-               {
+               if ((nop.nop_command & CMD_MASK) != CMD_TX) {
                        printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name);
                        break;
                }
@@ -1004,15 +970,15 @@ again:
        mark_bh (NET_BH);
 }
 
-static void ether1_recv_done (struct device *dev)
+static void
+ether1_recv_done (struct device *dev)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        int status;
        int nexttail, rbdaddr;
        rbd_t rbd;
 
-       do
-       {
+       do {
                status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status, NORMALIRQS);
                if ((status & RFD_COMPLETE) == 0)
                        break;
@@ -1020,16 +986,14 @@ static void ether1_recv_done (struct device *dev)
                rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
                ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
 
-               if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) 
-               {
+               if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
                        int length = rbd.rbd_status & RBD_ACNT;
                        struct sk_buff *skb;
 
                        length = (length + 1) & ~1;
                        skb = dev_alloc_skb (length + 2);
 
-                       if (skb) 
-                       {
+                       if (skb) {
                                skb->dev = dev;
                                skb_reserve (skb, 2);
 
@@ -1038,13 +1002,10 @@ static void ether1_recv_done (struct device *dev)
                                skb->protocol = eth_type_trans (skb, dev);
                                netif_rx (skb);
                                priv->stats.rx_packets ++;
-                       }
-                       else
+                       } else
                                priv->stats.rx_dropped ++;
-               }
-               else 
-               {
-                       printk (KERN_WARNING "%s: %s\n", dev->name,
+               } else {
+                       printk(KERN_WARNING "%s: %s\n", dev->name,
                                (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
                        priv->stats.rx_dropped ++;
                }
@@ -1052,7 +1013,7 @@ static void ether1_recv_done (struct device *dev)
                nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link, NORMALIRQS);
                /* nexttail should be rx_head */
                if (nexttail != priv->rx_head)
-                       printk (KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
+                       printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
                                dev->name, nexttail, priv->rx_head);
                ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
                ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command, NORMALIRQS);
@@ -1061,86 +1022,85 @@ static void ether1_recv_done (struct device *dev)
        
                priv->rx_tail = nexttail;
                priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link, NORMALIRQS);
-       }
-       while (1);
+       } while (1);
 }
 
-static void ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+static void
+ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
        struct device *dev = (struct device *)dev_id;
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        int status;
 
        dev->interrupt = 1;
 
        status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
 
-       if (status) 
-       {
-               ether1_outw (dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
-                       SCB_ADDR, scb_t, scb_command, NORMALIRQS);
+       if (status) {
+               ether1_outw(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
+                           SCB_ADDR, scb_t, scb_command, NORMALIRQS);
                outb (CTRL_CA | CTRL_ACK, REG_CONTROL);
-               if (status & SCB_STCX)
+               if (status & SCB_STCX) {
                        ether1_xmit_done (dev);
-               if (status & SCB_STCNA) 
-               {
+               }
+               if (status & SCB_STCNA) {
                        if (priv->resetting == 0)
                                printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name);
                        else
                                priv->resetting += 1;
-                       if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) != (unsigned short)I82586_NULL) 
-                       {
+                       if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+                                       != (unsigned short)I82586_NULL) {
                                ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
                                outb (CTRL_CA, REG_CONTROL);
                        }
                        if (priv->resetting == 2)
                                priv->resetting = 0;
                }
-               if (status & SCB_STFR)
+               if (status & SCB_STFR) {
                        ether1_recv_done (dev);
-
-               if (status & SCB_STRNR) 
-               {
-                       if (ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) 
-                       {
+               }
+               if (status & SCB_STRNR) {
+                       if (ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
                                printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
                                ether1_outw (dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
                                outb (CTRL_CA, REG_CONTROL);
                                priv->stats.rx_dropped ++;      /* we suspended due to lack of buffer space */
-                       }
-                       else
-                               printk (KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
-                       ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
-                       printk (KERN_WARNING "RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset,NORMALIRQS));
+                       } else
+                               printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
+                                       ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
+                       printk (KERN_WARNING "RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset,
+                                               NORMALIRQS));
                }
-       }
-       else
-               outb (CTRL_ACK, REG_CONTROL);
+       } else
+               outb (CTRL_ACK, REG_CONTROL);
 
        dev->interrupt = 0;
 }
 
-static int ether1_close (struct device *dev)
+static int
+ether1_close (struct device *dev)
 {
 #ifdef CLAIM_IRQ_AT_OPEN
        free_irq (dev->irq, dev);
 #endif
 
-       ether1_reset (dev);     
+       ether1_reset (dev);
+
        dev->start = 0;
        dev->tbusy = 0;
+
        MOD_DEC_USE_COUNT;
 
        return 0;
 }
 
-static struct enet_statistics *ether1_getstats (struct device *dev)
+static struct enet_statistics *
+ether1_getstats (struct device *dev)
 {
-       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+       struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
        return &priv->stats;
 }
 
-
 /*
  * Set or clear the multicast filter for this adaptor.
  * num_addrs == -1     Promiscuous mode, receive all packets.
@@ -1148,8 +1108,8 @@ static struct enet_statistics *ether1_getstats (struct device *dev)
  * num_addrs > 0       Multicast mode, receive normal and MC packets, and do
  *                     best-effort filtering.
  */
-
-static void ether1_setmulticastlist (struct device *dev)
+static void
+ether1_setmulticastlist (struct device *dev)
 {
 }
 
@@ -1161,12 +1121,12 @@ static char ethernames[MAX_ECARDS][9];
 static struct device *my_ethers[MAX_ECARDS];
 static struct expansion_card *ec[MAX_ECARDS];
 
-int init_module (void)
+int
+init_module (void)
 {
        int i;
 
-       for (i = 0; i < MAX_ECARDS; i++) 
-       {
+       for (i = 0; i < MAX_ECARDS; i++) {
                my_ethers[i] = NULL;
                ec[i] = NULL;
                strcpy (ethernames[i], "        ");
@@ -1174,10 +1134,9 @@ int init_module (void)
 
        i = 0;
 
-       ecard_startfind();
+       ecard_startfind ();
 
-       do 
-       {
+       do {
                if ((ec[i] = ecard_find(0, ether1_cids)) == NULL)
                        break;
 
@@ -1191,17 +1150,13 @@ int init_module (void)
 
                ecard_claim (ec[i]);
 
-               if (register_netdev (my_ethers[i]) != 0) 
-               {
-                       for (i = 0; i < 4; i++) 
-                       {
-                               if (my_ethers[i]) 
-                               {
+               if (register_netdev (my_ethers[i]) != 0) {
+                       for (i = 0; i < 4; i++) {
+                               if (my_ethers[i]) {
                                        kfree (my_ethers[i]);
                                        my_ethers[i] = NULL;
                                }
-                               if (ec[i])
-                               {
+                               if (ec[i]) {
                                        ecard_release (ec[i]);
                                        ec[i] = NULL;
                                }
@@ -1209,20 +1164,18 @@ int init_module (void)
                        return -EIO;
                }
                i++;
-       }
-       while (i < MAX_ECARDS);
+       } while (i < MAX_ECARDS);
 
        return i != 0 ? 0 : -ENODEV;
 }
 
-void cleanup_module (void)
+void
+cleanup_module (void)
 {
        int i;
 
-       for (i = 0; i < MAX_ECARDS; i++) 
-       {
-               if (my_ethers[i]) 
-               {
+       for (i = 0; i < MAX_ECARDS; i++) {
+               if (my_ethers[i]) {
                        unregister_netdev (my_ethers[i]);
                        release_region (my_ethers[i]->base_addr, 16);
                        release_region (my_ethers[i]->base_addr + 0x800, 4096);
@@ -1231,8 +1184,7 @@ void cleanup_module (void)
 #endif
                        my_ethers[i] = NULL;
                }
-               if (ec[i]) 
-               {
+               if (ec[i]) {
                        ecard_release (ec[i]);
                        ec[i] = NULL;
                }
index 4e11641b0a9030741297cc5ff35d0a63876ef467..c0b5c1f76cc64d0515618295cf595c3e5346ad92 100644 (file)
@@ -7,29 +7,30 @@
  * By Russell King, with some suggestions from borris@ant.co.uk
  *
  * Changelog:
- * 1.04 RMK     29/02/1996      Won't pass packets that are from our ethernet
- *                              address up to the higher levels - they're
- *                              silently ignored.  I/F can now be put into
- *                              multicast mode.  Receiver routine optimised.
- * 1.05 RMK     30/02/1996      Now claims interrupt at open when part of
- *                              the kernel rather than when a module.
- * 1.06 RMK     02/03/1996      Various code cleanups
- * 1.07 RMK     13/10/1996      Optimised interrupt routine and transmit
- *                              routines.
- * 1.08 RMK     14/10/1996      Fixed problem with too many packets,
- *                              prevented the kernel message about dropped
- *                              packets appearing too many times a second.
- *                              Now does not disable all IRQs, only the IRQ
- *                              used by this card.
- * 1.09 RMK     10/11/1996      Only enables TX irq when buffer space is low,
- *                              but we still service the TX queue if we get a
- *                              RX interrupt.
- * 1.10 RMK     15/07/1997      Fixed autoprobing of NQ8004.
- * 1.11 RMK     16/11/1997      Fixed autoprobing of NQ8005A.
- * 1.12 RMK     31/12/1997      Removed reference to dev_tint for Linux 2.1.
+ * 1.04        RMK     29/02/1996      Won't pass packets that are from our ethernet
+ *                             address up to the higher levels - they're
+ *                             silently ignored.  I/F can now be put into
+ *                             multicast mode.  Receiver routine optimised.
+ * 1.05        RMK     30/02/1996      Now claims interrupt at open when part of
+ *                             the kernel rather than when a module.
+ * 1.06        RMK     02/03/1996      Various code cleanups
+ * 1.07        RMK     13/10/1996      Optimised interrupt routine and transmit
+ *                             routines.
+ * 1.08        RMK     14/10/1996      Fixed problem with too many packets,
+ *                             prevented the kernel message about dropped
+ *                             packets appearing too many times a second.
+ *                             Now does not disable all IRQs, only the IRQ
+ *                             used by this card.
+ * 1.09        RMK     10/11/1996      Only enables TX irq when buffer space is low,
+ *                             but we still service the TX queue if we get a
+ *                             RX interrupt.
+ * 1.10        RMK     15/07/1997      Fixed autoprobing of NQ8004.
+ * 1.11        RMK     16/11/1997      Fixed autoprobing of NQ8005A.
+ * 1.12        RMK     31/12/1997      Removed reference to dev_tint for Linux 2.1.
  *
  * TODO:
  *  When we detect a fatal error on the interface, we should restart it.
+ *  Reap transmit packets after some time even if the buffer never filled.
  */
 
 static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.12\n";
@@ -49,6 +50,7 @@ static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.12\n";
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -64,25 +66,20 @@ static char *version = "ether3 ethernet driver (c) 1995-1998 R.M.King v1.12\n";
 #endif
 
 static unsigned int net_debug = NET_DEBUG;
-
-static const card_ids ether3_cids[] =
-{
-       {MANU_ANT2, PROD_ANT_ETHER3},
-       {MANU_ANT, PROD_ANT_ETHER3},
-       {MANU_ANT, PROD_ANT_ETHERB},    /* trial - will etherb work? */
-       {0xffff, 0xffff}
+static const card_ids ether3_cids[] = {
+       { MANU_ANT2, PROD_ANT_ETHER3 },
+       { MANU_ANT,  PROD_ANT_ETHER3 },
+       { MANU_ANT,  PROD_ANT_ETHERB }, /* trial - will etherb work? */
+       { 0xffff, 0xffff }
 };
 
 static void ether3_setmulticastlist(struct device *dev);
-static int ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int maxcnt);
+static int  ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int maxcnt);
 static void ether3_tx(struct device *dev, struct dev_priv *priv);
 
 extern int inswb(int reg, void *buffer, int len);
 extern int outswb(int reg, void *buffer, int len);
 
-#define        struct dev_priv *priv = (struct dev_priv *)dev->priv \
-       struct dev_priv *priv = (struct dev_priv *)dev->priv
-
 #define BUS_16         2
 #define BUS_8          1
 #define BUS_UNKNOWN    0
@@ -91,9 +88,7 @@ extern int outswb(int reg, void *buffer, int len);
  * I'm not sure what address we should default to if the internal one
  * is corrupted...
  */
-
-unsigned char def_eth_addr[6] =
-{0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
+unsigned char def_eth_addr[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
 
 /* --------------------------------------------------------------------------- */
 
@@ -102,16 +97,17 @@ typedef enum {
        buffer_read
 } buffer_rw_t;
 
-static int ether3_setbuffer(struct device *dev, buffer_rw_t read, int start)
+static int
+ether3_setbuffer(struct device *dev, buffer_rw_t read, int start)
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
        int timeout = 1000;
 
        outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
        outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND);
        while ((inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) {
                if (!timeout--) {
-                       printk(KERN_ERR "%s: setbuffer broken\n", dev->name);
+                       printk("%s: setbuffer broken\n", dev->name);
                        priv->broken = 1;
                        return 1;
                }
@@ -131,47 +127,49 @@ static int ether3_setbuffer(struct device *dev, buffer_rw_t read, int start)
  * write data to the buffer memory
  */
 #define ether3_writebuffer(dev,data,length)                    \
-       outswb (REG_BUFWIN, (data), (length))
+       outswb(REG_BUFWIN, (data), (length))
 
 #define ether3_writeword(dev,data)                             \
-       outw ((data), REG_BUFWIN)
+       outw((data), REG_BUFWIN)
 
 #define ether3_writelong(dev,data)     {                       \
        unsigned long reg_bufwin = REG_BUFWIN;                  \
-       outw ((data), reg_bufwin);                              \
-       outw ((data) >> 16, reg_bufwin);                        \
+       outw((data), reg_bufwin);                               \
+       outw((data) >> 16, reg_bufwin);                 \
 }
 
 /*
  * read data from the buffer memory
  */
 #define ether3_readbuffer(dev,data,length)                     \
-       inswb (REG_BUFWIN, (data), (length))
+       inswb(REG_BUFWIN, (data), (length))
 
 #define ether3_readword(dev)                                   \
-       inw (REG_BUFWIN)
+       inw(REG_BUFWIN)
 
 #define ether3_readlong(dev)                                   \
-       inw (REG_BUFWIN) | (inw (REG_BUFWIN) << 16)
+       inw(REG_BUFWIN) | (inw(REG_BUFWIN) << 16)
 
 /*
  * Switch LED off...
  */
-static void ether3_ledoff(unsigned long data)
+static void
+ether3_ledoff(unsigned long data)
 {
-       struct device *dev = (struct device *) data;
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct device *dev = (struct device *)data;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
        outw(priv->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
 }
 
 /*
  * switch LED on...
  */
-static inline void ether3_ledon(struct device *dev, struct dev_priv *priv)
+static inline void
+ether3_ledon(struct device *dev, struct dev_priv *priv)
 {
        del_timer(&priv->timer);
-       priv->timer.expires = jiffies + HZ / 50;        /* leave on for 1/50th second */
-       priv->timer.data = (unsigned long) dev;
+       priv->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
+       priv->timer.data = (unsigned long)dev;
        priv->timer.function = ether3_ledoff;
        add_timer(&priv->timer);
        if (priv->regs.config2 & CFG2_CTRLO)
@@ -182,30 +180,36 @@ static inline void ether3_ledon(struct device *dev, struct dev_priv *priv)
  * Read the ethernet address string from the on board rom.
  * This is an ascii string!!!
  */
-static void ether3_addr(char *addr, struct expansion_card *ec)
+__initfunc(static void
+ether3_addr(char *addr, struct expansion_card *ec))
 {
        struct in_chunk_dir cd;
        char *s;
-
+       
        if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
                int i;
-               for (i = 0; i < 6; i++) {
+               for (i = 0; i<6; i++) {
                        addr[i] = simple_strtoul(s + 1, &s, 0x10);
-                       if (*s != (i == 5 ? ')' : ':'))
+                       if (*s != (i==5?')' : ':' ))
                                break;
                }
                if (i == 6)
                        return;
        }
+       /* I wonder if we should even let the user continue in this case
+        *   - no, it would be better to disable the device
+        */
+       printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n");
        memcpy(addr, def_eth_addr, 6);
 }
 
 /* --------------------------------------------------------------------------- */
 
-static int ether3_ramtest(struct device *dev, unsigned char byte)
+__initfunc(static int
+ether3_ramtest(struct device *dev, unsigned char byte))
 {
        unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
-       int i, ret = 0;
+       int i,ret = 0;
        int max_errors = 4;
        int bad = -1;
 
@@ -234,7 +238,7 @@ static int ether3_ramtest(struct device *dev, unsigned char byte)
                        }
                } else {
                        if (bad != -1) {
-                               if (bad != i - 1)
+                               if (bad != i - 1)
                                        printk(" - 0x%04X", i - 1);
                                printk("\n");
                                bad = -1;
@@ -250,13 +254,14 @@ static int ether3_ramtest(struct device *dev, unsigned char byte)
 
 /* ------------------------------------------------------------------------------- */
 
-static int ether3_init_2(struct device *dev)
+__initfunc(static int
+ether3_init_2(struct device *dev))
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
        int i;
 
-       priv->regs.config1 = CFG1_RECVCOMPSTAT0 | CFG1_DMABURST8;
-       priv->regs.config2 = CFG2_CTRLO | CFG2_RECVCRC | CFG2_ERRENCRC;
+       priv->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
+       priv->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
        priv->regs.command = 0;
        /*
         * Set up our hardware address
@@ -273,12 +278,12 @@ static int ether3_init_2(struct device *dev)
                priv->regs.config1 |= CFG1_RECVSPECBROAD;
 
        /*
-        * There is a problem with the NQ8005 in that it occasionally losses the
-        * last two bytes.  To get round this problem, we receive the CRC as well.
-        * That way, if we do loose the last two, then it doesn't matter
+        * There is a problem with the NQ8005 in that it occasionally loses the
+        * last two bytes.  To get round this problem, we receive the CRC as
+        * well.  That way, if we do loose the last two, then it doesn't matter.
         */
        outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
-       outw((TX_END >> 8) - 1, REG_BUFWIN);
+       outw((TX_END>>8) - 1, REG_BUFWIN);
        outw(priv->rx_head, REG_RECVPTR);
        outw(0, REG_TRANSMITPTR);
        outw(priv->rx_head >> 8, REG_RECVEND);
@@ -287,10 +292,10 @@ static int ether3_init_2(struct device *dev)
        outw(priv->regs.command, REG_COMMAND);
 
        i = ether3_ramtest(dev, 0x5A);
-       if (i)
+       if(i)
                return i;
        i = ether3_ramtest(dev, 0x1E);
-       if (i)
+       if(i)
                return i;
 
        ether3_setbuffer(dev, buffer_write, 0);
@@ -298,29 +303,30 @@ static int ether3_init_2(struct device *dev)
        return 0;
 }
 
-static void ether3_init_for_open(struct device *dev)
+static void
+ether3_init_for_open(struct device *dev)
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
        int i;
 
        memset(&priv->stats, 0, sizeof(struct enet_statistics));
 
        priv->regs.command = 0;
-       outw(CMD_RXOFF | CMD_TXOFF, REG_COMMAND);
-       while (inw(REG_STATUS) & (STAT_RXON | STAT_TXON));
+       outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
+       while (inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
 
        outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
        for (i = 0; i < 6; i++)
                outb(dev->dev_addr[i], REG_BUFWIN);
 
-       priv->tx_used = 0;
-       priv->tx_head = 0;
-       priv->tx_tail = 0;
+       priv->tx_used   = 0;
+       priv->tx_head   = 0;
+       priv->tx_tail   = 0;
        priv->regs.config2 |= CFG2_CTRLO;
-       priv->rx_head = RX_START;
+       priv->rx_head   = RX_START;
 
        outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
-       outw((TX_END >> 8) - 1, REG_BUFWIN);
+       outw((TX_END>>8) - 1, REG_BUFWIN);
        outw(priv->rx_head, REG_RECVPTR);
        outw(priv->rx_head >> 8, REG_RECVEND);
        outw(0, REG_TRANSMITPTR);
@@ -337,20 +343,22 @@ static void ether3_init_for_open(struct device *dev)
 /*
  * This is the real probe routine.
  */
-static int ether3_probe1(struct device *dev)
+__initfunc(static int
+ether3_probe1(struct device *dev))
 {
        static unsigned version_printed = 0;
        struct dev_priv *priv;
        unsigned int i, bus_type, error = ENODEV;
 
-       if (net_debug && version_printed++ == 0)
+       if (net_debug  &&  version_printed++ == 0)
                printk(version);
 
        if (!dev->priv) {
-               dev->priv = kmalloc(sizeof(struct dev_priv), GFP_KERNEL);
+               dev->priv = kmalloc(sizeof (struct dev_priv), GFP_KERNEL);
                if (!dev->priv)
                        return -ENOMEM;
        }
+
        priv = (struct dev_priv *) dev->priv;
        memset(priv, 0, sizeof(struct dev_priv));
 
@@ -374,6 +382,7 @@ static int ether3_probe1(struct device *dev)
                else if (inw(REG_RECVPTR) == 0x101)
                        bus_type = BUS_16;
        }
+
        switch (bus_type) {
        case BUS_UNKNOWN:
                printk(KERN_ERR "%s: unable to identify podule bus width\n", dev->name);
@@ -407,7 +416,8 @@ static int ether3_probe1(struct device *dev)
 #endif
                        return 0;
        }
-      failed:
+
+failed:
        kfree(dev->priv);
        dev->priv = NULL;
        release_region(dev->base_addr, 128);
@@ -415,7 +425,8 @@ static int ether3_probe1(struct device *dev)
 }
 
 #ifndef MODULE
-int ether3_probe(struct device *dev)
+__initfunc(int
+ether3_probe(struct device *dev))
 {
        struct expansion_card *ec;
 
@@ -445,7 +456,8 @@ int ether3_probe(struct device *dev)
  * registers that "should" only need to be set once at boot, so that
  * there is non-reboot way to recover if something goes wrong.
  */
-static int ether3_open(struct device *dev)
+static int
+ether3_open(struct device *dev)
 {
        ether3_init_for_open(dev);
 
@@ -453,7 +465,7 @@ static int ether3_open(struct device *dev)
 
 #ifdef CLAIM_IRQ_AT_OPEN
        if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) {
-               MOD_DEC_USE_COUNT;
+               MOD_DEC_USE_COUNT;
                return -EAGAIN;
        }
 #endif
@@ -467,18 +479,19 @@ static int ether3_open(struct device *dev)
 /*
  * The inverse routine to ether3_open().
  */
-static int ether3_close(struct device *dev)
+static int
+ether3_close(struct device *dev)
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
        dev->tbusy = 1;
        dev->start = 0;
 
        disable_irq(dev->irq);
 
-       outw(CMD_RXOFF | CMD_TXOFF, REG_COMMAND);
+       outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
        priv->regs.command = 0;
-       while (inw(REG_STATUS) & (STAT_RXON | STAT_TXON));
+       while (inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
        outb(0x80, REG_CONFIG2 + 1);
        outw(0, REG_COMMAND);
 
@@ -492,12 +505,12 @@ static int ether3_close(struct device *dev)
 }
 
 /*
- * Get the current statistics.        This may be called with the card open or
+ * Get the current statistics. This may be called with the card open or
  * closed.
  */
 static struct enet_statistics *ether3_getstats(struct device *dev)
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
        return &priv->stats;
 }
 
@@ -509,14 +522,15 @@ static struct enet_statistics *ether3_getstats(struct device *dev)
  */
 static void ether3_setmulticastlist(struct device *dev)
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
        priv->regs.config1 &= ~CFG1_RECVPROMISC;
 
        if (dev->flags & IFF_PROMISC) {
                /* promiscuous mode */
                priv->regs.config1 |= CFG1_RECVPROMISC;
-       } else if (dev->flags & IFF_ALLMULTI) {
+       } else
+       if (dev->flags & IFF_ALLMULTI) {
                priv->regs.config1 |= CFG1_RECVSPECBRMULTI;
        } else
                priv->regs.config1 |= CFG1_RECVSPECBROAD;
@@ -527,15 +541,16 @@ static void ether3_setmulticastlist(struct device *dev)
 /*
  * Transmit a packet
  */
-static int ether3_sendpacket(struct sk_buff *skb, struct device *dev)
+static int
+ether3_sendpacket(struct sk_buff *skb, struct device *dev)
 {
-       struct dev_priv *priv = (struct dev_priv *) dev->priv;
-      retry:
+       struct dev_priv *priv = (struct dev_priv *)dev->priv;
+retry:
        if (!dev->tbusy) {
                /* Block a timer-based transmit from overlapping.  This could better be
                 * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
                 */
-               if (!test_and_set_bit(0, (void *) &dev->tbusy)) {
+               if (!test_and_set_bit(0, (void *)&dev->tbusy)) {
                        unsigned long flags;
                        unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
                        unsigned int ptr, nextptr;
@@ -543,17 +558,18 @@ static int ether3_sendpacket(struct sk_buff *skb, struct device *dev)
                        length = (length + 1) & ~1;
 
                        if (priv->broken) {
-                               dev_kfree_skb(skb, FREE_WRITE);
-                               priv->stats.tx_dropped++;
+                               dev_kfree_skb(skb);
+                               priv->stats.tx_dropped ++;
                                dev->tbusy = 0;
                                return 0;
                        }
+
                        ptr = priv->tx_head;
                        nextptr = ptr + 0x600;
                        if (nextptr >= TX_END)
                                nextptr = 0;
                        if (nextptr == priv->tx_tail)
-                               return 1;       /* unable to queue */
+                               return 1;               /* unable to queue */
                        priv->tx_head = nextptr;
 
                        save_flags_cli(flags);
@@ -562,13 +578,13 @@ static int ether3_sendpacket(struct sk_buff *skb, struct device *dev)
                        ether3_setbuffer(dev, buffer_write, ptr + 4);
                        ether3_writebuffer(dev, skb->data, length);
                        ether3_writeword(dev, htons(nextptr));
-                       ether3_writeword(dev, (TXHDR_TRANSMIT | TXHDR_CHAINCONTINUE) >> 16);
+                       ether3_writeword(dev, (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE) >> 16);
                        ether3_setbuffer(dev, buffer_write, ptr);
 #define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
                        ether3_writeword(dev, htons(ptr + length + 4));
                        ether3_writeword(dev, (TXHDR_FLAGS >> 16));
                        ether3_ledon(dev, priv);
-                       priv->tx_used++;
+                       priv->tx_used ++;
                        if (priv->tx_used < MAX_TX_BUFFERED)
                                dev->tbusy = 0;
                        if (priv->tx_used >= (MAX_TX_BUFFERED * 3 / 4)) {
@@ -578,7 +594,7 @@ static int ether3_sendpacket(struct sk_buff *skb, struct device *dev)
                        restore_flags(flags);
 
                        dev->trans_start = jiffies;
-                       dev_kfree_skb(skb, FREE_WRITE);
+                       dev_kfree_skb(skb);
                        if (!(inw(REG_STATUS) & STAT_TXON)) {
                                outw(ptr, REG_TRANSMITPTR);
                                outw(priv->regs.command | CMD_TXON, REG_COMMAND);
@@ -599,24 +615,25 @@ static int ether3_sendpacket(struct sk_buff *skb, struct device *dev)
                printk("%s: transmit timed out, network cable problem?\n", dev->name);
                dev->tbusy = 0;
                priv->regs.config2 |= CFG2_CTRLO;
-               outw(priv->regs.config2, REG_CONFIG2);
+               outw(priv->regs.config2 , REG_CONFIG2);
                dev->trans_start = jiffies;
                goto retry;
        }
 }
 
-static void ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void
+ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       struct device *dev = (struct device *) dev_id;
+       struct device *dev = (struct device *)dev_id;
        struct dev_priv *priv;
        unsigned int status;
 
 #if NET_DEBUG > 1
-       if (net_debug & DEBUG_INT)
+       if(net_debug & DEBUG_INT)
                printk("eth3irq: %d ", irq);
 #endif
 
-       priv = (struct dev_priv *) dev->priv;
+       priv = (struct dev_priv *)dev->priv;
 
        dev->interrupt = 1;
        status = inw(REG_STATUS);
@@ -625,12 +642,13 @@ static void ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * mostly empty, if we happen to get a RX interrupt, we might as
         * well handle the TX packets as well.
         */
-       if (status & STAT_INTTX) {      /* Packets transmitted */
+       if (status & STAT_INTTX) { /* Packets transmitted */
                outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);
                ether3_tx(dev, priv);
        }
+
        status = inw(REG_STATUS);
-       if (status & STAT_INTRX && ether3_rx(dev, priv, 12)) {  /* Got packet(s). */
+       if (status & STAT_INTRX && ether3_rx(dev, priv, 12)) { /* Got packet(s). */
                /*
                 * We only acknowledge the interrupt if we have received all packets
                 * in the buffer or else we run out of memory. This is to allow the
@@ -646,7 +664,7 @@ static void ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        dev->interrupt = 0;
 
 #if NET_DEBUG > 1
-       if (net_debug & DEBUG_INT)
+       if(net_debug & DEBUG_INT)
                printk("done\n");
 #endif
 }
@@ -654,7 +672,8 @@ static void ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 /*
  * If we have a good packet(s), get it/them out of the buffers.
  */
-static int ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int maxcnt)
+static int
+ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int maxcnt)
 {
        unsigned int next_ptr = priv->rx_head, received = 0;
        ether3_ledon(dev, priv);
@@ -681,16 +700,17 @@ static int ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int max
                        next_ptr = ntohs(temp_ptr);
                }
                ether3_setbuffer(dev, buffer_read, this_ptr);
-               ether3_readbuffer(dev, addrs + 2, 12);
+               ether3_readbuffer(dev, addrs+2, 12);
 
                /*
-                * ignore our own packets...
-                */
-               if (!(*(unsigned long *) &dev->dev_addr[0] ^ *(unsigned long *) &addrs[2 + 6]) &&
-                   !(*(unsigned short *) &dev->dev_addr[4] ^ *(unsigned short *) &addrs[2 + 10])) {
-                       maxcnt++;       /* compensate for loopedback packet */
+                * ignore our own packets...
+                */
+               if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) &&
+                   !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) {
+                       maxcnt ++; /* compensate for loopedback packet */
                        outw(next_ptr >> 8, REG_RECVEND);
-               } else if (!(status & (RXSTAT_OVERSIZE | RXSTAT_CRCERROR | RXSTAT_DRIBBLEERROR | RXSTAT_SHORTPACKET))) {
+               } else
+               if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) {
                        unsigned int length = next_ptr - this_ptr;
                        struct sk_buff *skb;
 
@@ -706,32 +726,28 @@ static int ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int max
                                buf = skb_put(skb, length);
                                ether3_readbuffer(dev, buf + 12, length - 12);
                                outw(next_ptr >> 8, REG_RECVEND);
-                               *(unsigned short *) (buf + 0) = *(unsigned short *) (addrs + 2);
-                               *(unsigned long *) (buf + 2) = *(unsigned long *) (addrs + 4);
-                               *(unsigned long *) (buf + 6) = *(unsigned long *) (addrs + 8);
-                               *(unsigned short *) (buf + 10) = *(unsigned short *) (addrs + 12);
+                               *(unsigned short *)(buf + 0)    = *(unsigned short *)(addrs + 2);
+                               *(unsigned long *)(buf + 2)     = *(unsigned long *)(addrs + 4);
+                               *(unsigned long *)(buf + 6)     = *(unsigned long *)(addrs + 8);
+                               *(unsigned short *)(buf + 10)   = *(unsigned short *)(addrs + 12);
                                skb->protocol = eth_type_trans(skb, dev);
                                netif_rx(skb);
-                               received++;
+                               received ++;
                        } else
                                goto dropping;
                } else {
                        struct enet_statistics *stats = &priv->stats;
                        outw(next_ptr >> 8, REG_RECVEND);
-                       if (status & RXSTAT_OVERSIZE)
-                               stats->rx_length_errors++;
-                       if (status & RXSTAT_CRCERROR)
-                               stats->rx_crc_errors++;
-                       if (status & RXSTAT_DRIBBLEERROR)
-                               stats->rx_fifo_errors++;
-                       if (status & RXSTAT_SHORTPACKET)
-                               stats->rx_length_errors++;
+                       if (status & RXSTAT_OVERSIZE)     stats->rx_length_errors ++;
+                       if (status & RXSTAT_CRCERROR)     stats->rx_crc_errors ++;
+                       if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++;
+                       if (status & RXSTAT_SHORTPACKET)  stats->rx_length_errors ++;
                        stats->rx_errors++;
                }
        }
-       while (--maxcnt);
+       while (-- maxcnt);
 
-      done:
+done:
        priv->stats.rx_packets += received;
        priv->rx_head = next_ptr;
        /*
@@ -739,42 +755,44 @@ static int ether3_rx(struct device *dev, struct dev_priv *priv, unsigned int max
         * have dropped at least one packet.
         */
        if (!(inw(REG_STATUS) & STAT_RXON)) {
-               priv->stats.rx_dropped++;
-               outw(next_ptr, REG_RECVPTR);
+               priv->stats.rx_dropped ++;
+               outw(next_ptr, REG_RECVPTR);
                outw(priv->regs.command | CMD_RXON, REG_COMMAND);
        }
+
        return maxcnt;
 
-      dropping:{
-               static unsigned long last_warned;
+dropping:{
+       static unsigned long last_warned;
 
-               outw(next_ptr >> 8, REG_RECVEND);
-               /*
-                * Don't print this message too many times...
-                */
-               if (jiffies - last_warned > 30 * HZ) {
-                       last_warned = jiffies;
-                       printk("%s: memory squeeze, dropping packet.\n", dev->name);
-               }
-               priv->stats.rx_dropped++;
-               goto done;
+       outw(next_ptr >> 8, REG_RECVEND);
+       /*
+        * Don't print this message too many times...
+        */
+       if (jiffies - last_warned > 30 * HZ) {
+               last_warned = jiffies;
+               printk("%s: memory squeeze, dropping packet.\n", dev->name);
+       }
+       priv->stats.rx_dropped ++;
+       goto done;
        }
 }
 
 /*
  * Update stats for the transmitted packet(s)
  */
-static void ether3_tx(struct device *dev, struct dev_priv *priv)
+static void
+ether3_tx(struct device *dev, struct dev_priv *priv)
 {
        unsigned int tx_tail = priv->tx_tail;
 
        do {
-               unsigned long status;
-               /*
-                * Read the packet header
-                */
-               ether3_setbuffer(dev, buffer_read, tx_tail);
-               status = ether3_readlong(dev);
+               unsigned long status;
+               /*
+                * Read the packet header
+                */
+               ether3_setbuffer(dev, buffer_read, tx_tail);
+               status = ether3_readlong(dev);
 
                /*
                 * Check to see if this packet has been transmitted
@@ -788,11 +806,9 @@ static void ether3_tx(struct device *dev, struct dev_priv *priv)
                if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
                        priv->stats.tx_packets++;
                else {
-                       priv->stats.tx_errors++;
-                       if (status & TXSTAT_16COLLISIONS)
-                               priv->stats.collisions += 16;
-                       if (status & TXSTAT_BABBLED)
-                               priv->stats.tx_fifo_errors++;
+                       priv->stats.tx_errors ++;
+                       if (status & TXSTAT_16COLLISIONS) priv->stats.collisions += 16;
+                       if (status & TXSTAT_BABBLED) priv->stats.tx_fifo_errors ++;
                }
 
                /*
@@ -824,11 +840,12 @@ char ethernames[MAX_ECARDS][9];
 static struct device *my_ethers[MAX_ECARDS];
 static struct expansion_card *ec[MAX_ECARDS];
 
-int init_module(void)
+int
+init_module(void)
 {
        int i;
 
-       for (i = 0; i < MAX_ECARDS; i++) {
+       for(i = 0; i < MAX_ECARDS; i++) {
                my_ethers[i] = NULL;
                ec[i] = NULL;
                strcpy(ethernames[i], "        ");
@@ -842,11 +859,11 @@ int init_module(void)
                if ((ec[i] = ecard_find(0, ether3_cids)) == NULL)
                        break;
 
-               my_ethers[i] = (struct device *) kmalloc(sizeof(struct device), GFP_KERNEL);
+               my_ethers[i] = (struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);
                memset(my_ethers[i], 0, sizeof(struct device));
 
                my_ethers[i]->irq = ec[i]->irq;
-               my_ethers[i]->base_addr = ecard_address(ec[i], ECARD_MEMC, 0);
+               my_ethers[i]->base_addr= ecard_address(ec[i], ECARD_MEMC, 0);
                my_ethers[i]->init = ether3_probe1;
                my_ethers[i]->name = ethernames[i];
 
@@ -854,13 +871,13 @@ int init_module(void)
 
                ecard_claim(ec[i]);
 
-               if (register_netdev(my_ethers[i]) != 0) {
+               if(register_netdev(my_ethers[i]) != 0) {
                        for (i = 0; i < 4; i++) {
-                               if (my_ethers[i]) {
+                               if(my_ethers[i]) {
                                        kfree(my_ethers[i]);
                                        my_ethers[i] = NULL;
                                }
-                               if (ec[i]) {
+                               if(ec[i]) {
                                        ecard_release(ec[i]);
                                        ec[i] = NULL;
                                }
@@ -869,28 +886,25 @@ int init_module(void)
                }
                i++;
        }
-       while (i < MAX_ECARDS);
+       while(i < MAX_ECARDS);
 
        return i != 0 ? 0 : -ENODEV;
 }
 
-void cleanup_module(void)
+void
+cleanup_module(void)
 {
-       if (MOD_IN_USE) {
-               printk("ether3: device busy, remove delayed\n");
-       } else {
-               int i;
-               for (i = 0; i < MAX_ECARDS; i++) {
-                       if (my_ethers[i]) {
-                               release_region(my_ethers[i]->base_addr, 128);
-                               unregister_netdev(my_ethers[i]);
-                               my_ethers[i] = NULL;
-                       }
-                       if (ec[i]) {
-                               ecard_release(ec[i]);
-                               ec[i] = NULL;
-                       }
+       int i;
+       for (i = 0; i < MAX_ECARDS; i++) {
+               if (my_ethers[i]) {
+                       release_region(my_ethers[i]->base_addr, 128);
+                       unregister_netdev(my_ethers[i]);
+                       my_ethers[i] = NULL;
+               }
+               if (ec[i]) {
+                       ecard_release(ec[i]);
+                       ec[i] = NULL;
                }
        }
 }
-#endif                         /* MODULE */
+#endif /* MODULE */
index b68d382fea0e9b012a9597ad00fcc23352bbd184..8f98706519b311e8929be7bdc9c18c7eaaec4062 100644 (file)
@@ -41,7 +41,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "8390.h"
+#include "../../net/8390.h"
 
 #define NET_DEBUG  0
 #define DEBUG_INIT 2
index 9bdc594e6e54d823a7328de6e0d2aa5f0e982ea8..1dec519304735c0debde48574653313bed170ce1 100644 (file)
  */
 
 /*
- * $Log: cumana_NCR5380.c,v $
+ * $Log: cumana_1.c,v $
+ * Revision 1.2  1998/03/08 05:49:46  davem
+ * Merge to 2.1.89
+ *
+ * Revision 1.1  1998/02/23 02:45:22  davem
+ * Merge to 2.1.88
+ *
  */
 
 #include <linux/module.h>
index 55fcc18087f28964e94ba18138353806960f8740..447ce374488345b6448d532584c86847475faade 100644 (file)
  */
 
 /*
- * $Log: cumana_NCR5380.h,v $
+ * $Log: cumana_1.h,v $
+ * Revision 1.1  1998/02/23 02:45:22  davem
+ * Merge to 2.1.88
+ *
  */
 
 #ifndef CUMANA_NCR5380_H
index 1bdcf9d59185ea9f47e114459223dd8246946332..ca048138c7e6b51ca771a76766a85d07213d3267 100644 (file)
@@ -114,7 +114,7 @@ cumanascsi_2_dma_pseudo (struct Scsi_Host *instance, Scsi_Pointer *SCp,
            unsigned long word;
 
 
-           if (inb (REG0_STATUS(&info->info)) & STATUS_INT)
+           if (inb (REG_STAT(&info->info)) & STAT_INT)
                goto end;
 
            if (!(inb (info->cstatus) & CSTATUS_DRQ))
@@ -131,7 +131,7 @@ cumanascsi_2_dma_pseudo (struct Scsi_Host *instance, Scsi_Pointer *SCp,
     else {
        if (transfer && (transfer & 255)) {
            while (length >= 256) {
-               if (inb (REG0_STATUS(&info->info)) & STATUS_INT)
+               if (inb (REG_STAT(&info->info)) & STAT_INT)
                    goto end;
            
                if (!(inb (info->cstatus) & CSTATUS_DRQ))
@@ -146,7 +146,7 @@ cumanascsi_2_dma_pseudo (struct Scsi_Host *instance, Scsi_Pointer *SCp,
        while (length > 0) {
            unsigned long word;
 
-           if (inb (REG0_STATUS(&info->info)) & STATUS_INT)
+           if (inb (REG_STAT(&info->info)) & STAT_INT)
                goto end;
            
            if (!(inb (info->cstatus) & CSTATUS_DRQ))
index 6a3cd75eeed1a3f636d81706d3c7ce2767c4acd6..9346ed4f86eead926ff4d449a51c1da9f602f0f8 100644 (file)
  */
 
 /*
- * $Log: ecoscsi_NCR5380.c,v $
+ * $Log: ecoscsi.c,v $
+ * Revision 1.2  1998/03/08 05:49:47  davem
+ * Merge to 2.1.89
+ *
+ * Revision 1.1  1998/02/23 02:45:24  davem
+ * Merge to 2.1.88
+ *
  */
 
 #include <linux/module.h>
index ac098c9d3817f8fb2f4f4e422d0406ca3baadfb4..17a349173e67a66609da8c3ade19d83e90029ced 100644 (file)
  */
 
 /*
- * $Log: ecoscsi_NCR5380.h,v $
+ * $Log: ecoscsi.h,v $
+ * Revision 1.1  1998/02/23 02:45:24  davem
+ * Merge to 2.1.88
+ *
  */
 
 #ifndef ECOSCSI_NCR5380_H
index c05d89cbe900098f0b368e60726cc71bed717957..eb609393e8b992fc0eea252497ccf3fb9a56df11 100644 (file)
@@ -37,8 +37,8 @@
 
 #define FAS216_C
 
-#include "scsi.h"
-#include "hosts.h"
+#include "../../scsi/scsi.h"
+#include "../../scsi/hosts.h"
 #include "fas216.h"
 
 #define VER_MAJOR      0
@@ -104,7 +104,7 @@ static int fas216_syncperiod(FAS216_Info *info, int ns)
 
        if (value < 4)
                value = 4;
-       else if value > 35)
+       else if (value > 35)
                value = 35;
 
        return value & 31;
@@ -1269,6 +1269,46 @@ static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2,
                *SCpntp2 = NULL;
 }
 
+/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
+ * Purpose : abort this command
+ * Params  : SCpnt - command to abort
+ * Returns : FAILED if unable to abort
+ */
+int fas216_eh_abort(Scsi_Cmnd *SCpnt)
+{
+       return FAILED;
+}
+
+/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the device associated with this command
+ * Params  : SCpnt - command specifing device to reset
+ * Returns : FAILED if unable to reset
+ */
+int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
+{
+       return FAILED;
+}
+
+/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the complete bus associated with this command
+ * Params  : SCpnt - command specifing bus to reset
+ * Returns : FAILED if unable to reset
+ */
+int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
+{
+       return FAILED;
+}
+
+/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the host associated with this command
+ * Params  : SCpnt - command specifing host to reset
+ * Returns : FAILED if unable to reset
+ */
+int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
+{
+       return FAILED;
+}
+
 /* Function: int fas216_abort (Scsi_Cmnd *SCpnt)
  * Purpose : abort a command if something horrible happens.
  * Params  : SCpnt - Command that is believed to be causing a problem.
@@ -1352,7 +1392,7 @@ static void fas216_reset_state(FAS216_Info *info)
 #else
                info->device[i].disconnect_ok = 0;
 #endif
-               info->device[i].stp = fas216_syncperiod(info->ifcfg.asyncperiod);
+               info->device[i].stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
                info->device[i].sof = 0;
 #ifdef SCSI2SYNC
                info->device[i].negstate = syncneg_start;
@@ -1374,7 +1414,7 @@ static void fas216_init_chip(FAS216_Info *info)
        outb(info->scsi.cfg[2], REG_CNTL3(info));
        outb(info->ifcfg.select_timeout, REG_STIM(info));
        outb(0, REG_SOF(info));
-       outb(fas216_syncperiod(info->ifcfg.asyncperiod), REG_STP(info));
+       outb(fas216_syncperiod(info, info->ifcfg.asyncperiod), REG_STP(info));
        outb(info->scsi.cfg[0], REG_CNTL1(info));
 }
 
@@ -1465,7 +1505,7 @@ int fas216_init (struct Scsi_Host *instance)
        info->host = instance;
        info->scsi.cfg[0] = instance->this_id;
        info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;
-       info->scsi.cfg[2] = CNTL3_ADDIDCHK | CNTL3_G2CB | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+       info->scsi.cfg[2] = CNTL3_ADIDCHK | CNTL3_G2CB | CNTL3_FASTSCSI | CNTL3_FASTCLK;
        info->scsi.type = "unknown";
        info->SCpnt = NULL;
        fas216_reset_state(info);
@@ -1500,7 +1540,7 @@ int fas216_init (struct Scsi_Host *instance)
        }
 
 
-       outb(CNTL3_IDENABLE, REG_CNTL3(info));
+       outb(CNTL3_ADIDCHK, REG_CNTL3(info));
        outb(0, REG_CNTL3(info));
 
        outb(CMD_RESETCHIP, REG_CMD(info));
@@ -1562,6 +1602,11 @@ EXPORT_SYMBOL(fas216_queue_command);
 EXPORT_SYMBOL(fas216_command);
 EXPORT_SYMBOL(fas216_intr);
 EXPORT_SYMBOL(fas216_release);
+EXPORT_SYMBOL(fas216_eh_abort);
+EXPORT_SYMBOL(fas216_eh_device_reset);
+EXPORT_SYMBOL(fas216_eh_bus_reset);
+EXPORT_SYMBOL(fas216_eh_host_reset);
+
 
 #ifdef MODULE
 int init_module (void)
index 3dc8020319576b2f19b705cd37fe96e195d3d137..f88eb83d7e53b7ab2e64d99a1dcf9bc65c6998c1 100644 (file)
@@ -196,7 +196,7 @@ typedef enum {
 typedef enum {
        syncneg_start,                                  /* Negociate with device for Sync xfers */
        syncneg_sent,                                   /* Sync Xfer negociation sent           */
-       syncnsg_complete                                /* Sync Xfer complete                   */
+       syncneg_complete                                /* Sync Xfer complete                   */
 } syncneg_t;
 
 typedef struct {
@@ -277,81 +277,82 @@ typedef struct {
        int                     internal_done;          /* flag to indicate request done */
 } FAS216_Info;
 
-/*
- * Function: int fas216_init (struct Scsi_Host *instance)
- *
+/* Function: int fas216_init (struct Scsi_Host *instance)
  * Purpose : initialise FAS/NCR/AMD SCSI ic.
- *
  * Params  : instance - a driver-specific filled-out structure
- *
  * Returns : 0 on success
  */
 extern int fas216_init (struct Scsi_Host *instance);
 
-/*
- * Function: int fas216_abort (Scsi_Cmnd *SCpnt)
- *
+/* Function: int fas216_abort (Scsi_Cmnd *SCpnt)
  * Purpose : abort a command if something horrible happens.
- *
  * Params  : SCpnt - Command that is believed to be causing a problem.
- *
  * Returns : one of SCSI_ABORT_ macros.
  */
 extern int fas216_abort (Scsi_Cmnd *);
 
-/*
- * Function: int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
- *
+/* Function: int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  * Purpose : resets the adapter if something horrible happens.
- *
  * Params  : SCpnt - Command that is believed to be causing a problem.
  *          reset_flags - flags indicating reset type that is believed to be required.
- *
  * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET macros.
  */
 extern int fas216_reset (Scsi_Cmnd *, unsigned int);
 
-/*
- * Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
- *
+/* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
  * Purpose : queue a command for adapter to process.
- *
  * Params  : SCpnt - Command to queue
  *          done  - done function to call once command is complete
- *
  * Returns : 0 - success, else error
  */
 extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 
-/*
- * Function: int fas216_command (Scsi_Cmnd *SCpnt)
- *
+/* Function: int fas216_command (Scsi_Cmnd *SCpnt)
  * Purpose : queue a command for adapter to process.
- *
  * Params  : SCpnt - Command to queue
- *
  * Returns : scsi result code
  */
 extern int fas216_command (Scsi_Cmnd *);
 
-/*
- * Function: void fas216_intr (struct Scsi_Host *instance)
- *
+/* Function: void fas216_intr (struct Scsi_Host *instance)
  * Purpose : handle interrupts from the interface to progress a command
- *
  * Params  : instance - interface to service
  */
 extern void fas216_intr (struct Scsi_Host *instance);
 
-/*
- * Function: int fas216_release (struct Scsi_Host *instance)
- *
+/* Function: int fas216_release (struct Scsi_Host *instance)
  * Purpose : release all resources and put everything to bed for FAS/NCR/AMD SCSI ic.
- *
  * Params  : instance - a driver-specific filled-out structure
- *
  * Returns : 0 on success
  */
 extern int fas216_release (struct Scsi_Host *instance);
 
+/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt)
+ * Purpose : abort this command
+ * Params  : SCpnt - command to abort
+ * Returns : FAILED if unable to abort
+ */
+extern int fas216_eh_abort(Scsi_Cmnd *SCpnt);
+
+/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the device associated with this command
+ * Params  : SCpnt - command specifing device to reset
+ * Returns : FAILED if unable to reset
+ */
+extern int fas216_eh_device_reset(Scsi_Cmnd *SCpnt);
+
+/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the complete bus associated with this command
+ * Params  : SCpnt - command specifing bus to reset
+ * Returns : FAILED if unable to reset
+ */
+extern int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt);
+
+/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
+ * Purpose : Reset the host associated with this command
+ * Params  : SCpnt - command specifing host to reset
+ * Returns : FAILED if unable to reset
+ */
+extern int fas216_eh_host_reset(Scsi_Cmnd *SCpnt);
+
 #endif /* FAS216_H */
index 6addfd3314f666692987ab124ab2b5fcf3ca01be..54763f9ec2c17d9b02c502aa0936faffbc7e0f4e 100644 (file)
 
 /*
  * $Log: oak.c,v $
+ * Revision 1.2  1998/03/08 05:49:48  davem
+ * Merge to 2.1.89
+ *
+ * Revision 1.1  1998/02/23 02:45:27  davem
+ * Merge to 2.1.88
+ *
  */
 
 #include <linux/module.h>
index 290e39ed15ada7efc1ed82ff47970e6ac96a7c47..eeea25a72ce1008ac2f766f67a8240f6cd884644 100644 (file)
  */
 
 /*
- * $Log: oak_NCR5380.h,v $
+ * $Log: oak.h,v $
+ * Revision 1.1  1998/02/23 02:45:27  davem
+ * Merge to 2.1.88
+ *
  */
 
 #ifndef OAK_NCR5380_H
index 36b72b298317bc7dc63128edfca5ad4bb2cb93ef..203d81f1779e0c9a9022bc8ef8ef1d6c3a600ea9 100644 (file)
@@ -53,7 +53,13 @@ can_queue:   CAN_QUEUE,              /* can queue            */      \
 this_id:       SCSI_ID,                /* scsi host id         */      \
 sg_tablesize:  SG_ALL,                 /* sg_tablesize         */      \
 cmd_per_lun:   CMD_PER_LUN,            /* cmd per lun          */      \
-use_clustering:        ENABLE_CLUSTERING                                       \
+use_clustering:        ENABLE_CLUSTERING,                                      \
+eh_strategy_handler:           NULL,                                   \
+eh_host_reset_handler:         fas216_eh_host_reset,                   \
+eh_bus_reset_handler:          fas216_eh_bus_reset,                    \
+eh_device_reset_handler:       fas216_eh_device_reset,                 \
+eh_abort_handler:              fas216_eh_abort,                        \
+use_new_eh_code:               0                                       \
        }
 
 #ifndef HOSTS_C
index b1663d5e32c4c9f38f2d86cc704a4f76d0a7678e..60ad885b8819c6504376965f697722b4ee443385 100644 (file)
@@ -254,11 +254,13 @@ parse_error:
 static int proc_ide_read_config
        (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-       ide_hwif_t      *hwif = (ide_hwif_t *)data;
        char            *out = page;
-       int             len, reg = 0;
+       int             len;
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
+       ide_hwif_t      *hwif = (ide_hwif_t *)data;
+       int             reg = 0;
+
        struct pci_dev *dev = hwif->pci_dev;
 
        out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
index de922c74869f3b411253c6675e60b61e88f2e154..bfd6c4e5faf800e059603e1781b92b93781e19b0 100644 (file)
@@ -117,6 +117,13 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
     dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV
   fi
   dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
+  #dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
+  if [ "$CONFIG_VIDEO_SAA5249" != "n" ]; then
+       define_bool CONFIG_BUS_I2C $CONFIG_VIDEO_SAA5249
+  fi
+  if [ "$CONFIG_VIDEO_BT848" != "n" ]; then
+       define_bool CONFIG_BUS_I2C $CONFIG_VIDEO_BT848
+  fi
 fi
 tristate '/dev/nvram support' CONFIG_NVRAM
 tristate 'PC joystick support' CONFIG_JOYSTICK
index 76f21edfd32b658cdee3ea24bb815d8cf9ef3f9f..020f03cd7bffef6c3cb2444887c0be4e796ccee3 100644 (file)
@@ -302,11 +302,27 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_BUS_I2C),y)
+       LX_OBJS += i2c.o
+else
+  ifeq ($(CONFIG_BUS_I2C),m)
+       MX_OBJS += i2c.o
+  endif
+endif
+
 ifeq ($(CONFIG_VIDEO_BT848),y)
-L_OBJS += bttv.o
+L_OBJS += bttv.o msp3400.o tuner.o
 else
   ifeq ($(CONFIG_VIDEO_BT848),m)
-    M_OBJS += bttv.o
+    M_OBJS += bttv.o msp3400.o tuner.o
+  endif
+endif
+
+ifeq ($(CONFIG_VIDEO_SAA5249),y)
+L_OBJS += saa5249.o
+else
+  ifeq ($(CONFIG_VIDEO_SAA5249),m)
+    M_OBJS += saa5249.o
   endif
 endif
 
@@ -330,7 +346,7 @@ ifeq ($(CONFIG_VIDEO_PMS),y)
 L_OBJS += pms.o
 else
   ifeq ($(CONFIG_VIDEO_PMS),m)
-    M_OBJS += pms.o
+  M_OBJS += pms.o
   endif
 endif
 
index 2171a157473a7a5681e765e0c860bbc784930cad..5a76ea02adbce62e326e6f49614a9f34130c9cdf 100644 (file)
@@ -1,7 +1,7 @@
 /* 
     bt848.h - Bt848 register offsets
 
-    Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
+    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 #define _BT848_H_
 
 #ifndef PCI_VENDOR_ID_BROOKTREE
-#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#define PCI_VENDOR_ID_BROOKTREE 0x109e 
 #endif
 #ifndef PCI_DEVICE_ID_BT848
-#define PCI_DEVICE_ID_BT848     0x350
+#define PCI_DEVICE_ID_BT848     0x350  
+#endif
+#ifndef PCI_DEVICE_ID_BT849
+#define PCI_DEVICE_ID_BT849     0x351
 #endif
 
-#define RISCMEM_LEN 131040
 
 /* Brooktree 848 registers */
 
index db2a49b17d1b98ec7953a44889003d83e2708f5a..e61d6361c9b313e2adaca0fca761b4e2bcbfaa50 100644 (file)
@@ -1,7 +1,8 @@
 /* 
     bttv - Bt848 frame grabber driver
 
-    Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+                           & Marcus Metzler (mocm@thp.uni-koeln.de)
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     Modified to put the RISC code writer in the kernel and to fit a
     common (and I hope safe) kernel interface. When we have an X extension
     all will now be really sweet.
+    TODO:  
+   
+    * think of some good ioctls for Video4Linux to handle 
+      YUV, planar YUV, ...  grabs and sell them to AC :-)
+    * move norm from tuner to channel struct!?
+      composite source from a satellite tuner can deliver different norms
+      depending on tuned channel
+    * mmap VBI data?
 */
 
 #include <linux/module.h>
 #include <linux/bios32.h>
+#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <asm/segment.h>
 #include <linux/types.h>
-#include <linux/videodev.h>
+#include <linux/wrapper.h>
 
+#include <linux/videodev.h>
 #include <linux/version.h>
 #include <asm/uaccess.h>
 
+#include "i2c.h"
 #include "bttv.h"
 #include "tuner.h"
 
 #define DEBUG(x)               /* Debug driver */      
-#define IDEBUG(x)              /* Debug interrupt handler */
+#define IDEBUG(x)              /* Debug interrupt handler */
+
+static unsigned int remap=0;    /* remap Bt848 */
+static unsigned int vidmem=0;   /* manually set video mem address */
+static int triton1=0;
+static int radio=0;
 
-static unsigned int remap=0;
-static unsigned int vidmem=0;
-static unsigned int tuner=0;   /* Default tuner */
-MODULE_PARM(tuner,"i");
+static unsigned int card=0;
+
+MODULE_PARM(remap,"i");
+MODULE_PARM(vidmem,"i");
+MODULE_PARM(triton1,"i");
+MODULE_PARM(radio,"i");
+MODULE_PARM(card,"i");
 
 static int find_vga(void);
 static void bt848_set_risc_jmps(struct bttv *btv);
@@ -61,17 +82,21 @@ static void bt848_set_risc_jmps(struct bttv *btv);
 /* Anybody who uses more than four? */
 #define BTTV_MAX 4
 
-static int bttv_num;
+static int bttv_num;                   /* number of Bt848s in use */
 static struct bttv bttvs[BTTV_MAX];
 
 #define I2C_TIMING (0x7<<4)
 #define I2C_COMMAND (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA)
 
+#define I2C_DELAY   10
+#define I2C_SET(CTRL,DATA) \
+    { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
+#define I2C_GET()   (btread(BT848_I2C)&1)
+
 #define AUDIO_MUTE_DELAY 10000
 #define FREQ_CHANGE_DELAY 20000
 #define EEPROM_WRITE_DELAY 20000
 
-
 /*******************************/
 /* Memory management functions */
 /*******************************/
@@ -79,56 +104,137 @@ static struct bttv bttvs[BTTV_MAX];
 /* convert virtual user memory address to physical address */
 /* (virt_to_phys only works for kmalloced kernel memory) */
 
-static inline ulong uvirt_to_phys(ulong adr)
+static inline unsigned long uvirt_to_phys(unsigned long adr)
 {
        pgd_t *pgd;
        pmd_t *pmd;
        pte_t *ptep, pte;
   
-/*  printk("adr: 0x%08x\n",adr);*/
        pgd = pgd_offset(current->mm, adr);
-/*  printk("pgd: 0x%08x\n",pgd);*/
        if (pgd_none(*pgd))
                return 0;
        pmd = pmd_offset(pgd, adr);
-/*  printk("pmd: 0x%08x\n",pmd); */
        if (pmd_none(*pmd))
                return 0;
-       ptep = pte_offset(pmd, adr&(~PGDIR_MASK));
+       ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);
        pte = *ptep;
        if(pte_present(pte))
-               return (pte_page(pte)|(adr&(PAGE_SIZE-1)));
+               return 
+                 virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));
        return 0;
 }
 
+static inline unsigned long uvirt_to_bus(unsigned long adr) 
+{
+       /*  printk("adr: 0x%8x, ",adr);
+       printk("phys: 0x%8x, ",(uvirt_to_phys(adr)));
+       printk("bus: 0x%8x\n",virt_to_bus(phys_to_virt(uvirt_to_phys(adr))));
+       */
+       return virt_to_bus(phys_to_virt(uvirt_to_phys(adr)));
+}
+
 /* convert virtual kernel memory address to physical address */
 /* (virt_to_phys only works for kmalloced kernel memory) */
 
-static inline ulong kvirt_to_phys(ulong adr) 
+static inline unsigned long kvirt_to_phys(unsigned long adr) 
 {
        return uvirt_to_phys(VMALLOC_VMADDR(adr));
 }
 
-static inline ulong kvirt_to_bus(ulong adr) 
+static inline unsigned long kvirt_to_bus(unsigned long adr) 
 {
-       return virt_to_bus(phys_to_virt(kvirt_to_phys(adr)));
+       return uvirt_to_bus(VMALLOC_VMADDR(adr));
 }
 
+static void * rvmalloc(unsigned long size)
+{
+       void * mem;
+       unsigned long adr, page;
+        
+       mem=vmalloc(size);
+       if (mem) 
+       {
+               adr=(unsigned long) mem;
+               while (size > 0) 
+                {
+                       page = kvirt_to_phys(adr);
+                       mem_map_reserve(MAP_NR(phys_to_virt(page)));
+                       adr+=PAGE_SIZE;
+                       size-=PAGE_SIZE;
+               }
+       }
+       return mem;
+}
 
-/*****************/
-/* I2C functions */
-/*****************/
+static void rvfree(void * mem, unsigned long size)
+{
+        unsigned long adr, page;
+        
+       if (mem) 
+       {
+               adr=(unsigned long) mem;
+               while (size > 0) 
+                {
+                       page = kvirt_to_phys(adr);
+                       mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+                       adr+=PAGE_SIZE;
+                       size-=PAGE_SIZE;
+               }
+               vfree(mem);
+       }
+}
 
-static int I2CRead(struct bttv *btv, int addr)
+/*
+ *     Create the giant waste of buffer space we need for now
+ *     until we get DMA to user space sorted out (probably 2.3.x)
+ *
+ *     We only create this as and when someone uses mmap
+ */
+static int fbuffer_alloc(struct bttv *btv)
+{
+       if(!btv->fbuffer)
+               btv->fbuffer=(unsigned char *) rvmalloc(2*0x144000);
+       else
+               printk(KERN_ERR "bttv: Double alloc of fbuffer!\n");
+       if(!btv->fbuffer)
+               return -ENOBUFS;
+       return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions                                                           */
+
+/* software I2C functions */
+
+static void i2c_setlines(struct i2c_bus *bus,int ctrl,int data)
+{
+        struct bttv *btv = (struct bttv*)bus->data;
+       btwrite((ctrl<<1)|data, BT848_I2C);
+       udelay(I2C_DELAY);
+}
+
+static int i2c_getdataline(struct i2c_bus *bus)
+{
+        struct bttv *btv = (struct bttv*)bus->data;
+       return btread(BT848_I2C)&1;
+}
+
+/* hardware I2C functions */
+
+/* read I2C */
+static int I2CRead(struct i2c_bus *bus, unsigned char addr) 
 {
        u32 i;
        u32 stat;
+       struct bttv *btv = (struct bttv*)bus->data;
   
        /* clear status bit ; BT848_INT_RACK is ro */
        btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
   
        btwrite(((addr & 0xff) << 24) | I2C_COMMAND, BT848_I2C);
-
+  
        /*
         * Timeout for I2CRead is 1 second (this should be enough, really!)
         */
@@ -136,11 +242,12 @@ static int I2CRead(struct bttv *btv, int addr)
        {
                stat=btread(BT848_INT_STAT);
                if (stat & BT848_INT_I2CDONE)
-                       break;
-               udelay(1000); /* 1ms, as I2C is 1kHz (?) */
+                        break;
+                udelay(1000);
        }
   
-       if (!i) {
+       if (!i) 
+       {
                printk(KERN_DEBUG "bttv: I2CRead timeout\n");
                return -1;
        }
@@ -153,12 +260,13 @@ static int I2CRead(struct bttv *btv, int addr)
 
 /* set both to write both bytes, reset it to write only b1 */
 
-static int I2CWrite(struct bttv *btv, unchar addr, unchar b1,
-                   unchar b2, int both)
+static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1,
+                   unsigned char b2, int both)
 {
        u32 i;
        u32 data;
        u32 stat;
+       struct bttv *btv = (struct bttv*)bus->data;
   
        /* clear status bit; BT848_INT_RACK is ro */
        btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
@@ -172,15 +280,16 @@ static int I2CWrite(struct bttv *btv, unchar addr, unchar b1,
   
        btwrite(data, BT848_I2C);
 
-       for (i=1000; i; i--)
+       for (i=0x1000; i; i--)
        {
                stat=btread(BT848_INT_STAT);
                if (stat & BT848_INT_I2CDONE)
                        break;
-               udelay(1000);
+                udelay(1000);
        }
   
-       if (!i) {
+       if (!i) 
+       {
                printk(KERN_DEBUG "bttv: I2CWrite timeout\n");
                return -1;
        }
@@ -190,19 +299,20 @@ static int I2CWrite(struct bttv *btv, unchar addr, unchar b1,
        return 0;
 }
 
-static void readee(struct bttv *btv, unchar *eedata)
+/* read EEPROM */
+static void readee(struct i2c_bus *bus, unsigned char *eedata)
 {
        int i, k;
-  
-       if (I2CWrite(btv, 0xa0, 0, -1, 0)<0)
+        
+       if (I2CWrite(bus, 0xa0, 0, -1, 0)<0)
        {
                printk(KERN_WARNING "bttv: readee error\n");
                return;
        }
-
+        
        for (i=0; i<256; i++)
        {
-               k=I2CRead(btv, 0xa1);
+               k=I2CRead(bus, 0xa1);
                if (k<0)
                {
                        printk(KERN_WARNING "bttv: readee error\n");
@@ -212,13 +322,14 @@ static void readee(struct bttv *btv, unchar *eedata)
        }
 }
 
-static void writeee(struct bttv *btv, unchar *eedata)
+/* write EEPROM */
+static void writeee(struct i2c_bus *bus, unsigned char *eedata)
 {
        int i;
   
        for (i=0; i<256; i++)
        {
-               if (I2CWrite(btv, 0xa0, i, eedata[i], 1)<0)
+               if (I2CWrite(bus, 0xa0, i, eedata[i], 1)<0)
                {
                        printk(KERN_WARNING "bttv: writeee error (%d)\n", i);
                        break;
@@ -227,28 +338,91 @@ static void writeee(struct bttv *btv, unchar *eedata)
        }
 }
 
+void attach_inform(struct i2c_bus *bus, int id)
+{
+        struct bttv *btv = (struct bttv*)bus->data;
+       int tunertype;
+        
+       switch (id) 
+        {
+               case I2C_DRIVERID_MSP3400:
+                       btv->have_msp3400 = 1;
+                       break;
+               case I2C_DRIVERID_TUNER:
+                       btv->have_tuner = 1;
+                       if (btv->type == BTTV_MIRO) 
+                       {
+                               tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+                               i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
+                                       TUNER_SET_TYPE,&tunertype);
+                       }
+                       break;
+       }
+}
+
+void detach_inform(struct i2c_bus *bus, int id)
+{
+        struct bttv *btv = (struct bttv*)bus->data;
+
+       switch (id) 
+       {
+               case I2C_DRIVERID_MSP3400:
+                       btv->have_msp3400 = 0;
+                       break;
+               case I2C_DRIVERID_TUNER:
+                       btv->have_tuner = 0;
+                       break;
+       }
+}
+
+static struct i2c_bus bttv_i2c_bus_template = 
+{
+        "bt848",
+        I2C_BUSID_BT848,
+       NULL,
+
+       SPIN_LOCK_UNLOCKED,
+
+       attach_inform,
+       detach_inform,
+       
+       i2c_setlines,
+       i2c_getdataline,
+       I2CRead,
+       I2CWrite,
+};
+/* ----------------------------------------------------------------------- */
+
 /*
- *     Tuner, internal, external and mute 
+ *     Tuner, Radio, internal, external and mute 
  */
  
-static unchar audiomuxs[][4] = 
-{
-       { 0x00, 0x00, 0x00, 0x00}, /* unknown */
-       { 0x02, 0x00, 0x00, 0x0a}, /* MIRO */
-       { 0x00, 0x02, 0x03, 0x04}, /* Hauppauge */
-       { 0x04, 0x02, 0x03, 0x01}, /* STB */
-       { 0x01, 0x02, 0x03, 0x04}, /* Intel??? */
-       { 0x01, 0x02, 0x03, 0x04}, /* Diamond DTV2000??? */
+static unsigned char audiomuxs[][5] = 
+{
+       { 0x00, 0x00, 0x00, 0x00, 0x00}, /* unknown */
+       { 0x02, 0x00, 0x00, 0x00, 0x0a}, /* MIRO */
+       { 0x00, 0x01, 0x02, 0x03, 0x04}, /* Hauppauge */
+       { 0x04, 0x00, 0x02, 0x03, 0x01}, /* STB */
+       { 0x00, 0x01, 0x02, 0x03, 0x04}, /* Intel??? */
+       { 0x00, 0x01, 0x02, 0x03, 0x04}, /* Diamond DTV2000 */
+       { 0x0c, 0x00, 0x0b, 0x0b, 0x00}, /* AVerMedia TVPhone */
 };
 
 static void audio(struct bttv *btv, int mode)
 {
+        /* enable least significant GPIO output nibble */
        btwrite(0x0f, BT848_GPIO_OUT_EN);
+
+        /* select direct input */
        btwrite(0x00, BT848_GPIO_REG_INP);
 
        switch (mode)
        {
-               case AUDIO_UNMUTE:
+               case AUDIO_MUTE:
+                        btv->audio|=AUDIO_MUTE;
+                       break;
+               case AUDIO_UNMUTE:
                        btv->audio&=~AUDIO_MUTE;
                        mode=btv->audio;
                        break;
@@ -263,8 +437,12 @@ static void audio(struct bttv *btv, int mode)
                        btv->audio|=mode;
                        break;
        }
-       if ((btv->audio&AUDIO_MUTE) || !(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
-               mode=AUDIO_OFF;
+        /* if audio mute or not in H-lock, turn audio off */
+       if ((btv->audio&AUDIO_MUTE) || 
+           (!btv->radio && !(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)))
+               mode=AUDIO_OFF;
+        if ((mode == 0) && (btv->radio))
+               mode = 1;
        btaor(audiomuxs[btv->type][mode] , ~0x0f, BT848_GPIO_DATA);
 }
 
@@ -319,11 +497,19 @@ static void bt848_muxsel(struct bttv *btv, uint input)
 
 #define VBIBUF_SIZE 65536
 
+/* Maximum sample number per VBI line is 2044, can NTSC deliver this? 
+   Note that we write 2048-aligned to keep alignment to memory pages 
+*/
+#define VBI_SPL 2044
+
+/* RISC command to write one VBI data line */
+#define VBI_RISC BT848_RISC_WRITE|VBI_SPL|BT848_RISC_EOL|BT848_RISC_SOL
+
 static void make_vbitab(struct bttv *btv)
 {
        int i;
-       dword *po=(dword *) btv->vbi_odd;
-       dword *pe=(dword *) btv->vbi_even;
+       unsigned int *po=(unsigned int *) btv->vbi_odd;
+       unsigned int *pe=(unsigned int *) btv->vbi_even;
   
        DEBUG(printk(KERN_DEBUG "vbiodd: 0x%08x\n",(int)btv->vbi_odd));
        DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even));
@@ -333,8 +519,8 @@ static void make_vbitab(struct bttv *btv)
        *(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0;
        for (i=0; i<16; i++) 
        {
-               *(po++)=BT848_RISC_WRITE|2044|BT848_RISC_EOL|BT848_RISC_SOL|(13<<20);
-               *(po++)=kvirt_to_bus((ulong)btv->vbibuf+i*2048);
+               *(po++)=VBI_RISC;
+               *(po++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048);
        }
        *(po++)=BT848_RISC_JUMP;
        *(po++)=virt_to_bus(btv->risc_jmp+4);
@@ -342,11 +528,129 @@ static void make_vbitab(struct bttv *btv)
        *(pe++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(pe++)=0;
        for (i=16; i<32; i++) 
        {
-               *(pe++)=BT848_RISC_WRITE|2044|BT848_RISC_EOL|BT848_RISC_SOL;
-               *(pe++)=kvirt_to_bus((ulong)btv->vbibuf+i*2048);
+               *(pe++)=VBI_RISC;
+               *(pe++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048);
        }
        *(pe++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16);
        *(pe++)=virt_to_bus(btv->risc_jmp+10);
+       DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));
+       DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));
+}
+
+int fmtbppx2[16] = {
+        8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0 
+};
+
+static int  make_vrisctab(struct bttv *btv, unsigned int *ro, unsigned int *re, 
+       unsigned int *vbuf, unsigned short width, unsigned short height, unsigned short fmt)
+{
+        unsigned long line;
+       unsigned long bpl;  /* bytes per line */
+       unsigned long bl;
+       unsigned long todo;
+       unsigned int **rp;
+       int inter;
+       unsigned long vadr=(unsigned long) vbuf;
+
+       inter = (height>btv->win.cropheight/2) ? 1 : 0;
+       bpl=width*fmtbppx2[fmt&0xf]/2;
+       
+       *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
+       *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
+  
+       for (line=0; line < (height<<(1^inter)); line++)
+       {
+               if (inter) 
+                       rp= (line&1) ? &re : &ro;
+               else 
+                       rp= (line>height) ? &re : &ro; 
+
+               bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
+               if (bpl<=bl)
+                {
+                       *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_SOL|
+                               BT848_RISC_EOL|bpl; 
+                       *((*rp)++)=kvirt_to_bus(vadr);
+                       vadr+=bpl;
+               }
+               else
+               {
+                       todo=bpl;
+                       *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_SOL|bl;
+                       *((*rp)++)=kvirt_to_bus(vadr);
+                       vadr+=bl;
+                       todo-=bl;
+                       while (todo>PAGE_SIZE)
+                       {
+                               *((*rp)++)=BT848_RISC_WRITE|PAGE_SIZE;
+                               *((*rp)++)=kvirt_to_bus(vadr);
+                               vadr+=PAGE_SIZE;
+                               todo-=PAGE_SIZE;
+                       }
+                       *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_EOL|todo;
+                       *((*rp)++)=kvirt_to_bus(vadr);
+                       vadr+=todo;
+               }
+       }
+       
+       *(ro++)=BT848_RISC_JUMP;
+       *(ro++)=btv->bus_vbi_even;
+       *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
+       *(re++)=btv->bus_vbi_odd;
+       
+       return 0;
+}
+
+/* does this really make a difference ???? */
+#define BURST_MAX 4096
+
+static inline void write_risc_segment(unsigned int **rp, unsigned long line_adr, unsigned int command,
+                       int *x, uint dx, uint bpp, uint width)
+{
+        unsigned int flags, len;
+  
+       if (!dx)
+                return;
+       len=dx*bpp;
+
+#ifdef LIMIT_DMA
+       if (command==BT848_RISC_WRITEC)
+       {
+                unsigned int dx2=BURST_MAX/bpp;
+               while (len>BURST_MAX)
+               {
+                       write_risc_segment(rp, line_adr, command,
+                                          &x,dx2, bpp, width);
+                       dx-=dx2;
+                       len=dx*bpp;
+               }
+       }
+#endif
+
+       /* mask upper 8 bits for 24+8 bit overlay modes */
+       flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
+       
+       if (*x==0) 
+       {
+                if (command==BT848_RISC_SKIP) 
+               {
+                       if (dx<width)
+                       {
+                               flags|=BT848_RISC_BYTE_ALL;
+                               command=BT848_RISC_WRITE;
+                       }
+               }
+               else
+                       if (command==BT848_RISC_WRITEC)
+                                command=BT848_RISC_WRITE;
+               flags|=BT848_RISC_SOL;
+        }
+       if (*x+dx==width)
+                flags|=BT848_RISC_EOL;
+       *((*rp)++)=command|flags|len;
+       if (command==BT848_RISC_WRITE)
+                *((*rp)++)=line_adr+*x*bpp;
+       *x+=dx;
 }
 
 /*
@@ -358,237 +662,264 @@ static void make_vbitab(struct bttv *btv)
  *     www.brooktree.com - nicely done those folks.
  */
  
-static void bt848_set_size(struct bttv *btv)
+struct tvnorm 
+{
+        u16 cropwidth, cropheight;
+       u16 totalwidth;
+       u8 adelay, bdelay, iform;
+       u32 scaledtwidth;
+       u16 hdelayx1, hactivex1;
+       u16 vdelay;
+};
+
+static struct tvnorm tvnorms[] = {
+       /* PAL-BDGHI */
+        { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+           944, 186, 922, 0x20},
+       /* NTSC */
+       { 640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+           780, 135, 754, 0x16},
+       /* SECAM */
+       { 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+           944, 186, 922, 0x20},
+       /* PAL-M */
+       { 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+           780, 186, 922, 0x16},
+       /* PAL-N */
+       { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
+           944, 186, 922, 0x20},
+};
+#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
+
+
+/* set geometry for even/odd frames 
+   just if you are wondering:
+   handling of even and odd frames will be separated, e.g. for grabbing
+   the even ones as RGB into videomem and the others as YUV in main memory for 
+   compressing and sending to the video conferencing partner.
+
+*/
+static inline void bt848_set_eogeo(struct bttv *btv, int odd, u8 vtc, 
+                                  u16 hscale, u16 vscale,
+                                  u16 hactive, u16 vactive,
+                                  u16 hdelay, u16 vdelay,
+                                  u8 crop)
+{
+        int off = odd ? 0x80 : 0x00;
+  
+       btwrite(vtc, BT848_E_VTC+off);
+       btwrite(hscale>>8, BT848_E_HSCALE_HI+off);
+       btwrite(hscale&0xff, BT848_E_HSCALE_LO+off);
+       btaor((vscale>>8), 0xc0, BT848_E_VSCALE_HI+off);
+       btwrite(vscale&0xff, BT848_E_VSCALE_LO+off);
+       btwrite(hactive&0xff, BT848_E_HACTIVE_LO+off);
+       btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off);
+       btwrite(vactive&0xff, BT848_E_VACTIVE_LO+off);
+       btwrite(vdelay&0xff, BT848_E_VDELAY_LO+off);
+       btwrite(crop, BT848_E_CROP+off);
+}
+
+
+static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt)
 {
-       u16 vscale, hscale;
+        u16 vscale, hscale;
        u32 xsf, sr;
        u16 hdelay, vdelay;
        u16 hactive, vactive;
        u16 inter;
-       u8 crop;
+       u8 crop, vtc;  
+       struct tvnorm *tvn;
+       
+       if (!width || !height)
+               return;
 
-       /*
-        *      No window , no try...
-        */
-        
-       if (!btv->win.width)
-               return;
-       if (!btv->win.height)
-               return;
-    
+       tvn=&tvnorms[btv->win.norm];
+       
+       if (btv->win.cropwidth>tvn->cropwidth)
+                btv->win.cropwidth=tvn->cropwidth;
+       if (btv->win.cropheight>tvn->cropheight)
+               btv->win.cropheight=tvn->cropheight;
+
+       if (width>btv->win.cropwidth)
+                width=btv->win.cropwidth;
+       if (height>btv->win.cropheight)
+               height=btv->win.cropheight;
+
+       btwrite(tvn->adelay, BT848_ADELAY);
+       btwrite(tvn->bdelay, BT848_BDELAY);
+       btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
+
+       btwrite(fmt, BT848_COLOR_FMT);
+       hactive=width;
+
+        vtc=0;
+       /* Some people say interpolation looks bad ... */
+       /* vtc = (hactive < 193) ? 2 : ((hactive < 385) ? 1 : 0); */
+     
+       btv->win.interlace = (height>btv->win.cropheight/2) ? 1 : 0;
        inter=(btv->win.interlace&1)^1;
+       xsf = (hactive*tvn->scaledtwidth)/btv->win.cropwidth;
+       hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
+       vdelay=btv->win.cropy+tvn->vdelay;
 
-       switch (btv->win.bpp) 
-       {
-               /*
-                * RGB8 seems to be a 9x5x5 GRB color cube starting at color 16
-                * Why the h... can't they even mention this in the datasheet???
-                */
-               case 1: 
-                       btwrite(BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT);
-                       btand(~0x10, BT848_CAP_CTL);  /* Dithering looks much better in this mode */
-                       break;
-               case 2: 
-                       btwrite(BT848_COLOR_FMT_RGB16, BT848_COLOR_FMT);
-                       btor(0x10, BT848_CAP_CTL);
-                       break;
-               case 3: 
-                       btwrite(BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT);
-                       btor(0x10, BT848_CAP_CTL);
-                       break;
-               case 4: 
-                       btwrite(BT848_COLOR_FMT_RGB32, BT848_COLOR_FMT);
-                       btor(0x10, BT848_CAP_CTL);
-                       break;
-       }
-       
-       /*
-        *      Set things up according to the final picture width.
-        */
-        
-       hactive=btv->win.width;
-       if (hactive < 193) 
-       {
-               btwrite (2, BT848_E_VTC);
-               btwrite (2, BT848_O_VTC);
-       }
-       else if (hactive < 385) 
-       {
-               btwrite (1, BT848_E_VTC);
-               btwrite (1, BT848_O_VTC);
-       }
-       else 
-       {
-               btwrite (0, BT848_E_VTC);
-               btwrite (0, BT848_O_VTC);
-       }
+       hdelay=(tvn->hdelayx1*tvn->scaledtwidth)/tvn->totalwidth;
+       hdelay=((hdelay+btv->win.cropx)*hactive)/btv->win.cropwidth;
+       hdelay&=0x3fe;
 
-       /*
-        *      Ok are we doing Never The Same Color or PAL ?
-        */
-        
-       if (btv->win.norm==1) 
-       { 
-               btv->win.cropwidth=640;
-               btv->win.cropheight=480;
-               btwrite(0x68, BT848_ADELAY);
-               btwrite(0x5d, BT848_BDELAY);
-               btaor(BT848_IFORM_NTSC, ~7, BT848_IFORM);
-               btaor(BT848_IFORM_XT0, ~0x18, BT848_IFORM);
-               xsf = (btv->win.width*365625UL)/300000UL;
-               hscale = ((910UL*4096UL)/xsf-4096);
-               vdelay=btv->win.cropy+0x16;
-               hdelay=((hactive*135)/754+btv->win.cropx)&0x3fe;
-       }
-       else
-       {
-               btv->win.cropwidth=768;
-               btv->win.cropheight=576;
-               if (btv->win.norm==0)
-               { 
-                       btwrite(0x7f, BT848_ADELAY);
-                       btwrite(0x72, BT848_BDELAY);
-                       btaor(BT848_IFORM_PAL_BDGHI, ~BT848_IFORM_NORM, BT848_IFORM);
-               }
-               else
-               {
-                       btwrite(0x7f, BT848_ADELAY);
-                       btwrite(0x00, BT848_BDELAY);
-                       btaor(BT848_IFORM_SECAM, ~BT848_IFORM_NORM, BT848_IFORM);
-               }
-               btaor(BT848_IFORM_XT1, ~0x18, BT848_IFORM);
-               xsf = (btv->win.width*36875UL)/30000UL;
-               hscale = ((1135UL*4096UL)/xsf-4096);
-               vdelay=btv->win.cropy+0x20;
-               hdelay=((hactive*186)/922+btv->win.cropx)&0x3fe;
-       }
-       sr=((btv->win.cropheight>>inter)*512)/btv->win.height-512;
+       sr=((btv->win.cropheight>>inter)*512)/height-512;
        vscale=(0x10000UL-sr)&0x1fff;
        vactive=btv->win.cropheight;
+       crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)|
+               ((vactive>>4)&0x30)|((vdelay>>2)&0xc0);
+       vscale|= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0;
+       
+       bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, vactive,
+                       hdelay, vdelay, crop);
+       bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive,
+                       hdelay, vdelay, crop);
+       
+}
 
-#if 0
-       printk("bttv: hscale=0x%04x, ",hscale);
-       printk("bttv: vscale=0x%04x\n",vscale);
 
-       printk("bttv: hdelay =0x%04x\n",hdelay);
-       printk("bttv: hactive=0x%04x\n",hactive);
-       printk("bttv: vdelay =0x%04x\n",vdelay);
-       printk("bttv: vactive=0x%04x\n",vactive);
-#endif
+int bpp2fmt[4] = {
+        BT848_COLOR_FMT_RGB8, BT848_COLOR_FMT_RGB16, 
+        BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32 
+};
 
-       /*
-        *      Interlace is set elsewhere according to the final image 
-        *      size we desire
-        */
-        
-       if (btv->win.interlace) 
-       { 
-               btor(BT848_VSCALE_INT, BT848_E_VSCALE_HI);
-               btor(BT848_VSCALE_INT, BT848_O_VSCALE_HI);
-       }
-       else
+static void bt848_set_winsize(struct bttv *btv)
+{
+        unsigned short format;
+       int bpp;
+
+       bpp=fmtbppx2[btv->win.color_fmt&0x0f]/2;
+       if (btv->win.bpp == 0) 
        {
-               btand(~BT848_VSCALE_INT, BT848_E_VSCALE_HI);
-               btand(~BT848_VSCALE_INT, BT848_O_VSCALE_HI);
+               btv->win.bpp=bpp;
+               format=btv->win.color_fmt;
        }
-
-       /*
-        *      Load her up
+       else if (btv->win.bpp!=bpp)
+               btv->win.color_fmt=format=bpp2fmt[(btv->win.bpp-1)&3];
+       else
+                format=btv->win.color_fmt;
+                       
+       /*      RGB8 seems to be a 9x5x5 GRB color cube starting at
+        *      color 16. Why the h... can't they even mention this in the
+        *      datasheet???  [AC - because its a standard format so I guess
+        *      it never occured them]
+        *      Enable dithering in this mode
         */
-        
-       btwrite(hscale>>8, BT848_E_HSCALE_HI);
-       btwrite(hscale>>8, BT848_O_HSCALE_HI);
-       btwrite(hscale&0xff, BT848_E_HSCALE_LO);
-       btwrite(hscale&0xff, BT848_O_HSCALE_LO);
-
-       btwrite((vscale>>8)|(btread(BT848_E_VSCALE_HI)&0xe0), BT848_E_VSCALE_HI);
-       btwrite((vscale>>8)|(btread(BT848_O_VSCALE_HI)&0xe0), BT848_O_VSCALE_HI);
-       btwrite(vscale&0xff, BT848_E_VSCALE_LO);
-       btwrite(vscale&0xff, BT848_O_VSCALE_LO);
-
-       btwrite(hactive&0xff, BT848_E_HACTIVE_LO);
-       btwrite(hactive&0xff, BT848_O_HACTIVE_LO);
-       btwrite(hdelay&0xff, BT848_E_HDELAY_LO);
-       btwrite(hdelay&0xff, BT848_O_HDELAY_LO);
-
-       btwrite(vactive&0xff, BT848_E_VACTIVE_LO);
-       btwrite(vactive&0xff, BT848_O_VACTIVE_LO);
-       btwrite(vdelay&0xff, BT848_E_VDELAY_LO);
-       btwrite(vdelay&0xff, BT848_O_VDELAY_LO);
+       if (format==BT848_COLOR_FMT_RGB8)
+                btand(~0x10, BT848_CAP_CTL); 
+       else
+               btor(0x10, BT848_CAP_CTL);
 
-       crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)|
-               ((vactive>>4)&0x30)|((vdelay>>2)&0xc0);
-       btwrite(crop, BT848_E_CROP);
-       btwrite(crop, BT848_O_CROP);
+        bt848_set_geo(btv,btv->win.width, btv->win.height, format);
 }
 
-
-/*
- *     The floats in the tuner struct are computed at compile time
- *     by gcc and cast back to integers. Thus we don't violate the
- *     "no float in kernel" rule.
- */
-static struct tunertype tuners[] = {
-       {"Temic PAL", TEMIC, PAL,
-               16*140.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2, 623},
-       {"Philips PAL_I", Philips, PAL_I,
-               16*140.25,16*463.25,0x00,0x00,0x00,0x00,0x00, 623},
-       {"Philips NTSC", Philips, NTSC,
-               16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,0xc0, 732},
-       {"Philips SECAM", Philips, SECAM,
-               16*168.25,16*447.25,0xA3,0x93,0x33,0x8e,0xc0, 623},
-       {"NoTuner", NoTuner, NOTUNER,
-               0        ,0        ,0x00,0x00,0x00,0x00,0x00, 0},
-       {"Philips PAL", Philips, PAL,
-               16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,0xc0, 623},
-       {"Temic NTSC", TEMIC, NTSC,
-               16*157.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2, 732},
-       {"TEMIC PAL_I", TEMIC, PAL_I,
-               0        ,0        ,0x00,0x00,0x00,0x00,0xc2, 623},
-}; 
-
 /*
  *     Set TSA5522 synthesizer frequency in 1/16 Mhz steps
  */
 
-static void set_freq(struct bttv *btv, ushort freq)
+static void set_freq(struct bttv *btv, unsigned short freq)
 {
-       u8 config;
-       u16 div;
-       struct tunertype *tun=&tuners[btv->tuner];
+       int fixme = freq; /* XXX */
        int oldAudio = btv->audio;
-
+       
        audio(btv, AUDIO_MUTE);
        udelay(AUDIO_MUTE_DELAY);
-       
-       if (freq < tun->thresh1) 
-               config = tun->VHF_L;
-       else if (freq < tun->thresh2) 
-               config = tun->VHF_H;
-       else
-               config = tun->UHF;
 
-       if(freq < tun->thresh1)
-               config = tun->VHF_L;
-       else if(freq < tun->thresh2)
-               config = tun->VHF_H;
-       else
-               config=tun->UHF;
-               
-       div=freq+tun->IFPCoff;
-         
-       div&=0x7fff;
+       if (btv->radio) 
+       {
+               if (btv->have_tuner)
+                       i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
+                                          TUNER_SET_RADIOFREQ,&fixme);
        
-       if (I2CWrite(btv, btv->tuneradr, (div>>8)&0x7f, div&0xff, 1)<0)
-               return;
-       I2CWrite(btv, btv->tuneradr, tun->config, config, 1);
-       if (!(oldAudio & AUDIO_MUTE))
+               if (btv->have_msp3400) {
+                       i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+                                          MSP_SET_RADIO,0);
+                       i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+                                          MSP_NEWCHANNEL,0);
+               }
+       }
+       else
        {
+               if (btv->have_tuner)
+                       i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
+                                          TUNER_SET_TVFREQ,&fixme);
+
+               if (btv->have_msp3400) {
+                       i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+                                          MSP_SET_TVNORM,&(btv->win.norm));
+                       i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+                                          MSP_NEWCHANNEL,0);
+               }
+       }
+
+       if (!(oldAudio & AUDIO_MUTE)) {
                udelay(FREQ_CHANGE_DELAY);
                audio(btv, AUDIO_UNMUTE);
        }
 }
+      
+
+/*
+ *     Grab into virtual memory.
+ *     Currently only does double buffering. Do we need more?
+ */
+
+static int vgrab(struct bttv *btv, struct video_mmap *mp)
+{
+       unsigned int *ro, *re;
+       unsigned int *vbuf;
+       
+       if(btv->fbuffer==NULL)
+       {
+               if(fbuffer_alloc(btv))
+                       return -ENOBUFS;
+       }
+       
+       /*
+        *      No grabbing past the end of the buffer!
+        */
+        
+       if(mp->frame>1 || mp->frame <0)
+               return -EINVAL;
+               
+       if(mp->height <0 || mp->width <0)
+               return -EINVAL;
+       
+       if(mp->height>480 || mp->width>640)
+               return -EINVAL;
+
+       /*
+        *      FIXME: Check the format of the grab here. This is probably
+        *      also less restrictive than the normal overlay grabs. Stuff
+        *      like QCIF has meaning as a capture.
+        */
+        
+       /*
+        *      Ok load up the BT848
+        */
+        
+       vbuf=(unsigned int *)(btv->fbuffer+0x144000*mp->frame);
+       if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
+                return -EAGAIN;
+       ro=btv->grisc+(((btv->grabcount++)&1) ? 2048 :0);
+       re=ro+1024;
+       btv->gwidth=mp->width;
+       btv->gheight=mp->height;
+       btv->gfmt=mp->format;
+       make_vrisctab(btv, ro, re, vbuf, btv->gwidth, btv->gheight, btv->gfmt);
+       /* bt848_set_risc_jmps(btv); */
+       btor(3, BT848_CAP_CTL);
+       btor(3, BT848_GPIO_DMA_CTL);
+       btv->gro=virt_to_bus(ro);
+       btv->gre=virt_to_bus(re);
+       if (!(btv->grabbing++)) 
+               btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
+       /* interruptible_sleep_on(&btv->capq); */
+       return 0;
+}
 
 static long bttv_write(struct video_device *v, const char *buf, unsigned long count, int nonblock)
 {
@@ -608,7 +939,6 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in
                todo-=q;
                buf+=q;
 
-/*             btv->vbip=0; */
                cli();
                if (todo && q==VBIBUF_SIZE-btv->vbip) 
                {
@@ -659,14 +989,17 @@ static int bttv_open(struct video_device *dev, int flags)
                                users+=bttvs[i].user;
                        if (users==1)
                                find_vga();
+                       btv->fbuffer=NULL;
+                       if (!btv->fbuffer)
+                               btv->fbuffer=(unsigned char *) rvmalloc(2*0x144000);
+                       if (!btv->fbuffer)
+                        { 
+                               btv->user--;
+                               return -EINVAL;
+                       }
                        break;
                case 1:
                        break;
-               case 2:
-                       btv->vbip=VBIBUF_SIZE;
-                       btv->cap|=0x0c;
-                       bt848_set_risc_jmps(btv);
-                       break;
        }
        MOD_INC_USE_COUNT;
        return 0;   
@@ -679,17 +1012,15 @@ static void bttv_close(struct video_device *dev)
        btv->user--;
        audio(btv, AUDIO_MUTE);
        btv->cap&=~3;
-#if 0 /* FIXME */      
-       if(minor&0x20) 
-       {
-               btv->cap&=~0x0c;
-       }
-#endif 
        bt848_set_risc_jmps(btv);
 
+       if(btv->fbuffer)
+               rvfree((void *) btv->fbuffer, 2*0x144000);
+       btv->fbuffer=0;
        MOD_DEC_USE_COUNT;  
 }
 
+
 /***********************************/
 /* ioctls and supporting functions */
 /***********************************/
@@ -714,7 +1045,7 @@ extern inline void bt848_contrast(struct bttv *btv, uint cont)
        btaor(conthi, ~4, BT848_O_CONTROL);
 }
 
-extern inline void bt848_sat_u(struct bttv *btv, ulong data)
+extern inline void bt848_sat_u(struct bttv *btv, unsigned long data)
 {
        u32 datahi;
 
@@ -724,7 +1055,7 @@ extern inline void bt848_sat_u(struct bttv *btv, ulong data)
        btaor(datahi, ~2, BT848_O_CONTROL);
 }
 
-static inline void bt848_sat_v(struct bttv *btv, ulong data)
+static inline void bt848_sat_v(struct bttv *btv, unsigned long data)
 {
        u32 datahi;
 
@@ -734,6 +1065,7 @@ static inline void bt848_sat_v(struct bttv *btv, ulong data)
        btaor(datahi, ~1, BT848_O_CONTROL);
 }
 
+
 /*
  *     Cliprect -> risc table.
  *
@@ -772,15 +1104,17 @@ static void write_risc_data(struct bttv *btv, struct video_clip *vp, int count)
        }
        first2.next=NULL;
        
-       rmem[rpo++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; rmem[rpo++]=0;
+       rmem[rpo++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1|(0xf<<20);
+       rmem[rpo++]=0;
 
-       rmem2[rpe++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; rmem2[rpe++]=0;
+       rmem2[rpe++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1;
+       rmem2[rpe++]=0;
 
 
        /*
         *      32bit depth frame buffers need extra flags setting
         */
-
+        
        if (depth==4)
                mask=BT848_RISC_BYTE3;
        else
@@ -842,7 +1176,7 @@ static void write_risc_data(struct bttv *btv, struct video_clip *vp, int count)
                 *      here, but the overlap might be partial
                 */
                 
-               /* add rect to second (x-sorted) list if rect.y == y  */
+               /* add rect to second (x-sorted) list if rect.y == y  */
                if ((cur=first.next)) 
                {
                        while ((cur) && (cur->y == y))
@@ -953,8 +1287,9 @@ static void write_risc_data(struct bttv *btv, struct video_clip *vp, int count)
                        {
                                /* Skip the line : write a SKIP + start/end of line marks */
                                (*rp)--;
-                               rpp[(*rp)-1]=BT848_RISC_SKIP|(btv->win.width*depth)|
-                                       BT848_RISC_EOL|BT848_RISC_SOL;
+                               rpp[(*rp)-1]=BT848_RISC_SKIP|
+                                       (btv->win.width*depth)|
+                                         BT848_RISC_EOL|BT848_RISC_SOL;
                        }
                }
                /*
@@ -988,15 +1323,15 @@ static void new_risc_clip(struct video_window *vw, struct video_clip *vcp, int x
        vw->clipcount++;
 }
 
+
 /*
  *     ioctl routine
  */
  
+
 static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
        unsigned char eedata[256];
-/*     unsigned long data;*/
-/*     static ushort creg;*/
        struct bttv *btv=(struct bttv *)dev;
        static int lastchan=0;
        
@@ -1092,10 +1427,14 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        /* Only channel 0 has a tuner */
                        if(v.tuner!=0 || lastchan)
                                return -EINVAL;
-                       if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC)
+                       if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC
+                          &&v.mode!=VIDEO_MODE_SECAM)
                                return -EOPNOTSUPP;
+                       /* FIXME: norm should be in video_channel struct 
+                          composite source can have different norms too
+                        */
                        btv->win.norm = v.mode;
-                       bt848_set_size(btv);
+                       bt848_set_winsize(btv);
                        return 0;
                }
                case VIDIOCGPICT:
@@ -1109,6 +1448,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                p.palette=VIDEO_PALETTE_RGB24;
                        if(btv->win.bpp==4)
                                p.palette=VIDEO_PALETTE_RGB32;
+                       
                        if(copy_to_user(arg, &p, sizeof(p)))
                                return -EFAULT;
                        return 0;
@@ -1155,7 +1495,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        on=(btv->cap&3)?1:0;
                        
                        bt848_cap(btv,0);
-                       bt848_set_size(btv);
+                       bt848_set_winsize(btv);
 
                        if(vw.clipcount>256)
                                return -EDOM;   /* Too many! */
@@ -1188,7 +1528,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                         */
                        write_risc_data(btv,vcp, vw.clipcount);
                        vfree(vcp);
-                       if(on)
+                       if(on && btv->win.vidadr!=0)
                                bt848_cap(btv,1);
                        return 0;
                }
@@ -1213,14 +1553,15 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        int v;
                        if(copy_from_user(&v, arg,sizeof(v)))
                                return -EFAULT;
-                       if(btv->win.vidadr==0 || btv->win.width==0 || btv->win.height==0)
-                               return -EINVAL;
                        if(v==0)
                        {
                                bt848_cap(btv,0);
                        }
                        else
                        {
+                               if(btv->win.vidadr==0 || btv->win.width==0
+                                  || btv->win.height==0)
+                                 return -EINVAL;
                                bt848_cap(btv,1);
                        }
                        return 0;
@@ -1247,7 +1588,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EFAULT;
                        if(v.depth!=8 && v.depth!=16 && v.depth!=24 && v.depth!=32)
                                return -EINVAL;
-                       btv->win.vidadr=(int)v.base;
+                       if (v.base)
+                               /* also handle virtual base addresses */
+                               if ((unsigned int)v.base>=0xe0000000UL)
+                                       btv->win.vidadr=(uint)v.base;
+                               else 
+                                 btv->win.vidadr=PAGE_OFFSET|
+                                   uvirt_to_bus((uint)v.base);
                        btv->win.sheight=v.height;
                        btv->win.swidth=v.width;
                        btv->win.bpp=v.depth/8;
@@ -1255,7 +1602,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        
                        DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
                                v.base, v.width,v.height, btv->win.bpp, btv->win.bpl));
-                       bt848_set_size(btv);
+                       bt848_set_winsize(btv);
                        return 0;               
                }
                case VIDIOCKEY:
@@ -1287,6 +1634,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE);
                        v.flags|=VIDEO_AUDIO_MUTABLE;
                        strcpy(v.name,"TV");
+                       if (btv->have_msp3400) 
+                       {
+                               v.flags|=VIDEO_AUDIO_VOLUME;
+                               i2c_control_device(&(btv->i2c),
+                                       I2C_DRIVERID_MSP3400,
+                                       MSP_GET_VOLUME,&(v.volume));
+                               i2c_control_device(&(btv->i2c),
+                                       I2C_DRIVERID_MSP3400,
+                                       MSP_GET_STEREO,&(v.mode));
+                       }
+                       else v.mode = VIDEO_SOUND_MONO;
                        if(copy_to_user(arg,&v,sizeof(v)))
                                return -EFAULT;
                        return 0;
@@ -1296,28 +1654,55 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        struct video_audio v;
                        if(copy_from_user(&v,arg, sizeof(v)))
                                return -EFAULT;
-                       if(v.audio!=0)
-                               return -EINVAL;
                        if(v.flags&VIDEO_AUDIO_MUTE)
                                audio(btv, AUDIO_MUTE);
+                       if(v.audio<0||v.audio>2)
+                               return -EINVAL;
+                       bt848_muxsel(btv,v.audio);
                        if(!(v.flags&VIDEO_AUDIO_MUTE))
                                audio(btv, AUDIO_UNMUTE);
+                       if (btv->have_msp3400) 
+                       {
+                               i2c_control_device(&(btv->i2c),
+                                       I2C_DRIVERID_MSP3400,
+                                       MSP_SET_VOLUME,&(v.volume));
+                               i2c_control_device(&(btv->i2c),
+                                       I2C_DRIVERID_MSP3400,
+                                       MSP_SET_STEREO,&(v.mode));
+                       }
                        btv->audio_dev=v;
                        return 0;
                }
 
-               case BTTV_WRITEEE:
+               case VIDIOCSYNC:
+                       if (btv->grabbing && btv->grab==btv->lastgrab)
+                               interruptible_sleep_on(&btv->capq);
+                       btv->lastgrab=btv->grab;
+                       return 0;
+
+               case BTTV_WRITEE:
+                       if(!suser())
+                               return -EPERM;
                        if(copy_from_user((void *) eedata, (void *) arg, 256))
                                return -EFAULT;
-                       writeee(btv, eedata);
-                       break;
+                       writeee(&(btv->i2c), eedata);
+                       return 0;
 
                case BTTV_READEE:
-                       readee(btv, eedata);
+                       if(!suser())
+                               return -EPERM;
+                       readee(&(btv->i2c), eedata);
                        if(copy_to_user((void *) arg, (void *) eedata, 256))
                                return -EFAULT;
                        break;
 
+               case VIDIOCMCAPTURE:
+               {
+                        struct video_mmap vm;
+                       if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
+                               return -EFAULT;
+                       return vgrab(btv, &vm);
+               }
                default:
                        return -ENOIOCTLCMD;
        }
@@ -1329,6 +1714,41 @@ static int bttv_init_done(struct video_device *dev)
        return 0;
 }
 
+/*
+ *     This maps the vmalloced and reserved fbuffer to user space.
+ *
+ *  FIXME: 
+ *  - PAGE_READONLY should suffice!?
+ *  - remap_page_range is kind of inefficient for page by page remapping.
+ *    But e.g. pte_alloc() does not work in modules ... :-(
+ */
+static int bttv_mmap(struct video_device *dev, const char *adr, unsigned long size)
+{
+       struct bttv *btv=(struct bttv *)dev;
+        unsigned long start=(unsigned long) adr;
+       unsigned long page,pos;
+
+       if (size>2*0x144000)
+               return -EINVAL;
+       if (!btv->fbuffer)
+       {
+               if(fbuffer_alloc(btv))
+                       return -EINVAL;
+       }
+       pos=(unsigned long) btv->fbuffer;
+       while (size > 0) 
+       {
+               page = kvirt_to_phys(pos);
+               if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+                       return -EAGAIN;
+               start+=PAGE_SIZE;
+               pos+=PAGE_SIZE;
+               size-=PAGE_SIZE;    
+       }
+       return 0;
+}
+
 static struct video_device bttv_template=
 {
        "UNSET",
@@ -1339,6 +1759,96 @@ static struct video_device bttv_template=
        bttv_read,
        bttv_write,
        bttv_ioctl,
+       bttv_mmap,
+       bttv_init_done,
+       NULL,
+       0,
+       0
+};
+
+
+static long vbi_read(struct video_device *v, char *buf, unsigned long count,
+                    int nonblock)
+{
+       struct bttv *btv=(struct bttv *)(v-2);
+       int q,todo;
+
+       todo=count;
+       while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) 
+       {
+               if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q))
+                       return -EFAULT;
+               todo-=q;
+               buf+=q;
+
+               cli();
+               if (todo && q==VBIBUF_SIZE-btv->vbip) 
+               {
+                       if(nonblock)
+                       {
+                               sti();
+                               if(count==todo)
+                                       return -EWOULDBLOCK;
+                               return count-todo;
+                       }
+                       interruptible_sleep_on(&btv->vbiq);
+                       sti();
+                       if(signal_pending(current))
+                       {
+                               if(todo==count)
+                                       return -EINTR;
+                               else
+                                       return count-todo;
+                       }
+               }
+       }
+       if (todo) 
+       {
+               if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, todo))
+                       return -EFAULT;
+               btv->vbip+=todo;
+       }
+       return count;
+}
+
+static int vbi_open(struct video_device *dev, int flags)
+{
+       struct bttv *btv=(struct bttv *)(dev-2);
+
+       btv->vbip=VBIBUF_SIZE;
+       btv->cap|=0x0c;
+       bt848_set_risc_jmps(btv);
+
+       MOD_INC_USE_COUNT;
+       return 0;   
+}
+
+static void vbi_close(struct video_device *dev)
+{
+       struct bttv *btv=(struct bttv *)(dev-2);
+  
+       btv->cap&=~0x0c;
+       bt848_set_risc_jmps(btv);
+
+       MOD_DEC_USE_COUNT;  
+}
+
+
+static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+       return -EINVAL;
+}
+
+static struct video_device vbi_template=
+{
+       "bttv vbi",
+       VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
+       VID_HARDWARE_BT848,
+       vbi_open,
+       vbi_close,
+       vbi_read,
+       bttv_write,
+       vbi_ioctl,
        NULL,   /* no mmap yet */
        bttv_init_done,
        NULL,
@@ -1346,9 +1856,106 @@ static struct video_device bttv_template=
        0
 };
 
+
+static int radio_open(struct video_device *dev, int flags)
+{
+       struct bttv *btv = (struct bttv *)(dev-1);
+
+       if (btv->user)
+               return -EBUSY;
+       btv->user++;
+       set_freq(btv,400*16);
+       btv->radio = 1;
+       bt848_muxsel(btv,0);
+       audio(btv, AUDIO_UNMUTE);
+       
+       MOD_INC_USE_COUNT;
+       return 0;   
+}
+
+static void radio_close(struct video_device *dev)
+{
+       struct bttv *btv=(struct bttv *)(dev-1);
+  
+       btv->user--;
+       btv->radio = 0;
+       audio(btv, AUDIO_MUTE);
+       MOD_DEC_USE_COUNT;  
+}
+
+static long radio_read(struct video_device *v, char *buf, unsigned long count, int nonblock)
+{
+       return -EINVAL;
+}
+
+static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+        struct bttv *btv=(struct bttv *)(dev-1);
+       static int lastchan=0;
+       switch (cmd) {  
+       case VIDIOCGCAP:
+               /* XXX */
+               break;
+       case VIDIOCGTUNER:
+       {
+               struct video_tuner v;
+               if(copy_from_user(&v,arg,sizeof(v))!=0)
+                       return -EFAULT;
+               if(v.tuner||lastchan)   /* Only tuner 0 */
+                       return -EINVAL;
+               strcpy(v.name, "Radio");
+               v.rangelow=(int)(87.5*16);
+               v.rangehigh=(int)(108.0*16);
+               v.flags= 0; /* XXX */
+               v.mode = 0; /* XXX */
+               if(copy_to_user(arg,&v,sizeof(v)))
+                       return -EFAULT;
+               return 0;
+       }
+       case VIDIOCSTUNER:
+       {
+               struct video_tuner v;
+               if(copy_from_user(&v, arg, sizeof(v)))
+                       return -EFAULT;
+               /* Only channel 0 has a tuner */
+               if(v.tuner!=0 || lastchan)
+                       return -EINVAL;
+               /* XXX anything to do ??? */
+               return 0;
+       }
+       case VIDIOCGFREQ:
+       case VIDIOCSFREQ:
+       case VIDIOCGAUDIO:
+       case VIDIOCSAUDIO:
+               bttv_ioctl((struct video_device *)btv,cmd,arg);
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+       return 0;
+}
+
+static struct video_device radio_template=
+{
+       "bttv radio",
+       VID_TYPE_TUNER,
+       VID_HARDWARE_BT848,
+       radio_open,
+       radio_close,
+       radio_read,          /* just returns -EINVAL */
+       bttv_write,          /* just returns -EINVAL */
+       radio_ioctl,
+       NULL,                /* no mmap */
+       bttv_init_done,      /* just returns 0 */
+       NULL,
+       0,
+       0
+};
+
+
 struct vidbases 
 {
-       ushort vendor, device;
+       unsigned short vendor, device;
        char *name;
        uint badr;
 };
@@ -1386,7 +1993,7 @@ static uint dec_offsets[4] = {
 static int find_vga(void)
 {
        unsigned int devfn, class, vendev;
-       ushort vendor, device, badr;
+       unsigned short vendor, device, badr;
        int found=0, bus=0, i, tga_type;
        unsigned int vidadr=0;
 
@@ -1470,6 +2077,8 @@ static int find_vga(void)
        return found;
 }
 
+
+
 #define  TRITON_PCON              0x50 
 #define  TRITON_BUS_CONCURRENCY   (1<<0)
 #define  TRITON_STREAMING        (1<<1)
@@ -1480,28 +2089,27 @@ static void handle_chipset(void)
 {
        int index;
   
+       /*      Just in case some nut set this to something dangerous */
+       if (triton1)
+               triton1=BT848_INT_ETBF;
+       
        for (index = 0; index < 8; index++)
        {
                unsigned char bus, devfn;
-               unsigned char b, bo;
+               unsigned char b;
     
                /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */
                
-               if (!pcibios_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, index, &bus, &devfn))
+               if (!pcibios_find_device(PCI_VENDOR_ID_SI, 
+                                        PCI_DEVICE_ID_SI_496, 
+                                        index, &bus, &devfn))
                {
                        printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
                }                       
 
-               if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
-                           index, &bus, &devfn)) 
-               {
-                       pcibios_read_config_byte(bus, devfn, 0x53, &b);
-                       DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
-                       DEBUG(printk("bufcon=0x%02x\n",b));
-               }
-
-               if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
-                           index, &bus, &devfn)) 
+               if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, 
+                                        PCI_DEVICE_ID_INTEL_82441,
+                                        index, &bus, &devfn)) 
                {
                        pcibios_read_config_byte(bus, devfn, 0x53, &b);
                        DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
@@ -1512,139 +2120,176 @@ static void handle_chipset(void)
                            index, &bus, &devfn)) 
                {
                        printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
-                       pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b);
-                       bo=b;
-                       DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
-
+                       triton1=BT848_INT_ETBF;
+                       
+#if 0                  
+                       /* The ETBF bit SHOULD make all this unnecessary */
                        /* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
-                       if(!(b & TRITON_BUS_CONCURRENCY)) 
-                       {
-                               printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
-                               b |= TRITON_BUS_CONCURRENCY;
-                       }
+                       {   
+                               unsigned char bo;
 
-                       /* still freezes on other boards -> switch off even more */
-                       if(b & TRITON_PEER_CONCURRENCY) 
-                       {
-                               printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
-                               b &= ~TRITON_PEER_CONCURRENCY;
-                       }
-                       if(!(b & TRITON_STREAMING)) 
-                       {
-                               printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
-                               b |=  TRITON_STREAMING;
-                       }
+                               pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b);
+                               bo=b;
+                               DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
 
-                       if (b!=bo) 
-                       {
-                               pcibios_write_config_byte(bus, devfn, TRITON_PCON, b); 
-                               printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
+                               if(!(b & TRITON_BUS_CONCURRENCY)) 
+                               {
+                                       printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
+                                       b |= TRITON_BUS_CONCURRENCY;
+                               }
+
+                               if(b & TRITON_PEER_CONCURRENCY) 
+                               {
+                                       printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
+                                       b &= ~TRITON_PEER_CONCURRENCY;
+                               }
+                               if(!(b & TRITON_STREAMING)) 
+                               {
+                                       printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
+                                       b |=  TRITON_STREAMING;
+                               }
+
+                               if (b!=bo) 
+                               {
+                                       pcibios_write_config_byte(bus, devfn, TRITON_PCON, b); 
+                                       printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
+                               }
                        }
+#endif
                }
        }
 }
 
-static void init_tda9850(struct bttv *btv)
+
+static void init_tda9850(struct i2c_bus *bus)
 {
-       I2CWrite(btv, I2C_TDA9850, TDA9850_CON3, 0, 1);
+        I2CWrite(bus, I2C_TDA9850, TDA9850_CON1, 0x08, 1);  /* noise threshold st */
+       I2CWrite(bus, I2C_TDA9850, TDA9850_CON2, 0x08, 1);  /* noise threshold sap */
+       I2CWrite(bus, I2C_TDA9850, TDA9850_CON3, 0x40, 1);  /* stereo mode */
+       I2CWrite(bus, I2C_TDA9850, TDA9850_CON4, 0x07, 1);  /* 0 dB input gain?*/
+       I2CWrite(bus, I2C_TDA9850, TDA9850_ALI1, 0x10, 1);  /* wideband alignment? */
+       I2CWrite(bus, I2C_TDA9850, TDA9850_ALI2, 0x10, 1);  /* spectral alignment? */
+       I2CWrite(bus, I2C_TDA9850, TDA9850_ALI3, 0x03, 1);
 }
 
+
+
 /* Figure out card and tuner type */
 
 static void idcard(struct bttv *btv)
 {
-       int i;
-
+       int tunertype;
        btwrite(0, BT848_GPIO_OUT_EN);
        DEBUG(printk(KERN_DEBUG "bttv: GPIO: 0x%08x\n", btread(BT848_GPIO_DATA)));
 
-       btv->type=BTTV_MIRO;
-       btv->tuner=tuner;
-  
-       if (I2CRead(btv, I2C_HAUPEE)>=0)
-               btv->type=BTTV_HAUPPAUGE;
-       else if (I2CRead(btv, I2C_STBEE)>=0)
-               btv->type=BTTV_STB;
-
-       for (i=0xc0; i<0xd0; i+=2)
+       /* Default the card to the user-selected one. */
+       btv->type=card;
+       /* If we were asked to auto-detect, then do so! 
+          Right now this will only recognize Miro, Hauppauge or STB
+          */
+       if (btv->type == BTTV_UNKNOWN) 
        {
-               if (I2CRead(btv, i)>=0) 
-               {
-                       btv->tuneradr=i;
-                       break;
-               }
+               btv->type=BTTV_MIRO;
+    
+               if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0)
+                       btv->type=BTTV_HAUPPAUGE;
+               else
+                       if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
+                               btv->type=BTTV_STB;
        }
 
-       btv->dbx = I2CRead(btv, I2C_TDA9850) ? 0 : 1;
+       btv->dbx = I2CRead(&(btv->i2c), I2C_TDA9850) ? 0 : 1;
 
        if (btv->dbx)
-               init_tda9850(btv);
+               init_tda9850(&(btv->i2c));
 
        /* How do I detect the tuner type for other cards but Miro ??? */
        printk(KERN_INFO "bttv: model: ");
        switch (btv->type) 
        {
                case BTTV_MIRO:
-                       btv->tuner=((btread(BT848_GPIO_DATA)>>10)-1)&7;
-                       printk("MIRO");
+                       printk("MIRO\n");
+                       if (btv->have_tuner) 
+                       {
+                               tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+                               i2c_control_device(&(btv->i2c),
+                                                  I2C_DRIVERID_TUNER,
+                                                  TUNER_SET_TYPE,&tunertype);
+                       }
                        strcpy(btv->video_dev.name,"BT848(Miro)");
                        break;
                case BTTV_HAUPPAUGE:
-                       printk("HAUPPAUGE");
+                       printk("HAUPPAUGE\n");
                        strcpy(btv->video_dev.name,"BT848(Hauppauge)");
                        break;
                case BTTV_STB: 
-                       printk("STB");
+                       printk("STB\n");
                        strcpy(btv->video_dev.name,"BT848(STB)");
                        break;
                case BTTV_INTEL: 
-                       printk("Intel");
+                       printk("Intel\n");
                        strcpy(btv->video_dev.name,"BT848(Intel)");
                        break;
                case BTTV_DIAMOND: 
-                       printk("Diamond");
+                       printk("Diamond\n");
                        strcpy(btv->video_dev.name,"BT848(Diamond)");
                        break;
+               case BTTV_AVERMEDIA: 
+                       printk("AVerMedia\n");
+                       strcpy(btv->video_dev.name,"BT848(AVerMedia)");
+                       break;
        }
-       printk(" (%s @ 0x%02x)\n", tuners[btv->tuner].name, btv->tuneradr);
        audio(btv, AUDIO_MUTE);
 }
 
 
+
 static void bt848_set_risc_jmps(struct bttv *btv)
 {
        int flags=btv->cap;
-  
+
+       /* Sync to start of odd field */
        btv->risc_jmp[0]=BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRE;
        btv->risc_jmp[1]=0;
 
-       btv->risc_jmp[2]=BT848_RISC_JUMP;
+       /* Jump to odd vbi sub */
+       btv->risc_jmp[2]=BT848_RISC_JUMP|(0x5<<20);
        if (flags&8)
                btv->risc_jmp[3]=virt_to_bus(btv->vbi_odd);
        else
                btv->risc_jmp[3]=virt_to_bus(btv->risc_jmp+4);
 
-       btv->risc_jmp[4]=BT848_RISC_JUMP;
+        /* Jump to odd sub */
+       btv->risc_jmp[4]=BT848_RISC_JUMP|(0x6<<20);
        if (flags&2)
                btv->risc_jmp[5]=virt_to_bus(btv->risc_odd);
        else
                btv->risc_jmp[5]=virt_to_bus(btv->risc_jmp+6);
 
+
+       /* Sync to start of even field */
        btv->risc_jmp[6]=BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRO;
        btv->risc_jmp[7]=0;
 
+       /* Jump to even vbi sub */
        btv->risc_jmp[8]=BT848_RISC_JUMP;
        if (flags&4)
                btv->risc_jmp[9]=virt_to_bus(btv->vbi_even);
        else
                btv->risc_jmp[9]=virt_to_bus(btv->risc_jmp+10);
 
-       btv->risc_jmp[10]=BT848_RISC_JUMP;
+       /* Jump to even sub */
+       btv->risc_jmp[10]=BT848_RISC_JUMP|(8<<20);
        if (flags&1)
                btv->risc_jmp[11]=virt_to_bus(btv->risc_even);
        else
-               btv->risc_jmp[11]=virt_to_bus(btv->risc_jmp);
+               btv->risc_jmp[11]=virt_to_bus(btv->risc_jmp+12);
+
+       btv->risc_jmp[12]=BT848_RISC_JUMP;
+       btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
 
+       /* enable cpaturing and DMA */
        btaor(flags, ~0x0f, BT848_CAP_CTL);
        if (flags&0x0f)
                bt848_dma(btv, 3);
@@ -1653,12 +2298,15 @@ static void bt848_set_risc_jmps(struct bttv *btv)
 }
 
 
-static int init_bt848(struct bttv *btv)
+static int init_bt848(int i)
 {
-       /* reset the bt848 */
-       btwrite(0,BT848_SRESET);
+        struct bttv *btv = &bttvs[i];
+
        btv->user=0; 
 
+       /* reset the bt848 */
+       btwrite(0, BT848_SRESET);
+
        DEBUG(printk(KERN_DEBUG "bttv: bt848_mem: 0x%08x\n",(unsigned int) btv->bt848_mem));
 
        /* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
@@ -1674,43 +2322,66 @@ static int init_bt848(struct bttv *btv)
        btv->win.cropx=0;
        btv->win.cropy=0;
        btv->win.bpp=2;
+       btv->win.color_fmt=BT848_COLOR_FMT_RGB16;
        btv->win.bpl=1024*btv->win.bpp;
        btv->win.swidth=1024;
        btv->win.sheight=768;
        btv->cap=0;
 
-       if (!(btv->risc_odd=(dword *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
+       btv->gmode=0;
+       btv->risc_odd=0;
+       btv->risc_even=0;
+       btv->risc_jmp=0;
+       btv->vbibuf=0;
+       btv->grisc=0;
+       btv->grabbing=0;
+       btv->grabcount=0;
+       btv->grab=0;
+       btv->lastgrab=0;
+
+       /* i2c */
+       memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus));
+       sprintf(btv->i2c.name,"bt848-%d",i);
+       btv->i2c.data = btv;
+
+       if (!(btv->risc_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
                return -1;
-       if (!(btv->risc_even=(dword *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
+       if (!(btv->risc_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
                return -1;
-       if (!(btv->risc_jmp =(dword *) kmalloc(2048, GFP_KERNEL)))
+       if (!(btv->risc_jmp =(unsigned int *) kmalloc(2048, GFP_KERNEL)))
                return -1;
-       btv->vbi_odd=btv->risc_jmp+12;
+       DEBUG(printk(KERN_DEBUG "risc_jmp: %p\n",btv->risc_jmp));
+       btv->vbi_odd=btv->risc_jmp+16;
        btv->vbi_even=btv->vbi_odd+256;
-       btv->bus_vbi_odd=virt_to_bus(btv->risc_jmp);
+       btv->bus_vbi_odd=virt_to_bus(btv->risc_jmp+12);
        btv->bus_vbi_even=virt_to_bus(btv->risc_jmp+6);
 
        btwrite(virt_to_bus(btv->risc_jmp+2), BT848_RISC_STRT_ADD);
-       btv->vbibuf=(unchar *) vmalloc(VBIBUF_SIZE);
+       btv->vbibuf=(unsigned char *) vmalloc(VBIBUF_SIZE);
        if (!btv->vbibuf) 
                return -1;
+       if (!(btv->grisc=(unsigned int *) kmalloc(16384, GFP_KERNEL)))
+               return -1;
+
+       btv->fbuffer=NULL;
 
        bt848_muxsel(btv, 1);
-       bt848_set_size(btv);
+       bt848_set_winsize(btv);
 
 /*     btwrite(0, BT848_TDEC); */
        btwrite(0x10, BT848_COLOR_CTL);
        btwrite(0x00, BT848_CAP_CTL);
+       btwrite(0xfc, BT848_GPIO_DMA_CTL);
 
        btwrite(0x0ff, BT848_VBI_PACK_SIZE);
        btwrite(1, BT848_VBI_PACK_DEL);
 
-       btwrite(0xfc, BT848_GPIO_DMA_CTL);
+               
        btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_PAL_BDGHI,
                BT848_IFORM);
 
-       bt848_bright(btv, 0x10);
        btwrite(0xd8, BT848_CONTRAST_LO);
+       bt848_bright(btv, 0x10);
 
        btwrite(0x60, BT848_E_VSCALE_HI);
        btwrite(0x60, BT848_O_VSCALE_HI);
@@ -1719,19 +2390,27 @@ static int init_bt848(struct bttv *btv)
 
        btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
        btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
+
+       btv->picture.colour=254<<7;
+       btv->picture.brightness=128<<8;
+       btv->picture.hue=128<<8;
+       btv->picture.contrast=0xd8<<7;
+
        btwrite(0x00, BT848_E_SCLOOP);
        btwrite(0x00, BT848_O_SCLOOP);
 
-       btwrite(0xffffffUL,BT848_INT_STAT);
-/*       BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|BT848_INT_FDSR|
-         BT848_INT_FTRGT|BT848_INT_FBUS|*/
-       btwrite(BT848_INT_ETBF|
+       /* clear interrupt status */
+       btwrite(0xfffffUL, BT848_INT_STAT);
+        
+       /* set interrupt mask */
+       btwrite(triton1|
+/*             BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|
+               BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/
                BT848_INT_SCERR|
                BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
                BT848_INT_FMTCHG|BT848_INT_HLOCK,
                BT848_INT_MASK);
 
-/*     make_risctab(btv); */
        make_vbitab(btv);
        bt848_set_risc_jmps(btv);
   
@@ -1739,20 +2418,32 @@ static int init_bt848(struct bttv *btv)
         *      Now add the template and register the device unit.
         */
 
-       memcpy(&btv->video_dev,&bttv_template,sizeof(bttv_template));
+       memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
+       memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
+       memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
        idcard(btv);
-       
-       btv->picture.brightness=0x90<<8;
-       btv->picture.contrast = 0x70 << 8;
-       btv->picture.colour = 0x70<<8;
-       btv->picture.hue = 0x8000;
-       
-       if(video_register_device(&btv->video_dev)<0)
+
+       if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
                return -1;
+       if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI)<0) 
+        {
+               video_unregister_device(&btv->video_dev);
+               return -1;
+       }
+       if (radio)
+       {
+               if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) 
+                {
+                       video_unregister_device(&btv->vbi_dev);
+                       video_unregister_device(&btv->video_dev);
+                       return -1;
+               }
+       }
+       i2c_register_bus(&btv->i2c);
+
        return 0;
 }
 
-
 static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
 {
        u32 stat,astat;
@@ -1779,7 +2470,8 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                if (astat&BT848_INT_FMTCHG) 
                {
                        IDEBUG(printk ("bttv: IRQ_FMTCHG\n"));
-/*                     btv->win.norm&=(dstat&BT848_DSTATUS_NUML) ? (~1) : (~0); */
+                       /*btv->win.norm&=
+                         (dstat&BT848_DSTATUS_NUML) ? (~1) : (~0); */
                }
                if (astat&BT848_INT_VPRES) 
                {
@@ -1795,22 +2487,47 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                        bt848_dma(btv, 1);
                        wake_up_interruptible(&btv->vbiq);
                        wake_up_interruptible(&btv->capq);
+
                }
                if (astat&BT848_INT_RISCI) 
                {
                        IDEBUG(printk ("bttv: IRQ_RISCI\n"));
-                       /* printk ("bttv: IRQ_RISCI%d\n",stat>>28); */
+
+                       /* captured VBI frame */
                        if (stat&(1<<28)) 
                        {
                                btv->vbip=0;
                                wake_up_interruptible(&btv->vbiq);
                        }
+
+                       /* captured full frame */
                        if (stat&(2<<28)) 
                        {
-                               bt848_set_risc_jmps(btv);
+                               btv->grab++;
                                wake_up_interruptible(&btv->capq);
+                               if ((--btv->grabbing))
+                               {
+                                        btv->risc_jmp[5]=btv->gro;
+                                       btv->risc_jmp[11]=btv->gre;
+                                       bt848_set_geo(btv, btv->gwidth,
+                                                     btv->gheight,
+                                                     btv->gfmt);
+                               } else {
+                                       bt848_set_risc_jmps(btv);
+                                       bt848_set_geo(btv, btv->win.width, 
+                                                     btv->win.height,
+                                                     btv->win.color_fmt);
+                               }
                                break;
                        }
+                       if (stat&(8<<28)) 
+                       {
+                               btv->risc_jmp[5]=btv->gro;
+                               btv->risc_jmp[11]=btv->gre;
+                               btv->risc_jmp[12]=BT848_RISC_JUMP;
+                               bt848_set_geo(btv, btv->gwidth, btv->gheight,
+                                             btv->gfmt);
+                       }
                }
                if (astat&BT848_INT_OCERR) 
                {
@@ -1842,7 +2559,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                }
                if (astat&BT848_INT_HLOCK) 
                {
-                       if (dstat&BT848_DSTATUS_HLOC)
+                       if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio))
                                audio(btv, AUDIO_ON);
                        else
                                audio(btv, AUDIO_OFF);
@@ -1858,12 +2575,14 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
                if (count > 20) 
                {
                        btwrite(0, BT848_INT_MASK);
-                       printk(KERN_ERR "bttv: IRQ lockup, cleared int mask\n");
+                       printk(KERN_ERR 
+                              "bttv: IRQ lockup, cleared int mask\n");
                }
        }
 }
 
 
+
 /*
  *     Scan for a Bt848 card, request the irq and map the io memory 
  */
@@ -1885,8 +2604,10 @@ static int find_bt848(void)
        }
 
        for (pci_index = 0;
-               !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
-                           pci_index, &bus, &devfn);
+                !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
+                                    pci_index, &bus, &devfn)
+             ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
+                                   pci_index, &bus, &devfn);
                ++pci_index) 
        {
                btv=&bttvs[bttv_num];
@@ -1899,8 +2620,13 @@ static int find_bt848(void)
                btv->vbi_even=NULL;
                btv->vbiq=NULL;
                btv->capq=NULL;
+               btv->capqo=NULL;
+               btv->capqe=NULL;
+
                btv->vbip=VBIBUF_SIZE;
 
+               pcibios_read_config_word(btv->bus, btv->devfn, PCI_DEVICE_ID,
+                                        &btv->id);
                pcibios_read_config_byte(btv->bus, btv->devfn,
                        PCI_INTERRUPT_LINE, &btv->irq);
                pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
@@ -1921,7 +2647,8 @@ static int find_bt848(void)
                btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
                pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION,
                             &btv->revision);
-               printk(KERN_INFO "bttv: Brooktree Bt848 (rev %d) ",btv->revision);
+               printk(KERN_INFO "bttv: Brooktree Bt%d (rev %d) ",
+                      btv->id, btv->revision);
                printk("bus: %d, devfn: %d, ",
                        btv->bus, btv->devfn);
                printk("irq: %d, ",btv->irq);
@@ -1959,8 +2686,8 @@ static int find_bt848(void)
                if (!latency) 
                {
                        latency=32;
-                       pcibios_write_config_byte(btv->bus, btv->devfn, PCI_LATENCY_TIMER,
-                               latency);
+                       pcibios_write_config_byte(btv->bus, btv->devfn,
+                                                 PCI_LATENCY_TIMER, latency);
                }
                DEBUG(printk(KERN_DEBUG "bttv: latency: %02x\n", latency));
                bttv_num++;
@@ -1970,6 +2697,7 @@ static int find_bt848(void)
        return bttv_num;
 }
 
+
 static void release_bttv(void)
 {
        u8 command;
@@ -1979,21 +2707,28 @@ static void release_bttv(void)
        for (i=0;i<bttv_num; i++) 
        {
                btv=&bttvs[i];
+
                /* turn off all capturing, DMA and IRQs */
 
+               btand(~15, BT848_GPIO_DMA_CTL);
+
                /* first disable interrupts before unmapping the memory! */
                btwrite(0, BT848_INT_MASK);
                btwrite(0xffffffffUL,BT848_INT_STAT);
                btwrite(0x0, BT848_GPIO_OUT_EN);
 
-               bt848_cap(btv, 0);
-    
+               /* unregister i2c_bus */
+               i2c_unregister_bus((&btv->i2c));
+
                /* disable PCI bus-mastering */
                pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
                command|=PCI_COMMAND_MASTER;
                pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
     
                /* unmap and free memory */
+               if (btv->grisc)
+                       kfree((void *) btv->grisc);
+
                if (btv->risc_odd)
                        kfree((void *) btv->risc_odd);
                        
@@ -2007,15 +2742,20 @@ static void release_bttv(void)
                DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%08x.\n", btv->vbibuf));
                if (btv->vbibuf)
                        vfree((void *) btv->vbibuf);
+
+
                free_irq(btv->irq,btv);
                DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%08x.\n", btv->bt848_mem));
                if (btv->bt848_mem)
                        iounmap(btv->bt848_mem);
+
                video_unregister_device(&btv->video_dev);
+               video_unregister_device(&btv->vbi_dev);
+               if (radio)
+                       video_unregister_device(&btv->radio_dev);
        }
 }
 
-
 #ifdef MODULE
 
 int init_module(void)
@@ -2030,22 +2770,39 @@ int init_bttv_cards(struct video_init *unused)
        if (find_bt848()<0)
                return -EIO;
 
+       /* initialize Bt848s */
        for (i=0; i<bttv_num; i++) 
        {
-               if (init_bt848(&bttvs[i])<0) 
+               if (init_bt848(i)<0) 
                {
                        release_bttv();
                        return -EIO;
                } 
-       }  
+       }
        return 0;
 }
 
+
+
 #ifdef MODULE
 
 void cleanup_module(void)
 {
-       release_bttv();
+        release_bttv();
 }
 
 #endif
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
index e1c54e94c9fb410f3fba715ca16a957c1ee54962..ca0fb057c655fd68526eca159fb8b6a7f37b8fa5 100644 (file)
 #include <linux/types.h>
 #include <linux/wait.h>
 
+#include "i2c.h"
+#include "msp3400.h"
 #include "bt848.h"
+#include <linux/videodev.h>
 
-typedef unsigned int dword;
+#define MAX_CLIPRECS   100
+#define RISCMEM_LEN    (32744*2)
+#define MAX_FBUF       0x144000
 
-struct riscprog {
-  uint length;  
-  dword *busadr;
-  dword *prog;
+struct riscprog 
+{
+       unsigned int length;  
+       u32 *busadr;
+       u32 *prog;
 };
 
-/* values that can be set by user programs */
-
-struct bttv_window {
-  int x, y;
-  ushort width, height;
-  ushort bpp, bpl;
-  ushort swidth, sheight;
-  short cropx, cropy;
-  ushort cropwidth, cropheight;
-  int vidadr;
-  ushort freq;
-  int norm;
-  int interlace;
-  int color_fmt;
+
+/* clipping rectangle */
+struct cliprec 
+{
+       int x, y, x2, y2;
+       struct cliprec *next;
+};
+
+
+/* grab buffer */
+struct gbuffer 
+{
+       struct gbuffer *next;
+       struct gbuffer *next_active;
+       void *adr;
+       int x, y;
+       int width, height;
+       unsigned int bpl;
+       unsigned int fmt;
+       int flags;
+#define GBUF_ODD  1
+#define GBUF_EVEN 2
+#define GBUF_LFB  4
+#define GBUF_INT  8
+       unsigned int length;
+       void *ro;
+       void *re;
+       u32 bro;
+       u32 bre;
+};
+
+
+#ifdef __KERNEL__
+
+struct bttv_window 
+{
+       int x, y;
+       ushort width, height;
+       ushort bpp, bpl;
+       ushort swidth, sheight;
+       short cropx, cropy;
+       ushort cropwidth, cropheight;
+       unsigned int vidadr;
+       ushort freq;
+       int norm;
+       int interlace;
+       int color_fmt;
 };
 
-/* private data that can only be read (or set indirectly) by user program */
-
-struct bttv {
-  struct video_device video_dev;
-  struct video_picture picture;                /* Current picture params */
-  struct video_audio audio_dev;                /* Current audio params */
-  u_char bus;          /* PCI bus the Bt848 is on */
-  u_char devfn;
-  u_char revision;
-  u_char irq;          /* IRQ used by Bt848 card */
-  uint bt848_adr;      /* bus address of IO mem returned by PCI BIOS */
-  u_char *bt848_mem;   /* pointer to mapped IO memory */
-  ulong busriscmem; 
-  dword *riscmem;
+
+struct bttv 
+{
+       struct video_device video_dev;
+       struct video_device radio_dev;
+       struct video_device vbi_dev;
+       struct video_picture picture;           /* Current picture params */
+       struct video_audio audio_dev;           /* Current audio params */
+
+       struct i2c_bus i2c;
+       int have_msp3400;
+       int have_tuner;
+
+       unsigned short id;
+       unsigned char bus;          /* PCI bus the Bt848 is on */
+       unsigned char devfn;
+       unsigned char revision;
+       unsigned char irq;          /* IRQ used by Bt848 card */
+       unsigned int bt848_adr;      /* bus address of IO mem returned by PCI BIOS */
+       unsigned char *bt848_mem;   /* pointer to mapped IO memory */
+       unsigned long busriscmem; 
+       u32 *riscmem;
   
-  u_char *vbibuf;
-  struct bttv_window win;
-  int type;            /* card type  */
-  int audio;           /* audio mode */
-  int user;
-  int tuner;
-  int tuneradr;
-  int dbx;
-
-  dword *risc_jmp;
-  dword *vbi_odd;
-  dword *vbi_even;
-  dword bus_vbi_even;
-  dword bus_vbi_odd;
-  struct wait_queue *vbiq;
-  struct wait_queue *capq;
-  int vbip;
-
-  dword *risc_odd;
-  dword *risc_even;
-  int cap;
+       unsigned char *vbibuf;
+       struct bttv_window win;
+       int type;            /* card type  */
+       int audio;           /* audio mode */
+       int user;
+       int dbx;
+       int radio;
+
+       u32 *risc_jmp;
+       u32 *vbi_odd;
+       u32 *vbi_even;
+       u32 bus_vbi_even;
+       u32 bus_vbi_odd;
+       struct wait_queue *vbiq;
+       struct wait_queue *capq;
+       struct wait_queue *capqo;
+       struct wait_queue *capqe;
+       int vbip;
+
+       u32 *risc_odd;
+       u32 *risc_even;
+       int cap;
+       struct cliprec *cliprecs;
+       int ncr;                /* number of clipping rectangles */
+
+       struct gbuffer *ogbuffers;
+       struct gbuffer *egbuffers;
+       u16 gwidth, gheight, gfmt;
+       u32 *grisc;
+       unsigned long gro;
+       unsigned long gre;
+       char *fbuffer;
+       int gmode;
+       int grabbing;
+       int lastgrab;
+       int grab;
+       int grabcount;
 };
 
+#endif
+
 /*The following should be done in more portable way. It depends on define
   of _ALPHA_BTTV in the Makefile.*/
+
 #ifdef _ALPHA_BTTV
 #define btwrite(dat,adr)    writel((dat),(char *) (btv->bt848_adr+(adr)))
 #define btread(adr)         readl(btv->bt848_adr+(adr))
@@ -105,30 +171,10 @@ struct bttv {
 #define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
 
 /* bttv ioctls */
-#define BTTV_WRITE_BTREG   0x00
-#define BTTV_READ_BTREG    0x01
-#define BTTV_SET_BTREG     0x02
-#define BTTV_SETRISC       0x03
-#define BTTV_SETWTW        0x04
-#define BTTV_GETWTW        0x05
-#define BTTV_DMA           0x06
-#define BTTV_CAP_OFF       0x07
-#define BTTV_CAP_ON        0x08
-#define BTTV_GETBTTV       0x09
-#define BTTV_SETFREQ       0x0a
-#define BTTV_SETCHAN       0x0b
-#define BTTV_INPUT         0x0c
-#define BTTV_READEE        0x0d
-#define BTTV_WRITEEE       0x0e
-#define BTTV_BRIGHT        0x0f
-#define BTTV_HUE           0x10
-#define BTTV_COLOR         0x11
-#define BTTV_CONTRAST      0x12
-#define BTTV_SET_FFREQ     0x13
-#define BTTV_MUTE          0x14
-
-#define BTTV_GRAB          0x20
-#define BTTV_TESTM         0x20
+
+#define BTTV_READEE            _IOW('v',  BASE_VIDIOCPRIVATE+0, char [256])
+#define BTTV_WRITEE            _IOR('v',  BASE_VIDIOCPRIVATE+1, char [256])
+#define BTTV_GRAB              _IOR('v' , BASE_VIDIOCPRIVATE+2, struct gbuf)
 
 
 #define BTTV_UNKNOWN       0x00
@@ -137,12 +183,14 @@ struct bttv {
 #define BTTV_STB           0x03
 #define BTTV_INTEL         0x04
 #define BTTV_DIAMOND       0x05 
+#define BTTV_AVERMEDIA     0x06 
 
 #define AUDIO_TUNER        0x00
-#define AUDIO_EXTERN       0x01
-#define AUDIO_INTERN       0x02
-#define AUDIO_OFF          0x03 
-#define AUDIO_ON           0x04
+#define AUDIO_RADIO        0x01
+#define AUDIO_EXTERN       0x02
+#define AUDIO_INTERN       0x03
+#define AUDIO_OFF          0x04 
+#define AUDIO_ON           0x05
 #define AUDIO_MUTE         0x80
 #define AUDIO_UNMUTE       0x81
 
index 48951cdb8ef10b90b4dbda0c2759c7e8e615416d..2142cf6a1db92184c6ef6f9df497af8f02ba3766 100644 (file)
@@ -885,7 +885,7 @@ int init_bwqcam(struct parport *port)
        
        printk(KERN_INFO "Connectix Quickcam on %s\n", qcam->pport->name);
        
-       if(video_register_device(&qcam->vdev)==-1)
+       if(video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
        {
                parport_unregister_device(qcam->pdev);
                kfree(qcam);
index a69684110495bd0439cc0283a10b411831005826..e424266c862e7ad46558976bc2771df304dc55d7 100644 (file)
@@ -727,7 +727,7 @@ int init_cqcam(struct parport *port)
        printk(KERN_INFO "Connectix Colour Quickcam on %s\n", 
               qcam->pport->name);
        
-       if (video_register_device(&qcam->vdev)==-1)
+       if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
        {
                parport_unregister_device(qcam->pdev);
                kfree(qcam);
index 73634b1db191b0dd62d452f22b42b3d6b74f857c..dc437cc2f083888b41819b4970a08bd83e72375c 100644 (file)
@@ -204,7 +204,6 @@ int last_console = 0;
 int want_console = -1;
 int kmsg_redirect = 0;
 
-#define CONFIG_SERIAL_ECHO
 #ifdef CONFIG_SERIAL_ECHO
 
 #include <linux/serial_reg.h>
index c99b963d89c14492af5695cd88bf1f71fd6190fc..d60651b1b173eadb610376ef3655e35e8b46256b 100644 (file)
@@ -62,7 +62,7 @@ int main(int argc, char *argv[])
        printf("/*\n * This file is automatically generated by %s, DO NOT EDIT!\n*/\n\n",
               argv[0]);
        gensintbl();
-       return(0);
+       exit(0);
 }
 
 /* --------------------------------------------------------------------- */
diff --git a/drivers/char/i2c.c b/drivers/char/i2c.c
new file mode 100644 (file)
index 0000000..5507d94
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ *     Generic i2c interface for linux
+ *
+ *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/locks.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+
+#include "i2c.h"
+
+#define REGPRINT(x)   if (verbose)   (x)
+#define I2C_DEBUG(x)  if (i2c_debug) (x)
+
+static int scan      = 0;
+static int verbose   = 1;
+static int i2c_debug = 0;
+
+MODULE_PARM(scan,"i");
+MODULE_PARM(verbose,"i");
+MODULE_PARM(i2c_debug,"i");
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_bus    *busses[I2C_BUS_MAX];
+static struct i2c_driver *drivers[I2C_DRIVER_MAX];
+static int bus_count = 0, driver_count = 0;
+
+int i2c_init(void)
+{
+       printk(KERN_INFO "i2c: initialized%s\n",
+               scan ? " (i2c bus scan enabled)" : "");
+       /* anything to do here ? */
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void i2c_attach_device(struct i2c_bus *bus, struct i2c_driver *driver)
+{
+       unsigned long flags;
+       struct i2c_device *device;
+       int i,j,ack=1;
+       unsigned char addr;
+    
+       /* probe for device */
+       LOCK_I2C_BUS(bus);
+       for (addr = driver->addr_l; addr <= driver->addr_h; addr += 2) 
+       {
+               i2c_start(bus);
+               ack = i2c_sendbyte(bus,addr,0);
+               i2c_stop(bus);
+               if (!ack)
+                       break;
+       }
+       UNLOCK_I2C_BUS(bus);
+       if (ack)
+               return;
+
+       /* got answer */
+       for (i = 0; i < I2C_DEVICE_MAX; i++)
+               if (NULL == driver->devices[i])
+                       break;
+       if (I2C_DEVICE_MAX == i)
+               return;
+
+       for (j = 0; j < I2C_DEVICE_MAX; j++)
+               if (NULL == bus->devices[j])
+                       break;
+       if (I2C_DEVICE_MAX == j)
+               return;
+
+       if (NULL == (device = kmalloc(sizeof(struct i2c_device),GFP_KERNEL)))
+               return;
+       device->bus = bus;
+       device->driver = driver;
+       device->addr = addr;
+
+       /* Attach */
+       
+       if (driver->attach(device)!=0) 
+       {
+               kfree(device);
+               return;
+       }
+       driver->devices[i] = device;
+       driver->devcount++;
+       bus->devices[j] = device;
+       bus->devcount++;
+
+       if (bus->attach_inform)
+               bus->attach_inform(bus,driver->id);
+       REGPRINT(printk("i2c: device attached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,addr,bus->name,driver->name));
+}
+
+static void i2c_detach_device(struct i2c_device *device)
+{
+       int i;
+
+       if (device->bus->detach_inform)
+               device->bus->detach_inform(device->bus,device->driver->id);
+       device->driver->detach(device);
+
+       for (i = 0; i < I2C_DEVICE_MAX; i++)
+               if (device == device->driver->devices[i])
+                       break;
+       if (I2C_DEVICE_MAX == i) 
+       {
+               printk(KERN_WARNING "i2c: detach_device #1: device not found: %s\n",
+                       device->name);
+               return;
+       }
+       device->driver->devices[i] = NULL;
+       device->driver->devcount--;
+
+       for (i = 0; i < I2C_DEVICE_MAX; i++)
+               if (device == device->bus->devices[i])
+                       break;
+       if (I2C_DEVICE_MAX == i) 
+       {
+               printk(KERN_WARNING "i2c: detach_device #2: device not found: %s\n",
+                      device->name);
+               return;
+       }
+       device->bus->devices[i] = NULL;
+       device->bus->devcount--;
+
+       REGPRINT(printk("i2c: device detached: %s (addr=0x%02x, bus=%s, driver=%s)\n",device->name,device->addr,device->bus->name,device->driver->name));
+       kfree(device);
+}
+
+/* ----------------------------------------------------------------------- */
+
+int i2c_register_bus(struct i2c_bus *bus)
+{
+       unsigned long flags;
+       int i,ack;
+
+       memset(bus->devices,0,sizeof(bus->devices));
+       bus->devcount = 0;
+
+       for (i = 0; i < I2C_BUS_MAX; i++)
+               if (NULL == busses[i])
+                       break;
+       if (I2C_BUS_MAX == i)
+               return -ENOMEM;
+
+       busses[i] = bus;
+       bus_count++;
+       REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
+       
+       MOD_INC_USE_COUNT;
+
+       if (scan) 
+       {
+               /* scan whole i2c bus */
+               LOCK_I2C_BUS(bus);
+               for (i = 0; i < 256; i+=2) 
+               {
+                       i2c_start(bus);
+                       ack = i2c_sendbyte(bus,i,0);
+                       i2c_stop(bus);
+                       if (!ack) 
+                       {
+                               printk(KERN_INFO "i2c: scanning bus %s: found device at addr=0x%02x\n",
+                                       bus->name,i);
+                       }
+               }
+               UNLOCK_I2C_BUS(bus);
+       }
+
+       /* probe available drivers */
+       for (i = 0; i < I2C_DRIVER_MAX; i++)
+               if (drivers[i])
+                       i2c_attach_device(bus,drivers[i]);
+       return 0;
+}
+
+int i2c_unregister_bus(struct i2c_bus *bus)
+{
+       int i;
+
+       /* detach devices */
+       for (i = 0; i < I2C_DEVICE_MAX; i++)
+               if (bus->devices[i])
+                       i2c_detach_device(bus->devices[i]);
+
+       for (i = 0; i < I2C_BUS_MAX; i++)
+               if (bus == busses[i])
+                       break;
+       if (I2C_BUS_MAX == i) 
+       {
+               printk(KERN_WARNING "i2c: unregister_bus #1: bus not found: %s\n",
+                       bus->name);
+               return -ENODEV;
+       }
+       
+       MOD_DEC_USE_COUNT;
+       
+       busses[i] = NULL;
+       bus_count--;
+       REGPRINT(printk("i2c: bus unregistered: %s\n",bus->name));
+
+       return 0;    
+}
+
+/* ----------------------------------------------------------------------- */
+
+int i2c_register_driver(struct i2c_driver *driver)
+{
+       int i;
+
+       memset(driver->devices,0,sizeof(driver->devices));
+       driver->devcount = 0;
+
+       for (i = 0; i < I2C_DRIVER_MAX; i++)
+               if (NULL == drivers[i])
+                       break;
+       if (I2C_DRIVER_MAX == i)
+               return -ENOMEM;
+
+       drivers[i] = driver;
+       driver_count++;
+       
+       MOD_INC_USE_COUNT;
+       
+       REGPRINT(printk("i2c: driver registered: %s\n",driver->name));
+
+       /* Probe available busses */
+       for (i = 0; i < I2C_BUS_MAX; i++)
+               if (busses[i])
+                       i2c_attach_device(busses[i],driver);
+
+       return 0;
+}
+
+int i2c_unregister_driver(struct i2c_driver *driver)
+{
+       int i;
+
+       /* detach devices */
+       for (i = 0; i < I2C_DEVICE_MAX; i++)
+               if (driver->devices[i])
+                       i2c_detach_device(driver->devices[i]);
+
+       for (i = 0; i < I2C_DRIVER_MAX; i++)
+               if (driver == drivers[i])
+                       break;
+       if (I2C_DRIVER_MAX == i) 
+       {
+               printk(KERN_WARNING "i2c: unregister_driver: driver not found: %s\n",
+                       driver->name);
+               return -ENODEV;
+       }
+
+       MOD_DEC_USE_COUNT;
+       
+       drivers[i] = NULL;
+       driver_count--;
+       REGPRINT(printk("i2c: driver unregistered: %s\n",driver->name));
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int i2c_control_device(struct i2c_bus *bus, int id,
+                      unsigned int cmd, void *arg)
+{
+       int i;
+
+       for (i = 0; i < I2C_DEVICE_MAX; i++)
+               if (bus->devices[i] && bus->devices[i]->driver->id == id)
+                       break;
+       if (i == I2C_DEVICE_MAX)
+               return -ENODEV;
+       if (NULL == bus->devices[i]->driver->command)
+               return -ENODEV;
+       return bus->devices[i]->driver->command(bus->devices[i],cmd,arg);
+}
+
+/* ----------------------------------------------------------------------- */
+
+#define I2C_SET(bus,ctrl,data)  (bus->i2c_setlines(bus,ctrl,data))
+#define I2C_GET(bus)            (bus->i2c_getdataline(bus))
+
+void i2c_start(struct i2c_bus *bus)
+{
+       I2C_SET(bus,0,1);
+       I2C_SET(bus,1,1);
+       I2C_SET(bus,1,0);
+       I2C_SET(bus,0,0);
+       I2C_DEBUG(printk("%s: < ",bus->name));
+}
+
+void i2c_stop(struct i2c_bus *bus)
+{
+       I2C_SET(bus,0,0);
+       I2C_SET(bus,1,0);
+       I2C_SET(bus,1,1);
+       I2C_DEBUG(printk(">\n"));
+}
+
+void i2c_one(struct i2c_bus *bus)
+{
+       I2C_SET(bus,0,1);
+       I2C_SET(bus,1,1);
+       I2C_SET(bus,0,1);
+}
+
+void i2c_zero(struct i2c_bus *bus)
+{
+       I2C_SET(bus,0,0);
+       I2C_SET(bus,1,0);
+       I2C_SET(bus,0,0);
+}
+
+int i2c_ack(struct i2c_bus *bus)
+{
+       int ack;
+    
+       I2C_SET(bus,0,1);
+       I2C_SET(bus,1,1);
+       ack = I2C_GET(bus);
+       I2C_SET(bus,0,1);
+       return ack;
+}
+
+int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack)
+{
+       int i, ack;
+    
+       I2C_SET(bus,0,0);
+       for (i=7; i>=0; i--)
+               (data&(1<<i)) ? i2c_one(bus) : i2c_zero(bus);
+       if (wait_for_ack)
+               udelay(wait_for_ack);
+       ack=i2c_ack(bus);
+       I2C_DEBUG(printk("%02x%c ",(int)data,ack?'-':'+'));
+       return ack;
+}
+
+unsigned char i2c_readbyte(struct i2c_bus *bus,int last)
+{
+       int i;
+       unsigned char data=0;
+    
+       I2C_SET(bus,0,1);
+       for (i=7; i>=0; i--) 
+       {
+               I2C_SET(bus,1,1);
+               if (I2C_GET(bus))
+                       data |= (1<<i);
+               I2C_SET(bus,0,1);
+       }
+       last ? i2c_one(bus) : i2c_zero(bus);
+       I2C_DEBUG(printk("=%02x%c ",(int)data,last?'-':'+'));
+       return data;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int i2c_read(struct i2c_bus *bus, unsigned char addr)
+{
+       int ret;
+    
+       if (bus->i2c_read)
+               return bus->i2c_read(bus, addr);
+
+       i2c_start(bus);
+       i2c_sendbyte(bus,addr,0);
+       ret = i2c_readbyte(bus,1);
+       i2c_stop(bus);
+       return ret;
+}
+
+int i2c_write(struct i2c_bus *bus, unsigned char addr,
+             unsigned char data1, unsigned char data2, int both)
+{
+       int ack;
+
+       if (bus->i2c_write)
+               return bus->i2c_write(bus, addr, data1, data2, both);
+
+       i2c_start(bus);
+       i2c_sendbyte(bus,addr,0);
+       ack = i2c_sendbyte(bus,data1,0);
+       if (both)
+               ack = i2c_sendbyte(bus,data2,0);
+       i2c_stop(bus);
+       return ack ? -1 : 0 ;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef MODULE
+
+EXPORT_SYMBOL(i2c_register_bus);
+EXPORT_SYMBOL(i2c_unregister_bus);
+EXPORT_SYMBOL(i2c_register_driver);
+EXPORT_SYMBOL(i2c_unregister_driver);
+EXPORT_SYMBOL(i2c_control_device);
+EXPORT_SYMBOL(i2c_start);
+EXPORT_SYMBOL(i2c_stop);
+EXPORT_SYMBOL(i2c_one);
+EXPORT_SYMBOL(i2c_zero);
+EXPORT_SYMBOL(i2c_ack);
+EXPORT_SYMBOL(i2c_sendbyte);
+EXPORT_SYMBOL(i2c_readbyte);
+EXPORT_SYMBOL(i2c_read);
+EXPORT_SYMBOL(i2c_write);
+
+
+int init_module(void)
+{
+       return i2c_init();
+}
+
+void cleanup_module(void)
+{
+}
+#endif
diff --git a/drivers/char/i2c.h b/drivers/char/i2c.h
new file mode 100644 (file)
index 0000000..66aef22
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef I2C_H
+#define I2C_H
+
+/*
+ * linux i2c interface.  Works a little bit like the scsi subsystem.
+ * There are:
+ *
+ *     i2c          the basic control module        (like scsi_mod)
+ *     bus driver   a driver with a i2c bus         (hostadapter driver)
+ *     chip driver  a driver for a chip connected
+ *                  to a i2c bus                    (cdrom/hd driver)
+ *
+ * A device will be attached to one bus and one chip driver.  Every chip
+ * driver gets a unique ID.
+ *
+ * A chip driver can provide a ioctl-like callback for the
+ * communication with other parts of the kernel (not every i2c chip is
+ * useful without other devices, a TV card tuner for example). 
+ *
+ * "i2c internal" parts of the structs: only the i2c module is allowed to
+ * write to them, for others they are read-only.
+ *
+ */
+
+#define I2C_BUS_MAX       4    /* max # of bus drivers  */
+#define I2C_DRIVER_MAX    8    /* max # of chip drivers */
+#define I2C_DEVICE_MAX    8    /* max # if devices per bus/driver */
+
+struct i2c_bus;
+struct i2c_driver;
+struct i2c_device;
+
+#define I2C_DRIVERID_MSP3400     1
+#define I2C_DRIVERID_TUNER       2
+#define I2C_DRIVERID_VIDEOTEXT  3
+
+#define I2C_BUSID_BT848                1       /* I2C bus on a BT848 */
+
+/*
+ * struct for a driver for a i2c chip (tuner, soundprocessor,
+ * videotext, ... ).
+ *
+ * a driver will register within the i2c module.  The i2c module will
+ * callback the driver (i2c_attach) for every device it finds on a i2c
+ * bus at the specified address.  If the driver decides to "accept"
+ * the, device, it must return a struct i2c_device, and NULL
+ * otherwise.
+ *
+ * i2c_detach = i2c_attach ** -1
+ * 
+ * i2c_command will be used to pass commands to the driver in a
+ * ioctl-line manner.
+ *
+ */
+
+struct i2c_driver 
+{
+    char           name[32];         /* some useful label         */
+    int            id;               /* device type ID            */
+    unsigned char  addr_l, addr_h;   /* address range of the chip */
+
+    int (*attach)(struct i2c_device *device);
+    int (*detach)(struct i2c_device *device);
+    int (*command)(struct i2c_device *device,unsigned int cmd, void *arg);
+
+    /* i2c internal */
+    struct i2c_device   *devices[I2C_DEVICE_MAX];
+    int                 devcount;
+};
+
+
+/*
+ * this holds the informations about a i2c bus available in the system.
+ * 
+ * a chip with a i2c bus interface (like bt848) registers the bus within
+ * the i2c module. This struct provides functions to access the i2c bus.
+ * 
+ * One must hold the spinlock to access the i2c bus (XXX: is the irqsave
+ * required? Maybe better use a semaphore?). 
+ * [-AC-] having a spinlock_irqsave is only needed if we have drivers wishing
+ *       to bang their i2c bus from an interrupt.
+ * 
+ * attach/detach_inform is a callback to inform the bus driver about
+ * attached chip drivers.
+ *
+ */
+
+/* needed: unsigned long flags */
+
+#define LOCK_I2C_BUS(bus)    spin_lock_irqsave(&(bus->bus_lock),flags);
+#define UNLOCK_I2C_BUS(bus)  spin_unlock_irqrestore(&(bus->bus_lock),flags);
+
+struct i2c_bus 
+{
+       char  name[32];         /* some useful label */
+       int   id;
+       void  *data;            /* free for use by the bus driver */
+
+       spinlock_t bus_lock;
+
+       /* attach/detach inform callbacks */
+       void    (*attach_inform)(struct i2c_bus *bus, int id);
+       void    (*detach_inform)(struct i2c_bus *bus, int id);
+
+       /* Software I2C */
+       void    (*i2c_setlines)(struct i2c_bus *bus, int ctrl, int data);
+       int     (*i2c_getdataline)(struct i2c_bus *bus);
+
+       /* Hardware I2C */
+       int     (*i2c_read)(struct i2c_bus *bus, unsigned char addr);
+       int     (*i2c_write)(struct i2c_bus *bus, unsigned char addr,
+                        unsigned char b1, unsigned char b2, int both);
+
+       /* internal data for i2c module */
+       struct i2c_device   *devices[I2C_DEVICE_MAX];
+       int                 devcount;
+};
+
+
+/*
+ *     This holds per-device data for a i2c device
+ */
+
+struct i2c_device 
+{
+       char           name[32];         /* some useful label */
+       void           *data;            /* free for use by the chip driver */
+       unsigned char  addr;             /* chip addr */
+
+       /* i2c internal */
+       struct i2c_bus     *bus;
+       struct i2c_driver  *driver;
+};
+
+
+/* ------------------------------------------------------------------- */
+/* i2c module functions                                                */
+
+/* register/unregister a i2c bus */
+int i2c_register_bus(struct i2c_bus *bus);
+int i2c_unregister_bus(struct i2c_bus *bus);
+
+/* register/unregister a chip driver */
+int i2c_register_driver(struct i2c_driver *driver);
+int i2c_unregister_driver(struct i2c_driver *driver);
+
+/* send a command to a chip using the ioctl-like callback interface */
+int i2c_control_device(struct i2c_bus *bus, int id,
+                      unsigned int cmd, void *arg);
+
+/* i2c bus access functions */
+void    i2c_start(struct i2c_bus *bus);
+void    i2c_stop(struct i2c_bus *bus);
+void    i2c_one(struct i2c_bus *bus);
+void    i2c_zero(struct i2c_bus *bus);
+int     i2c_ack(struct i2c_bus *bus);
+
+int     i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack);
+unsigned char i2c_readbyte(struct i2c_bus *bus,int last);
+
+/* i2c (maybe) hardware functions */
+int     i2c_read(struct i2c_bus *bus, unsigned char addr);
+int     i2c_write(struct i2c_bus *bus, unsigned char addr,
+                 unsigned char b1, unsigned char b2, int both);
+
+#endif /* I2C_H */
index 78c42639ee7fe5ab132822feb3b89acbba1ae44e..2dbab35e574528c5af07369ee16b736c8b223238 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *  $Id: joystick.c,v 1.2 1997/10/31 19:11:48 mj Exp $
+ *  $Id: joystick.c,v 1.6 1998/03/30 11:10:43 mj Exp $
  *
- *  Copyright (C) 1997 Vojtech Pavlik
+ *  Copyright (C) 1997, 1998 Vojtech Pavlik
  */
 
 /*
 #include <linux/ioport.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/ptrace.h>
 #include <linux/interrupt.h>
 #include <linux/malloc.h>
 #include <linux/poll.h>
 #include <linux/major.h>
 #include <linux/joystick.h>
-
 #include <asm/io.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/param.h>
 
 #define PIT_HZ                 1193180L        /* PIT clock is 1.19318 MHz */
 
 #define JS_MAXTIME             PIT_HZ/250      /* timeout for read (4 ms) */
 
-#define JS_BUTTON_PERIOD       HZ/50           /* button valid time (20 ms) */
-#define JS_AXIS_MIN_PERIOD     HZ/25           /* axis min valid time (40 ms) */
-#define JS_AXIS_MAX_PERIOD     HZ/25*2         /* axis max valid time (80 ms) */
+#define JS_TIMER_PERIOD                HZ/50           /* button valid time (20 ms) */
+#define JS_BH_MIN_PERIOD       HZ/25           /* axis min valid time (40 ms) */
+#define JS_BH_MAX_PERIOD       HZ/25*2         /* axis max valid time (80 ms) */
 
 #define JS_FIFO_SIZE           16              /* number of FIFO entries */
 #define JS_BUFF_SIZE           32              /* output buffer size */
@@ -95,7 +90,7 @@ static unsigned char js_fifo_tail = JS_FIFO_SIZE - 1; /* tail of the fifo */
 static struct js_fifo js_fifo[JS_FIFO_SIZE];           /* the fifo */
 
 static unsigned char js_last_buttons = 0;              /* last read button state */
-static unsigned long js_axis_time = 0;                 /* last read axis time */
+static unsigned long js_bh_time = 0;                   /* last read axis time */
 static unsigned long js_mark_time = 0;
 
 static unsigned char js_axes_exist;                    /* all axes that exist */
@@ -132,12 +127,14 @@ static inline int get_pit(void)
  * count_bits() counts set bits in a byte.
  */
 
-static int count_bits(unsigned char c)
+static int count_bits(unsigned int c)
 {
-       int i, t = 0;
-       for (i = 0; i < 8; i++)
-               if (c & (1 << i)) t++;
-       return t;
+       int i = 0;
+       while (c) {
+               i += c & 1;
+               c >>= 1;
+       }
+       return i;
 }
 
 /*
@@ -228,14 +225,59 @@ static void js_do_timer(unsigned long data)
                }
        } 
        else
-       if ((jiffies > js_axis_time + JS_AXIS_MAX_PERIOD) && !js_mark_time) {
+       if ((jiffies > js_bh_time + JS_BH_MAX_PERIOD) && !js_mark_time) {
                js_mark_time = jiffies;
                mark_bh(JS_BH);
        }
-       js_timer.expires = jiffies + JS_BUTTON_PERIOD;
+       js_timer.expires = jiffies + JS_TIMER_PERIOD;
        add_timer(&js_timer);
 }
 
+
+/*
+ * Put an event in the buffer. This requires additional queue processing
+ * done by js_sync_buff, otherwise the buffer will be corrupted.
+ */
+
+static void js_add_event(int i, __u32 time, __u8 type, __u8 number, __u16 value)
+{
+       int ahead = jsd[i].ahead++;
+       jsd[i].buff[ahead].time = time;
+       jsd[i].buff[ahead].type = type;
+       jsd[i].buff[ahead].number = number;
+       jsd[i].buff[ahead].value = value;
+       if (jsd[i].ahead == JS_BUFF_SIZE) jsd[i].ahead=0;
+}
+
+/*
+ * This checks for all owerflows caused by recent additions to the buffer.
+ * It does anything only if some processes are reading the data too slowly.
+ */
+
+static void js_sync_buff(void)
+{
+       int i;
+       
+       for (i = 0; i < JS_NUM; i++)
+       if (jsd[i].list)
+       if (jsd[i].bhead != jsd[i].ahead)       {
+               if (ROT(jsd[i].bhead, jsd[i].tail, jsd[i].ahead) || (jsd[i].tail == jsd[i].bhead)) {
+                       struct js_list *curl;
+                       curl = jsd[i].list;
+                       while (curl) {
+                               if (ROT(jsd[i].bhead, curl->tail, jsd[i].ahead) || (curl->tail == jsd[i].bhead)) {
+                                       curl->tail = jsd[i].ahead;                              
+                                       curl->startup = jsd[i].exist;
+                               }
+                               curl = curl->next;
+                       }
+                       jsd[i].tail = jsd[i].ahead;             
+               }
+               jsd[i].bhead = jsd[i].ahead;
+               wake_up_interruptible(&jsd[i].wait);
+       }
+}
+
 /*
  * js_do_bh() does the main processing and adds events to output buffers.
  */
@@ -246,7 +288,7 @@ static void js_do_bh(void)
        int i, j, k;
        unsigned int t;
 
-       if (jiffies > js_axis_time + JS_AXIS_MIN_PERIOD) {
+       if (jiffies > js_bh_time + JS_BH_MIN_PERIOD) {
 
                unsigned int old_axis[4];
                unsigned int t_low, t_high;
@@ -348,18 +390,12 @@ static void js_do_bh(void)
                        k = 0;
                        for (j = 0; j < 4; j++)
                        if ((1 << j) & jsd[i].exist) {
-                               if (!js_compare(js_axis[j].value, old_axis[j], js_axis[j].corr.prec)) {
-                                       jsd[i].buff[jsd[i].ahead].time = js_mark_time;
-                                       jsd[i].buff[jsd[i].ahead].type = JS_EVENT_AXIS;
-                                       jsd[i].buff[jsd[i].ahead].number = k;
-                                       jsd[i].buff[jsd[i].ahead].value = js_axis[j].value;
-                                       jsd[i].ahead++;
-                                       if (jsd[i].ahead == JS_BUFF_SIZE) jsd[i].ahead = 0;
-                               }
+                               if (!js_compare(js_axis[j].value, old_axis[j], js_axis[j].corr.prec))
+                                       js_add_event(i, js_mark_time, JS_EVENT_AXIS, k, js_axis[j].value);
                                k++;
                        }
                }
-               js_axis_time = jiffies;
+               js_bh_time = jiffies;
        }
        js_mark_time = 0;
 
@@ -373,14 +409,8 @@ static void js_do_bh(void)
                        k = 0;
                        for (j = 4; j < 8; j++)
                        if ((1 << j) & jsd[i].exist) {
-                               if ((1 << j) & (js_buttons ^ js_fifo[t].event)) {
-                                       jsd[i].buff[jsd[i].ahead].time = js_fifo[t].time;
-                                       jsd[i].buff[jsd[i].ahead].type = JS_EVENT_BUTTON;
-                                       jsd[i].buff[jsd[i].ahead].number = k;
-                                       jsd[i].buff[jsd[i].ahead].value = (js_fifo[t].event >> j) & 1;
-                                       jsd[i].ahead++;
-                                       if (jsd[i].ahead == JS_BUFF_SIZE) jsd[i].ahead = 0;
-                                       }
+                               if ((1 << j) & (js_buttons ^ js_fifo[t].event))
+                                       js_add_event(i, js_fifo[t].time, JS_EVENT_BUTTON, k, (js_fifo[t].event >> j) & 1);
                                k++;
                        }
                }
@@ -388,27 +418,10 @@ static void js_do_bh(void)
        }
 
 /*
- * Sync ahead with bhead and cut too long tails.
+ * Synchronize the buffer.
  */
-       
-       for (i = 0; i < JS_NUM; i++)
-       if (jsd[i].list)
-       if (jsd[i].bhead != jsd[i].ahead)       {
-               if (ROT(jsd[i].bhead, jsd[i].tail, jsd[i].ahead) || (jsd[i].tail == jsd[i].bhead)) {
-                       struct js_list *curl;
-                       curl = jsd[i].list;
-                       while (curl) {
-                               if (ROT(jsd[i].bhead, curl->tail, jsd[i].ahead) || (curl->tail == jsd[i].bhead)) {
-                                       curl->tail = jsd[i].ahead;                              
-                                       curl->startup = jsd[i].exist;
-                               }
-                               curl = curl->next;
-                       }
-                       jsd[i].tail = jsd[i].ahead;             
-               }
-               jsd[i].bhead = jsd[i].ahead;
-               wake_up_interruptible(&jsd[i].wait);
-       }
+
+       js_sync_buff();
 
 }
 
@@ -459,38 +472,46 @@ static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  * Handle (non)blocking i/o.
  */
 
-       if (count != sizeof(struct JS_DATA_TYPE)) {
 
-               if ((GOF(curl->tail) == jsd[minor].ahead && !curl->startup) || (curl->startup && !js_axis_time)) {
-                       add_wait_queue(&jsd[minor].wait, &wait);
-                       current->state = TASK_INTERRUPTIBLE;
-                       while ((GOF(curl->tail) == jsd[minor].ahead && !curl->startup) || (curl->startup && !js_axis_time)) {
-                               if (file->f_flags & O_NONBLOCK) {
-                                       retval = -EAGAIN;
-                                       break;
-                               }
-                               if (signal_pending(current)) {
-                                       retval = -ERESTARTSYS;
-                                       break;
-                               }
-                               schedule();
-                               if (!jsd[minor].exist) {
-                                       retval = -ENODEV;
-                                       break;
-                               }
+       if ((GOF(curl->tail) == jsd[minor].ahead && !curl->startup && count != sizeof(struct JS_DATA_TYPE))
+            || (curl->startup && !js_bh_time)) {
+
+               add_wait_queue(&jsd[minor].wait, &wait);
+               current->state = TASK_INTERRUPTIBLE;
+
+               while ((GOF(curl->tail) == jsd[minor].ahead && !curl->startup && count != sizeof(struct JS_DATA_TYPE))
+                      || (curl->startup && !js_bh_time)) {
+
+                       if (file->f_flags & O_NONBLOCK) {
+                               retval = -EAGAIN;
+                               break;
+                       }
+                       if (signal_pending(current)) {
+                               retval = -ERESTARTSYS;
+                               break;
+                       }
+                       schedule();
+                       if (!jsd[minor].exist) {
+                               retval = -ENODEV;
+                               break;
                        }
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(&jsd[minor].wait, &wait);
                }
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&jsd[minor].wait, &wait);
+       }
 
-               if (retval) return retval;
+       if (retval) return retval;
        
 /*
  * Do the i/o.
  */
+       if (count != sizeof(struct JS_DATA_TYPE)) {
 
                if (curl->startup) {
                        struct js_event tmpevent;
+/*
+ * Initial button state.
+ */
 
                        t = 0;
                        for (j = 0; j < 4 && (i < blocks) && !retval; j++)
@@ -509,6 +530,10 @@ static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos)
                                t++;    
                        }
 
+/*
+ * Initial axis state.
+ */
+
                        t = 0;
                        for (j = 4; j < 8 && (i < blocks) && !retval; j++)
                        if (jsd[minor].exist & (1 << j)) {
@@ -527,6 +552,9 @@ static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos)
                        }
                }
 
+/*
+ * Buffer data.
+ */
 
                while ((jsd[minor].ahead != (t = GOF(curl->tail))) && (i < blocks) && !retval) {
                        if (copy_to_user(&buff[i], &jsd[minor].buff[t], sizeof(struct js_event)))
@@ -562,6 +590,7 @@ static ssize_t js_read(struct file *file, char *buf, size_t count, loff_t *ppos)
                        buttons |= (!!(js_last_buttons & (1 << j))) << (i++);
                copy_to_user(&bufo->buttons, &buttons, sizeof(int));
 
+               curl->startup = 0;
                curl->tail = GOB(jsd[minor].ahead);
                retval = sizeof(struct JS_DATA_TYPE);
        }
@@ -637,7 +666,7 @@ static int js_ioctl(struct inode *inode,
                                sizeof(struct js_corr))) return -EFAULT;
                        j++;
                }
-               js_axis_time = 0;
+               js_bh_time = 0;
                break;
        case JSIOCGCORR:
                j = 0;
@@ -680,7 +709,7 @@ static int js_open(struct inode *inode, struct file *file)
        MOD_INC_USE_COUNT;
 
        if (!jsd[0].list && !jsd[1].list) { 
-               js_timer.expires = jiffies + JS_BUTTON_PERIOD;
+               js_timer.expires = jiffies + JS_TIMER_PERIOD;
                add_timer(&js_timer);
        }
 
@@ -793,8 +822,8 @@ __initfunc(int js_init(void))
        }
 
        for (i = 0; i < JS_NUM; i++) {
-               if (jsd[i].exist) printk(KERN_INFO "js%d: %d-axis joystick at %#x\n",
-                        i,  count_bits(jsd[i].exist & JS_AXES), JS_PORT);
+               if (jsd[i].exist) printk(KERN_INFO "js%d: %d-axis %d-button joystick at %#x\n",
+                        i,  count_bits(jsd[i].exist & JS_AXES), count_bits(jsd[i].exist & JS_AXES), JS_PORT);
                jsd[i].ahead = jsd[i].bhead = 0;
                jsd[i].tail = JS_BUFF_SIZE - 1;
                jsd[i].list = NULL;
index 2999b70ddfb3ef53eb60e6643c697d015b7070eb..65262720d12be5573a5dacbf16483f14eaeb3b13 100644 (file)
@@ -14,6 +14,8 @@
  *                                             carsten@sol.wohnheim.uni-ulm.de
  * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
  * parport_sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
+ * Fixed kernel_(to/from)_user memory copy to check for errors
+ *                             by Riccardo Facchetti <fizban@tin.it>
  */
 
 /* This driver should, in theory, work with any parallel port that has an
@@ -273,7 +275,9 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
        do {
                bytes_written = 0;
                copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
-               copy_from_user(lp->lp_buffer, buf, copy_size);
+
+               if (copy_from_user(lp->lp_buffer, buf, copy_size))
+                       return -EFAULT;
 
                while (copy_size) {
                        if (lp_char(lp->lp_buffer[bytes_written], minor)) {
@@ -459,15 +463,19 @@ static ssize_t lp_read(struct file * file, char * buf,
                        current->timeout=jiffies + LP_TIME(minor);
                        schedule ();
                }
+
                counter=0;
+
                if (( i & 1) != 0) {
                        Byte= (Byte | z<<4);
-                       put_user(Byte, temp);
+                       if (put_user(Byte, (char *)temp))
+                               return -EFAULT;
                        temp++;
                } else Byte=z;
        }
+
        lp_select_in_high(minor);
-       parport_release(lp_table[minor].dev);
+       lp_parport_release(minor);
        return temp-buf;        
 }
 
@@ -538,6 +546,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
        unsigned int minor = MINOR(inode->i_rdev);
+       int status;
        int retval = 0;
 
 #ifdef LP_DEBUG
@@ -579,48 +588,33 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        return -EINVAL;
                        break;
                case LPGETIRQ:
-                       retval = verify_area(VERIFY_WRITE, (void *) arg,
-                           sizeof(int));
-                       if (retval)
-                               return retval;
-                       copy_to_user((int *) arg, &LP_IRQ(minor), sizeof(int));
+                       if (copy_to_user((int *) arg, &LP_IRQ(minor),
+                                       sizeof(int)))
+                               return -EFAULT;
                        break;
                case LPGETSTATUS:
-                       retval = verify_area(VERIFY_WRITE, (void *) arg,
-                           sizeof(int));
-                       if (retval)
-                               return retval;
-                       else {
-                               int status;
-                               lp_parport_claim (minor);
-                               status = r_str(minor);
-                               lp_parport_release (minor);
-                               copy_to_user((int *) arg, &status, sizeof(int));
-                       }
+                       lp_parport_claim(minor);
+                       status = r_str(minor);
+                       lp_parport_release(minor);
+
+                       if (copy_to_user((int *) arg, &status, sizeof(int)))
+                               return -EFAULT;
                        break;
                case LPRESET:
                        lp_reset(minor);
                        break;
                case LPGETSTATS:
-                       retval = verify_area(VERIFY_WRITE, (void *) arg,
-                           sizeof(struct lp_stats));
-                       if (retval)
-                               return retval;
-                       else {
-                               copy_to_user((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
-                               if (suser())
-                                       memset(&LP_STAT(minor), 0, sizeof(struct lp_stats));
-                       }
+                       if (copy_to_user((int *) arg, &LP_STAT(minor),
+                                       sizeof(struct lp_stats)))
+                               return -EFAULT;
+                       if (suser())
+                               memset(&LP_STAT(minor), 0,
+                                               sizeof(struct lp_stats));
                        break;
                case LPGETFLAGS:
-                       retval = verify_area(VERIFY_WRITE, (void *) arg,
-                           sizeof(int));
-                       if (retval)
-                               return retval;
-                       else {
-                               int status = LP_F(minor);
-                               copy_to_user((int *) arg, &status, sizeof(int));
-                       }
+                       status = LP_F(minor);
+                       if (copy_to_user((int *) arg, &status, sizeof(int)))
+                               return -EFAULT;
                        break;
                default:
                        retval = -EINVAL;
diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c
new file mode 100644 (file)
index 0000000..0d5f026
--- /dev/null
@@ -0,0 +1,923 @@
+/*
+ * programming the msp34* sound processor family
+ *
+ * (c) 1997,1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * what works and what doesn't:
+ *
+ *  AM-Mono
+ *      probably doesn't (untested)
+ *
+ *  FM-Mono
+ *      should work. The stereo modes are backward compatible to FM-mono,
+ *      therefore FM-Mono should be allways available.
+ *
+ *  FM-Stereo (B/G, used in germany)
+ *      should work, with autodetect
+ *
+ *  FM-Stereo (satellite)
+ *      should work, no autodetect (i.e. default is mono, but you can
+ *      switch to stereo -- untested)
+ *
+ *  NICAM (B/G, used in UK, Scandinavia and Spain)
+ *      should work, with autodetect. Support for NICAM was added by
+ *      Pekka Pietikainen <pp@netppl.fi>
+ *
+ *
+ * TODO:
+ *   - better SAT support
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+/* #include <asm/smp_lock.h> */
+
+/* kernel_thread */
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+
+#include "i2c.h"
+#include <linux/videodev.h>
+
+#include "msp3400.h"
+
+int debug = 0; /* insmod parameter */
+
+struct msp3400c 
+{
+       struct i2c_bus     *bus;
+
+       int nicam;
+       int mode;
+       int norm;
+       int volume;
+       int stereo;
+
+       /* thread */
+       struct task_struct      *thread;
+       struct semaphore        *wait;
+       struct semaphore        *notify;
+       int active,restart,rmmod;
+};
+
+#define VIDEO_MODE_RADIO 16      /* norm magic for radio mode */
+
+/* ---------------------------------------------------------------------- */
+
+#define dprintk     if (debug) printk
+
+MODULE_PARM(debug,"i");
+
+/* ---------------------------------------------------------------------- */
+
+#define I2C_MSP3400C       0x80
+#define I2C_MSP3400C_DEM   0x10
+#define I2C_MSP3400C_DFP   0x12
+
+/* ----------------------------------------------------------------------- */
+/* functions for talking to the MSP3400C Sound processor                   */
+
+static int msp3400c_reset(struct i2c_bus *bus)
+{
+       int ret = 0;
+    
+       udelay(2000);
+       i2c_start(bus);
+       i2c_sendbyte(bus, I2C_MSP3400C,2000);
+       i2c_sendbyte(bus, 0x00,0);
+       i2c_sendbyte(bus, 0x80,0);
+       i2c_sendbyte(bus, 0x00,0);
+       i2c_stop(bus);
+       udelay(2000);
+       i2c_start(bus);
+       if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
+               0 != i2c_sendbyte(bus, 0x00,0) ||
+               0 != i2c_sendbyte(bus, 0x00,0) ||
+               0 != i2c_sendbyte(bus, 0x00,0)) 
+       {
+               ret = -1;
+               printk(KERN_ERR "msp3400: chip reset failed, penguin on i2c bus?\n");
+       }
+       i2c_stop(bus);
+       udelay(2000);
+       return ret;
+}
+
+static int msp3400c_read(struct i2c_bus *bus, int dev, int addr)
+{
+       int ret=0;
+       short val = 0;
+       i2c_start(bus);
+       if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
+               0 != i2c_sendbyte(bus, dev+1,       0)    ||
+               0 != i2c_sendbyte(bus, addr >> 8,   0)    ||
+               0 != i2c_sendbyte(bus, addr & 0xff, 0)) 
+       {
+               ret = -1;
+       }
+       else
+       {
+               i2c_start(bus);
+               if (0 != i2c_sendbyte(bus, I2C_MSP3400C+1,2000)) 
+               {
+                       ret = -1;
+               }
+               else
+               {
+                       val |= (int)i2c_readbyte(bus,0) << 8;
+                       val |= (int)i2c_readbyte(bus,1);
+               }
+       }
+       i2c_stop(bus);
+       if (-1 == ret) 
+       {
+               printk(KERN_WARNING "msp3400: I/O error, trying reset (read %s 0x%x)\n",
+                       (dev == I2C_MSP3400C_DEM) ? "Demod" : "Audio", addr);
+               msp3400c_reset(bus);
+       }
+       return val;
+}
+
+static int msp3400c_write(struct i2c_bus *bus, int dev, int addr, int val)
+{
+       int ret = 0;
+    
+       i2c_start(bus);
+       if (0 != i2c_sendbyte(bus, I2C_MSP3400C,2000) ||
+               0 != i2c_sendbyte(bus, dev,         0)    ||
+               0 != i2c_sendbyte(bus, addr >> 8,   0)    ||
+               0 != i2c_sendbyte(bus, addr & 0xff, 0)    ||
+               0 != i2c_sendbyte(bus, val >> 8,    0)    ||
+               0 != i2c_sendbyte(bus, val & 0xff,  0))
+       {
+               ret = -1;
+       }
+       i2c_stop(bus);
+       if (-1 == ret) 
+       {
+               printk(KERN_ERR "msp3400: I/O error, trying reset (write %s 0x%x)\n",
+                       (dev == I2C_MSP3400C_DEM) ? "Demod" : "Audio", addr);
+               msp3400c_reset(bus);
+       }
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* This macro is allowed for *constants* only, gcc must calculate it
+   at compile time.  Remember -- no floats in kernel mode */
+#define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24)))
+
+#define MSP_MODE_AM_DETECT   0
+#define MSP_MODE_FM_RADIO    2
+#define MSP_MODE_FM_TERRA    3
+#define MSP_MODE_FM_SAT      4
+#define MSP_MODE_FM_NICAM1   5
+#define MSP_MODE_FM_NICAM2   6
+
+static struct MSP_INIT_DATA_DEM 
+{
+       int fir1[6];
+       int fir2[6];
+       int cdo1;
+       int cdo2;
+       int ad_cv;
+       int mode_reg;
+       int dfp_src;
+       int dfp_matrix;
+} msp_init_data[] = {
+               /* AM (for carrier detect / msp3400) */
+               { { 75, 19, 36, 35, 39, 40 }, { 75, 19, 36, 35, 39, 40 },
+               MSP_CARRIER(5.5), MSP_CARRIER(5.5),  0x00d0, 0x0500,   0x0020, 0x3000},
+
+               /* AM (for carrier detect / msp3410) */
+               { { -1, -1, -8, 2, 59, 126 }, { -1, -1, -8, 2, 59, 126 },
+               MSP_CARRIER(5.5), MSP_CARRIER(5.5),  0x00d0, 0x0100,   0x0020, 0x3000},
+
+               /* FM Radio */
+               { { -8, -8, 4, 6, 78, 107 }, { -8, -8, 4, 6, 78, 107 },
+               MSP_CARRIER(10.7), MSP_CARRIER(10.7),  0x00d0, 0x0480, 0x0020, 0x3002 },
+
+               /* Terrestial FM-mono */
+               { {  3, 18, 27, 48, 66, 72 }, {  3, 18, 27, 48, 66, 72 },
+               MSP_CARRIER(5.5), MSP_CARRIER(5.5),  0x00d0, 0x0480,   0x0030, 0x3000},
+
+               /* Sat FM-mono */
+               { {  1,  9, 14, 24, 33, 37 }, {  3, 18, 27, 48, 66, 72 },
+               MSP_CARRIER(6.5), MSP_CARRIER(6.5),  0x00c6, 0x0480,   0x0000, 0x3000},
+
+               /* NICAM B/G, D/K */
+               { { -2, -8, -10, 10, 50, 86 }, {  3, 18, 27, 48, 66, 72 },
+               MSP_CARRIER(5.5), MSP_CARRIER(5.5),  0x00d0, 0x0040,   0x0120, 0x3000},
+
+               /* NICAM I */
+               { {  2, 4, -6, -4, 40, 94 }, {  3, 18, 27, 48, 66, 72 },
+               MSP_CARRIER(5.5), MSP_CARRIER(5.5),  0x00d0, 0x0040,   0x0120, 0x3000},
+};
+
+struct CARRIER_DETECT 
+{
+       int   cdo;
+       char *name;
+};
+
+static struct CARRIER_DETECT carrier_detect_main[] = 
+{
+       /* main carrier */
+       { MSP_CARRIER(4.5),        "4.5   NTSC"                   }, 
+       { MSP_CARRIER(5.5),        "5.5   PAL B/G"                }, 
+       { MSP_CARRIER(6.0),        "6.0   PAL I"                  },
+       { MSP_CARRIER(6.5),        "6.5   PAL SAT / SECAM"        }
+};
+
+static struct CARRIER_DETECT carrier_detect_55[] = {
+       /* PAL B/G */
+       { MSP_CARRIER(5.7421875),  "5.742 PAL B/G FM-stereo"     }, 
+       { MSP_CARRIER(5.85),       "5.85  PAL B/G NICAM"         }
+};
+
+static struct CARRIER_DETECT carrier_detect_65[] = {
+       /* PAL SAT / SECAM */
+       { MSP_CARRIER(7.02),       "7.02  PAL SAT FM-stereo s/b" },
+       { MSP_CARRIER(7.20),       "7.20  PAL SAT FM-stereo s"   },
+       { MSP_CARRIER(7.38),       "7.38  PAL SAT FM-stereo b"   },
+};
+
+#define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT))
+
+/* ------------------------------------------------------------------------ */
+
+static void msp3400c_setcarrier(struct i2c_bus *bus, int cdo1, int cdo2)
+{
+       msp3400c_write(bus,I2C_MSP3400C_DEM, 0x0093, cdo1 & 0xfff);
+       msp3400c_write(bus,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
+       msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
+       msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
+}
+
+static void msp3400c_setvolume(struct i2c_bus *bus, int vol)
+{
+       int val = (vol * 0x73 / 65535) << 8;
+
+       dprintk("msp3400: setvolume: 0x%02x\n",val>>8);
+       msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
+       msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0006, val); /* headphones  */
+       /* scart - on/off only */
+       msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0);
+}
+
+static void msp3400c_setmode(struct msp3400c *msp, int type)
+{
+       int i;
+       
+       dprintk("msp3400: setmode: %d\n",type);
+       msp->mode   = type;
+       msp->stereo = VIDEO_SOUND_MONO;
+
+       msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x00bb,          /* ad_cv */
+               msp_init_data[type].ad_cv);
+    
+       for (i = 5; i >= 0; i--)                                   /* fir 1 */
+               msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0001,
+                       msp_init_data[type].fir1[i]);
+    
+       msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */
+       msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0040);
+       msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005, 0x0000);
+       for (i = 5; i >= 0; i--)
+               msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005,
+                       msp_init_data[type].fir2[i]);
+    
+       msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083,          /* MODE_REG */
+               msp_init_data[type].mode_reg);
+    
+       msp3400c_setcarrier(msp->bus, msp_init_data[type].cdo1,
+               msp_init_data[type].cdo2);
+    
+       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,
+               msp_init_data[type].dfp_src);
+       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,
+               msp_init_data[type].dfp_src);
+       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,
+               msp_init_data[type].dfp_src);
+       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e,
+               msp_init_data[type].dfp_matrix);
+
+       if (msp->nicam) 
+       {
+               /* msp3410 needs some more initialization */
+               msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0010, 0x3000);
+       }
+}
+
+static void msp3400c_setstereo(struct msp3400c *msp, int mode)
+{
+       int nicam=0; /* channel source: FM/AM or nicam */
+
+       /* switch demodulator */
+       switch (msp->mode) 
+       {
+               case MSP_MODE_FM_TERRA:
+                       dprintk("msp3400: B/G setstereo: %d\n",mode);
+                       msp->stereo = mode;
+                       msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.7421875),MSP_CARRIER(5.5));
+                       switch (mode) 
+                       {
+                               case VIDEO_SOUND_STEREO:
+                                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3001);
+                                       break;
+                               case VIDEO_SOUND_MONO:
+                               case VIDEO_SOUND_LANG1:
+                               case VIDEO_SOUND_LANG2:
+                                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3000);
+                                       break;
+                       }
+                       break;
+               case MSP_MODE_FM_SAT:
+                       dprintk("msp3400: sat setstereo: %d\n",mode);
+                       msp->stereo = mode;
+                       switch (mode) 
+                       {
+                               case VIDEO_SOUND_MONO:
+                                       msp3400c_setcarrier(msp->bus, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
+                                       break;
+                               case VIDEO_SOUND_STEREO:
+                                       msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
+                                       break;
+                               case VIDEO_SOUND_LANG1:
+                                       msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+                                       break;
+                               case VIDEO_SOUND_LANG2:
+                                       msp3400c_setcarrier(msp->bus, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+                                       break;
+                       }
+                       break;
+               case MSP_MODE_FM_NICAM1:
+                       dprintk("msp3400: NICAM1 setstereo: %d\n",mode);
+                       msp->stereo = mode;
+                       msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.85),MSP_CARRIER(5.5));
+                       nicam=0x0100;
+                       break;
+               default:
+                       /* can't do stereo - abort here */
+                       return;
+       }
+
+       /* switch audio */
+       switch (mode) 
+       {
+               case VIDEO_SOUND_STEREO:
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0020|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0020|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0020|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005, 0x4000);
+                       break;
+               case VIDEO_SOUND_MONO:
+               case VIDEO_SOUND_LANG1:
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0000|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0000|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0000|nicam);
+                       break;
+               case VIDEO_SOUND_LANG2:
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0010|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0010|nicam);
+                       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0010|nicam);
+                       break;
+       }
+}
+
+/* ----------------------------------------------------------------------- */
+
+struct REGISTER_DUMP {
+       int addr;
+       char *name;
+};
+
+struct REGISTER_DUMP d1[] = 
+{
+       { 0x007e, "autodetect" },
+       { 0x0023, "C_AD_BITS " },
+       { 0x0038, "ADD_BITS  " },
+       { 0x003e, "CIB_BITS  " },
+       { 0x0057, "ERROR_RATE" },
+};
+
+/*
+ * A kernel thread for msp3400 control -- we don't want to block the
+ * in the ioctl while doing the sound carrier & stereo detect
+ */
+
+int msp3400c_thread(void *data)
+{
+       unsigned long flags;
+       struct msp3400c *msp = data;
+       struct semaphore sem = MUTEX_LOCKED;
+    
+       struct CARRIER_DETECT *cd;
+       int count, max1,max2,val1,val2, val,this, check_stereo;
+       int i;
+    
+       /* lock_kernel(); */
+    
+       exit_mm(current);
+       current->session = 1;
+       current->pgrp = 1;
+       sigfillset(&current->blocked);
+       current->fs->umask = 0;
+       strcpy(current->comm,"msp3400");
+
+       msp->wait   = &sem;
+       msp->thread = current;
+
+       /* unlock_kernel(); */
+
+       dprintk("msp3400: thread: start\n");
+       if(msp->notify != NULL)
+               up(msp->notify);
+               
+       for (;;) 
+       {
+               if (msp->rmmod)
+                       goto done;
+               dprintk("msp3400: thread: sleep\n");
+               down_interruptible(&sem);
+               dprintk("msp3400: thread: wakeup\n");
+               if (msp->rmmod)
+                       goto done;
+#if 0
+               if (VIDEO_MODE_RADIO == msp->norm) 
+               {
+                       msp->active = 1;
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + HZ/10;
+                       schedule();
+                       if (signal_pending(current))
+                               goto done;
+                       LOCK_I2C_BUS(msp->bus);
+                       val1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
+                       val2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
+                       UNLOCK_I2C_BUS(msp->bus);
+                       printk("msp3400: DC %d/%d\n",val1,val2);
+                       msp->active = 0;
+                       continue;
+               }
+#endif
+       
+               if (VIDEO_MODE_RADIO == msp->norm)
+                       continue;  /* nothing to do */
+       
+               msp->active = 1;
+restart:
+               LOCK_I2C_BUS(msp->bus);
+               msp3400c_setvolume(msp->bus, 0);
+               msp3400c_setmode(msp, MSP_MODE_AM_DETECT);
+               val1 = val2 = max1 = max2 = check_stereo = 0;
+
+               /* carrier detect pass #1 -- main carrier */
+               cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
+               for (this = 0; this < count; this++) 
+               {
+                       msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
+                       UNLOCK_I2C_BUS(msp->bus);
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + HZ/25;
+                       schedule();
+                       if (signal_pending(current))
+                               goto done;
+                       if (msp->restart) 
+                       {
+                               msp->restart = 0;
+                               goto restart;
+                       }
+
+                       LOCK_I2C_BUS(msp->bus);
+                       val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
+                       if (val1 < val)
+                               val1 = val, max1 = this;
+                       dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name);
+               }
+
+               /* carrier detect pass #2 -- second (stereo) carrier */
+               switch (max1) 
+               {
+                       case 1: /* 5.5 */
+                               cd = carrier_detect_55; count = CARRIER_COUNT(carrier_detect_55);
+                               break;
+                       case 3: /* 6.5 */
+                               cd = carrier_detect_65; count = CARRIER_COUNT(carrier_detect_65);
+                               break;
+                       case 0: /* 4.5 */
+                       case 2: /* 6.0 */
+                       default:
+                               cd = NULL; count = 0;
+                               break;
+               }
+               for (this = 0; this < count; this++) 
+               {
+                       msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
+                       UNLOCK_I2C_BUS(msp->bus);
+
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + HZ/25;
+                       schedule();
+                       if (signal_pending(current))
+                               goto done;
+                       if (msp->restart) 
+                       {
+                               msp->restart = 0;
+                               goto restart;
+                       }
+
+                       LOCK_I2C_BUS(msp->bus);
+                       val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
+                       if (val2 < val)
+                               val2 = val, max2 = this;
+                       dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name);
+               }
+
+               /* programm the msp3400 according to the results */
+               switch (max1) 
+               {
+                       case 0: /* 4.5 */
+                       case 1: /* 5.5 */
+                               msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
+                               msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
+                               carrier_detect_main[max1].cdo);
+                               if (max2 == 0) 
+                               {
+                                       /* B/G FM-stereo */
+                                       msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
+                                       check_stereo = 1;
+                               }
+                               if (max2 == 1 && msp->nicam) 
+                               {
+                                       /* B/G NICAM */
+                                       msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
+                                       /* msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01); */
+                                       msp3400c_setcarrier(msp->bus, MSP_CARRIER(5.85),
+                                               MSP_CARRIER(5.5));
+                                       check_stereo = 1;
+                               }
+                               break;
+                       case 2: /* 6.0 */
+                       case 3: /* 6.5 */
+                       default:
+                               msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
+                               msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
+                                       carrier_detect_main[max1].cdo);
+                               msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
+                               break;
+               }
+       
+               /* unmute */
+               msp3400c_setvolume(msp->bus, msp->volume);
+
+               if (check_stereo) 
+               {
+                       /* stereo available -- check current mode */
+                       UNLOCK_I2C_BUS(msp->bus);
+                  
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + HZ;
+                       schedule();
+                       if (signal_pending(current))
+                               goto done;
+                       if (msp->restart) 
+                       {
+                               msp->restart = 0;
+                               goto restart;
+                       }
+                   
+                       LOCK_I2C_BUS(msp->bus);
+                       switch (msp->mode) 
+                       {
+                               case MSP_MODE_FM_TERRA:
+                                       val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x18);
+                                       dprintk("msp3400: stereo detect register: %d\n",val);
+                       
+                                       if (val > 4096) 
+                                       {
+                                               msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
+                                       }
+                                       else if (val < -4096) 
+                                       {
+                                               msp3400c_setstereo(msp, VIDEO_SOUND_LANG1);
+                                       }
+                                       else
+                                       {
+                                               msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
+                                       }
+                                       break;
+                               case MSP_MODE_FM_NICAM1:
+                                       val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
+                                       switch ((val & 0x1e) >> 1)  
+                                       {
+                                               case 0:
+                                               case 8:
+                                                       msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
+                                                       break;
+                                               default:
+                                                       msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
+                                                       break;
+                                       }                       
+
+                                       /* dump registers (for debugging) */
+                                       if (debug)
+                                       {
+                                               for (i=0; i<sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) 
+                                               {
+                                                       val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM, d1[i].addr);
+                                                       printk(KERN_DEBUG "msp3400: %s = 0x%x\n",
+                                                               d1[i].name,val);
+                                               }
+                                       }
+                                       break;
+                       }
+               }
+               UNLOCK_I2C_BUS(msp->bus);
+               msp->active = 0;
+       }
+
+done:
+       dprintk("msp3400: thread: exit\n");
+       msp->wait   = NULL;
+       msp->active = 0;
+       msp->thread = NULL;
+
+       if(msp->notify != NULL)
+               up(msp->notify);
+       return 0;
+}
+
+int msp3410d_thread(void *data)
+{
+       unsigned long flags;
+       struct msp3400c *msp = data;
+       struct semaphore sem = MUTEX_LOCKED;
+       int i, val;
+
+       /* lock_kernel(); */
+    
+       exit_mm(current);
+       current->session = 1;
+       current->pgrp = 1;
+       sigfillset(&current->blocked);
+       current->fs->umask = 0;
+       strcpy(current->comm,"msp3410 (nicam)");
+
+       msp->wait   = &sem;
+       msp->thread = current;
+
+       /* unlock_kernel(); */
+
+       dprintk("msp3410: thread: start\n");
+       if(msp->notify != NULL)
+               up(msp->notify);
+               
+       for (;;) 
+       {
+               if (msp->rmmod)
+                       goto done;
+               dprintk("msp3410: thread: sleep\n");
+               down_interruptible(&sem);
+               dprintk("msp3410: thread: wakeup\n");
+               if (msp->rmmod)
+                       goto done;
+       
+               if (VIDEO_MODE_RADIO == msp->norm)
+                       continue;  /* nothing to do */
+       
+               msp->active = 1;
+
+restart:
+               LOCK_I2C_BUS(msp->bus);
+               /* mute */
+               msp3400c_setvolume(msp->bus, 0);
+               /* quick & dirty hack:
+                  get the audio proccessor into some useful state */
+               msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
+               /* kick autodetect */
+               msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x20, 0x01);
+               msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01);
+               UNLOCK_I2C_BUS(msp->bus);
+
+               /* wait 1 sec */
+               current->state = TASK_INTERRUPTIBLE;
+               current->timeout = jiffies + HZ;
+               schedule();
+               if (signal_pending(current))
+                       goto done;
+               if (msp->restart) 
+               {
+                       msp->restart = 0;
+                       goto restart;
+               }
+       
+               LOCK_I2C_BUS(msp->bus);
+               /* debug register dump */
+               for (i = 0; i < sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) 
+               {
+                       val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM,d1[i].addr);
+                       printk(KERN_DEBUG "msp3400: %s = 0x%x\n",d1[i].name,val);
+               }       
+               /* unmute */
+               msp3400c_setvolume(msp->bus, msp->volume);
+               UNLOCK_I2C_BUS(msp->bus);
+
+               msp->active = 0;
+       }
+
+done:
+       dprintk("msp3410: thread: exit\n");
+       msp->wait   = NULL;
+       msp->active = 0;
+       msp->thread = NULL;
+
+       if(msp->notify != NULL)
+               up(msp->notify);
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int msp3400c_attach(struct i2c_device *device)
+{
+       unsigned long flags;
+       struct semaphore sem = MUTEX_LOCKED;
+       struct msp3400c *msp;
+       int rev1,rev2;
+       
+       /*
+        *      MSP3400's are for now only assumed to live on busses
+        *      connected to a BT848. Adjust as and when you get new
+        *      funky cards using these components.
+        */
+       
+       if(device->bus->id != I2C_BUSID_BT848)
+               return -EINVAL;
+
+       device->data = msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL);
+       if (NULL == msp)
+               return -ENOMEM;
+       memset(msp,0,sizeof(struct msp3400c));
+       msp->bus = device->bus;
+       msp->volume = 65535;
+
+       LOCK_I2C_BUS(msp->bus);
+       if (-1 == msp3400c_reset(msp->bus)) 
+       {
+               UNLOCK_I2C_BUS(msp->bus);
+               kfree(msp);
+               return -1;
+       }
+    
+       msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
+       msp3400c_setvolume(msp->bus, msp->volume);
+
+       rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
+       rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
+
+#if 0
+       /* this will turn on a 1kHz beep - might be useful for debugging... */
+       msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0014, 0x1040);
+#endif
+       UNLOCK_I2C_BUS(msp->bus);
+
+       sprintf(device->name,"MSP34%02d%c-%c%d",
+               (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
+       msp->nicam = (((rev2>>8)&0xff) == 10) ? 1 : 0;
+       printk(KERN_INFO "msp3400: init: chip=%s%s\n",
+               device->name, msp->nicam ? ", can decode nicam" : "");
+
+       MOD_INC_USE_COUNT;
+       /* startup control thread */
+       msp->notify = &sem;
+       kernel_thread(msp3400c_thread, (void *)msp, 0);
+       down(&sem);
+       msp->notify = NULL;
+       if (!msp->active)
+               up(msp->wait);
+       return 0;
+}
+
+static int msp3400c_detach(struct i2c_device *device)
+{
+       unsigned long flags;
+       struct semaphore sem = MUTEX_LOCKED;
+       struct msp3400c *msp  = (struct msp3400c*)device->data;
+    
+       /* shutdown control thread */
+       msp->notify = &sem;
+       msp->rmmod = 1;
+       if (!msp->active)
+               up(msp->wait);
+       down(&sem);
+       msp->notify = NULL;
+   
+       LOCK_I2C_BUS(msp->bus);
+       msp3400c_reset(msp->bus);
+       UNLOCK_I2C_BUS(msp->bus);
+
+       kfree(msp);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static int msp3400c_command(struct i2c_device *device,
+                unsigned int cmd, void *arg)
+{
+       unsigned long flags;
+       struct msp3400c *msp = (struct msp3400c*)device->data;
+       int *iarg = (int*)arg;
+
+       switch (cmd) 
+       {
+               case MSP_SET_RADIO:
+                       msp->norm = VIDEO_MODE_RADIO;
+                       LOCK_I2C_BUS(msp->bus);
+                       msp3400c_setmode(msp,MSP_MODE_FM_RADIO);
+                       msp3400c_setcarrier(msp->bus, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
+                       UNLOCK_I2C_BUS(msp->bus);
+                       break;
+               case MSP_SET_TVNORM:
+                       msp->norm = *iarg;
+                       break;
+               case MSP_NEWCHANNEL:
+                       if (!msp->active)
+                               up(msp->wait);
+                       else
+                               msp->restart = 1;
+                       break;
+
+               case MSP_GET_VOLUME:
+                       *iarg = msp->volume;
+                       break;
+               case MSP_SET_VOLUME:
+                       msp->volume = *iarg;
+                       LOCK_I2C_BUS(msp->bus);
+                       msp3400c_setvolume(msp->bus,msp->volume);
+                       UNLOCK_I2C_BUS(msp->bus);
+                       break;
+
+               case MSP_GET_STEREO:
+                       *iarg = msp->stereo;
+                       break;
+               case MSP_SET_STEREO:
+                       if (*iarg) 
+                       {
+                               LOCK_I2C_BUS(msp->bus);
+                               msp3400c_setstereo(msp,*iarg);
+                               UNLOCK_I2C_BUS(msp->bus);
+                       }
+                       break;
+
+               case MSP_GET_DC:
+                       LOCK_I2C_BUS(msp->bus);
+                       *iarg = (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
+                               (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
+                       UNLOCK_I2C_BUS(msp->bus);
+                       break;
+       
+               default:
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+struct i2c_driver i2c_driver_msp = 
+{
+       "msp3400",                    /* name       */
+       I2C_DRIVERID_MSP3400,         /* ID         */
+       I2C_MSP3400C, I2C_MSP3400C,   /* addr range */
+
+       msp3400c_attach,
+       msp3400c_detach,
+       msp3400c_command
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int msp3400c_init(void)
+#endif
+{
+       i2c_register_driver(&i2c_driver_msp);
+       return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+       i2c_unregister_driver(&i2c_driver_msp);
+}
+#endif
+
diff --git a/drivers/char/msp3400.h b/drivers/char/msp3400.h
new file mode 100644 (file)
index 0000000..1b4eeda
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef MSP3400_H
+#define MSP3400_H
+
+/* ---------------------------------------------------------------------- */
+
+#define MSP_SET_TVNORM     _IOW('m',1,int)  /* TV mode + PAL/SECAM/NTSC  */
+#define MSP_SET_RADIO      _IO('m',2)       /* Radio mode                */
+#define MSP_NEWCHANNEL     _IO('m',3)       /* indicate new channel      */
+
+#define MSP_GET_VOLUME     _IOR('m',4,int)
+#define MSP_SET_VOLUME     _IOW('m',5,int)
+
+#define MSP_GET_STEREO     _IOR('m',6,int)
+#define MSP_SET_STEREO     _IOW('m',7,int)
+
+#define MSP_GET_DC         _IOW('m',8,int)
+
+#endif /* MSP3400_H */
index 047ae09b29a5d5a8967d89cf872f1bc2bbfc7eb6..c17cb20ae033ee8465259433ad69425fa8d03314 100644 (file)
@@ -1020,11 +1020,10 @@ static void shutdown_mediavision(void)
  */
  
 #ifdef MODULE
-
-MODULE_PARM(io_port,"i");
-MODULE_PARM(mem_base,"i");
-
 int init_module(void)
+#else
+void init_pms_cards(void)
+#endif
 {
        printk(KERN_INFO "Mediavision Pro Movie Studio driver 0.02\n");
        
@@ -1040,9 +1039,14 @@ int init_module(void)
        pms_device.width=320;
        pms_swsense(75);
        pms_resolution(320,240);
-       return video_register_device((struct video_device *)&pms_device);
+       return video_register_device((struct video_device *)&pms_device, VFL_TYPE_GRABBER);
 }
 
+#ifdef MODULE
+
+MODULE_PARM(io_port,"i");
+MODULE_PARM(mem_base,"i");
+
 void cleanup_module(void)
 {
        shutdown_mediavision();
index acef03f538cb4fefce5d3f767e085b4810748f84..fb136c3e820dee54daeedcc31d93e46951a3adbf 100644 (file)
@@ -7,7 +7,6 @@
  *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
  */
 
-#include <linux/config.h>
 #include <linux/module.h>      /* For EXPORT_SYMBOL */
 
 #include <linux/errno.h>
diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c
new file mode 100644 (file)
index 0000000..a942985
--- /dev/null
@@ -0,0 +1,269 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+
+#include "i2c.h"
+#include <linux/videodev.h>
+
+#include "tuner.h"
+
+int debug = 0; /* insmod parameter */
+int type  = 0; /* tuner type */
+
+#define dprintk     if (debug) printk
+
+MODULE_PARM(debug,"i");
+MODULE_PARM(type,"i");
+
+struct tuner 
+{
+       struct i2c_bus   *bus;     /* where is our chip */
+       int               addr;
+
+       int type;            /* chip type */
+       int freq;            /* keep track of the current settings */
+       int radio;
+};
+
+/* ---------------------------------------------------------------------- */
+
+struct tunertype 
+{
+       char *name;
+       unsigned char Vendor;
+       unsigned char Type;
+  
+       unsigned short thresh1; /* frequency Range for UHF,VHF-L, VHF_H */   
+       unsigned short thresh2;  
+       unsigned char VHF_L;
+       unsigned char VHF_H;
+       unsigned char UHF;
+       unsigned char config; 
+       unsigned char I2C;
+       unsigned short IFPCoff;
+};
+
+/*
+ *     The floats in the tuner struct are computed at compile time
+ *     by gcc and cast back to integers. Thus we don't violate the
+ *     "no float in kernel" rule.
+ */
+static struct tunertype tuners[] = {
+        {"Temic PAL", TEMIC, PAL,
+                16*140.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,623},
+       {"Philips PAL_I", Philips, PAL_I,
+               16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc0,623},
+       {"Philips NTSC", Philips, NTSC,
+               16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,0xc0,732},
+       {"Philips SECAM", Philips, SECAM,
+               16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,0xc0,623},
+       {"NoTuner", NoTuner, NOTUNER,
+                0        ,0        ,0x00,0x00,0x00,0x00,0x00,000},
+       {"Philips PAL", Philips, PAL,
+               16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,0xc0,623},
+       {"Temic NTSC", TEMIC, NTSC,
+               16*157.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,732},
+       {"TEMIC PAL_I", TEMIC, PAL_I,
+               16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int tuner_getstatus (struct tuner *t)
+{
+       return i2c_read(t->bus,t->addr+1);
+}
+
+#define TUNER_POR       0x80
+#define TUNER_FL        0x40
+#define TUNER_AFC       0x07
+
+static int tuner_islocked (struct tuner *t)
+{
+        return (tuner_getstatus (t) & TUNER_FL);
+}
+
+static int tuner_afcstatus (struct tuner *t)
+{
+        return (tuner_getstatus (t) & TUNER_AFC) - 2;
+}
+
+
+static void set_tv_freq(struct tuner *t, int freq)
+{
+        unsigned long flags;
+       u8 config;
+       u16 div;
+       struct tunertype *tun=&tuners[t->type];
+
+       if (freq < tun->thresh1) 
+               config = tun->VHF_L;
+       else if (freq < tun->thresh2) 
+               config = tun->VHF_H;
+       else
+               config = tun->UHF;
+
+       div=freq + (int)(16*38.9);
+       div&=0x7fff;
+
+       LOCK_I2C_BUS(t->bus);
+       if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) {
+           printk("tuner: i2c i/o error #1\n");
+       } else {
+           if (i2c_write(t->bus, t->addr, tun->config, config, 1))
+               printk("tuner: i2c i/o error #2\n");
+       }
+       UNLOCK_I2C_BUS(t->bus);
+}
+
+static void set_radio_freq(struct tuner *t, int freq)
+{
+        unsigned long flags;
+       u8 config;
+       u16 div;
+       struct tunertype *tun=&tuners[type];
+
+       config = 0xa5;
+       div=freq + (int)(16*10.7);
+       div&=0x7fff;
+
+       LOCK_I2C_BUS(t->bus);
+       if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) {
+           printk("tuner: i2c i/o error #1\n");
+       } else {
+           if (i2c_write(t->bus, t->addr, tun->config, config, 1))
+               printk("tuner: i2c i/o error #2\n");
+       }
+       if (debug) {
+               UNLOCK_I2C_BUS(t->bus);
+               current->state = TASK_INTERRUPTIBLE;
+               current->timeout = jiffies + HZ/10;
+               schedule();
+               LOCK_I2C_BUS(t->bus);
+               
+               if (tuner_islocked (t))
+                       printk ("tuner: PLL locked\n");
+               else
+                       printk ("tuner: PLL not locked\n");
+               
+               printk ("tuner: AFC: %d\n", tuner_afcstatus (t));
+       }
+       UNLOCK_I2C_BUS(t->bus);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int tuner_attach(struct i2c_device *device)
+{
+       struct tuner *t;
+
+       /*
+        *      For now we only try and attach these tuners to the BT848
+        *      bus. This same module will however work different species
+        *      of card using these chips. Just change the constraints
+        *      (i2c doesn't have a totally clash free 'address' space)
+        */
+        
+       if(device->bus->id!=I2C_BUSID_BT848)
+               return -EINVAL;
+               
+       device->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
+       if (NULL == t)
+               return -ENOMEM;
+       memset(t,0,sizeof(struct tuner));
+       strcpy(device->name,"tuner");
+       t->bus  = device->bus;
+       t->addr = device->addr;
+       t->type = type;
+       dprintk("tuner: type is %d (%s)\n",t->type,tuners[t->type].name);
+       
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+static int tuner_detach(struct i2c_device *device)
+{
+       struct tuner *t = (struct tuner*)device->data;
+       kfree(t);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static int tuner_command(struct i2c_device *device,
+             unsigned int cmd, void *arg)
+{
+       struct tuner *t = (struct tuner*)device->data;
+       int *iarg = (int*)arg;
+
+       switch (cmd) 
+       {
+               case TUNER_SET_TYPE:
+                       t->type = *iarg;
+                       dprintk("tuner: type set to %d (%s)\n",
+                       t->type,tuners[t->type].name);
+                       break;
+
+               case TUNER_SET_TVFREQ:
+                       dprintk("tuner: tv freq set to %d.%02d\n",
+                               (*iarg)/16,(*iarg)%16*100/16);
+                       set_tv_freq(t,*iarg);
+                       t->radio = 0;
+                       t->freq = *iarg;
+                       break;
+           
+               case TUNER_SET_RADIOFREQ:
+                       dprintk("tuner: radio freq set to %d.%02d\n",
+                               (*iarg)/16,(*iarg)%16*100/16);
+                       set_radio_freq(t,*iarg);
+                       t->radio = 1;
+                       t->freq = *iarg;
+                       break;
+           
+               default:
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+struct i2c_driver i2c_driver_tuner = 
+{
+       "tuner",                      /* name       */
+       I2C_DRIVERID_TUNER,           /* ID         */
+       0xc0, 0xce,                   /* addr range */
+
+       tuner_attach,
+       tuner_detach,
+       tuner_command
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int msp3400c_init(void)
+#endif
+{
+       i2c_register_driver(&i2c_driver_tuner);
+       return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+       i2c_unregister_driver(&i2c_driver_tuner);
+}
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index e3e7b889fe7d119c0374a877fb6880ab469237ef..3fb77de47a7a74e90088d07a230c1c704481b6f4 100644 (file)
 #define TEMIC   2
 #define Sony    3
 
-struct tunertype {
-  char *name;
-  unchar Vendor;
-  unchar Type;
-  
-  ushort thresh1; /* frequency Range for UHF,VHF-L, VHF_H */   
-  ushort thresh2;  
-  unchar VHF_L;
-  unchar VHF_H;
-  unchar UHF;
-  unchar config; 
-  unchar I2C;
-  ushort IFPCoff;
-};
-#endif
+#define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
+#define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
+#define TUNER_SET_RADIOFREQ          _IOW('t',3,int)    /* set radio freq */
 
+#endif
index 9fd8b17f16025398977c9fd34f63f985a3484c50..e9566da5389e992275c82f4f41dca6c1ae8a459c 100644 (file)
@@ -39,6 +39,9 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES];
 #ifdef CONFIG_VIDEO_BT848
 extern int init_bttv_cards(struct video_init *);
 #endif
+#ifdef CONFIG_VIDEO_SAA5249
+extern int init_saa_5249(struct video_init *);
+#endif 
 #ifdef CONFIG_VIDEO_CQCAM
 extern int init_colour_qcams(struct video_init *);
 #endif
@@ -50,6 +53,9 @@ static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
        {"bttv", init_bttv_cards},
 #endif 
+#ifdef CONFIG_VIDEO_SAA5249
+       {"saa5249", init_saa_5249},
+#endif 
 #ifdef CONFIG_VIDEO_CQCAM
        {"c-qcam", init_colour_qcams},
 #endif 
@@ -57,7 +63,7 @@ static struct video_init video_init_list[]={
        {"bw-qcam", init_bw_qcams},
 #endif 
 #ifdef CONFIG_VIDEO_PMS
-       {"PMS", init_pms_cards},        /* not defined anywhere */
+       {"PMS", init_pms_cards}, 
 #endif 
        {"end", NULL}
 };
@@ -74,6 +80,8 @@ static ssize_t video_read(struct file *file,
        return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
 }
 
+
+
 /*
  *     Write for now does nothing. No reason it shouldnt do overlay setting
  *     for some boards I guess..
@@ -162,18 +170,51 @@ static int video_ioctl(struct inode *inode, struct file *file,
 /*
  *     We need to do MMAP support
  */
+int video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+       if(vfl->mmap)
+               return vfl->mmap(vfl, (char *)vma->vm_start, 
+                               (unsigned long)(vma->vm_end-vma->vm_start));
+       return -EINVAL;
+}
 
 /*
  *     Video For Linux device drivers request registration here.
  */
  
-int video_register_device(struct video_device *vfd)
+int video_register_device(struct video_device *vfd, int type)
 {
        int i=0;
-       int base=0;
+       int base;
        int err;
+       int end;
+       
+       switch(type)
+       {
+               case VFL_TYPE_GRABBER:
+                       base=0;
+                       end=64;
+                       break;
+               case VFL_TYPE_VTX:
+                       base=192;
+                       end=224;
+                       break;
+               case VFL_TYPE_VBI:
+                       base=224;
+                       end=240;
+                       break;
+               case VFL_TYPE_RADIO:
+                       base=64;
+                       end=128;
+                       break;
+               default:
+                       return -1;
+       }
        
-       for(i=base;i<base+VIDEO_NUM_DEVICES;i++)
+       for(i=base;i<end;i++)
        {
                if(video_device[i]==NULL)
                {
@@ -216,7 +257,7 @@ static struct file_operations video_fops=
        NULL,   /* readdir */
        NULL,   /* poll */
        video_ioctl,
-       NULL,   /* mmap */
+       video_mmap,
        video_open,
        video_release
 };
index 1d7d7e5dae8a5419671d22b606b93b96d662d957..59a8a94e34d90c95ab1a013627ed4f8ceb4f5eac 100644 (file)
@@ -15,7 +15,7 @@
  *
  */
 
-
+#include <linux/config.h>
 #define __NO_VERSION__
 #include "hisax.h"
 #include "isac.h"
index faf59ca6115a01b31a8c193d44b40cb15fd78c09..0235ccb59596df5b4c3d0a57a42d9a61c85f8300 100644 (file)
@@ -38,6 +38,7 @@
  *
  */
 
+#include <linux/config.h>
 #include "isdnloop.h"
 
 static char
index 2eb8d25835da5b005007ffa351afa4dc445044ed..cacd686d7202733703bf86127358d863a7491c4e 100644 (file)
@@ -53,7 +53,6 @@ typedef struct isdnloop_sdef {
 #ifdef __KERNEL__
 /* Kernel includes */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/errno.h>
index d038a77710373f7395481fe34e8bfde9dd4b74e7..1d1891857320019b8d56eeeabbca80affc232bbe 100644 (file)
@@ -4,6 +4,7 @@
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *          Philip Blundell <philb@gnu.org>
  *          Andrea Arcangeli <arcangeli@mbox.queen.it>
+ *          Riccardo Facchetti <fizban@tin.it>
  *
  * based on work by Grant Guenther <grant@torque.net>
  *              and Philip Blundell
@@ -11,6 +12,7 @@
 
 #include <linux/stddef.h>
 #include <linux/tasks.h>
+#include <linux/ctype.h>
 #include <asm/ptrace.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -32,55 +34,78 @@ extern void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
 static int irq_write_proc(struct file *file, const char *buffer,
                                          unsigned long count, void *data)
 {
-       int newirq, oldirq;
+       int retval = -EINVAL;
+       int newirq = PARPORT_IRQ_NONE;
        struct parport *pp = (struct parport *)data;
-       
-       if (count > 5 )  /* more than 4 digits + \n for a irq 0x?? 0?? ??  */
-               return -EOVERFLOW;
-
-       if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) {
-               newirq = PARPORT_IRQ_NONE;
-       } else {
-               if (buffer[0] == '0') {
-                       if (buffer[1] == 'x')
-                               newirq = simple_strtoul(&buffer[2], 0, 16);
-                       else
-                               newirq = simple_strtoul(&buffer[1], 0, 8);
-               } else {
-                       newirq = simple_strtoul(buffer, 0, 10);
-               }
-       }
+       struct pardevice *cad = pp->cad;
+       int oldirq = pp->irq;
+
+/*
+ * We can have these valid cases:
+ *     "none" (count == 4 || count == 5)
+ *     decimal number (count == 2 || count == 3)
+ *     octal number (count == 3 || count == 4)
+ *     hex number (count == 4 || count == 5)
+ * all other cases are -EINVAL
+ *
+ * Note: newirq is alredy set up to NONE.
+ *
+ * -RF
+ */
+       if (count > 5  || count < 1)
+               goto out;
 
-       if (newirq >= NR_IRQS)
-               return -EOVERFLOW;
+       if (isdigit(buffer[0]))
+               newirq = simple_strtoul(buffer, NULL, 0);
+       else if (strncmp(buffer, "none", 4) != 0) {
+               if (buffer[0] < 32)
+                       /* Things like '\n' are harmless */
+                       retval = count;
 
-       if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) {
-               if (pp->cad != NULL && pp->cad->irq_func != NULL)
-                       free_irq(pp->irq, pp->cad->private);
-               else
-                       free_irq(pp->irq, NULL);
+               goto out;
        }
 
-       oldirq = pp->irq;
-       pp->irq = newirq;
+       retval = count;
+
+       if (oldirq == newirq)
+               goto out;
 
-       if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) { 
-               struct pardevice *cad = pp->cad;
+       if (pp->flags & PARPORT_FLAG_COMA)
+               goto out_ok;
 
-               if (cad == NULL)
-                       request_irq(pp->irq, parport_null_intr_func,
-                                   SA_INTERRUPT, pp->name, NULL);
+       if (newirq != PARPORT_IRQ_NONE) { 
+               void (*handler)(int, void *, struct pt_regs *);
+
+               if (cad && cad->irq_func)
+                       handler = cad->irq_func;
+               else
+                       handler = parport_null_intr_func;
+
+               retval = request_irq(newirq, handler,
+                                    SA_INTERRUPT,
+                                    cad ? cad->name : pp->name,
+                                    cad ? cad->private : NULL);
+               if (retval)
+                       goto out;
+               else retval = count;
+       }
+
+       if (oldirq != PARPORT_IRQ_NONE) {
+               if (cad && cad->irq_func)
+                       free_irq(oldirq, cad->private);
                else
-                       request_irq(pp->irq, cad->irq_func ? cad->irq_func :
-                                   parport_null_intr_func, SA_INTERRUPT,
-                                   cad->name, cad->private);
+                       free_irq(oldirq, NULL);
        }
 
+out_ok:
+       pp->irq = newirq;
+
        if (oldirq != PARPORT_IRQ_NONE && newirq == PARPORT_IRQ_NONE &&
-           pp->cad != NULL && pp->cad->irq_func != NULL)
-               pp->cad->irq_func(pp->irq, pp->cad->private, NULL);
+           cad && cad->irq_func)
+               cad->irq_func(pp->irq, cad->private, NULL);
 
-       return count;
+out:
+       return retval;
 }
 
 static int irq_read_proc(char *page, char **start, off_t off,
@@ -167,6 +192,20 @@ static inline void destroy_proc_entry(struct proc_dir_entry *root,
        *d = NULL;
 }
 
+static void destroy_proc_tree(struct parport *pp) {
+       if (pp->pdir.entry) {
+               if (pp->pdir.irq) 
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+               if (pp->pdir.devices) 
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
+               if (pp->pdir.hardware)
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.hardware);
+               if (pp->pdir.probe)
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.probe);
+               destroy_proc_entry(base, &pp->pdir.entry);
+       }
+}
+
 static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
                                             struct proc_dir_entry *parent,
                                             unsigned short ino)
@@ -220,8 +259,6 @@ void parport_proc_cleanup(void)
 
 int parport_proc_register(struct parport *pp)
 {
-       static const char *proc_msg = KERN_ERR "%s: Trouble with /proc.\n";
-
        memset(&pp->pdir, 0, sizeof(struct parport_dir));
 
        if (base == NULL) {
@@ -233,63 +270,43 @@ int parport_proc_register(struct parport *pp)
                sizeof(pp->pdir.name));
 
        pp->pdir.entry = new_proc_entry(pp->pdir.name, S_IFDIR, base, 0);
-       if (pp->pdir.entry == NULL) {
-               printk(proc_msg, pp->name);
-               return 1;
-       }
+       if (pp->pdir.entry == NULL)
+               goto out_fail;
 
        pp->pdir.irq = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, 
                                      pp->pdir.entry, 0);
-       if (pp->pdir.irq == NULL) {
-               printk(proc_msg, pp->name);
-               destroy_proc_entry(base, &pp->pdir.entry);
-               return 1;
-       }
+       if (pp->pdir.irq == NULL)
+               goto out_fail;
+
        pp->pdir.irq->read_proc = irq_read_proc;
        pp->pdir.irq->write_proc = irq_write_proc;
        pp->pdir.irq->data = pp;
        
        pp->pdir.devices = new_proc_entry("devices", 0, pp->pdir.entry, 0);
-       if (pp->pdir.devices == NULL) {
-               printk(proc_msg, pp->name);
-               destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
-               destroy_proc_entry(base, &pp->pdir.entry);
-               return 1;
-       }
+       if (pp->pdir.devices == NULL)
+               goto out_fail;
+
        pp->pdir.devices->read_proc = devices_read_proc;
        pp->pdir.devices->data = pp;
        
        pp->pdir.hardware = new_proc_entry("hardware", 0, pp->pdir.entry, 0);
-       if (pp->pdir.hardware == NULL) {
-               printk(proc_msg, pp->name);
-               destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
-               destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
-               destroy_proc_entry(base, &pp->pdir.entry);
-               return 1;
-       }
+       if (pp->pdir.hardware == NULL)
+               goto out_fail;
+
        pp->pdir.hardware->read_proc = hardware_read_proc;
        pp->pdir.hardware->data = pp;
 
        return 0;
+
+out_fail:
+
+       printk(KERN_ERR "%s: failure registering /proc/ entry.\n", pp->name);
+       destroy_proc_tree(pp);
+       return 1;
 }
 
 int parport_proc_unregister(struct parport *pp)
 {
-       if (pp->pdir.entry) {
-               if (pp->pdir.irq) 
-                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
-               
-               if (pp->pdir.devices) 
-                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
-               
-               if (pp->pdir.hardware)
-                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.hardware);
-
-               if (pp->pdir.probe)
-                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.probe);
-               
-               destroy_proc_entry(base, &pp->pdir.entry);
-       }
-       
+       destroy_proc_tree(pp);
        return 0;
 }
index 03df2dc60d5a867172501aeaf453dabbfdbdd21f..d85b7c4141e3bad09e49d764be720cd68c0e957f 100644 (file)
@@ -102,8 +102,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
     tristate 'Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
     tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'TI ThunderLAN support (EXPERIMENTAL)' CONFIG_TLAN
       tristate 'Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210
+      tristate 'SMC EtherPower II (EXPERIMENTAL)' CONFIG_EPIC100
+      tristate 'TI ThunderLAN support (EXPERIMENTAL)' CONFIG_TLAN
       bool 'Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET
     fi
   fi
index 7af6c30e9c716951dc868cc7a1d060d0b34d49e9..e3e2798ee4b86df4543536f98e24a5c54d87bf67 100644 (file)
@@ -581,6 +581,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_EPIC100),y)
+L_OBJS += epic100.o
+else
+  ifeq ($(CONFIG_EPIC100),m)
+  M_OBJS += epic100.o
+  endif
+endif
+
 # If anything built-in uses slhc, then build it into the kernel also.
 # If not, but a module uses it, build as a module.
 ifdef CONFIG_SLHC_BUILTIN
index 9d880aa4d6cf95f13e338ef5b8d15a1b397827b6..b01c6a8a894902b5ac132b3de852a58cb5a1bff6 100644 (file)
@@ -94,6 +94,7 @@ extern int tlan_probe(struct device *);
 extern int mace_probe(struct device *);
 extern int cs89x0_probe(struct device *dev);
 extern int ethertap_probe(struct device *dev);
+extern int epic100_probe(struct device *dev);
 
 /* Detachable devices ("pocket adaptors") */
 extern int atp_init(struct device *);
@@ -286,6 +287,9 @@ __initfunc(static int ethif_probe(struct device *dev))
 #endif
 #ifdef CONFIG_ARM_AM79C961A
        && am79c961_probe(dev)
+#endif
+#ifdef CONFIG_EPIC100
+       && epic100_probe(dev)
 #endif
        && 1 ) {
        return 1;       /* -ENODEV or -EAGAIN would be more accurate. */
index d8ad8c67b4aab6ace044b3711326a755518f73eb..c0c52d24fb1462716b206aaefc4ca64fc5c2e424 100644 (file)
 
 static const char *version = "de4x5.c:V0.536 1998/3/5 davies@maniac.ultranet.com\n";
 
+#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
new file mode 100644 (file)
index 0000000..b6fc14f
--- /dev/null
@@ -0,0 +1,1215 @@
+/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Linux. */
+/*
+   NOTICE: THIS IS THE ALPHA TEST VERSION!
+       Written 1997 by Donald Becker.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+    All other rights reserved.
+
+       This driver is for the SMC EtherPower II 9432 PCI ethernet adapter based on
+       the SMC83c170.
+
+       The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+       Center of Excellence in Space Data and Information Sciences
+          Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+       Support and updates available at
+       http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html
+*/
+
+static const char *version =
+"epic100.c:v0.10 10/14/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+
+/* A few user-configurable values. */
+
+/* Keep the ring sizes a power of two for efficiency.
+   Making the Tx ring too large decreases the effectiveness of channel
+   bonding and packet priority.
+   There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE   16
+#define RX_RING_SIZE   32
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+   Setting to > 1518 effectively disables this feature. */
+static const int rx_copybreak = 200;
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 10;
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  ((2000*HZ)/1000)
+
+#define PKT_BUF_SZ             1536                    /* Size of each temporary Rx buffer.*/
+
+/* Bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 128             /* Rounded down to 4 byte units. */
+#define RX_FIFO_THRESH 1               /* 0-3, 0==32, 64,96, or 3==128 bytes  */
+
+#include <linux/config.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <asm/processor.h>             /* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+   This is only in the support-all-kernels source code. */
+#include <linux/version.h>             /* Evil, but neccessary */
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
+#define RUN_AT(x) (x)                  /* What to put in timer->expires.  */
+#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
+#define virt_to_bus(addr)  ((unsigned long)addr)
+#define bus_to_virt(addr) ((void*)addr)
+
+#else  /* 1.3.0 and later */
+#define RUN_AT(x) (jiffies + (x))
+#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+#endif
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
+#ifdef MODULE
+#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
+char kernel_version[] = UTS_RELEASE;
+#endif
+#else
+#undef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT
+#undef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+#endif /* 1.3.38 */
+
+#if (LINUX_VERSION_CODE >= 0x10344)
+#define NEW_MULTICAST
+#include <linux/delay.h>
+#endif
+
+#ifdef SA_SHIRQ
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
+#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+#else
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
+#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#else
+#ifdef MODULE
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("SMC 82c170 EPIC series Ethernet driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+#endif
+#endif
+
+/* The I/O extent. */
+#define EPIC_TOTAL_SIZE 0x100
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry epic100_drv =
+{"Epic100", epic100_pci_probe, EPIC_TOTAL_SIZE, NULL};
+#endif
+
+static int epic_debug = 1;
+
+/*
+                               Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the SMC "EPCI/100", the SMC
+single-chip ethernet controllers for PCI.  This chip is used on
+the SMC EtherPower II boards.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+Note: Kernel versions earlier than 1.3.73 do not support shared PCI
+interrupt lines.
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+IVb. References
+
+http://www.smc.com/components/catalog/smc83c170.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.national.com/pf/DP/DP83840.html
+
+IVc. Errata
+
+*/
+
+#ifndef PCI_VENDOR_ID_SMC
+#define PCI_VENDOR_ID_SMC                      0x10B8
+#endif
+#ifndef PCI_DEVICE_ID_SMC_EPIC100
+#define PCI_DEVICE_ID_SMC_EPIC100      0x0005
+#endif
+
+/* The rest of these values should never change. */
+/* Offsets to registers, using the (ugh) SMC names. */
+enum epic_registers {
+  COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
+  TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28,    /* Rx error counters. */
+  MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
+  LAN0=64,                                             /* MAC address. */
+  MC0=80,                                              /* Multicast filter table. */
+  RxCtrl=96, TxCtrl=112, TxSTAT=0x74,
+  PRxCDAR=0x84, RxSTAT=0xA4, EarlyRx=0xB0, PTxCDAR=0xC4, TxThresh=0xDC,
+};
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatus {
+  TxIdle=0x40000, RxIdle=0x20000,
+  CntFull=0x0200, TxUnderrun=0x0100,
+  TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
+  RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
+};
+
+/* The EPIC100 Rx and Tx buffer descriptors. */
+
+struct epic_tx_desc {
+       s16 status;
+       u16 txlength;
+       u32 bufaddr;
+       u16 buflength;
+       u16 control;
+    u32 next;
+};
+
+struct epic_rx_desc {
+       s16 status;
+       u16 rxlength;
+       u32 bufaddr;
+       u32 buflength;
+    u32 next;
+};
+
+struct epic_private {
+       char devname[8];                        /* Used only for kernel debugging. */
+       const char *product_name;
+       struct device *next_module;
+       struct epic_rx_desc rx_ring[RX_RING_SIZE];
+       struct epic_tx_desc tx_ring[TX_RING_SIZE];
+       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       struct sk_buff* tx_skbuff[TX_RING_SIZE];
+       /* The addresses of receive-in-place skbuffs. */
+       struct sk_buff* rx_skbuff[RX_RING_SIZE];
+       int chip_id;
+       int revision;
+       struct enet_statistics stats;
+       struct timer_list timer;        /* Media selection timer. */
+       unsigned int cur_rx, cur_tx;            /* The next free ring entry */
+       unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
+       unsigned char mc_filter[8];
+       signed char phys[4];                            /* MII device addresses. */
+       unsigned int tx_full:1;                         /* The Tx queue is full. */
+       unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
+       unsigned int default_port:4;            /* Last dev->if_port value. */
+       unsigned int media2:4;                          /* Secondary monitored media port. */
+       unsigned int medialock:1;                       /* Don't sense media type. */
+       unsigned int mediasense:1;                      /* Media sensing in progress. */
+       int pad0, pad1;                                         /* Used for 8-byte alignment */
+};
+
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#ifdef MODULE
+/* Used to pass the full-duplex flag, etc. */
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#endif
+
+static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
+                                                                        int chip_id, int options, int card_idx);
+static int epic_open(struct device *dev);
+static int read_eeprom(int ioaddr, int location);
+static int mii_read(int ioaddr, int phy_id, int location);
+static void epic_timer(unsigned long data);
+static void epic_tx_timeout(struct device *dev);
+static void epic_init_ring(struct device *dev);
+static int epic_start_xmit(struct sk_buff *skb, struct device *dev);
+static int epic_rx(struct device *dev);
+static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int epic_close(struct device *dev);
+static struct enet_statistics *epic_get_stats(struct device *dev);
+#ifdef NEW_MULTICAST
+static void set_rx_mode(struct device *dev);
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+
+\f
+
+#ifdef MODULE
+/* A list of all installed EPIC devices, for removing the driver module. */
+static struct device *root_epic_dev = NULL;
+#endif
+
+int epic100_probe(struct device *dev)
+{
+       int cards_found = 0;
+       static int pci_index = 0;       /* Static, for multiple probe calls. */
+
+       /* Ideally we would detect all network cards in slot order.  That would
+          be best done a central PCI probe dispatch, which wouldn't work
+          well with the current structure.  So instead we detect just the
+          Epic cards in slot order. */
+
+       if (pcibios_present()) {
+               unsigned char pci_bus, pci_device_fn;
+
+               for (;pci_index < 0xff; pci_index++) {
+                       unsigned char pci_irq_line, pci_latency;
+                       unsigned short pci_command, vendor, device;
+                       unsigned int pci_ioaddr, chip_idx = 0;
+
+                       if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+#ifdef REVERSE_PROBE_ORDER
+                                                                       0xff - pci_index,
+#else
+                                                                       pci_index,
+#endif
+                                                                       &pci_bus, &pci_device_fn)
+                               != PCIBIOS_SUCCESSFUL)
+                               break;
+                       pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                        PCI_VENDOR_ID, &vendor);
+                       if (vendor != PCI_VENDOR_ID_SMC)
+                               continue;
+
+                       pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                        PCI_DEVICE_ID, &device);
+                       pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                        PCI_INTERRUPT_LINE, &pci_irq_line);
+                       pcibios_read_config_dword(pci_bus, pci_device_fn,
+                                                                         PCI_BASE_ADDRESS_0, &pci_ioaddr);
+                       /* Remove I/O space marker in bit 0. */
+                       pci_ioaddr &= ~3;
+
+                       if (device != PCI_DEVICE_ID_SMC_EPIC100) {
+                               printk("Unknown SMC PCI ethernet chip type %4.4x detected:"
+                                          " not configured.\n", device);
+                               continue;
+                       }
+                       if (epic_debug > 2)
+                               printk("Found SMC PCI EPIC/100 at I/O %#x, IRQ %d.\n",
+                                          pci_ioaddr, pci_irq_line);
+
+                       if (check_region(pci_ioaddr, EPIC_TOTAL_SIZE))
+                               continue;
+
+#ifdef MODULE
+                       dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
+                                                options[cards_found], cards_found);
+#else
+                       dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
+                                                dev ? dev->mem_start : 0, -1);
+#endif
+
+                       if (dev) {
+                         /* Get and check the bus-master and latency values. */
+                         pcibios_read_config_word(pci_bus, pci_device_fn,
+                                                                          PCI_COMMAND, &pci_command);
+                         if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+                               printk("  PCI Master Bit has not been set! Setting...\n");
+                               pci_command |= PCI_COMMAND_MASTER;
+                               pcibios_write_config_word(pci_bus, pci_device_fn,
+                                                                                 PCI_COMMAND, pci_command);
+                         }
+                         pcibios_read_config_byte(pci_bus, pci_device_fn,
+                                                                          PCI_LATENCY_TIMER, &pci_latency);
+                         if (pci_latency < 10) {
+                               printk("  PCI latency timer (CFLT) is unreasonably low at %d."
+                                          "  Setting to 255 clocks.\n", pci_latency);
+                               pcibios_write_config_byte(pci_bus, pci_device_fn,
+                                                                                 PCI_LATENCY_TIMER, 255);
+                         } else if (epic_debug > 1)
+                               printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
+                         dev = 0;
+                         cards_found++;
+                       }
+               }
+       }
+
+#if defined (MODULE)
+       return cards_found;
+#else
+       return cards_found ? 0 : -ENODEV;
+#endif
+}
+
+static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
+                                                                  int chip_id, int options, int card_idx)
+{
+       static int did_version = 0;                     /* Already printed version info. */
+       struct epic_private *tp;
+       int i;
+
+       if (epic_debug > 0  &&  did_version++ == 0)
+               printk(version);
+
+       dev = init_etherdev(dev, 0);
+
+       printk("%s: SMC EPIC/100 at %#3x, IRQ %d, ", dev->name, ioaddr, irq);
+
+       /* Bring the chip out of low-power mode. */
+       outl(0x0200, ioaddr + GENCTL);
+       /* Magic?!  If we don't set this bit the MII interface won't work. */
+       outl(0x0008, ioaddr + TEST1);
+
+       /* This could also be read from the EEPROM. */
+       for (i = 0; i < 3; i++)
+               ((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
+
+       for (i = 0; i < 5; i++)
+               printk("%2.2x:", dev->dev_addr[i]);
+       printk("%2.2x.\n", dev->dev_addr[i]);
+
+       if (epic_debug > 1) {
+         printk("%s: EEPROM contents\n", dev->name);
+         for (i = 0; i < 64; i++)
+               printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : "");
+       }
+
+       /* We do a request_region() to register /proc/ioports info. */
+       request_region(ioaddr, EPIC_TOTAL_SIZE, "SMC EPIC/100");
+
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+
+       /* The data structures must be quadword aligned. */
+       tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
+       memset(tp, 0, sizeof(*tp));
+       dev->priv = tp;
+
+#ifdef MODULE
+       tp->next_module = root_epic_dev;
+       root_epic_dev = dev;
+#endif
+
+       tp->chip_id = chip_id;
+
+       /* Find the connected MII xcvrs.
+          Doing this in open() would allow detecting external xcvrs later, but
+          takes too much time. */
+       {
+               int phy, phy_idx;
+               for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+                        phy++) {
+                       int mii_status = mii_read(ioaddr, phy, 0);
+                       if (mii_status != 0xffff  && mii_status != 0x0000) {
+                               tp->phys[phy_idx++] = phy;
+                               printk("%s: MII transceiver found at address %d.\n",
+                                          dev->name, phy);
+                       }
+               }
+               if (phy_idx == 0) {
+                       printk("%s: ***WARNING***: No MII transceiver found!\n",
+                                  dev->name);
+                       /* Use the known PHY address of the EPII. */
+                       tp->phys[0] = 3;
+               }
+       }
+
+       /* Leave the chip in low-power mode. */
+       outl(0x0008, ioaddr + GENCTL);
+
+       /* The lower four bits are the media type. */
+       if (options > 0) {
+               tp->full_duplex = (options & 16) ? 1 : 0;
+               tp->default_port = options & 15;
+               if (tp->default_port)
+                 tp->medialock = 1;
+       }
+       if (card_idx >= 0) {
+               if (full_duplex[card_idx] >= 0)
+                       tp->full_duplex = full_duplex[card_idx];
+       }
+
+       /* The Epic-specific entries in the device structure. */
+       dev->open = &epic_open;
+       dev->hard_start_xmit = &epic_start_xmit;
+       dev->stop = &epic_close;
+       dev->get_stats = &epic_get_stats;
+       dev->set_multicast_list = &set_rx_mode;
+
+       return dev;
+}
+\f
+/* Serial EEPROM section. */
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK   0x04    /* EEPROM shift clock. */
+#define EE_CS                  0x02    /* EEPROM chip select. */
+#define EE_DATA_WRITE  0x08    /* EEPROM chip data in. */
+#define EE_WRITE_0             0x01
+#define EE_WRITE_1             0x09
+#define EE_DATA_READ   0x10    /* EEPROM chip data out. */
+#define EE_ENB                 (0x0001 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+   The 1.2 code is a "nasty" timing loop, but PC compatible machines are
+   *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro.  */
+#ifdef _LINUX_DELAY_H
+#define eeprom_delay(nanosec)  udelay((nanosec + 999)/1000)
+#else
+#define eeprom_delay(nanosec)  do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#endif
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD   (5 << 6)
+#define EE_READ_CMD            (6 << 6)
+#define EE_ERASE_CMD   (7 << 6)
+
+static int read_eeprom(int ioaddr, int location)
+{
+       int i;
+       int retval = 0;
+       int ee_addr = ioaddr + EECTL;
+       int read_cmd = location | EE_READ_CMD;
+       
+       outl(EE_ENB & ~EE_CS, ee_addr);
+       outl(EE_ENB, ee_addr);
+       
+       /* Shift the read command bits out. */
+       for (i = 10; i >= 0; i--) {
+               short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               outl(EE_ENB | dataval, ee_addr);
+               eeprom_delay(100);
+               outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay(150);
+               outl(EE_ENB | dataval, ee_addr);        /* Finish EEPROM a clock tick. */
+               eeprom_delay(250);
+       }
+       outl(EE_ENB, ee_addr);
+       
+       for (i = 16; i > 0; i--) {
+               outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
+               eeprom_delay(100);
+               retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+               outl(EE_ENB, ee_addr);
+               eeprom_delay(100);
+       }
+
+       /* Terminate the EEPROM access. */
+       outl(EE_ENB & ~EE_CS, ee_addr);
+       return retval;
+}
+
+#define MII_READOP             1
+#define MII_WRITEOP            2
+static int mii_read(int ioaddr, int phy_id, int location)
+{
+       int i;
+
+       outl((phy_id << 9) | (location << 4) | MII_READOP, ioaddr + MIICtrl);
+       /* Typical operation takes < 50 ticks. */
+       for (i = 4000; i > 0; i--)
+               if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0)
+                       break;
+       return inw(ioaddr + MIIData);
+}
+
+\f
+static int
+epic_open(struct device *dev)
+{
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+       int i;
+       int mii_reg5;
+       int full_duplex = 0;
+
+       /* Soft reset the chip. */
+       outl(0x0001, ioaddr + GENCTL);
+
+#ifdef SA_SHIRQ
+       if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ,
+                                       "SMC EPIC/100", dev)) {
+               return -EAGAIN;
+       }
+#else
+       if (irq2dev_map[dev->irq] != NULL
+               || (irq2dev_map[dev->irq] = dev) == NULL
+               || dev->irq == 0
+               || request_irq(dev->irq, &epic_interrupt, 0, "SMC EPIC/100")) {
+               return -EAGAIN;
+       }
+#endif
+
+       MOD_INC_USE_COUNT;
+
+       epic_init_ring(dev);
+
+       /* This next line by Ken Yamaguchi.. ?? */
+       outl(0x8, ioaddr + 0x1c);
+
+       /* Pull the chip out of low-power mode, enable interrupts, and set for PCI read multiple. */
+       outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+
+       for (i = 0; i < 3; i++)
+               outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+
+       outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+       full_duplex = tp->full_duplex;
+
+       mii_reg5 = mii_read(ioaddr, tp->phys[0], 5);
+       if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
+               full_duplex = 1;
+               if (epic_debug > 1)
+                       printk("%s: Setting %s-duplex based on MII xcvr %d"
+                                  " register read of %4.4x.\n", dev->name,
+                                  full_duplex ? "full" : "half", tp->phys[0],
+                                  mii_read(ioaddr, tp->phys[0], 5));
+       }
+
+       outl(full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+       outl(virt_to_bus(tp->rx_ring), ioaddr + PRxCDAR);
+       outl(virt_to_bus(tp->tx_ring), ioaddr + PTxCDAR);
+
+       /* Start the chip's Rx process. */
+       set_rx_mode(dev);
+       outl(0x000A, ioaddr + COMMAND);
+
+       dev->tbusy = 0;
+       dev->interrupt = 0;
+       dev->start = 1;
+
+       /* Enable interrupts by setting the interrupt mask. */
+       outl(CntFull | TxUnderrun | TxDone
+                | RxError | RxOverflow | RxFull | RxHeader | RxDone,
+                ioaddr + INTMASK);
+
+       if (epic_debug > 1)
+               printk("%s: epic_open() ioaddr %4.4x IRQ %d status %4.4x %s-duplex.\n",
+                          dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
+                          full_duplex ? "full" : "half");
+
+       /* Set the timer to switch to check for link beat and perhaps switch
+          to an alternate media type. */
+       init_timer(&tp->timer);
+       tp->timer.expires = RUN_AT((24*HZ)/10);                 /* 2.4 sec. */
+       tp->timer.data = (unsigned long)dev;
+       tp->timer.function = &epic_timer;                               /* timer handler */
+       add_timer(&tp->timer);
+
+       return 0;
+}
+
+static void epic_timer(unsigned long data)
+{
+       struct device *dev = (struct device *)data;
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+       int next_tick = 0;
+
+       if (epic_debug > 3) {
+               printk("%s: Media selection tick, Tx status %8.8x.\n",
+                          dev->name, inl(ioaddr + TxSTAT));
+               printk("%s: Other registers are IntMask %4.4x IntStatus %4.4x RxStatus"
+                          " %4.4x.\n",
+                          dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
+                          inl(ioaddr + RxSTAT));
+       }
+
+       if (next_tick) {
+               tp->timer.expires = RUN_AT(next_tick);
+               add_timer(&tp->timer);
+       }
+}
+
+static void epic_tx_timeout(struct device *dev)
+{
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+
+       if (epic_debug > 0) {
+               printk("%s: Transmit timeout using MII device, Tx status %4.4x.\n",
+                          dev->name, inw(ioaddr + TxSTAT));
+               if (epic_debug > 1) {
+                       printk("%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
+                        dev->name, tp->dirty_tx, tp->cur_tx);
+               }
+       }
+       /* Perhaps stop and restart the chip's Tx processes . */
+       /* Trigger a transmit demand. */
+       outl(0x0004, dev->base_addr + COMMAND);
+
+       dev->trans_start = jiffies;
+       tp->stats.tx_errors++;
+       return;
+}
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void
+epic_init_ring(struct device *dev)
+{
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int i;
+
+       tp->tx_full = 0;
+       tp->cur_rx = tp->cur_tx = 0;
+       tp->dirty_rx = tp->dirty_tx = 0;
+
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               tp->rx_ring[i].status = 0x8000;         /* Owned by Epic chip */
+               tp->rx_ring[i].buflength = PKT_BUF_SZ;
+               {
+                       /* Note the receive buffer must be longword aligned.
+                          dev_alloc_skb() provides 16 byte alignment.  But do *not*
+                          use skb_reserve() to align the IP header! */
+                       struct sk_buff *skb;
+                       skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+                       tp->rx_skbuff[i] = skb;
+                       if (skb == NULL)
+                               break;                  /* Bad news!  */
+                       skb->dev = dev;                 /* Mark as being used by this device. */
+#if LINUX_VERSION_CODE > 0x10300
+                       skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
+                       tp->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
+#else
+                       tp->rx_ring[i].bufaddr = virt_to_bus(skb->data);
+#endif
+               }
+               tp->rx_ring[i].next = virt_to_bus(&tp->rx_ring[i+1]);
+       }
+       /* Mark the last entry as wrapping the ring. */
+       tp->rx_ring[i-1].next = virt_to_bus(&tp->rx_ring[0]);
+
+       /* The Tx buffer descriptor is filled in as needed, but we
+          do need to clear the ownership bit. */
+       for (i = 0; i < TX_RING_SIZE; i++) {
+               tp->tx_skbuff[i] = 0;
+               tp->tx_ring[i].status = 0x0000;
+               tp->tx_ring[i].next = virt_to_bus(&tp->tx_ring[i+1]);
+       }
+       tp->tx_ring[i-1].next = virt_to_bus(&tp->tx_ring[0]);
+}
+
+static int
+epic_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int entry;
+       u32 flag;
+
+       /* Block a timer-based transmit from overlapping.  This could better be
+          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+               if (jiffies - dev->trans_start < TX_TIMEOUT)
+                       return 1;
+               epic_tx_timeout(dev);
+               return 1;
+       }
+
+       /* Caution: the write order is important here, set the base address
+          with the "ownership" bits last. */
+
+       /* Calculate the next Tx descriptor entry. */
+       entry = tp->cur_tx % TX_RING_SIZE;
+
+       tp->tx_skbuff[entry] = skb;
+       tp->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
+       tp->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
+       tp->tx_ring[entry].buflength = skb->len;
+
+       if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+         flag = 0x10; /* No interrupt */
+         dev->tbusy = 0;
+       } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+         flag = 0x14; /* Tx-done intr. */
+         dev->tbusy = 0;
+       } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+         flag = 0x10; /* No Tx-done intr. */
+         dev->tbusy = 0;
+       } else {
+         /* Leave room for two additional entries. */
+         flag = 0x14; /* Tx-done intr. */
+         tp->tx_full = 1;
+       }
+
+       tp->tx_ring[entry].control = flag;
+       tp->tx_ring[entry].status = 0x8000;     /* Pass ownership to the chip. */
+       tp->cur_tx++;
+       /* Trigger an immediate transmit demand. */
+       outl(0x0004, dev->base_addr + COMMAND);
+
+       dev->trans_start = jiffies;
+       if (epic_debug > 4)
+               printk("%s: Queued Tx packet size %d to slot %d, "
+                          "flag %2.2x Tx status %8.8x.\n",
+                          dev->name, (int)skb->len, entry, flag,
+                          inl(dev->base_addr + TxSTAT));
+
+       return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+{
+#ifdef SA_SHIRQ
+       struct device *dev = (struct device *)dev_instance;
+#else
+       struct device *dev = (struct device *)(irq2dev_map[irq]);
+#endif
+       struct epic_private *lp;
+       int status, ioaddr, boguscnt = max_interrupt_work;
+
+       if (dev == NULL) {
+               printk ("epic_interrupt(): irq %d for unknown device.\n", irq);
+               return;
+       }
+
+       ioaddr = dev->base_addr;
+       lp = (struct epic_private *)dev->priv;
+       if (dev->interrupt)
+               printk("%s: Re-entering the interrupt handler.\n", dev->name);
+
+       dev->interrupt = 1;
+
+       do {
+               status = inl(ioaddr + INTSTAT);
+               /* Acknowledge all of the current interrupt sources ASAP. */
+               outl(status & 0x00007fff, ioaddr + INTSTAT);
+
+               if (epic_debug > 4)
+                       printk("%s: interrupt  interrupt=%#8.8x new intstat=%#8.8x.\n",
+                                  dev->name, status, inl(ioaddr + INTSTAT));
+
+               if ((status & (RxDone | TxEmpty | TxDone)) == 0)
+                       break;
+
+               if (status & RxDone)                    /* Rx interrupt */
+                       epic_rx(dev);
+
+               if (status & (TxEmpty | TxDone)) {
+                       int dirty_tx;
+
+                       for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+                               int entry = dirty_tx % TX_RING_SIZE;
+                               int txstatus = lp->tx_ring[entry].status;
+
+                               if (txstatus < 0)
+                                       break;                  /* It still hasn't been Txed */
+
+                               if ( ! (txstatus & 0x0001)) {
+                                       /* There was an major error, log it. */
+#ifndef final_version
+                                       if (epic_debug > 1)
+                                               printk("%s: Transmit error, Tx status %8.8x.\n",
+                                                          dev->name, txstatus);
+#endif
+                                       lp->stats.tx_errors++;
+                                       if (txstatus & 0x1050) lp->stats.tx_aborted_errors++;
+                                       if (txstatus & 0x0008) lp->stats.tx_carrier_errors++;
+                                       if (txstatus & 0x0040) lp->stats.tx_window_errors++;
+                                       if (txstatus & 0x0010) lp->stats.tx_fifo_errors++;
+#ifdef ETHER_STATS
+                                       if (txstatus & 0x1000) lp->stats.collisions16++;
+#endif
+                               } else {
+#ifdef ETHER_STATS
+                                       if ((txstatus & 0x0002) != 0) lp->stats.tx_deferred++;
+#endif
+                                       lp->stats.collisions += (txstatus >> 8) & 15;
+                                       lp->stats.tx_packets++;
+                               }
+
+                               /* Free the original skb. */
+                               dev_kfree_skb(lp->tx_skbuff[entry]);
+                               lp->tx_skbuff[entry] = 0;
+                       }
+
+#ifndef final_version
+                       if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+                               printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+                                          dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+                               dirty_tx += TX_RING_SIZE;
+                       }
+#endif
+
+                       if (lp->tx_full && dev->tbusy
+                               && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+                               /* The ring is no longer full, clear tbusy. */
+                               lp->tx_full = 0;
+                               dev->tbusy = 0;
+                               mark_bh(NET_BH);
+                       }
+
+                       lp->dirty_tx = dirty_tx;
+               }
+
+               /* Check uncommon events all at once. */
+               if (status & (CntFull | TxUnderrun | RxOverflow)) {
+                       /* Always update the error counts to avoid overhead later. */
+                       lp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+                       lp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+                       lp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+
+                       if (status & TxUnderrun) { /* Tx FIFO underflow. */
+                         lp->stats.tx_fifo_errors++;
+                         /* Restart the transmit process. */
+                         outl(0x0080, ioaddr + COMMAND);
+                       }
+                       if (status & RxOverflow) {              /* Missed a Rx frame. */
+                               lp->stats.rx_errors++;
+                       }
+                       /* Clear all error sources. */
+                       outl(status & 0x7f18, ioaddr + INTSTAT);
+               }
+               if (--boguscnt < 0) {
+                       printk("%s: Too much work at interrupt, IntrStatus=0x%8.8x.\n",
+                                  dev->name, status);
+                       /* Clear all interrupt sources. */
+                       outl(0x0001ffff, ioaddr + INTSTAT);
+                       break;
+               }
+       } while (1);
+
+       if (epic_debug > 3)
+               printk("%s: exiting interrupt, intr_status=%#4.4x.\n",
+                          dev->name, inl(ioaddr + INTSTAT));
+
+       /* Code that should never be run!  Perhaps remove after testing.. */
+       {
+               static int stopit = 10;
+               if (dev->start == 0  &&  --stopit < 0) {
+                       printk("%s: Emergency stop, looping startup interrupt.\n",
+                                  dev->name);
+                       FREE_IRQ(irq, dev);
+               }
+       }
+
+       dev->interrupt = 0;
+       return;
+}
+
+static int
+epic_rx(struct device *dev)
+{
+       struct epic_private *lp = (struct epic_private *)dev->priv;
+       int entry = lp->cur_rx % RX_RING_SIZE;
+
+       if (epic_debug > 4)
+               printk(" In epic_rx(), entry %d %8.8x.\n", entry,
+                          lp->rx_ring[entry].status);
+       /* If we own the next entry, it's a new packet. Send it up. */
+       while (lp->rx_ring[entry].status >= 0) {
+               int status = lp->rx_ring[entry].status;
+
+               if (epic_debug > 4)
+                       printk("  epic_rx() status was %8.8x.\n", status);
+               if (status & 0x2000) {
+                       printk("%s: Oversized Ethernet frame spanned multiple buffers,"
+                                  " status %4.4x!\n", dev->name, status);
+                         lp->stats.rx_length_errors++;
+               } else if (status & 0x0006) {
+                       /* Rx Frame errors are counted in hardware. */
+                       lp->stats.rx_errors++;
+               } else {
+                       /* Malloc up new buffer, compatible with net-2e. */
+                       /* Omit the four octet CRC from the length. */
+                       short pkt_len = lp->rx_ring[entry].rxlength - 4;
+                       struct sk_buff *skb;
+                       int rx_in_place = 0;
+
+                       /* Check if the packet is long enough to just accept without
+                          copying to a properly sized skbuff. */
+                       if (pkt_len > rx_copybreak) {
+                               struct sk_buff *newskb;
+                               char *temp;
+
+                               /* Pass up the skb already on the Rx ring. */
+                               skb = lp->rx_skbuff[entry];
+                               temp = skb_put(skb, pkt_len);
+                               if (bus_to_virt(lp->rx_ring[entry].bufaddr) != temp)
+                                       printk("%s: Warning -- the skbuff addresses do not match"
+                                                  " in epic_rx: %p vs. %p / %p.\n", dev->name,
+                                                  bus_to_virt(lp->rx_ring[entry].bufaddr),
+                                                  skb->head, temp);
+                               /* Get a fresh skbuff to replace the filled one. */
+                               newskb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+                               if (newskb) {
+                                       rx_in_place = 1;
+                                       lp->rx_skbuff[entry] = newskb;
+                                       newskb->dev = dev;
+#if LINUX_VERSION_CODE > 0x10300
+                                       /* Align IP on 16 byte boundaries */
+                                       skb_reserve(newskb, 2);
+                                       lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->tail);
+#else
+                                       lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->data);
+#endif
+                               } else                  /* No memory, drop the packet. */
+                                 skb = 0;
+                       } else
+                               skb = DEV_ALLOC_SKB(pkt_len + 2);
+                       if (skb == NULL) {
+                               int i;
+                               printk("%s: Memory squeeze, deferring packet.\n", dev->name);
+                               /* Check that at least two ring entries are free.
+                                  If not, free one and mark stats->rx_dropped++. */
+                               for (i = 0; i < RX_RING_SIZE; i++)
+                                       if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0)
+                                               break;
+
+                               if (i > RX_RING_SIZE -2) {
+                                       lp->stats.rx_dropped++;
+                                       lp->rx_ring[entry].status = 0x8000;
+                                       lp->cur_rx++;
+                               }
+                               break;
+                       }
+                       skb->dev = dev;
+                       if (! rx_in_place) {
+                               skb_reserve(skb, 2);    /* 16 byte align the data fields */
+                               memcpy(skb_put(skb, pkt_len),
+                                          bus_to_virt(lp->rx_ring[entry].bufaddr), pkt_len);
+                       }
+#if LINUX_VERSION_CODE > 0x10300
+                       skb->protocol = eth_type_trans(skb, dev);
+#else
+                       skb->len = pkt_len;
+#endif
+                       netif_rx(skb);
+                       lp->stats.rx_packets++;
+               }
+
+               lp->rx_ring[entry].status = 0x8000;
+               entry = (++lp->cur_rx) % RX_RING_SIZE;
+       }
+
+       return 0;
+}
+
+static int
+epic_close(struct device *dev)
+{
+       int ioaddr = dev->base_addr;
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int i;
+
+       dev->start = 0;
+       dev->tbusy = 1;
+
+       if (epic_debug > 1)
+               printk("%s: Shutting down ethercard, status was %2.2x.\n",
+                          dev->name, inl(ioaddr + INTSTAT));
+
+       /* Disable interrupts by clearing the interrupt mask. */
+       outl(0x00000000, ioaddr + INTMASK);
+       /* Stop the chip's Tx and Rx DMA processes. */
+       outw(0x0061, ioaddr + COMMAND);
+
+       /* Update the error counts. */
+       tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+       tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+       tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+
+       del_timer(&tp->timer);
+
+#ifdef SA_SHIRQ
+       free_irq(dev->irq, dev);
+#else
+       free_irq(dev->irq);
+       irq2dev_map[dev->irq] = 0;
+#endif
+
+       /* Free all the skbuffs in the Rx queue. */
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               struct sk_buff *skb = tp->rx_skbuff[i];
+               tp->rx_skbuff[i] = 0;
+               tp->rx_ring[i].status = 0;              /* Not owned by Epic chip. */
+               tp->rx_ring[i].buflength = 0;
+               tp->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
+               if (skb) {
+#if LINUX_VERSION_CODE < 0x20100
+                       skb->free = 1;
+#endif
+                       dev_kfree_skb(skb);
+               }
+       }
+       for (i = 0; i < TX_RING_SIZE; i++) {
+               if (tp->tx_skbuff[i])
+                       dev_kfree_skb(tp->tx_skbuff[i]);
+               tp->tx_skbuff[i] = 0;
+       }
+
+
+       /* Green! Leave the chip in low-power mode. */
+       outl(0x0008, ioaddr + GENCTL);
+       
+       MOD_DEC_USE_COUNT;
+
+       return 0;
+}
+
+static struct enet_statistics *
+epic_get_stats(struct device *dev)
+{
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       int ioaddr = dev->base_addr;
+
+       if (dev->start) {
+               /* Update the error counts. */
+               tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+               tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+               tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+       }
+
+       return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   Note that we only use exclusion around actually queueing the
+   new frame, not around filling tp->setup_frame.  This is non-deterministic
+   when re-entered but still correct. */
+
+/* The little-endian AUTODIN II ethernet CRC calculation.
+   N.B. Do not use for bulk data, use a table-based routine instead.
+   This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline unsigned ether_crc_le(int length, unsigned char *data)
+{
+       unsigned int crc = 0xffffffff;  /* Initial value. */
+       while(--length >= 0) {
+               unsigned char current_octet = *data++;
+               int bit;
+               for (bit = 8; --bit >= 0; current_octet >>= 1) {
+                       if ((crc ^ current_octet) & 1) {
+                               crc >>= 1;
+                               crc ^= ethernet_polynomial_le;
+                       } else
+                               crc >>= 1;
+               }
+       }
+       return crc;
+}
+
+
+#ifdef NEW_MULTICAST
+static void set_rx_mode(struct device *dev)
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+{
+       int ioaddr = dev->base_addr;
+       struct epic_private *tp = (struct epic_private *)dev->priv;
+       unsigned char mc_filter[8];              /* Multicast hash filter */
+       int i;
+
+       if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous. */
+               outl(0x002C, ioaddr + RxCtrl);
+               /* Unconditionally log net taps. */
+               printk("%s: Promiscuous mode enabled.\n", dev->name);
+               memset(mc_filter, 0xff, sizeof(mc_filter));
+       } else if ((dev->mc_count > 0)  ||  (dev->flags & IFF_ALLMULTI)) {
+               /* There is apparently a chip bug, so the multicast filter
+                  is never enabled. */
+               /* Too many to filter perfectly -- accept all multicasts. */
+               memset(mc_filter, 0xff, sizeof(mc_filter));
+               outl(0x000C, ioaddr + RxCtrl);
+       } else if (dev->mc_count == 0) {
+               outl(0x0004, ioaddr + RxCtrl);
+               return;
+       } else {                                        /* Never executed, for now. */
+               struct dev_mc_list *mclist;
+
+               memset(mc_filter, 0, sizeof(mc_filter));
+               for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+                        i++, mclist = mclist->next)
+                       set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
+                                       mc_filter);
+       }
+       /* ToDo: perhaps we need to stop the Tx and Rx process here? */
+       if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
+               for (i = 0; i < 4; i++)
+                       outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
+               memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+       }
+       return;
+}
+\f
+#ifdef MODULE
+
+/* An additional parameter that may be passed in... */
+static int debug = -1;
+
+int
+init_module(void)
+{
+       int cards_found;
+
+       if (debug >= 0)
+               epic_debug = debug;
+
+       root_epic_dev = NULL;
+       cards_found = epic100_probe(0);
+
+       return cards_found ? 0 : -ENODEV;
+}
+
+void
+cleanup_module(void)
+{
+       struct device *next_dev;
+
+       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+       while (root_epic_dev) {
+               next_dev = ((struct epic_private *)root_epic_dev->priv)->next_module;
+               unregister_netdev(root_epic_dev);
+               release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
+               kfree(root_epic_dev);
+               root_epic_dev = next_dev;
+       }
+}
+
+#endif  /* MODULE */
+\f
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c"
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
new file mode 100644 (file)
index 0000000..198ba16
--- /dev/null
@@ -0,0 +1,1129 @@
+/*
+ * 6pack.c     This module implements the 6pack protocol for kernel-based
+ *             devices like TTY. It interfaces between a raw TTY and the
+ *             kernel's AX.25 protocol layers.
+ *
+ * Version:    @(#)6pack.c     0.3.0   04/07/98
+ *
+ * Authors:    Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ *
+ * Quite a lot of stuff "stolen" by Jörg Reuter from slip.c, written by
+ *
+ *             Laurence Culhane, <loz@holmes.demon.co.uk>
+ *             Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <net/ax25.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/if_slip.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+/* 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h> 
+*/
+
+#include "6pack.h"
+
+typedef unsigned char byte;
+
+
+typedef struct sixpack_ctrl {
+       char            if_name[8];     /* "sp0\0" .. "sp99999\0"       */
+       struct sixpack  ctrl;           /* 6pack things                 */
+       struct device   dev;            /* the device                   */
+} sixpack_ctrl_t;
+static sixpack_ctrl_t  **sixpack_ctrls = NULL;
+int sixpack_maxdev = SIXP_NRUNIT;      /* Can be overridden with insmod! */
+
+static struct tty_ldisc        sp_ldisc;
+
+static void sp_start_tx_timer(struct sixpack *);
+static void sp_xmit_on_air(unsigned long);
+static void resync_tnc(unsigned long);
+void sixpack_decode(struct sixpack *, unsigned char[], int);
+int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
+
+void decode_prio_command(byte, struct sixpack *);
+void decode_std_command(byte, struct sixpack *);
+void decode_data(byte, struct sixpack *);
+
+static int tnc_init(struct sixpack *);
+
+/* Find a free 6pack channel, and link in this `tty' line. */
+static inline struct sixpack *
+sp_alloc(void)
+{
+       sixpack_ctrl_t *spp = NULL;
+       int i;
+
+       if (sixpack_ctrls == NULL) return NULL; /* Master array missing ! */
+
+       for (i = 0; i < sixpack_maxdev; i++) 
+       {
+               spp = sixpack_ctrls[i];
+
+               if (spp == NULL)
+                       break;
+
+               if (!test_and_set_bit(SIXPF_INUSE, &spp->ctrl.flags))
+                       break;
+       }
+
+       /* Too many devices... */
+       if (i >= sixpack_maxdev) 
+               return NULL;
+
+       /* If no channels are available, allocate one */
+       if (!spp &&
+           (sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t),
+                                                   GFP_KERNEL)) != NULL) 
+       {
+               spp = sixpack_ctrls[i];
+               memset(spp, 0, sizeof(sixpack_ctrl_t));
+
+               /* Initialize channel control data */
+               set_bit(SIXPF_INUSE, &spp->ctrl.flags);
+               spp->ctrl.tty         = NULL;
+               sprintf(spp->if_name, "sp%d", i);
+               spp->dev.name         = spp->if_name;
+               spp->dev.base_addr    = i;
+               spp->dev.priv         = (void*)&(spp->ctrl);
+               spp->dev.next         = NULL;
+               spp->dev.init         = sixpack_init;
+       }
+
+       if (spp != NULL) 
+       {
+               /* register device so that it can be ifconfig'ed       */
+               /* sixpack_init() will be called as a side-effect         */
+               /* SIDE-EFFECT WARNING: sixpack_init() CLEARS spp->ctrl ! */
+
+               if (register_netdev(&(spp->dev)) == 0) 
+               {
+                       set_bit(SIXPF_INUSE, &spp->ctrl.flags);
+                       spp->ctrl.dev = &(spp->dev);
+                       spp->dev.priv = (void*)&(spp->ctrl);
+
+                       return (&(spp->ctrl));
+               } else {
+                       clear_bit(SIXPF_INUSE,&(spp->ctrl.flags));
+                       printk(KERN_WARNING "sp_alloc() - register_netdev() failure.\n");
+               }
+       }
+
+       return NULL;
+}
+
+
+/* Free a 6pack channel. */
+static inline void
+sp_free(struct sixpack *sp)
+{
+       /* Free all 6pack frame buffers. */
+       if (sp->rbuff)
+               kfree(sp->rbuff);
+       sp->rbuff = NULL;
+       if (sp->xbuff) {
+               kfree(sp->xbuff);
+       }
+       sp->xbuff = NULL;
+
+       if (!test_and_clear_bit(SIXPF_INUSE, &sp->flags)) 
+       {
+               printk(KERN_WARNING "%s: sp_free for already free unit.\n", sp->dev->name);
+       }
+}
+
+
+/* Set the "sending" flag. */
+static inline void
+sp_lock(struct sixpack *sp)
+{
+       if (test_and_set_bit(0, (void *) &sp->dev->tbusy))  
+               printk(KERN_WARNING "%s: trying to lock already locked device!\n", sp->dev->name);
+}
+
+
+/* Clear the "sending" flag. */
+static inline void
+sp_unlock(struct sixpack *sp)
+{
+       if (!test_and_clear_bit(0, (void *)&sp->dev->tbusy))  
+               printk(KERN_WARNING "%s: trying to unlock already unlocked device!\n", sp->dev->name);
+}
+
+
+/* Send one completely decapsulated IP datagram to the IP layer. */
+
+/* This is the routine that sends the received data to the kernel AX.25.
+   'cmd' is the KISS command. For AX.25 data, it is zero. */
+
+static void
+sp_bump(struct sixpack *sp, char cmd)
+{
+       struct sk_buff *skb;
+       int count;
+       unsigned char *ptr;
+
+       count = sp->rcount+1;
+
+       sp->rx_bytes+=count;
+
+       skb = dev_alloc_skb(count);
+       if (skb == NULL)
+       {
+               printk(KERN_DEBUG "%s: memory squeeze, dropping packet.\n", sp->dev->name);
+               sp->rx_dropped++;
+               return;
+       }
+
+       skb->dev = sp->dev;
+       ptr = skb_put(skb, count);
+       *ptr++ = cmd;   /* KISS command */
+
+       memcpy(ptr, (sp->cooked_buf)+1, count);
+       skb->mac.raw=skb->data;
+       skb->protocol=htons(ETH_P_AX25);
+       netif_rx(skb);
+       sp->rx_packets++;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
+static void
+sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
+{
+       unsigned char *p;
+       int actual, count;
+
+       if (len > sp->mtu)      /* sp->mtu = AX25_MTU = max. PACLEN = 256 */ 
+       {
+               len = sp->mtu;
+               printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
+               sp->tx_dropped++;
+               sp_unlock(sp);
+               return;
+       }
+
+       p = icp;
+
+       if (p[0] > 5)
+       {
+               printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
+               sp_unlock(sp);
+               return;
+       }
+
+       if ((p[0] != 0) && (len > 2))
+       {
+               printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
+               sp_unlock(sp);
+               return;
+       }
+
+       if ((p[0] == 0) && (len < 15))
+       {
+               printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
+               sp_unlock(sp);
+               sp->tx_dropped++;
+               return;
+       }
+
+       count = encode_sixpack(p, (unsigned char *) sp->xbuff, len, sp->tx_delay);
+       sp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+
+       switch(p[0])
+       {
+               case 1: sp->tx_delay = p[1];            return;
+               case 2: sp->persistance = p[1];         return;
+               case 3: sp->slottime = p[1];            return;
+               case 4: /* ignored */                   return;
+               case 5: sp->duplex = p[1];              return;
+       }
+
+       if (p[0] == 0) {
+               /* in case of fullduplex or DAMA operation, we don't take care
+                  about the state of the DCD or of any timers, as the determination
+                  of the correct time to send is the job of the AX.25 layer. We send
+                  immediately after data has arrived. */
+               if (sp->duplex == 1){
+                       sp->led_state = 0x70;
+                       sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+                       sp->tx_enable = 1;
+                       actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, count);
+                       sp->xleft = count - actual;
+                       sp->xhead = sp->xbuff + actual;
+                       sp->led_state = 0x60;
+                       sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+               }
+               else {
+                       sp->xleft = count;
+                       sp->xhead = sp->xbuff;
+                       sp->status2 = count;
+                       if (sp->duplex == 0)
+                               sp_start_tx_timer(sp);
+               }
+       }
+}
+
+/*
+ * Called by the TTY driver when there's room for more data.  If we have
+ * more packets to send, we send them here.
+ */
+static void sixpack_write_wakeup(struct tty_struct *tty)
+{
+       int actual;
+       struct sixpack *sp = (struct sixpack *) tty->disc_data;
+
+       /* First make sure we're connected. */
+       if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start) {
+               return;
+       }
+       if (sp->xleft <= 0)  {
+               /* Now serial buffer is almost free & we can start
+                * transmission of another packet */
+               sp->tx_packets++;
+               tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+               sp_unlock(sp);
+               sp->tx_enable = 0;
+               mark_bh(NET_BH);
+               return;
+       }
+
+       if (sp->tx_enable == 1) {
+               actual = tty->driver.write(tty, 0, sp->xhead, sp->xleft);
+               sp->xleft -= actual;
+               sp->xhead += actual;
+       }
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Encapsulate an IP datagram and kick it into a TTY queue. */
+
+static int
+sp_xmit(struct sk_buff *skb, struct device *dev)
+{
+       struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+       if (!dev->start)  
+       {
+               printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name);
+               return 1;
+       }
+
+       if (dev->tbusy)
+               return 1;
+
+       /* We were not busy, so we are now... :-) */
+       if (skb != NULL) {
+               sp_lock(sp);
+               sp->tx_bytes+=skb->len; /*---2.1.x---*/
+               sp_encaps(sp, skb->data, skb->len);
+               dev_kfree_skb(skb);
+       }
+       return 0;
+}
+/* #endif */
+
+
+/* perform the persistence/slottime algorithm for CSMA access. If the persistence
+   check was successful, write the data to the serial driver. Note that in case
+   of DAMA operation, the data is not sent here. */
+
+static 
+void sp_xmit_on_air(unsigned long channel)
+{
+       struct sixpack *sp = (struct sixpack *) channel;
+       int actual;
+       static unsigned char random;
+       
+       random = random * 17 + 41;
+
+       if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistance)) {
+               sp->led_state = 0x70;
+               sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
+               sp->tx_enable = 1;
+               actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
+               sp->xleft -= actual;
+               sp->xhead += actual;
+               sp->led_state = 0x60;
+               sp->tty->driver.write(sp->tty, 0, &(sp->led_state),1);
+               sp->status2 = 0;
+       } else
+               sp_start_tx_timer(sp);
+} /* sp_xmit */
+
+/* #if defined(CONFIG_6PACK) || defined(CONFIG_6PACK_MODULE) */
+
+/* Return the frame type ID */
+static int sp_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+         void *daddr, void *saddr, unsigned len)
+{
+#ifdef CONFIG_INET
+       if (type != htons(ETH_P_AX25))
+               return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+#endif
+       return 0;
+}
+
+
+static int sp_rebuild_header(struct sk_buff *skb)
+{
+#ifdef CONFIG_INET
+       return ax25_rebuild_header(skb);
+#else
+       return 0;
+#endif
+}
+
+/* #endif */ /* CONFIG_{AX25,AX25_MODULE} */
+
+/* Open the low-level part of the 6pack channel. */
+static int
+sp_open(struct device *dev)
+{
+       struct sixpack *sp = (struct sixpack*)(dev->priv);
+       unsigned long len;
+
+       if (sp->tty == NULL) 
+               return -ENODEV;
+
+       /*
+        * Allocate the 6pack frame buffers:
+        *
+        * rbuff        Receive buffer.
+        * xbuff        Transmit buffer.
+        * cbuff        Temporary compression buffer.
+        */
+        
+       /* !!! length of the buffers. MTU is IP MTU, not PACLEN!
+        */
+
+       len = dev->mtu * 2;
+
+       sp->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+       if (sp->rbuff == NULL)   
+               return -ENOMEM;
+
+       sp->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);
+       if (sp->xbuff == NULL)   
+       {
+               kfree(sp->rbuff);
+               return -ENOMEM;
+       }
+
+       sp->mtu      = AX25_MTU + 73;
+       sp->buffsize = len;
+       sp->rcount   = 0;
+       sp->rx_count = 0;
+       sp->rx_count_cooked = 0;
+       sp->xleft    = 0;
+
+       sp->flags   &= (1 << SIXPF_INUSE);      /* Clear ESCAPE & ERROR flags */
+
+       sp->duplex = 0;
+       sp->tx_delay    = SIXP_TXDELAY;
+       sp->persistance = SIXP_PERSIST;
+       sp->slottime    = SIXP_SLOTTIME;
+       sp->led_state   = 0x60;
+       sp->status      = 1;
+       sp->status1     = 1;
+       sp->status2     = 0;
+       sp->tnc_ok      = 0;
+       sp->tx_enable   = 0;
+       
+       dev->tbusy  = 0;
+       dev->start  = 1;
+
+       init_timer(&sp->tx_t);
+       init_timer(&sp->resync_t);
+       return 0;
+}
+
+
+/* Close the low-level part of the 6pack channel. */
+static int
+sp_close(struct device *dev)
+{
+       struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+       if (sp->tty == NULL) {
+               return -EBUSY;
+       }
+       sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+       dev->tbusy = 1;
+       dev->start = 0;
+       
+       return 0;
+}
+
+static int
+sixpack_receive_room(struct tty_struct *tty)
+{
+       return 65536;  /* We can handle an infinite amount of data. :-) */
+}
+
+/* !!! receive state machine */
+
+/*
+ * Handle the 'receiver data ready' interrupt.
+ * This function is called by the 'tty_io' module in the kernel when
+ * a block of 6pack data has been received, which can now be decapsulated
+ * and sent on to some IP layer for further processing.
+ */
+static void
+sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+{
+       unsigned char buf[512];
+       unsigned long flags;
+       int count1;
+
+       struct sixpack *sp = (struct sixpack *) tty->disc_data;
+
+       if (!sp || sp->magic != SIXPACK_MAGIC || !sp->dev->start || !count)
+               return;
+
+       save_flags(flags);
+       cli();
+       memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
+       restore_flags(flags);
+       
+       /* Read the characters out of the buffer */
+
+       count1 = count;
+       while(count)
+       {
+               count--;
+               if (fp && *fp++)
+               {
+                       if (!test_and_set_bit(SIXPF_ERROR, &sp->flags))  {
+                               sp->rx_errors++;
+                       }                       
+                       continue;
+               }
+       }
+       sixpack_decode(sp, buf, count1);
+}
+
+/*
+ * Open the high-level part of the 6pack channel.
+ * This function is called by the TTY module when the
+ * 6pack line discipline is called for.  Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free 6pcack channel...
+ */
+static int
+sixpack_open(struct tty_struct *tty)
+{
+       struct sixpack *sp = (struct sixpack *) tty->disc_data;
+       int err;
+
+       /* First make sure we're not already connected. */
+
+       if (sp && sp->magic == SIXPACK_MAGIC) 
+               return -EEXIST;
+
+       /* OK.  Find a free 6pack channel to use. */
+       if ((sp = sp_alloc()) == NULL)
+               return -ENFILE;
+       sp->tty = tty;
+       tty->disc_data = sp;
+       if (tty->driver.flush_buffer) 
+               tty->driver.flush_buffer(tty);
+
+       if (tty->ldisc.flush_buffer)
+               tty->ldisc.flush_buffer(tty);
+
+
+       /* Restore default settings */
+       sp->dev->type = ARPHRD_AX25;
+
+       /* Perform the low-level 6pack initialization. */
+       if ((err = sp_open(sp->dev)))  
+               return err;
+       
+       MOD_INC_USE_COUNT;
+
+       /* Done.  We have linked the TTY line to a channel. */
+
+       tnc_init(sp);
+
+       return sp->dev->base_addr;
+}
+
+
+/*
+ * Close down a 6pack channel.
+ * This means flushing out any pending queues, and then restoring the
+ * TTY line discipline to what it was before it got hooked to 6pack
+ * (which usually is TTY again).
+ */
+static void
+sixpack_close(struct tty_struct *tty)
+{
+       struct sixpack *sp = (struct sixpack *) tty->disc_data;
+
+       /* First make sure we're connected. */
+       if (!sp || sp->magic != SIXPACK_MAGIC)
+               return;
+
+       rtnl_lock();
+       if (sp->dev->flags & IFF_UP)
+               (void) dev_close(sp->dev);
+
+       del_timer(&(sp->tx_t));
+       del_timer(&(sp->resync_t));
+       
+       tty->disc_data = 0;
+       sp->tty = NULL;
+       /* VSV = very important to remove timers */
+
+       sp_free(sp);
+       unregister_netdev(sp->dev);
+       rtnl_unlock();
+       MOD_DEC_USE_COUNT;
+}
+
+
+static struct net_device_stats *
+sp_get_stats(struct device *dev)
+{
+       static struct net_device_stats stats;
+       struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+       memset(&stats, 0, sizeof(struct net_device_stats));
+
+       stats.rx_packets     = sp->rx_packets;
+       stats.tx_packets     = sp->tx_packets;
+       stats.rx_bytes       = sp->rx_bytes;
+       stats.tx_bytes       = sp->tx_bytes;
+       stats.rx_dropped     = sp->rx_dropped;
+       stats.tx_dropped     = sp->tx_dropped;
+       stats.tx_errors      = sp->tx_errors;
+       stats.rx_errors      = sp->rx_errors;
+       stats.rx_over_errors = sp->rx_over_errors;
+       return (&stats);
+}
+
+
+int
+sp_set_mac_address(struct device *dev, void *addr)
+{
+       int err;
+
+       err = verify_area(VERIFY_READ, addr, AX25_ADDR_LEN);
+       if (err)  {
+               return err;
+       }
+
+       copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN);     /* addr is an AX.25 shifted ASCII mac address */
+
+       return 0;
+}
+
+static int
+sp_set_dev_mac_address(struct device *dev, void *addr)
+{
+       struct sockaddr *sa=addr;
+       memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
+       return 0;
+}
+
+
+/* Perform I/O control on an active 6pack channel. */
+static int
+sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
+{
+       struct sixpack *sp = (struct sixpack *) tty->disc_data;
+       int err;
+       unsigned int tmp;
+
+       /* First make sure we're connected. */
+       if (!sp || sp->magic != SIXPACK_MAGIC) {
+               return -EINVAL;
+       }
+
+       switch(cmd) {
+        case SIOCGIFNAME:
+               err = verify_area(VERIFY_WRITE, arg, strlen(sp->dev->name) + 1);
+               if (err)  {
+                       return err;
+               }
+               copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1);
+               return 0;
+
+       case SIOCGIFENCAP:
+               err = verify_area(VERIFY_WRITE, arg, sizeof(int));
+               if (err)  {
+                       return err;
+               }
+               put_user(0, (int *)arg);
+               return 0;
+
+       case SIOCSIFENCAP:
+               err = verify_area(VERIFY_READ, arg, sizeof(int));
+               if (err)  {
+                       return err;
+               }
+               get_user(tmp,(int *)arg);
+
+               sp->mode = tmp;
+               sp->dev->addr_len        = AX25_ADDR_LEN;         /* sizeof an AX.25 addr */
+               sp->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
+               sp->dev->type            = ARPHRD_AX25;
+
+               return 0;
+
+        case SIOCSIFHWADDR:
+               return sp_set_mac_address(sp->dev, arg);
+
+       /* Allow stty to read, but not set, the serial port */
+       case TCGETS:
+       case TCGETA:
+               return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+
+static int sp_open_dev(struct device *dev)
+{
+       struct sixpack *sp = (struct sixpack*)(dev->priv);
+       if(sp->tty==NULL)
+               return -ENODEV;
+       return 0;
+}
+
+/* Initialize 6pack control device -- register 6pack line discipline */
+
+#ifdef MODULE
+static int sixpack_init_ctrl_dev(void)
+#else  /* !MODULE */
+__initfunc sixpack_init_ctrl_dev(struct device *dummy)
+#endif /* !MODULE */
+{
+       int status;
+
+       if (sixpack_maxdev < 4) sixpack_maxdev = 4; /* Sanity */
+
+       printk(KERN_INFO "6pack: %s (dynamic channels, max=%d)\n",
+              SIXPACK_VERSION, sixpack_maxdev);
+
+       sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
+       if (sixpack_ctrls == NULL) 
+       {
+               printk(KERN_WARNING "6pack: Can't allocate sixpack_ctrls[] array!  Uaargh! (-> No 6pack available)\n");
+               return -ENOMEM;
+       }
+
+       /* Clear the pointer array, we allocate devices when we need them */
+       memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
+
+
+       /* Fill in our line protocol discipline, and register it */
+       memset(&sp_ldisc, 0, sizeof(sp_ldisc));
+       sp_ldisc.magic  = TTY_LDISC_MAGIC;
+       sp_ldisc.name   = "6pack";
+       sp_ldisc.flags  = 0;
+       sp_ldisc.open   = sixpack_open;
+       sp_ldisc.close  = sixpack_close;
+       sp_ldisc.read   = NULL;
+       sp_ldisc.write  = NULL;
+       sp_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
+                                  unsigned int, unsigned long)) sixpack_ioctl;
+       sp_ldisc.poll = NULL;
+       sp_ldisc.receive_buf = sixpack_receive_buf;
+       sp_ldisc.receive_room = sixpack_receive_room;
+       sp_ldisc.write_wakeup = sixpack_write_wakeup;
+       if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0)  {
+               printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
+       }
+
+#ifdef MODULE
+       return status;
+#else
+       /* Return "not found", so that dev_init() will unlink
+        * the placeholder device entry for us.
+        */
+       return ENODEV;
+#endif
+}
+
+/* Initialize the 6pack driver.  Called by DDI. */
+int
+sixpack_init(struct device *dev)
+{
+       struct sixpack *sp = (struct sixpack*)(dev->priv);
+
+       static char ax25_bcast[AX25_ADDR_LEN] =
+               {'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
+       static char ax25_test[AX25_ADDR_LEN] =
+               {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+
+       if (sp == NULL)         /* Allocation failed ?? */
+         return -ENODEV;
+
+       /* Set up the "6pack Control Block". (And clear statistics) */
+       
+       memset(sp, 0, sizeof (struct sixpack));
+       sp->magic  = SIXPACK_MAGIC;
+       sp->dev    = dev;
+       
+       /* Finish setting up the DEVICE info. */
+       dev->mtu                = SIXP_MTU;
+       dev->hard_start_xmit    = sp_xmit;
+       dev->open               = sp_open_dev;
+       dev->stop               = sp_close;
+       dev->hard_header        = sp_header;
+       dev->get_stats          = sp_get_stats;
+       dev->set_mac_address    = sp_set_dev_mac_address;
+       dev->hard_header_len    = AX25_MAX_HEADER_LEN;
+       dev->addr_len           = AX25_ADDR_LEN;
+       dev->type               = ARPHRD_AX25;
+       dev->tx_queue_len       = 10;
+       dev->rebuild_header     = sp_rebuild_header;
+
+       memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);      /* Only activated in AX.25 mode */
+       memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);        /*    ""      ""       ""    "" */
+
+       dev_init_buffers(dev);
+
+       /* New-style flags. */
+       dev->flags              = 0;
+
+       return 0;
+}
+
+#ifdef MODULE
+
+int
+init_module(void)
+{
+       return sixpack_init_ctrl_dev();
+}
+
+void
+cleanup_module(void)
+{
+       int i;
+
+       if (sixpack_ctrls != NULL) 
+       {
+               for (i = 0; i < sixpack_maxdev; i++)  
+               {
+                       if (sixpack_ctrls[i])
+                       {
+                               /*
+                                * VSV = if dev->start==0, then device
+                                * unregistered while close proc.
+                                */ 
+                               if (sixpack_ctrls[i]->dev.start)
+                                       unregister_netdev(&(sixpack_ctrls[i]->dev));
+
+                               kfree(sixpack_ctrls[i]);
+                               sixpack_ctrls[i] = NULL;
+                       }
+               }
+               kfree(sixpack_ctrls);
+               sixpack_ctrls = NULL;
+       }
+       if ((i = tty_register_ldisc(N_6PACK, NULL)))  
+       {
+               printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
+       }
+}
+#endif /* MODULE */
+
+/* ----> 6pack timer interrupt handler and friends. <---- */
+static void 
+sp_start_tx_timer(struct sixpack *sp)
+{
+       int when = sp->slottime;
+       
+       del_timer(&(sp->tx_t));
+       sp->tx_t.data = (unsigned long) sp;
+       sp->tx_t.function = sp_xmit_on_air;
+       sp->tx_t.expires = jiffies + ((when+1)*HZ)/100;
+       add_timer(&(sp->tx_t));
+}
+
+
+/* encode an AX.25 packet into 6pack */
+
+int encode_sixpack(byte *tx_buf, byte *tx_buf_raw, int length, byte tx_delay)
+{
+       int count = 0;
+       byte checksum = 0, buf[400];
+       int raw_count = 0;
+
+       tx_buf_raw[raw_count++] = SIXP_PRIO_CMD_MASK | SIXP_TX_MASK;
+       tx_buf_raw[raw_count++] = SIXP_SEOF;
+
+       buf[0] = tx_delay;
+       for(count = 1; count < length; count++)
+               buf[count] = tx_buf[count];
+
+       for(count = 0; count < length; count++)
+               checksum += buf[count];
+       buf[length] = (byte)0xff - checksum;
+       
+       for(count = 0; count <= length; count++) {
+               if((count % 3) == 0) {
+                       tx_buf_raw[raw_count++] = (buf[count] & 0x3f);
+                       tx_buf_raw[raw_count] = ((buf[count] >> 2) & 0x30);
+               }
+               else if((count % 3) == 1) {
+                       tx_buf_raw[raw_count++] |= (buf[count] & 0x0f);
+                       tx_buf_raw[raw_count] =
+                               ((buf[count] >> 2) & 0x3c);
+               } else {
+                       tx_buf_raw[raw_count++] |= (buf[count] & 0x03);
+                       tx_buf_raw[raw_count++] =
+                               (buf[count] >> 2);
+               } /* else */
+       } /* for */
+       if ((length % 3) != 2)
+               raw_count++;
+       tx_buf_raw[raw_count++] = SIXP_SEOF;
+       return(raw_count);
+}
+
+
+/* decode a 6pack packet */
+
+void
+sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
+{
+       byte inbyte;
+       int count1;
+
+       for (count1 = 0; count1 < count; count1++) {
+               inbyte = pre_rbuff[count1];
+               if (inbyte == SIXP_FOUND_TNC) {
+                       printk(KERN_INFO "6pack: TNC found.\n");
+                       sp->tnc_ok = 1;
+                       del_timer(&(sp->resync_t));
+               }
+               if((inbyte & SIXP_PRIO_CMD_MASK) != 0)
+                       decode_prio_command(inbyte, sp);
+               else if((inbyte & SIXP_STD_CMD_MASK) != 0)
+                       decode_std_command(inbyte, sp);
+               else {
+                       if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
+                               decode_data(inbyte, sp);
+               } /* else */
+       } /* for */
+}
+
+static int
+tnc_init(struct sixpack *sp)
+{
+       static byte inbyte;
+       
+       inbyte = 0xe8;
+       sp->tty->driver.write(sp->tty, 0, &inbyte, 1);
+
+       del_timer(&(sp->resync_t));
+       sp->resync_t.data = (unsigned long) sp;
+       sp->resync_t.function = resync_tnc;
+       sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
+       add_timer(&(sp->resync_t));
+
+       return 0;
+}
+
+
+/* identify and execute a 6pack priority command byte */
+
+void decode_prio_command(byte cmd, struct sixpack *sp)
+{
+       byte channel;
+       int actual;
+
+       channel = cmd & SIXP_CHN_MASK;
+       if ((cmd & SIXP_PRIO_DATA_MASK) != 0) {     /* idle ? */
+
+       /* RX and DCD flags can only be set in the same prio command,
+          if the DCD flag has been set without the RX flag in the previous
+          prio command. If DCD has not been set before, something in the
+          transmission has gone wrong. In this case, RX and DCD are
+          cleared in order to prevent the decode_data routine from
+          reading further data that might be corrupt. */
+
+               if (((sp->status & SIXP_DCD_MASK) == 0) &&
+                       ((cmd & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)) {
+                               if (sp->status != 1)
+                                       printk(KERN_DEBUG "6pack: protocol violation\n");
+                               else
+                                       sp->status = 0;
+                               cmd &= !SIXP_RX_DCD_MASK;
+               }
+               sp->status = cmd & SIXP_PRIO_DATA_MASK;
+       } /* if */
+       else { /* output watchdog char if idle */
+               if ((sp->status2 != 0) && (sp->duplex == 1)) {
+                       sp->led_state = 0x70;
+                       sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+                       sp->tx_enable = 1;
+                       actual = sp->tty->driver.write(sp->tty, 0, sp->xbuff, sp->status2);
+                       sp->xleft -= actual;
+                       sp->xhead += actual;
+                       sp->led_state = 0x60;
+                       sp->status2 = 0;
+
+               } /* if */
+       } /* else */
+
+       /* needed to trigger the TNC watchdog */
+       sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+
+        /* if the state byte has been received, the TNC is present,
+           so the resync timer can be reset. */
+
+       if (sp->tnc_ok == 1) {
+               del_timer(&(sp->resync_t));
+               sp->resync_t.data = (unsigned long) sp;
+               sp->resync_t.function = resync_tnc;
+               sp->resync_t.expires = jiffies + SIXP_INIT_RESYNC_TIMEOUT;
+               add_timer(&(sp->resync_t));
+       }
+
+       sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
+}
+
+/* try to resync the TNC. Called by the resync timer defined in
+  decode_prio_command */
+
+static void
+resync_tnc(unsigned long channel)
+{
+       static char resync_cmd = 0xe8;
+       struct sixpack *sp = (struct sixpack *) channel;
+
+       printk(KERN_INFO "6pack: resyncing TNC\n");
+
+       /* clear any data that might have been received */
+       
+       sp->rx_count = 0;
+       sp->rx_count_cooked = 0;
+
+       /* reset state machine */
+
+       sp->status = 1;
+       sp->status1 = 1;
+       sp->status2 = 0;
+       sp->tnc_ok = 0;
+       
+       /* resync the TNC */
+
+       sp->led_state = 0x60;
+       sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+       sp->tty->driver.write(sp->tty, 0, &resync_cmd, 1);
+
+
+       /* Start resync timer again -- the TNC might be still absent */
+
+       del_timer(&(sp->resync_t));
+       sp->resync_t.data = (unsigned long) sp;
+       sp->resync_t.function = resync_tnc;
+       sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
+       add_timer(&(sp->resync_t));
+}
+
+
+
+/* identify and execute a standard 6pack command byte */
+
+void decode_std_command(byte cmd, struct sixpack *sp)
+{
+       byte checksum = 0, rest = 0, channel;
+       short i;
+
+       channel = cmd & SIXP_CHN_MASK;
+       switch(cmd & SIXP_CMD_MASK) {     /* normal command */
+               case SIXP_SEOF:
+                       if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
+                               if ((sp->status & SIXP_RX_DCD_MASK) ==
+                                       SIXP_RX_DCD_MASK) {
+                                       sp->led_state = 0x68;
+                                       sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+                               } /* if */
+                       } else {
+                               sp->led_state = 0x60;
+                               /* fill trailing bytes with zeroes */
+                               sp->tty->driver.write(sp->tty, 0, &(sp->led_state), 1);
+                               rest = sp->rx_count;
+                               if (rest != 0)
+                                        for(i=rest; i<=3; i++)
+                                               decode_data(0, sp);
+                               if (rest == 2)
+                                       sp->rx_count_cooked -= 2;
+                               else if (rest == 3)
+                                       sp->rx_count_cooked -= 1;
+                               for (i=0; i<sp->rx_count_cooked; i++)
+                                       checksum+=sp->cooked_buf[i];
+                               if (checksum != SIXP_CHKSUM) {
+                                       printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
+                               } else {
+                                       sp->rcount = sp->rx_count_cooked-2;
+                                       sp_bump(sp, 0);
+                               } /* else */
+                               sp->rx_count_cooked = 0;
+                       } /* else */
+                       break;
+               case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
+                       break;
+               case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
+                       break;
+               case SIXP_RX_BUF_OVL:
+                       printk(KERN_DEBUG "6pack: RX buffer overflow\n");
+       } /* switch */
+} /* function */
+
+/* decode 4 sixpack-encoded bytes into 3 data bytes */
+
+void decode_data(byte inbyte, struct sixpack *sp)
+{
+
+       unsigned char *buf;
+
+       if (sp->rx_count != 3)
+               sp->raw_buf[sp->rx_count++] = inbyte;
+       else {
+               buf = sp->raw_buf;
+               sp->cooked_buf[sp->rx_count_cooked++] =
+                       buf[0] | ((buf[1] << 2) & 0xc0);
+               sp->cooked_buf[sp->rx_count_cooked++] =
+                       (buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
+               sp->cooked_buf[sp->rx_count_cooked++] =
+                       (buf[2] & 0x03) | (inbyte << 2);
+               sp->rx_count = 0;
+       }
+}
diff --git a/drivers/net/hamradio/6pack.h b/drivers/net/hamradio/6pack.h
new file mode 100644 (file)
index 0000000..a5fe532
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 6pack.h     Define the 6pack device driver interface and constants.
+ *
+ * NOTE:       THIS FILE WILL BE MOVED TO THE LINUX INCLUDE DIRECTORY
+ *             AS SOON AS POSSIBLE!
+ *
+ * Version:    @(#)6pack.h     0.3.0   04/07/98
+ *
+ * Fixes:
+ *
+ * Author:     Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ *
+ *             This file is derived from slip.h, written by
+ *             Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ */
+
+#ifndef _LINUX_6PACK_H
+#define _LINUX_6PACK_H
+
+#define SIXPACK_VERSION    "Revision: 0.3.0"
+
+#ifdef __KERNEL__
+
+/* sixpack priority commands */
+#define SIXP_SEOF      0x40    /* start and end of a 6pack frame */
+#define SIXP_TX_URUN   0x48    /* transmit overrun */
+#define SIXP_RX_ORUN   0x50    /* receive overrun */
+#define SIXP_RX_BUF_OVL        0x58    /* receive buffer overflow */
+
+#define SIXP_CHKSUM    0xFF    /* valid checksum of a 6pack frame */
+
+/* masks to get certain bits out of the status bytes sent by the TNC */
+
+#define SIXP_CMD_MASK          0xC0
+#define SIXP_CHN_MASK          0x07
+#define SIXP_PRIO_CMD_MASK     0x80
+#define SIXP_STD_CMD_MASK      0x40
+#define SIXP_PRIO_DATA_MASK    0x38
+#define SIXP_TX_MASK           0x20
+#define SIXP_RX_MASK           0x10
+#define SIXP_RX_DCD_MASK       0x18
+#define SIXP_LEDS_ON           0x78
+#define SIXP_LEDS_OFF          0x60
+#define SIXP_CON               0x08
+#define SIXP_STA               0x10
+
+#define SIXP_FOUND_TNC         0xe9
+#define SIXP_CON_ON            0x68
+#define SIXP_DCD_MASK          0x08
+#define SIXP_DAMA_OFF          0
+
+/* default level 2 parameters */
+#define SIXP_TXDELAY                   25      /* in 10 ms */
+#define SIXP_PERSIST                   50      /* in 256ths */
+#define SIXP_SLOTTIME                  10      /* in 10 ms */
+#define SIXP_INIT_RESYNC_TIMEOUT       150     /* in 10 ms */
+#define SIXP_RESYNC_TIMEOUT            500     /* in 10 ms */
+
+/* 6pack configuration. */
+#define SIXP_NRUNIT                    256     /* MAX number of 6pack channels */
+#define SIXP_MTU                       256     /* Default MTU */
+
+enum sixpack_flags {
+       SIXPF_INUSE,    /* Channel in use       */
+       SIXPF_ERROR,    /* Parity, etc. error   */
+};
+
+struct sixpack {
+  int                  magic;
+
+  /* Various fields. */
+  struct tty_struct    *tty;           /* ptr to TTY structure         */
+  struct device                *dev;           /* easy for intr handling       */
+
+  /* These are pointers to the malloc()ed frame buffers. */
+  unsigned char                *rbuff;         /* receiver buffer              */
+  int                   rcount;         /* received chars counter       */
+  unsigned char                *xbuff;         /* transmitter buffer           */
+  unsigned char         *xhead;         /* pointer to next byte to XMIT */
+  int                   xleft;          /* bytes left in XMIT queue     */
+
+  unsigned char                raw_buf[4];
+  unsigned char                cooked_buf[400];
+
+  unsigned int         rx_count;
+  unsigned int         rx_count_cooked;
+
+  /* 6pack interface statistics. */
+  unsigned long                rx_packets;     /* inbound frames counter       */
+  unsigned long         tx_packets;     /* outbound frames counter      */
+  unsigned long         rx_bytes;       /* inbound bytes counter        */
+  unsigned long         tx_bytes;       /* outboud bytes counter        */
+  unsigned long         rx_errors;      /* Parity, etc. errors          */
+  unsigned long         tx_errors;      /* Planned stuff                */
+  unsigned long         rx_dropped;     /* No memory for skb            */
+  unsigned long         tx_dropped;     /* When MTU change              */
+  unsigned long         rx_over_errors; /* Frame bigger then 6pack buf. */
+
+  /* Detailed 6pack statistics. */
+
+  int                  mtu;            /* Our mtu (to spot changes!)   */
+  int                   buffsize;       /* Max buffers sizes            */
+
+  unsigned char                flags;          /* Flag values/ mode etc        */
+  unsigned char                mode;           /* 6pack mode                   */
+
+/* 6pack stuff */
+  
+  unsigned char tx_delay;
+  unsigned char persistance;
+  unsigned char slottime;
+  unsigned char duplex;
+  unsigned char led_state;
+  unsigned char status;
+  unsigned char status1;
+  unsigned char status2;
+  unsigned char tx_enable;
+  unsigned char tnc_ok;
+  
+/*  unsigned char retval; */
+
+  struct timer_list tx_t;
+  struct timer_list resync_t;
+}; /* struct sixpack */
+
+
+/* should later be moved to include/net/ax25.h */
+#define AX25_6PACK_HEADER_LEN 0
+#define SIXPACK_MAGIC 0x5304
+
+extern int sixpack_init(struct device *dev);
+
+#endif
+
+#endif /* _LINUX_6PACK.H */
index c0719608abe5f33851fb2282afa8acbe1b059bdf..29e182fe93bf3f7c93f1c5016acfb8c08fa9b113 100644 (file)
@@ -1,7 +1,7 @@
 comment 'AX.25 network device drivers'
 
 dep_tristate 'Serial port KISS driver' CONFIG_MKISS $CONFIG_AX25
-dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
+dep_tristate 'Serial port 6PACK driver' CONFIG_6PACK $CONFIG_AX25
 dep_tristate 'BPQ Ethernet driver' CONFIG_BPQETHER $CONFIG_AX25
     
 dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25
index c247cee790110912d2f9827a910738acacb0b51f..07e2aade5815c3ed15e58584f520fe9466cfc2a6 100644 (file)
@@ -45,6 +45,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_6PACK),y)
+L_OBJS += 6pack.o
+else
+  ifeq ($(CONFIG_6PACK),m)
+  M_OBJS += 6pack.o
+  endif
+endif
+
 ifeq ($(CONFIG_PI),y)
 L_OBJS += pi2.o
 else
index 3f507d2483ae155e811d683540d5f9b7d56dd8d3..e6773383125683cd0f230d9ce456a0bdba96675e 100644 (file)
@@ -681,7 +681,7 @@ int main(int argc, char *argv[])
        gentbl_costab(f, 6);
        gentbl_afsk2400(f, 7372800);
        fclose(f);
-       return(0);
+       exit(0);
 }
 
 
index 9c1c65af801eafdcd198de037221e3e0e72c1a75..79bd5d4ca0a2446fd941633f58e36f9b89f82ae2 100644 (file)
@@ -83,7 +83,6 @@
 * Jan 02, 1997 Gene Kozin      Initial version.
 *****************************************************************************/
 
-#include <linux/config.h>      /* OS configuration options */
 #include <linux/kernel.h>      /* printk(), and other useful stuff */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/errno.h>       /* return codes */
index 32675d3550d8850687934290d3a5c045a0d0b0be..fa4f98d61b7453b4f2e320595956b53acc6775cc 100644 (file)
@@ -56,7 +56,6 @@
 * Jan 06, 1997 Gene Kozin      Initial version.
 *****************************************************************************/
 
-#include <linux/config.h>      /* OS configuration options */
 #include <linux/kernel.h>      /* printk(), and other useful stuff */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/errno.h>       /* return codes */
index 6a649a2d2a48afe727b49ab332085e37b3e29f3a..6a1759040bc3c8ae675680eda2243929bd12f31d 100644 (file)
@@ -42,7 +42,6 @@
 #error This code MUST be compiled as a kernel module!
 #endif
 
-#include <linux/config.h>      /* OS configuration options */
 #include <linux/kernel.h>      /* printk(), and other useful stuff */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/errno.h>       /* return codes */
index c3ab67906c8237d56283d610a79d74ba92e8c39e..a0cc07494927fd59169f2a04456cfbcded116e40 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/blk.h>
 #include <linux/sched.h>
 #include <linux/version.h>
-#include <linux/config.h>
 #include <linux/zorro.h>
 
 #include <asm/page.h>
index d4678da825547383c36cabc7d44087a71da3ac64..d4f13d256a05531e989db58ba09c372b2abe0045 100644 (file)
@@ -6,8 +6,6 @@ fi
 
 dep_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND
 if [ "$CONFIG_SB" = "y" ]; then
-    bool 'Is the card a Soundman Games ?' CONFIG_SM_GAMES
-    bool 'Are you using the IBM Mwave "emulation" of SB ?' CONFIG_SB_MWAVE
     hex 'I/O base for SB Check from manual of the card' CONFIG_SB_BASE 220
     int 'Sound Blaster IRQ Check from manual of the card' CONFIG_SB_IRQ 7
     int 'Sound Blaster DMA 0, 1 or 3' CONFIG_SB_DMA 1
@@ -43,7 +41,7 @@ if [ "$CONFIG_MPU401" = "y" ]; then
     int 'MPU401 IRQ Check from manual of the card' CONFIG_MPU_IRQ 9
 fi
 
-dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND
+dep_tristate 'PSS (AD1848, ADSP-2115, ESC614) support' CONFIG_PSS $CONFIG_SOUND 
 if [ "$CONFIG_PSS" = "y" ]; then
     hex 'PSS I/O base 220 or 240' CONFIG_PSS_BASE 220
     hex 'PSS audio I/O base 530, 604, E80 or F40' CONFIG_PSS_MSS_BASE 530
@@ -56,6 +54,9 @@ if [ "$CONFIG_PSS" = "y" ]; then
        string '  Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE
     fi
 fi
+if [ "$CONFIG_PSS" = "m" ] || [ "$CONFIG_PSS" = "y" ]; then
+    bool '  Enable PSS mixer (Beethoven ADSP-16 and other compatibile)' CONFIG_PSS_MIXER
+fi
 
 dep_tristate 'Microsoft Sound System support' CONFIG_MSS $CONFIG_SOUND
 if [ "$CONFIG_MSS" = "y" ]; then
@@ -92,6 +93,7 @@ if [ "$CONFIG_TRIX" = "y" ]; then
 fi
 
 dep_tristate 'Support for OPTi MAD16 and/or Mozart based cards' CONFIG_MAD16 $CONFIG_SOUND
+dep_tristate 'Support MIDI in older MAD16 based cards (requires SB)' CONFIG_MAD16_OLDCARD $CONFIG_MAD16
 if [ "$CONFIG_MAD16" = "y" ]; then
     hex 'MAD16 audio I/O base 530, 604, E80 or F40' CONFIG_MAD16_BASE 530
     int 'MAD16 audio IRQ 7, 9, 10 or 11' CONFIG_MAD16_IRQ 11
@@ -213,3 +215,6 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
    fi
 fi
 
+if [ "$CONFIG_ARM" = "y" ]; then
+       bool 'VIDC 16-bit sound' CONFIG_VIDC_SOUND
+fi
index 6b9ef6bb621a504bb1f4ba8ac6dd9b3ebdf1a2f8..b2aef2dfb87649ef8c0344142dd6bf950461f87e 100644 (file)
@@ -231,6 +231,12 @@ CONFIG_SEQUENCER=y
 endif
 endif
 
+ifdef CONFIG_VIDC_SOUND
+ifneq ($(CONFIG_SEQUENCER),Y)
+CONFIG_SEQUENCER=y
+endif
+endif
+
 ifdef CONFIG_PAS
 ifneq ($(CONFIG_AUDIO),Y)
 CONFIG_AUDIO=y
@@ -309,6 +315,12 @@ CONFIG_AUDIO=y
 endif
 endif
 
+ifdef CONFIG_VIDC_SOUND
+ifneq ($(CONFIG_AUDIO),Y)
+CONFIG_AUDIO=y
+endif
+endif
+
 ifdef CONFIG_PAS
 ifneq ($(CONFIG_MIDI),Y)
 CONFIG_MIDI=y
index 6b09e336b5e5a8ebb0644939ed477261398ac637..1f71965f22769f24e9cb091637c4dcb15b6e45b6 100644 (file)
@@ -117,6 +117,22 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_MPU401),y)
+LX_OBJS += mpu401.o
+else
+  ifeq ($(CONFIG_MPU401),m)
+  MX_OBJS += mpu401.o
+  else
+    ifeq ($(CONFIG_MPU_EMU),y)
+    LX_OBJS += mpu401.o
+    else
+      ifeq ($(CONFIG_MPU_EMU),m)
+      MX_OBJS += mpu401.o
+      endif
+    endif
+  endif
+endif
+
 ifeq ($(CONFIG_UART401),y)
 LX_OBJS += uart401.o
 else
@@ -143,31 +159,9 @@ endif
 
 ifeq ($(CONFIG_SSCAPE),y)
 L_OBJS += sscape.o
-LX_OBJS += ad1848.o
-CONFIG_MPU401 = y
 else
   ifeq ($(CONFIG_SSCAPE),m)
   M_OBJS += sscape.o
-  MX_OBJS += ad1848.o
-  ifneq ($(CONFIG_MPU401),y)
-    CONFIG_MPU401 = m
-  endif
-  endif
-endif
-
-ifeq ($(CONFIG_MPU401),y)
-LX_OBJS += mpu401.o
-else
-  ifeq ($(CONFIG_MPU401),m)
-  MX_OBJS += mpu401.o
-  else
-    ifeq ($(CONFIG_MPU_EMU),y)
-    LX_OBJS += mpu401.o
-    else
-      ifeq ($(CONFIG_MPU_EMU),m)
-      MX_OBJS += mpu401.o
-      endif
-    endif
   endif
 endif
 
@@ -230,27 +224,31 @@ else
    endif
 endif
 
+ifeq ($(CONFIG_VIDC_SOUND),y)
+  L_OBJS += vidc.o vidc_audio.o vidc_mixer.o vidc_synth.o vidc_fill.o
+endif
+
 include $(TOPDIR)/Rules.make
 
 softoss2.o:    softoss.o softoss_rs.o
-       ld -r -o softoss2.o softoss.o softoss_rs.o
+       $(LD) -r -o softoss2.o softoss.o softoss_rs.o
 
 pas2.o:       pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
-       ld -r -o pas2.o pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
+       $(LD) -r -o pas2.o pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
 
 sb.o: sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o
-       ld -r -o sb.o sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o
+       $(LD) -r -o sb.o sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o
 
 lowlevel/lowlevel.o:
        cd lowlevel; make
 
-sound.o: soundcard.o dev_table.o audio.o dmabuf.o sequencer.o sys_timer.o sound_timer.o lowlevel/lowlevel.o midi_synth.o midibuf.o sound_firmware.o
-       ld -r -o sound.o soundcard.o dev_table.o audio.o dmabuf.o \
+sound.o: soundcard.o dev_table.o audio.o dmabuf.o sequencer.o sys_timer.o sound_timer.o lowlevel/lowlevel.o midi_synth.o midibuf.o sound_firmware.o sound_syms.o
+       $(LD) -r -o sound.o soundcard.o dev_table.o audio.o dmabuf.o \
               sequencer.o sys_timer.o sound_timer.o lowlevel/lowlevel.o \
-              midi_synth.o midibuf.o sound_firmware.o
+              midi_synth.o midibuf.o sound_firmware.o sound_syms.o
 
 gus.o: gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
-       ld -r -o gus.o gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
+       $(LD) -r -o gus.o gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
 
 # Firmware files that need translation
 #
diff --git a/drivers/sound/README.C931 b/drivers/sound/README.C931
deleted file mode 100644 (file)
index e6f72be..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-Support for the OPTI 82C931 chip
---------------------------------
-
-The opti 82C931 is supported in it's non PnP mode.
-You do not need to set jumpers etc... The sound driver
-will check the card status and if it is required it will
-force the card into a mode that it can be programmed.
-
-To compile support for the OPTI 82C931 card you can use
-the regular Linux config menus (ie, "make xconfig").
-
-Sound card support should be enabled as a module (chose m).
-Enable (m) for  these items:
-  100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support (CONFIG_SB)
-  Generic OPL2/OPL3 FM synthesizer support                         (CONFIG_ADLIB)
-  Microsoft Sound System support                                  (CONFIG_MSS)
-  Support for OPTi MAD16 and/or Mozart based cards                (CONFIG_MAD16)
-  FM synthesizer (YM3812/OPL-3) support                                   (CONFIG_YM3812)
-
-The configuration menu may ask for addresses, irq lines or dma
-channels. If the card is used as a module the module loading
-options will override these values.
-
-Go on and compile your kernel and modules, install the modules.
-
-I use this configuration as part of /etc/conf.modules:
-
-options sb mad16=1
-options mad16 irq=10 dma=1 io=0x530 joystick=1 cdtype=0
-options opl3 io=0x388
-
-After installing everything and booting to a kernel that
-matches the modules you can load the sound driver:
-
-modprobe mad16
-modprobe opl3
-
-As a result these modules are loaded:
-Module                  Size  Used by
-opl3                   10416   0  (unused)
-mad16                   6472   0 
-sb                     23544   0  [mad16]
-uart401                 5796   0  [mad16 sb]
-ad1848                 16532   1  [mad16]
-sound                  82052   0  [opl3 mad16 sb uart401 ad1848]
-
-Known problems:
-1. The uart401 cannot be used. This is probably a problem which
-   was introduced when the sound driver was modularized.
-   Do not try to load uart401 with options (io=xxx, irq=yyy) because
-   it will try to initialize itself and fail.
-
-2. Cannot use the sound driver in Duplex mode. Until it is fixed
-   use only one DMA channel (0, 1 or 3) for mad16.
-
-3. Configuration of the cdrom adaptor on the sound card is not
-   tested and probably does not work.
-
-4. General problem with the modularized sound driver: If you 
-   load part of the sound driver while a sound program is
-   running, stopping the program may result with a situation
-   where the "Used by" count becomes negative.
index d839ed20857285279297724301b25b38f276ac11..2bf9f2c52e8cf71c9a2b1dfc526cda1c2faa0cdf 100644 (file)
  *
  * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU).
  * CS4232A is an improved version of CS4232.
- */
-
-/*
+ *
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
- */
-/*
+ *
+ *
  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
  *                  general sleep/wakeup clean up.
  * Alan Cox       : reformatted. Fixed SMP bugs. Moved to kernel alloc/free
@@ -84,7 +84,6 @@ typedef struct
        int             irq_ok;
        mixer_ents     *mix_devices;
        int             mixer_output_port;
-       int             c930_password_port;
 } ad1848_info;
 
 typedef struct ad1848_port_info
@@ -561,6 +560,12 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
                val = devc->mixer_output_port;
                return put_user(val, (int *)arg);
        }
+       if (cmd == SOUND_MIXER_PRIVATE2)
+       {
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
+               return(ad1848_control(AD1848_MIXER_REROUTE, val));
+       }
        if (((cmd >> 8) & 0xff) == 'M') 
        {
                if (_SIOC_DIR(cmd) & _SIOC_WRITE)
@@ -1409,7 +1414,6 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
        devc->chip_name = devc->name = "AD1848";
        devc->model = MD_1848;  /* AD1848 or CS4248 */
        devc->levels = NULL;
-       devc->c930_password_port = 0;
        devc->debug_flag = 0;
 
        /*
@@ -1789,11 +1793,15 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt
                if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0)
                {
                        printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n");
+                       /* Don't free it either then.. */
+                       devc->irq = 0;
                }
                if (devc->model != MD_1848 && devc->model != MD_C930)
                {
+#ifndef __SMP__
                        int x;
                        unsigned char tmp = ad_read(devc, 16);
+#endif                 
 
                        devc->timer_ticks = 0;
 
@@ -1843,16 +1851,15 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt
        {
                audio_devs[my_dev]->mixer_dev = e;
        }
-       MOD_INC_USE_COUNT;
        return my_dev;
 }
 
-void ad1848_control(int cmd, int arg)
+int ad1848_control(int cmd, int arg)
 {
        ad1848_info *devc;
 
        if (nr_ad1848_devs < 1)
-               return;
+               return -ENODEV;
 
        devc = &adev_info[nr_ad1848_devs - 1];
 
@@ -1860,7 +1867,7 @@ void ad1848_control(int cmd, int arg)
        {
                case AD1848_SET_XTAL:   /* Change clock frequency of AD1845 (only ) */
                        if (devc->model != MD_1845)
-                               return;
+                               return -EINVAL;
                        ad_enter_MCE(devc);
                        ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5));
                        ad_leave_MCE(devc);
@@ -1871,32 +1878,37 @@ void ad1848_control(int cmd, int arg)
                        int o = (arg >> 8) & 0xff;
                        int n = arg & 0xff;
 
+                       if (o < 0 || o >= SOUND_MIXER_NRDEVICES)
+                               return -EINVAL;
+
+                       if (!(devc->supported_devices & (1 << o)) &&
+                           !(devc->supported_rec_devices & (1 << o)))
+                               return -EINVAL;
+
                        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;
+                               break;
                        }
-                       /* 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 */
+                       /* Make the mixer control identified by o to appear as n */
+                       if (n < 0 || n >= SOUND_MIXER_NRDEVICES)
+                               return -EINVAL;
 
                        devc->mixer_reroute[n] = o;     /* Rename the control */
-                       devc->supported_devices &= ~(1 << o);
-                       devc->supported_devices |= (1 << n);
+                       if (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_devices &= ~(1 << o);
                        devc->supported_rec_devices &= ~(1 << o);
                }
                break;
        }
-       return;
+       return 0;
 }
 
 void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
@@ -1932,7 +1944,6 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
        }
        else
                printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base);
-       MOD_DEC_USE_COUNT;
 }
 
 void adintr(int irq, void *dev_id, struct pt_regs *dummy)
@@ -1965,37 +1976,22 @@ interrupt_again:                /* Jump back here if int status doesn't reset */
                        save_flags(flags);
                        cli();
 
-                       alt_stat = 0;
-
-                       if (devc->c930_password_port)
-                               outb((0xe4), devc->c930_password_port); /* Password */
+                       /* 0xe0e is C930 address port
+                        * 0xe0f is C930 data port
+                        */
                        outb(11, 0xe0e);
                        c930_stat = inb(0xe0f);
+                       outb((~c930_stat), 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);
-
-               /* Acknowledge the intr before proceeding */
-               if (devc->model == MD_C930)
-               {               /* 82C930 has interrupt status register in MAD16 register MC11 */
-                       unsigned long   flags;
-
-                       save_flags(flags);
-                       cli();
 
-                       if (devc->c930_password_port)
-                               outb((0xe4), devc->c930_password_port); /* Password */
-                       outb((11), 0xe0e);
-                       outb((~c930_stat), 0xe0f);
-                       restore_flags(flags);
+                       alt_stat = (c930_stat << 2) & 0x30;
                }
                else if (devc->model != MD_1848)
+               {
+                       alt_stat = ad_read(devc, 24);
                        ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat);      /* Selective ack */
+               }
 
                if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
                {
@@ -2550,11 +2546,10 @@ static int loaded = 0;
 
 struct address_info hw_config;
 
-
 int init_module(void)
 {
        printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
-       if(io!=-1)
+       if(io != -1)
        {
                if(irq == -1 || dma == -1)
                {
@@ -2581,12 +2576,5 @@ void cleanup_module(void)
        if(loaded)
                unload_ms_sound(&hw_config);
 }
-
-#else
-
-void export_ad1848_syms(void)
-{
-}
-
 #endif
 #endif
index f6ea1c006ca3d28f19c9507f803e162127554cec..0cf54e710c7a56ccd0d48d98ba8a6864cfae3c9b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * sound/ad1848_mixer.h
- * 
+ *
  * Definitions for the mixer of AD1848 and compatible codecs.
  */
 
@@ -77,7 +77,7 @@ typedef mixer_ent mixer_ents[2];
  */
 
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit)      \
-       {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
+       {{reg_l, pola_l, pos_l, len_l, mute_bit}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
 
 static mixer_ents ad1848_mix_devices[32] = {
 MIX_ENT(SOUND_MIXER_VOLUME,    27, 1, 0, 4,    29, 1, 0, 4,  8),
@@ -88,13 +88,13 @@ MIX_ENT(SOUND_MIXER_PCM,     6, 1, 0, 6,     7, 1, 0, 6,  7),
 MIX_ENT(SOUND_MIXER_SPEAKER,   26, 1, 0, 4,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_LINE,      18, 1, 0, 5,    19, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_MIC,        0, 0, 5, 1,     1, 0, 5, 1,  8),
-MIX_ENT(SOUND_MIXER_CD,                 2, 1, 0, 5,     3, 1, 0, 5,  7),
+MIX_ENT(SOUND_MIXER_CD,                 2, 1, 0, 5,     3, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_IMIX,      13, 1, 2, 6,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_ALTPCM,     0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_RECLEV,     0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_IGAIN,      0, 0, 0, 4,     1, 0, 0, 4,  8),
 MIX_ENT(SOUND_MIXER_OGAIN,      0, 0, 0, 0,     0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 0, 5,     3, 1, 0, 5,  7),
+MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 0, 5,     3, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_LINE2,      4, 1, 0, 5,     5, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 0, 5,    19, 1, 0, 5,  7)
 };
@@ -108,13 +108,13 @@ MIX_ENT(SOUND_MIXER_PCM,   6, 1, 0, 6,     7, 1, 0, 6,  7),
 MIX_ENT(SOUND_MIXER_SPEAKER,   26, 1, 0, 4,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_LINE,      18, 1, 0, 5,    19, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_MIC,        0, 0, 5, 1,     1, 0, 5, 1,  8),
-MIX_ENT(SOUND_MIXER_CD,                 2, 1, 0, 5,     3, 1, 0, 5,  7),
+MIX_ENT(SOUND_MIXER_CD,                 2, 1, 0, 5,     3, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_IMIX,      16, 1, 0, 5,    17, 1, 0, 5,  8),
 MIX_ENT(SOUND_MIXER_ALTPCM,     0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_RECLEV,     0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_IGAIN,      0, 0, 0, 4,     1, 0, 0, 4,  8),
 MIX_ENT(SOUND_MIXER_OGAIN,      0, 0, 0, 0,     0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 0, 5,     3, 1, 0, 5,  7),
+MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 0, 5,     3, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_LINE2,      4, 1, 0, 5,     5, 1, 0, 5,  7),
 MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 0, 5,    19, 1, 0, 5,  7)
 };
@@ -125,21 +125,21 @@ MIX_ENT(SOUND_MIXER_LINE3,        18, 1, 0, 5,    19, 1, 0, 5,  7)
  * MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
  */
 static mixer_ents c930_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME,    22, 1, 0, 5,    23, 1, 0, 5,  7),
+MIX_ENT(SOUND_MIXER_VOLUME,    22, 1, 1, 5,    23, 1, 1, 5,  7),
 MIX_ENT(SOUND_MIXER_BASS,       0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_TREBLE,     0, 0, 0, 0,     0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_SYNTH,      4, 1, 0, 5,     5, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_PCM,        6, 1, 0, 6,     7, 1, 0, 6,  7),
-MIX_ENT(SOUND_MIXER_SPEAKER,   22, 1, 0, 5,     23, 1, 0, 5,  8),
+MIX_ENT(SOUND_MIXER_SYNTH,      4, 1, 1, 4,     5, 1, 1, 4,  7),
+MIX_ENT(SOUND_MIXER_PCM,        6, 1, 0, 5,     7, 1, 0, 5,  7),
+MIX_ENT(SOUND_MIXER_SPEAKER,   22, 1, 1, 5,    23, 1, 1, 5,  7),
 MIX_ENT(SOUND_MIXER_LINE,      18, 1, 1, 4,    19, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_MIC,        20, 1, 0, 4,    21, 1, 0, 4,  8),
-MIX_ENT(SOUND_MIXER_CD,                 2, 1, 1, 4,     3, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_IMIX,      0, 0, 0, 0,      0, 0, 0, 0,  8),
+MIX_ENT(SOUND_MIXER_MIC,       20, 1, 1, 4,    21, 1, 1, 4,  7),
+MIX_ENT(SOUND_MIXER_CD,                 2, 1, 1, 4,     3, 1, 1, 4,  7),
+MIX_ENT(SOUND_MIXER_IMIX,       0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_ALTPCM,     0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_RECLEV,     0, 0, 0, 0,     0, 0, 0, 0,  8),
 MIX_ENT(SOUND_MIXER_IGAIN,      0, 0, 0, 4,     1, 0, 0, 4,  8),
 MIX_ENT(SOUND_MIXER_OGAIN,      0, 0, 0, 0,     0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 1, 4,     3, 1, 1, 4,  7),
+MIX_ENT(SOUND_MIXER_LINE1,      2, 1, 1, 4,     3, 1, 1, 4,  7),
 MIX_ENT(SOUND_MIXER_LINE2,      4, 1, 1, 4,     5, 1, 1, 4,  7),
 MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 1, 4,    19, 1, 1, 4,  7)
 };
index 6d7dbb7b3a0ae5a9ee2a786f53e69ac27758bed7..b9b16cd8e1f8d576552ccab8996979ac463c2ae7 100644 (file)
@@ -2,19 +2,17 @@
  * sound/adlib_card.c
  *
  * Detection routine for the AdLib card.
- */
-
-/*
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
-#include <linux/config.h>
-#include <linux/module.h>
 
 
+#include <linux/config.h>
+#include <linux/module.h>
 #include "sound_config.h"
 #include "soundmodule.h"
 
@@ -28,7 +26,8 @@ void attach_adlib_card(struct address_info *hw_config)
 
 int probe_adlib(struct address_info *hw_config)
 {
-       if (check_region(hw_config->io_base, 4)) {
+       if (check_region(hw_config->io_base, 4)) 
+       {
                DDB(printk("opl3.c: I/O port %x already in use\n", hw_config->io_base));
                return 0;
        }
@@ -46,12 +45,14 @@ void unload_adlib(struct address_info *hw_config)
 int io = -1;
 MODULE_PARM(io, "i");
 
+EXPORT_NO_SYMBOLS;
+
 struct address_info cfg;
 
 int init_module(void)
 {
        if (io == -1) {
-               printk("adlib: must specify I/O address.\n");
+               printk(KERN_ERR "adlib: must specify I/O address.\n");
                return -EINVAL;
        }
        cfg.io_base = io;
index 9c9ccf095842797101daebf345db274e631c7e12..905bd83e77f8d8c0d2510298eb356571d5673f7a 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/config.h>
 #include <linux/stddef.h>
+#include <linux/kmod.h>
 
 #include "sound_config.h"
 
@@ -164,8 +165,6 @@ void audio_release(int dev, struct file *file)
        DMAbuf_release(dev, mode);
 }
 
-#if defined(NO_INLINE_ASM) || !defined(i386)
-
 static void translate_bytes(const unsigned char *table, unsigned char *buff, int n)
 {
        unsigned long   i;
@@ -177,24 +176,6 @@ static void translate_bytes(const unsigned char *table, unsigned char *buff, int
                buff[i] = table[buff[i]];
 }
 
-#else
-extern inline void
-translate_bytes(const void *table, void *buff, int n)
-{
-       if (n > 0)
-       {
-               __asm__("cld\n"
-                       "1:\tlodsb\n\t"
-                       "xlatb\n\t"
-                       "stosb\n\t"
-               "loop 1b\n\t":
-               :         "b"((long) table), "c"(n), "D"((long) buff), "S"((long) buff)
-               :         "bx", "cx", "di", "si", "ax");
-       }
-}
-
-#endif
-
 int audio_write(int dev, struct file *file, const char *buf, int count)
 {
        int c, p, l, buf_size;
@@ -827,8 +808,10 @@ int dma_ioctl(int dev, unsigned int cmd, caddr_t arg)
                                DMAbuf_launch_output(dev, dmap_out);
                        }
                        audio_devs[dev]->enable_bits = bits;
+#if 0
                        if (changed && audio_devs[dev]->d->trigger)
                                audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go);
+#endif                         
                        restore_flags(flags);
                        /* Falls through... */
 
index fdb5b738c30fd46bcb5f1b2783604a639369c5fe..571a3372b40d08fbdbd91f4b59ac74e23bfc611c 100644 (file)
@@ -301,6 +301,8 @@ MODULE_PARM(irq,"i");
 MODULE_PARM(dma,"i");
 MODULE_PARM(dma2,"i");
 
+EXPORT_NO_SYMBOLS;
+
 struct address_info cfg;
 
 /*
index 7f3957bfdf98c3a746262fbfa9b8f6a8704ab172..155cf529d789c31348d39d6ca7c3ee90f0f98909 100644 (file)
@@ -18,7 +18,6 @@
 #define _DEV_TABLE_C_
 #include "sound_config.h"
 
-int sb_be_quiet = 0;
 int softoss_dev = 0;
 int sound_started = 0;
 int sndtable_get_cardcount(void);
@@ -148,6 +147,9 @@ void sound_unload_drivers(void)
                }
        }
 
+        for (i=0;i<num_audiodevs;i++)
+               DMAbuf_deinit(i);
+
        if (trace_init)
                printk(KERN_DEBUG "Sound unload complete\n");
 }
@@ -418,13 +420,11 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
                return -(EBUSY);
        }
        d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver)));
-       sound_mem_sizes[sound_nblocks] = sizeof(struct audio_driver);
 
        if (sound_nblocks < 1024)
                sound_nblocks++;
 
        op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations)));
-       sound_mem_sizes[sound_nblocks] = sizeof(struct audio_operations);
 
        if (sound_nblocks < 1024)
                sound_nblocks++;
@@ -490,7 +490,6 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver,
           until you unload sound! */
           
        op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations)));
-       sound_mem_sizes[sound_nblocks] = sizeof(struct mixer_operations);
 
        if (sound_nblocks < 1024)
                sound_nblocks++;
index 878cb29719b7bdf4a6ec880d379712be8fe8fa6b..b6e273d4095e00993d46c7f297ead1900fedadf4 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #define SNDCARD_DESKPROXL              27      /* Compaq Deskpro XL */
+#define SNDCARD_VIDC                   28      /* ARMs VIDC */
 #define SNDCARD_SBPNP                  29
 #define SNDCARD_OPL3SA1                        38
 #define SNDCARD_OPL3SA1_SB             39
@@ -463,6 +464,9 @@ struct driver_info sound_drivers[] =
 
 #if defined(CONFIG_VMIDI) && defined(CONFIG_MIDI) && !defined(CONFIG_VMIDI_MODULE)
        {"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device",      attach_v_midi, probe_v_midi, unload_v_midi},
+#endif
+#ifdef CONFIG_VIDC_SOUND
+       {"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc },
 #endif
        {NULL, 0, 0,            "*?*",                  NULL, NULL, NULL}
 };
@@ -612,6 +616,9 @@ struct card_info snd_installed_cards[] =
        {SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
+#ifdef CONFIG_VIDC_SOUND
+       { SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE },
+#endif
        {0, {0}, 0}
 };
 
index db6a02d053861a5c6ddf85e0beadb9e02debd8c8..5066cfe5ae3db1aa5419439e914c6b3714f72152 100644 (file)
@@ -104,7 +104,7 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap)
        dmap->raw_buf_phys = virt_to_bus(start_addr);
 
        for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++)
-               set_bit(PG_reserved, &mem_map[i].flags);
+               set_bit(PG_reserved, &mem_map[i].flags);;
        return 0;
 }
 
@@ -115,6 +115,8 @@ static void sound_free_dmap(struct dma_buffparms *dmap)
 
        if (dmap->raw_buf == NULL)
                return;
+       if (dmap->mapping_flags & DMA_MAP_MAPPED)
+               return;         /* Don't free mmapped buffer. Will use it next time */
        for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1);
 
        start_addr = (unsigned long) dmap->raw_buf;
@@ -125,8 +127,6 @@ static void sound_free_dmap(struct dma_buffparms *dmap)
 
        free_pages((unsigned long) dmap->raw_buf, sz);
        dmap->raw_buf = NULL;
-       /* Remember the buffer is deleted so we dont Oops later */
-       dmap->fragment_size = 0;
 }
 
 
@@ -206,7 +206,6 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap
                dmap->dma_mode = DMODE_NONE;
        dmap->flags &= ~DMA_BUSY;
        disable_dma(dmap->dma);
-       sound_free_dmap(dmap);
 }
 
 
@@ -1212,4 +1211,18 @@ unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait)
        return poll_input(file, dev, wait) | poll_output(file, dev, wait);
 }
 
+void DMAbuf_deinit(int dev)
+{
+       struct audio_operations *adev = audio_devs[dev];
+       /* This routine is called when driver is being unloaded */
+       if (!adev)
+               return;
+#ifdef RUNTIME_DMA_ALLOC
+       sound_free_dmap(adev->dmap_out);
+
+       if (adev->flags & DMA_DUPLEX)
+               sound_free_dmap(adev->dmap_in);
+#endif
+}
+
 #endif
index 0d4c73c1fcb5d2463a91b448fadcad1b78e463ba..7805bed434e6f7893dd8de4c4717027366414674 100644 (file)
@@ -3,76 +3,76 @@
 
 /*
 
-   OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k
+OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k
 
-   (c) 1995 by Michael Schlueter & Michael Marte
+(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 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.
+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.
+/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.
+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
+History:
+1995/8/25      first release
 
-   1995/9/02    ++roman: fixed atari_stram_alloc() call, the timer programming
-   and several race conditions
+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/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/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/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/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
+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/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.
+1996/4/6       ++Martin Mitchell: updated to 1.3 kernel.
 
-   1996/6/13       ++topi: fixed things that were broken (mainly the amiga
-   14-bit routines), /dev/sndstat shows now the real
-   hardware frequency, the lowpass filter is disabled
-   by default now.
+1996/6/13       ++topi: fixed things that were broken (mainly the amiga
+                        14-bit routines), /dev/sndstat shows now the real
+                        hardware frequency, the lowpass filter is disabled
+                       by default now.
 
-   1996/9/25    ++geert: modularization
+1996/9/25      ++geert: modularization
 
- */
+*/
 
 
 #include <linux/module.h>
 #ifdef CONFIG_ATARI
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
-#endif                         /* CONFIG_ATARI */
+#include <asm/atari_stram.h>
+#endif /* CONFIG_ATARI */
 #ifdef CONFIG_AMIGA
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
-#endif                         /* CONFIG_AMIGA */
+#endif /* CONFIG_AMIGA */
 
 #include "dmasound.h"
 #include <linux/soundcard.h>
 
 
 #ifdef MODULE
-static int      chrdev_registered = 0;
-static int      irq_installed = 0;
-
-#endif                         /* MODULE */
-static char   **sound_buffers = NULL;
+static int chrdev_registered = 0;
+static int irq_installed = 0;
+#endif /* MODULE */
+static char **sound_buffers = NULL;
 
 
 #ifdef CONFIG_ATARI
-extern void     atari_microwire_cmd(int cmd);
-
-#endif                         /* CONFIG_ATARI */
+extern void atari_microwire_cmd(int cmd);
+#endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
    /*
-    * The minimum period for audio depends on htotal (for OCS/ECS/AGA)
-    *   (Imported from arch/m68k/amiga/amisound.c)
+    *  The minimum period for audio depends on htotal (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)
+    *  amiga_mksound() should be able to restore the period after beeping
+    *  (Imported from arch/m68k/amiga/amisound.c)
     */
 
-extern u_short  amiga_audio_period;
+extern u_short amiga_audio_period;
 
 
    /*
-    * Audio DMA masks
+    *  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 */
+#endif /* CONFIG_AMIGA */
 
 
 /*** Some declarations *******************************************************/
@@ -157,7 +156,7 @@ extern u_short  amiga_audio_period;
 #define MIN_BUFSIZE            4
 #define MAX_BUFSIZE            128     /* Limit for Amiga */
 
-static int      catchRadius = 0, numBufs = 4, bufSize = 32;
+static int catchRadius = 0, numBufs = 4, bufSize = 32;
 
 
 #define arraysize(x)   (sizeof(x)/sizeof(*(x)))
@@ -177,78 +176,76 @@ static int      catchRadius = 0, numBufs = 4, bufSize = 32;
 
 /* 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
+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
+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
 };
 
 
@@ -256,403 +253,381 @@ static char     alaw2dma8[] =
 
 /* 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,
+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,
+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 */
+#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
+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
+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 */
+#endif /* HAS_14BIT_TABLES */
 
 
 /*** Translations ************************************************************/
 
 
 #ifdef CONFIG_ATARI
-static long     ata_ct_law(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ct_s8(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ct_u8(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ct_s16be(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ct_u16be(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ct_s16le(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ct_u16le(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_law(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_s8(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_u8(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_s16be(const u_char * userPtr, unsigned long userCount,
+static long ata_ct_law(const u_char *userPtr, unsigned long userCount,
+                      u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ct_s8(const u_char *userPtr, unsigned long userCount,
+                     u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ct_u8(const u_char *userPtr, unsigned long userCount,
+                     u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ctx_law(const u_char *userPtr, unsigned long userCount,
                        u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_u16be(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_s16le(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ata_ctx_u16le(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-
-#endif                         /* CONFIG_ATARI */
+static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount,
+                      u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount,
+                      u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount,
+                         u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount,
+                         u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount,
+                         u_char frame[], long *frameUsed, long frameLeft);
+static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount,
+                         u_char frame[], long *frameUsed, long frameLeft);
+#endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
-static long     ami_ct_law(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ami_ct_s8(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ami_ct_u8(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ami_ct_s16be(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ami_ct_u16be(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ami_ct_s16le(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-static long     ami_ct_u16le(const u_char * userPtr, unsigned long userCount,
-                       u_char frame[], long *frameUsed, long frameLeft);
-
-#endif                         /* CONFIG_AMIGA */
+static long ami_ct_law(const u_char *userPtr, unsigned long userCount,
+                      u_char frame[], long *frameUsed, long frameLeft);
+static long ami_ct_s8(const u_char *userPtr, unsigned long userCount,
+                     u_char frame[], long *frameUsed, long frameLeft);
+static long ami_ct_u8(const u_char *userPtr, unsigned long userCount,
+                     u_char frame[], long *frameUsed, long frameLeft);
+static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft);
+static long ami_ct_u16le(const u_char *userPtr, unsigned 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);
+typedef struct {
+    int type;
+    void *(*dma_alloc)(unsigned int, int);
+    void (*dma_free)(void *, unsigned int);
+    int (*irqinit)(void);
 #ifdef MODULE
-         void            (*irqcleanup) (void);
-#endif                         /* MODULE */
-         void            (*init) (void);
-         void            (*silence) (void);
-         int             (*setFormat) (int);
-         int             (*setVolume) (int);
-         int             (*setBass) (int);
-         int             (*setTreble) (int);
-         void            (*play) (void);
-  }
-MACHINE;
+    void (*irqcleanup)(void);
+#endif /* MODULE */
+    void (*init)(void);
+    void (*silence)(void);
+    int (*setFormat)(int);
+    int (*setVolume)(int);
+    int (*setBass)(int);
+    int (*setTreble)(int);
+    int (*setGain)(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 *, unsigned long, u_char *, long *, long);
-         long            (*ct_alaw) (const u_char *, unsigned long, u_char *, long *, long);
-         long            (*ct_s8) (const u_char *, unsigned long, u_char *, long *, long);
-         long            (*ct_u8) (const u_char *, unsigned long, u_char *, long *, long);
-         long            (*ct_s16be) (const u_char *, unsigned long, u_char *, long *, long);
-         long            (*ct_u16be) (const u_char *, unsigned long, u_char *, long *, long);
-         long            (*ct_s16le) (const u_char *, unsigned long, u_char *, long *, long);
-         long            (*ct_u16le) (const u_char *, unsigned 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 */
+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 *, unsigned long, u_char *, long *, long);
+    long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long);
+    long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long);
+    long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long);
+    long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long);
+    long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long);
+    long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long);
+    long (*ct_u16le)(const u_char *, unsigned 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 gain;
+    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 */
-  };
+    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 void *AtaAlloc(unsigned int size, int flags);
+static void AtaFree(void *, unsigned int size);
+static int AtaIrqInit(void);
 #ifdef MODULE
-static void     AtaIrqCleanUp(void);
-
-#endif                         /* MODULE */
-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, void *dummy, struct pt_regs *fp);
-
-#endif                         /* CONFIG_ATARI */
+static void AtaIrqCleanUp(void);
+#endif /* MODULE */
+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 int TTSetGain(int gain);
+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, void *dummy, struct pt_regs *fp);
+#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 *AmiAlloc(unsigned int size, int flags);
+static void AmiFree(void *, unsigned int);
+static int AmiIrqInit(void);
 #ifdef MODULE
-static void     AmiIrqCleanUp(void);
-
-#endif                         /* MODULE */
-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, void *dummy, struct pt_regs *fp);
-
-#endif                         /* CONFIG_AMIGA */
+static void AmiIrqCleanUp(void);
+#endif /* MODULE */
+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, void *dummy, struct pt_regs *fp);
+#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);
-
+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,
-                                    unsigned long userCount,
-                                    u_char frame[], long *frameUsed,
-                                    long frameLeft);
+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,
+                                unsigned long userCount,
+                                u_char frame[], long *frameUsed,
+                                long frameLeft);
 
 
 /*
  * /dev/mixer abstraction
  */
 
-struct sound_mixer
-  {
-         int             busy;
-  };
+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);
+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;
+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 */
+    int ignore_int;            /* ++TeSche: used for Falcon */
+#endif /* CONFIG_ATARI */
 #ifdef CONFIG_AMIGA
-         int             block_size_half, block_size_quarter;
-#endif                         /* CONFIG_AMIGA */
-  };
+    int block_size_half, block_size_quarter;
+#endif /* CONFIG_AMIGA */
+};
 
 static struct sound_queue sq;
 
@@ -666,72 +641,69 @@ static struct sound_queue sq;
        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 long     sq_write(const char *src, unsigned long uLeft);
-static int      sq_open(int open_mode);
-static void     sq_reset(void);
-static int      sq_sync(void);
-static int      sq_release(void);
+static void sq_init(int numBufs, int bufSize, char **buffers);
+static void sq_play(void);
+static long sq_write(const char *src, unsigned long 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;
-  };
+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 long     state_read(char *dest, unsigned long count);
+static void state_init(void);
+static int state_open(int open_mode);
+static int state_release(void);
+static long state_read(char *dest, unsigned long 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 long long sound_lseek(struct inode *inode, struct file *file,
-                            long long offset, int orig);
-static long     sound_read(struct inode *inode, struct file *file, char *buf,
-                          unsigned long count);
-static long     sound_write(struct inode *inode, struct file *file,
-                           const char *buf, unsigned long count);
-static inline int
-ioctl_return(int *addr, int value)
+static int sound_open(struct inode *inode, struct file *file);
+static int sound_fsync(struct file *filp, struct dentry *dentry);
+static int sound_release(struct inode *inode, struct file *file);
+static long long sound_lseek(struct file *file, long long offset, int orig);
+static ssize_t sound_read(struct file *file, char *buf, size_t count,
+                         loff_t *ppos);
+static ssize_t sound_write(struct file *file, const char *buf, size_t count,
+                          loff_t *ppos);
+static inline int ioctl_return(int *addr, int value)
 {
-       if (value < 0)
-               return (value);
+    if (value < 0)
+       return(value);
 
-       return put_user(value, addr);
+    return put_user(value, addr);
 }
-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);
+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 */
+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
@@ -755,1014 +727,849 @@ void            sound_setup(char *str, int *ints);     /* ++Martin: stub for now */
  */
 
 #ifdef CONFIG_ATARI
-static long
-ata_ct_law(const u_char * userPtr, unsigned 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)
-         {
-                 u_char          data;
-
-                 get_user(data, userPtr++);
-                 *p++ = table[data];
-                 count--;
-         }
-       *frameUsed += used;
-       return (used);
-}
-
-
-static long
-ata_ct_s8(const u_char * userPtr, unsigned 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, unsigned 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)
-                   {
-                           u_char          data;
-
-                           get_user(data, userPtr++);
-                           *p++ = data ^ 0x80;
-                           count--;
-                   }
-       } else
-         {
-                 u_short        *p = (u_short *) & frame[*frameUsed];
-
-                 count = min(userCount, frameLeft) >> 1;
-                 used = count * 2;
-                 while (count > 0)
-                   {
-                           u_short         data;
-
-                           get_user(data, ((u_short *) userPtr)++);
-                           *p++ = data ^ 0x8080;
-                           count--;
-                   }
-         }
-       *frameUsed += used;
-       return (used);
-}
-
-
-static long
-ata_ct_s16be(const u_char * userPtr, unsigned 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)
-                   {
-                           get_user(data, ((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, unsigned 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)
-                   {
-                           get_user(data, ((u_short *) userPtr)++);
-                           data ^= 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)
-                   {
-                           get_user(data, ((u_int *) userPtr)++);
-                           *p++ = data ^ 0x80008000;
-                           count--;
-                   }
-                 *frameUsed += used;
-         }
-       return (used);
-}
-
-
-static long
-ata_ct_s16le(const u_char * userPtr, unsigned 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)
-                   {
-                           get_user(data, ((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)
-                   {
-                           get_user(data, ((u_int *) userPtr)++);
-                           data = le2be16dbl(data);
-                           *p++ = data;
-                           count--;
-                   }
-                 *frameUsed += used;
-         }
-       return (used);
-}
-
-
-static long
-ata_ct_u16le(const u_char * userPtr, unsigned 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)
-                   {
-                           get_user(data, ((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)
-                   {
-                           get_user(data, ((u_int *) userPtr)++);
-                           data = le2be16dbl(data) ^ 0x80008000;
-                           *p++ = data;
-                           count--;
-                   }
-                 *frameUsed += used;
-         }
-       return (used);
-}
-
-
-static long
-ata_ctx_law(const u_char * userPtr, unsigned 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)
-                   {
-                           u_char          c;
-
-                           if (bal < 0)
-                             {
-                                     if (!userCount)
-                                             break;
-                                     get_user(c, userPtr++);
-                                     data = table[c];
-                                     userCount--;
-                                     bal += hSpeed;
-                             }
-                           *p++ = data;
-                           frameLeft--;
-                           bal -= sSpeed;
-                   }
-       } else
-         {
-                 u_short        *p = (u_short *) & frame[*frameUsed];
-
-                 while (frameLeft >= 2)
-                   {
-                           u_char          c;
-
-                           if (bal < 0)
-                             {
-                                     if (userCount < 2)
-                                             break;
-                                     get_user(c, userPtr++);
-                                     data = table[c] << 8;
-                                     get_user(c, userPtr++);
-                                     data |= table[c];
-                                     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, unsigned long userCount,
-          u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_law(const u_char *userPtr, unsigned 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;
-                                     get_user(data, userPtr++);
-                                     userCount--;
-                                     bal += hSpeed;
-                             }
-                           *p++ = data;
-                           frameLeft--;
-                           bal -= sSpeed;
-                   }
-       } else
-         {
-                 u_short        *p = (u_short *) & frame[*frameUsed];
+    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
+    long count, used;
+    u_char *p = &frame[*frameUsed];
 
-                 while (frameLeft >= 2)
-                   {
-                           if (bal < 0)
-                             {
-                                     if (userCount < 2)
-                                             break;
-                                     get_user(data, ((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);
+    count = min(userCount, frameLeft);
+    if (sound.soft.stereo)
+       count &= ~1;
+    used = count;
+    while (count > 0) {
+       u_char data;
+       get_user(data, userPtr++);
+       *p++ = table[data];
+       count--;
+    }
+    *frameUsed += used;
+    return(used);
 }
 
 
-static long
-ata_ctx_u8(const u_char * userPtr, unsigned long userCount,
-          u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_s8(const u_char *userPtr, unsigned 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;
+    long count, used;
+    void *p = &frame[*frameUsed];
 
-       used = userCount;
-       usedf = frameLeft;
-       if (!sound.soft.stereo)
-         {
-                 u_char         *p = &frame[*frameUsed];
-
-                 while (frameLeft)
-                   {
-                           if (bal < 0)
-                             {
-                                     if (!userCount)
-                                             break;
-                                     get_user(data, userPtr++);
-                                     data ^= 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;
-                                     get_user(data, ((u_short *) userPtr)++);
-                                     data ^= 0x8080;
-                                     userCount -= 2;
-                                     bal += hSpeed;
-                             }
-                           *p++ = data;
-                           frameLeft -= 2;
-                           bal -= sSpeed;
-                   }
-         }
-       sound.bal = bal;
-       sound.data = data;
-       used -= userCount;
-       *frameUsed += usedf - frameLeft;
-       return (used);
+    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_ctx_s16be(const u_char * userPtr, unsigned long userCount,
-             u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_u8(const u_char *userPtr, unsigned 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];
+    long count, used;
 
-                 while (frameLeft >= 4)
-                   {
-                           if (bal < 0)
-                             {
-                                     if (userCount < 2)
-                                             break;
-                                     get_user(data, ((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;
-                                     get_user(data, ((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, unsigned 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;
-                                     get_user(data, ((u_short *) userPtr)++);
-                                     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;
-                                     get_user(data, ((u_int *) userPtr)++);
-                                     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);
+    if (!sound.soft.stereo) {
+       u_char *p = &frame[*frameUsed];
+       count = min(userCount, frameLeft);
+       used = count;
+       while (count > 0) {
+           u_char data;
+           get_user(data, userPtr++);
+           *p++ = data ^ 0x80;
+           count--;
+       }
+    } else {
+       u_short *p = (u_short *)&frame[*frameUsed];
+       count = min(userCount, frameLeft)>>1;
+       used = count*2;
+       while (count > 0) {
+           u_short data;
+           get_user(data, ((u_short *)userPtr)++);
+           *p++ = data ^ 0x8080;
+           count--;
+       }
+    }
+    *frameUsed += used;
+    return(used);
 }
 
 
-static long
-ata_ctx_s16le(const u_char * userPtr, unsigned long userCount,
-             u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_s16be(const u_char *userPtr, unsigned 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;
-                                     get_user(data, ((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];
+    long count, used;
+    u_long data;
 
-                 while (frameLeft >= 4)
-                   {
-                           if (bal < 0)
-                             {
-                                     if (userCount < 4)
-                                             break;
-                                     get_user(data, ((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);
+    if (!sound.soft.stereo) {
+       u_short *p = (u_short *)&frame[*frameUsed];
+       count = min(userCount, frameLeft)>>1;
+       used = count*2;
+       while (count > 0) {
+           get_user(data, ((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_ctx_u16le(const u_char * userPtr, unsigned long userCount,
-             u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_u16be(const u_char *userPtr, unsigned 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;
-                                     get_user(data, ((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];
+    long count, used;
+    u_long data;
 
-                 while (frameLeft >= 4)
-                   {
-                           if (bal < 0)
-                             {
-                                     if (userCount < 4)
-                                             break;
-                                     get_user(data, ((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);
+    if (!sound.soft.stereo) {
+       u_short *p = (u_short *)&frame[*frameUsed];
+       count = min(userCount, frameLeft)>>1;
+       used = count*2;
+       while (count > 0) {
+           get_user(data, ((u_short *)userPtr)++);
+           data ^= 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) {
+           get_user(data, ((u_int *)userPtr)++);
+           *p++ = data ^ 0x80008000;
+           count--;
+       }
+       *frameUsed += used;
+    }
+    return(used);
 }
-#endif                         /* CONFIG_ATARI */
 
 
-#ifdef CONFIG_AMIGA
-static long
-ami_ct_law(const u_char * userPtr, unsigned long userCount,
-          u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_s16le(const u_char *userPtr, unsigned 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)
-                   {
-                           u_char          data;
+    long count, used;
+    u_long data;
 
-                           get_user(data, userPtr++);
-                           *p++ = table[data];
-                           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)
-                   {
-                           u_char          data;
-
-                           get_user(data, userPtr++);
-                           *left++ = table[data];
-                           get_user(data, userPtr++);
-                           *right++ = table[data];
-                           count--;
-                   }
-         }
+    count = frameLeft;
+    if (!sound.soft.stereo) {
+       u_short *p = (u_short *)&frame[*frameUsed];
+       count = min(userCount, frameLeft)>>1;
+       used = count*2;
+       while (count > 0) {
+           get_user(data, ((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) {
+           get_user(data, ((u_int *)userPtr)++);
+           data = le2be16dbl(data);
+           *p++ = data;
+           count--;
+       }
        *frameUsed += used;
-       return (used);
+    }
+    return(used);
 }
 
 
-static long
-ami_ct_s8(const u_char * userPtr, unsigned long userCount,
-         u_char frame[], long *frameUsed, long frameLeft)
+static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount,
+                        u_char frame[], long *frameUsed, long frameLeft)
 {
-       long            count, used;
+    long count, used;
+    u_long data;
 
-       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)
-                   {
-                           get_user(*left++, userPtr++);
-                           get_user(*right++, userPtr++);
-                           count--;
-                   }
-         }
+    count = frameLeft;
+    if (!sound.soft.stereo) {
+       u_short *p = (u_short *)&frame[*frameUsed];
+       count = min(userCount, frameLeft)>>1;
+       used = count*2;
+       while (count > 0) {
+           get_user(data, ((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) {
+           get_user(data, ((u_int *)userPtr)++);
+           data = le2be16dbl(data) ^ 0x80008000;
+           *p++ = data;
+           count--;
+       }
        *frameUsed += used;
-       return (used);
+    }
+    return(used);
+}
+
+
+static long ata_ctx_law(const u_char *userPtr, unsigned 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) {
+           u_char c;
+           if (bal < 0) {
+               if (!userCount)
+                   break;
+               get_user(c, userPtr++);
+               data = table[c];
+               userCount--;
+               bal += hSpeed;
+           }
+           *p++ = data;
+           frameLeft--;
+           bal -= sSpeed;
+       }
+    } else {
+       u_short *p = (u_short *)&frame[*frameUsed];
+       while (frameLeft >= 2) {
+           u_char c;
+           if (bal < 0) {
+               if (userCount < 2)
+                   break;
+               get_user(c, userPtr++);
+               data = table[c] << 8;
+               get_user(c, userPtr++);
+               data |= table[c];
+               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, unsigned 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;
+               get_user(data, 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;
+               get_user(data, ((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, unsigned 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;
+               get_user(data, userPtr++);
+               data ^= 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;
+               get_user(data, ((u_short *)userPtr)++);
+               data ^= 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, unsigned 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;
+               get_user(data, ((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;
+               get_user(data, ((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, unsigned 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;
+               get_user(data, ((u_short *)userPtr)++);
+               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;
+               get_user(data, ((u_int *)userPtr)++);
+               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);
+}
+
+
+static long ata_ctx_s16le(const u_char *userPtr, unsigned 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;
+               get_user(data, ((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;
+               get_user(data, ((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, unsigned 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;
+               get_user(data, ((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;
+               get_user(data, ((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 */
 
 
-static long
-ami_ct_u8(const u_char * userPtr, unsigned long userCount,
-         u_char frame[], long *frameUsed, long frameLeft)
+#ifdef CONFIG_AMIGA
+static long ami_ct_law(const u_char *userPtr, unsigned 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)
-                   {
-                           u_char          data;
-
-                           get_user(data, userPtr++);
-                           *p++ = data ^ 0x80;
-                           count--;
-                   }
-       } else
-         {
-                 u_char         *left = &frame[*frameUsed >> 1];
-                 u_char         *right = left + sq.block_size_half;
+    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
+    long count, used;
 
-                 count = min(userCount, frameLeft) >> 1 & ~1;
-                 used = count * 2;
-                 while (count > 0)
-                   {
-                           u_char          data;
-
-                           get_user(data, userPtr++);
-                           *left++ = data ^ 0x80;
-                           get_user(data, userPtr++);
-                           *right++ = data ^ 0x80;
-                           count--;
-                   }
-         }
-       *frameUsed += used;
-       return (used);
+    if (!sound.soft.stereo) {
+       u_char *p = &frame[*frameUsed];
+       count = min(userCount, frameLeft) & ~1;
+       used = count;
+       while (count > 0) {
+           u_char data;
+           get_user(data, userPtr++);
+           *p++ = table[data];
+           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) {
+           u_char data;
+           get_user(data, userPtr++);
+           *left++ = table[data];
+           get_user(data, userPtr++);
+           *right++ = table[data];
+           count--;
+       }
+    }
+    *frameUsed += used;
+    return(used);
 }
 
 
-static long
-ami_ct_s16be(const u_char * userPtr, unsigned long userCount,
-            u_char frame[], long *frameUsed, long frameLeft)
+static long ami_ct_s8(const u_char *userPtr, unsigned long userCount,
+                     u_char frame[], long *frameUsed, long frameLeft)
 {
-       long            count, used;
-       u_long          data;
+    long count, used;
 
-       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)
-                   {
-                           get_user(data, ((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)
-                   {
-                           get_user(data, ((u_short *) userPtr)++);
-                           *lefth++ = data >> 8;
-                           *leftl++ = (data >> 2) & 0x3f;
-                           get_user(data, ((u_short *) userPtr)++);
-                           *righth++ = data >> 8;
-                           *rightl++ = (data >> 2) & 0x3f;
-                           count--;
-                   }
-         }
-       *frameUsed += used;
-       return (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) {
+           get_user(*left++, userPtr++);
+           get_user(*right++, userPtr++);
+           count--;
+       }
+    }
+    *frameUsed += used;
+    return(used);
 }
 
 
-static long
-ami_ct_u16be(const u_char * userPtr, unsigned long userCount,
-            u_char frame[], long *frameUsed, long frameLeft)
+static long ami_ct_u8(const u_char *userPtr, unsigned long userCount,
+                     u_char frame[], long *frameUsed, long frameLeft)
 {
-       long            count, used;
-       u_long          data;
+    long count, used;
 
-       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)
-                   {
-                           get_user(data, ((u_short *) userPtr)++);
-                           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)
-                   {
-                           get_user(data, ((u_short *) userPtr)++);
-                           data ^= 0x8000;
-                           *lefth++ = data >> 8;
-                           *leftl++ = (data >> 2) & 0x3f;
-                           get_user(data, ((u_short *) userPtr)++);
-                           data ^= 0x8000;
-                           *righth++ = data >> 8;
-                           *rightl++ = (data >> 2) & 0x3f;
-                           count--;
-                   }
-         }
-       *frameUsed += used;
-       return (used);
+    if (!sound.soft.stereo) {
+       char *p = &frame[*frameUsed];
+       count = min(userCount, frameLeft) & ~1;
+       used = count;
+       while (count > 0) {
+           u_char data;
+           get_user(data, userPtr++);
+           *p++ = data ^ 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) {
+           u_char data;
+           get_user(data, userPtr++);
+           *left++ = data ^ 0x80;
+           get_user(data, userPtr++);
+           *right++ = data ^ 0x80;
+           count--;
+        }
+    }
+    *frameUsed += used;
+    return(used);
+}
+
+
+static long ami_ct_s16be(const u_char *userPtr, unsigned 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) {
+           get_user(data, ((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) {
+           get_user(data, ((u_short *)userPtr)++);
+           *lefth++ = data>>8;
+           *leftl++ = (data>>2) & 0x3f;
+           get_user(data, ((u_short *)userPtr)++);
+           *righth++ = data>>8;
+           *rightl++ = (data>>2) & 0x3f;
+           count--;
+       }
+    }
+    *frameUsed += used;
+    return(used);
+}
+
+
+static long ami_ct_u16be(const u_char *userPtr, unsigned 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) {
+           get_user(data, ((u_short *)userPtr)++);
+           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) {
+           get_user(data, ((u_short *)userPtr)++);
+           data ^= 0x8000;
+           *lefth++ = data>>8;
+           *leftl++ = (data>>2) & 0x3f;
+           get_user(data, ((u_short *)userPtr)++);
+           data ^= 0x8000;
+           *righth++ = data>>8;
+           *rightl++ = (data>>2) & 0x3f;
+           count--;
+       }
+    }
+    *frameUsed += used;
+    return(used);
 }
 
 
-static long
-ami_ct_s16le(const u_char * userPtr, unsigned long userCount,
-            u_char frame[], long *frameUsed, long frameLeft)
+static long ami_ct_s16le(const u_char *userPtr, unsigned 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;
+    long count, used;
+    u_long data;
 
-                 count = min(userCount, frameLeft) >> 1 & ~1;
-                 used = count * 2;
-                 while (count > 0)
-                   {
-                           get_user(data, ((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)
-                   {
-                           get_user(data, ((u_short *) userPtr)++);
-                           data = le2be16(data);
-                           *lefth++ = data >> 8;
-                           *leftl++ = (data >> 2) & 0x3f;
-                           get_user(data, ((u_short *) userPtr)++);
-                           data = le2be16(data);
-                           *righth++ = data >> 8;
-                           *rightl++ = (data >> 2) & 0x3f;
-                           count--;
-                   }
-         }
-       *frameUsed += used;
-       return (used);
+    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) {
+           get_user(data, ((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) {
+           get_user(data, ((u_short *)userPtr)++);
+           data = le2be16(data);
+           *lefth++ = data>>8;
+           *leftl++ = (data>>2) & 0x3f;
+           get_user(data, ((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, unsigned long userCount,
-            u_char frame[], long *frameUsed, long frameLeft)
+static long ami_ct_u16le(const u_char *userPtr, unsigned 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;
+    long count, used;
+    u_long data;
 
-                 count = min(userCount, frameLeft) >> 1 & ~1;
-                 used = count * 2;
-                 while (count > 0)
-                   {
-                           get_user(data, ((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)
-                   {
-                           get_user(data, ((u_short *) userPtr)++);
-                           data = le2be16(data) ^ 0x8000;
-                           *lefth++ = data >> 8;
-                           *leftl++ = (data >> 2) & 0x3f;
-                           get_user(data, ((u_short *) userPtr)++);
-                           data = le2be16(data) ^ 0x8000;
-                           *righth++ = data >> 8;
-                           *rightl++ = (data >> 2) & 0x3f;
-                           count--;
-                   }
-         }
-       *frameUsed += used;
-       return (used);
+    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) {
+           get_user(data, ((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) {
+           get_user(data, ((u_short *)userPtr)++);
+           data = le2be16(data) ^ 0x8000;
+           *lefth++ = data>>8;
+           *leftl++ = (data>>2) & 0x3f;
+           get_user(data, ((u_short *)userPtr)++);
+           data = le2be16(data) ^ 0x8000;
+           *righth++ = data>>8;
+           *rightl++ = (data>>2) & 0x3f;
+           count--;
+       }
+    }
+    *frameUsed += used;
+    return(used);
 }
-#endif                         /* CONFIG_AMIGA */
+#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 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 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 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
+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 */
+#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
+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 */
+#endif /* CONFIG_AMIGA */
 
 
 /*** Low level stuff *********************************************************/
@@ -1774,68 +1581,44 @@ ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be,
  * 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. */
-       request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW,
-                   "DMA sound", ata_sq_interrupt);
-       mfp.int_en_a |= 0x20;   /* Turn interrupt on. */
-       mfp.int_mk_a |= 0x20;
-       return (1);
+static void *AtaAlloc(unsigned int size, int flags)
+{
+    return( atari_stram_alloc( size, NULL, "dmasound" ));
+}
+
+static void AtaFree(void *obj, unsigned int size)
+{
+    atari_stram_free( obj );
+}
+
+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. */
+    request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW,
+                "DMA sound", ata_sq_interrupt);
+    mfp.int_en_a |= 0x20;      /* Turn interrupt on. */
+    mfp.int_mk_a |= 0x20;
+    return(1);
 }
 
 #ifdef MODULE
-static void
-AtaIrqCleanUp(void)
+static void AtaIrqCleanUp(void)
 {
-       mfp.tim_ct_a = 0;       /* stop timer */
-       mfp.int_en_a &= ~0x20;  /* turn interrupt off */
-       free_irq(IRQ_MFP_TIMA, ata_sq_interrupt);
+    mfp.tim_ct_a = 0;          /* stop timer */
+    mfp.int_en_a &= ~0x20;     /* turn interrupt off */
+    free_irq(IRQ_MFP_TIMA, ata_sq_interrupt);
 }
-#endif                         /* MODULE */
+#endif /* MODULE */
 
 
 #define TONE_VOXWARE_TO_DB(v) \
@@ -1843,21 +1626,19 @@ AtaIrqCleanUp(void)
 #define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
 
 
-static int
-AtaSetBass(int bass)
+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));
+    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)
+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));
+    sound.treble = TONE_VOXWARE_TO_DB(treble);
+    atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble));
+    return(TONE_DB_TO_VOXWARE(sound.treble));
 }
 
 
@@ -1867,117 +1648,116 @@ AtaSetTreble(int treble)
  */
 
 
-static void
-TTSilence(void)
+static void TTSilence(void)
 {
-       tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-       atari_microwire_cmd(MW_LM1992_PSG_HIGH);        /* mix in PSG signal 1:1 */
+    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
+    atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
 }
 
 
-static void
-TTInit(void)
+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 */
+    int mode, i, idx;
+    const int freq[4] = {50066, 25033, 12517, 6258};
 
-       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;
-         }
+    /* search a frequency that fits into the allowed error range */
 
-       tt_dmasnd.mode = (sound.hard.stereo ?
-                         DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-           DMASND_MODE_8BIT | mode;
+    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();
 
-       sound.bal = -sound.soft.speed;
+    return(format);
 }
 
 
-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;
-         }
+#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)
 
-       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);
+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));
 }
 
 
-#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)
-
+#define GAIN_VOXWARE_TO_DB(v) \
+       (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80)
+#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4)
 
-static int
-TTSetVolume(int volume)
+static int TTSetGain(int gain)
 {
-       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));
+    sound.gain = GAIN_VOXWARE_TO_DB(gain);
+    atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain));
+    return GAIN_DB_TO_VOXWARE(sound.gain);
 }
 
 
@@ -1987,151 +1767,135 @@ TTSetVolume(int volume)
  */
 
 
-static void
-FalconSilence(void)
+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 */
+    /* 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)
+static void FalconInit(void)
 {
-       int             divider, i, idx;
-       const int       freq[8] =
-       {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
+    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 */
+    /* 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);
+    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);
 }
 
 
@@ -2143,181 +1907,168 @@ FalconSetFormat(int format)
 #define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
 
 
-static int
-FalconSetVolume(int volume)
+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);
+    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)
+static void ata_sq_play_next_frame(int index)
 {
-       char           *start, *end;
+    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));
+    /* 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);
-         }
+       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, void *dummy, struct pt_regs *fp)
+static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
 #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;
-                 }
+    /* ++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.
+    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.count--;
-       sq.playing--;
+       sq.ignore_int = 0;
+       return;
+    }
 
-       if (!sq.playing)
-         {
-                 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-                 sq.ignore_int = 1;
-         }
-       WAKE_UP(sq.write_queue);
+    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();
+       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);
+    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. */
+       is nothing to play any more. Wake up a process
+       waiting for audio output to drain. */
 }
-#endif                         /* CONFIG_ATARI */
+#endif /* CONFIG_ATARI */
 
 
 #ifdef CONFIG_AMIGA
@@ -2327,120 +2078,109 @@ ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp)
  */
 
 
-static void    *
-AmiAlloc(unsigned int size, int flags)
+static void *AmiAlloc(unsigned int size, int flags)
 {
-       return (amiga_chip_alloc((long) size));
+    return(amiga_chip_alloc((long)size));
 }
 
-static void
-AmiFree(void *obj, unsigned int size)
+static void AmiFree(void *obj, unsigned int size)
 {
-       amiga_chip_free(obj);
+    amiga_chip_free (obj);
 }
 
-static int
-AmiIrqInit(void)
+static int AmiIrqInit(void)
 {
-       /* turn off DMA for audio channels */
-       custom.dmacon = AMI_AUDIO_OFF;
+    /* turn off DMA for audio channels */
+    custom.dmacon = AMI_AUDIO_OFF;
 
-       /* Register interrupt handler. */
-       if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0,
-                       "DMA sound", ami_sq_interrupt))
-               return (0);
-       return (1);
+    /* Register interrupt handler. */
+    if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0,
+                    "DMA sound", ami_sq_interrupt))
+       return(0);
+    return(1);
 }
 
 #ifdef MODULE
-static void
-AmiIrqCleanUp(void)
+static void AmiIrqCleanUp(void)
 {
-       /* turn off DMA for audio channels */
-       custom.dmacon = AMI_AUDIO_OFF;
-       /* release the interrupt */
-       free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt);
+    /* turn off DMA for audio channels */
+    custom.dmacon = AMI_AUDIO_OFF;
+    /* release the interrupt */
+    free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt);
 }
-#endif                         /* MODULE */
+#endif /* MODULE */
 
-static void
-AmiSilence(void)
+static void AmiSilence(void)
 {
-       /* turn off DMA for audio channels */
-       custom.dmacon = AMI_AUDIO_OFF;
+    /* turn off DMA for audio channels */
+    custom.dmacon = AMI_AUDIO_OFF;
 }
 
 
-static void
-AmiInit(void)
+static void AmiInit(void)
 {
-       int             period, i;
+    int period, i;
 
-       AmiSilence();
+    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 (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;
-       } else if (period > 65535)
-         {
-                 period = 65535;
-         }
-       sound.hard.speed = amiga_colorclock / (period + 1);
+    if (period < amiga_audio_min_period) {
+       /* we would need to squeeze the sound, but we won't do that */
+       period = amiga_audio_min_period;
+    } 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;
+    for (i = 0; i < 4; i++)
+       custom.aud[i].audper = period;
+    amiga_audio_period = period;
 
-       AmiSetTreble(50);       /* recommended for newer amiga models */
+    AmiSetTreble(50);  /* recommended for newer amiga models */
 }
 
 
-static int
-AmiSetFormat(int format)
+static int AmiSetFormat(int format)
 {
-       int             size;
+    int size;
 
-       /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
+    /* 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;
-         }
+    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();
+    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);
+    return(format);
 }
 
 
@@ -2448,26 +2188,24 @@ AmiSetFormat(int format)
        (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
 #define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
 
-static int
-AmiSetVolume(int volume)
+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));
+    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)
+static int AmiSetTreble(int treble)
 {
-       sound.treble = treble;
-       if (treble < 50)
-               ciaa.pra &= ~0x02;
-       else
-               ciaa.pra |= 0x02;
-       return (treble);
+    sound.treble = treble;
+    if (treble < 50)
+       ciaa.pra &= ~0x02;
+    else
+       ciaa.pra |= 0x02;
+    return(treble);
 }
 
 
@@ -2476,302 +2214,286 @@ AmiSetTreble(int treble)
 #define AMI_PLAY_MASK          3
 
 
-static void
-ami_sq_play_next_frame(int index)
+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].audvol = 1;  /* we are being affected by the beeps */
+           custom.aud[3].audvol = 1;  /* restoring volume here helps a bit */
+           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)
 {
-       u_char         *start, *ch0, *ch1, *ch2, *ch3;
-       u_long          size;
+    int minframes = 1;
 
-       /* 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].audvol = 1;   /* we are being affected by the beeps */
-                           custom.aud[3].audvol = 1;   /* restoring volume here helps a bit */
-                           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_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, void *dummy, struct pt_regs *fp)
+static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp)
 {
-       int             minframes = 1;
+    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)
-         {
-                 /* 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;
+    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;
+    /* 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.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.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);
+    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 */
+#endif /* CONFIG_AMIGA */
 
 
 /*** Machine definitions *****************************************************/
 
 
 #ifdef CONFIG_ATARI
-static MACHINE  machTT =
-{
-       DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit,
+static MACHINE machTT = {
+    DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit,
 #ifdef MODULE
-       AtaIrqCleanUp,
-#endif                         /* MODULE */
-   TTInit, TTSilence, TTSetFormat, TTSetVolume, AtaSetBass, AtaSetTreble,
-       AtaPlay
+    AtaIrqCleanUp,
+#endif /* MODULE */
+    TTInit, TTSilence, TTSetFormat, TTSetVolume, AtaSetBass, AtaSetTreble,
+    TTSetGain,
+    AtaPlay
 };
 
-static MACHINE  machFalcon =
-{
-       DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit,
+static MACHINE machFalcon = {
+    DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit,
 #ifdef MODULE
-       AtaIrqCleanUp,
-#endif                         /* MODULE */
- FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, AtaSetBass,
-       AtaSetTreble, AtaPlay
+    AtaIrqCleanUp,
+#endif /* MODULE */
   FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, AtaSetBass,
+    AtaSetTreble, NULL, AtaPlay
 };
-
-#endif                         /* CONFIG_ATARI */
+#endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
-static MACHINE  machAmiga =
-{
-       DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit,
+static MACHINE machAmiga = {
+    DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit,
 #ifdef MODULE
-       AmiIrqCleanUp,
-#endif                         /* MODULE */
-     AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble,
-       AmiPlay
+    AmiIrqCleanUp,
+#endif /* MODULE */
+    AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble,
+    NULL,
+    AmiPlay
 };
-
-#endif                         /* CONFIG_AMIGA */
+#endif /* CONFIG_AMIGA */
 
 
 /*** Mid level stuff *********************************************************/
 
 
-static void
-sound_silence(void)
+static void sound_silence(void)
 {
-       /* update hardware settings one more */
-       (*sound.mach.init) ();
+    /* update hardware settings one more */
+    (*sound.mach.init)();
 
-       (*sound.mach.silence) ();
+    (*sound.mach.silence)();
 }
 
 
-static void
-sound_init(void)
+static void sound_init(void)
 {
-       (*sound.mach.init) ();
+    (*sound.mach.init)();
 }
 
 
-static int
-sound_set_format(int format)
+static int sound_set_format(int format)
 {
-       return (*sound.mach.setFormat) (format);
+    return(*sound.mach.setFormat)(format);
 }
 
 
-static int
-sound_set_speed(int speed)
+static int sound_set_speed(int speed)
 {
-       if (speed < 0)
-               return (sound.soft.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;
+    sound.soft.speed = speed;
+    (*sound.mach.init)();
+    if (sound.minDev == SND_DEV_DSP)
+       sound.dsp.speed = sound.soft.speed;
 
-       return (sound.soft.speed);
+    return(sound.soft.speed);
 }
 
 
-static int
-sound_set_stereo(int stereo)
+static int sound_set_stereo(int stereo)
 {
-       if (stereo < 0)
-               return (sound.soft.stereo);
+    if (stereo < 0)
+       return(sound.soft.stereo);
 
-       stereo = !!stereo;      /* should be 0 or 1 now */
+    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) ();
+    sound.soft.stereo = stereo;
+    if (sound.minDev == SND_DEV_DSP)
+       sound.dsp.stereo = stereo;
+    (*sound.mach.init)();
 
-       return (stereo);
+    return(stereo);
 }
 
 
-static int
-sound_set_volume(int volume)
+static int sound_set_volume(int volume)
 {
-       return (*sound.mach.setVolume) (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,
-                    unsigned long userCount,
-                    u_char frame[], long *frameUsed,
-                    long frameLeft)
-{
-       long            (*ct_func) (const u_char *, unsigned 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);
+static int sound_set_bass(int bass)
+{
+    return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50);
+}
+
+static int sound_set_gain(int gain)
+{
+    return sound.mach.setGain ? sound.mach.setGain(gain) : 100;
+}
+#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,
+                                unsigned long userCount,
+                                u_char frame[], long *frameUsed,
+                                long frameLeft)
+{
+    long (*ct_func)(const u_char *, unsigned 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);
 }
 
 
@@ -2785,215 +2507,203 @@ sound_copy_translate(const u_char * userPtr,
 #define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
 
 
-static void
-mixer_init(void)
+static void mixer_init(void)
 {
-       mixer.busy = 0;
-       sound.treble = 0;
-       sound.bass = 0;
-       switch (sound.mach.type)
-         {
+    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 */
+       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 */
-         }
+       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)
+static int mixer_open(int open_mode)
 {
-       if (mixer.busy)
-               return (-EBUSY);
-       mixer.busy = 1;
-       return (0);
+    if (mixer.busy)
+       return(-EBUSY);
+    mixer.busy = 1;
+    return(0);
 }
 
 
-static int
-mixer_release(void)
+static int mixer_release(void)
 {
-       mixer.busy = 0;
-       return (0);
+    mixer.busy = 0;
+    return(0);
 }
 
 
-static int
-mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-           u_long arg)
+static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
+                      u_long arg)
 {
-       int             data;
-
-       switch (sound.mach.type)
-         {
+    int data;
+    switch (sound.mach.type) {
 #ifdef CONFIG_ATARI
-         case DMASND_FALCON:
-                 switch (cmd)
+       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:
+                   IOCTL_IN(arg, data);
+                   tt_dmasnd.input_gain =
+                       RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
+                       RECLEVEL_VOXWARE_TO_GAIN(data >> 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:
                    {
-                   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:
-                           IOCTL_IN(arg, data);
-                           tt_dmasnd.input_gain =
-                               RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
-                               RECLEVEL_VOXWARE_TO_GAIN(data >> 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:
-                           IOCTL_IN(arg, data);
-                           return (IOCTL_OUT(arg, sound_set_volume(data)));
-                   case SOUND_MIXER_WRITE_SPEAKER:
-                           {
-                                   int             porta;
-
-                                   IOCTL_IN(arg, data);
-                                   cli();
-                                   sound_ym.rd_data_reg_sel = 14;
-                                   porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-                                       (data < 50 ? 0x40 : 0);
-                                   sound_ym.wd_data = porta;
-                                   sti();
-                                   return (IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-                           }
+                       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));
                    }
-                 break;
-
-         case DMASND_TT:
-                 switch (cmd)
+               case SOUND_MIXER_WRITE_VOLUME:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_volume(data)));
+               case SOUND_MIXER_WRITE_SPEAKER:
                    {
-                   case SOUND_MIXER_READ_DEVMASK:
-                           return (IOCTL_OUT(arg,
-                                             SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
-                             ((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 ((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:
-                           IOCTL_IN(arg, data);
-                           return (IOCTL_OUT(arg, sound_set_volume(data)));
-                   case SOUND_MIXER_WRITE_BASS:
-                           IOCTL_IN(arg, data);
-                           return (IOCTL_OUT(arg, sound_set_bass(data)));
-                   case SOUND_MIXER_WRITE_TREBLE:
-                           IOCTL_IN(arg, data);
-                           return (IOCTL_OUT(arg, sound_set_treble(data)));
-                   case SOUND_MIXER_WRITE_SPEAKER:
-                           if ((atari_mch_cookie >> 16) == ATARI_MCH_TT)
-                             {
-                                     int             porta;
-
-                                     IOCTL_IN(arg, data);
-                                     cli();
-                                     sound_ym.rd_data_reg_sel = 14;
-                                     porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-                                         (data < 50 ? 0x40 : 0);
-                                     sound_ym.wd_data = porta;
-                                     sti();
-                                     return (IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-                           } else
-                                   return (-EINVAL);
+                       int porta;
+                       IOCTL_IN(arg, data);
+                       cli();
+                       sound_ym.rd_data_reg_sel = 14;
+                       porta = (sound_ym.rd_data_reg_sel & ~0x40) |
+                               (data < 50 ? 0x40 : 0);
+                       sound_ym.wd_data = porta;
+                       sti();
+                       return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
                    }
-                 break;
-#endif                         /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-         case DMASND_AMIGA:
-                 switch (cmd)
+           }
+           break;
+
+       case DMASND_TT:
+           switch (cmd) {
+               case SOUND_MIXER_READ_DEVMASK:
+                   return(IOCTL_OUT(arg,
+                       SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
+                       (MACH_IS_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_OGAIN:
+                   return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain)));
+               case SOUND_MIXER_READ_SPEAKER:
                    {
-                   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:
-                           IOCTL_IN(arg, data);
-                           return (IOCTL_OUT(arg, sound_set_volume(data)));
-                   case SOUND_MIXER_READ_TREBLE:
-                           return (IOCTL_OUT(arg, sound.treble));
-                   case SOUND_MIXER_WRITE_TREBLE:
-                           IOCTL_IN(arg, data);
-                           return (IOCTL_OUT(arg, sound_set_treble(data)));
+                       int porta;
+                       if (MACH_IS_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);
                    }
-                 break;
-#endif                         /* CONFIG_AMIGA */
-         }
+               case SOUND_MIXER_WRITE_VOLUME:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_volume(data)));
+               case SOUND_MIXER_WRITE_BASS:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_bass(data)));
+               case SOUND_MIXER_WRITE_TREBLE:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_treble(data)));
+               case SOUND_MIXER_WRITE_OGAIN:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_gain(data)));
+               case SOUND_MIXER_WRITE_SPEAKER:
+                   if (MACH_IS_TT) {
+                       int porta;
+                       IOCTL_IN(arg, data);
+                       cli();
+                       sound_ym.rd_data_reg_sel = 14;
+                       porta = (sound_ym.rd_data_reg_sel & ~0x40) |
+                               (data < 50 ? 0x40 : 0);
+                       sound_ym.wd_data = porta;
+                       sti();
+                       return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
+                   } else
+                       return(-EINVAL);
+           }
+           break;
+#endif /* CONFIG_ATARI */
 
-       return (-EINVAL);
+#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:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_volume(data)));
+               case SOUND_MIXER_READ_TREBLE:
+                   return(IOCTL_OUT(arg, sound.treble));
+               case SOUND_MIXER_WRITE_TREBLE:
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_treble(data)));
+           }
+           break;
+#endif /* CONFIG_AMIGA */
+    }
+
+    return(-EINVAL);
 }
 
 
@@ -3003,216 +2713,198 @@ mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
  */
 
 
-static void
-sq_init(int numBufs, int bufSize, char **buffers)
+static void sq_init(int numBufs, int bufSize, char **buffers)
 {
-       sq.max_count = numBufs;
-       sq.block_size = bufSize;
-       sq.buffers = 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.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;
+    sq.playing = 0;
 
 #ifdef CONFIG_ATARI
-       sq.ignore_int = 0;
-#endif                         /* 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)
-         {
+    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 */
+       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 */
-         }
+       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;
-       sound.hard = sound.dsp;
+    /* before the first open to /dev/dsp this wouldn't be set */
+    sound.soft = sound.dsp;
+    sound.hard = sound.dsp;
 }
 
 
-static void
-sq_play(void)
+static void sq_play(void)
 {
-       (*sound.mach.play) ();
+    (*sound.mach.play)();
 }
 
 
 /* ++TeSche: radically changed this one too */
 
-static long
-sq_write(const char *src, unsigned long uLeft)
-{
-       long            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 == 0)
-               return (0);
+static long sq_write(const char *src, unsigned long uLeft)
+{
+    long 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 == 0)
+       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 {
+       while (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);
+       }
 
-       /* 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.)
+       /* 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.
         */
 
-       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
-         {
-                 while (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 */
+       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();
+    sq_play();
 
-       return (uWritten);
+    return(uWritten);
 }
 
 
-static int
-sq_open(int open_mode)
+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;
+    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);
+    sq.ignore_int = 1;
+#endif /* CONFIG_ATARI */
+    return(0);
 }
 
 
-static void
-sq_reset(void)
+static void sq_reset(void)
 {
-       sound_silence();
-       sq.playing = 0;
-       sq.count = 0;
-       sq.front = (sq.rear + 1) % sq.max_count;
+    sound_silence();
+    sq.playing = 0;
+    sq.count = 0;
+    sq.front = (sq.rear+1) % sq.max_count;
 }
 
 
-static int
-sq_sync(void)
+static int sq_sync(void)
 {
-       int             rc = 0;
+    int rc = 0;
 
-       sq.syncing = 1;
-       sq_play();              /* there may be an incomplete frame waiting */
+    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;
-                   }
-         }
+    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);
+    sq.syncing = 0;
+    return(rc);
 }
 
 
-static int
-sq_release(void)
+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);
+    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);
 }
 
 
@@ -3222,136 +2914,128 @@ sq_release(void)
  */
 
 
-static void
-state_init(void)
+static void state_init(void)
 {
-       state.busy = 0;
+    state.busy = 0;
 }
 
 
 /* state.buf should not overflow! */
 
-static int
-state_open(int open_mode)
+static int state_open(int open_mode)
 {
-       char           *buffer = state.buf, *mach = "";
-       int             len = 0;
+    char *buffer = state.buf, *mach = "";
+    int len = 0;
 
-       if (state.busy)
-               return (-EBUSY);
+    if (state.busy)
+       return(-EBUSY);
 
-       state.ptr = 0;
-       state.busy = 1;
+    state.ptr = 0;
+    state.busy = 1;
 
-       switch (sound.mach.type)
-         {
+    switch (sound.mach.type) {
 #ifdef CONFIG_ATARI
-         case DMASND_TT:
-         case DMASND_FALCON:
-                 mach = "Atari ";
-                 break;
-#endif                         /* 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)
-         {
+       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 */
+       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);
+       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)
+static int state_release(void)
 {
-       state.busy = 0;
-       return (0);
+    state.busy = 0;
+    return(0);
 }
 
 
-static long
-state_read(char *dest, unsigned long count)
+static long state_read(char *dest, unsigned long 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);
+    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);
 }
 
 
@@ -3359,241 +3043,232 @@ state_read(char *dest, unsigned long count)
 /*** High level stuff ********************************************************/
 
 
-static int
-sound_open(struct inode *inode, struct file *file)
-{
-       int             dev = MINOR(inode->i_rdev) & 0x0f;
-       int             rc = 0;
-
-       switch (dev)
-         {
-         case SND_DEV_STATUS:
-                 rc = state_open(file->f_flags);
-                 break;
-         case SND_DEV_CTL:
-                 rc = mixer_open(file->f_flags);
-                 break;
-         case SND_DEV_DSP:
-         case SND_DEV_AUDIO:
-                 rc = sq_open(file->f_flags);
-                 if (rc == 0)
-                   {
-                           sound.minDev = dev;
-                           sound.soft = sound.dsp;
-                           sound.hard = sound.dsp;
-                           sound_init();
-                           if (dev == SND_DEV_AUDIO)
-                             {
-                                     sound_set_speed(8000);
-                                     sound_set_stereo(0);
-                                     sound_set_format(AFMT_MU_LAW);
-                             }
-                   }
-                 break;
-         default:
-                 rc = -ENXIO;
-         }
+static int sound_open(struct inode *inode, struct file *file)
+{
+    int dev = MINOR(inode->i_rdev) & 0x0f;
+    int rc = 0;
+
+    switch (dev) {
+       case SND_DEV_STATUS:
+           rc = state_open(file->f_flags);
+           break;
+       case SND_DEV_CTL:
+           rc = mixer_open(file->f_flags);
+           break;
+       case SND_DEV_DSP:
+       case SND_DEV_AUDIO:
+           rc = sq_open(file->f_flags);
+           if (rc == 0) {
+               sound.minDev = dev;
+               sound.soft = sound.dsp;
+               sound.hard = sound.dsp;
+               sound_init();
+               if (dev == SND_DEV_AUDIO) {
+                   sound_set_speed(8000);
+                   sound_set_stereo(0);
+                   sound_set_format(AFMT_MU_LAW);
+               }
+           }
+           break;
+       default:
+           rc = -ENXIO;
+    }
 #ifdef MODULE
-       if (rc >= 0)
-               MOD_INC_USE_COUNT;
+    if (rc >= 0)
+       MOD_INC_USE_COUNT;
 #endif
-       return (rc);
-}
-
-
-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();
-                 break;
-         case SND_DEV_CTL:
-                 mixer_release();
-                 break;
-         case SND_DEV_DSP:
-         case SND_DEV_AUDIO:
-                 sq_release();
-                 sound.soft = sound.dsp;
-                 sound.hard = sound.dsp;
-                 sound_silence();
-                 break;
-         default:
-                 unknown_minor_dev("sound_release", dev);
-                 return;
-         }
+    return(rc);
+}
+
+
+static int sound_fsync(struct file *filp, struct dentry *dentry)
+{
+    int dev = MINOR(dentry->d_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 int sound_release(struct inode *inode, struct file *file)
+{
+    int dev = MINOR(inode->i_rdev);
+
+    switch (dev & 0x0f) {
+       case SND_DEV_STATUS:
+           state_release();
+           break;
+       case SND_DEV_CTL:
+           mixer_release();
+           break;
+       case SND_DEV_DSP:
+       case SND_DEV_AUDIO:
+           sq_release();
+           sound.soft = sound.dsp;
+           sound.hard = sound.dsp;
+           sound_silence();
+           break;
+       default:
+           return unknown_minor_dev("sound_release", dev);
+    }
 #ifdef MODULE
-       MOD_DEC_USE_COUNT;
+    MOD_DEC_USE_COUNT;
 #endif
+    return 0;
 }
 
 
-static long long
-sound_lseek(struct inode *inode, struct file *file,
-           long long offset, int orig)
+static long long sound_lseek(struct file *file, long long offset, int orig)
 {
-       return -ESPIPE;
+    return -ESPIPE;
 }
 
 
-static ssize_t sound_read(struct file *file, char *buf, szie_t count, loff_t *ppos)
+static ssize_t sound_read(struct file *file, char *buf, size_t count,
+                         loff_t *ppos)
 {
-       int             dev = MINOR(file->f_dentry->d_inode->i_rdev);
+    struct inode *inode = file->f_dentry->d_inode;
+    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));
-       }
+    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 ssize_t sound_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+static ssize_t sound_write(struct file *file, const char *buf, size_t count,
+                          loff_t *ppos)
 {
-       int             dev = MINOR(file->f_dentry->d_inode->i_rdev);
+    struct inode *inode = file->f_dentry->d_inode;
+    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));
-       }
+    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 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;
-       int data;
-
-       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);
-                                       IOCTL_IN(arg, data);
-                                       return (IOCTL_OUT(arg, sound_set_speed(data)));
-                               case SNDCTL_DSP_STEREO:
-                                       sound_fsync(inode, file);
-                                       IOCTL_IN(arg, data);
-                                       return (IOCTL_OUT(arg, sound_set_stereo(data)));
-                               case SOUND_PCM_WRITE_CHANNELS:
-                                       sound_fsync(inode, file);
-                                       IOCTL_IN(arg, data);
-                                       return (IOCTL_OUT(arg, sound_set_stereo(data - 1) + 1));
-                               case SNDCTL_DSP_SETFMT:
-                                       sound_fsync(inode, file);
-                                       IOCTL_IN(arg, data);
-                                       return (IOCTL_OUT(arg, sound_set_format(data)));
-                               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;
+    /* 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;
+    int data;
+
+    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(file, file->f_dentry));
+
+               /* ++TeSche: before changing any of these it's probably wise to
+                * wait until sound playing has settled down
+                */
+               case SNDCTL_DSP_SPEED:
+                   sound_fsync(file, file->f_dentry);
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_speed(data)));
+               case SNDCTL_DSP_STEREO:
+                   sound_fsync(file, file->f_dentry);
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_stereo(data)));
+               case SOUND_PCM_WRITE_CHANNELS:
+                   sound_fsync(file, file->f_dentry);
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1));
+               case SNDCTL_DSP_SETFMT:
+                   sound_fsync(file, file->f_dentry);
+                   IOCTL_IN(arg, data);
+                   return(IOCTL_OUT(arg, sound_set_format(data)));
+               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 (unknown_minor_dev("sound_ioctl", dev));
-       }
-       return (-EINVAL);
+                   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
+    sound_lseek,
+    sound_read,
+    sound_write,
+    NULL,
+    NULL,                      /* select */
+    sound_ioctl,
+    NULL,
+    sound_open,
+    sound_release,
+    sound_fsync
 };
 
 
@@ -3601,186 +3276,171 @@ static struct file_operations sound_fops =
 /*** Config & Setup **********************************************************/
 
 
-void
-soundcard_init(void)
+void soundcard_init(void)
 {
-       int             has_sound = 0;
-       int             i;
+    int has_sound = 0;
+    int i;
 
-       switch (m68k_machtype)
-       {
+    switch (m68k_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(KERN_ERR "DMA sound driver: Timer A interrupt already in use\n");
-                       }
-                       break;
-
-#endif                         /* 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. */
-       sound_buffers = kmalloc(numBufs * sizeof(char *), GFP_KERNEL);
+       case MACH_AMIGA:
+           if (AMIGAHW_PRESENT(AMI_AUDIO)) {
+               sound.mach = machAmiga;
+               has_sound = 1;
+           }
+           break;
+#endif /* CONFIG_AMIGA */
+    }
+    if (!has_sound)
+       return;
 
-       if (!sound_buffers)
-       {
+    /* Set up sound queue, /dev/audio and /dev/dsp. */
+    sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
+    if (!sound_buffers) {
 out_of_memory:
-               printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n");
-               return;
-       }
-       for (i = 0; i < numBufs; i++)
-       {
-               sound_buffers[i] = sound.mach.dma_alloc(bufSize << 10, GFP_KERNEL);
-               if (!sound_buffers[i])
-               {
-                       while (i--)
-                               sound.mach.dma_free(sound_buffers[i], bufSize << 10);
-                       kfree(sound_buffers);
-                       sound_buffers = 0;
-                       goto out_of_memory;
-               }
-       }
+       printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
+       return;
+    }
+    for (i = 0; i < numBufs; i++) {
+       sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
+       if (!sound_buffers[i]) {
+           while (i--)
+               sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+           kfree (sound_buffers);
+           sound_buffers = 0;
+           goto out_of_memory;
+        }
+    }
 
 #ifndef MODULE
-       /* Register driver with the VFS. */
-       register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
+    /* Register driver with the VFS. */
+    register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
 #endif
 
-       sq_init(numBufs, bufSize << 10, sound_buffers);
+    sq_init(numBufs, bufSize << 10, sound_buffers);
 
-       /* Set up /dev/sndstat. */
-       state_init();
+    /* Set up /dev/sndstat. */
+    state_init();
 
-       /* Set up /dev/mixer. */
-       mixer_init();
+    /* Set up /dev/mixer. */
+    mixer_init();
 
-       if (!sound.mach.irqinit())
-       {
-               printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n");
-               return;
-       }
+    if (!sound.mach.irqinit()) {
+       printk("DMA sound driver: Interrupt initialization failed\n");
+       return;
+    }
 #ifdef MODULE
-       irq_installed = 1;
+    irq_installed = 1;
 #endif
 
-       printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
-              bufSize);
+    printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
+          bufSize);
 
-       return;
+    return;
 }
 
 void sound_setup(char *str, int *ints)
 {
-       /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
+    /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
 }
 
 
 #define MAXARGS                8       /* Should be sufficient for now */
 
-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(KERN_WARNING "dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
-                       else
-                               catchRadius = ints[3];
-                 /* fall through */
-               case 2:
-                       if (ints[1] < MIN_BUFFERS)
-                               printk(KERN_WARNING "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(KERN_WARNING "dmasound_setup: illegal buffer size, using default = %d\n", bufSize);
-                       else
-                               bufSize = ints[2];
-                       break;
-               case 0:
-                       break;
-               default:
-                       printk(KERN_WARNING "dmasound_setup: illegal number of arguments\n");
-       }
+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");
+    }
 }
 
 
 #ifdef MODULE
 
-static int      dmasound[MAXARGS] = {
-       0
-};
+static int dmasound[MAXARGS] = { 0 };
 
 int init_module(void)
 {
-       int             err, i = 0;
-       int             ints[MAXARGS + 1];
+    int err, i = 0;
+    int ints[MAXARGS+1];
 
-       while (i < MAXARGS && dmasound[i])
-               ints[i + 1] = dmasound[i++];
-       ints[0] = i;
+    while (i < MAXARGS && dmasound[i])
+       ints[i + 1] = dmasound[i++];
+    ints[0] = i;
 
-       if (i)
-               dmasound_setup("dmasound=", ints);
+    if (i)
+       dmasound_setup("dmasound=", ints);
 
-       err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
-       if (err)
-       {
-               printk(KERN_ERR "dmasound: driver already loaded/included in kernel\n");
-               return err;
-       }
-       chrdev_registered = 1;
-       soundcard_init();
+    err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
+    if (err) {
+       printk("dmasound: driver already loaded/included in kernel\n");
+       return err;
+    }
+    chrdev_registered = 1;
+    soundcard_init();
 
-       return 0;
+    return 0;
 }
 
 
 void cleanup_module(void)
 {
-       int             i;
+    int i;
 
-       if (MOD_IN_USE)
-               return;
+    if (MOD_IN_USE)
+       return;
 
-       if (chrdev_registered)
-               unregister_chrdev(SOUND_MAJOR, "sound");
+    if (chrdev_registered)
+       unregister_chrdev(SOUND_MAJOR, "sound");
 
-       if (irq_installed)
-       {
-               sound_silence();
-               sound.mach.irqcleanup();
-       }
-       if (sound_buffers)
-       {
-               for (i = 0; i < numBufs; i++)
-                       sound.mach.dma_free(sound_buffers[i], bufSize << 10);
-               kfree(sound_buffers);
-       }
+    if (irq_installed) {
+       sound_silence();
+       sound.mach.irqcleanup();
+    }
+
+    if (sound_buffers) {
+       for (i = 0; i < numBufs; i++)
+           sound.mach.dma_free(sound_buffers[i], bufSize << 10);
+       kfree(sound_buffers);
+    }
 }
 
-#endif                         /* MODULE */
+#endif /* MODULE */
index 92e6dbab661b6c89a4426d4856cebe6dacddccfb..21abba1a83a5cea19cc1df282ccbbcd44e65cd81 100644 (file)
@@ -30,7 +30,8 @@ int             gus_pnp_flag = 0;
 
 void attach_gus_card(struct address_info *hw_config)
 {
-       snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp, hw_config);
+       if(request_irq(hw_config->irq, gusintr, 0,  "Gravis Ultrasound", hw_config)<0)
+               printk(KERN_ERR "gus_card.c: Unable to allocate IRQ %d\n", hw_config->irq);
 
        gus_wave_init(hw_config);
 
@@ -38,10 +39,10 @@ void attach_gus_card(struct address_info *hw_config)
        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");
+               printk(KERN_ERR "gus_card.c: Can't allocate DMA channel %d\n", hw_config->dma);
        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 channel 2\n");
+                       printk(KERN_ERR "gus_card.c: Can't allocate DMA channel %d\n", hw_config->dma2);
 #if defined(CONFIG_MIDI)
        gus_midi_init(hw_config);
 #endif
@@ -101,7 +102,7 @@ void unload_gus(struct address_info *hw_config)
 
        release_region(hw_config->io_base, 16);
        release_region(hw_config->io_base + 0x100, 12);         /* 0x10c-> is MAX */
-       snd_release_irq(hw_config->irq, hw_config);
+       free_irq(hw_config->irq, hw_config);
 
        sound_free_dma(hw_config->dma);
 
index 7b202f3efefb53fd590493c30f53c6e6729051cf..54e3793fc47cbaed8a933d868d234bc6d5b403db 100644 (file)
@@ -859,26 +859,26 @@ static void pnp_mem_init(void)
        int bank_sizes[4];
        int i, j, bits = -1, nbanks = 0;
 
-/*
- * This routine determines what kind of RAM is installed in each of the four
- * SIMM banks and configures the DRAM address decode logic accordingly.
- */
+       /*
       * This routine determines what kind of RAM is installed in each of the four
       * SIMM banks and configures the DRAM address decode logic accordingly.
       */
 
-/*
- *    Place the chip into enhanced mode
- */
+       /*
       *    Place the chip into enhanced mode
       */
        gus_write8(0x19, gus_read8(0x19) | 0x01);
        gus_write8(0x53, gus_look8(0x53) & ~0x02);      /* Select DRAM I/O access */
 
-/*
- * Set memory configuration to 4 DRAM banks of 4M in each (16M total).
- */
+       /*
       * Set memory configuration to 4 DRAM banks of 4M in each (16M total).
       */
 
        gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | 0x000c);
 
-/*
- * Perform the DRAM size detection for each bank individually.
- */
+       /*
       * Perform the DRAM size detection for each bank individually.
       */
        for (bank = 0; bank < 4; bank++)
        {
                int size = 0;
index b333f0ce003216e090f547137069c6349936823f..65d8c0259fb01035c16694c6d4061865a86e2058 100644 (file)
@@ -42,7 +42,7 @@
   defined(CONFIG_MSS_MODULE) || defined(CONFIG_SSCAPE_MODULE) || \
   defined(CONFIG_TRIX_MODULE) || defined(CONFIG_MAD16_MODULE) || \
   defined(CONFIG_CS4232_MODULE) || defined(CONFIG_OPL3SA1_MODULE) || \
-  defined(CONFIG_SOFTOSS_MODULE)
+  defined(CONFIG_SOFTOSS_MODULE) || defined(CONFIG_VIDC_SOUND)
 #       define CONFIG_AUDIO
 #endif
 
index 4870ec79997fa0aefe3c0bed67d44158ae9db1fa..30f36696463120c7304f82299bb39e3de20c3014 100644 (file)
  *      CD-ROM DMA (Mitsumi or IDE):    0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled
  *
  *      For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23.
+ *
+ *     Changes
+ *     
+ *     Alan Cox                Clean up, added module selections.
  */
 
 #include "sound_config.h"
@@ -118,48 +122,47 @@ static int        c931_detected;  /* minor diferences from C930 */
 #define DDB(x)
 #endif
 
-static unsigned char
-mad_read(int port)
+static unsigned char mad_read(int port)
 {
-       unsigned long   flags;
-       unsigned char   tmp;
+       unsigned long flags;
+       unsigned char tmp;
 
        save_flags(flags);
        cli();
 
        switch (board_type)     /* Output password */
-         {
-         case C928:
-         case MOZART:
-                 outb((0xE2), PASSWD_REG);
-                 break;
-
-         case C929:
-                 outb((0xE3), PASSWD_REG);
-                 break;
-
-         case C930:
-                 /* outb(( 0xE4),  PASSWD_REG); */
-                 break;
-
-         case C924:
-                 outb((0xE5), PASSWD_REG);
-                 break;
-         }
+       {
+               case C928:
+               case MOZART:
+                       outb((0xE2), PASSWD_REG);
+                       break;
+
+               case C929:
+                       outb((0xE3), PASSWD_REG);
+                       break;
+
+               case C930:
+                       /* 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 */
-                 tmp = inb(0xe0f);     /* Read from data reg */
-       } else
+       {
+               outb((port - MC0_PORT), 0xe0e); /* Write to index reg */
+               tmp = inb(0xe0f);       /* Read from data reg */
+       }
+       else
                tmp = inb(port);
        restore_flags(flags);
 
        return tmp;
 }
 
-static void
-mad_write(int port, int value)
+static void mad_write(int port, int value)
 {
        unsigned long   flags;
 
@@ -167,65 +170,65 @@ mad_write(int port, int value)
        cli();
 
        switch (board_type)     /* Output password */
-         {
-         case C928:
-         case MOZART:
-                 outb((0xE2), PASSWD_REG);
-                 break;
-
-         case C929:
-                 outb((0xE3), PASSWD_REG);
-                 break;
-
-         case C930:
-                 /* outb(( 0xE4),  PASSWD_REG); */
-                 break;
-
-         case C924:
-                 outb((0xE5), PASSWD_REG);
-                 break;
-         }
+       {
+               case C928:
+               case MOZART:
+                       outb((0xE2), PASSWD_REG);
+                       break;
+
+               case C929:
+                       outb((0xE3), PASSWD_REG);
+                       break;
+
+               case C930:
+                       /* 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);
-       } else
+       {
+               outb((port - MC0_PORT), 0xe0e); /* Write to index reg */
+               outb(((unsigned char) (value & 0xff)), 0xe0f);
+       }
+       else
                outb(((unsigned char) (value & 0xff)), port);
        restore_flags(flags);
 }
 
-static int
-detect_c930(void)
+static int detect_c930(void)
 {
        unsigned char   tmp = mad_read(MC1_PORT);
 
        if ((tmp & 0x06) != 0x06)
-         {
-                 DDB(printk("Wrong C930 signature (%x)\n", tmp));
-                 /* return 0; */
-         }
+       {
+               DDB(printk("Wrong C930 signature (%x)\n", tmp));
+               /* return 0; */
+       }
        mad_write(MC1_PORT, 0);
 
        if (mad_read(MC1_PORT) != 0x06)
-         {
-                 DDB(printk("Wrong C930 signature2 (%x)\n", tmp));
-                 /* return 0; */
-         }
+       {
+               DDB(printk("Wrong C930 signature2 (%x)\n", tmp));
+               /* return 0; */
+       }
        mad_write(MC1_PORT, tmp);       /* Restore bits */
 
        mad_write(MC7_PORT, 0);
        if ((tmp = mad_read(MC7_PORT)) != 0)
-         {
-                 DDB(printk("MC7 not writable (%x)\n", tmp));
-                 return 0;
-         }
+       {
+               DDB(printk("MC7 not writable (%x)\n", tmp));
+               return 0;
+       }
        mad_write(MC7_PORT, 0xcb);
        if ((tmp = mad_read(MC7_PORT)) != 0xcb)
-         {
-                 DDB(printk("MC7 not writable2 (%x)\n", tmp));
-                 return 0;
-         }
+       {
+               DDB(printk("MC7 not writable2 (%x)\n", tmp));
+               return 0;
+       }
 
        tmp = mad_read(MC0_PORT+18);
        if (tmp == 0xff)
@@ -262,113 +265,109 @@ detect_c930(void)
         * the PnP bios will not recognize the chip on the next
         * warm boot and may assignd different resources to other
         * PnP/PCI cards.
-       */
+        */
        mad_write(MC0_PORT+17, 0x04);
        return 1;
 }
 
-static int
-detect_mad16(void)
+static int detect_mad16(void)
 {
-       unsigned char   tmp, tmp2;
-       int             i;
+       unsigned char tmp, tmp2;
+       int i;
+
+       /*
+        * Check that reading a register doesn't return bus float (0xff)
+        * when the card is accessed using password. This may fail in case
+        * the card is in low power mode. Normally at least the power saving mode
+        * bit should be 0.
+        */
 
-/*
- * Check that reading a register doesn't return bus float (0xff)
- * when the card is accessed using password. This may fail in case
- * the card is in low power mode. Normally at least the power saving mode
- * bit should be 0.
- */
        if ((tmp = mad_read(MC1_PORT)) == 0xff)
-         {
-                 DDB(printk("MC1_PORT returned 0xff\n"));
-                 return 0;
-         }
+       {
+               DDB(printk("MC1_PORT returned 0xff\n"));
+               return 0;
+       }
        for (i = 0xf8d; i <= 0xf98; i++)
                DDB(printk("Port %0x (init value) = %0x\n", i, mad_read(i)));
 
        if (board_type == C930)
                return detect_c930();
-/*
- * Now check that the gate is closed on first I/O after writing
- * the password. (This is how a MAD16 compatible card works).
- */
+
+       /*
+        * Now check that the gate is closed on first I/O after writing
+        * the password. (This is how a MAD16 compatible card works).
+        */
 
        if ((tmp2 = inb(MC1_PORT)) == tmp)      /* It didn't close */
-         {
-                 DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
-                 return 0;
-         }
+       {
+               DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
+               return 0;
+       }
        mad_write(MC1_PORT, tmp ^ 0x80);        /* Toggle a bit */
        if ((tmp2 = mad_read(MC1_PORT)) != (tmp ^ 0x80))        /* Compare the bit */
-         {
-                 mad_write(MC1_PORT, tmp);     /* Restore */
-                 DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
-                 return 0;
-         }
+       {
+               mad_write(MC1_PORT, tmp);       /* Restore */
+               DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
+               return 0;
+       }
        mad_write(MC1_PORT, tmp);       /* Restore */
        return 1;               /* Bingo */
-
 }
 
-static int
-wss_init(struct address_info *hw_config)
+static int wss_init(struct address_info *hw_config)
 {
-       int             ad_flags = 0;
+       int ad_flags = 0;
 
-/*
- *    Verify the WSS parameters
- */
+       /*
       *    Verify the WSS parameters
       */
 
        if (check_region(hw_config->io_base, 8))
-         {
-                 printk("MSS: I/O port conflict\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: I/O port conflict\n");
+               return 0;
+       }
        if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
                return 0;
        /*
-          * Check if the IO port returns valid signature. The original MS Sound
-          * system returns 0x04 while some cards (AudioTrix Pro for example)
-          * return 0x00.
+        * Check if the IO port returns valid signature. The original MS Sound
+        * system returns 0x04 while some cards (AudioTrix Pro for example)
+        * return 0x00.
         */
 
        if ((inb(hw_config->io_base + 3) & 0x3f) != 0x04 &&
            (inb(hw_config->io_base + 3) & 0x3f) != 0x00)
-         {
-                 DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3)));
-                 return 0;
-         }
+       {
+               DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3)));
+               return 0;
+       }
        if (hw_config->irq > 11)
-         {
-                 printk("MSS: Bad IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-         {
-                 printk("MSS: Bad DMA %d\n", hw_config->dma);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma);
+               return 0;
+       }
        /*
-          * Check that DMA0 is not in use with a 8 bit board.
+        * Check that DMA0 is not in use with a 8 bit board.
         */
 
        if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
-         {
-                 printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
-                 return 0;
-         }
+       {
+               printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
+               return 0;
+       }
        if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
-         {
-                 printk("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
-         }
+               printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
        return 1;
 }
 
-static int
-init_c930(struct address_info *hw_config)
+static int init_c930(struct address_info *hw_config)
 {
-       unsigned char   cfg = 0;
+       unsigned char cfg = 0;
 
 #ifdef MAD16_CONF
        cfg |= (0x0f & MAD16_CONF);
@@ -384,24 +383,23 @@ init_c930(struct address_info *hw_config)
        }
 
        switch (hw_config->io_base)
-         {
-         case 0x530:
-                 cfg |= 0x00;
-                 break;
-         case 0xe80:
-                 cfg |= 0x10;
-                 break;
-         case 0xf40:
-                 cfg |= 0x20;
-                 break;
-         case 0x604:
-                 cfg |= 0x30;
-                 break;
-
-         default:
-                 printk("MAD16: Invalid codec port %x\n", hw_config->io_base);
-                 return 0;
-         }
+       {
+               case 0x530:
+                       cfg |= 0x00;
+                       break;
+               case 0xe80:
+                       cfg |= 0x10;
+                       break;
+               case 0xf40:
+                       cfg |= 0x20;
+                       break;
+               case 0x604:
+                       cfg |= 0x30;
+                       break;
+               default:
+                       printk(KERN_ERR "MAD16: Invalid codec port %x\n", hw_config->io_base);
+                       return 0;
+       }
        mad_write(MC1_PORT, cfg);
 
        /* MC2 is CD configuration. Don't touch it. */
@@ -423,94 +421,98 @@ init_c930(struct address_info *hw_config)
        return wss_init(hw_config);
 }
 
-static int
-chip_detect(void)
+static int chip_detect(void)
 {
-       int             i;
+       int i;
 
-/*
- *    Then try to detect with the old password
- */
+       /*
       *    Then try to detect with the old password
       */
        board_type = C924;
 
        DDB(printk("Detect using password = 0xE5\n"));
 
        if (!detect_mad16())    /* No luck. Try different model */
-         {
-                 board_type = C928;
-
-                 DDB(printk("Detect using password = 0xE2\n"));
-
-                 if (!detect_mad16())
-                   {
-                           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);
-
-                                     board_type = C930;
-
-                                     DDB(printk("Detect using password = 0xE4\n"));
-
-                                     for (i = 0xf8d; i <= 0xf93; i++)
-                                             DDB(printk("port %03x = %02x\n", i, mad_read(i)));
-
-                                     if (!detect_mad16())
-                                             return 0;
-
-                                     DDB(printk("mad16.c: 82C930 detected\n"));
-                           } else
-                             {
-                                     DDB(printk("mad16.c: 82C929 detected\n"));
-                             }
-                 } 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;
-                             }
-                   }
-         }
+       {
+               board_type = C928;
+
+               DDB(printk("Detect using password = 0xE2\n"));
+
+               if (!detect_mad16())
+               {
+                       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);
+
+                               board_type = C930;
+
+                               DDB(printk("Detect using password = 0xE4\n"));
+
+                               for (i = 0xf8d; i <= 0xf93; i++)
+                                       DDB(printk("port %03x = %02x\n", i, mad_read(i)));
+
+                               if (!detect_mad16())
+                                       return 0;
+
+                               DDB(printk("mad16.c: 82C930 detected\n"));
+                       }
+                       else
+                       {
+                               DDB(printk("mad16.c: 82C929 detected\n"));
+                       }
+               }
+               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 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 i;
+       static int valid_ports[] = 
+       {
+               0x530, 0xe80, 0xf40, 0x604
+       };
+       unsigned char tmp;
+       unsigned char cs4231_mode = 0;
 
-       int             ad_flags = 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.
- */
+
+       /*
+        *    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())
@@ -530,25 +532,25 @@ probe_mad16(struct address_info *hw_config)
        tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80;       /* Enable WSS, Disable SB */
 
        for (i = 0; i < 5; i++)
-         {
-                 if (i > 3)    /* Not a valid port */
-                   {
-                           printk("MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
-                           return 0;
-                   }
-                 if (valid_ports[i] == hw_config->io_base)
-                   {
-                           tmp |= i << 4;      /* WSS port select bits */
-                           break;
-                   }
-         }
+       {
+               if (i > 3)      /* Not a valid port */
+               {
+                       printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
+                       return 0;
+               }
+               if (valid_ports[i] == hw_config->io_base)
+               {
+                       tmp |= i << 4;  /* WSS port select bits */
+                       break;
+               }
+       }
 
-/*
- * Set optional CD-ROM and joystick settings.
- */
+       /*
       * Set optional CD-ROM and joystick settings.
       */
 
-#ifdef MAD16_CONF
        tmp &= ~0x0f;
+#if defined(MAD16_CONF)
        tmp |= ((MAD16_CONF) & 0x0f);   /* CD-ROM and joystick bits */
 #endif
        mad_write(MC1_PORT, tmp);
@@ -567,11 +569,11 @@ probe_mad16(struct address_info *hw_config)
        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);
-         }
+       {
+               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;
 
@@ -579,15 +581,16 @@ probe_mad16(struct address_info *hw_config)
                cs4231_mode = 0x02;     /* CS4248/CS4231 sync delay switch */
 
        if (board_type == C929)
-         {
-                 mad_write(MC4_PORT, 0xa2);
-                 mad_write(MC5_PORT, 0xA5 | cs4231_mode);
-                 mad_write(MC6_PORT, 0x03);    /* Disable MPU401 */
-       } else
-         {
-                 mad_write(MC4_PORT, 0x02);
-                 mad_write(MC5_PORT, 0x30 | cs4231_mode);
-         }
+       {
+               mad_write(MC4_PORT, 0xa2);
+               mad_write(MC5_PORT, 0xA5 | cs4231_mode);
+               mad_write(MC6_PORT, 0x03);      /* Disable MPU401 */
+       }
+       else
+       {
+               mad_write(MC4_PORT, 0x02);
+               mad_write(MC5_PORT, 0x30 | cs4231_mode);
+       }
 
        for (i = 0xf8d; i <= 0xf93; i++)
                DDB(printk("port %03x after init = %02x\n", i, mad_read(i)));
@@ -597,24 +600,21 @@ probe_mad16(struct address_info *hw_config)
        return 1;
 }
 
-void
-attach_mad16(struct address_info *hw_config)
+void attach_mad16(struct address_info *hw_config)
 {
 
-       static char     interrupt_bits[12] =
-       {
+       static char     interrupt_bits[12] = {
                -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
        };
-       char            bits;
+       char bits;
 
-       static char     dma_bits[4] =
-       {
+       static char     dma_bits[4] = {
                1, 2, 0, 3
        };
 
-       int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
-       int             ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
-       unsigned char   dma2_bit = 0;
+       int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+       int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
+       unsigned char dma2_bit = 0;
 
        already_initialized = 1;
 
@@ -622,8 +622,9 @@ attach_mad16(struct address_info *hw_config)
                return;
 
        /*
-          * Set the IRQ and DMA addresses.
+        * Set the IRQ and DMA addresses.
         */
+       
        if (board_type == C930)
                interrupt_bits[5] = 0x28;       /* Also IRQ5 is possible on C930 */
 
@@ -633,35 +634,35 @@ attach_mad16(struct address_info *hw_config)
 
        outb((bits | 0x40), config_port);
        if ((inb(version_port) & 0x40) == 0)
-               printk("[IRQ Conflict?]");
+               printk(KERN_ERR "[IRQ Conflict?]\n");
 
-/*
- * Handle the capture DMA channel
- */
+       /*
       * Handle the capture DMA channel
       */
 
        if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma)
-         {
-                 if (!((dma == 0 && dma2 == 1) ||
+       {
+               if (!((dma == 0 && dma2 == 1) ||
                        (dma == 1 && dma2 == 0) ||
                        (dma == 3 && dma2 == 0)))
-                   {           /* Unsupported combination. Try to swap channels */
-                           int             tmp = dma;
-
-                           dma = dma2;
-                           dma2 = tmp;
-                   }
-                 if ((dma == 0 && dma2 == 1) ||
-                     (dma == 1 && dma2 == 0) ||
-                     (dma == 3 && dma2 == 0))
-                   {
-                           dma2_bit = 0x04;    /* Enable capture DMA */
-                 } else
-                   {
-                           printk("MAD16: Invalid capture DMA\n");
-                           dma2 = dma;
-                   }
-       } else
-               dma2 = dma;
+               {               /* Unsupported combination. Try to swap channels */
+                       int tmp = dma;
+
+                       dma = dma2;
+                       dma2 = tmp;
+               }
+               if ((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) ||
+                       (dma == 3 && dma2 == 0))
+               {
+                       dma2_bit = 0x04;        /* Enable capture DMA */
+               }
+               else
+               {
+                       printk("MAD16: Invalid capture DMA\n");
+                       dma2 = dma;
+               }
+       }
+       else dma2 = dma;
 
        outb((bits | dma_bits[dma] | dma2_bit), config_port);   /* Write IRQ+DMA setup */
 
@@ -673,24 +674,23 @@ attach_mad16(struct address_info *hw_config)
        request_region(hw_config->io_base, 4, "MAD16 WSS config");
 }
 
-void
-attach_mad16_mpu(struct address_info *hw_config)
+void attach_mad16_mpu(struct address_info *hw_config)
 {
        if (board_type < C929)  /* Early chip. No MPU support. Just SB MIDI */
-         {
-#if defined(CONFIG_MIDI)
+       {
+#if defined(CONFIG_MIDI) && defined(CONFIG_MAD16_OLDCARD)
 
-                 if (mad_read(MC1_PORT) & 0x20)
-                         hw_config->io_base = 0x240;
-                 else
-                         hw_config->io_base = 0x220;
+               if (mad_read(MC1_PORT) & 0x20)
+                       hw_config->io_base = 0x240;
+               else
+                       hw_config->io_base = 0x220;
 
-                 hw_config->name = "Mad16/Mozart";
-                 sb_dsp_init(hw_config);
+               hw_config->name = "Mad16/Mozart";
+               sb_dsp_init(hw_config);
 #endif
 
-                 return;
-         }
+               return;
+       }
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
        if (!already_initialized)
                return;
@@ -701,68 +701,67 @@ attach_mad16_mpu(struct address_info *hw_config)
 #endif
 }
 
-int
-probe_mad16_mpu(struct address_info *hw_config)
+int probe_mad16_mpu(struct address_info *hw_config)
 {
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
-       static int      mpu_attached = 0;
-       static int      valid_ports[] =
-       {0x330, 0x320, 0x310, 0x300};
-       static short    valid_irqs[] =
-       {9, 10, 5, 7};
-       unsigned char   tmp;
-
-       int             i;      /* A variable with secret power */
+       static int mpu_attached = 0;
+       static int valid_ports[] = {
+               0x330, 0x320, 0x310, 0x300
+       };
+       
+       static short valid_irqs[] = {9, 10, 5, 7};
+       unsigned char tmp;
+       int i;                          /* A variable with secret power */
 
        if (!already_initialized)       /* The MSS port must be initialized first */
                return 0;
 
-       if (mpu_attached)       /* Don't let them call this twice */
+       if (mpu_attached)               /* Don't let them call this twice */
                return 0;
        mpu_attached = 1;
 
        if (board_type < C929)  /* Early chip. No MPU support. Just SB MIDI */
-         {
-
-#if defined(CONFIG_MIDI)
-                 unsigned char   tmp;
-
-                 tmp = mad_read(MC3_PORT);
-
-                 /* 
-                  * MAD16 SB base is defined by the WSS base. It cannot be changed 
-                  * alone.
-                  * Ignore configured I/O base. Use the active setting. 
-                  */
-
-                 if (mad_read(MC1_PORT) & 0x20)
-                         hw_config->io_base = 0x240;
-                 else
-                         hw_config->io_base = 0x220;
-
-                 switch (hw_config->irq)
-                   {
-                   case 5:
-                           tmp = (tmp & 0x3f) | 0x80;
-                           break;
-                   case 7:
-                           tmp = (tmp & 0x3f);
-                           break;
-                   case 11:
-                           tmp = (tmp & 0x3f) | 0x40;
-                           break;
-                   default:
-                           printk("mad16/Mozart: Invalid MIDI IRQ\n");
-                           return 0;
-                   }
-
-                 mad_write(MC3_PORT, tmp | 0x04);
-                 hw_config->driver_use_1 = SB_MIDI_ONLY;
-                 return sb_dsp_detect(hw_config);
+       {
+
+#if defined(CONFIG_MIDI) && defined(CONFIG_MAD16_OLDCARD)
+               unsigned char   tmp;
+
+               tmp = mad_read(MC3_PORT);
+
+               /* 
+                * MAD16 SB base is defined by the WSS base. It cannot be changed 
+                * alone.
+                * Ignore configured I/O base. Use the active setting. 
+                */
+
+               if (mad_read(MC1_PORT) & 0x20)
+                       hw_config->io_base = 0x240;
+               else
+                       hw_config->io_base = 0x220;
+
+               switch (hw_config->irq)
+               {
+                       case 5:
+                               tmp = (tmp & 0x3f) | 0x80;
+                               break;
+                       case 7:
+                               tmp = (tmp & 0x3f);
+                               break;
+                       case 11:
+                               tmp = (tmp & 0x3f) | 0x40;
+                               break;
+                       default:
+                               printk(KERN_ERR "mad16/Mozart: Invalid MIDI IRQ\n");
+                               return 0;
+               }
+
+               mad_write(MC3_PORT, tmp | 0x04);
+               hw_config->driver_use_1 = SB_MIDI_ONLY;
+               return sb_dsp_detect(hw_config);
 #else
-                 return 0;
+               return 0;
 #endif
-         }
+       }
        tmp = mad_read(MC6_PORT) & 0x83;
        tmp |= 0x80;            /* MPU-401 enable */
 
@@ -771,36 +770,36 @@ probe_mad16_mpu(struct address_info *hw_config)
  */
 
        for (i = 0; i < 5; i++)
-         {
-                 if (i > 3)    /* Out of array bounds */
-                   {
-                           printk("MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base);
-                           return 0;
-                   }
-                 if (valid_ports[i] == hw_config->io_base)
-                   {
-                           tmp |= i << 5;
-                           break;
-                   }
-         }
+       {
+               if (i > 3)      /* Out of array bounds */
+               {
+                       printk(KERN_ERR "MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base);
+                       return 0;
+               }
+               if (valid_ports[i] == hw_config->io_base)
+               {
+                       tmp |= i << 5;
+                       break;
+               }
+       }
 
 /*
  * Set the MPU IRQ bits
  */
 
        for (i = 0; i < 5; i++)
-         {
-                 if (i > 3)    /* Out of array bounds */
-                   {
-                           printk("MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq);
-                           return 0;
-                   }
-                 if (valid_irqs[i] == hw_config->irq)
-                   {
-                           tmp |= i << 3;
-                           break;
-                   }
-         }
+       {
+               if (i > 3)      /* Out of array bounds */
+               {
+                       printk(KERN_ERR "MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq);
+                       return 0;
+               }
+               if (valid_irqs[i] == hw_config->irq)
+               {
+                       tmp |= i << 3;
+                       break;
+               }
+       }
        mad_write(MC6_PORT, tmp);       /* Write MPU401 config */
 
        return probe_uart401(hw_config);
@@ -809,13 +808,12 @@ probe_mad16_mpu(struct address_info *hw_config)
 #endif
 }
 
-void
-unload_mad16(struct address_info *hw_config)
+void unload_mad16(struct address_info *hw_config)
 {
        ad1848_unload(hw_config->io_base + 4,
-                     hw_config->irq,
-                     hw_config->dma,
-                     hw_config->dma2, 0);
+                       hw_config->irq,
+                       hw_config->dma,
+                       hw_config->dma2, 0);
        release_region(hw_config->io_base, 4);
        sound_unload_audiodev(hw_config->slots[0]);
 
@@ -824,12 +822,12 @@ unload_mad16(struct address_info *hw_config)
 void
 unload_mad16_mpu(struct address_info *hw_config)
 {
-#if defined(CONFIG_MIDI)
+#if defined(CONFIG_MIDI) && defined(CONFIG_MAD16_OLDCARD)
        if (board_type < C929)  /* Early chip. No MPU support. Just SB MIDI */
-         {
-                 sb_dsp_unload(hw_config);
-                 return;
-         }
+       {
+               sb_dsp_unload(hw_config);
+               return;
+       }
 #endif
 
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
@@ -839,6 +837,8 @@ unload_mad16_mpu(struct address_info *hw_config)
 
 #ifdef MODULE
 
+int            mpu_io = 0;
+int            mpu_irq = 0;
 int             io = -1;
 int             dma = -1;
 int             dma16 = -1;    /* Set this for modules that need it */
@@ -851,6 +851,8 @@ int             cddma = 3;
 int             opl4 = 0;
 int             joystick = 0;
 
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM(mpu_irq, "i");
 MODULE_PARM(io,"i");
 MODULE_PARM(dma,"i");
 MODULE_PARM(dma16,"i");
@@ -862,17 +864,18 @@ MODULE_PARM(cddma,"i");
 MODULE_PARM(opl4,"i");
 MODULE_PARM(joystick,"i");
 
+EXPORT_NO_SYMBOLS;
 
-static int      found_mpu;
+static int found_mpu;
 
 
-static int      dma_map[2][8] =
+static int dma_map[2][8] =
 {
        {0x03, -1, -1, -1, -1, 0x00, 0x01, 0x02},
        {0x03, -1, 0x01, 0x00, -1, -1, -1, -1}
 };
 
-static int      irq_map[16] =
+static int irq_map[16] =
 {
        0x00, -1, -1, 0x0A,
        -1, 0x04, -1, 0x08,
@@ -881,80 +884,83 @@ static int      irq_map[16] =
 };
 
 struct address_info config;
+struct address_info config_mpu;
 
-int
-init_module(void)
+int init_module(void)
 {
-       int             dmatype = 0;
+       int dmatype = 0;
 
-       printk("MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
+       printk(KERN_INFO "MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
        if (io == -1 || dma == -1 || irq == -1)
-         {
-                 printk("I/O, DMA and irq are mandatory\n");
-                 return -EINVAL;
-         }
-       printk("CDROM ");
+       {
+               printk(KERN_ERR "I/O, DMA and irq are mandatory\n");
+               return -EINVAL;
+       }
+       printk(KERN_INFO "CDROM ");
        switch (cdtype)
-         {
-         case 0x00:
-                 printk("Disabled");
-                 cdirq = 0;
-                 break;
-         case 0x02:
-                 printk("Sony CDU31A");
-                 dmatype = 2;
-                 break;
-         case 0x04:
-                 printk("Mitsumi");
-                 dmatype = 1;
-                 break;
-         case 0x06:
-                 printk("Panasonic Lasermate");
-                 dmatype = 2;
-                 break;
-         case 0x08:
-                 printk("Secondary IDE");
-                 dmatype = 1;
-                 break;
-         case 0x0A:
-                 printk("Primary IDE");
-                 dmatype = 1;
-                 break;
-         default:
-                 printk("\nInvalid CDROM type\n");
-                 return -EINVAL;
-         }
+       {
+               case 0x00:
+                       printk("Disabled");
+                       cdirq = 0;
+                       break;
+               case 0x02:
+                       printk("Sony CDU31A");
+                       dmatype = 2;
+                       break;
+               case 0x04:
+                       printk("Mitsumi");
+                       dmatype = 1;
+                       break;
+               case 0x06:
+                       printk("Panasonic Lasermate");
+                       dmatype = 2;
+                       break;
+               case 0x08:
+                       printk("Secondary IDE");
+                       dmatype = 1;
+                       break;
+               case 0x0A:
+                       printk("Primary IDE");
+                       dmatype = 1;
+                       break;
+               default:
+                       printk("\n");
+                       printk(KERN_ERR "Invalid CDROM type\n");
+                       return -EINVAL;
+       }
 
        if (dmatype)
-         {
-                 if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1)
-                   {
-                           printk("\nInvalid CDROM DMA\n");
-                           return -EINVAL;
-                   }
-                 if (cddma)
-                         printk(", DMA %d", cddma);
-                 else
-                         printk(", no DMA");
-         }
+       {
+               if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1)
+               {
+                       printk("\n");
+                       printk(KERN_ERR "Invalid CDROM DMA\n");
+                       return -EINVAL;
+               }
+               if (cddma)
+                       printk(", DMA %d", cddma);
+               else
+                       printk(", no DMA");
+       }
        if (cdtype && !cdirq)
                printk(", no IRQ");
        else if (cdirq < 0 || cdirq > 15 || irq_map[cdirq] == -1)
-         {
+       {
                  printk(", invalid IRQ (disabling)");
                  cdirq = 0;
-       } else
-               printk(", IRQ %d", cdirq);
+       }
+       else printk(", IRQ %d", cdirq);
 
-       printk(".\nJoystick port ");
+       printk(".\n");
+       printk(KERN_INFO "Joystick port ");
        if (joystick == 1)
                printk("enabled.\n");
        else
-         {
-                 joystick = 0;
-                 printk("disabled.\n");
-         }
+       {
+               joystick = 0;
+               printk("disabled.\n");
+       }
 
        /*
         *    Build the config words
@@ -967,26 +973,26 @@ init_module(void)
        mad16_cdsel |= dma_map[dmatype][cddma];
 
        if (cdtype < 0x08)
-         {
-                 switch (cdport)
-                   {
-                   case 0x340:
-                           mad16_cdsel |= 0x00;
-                           break;
-                   case 0x330:
-                           mad16_cdsel |= 0x40;
-                           break;
-                   case 0x360:
-                           mad16_cdsel |= 0x80;
-                           break;
-                   case 0x320:
-                           mad16_cdsel |= 0xC0;
-                           break;
-                   default:
-                           printk("Unknown CDROM I/O base %d\n", cdport);
-                           return -EINVAL;
-                   }
-         }
+       {
+               switch (cdport)
+               {
+                       case 0x340:
+                               mad16_cdsel |= 0x00;
+                               break;
+                       case 0x330:
+                               mad16_cdsel |= 0x40;
+                               break;
+                       case 0x360:
+                               mad16_cdsel |= 0x80;
+                               break;
+                       case 0x320:
+                               mad16_cdsel |= 0xC0;
+                               break;
+                       default:
+                               printk(KERN_ERR "Unknown CDROM I/O base %d\n", cdport);
+                               return -EINVAL;
+               }
+       }
        mad16_cdsel |= irq_map[cdirq];
 
        config.io_base = io;
@@ -996,19 +1002,21 @@ init_module(void)
 
        if (!probe_mad16(&config))
                return -ENODEV;
-       found_mpu = probe_mad16_mpu(&config);
+
+       config_mpu.io_base = mpu_io;
+       config_mpu.irq = mpu_irq;
+       found_mpu = probe_mad16_mpu(&config_mpu);
 
        attach_mad16(&config);
 
        if (found_mpu)
-               attach_mad16_mpu(&config);
+               attach_mad16_mpu(&config_mpu);
 
        SOUND_LOCK;
        return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
        if (found_mpu)
                unload_mad16_mpu(&config);
index a7d37039cf2f78d7528d998337dd062d2d891f99..4d207627375ef7b989e363373c6f3476e8855e4d 100644 (file)
@@ -20,6 +20,7 @@
  
 #include <linux/config.h>
 #include <linux/module.h>
+#include <asm/init.h>
 
 #define USE_SEQ_MACROS
 #define USE_SIMPLE_MACROS
@@ -452,6 +453,11 @@ void unload_maui(struct address_info *hw_config)
 
 #ifdef MODULE
 
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+
+EXPORT_NO_SYMBOLS;
+
 int io = -1;
 int irq = -1;
 
@@ -489,7 +495,7 @@ int init_module(void)
 void cleanup_module(void)
 {
        if (fw_load && maui_os)
-               kfree(maui_os);
+               vfree(maui_os);
        unload_maui(&cfg);
        SOUND_LOCK_END;
 }
index 09dea3a3494b4e9cfb6e409c9366e3bc41409830..50d595d2fde91a61218d60669afe9d8a60a26985 100644 (file)
@@ -15,6 +15,7 @@
  */
 #include <linux/config.h>
 #include <linux/stddef.h>
+#include <linux/kmod.h>
 
 #define MIDIBUF_C
 
index 39adf4357cb8e1bacd5fbfbf294b923988f671d7..86fe07f109292ffca10a4fc0929e3b301eb18696 100644 (file)
@@ -3,14 +3,21 @@
  *
  * Low level driver for Yamaha YMF701B aka OPL3-SA chip
  * 
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
+ *
+ * Changes:
+ *     Alan Cox                Modularisation
+ *
+ * FIXME:
+ *     Check for install of mpu etc is wrong, should check result of the mss stuff
  */
 #include <linux/config.h>
 
 #undef  SB_OK
 #include "sound_config.h"
 #ifdef SB_OK
 #include "sb.h"
-static int      sb_initialized = 0;
+static int sb_initialized = 0;
 
 #endif
 
 #ifdef CONFIG_OPL3SA1
 
-static int      kilroy_was_here = 0;   /* Don't detect twice */
-static int      mpu_initialized = 0;
+static int kilroy_was_here = 0;        /* Don't detect twice */
+static int mpu_initialized = 0;
 
-static int     *opl3sa_osp = NULL;
+static int *opl3sa_osp = NULL;
 
-static unsigned char
-opl3sa_read(int addr)
+static unsigned char opl3sa_read(int addr)
 {
-       unsigned long   flags;
-       unsigned char   tmp;
+       unsigned long flags;
+       unsigned char tmp;
 
        save_flags(flags);
        cli();
@@ -45,10 +51,9 @@ opl3sa_read(int addr)
        return tmp;
 }
 
-static void
-opl3sa_write(int addr, int data)
+static void opl3sa_write(int addr, int data)
 {
-       unsigned long   flags;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -58,31 +63,32 @@ opl3sa_write(int addr, int data)
        restore_flags(flags);
 }
 
-static int
-opl3sa_detect(void)
+static int opl3sa_detect(void)
 {
-       int             tmp;
+       int tmp;
 
        if (((tmp = opl3sa_read(0x01)) & 0xc4) != 0x04)
-         {
-                 DDB(printk("OPL3-SA detect error 1 (%x)\n", opl3sa_read(0x01)));
-                 /* return 0; */
-         }
-/*
- * Check that the password feature has any effect
- */
+       {
+               DDB(printk("OPL3-SA detect error 1 (%x)\n", opl3sa_read(0x01)));
+               /* return 0; */
+       }
+
+       /*
+        * Check that the password feature has any effect
+        */
+       
        if (inb(0xf87) == tmp)
-         {
-                 DDB(printk("OPL3-SA detect failed 2 (%x/%x)\n", tmp, inb(0xf87)));
-                 return 0;
-         }
+       {
+               DDB(printk("OPL3-SA detect failed 2 (%x/%x)\n", tmp, inb(0xf87)));
+               return 0;
+       }
        tmp = (opl3sa_read(0x04) & 0xe0) >> 5;
 
        if (tmp != 0 && tmp != 1)
-         {
-                 DDB(printk("OPL3-SA detect failed 3 (%d)\n", tmp));
-                 return 0;
-         }
+       {
+               DDB(printk("OPL3-SA detect failed 3 (%d)\n", tmp));
+               return 0;
+       }
        DDB(printk("OPL3-SA mode %x detected\n", tmp));
 
        opl3sa_write(0x01, 0x00);       /* Disable MSS */
@@ -97,49 +103,50 @@ opl3sa_detect(void)
  *     OPL3-SA
  */
 
-int
-probe_opl3sa_wss(struct address_info *hw_config)
+int probe_opl3sa_wss(struct address_info *hw_config)
 {
-       int             ret;
-       unsigned char   tmp = 0x24;     /* WSS enable */
+       int ret;
+       unsigned char tmp = 0x24;       /* WSS enable */
 
        if (check_region(0xf86, 2))     /* Control port is busy */
                return 0;
        /*
-          * Check if the IO port returns valid signature. The original MS Sound
-          * system returns 0x04 while some cards (OPL3-SA for example)
-          * return 0x00.
+        * Check if the IO port returns valid signature. The original MS Sound
+        * system returns 0x04 while some cards (OPL3-SA for example)
+        * return 0x00.
         */
+
        if (check_region(hw_config->io_base, 8))
-         {
-                 printk("OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base);
+               return 0;
+       }
        opl3sa_osp = hw_config->osp;
 
        if (!opl3sa_detect())
-         {
-                 printk("OSS: OPL3-SA chip not found\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "OSS: OPL3-SA chip not found\n");
+               return 0;
+       }
+       
        switch (hw_config->io_base)
-         {
-         case 0x530:
-                 tmp |= 0x00;
-                 break;
-         case 0xe80:
-                 tmp |= 0x08;
-                 break;
-         case 0xf40:
-                 tmp |= 0x10;
-                 break;
-         case 0x604:
-                 tmp |= 0x18;
-                 break;
-         default:
-                 printk("OSS: Unsupported OPL3-SA/WSS base %x\n", hw_config->io_base);
+       {
+               case 0x530:
+                       tmp |= 0x00;
+                       break;
+               case 0xe80:
+                       tmp |= 0x08;
+                       break;
+               case 0xf40:
+                       tmp |= 0x10;
+                       break;
+               case 0x604:
+                       tmp |= 0x18;
+                       break;
+               default:
+                       printk(KERN_ERR "OSS: Unsupported OPL3-SA/WSS base %x\n", hw_config->io_base);
                  return 0;
-         }
+       }
 
        opl3sa_write(0x01, tmp);        /* WSS setup register */
        kilroy_was_here = 1;
@@ -151,23 +158,21 @@ probe_opl3sa_wss(struct address_info *hw_config)
        return ret;
 }
 
-void
-attach_opl3sa_wss(struct address_info *hw_config)
+void attach_opl3sa_wss(struct address_info *hw_config)
 {
-       int             nm = num_mixers;
+       int nm = num_mixers;
 
        attach_ms_sound(hw_config);
        if (num_mixers > nm)    /* A mixer was installed */
-         {
-                 AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
-                 AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
-                 AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
-         }
+       {
+               AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
+               AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
+               AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+       }
 }
 
 
-void
-attach_opl3sa_mpu(struct address_info *hw_config)
+void attach_opl3sa_mpu(struct address_info *hw_config)
 {
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
        hw_config->name = "OPL3-SA (MPU401)";
@@ -175,55 +180,54 @@ attach_opl3sa_mpu(struct address_info *hw_config)
 #endif
 }
 
-int
-probe_opl3sa_mpu(struct address_info *hw_config)
+int probe_opl3sa_mpu(struct address_info *hw_config)
 {
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
-       unsigned char   conf;
-       static char     irq_bits[] =
-       {-1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4};
+       unsigned char conf;
+       static char irq_bits[] = {
+               -1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4
+       };
 
        if (!kilroy_was_here)
-         {
-                 return 0;     /* OPL3-SA has not been detected earlier */
-         }
+               return 0;       /* OPL3-SA has not been detected earlier */
+
        if (mpu_initialized)
-         {
-                 DDB(printk("OPL3-SA: MPU mode already initialized\n"));
-                 return 0;
-         }
+       {
+               DDB(printk("OPL3-SA: MPU mode already initialized\n"));
+               return 0;
+       }
        if (check_region(hw_config->io_base, 4))
-         {
-                 printk("OPL3-SA: MPU I/O port conflict (%x)\n", hw_config->io_base);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "OPL3-SA: MPU I/O port conflict (%x)\n", hw_config->io_base);
+               return 0;
+       }
        if (hw_config->irq > 10)
-         {
-                 printk("OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        if (irq_bits[hw_config->irq] == -1)
-         {
-                 printk("OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        switch (hw_config->io_base)
-         {
-         case 0x330:
-                 conf = 0x00;
-                 break;
-         case 0x332:
-                 conf = 0x20;
-                 break;
-         case 0x334:
-                 conf = 0x40;
-                 break;
-         case 0x300:
-                 conf = 0x60;
-                 break;
-         default:
-                 return 0;     /* Invalid port */
-         }
+       {
+               case 0x330:
+                       conf = 0x00;
+                       break;
+               case 0x332:
+                       conf = 0x20;
+                       break;
+               case 0x334:
+                       conf = 0x40;
+                       break;
+               case 0x300:
+                       conf = 0x60;
+                       break;
+               default:
+                       return 0;       /* Invalid port */
+       }
 
        conf |= 0x83;           /* MPU & OPL3 (synth) & game port enable */
        conf |= irq_bits[hw_config->irq] << 2;
@@ -238,10 +242,9 @@ probe_opl3sa_mpu(struct address_info *hw_config)
 #endif
 }
 
-void
-unload_opl3sa_wss(struct address_info *hw_config)
+void unload_opl3sa_wss(struct address_info *hw_config)
 {
-       int             dma2 = hw_config->dma2;
+       int dma2 = hw_config->dma2;
 
        if (dma2 == -1)
                dma2 = hw_config->dma;
@@ -256,16 +259,15 @@ unload_opl3sa_wss(struct address_info *hw_config)
                      0);
 }
 
-void
-unload_opl3sa_mpu(struct address_info *hw_config)
+void unload_opl3sa_mpu(struct address_info *hw_config)
 {
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
        unload_uart401(hw_config);
 #endif
 }
+
 #ifdef SB_OK
-void
-unload_opl3sa_sb(struct address_info *hw_config)
+void unload_opl3sa_sb(struct address_info *hw_config)
 {
 #ifdef CONFIG_SBDSP
        sb_dsp_unload(hw_config);
@@ -273,5 +275,60 @@ unload_opl3sa_sb(struct address_info *hw_config)
 }
 #endif
 
+#ifdef MODULE
+int             io = -1;
+int             irq = -1;
+int             dma = -1;
+int             dma2 = -1;
+
+int            mpu_io = -1;
+int            mpu_irq = -1;
+
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma2,"i");
+MODULE_PARM(mpu_io,"i");
+MODULE_PARM(mpu_irq,"i");
+
+struct address_info cfg;
+struct address_info mpu_cfg;
+
+int init_module(void)
+{
+       if (io == -1 || irq == -1 || dma == -1)
+       {
+               printk(KERN_ERR "opl3sa: dma, irq and io must be set.\n");
+               return -EINVAL;
+       }
+       cfg.io_base = io;
+       cfg.irq = irq;
+       cfg.dma = dma;
+       cfg.dma2 = dma2;
+       
+       mpu_cfg.io_base = mpu_io;
+       mpu_cfg.irq = mpu_irq;
+
+       if (probe_opl3sa_wss(&cfg) == 0)
+               return -ENODEV;
+
+       found_mpu=probe_opl3_mpu(&mpu_cfg);
+
+       attach_opl3sa_wss(&cfg);
+       if(found_mpu)
+               attach_opl3sa_mpu(&mpu_cfg);
+       SOUND_LOCK;
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       if(found_mpu)
+               unload_opl3sa_mpu(&mpu_cfg);
+       unload_opl3sa(&cfg);
+       SOUND_LOCK_END;
+}
+
+#endif
 
 #endif
index 5bd4a27ebcaf9cb0d1c8bd2cdf3f9354bae01b39..31fcc81f7fe8d584cb22c17dfee0acfa9e95a621 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/fs.h>
 #include <asm/dma.h>
+#include <asm/io.h>
 #include <asm/param.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
@@ -32,7 +33,6 @@
 #include <asm/uaccess.h>
 #include <linux/poll.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #endif
 
 #include <linux/wrapper.h>
@@ -52,7 +52,6 @@ extern void reprogram_timer(void);
 #define USE_AUTOINIT_DMA
 
 extern caddr_t sound_mem_blocks[1024];
-extern int sound_mem_sizes[1024];
 extern int sound_nblocks;
 
 #undef PSEUDO_DMA_AUTOINIT
index e00108b0b935933d790c49a22cb05374523555f0..4d4d9e4bd9d39749de1b05c38539fd2ff963dd5a 100644 (file)
@@ -164,7 +164,7 @@ static int config_pas_hw(struct address_info *hw_config)
                }
                else
                {
-                       if (request_irq(pas_irq, pasintr, 0, "PAS16", NULL) < 0)
+                       if (request_irq(pas_irq, pasintr, 0, "PAS16",NULL) < 0)
                                ok = 0;
                }
        }
index 7a0a2e66eda5ebbf7b352ed9ca31cf3bd2d30aed..9b00aa43ad715dfdc9fc34f3e491ba8805a48781 100644 (file)
@@ -2,18 +2,29 @@
  * sound/pss.c
  *
  * The low level driver for the Personal Sound System (ECHO ESC614).
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
- */
-/*
+ *
+ *
  * Thomas Sailer       ioctl code reworked (vmalloc/vfree removed)
  * Alan Cox            modularisation, clean up.
+ *
+ * 98-02-21: Vladimir Michl <vladimir.michl@upol.cz>
+ *          Added mixer device for Beethoven ADSP-16 (master volume,
+ *         bass, treble, synth), only for speakers.
+ *          Fixed bug in pss_write (exchange parameters)
+ *          Fixed config port of SB
+ *          Requested two regions for PSS (PSS mixer, PSS config)
+ *          Modified pss_download_boot
+ *          To probe_pss_mss added test for initialize AD1848
  */
+
+
 #include <linux/config.h>
 #include <linux/module.h>
 
@@ -39,7 +50,7 @@
  */
 #define CONF_PSS       0x10
 #define CONF_WSS       0x12
-#define CONF_SB                0x13
+#define CONF_SB                0x14
 #define CONF_CDROM     0x16
 #define CONF_MIDI      0x18
 
 #define PSS_WRITE_EMPTY  0x8000
 #define PSS_READ_FULL    0x4000
 
+/*
+ * WSS registers
+ */
+#define WSS_INDEX 4
+#define WSS_DATA 5
+
+/*
+ * WSS status bits
+ */
+#define WSS_INITIALIZING 0x80
+#define WSS_AUTOCALIBRATION 0x20
+
+#define NO_WSS_MIXER   -1
+
 #include "coproc.h"
 
 #ifdef CONFIG_PSS_HAVE_BOOT
@@ -62,23 +87,32 @@ static unsigned char *pss_synth = NULL;
 static int pss_synthLen = 0;
 #endif
 
-typedef struct pss_confdata
-{
-       int     base;
-       int     irq;
-       int     dma;
-       int     *osp;
-}
-
-pss_confdata;
-
+unsigned char pss_mixer = 1;
+
+typedef struct pss_mixerdata {
+       unsigned int volume_l;
+       unsigned int volume_r;
+       unsigned int bass;
+       unsigned int treble;
+       unsigned int synth;
+} pss_mixerdata;
+
+typedef struct pss_confdata {
+       int             base;
+       int             irq;
+       int             dma;
+       int            *osp;
+       pss_mixerdata   mixer;
+       int             ad_mixer_dev;
+} pss_confdata;
+  
 static pss_confdata pss_data;
 static pss_confdata *devc = &pss_data;
 
 static int      pss_initialized = 0;
 static int      nonstandard_microcode = 0;
 
-static void pss_write(int data)
+static void pss_write(pss_confdata *devc, int data)
 {
        int i, limit;
 
@@ -92,14 +126,14 @@ static void pss_write(int data)
         */
 
        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(KERN_ERR "PSS: DSP Command (%04x) Timeout.\n", data);
+       {
+               if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY)
+               {
+                       outw(data, REG(PSS_DATA));
+                       return;
+               }
+       }
+       printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data);
 }
 
 int probe_pss(struct address_info *hw_config)
@@ -116,7 +150,7 @@ int probe_pss(struct address_info *hw_config)
                if (devc->base != 0x230 && devc->base != 0x250)         /* Some cards use these */
                        return 0;
 
-       if (check_region(devc->base, 16)) { 
+       if (check_region(devc->base, 0x19 /*16*/)) { 
                printk(KERN_ERR "PSS: I/O port conflict\n");
                return 0;
        }
@@ -249,7 +283,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
                pss_reset_dsp(devc);
        }
        count = 1;
-       while (1)
+       while ((flags&CPF_LAST) || count<size )
        {
                int j;
 
@@ -267,12 +301,22 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
                                break;
                        else
                        {
-                               printk("\nPSS: Download timeout problems, byte %d=%d\n", count, size);
+                               printk("\n");
+                               printk(KERN_ERR "PSS: Download timeout problems, byte %d=%d\n", count, size);
                                return 0;
                        }
                }
 /*_____ Send the next byte */
-               outw(*block++, REG(PSS_DATA));
+               if (count >= size) 
+               {
+                       /* If not data in block send 0xffff */
+                       outw (0xffff, REG (PSS_DATA));
+               }
+               else
+               {
+                       /*_____ Send the next byte */
+                       outw (*block++, REG (PSS_DATA));
+               };
                count++;
        }
 
@@ -309,6 +353,237 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
        return 1;
 }
 
+/* Mixer */
+static void set_master_volume(pss_confdata *devc, int left, int right)
+{
+       static unsigned char log_scale[101] =  {
+               0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
+               0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
+               0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
+               0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+               0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
+               0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+               0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
+               0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+               0xfe, 0xfe, 0xff, 0xff, 0xff
+       };
+       pss_write(devc, 0x0010);
+       pss_write(devc, log_scale[left] | 0x0000);
+       pss_write(devc, 0x0010);
+       pss_write(devc, log_scale[right] | 0x0100);
+}
+
+static void set_synth_volume(pss_confdata *devc, int volume)
+{
+       /* Should use:
+               int vol = (int)(0x8000/100.0 * (float)volume);
+               
+         Fixme: integerise the above cleanly
+       */
+       int vol = (0x8000/(100L*volume));
+       pss_write(devc, 0x0080);
+       pss_write(devc, vol);
+       pss_write(devc, 0x0081);
+       pss_write(devc, vol);
+}
+
+static void set_bass(pss_confdata *devc, int level)
+{
+       /* Should use
+          int vol = (int)((0xfd - 0xf0)/100.0 * (float)level) + 0xf0;     
+          
+          Fixme: integerise cleanly 
+       */
+       int vol = (int)((0xfd - 0xf0)/100L * level) + 0xf0;
+       pss_write(devc, 0x0010);
+       pss_write(devc, vol | 0x0200);
+};
+
+static void set_treble(pss_confdata *devc, int level)
+{      
+       /* Should use 
+          int vol = (int)((0xfd - 0xf0)/100.0 * (float)level) + 0xf0;
+          
+          Fixme: integerise properly
+       */
+       
+       int vol = ((0xfd - 0xf0)/100L * level) + 0xf0;
+       pss_write(devc, 0x0010);
+       pss_write(devc, vol | 0x0300);
+};
+
+static void pss_mixer_reset(pss_confdata *devc)
+{
+       set_master_volume(devc, 23, 23);
+       set_bass(devc, 50);
+       set_treble(devc, 50);
+       set_synth_volume(devc, 30);
+       pss_write (devc, 0x0010);
+       pss_write (devc, 0x0800 | 0xce);        /* Stereo */
+       
+       if(pss_mixer)
+       {
+               devc->mixer.volume_l = devc->mixer.volume_r = 23;
+               devc->mixer.bass = 50;
+               devc->mixer.treble = 50;
+               devc->mixer.synth = 30;
+       }
+}
+
+static void arg_to_volume_mono(unsigned int volume, int *aleft)
+{
+       int left;
+       
+       left = volume & 0x00ff;
+       if (left > 100)
+               left = 100;
+       *aleft = left;
+}
+
+static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright)
+{
+       arg_to_volume_mono(volume, aleft);
+       arg_to_volume_mono(volume >> 8, aright);
+}
+
+static int ret_vol_mono(int left)
+{
+       return ((left << 8) | left);
+}
+
+static int ret_vol_stereo(int left, int right)
+{
+       return ((right << 8) | left);
+}
+
+static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, caddr_t arg)
+{
+       if (devc->ad_mixer_dev != NO_WSS_MIXER) 
+               return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
+       else 
+               return -EINVAL;
+}
+
+static int pss_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+       pss_confdata *devc = mixer_devs[dev]->devc;
+       int cmdf = cmd & 0xff;
+       
+       if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
+               (cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) &&
+               (cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) &&
+               (cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) &&
+               (cmdf != SOUND_MIXER_RECSRC)) 
+       {
+               return call_ad_mixer(devc, cmd, arg);
+       }
+       
+       if (((cmd >> 8) & 0xff) != 'M') 
+               return -EINVAL;
+               
+       if (_SIOC_DIR (cmd) & _SIOC_WRITE)
+       {
+               switch (cmdf)   
+               {
+                       case SOUND_MIXER_RECSRC:
+                               if (devc->ad_mixer_dev != NO_WSS_MIXER)
+                                       return call_ad_mixer(devc, cmd, arg);
+                               else
+                               {
+                                       if (*(int *)arg != 0)
+                                               return -EINVAL;
+                                       return 0;
+                               }
+                       case SOUND_MIXER_VOLUME:
+                               arg_to_volume_stereo(*(unsigned int *)arg, &devc->mixer.volume_l,
+                                       &devc->mixer.volume_r); 
+                               set_master_volume(devc, devc->mixer.volume_l,
+                                       devc->mixer.volume_r);
+                               return ret_vol_stereo(devc->mixer.volume_l,
+                                       devc->mixer.volume_r);
+                 
+                       case SOUND_MIXER_BASS:
+                               arg_to_volume_mono(*(unsigned int *)arg,
+                                       &devc->mixer.bass);
+                               set_bass(devc, devc->mixer.bass);
+                               return ret_vol_mono(devc->mixer.bass);
+                 
+                       case SOUND_MIXER_TREBLE:
+                               arg_to_volume_mono(*(unsigned int *)arg,
+                                       &devc->mixer.treble);
+                               set_treble(devc, devc->mixer.treble);
+                               return ret_vol_mono(devc->mixer.treble);
+                 
+                       case SOUND_MIXER_SYNTH:
+                               arg_to_volume_mono(*(unsigned int *)arg,
+                                       &devc->mixer.synth);
+                               set_synth_volume(devc, devc->mixer.synth);
+                               return ret_vol_mono(devc->mixer.synth);
+                 
+                       default:
+                               return -EINVAL;
+               }
+       }
+       else                    
+       {
+               /*
+                * Return parameters
+                */
+               switch (cmdf)
+               {
+
+                       case SOUND_MIXER_DEVMASK:
+                               if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
+                                       *(int *)arg = 0; /* no mixer devices */
+                               return (*(int *)arg |= SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH);
+                 
+                       case SOUND_MIXER_STEREODEVS:
+                               if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
+                                       *(int *)arg = 0; /* no stereo devices */
+                               return (*(int *)arg |= SOUND_MASK_VOLUME);
+                 
+                       case SOUND_MIXER_RECMASK:
+                               if (devc->ad_mixer_dev != NO_WSS_MIXER)
+                                       return call_ad_mixer(devc, cmd, arg);
+                               else
+                                       return (*(int *)arg = 0); /* no record devices */
+
+                       case SOUND_MIXER_CAPS:
+                               if (devc->ad_mixer_dev != NO_WSS_MIXER)
+                                       return call_ad_mixer(devc, cmd, arg);
+                               else
+                                       return (*(int *)arg = SOUND_CAP_EXCL_INPUT);
+
+                       case SOUND_MIXER_RECSRC:
+                               if (devc->ad_mixer_dev != NO_WSS_MIXER)
+                                       return call_ad_mixer(devc, cmd, arg);
+                               else
+                                       return (*(int *)arg = 0); /* no record source */
+
+                       case SOUND_MIXER_VOLUME:
+                               return (*(int *)arg = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r));
+                         
+                       case SOUND_MIXER_BASS:
+                               return (*(int *)arg = ret_vol_mono(devc->mixer.bass));
+                         
+                       case SOUND_MIXER_TREBLE:
+                               return (*(int *)arg = ret_vol_mono(devc->mixer.treble));
+                         
+                       case SOUND_MIXER_SYNTH:
+                               return (*(int *)arg = ret_vol_mono(devc->mixer.synth));
+                       default:
+                               return -EINVAL;
+               }
+       }
+}
+
+static struct mixer_operations pss_mixer_operations =
+{
+       "SOUNDPORT",
+       "PSS-AD1848",
+        pss_mixer_ioctl
+};
+
 void attach_pss(struct address_info *hw_config)
 {
        unsigned short  id;
@@ -318,10 +593,14 @@ void attach_pss(struct address_info *hw_config)
        devc->irq = hw_config->irq;
        devc->dma = hw_config->dma;
        devc->osp = hw_config->osp;
+       devc->ad_mixer_dev = NO_WSS_MIXER;
 
        if (!probe_pss(hw_config))
                return;
 
+       request_region(hw_config->io_base, 0x10, "PSS mixer, SB emulation");
+       request_region(hw_config->io_base + 0x10, 0x9, "PSS config");
+
        id = inw(REG(PSS_ID)) & 0x00ff;
 
        /*
@@ -356,21 +635,6 @@ void 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)
 {
        int timeout;
@@ -380,17 +644,17 @@ int probe_pss_mpu(struct address_info *hw_config)
 
        if (check_region(hw_config->io_base, 2))
        {
-               printk("PSS: MPU I/O port conflict\n");
+               printk(KERN_ERR "PSS: MPU I/O port conflict\n");
                return 0;
        }
        if (!set_io_base(devc, CONF_MIDI, hw_config->io_base))
        {
-                 printk("PSS: MIDI base could not be set.\n");
+                 printk(KERN_ERR "PSS: MIDI base could not be set.\n");
                  return 0;
        }
        if (!set_irq(devc, CONF_MIDI, hw_config->irq))
        {
-                 printk("PSS: MIDI IRQ allocation error.\n");
+                 printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
                  return 0;
        }
        if (!pss_synthLen)
@@ -403,7 +667,6 @@ int probe_pss_mpu(struct address_info *hw_config)
                printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
                return 0;
        }
-       pss_init_speaker();
 
        /*
         * Finally wait until the DSP algorithm has initialized itself and
@@ -709,28 +972,51 @@ int probe_pss_mss(struct address_info *hw_config)
         * downloaded to the ADSP2115 spends some time initializing the card.
         * Let's try to wait until it finishes this task.
         */
-       for (timeout = 0;
-       timeout < 100000 && (inb(hw_config->io_base + 3) & 0x3f) != 0x04;
-            timeout++);
+       for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) & WSS_INITIALIZING); timeout++);
+
+       outb((0x0b), hw_config->io_base + WSS_INDEX);   /* Required by some cards */
 
-       outb((0x0b), hw_config->io_base + 4);   /* Required by some cards */
+       for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) && (timeout < 100000); timeout++);
 
-       for (timeout = 0;
-            timeout < 100000;
-            timeout++);
        return probe_ms_sound(hw_config);
 }
 
 void attach_pss_mss(struct address_info *hw_config)
 {
+       int        my_mix = -999;       /* gcc shut up */
+       
+       devc->ad_mixer_dev = NO_WSS_MIXER;
+       if (pss_mixer) 
+       {
+               if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION,
+                       "PSS-SPEAKERS and AD1848 (through MSS audio codec)",
+                       &pss_mixer_operations,
+                       sizeof (struct mixer_operations),
+                       devc)) < 0) 
+               {
+                       printk(KERN_ERR "Could not install PSS mixer\n");
+                       return;
+               }
+       }
+       pss_mixer_reset(devc);
        attach_ms_sound(hw_config);     /* Slot 0 */
 
-       if (hw_config->slots[0] != -1)  /* The MSS driver installed itself */
+       if (hw_config->slots[0] != -1)
+       {
+               /* The MSS driver installed itself */
                audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations;
+               if (pss_mixer && (num_mixers == (my_mix + 2)))
+               {
+                       /* The MSS mixer installed */
+                       devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
+               }
+       }
 }
 
 void unload_pss(struct address_info *hw_config)
 {
+       release_region(hw_config->io_base, 0x10);
+       release_region(hw_config->io_base+0x10, 0x9);
 }
 
 void unload_pss_mpu(struct address_info *hw_config)
@@ -761,11 +1047,21 @@ struct address_info cfgmpu = { 0 /* mpu_io */, 0 /* mpu_irq */, 0, -1 };
 struct address_info cfgmss = { 0 /* mss_io */, 0 /* mss_irq */, 0 /* mss_dma */, -1 };
 
 MODULE_PARM(pss_io, "i");
+MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");
 MODULE_PARM(mss_io, "i");
+MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)");
 MODULE_PARM(mss_irq, "i");
+MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)");
 MODULE_PARM(mss_dma, "i");
+MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)");
 MODULE_PARM(mpu_io, "i");
+MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)");
 MODULE_PARM(mpu_irq, "i");
+MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)");
+MODULE_PARM(pss_mixer, "b");
+MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble synth volume). The mixer is not available on all PSS cards.");
+MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl");
+MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).\n");
 
 static int fw_load = 0;
 static int pssmpu = 0, pssmss = 0;
@@ -816,7 +1112,7 @@ int init_module(void)
 void cleanup_module(void)
 {
        if (fw_load && pss_synth)
-               kfree(pss_synth);
+               vfree(pss_synth);
        if (pssmss)
                unload_pss_mss(&cfgmss);
        if (pssmpu)
@@ -825,5 +1121,4 @@ void cleanup_module(void)
        SOUND_LOCK_END;
 }
 #endif
-
 #endif
index 431645165f12ca238952b9683e4636dfe1c48123..4567d3f5b934ecd325a2cc4e9a8bf910ad42e702 100644 (file)
@@ -47,6 +47,8 @@
 #define MDL_ES1868MIDI 14      /* MIDI port of ESS1868 */
 #define MDL_AEDSP      15      /* Audio Excel DSP 16 */
 
+#define SUBMDL_ALS007  42      /* ALS-007 differs from SB16 only in mixer */
+                               /* register assignment */
 /*
  * Config flags
  */
index bf3a8dbef9f1a57235859999e224c322e473ad72..f9465cfe50a302d8782c93f55cafa8f3ae062c45 100644 (file)
@@ -2,17 +2,22 @@
  * sound/sb_audio.c
  *
  * Audio routines for Sound Blaster compatible cards.
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
+ *
+ * Changes
+ *     Alan Cox        :       Formatting and clean ups
+ *
+ * Status
+ *     Mostly working. mmap bug still present (swaps channels)
  */
-#include <linux/config.h>
-
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #if defined(CONFIG_SBDSP) || defined(MODULE)
 #include "sb_mixer.h"
 #include "sb.h"
 
-static int
-sb_audio_open(int dev, int mode)
+static int sb_audio_open(int dev, int mode)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned long   flags;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned long flags;
 
        if (devc == NULL)
-         {
-                 printk("SB: Incomplete initialization\n");
+       {
+                 printk(KERN_ERR "SB: Incomplete initialization\n");
                  return -ENXIO;
-         }
+       }
        if (devc->caps & SB_NO_RECORDING && mode & OPEN_READ)
-         {
-                 printk("Notice: Recording is not possible with /dev/dsp%d\n", dev);
-                 if (mode == OPEN_READ)
-                         return -EPERM;
-         }
+       {
+               if (mode == OPEN_READ)
+                       return -EPERM;
+       }
        save_flags(flags);
        cli();
        if (devc->opened)
-         {
+       {
                  restore_flags(flags);
                  return -EBUSY;
-         }
+       }
        if (devc->dma16 != -1 && devc->dma16 != devc->dma8)
-         {
-                 if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit"))
-                   {
-                           restore_flags(flags);
-                           return -EBUSY;
-                   }
-         }
+       {
+               if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit"))
+               {
+                       restore_flags(flags);
+                       return -EBUSY;
+               }
+       }
        devc->opened = mode;
        restore_flags(flags);
 
        devc->irq_mode = IMODE_NONE;
        sb_dsp_reset(devc);
 
+       /* The ALS007 seems to require that the DSP be removed from the output */
+       /* in order for recording to be activated properly.  This is done by   */
+       /* setting the appropriate bits of the output control register 4ch to  */
+       /* zero.  This code assumes that the output control registers are not  */
+       /* used anywhere else and therefore the DSP bits are *always* ON for   */
+       /* output and OFF for sampling.                                        */
+
+       if (devc->submodel == SUBMDL_ALS007) 
+       {
+               if (mode & OPEN_READ) 
+                       sb_setmixer(devc,ALS007_OUTPUT_CTRL2,
+                               sb_getmixer(devc,ALS007_OUTPUT_CTRL2) & 0xf9);
+               else
+                       sb_setmixer(devc,ALS007_OUTPUT_CTRL2,
+                               sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06);
+       }
        return 0;
 }
 
-static void
-sb_audio_close(int dev)
+static void sb_audio_close(int dev)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
-       audio_devs[dev]->dmap_in->dma =
-           audio_devs[dev]->dmap_out->dma =
-           devc->dma8;
+       audio_devs[dev]->dmap_in->dma = audio_devs[dev]->dmap_out->dma = devc->dma8;
 
        if (devc->dma16 != -1 && devc->dma16 != devc->dma8)
                sound_close_dma(devc->dma16);
 
+       /* For ALS007, turn DSP output back on if closing the device for read */
+       
+       if ((devc->submodel == SUBMDL_ALS007) && (devc->opened & OPEN_READ)) 
+       {
+               sb_setmixer(devc,ALS007_OUTPUT_CTRL2,
+                       sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06);
+       }
        devc->opened = 0;
 }
 
-static void
-sb_set_output_parms(int dev, unsigned long buf, int nr_bytes,
+static void sb_set_output_parms(int dev, unsigned long buf, int nr_bytes,
                    int intrflag)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        devc->trg_buf = buf;
        devc->trg_bytes = nr_bytes;
@@ -88,10 +110,9 @@ sb_set_output_parms(int dev, unsigned long buf, int nr_bytes,
        devc->irq_mode = IMODE_OUTPUT;
 }
 
-static void
-sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag)
+static void sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        devc->trg_buf = buf;
        devc->trg_bytes = count;
@@ -103,13 +124,11 @@ sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag)
  * SB1.x compatible routines 
  */
 
-static void
-sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes,
-                      int intrflag)
+static void sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes, int intrflag)
 {
-       unsigned long   flags;
-       int             count = nr_bytes;
-       sb_devc        *devc = audio_devs[dev]->devc;
+       unsigned long flags;
+       int count = nr_bytes;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
 
@@ -122,21 +141,21 @@ sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes,
        save_flags(flags);
        cli();
        if (sb_dsp_command(devc, 0x14))         /* 8 bit DAC using DMA */
-         {
-                 sb_dsp_command(devc, (unsigned char) (count & 0xff));
-                 sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
-       } else
-               printk("SB: Unable to start DAC\n");
+       {
+               sb_dsp_command(devc, (unsigned char) (count & 0xff));
+               sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
+       }
+       else
+               printk(KERN_WARNING "soundblaster: Unable to start DAC\n");
        restore_flags(flags);
        devc->intr_active = 1;
 }
 
-static void
-sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
+static void sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
 {
-       unsigned long   flags;
-       int             count = nr_bytes;
-       sb_devc        *devc = audio_devs[dev]->devc;
+       unsigned long flags;
+       int count = nr_bytes;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        /*
         * Start a DMA input to the buffer pointed by dmaqtail
@@ -153,49 +172,47 @@ sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
        save_flags(flags);
        cli();
        if (sb_dsp_command(devc, 0x24))         /* 8 bit ADC using DMA */
-         {
-                 sb_dsp_command(devc, (unsigned char) (count & 0xff));
-                 sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
-       } else
-               printk("SB Error: Unable to start ADC\n");
+       {
+               sb_dsp_command(devc, (unsigned char) (count & 0xff));
+               sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
+       }
+       else
+               printk(KERN_ERR "soundblaster: Unable to start ADC\n");
        restore_flags(flags);
 
        devc->intr_active = 1;
 }
 
-static void
-sb1_audio_trigger(int dev, int bits)
+static void sb1_audio_trigger(int dev, int bits)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        bits &= devc->irq_mode;
 
        if (!bits)
                sb_dsp_command(devc, 0xd0);     /* Halt DMA */
        else
-         {
-                 switch (devc->irq_mode)
-                   {
-                   case IMODE_INPUT:
-                           sb1_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
-                                                 devc->trg_intrflag);
-                           break;
-
-                   case IMODE_OUTPUT:
-                           sb1_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
-                                                  devc->trg_intrflag);
-                           break;
-                   }
-         }
+       {
+               switch (devc->irq_mode)
+               {
+                       case IMODE_INPUT:
+                               sb1_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
+                                               devc->trg_intrflag);
+                               break;
 
+                       case IMODE_OUTPUT:
+                               sb1_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
+                                               devc->trg_intrflag);
+                               break;
+               }
+       }
        devc->trigger_bits = bits;
 }
 
-static int
-sb1_audio_prepare_for_input(int dev, int bsize, int bcount)
+static int sb1_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned long   flags;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -208,11 +225,10 @@ sb1_audio_prepare_for_input(int dev, int bsize, int bcount)
        return 0;
 }
 
-static int
-sb1_audio_prepare_for_output(int dev, int bsize, int bcount)
+static int sb1_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned long   flags;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -224,55 +240,48 @@ sb1_audio_prepare_for_output(int dev, int bsize, int bcount)
        return 0;
 }
 
-static int
-sb1_audio_set_speed(int dev, int speed)
+static int sb1_audio_set_speed(int dev, int speed)
 {
-       int             max_speed = 23000;
-       sb_devc        *devc = audio_devs[dev]->devc;
-       int             tmp;
+       int max_speed = 23000;
+       sb_devc *devc = audio_devs[dev]->devc;
+       int tmp;
 
        if (devc->opened & OPEN_READ)
                max_speed = 13000;
 
        if (speed > 0)
-         {
-                 if (speed < 4000)
-                         speed = 4000;
-
-                 if (speed > max_speed)
-                         speed = max_speed;
+       {
+               if (speed < 4000)
+                       speed = 4000;
 
-                 devc->tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
+               if (speed > max_speed)
+                       speed = max_speed;
 
-                 tmp = 256 - devc->tconst;
-                 speed = (1000000 + tmp / 2) / tmp;
+               devc->tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
+               tmp = 256 - devc->tconst;
+               speed = (1000000 + tmp / 2) / tmp;
 
-                 devc->speed = speed;
-         }
+               devc->speed = speed;
+       }
        return devc->speed;
 }
 
-static short
-sb1_audio_set_channels(int dev, short channels)
+static short sb1_audio_set_channels(int dev, short channels)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-
+       sb_devc *devc = audio_devs[dev]->devc;
        return devc->channels = 1;
 }
 
-static unsigned int
-sb1_audio_set_bits(int dev, unsigned int bits)
+static unsigned int sb1_audio_set_bits(int dev, unsigned int bits)
 {
        sb_devc        *devc = audio_devs[dev]->devc;
-
        return devc->bits = 8;
 }
 
-static void
-sb1_audio_halt_xfer(int dev)
+static void sb1_audio_halt_xfer(int dev)
 {
-       unsigned long   flags;
-       sb_devc        *devc = audio_devs[dev]->devc;
+       unsigned long flags;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        save_flags(flags);
        cli();
@@ -284,14 +293,13 @@ sb1_audio_halt_xfer(int dev)
  * SB 2.0 and SB 2.01 compatible routines
  */
 
-static void
-sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes,
+static void sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes,
                        int intrflag)
 {
-       unsigned long   flags;
-       int             count = nr_bytes;
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned char   cmd;
+       unsigned long flags;
+       int count = nr_bytes;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned char cmd;
 
        /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
 
@@ -304,31 +312,30 @@ sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes,
        save_flags(flags);
        cli();
        if (sb_dsp_command(devc, 0x48))         /* DSP Block size */
-         {
-                 sb_dsp_command(devc, (unsigned char) (count & 0xff));
-                 sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
-
-                 if (devc->speed * devc->channels <= 23000)
-                         cmd = 0x1c;   /* 8 bit PCM output */
-                 else
-                         cmd = 0x90;   /* 8 bit high speed PCM output (SB2.01/Pro) */
+       {
+               sb_dsp_command(devc, (unsigned char) (count & 0xff));
+               sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
 
-                 if (!sb_dsp_command(devc, cmd))
-                         printk("SB: Unable to start DAC\n");
+               if (devc->speed * devc->channels <= 23000)
+                       cmd = 0x1c;     /* 8 bit PCM output */
+               else
+                       cmd = 0x90;     /* 8 bit high speed PCM output (SB2.01/Pro) */
 
-       } else
-               printk("SB: Unable to start DAC\n");
+               if (!sb_dsp_command(devc, cmd))
+                       printk(KERN_ERR "soundblaster: Unable to start DAC\n");
+       }
+       else
+               printk(KERN_ERR "soundblaster: Unable to start DAC\n");
        restore_flags(flags);
        devc->intr_active = 1;
 }
 
-static void
-sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
+static void sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
 {
-       unsigned long   flags;
-       int             count = nr_bytes;
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned char   cmd;
+       unsigned long flags;
+       int count = nr_bytes;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned char cmd;
 
        /*
         * Start a DMA input to the buffer pointed by dmaqtail
@@ -345,49 +352,46 @@ sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
        save_flags(flags);
        cli();
        if (sb_dsp_command(devc, 0x48))         /* DSP Block size */
-         {
-                 sb_dsp_command(devc, (unsigned char) (count & 0xff));
-                 sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
-
-                 if (devc->speed * devc->channels <= (devc->major == 3 ? 23000 : 13000))
-                         cmd = 0x2c;   /* 8 bit PCM input */
-                 else
-                         cmd = 0x98;   /* 8 bit high speed PCM input (SB2.01/Pro) */
-
-                 if (!sb_dsp_command(devc, cmd))
-                         printk("SB: Unable to start ADC\n");
-       } else
-               printk("SB Error: Unable to start ADC\n");
-       restore_flags(flags);
+       {
+               sb_dsp_command(devc, (unsigned char) (count & 0xff));
+               sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff));
 
+               if (devc->speed * devc->channels <= (devc->major == 3 ? 23000 : 13000))
+                       cmd = 0x2c;     /* 8 bit PCM input */
+               else
+                       cmd = 0x98;     /* 8 bit high speed PCM input (SB2.01/Pro) */
+
+               if (!sb_dsp_command(devc, cmd))
+                       printk(KERN_ERR "soundblaster: Unable to start ADC\n");
+       }
+       else
+               printk(KERN_ERR "soundblaster: Unable to start ADC\n");
+       restore_flags(flags);
        devc->intr_active = 1;
 }
 
-static void
-sb20_audio_trigger(int dev, int bits)
+static void sb20_audio_trigger(int dev, int bits)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-
+       sb_devc *devc = audio_devs[dev]->devc;
        bits &= devc->irq_mode;
 
        if (!bits)
                sb_dsp_command(devc, 0xd0);     /* Halt DMA */
        else
-         {
-                 switch (devc->irq_mode)
-                   {
-                   case IMODE_INPUT:
-                           sb20_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
-                                                  devc->trg_intrflag);
-                           break;
+       {
+               switch (devc->irq_mode)
+               {
+                       case IMODE_INPUT:
+                               sb20_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
+                                               devc->trg_intrflag);
+                               break;
 
-                   case IMODE_OUTPUT:
-                           sb20_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
-                                                   devc->trg_intrflag);
+                       case IMODE_OUTPUT:
+                               sb20_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
+                                               devc->trg_intrflag);
                            break;
-                   }
-         }
-
+               }
+       }
        devc->trigger_bits = bits;
 }
 
@@ -395,32 +399,26 @@ sb20_audio_trigger(int dev, int bits)
  * SB2.01 specific speed setup
  */
 
-static int
-sb201_audio_set_speed(int dev, int speed)
+static int sb201_audio_set_speed(int dev, int speed)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-       int             tmp;
-       int             s = speed * devc->channels;
+       sb_devc *devc = audio_devs[dev]->devc;
+       int tmp;
+       int s = speed * devc->channels;
 
        if (speed > 0)
-         {
-                 if (speed < 4000)
-                         speed = 4000;
-
-                 if (speed > 44100)
-                         speed = 44100;
-
-                 if (devc->opened & OPEN_READ && speed > 15000)
-                         speed = 15000;
-
-                 devc->tconst = ((65536 - ((256000000 + s / 2) /
-                                           s)) >> 8) & 0xff;
-
-                 tmp = 256 - devc->tconst;
-                 speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
+       {
+               if (speed < 4000)
+                       speed = 4000;
+               if (speed > 44100)
+                       speed = 44100;
+               if (devc->opened & OPEN_READ && speed > 15000)
+                       speed = 15000;
+               devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff;
+               tmp = 256 - devc->tconst;
+               speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
 
-                 devc->speed = speed;
-         }
+               devc->speed = speed;
+       }
        return devc->speed;
 }
 
@@ -428,17 +426,15 @@ sb201_audio_set_speed(int dev, int speed)
  * SB Pro specific routines
  */
 
-static int
-sbpro_audio_prepare_for_input(int dev, int bsize, int bcount)
+static int sbpro_audio_prepare_for_input(int dev, int bsize, int bcount)
 {                              /* For SB Pro and Jazz16 */
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned long   flags;
-       unsigned char   bits = 0;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned long flags;
+       unsigned char bits = 0;
 
        if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)
-               audio_devs[dev]->dmap_out->dma =
-                   audio_devs[dev]->dmap_in->dma =
-                   devc->bits == 16 ? devc->dma16 : devc->dma8;
+               audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma =
+                       devc->bits == 16 ? devc->dma16 : devc->dma8;
 
        if (devc->model == MDL_JAZZ || devc->model == MDL_SMW)
                if (devc->bits == AFMT_S16_LE)
@@ -459,18 +455,15 @@ sbpro_audio_prepare_for_input(int dev, int bsize, int bcount)
        return 0;
 }
 
-static int
-sbpro_audio_prepare_for_output(int dev, int bsize, int bcount)
+static int sbpro_audio_prepare_for_output(int dev, int bsize, int bcount)
 {                              /* For SB Pro and Jazz16 */
-       sb_devc        *devc = audio_devs[dev]->devc;
-       unsigned long   flags;
-       unsigned char   tmp;
-       unsigned char   bits = 0;
+       sb_devc *devc = audio_devs[dev]->devc;
+       unsigned long flags;
+       unsigned char tmp;
+       unsigned char bits = 0;
 
        if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)
-               audio_devs[dev]->dmap_out->dma =
-                   audio_devs[dev]->dmap_in->dma =
-                   devc->bits == 16 ? devc->dma16 : devc->dma8;
+               audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = devc->bits == 16 ? devc->dma16 : devc->dma8;
        if (devc->model == MDL_SBPRO)
                sb_mixer_set_stereo(devc, devc->channels == 2);
 
@@ -481,92 +474,83 @@ sbpro_audio_prepare_for_output(int dev, int bsize, int bcount)
        sb_dsp_command(devc, DSP_CMD_SPKON);
 
        if (devc->model == MDL_JAZZ || devc->model == MDL_SMW)
-         {
-                 if (devc->bits == AFMT_S16_LE)
-                         bits = 0x04;  /* 16 bit mode */
-
-                 if (devc->channels == 1)
-                         sb_dsp_command(devc, 0xa0 | bits);    /* Mono output */
-                 else
-                         sb_dsp_command(devc, 0xa8 | bits);    /* Stereo output */
-       } else
-         {
-                 tmp = sb_getmixer(devc, 0x0e);
-                 if (devc->channels == 1)
-                         tmp &= ~0x02;
-                 else
-                         tmp |= 0x02;
-                 sb_setmixer(devc, 0x0e, tmp);
-         }
+       {
+               if (devc->bits == AFMT_S16_LE)
+                       bits = 0x04;    /* 16 bit mode */
+
+               if (devc->channels == 1)
+                       sb_dsp_command(devc, 0xa0 | bits);      /* Mono output */
+               else
+                       sb_dsp_command(devc, 0xa8 | bits);      /* Stereo output */
+       }
+       else
+       {
+               tmp = sb_getmixer(devc, 0x0e);
+               if (devc->channels == 1)
+                       tmp &= ~0x02;
+               else
+                       tmp |= 0x02;
+               sb_setmixer(devc, 0x0e, tmp);
+       }
        restore_flags(flags);
        devc->trigger_bits = 0;
        return 0;
 }
 
-static int
-sbpro_audio_set_speed(int dev, int speed)
+static int sbpro_audio_set_speed(int dev, int speed)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        if (speed > 0)
-         {
-                 if (speed < 4000)
-                         speed = 4000;
-
-                 if (speed > 44100)
-                         speed = 44100;
-
-                 if (devc->channels > 1 && speed > 22050)
-                         speed = 22050;
-
-                 sb201_audio_set_speed(dev, speed);
-         }
+       {
+               if (speed < 4000)
+                       speed = 4000;
+               if (speed > 44100)
+                       speed = 44100;
+               if (devc->channels > 1 && speed > 22050)
+                       speed = 22050;
+               sb201_audio_set_speed(dev, speed);
+       }
        return devc->speed;
 }
 
-static short
-sbpro_audio_set_channels(int dev, short channels)
+static short sbpro_audio_set_channels(int dev, short channels)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        if (channels == 1 || channels == 2)
+       {
                if (channels != devc->channels)
-                 {
-                         devc->channels = channels;
-                         if (devc->model == MDL_SBPRO && devc->channels == 2)
-                           {
-                                   if (devc->speed > 22050)
-                                           printk("OSS: Application error. Wrong ioctl call order.\n");
-                                   sbpro_audio_set_speed(dev, devc->speed);
-                           }
-                 }
+               {
+                       devc->channels = channels;
+                       if (devc->model == MDL_SBPRO && devc->channels == 2)
+                               sbpro_audio_set_speed(dev, devc->speed);
+               }
+       }
        return devc->channels;
 }
 
-static int
-jazz16_audio_set_speed(int dev, int speed)
+static int jazz16_audio_set_speed(int dev, int speed)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        if (speed > 0)
-         {
-                 int             tmp;
-                 int             s = speed * devc->channels;
-
-                 if (speed < 5000)
-                         speed = 4000;
+       {
+               int tmp;
+               int s = speed * devc->channels;
 
-                 if (speed > 44100)
-                         speed = 44100;
+               if (speed < 5000)
+                       speed = 5000;
+               if (speed > 44100)
+                       speed = 44100;
 
-                 devc->tconst = ((65536 - ((256000000 + s / 2) /
-                                           s)) >> 8) & 0xff;
+               devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff;
 
-                 tmp = 256 - devc->tconst;
-                 speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
+               tmp = 256 - devc->tconst;
+               speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
 
-                 devc->speed = speed;
-         }
+               devc->speed = speed;
+       }
        return devc->speed;
 }
 
@@ -574,124 +558,123 @@ jazz16_audio_set_speed(int dev, int speed)
  * ESS specific routines
  */
 
-static int
-ess_audio_set_speed(int dev, int speed)
+static int ess_audio_set_speed(int dev, int speed)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-       int             divider;
+       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;
-         }
+       {
+               if (speed < 5000)
+                       speed = 5000;
+               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)
+static void ess_speed(sb_devc * devc)
 {
-       int             divider;
-       unsigned char   bits = 0;
-       int             speed = devc->speed;
+       int divider;
+       unsigned char bits = 0;
+       int speed = devc->speed;
 
        if (speed < 4000)
                speed = 4000;
        else if (speed > 48000)
                speed = 48000;
-
+       
        if (speed > 22000)
-         {
-                 bits = 0x80;
-                 divider = 256 - (795500 + speed / 2) / speed;
-       } else
-         {
-                 divider = 128 - (397700 + speed / 2) / speed;
-         }
+       {
+               bits = 0x80;
+               divider = 256 - (795500 + speed / 2) / speed;
+       }
+       else
+       {
+               divider = 128 - (397700 + speed / 2) / speed;
+       }
 
        bits |= (unsigned char) divider;
        ess_write(devc, 0xa1, bits);
 
-/*
- * Set filter divider register
- */
+       /*
       * Set filter divider register
       */
 
        speed = (speed * 9) / 20;       /* Set filter roll-off to 90% of speed/2 */
        divider = 256 - 7160000 / (speed * 82);
        ess_write(devc, 0xa2, divider);
-
        return;
 }
 
-static int
-ess_audio_prepare_for_input(int dev, int bsize, int bcount)
+static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
-
+       sb_devc *devc = audio_devs[dev]->devc;
        ess_speed(devc);
        sb_dsp_command(devc, DSP_CMD_SPKOFF);
 
        ess_write(devc, 0xb8, 0x0e);    /* Auto init DMA mode */
-       ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) |
-                 (3 - devc->channels));        /* Mono/stereo */
+       ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels));   /* Mono/stereo */
        ess_write(devc, 0xb9, 2);       /* Demand mode (4 bytes/DMA request) */
 
        if (devc->channels == 1)
-         {
-                 if (devc->bits == AFMT_U8)
-                   {           /* 8 bit mono */
-                           ess_write(devc, 0xb7, 0x51);
-                           ess_write(devc, 0xb7, 0xd0);
-                 } else
-                   {           /* 16 bit mono */
-                           ess_write(devc, 0xb7, 0x71);
-                           ess_write(devc, 0xb7, 0xf4);
-                   }
-       } else
-         {                     /* Stereo */
-                 if (devc->bits == AFMT_U8)
-                   {           /* 8 bit stereo */
-                           ess_write(devc, 0xb7, 0x51);
-                           ess_write(devc, 0xb7, 0x98);
-                 } else
-                   {           /* 16 bit stereo */
-                           ess_write(devc, 0xb7, 0x71);
-                           ess_write(devc, 0xb7, 0xbc);
-                   }
-         }
-
+       {
+               if (devc->bits == AFMT_U8)
+               {       
+                       /* 8 bit mono */
+                       ess_write(devc, 0xb7, 0x51);
+                       ess_write(devc, 0xb7, 0xd0);
+               }
+               else
+               {
+                       /* 16 bit mono */
+                       ess_write(devc, 0xb7, 0x71);
+                       ess_write(devc, 0xb7, 0xf4);
+               }
+       }
+       else
+       {       
+               /* Stereo */
+               if (devc->bits == AFMT_U8)
+               {
+                       /* 8 bit stereo */
+                       ess_write(devc, 0xb7, 0x51);
+                       ess_write(devc, 0xb7, 0x98);
+               }
+               else
+               {       
+                       /* 16 bit stereo */
+                       ess_write(devc, 0xb7, 0x71);
+                       ess_write(devc, 0xb7, 0xbc);
+               }
+       }
        ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
        ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
-
        devc->trigger_bits = 0;
        return 0;
 }
 
 static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        sb_dsp_reset(devc);
        ess_speed(devc);
 
        ess_write(devc, 0xb8, 4);       /* Auto init DMA mode */
-       ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) |
-                 (3 - devc->channels));        /* Mono/stereo */
+       ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels));   /* Mono/stereo */
        ess_write(devc, 0xb9, 2);       /* Demand mode (4 bytes/request) */
 
        if (devc->channels == 1)
@@ -701,7 +684,8 @@ static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
                        ess_write(devc, 0xb6, 0x80);
                        ess_write(devc, 0xb7, 0x51);
                        ess_write(devc, 0xb7, 0xd0);
-                 } else
+               }
+               else
                {       /* 16 bit mono */
                        ess_write(devc, 0xb6, 0x00);
                        ess_write(devc, 0xb7, 0x71);
@@ -733,11 +717,11 @@ static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
 }
 
 static void ess_audio_output_block(int dev, unsigned long buf, int nr_bytes,
-                      int intrflag)
+                       int intrflag)
 {
-       int             count = nr_bytes;
-       sb_devc        *devc = audio_devs[dev]->devc;
-       short           c = -nr_bytes;
+       int count = nr_bytes;
+       sb_devc *devc = audio_devs[dev]->devc;
+       short c = -nr_bytes;
 
        /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
 
@@ -756,9 +740,9 @@ static void ess_audio_output_block(int dev, unsigned long buf, int nr_bytes,
 
 static void ess_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
 {
-       int             count = nr_bytes;
-       sb_devc        *devc = audio_devs[dev]->devc;
-       short           c = -nr_bytes;
+       int count = nr_bytes;
+       sb_devc *devc = audio_devs[dev]->devc;
+       short c = -nr_bytes;
 
        /*
         * Start a DMA input to the buffer pointed by dmaqtail
@@ -781,7 +765,7 @@ static void ess_audio_start_input(int dev, unsigned long buf, int nr_bytes, int
 
 static void ess_audio_trigger(int dev, int bits)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        bits &= devc->irq_mode;
 
@@ -812,7 +796,7 @@ static void ess_audio_trigger(int dev, int bits)
 
 static int sb16_audio_set_speed(int dev, int speed)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        if (speed > 0)
        {
@@ -829,7 +813,7 @@ static int sb16_audio_set_speed(int dev, int speed)
 
 static unsigned int sb16_audio_set_bits(int dev, unsigned int bits)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        if (bits != 0)
        {
@@ -844,7 +828,7 @@ static unsigned int sb16_audio_set_bits(int dev, unsigned int bits)
 
 static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
        audio_devs[dev]->dmap_out->dma =
            audio_devs[dev]->dmap_in->dma =
@@ -856,11 +840,10 @@ static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount)
 
 static int sb16_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
-       sb_devc        *devc = audio_devs[dev]->devc;
+       sb_devc *devc = audio_devs[dev]->devc;
 
-       audio_devs[dev]->dmap_out->dma =
-           audio_devs[dev]->dmap_in->dma =
-           devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8;
+       audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma =
+                       devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8;
 
        devc->trigger_bits = 0;
        return 0;
@@ -1098,8 +1081,8 @@ static struct audio_driver ess_audio_driver =     /* ESS ES688/1688 */
 
 void sb_audio_init(sb_devc * devc, char *name)
 {
-       int             audio_flags = 0;
-       int             format_mask = AFMT_U8;
+       int audio_flags = 0;
+       int format_mask = AFMT_U8;
 
        struct audio_driver *driver = &sb1_audio_driver;
 
@@ -1151,14 +1134,9 @@ void sb_audio_init(sb_devc * devc, char *name)
        }
 
        if ((devc->my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
-                                               name,
-                                               driver,
-                                               sizeof(struct audio_driver),
-                                               audio_flags,
-                                               format_mask,
-                                               devc,
-                                               devc->dma8,
-                                               devc->dma8)) < 0)
+                               name,driver, sizeof(struct audio_driver),
+                               audio_flags, format_mask, devc,
+                               devc->dma8, devc->dma8)) < 0)
        {
                  printk(KERN_ERR "sb: unable to install audio.\n");
                  return;
index 941422c3f746532c037f0e9b238f06bbd579fb4c..ddf863372b25b60a9ecea55217ba4a3f99cdc30f 100644 (file)
@@ -2,18 +2,18 @@
  * sound/sb_card.c
  *
  * Detection routine for the Sound Blaster cards.
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
+
 #include <linux/config.h>
 #include <linux/module.h>
 
-
 #include "sound_config.h"
 #include "soundmodule.h"
 
 #include "sb_mixer.h"
 #include "sb.h"
 
-void
-attach_sb_card(struct address_info *hw_config)
+void attach_sb_card(struct address_info *hw_config)
 {
 #if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
        sb_dsp_init(hw_config);
 #endif
 }
 
-int
-probe_sb(struct address_info *hw_config)
+int probe_sb(struct address_info *hw_config)
 {
        if (check_region(hw_config->io_base, 16))
        {
-               printk("\n\nsb_card.c: I/O port %x is already in use\n\n", hw_config->io_base);
+               printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
                return 0;
        }
        return sb_dsp_detect(hw_config);
 }
 
-void
-unload_sb(struct address_info *hw_config)
+void unload_sb(struct address_info *hw_config)
 {
        sb_dsp_unload(hw_config);
 }
 
+int sb_be_quiet=0;
+
 #ifdef MODULE
 
 static struct address_info config;
@@ -58,18 +57,17 @@ static struct address_info config_mpu;
  *      to the 8bit channel.
  */
 
-int             mpu_io = 0;
-int             io = -1;
-int             irq = -1;
-int             dma = -1;
-int             dma16 = -1;    /* Set this for modules that need it */
-int             type = 0;      /* Can set this to a specific card type */
-int             mad16 = 0;     /* Set mad16=1 to load this as support for mad16 */
-int             trix = 0;      /* Set trix=1 to load this as support for trix */
-int             pas2 = 0;      /* Set pas2=1 to load this as support for pas2 */
-int             sm_games = 0;  /* Mixer - see sb_mixer.c */
-int             acer = 0;      /* Do acer notebook init */
-int            mwave_bug = 0;  /* Using the dreadful mwave sb emulation */
+int mpu_io = 0;
+int io = -1;
+int irq = -1;
+int dma = -1;
+int dma16 = -1;        /* Set this for modules that need it */
+int type = 0;  /* Can set this to a specific card type */
+int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */
+int trix = 0;  /* Set trix=1 to load this as support for trix */
+int pas2 = 0;  /* Set pas2=1 to load this as support for pas2 */
+int sm_games = 0;      /* Mixer - see sb_mixer.c */
+int acer = 0;  /* Do acer notebook init */
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
@@ -81,7 +79,6 @@ MODULE_PARM(mad16, "i");
 MODULE_PARM(trix, "i");
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
-MODULE_PARM(mwave_bug, "i");
 
 static int sbmpu = 0;
 
@@ -124,7 +121,7 @@ int init_module(void)
 void cleanup_module(void)
 {
        if (smw_free)
-               kfree(smw_free);
+               vfree(smw_free);
        if (!mad16 && !trix && !pas2)
                unload_sb(&config);
        if (sbmpu)
@@ -144,11 +141,6 @@ int             acer = 1;
 #else
 int             acer = 0;
 #endif
-#ifdef CONFIG_SB_MWAVE
-int            mwave_bug = 1;
-#else
-int            mwave_bug = 0;
-#endif
 #endif
 #endif
 
@@ -159,3 +151,4 @@ EXPORT_SYMBOL(sb_dsp_disable_midi);
 EXPORT_SYMBOL(attach_sb_card);
 EXPORT_SYMBOL(probe_sb);
 EXPORT_SYMBOL(unload_sb);
+EXPORT_SYMBOL(sb_be_quiet);
index fcdcfcf2c9d5ab55a46debcc3a09b980e3d1a154..d82c9379fb8d8c8ae4dfa80b54dea67e18d2ec96 100644 (file)
@@ -2,17 +2,18 @@
  * sound/sb_common.c
  *
  * Common routines for Sound Blaster compatible cards.
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
+
 #include <linux/config.h>
 #include <linux/delay.h>
-
+#include <asm/init.h>
 
 #include "sound_config.h"
 #include "sound_firmware.h"
 
 static sb_devc *detected_devc = NULL;  /* For communication from probe to init */
 static sb_devc *last_devc = NULL;      /* For MPU401 initialization */
+
 static unsigned char jazz_irq_bits[] = {
        0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6
 };
+
 static unsigned char jazz_dma_bits[] = {
        0, 1, 0, 2, 0, 3, 0, 4
 };
@@ -39,7 +42,7 @@ static unsigned char jazz_dma_bits[] = {
  * Jazz16 chipset specific control variables
  */
 
-static int      jazz16_base = 0;       /* Not detected */
+static int jazz16_base = 0;            /* Not detected */
 static unsigned char jazz16_bits = 0;  /* I/O relocation bits */
 
 /*
@@ -57,10 +60,11 @@ static int      smw_ucodeLen = 0;
 
 int sb_dsp_command(sb_devc * devc, unsigned char val)
 {
-       int             i;
-       unsigned long   limit;
+       int i;
+       unsigned long limit;
 
        limit = jiffies + HZ / 10;      /* Timeout */
+       
        /*
         * 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
@@ -69,7 +73,7 @@ int sb_dsp_command(sb_devc * devc, unsigned char val)
         * loops.
         */
 
-       for (i = 0; i < 500000 && jiffies < limit; i++)
+       for (i = 0; i < 500000 && (limit-jiffies)>0; i++)
        {
                if ((inb(DSP_STATUS) & 0x80) == 0)
                {
@@ -77,20 +81,19 @@ int sb_dsp_command(sb_devc * devc, unsigned char val)
                        return 1;
                }
        }
-
-       printk(KERN_WARNING "Sound Blaster: DSP Command(%x) Timeout.\n", val);
+       printk(KERN_WARNING "soundblaster: DSP Command(%x) Timeout.\n", val);
        return 0;
 }
 
 static int sb_dsp_get_byte(sb_devc * devc)
 {
-       int             i;
+       int i;
 
        for (i = 1000; i; i--)
+       {
                if (inb(DSP_DATA_AVAIL) & 0x80)
-               {
                        return inb(DSP_READ);
-               }
+       }
        return 0xffff;
 }
 
@@ -107,7 +110,6 @@ int ess_write(sb_devc * devc, unsigned char reg, unsigned char data)
 int ess_read(sb_devc * devc, unsigned char reg)
 {
 /* Read a byte from an extended mode register of ES1688 */
-
        if (!sb_dsp_command(devc, 0xc0))        /* Read register command */
                return -1;
 
@@ -239,7 +241,7 @@ static int sb16_set_dma_hw(sb_devc * devc)
 
        if (devc->dma8 != 0 && devc->dma8 != 1 && devc->dma8 != 3)
        {
-               printk(KERN_ERR "SB16: Invalid 8 bit DMA (%d)\n", devc->dma8);
+               printk(KERN_ERR "sb16: Invalid 8 bit DMA (%d)\n", devc->dma8);
                return 0;
        }
        bits = (1 << devc->dma8);
@@ -355,14 +357,12 @@ static int init_Jazz16(sb_devc * devc, struct address_info *hw_config)
        /*
         * OK so far. Now configure the IRQ and DMA channel used by the card.
         */
-       if (hw_config->irq < 1 || hw_config->irq > 15 ||
-           jazz_irq_bits[hw_config->irq] == 0)
+       if (hw_config->irq < 1 || hw_config->irq > 15 || jazz_irq_bits[hw_config->irq] == 0)
        {
                printk(KERN_ERR "Jazz16: Invalid interrupt (IRQ%d)\n", hw_config->irq);
                return 0;
        }
-       if (hw_config->dma < 0 || hw_config->dma > 3 ||
-           jazz_dma_bits[hw_config->dma] == 0)
+       if (hw_config->dma < 0 || hw_config->dma > 3 || jazz_dma_bits[hw_config->dma] == 0)
        {
                  printk(KERN_ERR "Jazz16: Invalid 8 bit DMA (DMA%d)\n", hw_config->dma);
                  return 0;
@@ -372,8 +372,7 @@ static int init_Jazz16(sb_devc * devc, struct address_info *hw_config)
                printk(KERN_ERR "Jazz16: No 16 bit DMA channel defined\n");
                return 0;
        }
-       if (hw_config->dma2 < 5 || hw_config->dma2 > 7 ||
-           jazz_dma_bits[hw_config->dma2] == 0)
+       if (hw_config->dma2 < 5 || hw_config->dma2 > 7 || jazz_dma_bits[hw_config->dma2] == 0)
        {
                printk(KERN_ERR "Jazz16: Invalid 16 bit DMA (DMA%d)\n", hw_config->dma2);
                return 0;
@@ -384,7 +383,7 @@ static int init_Jazz16(sb_devc * devc, struct address_info *hw_config)
                return 0;
 
        if (!sb_dsp_command(devc, jazz_dma_bits[hw_config->dma] |
-                           (jazz_dma_bits[hw_config->dma2] << 4)))
+                       (jazz_dma_bits[hw_config->dma2] << 4)))
                return 0;
 
        if (!sb_dsp_command(devc, jazz_irq_bits[hw_config->irq]))
@@ -683,11 +682,7 @@ int sb_dsp_detect(struct address_info *hw_config)
         */
 
 
-       detected_devc = (sb_devc *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(sb_devc)));
-       sound_mem_sizes[sound_nblocks] = sizeof(sb_devc);
-       if (sound_nblocks < 1024)
-               sound_nblocks++;;
-
+       detected_devc = (sb_devc *)kmalloc(sizeof(sb_devc), GFP_KERNEL);
        if (detected_devc == NULL)
        {
                printk(KERN_ERR "sb: Can't allocate memory for device information\n");
@@ -703,8 +698,8 @@ void sb_dsp_init(struct address_info *hw_config)
        sb_devc *devc;
        char name[100];
        extern int sb_be_quiet;
-       extern int mwave_bug;
-
+       int     mixer3c, mixer4c;
+       
 /*
  * Check if we had detected a SB device earlier
  */
@@ -769,7 +764,7 @@ void sb_dsp_init(struct address_info *hw_config)
                /* Skip IRQ detection if SMP (doesn't work) */
                devc->irq_ok = 1;
 #else
-               if ((devc->major == 4 && devc->minor <= 11 ) || mwave_bug )     /* Won't work */
+               if (devc->major == 4 && devc->minor <= 11 )     /* Won't work */
                        devc->irq_ok = 1;
                else
                {
@@ -819,7 +814,23 @@ void sb_dsp_init(struct address_info *hw_config)
 
                case 4:
                        devc->model = hw_config->card_subtype = MDL_SB16;
-                       if (hw_config->name == NULL)
+                       /*
+                        *      The ALS007 seems to return DSP version 4.2.  In addition it has 2
+                        *      output control registers (at 0x3c and 0x4c).  Both of these should
+                        *      be !=0 after a reset which forms the basis of the ALS007 test
+                        *      since a "standard" SoundBlaster does not have a register at 0x4c.
+                        */
+                       mixer3c = sb_getmixer(devc,0x3c);
+                       mixer4c = sb_getmixer(devc,0x4c);
+                       if ((devc->minor == 2) && (mixer3c != 0) && (mixer4c != 0)) 
+                       {
+                               sb_setmixer(devc,0x3c,0x1f);   /* Enable all inputs */
+                               sb_setmixer(devc,0x4c,0x1f);
+                               devc->submodel = SUBMDL_ALS007;
+                               if (hw_config->name == NULL)
+                                       hw_config->name = "Sound Blaster (ALS-007)";
+                       }
+                       else if (hw_config->name == NULL)
                                hw_config->name = "Sound Blaster 16";
 
                        if (hw_config->dma2 == -1)
@@ -885,15 +896,15 @@ void sb_dsp_init(struct address_info *hw_config)
                        printk(KERN_WARNING "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, "SoundBlaster16"))
-                       {
-                               printk(KERN_WARNING "SB: Can't allocate 16 bit DMA channel %d\n", devc->dma16);
-                       }
+                               printk(KERN_WARNING "soundblaster: Can't allocate 16 bit DMA channel %d\n", devc->dma16);
+               }
                sb_audio_init(devc, name);
        }
        else
        {
-               MDB(printk("sb: No audio devices found.\n"));
+               MDB(printk("soundblaster: No audio devices found.\n"));
        }
 }
 
@@ -932,6 +943,8 @@ void sb_dsp_unload(struct address_info *hw_config)
        }
        else
                release_region(hw_config->io_base, 16);
+       if(detected_devc)
+               kfree(detected_devc);
 }
 
 /*
@@ -940,7 +953,7 @@ void sb_dsp_unload(struct address_info *hw_config)
 
 void sb_setmixer(sb_devc * devc, unsigned int port, unsigned int value)
 {
-       unsigned long   flags;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -1318,5 +1331,4 @@ void attach_sbmpu(struct address_info *hw_config)
 {
 }
 #endif
-
 #endif
index b08f8d43f0a1c091fce9ca7bb10b6746dc396e18..f7c1c85a27af7788785143c903f6f1e2112a0176 100644 (file)
@@ -2,17 +2,16 @@
  * sound/sb_dsp.c
  *
  * The low level driver for the Sound Blaster DS chips.
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
-#include <linux/config.h>
-
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #ifdef CONFIG_SBDSP
  */
 
 
-static int
-sb_midi_open(int dev, int mode,
+static int sb_midi_open(int dev, int mode,
             void            (*input) (int dev, unsigned char data),
             void            (*output) (int dev)
 )
 {
-       sb_devc        *devc = midi_devs[dev]->devc;
-       unsigned long   flags;
+       sb_devc *devc = midi_devs[dev]->devc;
+       unsigned long flags;
 
        if (devc == NULL)
                return -ENXIO;
@@ -45,10 +43,10 @@ sb_midi_open(int dev, int mode,
        save_flags(flags);
        cli();
        if (devc->opened)
-         {
-                 restore_flags(flags);
-                 return -EBUSY;
-         }
+       {
+               restore_flags(flags);
+               return -EBUSY;
+       }
        devc->opened = 1;
        restore_flags(flags);
 
@@ -58,25 +56,24 @@ sb_midi_open(int dev, int mode,
        sb_dsp_reset(devc);
 
        if (!sb_dsp_command(devc, 0x35))        /* Start MIDI UART mode */
-         {
+       {
                  devc->opened = 0;
                  return -EIO;
-         }
+       }
        devc->intr_active = 1;
 
        if (mode & OPEN_READ)
-         {
-                 devc->input_opened = 1;
-                 devc->midi_input_intr = input;
-         }
+       {
+               devc->input_opened = 1;
+               devc->midi_input_intr = input;
+       }
        return 0;
 }
 
-static void
-sb_midi_close(int dev)
+static void sb_midi_close(int dev)
 {
-       sb_devc        *devc = midi_devs[dev]->devc;
-       unsigned long   flags;
+       sb_devc *devc = midi_devs[dev]->devc;
+       unsigned long flags;
 
        if (devc == NULL)
                return;
@@ -90,10 +87,9 @@ sb_midi_close(int dev)
        restore_flags(flags);
 }
 
-static int
-sb_midi_out(int dev, unsigned char midi_byte)
+static int sb_midi_out(int dev, unsigned char midi_byte)
 {
-       sb_devc        *devc = midi_devs[dev]->devc;
+       sb_devc *devc = midi_devs[dev]->devc;
 
        if (devc == NULL)
                return 1;
@@ -102,23 +98,21 @@ sb_midi_out(int dev, unsigned char midi_byte)
                return 1;
 
        if (!sb_dsp_command(devc, midi_byte))
-         {
-                 devc->midi_broken = 1;
-                 return 1;
-         }
+       {
+               devc->midi_broken = 1;
+               return 1;
+       }
        return 1;
 }
 
-static int
-sb_midi_start_read(int dev)
+static int sb_midi_start_read(int dev)
 {
        return 0;
 }
 
-static int
-sb_midi_end_read(int dev)
+static int sb_midi_end_read(int dev)
 {
-       sb_devc        *devc = midi_devs[dev]->devc;
+       sb_devc *devc = midi_devs[dev]->devc;
 
        if (devc == NULL)
                return -ENXIO;
@@ -128,14 +122,12 @@ sb_midi_end_read(int dev)
        return 0;
 }
 
-/* why -EPERM and not -EINVAL?? */
 static int sb_midi_ioctl(int dev, unsigned cmd, caddr_t arg)
 {
-        return -EPERM;
+        return -EINVAL;
 }
 
-void
-sb_midi_interrupt(sb_devc * devc)
+void sb_midi_interrupt(sb_devc * devc)
 {
        unsigned long   flags;
        unsigned char   data;
@@ -159,7 +151,9 @@ sb_midi_interrupt(sb_devc * devc)
 
 static struct midi_operations sb_midi_operations =
 {
-       {"Sound Blaster", 0, 0, SNDCARD_SB},
+       {
+               "Sound Blaster", 0, 0, SNDCARD_SB
+       },
        &std_midi_synth,
        {0},
        sb_midi_open,
@@ -174,10 +168,9 @@ static struct midi_operations sb_midi_operations =
        NULL
 };
 
-void
-sb_dsp_midi_init(sb_devc * devc)
+void sb_dsp_midi_init(sb_devc * devc)
 {
-       int             dev;
+       int dev;
 
        if (devc->model < 2)    /* No MIDI support for SB 1.x */
                return;
@@ -185,45 +178,34 @@ sb_dsp_midi_init(sb_devc * devc)
        dev = sound_alloc_mididev();
 
        if (dev == -1)
-         {
-                 printk("Sound: Too many midi devices detected\n");
-                 return;
-         }
+       {
+               printk("Sound: Too many midi devices detected\n");
+               return;
+       }
        std_midi_synth.midi_dev = dev;
        devc->my_mididev = dev;
-
        std_midi_synth.midi_dev = devc->my_mididev = dev;
-
-
-       midi_devs[dev] = (struct midi_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct midi_operations)));
-       sound_mem_sizes[sound_nblocks] = sizeof(struct midi_operations);
-
-       if (sound_nblocks < 1024)
-               sound_nblocks++;;
+       midi_devs[dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
        if (midi_devs[dev] == NULL)
-         {
-                 printk(KERN_WARNING "sb MIDI: Failed to allocate memory\n");
-                 sound_unload_mididev(dev);
+       {
+               printk(KERN_WARNING "soundblaster: Failed to allocate MIDI memory.\n");
+               sound_unload_mididev(dev);
                  return;
-         }
+       }
        memcpy((char *) midi_devs[dev], (char *) &sb_midi_operations,
               sizeof(struct midi_operations));
 
        midi_devs[dev]->devc = devc;
 
 
-       midi_devs[dev]->converter = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct synth_operations)));
-       sound_mem_sizes[sound_nblocks] = sizeof(struct synth_operations);
-
-       if (sound_nblocks < 1024)
-               sound_nblocks++;;
-
+       midi_devs[dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL);
        if (midi_devs[dev]->converter == NULL)
-         {
-                 printk(KERN_WARNING "sb MIDI: Failed to allocate memory\n");
+       {
+                 printk(KERN_WARNING "soundblaster: Failed to allocate MIDI memory.\n");
+                 kfree(midi_devs[dev]);
                  sound_unload_mididev(dev);
                  return;
-         }
+       }
        memcpy((char *) midi_devs[dev]->converter, (char *) &std_midi_synth,
               sizeof(struct synth_operations));
 
index 2d494a0ddc4849c5b8a903ed993a6f3da7aa3aa3..5f06807ce22c17cf4eca1a7d47b87b08f4fb717b 100644 (file)
  * 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.
- */
-/*
+ *
+ *
  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
  */
-#include <linux/config.h>
-
 
+#include <linux/config.h>
 #include "sound_config.h"
 
 #if defined(CONFIG_SBDSP) || defined(MODULE)
@@ -29,25 +28,22 @@ static int      sbmixnum = 1;
 
 static void     sb_mixer_reset(sb_devc * devc);
 
-void
-sb_mixer_set_stereo(sb_devc * devc, int mode)
+void sb_mixer_set_stereo(sb_devc * devc, int mode)
 {
        sb_setmixer(devc, OUT_FILTER, ((sb_getmixer(devc, OUT_FILTER) & ~STEREO_DAC)
                                       | (mode ? STEREO_DAC : MONO_DAC)));
 }
 
-static int
-detect_mixer(sb_devc * devc)
+static int detect_mixer(sb_devc * devc)
 {
        /* Just trust the mixer is there */
        return 1;
 }
 
-static void
-change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
+static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
 {
-       unsigned char   mask;
-       int             shift;
+       unsigned char mask;
+       int shift;
 
        mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1;
        newval = (int) ((newval * mask) + 50) / 100;    /* Scale */
@@ -58,19 +54,16 @@ change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
        *regval |= (newval & mask) << shift;    /* Set the new value */
 }
 
-static int
-sb_mixer_get(sb_devc * devc, int dev)
+static int sb_mixer_get(sb_devc * devc, int dev)
 {
        if (!((1 << dev) & devc->supported_devices))
                return -EINVAL;
-
        return devc->levels[dev];
 }
 
-void
-smw_mixer_init(sb_devc * devc)
+void smw_mixer_init(sb_devc * devc)
 {
-       int             i;
+       int i;
 
        sb_setmixer(devc, 0x00, 0x18);  /* Mute unused (Telephone) line */
        sb_setmixer(devc, 0x10, 0x38);  /* Config register 2 */
@@ -81,18 +74,15 @@ smw_mixer_init(sb_devc * devc)
                        devc->supported_devices |= (1 << i);
 
        devc->supported_rec_devices = devc->supported_devices &
-           ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM |
-             SOUND_MASK_VOLUME);
-
+               ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | SOUND_MASK_VOLUME);
        sb_mixer_reset(devc);
 }
 
-static int
-smw_mixer_set(sb_devc * devc, int dev, int value)
+static int smw_mixer_set(sb_devc * devc, int dev, int value)
 {
-       int             left = value & 0x000000ff;
-       int             right = (value & 0x0000ff00) >> 8;
-       int             reg, val;
+       int left = value & 0x000000ff;
+       int right = (value & 0x0000ff00) >> 8;
+       int reg, val;
 
        if (left > 100)
                left = 100;
@@ -106,46 +96,45 @@ smw_mixer_set(sb_devc * devc, int dev, int value)
                return -EINVAL;
 
        switch (dev)
-         {
-         case SOUND_MIXER_VOLUME:
-                 sb_setmixer(devc, 0x0b, 96 - (96 * left / 100));      /* 96=mute, 0=max */
-                 sb_setmixer(devc, 0x0c, 96 - (96 * right / 100));
-                 break;
-
-         case SOUND_MIXER_BASS:
-         case SOUND_MIXER_TREBLE:
-                 devc->levels[dev] = left | (right << 8);
-
-                 /* Set left bass and treble values */
-                 val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
-                 val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
-                 sb_setmixer(devc, 0x0d, val);
-
-                 /* Set right bass and treble values */
-                 val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
-                 val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
-                 sb_setmixer(devc, 0x0e, val);
-                 break;
-
-         default:
-                 reg = smw_mix_regs[dev];
-                 if (reg == 0)
-                         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);
-         }
+       {
+               case SOUND_MIXER_VOLUME:
+                       sb_setmixer(devc, 0x0b, 96 - (96 * left / 100));        /* 96=mute, 0=max */
+                       sb_setmixer(devc, 0x0c, 96 - (96 * right / 100));
+                       break;
+
+               case SOUND_MIXER_BASS:
+               case SOUND_MIXER_TREBLE:
+                       devc->levels[dev] = left | (right << 8);
+                       /* Set left bass and treble values */
+                       val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
+                       val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
+                       sb_setmixer(devc, 0x0d, val);
+
+                       /* Set right bass and treble values */
+                       val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
+                       val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
+                       sb_setmixer(devc, 0x0e, val);
+               
+                       break;
+
+               default:
+                       reg = smw_mix_regs[dev];
+                       if (reg == 0)
+                               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);
+       }
 
        devc->levels[dev] = left | (right << 8);
        return left | (right << 8);
 }
 
-static int
-sb_mixer_set(sb_devc * devc, int dev, int value)
+static int sb_mixer_set(sb_devc * devc, int dev, int value)
 {
-       int             left = value & 0x000000ff;
-       int             right = (value & 0x0000ff00) >> 8;
+       int left = value & 0x000000ff;
+       int right = (value & 0x0000ff00) >> 8;
 
-       int             regoffs;
+       int regoffs;
        unsigned char   val;
 
        if (devc->model == MDL_SMW)
@@ -177,21 +166,21 @@ sb_mixer_set(sb_devc * devc, int dev, int value)
        if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)    /*
                                                                 * Change register
                                                                 */
-         {
-                 sb_setmixer(devc, regoffs, val);      /*
+       {
+               sb_setmixer(devc, regoffs, val);        /*
                                                         * Save the old one
                                                         */
-                 regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
+               regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
 
-                 if (regoffs == 0)
-                         return left | (left << 8);    /*
+               if (regoffs == 0)
+                       return left | (left << 8);      /*
                                                         * Just left channel present
                                                         */
 
-                 val = sb_getmixer(devc, regoffs);     /*
-                                                          * Read the new one
+               val = sb_getmixer(devc, regoffs);       /*
+                                                        * Read the new one
                                                         */
-         }
+       }
        change_bits(devc, &val, dev, RIGHT_CHN, right);
 
        sb_setmixer(devc, regoffs, val);
@@ -200,86 +189,107 @@ sb_mixer_set(sb_devc * devc, int dev, int value)
        return left | (right << 8);
 }
 
-static void
-set_recsrc(sb_devc * devc, int src)
+static void set_recsrc(sb_devc * devc, int src)
 {
        sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7));
 }
 
-static int
-set_recmask(sb_devc * devc, int mask)
+static int set_recmask(sb_devc * devc, int mask)
 {
-       int             devmask, i;
-       unsigned char   regimageL, regimageR;
+       int devmask, i;
+       unsigned char  regimageL, regimageR;
 
        devmask = mask & devc->supported_rec_devices;
 
        switch (devc->model)
-         {
-         case MDL_SBPRO:
-         case MDL_ESS:
-         case MDL_JAZZ:
-         case MDL_SMW:
-
-                 if (devmask != SOUND_MASK_MIC &&
-                     devmask != SOUND_MASK_LINE &&
-                     devmask != SOUND_MASK_CD)
-                   {           /*
-                                * More than one devices selected. Drop the *
+       {
+               case MDL_SBPRO:
+               case MDL_ESS:
+               case MDL_JAZZ:
+               case MDL_SMW:
+
+                       if (devmask != SOUND_MASK_MIC &&
+                               devmask != SOUND_MASK_LINE &&
+                               devmask != SOUND_MASK_CD)
+                       {
+                               /*
+                                * More than one device selected. Drop the
                                 * previous selection
                                 */
-                           devmask &= ~devc->recmask;
-                   }
-                 if (devmask != SOUND_MASK_MIC &&
-                     devmask != SOUND_MASK_LINE &&
-                     devmask != SOUND_MASK_CD)
-                   {           /*
-                                * More than one devices selected. Default to
-                                * * mic
+                               devmask &= ~devc->recmask;
+                       }
+                       if (devmask != SOUND_MASK_MIC &&
+                               devmask != SOUND_MASK_LINE &&
+                               devmask != SOUND_MASK_CD)
+                       {
+                               /*
+                                * More than one device selected. Default to
+                                * mic
                                 */
-                           devmask = SOUND_MASK_MIC;
-                   }
-                 if (devmask ^ devc->recmask)  /*
-                                                  * Input source changed
-                                                */
-                   {
-                           switch (devmask)
-                             {
-
-                             case SOUND_MASK_MIC:
-                                     set_recsrc(devc, SRC__MIC);
-                                     break;
-
-                             case SOUND_MASK_LINE:
-                                     set_recsrc(devc, SRC__LINE);
-                                     break;
-
-                             case SOUND_MASK_CD:
-                                     set_recsrc(devc, SRC__CD);
-                                     break;
-
-                             default:
-                                     set_recsrc(devc, SRC__MIC);
-                             }
-                   }
-                 break;
-
-         case MDL_SB16:
-                 if (!devmask)
-                         devmask = SOUND_MASK_MIC;
-
-                 regimageL = regimageR = 0;
-                 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-                         if ((1 << i) & devmask)
-                           {
-                                   regimageL |= sb16_recmasks_L[i];
-                                   regimageR |= sb16_recmasks_R[i];
-                           }
-                 sb_setmixer(devc, SB16_IMASK_L, regimageL);
-                 sb_setmixer(devc, SB16_IMASK_R, regimageR);
-                 break;
-         }
-
+                               devmask = SOUND_MASK_MIC;
+                       }
+                       if (devmask ^ devc->recmask)    /*
+                                                        *      Input source changed
+                                                        */
+                       {
+                               switch (devmask)
+                               {
+                                       case SOUND_MASK_MIC:
+                                               set_recsrc(devc, SRC__MIC);
+                                               break;
+
+                                       case SOUND_MASK_LINE:
+                                               set_recsrc(devc, SRC__LINE);
+                                               break;
+
+                                       case SOUND_MASK_CD:
+                                               set_recsrc(devc, SRC__CD);
+                                               break;
+
+                                       default:
+                                               set_recsrc(devc, SRC__MIC);
+                               }
+                       }
+                       break;
+
+               case MDL_SB16:
+                       if (!devmask)
+                               devmask = SOUND_MASK_MIC;
+
+                       if (devc->submodel == SUBMDL_ALS007) 
+                       {
+                               switch (devmask) 
+                               {
+                                       case SOUND_MASK_LINE:
+                                               sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE);
+                                               break;
+                                       case SOUND_MASK_CD:
+                                               sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD);
+                                               break;
+                                       case SOUND_MASK_SYNTH:
+                                               sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH);
+                                               break;
+                                       default:           /* Also takes care of SOUND_MASK_MIC case */
+                                               sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC);
+                                               break;
+                               }
+                       }
+                       else
+                       {
+                               regimageL = regimageR = 0;
+                               for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+                               {
+                                       if ((1 << i) & devmask)
+                                       {
+                                               regimageL |= sb16_recmasks_L[i];
+                                               regimageR |= sb16_recmasks_R[i];
+                                       }
+                                       sb_setmixer (devc, SB16_IMASK_L, regimageL);
+                                       sb_setmixer (devc, SB16_IMASK_R, regimageR);
+                               }
+                       }
+                       break;
+       }
        devc->recmask = devmask;
        return devc->recmask;
 }
@@ -292,52 +302,57 @@ static int sb_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
        /*
         * Use ioctl(fd, SOUND_MIXER_PRIVATE1, &mode) to turn AGC off (0) or on (1).
         */
-       if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16) {
+       if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16) 
+       {
                if (get_user(val, (int *)arg))
                        return -EFAULT;
                sb_setmixer(devc, 0x43, (~val) & 0x01);
                return 0;
        }
-       if (((cmd >> 8) & 0xff) == 'M') {
-               if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
+       if (((cmd >> 8) & 0xff) == 'M') 
+       {
+               if (_SIOC_DIR(cmd) & _SIOC_WRITE) 
+               {
                        if (get_user(val, (int *)arg))
                                return -EFAULT;
-                       switch (cmd & 0xff) {
+                       switch (cmd & 0xff) 
+                       {
+                               case SOUND_MIXER_RECSRC:
+                                       ret = set_recmask(devc, val);
+                                       break;
+
+                               default:
+                                       ret = sb_mixer_set(devc, cmd & 0xff, val);
+                       }
+               }
+               else switch (cmd & 0xff) 
+               {
                        case SOUND_MIXER_RECSRC:
-                               ret = set_recmask(devc, val);
+                               ret = devc->recmask;
                                break;
-
-                       default:
-                               ret = sb_mixer_set(devc, cmd & 0xff, val);
-                       }
-                 } else
-                         switch (cmd & 0xff) {
-                         case SOUND_MIXER_RECSRC:
-                                 ret = devc->recmask;
-                                 break;
                                  
-                         case SOUND_MIXER_DEVMASK:
-                                 ret = devc->supported_devices;
-                                 break;
+                       case SOUND_MIXER_DEVMASK:
+                               ret = devc->supported_devices;
+                               break;
                                  
-                         case SOUND_MIXER_STEREODEVS:
-                                 ret = devc->supported_devices;
-                                 if (devc->model != MDL_JAZZ && devc->model != MDL_SMW)
-                                         ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
-                                 break;
+                       case SOUND_MIXER_STEREODEVS:
+                               ret = devc->supported_devices;
+                               if (devc->model != MDL_JAZZ && devc->model != MDL_SMW)
+                                       ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
+                               break;
                                  
-                         case SOUND_MIXER_RECMASK:
-                                 ret = devc->supported_rec_devices;
-                                 break;
+                       case SOUND_MIXER_RECMASK:
+                               ret = devc->supported_rec_devices;
+                               break;
                                  
-                         case SOUND_MIXER_CAPS:
-                                 ret = devc->mixer_caps;
-                                 break;
+                       case SOUND_MIXER_CAPS:
+                               ret = devc->mixer_caps;
+                               break;
                                    
-                         default:
-                                 ret = sb_mixer_get(devc, cmd & 0xff);
-                                 break;
-                         }
+                       default:
+                               ret = sb_mixer_get(devc, cmd & 0xff);
+                               break;
+               }
                return put_user(ret, (int *)arg); 
        } else
                return -EINVAL;
@@ -350,12 +365,18 @@ static struct mixer_operations sb_mixer_operations =
        sb_mixer_ioctl
 };
 
-static void
-sb_mixer_reset(sb_devc * devc)
+static struct mixer_operations als007_mixer_operations =
 {
-       char            name[32];
-       int             i;
-       extern int      sm_games;
+       "ALS007",
+       "Avance ALS-007",
+       sb_mixer_ioctl
+};
+
+static void sb_mixer_reset(sb_devc * devc)
+{
+       char name[32];
+       int i;
+       extern int sm_games;
 
        sprintf(name, "SB_%d", devc->sbmixnum);
 
@@ -366,15 +387,13 @@ sb_mixer_reset(sb_devc * devc)
 
        for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
                sb_mixer_set(devc, i, devc->levels[i]);
-
        set_recmask(devc, SOUND_MASK_MIC);
 }
 
-int
-sb_mixer_init(sb_devc * devc)
+int sb_mixer_init(sb_devc * devc)
 {
-       int             mixer_type = 0;
-       int             m;
+       int mixer_type = 0;
+       int m;
 
        devc->sbmixnum = sbmixnum++;
        devc->levels = NULL;
@@ -385,64 +404,69 @@ sb_mixer_init(sb_devc * devc)
                return 0;       /* No mixer. Why? */
 
        switch (devc->model)
-         {
-         case MDL_SBPRO:
-         case MDL_AZTECH:
-         case MDL_JAZZ:
-                 devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
-                 devc->supported_devices = SBPRO_MIXER_DEVICES;
-                 devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
-                 devc->iomap = &sbpro_mix;
-                 break;
-
-         case MDL_ESS:
-                 devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
-                 devc->supported_devices = ES688_MIXER_DEVICES;
-                 devc->supported_rec_devices = ES688_RECORDING_DEVICES;
-                 devc->iomap = &es688_mix;
-                 break;
-
-         case MDL_SMW:
-                 devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
-                 devc->supported_devices = 0;
-                 devc->supported_rec_devices = 0;
-                 devc->iomap = &sbpro_mix;
-                 smw_mixer_init(devc);
-                 break;
-
-         case MDL_SB16:
-                 devc->mixer_caps = 0;
-                 devc->supported_devices = SB16_MIXER_DEVICES;
-                 devc->supported_rec_devices = SB16_RECORDING_DEVICES;
-                 devc->iomap = &sb16_mix;
-                 break;
-
-         default:
-                 printk("SB Warning: Unsupported mixer type %d\n", devc->model);
-                 return 0;
-         }
+       {
+               case MDL_SBPRO:
+               case MDL_AZTECH:
+               case MDL_JAZZ:
+                       devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
+                       devc->supported_devices = SBPRO_MIXER_DEVICES;
+                       devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
+                       devc->iomap = &sbpro_mix;
+                       break;
+
+               case MDL_ESS:
+                       devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
+                       devc->supported_devices = ES688_MIXER_DEVICES;
+                       devc->supported_rec_devices = ES688_RECORDING_DEVICES;
+                       devc->iomap = &es688_mix;
+                       break;
+
+               case MDL_SMW:
+                       devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
+                       devc->supported_devices = 0;
+                       devc->supported_rec_devices = 0;
+                       devc->iomap = &sbpro_mix;
+                       smw_mixer_init(devc);
+                       break;
+
+               case MDL_SB16:
+                       devc->mixer_caps = 0;
+                       devc->supported_rec_devices = SB16_RECORDING_DEVICES;
+                       if (devc->submodel != SUBMDL_ALS007)
+                       {
+                               devc->supported_devices = SB16_MIXER_DEVICES;
+                               devc->iomap = &sb16_mix;
+                       }
+                       else
+                       {
+                               devc->supported_devices = ALS007_MIXER_DEVICES;
+                               devc->iomap = &als007_mix;
+                       }
+                       break;
+
+               default:
+                       printk(KERN_WARNING "sb_mixer: Unsupported mixer type %d\n", devc->model);
+                       return 0;
+       }
 
        m = sound_alloc_mixerdev();
        if (m == -1)
                return 0;
 
-
-       mixer_devs[m] = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations)));
-       sound_mem_sizes[sound_nblocks] = sizeof(struct mixer_operations);
-
-       if (sound_nblocks < 1024)
-               sound_nblocks++;;
+       mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
        if (mixer_devs[m] == NULL)
-         {
-                 printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
-                 sound_unload_mixerdev(m);
-                 return 0;
-         }
-       memcpy((char *) mixer_devs[m], (char *) &sb_mixer_operations,
-              sizeof(struct mixer_operations));
+       {
+               printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
+               sound_unload_mixerdev(m);
+               return 0;
+       }
 
-       mixer_devs[m]->devc = devc;
+       if (devc->submodel != SUBMDL_ALS007)
+               memcpy ((char *) mixer_devs[m], (char *) &sb_mixer_operations, sizeof (struct mixer_operations));
+       else
+               memcpy ((char *) mixer_devs[m], (char *) &als007_mixer_operations, sizeof (struct mixer_operations));
 
+       mixer_devs[m]->devc = devc;
        devc->my_mixerdev = m;
        sb_mixer_reset(devc);
        return 1;
index 2f68a62f3611f70310eaefff6623438c2e3d31be..f92f02e7d9414d2cd43f0e12cb7a2fda2ac2802a 100644 (file)
                                         SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
                                        SOUND_MASK_IMIX)
 
+/* These are the only devices that are working at the moment.  Others could
+ * be added once they are identified and a method is found to control them.
+ */
+#define ALS007_MIXER_DEVICES   (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
+                                SOUND_MASK_PCM | SOUND_MASK_MIC | \
+                                SOUND_MASK_CD | \
+                                SOUND_MASK_VOLUME)
 /*
  * Mixer registers
  * 
 #define LEFT_CHN       0
 #define RIGHT_CHN      1
 
+/*
+ * Mixer registers of ALS007
+ */
+#define ALS007_RECORD_SRC      0x6c
+#define ALS007_OUTPUT_CTRL1    0x3c
+#define ALS007_OUTPUT_CTRL2    0x4c
+
 #define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r)        \
        {{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
 
@@ -173,6 +187,25 @@ MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2),
 MIX_ENT(SOUND_MIXER_OGAIN,     0x41, 7, 2, 0x42, 7, 2)
 };
 
+static mixer_tab als007_mix = 
+{
+MIX_ENT(SOUND_MIXER_VOLUME,    0x62, 7, 4, 0x62, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,    0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,     0x66, 7, 4, 0x66, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM,       0x64, 7, 4, 0x64, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER,   0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,      0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC,       0x6a, 6, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD,                0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX,      0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,    0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,    0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
+MIX_ENT(SOUND_MIXER_IGAIN,     0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN,     0x00, 0, 0, 0x00, 0, 0)
+};
+
+
 /* SM_GAMES          Master volume is lower and PCM & FM volumes
                             higher than with SB Pro. This improves the
                             sound quality */
@@ -284,5 +317,14 @@ static char     smw_mix_regs[] =   /* Left mixer registers */
 #define SRC__CD          3     /* Select CD recording source */
 #define SRC__LINE        7     /* Use Line-in for recording source */
 
+/*
+ *     Recording sources for ALS-007
+ */
+
+#define ALS007_MIC     4
+#define ALS007_LINE    6
+#define ALS007_CD      2
+#define ALS007_SYNTH   7
+
 #endif
 #endif
index 22d30569fb7f06c1b3974afe64b4f0b3f21d3260..e659959372afd0d57601d60af704b01e39499ee5 100644 (file)
  */
 #include <linux/config.h>
 
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
 
 #define SEQUENCER_C
 #include "sound_config.h"
@@ -478,7 +482,7 @@ static void seq_chn_voice_event(unsigned char *event_rec)
                        parm = 64;
                }
        }
-       
+
        switch (cmd)
        {
                case MIDI_NOTEON:
@@ -950,7 +954,7 @@ static void setup_mode2(void)
                        synth_devs[max_synthdev++] = midi_devs[dev]->converter;
                }
        }
-       
+
        for (dev = 0; dev < max_synthdev; dev++)
        {
                int chn;
@@ -993,15 +997,20 @@ int sequencer_open(int dev, struct file *file)
                return -ENXIO;
        }
        if (dev)                /* Patch manager device (obsolete) */
-                 return -ENXIO;
+               return -ENXIO;
+
+#ifdef CONFIG_KMOD
+       if(synth_devs[dev] == NULL)
+               request_module("synth0");
+#endif
 
        if (mode == OPEN_READ)
        {
                if (!num_midis)
                {
-                         /*printk("Sequencer: No MIDI devices. Input not possible\n");*/
-                         sequencer_busy = 0;
-                         return -ENXIO;
+                       /*printk("Sequencer: No MIDI devices. Input not possible\n");*/
+                       sequencer_busy = 0;
+                       return -ENXIO;
                }
        }
        save_flags(flags);
@@ -1033,8 +1042,8 @@ int sequencer_open(int dev, struct file *file)
                for (i = 0; i < num_sound_timers; i++)
                        if (sound_timer_devs[i] && sound_timer_devs[i]->priority > best)
                        {
-                                   tmr_no = i;
-                                   best = sound_timer_devs[i]->priority;
+                               tmr_no = i;
+                               best = sound_timer_devs[i]->priority;
                        }
                if (tmr_no == -1)       /* Should not be */
                        tmr_no = 0;
@@ -1066,7 +1075,7 @@ int sequencer_open(int dev, struct file *file)
        {
                if (synth_devs[i]==NULL)
                        continue;
-                       
+
                if ((tmp = synth_devs[i]->open(i, mode)) < 0)
                {
                        printk(KERN_WARNING "Sequencer: Warning! Cannot open synth device #%d (%d)\n", i, tmp);
@@ -1096,7 +1105,7 @@ int sequencer_open(int dev, struct file *file)
                /*
                 * Initialize midi input devices
                 */
-               
+
                for (i = 0; i < max_mididev; i++)
                        if (!midi_opened[i])
                        {
@@ -1140,7 +1149,7 @@ void seq_drain_midi_queues(void)
                /*
                 * Let's have a delay
                 */
-               
+
                if (n) {
                        current->timeout = jiffies + HZ / 10;
                        interruptible_sleep_on(&seq_sleeper);
@@ -1173,7 +1182,7 @@ void sequencer_release(int dev, struct file *file)
                        /* Extra delay */
                }
        }
-                 
+
        if (mode != OPEN_READ)
                seq_drain_midi_queues();        /*
                                                 * Ensure the output queues are empty
@@ -1201,7 +1210,7 @@ void sequencer_release(int dev, struct file *file)
        for (i = 0; i < max_mididev; i++)
        {
                if (midi_opened[i])
-                         midi_devs[i]->close(i);
+                       midi_devs[i]->close(i);
        }
 
        if (seq_mode == SEQ_2)
@@ -1329,7 +1338,7 @@ static void seq_reset(void)
 
        save_flags(flags);
        cli();
-       
+
        if (waitqueue_active(&seq_sleeper)) {
                /*      printk( "Sequencer Warning: Unexpected sleeping process - Waking up\n"); */
                wake_up(&seq_sleeper);
@@ -1368,7 +1377,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
 
        orig_dev = dev = dev >> 4;
 
-       switch (cmd) 
+       switch (cmd)
        {
                case SNDCTL_TMR_TIMEBASE:
                case SNDCTL_TMR_TEMPO:
@@ -1380,13 +1389,13 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                        if (seq_mode != SEQ_2)
                                return -EINVAL;
                        return tmr->ioctl(tmr_no, cmd, arg);
-               
+
                case SNDCTL_TMR_SELECT:
                        if (seq_mode != SEQ_2)
                                return -EINVAL;
                        if (get_user(pending_timer, (int *)arg))
                                return -EFAULT;
-                       if (pending_timer < 0 || pending_timer >= num_sound_timers || sound_timer_devs[pending_timer] == NULL) 
+                       if (pending_timer < 0 || pending_timer >= num_sound_timers || sound_timer_devs[pending_timer] == NULL)
                        {
                                pending_timer = -1;
                                return -EINVAL;
@@ -1397,14 +1406,14 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                case SNDCTL_SEQ_PANIC:
                        seq_panic();
                        return -EINVAL;
-               
+
                case SNDCTL_SEQ_SYNC:
                        if (mode == OPEN_READ)
                                return 0;
                        while (qlen > 0 && !signal_pending(current))
                                seq_sync();
                        return qlen ? -EINTR : 0;
-               
+
                case SNDCTL_SEQ_RESET:
                        seq_reset();
                        return 0;
@@ -1414,8 +1423,8 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                                return -EFAULT;
                        if (midi_dev < 0 || midi_dev >= max_mididev)
                                return -ENXIO;
-               
-                       if (!midi_opened[midi_dev] && 
+
+                       if (!midi_opened[midi_dev] &&
                                (err = midi_devs[midi_dev]->open(midi_dev, mode, sequencer_midi_input,
                                                     sequencer_midi_output)) < 0)
                                return err;
@@ -1427,13 +1436,13 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                                return 0;
                        val = iqlen;
                        break;
-               
+
                case SNDCTL_SEQ_GETOUTCOUNT:
                        if (mode == OPEN_READ)
                                return 0;
                        val = SEQ_MAX_QUEUE - qlen;
                        break;
-               
+
                case SNDCTL_SEQ_GETTIME:
                        if (seq_mode == SEQ_2)
                                return tmr->ioctl(tmr_no, cmd, arg);
@@ -1442,14 +1451,14 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                        else
                                val = jiffies - seq_time;
                        break;
-               
+
                case SNDCTL_SEQ_CTRLRATE:
                        /*
                         * If *arg == 0, just return the current rate
                         */
                        if (seq_mode == SEQ_2)
                                return tmr->ioctl(tmr_no, cmd, arg);
-               
+
                        if (get_user(val, (int *)arg))
                                return -EFAULT;
                        if (val != 0)
@@ -1504,7 +1513,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                        if (!(synth_open_mask & (1 << dev)) && !orig_dev)
                                return -EBUSY;
                        return synth_devs[dev]->ioctl(dev, cmd, arg);
-               
+
                /* Like SYNTH_INFO but returns ID in the name field */
                case SNDCTL_SYNTH_ID:
                        if (get_user(dev, (int *)(&(((struct synth_info *)arg)->device))))
@@ -1517,7 +1526,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                        strncpy(inf.name, synth_devs[dev]->id, sizeof(inf.name));
                        inf.device = dev;
                        return copy_to_user(arg, &inf, sizeof(inf))?-EFAULT:0;
-               
+
                case SNDCTL_SEQ_OUTOFBAND:
                        if (copy_from_user(&event_rec, arg, sizeof(event_rec)))
                                return -EFAULT;
@@ -1526,7 +1535,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                        play_event(event_rec.arr);
                        restore_flags(flags);
                        return 0;
-                 
+
                case SNDCTL_MIDI_INFO:
                        if (get_user(dev, (int *)(&(((struct synth_info *)arg)->device))))
                                return -EFAULT;
@@ -1534,7 +1543,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                                return -ENXIO;
                        midi_devs[dev]->info.device = dev;
                        return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct synth_info))?-EFAULT:0;
-               
+
                case SNDCTL_SEQ_THRESHOLD:
                        if (get_user(val, (int *)arg))
                                return -EFAULT;
@@ -1544,7 +1553,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                                val = SEQ_MAX_QUEUE - 1;
                        output_threshold = val;
                        return 0;
-               
+
                case SNDCTL_MIDI_PRETIME:
                        if (get_user(val, (int *)arg))
                                return -EFAULT;
@@ -1584,7 +1593,7 @@ unsigned int sequencer_poll(int dev, struct file *file, poll_table * wait)
 
        /* output */
        poll_wait(file, &seq_sleeper, wait);
-       if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) 
+       if ((SEQ_MAX_QUEUE - qlen) >= output_threshold)
                mask |= POLLOUT | POLLWRNORM;
        restore_flags(flags);
        return mask;
@@ -1665,8 +1674,8 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range,
         */
        while (bend > 2399)
        {
-                 multiplier *= 4;
-                 bend -= 2400;
+               multiplier *= 4;
+               bend -= 2400;
        }
 
        semitones = bend / 100;
@@ -1693,8 +1702,8 @@ void sequencer_init(void)
        queue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * EV_SZ);
        if (queue == NULL)
        {
-                 printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n");
-                 return;
+               printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n");
+               return;
        }
        iqueue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * IEV_SZ);
        if (iqueue == NULL)
index 43c3a7ec3acd1f6816ec6985eb9caff8fe11c467..6306688539689fc2bfb5cb927a30860051fcd725 100644 (file)
@@ -2,15 +2,15 @@
  * sound/softoss.c
  *
  * Software based MIDI synthsesizer driver.
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
- */
-/*
+ *
+ *
  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
  */
 #include <linux/config.h>
 #include "softoss.h"
 #include <linux/ultrasound.h>
 
-int             softsynth_disabled = 0;
+int softsynth_disabled = 0;
 
 static volatile int intr_pending = 0;
 
 #ifdef POLLED_MODE
 
-static struct timer_list poll_timer =
-{NULL, NULL, 0, 0, softsyn_poll};
+static struct timer_list poll_timer = {
+       NULL, NULL, 0, 0, softsyn_poll
+};
 
 #else
 #endif
@@ -101,11 +102,14 @@ extern int     *sound_osp;
 static volatile int is_running = 0;
 static int      softsynth_loaded = 0;
 
-static struct synth_info softsyn_info =
-{"SoftOSS", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH};
+static struct synth_info softsyn_info = {
+       "SoftOSS", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH
+};
+
+static struct softsyn_devc sdev_info = {
+       0
+};
 
-static struct softsyn_devc sdev_info =
-{0};
 softsyn_devc   *devc = &sdev_info;     /* used in softoss_rs.c */
 
 static struct voice_alloc_info *voice_alloc;
@@ -118,10 +122,9 @@ static volatile int tmr_running = 0;
 static int      voice_limit = 24;
 
 
-static void
-set_max_voices(int nr)
+static void set_max_voices(int nr)
 {
-       int             i;
+       int i;
 
        if (nr < 4)
                nr = 4;
@@ -134,19 +137,18 @@ set_max_voices(int nr)
 
        for (i = 31; i > 0; i--)
                if (nr & (1 << i))
-                 {
-                         devc->afterscale = i + 1;
-                         return;
-                 }
+               {
+                       devc->afterscale = i + 1;
+                       return;
+               }
 }
 
-static void
-update_vibrato(int voice)
+static void update_vibrato(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
+       voice_info *v = &softoss_voices[voice];
 
 #ifdef HANDLE_LFO
-       int             x;
+       int x;
 
        x = vibrato_table[v->vibrato_phase >> 8];
        v->vibrato_phase = (v->vibrato_phase + v->vibrato_step) & 0x7fff;
@@ -161,11 +163,10 @@ update_vibrato(int voice)
 }
 
 #ifdef HANDLE_LFO
-static void
-update_tremolo(int voice)
+static void update_tremolo(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
-       int             x;
+       voice_info *v = &softoss_voices[voice];
+       int x;
 
        x = tremolo_table[v->tremolo_phase >> 8];
        v->tremolo_phase = (v->tremolo_phase + v->tremolo_step) & 0x7fff;
@@ -174,11 +175,10 @@ update_tremolo(int voice)
 }
 #endif
 
-static void
-start_vibrato(int voice)
+static void start_vibrato(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
-       int             rate;
+       voice_info *v = &softoss_voices[voice];
+       int rate;
 
        if (!v->vibrato_depth)
                return;
@@ -189,11 +189,10 @@ start_vibrato(int voice)
        devc->vibratomap |= (1 << voice);       /* Enable vibrato */
 }
 
-static void
-start_tremolo(int voice)
+static void start_tremolo(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
-       int             rate;
+       voice_info *v = &softoss_voices[voice];
+       int rate;
 
        if (!v->tremolo_depth)
                return;
@@ -204,43 +203,43 @@ start_tremolo(int voice)
        devc->tremolomap |= (1 << voice);       /* Enable tremolo */
 }
 
-static void
-update_volume(int voice)
+static void update_volume(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
-       unsigned int    vol;
+       voice_info *v = &softoss_voices[voice];
+       unsigned int vol;
 
-/*
* Compute plain volume
- */
+       /*
       *      Compute plain volume
       */
 
        vol = (v->velocity * v->expression_vol * v->main_vol) >> 12;
 
 #ifdef HANDLE_LFO
-/*
* Handle LFO
- */
+       /*
       *      Handle LFO
       */
 
        if (devc->tremolomap & (1 << voice))
-         {
-                 int             t;
+       {
+               int t;
 
-                 t = 32768 - v->tremolo_level;
-                 vol = (vol * t) >> 15;
-                 update_tremolo(voice);
-         }
+               t = 32768 - v->tremolo_level;
+               vol = (vol * t) >> 15;
+               update_tremolo(voice);
+       }
 #endif
-/*
- * Envelope
- */
+       /*
+        *      Envelope
+        */
+        
        if (v->mode & WAVE_ENVELOPES && !v->percussive_voice)
                vol = (vol * (v->envelope_vol >> 16)) >> 19;
        else
                vol >>= 4;
 
-/*
- * Handle panning
- */
+       /*
       * Handle panning
       */
 
        if (v->panning < 0)     /* Pan left */
                v->rightvol = (vol * (128 + v->panning)) / 128;
@@ -253,45 +252,47 @@ update_volume(int voice)
                v->leftvol = vol;
 }
 
-static void
-step_envelope(int voice, int do_release, int velocity)
+static void step_envelope(int voice, int do_release, int velocity)
 {
-       voice_info     *v = &softoss_voices[voice];
-       int             r, rate, time, dif;
-       unsigned int    vol;
-       unsigned long   flags;
+       voice_info *v = &softoss_voices[voice];
+       int r, rate, time, dif;
+       unsigned int vol;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
 
        if (!voice_active[voice] || v->sample == NULL)
-         {
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               restore_flags(flags);
+               return;
+       }
        if (!do_release)
+       {
                if (v->mode & WAVE_SUSTAIN_ON && v->envelope_phase == 2)
-                 {             /* Stop envelope until note off */
-                         v->envelope_volstep = 0;
-                         v->envelope_time = 0x7fffffff;
-                         if (v->mode & WAVE_VIBRATO)
-                                 start_vibrato(voice);
-                         if (v->mode & WAVE_TREMOLO)
-                                 start_tremolo(voice);
-                         restore_flags(flags);
-                         return;
-                 }
+               {       
+                       /* Stop envelope until note off */
+                       v->envelope_volstep = 0;
+                       v->envelope_time = 0x7fffffff;
+                       if (v->mode & WAVE_VIBRATO)
+                               start_vibrato(voice);
+                       if (v->mode & WAVE_TREMOLO)
+                               start_tremolo(voice);
+                       restore_flags(flags);
+                       return;
+               }
+       }
        if (do_release)
                v->envelope_phase = 3;
        else
                v->envelope_phase++;
 
        if (v->envelope_phase >= 5)     /* Finished */
-         {
-                 init_voice(devc, voice);
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               init_voice(devc, voice);
+               restore_flags(flags);
+               return;
+       }
        vol = v->envelope_target = v->sample->env_offset[v->envelope_phase] << 22;
 
 
@@ -308,72 +309,69 @@ step_envelope(int voice, int do_release, int velocity)
        if (dif < 0)
                dif *= -1;
        if (dif < rate * 2)     /* Too close */
-         {
-                 step_envelope(voice, 0, 60);
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               step_envelope(voice, 0, 60);
+               restore_flags(flags);
+               return;
+       }
+
        if (vol > v->envelope_vol)
-         {
-                 v->envelope_volstep = rate;
-                 time = (vol - v->envelope_vol) / rate;
-       } else
-         {
-                 v->envelope_volstep = -rate;
-                 time = (v->envelope_vol - vol) / rate;
-         }
+       {
+               v->envelope_volstep = rate;
+               time = (vol - v->envelope_vol) / rate;
+       }
+       else
+       {
+               v->envelope_volstep = -rate;
+               time = (v->envelope_vol - vol) / rate;
+       }
 
        time--;
        if (time <= 0)
                time = 1;
-
        v->envelope_time = time;
-
-
        restore_flags(flags);
 }
 
-static void
-step_envelope_lfo(int voice)
+static void step_envelope_lfo(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
+       voice_info *v = &softoss_voices[voice];
 
-/*
- * Update pitch (vibrato) LFO 
- */
+       /*
       * Update pitch (vibrato) LFO 
       */
 
        if (devc->vibratomap & (1 << voice))
                update_vibrato(voice);
 
-/* 
- * Update envelope
- */
+       /* 
       * Update envelope
       */
 
        if (v->mode & WAVE_ENVELOPES)
-         {
-                 v->envelope_vol += v->envelope_volstep;
-                 /* Overshoot protection */
-                 if (v->envelope_vol < 0)
-                   {
-                           v->envelope_vol = v->envelope_target;
-                           v->envelope_volstep = 0;
-                   }
-                 if (v->envelope_time-- <= 0)
-                   {
-                           v->envelope_vol = v->envelope_target;
-                           step_envelope(voice, 0, 60);
-                   }
-         }
+       {
+               v->envelope_vol += v->envelope_volstep;
+               /* Overshoot protection */
+               if (v->envelope_vol < 0)
+               {
+                       v->envelope_vol = v->envelope_target;
+                       v->envelope_volstep = 0;
+               }
+               if (v->envelope_time-- <= 0)
+               {
+                       v->envelope_vol = v->envelope_target;
+                       step_envelope(voice, 0, 60);
+               }
+       }
 }
 
-static void
-compute_step(int voice)
+static void compute_step(int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
+       voice_info *v = &softoss_voices[voice];
 
        /*
-        * Since the pitch bender may have been set before playing the note, we
-        * have to calculate the bending now.
+        *      Since the pitch bender may have been set before playing the note, we
+        *      have to calculate the bending now.
         */
 
        v->current_freq = compute_finetune(v->orig_freq,
@@ -386,11 +384,10 @@ compute_step(int voice)
                v->step *= -1;  /* Reversed playback */
 }
 
-static void
-init_voice(softsyn_devc * devc, int voice)
+static void init_voice(softsyn_devc * devc, int voice)
 {
-       voice_info     *v = &softoss_voices[voice];
-       unsigned long   flags;
+       voice_info *v = &softoss_voices[voice];
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -433,18 +430,17 @@ init_voice(softsyn_devc * devc, int voice)
        restore_flags(flags);
 }
 
-static void
-reset_samples(softsyn_devc * devc)
+static void reset_samples(softsyn_devc * devc)
 {
-       int             i;
+       int i;
 
        for (i = 0; i < MAX_VOICE; i++)
                voice_active[i] = 0;
        for (i = 0; i < devc->maxvoice; i++)
-         {
-                 init_voice(devc, i);
-                 softoss_voices[i].instr = 0;
-         }
+       {
+               init_voice(devc, i);
+               softoss_voices[i].instr = 0;
+       }
 
        devc->ram_used = 0;
 
@@ -452,20 +448,18 @@ reset_samples(softsyn_devc * devc)
                devc->programs[i] = NO_SAMPLE;
 
        for (i = 0; i < devc->nrsamples; i++)
-         {
-                 vfree(devc->samples[i]);
-                 vfree(devc->wave[i]);
-                 devc->samples[i] = NULL;
-                 devc->wave[i] = NULL;
-         }
-
+       {
+               vfree(devc->samples[i]);
+               vfree(devc->wave[i]);
+               devc->samples[i] = NULL;
+               devc->wave[i] = NULL;
+       }
        devc->nrsamples = 0;
 }
 
-static void
-init_engine(softsyn_devc * devc)
+static void init_engine(softsyn_devc * devc)
 {
-       int             i, fz, srate, sz = devc->channels;
+       int i, fz, srate, sz = devc->channels;
 
        set_max_voices(devc->default_max_voices);
        voice_alloc->timestamp = 0;
@@ -480,16 +474,15 @@ init_engine(softsyn_devc * devc)
        devc->usecs_per_frag = (1000000 * fz) / devc->speed;
 
        for (i = 0; i < devc->maxvoice; i++)
-         {
-                 init_voice(devc, i);
-                 softoss_voices[i].instr = 0;
-         }
-
+       {
+               init_voice(devc, i);
+               softoss_voices[i].instr = 0;
+       }
        devc->engine_state = ES_STOPPED;
 
-/*
- *    Initialize delay
- */
+       /*
       *    Initialize delay
       */
 
        for (i = 0; i < DELAY_SIZE; i++)
                left_delay[i] = right_delay[i] = 0;
@@ -502,34 +495,35 @@ init_engine(softsyn_devc * devc)
                devc->delay_size = DELAY_SIZE;
 }
 
-void
-softsyn_control_loop(void)
+void softsyn_control_loop(void)
 {
-       int             voice;
+       int voice;
 
-/*
- *    Recompute envlope, LFO, etc.
- */
+       /*
       *    Recompute envlope, LFO, etc.
       */
        for (voice = 0; voice < devc->maxvoice; voice++)
+       {
                if (voice_active[voice])
-                 {
-                         update_volume(voice);
-                         step_envelope_lfo(voice);
-               } else
+               {
+                       update_volume(voice);
+                       step_envelope_lfo(voice);
+               }
+               else
                        voice_alloc->map[voice] = 0;
+       }
 }
 
-static void     start_engine(softsyn_devc * devc);
+static void start_engine(softsyn_devc * devc);
 
-static void
-do_resample(int dummy)
+static void do_resample(int dummy)
 {
        struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
        struct voice_info *vinfo;
        unsigned long   flags, jif;
 
-       int             voice, loops;
-       short          *buf;
+       int voice, loops;
+       short *buf;
 
        if (softsynth_disabled)
                return;
@@ -538,68 +532,70 @@ do_resample(int dummy)
        cli();
 
        if (is_running)
-         {
-                 printk("SoftOSS: Playback overrun\n");
-                 restore_flags(flags);
-                 return;
-         }
+       {
+               printk(KERN_WARNING "SoftOSS: Playback overrun\n");
+               restore_flags(flags);
+               return;
+       }
        jif = jiffies;
        if (jif == last_resample_jiffies)
-         {
-                 if (resample_counter++ > 50)
-                   {
-                           for (voice = 0; voice < devc->maxvoice; voice++)
-                                   init_voice(devc, voice);
-                           voice_limit--;
-                           resample_counter = 0;
-                           printk("SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit);
-
-                           if (voice_limit < 10)
-                             {
-                                     voice_limit = 10;
-                                     devc->speed = (devc->speed * 2) / 3;
-
-                                     printk("SoftOSS: Dropping sampling rate and stopping the device.\n");
-                                     softsynth_disabled = 1;
-                             }
-                   }
-       } else
-         {
-                 last_resample_jiffies = jif;
-                 resample_counter = 0;
-         }
+       {
+               if (resample_counter++ > 50)
+               {
+                       for (voice = 0; voice < devc->maxvoice; voice++)
+                               init_voice(devc, voice);
+                       voice_limit--;
+                       resample_counter = 0;
+                       printk(KERN_WARNING "SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit);
+
+                       if (voice_limit < 10)
+                       {
+                               voice_limit = 10;
+                               devc->speed = (devc->speed * 2) / 3;
+
+                               printk(KERN_WARNING "SoftOSS: Dropping sampling rate and stopping the device.\n");
+                               softsynth_disabled = 1;
+                       }
+               }
+       }
+       else
+       {
+               last_resample_jiffies = jif;
+               resample_counter = 0;
+       }
 
        /* is_running = 1; */
 
        if (dmap->qlen > devc->max_playahead)
-         {
-                 printk("SoftOSS: audio buffers full\n");
-                 is_running = 0;
-                 restore_flags(flags);
-                 return;
-         }
-/*
- * First verify that all active voices are valid (do this just once per block).
- */
+       {
+               printk(KERN_WARNING "SoftOSS: audio buffers full\n");
+               is_running = 0;
+               restore_flags(flags);
+               return;
+       }
+       /*
+        * First verify that all active voices are valid (do this just once per block).
+        */
+
        for (voice = 0; voice < devc->maxvoice; voice++)
+       {
                if (voice_active[voice])
-                 {
-                         int             ptr;
-
-                         vinfo = &softoss_voices[voice];
-                         ptr = vinfo->ptr >> 9;
-
-                         if (vinfo->wave == NULL ||
-                             ptr < 0 ||
-                             ptr > vinfo->sample->len)
-                                 init_voice(devc, voice);
-                         else if (!(vinfo->mode & WAVE_LOOPING) &&
-                            (vinfo->ptr + vinfo->step) > vinfo->endloop)
+               {
+                       int ptr;
+
+                       vinfo = &softoss_voices[voice];
+                       ptr = vinfo->ptr >> 9;
+
+                       if (vinfo->wave == NULL || ptr < 0 || ptr > vinfo->sample->len)
+                               init_voice(devc, voice);
+                       else if (!(vinfo->mode & WAVE_LOOPING) && (vinfo->ptr + vinfo->step) > vinfo->endloop)
                                  voice_active[voice] = 0;
-                 }
-/*
- *    Start the resampling process
- */
+               }
+       }
+       
+       /*
+        *    Start the resampling process
+        */
 
        loops = devc->samples_per_fragment;
        buf = (short *) (dmap->raw_buf + (dmap->qtail * dmap->fragment_size));
@@ -613,54 +609,51 @@ do_resample(int dummy)
        devc->usecs += devc->usecs_per_frag;
 
        if (tmr_running)
-         {
-                 sound_timer_interrupt();
-         }
-/*
- *    Execute timer
- */
+               sound_timer_interrupt();
+       /*
+        *    Execute timer
+        */
 
        if (!tmr_running)
+       {
                if (devc->usecs >= devc->next_event_usecs)
-                 {
-                         devc->next_event_usecs = ~0;
-                         sequencer_timer(0);
-                 }
+               {
+                       devc->next_event_usecs = ~0;
+                       sequencer_timer(0);
+               }
+       }
+       
        is_running = 0;
        restore_flags(flags);
 }
 
-static void
-delayed_resample(int dummy)
+static void delayed_resample(int dummy)
 {
        struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out;
-       int             n = 0;
+       int n = 0;
 
        if (is_running)
                return;
 
-       while (devc->engine_state != ES_STOPPED &&
-              dmap->qlen < devc->max_playahead && n++ < 2)
+       while (devc->engine_state != ES_STOPPED && dmap->qlen < devc->max_playahead && n++ < 2)
                do_resample(0);
        intr_pending = 0;
 }
 
 #ifdef POLLED_MODE
-static void
-softsyn_poll(unsigned long dummy)
+static void softsyn_poll(unsigned long dummy)
 {
        delayed_resample(0);
 
        if (devc->engine_state != ES_STOPPED)
-
-         {
-                 poll_timer.expires = (1) + jiffies;
+       {
+                 poll_timer.expires = jiffies+1;
                  add_timer(&poll_timer);
-         };
+       }
 }
+
 #else
-static void
-softsyn_callback(int dev, int parm)
+static void softsyn_callback(int dev, int parm)
 {
        delayed_resample(0);
 }
@@ -686,13 +679,14 @@ static void start_engine(softsyn_devc * devc)
        devc->control_rate = 64;
        devc->control_counter = 0;
 
-       if (devc->engine_state == ES_STOPPED) {
+       if (devc->engine_state == ES_STOPPED) 
+       {
                n = trig = 0;
                fs = get_fs();
                set_fs(get_ds());
                dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t)&trig);
 #ifdef POLLED_MODE
-               poll_timer.expires = (1) + jiffies;
+               poll_timer.expires = jiffies+1;
                add_timer(&poll_timer);
                /* Start polling */
 #else
@@ -711,13 +705,11 @@ static void start_engine(softsyn_devc * devc)
        }
 }
 
-static void
-stop_engine(softsyn_devc * devc)
+static void stop_engine(softsyn_devc * devc)
 {
 }
 
-static void
-request_engine(softsyn_devc * devc, int ticks)
+static void request_engine(softsyn_devc * devc, int ticks)
 {
        if (ticks < 0)          /* Relative time */
                devc->next_event_usecs = devc->usecs - ticks * (1000000 / HZ);
@@ -728,74 +720,72 @@ request_engine(softsyn_devc * devc, int ticks)
 /*
  * Softsync hook serves mode1 (timing) calls made by sequencer.c
  */
-static int
-softsynth_hook(int cmd, int parm1, int parm2, unsigned long parm3)
+static int softsynth_hook(int cmd, int parm1, int parm2, unsigned long parm3)
 {
        switch (cmd)
-         {
-         case SSYN_START:
-                 start_engine(devc);
-                 break;
+       {
+               case SSYN_START:
+                       start_engine(devc);
+                       break;
 
-         case SSYN_STOP:
-                 stop_engine(devc);
-                 break;
+               case SSYN_STOP:
+                       stop_engine(devc);
+                       break;
 
-         case SSYN_REQUEST:
-                 request_engine(devc, parm1);
-                 break;
+               case SSYN_REQUEST:
+                       request_engine(devc, parm1);
+                       break;
 
-         case SSYN_GETTIME:
-                 return devc->usecs / (1000000 / HZ);
-                 break;
-
-         default:
-                 printk("SoftOSS: Unknown request %d\n", cmd);
-         }
+               case SSYN_GETTIME:
+                       return devc->usecs / (1000000 / HZ);
+                       break;
 
+               default:
+                       printk(KERN_WARNING "SoftOSS: Unknown request %d\n", cmd);
+       }
        return 0;
 }
 
 static int softsyn_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
-       switch (cmd) {
-
-       case SNDCTL_SYNTH_INFO:
-               softsyn_info.nr_voices = devc->maxvoice;
-               if (__copy_to_user(arg, &softsyn_info, sizeof(softsyn_info)))
-                       return -EFAULT;
-               return 0;
-
-       case SNDCTL_SEQ_RESETSAMPLES:
-               stop_engine(devc);
-               reset_samples(devc);
-               return 0;
+       switch (cmd) 
+       {
+               case SNDCTL_SYNTH_INFO:
+                       softsyn_info.nr_voices = devc->maxvoice;
+                       if (copy_to_user(arg, &softsyn_info, sizeof(softsyn_info)))
+                               return -EFAULT;
+                       return 0;
+
+               case SNDCTL_SEQ_RESETSAMPLES:
+                       stop_engine(devc);
+                       reset_samples(devc);
+                       return 0;
                  
-       case SNDCTL_SYNTH_MEMAVL:
-               return devc->ram_size - devc->ram_used;
+               case SNDCTL_SYNTH_MEMAVL:
+                       return devc->ram_size - devc->ram_used;
 
-       default:
-               return -EINVAL;
+               default:
+                       return -EINVAL;
        }
 }
 
-static int
-softsyn_kill_note(int devno, int voice, int note, int velocity)
+static int softsyn_kill_note(int devno, int voice, int note, int velocity)
 {
        if (voice < 0 || voice > devc->maxvoice)
                return 0;
        voice_alloc->map[voice] = 0xffff;       /* Releasing */
 
        if (softoss_voices[voice].sustain_mode & 1)     /* Sustain controller on */
-         {
-                 softoss_voices[voice].sustain_mode = 3;       /* Note off pending */
-                 return 0;
-         }
+       {
+               softoss_voices[voice].sustain_mode = 3; /* Note off pending */
+               return 0;
+       }
        if (velocity > 127 || softoss_voices[voice].mode & WAVE_FAST_RELEASE)
-         {
-                 init_voice(devc, voice);      /* Mark it inactive */
-                 return 0;
-         }
+       {
+               init_voice(devc, voice);        /* Mark it inactive */
+               return 0;
+       }
        if (softoss_voices[voice].mode & WAVE_ENVELOPES)
                step_envelope(voice, 1, velocity);      /* Enter sustain phase */
        else
@@ -803,29 +793,26 @@ softsyn_kill_note(int devno, int voice, int note, int velocity)
        return 0;
 }
 
-static int
-softsyn_set_instr(int dev, int voice, int instr)
+static int softsyn_set_instr(int dev, int voice, int instr)
 {
        if (voice < 0 || voice > devc->maxvoice)
                return 0;
 
        if (instr < 0 || instr > MAX_PATCH)
-         {
-                 printk("SoftOSS: Invalid instrument number %d\n", instr);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "SoftOSS: Invalid instrument number %d\n", instr);
+               return 0;
+       }
        softoss_voices[voice].instr = instr;
-
        return 0;
 }
 
-static int
-softsyn_start_note(int dev, int voice, int note, int volume)
+static int softsyn_start_note(int dev, int voice, int note, int volume)
 {
-       int             instr = 0;
-       int             best_sample, best_delta, delta_freq, selected;
-       unsigned long   note_freq, freq, base_note, flags;
-       voice_info     *v = &softoss_voices[voice];
+       int instr = 0;
+       int best_sample, best_delta, delta_freq, selected;
+       unsigned long note_freq, freq, base_note, flags;
+       voice_info *v = &softoss_voices[voice];
 
        struct patch_info *sample;
 
@@ -839,32 +826,32 @@ softsyn_start_note(int dev, int voice, int note, int volume)
        cli();
 
        if (note == 255)
-         {                     /* Just volume update */
-                 v->velocity = volume;
-                 if (voice_active[voice])
-                         update_volume(voice);
-                 restore_flags(flags);
-                 return 0;
-         }
+       {                       /* Just volume update */
+               v->velocity = volume;
+               if (voice_active[voice])
+                       update_volume(voice);
+               restore_flags(flags);
+               return 0;
+       }
        voice_active[voice] = 0;        /* Stop the voice for a while */
        devc->vibratomap &= ~(1 << voice);
        devc->tremolomap &= ~(1 << voice);
 
        instr = v->instr;
        if (instr < 0 || instr > MAX_PATCH || devc->programs[instr] == NO_SAMPLE)
-         {
-                 printk("SoftOSS: Undefined MIDI instrument %d\n", instr);
-                 restore_flags(flags);
-                 return 0;
-         }
+       {
+               printk(KERN_WARNING "SoftOSS: Undefined MIDI instrument %d\n", instr);
+               restore_flags(flags);
+               return 0;
+       }
        instr = devc->programs[instr];
 
        if (instr < 0 || instr >= devc->nrsamples)
-         {
-                 printk("SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr);
-                 restore_flags(flags);
-                 return 0;
-         }
+       {
+               printk(KERN_WARNING "SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr);
+               restore_flags(flags);
+               return 0;
+       }
        note_freq = note_to_freq(note);
 
        selected = -1;
@@ -873,25 +860,26 @@ softsyn_start_note(int dev, int voice, int note, int volume)
        best_delta = 1000000;
 
        while (instr != NO_SAMPLE && instr >= 0 && selected == -1)
-         {
-                 delta_freq = note_freq - devc->samples[instr]->base_note;
-
-                 if (delta_freq < 0)
-                         delta_freq = -delta_freq;
-                 if (delta_freq < best_delta)
-                   {
-                           best_sample = instr;
-                           best_delta = delta_freq;
-                   }
-                 if (devc->samples[instr]->low_note <= note_freq &&
-                     note_freq <= devc->samples[instr]->high_note)
-                         selected = instr;
-                 else
-                         instr = devc->samples[instr]->key;    /* Link to next sample */
-
-                 if (instr < 0 || instr >= devc->nrsamples)
-                         instr = NO_SAMPLE;
-         }
+       {
+               delta_freq = note_freq - devc->samples[instr]->base_note;
+
+               if (delta_freq < 0)
+                       delta_freq = -delta_freq;
+               if (delta_freq < best_delta)
+               {
+                       best_sample = instr;
+                       best_delta = delta_freq;
+               }
+               if (devc->samples[instr]->low_note <= note_freq &&
+                       note_freq <= devc->samples[instr]->high_note)
+               {
+                       selected = instr;
+               }
+               else instr = devc->samples[instr]->key; /* Link to next sample */
+
+               if (instr < 0 || instr >= devc->nrsamples)
+                       instr = NO_SAMPLE;
+       }
 
        if (selected == -1)
                instr = best_sample;
@@ -899,37 +887,33 @@ softsyn_start_note(int dev, int voice, int note, int volume)
                instr = selected;
 
        if (instr < 0 || instr == NO_SAMPLE || instr > devc->nrsamples)
-         {
-                 printk("SoftOSS: Unresolved MIDI instrument %d\n", v->instr);
-                 restore_flags(flags);
-                 return 0;
-         }
+       {
+               printk(KERN_WARNING "SoftOSS: Unresolved MIDI instrument %d\n", v->instr);
+               restore_flags(flags);
+               return 0;
+       }
        sample = devc->samples[instr];
        v->sample = sample;
 
        if (v->percussive_voice)        /* No key tracking */
-         {
                  v->orig_freq = sample->base_freq;     /* Fixed pitch */
-       else
-         {
-                 base_note = sample->base_note / 100;
-                 note_freq /= 100;
+       else
+       {
+               base_note = sample->base_note / 100;
+               note_freq /= 100;
 
-                 freq = sample->base_freq * note_freq / base_note;
-                 v->orig_freq = freq;
-         }
+               freq = sample->base_freq * note_freq / base_note;
+               v->orig_freq = freq;
+       }
 
        if (!(sample->mode & WAVE_LOOPING))
-         {
-                 sample->loop_end = sample->len;
-         }
-       v->wave = devc->wave[instr];
+               sample->loop_end = sample->len;
 
+       v->wave = devc->wave[instr];
        if (volume < 0)
                volume = 0;
        else if (volume > 127)
                volume = 127;
-
        v->ptr = 0;
        v->startloop = sample->loop_start * 512;
        v->startbackloop = 0;
@@ -954,40 +938,39 @@ softsyn_start_note(int dev, int voice, int note, int volume)
        if (!(v->mode & WAVE_LOOPING))
                v->mode &= ~(WAVE_BIDIR_LOOP | WAVE_LOOP_BACK);
        else if (v->mode & WAVE_LOOP_BACK)
-         {
-                 v->ptr = sample->len;
-                 v->startbackloop = v->startloop;
-         }
+       {
+               v->ptr = sample->len;
+               v->startbackloop = v->startloop;
+       }
        if (v->mode & WAVE_VIBRATO)
-         {
-                 v->vibrato_rate = sample->vibrato_rate;
-                 v->vibrato_depth = sample->vibrato_depth;
-         }
+       {
+               v->vibrato_rate = sample->vibrato_rate;
+               v->vibrato_depth = sample->vibrato_depth;
+       }
        if (v->mode & WAVE_TREMOLO)
-         {
-                 v->tremolo_rate = sample->tremolo_rate;
-                 v->tremolo_depth = sample->tremolo_depth;
-         }
+       {
+               v->tremolo_rate = sample->tremolo_rate;
+               v->tremolo_depth = sample->tremolo_depth;
+       }
        if (v->mode & WAVE_ENVELOPES)
-         {
-                 v->envelope_phase = -1;
-                 v->envelope_vol = 0;
-                 step_envelope(voice, 0, 60);
-         }
+       {
+               v->envelope_phase = -1;
+               v->envelope_vol = 0;
+               step_envelope(voice, 0, 60);
+       }
        update_volume(voice);
        compute_step(voice);
 
        voice_active[voice] = 1;        /* Mark it active */
-
        restore_flags(flags);
        return 0;
 }
 
 static int softsyn_open(int synthdev, int mode)
 {
-       int             err;
-       extern int      softoss_dev;
-       int             frags = 0x7fff0007;     /* fragment size of 128 bytes */
+       int err;
+       extern int softoss_dev;
+       int frags = 0x7fff0007; /* fragment size of 128 bytes */
        mm_segment_t fs;
 
        if (devc->audio_opened) /* Already opened */
@@ -1007,10 +990,10 @@ static int softsyn_open(int synthdev, int mode)
        devc->audiodev = softoss_dev;
 
        if (!(audio_devs[devc->audiodev]->format_mask & AFMT_S16_LE))
-         {
-                 printk("SoftOSS: The audio device doesn't support 16 bits\n");
-                 return -ENXIO;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: The audio device doesn't support 16 bits\n"); */
+               return -ENXIO;
+       }
        if ((err = audio_open((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo)) < 0)
                return err;
 
@@ -1023,7 +1006,6 @@ static int softsyn_open(int synthdev, int mode)
 
 
        DDB(printk("SoftOSS: Using audio dev %d, speed %d, bits %d, channels %d\n", devc->audiodev, devc->speed, devc->bits, devc->channels));
-
        fs = get_fs();
        set_fs(get_ds());
        dma_ioctl(devc->audiodev, SNDCTL_DSP_SETFRAGMENT, (caddr_t) & frags);
@@ -1031,11 +1013,11 @@ static int softsyn_open(int synthdev, int mode)
        set_fs(fs);
 
        if (devc->bits != 16 || devc->channels != 2)
-         {
-                 audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
-                 printk("SoftOSS: A 16 bit stereo soundcard is required\n");
-                 return 0;
-         }
+       {
+               audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo);
+/*             printk("SoftOSS: A 16 bit stereo soundcard is required\n");*/
+               return -EINVAL;
+       }
        if (devc->max_playahead >= audio_devs[devc->audiodev]->dmap_out->nbufs)
                devc->max_playahead = audio_devs[devc->audiodev]->dmap_out->nbufs;
 
@@ -1064,12 +1046,11 @@ static void softsyn_close(int synthdev)
        devc->audio_opened = 0;
 }
 
-static void
-softsyn_hw_control(int dev, unsigned char *event_rec)
+static void softsyn_hw_control(int dev, unsigned char *event_rec)
 {
-       int             voice, cmd;
-       unsigned short  p1, p2;
-       unsigned int    plong;
+       int voice, cmd;
+       unsigned short p1, p2;
+       unsigned int plong;
 
        cmd = event_rec[2];
        voice = event_rec[3];
@@ -1078,48 +1059,47 @@ softsyn_hw_control(int dev, unsigned char *event_rec)
        plong = *(unsigned int *) &event_rec[4];
 
        switch (cmd)
-         {
-
-         case _GUS_NUMVOICES:
-                 set_max_voices(p1);
-                 break;
+       {
 
+               case _GUS_NUMVOICES:
+                       set_max_voices(p1);
+                       break;
 
-         default:;
-         }
+               default:;
+       }
 }
 
-static int
-softsyn_load_patch(int dev, int format, const char *addr,
+static int softsyn_load_patch(int dev, int format, const char *addr,
                   int offs, int count, int pmgr_flag)
 {
        struct patch_info *patch = NULL;
 
-       int             i, p, instr;
-       long            sizeof_patch;
-       int             memlen, adj;
+       int i, p, instr;
+       long sizeof_patch;
+       int memlen, adj;
        unsigned short  data;
-       short          *wave = NULL;
+       short *wave = NULL;
 
        sizeof_patch = (long) &patch->data[0] - (long) patch;   /* Header size */
 
        if (format != GUS_PATCH)
-         {
-                 printk("SoftOSS: Invalid patch format (key) 0x%x\n", format);
-                 return -EINVAL;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: Invalid patch format (key) 0x%x\n", format);*/
+               return -EINVAL;
+       }
        if (count < sizeof_patch)
-         {
-                 printk("SoftOSS: Patch header too short\n");
-                 return -EINVAL;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: Patch header too short\n");*/
+               return -EINVAL;
+       }
        count -= sizeof_patch;
 
        if (devc->nrsamples >= MAX_SAMPLE)
-         {
-                 printk("SoftOSS: Sample table full\n");
-                 return -ENOSPC;
-         }
+       {
+/*               printk(KERN_ERR "SoftOSS: Sample table full\n");*/
+                 return -ENOBUFS;
+       }
+       
        /*
         * Copy the header from user space but ignore the first bytes which have
         * been transferred already.
@@ -1128,54 +1108,55 @@ softsyn_load_patch(int dev, int format, const char *addr,
        patch = vmalloc(sizeof(*patch));
 
        if (patch == NULL)
-         {
-                 printk("SoftOSS: Out of memory\n");
-                 return -ENOSPC;
-         }
-       copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs);
+       {
+/*             printk(KERN_ERR "SoftOSS: Out of memory\n");*/
+               return -ENOMEM;
+       }
+       if(copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs))
+               return -EFAULT;
 
        if (patch->mode & WAVE_ROM)
-         {
-                 vfree(patch);
-                 return -EINVAL;
-         }
+       {
+               vfree(patch);
+               return -EINVAL;
+       }
        instr = patch->instr_no;
 
        if (instr < 0 || instr > MAX_PATCH)
-         {
-                 printk("SoftOSS: Invalid patch number %d\n", instr);
-                 vfree(patch);
-                 return -EINVAL;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: Invalid patch number %d\n", instr);*/
+               vfree(patch);
+               return -EINVAL;
+       }
        if (count < patch->len)
-         {
-                 printk("SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len);
-                 patch->len = count;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len);*/
+               patch->len = count;
+       }
        if (patch->len <= 0 || patch->len > (devc->ram_size - devc->ram_used))
-         {
-                 printk("SoftOSS: Invalid sample length %d\n", (int) patch->len);
-                 vfree(patch);
-                 return -EINVAL;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: Invalid sample length %d\n", (int) patch->len); */
+               vfree(patch);
+               return -EINVAL;
+       }
        if (patch->mode & WAVE_LOOPING)
-         {
-                 if (patch->loop_start < 0 || patch->loop_start >= patch->len)
-                   {
-                           printk("SoftOSS: Invalid loop start %d\n", patch->loop_start);
-                           vfree(patch);
-                           return -EINVAL;
-                   }
-                 if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len)
-                   {
-                           printk("SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end);
-                           vfree(patch);
-                           return -EINVAL;
-                   }
-         }
-/* 
* Next load the wave data to memory
- */
+       {
+               if (patch->loop_start < 0 || patch->loop_start >= patch->len)
+               {
+/*                     printk(KERN_ERR "SoftOSS: Invalid loop start %d\n", patch->loop_start);*/
+                       vfree(patch);
+                       return -EINVAL;
+               }
+               if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len)
+               {
+/*                     printk(KERN_ERR "SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end);*/
+                       vfree(patch);
+                       return -EINVAL;
+               }
+       }
+       /* 
       *      Next load the wave data to memory
       */
 
        memlen = patch->len;
        adj = 1;
@@ -1188,48 +1169,47 @@ softsyn_load_patch(int dev, int format, const char *addr,
        wave = vmalloc(memlen);
 
        if (wave == NULL)
-         {
-                 printk("SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);
-                 vfree(patch);
-                 return -ENOSPC;
-         }
+       {
+/*             printk(KERN_ERR "SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);*/
+               vfree(patch);
+               return -ENOMEM;
+       }
        p = 0;
        for (i = 0; i < memlen / 2; i++)        /* Handle words */
-         {
-                 unsigned char   tmp;
-
-                 data = 0;
-
-                 if (patch->mode & WAVE_16_BITS)
-                   {
-                           get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));         /* Get lsb */
-                           data = tmp;
-                           get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));         /* Get msb */
-                           if (patch->mode & WAVE_UNSIGNED)
-                                   tmp ^= 0x80;        /* Convert to signed */
-                           data |= (tmp << 8);
-                 } else
-                   {
-                           get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));
-                           if (patch->mode & WAVE_UNSIGNED)
-                                   tmp ^= 0x80;        /* Convert to signed */
+       {
+               unsigned char tmp;
+               data = 0;
+               if (patch->mode & WAVE_16_BITS)
+               {
+                       get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));             /* Get lsb */
+                       data = tmp;
+                       get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));             /* Get msb */
+                       if (patch->mode & WAVE_UNSIGNED)
+                               tmp ^= 0x80;    /* Convert to signed */
+                       data |= (tmp << 8);
+               }
+               else
+               {
+                       get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++]));
+                       if (patch->mode & WAVE_UNSIGNED)
+                               tmp ^= 0x80;    /* Convert to signed */
                            data = (tmp << 8);  /* Convert to 16 bits */
-                   }
-
-                 wave[i] = (short) data;
-         }
+               }
+               wave[i] = (short) data;
+       }
 
        devc->ram_used += patch->len;
-/*
- * Convert pointers to 16 bit indexes
- */
+
+       /*
+        * Convert pointers to 16 bit indexes
+        */
        patch->len /= adj;
        patch->loop_start /= adj;
        patch->loop_end /= adj;
 
-/*
- * Finally link the loaded patch to the chain
- */
+       /*
       * Finally link the loaded patch to the chain
       */
 
        patch->key = devc->programs[instr];
        devc->programs[instr] = devc->nrsamples;
@@ -1239,8 +1219,7 @@ softsyn_load_patch(int dev, int format, const char *addr,
        return 0;
 }
 
-static void
-softsyn_panning(int dev, int voice, int pan)
+static void softsyn_panning(int dev, int voice, int pan)
 {
        if (voice < 0 || voice > devc->maxvoice)
                return;
@@ -1255,13 +1234,11 @@ softsyn_panning(int dev, int voice, int pan)
                update_volume(voice);
 }
 
-static void
-softsyn_volume_method(int dev, int mode)
+static void softsyn_volume_method(int dev, int mode)
 {
 }
 
-static void
-softsyn_aftertouch(int dev, int voice, int pressure)
+static void softsyn_aftertouch(int dev, int voice, int pressure)
 {
        if (voice < 0 || voice > devc->maxvoice)
                return;
@@ -1270,10 +1247,9 @@ softsyn_aftertouch(int dev, int voice, int pressure)
                update_volume(voice);
 }
 
-static void
-softsyn_controller(int dev, int voice, int ctrl_num, int value)
+static void softsyn_controller(int dev, int voice, int ctrl_num, int value)
 {
-       unsigned long   flags;
+       unsigned long flags;
 
        if (voice < 0 || voice > devc->maxvoice)
                return;
@@ -1281,48 +1257,46 @@ softsyn_controller(int dev, int voice, int ctrl_num, int value)
        cli();
 
        switch (ctrl_num)
-         {
-         case CTRL_PITCH_BENDER:
-                 softoss_voices[voice].bender = value;
-
-                 if (voice_active[voice])
-                         compute_step(voice);  /* Update pitch */
-                 break;
-
-
-         case CTRL_PITCH_BENDER_RANGE:
-                 softoss_voices[voice].bender_range = value;
-                 break;
-         case CTL_EXPRESSION:
-                 value /= 128;
-         case CTRL_EXPRESSION:
-                 softoss_voices[voice].expression_vol = value;
-                 if (voice_active[voice])
-                         update_volume(voice);
-                 break;
-
-         case CTL_PAN:
-                 softsyn_panning(dev, voice, (value * 2) - 128);
-                 break;
-
-         case CTL_MAIN_VOLUME:
-                 value = (value * 100) / 16383;
-
-         case CTRL_MAIN_VOLUME:
-                 softoss_voices[voice].main_vol = value;
-                 if (voice_active[voice])
-                         update_volume(voice);
-                 break;
-
-         default:
-                 break;
-         }
-
+       {
+               case CTRL_PITCH_BENDER:
+                       softoss_voices[voice].bender = value;
+                       if (voice_active[voice])
+                               compute_step(voice);    /* Update pitch */
+                       break;
+
+
+               case CTRL_PITCH_BENDER_RANGE:
+                       softoss_voices[voice].bender_range = value;
+                       break;
+                       
+               case CTL_EXPRESSION:
+                       value /= 128;
+               case CTRL_EXPRESSION:
+                       softoss_voices[voice].expression_vol = value;
+                       if (voice_active[voice])
+                               update_volume(voice);
+                       break;
+
+               case CTL_PAN:
+                       softsyn_panning(dev, voice, (value * 2) - 128);
+                       break;
+
+               case CTL_MAIN_VOLUME:
+                       value = (value * 100) / 16383;
+
+               case CTRL_MAIN_VOLUME:
+                       softoss_voices[voice].main_vol = value;
+                       if (voice_active[voice])
+                               update_volume(voice);
+                       break;
+
+               default:
+                       break;
+       }
        restore_flags(flags);
 }
 
-static void
-softsyn_bender(int dev, int voice, int value)
+static void softsyn_bender(int dev, int voice, int value)
 {
        if (voice < 0 || voice > devc->maxvoice)
                return;
@@ -1332,46 +1306,46 @@ softsyn_bender(int dev, int voice, int value)
                compute_step(voice);    /* Update pitch */
 }
 
-static int
-softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc)
+static int softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc)
 {
-       int             i, p, best = -1, best_time = 0x7fffffff;
+       int i, p, best = -1, best_time = 0x7fffffff;
 
        p = alloc->ptr;
+
        /*
-          * First look for a completely stopped voice
+        * First look for a completely stopped voice
         */
 
        for (i = 0; i < alloc->max_voice; i++)
-         {
-                 if (alloc->map[p] == 0)
-                   {
-                           alloc->ptr = p;
-                           voice_active[p] = 0;
-                           return p;
-                   }
-                 if (alloc->alloc_times[p] < best_time)
-                   {
-                           best = p;
-                           best_time = alloc->alloc_times[p];
-                   }
-                 p = (p + 1) % alloc->max_voice;
-         }
+       {
+               if (alloc->map[p] == 0)
+               {
+                       alloc->ptr = p;
+                       voice_active[p] = 0;
+                       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
+        * Then look for a releasing voice
         */
 
        for (i = 0; i < alloc->max_voice; i++)
-         {
-                 if (alloc->map[p] == 0xffff)
-                   {
-                           alloc->ptr = p;
-                           voice_active[p] = 0;
-                           return p;
-                   }
-                 p = (p + 1) % alloc->max_voice;
-         }
+       {
+               if (alloc->map[p] == 0xffff)
+               {
+                       alloc->ptr = p;
+                       voice_active[p] = 0;
+                       return p;
+               }
+               p = (p + 1) % alloc->max_voice;
+       }
 
        if (best >= 0)
                p = best;
@@ -1381,23 +1355,20 @@ softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc)
        return p;
 }
 
-static void
-softsyn_setup_voice(int dev, int voice, int chn)
+static void softsyn_setup_voice(int dev, int voice, int chn)
 {
-       unsigned long   flags;
+       unsigned long flags;
 
-       struct channel_info *info =
-       &synth_devs[dev]->chn_info[chn];
+       struct channel_info *info = &synth_devs[dev]->chn_info[chn];
 
        save_flags(flags);
        cli();
+
        /* init_voice(devc, voice); */
        softsyn_set_instr(dev, voice, info->pgm_num);
 
-       softoss_voices[voice].expression_vol =
-           info->controllers[CTL_EXPRESSION];  /* Just MSB */
-       softoss_voices[voice].main_vol =
-           (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
+       softoss_voices[voice].expression_vol = info->controllers[CTL_EXPRESSION];       /* Just MSB */
+       softoss_voices[voice].main_vol = (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
        softsyn_panning(dev, voice, (info->controllers[CTL_PAN] * 2) - 128);
        softoss_voices[voice].bender = 0;       /* info->bender_value; */
        softoss_voices[voice].bender_range = info->bender_range;
@@ -1407,11 +1378,10 @@ softsyn_setup_voice(int dev, int voice, int chn)
        restore_flags(flags);
 }
 
-static void
-softsyn_reset(int devno)
+static void softsyn_reset(int devno)
 {
-       int             i;
-       unsigned long   flags;
+       int i;
+       unsigned long flags;
 
        save_flags(flags);
        cli();
@@ -1450,23 +1420,20 @@ static struct synth_operations softsyn_operations =
  * Timer stuff (for /dev/music).
  */
 
-static unsigned int
-soft_tmr_start(int dev, unsigned int usecs)
+static unsigned int soft_tmr_start(int dev, unsigned int usecs)
 {
        tmr_running = 1;
        start_engine(devc);
        return devc->usecs_per_frag;
 }
 
-static void
-soft_tmr_disable(int dev)
+static void soft_tmr_disable(int dev)
 {
        stop_engine(devc);
        tmr_running = 0;
 }
 
-static void
-soft_tmr_restart(int dev)
+static void soft_tmr_restart(int dev)
 {
        tmr_running = 1;
 }
@@ -1480,10 +1447,9 @@ static struct sound_lowlev_timer soft_tmr =
        soft_tmr_restart
 };
 
-int
-probe_softsyn(struct address_info *hw_config)
+int probe_softsyn(struct address_info *hw_config)
 {
-       int             i;
+       int i;
 
        if (softsynth_loaded)
                return 0;
@@ -1492,10 +1458,10 @@ probe_softsyn(struct address_info *hw_config)
        devc->ram_used = 0;
        devc->nrsamples = 0;
        for (i = 0; i < MAX_PATCH; i++)
-         {
-                 devc->programs[i] = NO_SAMPLE;
-                 devc->wave[i] = NULL;
-         }
+       {
+               devc->programs[i] = NO_SAMPLE;
+               devc->wave[i] = NULL;
+       }
 
        devc->maxvoice = DEFAULT_VOICES;
 
@@ -1516,15 +1482,12 @@ probe_softsyn(struct address_info *hw_config)
 #else
        devc->default_max_voices = 32;
 #endif
-
        softsynth_loaded = 1;
        return 1;
 }
 
-void
-attach_softsyn_card(struct address_info *hw_config)
+void attach_softsyn_card(struct address_info *hw_config)
 {
-
        voice_alloc = &softsyn_operations.alloc;
        synth_devs[devc->synthdev = num_synths++] = &softsyn_operations;
        sequencer_init();
@@ -1536,14 +1499,10 @@ attach_softsyn_card(struct address_info *hw_config)
 #endif
 }
 
-void
-unload_softsyn(struct address_info *hw_config)
+void unload_softsyn(struct address_info *hw_config)
 {
        if (!softsynth_loaded)
                return;
-#ifndef POLLED_MODE
-#endif
-
        softsynthp = NULL;
        softsynth_loaded = 0;
        reset_samples(devc);
@@ -1553,10 +1512,9 @@ unload_softsyn(struct address_info *hw_config)
 
 static struct address_info config;
 
-int
-init_module(void)
+int init_module(void)
 {
-       printk("SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n");
+       printk(KERN_INFO "SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n");
        if (!probe_softsyn(&config))
                return -ENODEV;
        attach_softsyn_card(&config);
@@ -1564,8 +1522,7 @@ init_module(void)
        return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
        unload_softsyn(&config);
        sound_unload_synthdev(devc->synthdev);
index f8dac8ed5d277b5387766afc8b5df56c5b5d095e..17ebb8b5986ad9a44a49dc0520428b86137ec7c3 100644 (file)
@@ -5,8 +5,8 @@
  * Software based MIDI synthsesizer driver, the actual mixing loop.
  * Keep the loop as simple as possible to make it easier to rewrite this 
  * routine in assembly.
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
 #if defined(CONFIG_SOFTOSS) || defined(MODULE)
 #include "softoss.h"
 
-void
-softsynth_resample_loop(short *buf, int loops)
+void softsynth_resample_loop(short *buf, int loops)
 {
-       int             iloop, voice;
+       int iloop, voice;
        volatile voice_info *v;
 
 #ifdef OSS_BIG_ENDIAN
@@ -33,104 +32,102 @@ softsynth_resample_loop(short *buf, int loops)
 #endif
 
        for (iloop = 0; iloop < loops; iloop++)
-         {                     /* Mix one sample */
-
-                 int             accum, left = 0, right = 0;
-                 int             ix, position;
-
-                 for (voice = 0; voice < devc->maxvoice; voice++)
-                         if (voice_active[voice])
-                           {   /* Compute voice */
-
-                                   v = &softoss_voices[voice];
+       {                       /* Mix one sample */
+               int accum, left = 0, right = 0;
+               int ix, position;
+
+               for (voice = 0; voice < devc->maxvoice; voice++)
+               {
+                       if (voice_active[voice])
+                       {       /* Compute voice */
+                               v = &softoss_voices[voice];
 #ifdef SOFTOSS_TEST
-                                   ix = iloop << 3;
-                                   position = v->ptr;
+                               ix = iloop << 3;
+                               position = v->ptr;
 #else
-                                   ix = (position = v->ptr) >> 9;
+                               ix = (position = v->ptr) >> 9;
 #endif
-                                   /* Interpolation (resolution of 512 steps) */
-                                   {
-                                           int             fract = v->ptr & 0x1f;      /* 9 bits */
-
-                                           /* This method works with less arithmetic operations */
-                                           register int    v1 = v->wave[ix];
-
-                                           accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9);
-                                   }
-
-                                   left += (accum * v->leftvol);
-                                   right += (accum * v->rightvol);
-
-                                   /* Update sample pointer */
-
-                                   position += v->step;
-                                   if (position <= v->endloop)
-                                           v->ptr = position;
-                                   else if (v->mode & WAVE_LOOPING)
-                                     {
-                                             if (v->mode & WAVE_BIDIR_LOOP)
-                                               {
-                                                       v->mode ^= WAVE_LOOP_BACK;      /* Turn around */
-                                                       v->step *= -1;
-                                             } else
-                                               {
-                                                       position -= v->looplen;
-                                                       v->ptr = position;
-                                               }
-                                     }
-                                   /*  else leave the voice looping the current sample */
-
-                                   if (v->mode & WAVE_LOOP_BACK && position < v->startloop)
-                                     {
-                                             if (v->mode & WAVE_BIDIR_LOOP)
-                                               {
-                                                       v->mode ^= WAVE_LOOP_BACK;      /* Turn around */
-                                                       v->step *= -1;
-                                             } else
-                                               {
-                                                       position += v->looplen;
-                                                       v->ptr = position;
-                                               }
-                                     }
-                           }   /* Compute voice */
+                               /* Interpolation (resolution of 512 steps) */
+                               {
+                                       int fract = v->ptr & 0x1f;      /* 9 bits */
+
+                                       /* This method works with less arithmetic operations */
+                                       register int v1 = v->wave[ix];
+                                       accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9);
+                               }
+
+                               left += (accum * v->leftvol);
+                               right += (accum * v->rightvol);
+
+                               /* Update sample pointer */
+                               position += v->step;
+                               if (position <= v->endloop)
+                                       v->ptr = position;
+                               else if (v->mode & WAVE_LOOPING)
+                               {
+                                       if (v->mode & WAVE_BIDIR_LOOP)
+                                       {                                                       v->mode ^= WAVE_LOOP_BACK;      /* Turn around */
+                                               v->step *= -1;
+                                       }
+                                       else
+                                       {
+                                               position -= v->looplen;
+                                               v->ptr = position;
+                                       }
+                               }
+                               /*  else leave the voice looping the current sample */
+
+                               if (v->mode & WAVE_LOOP_BACK && position < v->startloop)
+                               {
+                                       if (v->mode & WAVE_BIDIR_LOOP)
+                                       {                                                       v->mode ^= WAVE_LOOP_BACK;      /* Turn around */
+                                               v->step *= -1;
+                                       }
+                                       else
+                                       {
+                                               position += v->looplen;
+                                               v->ptr = position;
+                                       }
+                               }
+                       }       /* Compute voice */
+               }
 #if 1                          /* Delay */
-                 left += left_delay[delayp];
-                 right += right_delay[delayp];
+               left += left_delay[delayp];
+               right += right_delay[delayp];
 
-                 left_delay[delayp] = right >> 2;
-                 right_delay[delayp] = left >> 2;
-                 delayp = (delayp + 1) % devc->delay_size;
+               left_delay[delayp] = right >> 2;
+               right_delay[delayp] = left >> 2;
+               delayp = (delayp + 1) % devc->delay_size;
 #endif
 
 #define AFTERSCALE devc->afterscale;
 
-                 left >>= AFTERSCALE;
-                 right >>= AFTERSCALE;
+               left >>= AFTERSCALE;
+               right >>= AFTERSCALE;
 
-                 if (left > 32767)
-                         left = 32767;
-                 if (left < -32768)
-                         left = -32768;
-                 if (right > 32767)
-                         right = 32767;
-                 if (right < -32768)
-                         right = -32768;
+               if (left > 32767)
+                       left = 32767;
+               if (left < -32768)
+                       left = -32768;
+               if (right > 32767)
+                       right = 32767;
+               if (right < -32768)
+                       right = -32768;
 
 #ifdef OSS_BIG_ENDIAN
-                 *cbuf++ = left & 0xff;
-                 *cbuf++ = (left >> 8) & 0xff;
-                 *cbuf++ = right & 0xff;
-                 *cbuf++ = (right >> 8) & 0xff;
+               *cbuf++ = left & 0xff;
+               *cbuf++ = (left >> 8) & 0xff;
+               *cbuf++ = right & 0xff;
+               *cbuf++ = (right >> 8) & 0xff;
 #else
-                 *buf++ = left;
-                 *buf++ = right;
+               *buf++ = left;
+               *buf++ = right;
 #endif
-                 if (devc->control_counter++ >= devc->control_rate)
-                   {
-                           devc->control_counter = 0;
-                           softsyn_control_loop();
-                   }
-         }                     /* Mix one sample */
+               if (devc->control_counter++ >= devc->control_rate)
+               {
+                       devc->control_counter = 0;
+                       softsyn_control_loop();
+               }
+       }                       /* Mix one sample */
 }
 #endif
index 416737f651b3598ef32d9f6e06f88b096184ee2f..2a95950e52199c5d3c68ddb43bd71308c3261d06 100644 (file)
@@ -11,6 +11,7 @@ int DMAbuf_start_output(int dev, int buff_no, int l);
 int DMAbuf_move_wrpointer(int dev, int l);
 /* int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local); */
 void DMAbuf_init(int dev, int dma1, int dma2);
+void DMAbuf_deinit(int dev);
 int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode);
 int DMAbuf_open_dma (int dev);
 void DMAbuf_close_dma (int dev);
@@ -83,15 +84,8 @@ void MIDIbuf_init(void);
 /*     From soundcard.c        */
 void request_sound_timer (int count);
 void sound_stop_timer(void);
-/* These two are about to die.. */
-int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp, void *dev_id);
-void snd_release_irq(int vect, void *ptr);
-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 opl3.c     */
 int opl3_detect (int ioaddr, int *osp);
@@ -187,7 +181,7 @@ 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);
+int     ad1848_control(int cmd, int arg);
 #define                AD1848_SET_XTAL         1
 #define                AD1848_MIXER_REROUTE    2
 #define AD1848_REROUTE(oldctl, newctl) \
@@ -196,9 +190,6 @@ void         ad1848_control(int cmd, int arg);
 void adintr(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);
-void attach_pnp_ad1848(struct address_info * hw_config);
-int probe_pnp_ad1848(struct address_info *hw_config);
-void unload_pnp_ad1848(struct address_info *hw_info);
 
 /*     From pss.c */
 int probe_pss (struct address_info *hw_config);
@@ -235,7 +226,6 @@ void attach_mad16 (struct address_info *hw_config);
 int probe_mad16 (struct address_info *hw_config);
 void attach_mad16_mpu (struct address_info *hw_config);
 int probe_mad16_mpu (struct address_info *hw_config);
-int mad16_sb_dsp_detect (struct address_info *hw_config);
 
 /*     Unload routines from various source files*/
 void unload_pss(struct address_info *hw_info);
@@ -278,3 +268,7 @@ void attach_v_midi (struct address_info *hw_config);
 int probe_v_midi (struct address_info *hw_config);
 void unload_v_midi (struct address_info *hw_config);
 
+/*     From vidc.c */
+void attach_vidc(struct address_info *hw_config);
+int probe_vidc(struct address_info *hw_config);
+void unload_vidc(struct address_info *hw_config);
index cc566e497c999d546c444d938dcd1f59ac151def..97ce9d65711b59322274a640b1acafd87c948816 100644 (file)
@@ -1,3 +1,4 @@
+#include "os.h"
 #define __KERNEL_SYSCALLS__
 #include <linux/fs.h>
 #include <linux/mm.h>
@@ -19,14 +20,14 @@ static int do_mod_firmware_load(const char *fn, char **fp)
                return 0;
        }
        l = lseek(fd, 0L, 2);
-       if (l <= 0 || l > 65535)
+       if (l <= 0 || l > 131072)
        {
                printk(KERN_INFO "Invalid firmware '%s'\n", fn);
                sys_close(fd);
-                 return 0;
+               return 0;
        }
        lseek(fd, 0L, 0);
-       dp = kmalloc(l, GFP_KERNEL);
+       dp = vmalloc(l);
        if (dp == NULL)
        {
                printk(KERN_INFO "Out of memory loading '%s'.\n", fn);
@@ -36,7 +37,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
        if (read(fd, dp, l) != l)
        {
                printk(KERN_INFO "Failed to read '%s'.\n", fn);
-               kfree(dp);
+               vfree(dp);
                sys_close(fd);
                return 0;
        }
@@ -45,7 +46,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
        return (int) l;
 }
 
-int  mod_firmware_load(const char *fn, char **fp)
+int mod_firmware_load(const char *fn, char **fp)
 {
        int r;
        mm_segment_t fs = get_fs();
@@ -55,3 +56,4 @@ int  mod_firmware_load(const char *fn, char **fp)
        set_fs(fs);
        return r;
 }
+
index 648a769a4543b2e6f7def59b4071112d5d8e42be..2758660d565c47e21c4eb8f22bc213545cf872bb 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *    The sound core exports the following symbols to the rest of
- *      modulespace.
+ *     The sound core exports the following symbols to the rest of
+ *     modulespace.
  *
  *      (C) Copyright 1997      Alan Cox, Licensed under the GNU GPL
  */
@@ -9,6 +9,8 @@
 #include "sound_config.h"
 #define _MIDI_SYNTH_C_
 #include "midi_synth.h"
+#define _SEQUENCER_C_
+#include "tuning.h"
 #include <linux/notifier.h>
 #include "sound_firmware.h"
 
@@ -31,16 +33,13 @@ EXPORT_SYMBOL(sound_install_audiodrv);
 EXPORT_SYMBOL(sound_install_mixer);
 EXPORT_SYMBOL(sound_alloc_dma);
 EXPORT_SYMBOL(sound_free_dma);
-EXPORT_SYMBOL(snd_set_irq_handler);
-EXPORT_SYMBOL(snd_release_irq);
+EXPORT_SYMBOL(sound_open_dma);
+EXPORT_SYMBOL(sound_close_dma);
 EXPORT_SYMBOL(sound_alloc_audiodev);
 EXPORT_SYMBOL(sound_alloc_mididev);
 EXPORT_SYMBOL(sound_alloc_mixerdev);
 EXPORT_SYMBOL(sound_alloc_timerdev);
 EXPORT_SYMBOL(sound_alloc_synthdev);
-EXPORT_SYMBOL(sound_mem_blocks);
-EXPORT_SYMBOL(sound_mem_sizes);
-EXPORT_SYMBOL(sound_nblocks);
 EXPORT_SYMBOL(sound_unload_audiodev);
 EXPORT_SYMBOL(sound_unload_mididev);
 EXPORT_SYMBOL(sound_unload_mixerdev);
@@ -90,3 +89,14 @@ EXPORT_SYMBOL(midi_synth_send_sysex);
 EXPORT_SYMBOL(midi_synth_bender);
 EXPORT_SYMBOL(midi_synth_load_patch);
 
+/* Firmware */
+
+EXPORT_SYMBOL(mod_firmware_load);
+
+/* Tuning */
+
+EXPORT_SYMBOL(cent_tuning);
+EXPORT_SYMBOL(semitone_tuning);
+
+MODULE_DESCRIPTION("Sound subsystem");
+MODULE_AUTHOR("Hannu Savolainen, et al.");
index fe3622a737bd63dc1afcc68d578fc8d34cf948cb..42ea158cc40e795181ffc9b1359656b30de79bc8 100644 (file)
@@ -16,8 +16,8 @@
  * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat,
  *                   which should disappear in the near future)
  */
-#include <linux/config.h>
 
+#include <linux/config.h>
 
 #include "sound_config.h"
 #include <linux/types.h>
@@ -28,6 +28,7 @@
 #include <linux/stddef.h>
 #include <linux/kmod.h>
 #ifdef __KERNEL__
+#include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <linux/wait.h>
 #define modular 0
 #endif
 
+/*
+ * This ought to be moved into include/asm/dma.h
+ */
+#ifndef valid_dma
+#define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4)
+#endif
+
 static int      chrdev_registered = 0;
 static int      sound_major = SOUND_MAJOR;
 
@@ -57,12 +65,11 @@ static int      is_unloading = 0;
  * Table for permanently allocated memory (used when unloading the module)
  */
 caddr_t         sound_mem_blocks[1024];
-int             sound_mem_sizes[1024];
 int             sound_nblocks = 0;
 
 static int      soundcard_configured = 0;
 
-static char     dma_alloc_map[8] =
+static char     dma_alloc_map[MAX_DMA_CHANNELS] =
 {0};
 
 #define DMA_MAP_UNAVAIL                0
@@ -788,31 +795,9 @@ soundcard_init(void)
 
 }
 
-static unsigned int irqs = 0;
-
-#ifdef MODULE
-static void
-free_all_irqs(void)
-{
-       int i;
-
-       for (i = 0; i < 31; i++)
-       {
-               if (irqs & (1ul << i))
-               {
-                       printk(KERN_WARNING "Sound warning: IRQ%d was left allocated - fixed.\n", i);
-                       snd_release_irq(i, NULL);
-               }
-       }
-       irqs = 0;
-}
-
-char            kernel_version[] = UTS_RELEASE;
-
-#endif
-
-static int      sound[20] =
-{0};
+static int      sound[20] = {
+       0
+};
 
 int init_module(void)
 {
@@ -876,10 +861,9 @@ void cleanup_module(void)
        }
 #endif
        sound_unload_drivers();
-       free_all_irqs();        /* If something was left allocated by accident */
        sequencer_unload();
 
-       for (i = 0; i < 8; i++)
+       for (i = 0; i < MAX_DMA_CHANNELS; i++)
        {
                if (dma_alloc_map[i] != DMA_MAP_UNAVAIL)
                {
@@ -895,35 +879,6 @@ void cleanup_module(void)
 }
 #endif
 
-int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp, void *dev_id)
-{
-       int retcode;
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-       retcode = request_irq(interrupt_level, iproc, 0, name, dev_id);
-       
-       if (retcode < 0)
-       {
-               printk(KERN_ERR "Sound: IRQ%d already in use\n", interrupt_level);
-       }
-       else
-               irqs |= (1ul << interrupt_level);
-
-       restore_flags(flags);
-       return retcode;
-}
-
-void snd_release_irq(int vect, void *dev_id)
-{
-       if (!(irqs & (1ul << vect)))
-               return;
-
-       irqs &= ~(1ul << vect);
-       free_irq(vect, dev_id);
-}
-
 int sound_alloc_dma(int chn, char *deviceID)
 {
        int err;
@@ -940,7 +895,7 @@ int sound_open_dma(int chn, char *deviceID)
 {
        unsigned long   flags;
 
-       if (chn < 0 || chn > 7 || chn == 4)
+       if (!valid_dma(chn))
        {
                printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn);
                return 1;
index 9b34c4422744de50c2e83e28f77d6c66e5083cc3..1c5820fcd9df085ad588bde8265639b9378e06ba 100644 (file)
@@ -3,14 +3,18 @@
  *
  * Low level driver for the MediaTrix AudioTrix Pro
  * (MT-0002-PC Control Chip)
- */
-/*
+ *
+ *
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
+ *
+ * Changes
+ *     Alan Cox                Modularisation, cleanup.
  */
 #include <linux/config.h>
 #include <linux/module.h>
 
@@ -35,30 +39,27 @@ static int trix_boot_len = 0;
 #endif
 
 
-static int      kilroy_was_here = 0;   /* Don't detect twice */
-static int      sb_initialized = 0;
-static int      mpu_initialized = 0;
+static int kilroy_was_here = 0;        /* Don't detect twice */
+static int sb_initialized = 0;
+static int mpu_initialized = 0;
 
-static int     *trix_osp = NULL;
+static int *trix_osp = NULL;
 
-static unsigned char
-trix_read(int addr)
+static unsigned char trix_read(int addr)
 {
        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)
+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 */
 }
 
-static void
-download_boot(int base)
+static void download_boot(int base)
 {
-       int             i = 0, n = trix_boot_len;
+       int i = 0, n = trix_boot_len;
 
        if (trix_boot_len == 0)
                return;
@@ -83,24 +84,23 @@ download_boot(int base)
 
 }
 
-static int
-trix_set_wss_port(struct address_info *hw_config)
+static int trix_set_wss_port(struct address_info *hw_config)
 {
        unsigned char   addr_bits;
 
        if (check_region(0x390, 2))
-         {
-                 printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
+               return 0;
+       }
        if (kilroy_was_here)    /* Already initialized */
                return 0;
 
        if (trix_read(0x15) != 0x71)    /* No ASIC signature */
-         {
-                 MDB(printk("No AudioTrix ASIC signature found\n"));
-                 return 0;
-         }
+       {
+               MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
+               return 0;
+       }
        kilroy_was_here = 1;
 
        /*
@@ -111,26 +111,26 @@ trix_set_wss_port(struct address_info *hw_config)
        trix_write(0x14, 0);
 
        /*
-          * Configure the ASIC to place the codec to the proper I/O location
+        * Configure the ASIC to place the codec to the proper I/O location
         */
 
        switch (hw_config->io_base)
-         {
-         case 0x530:
-                 addr_bits = 0;
-                 break;
-         case 0x604:
-                 addr_bits = 1;
-                 break;
-         case 0xE80:
-                 addr_bits = 2;
-                 break;
-         case 0xF40:
-                 addr_bits = 3;
-                 break;
-         default:
-                 return 0;
-         }
+       {
+               case 0x530:
+                       addr_bits = 0;
+                       break;
+               case 0x604:
+                       addr_bits = 1;
+                       break;
+               case 0xE80:
+                       addr_bits = 2;
+                       break;
+               case 0xF40:
+                       addr_bits = 3;
+                       break;
+               default:
+                       return 0;
+       }
 
        trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits);
        return 1;
@@ -141,120 +141,123 @@ trix_set_wss_port(struct address_info *hw_config)
  *      AudioTrix Pro
  */
 
-int
-probe_trix_wss(struct address_info *hw_config)
+int probe_trix_wss(struct address_info *hw_config)
 {
-       int             ret;
+       int ret;
 
        /*
-          * Check if the IO port returns valid signature. The original MS Sound
-          * system returns 0x04 while some cards (AudioTrix Pro for example)
-          * return 0x00.
+        * Check if the IO port returns valid signature. The original MS Sound
+        * system returns 0x04 while some cards (AudioTrix Pro for example)
+        * return 0x00.
         */
        if (check_region(hw_config->io_base, 8))
-         {
-                 printk("AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
+               return 0;
+       }
        trix_osp = hw_config->osp;
 
        if (!trix_set_wss_port(hw_config))
                return 0;
 
        if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00)
-         {
-                 MDB(printk("No MSS signature detected on port 0x%x\n", hw_config->io_base));
-                 return 0;
-         }
+       {
+               MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
+               return 0;
+       }
        if (hw_config->irq > 11)
-         {
-                 printk("AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-         {
-                 printk("AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
+               return 0;
+       }
        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);
+               {
+                         printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
                          return 0;
-                 }
+               }
        /*
-          * Check that DMA0 is not in use with a 8 bit board.
+        * Check that DMA0 is not in use with a 8 bit board.
         */
 
        if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
-         {
-                 printk("AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
+               return 0;
+       }
        if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
-         {
-                 printk("AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
+               return 0;
+       }
        ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
 
        if (ret)
-         {
+       {
 #ifdef TRIX_ENABLE_JOYSTICK
-                 trix_write(0x15, 0x80);
+               trix_write(0x15, 0x80);
 #endif
-                 request_region(0x390, 2, "AudioTrix");
-         }
+               request_region(0x390, 2, "AudioTrix");
+       }
        return ret;
 }
 
 void
 attach_trix_wss(struct address_info *hw_config)
 {
-       static unsigned char interrupt_bits[12] =
-       {0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20};
-       char            bits;
+       static unsigned char interrupt_bits[12] = {
+               0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20
+       };
+       char bits;
 
-       static unsigned char dma_bits[4] =
-       {1, 2, 0, 3};
+       static unsigned char dma_bits[4] = {
+               1, 2, 0, 3
+       };
 
-       int             config_port = hw_config->io_base + 0;
-       int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
-       int             old_num_mixers = num_mixers;
+       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;
 
        if (!kilroy_was_here)
-         {
-                 DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
-                 return;
-         }
+       {
+               DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
+               return;
+       }
+       
        /*
-          * Set the IRQ and DMA addresses.
+        * Set the IRQ and DMA addresses.
         */
 
        bits = interrupt_bits[hw_config->irq];
        if (bits == 0)
-         {
-                 printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
-                 return;
-         }
+       {
+               printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
+               return;
+       }
        outb((bits | 0x40), config_port);
 
        if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
-         {
+       {
                  bits |= dma_bits[dma1];
                  dma2 = dma1;
-       } else
-         {
-                 unsigned char   tmp;
+       }
+       else
+       {
+               unsigned char tmp;
 
-                 tmp = trix_read(0x13) & ~30;
-                 trix_write(0x13, tmp | 0x80 | (dma1 << 4));
+               tmp = trix_read(0x13) & ~30;
+               trix_write(0x13, tmp | 0x80 | (dma1 << 4));
 
-                 tmp = trix_read(0x14) & ~30;
-                 trix_write(0x14, tmp | 0x80 | (dma2 << 4));
-         }
+               tmp = trix_read(0x14) & ~30;
+               trix_write(0x14, tmp | 0x80 | (dma2 << 4));
+       }
 
        outb((bits), config_port);      /* Write IRQ+DMA setup */
 
@@ -267,22 +270,22 @@ attach_trix_wss(struct address_info *hw_config)
        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 */
-         }
+       {
+               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
-probe_trix_sb(struct address_info *hw_config)
+int probe_trix_sb(struct address_info *hw_config)
 {
 
-       int             tmp;
-       unsigned char   conf;
-       static char     irq_translate[] =
-       {-1, -1, -1, 0, 1, 2, -1, 3};
+       int tmp;
+       unsigned char conf;
+       static char irq_translate[] = {
+               -1, -1, -1, 0, 1, 2, -1, 3
+       };
 
        if (trix_boot_len == 0)
                return 0;       /* No boot code -> no fun */
@@ -294,10 +297,10 @@ probe_trix_sb(struct address_info *hw_config)
                return 0;
 
        if (check_region(hw_config->io_base, 16))
-         {
-                 printk("AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
+               return 0;
+       }
        if ((hw_config->io_base & 0xffffff8f) != 0x200)
                return 0;
 
@@ -329,11 +332,10 @@ probe_trix_sb(struct address_info *hw_config)
 #endif
 }
 
-void
-attach_trix_sb(struct address_info *hw_config)
+void attach_trix_sb(struct address_info *hw_config)
 {
-       extern int      sb_be_quiet;
-       int             old_quiet;
+       extern int sb_be_quiet;
+       int old_quiet;
 
 #ifdef CONFIG_SBDSP
        hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
@@ -348,8 +350,7 @@ attach_trix_sb(struct address_info *hw_config)
 #endif
 }
 
-void
-attach_trix_mpu(struct address_info *hw_config)
+void attach_trix_mpu(struct address_info *hw_config)
 {
 #if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
        hw_config->name = "AudioTrix Pro";
@@ -357,78 +358,74 @@ attach_trix_mpu(struct address_info *hw_config)
 #endif
 }
 
-int
-probe_trix_mpu(struct address_info *hw_config)
+int probe_trix_mpu(struct address_info *hw_config)
 {
 #ifdef DO_MIDI
-       unsigned char   conf;
-       static char     irq_bits[] =
-       {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
+       unsigned char conf;
+       static char irq_bits[] = {
+               -1, -1, -1, 1, 2, 3, -1, 4, -1, 5
+       };
 
        if (!kilroy_was_here)
-         {
-                 DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
-                 return 0;     /* AudioTrix Pro has not been detected earlier */
-         }
+       {
+               DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
+               return 0;       /* AudioTrix Pro has not been detected earlier */
+       }
        if (!sb_initialized)
-         {
-                 DDB(printk("Trix: SB mode must be initialized before MPU\n"));
-                 return 0;
-         }
+       {
+               DDB(printk("Trix: SB mode must be initialized before MPU\n"));
+               return 0;
+       }
        if (mpu_initialized)
-         {
-                 DDB(printk("Trix: MPU mode already initialized\n"));
-                 return 0;
-         }
+       {
+               DDB(printk("Trix: MPU mode already initialized\n"));
+               return 0;
+       }
        if (check_region(hw_config->io_base, 4))
-         {
-                 printk("AudioTrix: MPU I/O port conflict (%x)\n", hw_config->io_base);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: MPU I/O port conflict (%x)\n", hw_config->io_base);
+               return 0;
+       }
        if (hw_config->irq > 9)
-         {
-                 printk("AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        if (irq_bits[hw_config->irq] == -1)
-         {
-                 printk("AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
-                 return 0;
-         }
+       {
+               printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
+               return 0;
+       }
        switch (hw_config->io_base)
-         {
-         case 0x330:
-                 conf = 0x00;
-                 break;
-         case 0x370:
-                 conf = 0x04;
-                 break;
-         case 0x3b0:
-                 conf = 0x08;
-                 break;
-         case 0x3f0:
-                 conf = 0x0c;
-                 break;
-         default:
-                 return 0;     /* Invalid port */
-         }
+       {
+               case 0x330:
+                       conf = 0x00;
+                       break;
+               case 0x370:
+                       conf = 0x04;
+                       break;
+               case 0x3b0:
+                       conf = 0x08;
+                       break;
+               case 0x3f0:
+                       conf = 0x0c;
+                       break;
+               default:
+                       return 0;       /* Invalid port */
+       }
 
        conf |= irq_bits[hw_config->irq] << 4;
-
        trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
-
        mpu_initialized = 1;
-
        return probe_uart401(hw_config);
 #else
        return 0;
 #endif
 }
 
-void
-unload_trix_wss(struct address_info *hw_config)
+void unload_trix_wss(struct address_info *hw_config)
 {
-       int             dma2 = hw_config->dma2;
+       int dma2 = hw_config->dma2;
 
        if (dma2 == -1)
                dma2 = hw_config->dma;
@@ -444,15 +441,14 @@ unload_trix_wss(struct address_info *hw_config)
        sound_unload_audiodev(hw_config->slots[0]);
 }
 
-void
-unload_trix_mpu(struct address_info *hw_config)
+void unload_trix_mpu(struct address_info *hw_config)
 {
 #ifdef DO_MIDI
        unload_uart401(hw_config);
 #endif
 }
-void
-unload_trix_sb(struct address_info *hw_config)
+
+void unload_trix_sb(struct address_info *hw_config)
 {
 #ifdef CONFIG_SBDSP
        sb_dsp_unload(hw_config);
@@ -473,6 +469,18 @@ int             sb_irq = -1;
 int             mpu_io = -1;
 int             mpu_irq = -1;
 
+EXPORT_NO_SYMBOLS;
+
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma2,"i");
+MODULE_PARM(sb_io,"i");
+MODULE_PARM(sb_dma,"i");
+MODULE_PARM(sb_irq,"i");
+MODULE_PARM(mpu_io,"i");
+MODULE_PARM(mpu_irq,"i");
+
 struct address_info config;
 struct address_info sb_config;
 struct address_info mpu_config;
@@ -482,16 +490,15 @@ static int      sb = 0;
 
 static int      fw_load;
 
-int 
-init_module(void)
+int init_module(void)
 {
-       printk("MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
+       printk(KERN_INFO "MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
        if (io == -1 || dma == -1 || irq == -1)
-         {
-                 printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
-                 return -EINVAL;
-         }
+       {
+               printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
+               return -EINVAL;
+       }
        config.io_base = io;
        config.irq = irq;
        config.dma = dma;
@@ -505,21 +512,21 @@ init_module(void)
        mpu_config.irq = mpu_irq;
 
        if (sb_io != -1 && (sb_irq == -1 || sb_dma == -1))
-         {
-                 printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n");
-                 return -EINVAL;
-         }
+       {
+               printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n");
+               return -EINVAL;
+       }
        if (mpu_io != -1 && mpu_irq == -1)
-         {
-                 printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n");
-                 return -EINVAL;
-         }
+       {
+               printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n");
+               return -EINVAL;
+       }
        if (!trix_boot)
-         {
-                 fw_load = 1;
-                 trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
+       {
+               fw_load = 1;
+               trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
                                                    (char **) &trix_boot);
-         }
+       }
        if (!probe_trix_wss(&config))
                return -ENODEV;
        attach_trix_wss(&config);
@@ -530,26 +537,26 @@ init_module(void)
         */
 
        if (sb_io != -1)
-         {
-                 sb = probe_trix_sb(&sb_config);
-                 if (sb)
-                         attach_trix_sb(&sb_config);
-         }
+       {
+               sb = probe_trix_sb(&sb_config);
+               if (sb)
+                       attach_trix_sb(&sb_config);
+       }
+       
        if (mpu_io != -1)
-         {
-                 mpu = probe_trix_mpu(&mpu_config);
-                 if (mpu)
-                         attach_trix_mpu(&mpu_config);
-         }
+       {
+               mpu = probe_trix_mpu(&mpu_config);
+               if (mpu)
+                       attach_trix_mpu(&mpu_config);
+       }
        SOUND_LOCK;
        return 0;
 }
 
-void 
-cleanup_module(void)
+void cleanup_module(void)
 {
        if (fw_load && trix_boot)
-               kfree(trix_boot);
+               vfree(trix_boot);
        if (sb)
                unload_trix_sb(&sb_config);
        if (mpu)
index 2e7ed2a2783fd04d271831503de7a25422101c5d..4d8857e569dd11f0c06d7d3d4a4a633f89456842 100644 (file)
@@ -12,7 +12,8 @@
  *
  * Changes:
  *     Alan Cox        Reformatted, removed sound_mem usage, use normal Linux
- *                     interrupt allocation.
+ *                     interrupt allocation. Protect against bogus unload
+ *                     Fixed to allow IRQ > 15
  *
  * Status:
  *             Untested
@@ -244,6 +245,7 @@ void attach_uart401(struct address_info *hw_config)
        uart401_devc *devc;
        char *name = "MPU-401 (UART) MIDI";
 
+       
        if (hw_config->name)
                name = hw_config->name;
 
@@ -269,12 +271,6 @@ void attach_uart401(struct address_info *hw_config)
        else
                devc->share_irq = 0;
 
-       if (devc->irq < 1 || devc->irq > 15)
-       {
-               kfree(devc);
-               return;
-       }
-
        if (!devc->share_irq)
        {
                if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0)
@@ -345,6 +341,7 @@ static int reset_uart401(uart401_devc * devc)
                for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--);
                devc->input_byte = 0;
                uart401_cmd(devc, MPU_RESET);
+
                /*
                 * Wait at least 25 msec. This method is not accurate so let's make the
                 * loop bit longer. Cannot sleep since this is called during boot.
@@ -387,6 +384,8 @@ int probe_uart401(struct address_info *hw_config)
 
        DDB(printk("Entered probe_uart401()\n"));
 
+       /* Default to "not found" */
+       hw_config->slots[4] = -1;
        detected_devc = NULL;
 
        if (check_region(hw_config->io_base, 4))
@@ -415,6 +414,14 @@ int probe_uart401(struct address_info *hw_config)
 void unload_uart401(struct address_info *hw_config)
 {
        uart401_devc *devc;
+       int n=hw_config->slots[4];
+       
+       /* Not set up */
+       if(n==-1 || midi_devs[n]==NULL)
+               return;
+               
+       /* Not allocated (erm ??) */
+       
        devc = midi_devs[hw_config->slots[4]]->devc;
        if (devc == NULL)
                return;
index b26e75a89eb9268ac69f9f7e9be03719365f20c8..75b02ff94a479d53efa358a17fdf79d3b702896a 100644 (file)
@@ -325,6 +325,8 @@ int irq = -1;
 MODULE_PARM(io,"i");
 MODULE_PARM(irq,"i");
 
+EXPORT_NO_SYMBOLS;
+
 struct address_info cfg;
 
 int init_module(void)
diff --git a/drivers/sound/vidc.c b/drivers/sound/vidc.c
new file mode 100644 (file)
index 0000000..8966959
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *     drivers/sound/vidc.c
+ *
+ *     Detection routine for the VIDC.
+ *
+ *     Copyright (C) 1997 by Russell King <rmk@arm.uk.linux.org>
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include "sound_config.h"
+
+#include "vidc.h"
+
+int vidc_busy;
+
+void vidc_update_filler(int bits, int channels)
+{
+       int filltype;
+
+       filltype = bits + channels;
+       switch (filltype)
+       {
+               default:
+               case 9:
+                       vidc_filler = vidc_fill_1x8;
+                       break;
+               case 10:
+                       vidc_filler = vidc_fill_2x8;
+                       break;
+               case 17:
+                       vidc_filler = vidc_fill_1x16;
+                       break;
+               case 18:
+                       vidc_filler = vidc_fill_2x16;
+                       break;
+       }
+}
+
+void attach_vidc(struct address_info *hw_config)
+{
+       char name[32];
+       int i;
+
+       sprintf(name, "VIDC %d-bit sound", hw_config->card_subtype);
+       conf_printf(name, hw_config);
+
+       for (i = 0; i < 2; i++)
+       {
+               dma_buf[i] = get_free_page(GFP_KERNEL);
+               dma_pbuf[i] = virt_to_phys(dma_buf[i]);
+       }
+
+       if (sound_alloc_dma(hw_config->dma, "VIDCsound"))
+       {
+               printk(KERN_ERR "VIDCsound: can't allocate virtual DMA channel\n");
+               return;
+       }
+       if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, "VIDCsound", NULL))
+       {
+               printk(KERN_ERR "VIDCsound: can't allocate DMA interrupt\n");
+               return;
+       }
+       vidc_synth_init(hw_config);
+       vidc_audio_init(hw_config);
+       vidc_mixer_init(hw_config);
+}
+
+int probe_vidc(struct address_info *hw_config)
+{
+       hw_config->irq = IRQ_DMAS0;
+       hw_config->dma = DMA_VIRTUAL_SOUND;
+       hw_config->dma2 = -1;
+       hw_config->card_subtype = 16;
+       return 1;
+}
+
+void unload_vidc(struct address_info *hw_config)
+{
+       free_irq(hw_config->irq, NULL);
+       sound_free_dma(hw_config->dma);
+}
diff --git a/drivers/sound/vidc.h b/drivers/sound/vidc.h
new file mode 100644 (file)
index 0000000..33625f3
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * drivers/sound/vidc.h
+ *
+ * VIDC sound function prototypes
+ *
+ * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org>
+ */
+
+/* vidc.c */
+
+extern int vidc_busy;
+
+/* vidc_fill.S */
+
+/*
+ * Filler routines for different channels and sample sizes
+ */
+
+extern unsigned long vidc_fill_1x8(unsigned long ibuf, unsigned long iend,
+                                  unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x8(unsigned long ibuf, unsigned long iend,
+                                  unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x16(unsigned long ibuf, unsigned long iend,
+                                   unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x16(unsigned long ibuf, unsigned long iend,
+                                   unsigned long obuf, int mask);
+
+/*
+ * DMA Interrupt handler
+ */
+
+extern void vidc_sound_dma_irq(int irqnr, void *ref, struct pt_regs *regs);
+
+/*
+ * Filler routine pointer
+ */
+
+extern unsigned long (*vidc_filler) (unsigned long ibuf, unsigned long iend,
+                                    unsigned long obuf, int mask);
+
+/*
+ * Virtual DMA buffer exhausted
+ */
+
+extern void     (*dma_interrupt) (void);
+
+/*
+ * Virtual DMA buffer addresses
+ */
+
+extern unsigned long dma_start, dma_count, dma_bufsize;
+extern unsigned long dma_buf[2], dma_pbuf[2];
+
+/* vidc_audio.c */
+
+extern void     vidc_audio_init(struct address_info *hw_config);
+extern int      vidc_audio_get_volume(void);
+extern int      vidc_audio_set_volume(int vol);
+
+/* vidc_mixer.c */
+
+extern void     vidc_mixer_init(struct address_info *hw_config);
+
+/* vidc_synth.c */
+
+extern void     vidc_synth_init(struct address_info *hw_config);
+extern int      vidc_synth_get_volume(void);
+extern int      vidc_synth_set_volume(int vol);
diff --git a/drivers/sound/vidc_audio.c b/drivers/sound/vidc_audio.c
new file mode 100644 (file)
index 0000000..59ea01b
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * drivers/sound/vidc_audio.c
+ *
+ * Audio routines for the VIDC
+ *
+ * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org>
+ */
+
+#include <linux/config.h>
+#include "sound_config.h"
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include "vidc.h"
+
+/*
+ * VIDC sound
+ *
+ * When using SERIAL SOUND mode (external DAC), the number of physical
+ * channels is fixed at 2.  Therefore, the sample rate = vidc sample rate.
+ */
+
+static int      vidc_adev;
+
+static int      vidc_audio_volume;
+static int      vidc_audio_rate;
+static char     vidc_audio_bits;
+static char     vidc_audio_channels;
+
+extern void     vidc_update_filler(int bits, int channels);
+
+int  vidc_audio_get_volume(void)
+{
+       return vidc_audio_volume;
+}
+
+int vidc_audio_set_volume(int newvol)
+{
+       vidc_audio_volume = newvol;
+       return vidc_audio_volume;
+}
+
+static int vidc_audio_set_bits(int bits)
+{
+       switch (bits)
+       {
+               case AFMT_QUERY:
+                       break;
+               case AFMT_U8:
+               case AFMT_S16_LE:
+                       vidc_audio_bits = bits;
+                       vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+                       break;
+               default:
+                       vidc_audio_bits = 16;
+                       vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+                       break;
+       }
+       return vidc_audio_bits;
+}
+
+static int vidc_audio_set_rate(int rate)
+{
+       if (rate)
+       {
+               int newsize, new2size;
+
+               vidc_audio_rate = ((500000 / rate) + 1) >> 1;
+               if (vidc_audio_rate < 3)
+                       vidc_audio_rate = 3;
+               if (vidc_audio_rate > 255)
+                       vidc_audio_rate = 255;
+               outl((vidc_audio_rate - 2) | 0xb0000000, VIDC_BASE);
+               outl(0xb1000003, VIDC_BASE);
+               newsize = (10000 / vidc_audio_rate) & ~3;
+               if (newsize < 208)
+                       newsize = 208;
+               if (newsize > 4096)
+                       newsize = 4096;
+               for (new2size = 128; new2size < newsize; new2size <<= 1);
+                       if (new2size - newsize > newsize - (new2size >> 1))
+                               new2size >>= 1;
+               dma_bufsize = new2size;
+       }
+       return 250000 / vidc_audio_rate;
+}
+
+static int vidc_audio_set_channels(int channels)
+{
+       switch (channels)
+       {
+               case 0:
+                       break;
+               case 1:
+               case 2:
+                       vidc_audio_channels = channels;
+                       vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+                       break;
+               default:
+                       vidc_audio_channels = 2;
+                       vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+                       break;
+       }
+       return vidc_audio_channels;
+}
+
+/*
+ * Open the device
+ *
+ * dev  - device
+ * mode - mode to open device (logical OR of OPEN_READ and OPEN_WRITE)
+ *
+ * Called when opening the DMAbuf               (dmabuf.c:259)
+ */
+
+static int vidc_audio_open(int dev, int mode)
+{
+       if (vidc_busy)
+               return -EBUSY;
+
+       if ((mode & OPEN_READ) && (!mode & OPEN_WRITE))
+       {
+               /* This audio device doesn't have recording capability */
+               return -EIO;
+       }
+       vidc_busy = 1;
+       return 0;
+}
+
+/*
+ * Close the device
+ *
+ * dev  - device
+ *
+ * Called when closing the DMAbuf               (dmabuf.c:477)
+ *      after halt_xfer
+ */
+
+static void vidc_audio_close(int dev)
+{
+       vidc_busy = 0;
+}
+
+static int vidc_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+       int ret;
+
+       switch (cmd)
+       {
+               case SOUND_PCM_WRITE_RATE:
+                       if (get_user(ret, (int *) arg))
+                               return -EFAULT;
+                       ret = vidc_audio_set_rate(ret);
+                       break;
+
+               case SOUND_PCM_READ_RATE:
+                       ret = vidc_audio_set_rate(0);
+                       break;
+
+               case SNDCTL_DSP_STEREO:
+                       if (get_user(ret, (int *) arg))
+                               return -EFAULT;
+                       ret = vidc_audio_set_channels(ret + 1) - 1;
+                       break;
+
+               case SOUND_PCM_WRITE_CHANNELS:
+                       if (get_user(ret, (int *) arg))
+                               return -EFAULT;
+                       ret = vidc_audio_set_channels(ret);
+                       break;
+
+               case SOUND_PCM_READ_CHANNELS:
+                       ret = vidc_audio_set_channels(0);
+                       break;
+
+               case SNDCTL_DSP_SETFMT:
+                       if (get_user(ret, (int *) arg))
+                               return -EFAULT;
+                       ret = vidc_audio_set_bits(ret);
+                       break;
+
+               case SOUND_PCM_READ_BITS:
+                       ret = vidc_audio_set_bits(0);
+                       break;
+
+               case SOUND_PCM_WRITE_FILTER:
+               case SOUND_PCM_READ_FILTER:
+                       return -EINVAL;
+
+               default:
+                       return -EINVAL;
+       }
+       return put_user(ret, (int *) arg);
+}
+
+/*
+ * Output a block via DMA to sound device
+ *
+ * dev          - device number
+ * buf          - physical address of buffer
+ * total_count  - total byte count in buffer
+ * intrflag     - set if this has been called from an interrupt (via DMAbuf_outputintr)
+ * restart_dma  - set if DMA needs to be re-initialised
+ *
+ * Called when:
+ *  1. Starting output                                  (dmabuf.c:1327)
+ *  2.                                                  (dmabuf.c:1504)
+ *  3. A new buffer needs to be sent to the device      (dmabuf.c:1579)
+ */
+static void vidc_audio_dma_interrupt(void)
+{
+       DMAbuf_outputintr(vidc_adev, 1);
+}
+
+static void vidc_audio_output_block(int dev, unsigned long buf, int total_count,
+                       int intrflag)
+{
+       dma_start = buf;
+       dma_count = total_count;
+
+       if (!intrflag)
+       {
+               dma_interrupt = vidc_audio_dma_interrupt;
+               vidc_sound_dma_irq(0, NULL, NULL);
+               outb(DMA_CR_D | DMA_CR_E, IOMD_SD0CR);
+       }
+}
+
+static void vidc_audio_start_input(int dev, unsigned long buf, int count,
+                      int intrflag)
+{
+}
+
+static int vidc_audio_prepare_for_input(int dev, int bsize, int bcount)
+{
+       return -EINVAL;
+}
+
+/*
+ * Prepare for outputting samples to `dev'
+ *
+ * Each buffer that will be passed will be `bsize' bytes long,
+ * with a total of `bcount' buffers.
+ *
+ * Called when:
+ *  1. A trigger enables audio output                   (dmabuf.c:978)
+ *  2. We get a write buffer without dma_mode setup     (dmabuf.c:1152)
+ *  3. We restart a transfer                            (dmabuf.c:1324)
+ */
+
+static int vidc_audio_prepare_for_output(int dev, int bsize, int bcount)
+{
+       return 0;
+}
+
+static void vidc_audio_reset(int dev)
+{
+}
+
+/*
+ * Halt a DMA transfer to `dev'
+ *
+ * Called when:
+ *  1. We close the DMAbuf                                      (dmabuf.c:476)
+ *  2. We run out of output buffers to output to the device.    (dmabuf.c:1456)
+ *  3. We run out of output buffers and we're closing down.     (dmabuf.c:1546)
+ *  4. We run out of input buffers in AUTOMODE.                 (dmabuf.c:1651)
+ */
+static void vidc_audio_halt_xfer(int dev)
+{
+       dma_count = 0;
+}
+
+static int vidc_audio_local_qlen(int dev)
+{
+       return dma_count != 0;
+}
+
+static struct audio_driver vidc_audio_driver =
+{
+       vidc_audio_open,                /* open                 */
+       vidc_audio_close,               /* close                */
+       vidc_audio_output_block,        /* output_block         */
+       vidc_audio_start_input,         /* start_input          */
+       vidc_audio_ioctl,               /* ioctl                */
+       vidc_audio_prepare_for_input,   /* prepare_for_input    */
+       vidc_audio_prepare_for_output,  /* prepare_for_output   */
+       vidc_audio_reset,               /* reset                */
+       vidc_audio_halt_xfer,           /* halt_xfer            */
+       vidc_audio_local_qlen,          /*+local_qlen           */
+       NULL,                           /*+copy_from_user       */
+       NULL,                           /*+halt_input           */
+       NULL,                           /*+halt_output          */
+       NULL,                           /*+trigger              */
+       NULL,                           /*+set_speed            */
+       NULL,                           /*+set_bits             */
+       NULL,                           /*+set_channels         */
+};
+
+static struct audio_operations vidc_audio_operations =
+{
+       "VIDCsound",
+       0,
+       AFMT_U8 | AFMT_S16_LE,
+       NULL,
+       &vidc_audio_driver
+};
+
+void vidc_audio_init(struct address_info *hw_config)
+{
+       vidc_audio_volume = 100 | (100 << 8);
+       if ((vidc_adev = sound_alloc_audiodev())!=-1)
+       {
+               audio_devs[vidc_adev] = &vidc_audio_operations;
+               audio_devs[vidc_adev]->min_fragment = 10;       /* 1024 bytes => 64 buffers */
+               audio_devs[vidc_adev]->mixer_dev = num_mixers;
+               audio_devs[vidc_adev]->flags |= 0;
+       }
+       else printk(KERN_ERR "VIDCsound: Too many PCM devices available\n");
+}
diff --git a/drivers/sound/vidc_fill.S b/drivers/sound/vidc_fill.S
new file mode 100644 (file)
index 0000000..841fe5b
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * sound/vidc_fill.S
+ *
+ * Filler routines for DMA buffers
+ *
+ * Copyright (C) 1997 Russell King
+ */
+#define __ASSEMBLY__
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+               .text
+
+ENTRY(vidc_fill_1x8)
+               mov     ip, #0xff00
+1:             cmp     r0, r1
+               bge     SYMBOL_NAME(vidc_clear)
+               ldrb    r4, [r0], #1
+               and     r4, ip, r4, lsl #8
+               orr     r4, r4, r4, lsl #16
+               str     r4, [r2], #4
+               cmp     r2, r3
+               blt     1b
+               mov     pc, lr
+
+ENTRY(vidc_fill_2x8)
+               mov     ip, #0xff00
+1:             cmp     r0, r1
+               bge     SYMBOL_NAME(vidc_clear)
+               ldr     r4, [r0], #2
+               and     r5, r4, ip
+               and     r4, ip, r4, lsl #8
+               orr     r4, r4, r5, lsl #16
+               orr     r4, r4, r4, lsr #8
+               str     r4, [r2], #4
+               cmp     r2, r3
+               blt     1b
+               mov     pc, lr
+
+ENTRY(vidc_fill_1x16)
+               mov     ip, #0xff00
+               orr     ip, ip, ip, lsr #8
+1:             cmp     r0, r1
+               bge     SYMBOL_NAME(vidc_clear)
+               ldr     r5, [r0], #2
+               and     r4, r5, ip
+               orr     r4, r4, r4, lsl #16
+               str     r4, [r2], #4
+               cmp     r0, r1
+               addlt   r0, r0, #2
+               andlt   r4, r5, ip, lsl #16
+               orrlt   r4, r4, r4, lsr #16
+               strlt   r4, [r2], #4
+               cmp     r2, r3
+               blt     1b
+               mov     pc, lr
+
+ENTRY(vidc_fill_2x16)
+               mov     ip, #0xff00
+               orr     ip, ip, ip, lsr #8
+1:             cmp     r0, r1
+               bge     SYMBOL_NAME(vidc_clear)
+               ldr     r4, [r0], #4
+               str     r4, [r2], #4
+               cmp     r0, r1
+               ldrlt   r4, [r0], #4
+               strlt   r4, [r2], #4
+               cmp     r2, r3
+               blt     1b
+               mov     pc, lr
+
+ENTRY(vidc_fill_noaudio)
+               mov     r0, #0
+               mov     r1, #0
+2:             mov     r4, #0
+               mov     r5, #0
+1:             cmp     r2, r3
+               stmltia r2!, {r0, r1, r4, r5}
+               blt     1b
+               mov     pc, lr
+
+ENTRY(vidc_clear)
+               mov     r0, #0
+               mov     r1, #0
+               tst     r2, #4
+               str     r0, [r2], #4
+               tst     r2, #8
+               stmia   r2!, {r0, r1}
+               b       2b
+
+/*
+ * Call filler routines with:
+ *  r0 = phys address
+ *  r1 = phys end
+ *  r2 = buffer
+ * Returns:
+ *  r0 = new buffer address
+ *  r2 = new buffer finish
+ *  r4 = corrupted
+ *  r5 = corrupted
+ *  ip = corrupted
+ */
+
+ENTRY(vidc_sound_dma_irq)
+               stmfd   sp!, {r4 - r9, lr}
+               ldr     r9, =SYMBOL_NAME(dma_start)
+               ldmia   r9, {r0, r1, r2, r3, r4, r5}
+               teq     r1, #0
+               adreq   r4, SYMBOL_NAME(vidc_fill_noaudio)
+               moveq   r8, #1 << 31
+               movne   r8, #0
+               mov     ip, #IOMD_BASE & 0xff000000
+               orr     ip, ip, #IOMD_BASE & 0x00ff0000
+               ldrb    r7, [ip, #IOMD_SD0ST]
+               tst     r7, #DMA_ST_OFL                 @ Check for overrun
+               eorne   r7, r7, #DMA_ST_AB
+               tst     r7, #DMA_ST_AB
+               moveq   r2, r3                          @ DMAing A, update B
+               add     r3, r2, r5                      @ End of DMA buffer
+               add     r1, r1, r0                      @ End of virtual DMA buffer
+               mov     lr, pc
+               mov     pc, r4                          @ Call fill routine
+               sub     r1, r1, r0                      @ Remaining length
+               stmia   r9, {r0, r1}
+               mov     r0, #0
+               tst     r2, #4                          @ Round buffer up to 4 words
+               strne   r0, [r2], #4
+               tst     r2, #8
+               strne   r0, [r2], #4
+               strne   r0, [r2], #4
+               sub     r2, r2, #16
+               mov     r2, r2, lsl #20
+               movs    r2, r2, lsr #20
+               orreq   r2, r2, #1 << 30                @ Set L bit
+               orr     r2, r2, r8
+               ldmdb   r9, {r3, r4, r5}
+               tst     r7, #DMA_ST_AB
+               mov     ip, #IOMD_BASE & 0xff000000
+               orr     ip, ip, #IOMD_BASE & 0x00ff0000
+               streq   r4, [ip, #IOMD_SD0CURB]
+               strne   r5, [ip, #IOMD_SD0CURA]
+               streq   r2, [ip, #IOMD_SD0ENDB]
+               strne   r2, [ip, #IOMD_SD0ENDA]
+               ldr     r6, [ip, #IOMD_SD0ST]
+               tst     r6, #DMA_ST_OFL
+               bne     1f
+               tst     r7, #DMA_ST_AB
+               strne   r4, [ip, #IOMD_SD0CURB]
+               streq   r5, [ip, #IOMD_SD0CURA]
+               strne   r2, [ip, #IOMD_SD0ENDB]
+               streq   r2, [ip, #IOMD_SD0ENDA]
+1:             teq     r8, #0
+               mov     r0, #0x10
+               strneb  r0, [ip, #IOMD_SD0CR]
+               teqeq   r1, #0
+               ldmfd   sp!, {r4 - r9, lr}
+               moveq   pc, r3                          @ Call interrupt routine
+               mov     pc, lr
+
+               .data
+               .globl  SYMBOL_NAME(dma_interrupt)
+SYMBOL_NAME(dma_interrupt):
+               .long   0
+               .globl  SYMBOL_NAME(dma_pbuf)
+SYMBOL_NAME(dma_pbuf):
+               .long   0
+               .long   0
+               .globl  SYMBOL_NAME(dma_start)
+SYMBOL_NAME(dma_start):
+               .long   0
+               .globl  SYMBOL_NAME(dma_count)
+SYMBOL_NAME(dma_count):
+               .long   0
+               .globl  SYMBOL_NAME(dma_buf)
+SYMBOL_NAME(dma_buf):
+               .long   0
+               .long   0
+               .globl  SYMBOL_NAME(vidc_filler)
+SYMBOL_NAME(vidc_filler):
+               .long   SYMBOL_NAME(vidc_fill_noaudio)
+               .globl  SYMBOL_NAME(dma_bufsize)
+SYMBOL_NAME(dma_bufsize):
+               .long   0x1000
diff --git a/drivers/sound/vidc_mixer.c b/drivers/sound/vidc_mixer.c
new file mode 100644 (file)
index 0000000..b9c8b4c
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * drivers/sound/vidc_mixer.c
+ *
+ * Mixer routines for VIDC
+ *
+ * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org>
+ */
+
+#include <linux/config.h>
+#include "sound_config.h"
+
+#include "vidc.h"
+
+int vidc_volume;
+
+static int vidc_get_volume(void)
+{
+       return vidc_volume;
+}
+
+static int vidc_set_volume(int newvol)
+{
+       vidc_volume = newvol;
+/*  printk ("vidc_set_volume: %X\n", newvol); */
+       return newvol;
+}
+
+static int vidc_default_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+       int ret;
+
+       switch (cmd)
+       {
+               case SOUND_MIXER_READ_VOLUME:
+                       ret = vidc_get_volume();
+                       break;
+
+               case SOUND_MIXER_WRITE_VOLUME:
+                       if (get_user(ret, (int *) arg))
+                               return -EINVAL;
+                       ret = vidc_set_volume(ret);
+                       break;
+
+               case SOUND_MIXER_READ_BASS:
+               case SOUND_MIXER_WRITE_BASS:
+               case SOUND_MIXER_READ_TREBLE:
+               case SOUND_MIXER_WRITE_TREBLE:
+                       ret = 50;
+                       break;
+
+               case SOUND_MIXER_READ_SYNTH:
+                       ret = vidc_synth_get_volume();
+                       break;
+
+               case SOUND_MIXER_WRITE_SYNTH:
+                       if (get_user(ret, (int *) arg))
+                               return -EINVAL;
+                       ret = vidc_synth_set_volume(ret);
+                       break;
+
+               case SOUND_MIXER_READ_PCM:
+                       ret = vidc_audio_get_volume();
+                       break;
+
+               case SOUND_MIXER_WRITE_PCM:
+                       if (get_user(ret, (int *) arg))
+                               return -EINVAL;
+                       ret = vidc_audio_set_volume(ret);
+                       break;
+
+               case SOUND_MIXER_READ_SPEAKER:
+                       ret = 100;
+                       break;
+
+               case SOUND_MIXER_WRITE_SPEAKER:
+                       ret = 100;
+                       break;
+
+               case SOUND_MIXER_READ_LINE:
+               case SOUND_MIXER_WRITE_LINE:
+               case SOUND_MIXER_READ_MIC:
+               case SOUND_MIXER_WRITE_MIC:
+                       ret = 0;
+                       break;
+
+               case SOUND_MIXER_READ_CD:
+               case SOUND_MIXER_WRITE_CD:
+                       ret = 100 | (100 << 8);
+                       break;
+
+               case SOUND_MIXER_READ_IMIX:
+               case SOUND_MIXER_WRITE_IMIX:
+               case SOUND_MIXER_READ_ALTPCM:
+               case SOUND_MIXER_WRITE_ALTPCM:
+               case SOUND_MIXER_READ_LINE1:
+               case SOUND_MIXER_WRITE_LINE1:
+               case SOUND_MIXER_READ_LINE2:
+               case SOUND_MIXER_WRITE_LINE2:
+               case SOUND_MIXER_READ_LINE3:
+               case SOUND_MIXER_WRITE_LINE3:
+                       ret = 0;
+                       break;
+
+               case SOUND_MIXER_READ_RECSRC:
+                       ret = 0;
+                       break;
+
+               case SOUND_MIXER_WRITE_RECSRC:
+                       return -EINVAL;
+                       break;
+
+               case SOUND_MIXER_READ_DEVMASK:
+                       ret = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH;
+                       break;
+
+               case SOUND_MIXER_READ_RECMASK:
+                       ret = 0;
+                       break;
+
+               case SOUND_MIXER_READ_STEREODEVS:
+                       ret = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH;
+                       break;
+
+               case SOUND_MIXER_READ_CAPS:
+                       ret = 0;
+                       break;
+
+               case SOUND_MIXER_READ_MUTE:
+                       return -EINVAL;
+                       break;
+
+               default:
+                       return -EINVAL;
+                       break;
+       }
+       return put_user(ret, (int *) arg);
+}
+
+static struct mixer_operations vidc_mixer_operations = {
+       "VIDC",
+       "VIDCsound",
+       vidc_default_mixer_ioctl        /* ioctl                */
+};
+
+void vidc_mixer_init(struct address_info *hw_config)
+{
+       int vidc_mixer = sound_alloc_mixerdev();
+       vidc_volume = 100 | (100 << 8);
+       if (num_mixers < MAX_MIXER_DEV)
+               mixer_devs[vidc_mixer] = &vidc_mixer_operations;
+}
diff --git a/drivers/sound/vidc_synth.c b/drivers/sound/vidc_synth.c
new file mode 100644 (file)
index 0000000..556af84
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * drivers/sound/vidc_synth.c
+ *
+ * Synthesizer routines for the VIDC
+ *
+ * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org>
+ */
+#include <linux/config.h>
+#include "sound_config.h"
+
+#include "vidc.h"
+
+static struct synth_info vidc_info =
+{
+       "VIDCsound",            /* name                 */
+       0,                      /* device               */
+       SYNTH_TYPE_SAMPLE,      /* synth_type           */
+       0,                      /* synth_subtype        */
+       0,                      /* perc_mode            */
+       16,                     /* nr_voices            */
+       0,                      /* nr_drums             */
+       0,                      /* instr_bank_size      */
+       0,                      /* capabilities         */
+};
+
+int             vidc_sdev;
+int             vidc_synth_volume;
+
+static int vidc_synth_open(int dev, int mode)
+{
+       if (vidc_busy)
+               return -EBUSY;
+
+       vidc_busy = 1;
+       return 0;
+}
+
+static void vidc_synth_close(int dev)
+{
+       vidc_busy = 0;
+}
+
+
+static struct synth_operations vidc_synth_operations =
+{
+       &vidc_info,             /* info                 */
+       0,                      /* midi_dev             */
+       SYNTH_TYPE_SAMPLE,      /* synth_type           */
+                               /*SAMPLE_TYPE_XXX */ 0,
+                               /* SAMPLE_TYPE GUS *//* synth_subtype                */
+       vidc_synth_open,        /* open                 */
+       vidc_synth_close,       /* close                */
+       NULL,                   /* ioctl                */
+       NULL,                   /* kill_note            */
+       NULL,                   /* start_note           */
+       NULL,                   /* set_instr            */
+       NULL,                   /* reset                */
+       NULL,                   /* hw_control           */
+       NULL,                   /* load_patch           */
+       NULL,                   /* aftertouch           */
+       NULL,                   /* controller           */
+       NULL,                   /* panning              */
+       NULL,                   /* volume_method        */
+       NULL,                   /* patchmgr             */
+       NULL,                   /* bender               */
+       NULL,                   /* alloc                */
+       NULL,                   /* setup_voice          */
+       NULL,                   /* send_sysex           */
+                               /* alloc                */
+                               /* chn_info[16]         */
+};
+
+int  vidc_synth_get_volume(void)
+{
+       return vidc_synth_volume;
+}
+
+int vidc_synth_set_volume(int newvol)
+{
+       return vidc_synth_volume = newvol;
+}
+
+void vidc_synth_init(struct address_info *hw_config)
+{
+       vidc_synth_volume = 100 | (100 << 8);
+       if ((vidc_sdev=sound_alloc_synthdev())!=-1)
+               synth_devs[vidc_sdev] = &vidc_synth_operations;
+       else
+               printk(KERN_ERR "VIDCsound: Too many synthesizers\n");
+}
index 2eaacb57dd05801158bc87bc873297e7783bc3e7..c0767a0f0c462a6c44c2333c448357a038d44cd1 100644 (file)
@@ -20,7 +20,7 @@
  * for more details.
  */
 
-
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 66132809a34d2205de2fae6c707bd4eb062c9978..efe9833cb1ff98578e8e4153feef40dc926ba67e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index b27683c95850a3b58ff0724441686f916dcd18ed..475095988264e36932240ee036fb57ee190e277f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index 617c8523578ffa24836eef7fc498524554b12a4a..6ed68e89d5452211e32e7c8d1d39459a42e2ca1f 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index 65a4ad5562ac9286532d478d9455628f407d1fac..2a95a28cf1ef4c5556e3c553643786394bc6236f 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index 8c33064588250383f5b84f11e7ca937a1c1ee145..cedc0481407cfd95b4fe86432cc97d408fa5406e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index bcdfcc4363075c302d34bcf5a069b1ab7054b960..8df0656950ec4a284d75b89987fed51e055a89e2 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index c559f4025f74f934c808e6d895ae760602fca4b4..dcd3ebd97640ae054ec1b0406160a3fc95186101 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index 1dd5f198893584c017bffdbcb1ce0b7a080057f2..5518e5defcf15f5cf97886134e6b217e54127131 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
 
index 3484cef2a8e8d4bd356091aa69b21c0155aee8f6..60ef11221eec5d3ba593c0c9f5a38d9691440cb0 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/fb.h>
 
 #include "fbcon.h"
index 3f795cd63e985f5d09426e96edcd7a8bda470d08..e2c553392dbf3b5f23dc6f50c6e86157d1e68e99 100644 (file)
@@ -8,6 +8,7 @@
  * for more details.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 9aefbe8f3ae0f2da9680d69643265a3829e6b21e..5e55f89c74c072f4b75b03d35bd2c1fdc7eef2e0 100644 (file)
@@ -1335,6 +1335,8 @@ static inline void after_unlock_page (struct page * page)
                        atomic_read(&nr_async_pages));
 #endif
        }
+       if (test_and_clear_bit(PG_swap_unlock_after, &page->flags))
+               swap_after_unlock_page(page->offset);
        if (test_and_clear_bit(PG_free_after, &page->flags))
                __free_page(page);
 }
index 1d48836b870a3de702e592d175cc3b17be312e58..1ee855bb439a52bf68c4d5747fcb5d056f7b70ae 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/param.h>
+#include <linux/string.h>
 #include "devpts_i.h"
 
 static int devpts_root_readdir(struct file *,void *,filldir_t);
index ae3c84667d12e36cb1f775e4f5f62cbb77805d33..71c51809f4577448e9340f69c636bbb85f253854 100644 (file)
@@ -205,21 +205,23 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf,
                        return -EFBIG;
        }
 #else
-       off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)];
+       {
+               off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)];
 
-       if (pos + count > max) {
-               count = max - pos;
-               if (!count)
-                       return -EFBIG;
-       }
-       if (((pos + count) >> 32) && 
-           !(sb->u.ext2_sb.s_es->s_feature_ro_compat &
-             cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
-               /* If this is the first large file created, add a flag
-                  to the superblock */
-               sb->u.ext2_sb.s_es->s_feature_ro_compat |=
-                       cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
-               mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+               if (pos + count > max) {
+                       count = max - pos;
+                       if (!count)
+                               return -EFBIG;
+               }
+               if (((pos + count) >> 32) && 
+                   !(sb->u.ext2_sb.s_es->s_feature_ro_compat &
+                     cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+                       /* If this is the first large file created, add a flag
+                          to the superblock */
+                       sb->u.ext2_sb.s_es->s_feature_ro_compat |=
+                               cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+                       mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+               }
        }
 #endif
 
index ae7851a10e48ca84d321396815cd3213524c2a63..583b94c256b6fac411eece48afba861cf9534149 100644 (file)
@@ -495,7 +495,7 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
        if (!sb->s_root) {
                printk("SysV FS: get root inode failed\n");
                sysv_put_super(sb);
-               sb->sb_dev = 0;
+               sb->s_dev = 0;
                unlock_super(sb);
                return NULL;
        }
index ddc2911fcc76c5e0b9ac75a5f5ec80f9aba7b514..1357fdd69db1ec7062fd096c9c972b55c5a208c8 100644 (file)
@@ -8,7 +8,7 @@ UMSDOS FILESYSTEM, AND MAYBE EVEN OTHER FILESYSTEMS IN USE.
 YOU'VE BEEN WARNED.
 --------- WARNING --------- WARNING --------- WARNING -----------
 
-Current status (980220) - UMSDOS dentry-WIP-Beta 0.82-1:
+Current status (980220) - UMSDOS dentry-WIP-Beta 0.82-3:
 
 (1) pure MSDOS (no --linux-.--- EMD file):
 
@@ -19,7 +19,7 @@ Current status (980220) - UMSDOS dentry-WIP-Beta 0.82-1:
 - creat file - works
 - write file - works
 - mkdir - works
-- rmdir - questionable. probable problem on non-empty dirs.
+- rmdir - QUESTIONABLE. probable problem on non-empty dirs.
 
 Notes: possible very minor problems with dentry/inode/... kernel structures (very rare)
 
@@ -42,28 +42,29 @@ Notes: possible very minor problems with dentry/inode/... kernel structures (ver
 - other ioctls - MOSTLY UNTESTED
 - dangling symlink - UNTESTED !
 
-- create symlink               - works on short names, but fails (gets
-                                 truncated on long ones) (also
-                                 due to some dentries problems, it may not
-                                 be visible right away always - eg. before
-                                 umount/mount)
+- create symlink               - seems to work both on short & long names now !
 - create hardlink              - WARNING: NOT FIXED YET!
-- create file                  - creates short names, but probs with long ones ?
-- create special file          - seems to work on short names.
-- write to file                        - seems to work on short names.
+- create file                  - seems to work both on short & long names now !
+- create special file          - seems to work both on short & long names now !
+- write to file                        - seems to work both on short & long names now !
 - rename file (same dir)       - WARNING: NOT FIXED YET!
 - rename file (dif. dir)       - WARNING: NOT FIXED YET!
 - rename dir (same dir)                - WARNING: NOT FIXED YET!
 - rename dir (dif. dir)                - WARNING: NOT FIXED YET!
-- delete file                  - WARNING: NOT FIXED YET!
+- delete file                  - seems to work fully now!
 - notify_change (chown,perms)  - seems to work!
 - delete hardlink              - WARNING: NOT FIXED YET!
-- mkdir                                - seems to work, even with long names ! (but
-                                 due to some dentries problems, it may not
-                                 be visible right away always - eg. before
-                                 umount/mount)
+- mkdir                                - seems to work both on short & long names now !
 - rmdir                        - WARNING: NOT FIXED YET!
-- umssyncing                   - does something :-), but NEEDS EXTENSIVE TESTING
+- umssyncing                   - seems to work, but NEEDS EXTENSIVE TESTING
+
+- CVF-FAT stuff (compressed DOS filesystem) - there is some support from
+  Frank Gockel <gockel@sent13.uni-duisburg.de> to use it even under
+  umsdosfs. But I have no way of testing it -- please let me know if there
+  are problems that are specific to umsdos (eg. it works under msdosfs, but
+  not under umsdosfs)
+
+
 
 Notes: moderate dentry/inode kernel structures trashing. Probably some other
 kernel structures compromised. Have SysRq support compiled in, and use
@@ -77,16 +78,18 @@ Notes3: Notes2 is probably somewhat outdated now that hardlink/symlink stuff
 is supposed to be fixed enough to work, but I haven't got the time to test
 it.
 
-Note4: on failure of creating of long filenames: MSDOS filename gets
-created, and EMD entry gets created. Check: either they mismatch, or EMD
-entry contains some wrong flags.
+Note5: rmdir(2) fails with EBUSY - sdir->i_count > 1 (like 7 ??). It must be
+some error with dir->i_count++, or something related to iput() ? See if
+number changes if we access the dir in different ways..
 
-Note5: rmdir(2) probably fails because do_rmdir calls lock_parent, which
-uses dentry->d_parent, which we neglect to set, so it returns -ENOENT.
-Probably same problem on unlink(2) ? What to do ? How to set
-dentry->d_parent to something useful ?? Must I recurse down whole pathname
-and set one by one all directory components ?! or only last one is really
-needed ? help !
+Note6: there is problem with unmounting umsdosfs, it seems to stay
+registered or something. Remounting same device on any mount point with
+different fstype (like msdos or vfat) ignores fstype and umsdosfs kicks back
+in. 
+
+Note7: also we screwed umount(2)-ing the fs at times (EBUSY), by removing
+all those iput/dput's. When rest of code is fixed, we'll put them back at
+(hopefully) correct places.
 
 ------------------------------------------------------------------------------
 
@@ -110,10 +113,10 @@ should we destroy temp dentries ? using d_invalidate ? using d_drop ? just
 dput them ?
 
 I'm unfortunatelly somewhat out of time to read linux-kernel, but I do check
-for any messages having UMSDOS in subject, and read them. I should reply to
-any direct Email in few days. If I don't - probably I never got your
-message. You can try mnalis@open.hr or mnalis@voyager.hr; however
-mnalis@jagor.srce.hr is preferable one.
+for any messages having UMSDOS in subject, and read them. I might miss it in
+all that volume, though. I should reply to any direct Email in few days. If
+I don't - probably I never got your message. You can try mnalis@open.hr or
+mnalis@voyager.hr; however mnalis@jagor.srce.hr is preferable one.
 
 
 ------------------------------------------------------------------------------
@@ -122,7 +125,7 @@ some of my notes for myself /mn/:
 + hardlinks/symlinks. test with files in not_the_same_dir
 - also test not_the_same_dir for other file operations like rename etc.
 - iput: device 00:00 inode 318 still has aliases! problem. Check in iput()
-  for device 0,0. Probably null pointer passed arount when it shouldn't be ?
+  for device 0,0. Probably null pointer passed around when it shouldn't be ?
 - dput/iput problem...
 - what about .dotfiles ? working ? multiple dots ? etc....
 - fix stuff like dir->i_count++ to atomic_inc(&dir->i_count) and simular?
@@ -133,11 +136,23 @@ some of my notes for myself /mn/:
 
 - when should dput()/iput() be used ?!!
 
-- probably problem with filename mangling somewhere, since both create and
-  write to file work on short filenames, but fail on long ones. Path
-  components may be of any size (eg. mkfifo /mnt/Very_long_dir2/blah1 will
-  succeed, but mkfifo /mnt/very_long_filename.txt won't)
-
-
 - what is dir->i_count++ ? locking directory ? should this be lock_parent or
 something ?
+
+- i_binary=2 is for CVF (compressed filesystem).
+
+- SECURITY WARNING: short dentries should be invalidated, or they could be
+  accessed instead of proper long names.
+
+- as for iput() : (my only pointer so far. anyone else ?)
+
+>development I only know about iput. All functions that get an inode as
+>argument and don't return it have to call iput on it before exit, i.e. when
+>it is no longer needed and the code returns to vfs layer. The rest is quite
+>new to me, but it might be similar for dput. Typical side effect of a
+>missing iput was a memory runout (but no crash). You also couldn't unmount
+>the filesystem later though no process was using it. On the other hand, one
+>iput too much lead to serious pointer corruption and crashed the system
+>very soon. I used to look at the FAT filesystem and copy those pieces of
+>
+> Frank
index 52a72367e9aa242e10618eb8ac371604e701e499..288c77d451648012d15a8bb5a4907afcdf9c83b2 100644 (file)
@@ -36,7 +36,7 @@ int compat_umsdos_real_lookup (struct inode *dir,const char *name,int len, struc
   int rv;
   struct dentry *dentry;
 
-  dentry = creat_dentry (name, len, NULL);
+  dentry = creat_dentry (name, len, NULL, NULL);
   rv = umsdos_real_lookup(dir,dentry);
   if (inode) *inode = dentry->d_inode;
   kill_dentry (dentry);
@@ -50,7 +50,7 @@ int compat_msdos_create(struct inode *dir,const char *name,int len, int mode, st
   int rv;
   struct dentry *dentry;
 
-  dentry = creat_dentry (name, len, NULL);
+  dentry = creat_dentry (name, len, NULL, NULL);
   rv = msdos_create(dir,dentry,mode);
   if(inode != NULL) *inode = dentry->d_inode;
   
@@ -270,10 +270,10 @@ static int umsdos_readdir_x(
              }
              Printk (("Trouve ino %ld ",inode->i_ino));
              if (u_entry != NULL) *u_entry = entry;
-             iput (inode);
+             /* iput (inode); FIXME */
              break;
            }
-           iput (inode);
+           /* iput (inode); FIXME */
          }else{
            /* #Specification: umsdos / readdir / not in MSDOS
               During a readdir operation, if the file is not
@@ -295,7 +295,7 @@ static int umsdos_readdir_x(
        the special offset.
       */
       if (filp->f_pos == 0) filp->f_pos = start_fpos;
-      iput(emd_dir);
+      /* iput(emd_dir); FIXME */
     }
   }
   umsdos_endlookup(dir);       
@@ -530,7 +530,7 @@ int umsdos_inode2entry (
     ret = 0;
   }else{
     struct inode *emddir = umsdos_emd_dir_lookup(dir,0);
-    iput (emddir);
+    /* iput (emddir); FIXME */
     if (emddir == NULL){
       /* This is a DOS directory */
       struct UMSDOS_DIR_SEARCH bufk;
@@ -639,7 +639,7 @@ int umsdos_locate_path (
       while (dir != root_inode){
        struct inode *adir;
        ret = umsdos_locate_ancestor (dir,&adir,&entry);
-       iput (dir);
+       /* iput (dir); FIXME */
        dir = NULL;
        Printk (("ancestor %d ",ret));
        if (ret == 0){
@@ -657,7 +657,7 @@ int umsdos_locate_path (
     kfree (bpath);
   }
   Printk (("\n"));
-  iput (dir);
+  /* iput (dir); FIXME */
   return ret;
 }
 
@@ -697,12 +697,16 @@ int umsdos_lookup_x (
   struct inode *pseudo_root_inode=NULL;
   int len = dentry->d_name.len;
   const char *name = dentry->d_name.name;
+  
+  Printk ((KERN_DEBUG "umsdos_lookup_x: /mn/ name=%.*s, dir=%lu, d_parent=%p\n", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino, dentry->d_parent));        /* FIXME /mn/ debug only */
+  if (dentry->d_parent) Printk ((KERN_DEBUG "   d_parent is %.*s\n", (int) dentry->d_parent->d_name.len, dentry->d_parent->d_name.name)); /* FIXME : delme /mn/ */
+  
   root_inode = iget(dir->i_sb,UMSDOS_ROOT_INO);
   /*   pseudo_root_inode = iget( ... ) ? */
   dentry->d_inode = NULL;
-  umsdos_startlookup(dir);     
+  umsdos_startlookup(dir);
   if (len == 1 && name[0] == '.'){
-    dentry->d_inode = dir;
+    d_add (dentry, dir);
     dir->i_count++;
     ret = 0;
   }else if (len == 2 && name[0] == '.' && name[1] == '.'){
@@ -713,7 +717,7 @@ int umsdos_lookup_x (
         pseudo root is returned.
       */
       ret = 0;
-      dentry->d_inode = pseudo_root;
+      d_add (dentry, pseudo_root);
       pseudo_root->i_count++;
     }else{
       /* #Specification: locating .. / strategy
@@ -735,7 +739,7 @@ int umsdos_lookup_x (
        struct inode *aadir;
        struct umsdos_dirent entry;
        ret = umsdos_locate_ancestor (dentry->d_inode,&aadir,&entry);
-       iput (aadir);
+       /* iput (aadir); FIXME */
       }
     }
   }else if (umsdos_is_pseudodos(dir,dentry)){
@@ -743,7 +747,7 @@ int umsdos_lookup_x (
        A lookup of DOS in the pseudo root will always succeed
        and return the inode of the real root.
     */
-    dentry->d_inode = root_inode;
+    d_add (dentry, root_inode);
     (dentry->d_inode)->i_count++;
     ret = 0;
   }else{
@@ -776,7 +780,7 @@ int umsdos_lookup_x (
         Printk ((KERN_DEBUG "umsdos_lookup_x /mn/ debug: ino=%li\n", inode->i_ino));
 
         /* we've found it. now get inode and put it in dentry. Is this ok /mn/ ? */
-        dentry->d_inode = iget(dir->i_sb, inode->i_ino);
+        d_add (dentry, iget(dir->i_sb, inode->i_ino));
         
        umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
        Printk (("lookup ino %ld flags %d\n",inode->i_ino
@@ -796,7 +800,7 @@ int umsdos_lookup_x (
            mode.
          */
          Printk ((KERN_ERR "umsdos_lookup_x: warning: untested /mn/ Pseudo_root thingy\n"));
-         iput (pseudo_root);
+         /* iput (pseudo_root); FIXME */
          dentry->d_inode = NULL;
          ret = -ENOENT;
        }
@@ -804,7 +808,7 @@ int umsdos_lookup_x (
     }
   }
   umsdos_endlookup(dir);       
-  iput (dir);
+  /* iput (dir); FIXME */
   Printk ((KERN_DEBUG "umsdos_lookup_x: returning %d\n", ret));
   return ret;
 }
@@ -858,7 +862,7 @@ int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
   *result = NULL;
   if (path == NULL){
     ret = -ENOMEM;
-    iput (hlink);
+    /* iput (hlink); FIXME */
   }else{
     struct file filp;
     loff_t offs = 0;
@@ -866,7 +870,7 @@ int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
     fill_new_filp (&filp, NULL);
       
 
-    dentry_src = creat_dentry ("hlink-mn", 8, hlink);
+    dentry_src = creat_dentry ("hlink-mn", 8, hlink, NULL);
 
     memset (&filp, 0, sizeof (filp));
 
@@ -894,7 +898,7 @@ int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
            if (*pt == '/') *pt++ = '\0';
            /* FIXME. /mn/ fixed ? */
 
-            dentry_dst = creat_dentry (start, len, NULL);
+            dentry_dst = creat_dentry (start, len, NULL, NULL);
 
            if (dir->u.umsdos_i.i_emd_dir == 0){
              /* This is a DOS directory */
@@ -917,7 +921,7 @@ int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
          }
       }else{
          Printk (("umsdos_hlink2inode: all those iput's() frighten me /mn/. Whatabout dput() ? FIXME!\n"));
-         iput (hlink); /* FIXME */
+         /* iput (hlink); / * FIXME */
       }
     Printk (("hlink2inode ret = %d %p -> %p\n", ret, hlink, *result));
     kfree (path);
index 8ba6571eb16c09d966581007b1e8c15deb8a67a4..6cb630b1c70305e95c695d8bc54a4f9a790e706c 100644 (file)
@@ -52,9 +52,11 @@ void fill_new_filp (struct file *filp, struct dentry *dentry)
  *
  */
  
-struct dentry *creat_dentry (const char *name, const int len, struct inode *inode)
+struct dentry *creat_dentry (const char *name, const int len, struct inode *inode, struct dentry *parent)
 {
-    struct dentry *ret, *parent=NULL;  /* FIXME /mn/: whatis parent ?? */
+/* FIXME /mn/: parent is not passed many times... if it is not, dentry should be destroyed before someone else gets to use it */
+
+    struct dentry *ret;
     struct qstr qname;
     
     if (inode)
@@ -71,10 +73,10 @@ struct dentry *creat_dentry (const char *name, const int len, struct inode *inod
 
     if (inode) d_add (ret, inode);
       
-/*    ret->d_inode = inode; /mn/ FIXME this was old, replaced by d_add, delete this ! */
     return ret;
 }
 
+
 /*
  * removes temporary dentry created by creat_dentry
  *
@@ -123,7 +125,7 @@ ssize_t umsdos_file_read_kmem (struct inode *emd_dir,
     set_fs (KERNEL_DS);
 
     old_dentry=filp->f_dentry; /* save it */
-    filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir);
+    filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL);
     *offs = filp->f_pos;
     
     PRINTK ((KERN_DEBUG "umsdos_file_read_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
@@ -138,6 +140,7 @@ ssize_t umsdos_file_read_kmem (struct inode *emd_dir,
     PRINTK ((KERN_DEBUG "  f_version=%ld\n", filp->f_version));
     PRINTK ((KERN_DEBUG "  f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
 
+    MSDOS_I(filp->f_dentry->d_inode)->i_binary=2;
     ret = fat_file_read(filp,buf,count,offs);
     PRINTK ((KERN_DEBUG "fat_file_read returned with %d!\n", ret));
 
@@ -195,21 +198,28 @@ ssize_t umsdos_file_write_kmem_real (struct file *filp,
        
        set_fs (KERNEL_DS);
 
-        Printk ((KERN_ERR "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
-        Printk ((KERN_ERR "  struct dentry=%p\n", filp->f_dentry));
-        Printk ((KERN_ERR "  struct inode=%p\n", filp->f_dentry->d_inode));
-        Printk ((KERN_ERR "  inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
-        Printk ((KERN_ERR "  ofs=%ld\n",(unsigned long) *offs));
-        Printk ((KERN_ERR "  f_pos=%Lu\n", filp->f_pos));
-        Printk ((KERN_ERR "  name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
-        Printk ((KERN_ERR "  i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
-        Printk ((KERN_ERR "  f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
-        Printk ((KERN_ERR "  f_owner=%d\n", filp->f_owner.uid));
-        Printk ((KERN_ERR "  f_version=%ld\n", filp->f_version));
-        Printk ((KERN_ERR "  f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
-
+        Printk ((KERN_DEBUG "umsdos_file_write_kmem /mn/: Checkin: filp=%p, buf=%p, size=%d, offs=%p\n", filp, buf, count, offs));
+        Printk ((KERN_DEBUG "  struct dentry=%p\n", filp->f_dentry));
+        Printk ((KERN_DEBUG "  struct inode=%p\n", filp->f_dentry->d_inode));
+        Printk ((KERN_DEBUG "  inode=%lu, i_size=%lu\n", filp->f_dentry->d_inode->i_ino, filp->f_dentry->d_inode->i_size));
+        Printk ((KERN_DEBUG "  ofs=%ld\n",(unsigned long) *offs));
+        Printk ((KERN_DEBUG "  f_pos=%Lu\n", filp->f_pos));
+        Printk ((KERN_DEBUG "  name=%.*s\n", (int) filp->f_dentry->d_name.len, filp->f_dentry->d_name.name));
+        Printk ((KERN_DEBUG "  i_binary(sb)=%d\n", MSDOS_I(filp->f_dentry->d_inode)->i_binary ));
+        Printk ((KERN_DEBUG "  f_count=%d, f_flags=%d\n", filp->f_count, filp->f_flags));
+        Printk ((KERN_DEBUG "  f_owner=%d\n", filp->f_owner.uid));
+        Printk ((KERN_DEBUG "  f_version=%ld\n", filp->f_version));
+        Printk ((KERN_DEBUG "  f_reada=%ld, f_ramax=%ld, f_raend=%ld, f_ralen=%ld, f_rawin=%ld\n", filp->f_reada, filp->f_ramax, filp->f_raend, filp->f_ralen, filp->f_rawin));
+
+       /* note: i_binary=2 is for CVF-FAT. We put it here, instead of
+          umsdos_file_write_kmem, since it is also wise not to compress symlinks
+          (in unlikely event that they are > 512 bytes and can be compressed 
+          FIXME: should we set it when reading symlink too ? */
+
+        MSDOS_I(filp->f_dentry->d_inode)->i_binary=2;
+        
        ret = fat_file_write (filp, buf, count, offs);
-       PRINTK ((KERN_ERR "fat_file_write returned with %ld!\n", ret));
+       PRINTK ((KERN_DEBUG "fat_file_write returned with %ld!\n", ret));
 
        set_fs (old_fs);
        return ret;
@@ -231,11 +241,11 @@ ssize_t umsdos_file_write_kmem (struct inode *emd_dir,
        struct dentry *old_dentry;
 
        
-       Printk ((KERN_ERR " STARTED WRITE_KMEM /mn/\n"));
-        Printk ((KERN_ERR "  using emd=%ld\n", emd_dir->i_ino));
+       Printk ((KERN_DEBUG " STARTED WRITE_KMEM /mn/\n"));
+        Printk ((KERN_DEBUG "  using emd=%ld\n", emd_dir->i_ino));
 
        old_dentry=filp->f_dentry;      /* save it */
-       filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir);
+       filp->f_dentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, emd_dir, NULL);
 
        *offs = filp->f_pos;    /* FIXME, in read_kmem also: offs is not used so why pass it ?!!! /mn/ */
 
@@ -500,7 +510,7 @@ int umsdos_writeentry (
         fill_new_filp (&filp, NULL);
 
        Printk (("umsdos_writeentry /mn/: entering...\n"));
-       emd_dentry=creat_dentry ("wremd_mn", 8, emd_dir);
+       emd_dentry=creat_dentry ("wremd_mn", 8, emd_dir, NULL);
        
        if (free_entry){
                /* #Specification: EMD file / empty entries
@@ -650,7 +660,7 @@ static int umsdos_find (
 
                memset (&buf.filp, 0, sizeof (buf.filp));
 
-               dentry = creat_dentry ("umsfind-mn", 10, emd_dir);
+               dentry = creat_dentry ("umsfind-mn", 10, emd_dir, NULL);
        
                fill_new_filp (&buf.filp, dentry);
 
@@ -743,7 +753,7 @@ int umsdos_newentry (
                ret = umsdos_writeentry(dir,emd_dir,info,0);
                Printk (("umsdos_newentry EMD ret = %d\n",ret));
        }
-       iput (emd_dir);
+       /* iput (emd_dir); FIXME */
        return ret;
 }
 
@@ -760,7 +770,7 @@ int umsdos_newhidden (
        umsdos_parse ("..LINK",6,info);
        info->entry.name_len = 0;
        ret = umsdos_find (dir,info,&emd_dir);
-       iput (emd_dir);
+       /* iput (emd_dir); FIXME */
        if (ret == -ENOENT || ret == 0){
                /* #Specification: hard link / hidden name
                        When a hard link is created, the original file is renamed
@@ -799,7 +809,7 @@ int umsdos_delentry (
                        }
                }
        }
-       iput(emd_dir);
+       /* iput(emd_dir); FIXME */
        return ret;
 }
 
@@ -824,7 +834,7 @@ int umsdos_isempty (struct inode *dir)
                /* Find an empty slot */
                memset (&filp, 0, sizeof (filp));
 
-               dentry = creat_dentry ("isempty-mn", 10, dir);
+               dentry = creat_dentry ("isempty-mn", 10, dir, NULL);
        
                filp.f_pos = 0;
                filp.f_reada = 1;
@@ -843,7 +853,7 @@ int umsdos_isempty (struct inode *dir)
                                break;
                        }       
                }
-               iput (emd_dir);
+               /* iput (emd_dir); FIXME */
        }
        return ret;
 }
@@ -870,7 +880,7 @@ int umsdos_findentry (
                        }
                }
        }
-       iput (emd_dir);
+       /* iput (emd_dir); FIXME */
        Printk (("umsdos_findentry: returning %d\n", ret));
        return ret;
 }
index 04a3320ec499730380a70f74caa68ae255414380..b7f58a2b92d9d643d6cab530c08cb6936c396dc9 100644 (file)
@@ -144,3 +144,38 @@ struct inode_operations umsdos_file_inode_operations_no_bmap = {
        NULL,                   /* smap */
 };
 
+/* For other with larger and unaligned file system with readpage */
+struct file_operations umsdos_file_operations_readpage = {
+       NULL,                           /* lseek - default */
+       UMSDOS_file_read,               /* read */
+       UMSDOS_file_write,              /* write */
+       NULL,                           /* readdir - bad */
+       NULL,                           /* poll - default */
+       NULL,                           /* ioctl - default */
+       generic_file_mmap,              /* mmap */
+       NULL,                           /* no special open is needed */
+       NULL,                           /* release */
+       file_fsync                      /* fsync */
+};
+
+struct inode_operations umsdos_file_inode_operations_readpage = {
+       &umsdos_file_operations_readpage,       /* default file operations */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow link */
+       fat_readpage,           /* readpage */
+       NULL,                   /* writepage */
+       NULL,                   /* bmap */
+       UMSDOS_truncate,        /* truncate */
+       NULL,                   /* permission */
+       NULL,                   /* smap */
+};
+
index e8b65558c30df70c1744c0c6894c8f0d3c0fe167..0238a5bd1376b631b56451ef043ae9c2bbbc1129 100644 (file)
@@ -125,7 +125,7 @@ void umsdos_set_dirinfo(
     Printk (("umsdos_set_dirinfo: emd_owner is %lu for dir %lu\n", emd_owner->i_ino, dir->i_ino));
     inode->u.umsdos_i.i_dir_owner = dir->i_ino;
     inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino;
-    iput (emd_owner);
+    /* iput (emd_owner); FIXME */
     inode->u.umsdos_i.pos = f_pos;
 }
 
@@ -176,12 +176,22 @@ void umsdos_patch_inode (
   if (!umsdos_isinit(inode)){
     inode->u.umsdos_i.i_emd_dir = 0;
     if (S_ISREG(inode->i_mode)){
-      if (inode->i_op->bmap != NULL){
-        Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations\n"));
-       inode->i_op = &umsdos_file_inode_operations;
-      }else{
-        Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
-       inode->i_op = &umsdos_file_inode_operations_no_bmap;
+       if (MSDOS_SB(inode->i_sb)->cvf_format){
+         if (MSDOS_SB(inode->i_sb)->cvf_format->flags&CVF_USE_READPAGE){
+           Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_readpage\n"));
+           inode->i_op = &umsdos_file_inode_operations_readpage;
+         }else{
+           Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
+           inode->i_op = &umsdos_file_inode_operations_no_bmap;
+         }
+       }else{      
+         if (inode->i_op->bmap != NULL){
+           Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations\n"));
+          inode->i_op = &umsdos_file_inode_operations;
+         }else{
+           Printk ((KERN_DEBUG "umsdos_patch_inode /mn/: seting i_op = umsdos_file_inode_operations_no_bmap\n"));
+           inode->i_op = &umsdos_file_inode_operations_no_bmap;
+         }
       }
     }else if (S_ISDIR(inode->i_mode)){
       if (dir != NULL){
@@ -223,7 +233,7 @@ void umsdos_patch_inode (
       struct inode *emd_owner;
       Printk ((KERN_WARNING "umsdos_patch_inode: /mn/ Warning: untested emd_owner thingy...\n"));
       emd_owner = umsdos_emd_dir_lookup(dir,1);
-      iput (emd_owner);
+      /* iput (emd_owner); FIXME */
       if (emd_owner->i_ino != inode->u.umsdos_i.i_emd_owner){
          printk ("UMSDOS: *** EMD_OWNER ??? *** ino = %ld %ld <> %ld "
                  ,inode->i_ino,emd_owner->i_ino,inode->u.umsdos_i.i_emd_owner);
@@ -323,7 +333,7 @@ int internal_notify_change(struct inode *inode, struct iattr *attr)
 {
   int ret = 0;
   
-  Printk ((KERN_ERR "UMSDOS_notify_change: /mn/ completly untested\n"));
+  PRINTK ((KERN_DEBUG "UMSDOS_notify_change: entering\n"));
   
   if ((ret = inode_change_ok(inode, attr)) != 0)
     return ret;
@@ -366,7 +376,7 @@ int internal_notify_change(struct inode *inode, struct iattr *attr)
        struct dentry *emd_dentry;
        loff_t offs;
        
-       emd_dentry = creat_dentry ("notify_emd", 10, emd_owner);
+       emd_dentry = creat_dentry ("notify_emd", 10, emd_owner, NULL);
        fill_new_filp (&filp, emd_dentry);
        
        filp.f_pos = inode->u.umsdos_i.pos;
@@ -403,7 +413,7 @@ int internal_notify_change(struct inode *inode, struct iattr *attr)
             EMD file. The msdos fs is not even called.
          */
        }
-       iput (emd_owner);
+       /* iput (emd_owner); FIXME */
       }
       Printk (("\n"));
     }
@@ -472,7 +482,7 @@ struct super_block *UMSDOS_read_super(
     PRINTK ((KERN_DEBUG "UMSDOS /mn/: sb = %p\n",sb));
     res = msdos_read_super(sb,data,silent);
     PRINTK ((KERN_DEBUG "UMSDOS /mn/: res = %p\n",res));
-    printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-2 (compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE);
+    printk (KERN_INFO "UMSDOS dentry-WIP-Beta 0.82-3 (compatibility level %d.%d, fast msdos)\n", UMSDOS_VERSION, UMSDOS_RELEASE);
          
     if (res == NULL) { MOD_DEC_USE_COUNT; return NULL; }
 
@@ -480,7 +490,7 @@ struct super_block *UMSDOS_read_super(
     res->s_op = &umsdos_sops;
     Printk ((KERN_DEBUG "umsdos /mn/: here goes the iget ROOT_INO\n"));
 
-    pseudo = iget(res,UMSDOS_ROOT_INO);                
+    pseudo = iget(res,UMSDOS_ROOT_INO);
     Printk ((KERN_DEBUG "umsdos_read_super %p\n",pseudo));
 
     umsdos_setup_dir_inode (pseudo);
@@ -521,8 +531,8 @@ struct super_block *UMSDOS_read_super(
       */
       struct dentry *root, *etc, *etc_rc, *init, *sbin;
 
-      root = creat_dentry (UMSDOS_PSDROOT_NAME, strlen(UMSDOS_PSDROOT_NAME), NULL);
-      sbin = creat_dentry ("sbin", 4, NULL);
+      root = creat_dentry (UMSDOS_PSDROOT_NAME, strlen(UMSDOS_PSDROOT_NAME), NULL, NULL);
+      sbin = creat_dentry ("sbin", 4, NULL, NULL);
       
       Printk ((KERN_DEBUG "Mounting root\n"));
       if (umsdos_real_lookup (pseudo,root)==0
@@ -531,7 +541,7 @@ struct super_block *UMSDOS_read_super(
        
        int pseudo_ok = 0;
        Printk ((KERN_DEBUG "/%s is there\n",UMSDOS_PSDROOT_NAME));
-       etc = creat_dentry ("etc", 3, NULL);
+       etc = creat_dentry ("etc", 3, NULL, NULL);
        
        
        /* if (umsdos_real_lookup (pseudo,"etc",3,etc)==0 */
@@ -540,8 +550,8 @@ struct super_block *UMSDOS_read_super(
 
            Printk ((KERN_DEBUG "/%s/etc is there\n",UMSDOS_PSDROOT_NAME));
            
-           init = creat_dentry ("init", 4, NULL);
-           etc_rc = creat_dentry ("rc", 2, NULL);
+           init = creat_dentry ("init", 4, NULL, NULL);
+           etc_rc = creat_dentry ("rc", 2, NULL, NULL);
          
            /* if ((umsdos_real_lookup (etc,"init",4,init)==0*/
            if((umsdos_real_lookup(pseudo, init) == 0
@@ -585,7 +595,7 @@ struct super_block *UMSDOS_read_super(
       
       Printk ((KERN_WARNING "umsdos_read_super /mn/: Pseudo should be iput-ed here...\n"));
 
-      iput (pseudo); /* FIXME */
+      /* iput (pseudo); / * FIXME */
     }
 
 #endif /* disabled */
index 7b92c49a47f0fe48bfb6e056288a3891fab815ca..b3f11ee32d59d7b4125d9205de31d5d8a2eda8b7 100644 (file)
@@ -60,6 +60,21 @@ int UMSDOS_ioctl_dir (
 {
   int ret = -EPERM;
   int err;
+
+       /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */
+       if(cmd!=UMSDOS_GETVERSION
+          &&cmd!=UMSDOS_READDIR_DOS
+          &&cmd!=UMSDOS_READDIR_EMD
+          &&cmd!=UMSDOS_INIT_EMD
+          &&cmd!=UMSDOS_CREAT_EMD
+          &&cmd!=UMSDOS_RENAME_DOS
+          &&cmd!=UMSDOS_UNLINK_EMD
+          &&cmd!=UMSDOS_UNLINK_DOS
+          &&cmd!=UMSDOS_RMDIR_DOS
+          &&cmd!=UMSDOS_STAT_DOS
+          &&cmd!=UMSDOS_DOS_SETUP)
+              return fat_dir_ioctl(dir,filp,cmd,data);
+
   /* #Specification: ioctl / acces
      Only root (effective id) is allowed to do IOCTL on directory
      in UMSDOS. EPERM is returned for other user.
@@ -162,7 +177,7 @@ int UMSDOS_ioctl_dir (
            }
          }
        }
-       iput (emd_dir);
+       /* iput (emd_dir); FIXME */
       }else{
                                /* The absence of the EMD is simply seen as an EOF */
        ret = 0;
@@ -182,7 +197,7 @@ int UMSDOS_ioctl_dir (
       extern struct inode_operations umsdos_rdir_inode_operations;
       struct inode *emd_dir = umsdos_emd_dir_lookup (dir,1);
       ret = emd_dir != NULL;
-      iput (emd_dir);
+      /* iput (emd_dir); FIXME */
       
       dir->i_op = ret
        ? &umsdos_dir_inode_operations
@@ -225,8 +240,8 @@ int UMSDOS_ioctl_dir (
          ,dir
          ,data.umsdos_dirent.name,data.umsdos_dirent.name_len);
        */
-       old_dentry = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, NULL);
-       new_dentry = creat_dentry (data.umsdos_dirent.name, data.umsdos_dirent.name_len, NULL);
+       old_dentry = creat_dentry (data.dos_dirent.d_name, data.dos_dirent.d_reclen, NULL, NULL);       /* FIXME: prolly should fill inode part */
+       new_dentry = creat_dentry (data.umsdos_dirent.name, data.umsdos_dirent.name_len, NULL, NULL);
        ret = msdos_rename(dir,old_dentry,dir,new_dentry);
       }else if (cmd == UMSDOS_UNLINK_EMD){
        /* #Specification: ioctl / UMSDOS_UNLINK_EMD
@@ -297,7 +312,7 @@ int UMSDOS_ioctl_dir (
          data.stat.st_ctime = inode->i_ctime;
          data.stat.st_mtime = inode->i_mtime;
          copy_to_user (&idata->stat,&data.stat,sizeof(data.stat));
-         iput (inode);
+         /* iput (inode); FIXME */
        }
       }else if (cmd == UMSDOS_DOS_SETUP){
       /* #Specification: ioctl / UMSDOS_DOS_SETUP
index dcea137fe2fc0c8d38322bc63f4a4642c4adc69f..be72a9cb48ae90612865456ebc4345718fcd5833 100644 (file)
@@ -216,6 +216,7 @@ static int umsdos_create_any (
 {
     
   int ret;
+  struct dentry *fake;
   
   Printk (("umsdos_create_any /mn/: create %.*s in dir=%lu - nevercreat=/", (int) dentry->d_name.len, dentry->d_name.name, dir->i_ino));
   ret = umsdos_nevercreat(dir,dentry,-EEXIST);
@@ -238,17 +239,16 @@ static int umsdos_create_any (
       ret = umsdos_newentry (dir,&info);
       if (ret == 0){
        dir->i_count++;
-      /* FIXME
-        ret = msdos_create (dir,info.fake.fname,info.fake.len
-        ,S_IFREG|0777,result);
-      */
-       ret =msdos_create(dir,dentry,S_IFREG|0777);
+        fake = creat_dentry (info.fake.fname, info.fake.len, NULL, dentry->d_parent);  /* create short name dentry */
+       ret = msdos_create (dir, fake, S_IFREG|0777);
        if (ret == 0){
-         struct inode *inode = dentry->d_inode;
+         struct inode *inode = fake->d_inode;
          umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
          Printk (("inode %p[%lu], count=%d ",inode, inode->i_ino, inode->i_count));
          Printk (("Creation OK: [dir %lu] %.*s pid=%d pos %ld\n", dir->i_ino,
                   info.fake.len, info.fake.fname, current->pid, info.f_pos));
+         
+         d_instantiate(dentry, inode); /* long name also gets inode info */
        }else{
          /* #Specification: create / file exist in DOS
             Here is a situation. Trying to create a file with
@@ -367,8 +367,8 @@ static int umsdos_rename_f(
          PRINTK (("ret %d %d ",ret,new_info.fake.len));
          if (ret == 0){
            struct dentry *old, *new;
-           old = creat_dentry (old_info.fake.fname, old_info.fake.len, NULL);
-           new = creat_dentry (new_info.fake.fname, new_info.fake.len, NULL);
+           old = creat_dentry (old_info.fake.fname, old_info.fake.len, NULL, NULL);
+           new = creat_dentry (new_info.fake.fname, new_info.fake.len, NULL, NULL);
 
            PRINTK (("msdos_rename "));
            old_dir->i_count++;
@@ -471,7 +471,7 @@ static int umsdos_symlink_x(
     fill_new_filp (&filp, dentry);
 
     /* Make the inode acceptable to MSDOS FIXME */
-    Printk ((KERN_ERR "umsdos_symlink_x: FIXME /mn/ Here goes the crash.. known wrong code...\n"));
+    Printk ((KERN_WARNING "umsdos_symlink_x: /mn/ Is this ok?\n"));
     Printk ((KERN_WARNING "   symname=%s ; dentry name=%.*s (ino=%lu)\n", symname, (int) dentry->d_name.len, dentry->d_name.name, dentry->d_inode->i_ino));
     ret = umsdos_file_write_kmem_real (&filp, symname, len, &myofs);
     /* dput(dentry); ?? where did this come from FIXME */
@@ -489,7 +489,7 @@ static int umsdos_symlink_x(
       dir = NULL;
     }
   }
-  d_instantiate(dentry,dir);
+  /* d_instantiate(dentry,dir);   //already done in umsdos_create_any */
   Printk (("\n"));
   return ret;
 }
@@ -634,7 +634,7 @@ int UMSDOS_link (
                ret = -ENOMEM;
              }else{
                struct dentry *temp;
-               temp = creat_dentry (entry.name, entry.name_len, NULL);
+               temp = creat_dentry (entry.name, entry.name_len, NULL, NULL);
                Printk (("olddir[%d] ",olddir->i_count));
                ret = umsdos_locate_path (oldinode,path);
                Printk (("olddir[%d] ",olddir->i_count));
@@ -673,7 +673,7 @@ int UMSDOS_link (
       umsdos_unlockcreate(olddir);
       umsdos_unlockcreate(dir);
     }
-    iput (olddir);
+    /* iput (olddir); FIXME */
   }
   if (ret == 0){
     struct iattr newattrs;
@@ -681,8 +681,10 @@ int UMSDOS_link (
     newattrs.ia_valid = 0;
     ret = UMSDOS_notify_change(olddentry, &newattrs);
   }
-  dput (olddentry);
-  dput (dentry);
+
+/*  dput (olddentry);
+  dput (dentry); FIXME.... */
+  
   Printk (("umsdos_link %d\n",ret));
   return ret;
 }
@@ -735,10 +737,12 @@ int UMSDOS_mkdir(
       ret = umsdos_newentry (dir,&info);
       Printk (("newentry %d ",ret));
       if (ret == 0){
-       struct dentry *temp;
-       temp = creat_dentry (info.fake.fname, info.fake.len, NULL);
+       struct dentry *temp, *tdir;
+       tdir = creat_dentry ("mkd-dir", 7, dir, NULL);
+       temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
        dir->i_count++;
        ret = msdos_mkdir (dir, temp, mode);
+       
        if (ret != 0){
          umsdos_delentry (dir,&info,1);
          /* #Specification: mkdir / Directory already exist in DOS
@@ -756,17 +760,22 @@ int UMSDOS_mkdir(
          ret = compat_umsdos_real_lookup (dir,info.fake.fname,
                                           info.fake.len,&subdir);
          if (ret == 0){
-/*         struct inode *result;       FIXME /mn/ hmmm what is this supposed to be ? */
-           struct dentry *tdentry;
-           tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL);
-
-           ret = msdos_create (subdir, tdentry,S_IFREG|0777);
+           struct dentry *tdentry, *tdsub;
+           tdsub = creat_dentry ("mkd-emd", 7, subdir, NULL);
+           tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tdsub);
+           ret = msdos_create (subdir, tdentry, S_IFREG|0777);
+           kill_dentry (tdentry);      /* we don't want empty EMD file to be visible ! too bad kill_dentry does nothing at the moment :-)  FIXME */
+           kill_dentry (tdsub);
+           umsdos_setup_dir_inode (subdir);    /* this should setup dir so it is promoted to EMD, and EMD file is not visible inside it */
            subdir = NULL;
+           d_instantiate(dentry, temp->d_inode);
            /* iput (result); FIXME */
          }
          if (ret < 0){
            printk ("UMSDOS: Can't create empty --linux-.---\n");
          }
+         
+       
          /* iput (subdir); FIXME */
        }
       }
@@ -774,7 +783,7 @@ int UMSDOS_mkdir(
     }
   }
   Printk (("umsdos_mkdir %d\n",ret));
-/*  dput (dentry); FIXME /mn/ */
+  /* dput (dentry); / * FIXME /mn/ */
   return ret;
 }
 
@@ -803,7 +812,7 @@ int UMSDOS_mknod(
   */
 
   int ret = umsdos_create_any (dir,dentry,mode,rdev,0);
-/*  dput(dentry); /mn/ FIXME! */
+  /* dput(dentry); / * /mn/ FIXME! */
   return ret;
 }
 
@@ -902,7 +911,9 @@ int UMSDOS_rmdir(
      as possible.
   */           
 
-  int ret = umsdos_nevercreat(dir,dentry,-EPERM);
+  int ret;
+  
+  ret = umsdos_nevercreat(dir,dentry,-EPERM);
   if (ret == 0){
     volatile struct inode *sdir;
     dir->i_count++;
@@ -913,18 +924,22 @@ int UMSDOS_rmdir(
       int empty;
       umsdos_lockcreate(dir);
       if (sdir->i_count > 1){
+        Printk ((" /mn/ rmdir: FIXME EBUSY: hmmm, i_count is %d > 1\n", sdir->i_count));
        ret = -EBUSY;
       }else if ((empty = umsdos_isempty (sdir)) != 0){
-       struct dentry *tdentry;
-       tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL);
+       struct dentry *tdentry, *tedir;
+       tedir = creat_dentry ("emd-rmd", 7, dir, NULL);
+       tdentry = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, tedir);
+        umsdos_real_lookup (dir, tdentry);     /* fill inode part */
        Printk (("isempty %d i_count %d ",empty,sdir->i_count));
                                /* check sticky bit */
        if ( !(dir->i_mode & S_ISVTX) || fsuser() ||
             current->fsuid == sdir->i_uid ||
             current->fsuid == dir->i_uid ) {
          if (empty == 1){
-           /* We have to removed the EMD file */
+           /* We have to remove the EMD file */
            ret = msdos_unlink (sdir, tdentry);
+           Printk (("UMSDOS_rmdir: unlinking empty EMD ret=%d", ret));
            sdir = NULL;
          }
          /* sdir must be free before msdos_rmdir() */
@@ -933,17 +948,34 @@ int UMSDOS_rmdir(
          Printk (("isempty ret %d nlink %d ",ret,dir->i_nlink));
          if (ret == 0){
            struct umsdos_info info;
-           struct dentry *temp;
+           struct dentry *temp, *tdir;
            dir->i_count++;
            umsdos_parse (dentry->d_name.name,dentry->d_name.len,&info);
            /* The findentry is there only to complete */
            /* the mangling */
            umsdos_findentry (dir,&info,2);
-           temp = creat_dentry (info.fake.fname, info.fake.len, NULL);
-           
+
+            tdir = creat_dentry ("dir-rmd", 7, dir, NULL);
+            temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
+            umsdos_real_lookup (dir, temp);    /* fill inode part */
+            
+             Printk ((KERN_ERR "  rmdir start dir=%lu, dir->sb=%p\n", dir->i_ino, dir->i_sb)); /* FIXME: /mn/ debug only */
+             Printk ((KERN_ERR "    dentry=%.*s d_count=%d ino=%lu\n", (int) temp->d_name.len, temp->d_name.name, temp->d_count, temp->d_inode->i_ino));
+             Printk ((KERN_ERR "    d_parent=%.*s d_count=%d ino=%lu\n", (int) temp->d_parent->d_name.len, temp->d_parent->d_name.name, temp->d_parent->d_count, temp->d_parent->d_inode->i_ino));
+
            ret = msdos_rmdir (dir, temp);
+
+             Printk ((KERN_ERR "  rmdir passed %d\n", ret)); /* FIXME: /mn/ debug only */
+             Printk ((KERN_ERR "  rmdir end dir=%lu, dir->sb=%p\n", dir->i_ino, dir->i_sb));
+             Printk ((KERN_ERR "    dentry=%.*s d_count=%d ino=%p\n", (int) temp->d_name.len, temp->d_name.name, temp->d_count, temp->d_inode));
+             Printk ((KERN_ERR "    d_parent=%.*s d_count=%d ino=%lu\n", (int) temp->d_parent->d_name.len, temp->d_parent->d_name.name, temp->d_parent->d_count, temp->d_parent->d_inode->i_ino));
+
+            kill_dentry (tdir);
+            kill_dentry (temp);
+            
            if (ret == 0){
              ret = umsdos_delentry (dir,&info,1);
+              d_delete (dentry);
            }
          }
        }else{
@@ -961,7 +993,7 @@ int UMSDOS_rmdir(
       umsdos_unlockcreate(dir);
     }  
   }
-  dput(dentry);
+ /*  dput(dentry); FIXME /mn/ */
   Printk (("umsdos_rmdir %d\n",ret));
   return ret;
 }
@@ -1036,13 +1068,21 @@ int UMSDOS_unlink (
          if (ret == 0){
            ret = umsdos_delentry (dir,&info,0);
            if (ret == 0){
-             struct dentry *temp;
+             struct dentry *temp, *tdir;
              Printk (("Avant msdos_unlink %.*s ",info.fake.len,info.fake.fname));
-             dir->i_count++;
-             temp = creat_dentry (info.fake.fname, info.fake.len, NULL);
+             dir->i_count++;  /* FIXME /mn/ is this needed anymore now that msdos_unlink locks dir using d_parent ? */
+             tdir = creat_dentry ("dir-del", 7, dir, NULL);    /* FIXME /mn/: do we need iget(dir->i_ino) or would dir itself suffice ? */
+             temp = creat_dentry (info.fake.fname, info.fake.len, NULL, tdir);
+             umsdos_real_lookup (dir, temp);   /* fill inode part */
+             
              ret = msdos_unlink_umsdos (dir, temp);
              Printk (("msdos_unlink %.*s %o ret %d ",info.fake.len,info.fake.fname
                       ,info.entry.mode,ret));
+
+             d_delete (dentry);
+             
+             kill_dentry (tdir);
+             kill_dentry (temp);
            }
          }
        }else{
@@ -1054,7 +1094,7 @@ int UMSDOS_unlink (
       umsdos_unlockcreate(dir);
     }
   }    
-  dput(dentry);
+  /* dput(dentry); FIXME: shouldn't this be done in msdos_unlink ? */
   Printk (("umsdos_unlink %d\n",ret));
   return ret;
 }
@@ -1140,8 +1180,9 @@ int UMSDOS_rename(
       }
     }
   }
+  /*
   dput (new_dentry);
-  dput (old_dentry);
+  dput (old_dentry); FIXME /mn/ */
   return ret;
 }
 
index 7cd50e133a1756f594ba480af972552c299fc47f..612002c3b926aa6ee9725daeb67a72aa9906d4a7 100644 (file)
@@ -135,7 +135,7 @@ int umsdos_rlookup_x(
       */
         Printk ((KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n"));
        ret = -ENOENT;
-       iput (pseudo_root);
+       /* iput (pseudo_root); FIXME */
        
       }else if (S_ISDIR(inode->i_mode)){
        /* We must place the proper function table */
@@ -145,7 +145,7 @@ int umsdos_rlookup_x(
       }
     }
   }
-  iput (dir);
+  /* iput (dir); FIXME */
   PRINTK ((KERN_DEBUG "umsdos_rlookup_x: returning %d\n", ret));
   return ret;
 }
@@ -215,7 +215,7 @@ static int UMSDOS_rrmdir (
          }else if (empty == 1){
            /* We have to removed the EMD file */
            struct dentry *temp;
-           temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL);
+           temp = creat_dentry (UMSDOS_EMD_FILE, UMSDOS_EMD_NAMELEN, NULL, NULL); /* FIXME: prolly should fill inode part ? */
            ret = msdos_unlink(sdir, temp);
            sdir = NULL;
            if (ret == 0){
@@ -226,12 +226,12 @@ static int UMSDOS_rrmdir (
        }else{
          ret = -ENOTEMPTY;
        }
-       iput (sdir);
+       /* iput (sdir); FIXME */
       }
     }
     umsdos_unlockcreate (dir);
   }
-  iput (dir);
+  /* iput (dir); FIXME */
   return ret;
 }
 
index 9ea03dd9b4aea030d8ffe96e811f91c69d27ae2c..f1f8a1ad7f1efdbeb857eb98fb83dd2bb723e9e9 100644 (file)
@@ -52,6 +52,7 @@
  * ugh).
  */
 
+#include <linux/config.h>
 #include <asm/system.h>
 
 #ifdef CONFIG_ALPHA_SRM_SETUP
index 6ef1f4120593d6e61d49c860622dce7cef41e1b1..4b83c82919a17637d88c784c5f8cacf7cae853d6 100644 (file)
@@ -3,29 +3,40 @@
 
 #ifdef __KERNEL__
 
-extern void * __constant_c_memset(void *, unsigned long, long);
-extern void * __memset(void *, char, size_t);
-
 /*
- * Ugh. Gcc uses "bcopy()" internally for structure assignments.
+ * GCC of any recent vintage doesn't do stupid things with bcopy.  Of
+ * EGCS-devel vintage, it knows all about expanding memcpy inline.
+ * For things other than EGCS-devel but still recent, GCC will expand
+ * __builtin_memcpy as a simple call to memcpy.
+ *
+ * Similarly for a memset with data = 0.
  */
-#define __HAVE_ARCH_BCOPY
 
-/*
- * Define "memcpy()" to something else, otherwise gcc will
- * corrupt that too into a "bcopy".  Also, some day we might
- * want to do a separate inlined constant-size memcpy (for 8
- * and 16 byte user<->kernel structure copying).
- */
 #define __HAVE_ARCH_MEMCPY
+/* For backward compatibility with modules.  Unused otherwise.  */
 extern void * __memcpy(void *, const void *, size_t);
-#define memcpy __memcpy
+
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 8
+#define memcpy __builtin_memcpy
+#endif
 
 #define __HAVE_ARCH_MEMSET
-#define memset(s, c, count) \
-(__builtin_constant_p(c) ? \
- __constant_c_memset((s),(0x0101010101010101UL*(unsigned char)c),(count)) : \
- __memset((s),(c),(count)))
+extern void * __constant_c_memset(void *, unsigned long, long);
+extern void * __memset(void *, char, size_t);
+
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 8
+#define memset(s, c, n)                                                            \
+(__builtin_constant_p(c)                                                   \
+ ? (__builtin_constant_p(n) && (c) == 0                                            \
+    ? __builtin_memset((s),0,(n))                                          \
+    : __constant_c_memset((s),0x0101010101010101UL*(unsigned char)(c),(n))) \
+ : __memset((s),(c),(n)))
+#else
+#define memset(s, c, n)                                                        \
+(__builtin_constant_p(c)                                               \
+ ? __constant_c_memset((s),0x0101010101010101UL*(unsigned char)(c),(n)) \
+ : __memset((s),(c),(n)))
+#endif
 
 #define __HAVE_ARCH_STRCPY
 #define __HAVE_ARCH_STRNCPY
index 3cd68d99c17aca26a1f8897aaaf740db38125d24..07b9489d94c273ea6f211b1c1fd8b70aca195d62 100644 (file)
@@ -72,6 +72,8 @@ struct termio {
 #define N_MOUSE                2
 #define N_PPP          3
 #define N_AX25         5
+#define N_X25          6
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 /*     eof=^D          eol=\0          eol2=\0         erase=del
index 64361c234df68c7f2d7c758c640b64d47745108c..e5c3636f79b11e0f02759a2007208fbff9d8c046 100644 (file)
@@ -421,12 +421,6 @@ static inline int read(int fd, char * buf, int nr)
        return sys_read(fd, buf, nr);
 }
 
-extern int sys_fork(void);
-static inline int fork(void)
-{
-       return sys_fork();
-}
-
 extern int __kernel_execve(char *, char **, char **, struct pt_regs *);
 static inline int execve(char * file, char ** argvp, char ** envp)
 {
index 3fdb824e76db43f0608a79b9fd5e62708e38d2df..1f27878efb83cdbdb2e35dbfcbba0020fe88805b 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <asm/arch/mmu.h>
 #include <linux/slab.h>
+#include <asm/arch/processor.h>                /* For TASK_SIZE */
 
 #define LIBRARY_TEXT_START 0x0c000000
 
@@ -116,6 +117,7 @@ extern __inline__ void update_mm_cache_mm_addr(struct mm_struct *mm, unsigned lo
 #define PTRS_PER_PTE    32
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    32
+#define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SHIFT)
 
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
@@ -321,43 +323,111 @@ extern __inline__ pte_t * pte_offset(pmd_t *dir, unsigned long address)
  * used to allocate a kernel page table - this turns on ASN bits
  * if any.
  */
-#define pte_free_kernel(pte) pte_free((pte))
-#define pte_alloc_kernel(pmd,address) pte_alloc((pmd),(address))
 
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free_kernel(pmdp)
-#define pmd_alloc_kernel(pgd,address) ((pmd_t *)(pgd))
+#ifndef __SMP__
+extern struct pgtable_cache_struct {
+       unsigned long *pgd_cache;
+       unsigned long *pte_cache;
+       unsigned long pgtable_cache_sz;
+} quicklists;
+
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (quicklists.pte_cache)
+#define pgd_quicklist (quicklists.pgd_cache)
+#define pgtable_cache_size (quicklists.pgtable_cache_sz)
+
+#else
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif
 
-extern __inline__ void pte_free(pte_t * pte)
+extern pgd_t *get_pgd_slow(void);
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+       unsigned long *ret;
+
+       if((ret = pgd_quicklist) != NULL) {
+               pgd_quicklist = (unsigned long *)(*ret);
+               ret[0] = ret[1];
+               pgtable_cache_size--;
+       } else
+               ret = (unsigned long *)get_pgd_slow();
+       return (pgd_t *)ret;
+}
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
 {
-       kfree (pte);
+       *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+       pgd_quicklist = (unsigned long *) pgd;
+       pgtable_cache_size++;
 }
 
-extern const char bad_pmd_string[];
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+       kfree(pgd);
+}
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+
+extern __inline__ pte_t *get_pte_fast(void)
+{
+       unsigned long *ret;
+
+       if((ret = (unsigned long *)pte_quicklist) != NULL) {
+               pte_quicklist = (unsigned long *)(*ret);
+               ret[0] = ret[1];
+               pgtable_cache_size--;
+       }
+       return (pte_t *)ret;
+}
+
+extern __inline__ void free_pte_fast(pte_t *pte)
+{
+       *(unsigned long *)pte = (unsigned long) pte_quicklist;
+       pte_quicklist = (unsigned long *) pte;
+       pgtable_cache_size++;
+}
+
+extern __inline__ void free_pte_slow(pte_t *pte)
+{
+       kfree(pte);
+}
+
+/* We don't use pmd cache, so this is a dummy routine */
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+       return (pmd_t *)0;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+}
+
+extern void __bad_pte(pmd_t *pmd);
+
+#define pte_free_kernel(pte)    free_pte_fast(pte)
+#define pte_free(pte)           free_pte_fast(pte)
+#define pgd_free(pgd)           free_pgd_fast(pgd)
+#define pgd_alloc()             get_pgd_fast()
 
 extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
 {
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 
        if (pmd_none (*pmd)) {
-               pte_t *page = (pte_t *) kmalloc (PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
-               if (pmd_none (*pmd)) {
-                       if (page) {
-                               memzero (page, PTRS_PER_PTE * BYTES_PER_PTR);
-                               set_pmd(pmd, mk_pmd(page));
-                               return page + address;
-                       }
-                       set_pmd (pmd, mk_pmd (BAD_PAGETABLE));
-                       return NULL;
-               }
-               kfree (page);
+               pte_t *page = (pte_t *) get_pte_fast();
+
+               if (!page)
+                       return get_pte_slow(pmd, address);
+               set_pmd(pmd, mk_pmd(page));
+               return page + address;
        }
        if (pmd_bad (*pmd)) {
-               printk(bad_pmd_string, pmd_val(*pmd));
-               set_pmd (pmd, mk_pmd (BAD_PAGETABLE));
+               __bad_pte(pmd);
                return NULL;
        }
        return (pte_t *) pmd_page(*pmd) + address;
@@ -367,28 +437,33 @@ extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  * inside the pgd, so has no extra memory associated with it.
  */
-#define pmd_free(pmd)
-#define pmd_alloc(pgd,address) ((pmd_t *)(pgd))
+extern __inline__ void pmd_free(pmd_t *pmd)
+{
+}
 
-/*
- * Free a page directory.  Takes the virtual address.
- */
-extern __inline__ void pgd_free(pgd_t * pgd)
+extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
 {
-       kfree ((void *)pgd);
+       return (pmd_t *) pgd;
 }
 
-/*
- * Allocate a new page directory.  Return the virtual address of it.
- */
-extern __inline__ pgd_t * pgd_alloc(void)
+#define pmd_free_kernel         pmd_free
+#define pmd_alloc_kernel        pmd_alloc
+#define pte_alloc_kernel        pte_alloc
+
+extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
+       struct task_struct * p;
        pgd_t *pgd;
-       
-       pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
-       if (pgd)
-               memzero (pgd, PTRS_PER_PGD * BYTES_PER_PTR);
-       return pgd;
+
+       read_lock(&tasklist_lock);
+       for_each_task(p) {
+               if (!p->mm)
+                       continue;
+               *pgd_offset(p->mm,address) = entry;
+       }
+       read_unlock(&tasklist_lock);
+       for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+               pgd[address >> PGDIR_SHIFT)] = entry;
 }
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
index 5816b2698c1b64f9d9ab919072c068c58f6cb6bc..20778c1931c87c78b990e1f08da15c10a58c82ac 100644 (file)
@@ -10,6 +10,7 @@
 #define __ASM_PROC_PGTABLE_H
 
 #include <asm/arch/mmu.h>
+#include <asm/arch/processor.h>                /* For TASK_SIZE */
 
 #define LIBRARY_TEXT_START 0x0c000000
 
 #define PTRS_PER_PTE    256
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    4096
+#define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SIZE)
 
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
@@ -263,6 +265,9 @@ extern __inline__ int pte_none(pte_t pte)
 
 extern __inline__ int pte_present(pte_t pte)
 {
+#if 0
+       /* This is what it really does, the else
+          part is just to make it easier for the compiler */
        switch (pte_val(pte) & PTE_TYPE_MASK) {
        case PTE_TYPE_LARGE:
        case PTE_TYPE_SMALL:
@@ -270,6 +275,9 @@ extern __inline__ int pte_present(pte_t pte)
        default:
                return 0;
        }
+#else
+       return ((pte_val(pmd) + 1) & PMD_TYPE_MASK);
+#endif
 }
 
 extern __inline__ int pmd_none(pmd_t pmd)
@@ -281,6 +289,9 @@ extern __inline__ int pmd_none(pmd_t pmd)
 
 extern __inline__ int pmd_bad(pmd_t pmd)
 {
+#if 0
+       /* This is what it really does, the else
+          part is just to make it easier for the compiler */
        switch (pmd_val(pmd) & PMD_TYPE_MASK) {
        case PMD_TYPE_FAULT:
        case PMD_TYPE_TABLE:
@@ -288,6 +299,9 @@ extern __inline__ int pmd_bad(pmd_t pmd)
        default:
                return 1;
        }
+#else
+       return (pmd_val(pmd) & PMD_TYPE_SECT);
+#endif
 }
 
 extern __inline__ int pmd_present(pmd_t pmd)
@@ -479,7 +493,7 @@ extern __inline__ unsigned long pmd_page(pmd_t pmd)
 /* to find an entry in a page-table-directory */
 extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
 {
-        return mm->pgd + (address >> PGDIR_SHIFT);
+       return mm->pgd + (address >> PGDIR_SHIFT);
 }
 
 /* Find an entry in the second-level page table.. */
@@ -488,7 +502,7 @@ extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long addres
 /* Find an entry in the third-level page table.. */
 extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
 {
-        return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+       return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
 }
 
 extern unsigned long get_small_page(int priority);
@@ -499,69 +513,129 @@ extern void free_small_page(unsigned long page);
  * used to allocate a kernel page table - this turns on ASN bits
  * if any.
  */
-extern __inline__ void pte_free_kernel(pte_t * pte)
+#ifndef __SMP__
+extern struct pgtable_cache_struct {
+       unsigned long *pgd_cache;
+       unsigned long *pte_cache;
+       unsigned long pgtable_cache_sz;
+} quicklists;
+#define pgd_quicklist (quicklists.pgd_cache)
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (quicklists.pte_cache)
+#define pgtable_cache_size (quicklists.pgtable_cache_sz)
+#else
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif
+
+extern pgd_t *get_pgd_slow(void);
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+       unsigned long *ret;
+
+       if((ret = pgd_quicklist) != NULL) {
+               pgd_quicklist = (unsigned long *)(*ret);
+               ret[0] = ret[1];
+               pgtable_cache_size--;
+       } else
+               ret = (unsigned long *)get_pgd_slow();
+       return (pgd_t *)ret;
+}
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+       *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+       pgd_quicklist = (unsigned long *) pgd;
+       pgtable_cache_size++;
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+       free_pages((unsigned long) pgd, 2);
+}
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
+
+extern __inline__ pte_t *get_pte_fast(void)
+{
+       unsigned long *ret;
+
+       if((ret = (unsigned long *)pte_quicklist) != NULL) {
+               pte_quicklist = (unsigned long *)(*ret);
+               ret[0] = ret[1];
+               pgtable_cache_size--;
+       }
+       return (pte_t *)ret;
+}
+
+extern __inline__ void free_pte_fast(pte_t *pte)
+{
+       *(unsigned long *)pte = (unsigned long) pte_quicklist;
+       pte_quicklist = (unsigned long *) pte;
+       pgtable_cache_size++;
+}
+
+extern __inline__ void free_pte_slow(pte_t *pte)
+{
+       free_small_page((unsigned long)pte);
+}
+
+/* We don't use pmd cache, so this is a dummy routine */
+extern __inline__ pmd_t *get_pmd_fast(void)
 {
-       free_small_page((unsigned long) pte);
+       return (pmd_t *)0;
 }
 
-extern const char bad_pmd_string[];
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+}
+
+extern void __bad_pte(pmd_t *pmd);
+extern void __bad_pte_kernel(pmd_t *pmd);
+
+#define pte_free_kernel(pte)   free_pte_fast(pte)
+#define pte_free(pte)          free_pte_fast(pte)
+#define pgd_free(pgd)          free_pgd_fast(pgd)
+#define pgd_alloc()            get_pgd_fast()
 
 extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
 {
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
        if (pmd_none(*pmd)) {
-               pte_t *page = (pte_t *) get_small_page(GFP_KERNEL);
-               if (pmd_none(*pmd)) {
-                       if (page) {
-                               memzero (page, PTRS_PER_PTE * BYTES_PER_PTR);
-                               set_pmd(pmd, mk_kernel_pmd(page));
-                               return page + address;
-                       }
-                       set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
-                       return NULL;
-               }
-               free_small_page((unsigned long) page);
+               pte_t *page = (pte_t *) get_pte_fast();
+
+               if (!page)
+                       return get_pte_kernel_slow(pmd, address);
+               set_pmd(pmd, mk_kernel_pmd(page));
+               return page + address;
        }
        if (pmd_bad(*pmd)) {
-               printk(bad_pmd_string, pmd_val(*pmd));
-               set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+               __bad_pte_kernel(pmd);
                return NULL;
        }
        return (pte_t *) pmd_page(*pmd) + address;
 }
 
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free_kernel(pmdp) pmd_val(*(pmdp)) = 0;
-#define pmd_alloc_kernel(pgdp, address) ((pmd_t *)(pgdp))
-
-extern __inline__ void pte_free(pte_t * pte)
-{
-       free_small_page((unsigned long) pte);
-}
-
 extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
 {
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 
        if (pmd_none(*pmd)) {
-               pte_t *page = (pte_t *) get_small_page(GFP_KERNEL);
-               if (pmd_none(*pmd)) {
-                       if (page) {
-                               memzero (page, PTRS_PER_PTE * BYTES_PER_PTR);
-                               set_pmd(pmd, mk_user_pmd(page));
-                               return page + address;
-                       }
-                       set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
-                       return NULL;
-               }
-               free_small_page ((unsigned long) page);
+               pte_t *page = (pte_t *) get_pte_fast();
+               
+               if (!page)
+                       return get_pte_slow(pmd, address);
+               set_pmd(pmd, mk_user_pmd(page);
+               return page + address;
        }
        if (pmd_bad(*pmd)) {
-               printk(bad_pmd_string, pmd_val(*pmd));
-               set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+               __bad_pte(pmd);
                return NULL;
        }
        return (pte_t *) pmd_page(*pmd) + address;
@@ -571,31 +645,32 @@ extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  * inside the pgd, so has no extra memory associated with it.
  */
-#define pmd_free(pmdp) pmd_val(*(pmdp)) = 0;
-#define pmd_alloc(pgdp, address) ((pmd_t *)(pgdp))
+extern __inline__ void pmd_free(pmd_t *pmd)
+{
+}
 
-/*
- * Free a page directory.  Takes the virtual address.
- */
-extern __inline__ void pgd_free(pgd_t * pgd)
+extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
 {
-       free_pages((unsigned long) pgd, 2);
+       return (pmd_t *) pgd;
 }
 
-/*
- * Allocate a new page directory.  Return the virtual address of it.
- */
-extern __inline__ pgd_t * pgd_alloc(void)
+#define pmd_free_kernel         pmd_free
+#define pmd_alloc_kernel        pmd_alloc
+
+extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
-       unsigned long pgd;
+       struct task_struct * p;
+       pgd_t *pgd;
 
-       /*
-        * need to get a 16k page for level 1
-        */
-       pgd = __get_free_pages(GFP_KERNEL,2,0);
-       if (pgd)
-               memzero ((void *)pgd, PTRS_PER_PGD * BYTES_PER_PTR);
-       return (pgd_t *)pgd;
+       read_lock(&tasklist_lock);
+       for_each_task(p) {
+               if (!p->mm)
+                       continue;
+               *pgd_offset(p->mm,address) = entry;
+       }
+       read_unlock(&tasklist_lock);
+       for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+               pgd[address >> PGDIR_SHIFT] = entry;
 }
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
index cc2be2ceb4a2bdcea8a7d77435748b4b9fc3d3f3..acb22e191d4109edef3730c6d0a26f8d54cec9f4 100644 (file)
@@ -95,7 +95,7 @@ extern __inline__ void copy_thread_css (struct context_save_struct *save)
  * NOTE! The task struct and the stack go together
  */
 #define alloc_task_struct() \
-       ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0))
+       ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)    free_pages((unsigned long)(p),1)
 
 #endif
index 76c20e28fa94a06e84d9893121ea23c870f33f6b..924fabca81dceb1561697b38476019d0c9c4e3af 100644 (file)
@@ -38,4 +38,40 @@ struct stat {
        unsigned long  __unused5;
 };
 
+typedef struct {
+       unsigned int    minor;
+       unsigned int    major;
+} __new_dev_t;
+
+struct stat64 {
+       __new_dev_t     st_dev;
+       __u64           st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       __new_dev_t     st_rdev;
+       __s64           st_size;
+       __u64           st_blocks;
+       unsigned long   st_atime;
+       unsigned long   __unused1;
+       unsigned long   st_mtime;
+       unsigned long   __unused2;
+       unsigned long   st_ctime;
+       unsigned long   __unused3;
+       unsigned long   st_blksize;
+       unsigned long   __unused4;
+};
+
+#define __XSTAT_VER_1          1
+#define __XSTAT_VER_2          2
+#define __XSTAT_VER_MASK       0xff
+
+#define __XSTAT_VER_XSTAT      0x000
+#define __XSTAT_VER_LXSTAT     0x100
+#define __XSTAT_VER_FXSTAT     0x200
+#define __XSTAT_VER_TYPEMASK   0xff00
+
+#define __XMKNOD_VER_1         1
+
 #endif
index 9ad62d15430bd07e79190780b16bb72abffc1007..4a74e20cb8d6ba2b0a40f2db0b579f69ba27c876 100644 (file)
@@ -54,6 +54,7 @@ struct termio {
 #define N_STRIP                4
 #define N_AX25         5
 #define N_X25          6       /* X.25 async */
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 
index 9bcf627939cbeb63e4bb02f2b87328f7da676d09..5ec2e008d2962d100dae3e0e061f99d126b9f269 100644 (file)
 #define __NR_rt_sigsuspend             (__NR_SYSCALL_BASE+179)
 #define __NR_pread                     (__NR_SYSCALL_BASE+180)
 #define __NR_pwrite                    (__NR_SYSCALL_BASE+181)
+#define __NR_xstat                     (__NR_SYSCALL_BASE+182)
+#define __NR_xmknod                    (__NR_SYSCALL_BASE+183)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
@@ -311,8 +313,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {                     \
  */
 #define __NR__exit __NR_exit
 static inline _syscall0(int,idle);
-static inline _syscall0(int,fork);
-static inline _syscall2(int,clone,unsigned long,flags,char *,esp);
 static inline _syscall0(int,pause);
 static inline _syscall1(int,setup,int,magic);
 static inline _syscall0(int,sync);
diff --git a/include/asm-arm/xstat.h b/include/asm-arm/xstat.h
new file mode 100644 (file)
index 0000000..84a9b07
--- /dev/null
@@ -0,0 +1,35 @@
+/* $Id: xstat.h,v 1.1 1998/02/06 12:52:45 jj Exp $
+ * xstat.h: sys_xstat/xmknod architecture dependent stuff.
+ *
+ * Copyright (C) 1998  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
+ */
+extern __inline__ int cp_xstat(struct inode *inode, struct stat64 *s, unsigned long blocks, int blksize)
+{
+       struct stat64 tmp;
+       
+       memset (&tmp, 0, sizeof(tmp));
+       tmp.st_dev.major = MAJOR(inode->i_dev);
+       tmp.st_dev.minor = MINOR(inode->i_dev);
+       tmp.st_ino = inode->i_ino;
+       tmp.st_mode = inode->i_mode;
+       tmp.st_nlink = inode->i_nlink;
+       tmp.st_uid = inode->i_uid;
+       tmp.st_gid = inode->i_gid;
+       tmp.st_rdev.major = MAJOR(inode->i_rdev);
+       tmp.st_rdev.minor = MINOR(inode->i_rdev);
+       tmp.st_size = inode->i_size;
+       tmp.st_blksize = blksize;
+       tmp.st_blocks = blocks;
+       tmp.st_atime = inode->i_atime;
+       tmp.st_mtime = inode->i_mtime;
+       tmp.st_ctime = inode->i_ctime;
+       return copy_to_user(s,&tmp,sizeof(tmp));
+}
+
+extern __inline__ int get_user_new_dev_t(kdev_t *kdev, __new_dev_t *udev) {
+       __new_dev_t ndev;
+       if (copy_from_user (&ndev, udev, sizeof(__new_dev_t))) return -EFAULT;
+       *kdev = MKDEV(ndev.major, ndev.minor);
+       return 0;
+}
index 5889ec88090f861f333c31f418ccf76399dcb538..e9952bd8e3ce04f19ec490a95793a38827a8de07 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _I386_PAGE_H
 #define _I386_PAGE_H
 
-#include <linux/config.h>
-
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
 #define PAGE_SIZE      (1UL << PAGE_SHIFT)
@@ -60,8 +58,30 @@ typedef unsigned long pgprot_t;
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
-/* This handles the memory map.. */
-#define __PAGE_OFFSET          ((0x1000-CONFIG_MAX_MEMSIZE)<<20)
+/*
+ * This handles the memory map.. We could make this a config
+ * option, but too many people screw it up, and too few need
+ * it.
+ *
+ * A __PAGE_OFFSET of 0xC0000000 means that the kernel has
+ * a virtual address space of one gigabyte, which limits the
+ * amount of physical memory you can use to about 950MB. If
+ * you want to use more physical memory, change this define.
+ *
+ * For example, if you have 2GB worth of physical memory, you
+ * could change this define to 0x70000000, which gives the
+ * kernel slightly more than 2GB of virtual memory (enough to
+ * map all your physical memory + a bit extra for various
+ * io-memory mappings)
+ *
+ * IF YOU CHANGE THIS, PLEASE ALSO CHANGE
+ *
+ *     arch/i386/vmlinux.lds
+ *
+ * which has the same constant encoded..
+ */
+#define __PAGE_OFFSET          (0xC0000000)
+
 #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
index c1176d6f83faf731a1d343b8fb417b717c958ba5..6deebbb03288cf5f4d6e7a41d7c4e60e1751eed8 100644 (file)
@@ -46,6 +46,7 @@ struct termio {
 #define N_STRIP                4
 #define N_AX25         5
 #define N_X25          6       /* X.25 async */
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 
index 6819f825b252047f4fadfb26642626f19aaecbf0..3ac10a193a86c05c675abc32596710e8ac5bdeda 100644 (file)
@@ -282,8 +282,6 @@ __syscall_return(type,__res); \
  */
 #define __NR__exit __NR_exit
 static inline _syscall0(int,idle)
-static inline _syscall0(int,fork)
-static inline _syscall2(int,clone,unsigned long,flags,char *,esp)
 static inline _syscall0(int,pause)
 static inline _syscall1(int,setup,int,magic)
 static inline _syscall0(int,sync)
index 3c022c3c8413188b1130427ed636d26e0f79d386..43d6707e715d91c76ccd0b72ced127c1b08777b2 100644 (file)
@@ -54,6 +54,7 @@ struct termio {
 #define N_STRIP                4
 #define N_AX25         5
 #define N_X25          6       /* X.25 async */
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 
index f82743219b8108afcd443ceb297786a1e1bf80ee..df55187a678916a2a9d212727e71b73eda94cfd1 100644 (file)
@@ -303,8 +303,6 @@ __syscall_return(type,__res); \
  */
 #define __NR__exit __NR_exit
 static inline _syscall0(int,idle)
-static inline _syscall0(int,fork)
-static inline _syscall2(int,clone,unsigned long,flags,char *,usp)
 static inline _syscall0(int,pause)
 static inline _syscall1(int,setup,int,magic)
 static inline _syscall0(int,sync)
index 5dfb3a995a414bc4d3692dbf41cc0b825bc39b65..8293b5df1178859834aed4f9555150cdb90d4c9e 100644 (file)
@@ -92,6 +92,7 @@ struct termio {
 #define N_STRIP                4
 #define N_AX25         5
 #define N_X25          6               /* X.25 async */
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 
index 0aac2ed4278533d890687c866f43abdeaab230cf..738a5f27227d1620a57e39803f2abbfa2eaacf0a 100644 (file)
@@ -1397,8 +1397,6 @@ return -1; \
  */
 #define __NR__exit __NR_exit
 static inline _syscall0(int,idle)
-static inline _syscall0(int,fork)
-static inline _syscall2(int,clone,unsigned long,flags,char *,esp)
 static inline _syscall0(int,pause)
 static inline _syscall1(int,setup,int,magic)
 static inline _syscall0(int,sync)
index 2ad2868ce0c44f5458c470c5fdfe24abf002b9d5..23f293eaa616062f365f04fd7b77b69c78cba2e8 100644 (file)
@@ -61,6 +61,8 @@ struct winsize {
 #define N_PPP          3
 #define N_STRIP                4
 #define N_AX25         5
+#define N_X25          6
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 
index f5425f51bd82fafdf38a9df5ecce4f2974cf1ad7..2b34f42a979153f436483ba37d04d68765e7d2d8 100644 (file)
@@ -425,8 +425,6 @@ return -1; \
  */
 #define __NR__exit __NR_exit
 static __inline__ _syscall0(int,idle)
-static __inline__ _syscall0(int,fork)
-static __inline__ _syscall2(int,clone,unsigned long,flags,char *,ksp)
 static __inline__ _syscall0(int,pause)
 static __inline__ _syscall1(int,setup,int,magic)
 static __inline__ _syscall0(int,sync)
index 3d7c5c2f44ee067d3afd0c6f2a65f1ac5f3ff945..622158d244fcaad8d2fb1b502608acc0a47876ff 100644 (file)
@@ -61,6 +61,8 @@ struct winsize {
 #define N_PPP          3
 #define N_STRIP                4
 #define N_AX25         5
+#define N_X25          6
+#define N_6PACK                7
 
 #ifdef __KERNEL__
 
index 67a3c4108c7177b2c0b3b49a1101de8c3a126a5d..70b12d890e6be1df9f48c86c086aa96953a04b97 100644 (file)
@@ -413,8 +413,6 @@ return -1; \
  */
 #define __NR__exit __NR_exit
 static __inline__ _syscall0(int,idle)
-static __inline__ _syscall0(int,fork)
-static __inline__ _syscall2(int,clone,unsigned long,flags,char *,ksp)
 static __inline__ _syscall0(int,pause)
 static __inline__ _syscall1(int,setup,int,magic)
 static __inline__ _syscall0(int,sync)
index 4d90c2eefae2087b95c2f9925b31a12ea170839c..b44cd83de1e69bf87200e4797f1f1f6d5f36964d 100644 (file)
@@ -11,6 +11,8 @@
  */
 #define MAX_ARG_PAGES 32
 
+#ifdef __KERNEL__
+
 /*
  * This structure is used to hold the arguments that are used when loading binaries.
  */
@@ -70,4 +72,5 @@ extern void compute_creds(struct linux_binprm *binprm);
 /* this eventually goes away */
 #define change_ldt(a,b) setup_arg_pages(a,b)
 
-#endif
+#endif /* __KERNEL__ */
+#endif /* _LINUX_BINFMTS_H */
index 05d0bbab8f66237d91491e73d22549c1f5d5d762..2a3f1f8ba13dab8eff3801befa044abc08d2a54d 100644 (file)
@@ -2,19 +2,18 @@
 #define _LINUX_JOYSTICK_H
 
 /*
- *  $Id: joystick.h,v 1.2 1997/10/31 19:11:57 mj Exp $
+ *  $Id: joystick.h,v 1.3 1998/03/30 11:10:40 mj Exp $
  *
- *  Copyright (C) 1997 Vojtech Pavlik
+ *  Copyright (C) 1997, 1998 Vojtech Pavlik
  */
 
-#include <linux/ioctl.h>
 #include <asm/types.h>
 
 /*
  * Version
  */
 
-#define JS_VERSION             0x00010006L             /* 1.0.6 BCD */
+#define JS_VERSION             0x00010007L             /* 1.0.7 BCD */
 
 /*
  * IOCTL commands for joystick driver
index 9a90d291bef89b2faaa95ae762edaa5c2cc3aa44..dbc03b0e20b1e23dd583726282eb2e9fb8c50465 100644 (file)
@@ -133,7 +133,7 @@ typedef struct page {
 #define PG_uptodate             3
 #define PG_free_after           4
 #define PG_decr_after           5
-/* Unused                       6 */
+#define PG_swap_unlock_after    6
 #define PG_DMA                  7
 #define PG_Slab                         8
 #define PG_swap_cache           9
@@ -146,6 +146,7 @@ typedef struct page {
 #define PageUptodate(page)     (test_bit(PG_uptodate, &(page)->flags))
 #define PageFreeAfter(page)    (test_bit(PG_free_after, &(page)->flags))
 #define PageDecrAfter(page)    (test_bit(PG_decr_after, &(page)->flags))
+#define PageSwapUnlockAfter(page) (test_bit(PG_swap_unlock_after, &(page)->flags))
 #define PageDMA(page)          (test_bit(PG_DMA, &(page)->flags))
 #define PageSlab(page)         (test_bit(PG_Slab, &(page)->flags))
 #define PageSwapCache(page)    (test_bit(PG_swap_cache, &(page)->flags))
index ba411531c09c0ca388fce4e194e1195891270062..3cab9e664d3adedde7f56331806cbf28cabc92f3 100644 (file)
 
 #ifdef __KERNEL__
 
+/* Create an index into the pci_dev base_address[] array from an offset.  */
+#define PCI_BASE_INDEX(o) (((o)-PCI_BASE_ADDRESS_0)>>2)
+
 /*
  * Error values that may be returned by the PCI bios.  Use
  * pcibios_strerror() to convert to a printable string.
index 48a0ca02c757890ac9175bb7454fc2de1b24f65f..c407d7428988edc247ea5a63062c3f7a5eb6eb26 100644 (file)
@@ -23,6 +23,7 @@ struct swap_info_struct {
        kdev_t swap_device;
        struct dentry * swap_file;
        unsigned char * swap_map;
+       unsigned char * swap_lockmap;
        unsigned int lowest_bit;
        unsigned int highest_bit;
        unsigned int cluster_next;
@@ -64,6 +65,7 @@ extern void swap_in(struct task_struct *, struct vm_area_struct *,
 extern void show_swap_cache_info(void);
 extern int add_to_swap_cache(struct page *, unsigned long);
 extern void swap_duplicate(unsigned long);
+extern void swap_after_unlock_page (unsigned long entry);
 extern struct page * read_swap_cache_async(unsigned long, int);
 #define read_swap_cache(entry) read_swap_cache_async(entry, 1);
 
index 730517cef8ef7bdf71fe997f7d7a1454a04ab23d..b5f6b38c78bd7715c616daca3def3397d2d57044 100644 (file)
@@ -141,6 +141,7 @@ extern struct inode_operations umsdos_dir_inode_operations;
 extern struct file_operations  umsdos_file_operations;
 extern struct inode_operations umsdos_file_inode_operations;
 extern struct inode_operations umsdos_file_inode_operations_no_bmap;
+extern struct inode_operations umsdos_file_inode_operations_readpage;
 extern struct inode_operations umsdos_symlink_inode_operations;
 extern int init_umsdos_fs(void);
 
index 7c0e64ec31ec70d9e8ebb05309ae6937ecc8a902..586f168fe0212ee976c4579703c0408140782a33 100644 (file)
@@ -31,7 +31,8 @@ void fill_new_filp (struct file *filp, struct dentry *dentry);
 void kill_dentry (struct dentry *dentry);
 struct dentry *creat_dentry (const char *name,
                             const int len,
-                            struct inode *inode);
+                            struct inode *inode,
+                            struct dentry *parent);
 ssize_t umsdos_file_write_kmem_real (struct file *filp,
                                const char *buf,
                                size_t  count,
index 064ee9d064fd1bbc5fcf5bc9de31f8045b602030..960ffad9a70d1157aed5e271f6b9ae7fa29f946d 100644 (file)
@@ -17,14 +17,20 @@ struct video_device
        int (*ioctl)(struct video_device *, unsigned int , void *);
        int (*mmap)(struct video_device *, const char *, unsigned long);
        int (*initialize)(struct video_device *);       
-       void *private;
+       void *priv;             /* Used to be 'private' but that upsets C++ */
        int busy;
        int minor;
 };
 
 extern int videodev_init(void);
 #define VIDEO_MAJOR    81
-extern int video_register_device(struct video_device *);
+extern int video_register_device(struct video_device *, int type);
+
+#define VFL_TYPE_GRABBER       0
+#define VFL_TYPE_VBI           1
+#define VFL_TYPE_RADIO         2
+#define VFL_TYPE_VTX           3
+
 extern void video_unregister_device(struct video_device *);
 #endif
 
@@ -39,10 +45,9 @@ extern void video_unregister_device(struct video_device *);
 #define VID_TYPE_SCALES                128     /* Scalable */
 #define VID_TYPE_MONOCHROME    256     /* Monochrome only */
 
-
 struct video_capability
 {
-       char    name[32];
+       char name[32];
        int type;
        int channels;   /* Num channels */
        int audios;     /* Num audio devices */
@@ -111,6 +116,11 @@ struct video_audio
 #define VIDEO_AUDIO_BASS       8
 #define VIDEO_AUDIO_TREBLE     16      
        char    name[16];
+#define VIDEO_SOUND_MONO       1
+#define VIDEO_SOUND_STEREO     2
+#define VIDEO_SOUND_LANG1      3
+#define VIDEO_SOUND_LANG2      4
+        __u16   mode;
 };
 
 struct video_clip
@@ -139,6 +149,12 @@ struct video_buffer
        int     bytesperline;
 };
 
+struct video_mmap
+{
+       unsigned int frame;             /* Frame (0 or 1) for double buffer */
+       int height,width;
+       unsigned int format;
+};
 
 struct video_key
 {
@@ -163,6 +179,8 @@ struct video_key
 #define VIDIOCSFREQ            _IOW('v',15, unsigned long)             /* Set tuner */
 #define VIDIOCGAUDIO           _IOR('v',16, struct video_audio)        /* Get audio info */
 #define VIDIOCSAUDIO           _IOW('v',17, struct video_audio)        /* Audio source, mute etc */
+#define VIDIOCSYNC             _IO('v',18)                             /* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE         _IOW('v',19, struct video_mmap)         /* Grab frames */
 
 
 #define BASE_VIDIOCPRIVATE     192             /* 192-255 are private */
@@ -172,6 +190,8 @@ struct video_key
 #define VID_HARDWARE_QCAM_BW   2
 #define VID_HARDWARE_PMS       3
 #define VID_HARDWARE_QCAM_C    4
+#define VID_HARDWARE_PSEUDO    5
+#define VID_HARDWARE_SAA5249   6
 
 /*
  *     Initialiser list
diff --git a/include/linux/videotext.h b/include/linux/videotext.h
new file mode 100644 (file)
index 0000000..bd427fb
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef _VTX_H
+#define _VTX_H
+
+/* $Id: videotext.h,v 1.1 1998/03/30 22:26:39 alan Exp $
+ *
+ * Copyright (c) 1994-97 Martin Buck  <martin-2.buck@student.uni-ulm.de>
+ * Read COPYING for more information
+ *
+ */
+
+
+/*
+ *     Videotext ioctls
+ */
+#define VTXIOCGETINFO  0x7101  /* get version of driver & capabilities of vtx-chipset */
+#define VTXIOCCLRPAGE  0x7102  /* clear page-buffer */
+#define VTXIOCCLRFOUND 0x7103  /* clear bits indicating that page was found */
+#define VTXIOCPAGEREQ  0x7104  /* search for page */
+#define VTXIOCGETSTAT  0x7105  /* get status of page-buffer */
+#define VTXIOCGETPAGE  0x7106  /* get contents of page-buffer */
+#define VTXIOCSTOPDAU  0x7107  /* stop data acquisition unit */
+#define VTXIOCPUTPAGE  0x7108  /* display page on TV-screen */
+#define VTXIOCSETDISP  0x7109  /* set TV-mode */
+#define VTXIOCPUTSTAT  0x710a  /* set status of TV-output-buffer */
+#define VTXIOCCLRCACHE 0x710b  /* clear cache on VTX-interface (if avail.) */
+#define VTXIOCSETVIRT  0x710c  /* turn on virtual mode (this disables TV-display) */
+
+
+/* 
+ *     Definitions for VTXIOCGETINFO
+ */
+#define SAA5243 0
+#define SAA5246 1
+#define SAA5249 2
+#define SAA5248 3
+#define XSTV5346 4
+
+typedef struct {
+       int version_major, version_minor;       /* version of driver; if version_major changes, driver */
+                                               /* is not backward compatible!!! CHECK THIS!!! */  
+       int numpages;                           /* number of page-buffers of vtx-chipset */
+       int cct_type;                           /* type of vtx-chipset (SAA5243, SAA5246, SAA5248 or
+                                                * SAA5249) */
+}
+vtx_info_t;
+
+
+/*
+ *     Definitions for VTXIOC{CLRPAGE,CLRFOUND,PAGEREQ,GETSTAT,GETPAGE,STOPDAU,PUTPAGE,SETDISP}
+ */
+
+#define MIN_UNIT   (1<<0)
+#define MIN_TEN    (1<<1)
+#define HR_UNIT    (1<<2)
+#define HR_TEN     (1<<3)
+#define PG_UNIT    (1<<4)
+#define PG_TEN     (1<<5)
+#define PG_HUND    (1<<6)
+#define PGMASK_MAX (1<<7)
+#define PGMASK_PAGE (PG_HUND | PG_TEN | PG_UNIT)
+#define PGMASK_HOUR (HR_TEN | HR_UNIT)
+#define PGMASK_MINUTE (MIN_TEN | MIN_UNIT)
+
+typedef struct 
+{
+       int page;       /* number of requested page (hexadecimal) */
+       int hour;       /* requested hour (hexadecimal) */
+       int minute;     /* requested minute (hexadecimal) */
+       int pagemask;   /* mask defining which values of the above are set */
+       int pgbuf;      /* buffer where page will be stored */
+       int start;      /* start of requested part of page */
+       int end;        /* end of requested part of page */
+       void *buffer;   /* pointer to beginning of destination buffer */
+}
+vtx_pagereq_t;
+
+
+/*
+ *     Definitions for VTXIOC{GETSTAT,PUTSTAT}
+ */
+#define VTX_PAGESIZE (40 * 24)
+#define VTX_VIRTUALSIZE (40 * 49)
+
+typedef struct 
+{
+       int pagenum;                    /* number of page (hexadecimal) */
+       int hour;                       /* hour (hexadecimal) */
+       int minute;                     /* minute (hexadecimal) */
+       int charset;                    /* national charset */
+       unsigned delete : 1;            /* delete page (C4) */
+       unsigned headline : 1;          /* insert headline (C5) */
+       unsigned subtitle : 1;          /* insert subtitle (C6) */
+       unsigned supp_header : 1;       /* suppress header (C7) */
+       unsigned update : 1;            /* update page (C8) */
+       unsigned inter_seq : 1;         /* interrupted sequence (C9) */
+       unsigned dis_disp : 1;          /* disable/suppress display (C10) */
+       unsigned serial : 1;            /* serial mode (C11) */
+       unsigned notfound : 1;          /* /FOUND */
+       unsigned pblf : 1;              /* PBLF */
+       unsigned hamming : 1;           /* hamming-error occured */
+}
+vtx_pageinfo_t;
+
+
+/*
+ *     Definitions for VTXIOCSETDISP
+ */
+typedef enum { 
+       DISPOFF, DISPNORM, DISPTRANS, DISPINS, INTERLACE_OFFSET 
+} vtxdisp_t;
+
+
+
+/*
+ *     Tuner ioctls
+ */
+#define TUNIOCGETINFO  0x7201  /* get version of driver & capabilities of tuner */
+#define TUNIOCRESET    0x7202  /* reset tuner */
+#define TUNIOCSETFREQ  0x7203  /* set tuning frequency (unit: kHz) */
+#define TUNIOCGETFREQ  0x7204  /* get tuning frequency (unit: kHz) */
+#define TUNIOCSETCHAN  0x7205  /* set tuning channel */
+#define TUNIOCGETCHAN  0x7206  /* get tuning channel */
+
+
+typedef struct 
+{
+       int version_major, version_minor;       /* version of driver; if version_major changes, driver */
+                                               /* is not backward compatible!!! CHECK THIS!!! */  
+       unsigned freq : 1;                      /* tuner can be set to given frequency */
+       unsigned chan : 1;                      /* tuner stores several channels */
+       unsigned scan : 1;                      /* tuner supports scanning */
+       unsigned autoscan : 1;          /* tuner supports scanning with automatic stop */
+       unsigned afc : 1;                       /* tuner supports AFC */
+       unsigned dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, dummy7, dummy8, dummy9, dummy10,
+               dummy11 : 1;
+       int dummy12, dummy13, dummy14, dummy15, dummy16, dummy17, dummy18, dummy19;
+} tuner_info_t;
+
+
+#endif /* _VTX_H */
index 35801b7c5e0f075d6eb8562f8bf5557d893ddd6c..05c5b3b52b8486aa0c63d10cb40aefac178cacb3 100644 (file)
@@ -142,15 +142,7 @@ extern __inline__ int ip_finish_output(struct sk_buff *skb)
        skb->protocol = __constant_htons(ETH_P_IP);
 
        if (hh) {
-#ifdef __alpha__
-               /* Alpha has disguisting memcpy. Help it. */
-               u64 *aligned_hdr = (u64*)(skb->data - 16);
-               u64 *aligned_hdr0 = hh->hh_data;
-               aligned_hdr[0] = aligned_hdr0[0];
-               aligned_hdr[1] = aligned_hdr0[1];
-#else
                memcpy(skb->data - 16, hh->hh_data, 16);
-#endif
                skb_push(skb, dev->hard_header_len);
                return hh->hh_output(skb);
        } else if (dst->neighbour)
index 88d56c0a7b2882e48405c829779097776a455069..a54b51783114609cde47276d66844956ed1547a5 100644 (file)
@@ -70,7 +70,7 @@ extern void init_modules(void);
 extern long console_init(long, long);
 extern void sock_init(void);
 extern void uidcache_init(void);
-extern long mca_init(long, long);
+extern void mca_init(void);
 extern long sbus_init(long, long);
 extern long powermac_init(unsigned long, unsigned long);
 extern void sysctl_init(void);
@@ -1012,6 +1012,12 @@ __initfunc(asmlinkage void start_kernel(void))
        sched_init();
        time_init();
        parse_options(command_line);
+
+       /*
+        * HACK ALERT! This is early. We're enabling the console before
+        * we've done PCI setups etc, and console_init() must be aware of
+        * this. But we do want output early, in case something goes wrong.
+        */
        memory_start = console_init(memory_start,memory_end);
 #ifdef CONFIG_MODULES
        init_modules();
@@ -1027,14 +1033,6 @@ __initfunc(asmlinkage void start_kernel(void))
        }
 #endif
 
-/*
- * HACK ALERT! This is early. We're enabling the console before
- * we've done PCI setups etc, and console_init() must be aware of
- * this. But we do want output early, in case something goes wrong.
- */
-#if HACK
-       memory_start = console_init(memory_start,memory_end);
-#endif
        memory_start = kmem_cache_init(memory_start, memory_end);
        sti();
        calibrate_delay();
index 379c276955789cb3e71fab2c4d08e065eb91f11a..5a5602c6f844f4eab96ea8b875dd3330b1ca7516 100644 (file)
@@ -15,8 +15,8 @@
 int kmod_unload_delay = 60;
 char modprobe_path[256] = "/sbin/modprobe";
 static char module_name[64] = "";
-static char * argv[] = { "modprobe", "-k", module_name, NULL, };
-static char * envp[] = { "HOME=/", "TERM=linux", NULL, };
+static char * argv[] = { modprobe_path, "-s", "-k", module_name, NULL };
+static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };
 
 /*
        kmod_queue synchronizes the kmod thread and the rest of the system
@@ -26,11 +26,24 @@ static char * envp[] = { "HOME=/", "TERM=linux", NULL, };
 static struct wait_queue * kmod_queue = NULL;
 static struct timer_list kmod_unload_timer;
 
+/*
+       It is not easy to implement a full fork in kernel-space on some
+       systems (Alpha), and it is not necessary for us here.  This is 
+       a new thread that does the exec.
+*/
+static int kmod_exec_modprobe(void * data)
+{
+       sigemptyset(&current->blocked);
+       execve(modprobe_path, argv, envp);
+       printk(KERN_ERR "kmod: failed to load module %s\n", module_name);
+       return 0;
+}
+
 /*
        kmod_thread is the thread that does most of the work.  kmod_unload and
        request_module tell it to wake up and do work.
 */
-int kmod_thread(void * data)
+static int kmod_thread(void * data)
 {
        int pid;
 
@@ -60,24 +73,13 @@ int kmod_thread(void * data)
                if (module_name[0] == '\0') {
                        delete_module(NULL);
                } else {
-                       pid = fork();
+                       pid = kernel_thread(kmod_exec_modprobe, NULL, SIGCHLD);
                        if (pid > 0) {
                                waitpid(pid, NULL, 0);
                                module_name[0] = '\0';
                                wake_up(&kmod_queue);
-                       } else
-                       if (pid == 0) {
-
-                               /*
-                                       Call modprobe with module_name.  If execve returns,
-                                       print out an error.
-                               */
-                               execve(modprobe_path, argv, envp);
-
-                               printk("kmod: failed to load module %s\n", module_name);
-                               _exit(0);
                        } else {
-                               printk("error, fork failed in kmod\n");
+                               printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid);
                        }
                }
        }
@@ -104,7 +106,7 @@ void kmod_unload(unsigned long x)
 
 int kmod_init(void)
 {
-       printk ("Starting kmod\n");
+       printk("Starting kmod\n");
 
        kernel_thread(kmod_thread, NULL, 0);
 
index e02565def7e67a580b2f9f3fbc3e9a3f205d3c4c..eb436f7b7c10eefe6c8ff1b4dc8ae20fb10e64d1 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
+static struct wait_queue * lock_queue = NULL;
+
 /*
  * Reads or writes a swap page.
  * wait=1: start I/O and wait for completion. wait=0: start asynchronous I/O.
@@ -87,6 +89,12 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait)
                return;
        }
        
+       /* Make sure we are the only process doing I/O with this swap page. */
+       while (test_and_set_bit(offset,p->swap_lockmap)) {
+               run_task_queue(&tq_disk);
+               sleep_on(&lock_queue);
+       }
+       
        if (rw == READ) {
                clear_bit(PG_uptodate, &page->flags);
                kstat.pswpin++;
@@ -115,6 +123,7 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait)
                if (!wait) {
                        set_bit(PG_free_after, &page->flags);
                        set_bit(PG_decr_after, &page->flags);
+                       set_bit(PG_swap_unlock_after, &page->flags);
                        atomic_inc(&nr_async_pages);
                }
                ll_rw_page(rw,p->swap_device,offset,buf);
@@ -173,6 +182,9 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait)
                printk("rw_swap_page: no swap file or device\n");
 
        atomic_dec(&page->count);
+       if (offset && !test_and_clear_bit(offset,p->swap_lockmap))
+               printk("rw_swap_page: lock already cleared\n");
+       wake_up(&lock_queue);
 #ifdef DEBUG_SWAP
        printk ("DebugVM: %s_swap_page finished on page %p (count %d)\n",
                (rw == READ) ? "read" : "write", 
@@ -180,6 +192,28 @@ void rw_swap_page(int rw, unsigned long entry, char * buf, int wait)
 #endif
 }
 
+/* This is run when asynchronous page I/O has completed. */
+void swap_after_unlock_page (unsigned long entry)
+{
+       unsigned long type, offset;
+       struct swap_info_struct * p;
+
+       type = SWP_TYPE(entry);
+       if (type >= nr_swapfiles) {
+               printk("swap_after_unlock_page: bad swap-device\n");
+               return;
+       }
+       p = &swap_info[type];
+       offset = SWP_OFFSET(entry);
+       if (offset >= p->max) {
+               printk("swap_after_unlock_page: weirdness\n");
+               return;
+       }
+       if (!test_and_clear_bit(offset,p->swap_lockmap))
+               printk("swap_after_unlock_page: lock already cleared\n");
+       wake_up(&lock_queue);
+}
+
 /*
  * Setting up a new swap file needs a simple wrapper just to read the 
  * swap signature.  SysV shared memory also needs a simple wrapper.
index ba786460420b28926c1fdf8180cbccd8f18163b5..581cde3d70c3093956480bcc3bc6e59d5860e296 100644 (file)
--- a/mm/simp.c
+++ b/mm/simp.c
@@ -70,7 +70,8 @@ struct simp {
        /* next cache line */
        struct header * usable_list;
        spinlock_t lock;
-       char fill[sizeof(void*) - sizeof(spinlock_t)];
+       /* This value is negative on Alpha SMP.  */
+       /* char fill[sizeof(void*) - sizeof(spinlock_t)]; */
        long real_size;
        long max_elems;
        structor again_ctor;
index 8608db8d8e6059fc250e6c6a79fbfaf52e753ec2..f9cd0d47e852f422618704552754ce62c4cbb544 100644 (file)
@@ -52,6 +52,8 @@ static inline int scan_swap_map(struct swap_info_struct *si)
                        offset = si->cluster_next++;
                        if (si->swap_map[offset])
                                continue;
+                       if (test_bit(offset, si->swap_lockmap))
+                               continue;
                        si->cluster_nr--;
                        goto got_page;
                }
@@ -60,6 +62,8 @@ static inline int scan_swap_map(struct swap_info_struct *si)
        for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) {
                if (si->swap_map[offset])
                        continue;
+               if (test_bit(offset, si->swap_lockmap))
+                       continue;
                si->lowest_bit = offset;
 got_page:
                si->swap_map[offset] = 1;
@@ -424,6 +428,8 @@ asmlinkage int sys_swapoff(const char * specialfile)
        p->swap_device = 0;
        vfree(p->swap_map);
        p->swap_map = NULL;
+       free_page((long) p->swap_lockmap);
+       p->swap_lockmap = NULL;
        p->flags = 0;
        err = 0;
 out:
@@ -483,7 +489,6 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
        int error = -EPERM;
        struct file filp;
        static int least_priority = 0;
-       unsigned char *avail_map = 0;
 
        lock_kernel();
        if (!suser())
@@ -501,6 +506,7 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
        p->swap_file = NULL;
        p->swap_device = 0;
        p->swap_map = NULL;
+       p->swap_lockmap = NULL;
        p->lowest_bit = 0;
        p->highest_bit = 0;
        p->cluster_nr = 0;
@@ -543,24 +549,24 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
                }
        } else if (!S_ISREG(swap_dentry->d_inode->i_mode))
                goto bad_swap;
-       avail_map = (unsigned char *) get_free_page(GFP_USER);
-       if (!avail_map) {
+       p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER);
+       if (!p->swap_lockmap) {
                printk("Unable to start swapping: out of memory :-)\n");
                error = -ENOMEM;
                goto bad_swap;
        }
-       rw_swap_page_nocache(READ, SWP_ENTRY(type,0), (char *) avail_map);
-       if (memcmp("SWAP-SPACE",avail_map+PAGE_SIZE-10,10)) {
+       rw_swap_page_nocache(READ, SWP_ENTRY(type,0), (char *) p->swap_lockmap);
+       if (memcmp("SWAP-SPACE",p->swap_lockmap+PAGE_SIZE-10,10)) {
                printk("Unable to find swap-space signature\n");
                error = -EINVAL;
                goto bad_swap;
        }
-       memset(avail_map+PAGE_SIZE-10,0,10);
+       memset(p->swap_lockmap+PAGE_SIZE-10,0,10);
        j = 0;
        p->lowest_bit = 0;
        p->highest_bit = 0;
        for (i = 1 ; i < 8*PAGE_SIZE ; i++) {
-               if (test_bit(i,avail_map)) {
+               if (test_bit(i,p->swap_lockmap)) {
                        if (!p->lowest_bit)
                                p->lowest_bit = i;
                        p->highest_bit = i;
@@ -579,12 +585,13 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
                goto bad_swap;
        }
        for (i = 1 ; i < p->max ; i++) {
-               if (test_bit(i,avail_map))
+               if (test_bit(i,p->swap_lockmap))
                        p->swap_map[i] = 0;
                else
                        p->swap_map[i] = 0x80;
        }
        p->swap_map[0] = 0x80;
+       memset(p->swap_lockmap,0,PAGE_SIZE);
        p->flags = SWP_WRITEOK;
        p->pages = j;
        nr_swap_pages += j;
@@ -611,15 +618,15 @@ bad_swap:
        if(filp.f_op && filp.f_op->release)
                filp.f_op->release(filp.f_dentry->d_inode,&filp);
 bad_swap_2:
+       free_page((long) p->swap_lockmap);
        vfree(p->swap_map);
        dput(p->swap_file);
        p->swap_device = 0;
        p->swap_file = NULL;
        p->swap_map = NULL;
+       p->swap_lockmap = NULL;
        p->flags = 0;
 out:
-       if (avail_map)
-               free_page((long) avail_map);
        unlock_kernel();
        return error;
 }
index f1601e4919684bd8f0ff87ae1b380e0dad28a766..3396d3aa493939b48cab78ad972e78dd81c52cf0 100644 (file)
@@ -1483,7 +1483,7 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
                skb->csum = csum_partial((char *)th, len, 0);
        case CHECKSUM_HW:
                if (tcp_v4_check(th,len,skb->nh.iph->saddr,skb->nh.iph->daddr,skb->csum)) {
-                       printk(KERN_DEBUG "TCPv4 bad checksum from %d.%d.%d.%d:%04x to %d.%d.%d.%d:%04x, "
+                       printk(KERN_DEBUG "TCPv4 bad checksum from %ld.%ld.%ld.%ld:%04x to %ld.%ld.%ld.%ld:%04x, "
                               "len=%d/%d/%d\n",
                               NIPQUAD(ntohl(skb->nh.iph->saddr)),
                               ntohs(th->source),