]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.19pre3 2.2.19pre3
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:23:02 +0000 (15:23 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:23:02 +0000 (15:23 -0500)
o Merge ADMtek-comet tulip support (Jim McQuillan)
o Update microcode driver (Tigran Aivazian)
o Merge Don Becker's NE2K full duplex support (Juan Lacarta)
o Optimise kernel compiler detect, kgcc before (Peter Samuelson)
gcc272 also
o Fix compile combination problems (Arjan van de Ven)
o Update via-rhine driver to include Don's changes(Urban Widmark)
for VT6102
o Documentation updates (Tim Waugh)
o Add ISDN PCI defines to pci.h (Kai Germaschewski)
o Fix smb/fat handling for pre 1980 dates (Igor Zhbanov)
o SyncLink updates (Paul Fulghum)
o ICP vortex driver updates  (Andreas Köpf)
o mdacon clean up (Pavel Rabel)
o Fix bugs in es1370/es1371/sonicvibes/solo1/ (Thomas Sailer)
dabusb
o Speed up x86 irq/fault paths by avoiding xchg (Mikael Pettersson)
locked cycles (from Brian Gerst's 2.4test change)
o Tighten up K6 check in bug tests (Mikael Pettersson)
o Backport configure scripts bug fixes (Mikael Pettersson)
o Fix duplicat help entries (Riley Williams)
o Fix small asm bug in constant size uaccess (David Kutz)
o Update ymfpci driver to handle legacy audio (Daisuke Nagano)
o Remove ymfsb driver now no longer needed (Daisuke Nagano)
o Add Empeg support to usb-serial (Gary Brubaker)
o Fix e820 handling (Andrea Arcangeli)
o Fix lanstreamer SMP locking (George Staikos)
o Fix S/390 non SMP build (Kurt Roeckx)
o Fix the PCI syscall on PowerMac (Benjamin Herrenschmidt)
o Fix IPC_RMID behaviour (Christoph Rohland)
o Fix NETCTL_GETFD on sparc64 (Dave Miller)
o Tidy unneeded restore_flags/save sequence  (Arnaldo Carvalho de Melo)
on the ultrastor
o Fix resource clean up on error in 89xo     (Arnaldo Carvalho de Melo)
driver
o Update wireless headers (Jean Tourrilhes)
o Fix non modular emu10k init (Mikael Pettersson)
o Fix cpuid/msr driver crashes (Andrew Morton)
o Write core files sparse (Christoph Rohland)
o Merge the i810 tco (watchdog) timer (Alan Cox)
| original by Jeff Garzik

79 files changed:
Documentation/Changes
Documentation/Configure.help
Documentation/sound/ChangeLog.ymfsb [deleted file]
Documentation/sound/README.ymfsb [deleted file]
Documentation/usb/usb-serial.txt
Makefile
arch/i386/kernel/cpuid.c
arch/i386/kernel/entry.S
arch/i386/kernel/microcode.c
arch/i386/kernel/msr.c
arch/i386/kernel/setup.c
arch/i386/kernel/smp.c
arch/i386/kernel/traps.c
arch/i386/mm/init.c
arch/ppc/kernel/pmac_setup.c
arch/s390/config.in
arch/s390/kernel/s390_ksyms.c
arch/s390/kernel/setup.c
arch/sparc64/kernel/sys_sparc32.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/i810-tco.c [new file with mode: 0644]
drivers/char/i810-tco.h [new file with mode: 0644]
drivers/char/n_hdlc.c
drivers/char/synclink.c
drivers/isdn/hisax/bkm_a8.c
drivers/isdn/hisax/nj_s.c
drivers/isdn/hisax/nj_u.c
drivers/net/Config.in
drivers/net/cs89x0.c
drivers/net/lanstreamer.c
drivers/net/lanstreamer.h
drivers/net/ne2k-pci.c
drivers/net/tulip.c
drivers/net/via-rhine.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd.h
drivers/s390/block/dasd_3370_erp.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_9336_erp.c
drivers/s390/block/dasd_9343_erp.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_fba.h
drivers/s390/block/mdisk.c
drivers/scsi/gdth.c
drivers/scsi/gdth.h
drivers/scsi/gdth_ioctl.h
drivers/scsi/gdth_proc.c
drivers/scsi/ultrastor.c
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/emu10k1/main.c
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/esssolo1.c
drivers/sound/sonicvibes.c
drivers/sound/sound_core.c
drivers/sound/ymf_sb.c [deleted file]
drivers/sound/ymfpci.c
drivers/sound/ymfpci.h
drivers/usb/Config.in
drivers/usb/dabusb.c
drivers/usb/serial/Makefile
drivers/usb/serial/empeg.c [new file with mode: 0644]
drivers/video/mdacon.c
fs/binfmt_elf.c
fs/fat/misc.c
fs/smbfs/ChangeLog
fs/smbfs/proc.c
include/asm-i386/bugs.h
include/asm-i386/uaccess.h
include/linux/interrupt.h
include/linux/pci.h
include/linux/synclink.h
include/linux/wireless.h
ipc/shm.c
scripts/Configure

index 371eb98e7c7f84df5f465da3319298f7ebd576c3..84157c85c028fddc14c0c11fea5b55bd01fb6d1a 100644 (file)
@@ -542,6 +542,28 @@ alias char-major-10-184 microcode
 to your /etc/modules.conf file.
 
 
+Intel IA32 microcode
+====================
+
+A driver has been added to allow updating of Intel IA32 microcode,
+accessible as both a devfs regular file and as a normal (misc)
+character device.  If you are not using devfs you may need to:
+
+mkdir /dev/cpu
+mknod /dev/cpu/microcode c 10 184
+chmod 0644 /dev/cpu/microcode
+
+as root before you can use this.  You'll probably also want to
+get the user-space microcode_ctl utility to use with this.
+
+If you have compiled the driver as a module you may need to add
+the following line:
+
+alias char-major-10-184 microcode
+
+to your /etc/modules.conf file.
+
+
 Where to get the files
 **********************
 
index f9c2acc4a052a5a9c7247c73589a6462ca2cf95c..83d751d191af2c36f5ce3fbd77a39f7c51326a3f 100644 (file)
@@ -5895,6 +5895,25 @@ CONFIG_COMX_HW_MIXCOM
   If you want to compile this as a module, say M and read
   Documentation/modules.txt. The module will be called comx-hw-mixcom.o.
 
+i810 TCO support
+CONFIG_I810_TCO
+  Hardware driver for the TCO timer built into the Intel i810 and i815
+  chipset family. The TCO (Total Cost of Ownership) timer is a watchdog
+  timer that will reboot the machine after it's second expiration. The
+  expiration time can be configured by commandline argument
+  "i810_margin=<n>" where <n> is the counter initial value. It is
+  decremented every 0.6 secs, the default is 50 which gives a timeout
+  of 30 seconds and one minute until reset.
+
+  On some motherboards the driver may fail to reset the chipset's
+  NO_REBOOT flag which prevents the watchdog from rebooting the machine.
+  If this is the case you will get a kernel message like
+  "i810tco init: failed to reset NO_REBOOT flag".
+
+  If you want to compile this as a module, say M and read
+  Documentation/modules.txt. The module will be called
+  i810-tco.o.
+
 MultiGate Cisco-HDLC and synchronous PPP protocol support
 CONFIG_COMX_PROTO_PPP
   Cisco-HDLC and synchronous PPP protocol driver for all MultiGate boards. 
@@ -7511,13 +7530,6 @@ CONFIG_QUOTA
   ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/mini. Probably the quota
   support is only useful for multi user systems. If unsure, say N.
 
-Acorn's ADFS filesystem support (read only) (EXPERIMENTAL)
-CONFIG_ADFS_FS
-  The Advanced Disk File System is the filesystem used on floppy and
-  hard disks by Acorn Systems.  Currently in development, as a read-
-  only driver for hard disks.  These should be the first partition
-  (eg. /dev/[sh]d?1) on each of your drives.  If unsure, say N.
-
 Support for USB
 CONFIG_USB
   Universal Serial Bus (USB) is a specification for a serial bus
@@ -7890,6 +7902,16 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT
   The module will be called digi_acceleport.o. If you want to compile 
   it as a module, say M here and read Documentation/modules.txt.
 
+USB Empeg empeg-car Mark I/II Driver
+CONFIG_USB_SERIAL_EMPEG
+  Say Y here if you want to connect to your Empeg empeg-car Mark I/II
+  mp3 player via USB.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called empeg.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
 USB Serial Converter verbose debug
 CONFIG_USB_SERIAL_DEBUG
   Say Y here if you want verbose debug messages from the USB Serial
@@ -9696,6 +9718,24 @@ CONFIG_PRINTER
   If you have more than 3 printers, you need to increase the LP_NO
   variable in lp.c.
 
+Amiga built-in parallel port support
+CONFIG_PARPORT_AMIGA
+  Say Y here if you need support for the parallel port hardware on
+  Amiga machines. This code is also available as a module (say M),
+  called parport_amiga.o. If in doubt, saying N is the safe plan.
+
+Atari built-in parallel port support
+CONFIG_PARPORT_ATARI
+  Say Y here if you need support for the parallel port hardware on
+  Atari machines. This code is also available as a module (say M),
+  called parport_atari.o. If in doubt, saying N is the safe plan.
+
+Multiface 3 parallel port card support
+CONFIG_PARPORT_MFC3
+  Say Y here if you need parallel port support for the MFC3 card.
+  This code is also available as a module (say M), called
+  parport_mfc3.o. If in doubt, saying N is the safe plan.
+
 Support IEEE1284 status readback
 CONFIG_PRINTER_READBACK
   If your printer conforms to IEEE 1284, it may be able to provide a
@@ -10742,17 +10782,6 @@ CONFIG_JOY_AMIGA
   to it. For more information on how to use the driver please read
   Documentation/joystick.txt
 
-Atomwide Serial Support
-CONFIG_ATOMWIDE_SERIAL
-  If you have an Atomwide Serial card for an Acorn system, say Y to
-  this option. The driver can handle 1, 2, or 3 port cards.
-  If unsure, say N
-
-The Serial Port Dual Serial Port
-CONFIG_DUALSP_SERIAL
-  If you have the Serial Port's dual serial card for an Acorn system,
-  say Y to this option. If unsure, say N
-
 NetWinder Button
 CONFIG_NWBUTTON
   If you enable this driver and create a character device node
@@ -12815,22 +12844,6 @@ ZOLTRIX I/O port (0x20c or 0x30c)
 CONFIG_RADIO_ZOLTRIX_PORT
   Enter the I/O port of your Zoltrix radio card.
 
-ADS Cadet AM/FM Tuner
-CONFIG_RADIO_CADET
-  Say Y here if this is your AM/FM radio card.
-
-  In order to control your radio card, you will need to use programs
-  that are compatible with the Video for Linux API. Information on 
-  this API and pointers to "v4l" programs may be found on the WWW at
-  http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW,
-  you need to have access to a machine on the Internet that has a 
-  program like lynx or netscape.
-
-  If you want to compile this driver as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read Documentation/modules.txt. The module will be
-  called radio-cadet.o
-
 Miro PCM20 Radio
 CONFIG_RADIO_MIROPCM20
   Choose Y here if you have this FM radio card. You also need to say Y
diff --git a/Documentation/sound/ChangeLog.ymfsb b/Documentation/sound/ChangeLog.ymfsb
deleted file mode 100644 (file)
index 11fede8..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-Sun May 21 15:14:37 2000  Daisuke Nagano  <breeze.nagano@nifty.ne.jp>
-
-       * ymf_sb.c: Add 'master_vol' module parameter to change
-       'PCM out Vol" of AC'97.
-       Should I support AC'97 mixer by implementing original mixer
-       codes... ?
-
-       * ymf_sb.c: remove native UART401 support. External MIDI port
-       should be supported by sb_midi driver.
-
-       *ymf_sb.c: add support for SPDIF OUT. Module parameter
-       'spdif_out' is now available.
-
-
-Tue May 16 19:29:29 2000  Daisuke Nagano  <breeze.nagano@nifty.ne.jp>
-
-       * ymf_sb.c (checkCodec): add a little delays for reset devices.
-       
-       * ymf_sb.c (readRegWord): fixed addressing bug.
diff --git a/Documentation/sound/README.ymfsb b/Documentation/sound/README.ymfsb
deleted file mode 100644 (file)
index 3218d1d..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-Legacy audio driver for YMF7xx PCI cards.
-
-
-FIRST OF ALL
-============
-
-  This code references YAMAHA's sample codes and data sheets.
-  I respect and thank for all people they made open the informations
-  about YMF7xx cards.
-
-  And this codes heavily based on Jeff Garzik <jgarzik@pobox.com>'s
-  old VIA 82Cxxx driver (via82cxxx.c). I also respect him.
-
-
-DISCLIMER
-=========
-
- This driver is currently at early ALPHA stage. It may cause serious
- damage to your computer when used.
- PLEASE USE IT AT YOUR OWN RISK.
-
-
-ABOUT THIS DRIVER
-=================
-
-  This code enables you to use your YMF724[A-F], YMF740[A-C], YMF744, YMF754
- cards as "SoundBlaster Pro" compatible card. It can only play 22.05kHz /
- 8bit / Stereo samples, control external MIDI port.
- And it can handle AC'97 mixer of these cards.
-
-  If you want to use your card as recent "16-bit" card, you should use
- Alsa or OSS/Linux driver. Ofcource you can write native PCI driver for
- your cards :)
-
-
-INSTALL
-=======
-
-  First, it requires some sound driver modules in Linux kernel 
- (soundcore.o , sound.o, sb.o and uart401.o), so you should enable
- these modules at kernel configuration (please refer some other 
- documentations for configuration of kernel).
- And add the following line in /etc/modules.conf:
-
-  options sb support=1
-
- (NOTE: There are no need any configuration of sb modules)
-
- To compile ymfsb module, type 'make'.
- And copy it to /lib/modules/(kernel_version)/misc, type 'depmod -a'.
-  This module also requires /usr/src/linux/drivers/sound/ac97.[ch].
- If your kernel doesn't have these files, you should upgrade your kernel.
-
-
-USAGE
-=====
-
- # modprobe ymfsb (options)
-
-
-OPTIONS FOR YMFSB
-=================
-
-  io           : SB base address     (0x220, 0x240, 0x260, 0x280)
-  synth_io     : OPL3 base address   (0x388, 0x398, 0x3a0, 0x3a8)
-  dma          : DMA number          (0,1,3)
-  spdif_out    : SPDIF-out flag      (0:disable 1:enable)
-
- These options will change in future...
-
-
-FREQUENCY
-=========
-
-  When playing sounds via this driver, you will hear its pitch is slightly
- lower than original sounds. Since this driver recognizes your card acts
- with 21.739kHz sample rates rather than 22.050kHz (I think it must be
- hardware restriction). So many players become tone deafness.
- To prevent this, you should express some options to your sound player
- that specify correct sample frequency. For example, to play your MP3 file
- correctly with mpg123, specify the frequency like following:
-
-  %  mpg123 -r 21739 foo.mp3
-
-
-SPDIF OUT
-=========
-
-  With installing modules with option 'spdif_out=1', you can enjoy your
- sounds from SPDIF-out of your card (if it had).
- Its Fs is fixed to 48kHz (It never means the sample frequency become 
- up to 48kHz. All sounds via SPDIF-out also 22kHz samples). So your
- digital-in capable components has to be able to handle 48kHz Fs.
-
-
-COPYING
-=======
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-TODO
-====
- * support for multiple cards
-   (set the different SB_IO,MPU_IO,OPL_IO for each cards)
-
- * support for OPL (dmfm) : There will be no requirements... :-<
-
-
-AUTHOR
-======
-
- Daisuke Nagano <breeze.nagano@nifty.ne.jp>
-
index 1be7b76b59e72f2d8ae9addd4dec4c212eb16c65..c12592e642ebf17fd3fc44d2c9bd04d643e66398 100644 (file)
@@ -185,6 +185,15 @@ TO DO List:
   -- Add everything else that is missing :)
 
 
+Empeg empeg-car Mark I/II Driver (empeg.c)
+
+  This is an experimental driver to provide connectivity support for the
+  client synchronization tools for an Empeg empeg-car mp3 player.
+
+  The driver is still pretty new, so some testing 'in the wild' would be
+  helpful. :)
+
+
 Generic Serial driver
 
   If your device is not one of the above listed devices, compatible with
index a751970a0f59425142abd43bb225b812acf0e886..aec27f60880be20553c902c9bd998b5408b3eb83 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 19
-EXTRAVERSION = pre2
+EXTRAVERSION = pre3
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -24,12 +24,14 @@ AS  =$(CROSS_COMPILE)as
 LD     =$(CROSS_COMPILE)ld
 #
 #      foo-bar-gcc for cross builds
-#      gcc272 for Debian's old compiler for kernels
-#      kgcc for Conectiva and Red Hat 7
+#      kgcc for Conectiva, Red Hat, Mandrake
+#      gcc272 for Debian
 #      otherwise 'cc'
 #
-CC     =$(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else \
-       $(CONFIG_SHELL) scripts/kwhich gcc272 2>/dev/null || $(CONFIG_SHELL) scripts/kwhich kgcc 2>/dev/null || echo cc; fi) \
+CCFOUND :=$(shell $(CONFIG_SHELL) scripts/kwhich kgcc gcc272 cc gcc)
+## Faster, but requires GNU make 3.78, which postdates Linux 2.2.0
+##CC   =$(if $(CROSS_COMPILE),$(CROSS_COMPILE)gcc,$(CCFOUND)) -D__KERNEL__ -I$(HPATH)
+CC     =$(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else echo $(CCFOUND); fi) \
        -D__KERNEL__ -I$(HPATH)
 CPP    =$(CC) -E
 AR     =$(CROSS_COMPILE)ar
index 0f3a95106ec10f6d3c746830e51e9f2cfae5d792..f05e0994d1ab5f7242db4cd671deb11499f01c85 100644 (file)
@@ -152,6 +152,7 @@ int __init cpuid_init(void)
 
 static void cpuid_exit(void)
 {
+  unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
 }
 
 module_init(cpuid_init);
index 474b9d6d9fd31f8ed40ef9c88e9a69ce6800404c..419752f90834cc8d265bdfcb9329276f3d7f0008 100644 (file)
@@ -267,16 +267,18 @@ error_code:
        pushl %ebx
        cld
        movl %es,%cx
-       xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
+       movl ORIG_EAX(%esp), %esi       # get the error code
+       movl ES(%esp), %edi             # get the function address
+       movl %eax, ORIG_EAX(%esp)
+       movl %ecx, ES(%esp)
        movl %esp,%edx
-       xchgl %ecx, ES(%esp)            # get the address and save es.
-       pushl %eax                      # push the error code
-       pushl %edx
+       pushl %esi                      # push the error code
+       pushl %edx                      # push the pt_regs pointer
        movl $(__KERNEL_DS),%edx
        movl %dx,%ds
        movl %dx,%es
        GET_CURRENT(%ebx)
-       call *%ecx
+       call *%edi
        addl $8,%esp
        jmp ret_from_exception
 
@@ -333,11 +335,6 @@ ENTRY(coprocessor_segment_overrun)
        pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun)
        jmp error_code
 
-ENTRY(reserved)
-       pushl $0
-       pushl $ SYMBOL_NAME(do_reserved)
-       jmp error_code
-
 ENTRY(double_fault)
        pushl $ SYMBOL_NAME(do_double_fault)
        jmp error_code
index 27f1c8c90fdcc315bc1c84d4b0d94b59347c4900..61ca27d34a1313f7753a873f2b97cfd911668152 100644 (file)
@@ -33,6 +33,8 @@
  *             Messages for error cases (non intel & no suitable microcode).
  *     1.06    07 Dec 2000, Tigran Aivazian <tigran@veritas.com>
  *             Pentium 4 support + backported fixes from 2.4
+ *     1.07    13 Dec 2000, Tigran Aivazian <tigran@veritas.com>
+ *             More bugfixes backported from 2.4
  */
 
 #include <linux/init.h>
@@ -47,7 +49,7 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-#define MICROCODE_VERSION      "1.06"
+#define MICROCODE_VERSION      "1.07"
 
 MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
@@ -87,13 +89,10 @@ static struct miscdevice microcode_dev = {
 
 int __init microcode_init(void)
 {
-       int error = 0;
-
        if (misc_register(&microcode_dev) < 0) {
-               printk(KERN_WARNING 
-                       "microcode: can't misc_register on minor=%d\n",
+               printk(KERN_ERR "microcode: can't misc_register on minor=%d\n",
                        MICROCODE_MINOR);
-               error = 1;
+               return -EINVAL;
        }
        printk(KERN_INFO "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", 
                        MICROCODE_VERSION);
@@ -234,18 +233,21 @@ static void do_update_one(void *arg)
 
 static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
 {
-       if (*ppos >= mc_fsize)
-               return 0;
+       ssize_t err = 0;
+
        down(&microcode_sem);
+       if (*ppos >= mc_fsize)
+               goto out;
        if (*ppos + len > mc_fsize)
                len = mc_fsize - *ppos;
-       if (copy_to_user(buf, mc_applied + *ppos, len)) {
-               up(&microcode_sem);
-               return -EFAULT;
-       }
+       err = -EFAULT;
+       if (copy_to_user(buf, mc_applied + *ppos, len))
+               goto out;
        *ppos += len;
+       err = len;
+out:
        up(&microcode_sem);
-       return len;
+       return err;
 }
 
 static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
@@ -300,11 +302,12 @@ static int microcode_ioctl(struct inode *inode, struct file *file,
                case MICROCODE_IOCFREE:
                        down(&microcode_sem);
                        if (mc_applied) {
+                               int bytes = smp_num_cpus * sizeof(struct microcode);
+
                                memset(mc_applied, 0, mc_fsize);
                                kfree(mc_applied);
                                mc_applied = NULL;
-                               printk(KERN_WARNING 
-                                       "microcode: freed %d bytes\n", mc_fsize);
+                               printk(KERN_WARNING "microcode: freed %d bytes\n", bytes);
                                mc_fsize = 0;
                                up(&microcode_sem);
                                return 0;
index 3e0acbf5055e4341fac2edc576d708a6522f0931..dc8c97da690e2cc9dccd3c924c2436fd747a4621 100644 (file)
@@ -260,6 +260,7 @@ int __init msr_init(void)
 
 static void msr_exit(void)
 {
+  unregister_chrdev(MSR_MAJOR, "cpu/msr");
 }
 
 module_init(msr_init);
index 7b771822b4f539632f551dacccf4b581ddd0f5d5..bf9a830a7c62bca8b4ff3cea0ec88abf6b4e1edc 100644 (file)
@@ -104,7 +104,7 @@ struct sys_desc_table_struct {
        unsigned short length;
        unsigned char table[0];
 };
-struct e820map e820;
+struct e820map e820 __initdata = { 0, };
 
 unsigned char aux_device_present;
 
@@ -272,8 +272,9 @@ visws_get_board_type_and_rev(void)
                                        visws_board_rev);
        }
 #endif
-void __init add_memory_region(unsigned long long start,
-                                  unsigned long long size, int type)
+
+static void __init add_memory_region(unsigned long long start,
+                                    unsigned long long size, int type)
 {
        int x = e820.nr_map;
 
@@ -288,6 +289,8 @@ void __init add_memory_region(unsigned long long start,
        e820.nr_map++;
 } /* add_memory_region */
 
+unsigned long i386_endbase __initdata =  0;
+
 static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 {
        /* Only one memory region (or negative)? Ignore it */
@@ -309,10 +312,10 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
                 * Not right. Fix it up.
                 */
                if (type == E820_RAM) {
-                       if (start < 0x100000ULL && end > 0xA0000ULL) {
-                               if (start < 0xA0000ULL)
-                                       add_memory_region(start, 0xA0000ULL-start, type);
-                               if (end < 0x100000ULL)
+                       if (start < 0x100000ULL && end > i386_endbase) {
+                               if (start < i386_endbase)
+                                       add_memory_region(start, i386_endbase-start, type);
+                               if (end <= 0x100000ULL)
                                        continue;
                                start = 0x100000ULL;
                                size = end - start;
@@ -323,9 +326,33 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
        return 0;
 }
 
-#define LOWMEMSIZE() (0x9f000)
+static void __init print_memory_map(char *who)
+{
+       int i;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               printk(" %s: %08lx @ %08lx ", who,
+                      (unsigned long) e820.map[i].size,
+                      (unsigned long) e820.map[i].addr);
+               switch (e820.map[i].type) {
+               case E820_RAM:  printk("(usable)\n");
+                               break;
+               case E820_RESERVED:
+                               printk("(reserved)\n");
+                               break;
+               case E820_ACPI:
+                               printk("(ACPI data)\n");
+                               break;
+               case E820_NVS:
+                               printk("(ACPI NVS)\n");
+                               break;
+               default:        printk("type %lu\n", e820.map[i].type);
+                               break;
+               }
+       }
+}
 
-void __init setup_memory_region(void)
+static void __init setup_memory_region(void)
 {
        char *who = "BIOS-e820";
 
@@ -348,26 +375,27 @@ void __init setup_memory_region(void)
                }
 
                e820.nr_map = 0;
-               add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-               add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+               add_memory_region(0, i386_endbase, E820_RAM);
+               add_memory_region(HIGH_MEMORY, (mem_size << 10)-HIGH_MEMORY,
+                                E820_RAM);
        }
        printk("BIOS-provided physical RAM map:\n");
+       print_memory_map(who);
 } /* setup_memory_region */
 
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
-unsigned long i386_endbase __initdata =  0;
 
 __initfunc(void setup_arch(char **cmdline_p,
        unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
-       unsigned long memory_start, memory_end;
-       unsigned long max_pfn;
+       unsigned long memory_start, memory_end = 0;
        char c = ' ', *to = command_line, *from = COMMAND_LINE;
        int len = 0;
        int read_endbase_from_BIOS = 1;
        int i;
+       unsigned long user_mem = 0;
 
 #ifdef CONFIG_VISWS
        visws_get_board_type_and_rev();
@@ -402,26 +430,6 @@ __initfunc(void setup_arch(char **cmdline_p,
        memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
        saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
-       setup_memory_region();
-
-#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
-       max_pfn = 0;
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long start, end;
-               /* RAM? */
-               if (e820.map[i].type != E820_RAM)
-                       continue;
-               start = PFN_UP(e820.map[i].addr);
-               end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-               if (start >= end)
-                       continue;
-               if (end > max_pfn)
-                       max_pfn = end;
-       }
-       memory_end = (max_pfn << PAGE_SHIFT);
-
-
        for (;;) {
                /*
                 * "mem=nopentium" disables the 4MB page tables.
@@ -434,12 +442,12 @@ __initfunc(void setup_arch(char **cmdline_p,
                                from += 9+4;
                                boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
                        } else {
-                               memory_end = simple_strtoul(from+4, &from, 0);
+                               user_mem = simple_strtoul(from+4, &from, 0);
                                if ( *from == 'K' || *from == 'k' ) {
-                                       memory_end = memory_end << 10;
+                                       user_mem = user_mem << 10;
                                        from++;
                                } else if ( *from == 'M' || *from == 'm' ) {
-                                       memory_end = memory_end << 20;
+                                       user_mem = user_mem << 20;
                                        from++;
                                }
                        }
@@ -448,7 +456,6 @@ __initfunc(void setup_arch(char **cmdline_p,
                {
                        if (to != command_line) to--;
                        i386_endbase = simple_strtoul(from+8, &from, 0);
-                       i386_endbase += PAGE_OFFSET;
                        read_endbase_from_BIOS = 0;
                }
                c = *(from++);
@@ -484,7 +491,35 @@ __initfunc(void setup_arch(char **cmdline_p,
                        }
                        i386_endbase = BIOS_ENDBASE;
                }
-               i386_endbase += PAGE_OFFSET;
+       }
+
+       if (!user_mem)
+               setup_memory_region();
+       else {
+               e820.nr_map = 0;
+               add_memory_region(0, i386_endbase, E820_RAM);
+               add_memory_region(HIGH_MEMORY, user_mem-HIGH_MEMORY, E820_RAM);
+               printk("USER-provided physical RAM map:\n");
+               print_memory_map("USER");
+       }
+
+#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
+       for (i = 0; i < e820.nr_map; i++) {
+               unsigned long long start, end;
+               /* RAM? */
+               if (e820.map[i].type != E820_RAM)
+                       continue;
+               start = e820.map[i].addr;
+               if (start >= 0xffffffff)
+                       continue;
+               end = e820.map[i].addr + e820.map[i].size;
+               if (start >= end)
+                       continue;
+               if (end > 0xffffffff)
+                       end = 0xffffffff;
+               if (end > memory_end)
+                       memory_end = end;
        }
 
 #define VMALLOC_RESERVE        (64 << 20)      /* 64MB for vmalloc */
index cbcbf45c4d1dbcb5a6b8b841f96ab18253bb942b..bad8514d60cd3597eb534acbac349e160f280272 100644 (file)
@@ -680,7 +680,7 @@ extern unsigned long i386_endbase;
  */
 unsigned long __init smp_alloc_memory(unsigned long mem_base)
 {
-       if (mem_base + PAGE_SIZE > i386_endbase)
+       if (mem_base + PAGE_SIZE > i386_endbase + PAGE_OFFSET)
                panic("smp_alloc_memory: Insufficient low memory for kernel trampoline 0x%lx.", mem_base);
        trampoline_base = (void *)mem_base;
        return mem_base + PAGE_SIZE;
index c15ade35b23a23b739c714fa24c1b83aff5e7e61..5bd458b0b74c73f74c6186652286d9dd69d3e7bd 100644 (file)
@@ -106,7 +106,6 @@ asmlinkage void stack_segment(void);
 asmlinkage void general_protection(void);
 asmlinkage void page_fault(void);
 asmlinkage void coprocessor_error(void);
-asmlinkage void reserved(void);
 asmlinkage void alignment_check(void);
 asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
@@ -246,7 +245,6 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
 DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
-DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
 /* I don't have documents for this but it does seem to cover the cache
    flush from user space exception some people get. */
 DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current)
index 757e59cef8fbca925797171901fc11d111d53931..9de0d67c0dcc1aacd976f78c6511149085b77b00 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/fixmap.h>
+#include <asm/e820.h>
 
 extern void show_net_buffers(void);
 extern unsigned long init_smp_mappings(unsigned long);
@@ -384,8 +385,6 @@ __initfunc(void test_wp_bit(void))
                printk(".\n");
 }
 
-extern unsigned long i386_endbase;
-
 __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 {
        unsigned long start_low_mem = PAGE_SIZE;
@@ -417,15 +416,36 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 #endif
        start_mem = PAGE_ALIGN(start_mem);
 
-       while (start_low_mem < i386_endbase) {
-               clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
-               start_low_mem += PAGE_SIZE;
-       }
+       for (tmp = __pa(start_low_mem); tmp < __pa(end_mem);
+            tmp += PAGE_SIZE) {
+               struct page * page = mem_map + (tmp >> PAGE_SHIFT);
+               int i;
+               extern struct e820map e820;
 
-       while (start_mem < end_mem) {
-               clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-               start_mem += PAGE_SIZE;
+               /* don't include kernel memory and bootmem allocations */
+               if (tmp >= 0x100000 && tmp < __pa(start_mem))
+                       continue;
+
+               for (i = 0; i < e820.nr_map; i++) {
+                       unsigned long long start, end;
+                       /* RAM? */
+                       if (e820.map[i].type != E820_RAM)
+                               continue;
+                       start = e820.map[i].addr;
+                       if (start >= 0xffffffff)
+                               continue;
+                       end = e820.map[i].addr + e820.map[i].size;
+                       if (start >= end)
+                               continue;
+                       if (end > 0xffffffff)
+                               end = 0xffffffff;
+
+                       /* start and end are valid here */
+                       if (start <= tmp && tmp+PAGE_SIZE <= end)
+                               clear_bit(PG_reserved, &page->flags);
+               }
        }
+
        for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
                if (tmp >= MAX_DMA_ADDRESS)
                        clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
index 42d1cfee68a2593bc49f5f59560bf3652ef722fd..f85aa8d4a26d5efcc9cae3fea5ab2df743256c48 100644 (file)
@@ -658,6 +658,10 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
        ppc_md.get_rtc_time   = pmac_get_rtc_time;
        ppc_md.calibrate_decr = pmac_calibrate_decr;
 
+       ppc_md.pci_dev_root_bridge      = pmac_pci_dev_root_bridge;
+       ppc_md.pci_dev_mem_base         = pmac_pci_dev_mem_base;
+       ppc_md.pci_dev_io_base          = pmac_pci_dev_io_base;
+
 #ifdef CONFIG_VT
 #ifdef CONFIG_MAC_KEYBOARD
        ppc_md.kbd_setkeycode    = mackbd_setkeycode;
index e1d357979d3c0faf032da8b540f0db407d4ecfb7..f9155b285192dfa7e525fc8ebfb6a26788f575b2 100644 (file)
@@ -44,11 +44,14 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 endmenu
 
 source drivers/s390/Config.in
+
+mainmenu_option next_comment
 comment 'Character devices'
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
   int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
+endmenu
 
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
index 2477b5878a16fa39338263a39723ee2417b9d45b..410cd597b0943134c33b7439664776672f7a3987 100644 (file)
@@ -41,7 +41,9 @@ EXPORT_SYMBOL(s390_request_irq_special);
 EXPORT_SYMBOL(s390_device_register);
 EXPORT_SYMBOL(s390_device_unregister);
 
+#ifdef __SMP__
 EXPORT_SYMBOL(s390_bh_lock);
+#endif
 
 EXPORT_SYMBOL(ccw_alloc_request);
 EXPORT_SYMBOL(ccw_free_request);
index ec0eff9e4bfa48f17111019520daa600993872a6..9980903cc4581186a83f8abdcc657af07ea367ce 100644 (file)
@@ -36,6 +36,9 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/smp.h>
+#include "cpcmd.h"
+
+extern void reipl(int ipl_device);
 
 /*
  * Machine setup..
index b77c8e643e4192b29164eb29ce524676e269b78a..f5314b95de393c8d65344e864da9cd437c6b0bbf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.107.2.14 2000/10/10 04:50:50 davem Exp $
+/* $Id: sys_sparc32.c,v 1.107.2.16 2000/12/20 02:45:00 anton Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3462,7 +3462,7 @@ asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
        set_fs (KERNEL_DS);
        sys_get_kernel_syms(tbl);
        set_fs (old_fs);
-       for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
+       for (i = 0; i < len; i++, table++) {
                if (put_user (tbl[i].value, &table->value) ||
                    copy_to_user (table->name, tbl[i].name, 60))
                        break;
@@ -3553,6 +3553,12 @@ struct nfsctl_fhparm32 {
        s32                     gf32_version;
 };
 
+struct nfsctl_fdparm32 {
+       struct sockaddr         gd32_addr;
+       s8                      gd32_path[NFS_MAXPATHLEN+1];
+       s32                     gd32_version;
+};
+
 struct nfsctl_arg32 {
        s32                     ca32_version;   /* safeguard */
        union {
@@ -3561,6 +3567,7 @@ struct nfsctl_arg32 {
                struct nfsctl_export32  u32_export;
                struct nfsctl_uidmap32  u32_umap;
                struct nfsctl_fhparm32  u32_getfh;
+               struct nfsctl_fdparm32  u32_getfd;
                u32                     u32_debug;
        } u;
 #define ca32_svc       u.u32_svc
@@ -3569,6 +3576,7 @@ struct nfsctl_arg32 {
 #define ca32_umap      u.u32_umap
 #define ca32_getfh     u.u32_getfh
 #define ca32_authd     u.u32_authd
+#define ca32_getfd     u.u32_getfd
 #define ca32_debug     u.u32_debug
 };
 
@@ -3698,6 +3706,22 @@ static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32
        return err;
 }
 
+static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+       int err;
+       
+       err = __get_user(karg->ca_version, &arg32->ca32_version);
+       err |= copy_from_user(&karg->ca_getfd.gd_addr,
+                         &arg32->ca32_getfd.gd32_addr,
+                         (sizeof(struct sockaddr)));
+       err |= copy_from_user(&karg->ca_getfd.gd_path,
+                         &arg32->ca32_getfd.gd32_path,
+                         (NFS_MAXPATHLEN+1));
+       err |= __get_user(karg->ca_getfd.gd_version,
+                     &arg32->ca32_getfd.gd32_version);
+       return err;
+}
+
 static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
 {
        int err;
@@ -3739,6 +3763,7 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct
                err = nfs_clnt32_trans(karg, arg32);
                break;
        case NFSCTL_EXPORT:
+       case NFSCTL_UNEXPORT:
                err = nfs_exp32_trans(karg, arg32);
                break;
        /* This one is unimplemented, be we're ready for it. */
@@ -3748,6 +3773,9 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct
        case NFSCTL_GETFH:
                err = nfs_getfh32_trans(karg, arg32);
                break;
+       case NFSCTL_GETFD:
+               err = nfs_getfd32_trans(karg, arg32);
+               break;
        case NFSCTL_LOCKD:
                /* We still have to copy over the version
                 * because nfsctl still checks that.
@@ -3765,7 +3793,11 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct
        err = sys_nfsservctl(cmd, karg, kres);
        set_fs(oldfs);
 
-       if(!err && cmd == NFSCTL_GETFH)
+       if (err)
+               goto done;
+
+       if((cmd == NFSCTL_GETFH) ||
+          (cmd == NFSCTL_GETFD))
                err = nfs_getfh32_res_trans(kres, res32);
 
 done:
index 28e8de47fceacc66c48ad1e00079704283b21831..76a4ec56c0b92c97bc8e6dd6807cff5b08568b48 100644 (file)
@@ -102,6 +102,7 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
   tristate '   Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
   tristate '   Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT
   tristate '   Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
+  tristate '  Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO
   tristate '   Mixcom Watchdog' CONFIG_MIXCOMWD 
   tristate '   SBC-60XX Watchdog Timer' CONFIG_60XX_WDT
   tristate '   Software Watchdog' CONFIG_SOFT_WATCHDOG
index b20ee607885de79c837879d157e2600d2d0775d9..acc8e533e7c673a1a54ece4029fad309a598d527 100644 (file)
@@ -689,6 +689,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_I810_TCO),y)
+O_OBJS += i810-tco.o
+else
+  ifeq ($(CONFIG_I810_TCO),m)
+  M_OBJS += i810-tco.o
+  endif
+endif
+
 # remove objects from modular that are also built in
 obj-m           := $(filter-out $(obj-y), $(obj-m))
 
diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c
new file mode 100644 (file)
index 0000000..1d6c42f
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ *     i810-tco 0.02:  TCO timer driver for i810 chipsets
+ *
+ *     (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
+ *                             http://www.kernelconcepts.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 the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *     
+ *     Neither kernel concepts nor Nils Faerber admit liability nor provide 
+ *     warranty for any of this software. This material is provided 
+ *     "AS-IS" and at no charge.       
+ *
+ *     (c) Copyright 2000      kernel concepts <nils@kernelconcepts.de>
+ *                             developed for
+ *                              Jentro AG, Haar/Munich (Germany)
+ *
+ *     TCO timer driver for i810/i815 chipsets
+ *     based on softdog.c by Alan Cox <alan@redhat.com>
+ *
+ *     The TCO timer is implemented in the 82801AA (82801AB) chip,
+ *     see intel documentation from http://developer.intel.com,
+ *     order number 290655-003
+ *
+ *  20000710 Nils Faerber
+ *     Initial Version 0.01
+ *  20000728 Nils Faerber
+ *      0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include "i810-tco.h"
+
+
+/* Just in case that the PCI vendor and device IDs are not yet defined */
+#ifndef PCI_DEVICE_ID_INTEL_82801AA_0
+#define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
+#endif
+
+/* Default expire timeout */
+#define TIMER_MARGIN   50      /* steps of 0.6sec, 2<n<64. Default is 30 seconds */
+
+static unsigned int ACPIBASE;
+static spinlock_t tco_lock;    /* Guards the hardware */
+
+static int i810_margin = TIMER_MARGIN; /* steps of 0.6sec */
+
+MODULE_PARM (i810_margin, "i");
+
+/*
+ *     Timer active flag
+ */
+
+static int timer_alive;
+static int boot_status;
+
+/*
+ * Some i810 specific functions
+ */
+
+
+/*
+ * Start the timer countdown
+ */
+static int tco_timer_start (void)
+{
+       unsigned char val;
+
+       spin_lock(&tco_lock);
+       val = inb (TCO1_CNT + 1);
+       val &= 0xf7;
+       outb (val, TCO1_CNT + 1);
+       val = inb (TCO1_CNT + 1);
+       spin_unlock(&tco_lock);
+       
+       if (val & 0x08)
+               return -1;
+       return 0;
+}
+
+/*
+ * Stop the timer countdown
+ */
+static int tco_timer_stop (void)
+{
+       unsigned char val;
+
+       spin_lock(&tco_lock);
+       val = inb (TCO1_CNT + 1);
+       val |= 0x08;
+       outb (val, TCO1_CNT + 1);
+       val = inb (TCO1_CNT + 1);
+       spin_unlock(&tco_lock);
+       
+       if ((val & 0x08) == 0)
+               return -1;
+       return 0;
+}
+
+/*
+ * Set the timer reload value
+ */
+static int tco_timer_settimer (unsigned char tmrval)
+{
+       unsigned char val;
+
+       /* from the specs: */
+       /* "Values of 0h-3h are ignored and should not be attempted" */
+       if (tmrval > 0x3f || tmrval < 0x03)
+               return -1;
+       
+       spin_lock(&tco_lock);
+       val = inb (TCO1_TMR);
+       val &= 0xc0;
+       val |= tmrval;
+       outb (val, TCO1_TMR);
+       val = inb (TCO1_TMR);
+       spin_unlock(&tco_lock);
+       
+       if ((val & 0x3f) != tmrval)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * Reload (trigger) the timer. Lock is needed so we dont reload it during
+ * a reprogramming event
+ */
+static void tco_timer_reload (void)
+{
+       spin_lock(&tco_lock);
+       outb (0x01, TCO1_RLD);
+       spin_unlock(&tco_lock);
+}
+
+/*
+ * Read the current timer value
+ */
+static unsigned char tco_timer_read (void)
+{
+       return (inb (TCO1_RLD));
+}
+
+
+/*
+ *     Allow only one person to hold it open
+ */
+
+static int i810tco_open (struct inode *inode, struct file *file)
+{
+       if (timer_alive)
+               return -EBUSY;
+
+       /*
+        *      Reload and activate timer
+        */
+       tco_timer_reload ();
+       tco_timer_start ();
+       timer_alive = 1;
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+static int i810tco_release (struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        */
+       MOD_INC_USE_COUNT;
+       tco_timer_stop ();
+       timer_alive = 0;
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static ssize_t i810tco_write (struct file *file, const char *data,
+                             size_t len, loff_t * ppos)
+{
+       /*  Can't seek (pwrite) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /*
+        *      Refresh the timer.
+        */
+       if (len) {
+               tco_timer_reload ();
+               return 1;
+       }
+       return 0;
+}
+
+static int i810tco_ioctl (struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               0,
+               0,
+               "i810 TCO timer"
+       };
+       switch (cmd) {
+       default:
+               return -ENOIOCTLCMD;
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user
+                   ((struct watchdog_info *) arg, &ident, sizeof (ident)))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_GETSTATUS:
+               return put_user (tco_timer_read (),
+                                (unsigned int *) (int) arg);
+       case WDIOC_GETBOOTSTATUS:
+               return put_user (boot_status, (int *) arg);
+       case WDIOC_KEEPALIVE:
+               tco_timer_reload ();
+               return 0;
+       }
+}
+
+static struct pci_dev *i810tco_pci;
+
+static unsigned char i810tco_getdevice (void)
+{
+       u8 val1, val2;
+       u16 badr;
+       /*
+        *      Find the PCI device which has vendor id 0x8086
+        *      and device ID 0x2410
+        */
+       i810tco_pci = pci_find_device (PCI_VENDOR_ID_INTEL,
+                                      PCI_DEVICE_ID_INTEL_82801AA_0, NULL);
+       if (i810tco_pci) {
+               /*
+                *      Find the ACPI base I/O address which is the base
+                *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
+                *      ACPIBASE is bits [15:7] from 0x40-0x43
+                */
+               pci_read_config_byte (i810tco_pci, 0x40, &val1);
+               pci_read_config_byte (i810tco_pci, 0x41, &val2);
+               badr = ((val2 << 1) | (val1 >> 7)) << 7;
+               ACPIBASE = badr;
+               /* Something's wrong here, ACPIBASE has to be set */
+               if (badr == 0x0001 || badr == 0x0000) {
+                       printk (KERN_ERR "i810tco init: failed to get TCOBASE address\n");
+                       return 0;
+               }
+               /*
+                * Check chipset's NO_REBOOT bit
+                */
+               pci_read_config_byte (i810tco_pci, 0xd4, &val1);
+               if (val1 & 0x02) {
+                       val1 &= 0xfd;
+                       pci_write_config_byte (i810tco_pci, 0xd4, val1);
+                       pci_read_config_byte (i810tco_pci, 0xd4, &val1);
+                       if (val1 & 0x02) {
+                               printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag\n");
+                               return 0;       /* Cannot reset NO_REBOOT bit */
+                       }
+               }
+               /* Set the TCO_EN bit in SMI_EN register */
+               val1 = inb (SMI_EN + 1);
+               val1 &= 0xdf;
+               outb (val1, SMI_EN + 1);
+               /* Clear out the (probably old) status */
+               outb (0, TCO1_STS);
+               boot_status = (int) inb (TCO2_STS);
+               outb (3, TCO2_STS);
+               return 1;
+       }
+       return 0;
+}
+
+static struct file_operations i810tco_fops = {
+       write:          i810tco_write,
+       ioctl:          i810tco_ioctl,
+       open:           i810tco_open,
+       release:        i810tco_release,
+};
+
+static struct miscdevice i810tco_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &i810tco_fops
+};
+
+static int __init watchdog_init (void)
+{
+       spin_lock_init(&tco_lock);
+       if (!i810tco_getdevice () || i810tco_pci == NULL)
+               return -ENODEV;
+       if (!check_region (TCOBASE, 0x10)) {
+               printk (KERN_ERR
+                       "i810 TCO timer: I/O address 0x%04x already in use\n",
+                       TCOBASE);
+               return -EIO;
+       }
+       request_region (TCOBASE, 0x10, "i810 TCO");
+       if (misc_register (&i810tco_miscdev) != 0) {
+               release_region (TCOBASE, 0x10);
+               printk (KERN_ERR "i810 TCO timer: cannot register miscdev\n");
+               return -EIO;
+       }
+       tco_timer_settimer ((unsigned char) i810_margin);
+       tco_timer_reload ();
+
+       printk (KERN_INFO
+               "i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
+               (int) (i810_margin * 6 / 10), TCOBASE);
+       return 0;
+}
+
+static void watchdog_cleanup (void)
+{
+       u8 val;
+
+       /* Reset the timer before we leave */
+       tco_timer_reload ();
+       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+       pci_read_config_byte (i810tco_pci, 0xd4, &val);
+       val |= 0x02;
+       pci_write_config_byte (i810tco_pci, 0xd4, val);
+       release_region (TCOBASE, 0x10);
+       misc_deregister (&i810tco_miscdev);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
diff --git a/drivers/char/i810-tco.h b/drivers/char/i810-tco.h
new file mode 100644 (file)
index 0000000..a078ae8
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *     i810-tco 0.02:  TCO timer driver for i810 chipsets
+ *
+ *     (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
+ *                             http://www.kernelconcepts.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 the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *     
+ *     Neither kernel concepts nor Nils Faerber admit liability nor provide 
+ *     warranty for any of this software. This material is provided 
+ *     "AS-IS" and at no charge.       
+ *
+ *     (c) Copyright 2000      kernel concepts <nils@kernelconcepts.de>
+ *                             developed for
+ *                              Jentro AG, Haar/Munich (Germany)
+ *
+ *     TCO timer driver for i810 chipsets
+ *     based on softdog.c by Alan Cox <alan@redhat.com>
+ *
+ *      The TCO timer is implemented in the 82801AA (82801AB) chip,
+ *     see intel documentation from http://developer.intel.com,
+ *     order number 290655-003
+ *
+ *     For history see i810-tco.c
+ */
+
+
+/*
+ * Some address definitions for the i810 TCO
+ */
+
+#define        TCOBASE         ACPIBASE + 0x60 /* TCO base address             */
+#define TCO1_RLD       TCOBASE + 0x00  /* TCO Timer Reload and Current Value */
+#define TCO1_TMR       TCOBASE + 0x01  /* TCO Timer Initial Value      */
+#define        TCO1_DAT_IN     TCOBASE + 0x02  /* TCO Data In Register         */
+#define        TCO1_DAT_OUT    TCOBASE + 0x03  /* TCO Data Out Register        */
+#define        TCO1_STS        TCOBASE + 0x04  /* TCO1 Status Register         */
+#define        TCO2_STS        TCOBASE + 0x06  /* TCO2 Status Register         */
+#define TCO1_CNT       TCOBASE + 0x08  /* TCO1 Control Register        */
+#define TCO2_CNT       TCOBASE + 0x0a  /* TCO2 Control Register        */
+
+#define        SMI_EN          ACPIBASE + 0x30 /* SMI Control and Enable Register */
index eddb88f7f76804a436d07b83ee5e7d5861662c78..abdb4baa1576ae235f9fea63fa275f7d35aac57a 100644 (file)
@@ -9,7 +9,7 @@
  *     Al Longyear <longyear@netcom.com>, Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  *
  * Original release 01/11/99
- * ==FILEDATE 20000515==
+ * $Id: n_hdlc.c,v 2.2 2000/11/08 17:08:29 paul Exp $
  *
  * This code is released under the GNU General Public License (GPL)
  *
@@ -78,7 +78,7 @@
  */
 
 #define HDLC_MAGIC 0x239e
-#define HDLC_VERSION "1.15"
+#define HDLC_VERSION "2.2"
 
 #include <linux/version.h>
 #include <linux/config.h>
 #undef VERSION
 #define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch))
 
-#if LINUX_VERSION_CODE < VERSION(2,1,14)
-#include <linux/ioport.h>
-#endif
-
-#if LINUX_VERSION_CODE >= VERSION(2,1,23)
 #include <linux/poll.h>
-#endif
-
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/tty.h>
 #include <linux/kerneld.h>
 #endif
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,4)
+#if LINUX_VERSION_CODE < VERSION(2,2,18) 
+typedef struct wait_queue *wait_queue_head_t;
+#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL}
+#define init_waitqueue_head(head) *(head) = NULL
+#define set_current_state(a) current->state = (a)
+#endif
+
 #include <asm/segment.h>
 #define GET_USER(error,value,addr) error = get_user(value,addr)
 #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
 #define PUT_USER(error,value,addr) error = put_user(value,addr)
 #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,5)
 #include <asm/uaccess.h>
-#endif
-
-#else  /* 2.0.x and 2.1.x before 2.1.4 */
-
-#define GET_USER(error,value,addr)                                       \
-do {                                                                     \
-       error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
-       if (error == 0)                                                   \
-               value = get_user(addr);                                   \
-} while (0)
-
-#define COPY_FROM_USER(error,dest,src,size)                              \
-do {                                                                     \
-       error = verify_area (VERIFY_READ, (void *) src, size);            \
-       if (error == 0)                                                   \
-               memcpy_fromfs (dest, src, size);                          \
-} while (0)
-
-#define PUT_USER(error,value,addr)                                        \
-do {                                                                      \
-       error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
-       if (error == 0)                                                    \
-               put_user (value, addr);                                    \
-} while (0)
-
-#define COPY_TO_USER(error,dest,src,size)                                \
-do {                                                                     \
-       error = verify_area (VERIFY_WRITE, (void *) dest, size);                  \
-       if (error == 0)                                                   \
-               memcpy_tofs (dest, src, size);                            \
-} while (0)
-
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,0)
-#define __init
-typedef int spinlock_t;
-#define spin_lock_init(a)
-#define spin_lock_irqsave(a,b) {save_flags((b));cli();}
-#define spin_unlock_irqrestore(a,b) {restore_flags((b));}
-#define spin_lock(a)
-#define spin_unlock(a)
-#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,37)
-#define test_and_set_bit(nr, addr)     set_bit(nr, addr)
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,57)
-#define signal_pending(p)      ((p)->signal & ~(p)->blocked)
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,25)
-#define net_device_stats       enet_statistics
-#endif
 
-#if LINUX_VERSION_CODE < VERSION(2,1,60)
-typedef int            rw_ret_t;
-typedef unsigned int   rw_count_t;
-#else
 typedef ssize_t                rw_ret_t;
 typedef size_t         rw_count_t;
-#endif
 
 /*
  * Buffers for individual HDLC frames
@@ -254,10 +191,8 @@ N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list);
 
 static struct n_hdlc *n_hdlc_alloc (void);
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,19) 
 MODULE_PARM(debuglevel, "i");
 MODULE_PARM(maxframe, "i");
-#endif
 
 /* debug level can be set by insmod for debugging purposes */
 #define DEBUG_LEVEL_INFO       1
@@ -274,13 +209,8 @@ static rw_ret_t n_hdlc_tty_write(struct tty_struct *,
        struct file *, const __u8 *, rw_count_t);
 static int n_hdlc_tty_ioctl(struct tty_struct *,
        struct file *, unsigned int, unsigned long);
-#if LINUX_VERSION_CODE < VERSION(2,1,23)
-static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode,
-                     struct file *filp, int sel_type, select_table * wait);
-#else
 static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, struct file *filp,
                                  poll_table * wait);
-#endif
 static int n_hdlc_tty_open (struct tty_struct *);
 static void n_hdlc_tty_close (struct tty_struct *);
 static int n_hdlc_tty_room (struct tty_struct *tty);
@@ -653,10 +583,10 @@ static void n_hdlc_tty_receive(struct tty_struct *tty,
        wake_up_interruptible (&n_hdlc->read_wait);
        wake_up_interruptible (&n_hdlc->poll_wait);
        if (n_hdlc->tty->fasync != NULL)
-#if LINUX_VERSION_CODE < VERSION(2,3,0) 
-               kill_fasync (n_hdlc->tty->fasync, SIGIO);
-#else
+#if LINUX_VERSION_CODE >= VERSION(2,2,14) && defined(__rh_config_h__)
                kill_fasync (n_hdlc->tty->fasync, SIGIO, POLL_IN);
+#else
+               kill_fasync (n_hdlc->tty->fasync, SIGIO);
 #endif
 }      /* end of n_hdlc_tty_receive() */
 
@@ -886,73 +816,6 @@ static int n_hdlc_tty_ioctl (struct tty_struct *tty, struct file * file,
        
 }      /* end of n_hdlc_tty_ioctl() */
 
-#if LINUX_VERSION_CODE < VERSION(2,1,23)
-/* n_hdlc_tty_select()
- * 
- *     Device select method. Determine if operation requires
- *     blocking and if so put appropriate wait queue in select
- *     table and return 0, otherwise return 1.
- *     
- * Arguments:
- * 
- *     tty             pointer to tty device instance data
- *     inode           pointer to inode for device
- *     filp            pointer to file object
- *     sel_type        identified the select type (read/write/exception)
- *     wait            select table for adding wait queue if appropriate
- *     
- * Return Value:
- * 
- *     1 if no need to block on operation
- *     0 if must block and wait queue added to select table
- */
-static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode,
-               struct file *filp, int sel_type, select_table * wait)
-{
-       struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
-       int result = 1;
-       
-       if (debuglevel >= DEBUG_LEVEL_INFO)     
-               printk("%s(%d)n_hdlc_tty_select() called\n",__FILE__,__LINE__);
-               
-       /* Verify the status of the device */
-       if (!n_hdlc)
-               return -EBADF;
-
-       if (n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty)
-               return -EBADF;
-
-       switch (sel_type) {
-       case SEL_IN:
-               if (n_hdlc->rx_buf_list.head)
-                       break;
-
-       case SEL_EX:    /* Exceptions or read errors */
-               /* Is this a pty link and the remote disconnected? */
-               if (tty->flags & (1 << TTY_OTHER_CLOSED))
-                       break;
-
-               /* Is this a local link and the modem disconnected? */
-               if (tty_hung_up_p (filp))
-                       break;
-
-               select_wait (&n_hdlc->read_wait, wait);
-               result = 0;
-               break;
-               
-       /* Write mode. A write is allowed if there is no current transmission */
-       case SEL_OUT:
-               if (!n_hdlc->tx_free_buf_list.head) {
-                       select_wait (&n_hdlc->write_wait, wait);
-                       result = 0;
-               }
-               break;
-       }
-       return result;
-}      /* end of n_hdlc_tty_select() */
-
-#else  /* 2.1.23 or later */
-
 /* n_hdlc_tty_poll()
  * 
  *     TTY callback for poll system call. Determine which 
@@ -981,11 +844,8 @@ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty,
        if (n_hdlc && n_hdlc->magic == HDLC_MAGIC && tty == n_hdlc->tty) {
                /* queue current process into any wait queue that */
                /* may awaken in the future (read and write) */
-#if LINUX_VERSION_CODE < VERSION(2,1,89)
-               poll_wait(&n_hdlc->poll_wait, wait);
-#else
                poll_wait(filp, &n_hdlc->poll_wait, wait);
-#endif
+
                /* set bits for operations that wont block */
                if(n_hdlc->rx_buf_list.head)
                        mask |= POLLIN | POLLRDNORM;    /* readable */
@@ -999,8 +859,6 @@ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty,
        return mask;
 }      /* end of n_hdlc_tty_poll() */
 
-#endif
-
 /* n_hdlc_alloc()
  * 
  *     Allocate an n_hdlc instance data structure
@@ -1153,19 +1011,13 @@ int init_module(void)
        
        memset(&n_hdlc_ldisc, 0, sizeof (n_hdlc_ldisc));
        n_hdlc_ldisc.magic              = TTY_LDISC_MAGIC;
-#if LINUX_VERSION_CODE >= VERSION(2,1,28)
        n_hdlc_ldisc.name               = "hdlc";
-#endif
        n_hdlc_ldisc.open               = n_hdlc_tty_open;
        n_hdlc_ldisc.close              = n_hdlc_tty_close;
        n_hdlc_ldisc.read               = n_hdlc_tty_read;
        n_hdlc_ldisc.write              = n_hdlc_tty_write;
        n_hdlc_ldisc.ioctl              = n_hdlc_tty_ioctl;
-#if LINUX_VERSION_CODE < VERSION(2,1,23)
-       n_hdlc_ldisc.select             = n_hdlc_tty_select;
-#else
        n_hdlc_ldisc.poll               = n_hdlc_tty_poll;
-#endif
        n_hdlc_ldisc.receive_room       = n_hdlc_tty_room;
        n_hdlc_ldisc.receive_buf        = n_hdlc_tty_receive;
        n_hdlc_ldisc.write_wakeup       = n_hdlc_tty_wakeup;
index 0dc91c991d6862f7d9b510ce2d4e460eb253d5bb..f2c44510aadda4561fe7201340ef600d7e113d1c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * ==FILEDATE 20000821==
+ * $Id: synclink.c,v 2.4 2000/12/11 20:08:18 paul Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
-
 #include <linux/netdevice.h>
-
-#if LINUX_VERSION_CODE >= VERSION(2,1,0) 
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <asm/serial.h>
-#else
-#include <linux/bios32.h>
-#endif
-
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 
 #include <linux/termios.h>
 #include <linux/tqueue.h>
 
+#if LINUX_VERSION_CODE < VERSION(2,2,18) 
+typedef struct wait_queue *wait_queue_head_t;
+#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL}
+#define init_waitqueue_head(head) *(head) = NULL
+#define DECLARE_MUTEX(name) struct semaphore (name) = MUTEX
+#define set_current_state(a) current->state = (a)
+#endif
+
 #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
 #define CONFIG_SYNCLINK_SYNCPPP 1
 #endif
 
 #ifdef CONFIG_SYNCLINK_SYNCPPP
-#if LINUX_VERSION_CODE < VERSION(2,3,43) 
 #include "../net/syncppp.h"
 #define net_device device
 #define netif_stop_queue(a) (a)->tbusy = 1
 #define netif_start_queue(a) (a)->tbusy = 0
 #define netif_wake_queue(a) (a)->tbusy = 0; mark_bh(NET_BH)
 #define netif_queue_stopped(a) ((a)->tbusy)
-#else
-#include "../net/wan/syncppp.h"
-#endif
 #endif
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,4)
 #include <asm/segment.h>
 #define GET_USER(error,value,addr) error = get_user(value,addr)
 #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
 #define PUT_USER(error,value,addr) error = put_user(value,addr)
 #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,5)
 #include <asm/uaccess.h>
-#endif
-
-#else  /* 2.0.x and 2.1.x before 2.1.4 */
-
-#define GET_USER(error,value,addr)                                       \
-do {                                                                     \
-       error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
-       if (error == 0)                                                   \
-               value = get_user(addr);                                   \
-} while (0)
-
-#define COPY_FROM_USER(error,dest,src,size)                              \
-do {                                                                     \
-       error = verify_area (VERIFY_READ, (void *) src, size);            \
-       if (error == 0)                                                   \
-               memcpy_fromfs (dest, src, size);                          \
-} while (0)
-
-#define PUT_USER(error,value,addr)                                        \
-do {                                                                      \
-       error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
-       if (error == 0)                                                    \
-               put_user (value, addr);                                    \
-} while (0)
-
-#define COPY_TO_USER(error,dest,src,size)                                \
-do {                                                                     \
-       error = verify_area (VERIFY_WRITE, (void *) dest, size);                  \
-       if (error == 0)                                                   \
-               memcpy_tofs (dest, src, size);                            \
-} while (0)
-
-#endif
-
-#if LINUX_VERSION_CODE < VERSION(2,1,0)
-/*
- * This is used to figure out the divisor speeds and the timeouts
- */
-static int baud_table[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
-
-#define __init
-#define ioremap(a,b) vremap((a),(b))
-#define iounmap(a) vfree((a))
-#define SERIAL_TYPE_NORMAL     1
-#define SERIAL_TYPE_CALLOUT    2
-typedef int spinlock_t;
-#define spin_lock_init(a)
-#define spin_lock_irqsave(a,b) {save_flags((b));cli();}
-#define spin_unlock_irqrestore(a,b) {restore_flags((b));}
-#define spin_lock(a)
-#define spin_unlock(a)
-#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
-#define signal_pending(a) ((a)->signal & ~(a)->blocked)
-#endif
-
-
 
 #include "linux/synclink.h"
 
@@ -944,7 +881,6 @@ static int debug_level = 0;
 static int maxframe[MAX_TOTAL_DEVICES] = {0,};
 static int dosyncppp[MAX_TOTAL_DEVICES] = {0,};
        
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 MODULE_PARM(break_on_load,"i");
 MODULE_PARM(ttymajor,"i");
 MODULE_PARM(cuamajor,"i");
@@ -954,10 +890,9 @@ MODULE_PARM(dma,"1-" __MODULE_STRING(MAX_ISA_DEVICES) "i");
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
-#endif
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "1.22";
+static char *driver_version = "2.3";
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
@@ -969,9 +904,9 @@ static int serial_refcount;
 static void mgsl_change_params(struct mgsl_struct *info);
 static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
 
-static struct tty_struct **serial_table = NULL;
-static struct termios **serial_termios = NULL;
-static struct termios **serial_termios_locked = NULL;
+static struct tty_struct *serial_table[MAX_TOTAL_DEVICES];
+static struct termios *serial_termios[MAX_TOTAL_DEVICES];
+static struct termios *serial_termios_locked[MAX_TOTAL_DEVICES];
 
 #ifndef MIN
 #define MIN(a,b)       ((a) < (b) ? (a) : (b))
@@ -1372,11 +1307,6 @@ void mgsl_isr_io_pin( struct mgsl_struct *info )
 #endif
                        } else
                                info->input_signal_events.dcd_down++;
-#ifdef CONFIG_HARD_PPS
-                       if ((info->flags & ASYNC_HARDPPS_CD) &&
-                           (status & MISCSTATUS_DCD_LATCHED))
-                               hardpps();
-#endif
                }
                if (status & MISCSTATUS_CTS_LATCHED)
                {
@@ -1583,14 +1513,8 @@ void mgsl_isr_receive_data( struct mgsl_struct *info )
                        icount->parity,icount->frame,icount->overrun);
        }
                        
-       if ( tty->flip.count ) {
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
+       if ( tty->flip.count )
                tty_flip_buffer_push(tty);
-#else          
-               queue_task(&tty->flip.tqueue, &tq_timer); 
-#endif         
-       }
-       
 
 }      /* end of mgsl_isr_receive_data() */
 
@@ -1787,11 +1711,7 @@ static int startup(struct mgsl_struct * info)
                retval = mgsl_adapter_test(info);
                
        if ( retval ) {
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
                if (capable(CAP_SYS_ADMIN) && info->tty)
-#else
-               if (suser() && info->tty)
-#endif         
                        set_bit(TTY_IO_ERROR, &info->tty->flags);
                mgsl_release_resources(info);
                return retval;
@@ -1967,19 +1887,7 @@ static void mgsl_change_params(struct mgsl_struct *info)
         * current data rate.
         */
        if (info->params.data_rate <= 460800) {
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
                info->params.data_rate = tty_get_baud_rate(info->tty);
-#else
-               int i = cflag & CBAUD;
-               if (i & CBAUDEX) {
-                       i &= ~CBAUDEX;
-                       if (i < 1 || i > 4) 
-                               info->tty->termios->c_cflag &= ~CBAUDEX;
-                       else
-                               i += 15;
-               }
-               info->params.data_rate = baud_table[i];
-#endif 
        }
        
        if ( info->params.data_rate ) {
@@ -2942,7 +2850,6 @@ static int set_modem_info(struct mgsl_struct * info, unsigned int cmd,
        
 }      /* end of set_modem_info() */
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
 /* mgsl_break()                Set or clear transmit break condition
  *
  * Arguments:          tty             pointer to tty instance data
@@ -2969,7 +2876,6 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
        
 }      /* end of mgsl_break() */
-#endif
 
 /* mgsl_ioctl()        Service an IOCTL request
  *     
@@ -3092,7 +2998,6 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long
                        if (error) return error;
                        PUT_USER(error,cnow.dcd, &p_cuser->dcd);
                        if (error) return error;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
                        PUT_USER(error,cnow.rx, &p_cuser->rx);
                        if (error) return error;
                        PUT_USER(error,cnow.tx, &p_cuser->tx);
@@ -3107,7 +3012,6 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long
                        if (error) return error;
                        PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
                        if (error) return error;
-#endif                 
                        return 0;
                default:
                        return -ENOIOCTLCMD;
@@ -3346,7 +3250,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
                }
        }
       
-       set_current_state(TASK_RUNNING);
 exit:
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):mgsl_wait_until_sent(%s) exit\n",
@@ -3589,9 +3492,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
                        tmp_buf = (unsigned char *) page;
        }
        
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
        info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-#endif
 
        spin_lock_irqsave(&info->netlock, flags);
        if (info->netcount) {
@@ -3978,27 +3879,19 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
 
 }      /* end of mgsl_alloc_buffer_list_memory() */
 
-/*
- * mgsl_free_buffer_list_memory()
- * 
- *     Free the common DMA buffer allocated for use as the
- *     receive and transmit buffer lists. The associated Memory
- *     Descriptor List (MDL) is also freed.
- * 
+/* Free DMA buffers allocated for use as the
+ * receive and transmit buffer lists.
  * Warning:
  * 
  *     The data transfer buffers associated with the buffer list
  *     MUST be freed before freeing the buffer list itself because
  *     the buffer list contains the information necessary to free
  *     the individual buffers!
- * 
- * Arguments:          info    pointer to device extension
- * Return Value:       None
  */
 void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
 {
        if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI )
-               kfree_s(info->buffer_list, BUFFERLISTSIZE);
+               kfree(info->buffer_list);
                
        info->buffer_list = NULL;
        info->rx_buffer_list = NULL;
@@ -4072,7 +3965,7 @@ void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList
                for ( i = 0 ; i < Buffercount ; i++ ) {
                        if ( BufferList[i].virt_addr ) {
                                if ( info->bus_type != MGSL_BUS_TYPE_PCI )
-                                       kfree_s(BufferList[i].virt_addr, DMABUFFERSIZE);
+                                       kfree(BufferList[i].virt_addr);
                                BufferList[i].virt_addr = NULL;
                        }
                }
@@ -4131,19 +4024,12 @@ int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
 void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
 {
        if ( info->intermediate_rxbuffer )
-               kfree_s( info->intermediate_rxbuffer, info->max_frame_size);
+               kfree(info->intermediate_rxbuffer);
 
        info->intermediate_rxbuffer = NULL;
 
 }      /* end of mgsl_free_intermediate_rxbuffer_memory() */
 
-/* mgsl_claim_resources()
- * 
- *     Claim all resources used by a device
- *     
- * Arguments:          info    pointer to device instance data
- * Return Value:       0 if success, otherwise -ENODEV
- */
 int mgsl_claim_resources(struct mgsl_struct *info)
 {
        /* claim 16C32 I/O base address */
@@ -4168,7 +4054,7 @@ int mgsl_claim_resources(struct mgsl_struct *info)
        info->irq_requested = 1;
        
        if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-               /* claim shared memory range */
+
                info->memory_base = ioremap(info->phys_memory_base,0x40000);
                if (!info->memory_base) {
                        printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
@@ -4177,7 +4063,6 @@ int mgsl_claim_resources(struct mgsl_struct *info)
                        return -ENODEV;
                }
                
-               /* test the shared memory range */
                if ( !mgsl_memory_test(info) ) {
                        printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
                                __FILE__,__LINE__,info->device_name, info->phys_memory_base );
@@ -4185,7 +4070,6 @@ int mgsl_claim_resources(struct mgsl_struct *info)
                        return -ENODEV;
                }
                
-               /* claim LCR memory range */
                info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
                if (!info->lcr_base) {
                        printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
@@ -4221,13 +4105,6 @@ int mgsl_claim_resources(struct mgsl_struct *info)
                
 }      /* end of mgsl_claim_resources() */
 
-/* mgsl_release_resources()
- * 
- *     Release all resources used by a device
- *     
- * Arguments:          info    pointer to device instance data
- * Return Value:       None
- */
 void mgsl_release_resources(struct mgsl_struct *info)
 {
        if ( debug_level >= DEBUG_LEVEL_INFO )
@@ -4380,9 +4257,7 @@ int mgsl_enumerate_devices()
                        printk("ISA device specified io=%04X,irq=%d,dma=%d\n",
                                io[i], irq[i], dma[i] );
                
-               info = mgsl_allocate_device();
-               if ( !info ) {
-                       /* error allocating device instance data */
+               if (!(info = mgsl_allocate_device())) {
                        if ( debug_level >= DEBUG_LEVEL_ERROR )
                                printk( "can't allocate device instance data.\n");
                        continue;
@@ -4391,12 +4266,7 @@ int mgsl_enumerate_devices()
                /* Copy user configuration info to device instance data */
                info->io_base = (unsigned int)io[i];
                info->irq_level = (unsigned int)irq[i];
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
                info->irq_level = irq_cannonicalize(info->irq_level);
-#else          
-               if (info->irq_level == 2)
-                       info->irq_level = 9;
-#endif                 
                info->dma_level = (unsigned int)dma[i];
                info->bus_type = MGSL_BUS_TYPE_ISA;
                info->io_addr_size = 16;
@@ -4412,73 +4282,29 @@ int mgsl_enumerate_devices()
        if ( pcibios_present() ) {
                unsigned char bus;
                unsigned char func;
-               unsigned int  shared_mem_base;
-               unsigned int  lcr_mem_base;
-               unsigned int  io_base;
-               unsigned char irq_line;
                
                for(i=0;;i++){
                        if ( PCIBIOS_SUCCESSFUL == pcibios_find_device(
                                MICROGATE_VENDOR_ID, SYNCLINK_DEVICE_ID, i, &bus, &func) ) {
                                
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
                                struct pci_dev *pdev = pci_find_slot(bus,func);
-                               irq_line = pdev->irq;                           
-#else                                                                                          
-                               if (pcibios_read_config_byte(bus,func,
-                                       PCI_INTERRUPT_LINE,&irq_line) ) {
-                                       printk( "%s(%d):USC I/O addr not set.\n",
-                                               __FILE__,__LINE__);
-                                       continue;
-                               }
-#endif
-
-                               if (pcibios_read_config_dword(bus,func,
-                                       PCI_BASE_ADDRESS_3,&shared_mem_base) ) {
-                                       printk( "%s(%d):Shared mem addr not set.\n",
-                                               __FILE__,__LINE__);
-                                       continue;
-                               }
-                                                       
-                               if (pcibios_read_config_dword(bus,func,
-                                       PCI_BASE_ADDRESS_0,&lcr_mem_base) ) {
-                                       printk( "%s(%d):LCR mem addr not set.\n",
-                                               __FILE__,__LINE__);
-                                       continue;
-                               }
                                
-                               if (pcibios_read_config_dword(bus,func,
-                                       PCI_BASE_ADDRESS_2,&io_base) ) {
-                                       printk( "%s(%d):USC I/O addr not set.\n",
-                                               __FILE__,__LINE__);
-                                       continue;
-                               }
-                               
-                               info = mgsl_allocate_device();
-                               if ( !info ) {
-                                       /* error allocating device instance data */
+                               if (!(info = mgsl_allocate_device())) {
                                        if ( debug_level >= DEBUG_LEVEL_ERROR )
                                                printk( "can't allocate device instance data.\n");
                                        continue;
                                }
                
                                /* Copy user configuration info to device instance data */
+                               info->irq_level = pdev->irq;                            
+                               info->phys_lcr_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+                               info->io_base = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
+                               info->phys_memory_base = pdev->base_address[3] & PCI_BASE_ADDRESS_MEM_MASK;
                
-                               info->io_base = io_base & PCI_BASE_ADDRESS_IO_MASK;
-                               info->irq_level = (unsigned int)irq_line;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
-                               info->irq_level = irq_cannonicalize(info->irq_level);
-#else          
-                               if (info->irq_level == 2)
-                                       info->irq_level = 9;
-#endif                 
-                               info->phys_memory_base = shared_mem_base & PCI_BASE_ADDRESS_MEM_MASK;
-                               
                                /* Because veremap only works on page boundaries we must map
                                 * a larger area than is actually implemented for the LCR
                                 * memory range. We map a full page starting at the page boundary.
                                 */
-                               info->phys_lcr_base = lcr_mem_base & PCI_BASE_ADDRESS_MEM_MASK;
                                info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
                                info->phys_lcr_base &= ~(PAGE_SIZE-1);
                                
@@ -4508,30 +4334,9 @@ int mgsl_enumerate_devices()
        }
 #endif
 
-       /*
-        * Allocate memory to hold the following tty/termios arrays
-        * with an element for each enumerated device.
-        */     
-       
-       serial_table = (struct tty_struct**)kmalloc(sizeof(struct tty_struct*)*mgsl_device_count, GFP_KERNEL);
-       serial_termios = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL);
-       serial_termios_locked = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL);
-       
-       if (!serial_table || !serial_termios || !serial_termios_locked){
-               printk("%s(%d):Can't allocate tty/termios arrays.\n",
-                       __FILE__,__LINE__);
-               if (serial_table)
-                       kfree(serial_table);
-               if (serial_termios)
-                       kfree(serial_termios);
-               if (serial_termios_locked)
-                       kfree(serial_termios_locked);
-               return -ENOMEM;
-       }
-       
-       memset(serial_table,0,sizeof(struct tty_struct*)*mgsl_device_count);
-       memset(serial_termios,0,sizeof(struct termios*)*mgsl_device_count);
-       memset(serial_termios_locked,0,sizeof(struct termios*)*mgsl_device_count);
+       memset(serial_table,0,sizeof(struct tty_struct*)*MAX_TOTAL_DEVICES);
+       memset(serial_termios,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES);
+       memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES);
 
        return 0;
        
@@ -4548,11 +4353,7 @@ int __init mgsl_init(void)
 {
        struct mgsl_struct *info;
 
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
        EXPORT_NO_SYMBOLS;
-#else
-       register_symtab(NULL);
-#endif         
        
        printk("%s version %s\n", driver_name, driver_version);
        
@@ -4567,9 +4368,7 @@ int __init mgsl_init(void)
        
        memset(&serial_driver, 0, sizeof(struct tty_driver));
        serial_driver.magic = TTY_DRIVER_MAGIC;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
        serial_driver.driver_name = "synclink";
-#endif 
        serial_driver.name = "ttySL";
        serial_driver.major = ttymajor;
        serial_driver.minor_start = 64;
@@ -4596,12 +4395,10 @@ int __init mgsl_init(void)
        serial_driver.ioctl = mgsl_ioctl;
        serial_driver.throttle = mgsl_throttle;
        serial_driver.unthrottle = mgsl_unthrottle;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
        serial_driver.send_xchar = mgsl_send_xchar;
        serial_driver.break_ctl = mgsl_break;
        serial_driver.wait_until_sent = mgsl_wait_until_sent;
        serial_driver.read_proc = mgsl_read_proc;
-#endif 
        serial_driver.set_termios = mgsl_set_termios;
        serial_driver.stop = mgsl_stop;
        serial_driver.start = mgsl_start;
@@ -4615,10 +4412,8 @@ int __init mgsl_init(void)
        callout_driver.name = "cuaSL";
        callout_driver.major = cuamajor;
        callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-#if LINUX_VERSION_CODE >= VERSION(2,1,0)
        callout_driver.read_proc = 0;
        callout_driver.proc_entry = 0;
-#endif 
 
        if (tty_register_driver(&serial_driver) < 0)
                printk("%s(%d):Couldn't register serial driver\n",
@@ -4645,8 +4440,7 @@ int __init mgsl_init(void)
        
 }      /* end of mgsl_init() */
 
-#ifdef MODULE
-int init_module(void)
+int __init init_module(void)
 {
 /* Uncomment this to kernel debug module.
  * mgsl_get_text_ptr() leaves the .text address in eax
@@ -4692,20 +4486,8 @@ void cleanup_module(void)
                tmp_buf = NULL;
        }
        
-       if (serial_table)
-               kfree_s(serial_table,sizeof(struct tty_struct*)*mgsl_device_count);
-               
-       if (serial_termios)
-               kfree_s(serial_termios,sizeof(struct termios*)*mgsl_device_count);
-               
-       if (serial_termios_locked)
-               kfree_s(serial_termios_locked,sizeof(struct termios*)*mgsl_device_count);
-       
 }      /* end of cleanup_module() */
 
-#endif /* MODULE */
-
-
 /*
  * usc_RTCmd()
  *
@@ -6952,7 +6734,6 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
        while( EndTime-- && !info->irq_occurred ) {
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(jiffies_from_ms(10));
-               set_current_state(TASK_RUNNING);
        }
        
        spin_lock_irqsave(&info->irq_spinlock,flags);
@@ -7575,7 +7356,7 @@ void mgsl_sppp_init(struct mgsl_struct *info)
        sppp_attach(&info->pppdev);
 
        d = info->netdev;
-       strcpy(d->name, info->netname);
+       d->name = info->netname;
        d->base_addr = info->io_base;
        d->irq = info->irq_level;
        d->dma = info->dma_level;
@@ -7586,10 +7367,6 @@ void mgsl_sppp_init(struct mgsl_struct *info)
        d->hard_start_xmit = mgsl_sppp_tx;
        d->do_ioctl = mgsl_sppp_ioctl;
        d->get_stats = mgsl_net_stats;
-#if LINUX_VERSION_CODE >= VERSION(2,3,43) 
-       d->tx_timeout = mgsl_sppp_tx_timeout;
-       d->watchdog_timeo = 10*HZ;
-#endif
        dev_init_buffers(d);
 
        if (register_netdev(d) == -1) {
@@ -7679,7 +7456,6 @@ int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev)
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("mgsl_sppp_tx(%s)\n",info->netname);     
 
-#if LINUX_VERSION_CODE < VERSION(2,3,43) 
        if (dev->tbusy) { 
                if (time_before(jiffies, dev->trans_start+10*HZ))
                        return -EBUSY;  /* 10 seconds timeout */
@@ -7687,9 +7463,6 @@ int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev)
        }
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
                return -EBUSY;
-#else
-       netif_stop_queue(dev);
-#endif
 
        info->xmit_cnt = skb->len;
        mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
index d9b2e80e04cc23d24ad7d08c0eb29fe661762224..a9c7b9ecd899ece1a9b79ea25c8db38c652698fa 100644 (file)
@@ -463,5 +463,6 @@ setup_sct_quadro(struct IsdnCard *card))
        return (1);
 #else
        printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n");
+       return (0);
 #endif /* CONFIG_PCI */
 }
index ce58ec1d08d83344b86eb11049c097e9c74a2ed1..4c562e37bbdfbd22755fc4931e8d9b1d9d8653c6 100644 (file)
@@ -148,10 +148,10 @@ setup_netjet_s(struct IsdnCard *card))
                return(0);
        test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
+#if CONFIG_PCI
        for ( ;; )
        {
 
-#if CONFIG_PCI
 
                if (!pci_present()) {
                        printk(KERN_ERR "Netjet: no PCI bus present\n");
index cb7ce68f991ce7831606ebe07deb9e766bda7e3f..8e5bc14c0645d431ea729c639be484bbb692eb12 100644 (file)
@@ -150,10 +150,10 @@ setup_netjet_u(struct IsdnCard *card))
                return(0);
        test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
+#if CONFIG_PCI
        for ( ;; )
        {
 
-#if CONFIG_PCI
 
                if (!pci_present()) {
                        printk(KERN_ERR "NETspider-U: no PCI bus present\n");
index 75e7b08328bafd5b55e48b90a3b300b6cdb921af..528c1900938e077e8965ca6be58ecbf415683a26 100644 (file)
@@ -183,7 +183,7 @@ comment 'Ethernet (1000 Mbit)'
       tristate 'Packet Engines GNIC-II (Hamachi) support' CONFIG_HAMACHI
       tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN
     fi
-    tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN
+    dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI
 endmenu
 
 bool 'FDDI driver support' CONFIG_FDDI
index 7157f5d5209dbb4d75626ba32f6bdb4435d925b4..9238b0e72e3afc6ab47a5c04ab46fa5c3ad05546 100644 (file)
@@ -27,6 +27,8 @@
                     : is running from all accounts.
                     
   Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
+
+  Arnaldo Melo     : release resources on failure in cs89x0_probe1
 */
 
 static char *version =
@@ -249,13 +251,17 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr))
        struct net_local *lp;
        static unsigned version_printed = 0;
        int i;
+       char priv_alloced_here = 0;
        unsigned rev_type = 0;
        int eeprom_buff[CHKSUM_LEN];
 
        /* Initialize the device structure. */
        if (dev->priv == NULL) {
                dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+               if (!dev->priv)
+                       return -ENOMEM;
                 memset(dev->priv, 0, sizeof(struct net_local));
+               priv_alloced_here = 1;
         }
        lp = (struct net_local *)dev->priv;
 
@@ -265,12 +271,12 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr))
        if (ioaddr & 1) {
                ioaddr &= ~1;
                if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
-                       return ENODEV;
+                       goto err;
                outw(PP_ChipID, ioaddr + ADD_PORT);
        }
 
        if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
-               return ENODEV;
+               goto err;
 
        /* Fill in the 'dev' fields. */
        dev->base_addr = ioaddr;
@@ -388,6 +394,11 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr))
 
        printk("\n");
        return 0;
+err:   if (priv_alloced_here) {
+               kfree(dev->priv);
+               dev->priv = NULL;
+       }
+       return -ENODEV;
 }
 
 
index bd0c3fd90b649cf788a14c7ca97c3c9a31e0ab78..19af8b2da7de34d6758f5df0cce1e9156f137d41 100644 (file)
@@ -58,6 +58,7 @@
  *            First release to the public
  *  03/03/00 - Merged to kernel, indented -kr -i8 -bri0, fixed some missing
  *             malloc free checks, reviewed code. <alan@redhat.com>
+ *  12/18/00 - Made it SMP safe   - George Staikos <staikos@0wned.org>
  *  
  *  To Do:
  *
 #include <net/checksum.h>
 
 #include <asm/io.h>
+#include <asm/spinlock.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 
@@ -285,6 +287,8 @@ static int __init streamer_init(struct device *dev)
        streamer_priv = (struct streamer_private *) dev->priv;
        streamer_mmio = streamer_priv->streamer_mmio;
 
+        streamer_priv->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+
        printk("%s \n", version);
        printk(KERN_INFO "%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, using irq %d\n",
                        dev->name, (unsigned int) dev->base_addr,
@@ -823,6 +827,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        __u16 misr;
        __u16 sisrmask;
 
+        spin_lock(&(streamer_priv->lock));
        sisrmask = SISR_MI;
        writew(~sisrmask, streamer_mmio + SISR_MASK_RUM);
        sisr = readw(streamer_mmio + SISR);
@@ -831,6 +836,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        writew(~misr, streamer_mmio + MISR_RUM);
 
        if (!sisr) {            /* Interrupt isn't for us */
+                spin_unlock(&(streamer_priv->lock));
                return;
        }
 
@@ -919,6 +925,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        dev->interrupt = 0;
        writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
+        spin_unlock(&(streamer_priv->lock));
 }
 
 
@@ -927,11 +934,14 @@ static int streamer_xmit(struct sk_buff *skb, struct device *dev)
        struct streamer_private *streamer_priv =
            (struct streamer_private *) dev->priv;
        __u8 *streamer_mmio = streamer_priv->streamer_mmio;
+        int flags;
 
        if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
                return 1;
        }
 
+        spin_lock_irqsave(&(streamer_priv->lock), flags);
+
        if (streamer_priv->free_tx_ring_entries) {
                streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].status = 0;
                streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].bufcnt_framelen = 0x00010000 | skb->len;
@@ -956,8 +966,10 @@ static int streamer_xmit(struct sk_buff *skb, struct device *dev)
 
                streamer_priv->tx_ring_free = (streamer_priv->tx_ring_free + 1) & (STREAMER_TX_RING_SIZE - 1);
                dev->tbusy = 0;
+                spin_unlock_irqrestore(&(streamer_priv->lock), flags);
                return 0;
        } else {
+                spin_unlock_irqrestore(&(streamer_priv->lock), flags);
                return 1;
        }
 }
index f8803334889efa477f0071e85e2542b08080fb54..085006cf99617f4046001f2b8d188d104ba6f4e1 100644 (file)
@@ -283,6 +283,7 @@ struct streamer_private {
        __u16 streamer_addr_table_addr, streamer_parms_addr;
        __u16 mac_rx_buffer;
        __u8 streamer_laa[6];
+        spinlock_t lock;
 };
 
 struct streamer_adapter_addr_table {
index 1bfe98d89b8b012efdd5b55fb6b11cadfc7dcc85..4ef5a218a54914a88b49465f51077776ab411e55 100644 (file)
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
 
-       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
+       Drivers based on or derived from this code fall under the GPL and must
+       retain the authorship, copyright and license notice.  This file is not
+       a complete program and may only be used when the entire operating
+       system is licensed under the GPL.
 
-       People are making PCI ne2000 clones! Oh the horror, the horror...
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
 
        Issues remaining:
-       No full-duplex support.
+       People are making PCI ne2000 clones! Oh the horror, the horror...
+       Limited full-duplex support.
+
+       ChangeLog:
+
+       12/15/2000 Merged Scyld v1.02 into 2.2.18
+                                                                       J.A. Magallon <jamagallon@able.es>
 */
 
-/* Our copyright info must remain in the binary. */
-static const char *version =
-"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
+/* These identify the driver base version and may not be removed. */
+static const char version1[] =
+"ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker\n";
+static const char version2[] =
+"  http://www.scyld.com/network/ne2k-pci.html\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -49,7 +61,18 @@ static const char *version =
 #endif
 
 /* Set statically or when loading the driver module. */
-static int debug = 1;
+static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
+/* More are supported, limit only on options */
+#define MAX_UNITS 6
+/* Used to pass the full-duplex flag, etc. */
+static int full_duplex[MAX_UNITS] = {0, };
+static int options[MAX_UNITS] = {0, };
+
+MODULE_AUTHOR("Donald Becker / Paul Gortmaker");
+MODULE_DESCRIPTION("PCI NE2000 clone driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
 /* Some defines that people can play with if so inclined. */
 
@@ -62,12 +85,13 @@ static int debug = 1;
 /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
 /* #define PACKETBUF_MEMSIZE   0x40 */
 
-#define ne2k_flags reg0                        /* Rename an existing field to store flags! */
-
-/* Only the low 8 bits are usable for non-init-time flags! */
+/* Flags.  We rename an existing ei_status field to store flags! */
+/* Thus only the low 8 bits are usable for non-init-time flags. */
+#define ne2k_flags reg0
 enum {
-       HOLTEK_FDX=1,           /* Full duplex -> set 0x80 at offset 0x20. */
-       ONLY_16BIT_IO=2, ONLY_32BIT_IO=4,       /* Chip can do only 16/32-bit xfers. */
+       ONLY_16BIT_IO=8, ONLY_32BIT_IO=4,   /* Chip can do only 16/32-bit xfers. */
+       FORCE_FDX=0x20,                     /* User override. */
+       REALTEK_FDX=0x40, HOLTEK_FDX=0x80,
        STOP_PG_0x60=0x100,
 };
 
@@ -79,18 +103,17 @@ static struct {
        int flags;
 }
 pci_clone_list[] __initdata = {
-       {0x10ec, 0x8029, "RealTek RTL-8029", 0},
-       {0x1050, 0x0940, "Winbond 89C940", 0},
-       {0x11f6, 0x1401, "Compex RL2000", 0},
-       {0x8e2e, 0x3000, "KTI ET32P2", 0},
-       {0x4a14, 0x5000, "NetVin NV5000SC", 0},
-       {0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
-       {0x10bd, 0x0e34, "SureCom NE34", 0},
-       {0x1050, 0x5a5a, "Winbond", 0},
-       {0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
-       {0x12c3, 0x5598, "Holtek HT80229",
-        ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
-       {0,}
+{0x10ec, 0x8029, "RealTek RTL-8029", REALTEK_FDX},
+{0x1050, 0x0940, "Winbond 89C940", 0},
+{0x1050, 0x5a5a, "Winbond w89c940", 0},
+{0x8e2e, 0x3000, "KTI ET32P2", 0},
+{0x4a14, 0x5000, "NetVin NV5000SC", 0},
+{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
+{0x10bd, 0x0e34, "SureCom NE34", 0},
+{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO|HOLTEK_FDX},
+{0x12c3, 0x5598, "Holtek HT80229", ONLY_32BIT_IO|HOLTEK_FDX|STOP_PG_0x60 },
+{0x11f6, 0x1401, "Compex RL2000", 0},
+{0,}
 };
 
 /* ---- No user-serviceable parts below ---- */
@@ -119,7 +142,7 @@ static void ne2k_pci_block_input(struct device *dev, int count,
 static void ne2k_pci_block_output(struct device *dev, const int count,
                const unsigned char *buf, const int start_page);
 
-\f
+
 
 /* No room in the standard 8390 structure for extra info we need. */
 struct ne2k_pci_card {
@@ -137,7 +160,7 @@ init_module(void)
 {
        /* We must emit version information. */
        if (debug)
-               printk(KERN_INFO "%s", version);
+               printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 
        if (ne2k_pci_probe(0)) {
                printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n");
@@ -263,8 +286,8 @@ __initfunc (int ne2k_pci_probe(struct device *dev))
        return cards_found ? 0 : -ENODEV;
 }
 
-__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioaddr, int irq,
-                                                                         int chip_idx))
+__initfunc (static struct device *ne2k_pci_probe1(struct device *dev,
+                       long ioaddr, int irq, int chip_idx))
 {
        int i;
        unsigned char SA_prom[32];
@@ -291,6 +314,8 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioadd
 
        dev = init_etherdev(dev, 0);
 
+       if (!dev) return 0;
+
        /* Reset card. Who knows what dain-bramaged state it was left in. */
        {
                unsigned long reset_start_time = jiffies;
@@ -342,7 +367,7 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioadd
        /* Note: all PCI cards have at least 16 bit access, so we don't have
           to check for 8 bit cards.  Most cards permit 32 bit access. */
        if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) {
-               for (i = 0; i < 4 ; i++)
+               for (i = 0; i < 8 ; i++)
                        ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
        } else
                for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
@@ -379,6 +404,10 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioadd
        ei_status.stop_page = stop_page;
        ei_status.word16 = 1;
        ei_status.ne2k_flags = pci_clone_list[chip_idx].flags;
+       if (chip_idx < MAX_UNITS) {
+               if (full_duplex[chip_idx]  ||  (options[chip_idx] & FORCE_FDX))
+                       ei_status.ne2k_flags |= FORCE_FDX;
+       }
 
        ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
@@ -401,8 +430,17 @@ ne2k_pci_open(struct device *dev)
 {
        if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev))
                return -EAGAIN;
-       ei_open(dev);
        MOD_INC_USE_COUNT;
+       /* Set full duplex for the chips that we know about. */
+       if (ei_status.ne2k_flags & FORCE_FDX) {
+               long ioaddr = dev->base_addr;
+               if (ei_status.ne2k_flags & REALTEK_FDX) {
+                       outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */
+                       outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
+               } else if (ei_status.ne2k_flags & HOLTEK_FDX)
+                       outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
+       }
+       ei_open(dev);
        return 0;
 }
 
index e2e67668878de5bb04d1cf511b982c1a40ab1161..79baa359b4ea0556c5fc23b74951ea7aed9ff715 100644 (file)
 
        Support and updates available at
        http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
-       
+
        This driver also contains updates by Wolfgang Walter and others.
        For this specific driver variant please use linux-kernel for 
        bug reports.
+
+       Updated 12/17/2000 by Jim McQuillan <jam@McQuil.com> to
+       include support for the Linksys LNE100TX card based on the
+       Admtek 985 Centaur-P chipset.
 */
 
 #define SMP_CHECK
@@ -398,6 +402,8 @@ static struct tulip_chip_table {
        HAS_MII | HAS_NWAY143 | HAS_8023X, t21142_timer },
   { "ADMtek Comet", 256, 0x0001abef,
        MC_HASH_ONLY, comet_timer },
+  { "ADMtek Centaur-P", 256, 0x0001abef,
+       MC_HASH_ONLY, comet_timer },
   { "Compex 9881 PMAC", 128, 0x0001ebef,
        HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
   { "Intel DS21145 Tulip", 128, 0x0801fbff,
@@ -411,8 +417,8 @@ static struct tulip_chip_table {
 /* This matches the table above.  Note 21142 == 21143. */
 enum chips {
        DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
-       LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881,
-       I21145,
+       LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMET5,
+        COMPEX9881, I21145, XIRCOM,
 };
 
 /* A full-duplex map for media types. */
@@ -423,7 +429,7 @@ static const char media_cap[] =
 {0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
 static u8 t21040_csr13[] = {2,0x0C,8,4,  4,0,0,0, 0,0,0,0, 4,0,0,0};
 /* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
-static u16 t21041_csr13[] = { 0xEF05, 0xEF0D, 0xEF0D, 0xEF05, 0xEF05, };
+static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
 static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
 static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
 
@@ -584,7 +590,7 @@ int __init tulip_probe(struct device *dev)
                return -ENODEV;
 
        for (;pci_index < 0xff; pci_index++) {
-               u16 vendor, device, pci_command, new_command, subvendor;
+               u16 vendor, device, pci_command, new_command;
                int chip_idx;
                int irq;
                long ioaddr;
@@ -602,13 +608,6 @@ int __init tulip_probe(struct device *dev)
                                                                 PCI_VENDOR_ID, &vendor);
                pcibios_read_config_word(pci_bus, pci_device_fn,
                                                                 PCI_DEVICE_ID, &device);
-               pcibios_read_config_word(pci_bus, pci_device_fn,
-                                                                PCI_SUBSYSTEM_VENDOR_ID, &subvendor);
-               
-               if( subvendor == 0x1376 ){
-                       printk("tulip: skipping LMC card.\n");
-                       continue;
-               }       
 
                for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
                        if (vendor == pci_tbl[chip_idx].vendor_id
@@ -750,7 +749,13 @@ static struct device *tulip_probe1(int pci_bus, int pci_devfn,
                        put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i);
                        sum += value & 0xffff;
                }
-       } else if (chip_idx == COMET) {
+       } else if (chip_idx == COMET){
+               /* No need to read the EEPROM. */
+               put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
+               put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
+               for (i = 0; i < 6; i ++)
+                       sum += dev->dev_addr[i];
+       } else if (chip_idx == COMET5){
                /* No need to read the EEPROM. */
                put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
                put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
@@ -995,6 +1000,9 @@ static struct device *tulip_probe1(int pci_bus, int pci_devfn,
        case COMET:
                /* No initialization necessary. */
                break;
+       case COMET5:
+               /* No initialization necessary. */
+               break;
        }
 
        if (tulip_tbl[chip_idx].flags & HAS_PWRDWN)
@@ -1321,6 +1329,17 @@ static int mdio_read(struct device *dev, int phy_id, int location)
                }
                return 0xffff;
        }
+       if (tp->chip_id == COMET5) {
+               if (phy_id == 1) {
+                       if (location < 7)
+                               return inl(ioaddr + 0xB4 + (location<<2));
+                       else if (location == 17)
+                               return inl(ioaddr + 0xD0);
+                       else if (location >= 29 && location <= 31)
+                               return inl(ioaddr + 0xD4 + ((location-29)<<2));
+               }
+               return 0xffff;
+       }
 
        /* Establish sync by sending at least 32 logic ones. */
        for (i = 32; i >= 0; i--) {
@@ -1379,6 +1398,18 @@ static void mdio_write(struct device *dev, int phy_id, int location, int value)
                return;
        }
 
+       if (tp->chip_id == COMET5) {
+               if (phy_id != 1)
+                       return;
+               if (location < 7)
+                       outl(value, ioaddr + 0xB4 + (location<<2));
+               else if (location == 17)
+                       outl(value, ioaddr + 0xD0);
+               else if (location >= 29 && location <= 31)
+                       outl(value, ioaddr + 0xD4 + ((location-29)<<2));
+               return;
+       }
+
        /* Establish sync by sending 32 logic ones. */
        for (i = 32; i >= 0; i--) {
                outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -1462,6 +1493,11 @@ tulip_open(struct device *dev)
                        outl(addr_high, ioaddr + 0xA8);
                        outl(0, ioaddr + 0xAC);
                        outl(0, ioaddr + 0xB0);
+               } else if (tp->chip_id == COMET5) {
+                       outl(addr_low,  ioaddr + 0xA4);
+                       outl(addr_high, ioaddr + 0xA8);
+                       outl(0, ioaddr + 0xAC);
+                       outl(0, ioaddr + 0xB0);
                }
        } else {
                /* This is set_rx_mode(), but without starting the transmitter. */
@@ -1575,6 +1611,9 @@ media_picked:
        } else if (tp->chip_id == COMET) {
                dev->if_port = 0;
                tp->csr6 = 0x00040000;
+       } else if (tp->chip_id == COMET5) {
+               dev->if_port = 0;
+               tp->csr6 = 0x00040000;
        } else if (tp->chip_id == AX88140) {
                tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
        } else
@@ -3014,6 +3053,8 @@ static int private_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                        data[0] = 32;
                else if (tp->chip_id == COMET)
                        data[0] = 1;
+               else if (tp->chip_id == COMET5)
+                       data[0] = 1;
                else
                        return -ENODEV;
        case SIOCDEVPRIVATE+1:          /* Read the specified MII register. */
@@ -3142,6 +3183,9 @@ static void set_rx_mode(struct device *dev)
                        } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */
                                outl(mc_filter[0], ioaddr + 0xAC);
                                outl(mc_filter[1], ioaddr + 0xB0);
+                       } else if (tp->chip_id == COMET5) { /* Has a simple hash filter. */
+                               outl(mc_filter[0], ioaddr + 0xAC);
+                               outl(mc_filter[1], ioaddr + 0xB0);
                        }
                }
        } else {
index 6ed796962939e695b1aa20bcecb5a1684ed0603c..7ad2863faddf834ade86c1e25060a5b4a533bb43 100644 (file)
@@ -1,35 +1,44 @@
 /* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */
 /*
-       Written 1998-1999 by Donald Becker.
+       Written 1998-2000 by Donald Becker.
 
-       This software may be used and distributed according to the terms
-       of the GNU Public License (GPL), incorporated herein by reference.
-       Drivers derived from this code also fall under the GPL and must retain
-       this authorship and copyright notice.
+       This software may be used and distributed according to the terms of
+       the GNU General Public License (GPL), incorporated herein by reference.
+       Drivers based on or derived from this code fall under the GPL and must
+       retain the authorship, copyright and license notice.  This file is not
+       a complete program and may only be used when the entire operating
+       system is licensed under the GPL.
 
        This driver is designed for the VIA VT86c100A Rhine-II PCI Fast Ethernet
        controller.  It also works with the older 3043 Rhine-I chip.
 
-       The author may be reached as becker@cesdis.edu, or
-       Donald Becker
-       312 Severn Ave. #W302
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
        Annapolis MD 21403
 
        Support and updates available at
-       http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html
+       http://www.scyld.com/network/via-rhine.html
+
+
+       Linux kernel version history:
+
+       LK1.0.0:
+       - Urban Widmark: merges from Beckers 1.08b version and 2.4.0 (VT6102)
 */
 
-static const char *versionA =
-"via-rhine.c:v1.01 2/27/99  Written by Donald Becker\n";
-static const char *versionB =
-"  http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n";
+/* These identify the driver base version and may not be removed. */
+static const char version1[] =
+"via-rhine.c:v1.08b-LK1.0.0 12/14/2000  Written by Donald Becker\n";
+static const char version2[] =
+"  http://www.scyld.com/network/via-rhine.html\n";
 
-/* A few user-configurable values.   These may be modified when a driver
-   module is loaded.*/
+/* The user-configurable values.
+   These may be modified when a driver module is loaded.*/
 
 static int debug = 1;                  /* 1 normal messages, 0 quiet .. 7 verbose. */
 static int max_interrupt_work = 20;
-static int min_pci_latency = 64;
+static int min_pci_latency = 32;
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
@@ -55,7 +64,8 @@ static const int multicast_filter_limit = 32;
    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   8
+#define TX_RING_SIZE   16
+#define TX_QUEUE_LEN   10              /* Limit ring entries actually used.  */
 #define RX_RING_SIZE   16
 
 /* Operational parameters that usually are not changed. */
@@ -64,9 +74,15 @@ static const int multicast_filter_limit = 32;
 
 #define PKT_BUF_SZ             1536                    /* Size of each temporary Rx buffer.*/
 
+
+#if !defined(__OPTIMIZE__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error  You must compile this driver with "-O".
+#endif
+
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
@@ -82,15 +98,17 @@ static const int multicast_filter_limit = 32;
 #include <asm/bitops.h>
 #include <asm/io.h>
 
-/* This driver was written to use PCI memory space, however some x86
-   motherboards only configure I/O space accesses correctly. */
-#if defined(__i386__)  &&  !defined(VIA_USE_MEMORY)
-#define VIA_USE_IO
-#endif
-#if defined(__alpha__)
-#define VIA_USE_IO
-#endif
-#ifdef VIA_USE_IO
+/* Condensed bus+endian portability operations. */
+#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+/* This driver was written to use PCI memory space, however most versions
+   of the Rhine only work correctly with I/O space accesses. */
+#if defined(VIA_USE_MEMORY)
+#warning Many adapters using the VIA Rhine chip are not configured to work
+#warning with PCI memory space accesses.
+#else
+#define USE_IO_OPS
 #undef readb
 #undef readw
 #undef readl
@@ -105,21 +123,7 @@ static const int multicast_filter_limit = 32;
 #define writel outl
 #endif
 
-/* Kernel compatibility defines, some common to David Hind's PCMCIA package.
-   This is only in the support-all-kernels source code. */
-
-#define RUN_AT(x) (jiffies + (x))
-
-#if (LINUX_VERSION_CODE >= 0x20100)
-static char kernel_version[] = UTS_RELEASE;
-#else
-#ifndef __alpha__
-#define ioremap vremap
-#define iounmap vfree
-#endif
-#endif
-#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(min_pci_latency, "i");
@@ -127,28 +131,6 @@ MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-#endif
-#if LINUX_VERSION_CODE < 0x20123
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if LINUX_VERSION_CODE <= 0x20139
-#define        net_device_stats enet_statistics
-#else
-#define NETSTATS_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20155  ||  defined(CARDBUS)
-/* Grrrr, the PCI code changed, but did not consider CardBus... */
-#include <linux/bios32.h>
-#define PCI_SUPPORT_VER1
-#else
-#define PCI_SUPPORT_VER2
-#endif
-#if LINUX_VERSION_CODE < 0x20159
-#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE);
-#else
-#define dev_free_skb(skb) dev_kfree_skb(skb);
-#endif
-
 
 /*
                                Theory of Operation
@@ -226,13 +208,13 @@ IV. Notes
 IVb. References
 
 Preliminary VT86C100A manual from http://www.via.com.tw/
-http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+http://www.scyld.com/expert/100mbps.html
+http://www.scyld.com/expert/NWay.html
 
 IVc. Errata
 
 The VT86C100A manual is not reliable information.
-The chip does not handle unaligned transmit or receive buffers, resulting
+The 3043 chip does not handle unaligned transmit or receive buffers, resulting
 in significant performance degradation for bounce buffer copies on transmit
 and unaligned IP headers on receive.
 The chip does not pad to minimum transmit length.
@@ -250,6 +232,15 @@ enum pci_flags_bit {
        PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
        PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
 };
+
+#if defined(VIA_USE_MEMORY)
+#define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR0)
+#define RHINEII_IOSIZE 4096
+#else
+#define RHINE_IOTYPE (PCI_USES_IO  | PCI_USES_MASTER | PCI_ADDR1)
+#define RHINEII_IOSIZE 256
+#endif
+
 struct pci_id_info {
        const char *name;
        u16     vendor_id, device_id, device_id_mask, flags;
@@ -264,34 +255,41 @@ static struct device *via_probe1(int pci_bus, int pci_devfn,
 
 static struct pci_id_info pci_tbl[] __initdata = {
        { "VIA VT86C100A Rhine-II", 0x1106, 0x6100, 0xffff,
-         PCI_USES_MEM|PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1},
+         RHINE_IOTYPE, 128, via_probe1},
+       { "VIA VT6102 Rhine-II", 0x1106, 0x3065, 0xffff,
+         RHINE_IOTYPE, RHINEII_IOSIZE, via_probe1},
        { "VIA VT3043 Rhine", 0x1106, 0x3043, 0xffff,
-         PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1},
+         RHINE_IOTYPE, 128, via_probe1},
        {0,},                                           /* 0 terminated list. */
 };
 
 
 /* A chip capabilities table, matching the entries in pci_tbl[] above. */
-enum chip_capability_flags {CanHaveMII=1, };
+enum chip_capability_flags {
+       CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4,
+       ReqTxAlign=0x10, HasWOL=0x20,
+};
+
 struct chip_info {
        int io_size;
        int flags;
 } static cap_tbl[] __initdata = {
-       {128, CanHaveMII, },
-       {128, CanHaveMII, },
+       {128, CanHaveMII | ReqTxAlign, },
+       {128, CanHaveMII | HasWOL, },
+       {128, CanHaveMII | ReqTxAlign, },
 };
 
 
-/* Offsets to the device registers.
-*/
+/* Offsets to the device registers. */
 enum register_offsets {
        StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08,
        IntrStatus=0x0C, IntrEnable=0x0E,
        MulticastFilter0=0x10, MulticastFilter1=0x14,
        RxRingPtr=0x18, TxRingPtr=0x1C,
-       MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIConfig=0x6E,
+       MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E,
        MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72,
-       Config=0x78, RxMissed=0x7C, RxCRCErrs=0x7E,
+       Config=0x78, ConfigA=0x7A, RxMissed=0x7C, RxCRCErrs=0x7E,
+       StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC,
 };
 
 /* Bits in the interrupt status/mask registers. */
@@ -303,21 +301,18 @@ enum intr_status_bits {
        IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000,
        IntrTxAborted=0x2000, IntrLinkChange=0x4000,
        IntrRxWakeUp=0x8000,
-       IntrNormalSummary=0x0003, IntrAbnormalSummary=0x8260,
+       IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260,
 };
 
-
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
-       u16 rx_status;
-       u16 rx_length;
+       s32 rx_status;
        u32 desc_length;
        u32 addr;
        u32 next_desc;
 };
 struct tx_desc {
-       u16 tx_status;
-       u16 tx_own;
+       s32 tx_status;
        u32 desc_length;
        u32 addr;
        u32 next_desc;
@@ -325,9 +320,10 @@ struct tx_desc {
 
 /* Bits in *_desc.status */
 enum rx_status_bits {
-       RxDescOwn=0x80000000, RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F};
+       RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F
+};
 enum desc_status_bits {
-       DescOwn=0x8000, DescEndPacket=0x4000, DescIntr=0x1000,
+       DescOwn=0x80000000, DescEndPacket=0x4000, DescIntr=0x1000,
 };
 
 /* Bits in ChipCmd. */
@@ -338,6 +334,7 @@ enum chip_cmd_bits {
        CmdNoTxPoll=0x0800, CmdReset=0x8000,
 };
 
+#define PRIV_ALIGN     15      /* Required alignment mask */
 struct netdev_private {
        /* Descriptor rings first for alignment. */
        struct rx_desc rx_ring[RX_RING_SIZE];
@@ -349,12 +346,12 @@ struct netdev_private {
        unsigned char *tx_buf[TX_RING_SIZE];    /* Tx bounce buffers */
        unsigned char *tx_bufs;                         /* Tx bounce buffer region. */
        struct device *next_module;                     /* Link for devices of this type. */
+       void *priv_addr;                                        /* Unaligned address for kfree */
        struct net_device_stats stats;
        struct timer_list timer;        /* Media monitoring timer. */
        unsigned char pci_bus, pci_devfn;
        /* Frequently used values: keep some adjacent for cache effect. */
-       int chip_id;
-       long in_interrupt;                      /* Word-long for SMP locks. */
+       int chip_id, drv_flags;
        struct rx_desc *rx_head_desc;
        unsigned int cur_rx, dirty_rx;          /* Producer/consumer ring indices */
        unsigned int cur_tx, dirty_tx;
@@ -388,6 +385,7 @@ static void set_rx_mode(struct device *dev);
 static struct net_device_stats *get_stats(struct device *dev);
 static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 static int  netdev_close(struct device *dev);
+static inline void clear_tally_counters(long ioaddr);
 
 \f
 
@@ -432,30 +430,13 @@ static int __init pci_etherdev_probe(struct device *dev, struct pci_id_info pci_
                        continue;
 
                {
-#if defined(PCI_SUPPORT_VER2)
                        struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
-#ifdef VIA_USE_IO
+#ifdef USE_IO_OPS
                        pciaddr = pdev->base_address[0];
 #else
                        pciaddr = pdev->base_address[1];
 #endif
                        irq = pdev->irq;
-#else
-                       u32 pci_memaddr;
-                       u8 pci_irq_line;
-                       pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                        PCI_INTERRUPT_LINE, &pci_irq_line);
-#ifdef VIA_USE_IO
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                                         PCI_BASE_ADDRESS_0, &pci_memaddr);
-                       pciaddr = pci_memaddr;
-#else
-                       pcibios_read_config_dword(pci_bus, pci_device_fn,
-                                                                         PCI_BASE_ADDRESS_1, &pci_memaddr);
-                       pciaddr = pci_memaddr;
-#endif
-                       irq = pci_irq_line;
-#endif
                }
 
                if (debug > 2)
@@ -511,7 +492,7 @@ int __init via_rhine_probe(struct device *dev)
 {
        static int did_version = 0;
        if (!did_version++)
-               printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+               printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
        return pci_etherdev_probe(dev, pci_tbl);
 }
 #endif
@@ -521,6 +502,7 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn,
                                                                 int chip_id, int card_idx)
 {
        struct netdev_private *np;
+       void *priv_mem;
        int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 
        dev = init_etherdev(dev, 0);
@@ -528,14 +510,20 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn,
        printk(KERN_INFO "%s: %s at 0x%lx, ",
                   dev->name, pci_tbl[chip_id].name, ioaddr);
 
-       /* Ideally we would be read the EEPROM but access may be locked. */
-       for (i = 0; i <6; i++)
+       /* We would prefer to read the EEPROM but access may be locked. */
+       for (i = 0; i < 6; i++)
                dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
        for (i = 0; i < 5; i++)
                        printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
 
-#ifdef VIA_USE_IO
+       /* Allocate driver private memory for descriptor lists.
+          Check for the very unlikely case of no memory. */
+       priv_mem = kmalloc(sizeof(*np) + PRIV_ALIGN, GFP_KERNEL);
+       if (priv_mem == NULL)
+               return NULL;
+
+#ifdef USE_IO_OPS
        request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name);
 #endif
 
@@ -546,9 +534,9 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn,
        dev->irq = irq;
 
        /* Make certain the descriptor lists are cache-aligned. */
-       np = (void *)(((long)kmalloc(sizeof(*np), GFP_KERNEL) + 31) & ~31);
+       dev->priv = np = (void *)(((long)priv_mem + PRIV_ALIGN) & ~PRIV_ALIGN);
        memset(np, 0, sizeof(*np));
-       dev->priv = np;
+       np->priv_addr = priv_mem;
 
        np->next_module = root_net_dev;
        root_net_dev = dev;
@@ -556,6 +544,7 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn,
        np->pci_bus = pci_bus;
        np->pci_devfn = pci_devfn;
        np->chip_id = chip_id;
+       np->drv_flags = cap_tbl[chip_id].flags;
 
        if (dev->mem_start)
                option = dev->mem_start;
@@ -582,7 +571,7 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn,
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &mii_ioctl;
 
-       if (cap_tbl[np->chip_id].flags & CanHaveMII) {
+       if (np->drv_flags & CanHaveMII) {
                int phy, phy_idx = 0;
                np->phys[0] = 1;                /* Standard for this chip. */
                for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
@@ -625,9 +614,23 @@ static int mdio_read(struct device *dev, int phy_id, int regnum)
 
 static void mdio_write(struct device *dev, int phy_id, int regnum, int value)
 {
+       struct netdev_private *np = (struct netdev_private *)dev->priv;
        long ioaddr = dev->base_addr;
        int boguscnt = 1024;
 
+       if (phy_id == np->phys[0]) {
+               switch (regnum) {
+               case 0:                                 /* Is user forcing speed/duplex? */
+                       if (value & 0x9000)     /* Autonegotiation. */
+                               np->duplex_lock = 0;
+                       else
+                               np->full_duplex = (value & 0x0100) ? 1 : 0;
+                       break;
+               case 4:
+                       np->advertising = value;
+                       break;
+               }
+       }
        /* Wait for a previous command to complete. */
        while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
                ;
@@ -649,15 +652,17 @@ static int netdev_open(struct device *dev)
        /* Reset the chip. */
        writew(CmdReset, ioaddr + ChipCmd);
 
-       if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))
+       MOD_INC_USE_COUNT;
+
+       if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) {
+               MOD_DEC_USE_COUNT;
                return -EAGAIN;
+       }
 
        if (debug > 1)
                printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
                           dev->name, dev->irq);
 
-       MOD_INC_USE_COUNT;
-
        init_ring(dev);
 
        writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr);
@@ -667,7 +672,7 @@ static int netdev_open(struct device *dev)
                writeb(dev->dev_addr[i], ioaddr + StationAddr + i);
 
        /* Initialize other registers. */
-       writew(0x0006, ioaddr + PCIConfig);     /* Tune configuration??? */
+       writew(0x0006, ioaddr + PCIBusConfig);  /* Tune configuration??? */
        /* Configure the FIFO thresholds. */
        writeb(0x20, ioaddr + TxConfig);        /* Initial threshold 32 bytes */
        np->tx_thresh = 0x20;
@@ -678,7 +683,6 @@ static int netdev_open(struct device *dev)
 
        dev->tbusy = 0;
        dev->interrupt = 0;
-       np->in_interrupt = 0;
 
        set_rx_mode(dev);
 
@@ -696,6 +700,11 @@ static int netdev_open(struct device *dev)
        writew(np->chip_cmd, ioaddr + ChipCmd);
 
        check_duplex(dev);
+       /* The LED outputs of various MII xcvrs should be configured.  */
+       /* For NS or Mison phys, turn on bit 1 in register 0x17 */
+       /* For ESI phys, turn on bit 7 in register 0x17. */
+       mdio_write(dev, np->phys[0], 0x17, mdio_read(dev, np->phys[0], 0x17) |
+                          (np->drv_flags & HasESIPhy) ? 0x0080 : 0x0001);
 
        if (debug > 2)
                printk(KERN_DEBUG "%s: Done netdev_open(), status %4.4x "
@@ -705,7 +714,7 @@ static int netdev_open(struct device *dev)
 
        /* Set the timer to check for link beat. */
        init_timer(&np->timer);
-       np->timer.expires = RUN_AT(1);
+       np->timer.expires = jiffies + 2;
        np->timer.data = (unsigned long)dev;
        np->timer.function = &netdev_timer;                             /* timer handler */
        add_timer(&np->timer);
@@ -718,11 +727,12 @@ static void check_duplex(struct device *dev)
        struct netdev_private *np = (struct netdev_private *)dev->priv;
        long ioaddr = dev->base_addr;
        int mii_reg5 = mdio_read(dev, np->phys[0], 5);
+       int negotiated = mii_reg5 & np->advertising;
        int duplex;
 
        if (np->duplex_lock  ||  mii_reg5 == 0xffff)
                return;
-       duplex = (mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+       duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
        if (np->full_duplex != duplex) {
                np->full_duplex = duplex;
                if (debug)
@@ -748,9 +758,14 @@ static void netdev_timer(unsigned long data)
                printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n",
                           dev->name, readw(ioaddr + IntrStatus));
        }
+       if (test_bit(0, (void*)&dev->tbusy) != 0
+               && np->cur_tx - np->dirty_tx > 1
+               && jiffies - dev->trans_start > TX_TIMEOUT)
+               tx_timeout(dev);
+
        check_duplex(dev);
 
-       np->timer.expires = RUN_AT(next_tick);
+       np->timer.expires = jiffies + next_tick;
        add_timer(&np->timer);
 }
 
@@ -764,15 +779,15 @@ static void tx_timeout(struct device *dev)
                   dev->name, readw(ioaddr + IntrStatus),
                   mdio_read(dev, np->phys[0], 1));
 
-  /* Perhaps we should reinitialize the hardware here. */
-  dev->if_port = 0;
-  /* Stop and restart the chip's Tx processes . */
+       /* Perhaps we should reinitialize the hardware here. */
+       dev->if_port = 0;
+       /* Stop and restart the chip's Tx processes . */
 
-  /* Trigger an immediate transmit demand. */
+       /* Trigger an immediate transmit demand. */
 
-  dev->trans_start = jiffies;
-  np->stats.tx_errors++;
-  return;
+       dev->trans_start = jiffies;
+       np->stats.tx_errors++;
+       return;
 }
 
 
@@ -791,35 +806,33 @@ static void init_ring(struct device *dev)
 
        for (i = 0; i < RX_RING_SIZE; i++) {
                np->rx_ring[i].rx_status = 0;
-               np->rx_ring[i].rx_length = 0;
-               np->rx_ring[i].desc_length = np->rx_buf_sz;
-               np->rx_ring[i].next_desc = virt_to_bus(&np->rx_ring[i+1]);
+               np->rx_ring[i].desc_length = cpu_to_le32(np->rx_buf_sz);
+               np->rx_ring[i].next_desc = virt_to_le32desc(&np->rx_ring[i+1]);
                np->rx_skbuff[i] = 0;
        }
        /* Mark the last entry as wrapping the ring. */
-       np->rx_ring[i-1].next_desc = virt_to_bus(&np->rx_ring[0]);
+       np->rx_ring[i-1].next_desc = virt_to_le32desc(&np->rx_ring[0]);
 
-       /* Fill in the Rx buffers. */
+       /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
                struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
                np->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
                skb->dev = dev;                 /* Mark as being used by this device. */
-               np->rx_ring[i].addr = virt_to_bus(skb->tail);
-               np->rx_ring[i].rx_status = 0;
-               np->rx_ring[i].rx_length = DescOwn;
+               np->rx_ring[i].addr = virt_to_le32desc(skb->tail);
+               np->rx_ring[i].rx_status = cpu_to_le32(DescOwn);
        }
        np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 
        for (i = 0; i < TX_RING_SIZE; i++) {
                np->tx_skbuff[i] = 0;
-               np->tx_ring[i].tx_own = 0;
-               np->tx_ring[i].desc_length = 0x00e08000;
-               np->tx_ring[i].next_desc = virt_to_bus(&np->tx_ring[i+1]);
+               np->tx_ring[i].tx_status = 0;
+               np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000);
+               np->tx_ring[i].next_desc = virt_to_le32desc(&np->tx_ring[i+1]);
                np->tx_buf[i] = kmalloc(PKT_BUF_SZ, GFP_KERNEL);
        }
-       np->tx_ring[i-1].next_desc = virt_to_bus(&np->tx_ring[0]);
+       np->tx_ring[i-1].next_desc = virt_to_le32desc(&np->tx_ring[0]);
 
        return;
 }
@@ -832,41 +845,45 @@ static int start_tx(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) {
-               if (jiffies - dev->trans_start < TX_TIMEOUT)
-                       return 1;
-               tx_timeout(dev);
+               /* This watchdog code is redundant with the media monitor timer. */
+               if (jiffies - dev->trans_start > TX_TIMEOUT)
+                       tx_timeout(dev);
                return 1;
        }
 
-       /* Caution: the write order is important here, set the field
-          with the "ownership" bits last. */
+       /* Explicitly flush packet data cache lines here. */
+
+       /* Caution: the write order is important here, set the descriptor word
+          with the "ownership" bit last.  No SMP locking is needed if the
+          cur_tx is incremented after the descriptor is consistent.  */
 
        /* Calculate the next Tx descriptor entry. */
        entry = np->cur_tx % TX_RING_SIZE;
 
        np->tx_skbuff[entry] = skb;
 
-       if ((long)skb->data & 3) {                      /* Must use alignment buffer. */
+       if ((np->drv_flags & ReqTxAlign)  && ((long)skb->data & 3)) {
+               /* Must use alignment buffer. */
                if (np->tx_buf[entry] == NULL &&
                        (np->tx_buf[entry] = kmalloc(PKT_BUF_SZ, GFP_KERNEL)) == NULL)
                        return 1;
                memcpy(np->tx_buf[entry], skb->data, skb->len);
-               np->tx_ring[entry].addr = virt_to_bus(np->tx_buf[entry]);
+               np->tx_ring[entry].addr = virt_to_le32desc(np->tx_buf[entry]);
        } else
-               np->tx_ring[entry].addr = virt_to_bus(skb->data);
+               np->tx_ring[entry].addr = virt_to_le32desc(skb->data);
 
-       np->tx_ring[entry].desc_length = 0x00E08000 |
-               (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
-       np->tx_ring[entry].tx_own = DescOwn;
+       np->tx_ring[entry].desc_length =
+               cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+       np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
 
        np->cur_tx++;
 
-       /* Non-x86 Todo: explicitly flush cache lines here. */
+       /* Explicitly flush descriptor cache lines here. */
 
        /* Wake the potentially-idle transmit channel. */
        writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd);
 
-       if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1)
+       if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1)
                clear_bit(0, (void*)&dev->tbusy);               /* Typical path */
        else
                np->tx_full = 1;
@@ -884,26 +901,9 @@ static int start_tx(struct sk_buff *skb, struct device *dev)
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
        struct device *dev = (struct device *)dev_instance;
-       struct netdev_private *np;
-       long ioaddr, boguscnt = max_interrupt_work;
-
-       ioaddr = dev->base_addr;
-       np = (struct netdev_private *)dev->priv;
-#if defined(__i386__)
-       /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
-       if (test_and_set_bit(0, (void*)&dev->interrupt)) {
-               printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
-                          dev->name);
-               dev->interrupt = 0;     /* Avoid halting machine. */
-               return;
-       }
-#else
-       if (dev->interrupt) {
-               printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-               return;
-       }
-       dev->interrupt = 1;
-#endif
+       struct netdev_private *np = (void *)dev->priv;
+       long ioaddr = dev->base_addr;
+       int boguscnt = max_interrupt_work;
 
        do {
                u32 intr_status = readw(ioaddr + IntrStatus);
@@ -924,10 +924,9 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 
                for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
                        int entry = np->dirty_tx % TX_RING_SIZE;
-                       int txstatus;
-                       if (np->tx_ring[entry].tx_own)
+                       int txstatus = le32_to_cpu(np->tx_ring[entry].tx_status);
+                       if (txstatus & DescOwn)
                                break;
-                       txstatus = np->tx_ring[entry].tx_status;
                        if (debug > 6)
                                printk(KERN_DEBUG " Tx scavenge %d status %4.4x.\n",
                                           entry, txstatus);
@@ -951,16 +950,16 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 #endif
                                np->stats.collisions += (txstatus >> 3) & 15;
 #if defined(NETSTATS_VER2)
-                               np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff;
+                               np->stats.tx_bytes += np->tx_skbuff[entry]->len;
 #endif
                                np->stats.tx_packets++;
                        }
                        /* Free the original skb. */
-                       dev_free_skb(np->tx_skbuff[entry]);
+                       dev_kfree_skb(np->tx_skbuff[entry]);
                        np->tx_skbuff[entry] = 0;
                }
                if (np->tx_full && dev->tbusy
-                       && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
+                       && np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
                        /* The ring is no longer full, clear tbusy. */
                        np->tx_full = 0;
                        clear_bit(0, (void*)&dev->tbusy);
@@ -984,11 +983,6 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
                printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
                           dev->name, readw(ioaddr + IntrStatus));
 
-#if defined(__i386__)
-       clear_bit(0, (void*)&dev->interrupt);
-#else
-       dev->interrupt = 0;
-#endif
        return;
 }
 
@@ -1001,15 +995,15 @@ static int netdev_rx(struct device *dev)
        int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
 
        if (debug > 4) {
-               printk(KERN_DEBUG " In netdev_rx(), entry %d status %4.4x.\n",
-                          entry, np->rx_head_desc->rx_length);
+               printk(KERN_DEBUG " In netdev_rx(), entry %d status %8.8x.\n",
+                          entry, np->rx_head_desc->rx_status);
        }
 
        /* If EOP is set on the next entry, it's a new packet. Send it up. */
-       while ( ! (np->rx_head_desc->rx_length & DescOwn)) {
+       while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
                struct rx_desc *desc = np->rx_head_desc;
-               int data_size = desc->rx_length;
-               u16 desc_status = desc->rx_status;
+               u32 desc_status = le32_to_cpu(desc->rx_status);
+               int data_size = desc_status >> 16;
 
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status is %4.4x.\n",
@@ -1039,7 +1033,7 @@ static int netdev_rx(struct device *dev)
                } else {
                        struct sk_buff *skb;
                        /* Length should omit the CRC */
-                       u16 pkt_len = data_size - 4;
+                       int pkt_len = data_size - 4;
 
                        /* Check if the packet is long enough to accept without copying
                           to a minimally-sized skbuff. */
@@ -1047,21 +1041,23 @@ static int netdev_rx(struct device *dev)
                                && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
                                skb->dev = dev;
                                skb_reserve(skb, 2);    /* 16 byte align the IP header */
-#if ! defined(__alpha__) || USE_IP_COPYSUM             /* Avoid misaligned on Alpha */
-                               eth_copy_and_sum(skb, bus_to_virt(desc->addr),
-                                                                pkt_len, 0);
+#if HAS_IP_COPYSUM                     /* Call copy + cksum if available. */
+                               eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
                                skb_put(skb, pkt_len);
 #else
-                               memcpy(skb_put(skb,pkt_len), bus_to_virt(desc->addr), pkt_len);
+                               memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail,
+                                          pkt_len);
 #endif
                        } else {
                                skb_put(skb = np->rx_skbuff[entry], pkt_len);
                                np->rx_skbuff[entry] = NULL;
                        }
                        skb->protocol = eth_type_trans(skb, dev);
-                       np->stats.rx_bytes+=skb->len;
                        netif_rx(skb);
                        dev->last_rx = jiffies;
+#if defined(NETSTATS_VER2)
+                       np->stats.rx_bytes += skb->len;
+#endif
                        np->stats.rx_packets++;
                }
                entry = (++np->cur_rx) % RX_RING_SIZE;
@@ -1078,10 +1074,9 @@ static int netdev_rx(struct device *dev)
                        if (skb == NULL)
                                break;                  /* Better luck next round. */
                        skb->dev = dev;                 /* Mark as being used by this device. */
-                       np->rx_ring[entry].addr = virt_to_bus(skb->tail);
+                       np->rx_ring[entry].addr = virt_to_le32desc(skb->tail);
                }
-               np->rx_ring[entry].rx_status = 0;
-               np->rx_ring[entry].rx_length = DescOwn;
+               np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
        }
 
        /* Pre-emptively restart Rx engine. */
@@ -1095,10 +1090,11 @@ static void netdev_error(struct device *dev, int intr_status)
        long ioaddr = dev->base_addr;
 
        if (intr_status & (IntrMIIChange | IntrLinkChange)) {
-               if (readb(ioaddr + MIIStatus) & 0x02)
+               if (readb(ioaddr + MIIStatus) & 0x02) {
                        /* Link failed, restart autonegotiation. */
-                       mdio_write(dev, np->phys[0], 0, 0x3300);
-               else
+                       if (np->drv_flags & HasDavicomPhy)
+                               mdio_write(dev, np->phys[0], 0, 0x3300);
+               } else
                        check_duplex(dev);
                if (debug)
                        printk(KERN_ERR "%s: MII status changed: Autonegotiation "
@@ -1109,7 +1105,7 @@ static void netdev_error(struct device *dev, int intr_status)
        if (intr_status & IntrStatsMax) {
                np->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs);
                np->stats.rx_missed_errors      += readw(ioaddr + RxMissed);
-               writel(0, RxMissed);
+               clear_tally_counters(ioaddr);
        }
        if (intr_status & IntrTxAbort) {
                /* Stats counted in Tx-done handler, just restart Tx. */
@@ -1122,7 +1118,8 @@ static void netdev_error(struct device *dev, int intr_status)
                        printk(KERN_INFO "%s: Transmitter underrun, increasing Tx "
                                   "threshold setting to %2.2x.\n", dev->name, np->tx_thresh);
        }
-       if ((intr_status & ~(IntrLinkChange|IntrStatsMax|IntrTxAbort)) && debug) {
+       if ((intr_status & ~(IntrLinkChange | IntrStatsMax |
+                                                IntrTxAbort|IntrTxAborted))  &&  debug) {
                printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
                           dev->name, intr_status);
                /* Recovery for other fault sources not known. */
@@ -1140,28 +1137,39 @@ static struct enet_statistics *get_stats(struct device *dev)
           non-critical. */
        np->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs);
        np->stats.rx_missed_errors      += readw(ioaddr + RxMissed);
-       writel(0, RxMissed);
+       clear_tally_counters(ioaddr);
 
        return &np->stats;
 }
 
+/* Clears the "tally counters" for CRC errors and missed frames(?).
+   It has been reported that some chips need a write of 0 to clear
+   these, for others the counters are set to 1 when written to and
+   instead cleared when read. So we clear them both ways ... */
+static inline void clear_tally_counters(const long ioaddr)
+{
+       writel(0, ioaddr + RxMissed);
+       readw(ioaddr + RxCRCErrs);
+       readw(ioaddr + RxMissed);
+}
+
 /* The big-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 = 0x04c11db7U;
 static inline u32 ether_crc(int length, unsigned char *data)
 {
-    int crc = -1;
+       int crc = -1;
 
-    while(--length >= 0) {
+       while(--length >= 0) {
                unsigned char current_octet = *data++;
                int bit;
                for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
                        crc = (crc << 1) ^
                                ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
                }
-    }
-    return crc;
+       }
+       return crc;
 }
 
 static void set_rx_mode(struct device *dev)
@@ -1178,6 +1186,8 @@ static void set_rx_mode(struct device *dev)
        } else if ((dev->mc_count > multicast_filter_limit)
                           ||  (dev->flags & IFF_ALLMULTI)) {
                /* Too many to match, or accept all multicasts. */
+               writel(0xffffffff, ioaddr + MulticastFilter0);
+               writel(0xffffffff, ioaddr + MulticastFilter1);
                rx_mode = 0x0C;
        } else {
                struct dev_mc_list *mclist;
@@ -1190,7 +1200,7 @@ static void set_rx_mode(struct device *dev)
                }
                writel(mc_filter[0], ioaddr + MulticastFilter0);
                writel(mc_filter[1], ioaddr + MulticastFilter1);
-               rx_mode = 0x08;
+               rx_mode = 0x0C;
        }
        writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
@@ -1207,7 +1217,7 @@ static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
                return 0;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
                return 0;
@@ -1229,32 +1239,39 @@ static int netdev_close(struct device *dev)
                printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
                           dev->name, readw(ioaddr + ChipCmd));
 
+       del_timer(&np->timer);
+
+       /* Switch to loopback mode to avoid hardware races. */
+       writeb(np->tx_thresh | 0x01, ioaddr + TxConfig);
+
        /* Disable interrupts by clearing the interrupt mask. */
        writew(0x0000, ioaddr + IntrEnable);
 
        /* Stop the chip's Tx and Rx processes. */
        writew(CmdStop, ioaddr + ChipCmd);
 
-       del_timer(&np->timer);
-
        free_irq(dev->irq, dev);
 
        /* Free all the skbuffs in the Rx queue. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               np->rx_ring[i].rx_length = 0;
+               np->rx_ring[i].rx_status = 0;
                np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
                if (np->rx_skbuff[i]) {
 #if LINUX_VERSION_CODE < 0x20100
                        np->rx_skbuff[i]->free = 1;
 #endif
-                       dev_free_skb(np->rx_skbuff[i]);
+                       dev_kfree_skb(np->rx_skbuff[i]);
                }
                np->rx_skbuff[i] = 0;
        }
        for (i = 0; i < TX_RING_SIZE; i++) {
                if (np->tx_skbuff[i])
-                       dev_free_skb(np->tx_skbuff[i]);
+                       dev_kfree_skb(np->tx_skbuff[i]);
                np->tx_skbuff[i] = 0;
+               if (np->tx_buf[i]) {
+                       kfree(np->tx_buf[i]);
+                       np->tx_buf[i] = 0;
+               }
        }
 
        MOD_DEC_USE_COUNT;
@@ -1267,37 +1284,28 @@ static int netdev_close(struct device *dev)
 int init_module(void)
 {
        if (debug)                                      /* Emit version even if no cards detected. */
-               printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-#ifdef CARDBUS
-       register_driver(&etherdev_ops);
-       return 0;
-#else
+               printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
        return pci_etherdev_probe(NULL, pci_tbl);
-#endif
 }
 
 void cleanup_module(void)
 {
-
-#ifdef CARDBUS
-       unregister_driver(&etherdev_ops);
-#endif
+       struct device *next_dev;
 
        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
        while (root_net_dev) {
-               struct netdev_private *np =
-                       (struct netdev_private *)(root_net_dev->priv);
+               struct netdev_private *np = (void *)(root_net_dev->priv);
                unregister_netdev(root_net_dev);
-#ifdef VIA_USE_IO
+#ifdef USE_IO_OPS
                release_region(root_net_dev->base_addr, pci_tbl[np->chip_id].io_size);
 #else
                iounmap((char *)(root_net_dev->base_addr));
 #endif
+               next_dev = np->next_module;
+               if (np->priv_addr)
+                       kfree(np->priv_addr);
                kfree(root_net_dev);
-               root_net_dev = np->next_module;
-#if 0
-               kfree(np);                              /* Assumption: no struct realignment. */
-#endif
+               root_net_dev = next_dev;
        }
 }
 
index 951207e09853e1193115c7b7a17b8d3113845361..6dc1b70707236fc80cde1adb9d01005d072743cc 100644 (file)
@@ -2924,9 +2924,7 @@ cleanup_dasd (void)
 int
 init_module ( void )
 {
-        int rc=0;
         return dasd_init(); 
-        return rc;
 }
 
 void 
index bb063f304aff423a5f19d0a853f7decdcc17133e..3a0313007f88782efdcfb272a01aec77a8443beb 100644 (file)
@@ -7,3 +7,8 @@ void dasd_free_request(ccw_req_t *);
 int (*genhd_dasd_name)(char*,int,int,struct gendisk*);
 int dasd_oper_handler ( int irq, devreg_t *devreg );
 
+dasd_era_t dasd_3370_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+dasd_era_t dasd_3990_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+dasd_era_t dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+dasd_era_t dasd_9343_erp_examine (ccw_req_t * cqr, devstat_t * stat);
+
index 75af18b39c34b8b2e3f938aac49ebf431d16bc32..1069308746d929503679c42deed58f47f38b34c5 100644 (file)
@@ -5,6 +5,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
index 963260f3f9c98bd135b48fb5c0171a563e99e25b..a116db771ba472f3c2ce4dac096e6a30ce8fae6d 100644 (file)
@@ -6,6 +6,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
index 2c04ca437681ca1545539ab5b9d35cb27ebab9eb..6cf40a0d2798692f3fc25b6d975094001a93f0b2 100644 (file)
@@ -5,6 +5,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
@@ -32,8 +33,6 @@
 dasd_era_t
 dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat)
 {
-       char *sense = stat->ii.sense.data;
-
        /* check for successful execution first */
        if (stat->cstat == 0x00 &&
            stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
index 5f7d6c5ede778ac8a74ee99ce196dbef3e733af4..aa0d8f10e4e00b1c489305e68f7ac8763dd64523 100644 (file)
@@ -5,6 +5,7 @@
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
  */
 
+#include <linux/blkdev.h>
 #include <asm/ccwcache.h>
 #include <asm/dasd.h>
 
index cc472471e950ad1f9e99e1421b8b02e375a75cde..1d6adbe01b6344ebe671ffc095c364dbd271a42f 100644 (file)
@@ -74,6 +74,7 @@ dasd_eckd_private_t {
         eckd_count_t count_area;
 } dasd_eckd_private_t;
 
+#ifdef CONFIG_DASD_DYNAMIC
 static
 devreg_t dasd_eckd_known_devices[] = {
        {
@@ -92,6 +93,7 @@ devreg_t dasd_eckd_known_devices[] = {
                 oper_func: dasd_oper_handler
         }
 };
+#endif
 
 static inline unsigned int
 round_up_multiple (unsigned int no, unsigned int mult)
@@ -923,7 +925,9 @@ dasd_discipline_t dasd_eckd_discipline = {
 int
 dasd_eckd_init( void ) {
         int rc = 0;
+#ifdef CONFIG_DASD_DYNAMIC
        int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline initializing\n", dasd_eckd_discipline.name);
         ASCEBC(dasd_eckd_discipline.ebcname,4);
@@ -944,8 +948,9 @@ dasd_eckd_init( void ) {
 
 void
 dasd_eckd_cleanup( void ) {
-        int rc = 0;
+#ifdef CONFIG_DASD_DYNAMIC
        int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline cleaning up\n", dasd_eckd_discipline.name);
 #ifdef CONFIG_DASD_DYNAMIC
@@ -960,7 +965,7 @@ dasd_eckd_cleanup( void ) {
        } 
 #endif /* CONFIG_DASD_DYNAMIC */
         dasd_discipline_deq(&dasd_eckd_discipline);
-        return rc;
+        return;
 }
 
 /*
index fd713ef877374d97e1e7568c5b4dbb454eec3a4e..36c505a185ca1279919cb8d8e57d89ee026a1c69 100644 (file)
@@ -282,5 +282,6 @@ typedef struct dasd_eckd_confdata_t {
 } __attribute__ ((packed)) dasd_eckd_confdata_t;
 
 int dasd_eckd_init( void );
+void dasd_eckd_cleanup( void );
 
 #endif /* DASD_ECKD_H */
index c91963c42dfee9447f52f28c1451f5286160de39..eeec40c2e2fd4479d69749f80d19afeafe3d65df 100644 (file)
@@ -181,9 +181,7 @@ dasd_fba_fill_geometry(struct dasd_device_t *device, struct hd_geometry *geo)
         int rc = 0;
        unsigned long sectors = device->sizes.blocks << device->sizes.s2b_shift;
        unsigned long tracks = sectors >> 6;
-       unsigned long trk_rem = sectors & ((1<<6)-1);
        unsigned long cyls = tracks >> 4;
-       unsigned long cyls_rem = tracks & ((1<<4)-1);
 
         switch(device->sizes.bp_block) {
         case 512:
@@ -371,7 +369,9 @@ dasd_discipline_t dasd_fba_discipline = {
 int
 dasd_fba_init( void ) {
         int rc = 0;
+#ifdef CONFIG_DASD_DYNAMIC
        int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline initializing\n", dasd_fba_discipline.name);
         ASCEBC(dasd_fba_discipline.ebcname,4);
@@ -392,8 +392,9 @@ dasd_fba_init( void ) {
 
 void
 dasd_fba_cleanup( void ) {
-        int rc = 0;
+#ifdef CONFIG_DASD_DYNAMIC
        int i;
+#endif
         printk ( KERN_INFO PRINTK_HEADER
                  "%s discipline cleaning up\n", dasd_fba_discipline.name);
 #ifdef CONFIG_DASD_DYNAMIC
@@ -408,7 +409,7 @@ dasd_fba_cleanup( void ) {
         }
 #endif /* CONFIG_DASD_DYNAMIC */
         dasd_discipline_deq(&dasd_fba_discipline);
-        return rc;
+        return;
 }
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 1891592b584b891c6e7ea990ef9d062945a8a099..0e151534a2fb3be13e19ee50c004c0055f11ec74 100644 (file)
@@ -66,5 +66,6 @@ struct dasd_fba_characteristics_t {
 } __attribute__ ((packed)) dasd_fba_characteristics_t;
 
 int dasd_fba_init( void );
+void dasd_fba_cleanup( void );
 
 #endif /* DASD_FBA_H */
index df05be8883c2e35ccbb27cf0c169fcb5fa9821e6..565934c1dff40c656e1f857b4e10867ebca4f83b 100644 (file)
@@ -104,6 +104,122 @@ struct {
         long blksize[MDISK_DEVS];
 } mdisk_setup_data;
 
+/*
+ * The 'low level' IO function
+ */
+
+static __inline__ int
+dia250(void* iob,int cmd)
+{
+       int rc;
+       
+       iob = (void*) virt_to_phys(iob);
+
+       asm volatile ("    lr    2,%1\n"
+                     "    lr    3,%2\n"
+                     "    .long 0x83230250\n"
+                     "    lr    %0,3"
+                     : "=d" (rc)
+                     : "d" (iob) , "d" (cmd)
+                     : "2", "3" );
+       return rc;
+}
+
+/*
+ * The device characteristics function
+ */
+
+static __inline__ int
+dia210(void* devchar)
+{
+       int rc;
+
+       devchar = (void*) virt_to_phys(devchar);
+
+       asm volatile ("    lr    2,%1\n"
+                     "    .long 0x83200210\n"
+                     "    ipm   %0\n"
+                     "    srl   %0,28"
+                     : "=d" (rc)
+                     : "d" (devchar)
+                     : "2" );
+       return rc;
+}
+
+
+/*
+ * release of minidisk device
+ */
+
+static __inline__ int
+mdisk_term_io(mdisk_Dev *dev)
+{
+       mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
+       
+       memset(iob,0,sizeof(mdisk_init_io_t));
+       
+       iob->dev_nr = dev->vdev;
+       
+       return dia250(iob,TERM_BIO);
+}
+
+
+/*
+ * Init of minidisk device
+ */
+
+static __inline__ int
+mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size)
+{
+       mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
+       int rc;
+
+       memset(iob,0,sizeof(mdisk_init_io_t));
+       
+       iob->dev_nr = dev->vdev;
+       iob->block_size = blocksize;
+       iob->offset     = offset;
+       iob->start_block= 0;
+       iob->end_block  = size;
+       
+       rc = dia250(iob,INIT_BIO);
+       
+       /*
+        * clear for following io once
+        */
+       
+       memset(iob,0,sizeof(mdisk_rw_io_t));
+       
+       return rc;
+}
+
+
+/*
+ * setup and start of minidisk io request
+ */
+
+static __inline__ int
+mdisk_rw_io_clustered (mdisk_Dev *dev,
+                       mdisk_bio_t* bio_array,
+                       int length,
+                       int req,
+                       int sync)
+{
+       int rc;
+       mdisk_rw_io_t *iob = dev->iob;
+       
+       iob->dev_nr      = dev->vdev;
+       iob->key         = 0;
+       iob->flags       = sync;
+       
+       iob->block_count = length;
+       iob->interrupt_params = req;
+       iob->bio_list     = virt_to_phys(bio_array);
+       
+       rc = dia250(iob,RW_BIO);
+       return rc;
+}
+
 /*
  * Parameter parsing function, called from init/main.c
  * vdev    : virtual device number
@@ -117,7 +233,7 @@ __initfunc(void mdisk_setup(char *str,int *ints))
 {
        char *cur = str;
        int vdev, size, offset=0,blksize;
-       static i = 0;
+static int i = 0;
        if (!i)
          memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data));
 
@@ -280,48 +396,7 @@ static struct file_operations mdisk_fops = {
        NULL,          /* mdisk_lock */
 };
 
-/*
- * The 'low level' IO function
- */
-
-
-static __inline__ int
-dia250(void* iob,int cmd)
-{
-       int rc;
-       
-       iob = (void*) virt_to_phys(iob);
-
-       asm volatile ("    lr    2,%1\n"
-                     "    lr    3,%2\n"
-                     "    .long 0x83230250\n"
-                     "    lr    %0,3"
-                     : "=d" (rc)
-                     : "d" (iob) , "d" (cmd)
-                     : "2", "3" );
-       return rc;
-}
-
-/*
- * The device characteristics function
- */
-
-static __inline__ int
-dia210(void* devchar)
-{
-       int rc;
-
-       devchar = (void*) virt_to_phys(devchar);
 
-       asm volatile ("    lr    2,%1\n"
-                     "    .long 0x83200210\n"
-                     "    ipm   %0\n"
-                     "    srl   %0,28"
-                     : "=d" (rc)
-                     : "d" (devchar)
-                     : "2" );
-       return rc;
-}
 /*
  * read the label of a minidisk and extract its characteristics
  */
@@ -396,80 +471,6 @@ mdisk_read_label (mdisk_Dev *dev, int i)
 }
 
 
-
-/*
- * Init of minidisk device
- */
-
-static __inline__ int
-mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size)
-{
-       mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
-       int rc;
-
-       memset(iob,0,sizeof(mdisk_init_io_t));
-       
-       iob->dev_nr = dev->vdev;
-       iob->block_size = blocksize;
-       iob->offset     = offset;
-       iob->start_block= 0;
-       iob->end_block  = size;
-       
-       rc = dia250(iob,INIT_BIO);
-       
-       /*
-        * clear for following io once
-        */
-       
-       memset(iob,0,sizeof(mdisk_rw_io_t));
-       
-       return rc;
-}
-
-/*
- * release of minidisk device
- */
-
-static __inline__ int
-mdisk_term_io(mdisk_Dev *dev)
-{
-       mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
-       
-       memset(iob,0,sizeof(mdisk_init_io_t));
-       
-       iob->dev_nr = dev->vdev;
-       
-       return dia250(iob,TERM_BIO);
-}
-
-/*
- * setup and start of minidisk io request
- */
-
-static __inline__ int
-mdisk_rw_io_clustered (mdisk_Dev *dev,
-                       mdisk_bio_t* bio_array,
-                       int length,
-                       int req,
-                       int sync)
-{
-       int rc;
-       mdisk_rw_io_t *iob = dev->iob;
-       
-       iob->dev_nr      = dev->vdev;
-       iob->key         = 0;
-       iob->flags       = sync;
-       
-       iob->block_count = length;
-       iob->interrupt_params = req;
-       iob->bio_list     = virt_to_phys(bio_array);
-       
-       rc = dia250(iob,RW_BIO);
-       return rc;
-}
-
-
-
 /*
  * this handles a clustered request in success case
  * all buffers are detach and marked uptodate to the kernel
@@ -640,11 +641,8 @@ void mdisk_request(void)
  */
 void do_mdisk_interrupt(struct pt_regs *regs, __u16 code)
 {
-        u16 code;
        mdisk_Dev *dev;
        
-       code = S390_lowcore.cpu_addr;
-
        if ((code >> 8) != 0x03) {
          printk("mnd: wrong sub-interruption code %d",code>>8);
          return;
index db67ff042284da6a15250eeba4e69bca42b975ae..b17785525333967cdb601c334282e25b0e1e0298 100644 (file)
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Tested with Linux 1.2.13, ..., 2.2.16, ..., 2.4.0-test             *
+ * Tested with Linux 1.2.13, ..., 2.2.16, ..., 2.4.0-test10             *
  *                                                                      *
  * $Log: gdth.c,v $
+ * Revision 1.45  2000/11/16 12:02:24  achim
+ * Changes for kernel 2.4
+ *
+ * Revision 1.44  2000/10/11 08:44:10  achim
+ * Clustering changes: New flag media_changed added
+ *
+ * Revision 1.43  2000/09/20 12:59:01  achim
+ * DPMEM remap functions for all PCI controller types implemented
+ * Small changes for ia64 platform
+ *
  * Revision 1.42  2000/07/20 09:04:50  achim
  * Small changes for kernel 2.4
  *
  * Initial revision
  *
  ************************************************************************/
-#ident "$Id: gdth.c,v 1.42 2000/07/20 09:04:50 achim Exp $" 
+#ident "$Id: gdth.c,v 1.45 2000/11/16 12:02:24 achim Exp $" 
 
 /* All GDT Disk Array Controllers are fully supported by this driver.
  * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -1111,8 +1121,51 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
             printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
             return 0;
         }
+        /* check and reset interface area */
         dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        /* reset interface area */
+        gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
+        if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_old() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_0, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_0, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6_ptr = (gdt6_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
+                if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
+        }
         memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
         if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
@@ -1181,8 +1234,51 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
             gdth_munmap(ha->brd);
             return 0;
         }
+        /* check and reset interface area */
         dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
-        /* reset interface area */
+        gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
+        if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
+            printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
+                   pcistr->dpmem);
+            found = FALSE;
+            for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+                gdth_munmap(ha->brd);
+                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                if (gdth_readw(ha->brd) != 0xffff) {
+                    TRACE2(("init_pci_plx() address 0x%x busy\n", i));
+                    continue;
+                }
+                gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+                pci_write_config_dword(pcistr->pdev, 
+                                       PCI_BASE_ADDRESS_2, i);
+#else
+                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+                                           PCI_BASE_ADDRESS_2, i);
+#endif
+                ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); 
+                if (ha->brd == NULL) {
+                    printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+                    return 0;
+                }
+                dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+                gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
+                if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
+                    printk("GDT-PCI: Use free address at 0x%x\n", i);
+                    found = TRUE;
+                    break;
+                }
+            }   
+            if (!found) {
+                printk("GDT-PCI: No free address found!\n");
+                gdth_munmap(ha->brd);
+                return 0;
+            }
+        }
         memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
         if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
@@ -1966,7 +2062,6 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum))
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
 
     /* set/get features raw service (scatter/gather) */
-    ha->raw_feat = 0;
     if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
                           0,0)) {
         TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
@@ -2061,18 +2156,14 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive)
         TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n",
                 hdrive,ha->info));
         ha->hdr[hdrive].cluster_type = (unchar)ha->info;
-    } else {
-        ha->hdr[hdrive].cluster_type = 0;
-    }           
+    }
 
     /* R/W attributes */
     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) {
         TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n",
                 hdrive,ha->info));
         ha->hdr[hdrive].rw_attribs = (unchar)ha->info;
-    } else {
-        ha->hdr[hdrive].rw_attribs = 0;
-    }           
+    }
 
     return 1;
 }
@@ -2264,10 +2355,14 @@ static void gdth_next(int hanum)
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
                     nscp->cmnd[0], b, t, nscp->lun));
             nscp->result = DID_BAD_TARGET << 16;
-            GDTH_UNLOCK_HA(ha,flags);
-            /* io_request_lock already active ! */      
-            nscp->scsi_done(nscp);
-            GDTH_LOCK_HA(ha,flags);
+           if (!nscp->SCp.have_data_in)
+               nscp->SCp.have_data_in++;
+           else {
+               GDTH_UNLOCK_HA(ha,flags);
+               /* io_request_lock already active ! */      
+               nscp->scsi_done(nscp);
+               GDTH_LOCK_HA(ha,flags);
+           }
         } else {
             switch (nscp->cmnd[0]) {
               case TEST_UNIT_READY:
@@ -2280,7 +2375,24 @@ static void gdth_next(int hanum)
                 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                        nscp->cmnd[4],nscp->cmnd[5]));
-                if (gdth_internal_cache_cmd(hanum,nscp)) {
+                if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) {
+                    /* return UNIT_ATTENTION */
+                    TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
+                             nscp->cmnd[0], t));
+                    ha->hdr[t].media_changed = FALSE;
+                    memset((char*)nscp->sense_buffer,0,16);
+                    nscp->sense_buffer[0] = 0x70;
+                    nscp->sense_buffer[2] = UNIT_ATTENTION;
+                    nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
+                        nscp->scsi_done(nscp);
+                        GDTH_LOCK_HA(ha,flags);
+                    }
+               } else if (gdth_internal_cache_cmd(hanum,nscp)) {
                     GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */      
                     nscp->scsi_done(nscp);
@@ -2325,7 +2437,24 @@ static void gdth_next(int hanum)
               case WRITE_6:
               case READ_10:
               case WRITE_10:
-                if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+                if (ha->hdr[t].media_changed) {
+                    /* return UNIT_ATTENTION */
+                    TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
+                             nscp->cmnd[0], t));
+                    ha->hdr[t].media_changed = FALSE;
+                    memset((char*)nscp->sense_buffer,0,16);
+                    nscp->sense_buffer[0] = 0x70;
+                    nscp->sense_buffer[2] = UNIT_ATTENTION;
+                    nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+                    if (!nscp->SCp.have_data_in)
+                        nscp->SCp.have_data_in++;
+                    else {
+                        GDTH_UNLOCK_HA(ha,flags);
+                        /* io_request_lock already active ! */      
+                        nscp->scsi_done(nscp);
+                        GDTH_LOCK_HA(ha,flags);
+                    }
+               } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
                     this_cmd = FALSE;
                 break;
 
@@ -2471,6 +2600,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
         TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
         break;
     }
+
     scp->result = DID_OK << 16;
     scp->sense_buffer[0] = 0;
 
@@ -2487,7 +2617,8 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
-    ushort i;
+    ushort i, cnt;
+    ulong32 no;
     int cmd_index, read_write;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -2543,11 +2674,13 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
 
     if (read_write) {
         if (scp->cmd_len != 6) {
-            cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]);
-            cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]);
+            memcpy(&no, &scp->cmnd[2], sizeof(ulong32));
+            cmdp->u.cache.BlockNo = ntohl(no);
+            memcpy(&cnt, &scp->cmnd[7], sizeof(ushort));
+            cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt);
         } else {
-            cmdp->u.cache.BlockNo = 
-                ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL;
+            memcpy(&no, &scp->cmnd[0], sizeof(ulong32));
+            cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL;
             cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
         }
 
@@ -2660,7 +2793,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
         cmdp->u.raw.lun        = l;
         cmdp->u.raw.bus        = b;
         cmdp->u.raw.priority   = 0;
-        cmdp->u.raw.link_p     = NULL;
+        cmdp->u.raw.link_p     = 0;
         cmdp->u.raw.sdlen      = scp->request_bufflen;
         cmdp->u.raw.sense_len  = 16;
         cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
@@ -2825,6 +2958,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
         e->first_stamp = e->last_stamp = tv.tv_sec;
         e->same_count = 1;
         e->event_data = *evt;
+        e->application = 0;
     }
     return e;
 }
@@ -3195,36 +3329,28 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                     if (!(ha->hdr[scp->target].cluster_type & 
                         CLUSTER_MOUNTED)) {
                         /* NOT MOUNTED -> MOUNT */
-                        if (!(ha->hdr[scp->target].cluster_type & 
-                            CLUSTER_RESERVED)) {
-                            /* cluster drive NOT RESERVED */
-                            scp->SCp.Status = GDT_MOUNT;
-                        } else {
+                        scp->SCp.Status = GDT_MOUNT;
+                        if (ha->hdr[scp->target].cluster_type & 
+                            CLUSTER_RESERVED) {
                             /* cluster drive RESERVED (on the other node) */
-                            scp->SCp.Status = GDT_MOUNT;
                             scp->SCp.phase = -2;      /* reservation conflict */
                         }
                     } else {
                         scp->SCp.Status = -1;
                     }
-                    /* retry */
-                    scp->SCp.this_residual = HIGH_PRI;
-                    return 2;
-                } else if (scp->SCp.Status == GDT_MOUNT) {
-                    ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED;
+               } else {
+                    if (scp->SCp.Status == GDT_MOUNT) {
+                        ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED;
+                        ha->hdr[scp->target].media_changed = TRUE;
+                    } else if (scp->SCp.Status == GDT_UNMOUNT) {
+                        ha->hdr[scp->target].cluster_type &= ~CLUSTER_MOUNTED;
+                        ha->hdr[scp->target].media_changed = TRUE;
+                    } 
                     scp->SCp.Status = -1;
-                    /* return UNIT_ATTENTION */
-                    memset((char*)scp->sense_buffer,0,16);
-                    scp->sense_buffer[0] = 0x70;
-                    scp->sense_buffer[2] = UNIT_ATTENTION;
-                    scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-                    scp->SCp.Message = (int)(ha->info<<16|S_BSY);
-                } else {
-                    scp->SCp.Status = -1;
-                    /* retry */
-                    scp->SCp.this_residual = HIGH_PRI;
-                    return 2;
                 }
+                /* retry */
+                scp->SCp.this_residual = HIGH_PRI;
+                return 2;
             } else {
                 /* RESERVE/RELEASE ? */
                 if (scp->cmnd[0] == RESERVE) {
@@ -3259,12 +3385,6 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                 scp->sense_buffer[0] = 0x70;
                 scp->sense_buffer[2] = NOT_READY;
                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
-            } else if (scp->cmnd[0] == RESERVE ||
-                       scp->cmnd[0] == RELEASE) {
-                memset((char*)scp->sense_buffer,0,16);
-                scp->sense_buffer[0] = 0x70;
-                scp->sense_buffer[2] = NOT_READY;
-                scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
             } else if (service == CACHESERVICE) {
                 if (ha->status == S_CACHE_UNKNOWN &&
                     (ha->hdr[scp->target].cluster_type & 
@@ -3293,7 +3413,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                 }
             } else {
                 /* sense buffer filled from controller firmware (DMA) */
-                if (ha->status!=S_RAW_SCSI || ha->info>=0x100) {
+                if (ha->status != S_RAW_SCSI || ha->info >= 0x100) {
                     scp->result = DID_BAD_TARGET << 16;
                 } else {
                     scp->result = (DID_OK << 16) | ha->info;
@@ -4467,8 +4587,12 @@ GDTH_INITFUNC(void, gdth_setup(char *str,int *ints))
     }
 }
 
-
+#if LINUX_VERSION_CODE < 0x020400
 #ifdef MODULE
 Scsi_Host_Template driver_template = GDTH;
 #include "scsi_module.c"
 #endif
+#else
+Scsi_Host_Template driver_template = GDTH;
+#include "scsi_module.c"
+#endif
index df26a9be8476d842bb212d35b8195730cc3b136f..b8dc32909c58a138673c6c3ba24ac0a867ae1ec4 100644 (file)
@@ -10,7 +10,7 @@
  *
  * <achim@vortex.de>
  *
- * $Id: gdth.h,v 1.33 2000/07/24 09:29:25 achim Exp $
+ * $Id: gdth.h,v 1.35 2000/10/11 08:42:38 achim Exp $
  */
 
 #include <linux/version.h>
@@ -29,9 +29,9 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "1.23"
+#define GDTH_VERSION_STR        "1.25"
 #define GDTH_VERSION            1
-#define GDTH_SUBVERSION         23
+#define GDTH_SUBVERSION         25
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
@@ -625,7 +625,7 @@ typedef struct {
             unchar      priority;               /* only 0 used */
             ulong32     sense_len;              /* sense data length */
             ulong32     sense_data;             /* sense data addr. */
-            struct raw  *link_p;                /* linked cmds (not supp.) */
+            ulong32     link_p;                 /* linked cmds (not supp.) */
             ulong32     sg_ranz;                /* s/g element count */
             gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
         } PACKED raw;                           /* raw service cmd. struct. */
@@ -877,7 +877,7 @@ typedef struct {
     Scsi_Cmnd           *req_first;             /* top of request queue */
     struct {
         unchar          present;                /* Flag: host drive present? */
-        unchar          is_logdrv;              /* Flag: logical drive (master)? */
+        unchar          is_logdrv;              /* Flag: log. drive (master)? */
         unchar          is_arraydrv;            /* Flag: array drive? */
         unchar          is_master;              /* Flag: array drive master? */
         unchar          is_parity;              /* Flag: parity drive? */
@@ -891,7 +891,7 @@ typedef struct {
         unchar          ldr_no;                 /* log. drive no. */
         unchar          rw_attribs;             /* r/w attributes */
         unchar          cluster_type;           /* cluster properties */
-        unchar          reserved;
+        unchar          media_changed;          /* Flag:MOUNT/UNMOUNT occured */
         ulong32         start_sec;              /* start sector */
     } hdr[MAX_LDRIVES];                         /* host drives */
     struct {
index 34715246fbb1c3c298f32c4dc11bc226d12c1b19..de435c409a166f51d71b324bcc47de240a970619 100644 (file)
@@ -2,7 +2,7 @@
 #define _GDTH_IOCTL_H
 
 /* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.6 2000/07/24 09:29:43 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.7 2000/10/11 08:43:35 achim Exp $
  */
 
 /* IOCTLs */
@@ -19,6 +19,7 @@
 #define GDTIOCTL_SCSI       (GDTIOCTL_MASK | 9) /* SCSI command */
 #define GDTIOCTL_RESET_BUS  (GDTIOCTL_MASK |10) /* reset SCSI bus */
 #define GDTIOCTL_RESCAN     (GDTIOCTL_MASK |11) /* rescan host drives */
+#define GDTIOCTL_RESET_DRV  (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */
 
 #define GDTIOCTL_MAGIC      0xaffe0003UL
 #define EVENT_SIZE          294 
index dbbb435130505c4929134186ac2473b92fab4d37..4d561228188ae83900ed9fca2d7c0dba0faaf3c7 100644 (file)
@@ -1,5 +1,5 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.22 2000/07/24 09:30:28 achim Exp $
+ * $Id: gdth_proc.c,v 1.23 2000/10/11 08:43:11 achim Exp $
  */
 
 #include "gdth_ioctl.h"
@@ -526,6 +526,30 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
         GDTH_UNLOCK_HA(ha, flags);
         break;
 
+      case GDTIOCTL_RESET_DRV:
+        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
+            return(-EBUSY);
+        piord = (gdth_iord_str *)ha->pscratch;
+        piord->size = sizeof(gdth_iord_str);
+        piord->status = S_OK;
+        i = piowr->iu.scsi.target;
+        if (ha->hdr[i].present) {
+            gdtcmd.BoardNode = LOCALBOARD;
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_CLUST_RESET;
+            gdtcmd.u.cache.DeviceNo = i;
+            gdtcmd.u.cache.BlockNo = 0;
+            gdtcmd.u.cache.sg_canz = 0;
+#if LINUX_VERSION_CODE >= 0x020322
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            piord->status = (ulong32)scp->SCp.Message;
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            piord->status = (ulong32)scp.SCp.Message;
+#endif
+        }
+        break;
+
       default:
         return(-EINVAL);
     }
index 793875190f7822a85b41741478863b56ee3b9117..72407ccad6a7da1aa40fb50ff4b9f84ceb6423e4 100644 (file)
@@ -882,9 +882,8 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt)
        (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
       {
        int flags;
-       save_flags(flags);
        printk("Ux4F: abort while completed command pending\n");
-       restore_flags(flags);
+       save_flags(flags);
        cli();
        ultrastor_interrupt(0, NULL, NULL);
        restore_flags(flags);
index f4b5be5b5bdba3743c4a3416fe0d90d21d7730d4..bb857a41b22d19da288114e03c2ea4ed794c6047 100644 (file)
@@ -311,10 +311,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
   fi
   
   dep_tristate 'NM256AV/NM256ZX audio support' CONFIG_SOUND_NM256 $CONFIG_SOUND_OSS
-  dep_tristate 'Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS
-  if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then
-    dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
-  fi
+  dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
 
   # Additional low level drivers.
   
index c23c1d44259ce968e7b587b757ddce147f67a594..e8d1819a61e12440bd21879b64061722da56ba5a 100644 (file)
@@ -97,7 +97,7 @@ obj-$(CONFIG_SOUND_MAESTRO)   += maestro.o
 obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
 obj-$(CONFIG_SOUND_TRIDENT)     += trident.o ac97_codec.o
 obj-$(CONFIG_SOUND_VIA82CXXX)  += via82cxxx_audio.o ac97_codec.o
-obj-$(CONFIG_SOUND_YMFPCI)     += ymfpci.o ac97_codec.o
+obj-$(CONFIG_SOUND_YMFPCI)     += ymfpci.o ac97_codec.o uart401.o
 
 ifeq ($(CONFIG_SOUND_EMU10K1),y)
   obj-y                                += emu10k1/emu10k1.o
@@ -126,7 +126,6 @@ vidc_mod-objs       := vidc.o vidc_fill.o vidc_synth.o
 wavefront-objs  := wavfront.o wf_midi.o yss225.o
 nm256-objs     := nm256_audio.o ac97.o
 via82cxxx-objs  := via82cxxx_audio.o ac97.o
-ymfsb-objs     := ymf_sb.o ac97.o
 
 
 # Extract lists of the multi-part drivers.
@@ -218,9 +217,6 @@ nm256.o: $(nm256-objs)
 via82cxxx.o: $(via82cxxx-objs)
        $(LD) -r -o $@ $(via82cxxx-objs)
 
-ymfsb.o: $(ymfsb-objs)
-       $(LD) -r -o $@ $(ymfsb-objs)
-
 # Firmware files that need translation
 #
 # The translated files are protected by a file that keeps track
index 9385e53c0f6c65296e3bf908f2b18f064674c35b..5548786a28681eae3cd1d7991888edb408a12a0f 100644 (file)
@@ -784,10 +784,3 @@ static void __exit emu10k1_cleanup_module(void)
 
 module_init(emu10k1_init_module);
 module_exit(emu10k1_cleanup_module);
-
-#ifndef MODULE
-int __init init_emu10k1(void)
-{
-        return emu10k1_init_module();
-}
-#endif
index 43bea56d3ee3aa1ea5f4a9fa590dfe1bc1db3354..394989b777fefa21e1024496a60e0218dde74179 100644 (file)
  *    03.09.1999   0.30  change read semantics for MIDI to match
  *                       OSS more closely; remove possible wakeup race
  *    28.10.1999   0.31  More waitqueue races fixed
+ *    08.01.2000   0.32  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    21.11.2000   0.34  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.35  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -858,7 +863,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
        VALIDATE_STATE(s);
        if (cmd == SOUND_MIXER_PRIVATE1) {
                /* enable/disable/query mixer preamp */
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != -1) {
                        s->mix.micpreamp = !!val;
                        wrcodec(s, 0x19, s->mix.micpreamp);
@@ -867,7 +873,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
        }
        if (cmd == SOUND_MIXER_PRIVATE2) {
                /* enable/disable/query use of linein as second lineout */
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != -1) {
                        spin_lock_irqsave(&s->lock, flags);
                        if (val)
@@ -881,7 +888,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
        }
        if (cmd == SOUND_MIXER_PRIVATE3) {
                /* enable/disable/query microphone impedance setting */
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != -1) {
                        spin_lock_irqsave(&s->lock, flags);
                        if (val)
@@ -957,12 +965,14 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
        switch (_IOC_NR(cmd)) {
 
        case SOUND_MIXER_IMIX:
-               get_user_ret(s->mix.imix, (int *)arg, -EFAULT);
+               if (get_user(s->mix.imix, (int *)arg))
+                       return -EFAULT;
                set_recsrc(s, s->mix.recsrc);
                return 0;
 
        case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                set_recsrc(s, val);
                return 0;
 
@@ -970,7 +980,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
                i = _IOC_NR(cmd);
                if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail)
                        return -EINVAL;
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                l = val & 0xff;
                if (l > 100)
                        l = 100;
@@ -1354,6 +1365,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+       int count;
        int val, mapped, ret;
 
        VALIDATE_STATE(s);
@@ -1388,7 +1400,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val >= 0) {
                        if (s->open_mode & (~file->f_mode) & (FMODE_READ|FMODE_WRITE))
                                return -EINVAL;
@@ -1407,7 +1420,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg);
                
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        stop_adc(s);
                        s->dma_adc.ready = 0;
@@ -1433,7 +1447,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 0) {
                        if (file->f_mode & FMODE_READ) {
                                stop_adc(s);
@@ -1464,7 +1479,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
                
        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != AFMT_QUERY) {
                        if (file->f_mode & FMODE_READ) {
                                stop_adc(s);
@@ -1504,7 +1520,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return put_user(val, (int *)arg);
                
        case SNDCTL_DSP_SETTRIGGER:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        if (val & PCM_ENABLE_INPUT) {
                                if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1526,12 +1543,15 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0)
+               if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                abinfo.fragsize = s->dma_dac2.fragsize;
-                abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count;
+               count = s->dma_dac2.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = s->dma_dac2.dmasize - count;
                 abinfo.fragstotal = s->dma_dac2.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1540,12 +1560,15 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0)
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+               count = s->dma_adc.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1558,19 +1581,28 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
-                val = s->dma_dac2.count;
+                count = s->dma_dac2.count;
                spin_unlock_irqrestore(&s->lock, flags);
-               return put_user(val, (int *)arg);
+               if (count < 0)
+                       count = 0;
+               return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+               count = s->dma_adc.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
                if (s->dma_adc.mapped)
                        s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1580,10 +1612,15 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
-                cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
+               count = s->dma_dac2.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_dac2.fragshift;
                 cinfo.ptr = s->dma_dac2.hwptr;
                if (s->dma_dac2.mapped)
                        s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -1601,7 +1638,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        s->dma_adc.ossfragshift = val & 0xffff;
                        s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1628,7 +1666,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
                    (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
                        return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 1 && val != 2 && val != 4)
                        return -EINVAL;
                if (file->f_mode & FMODE_READ)
@@ -1878,6 +1917,7 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
        unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+       int count;
        unsigned ctrl;
        int val, ret;
 
@@ -1902,7 +1942,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val >= 0) {
                        stop_dac1(s);
                        s->dma_dac1.ready = 0;
@@ -1917,7 +1958,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg);
                
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                stop_dac1(s);
                s->dma_dac1.ready = 0;
                spin_lock_irqsave(&s->lock, flags);
@@ -1930,7 +1972,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 0) {
                        if (s->dma_dac1.mapped)
                                return -EINVAL;
@@ -1950,7 +1993,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
                
         case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != AFMT_QUERY) {
                        stop_dac1(s);
                        s->dma_dac1.ready = 0;
@@ -1971,7 +2015,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
                                                
        case SNDCTL_DSP_SETTRIGGER:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val & PCM_ENABLE_OUTPUT) {
                        if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
                                return ret;
@@ -1981,12 +2026,15 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return 0;
 
        case SNDCTL_DSP_GETOSPACE:
-               if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0)
+               if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                abinfo.fragsize = s->dma_dac1.fragsize;
-                abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count;
+               count = s->dma_dac1.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = s->dma_dac1.dmasize - count;
                 abinfo.fragstotal = s->dma_dac1.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1997,19 +2045,26 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                 return 0;
 
         case SNDCTL_DSP_GETODELAY:
+               if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
-                val = s->dma_dac1.count;
+                count = s->dma_dac1.count;
                spin_unlock_irqrestore(&s->lock, flags);
-               return put_user(val, (int *)arg);
+               if (count < 0)
+                       count = 0;
+               return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETOPTR:
-               if (!(file->f_mode & FMODE_WRITE))
-                       return -EINVAL;
+               if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac1.total_bytes;
-                cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
+               count = s->dma_dac1.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_dac1.fragshift;
                 cinfo.ptr = s->dma_dac1.hwptr;
                if (s->dma_dac1.mapped)
                        s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -2022,7 +2077,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                 return put_user(s->dma_dac1.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                s->dma_dac1.ossfragshift = val & 0xffff;
                s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
                if (s->dma_dac1.ossfragshift < 4)
@@ -2036,7 +2092,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
         case SNDCTL_DSP_SUBDIVIDE:
                if (s->dma_dac1.subdivision)
                        return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 1 && val != 2 && val != 4)
                        return -EINVAL;
                s->dma_dac1.subdivision = val;
@@ -2463,7 +2520,7 @@ __initfunc(int init_es1370(void))
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "es1370: version v0.35 time " __TIME__ " " __DATE__ "\n");
        while (index < NR_DEVICE && 
               (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
                if (pcidev->base_address[0] == 0 || 
index edc376a0df7271c74e72822d764337e3d43d595e..72276e623a5d603715bc8df255a1817ab7e61cbc 100644 (file)
  *                       detect ES137x chip and derivatives.
  *    05.01.2000   0.22  Should now work with rev7 boards; patch by
  *                       Eric Lemar, elemar@cs.washington.edu
+ *    08.01.2000   0.23  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    01.03.2000   0.26  SPDIF patch by Mikael Bouillot <mikael.bouillot@bigfoot.com>
+ *    21.11.2000   0.27  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.28  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  */
 
 /*****************************************************************************/
@@ -1937,6 +1943,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+       int count;
        int val, mapped, ret;
 
        VALIDATE_STATE(s);
@@ -1971,7 +1978,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val >= 0) {
                        if (file->f_mode & FMODE_READ) {
                                stop_adc(s);
@@ -1987,7 +1995,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
 
         case SNDCTL_DSP_STEREO:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        stop_adc(s);
                        s->dma_adc.ready = 0;
@@ -2013,7 +2022,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 0) {
                        if (file->f_mode & FMODE_READ) {
                                stop_adc(s);
@@ -2044,7 +2054,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
                
        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != AFMT_QUERY) {
                        if (file->f_mode & FMODE_READ) {
                                stop_adc(s);
@@ -2084,7 +2095,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return put_user(val, (int *)arg);
                
        case SNDCTL_DSP_SETTRIGGER:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        if (val & PCM_ENABLE_INPUT) {
                                if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -2106,12 +2118,15 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0)
+               if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                abinfo.fragsize = s->dma_dac2.fragsize;
-                abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count;
+               count = s->dma_dac2.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = s->dma_dac2.dmasize - count;
                 abinfo.fragstotal = s->dma_dac2.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -2120,12 +2135,15 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0)
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+               count = s->dma_adc.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -2138,19 +2156,28 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
-                val = s->dma_dac2.count;
+                count = s->dma_dac2.count;
                spin_unlock_irqrestore(&s->lock, flags);
-               return put_user(val, (int *)arg);
+               if (count < 0)
+                       count = 0;
+               return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+               count = s->dma_adc.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
                if (s->dma_adc.mapped)
                        s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -2160,10 +2187,15 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
-                cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
+               count = s->dma_dac2.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_dac2.fragshift;
                 cinfo.ptr = s->dma_dac2.hwptr;
                if (s->dma_dac2.mapped)
                        s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -2181,7 +2213,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        s->dma_adc.ossfragshift = val & 0xffff;
                        s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -2208,7 +2241,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
                    (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision))
                        return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 1 && val != 2 && val != 4)
                        return -EINVAL;
                if (file->f_mode & FMODE_READ)
@@ -2458,6 +2492,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
        unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+       int count;
        int val, ret;
 
        VALIDATE_STATE(s);
@@ -2481,7 +2516,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val >= 0) {
                        stop_dac1(s);
                        s->dma_dac1.ready = 0;
@@ -2490,7 +2526,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return put_user(s->dac1rate, (int *)arg);
 
         case SNDCTL_DSP_STEREO:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                stop_dac1(s);
                s->dma_dac1.ready = 0;
                spin_lock_irqsave(&s->lock, flags);
@@ -2503,7 +2540,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 0) {
                        stop_dac1(s);
                        s->dma_dac1.ready = 0;
@@ -2521,7 +2559,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
                
         case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != AFMT_QUERY) {
                        stop_dac1(s);
                        s->dma_dac1.ready = 0;
@@ -2542,7 +2581,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg);
                                                
        case SNDCTL_DSP_SETTRIGGER:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val & PCM_ENABLE_OUTPUT) {
                        if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s)))
                                return ret;
@@ -2552,12 +2592,15 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                return 0;
 
        case SNDCTL_DSP_GETOSPACE:
-               if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0)
+               if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                abinfo.fragsize = s->dma_dac1.fragsize;
-                abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count;
+               count = s->dma_dac1.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = s->dma_dac1.dmasize - count;
                 abinfo.fragstotal = s->dma_dac1.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -2568,19 +2611,26 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                 return 0;
 
         case SNDCTL_DSP_GETODELAY:
+               if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
-                val = s->dma_dac1.count;
+                count = s->dma_dac1.count;
                spin_unlock_irqrestore(&s->lock, flags);
-               return put_user(val, (int *)arg);
+               if (count < 0)
+                       count = 0;
+               return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETOPTR:
-               if (!(file->f_mode & FMODE_WRITE))
-                       return -EINVAL;
+               if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac1.total_bytes;
-                cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
+               count = s->dma_dac1.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_dac1.fragshift;
                 cinfo.ptr = s->dma_dac1.hwptr;
                if (s->dma_dac1.mapped)
                        s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -2593,7 +2643,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
                 return put_user(s->dma_dac1.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                s->dma_dac1.ossfragshift = val & 0xffff;
                s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff;
                if (s->dma_dac1.ossfragshift < 4)
@@ -2607,7 +2658,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
         case SNDCTL_DSP_SUBDIVIDE:
                if (s->dma_dac1.subdivision)
                        return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 1 && val != 2 && val != 4)
                        return -EINVAL;
                s->dma_dac1.subdivision = val;
@@ -3261,7 +3313,7 @@ __initfunc(int init_es1371(void))
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "es1371: version v0.28 time " __TIME__ " " __DATE__ "\n");
        for (pcidev = pci_devices; pcidev && index < NR_DEVICE; pcidev = pcidev->next) {
                if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
                        if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
index 1493738cad805186cd0bab4fb1bbec0ba0512532..ef470141a2d48e642dbfa1975f7619755eb3cd04 100644 (file)
  *    28.10.1999   0.10  More waitqueue races fixed
  *    09.12.1999   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
  *                       Disabling recording on Alpha
- *
+ *    12.01.2000   0.12  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *                       Integrated (aka redid 8-)) APM support patch by Zach Brown
+ *    21.11.2000   0.16  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.17  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  */
 
 /*****************************************************************************/
@@ -1276,7 +1281,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val >= 0) {
                        stop_adc(s);
                        stop_dac(s);
@@ -1303,7 +1309,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                return put_user(s->rate, (int *)arg);
                
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                stop_adc(s);
                stop_dac(s);
                s->dma_adc.ready = s->dma_dac.ready = 0;
@@ -1313,7 +1320,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 0) {
                        stop_adc(s);
                        stop_dac(s);
@@ -1328,7 +1336,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                 return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
 
        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != AFMT_QUERY) {
                        stop_adc(s);
                        stop_dac(s);
@@ -1354,7 +1363,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                return put_user(val, (int *)arg);
 
        case SNDCTL_DSP_SETTRIGGER:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        if (val & PCM_ENABLE_INPUT) {
                                if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
@@ -1378,7 +1388,7 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0)
+               if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
@@ -1395,7 +1405,7 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0)
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
@@ -1413,6 +1423,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                 count = s->dma_dac.count;
@@ -1424,13 +1436,12 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-               count = s->dma_dac.count;
-               if (count < 0)
-                       count = 0;
-               cinfo.blocks = count >> s->dma_dac.fragshift;
+                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
                if (s->dma_adc.mapped)
                        s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1440,10 +1451,15 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                solo1_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
-                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+               count = s->dma_dac.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_dac.hwptr;
                if (s->dma_dac.mapped)
                        s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -1467,7 +1483,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        s->dma_adc.ossfragshift = val & 0xffff;
                        s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1494,7 +1511,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
                    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
                        return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 1 && val != 2 && val != 4)
                        return -EINVAL;
                if (file->f_mode & FMODE_READ)
@@ -2170,7 +2188,7 @@ static struct initvol {
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "solo1: version v0.17 time " __TIME__ " " __DATE__ "\n");
        while (index < NR_DEVICE && 
               (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
                if (pcidev->base_address[0] == 0 ||
index 03ad29b9488571541fc90a1e1cf3898f0f9bf633..88ffcf29c1ea5094e408ad6502227a36c966a085 100644 (file)
  *    24.08.1999   0.19  get rid of the dmaio kludge, replace with allocate_resource
  *    31.08.1999   0.20  add spin_lock_init
  *                       __initlocaldata to fix gcc 2.7.x problems
- *                       use new resource allocation to allocate DDMA IO space
  *                       replaced current->state = x with set_current_state(x)
  *    03.09.1999   0.21  change read semantics for MIDI to match
  *                       OSS more closely; remove possible wakeup race
  *    28.10.1999   0.22  More waitqueue races fixed
+ *    08.01.2000   0.25  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    21.11.2000   0.27  Initialize dma buffers in poll, otherwise poll may return a bogus mask
+ *    12.12.2000   0.28  More dma buffer initializations, patch from
+ *                       Tjeerd Mulder <tjeerd.mulder@fujitsu-siemens.com>
  *
  */
 
@@ -1543,6 +1547,7 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+       int count;
        int val, mapped, ret;
        unsigned char fmtm, fmtd;
 
@@ -1578,7 +1583,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                return 0;
 
         case SNDCTL_DSP_SPEED:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val >= 0) {
                        if (file->f_mode & FMODE_READ) {
                                stop_adc(s);
@@ -1594,7 +1600,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
                
         case SNDCTL_DSP_STEREO:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                fmtd = 0;
                fmtm = ~0;
                if (file->f_mode & FMODE_READ) {
@@ -1617,7 +1624,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                return 0;
 
         case SNDCTL_DSP_CHANNELS:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 0) {
                        fmtd = 0;
                        fmtm = ~0;
@@ -1646,7 +1654,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                 return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);
                
        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != AFMT_QUERY) {
                        fmtd = 0;
                        fmtm = ~0;
@@ -1683,7 +1692,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                return put_user(val, (int *)arg);
                
        case SNDCTL_DSP_SETTRIGGER:
-               get_user_ret(val, (int *)arg, -EFAULT);
+               if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        if (val & PCM_ENABLE_INPUT) {
                                if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
@@ -1705,12 +1715,15 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        case SNDCTL_DSP_GETOSPACE:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
-               if (!(s->enable & SV_CENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
+               if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                abinfo.fragsize = s->dma_dac.fragsize;
-                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+               count = s->dma_dac.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = s->dma_dac.dmasize - count;
                 abinfo.fragstotal = s->dma_dac.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1719,12 +1732,15 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        case SNDCTL_DSP_GETISPACE:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
-               if (!(s->enable & SV_CENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
+               if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0)
                        return val;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+               count = s->dma_adc.count;
+               if (count < 0)
+                       count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
                spin_unlock_irqrestore(&s->lock, flags);
@@ -1737,19 +1753,28 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETODELAY:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
-                val = s->dma_dac.count;
+                count = s->dma_dac.count;
                spin_unlock_irqrestore(&s->lock, flags);
-               return put_user(val, (int *)arg);
+               if (count < 0)
+                       count = 0;
+               return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
                if (!(file->f_mode & FMODE_READ))
                        return -EINVAL;
+               if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+               count = s->dma_adc.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
                if (s->dma_adc.mapped)
                        s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1759,10 +1784,15 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
         case SNDCTL_DSP_GETOPTR:
                if (!(file->f_mode & FMODE_WRITE))
                        return -EINVAL;
+               if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0)
+                       return val;
                spin_lock_irqsave(&s->lock, flags);
                sv_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
-                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+               count = s->dma_dac.count;
+               if (count < 0)
+                       count = 0;
+                cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_dac.hwptr;
                if (s->dma_dac.mapped)
                        s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -1780,7 +1810,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                return put_user(s->dma_adc.fragsize, (int *)arg);
 
         case SNDCTL_DSP_SETFRAGMENT:
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (file->f_mode & FMODE_READ) {
                        s->dma_adc.ossfragshift = val & 0xffff;
                        s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
@@ -1807,7 +1838,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
                if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
                    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
                        return -EINVAL;
-                get_user_ret(val, (int *)arg, -EFAULT);
+                if (get_user(val, (int *)arg))
+                       return -EFAULT;
                if (val != 1 && val != 2 && val != 4)
                        return -EINVAL;
                if (file->f_mode & FMODE_READ)
@@ -2432,7 +2464,7 @@ __initfunc(int init_sonicvibes(void))
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "sv: version v0.28 time " __TIME__ " " __DATE__ "\n");
 #if 0
        if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
                printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
index 3b5c85680585e326856f2e18797a1913283c087d..daed78412ce481cf784b76ac5130859f55bd7198 100644 (file)
@@ -63,7 +63,6 @@ extern int msnd_pinnacle_init(void);
 extern int init_solo1(void);
 extern int init_ymf7xxsb_module(void);
 extern int cs_probe(void);
-extern int init_emu10k1(void);
 extern int cs4281_probe(void);
 extern void init_vwsnd(void);
 extern int ymf_probe(void);
@@ -435,9 +434,6 @@ int soundcore_init(void)
 #ifdef CONFIG_SOUND_CS4281
        cs4281_probe();
 #endif
-#ifdef CONFIG_SOUND_EMU10K1
-       init_emu10k1();
-#endif
 #ifdef CONFIG_SOUND_YMFPCI
        ymf_probe();
 #endif
diff --git a/drivers/sound/ymf_sb.c b/drivers/sound/ymf_sb.c
deleted file mode 100644 (file)
index 2af3819..0000000
+++ /dev/null
@@ -1,995 +0,0 @@
-/*
-  Legacy audio driver for YMF724, 740, 744, 754 series.
-  Copyright 2000 Daisuke Nagano <breeze.nagano@nifty.ne.jp>
-
-  Based on the VIA 82Cxxx driver by Jeff Garzik <jgarzik@pobox.com>
-
-  Distribued under the GNU PUBLIC LICENSE (GPL) Version 2.
-  See the "COPYING" file distributed with kernel source tree for more info.
-
-  -------------------------------------------------------------------------
-
-  It only supports SBPro compatible function of YMF7xx series s.t.
-    * 22.05kHz, 8-bit and stereo sample
-    * OPL3-compatible FM synthesizer
-    * MPU-401 compatible "external" MIDI interface
-
-  and AC'97 mixer of these cards.
-
-  -------------------------------------------------------------------------
-
-  Revision history
-
-   Tue May 14 19:00:00 2000   0.0.1
-   * initial release
-
-   Tue May 16 19:29:29 2000   0.0.2
-
-   * add a little delays for reset devices.
-   * fixed addressing bug.
-
-   Sun May 21 15:14:37 2000   0.0.3
-
-   * Add 'master_vol' module parameter to change 'PCM out Vol' of AC'97.
-   * remove native UART401 support. External MIDI port should be supported 
-     by sb_midi driver.
-   * add support for SPDIF OUT. Module parameter 'spdif_out' is now available.
-
-   Wed May 31 00:13:57 2000   0.0.4
-
-   * remove entries in Hwmcode.h. Now YMF744 / YMF754 sets instructions 
-     in 724hwmcode.h.
-   * fixed wrong legacy_io setting on YMF744/YMF754 .
-
-   Sat Jun  3 23:44:08 2000   0.0.5
-
-   * correct all return value -1 to appropriate -E* value.
-   * add pci_enable_device() for linux-2.3.x.
-
-   Sat Jun  7 00:17:32 2000   0.1.0
-
-   * Remove SBPro mixer support.
-   * Added AC'97 mixer support and remove option 'master_volume'.
-   * Correct all separated valuables into struct ymf_cards.
-
-   Mon Jun 12 21:36:50 2000   0.1.1
-
-   * Invalid dma setting fixed.
-     -- John A. Boyd Jr. <jaboydjr@netwalk.com>
-
-   * ymfsb only compiled as module: fixed
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/version.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-#include "soundmodule.h"
-#include "sb.h"
-#include "724hwmcode.h"
-
-#include "ac97.h"
-
-#undef YMF_DEBUG
-
-/* ---------------------------------------------------------------------- */
-
-#ifndef SOUND_LOCK
-# define SOUND_LOCK do {} while (0)
-# define SOUND_LOCK_END do {} while (0)
-#endif
-
-#ifndef PCI_VENDOR_ID_YAMAHA
-# define PCI_VENDOR_ID_YAMAHA  0x1073
-#endif
-#ifndef PCI_DEVICE_ID_YMF724
-# define PCI_DEVICE_ID_YMF724  0x0004
-#endif
-#ifndef PCI_DEVICE_ID_YMF740
-# define PCI_DEVICE_ID_YMF740  0x000A
-#endif
-#ifndef PCI_DEVICE_ID_YMF740C
-# define PCI_DEVICE_ID_YMF740C 0x000C
-#endif
-#ifndef PCI_DEVICE_ID_YMF724F
-# define PCI_DEVICE_ID_YMF724F 0x000D
-#endif
-#ifndef PCI_DEVICE_ID_YMF744
-# define PCI_DEVICE_ID_YMF744  0x0010
-#endif
-#ifndef PCI_DEVICE_ID_YMF754
-# define PCI_DEVICE_ID_YMF754  0x0012
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-#define YMFSB_RESET_DELAY               5
-
-#define YMFSB_REGSIZE                   0x8000
-
-#define YMFSB_AC97TIMEOUT               2000
-
-#define        YMFSB_WORKBITTIMEOUT            250000
-
-#define        YMFSB_DSPLENGTH                 0x0080
-#define        YMFSB_CTRLLENGTH                0x3000
-
-#define YMFSB_PCIR_VENDORID             0x00
-#define YMFSB_PCIR_DEVICEID             0x02
-#define YMFSB_PCIR_CMD                  0x04
-#define YMFSB_PCIR_REVISIONID           0x08
-#define YMFSB_PCIR_BASEADDR             0x10
-#define YMFSB_PCIR_IRQ                  0x3c
-
-#define        YMFSB_PCIR_LEGCTRL              0x40
-#define        YMFSB_PCIR_ELEGCTRL             0x42
-#define        YMFSB_PCIR_DSXGCTRL             0x48
-#define YMFSB_PCIR_OPLADR               0x60
-#define YMFSB_PCIR_SBADR                0x62
-#define YMFSB_PCIR_MPUADR               0x64
-
-#define        YMFSB_INTFLAG                   0x0004
-#define        YMFSB_ACTIVITY                  0x0006
-#define        YMFSB_GLOBALCTRL                0x0008
-#define        YMFSB_ZVCTRL                    0x000A
-#define        YMFSB_TIMERCTRL                 0x0010
-#define        YMFSB_TIMERCOUNT                0x0012
-#define        YMFSB_SPDIFOUTCTRL              0x0018
-#define        YMFSB_SPDIFOUTSTATUS            0x001C
-#define        YMFSB_EEPROMCTRL                0x0020
-#define        YMFSB_SPDIFINCTRL               0x0034
-#define        YMFSB_SPDIFINSTATUS             0x0038
-#define        YMFSB_DSPPROGRAMDL              0x0048
-#define        YMFSB_DLCNTRL                   0x004C
-#define        YMFSB_GPIOININTFLAG             0x0050
-#define        YMFSB_GPIOININTENABLE           0x0052
-#define        YMFSB_GPIOINSTATUS              0x0054
-#define        YMFSB_GPIOOUTCTRL               0x0056
-#define        YMFSB_GPIOFUNCENABLE            0x0058
-#define        YMFSB_GPIOTYPECONFIG            0x005A
-#define        YMFSB_AC97CMDDATA               0x0060
-#define        YMFSB_AC97CMDADR                0x0062
-#define        YMFSB_PRISTATUSDATA             0x0064
-#define        YMFSB_PRISTATUSADR              0x0066
-#define        YMFSB_SECSTATUSDATA             0x0068
-#define        YMFSB_SECSTATUSADR              0x006A
-#define        YMFSB_SECCONFIG                 0x0070
-#define        YMFSB_LEGACYOUTVOL              0x0080
-#define        YMFSB_LEGACYOUTVOLL             0x0080
-#define        YMFSB_LEGACYOUTVOLR             0x0082
-#define        YMFSB_NATIVEDACOUTVOL           0x0084
-#define        YMFSB_NATIVEDACOUTVOLL          0x0084
-#define        YMFSB_NATIVEDACOUTVOLR          0x0086
-#define        YMFSB_SPDIFOUTVOL               0x0088
-#define        YMFSB_SPDIFOUTVOLL              0x0088
-#define        YMFSB_SPDIFOUTVOLR              0x008A
-#define        YMFSB_AC3OUTVOL                 0x008C
-#define        YMFSB_AC3OUTVOLL                0x008C
-#define        YMFSB_AC3OUTVOLR                0x008E
-#define        YMFSB_PRIADCOUTVOL              0x0090
-#define        YMFSB_PRIADCOUTVOLL             0x0090
-#define        YMFSB_PRIADCOUTVOLR             0x0092
-#define        YMFSB_LEGACYLOOPVOL             0x0094
-#define        YMFSB_LEGACYLOOPVOLL            0x0094
-#define        YMFSB_LEGACYLOOPVOLR            0x0096
-#define        YMFSB_NATIVEDACLOOPVOL          0x0098
-#define        YMFSB_NATIVEDACLOOPVOLL         0x0098
-#define        YMFSB_NATIVEDACLOOPVOLR         0x009A
-#define        YMFSB_SPDIFLOOPVOL              0x009C
-#define        YMFSB_SPDIFLOOPVOLL             0x009E
-#define        YMFSB_SPDIFLOOPVOLR             0x009E
-#define        YMFSB_AC3LOOPVOL                0x00A0
-#define        YMFSB_AC3LOOPVOLL               0x00A0
-#define        YMFSB_AC3LOOPVOLR               0x00A2
-#define        YMFSB_PRIADCLOOPVOL             0x00A4
-#define        YMFSB_PRIADCLOOPVOLL            0x00A4
-#define        YMFSB_PRIADCLOOPVOLR            0x00A6
-#define        YMFSB_NATIVEADCINVOL            0x00A8
-#define        YMFSB_NATIVEADCINVOLL           0x00A8
-#define        YMFSB_NATIVEADCINVOLR           0x00AA
-#define        YMFSB_NATIVEDACINVOL            0x00AC
-#define        YMFSB_NATIVEDACINVOLL           0x00AC
-#define        YMFSB_NATIVEDACINVOLR           0x00AE
-#define        YMFSB_BUF441OUTVOL              0x00B0
-#define        YMFSB_BUF441OUTVOLL             0x00B0
-#define        YMFSB_BUF441OUTVOLR             0x00B2
-#define        YMFSB_BUF441LOOPVOL             0x00B4
-#define        YMFSB_BUF441LOOPVOLL            0x00B4
-#define        YMFSB_BUF441LOOPVOLR            0x00B6
-#define        YMFSB_SPDIFOUTVOL2              0x00B8
-#define        YMFSB_SPDIFOUTVOL2L             0x00B8
-#define        YMFSB_SPDIFOUTVOL2R             0x00BA
-#define        YMFSB_SPDIFLOOPVOL2             0x00BC
-#define        YMFSB_SPDIFLOOPVOL2L            0x00BC
-#define        YMFSB_SPDIFLOOPVOL2R            0x00BE
-#define        YMFSB_ADCSLOTSR                 0x00C0
-#define        YMFSB_RECSLOTSR                 0x00C4
-#define        YMFSB_ADCFORMAT                 0x00C8
-#define        YMFSB_RECFORMAT                 0x00CC
-#define        YMFSB_P44SLOTSR                 0x00D0
-#define        YMFSB_STATUS                    0x0100
-#define        YMFSB_CTRLSELECT                0x0104
-#define        YMFSB_MODE                      0x0108
-#define        YMFSB_SAMPLECOUNT               0x010C
-#define        YMFSB_NUMOFSAMPLES              0x0110
-#define        YMFSB_CONFIG                    0x0114
-#define        YMFSB_PLAYCTRLSIZE              0x0140
-#define        YMFSB_RECCTRLSIZE               0x0144
-#define        YMFSB_EFFCTRLSIZE               0x0148
-#define        YMFSB_WORKSIZE                  0x014C
-#define        YMFSB_MAPOFREC                  0x0150
-#define        YMFSB_MAPOFEFFECT               0x0154
-#define        YMFSB_PLAYCTRLBASE              0x0158
-#define        YMFSB_RECCTRLBASE               0x015C
-#define        YMFSB_EFFCTRLBASE               0x0160
-#define        YMFSB_WORKBASE                  0x0164
-#define        YMFSB_DSPINSTRAM                0x1000
-#define        YMFSB_CTRLINSTRAM               0x4000
-
-
-/* ---------------------------------------------------------------------- */
-
-#define MAX_CARDS      4
-
-#define PFX            "ymf_sb: "
-
-#define YMFSB_VERSION  "0.1.1"
-#define YMFSB_CARD_NAME        "YMF7xx Legacy Audio driver " YMFSB_VERSION
-
-#define ymf7xxsb_probe_midi probe_sbmpu
-#define ymf7xxsb_attach_midi attach_sbmpu
-#define ymf7xxsb_unload_midi unload_sbmpu
-
-/* ---------------------------------------------------------------------- */
-
-static struct ymf_card {
-  int                  card;
-  unsigned short      *ymfbase;
-
-  struct address_info sb_data, opl3_data, mpu_data;
-
-  struct ac97_hwint   ac97_dev;
-  int                 mixer_oss_dev;
-} ymf_cards[MAX_CARDS];
-
-static unsigned int cards = 0;
-
-/* ---------------------------------------------------------------------- */
-
-#ifdef MODULE
-static int mpu_io     = 0;
-static int synth_io   = 0;
-static int io         = 0;
-static int dma        = 0;
-static int spdif_out  = 1;
-MODULE_PARM(mpu_io, "i");
-MODULE_PARM(synth_io, "i");
-MODULE_PARM(io,"i");
-MODULE_PARM(dma,"i");
-MODULE_PARM(spdif_out,"i");
-#else
-static int mpu_io     = 0x330;
-static int synth_io   = 0x388;
-static int io         = 0x220;
-static int dma        = 1;
-static int spdif_out  = 1;
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-static int readRegWord( struct ymf_card *card, int adr ) {
-
-       if (card->ymfbase==NULL) return 0;
-
-       return readw(card->ymfbase+adr/2);
-}
-
-static void writeRegWord( struct ymf_card *card, int adr, int val ) {
-
-       if (card->ymfbase==NULL) return;
-
-       writew((unsigned short)(val&0xffff), card->ymfbase + adr/2);
-
-       return;
-}
-
-static int readRegDWord( struct ymf_card *card, int adr ) {
-
-       if (card->ymfbase==NULL) return 0;
-
-       return (readl(card->ymfbase+adr/2));
-}
-
-static void writeRegDWord( struct ymf_card *card, int adr, int val ) {
-
-       if (card->ymfbase==NULL) return;
-
-       writel((unsigned int)(val&0xffffffff), card->ymfbase+adr/2);
-
-       return;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int checkPrimaryBusy( struct ymf_card *card )
-{
-       int timeout=0;
-
-       while ( timeout++ < YMFSB_AC97TIMEOUT )
-       {
-               if ( (readRegWord(card, YMFSB_PRISTATUSADR) & 0x8000) == 0x0000 )
-                       return 0;
-       }
-       return -EBUSY;
-}
-
-static int checkCodec( struct ymf_card *card, struct pci_dev *pcidev )
-{
-       u8 tmp8;
-
-       pci_read_config_byte( pcidev, YMFSB_PCIR_DSXGCTRL, &tmp8 );
-       if ( tmp8 & 0x03 ) {
-               pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc);
-               mdelay(YMFSB_RESET_DELAY);
-               pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8|0x03);
-               mdelay(YMFSB_RESET_DELAY);
-               pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc);
-               mdelay(YMFSB_RESET_DELAY);
-       }
-
-       if ( checkPrimaryBusy( card ) ) return -EBUSY;
-
-       return 0;
-}
-
-static int setupLegacyIO( struct ymf_card *card, struct pci_dev *pcidev )
-{
-       int v;
-       int sbio=0, mpuio=0, oplio=0,dma=0;
-
-       switch(card->sb_data.io_base) {
-       case 0x220:
-               sbio = 0;
-               break;
-       case 0x240:
-               sbio = 1;
-               break;
-       case 0x260:
-               sbio = 2;
-               break;
-       case 0x280:
-               sbio = 3;
-               break;
-       default:
-               return -EINVAL;
-               break;
-       }
-#ifdef YMF_DEBUG
-       printk(PFX "set SBPro I/O at 0x%x\n",card->sb_data.io_base);
-#endif
-
-       switch(card->mpu_data.io_base) {
-       case 0x330:
-               mpuio = 0;
-               break;
-       case 0x300:
-               mpuio = 1;
-               break;
-       case 0x332:
-               mpuio = 2;
-               break;
-       case 0x334:
-               mpuio = 3;
-               break;
-       default:
-               mpuio = 0;
-               break;
-       }
-#ifdef YMF_DEBUG
-       printk(PFX "set MPU401 I/O at 0x%x\n",card->mpu_data.io_base);
-#endif
-
-       switch(card->opl3_data.io_base) {
-       case 0x388:
-               oplio = 0;
-               break;
-       case 0x398:
-               oplio = 1;
-               break;
-       case 0x3a0:
-               oplio = 2;
-               break;
-       case 0x3a8:
-               oplio = 3;
-               break;
-       default:
-               return -EINVAL;
-               break;
-       }
-#ifdef YMF_DEBUG
-       printk(PFX "set OPL3 I/O at 0x%x\n",card->opl3_data.io_base);
-#endif
-
-       dma = card->sb_data.dma;
-#ifdef YMF_DEBUG
-       printk(PFX "set DMA address at 0x%x\n",card->sb_data.dma);
-#endif
-
-       v = 0x0000 | ((dma&0x03)<<6) | 0x003f;
-       pci_write_config_word(pcidev, YMFSB_PCIR_LEGCTRL, v);
-#ifdef YMF_DEBUG
-       printk(PFX "LEGCTRL: 0x%x\n",v);
-#endif
-       switch( pcidev->device ) {
-       case PCI_DEVICE_ID_YMF724:
-       case PCI_DEVICE_ID_YMF740:
-       case PCI_DEVICE_ID_YMF724F:
-       case PCI_DEVICE_ID_YMF740C:
-               v = 0x8800 | ((mpuio<<4)&0x03) | ((sbio<<2)&0x03) | (oplio&0x03);
-               pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);
-#ifdef YMF_DEBUG
-               printk(PFX "ELEGCTRL: 0x%x\n",v);
-#endif
-               break;
-
-       case PCI_DEVICE_ID_YMF744:
-       case PCI_DEVICE_ID_YMF754:
-               v = 0x8800;
-               pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);
-               pci_write_config_word(pcidev, YMFSB_PCIR_OPLADR, card->opl3_data.io_base);
-               pci_write_config_word(pcidev, YMFSB_PCIR_SBADR,  card->sb_data.io_base);
-               pci_write_config_word(pcidev, YMFSB_PCIR_MPUADR, card->mpu_data.io_base);
-               break;
-
-       default:
-               printk(KERN_ERR PFX "Invalid device ID: %d\n",pcidev->device);
-               return -EINVAL;
-               break;
-       }
-
-       return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-/* AC'97 stuff */
-static int ymfsb_readAC97Reg( struct ac97_hwint *dev, u8 reg )
-{
-       struct ymf_card *card = (struct ymf_card *)dev->driver_private;
-       unsigned long flags;
-       int ret;
-
-       if ( reg > 0x7f ) return -EINVAL;
-
-       save_flags(flags);
-       cli();
-       writeRegWord( card, YMFSB_AC97CMDADR, 0x8000 | reg );
-       if ( checkPrimaryBusy( card ) ) {
-               restore_flags(flags);
-               return -EBUSY;
-       }
-       ret = readRegWord( card, YMFSB_AC97CMDDATA );
-       restore_flags(flags);
-
-       return ret;
-}
-
-static int ymfsb_writeAC97Reg( struct ac97_hwint *dev, u8 reg, u16 value )
-{
-       struct ymf_card *card = (struct ymf_card *)dev->driver_private;
-       unsigned long flags;
-
-       if ( reg > 0x7f ) return -EINVAL;
-
-       save_flags(flags);
-       cli();
-       if ( checkPrimaryBusy( card ) ) {
-         restore_flags(flags);
-         return -EBUSY;
-       }
-
-       writeRegWord( card, YMFSB_AC97CMDADR, 0x0000 | reg );
-       writeRegWord( card, YMFSB_AC97CMDDATA, value );
-
-       restore_flags(flags);
-       return 0;
-}
-
-struct initialValues
-{
-    unsigned short port;
-    unsigned short value;
-};
-
-static struct initialValues ymfsb_ac97_initial_values[] =
-{
-    { AC97_RESET,             0x0000 },
-    { AC97_MASTER_VOL_STEREO, 0x0000 },
-    { AC97_HEADPHONE_VOL,     0x8000 },
-    { AC97_PCMOUT_VOL,        0x0606 },
-    { AC97_MASTER_VOL_MONO,   0x0000 },
-    { AC97_PCBEEP_VOL,        0x0000 },
-    { AC97_PHONE_VOL,         0x0008 },
-    { AC97_MIC_VOL,           0x8000 },
-    { AC97_LINEIN_VOL,        0x8808 },
-    { AC97_CD_VOL,            0x8808 },
-    { AC97_VIDEO_VOL,         0x8808 },
-    { AC97_AUX_VOL,           0x8808 },
-    { AC97_RECORD_SELECT,     0x0000 },
-    { AC97_RECORD_GAIN,       0x0B0B },
-    { AC97_GENERAL_PURPOSE,   0x0000 },
-    { 0xffff, 0xffff }
-};
-
-static int ymfsb_resetAC97( struct ac97_hwint *dev )
-{
-       int i;
-
-       for ( i=0 ; ymfsb_ac97_initial_values[i].port != 0xffff ; i++ )
-       {
-               ac97_put_register ( dev,
-                                   ymfsb_ac97_initial_values[i].port,
-                                   ymfsb_ac97_initial_values[i].value );
-       }
-
-       return 0;
-}
-
-static int ymfsb_ac97_mixer_ioctl( int dev, unsigned int cmd, caddr_t arg )
-{
-       int i;
-
-       for ( i=0 ; i < MAX_CARDS ; i++ )
-       {
-               if ( ymf_cards[i].mixer_oss_dev == dev ) break;
-       }
-
-       if ( i < MAX_CARDS )
-               return ac97_mixer_ioctl(&(ymf_cards[i].ac97_dev), cmd, arg);
-       else
-               return -ENODEV;
-}
-
-static struct mixer_operations ymfsb_ac97_mixer_operations = {
-       "YAMAHA",
-       "YAMAHA PCI",
-       ymfsb_ac97_mixer_ioctl
-};
-
-static struct ac97_mixer_value_list ymfsb_ac97_mixer_defaults[] = {
-    { SOUND_MIXER_VOLUME,  { { 85, 85 } } },
-    { SOUND_MIXER_SPEAKER, { { 100 } } },
-    { SOUND_MIXER_PCM,     { { 65, 65 } } },
-    { SOUND_MIXER_CD,      { { 65, 65 } } },
-    { -1,                  {  { 0,  0 } } }
-};
-
-/* ---------------------------------------------------------------------- */
-
-static void enableDSP( struct ymf_card *card )
-{
-       writeRegDWord( card, YMFSB_CONFIG, 0x00000001 );
-       return;
-}
-
-static void disableDSP( struct ymf_card *card )
-{
-       int val;
-       int i;
-
-       val = readRegDWord( card, YMFSB_CONFIG );
-       if ( val ) {
-               writeRegDWord( card, YMFSB_CONFIG, 0 );
-       }
-
-       i=0;
-       while( ++i < YMFSB_WORKBITTIMEOUT ) {
-               val = readRegDWord( card, YMFSB_STATUS );
-               if ( (val & 0x00000002) == 0x00000000 ) break;
-       }
-
-       return;
-}
-
-static int setupInstruction( struct ymf_card *card, struct pci_dev *pcidev )
-{
-       int i;
-       int val;
-
-       writeRegDWord( card, YMFSB_NATIVEDACOUTVOL, 0 ); /* mute dac */
-       disableDSP( card );
-
-       writeRegDWord( card, YMFSB_MODE, 0x00010000 );
-
-       /* DS-XG Software Reset */
-       writeRegDWord( card, YMFSB_MODE,         0x00000000 );
-       writeRegDWord( card, YMFSB_MAPOFREC,     0x00000000 );
-       writeRegDWord( card, YMFSB_MAPOFEFFECT,  0x00000000 );
-       writeRegDWord( card, YMFSB_PLAYCTRLBASE, 0x00000000 );
-       writeRegDWord( card, YMFSB_RECCTRLBASE,  0x00000000 );
-       writeRegDWord( card, YMFSB_EFFCTRLBASE,  0x00000000 );
-
-       val = readRegWord( card, YMFSB_GLOBALCTRL );
-       writeRegWord( card, YMFSB_GLOBALCTRL, (val&~0x0007) );
-
-       /* setup DSP instruction code */
-       for ( i=0 ; i<YMFSB_DSPLENGTH ; i+=4 ) {
-         writeRegDWord( card, YMFSB_DSPINSTRAM+i, DspInst[i>>2] );
-       }
-
-       switch( pcidev->device ) {
-       case PCI_DEVICE_ID_YMF724:
-       case PCI_DEVICE_ID_YMF740:
-               /* setup Control instruction code */
-               for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) {
-                       writeRegDWord( card, YMFSB_CTRLINSTRAM+i, CntrlInst[i>>2] );
-               }
-               break;
-
-       case PCI_DEVICE_ID_YMF724F:
-       case PCI_DEVICE_ID_YMF740C:
-       case PCI_DEVICE_ID_YMF744:
-       case PCI_DEVICE_ID_YMF754:
-               /* setup Control instruction code */
-       
-               for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) {
-                       writeRegDWord( card, YMFSB_CTRLINSTRAM+i, CntrlInst1E[i>>2] );
-               }
-               break;
-
-       default:
-               return -ENXIO;
-       }
-
-       enableDSP( card );
-
-       return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int __init ymf7xx_init( struct ymf_card *card, struct pci_dev *pcidev )
-{
-       unsigned short v;
-       int mixer;
-
-       /* Read hardware information */
-#ifdef YMF_DEBUG
-       unsigned int   dv;
-       pci_read_config_word(pcidev, YMFSB_PCIR_VENDORID, &v);
-       printk(KERN_INFO PFX "Vendor ID = 0x%x\n",v);
-       pci_read_config_word(pcidev, YMFSB_PCIR_DEVICEID, &v);
-       printk(KERN_INFO PFX "Device ID = 0x%x\n",v);
-       pci_read_config_word(pcidev, YMFSB_PCIR_REVISIONID, &v);
-       printk(KERN_INFO PFX "Revision ID = 0x%x\n",v&0xff);
-       pci_read_config_dword(pcidev, YMFSB_PCIR_BASEADDR, &dv);
-       printk(KERN_INFO PFX "Base address = 0x%x\n",dv);
-       pci_read_config_word(pcidev, YMFSB_PCIR_IRQ, &v);
-       printk(KERN_INFO PFX "IRQ line = 0x%x\n",v&0xff);
-#endif
-
-       /* enables memory space access / bus mastering */
-       pci_read_config_word(pcidev, YMFSB_PCIR_CMD, &v);
-       pci_write_config_word(pcidev, YMFSB_PCIR_CMD, v|0x06);
-
-       /* check codec */
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "check codec...\n");
-#endif
-       if (checkCodec(card, pcidev)) return -EBUSY;
-
-       /* setup legacy I/O */
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "setup legacy I/O...\n");
-#endif
-       if (setupLegacyIO(card, pcidev)) return -EBUSY;
-       
-       /* setup instruction code */    
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "setup instructions...\n");
-#endif
-       if (setupInstruction(card, pcidev)) return -EBUSY;
-
-       /* AC'97 setup */       
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "setup AC'97...\n");
-#endif
-       if ( ac97_init( &card->ac97_dev ) ) return -EBUSY;
-
-       mixer = sound_alloc_mixerdev();
-       if ( num_mixers >= MAX_MIXER_DEV ) return -EBUSY;
-       
-       mixer_devs[mixer] = &ymfsb_ac97_mixer_operations;
-       card->mixer_oss_dev = mixer;
-       ac97_set_values( &card->ac97_dev, ymfsb_ac97_mixer_defaults );
-
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "setup Legacy Volume...\n");
-#endif
-       /* Legacy Audio Output Volume L & R ch */
-       writeRegDWord( card, YMFSB_LEGACYOUTVOL, 0x3fff3fff );
-
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "setup SPDIF output control...\n");
-#endif
-       /* SPDIF Output control */
-       v = spdif_out != 0 ? 0x0001 : 0x0000;
-       writeRegWord( card, YMFSB_SPDIFOUTCTRL, v );
-       /* no copyright protection, 
-          sample-rate converted,
-          re-recorded software comercially available (the 1st generation),
-          original */
-       writeRegWord( card, YMFSB_SPDIFOUTSTATUS, 0x9a04 );
-
-       return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void __init ymf7xxsb_attach_sb(struct address_info *hw_config)
-{
-       hw_config->driver_use_1 |= SB_NO_MIXER;
-       if(!sb_dsp_init(hw_config))
-               hw_config->slots[0] = -1;
-}
-
-static int __init ymf7xxsb_probe_sb(struct address_info *hw_config)
-{
-       if (check_region(hw_config->io_base, 16))
-       {
-               printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
-                      hw_config->io_base);
-               return 0;
-       }
-       return sb_dsp_detect(hw_config, SB_PCI_YAMAHA, 0);
-}
-
-
-static void ymf7xxsb_unload_sb(struct address_info *hw_config, int unload_mpu)
-{
-       if(hw_config->slots[0]!=-1)
-               sb_dsp_unload(hw_config, unload_mpu);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int __init ymf7xxsb_install (struct pci_dev *pcidev)
-{
-       struct {
-               unsigned short deviceid;
-               char           *devicename;
-       } devicetable[] = 
-       {
-               { PCI_DEVICE_ID_YMF724,  "YMF724A-E" },
-               { PCI_DEVICE_ID_YMF724F, "YMF724F" },
-               { PCI_DEVICE_ID_YMF740,  "YMF740A-B" },
-               { PCI_DEVICE_ID_YMF740C, "YMF740C" },
-               { PCI_DEVICE_ID_YMF744,  "YMF744" },
-               { PCI_DEVICE_ID_YMF754,  "YMF754" },
-       };
-
-       char            *devicename = "unknown";
-       int             i;
-       unsigned long   iobase;
-       struct ymf_card *card;
-
-       if ( pcidev->irq == 0 ) return -ENODEV;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-       if ( pci_enable_device(pcidev) ) {
-               printk (KERN_ERR PFX "cannot enable PCI device\n");
-               return -EIO;
-       }
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
-       iobase = pcidev->base_address[0]&PCI_BASE_ADDRESS_MEM_MASK;
-#else
-       iobase = pcidev->resource[0].start&PCI_BASE_ADDRESS_MEM_MASK;
-#endif
-       if ( iobase == 0x00000000 ) return -ENODEV;
-
-       for ( i=0 ; i<sizeof(devicetable) / sizeof(devicetable[0]); i++ )
-       {
-               if (devicetable[i].deviceid == pcidev->device)
-               {
-                       devicename = devicetable[i].devicename;
-                       break;
-               }
-       }
-
-       card = &ymf_cards[cards];
-
-       /* remap memory mapped I/O onto kernel virtual memory */
-       if ( (card->ymfbase = ioremap_nocache(iobase, YMFSB_REGSIZE)) == 0 )
-       {
-               printk(KERN_ERR PFX "ioremap (0x%lx) returns zero\n", iobase);
-               return -ENODEV;
-       }
-       printk(KERN_INFO PFX "found %s at 0x%lx\n", devicename, iobase);
-#ifdef YMF_DEBUG
-       printk(KERN_INFO PFX "remappling to 0x%p\n", card->ymfbase);
-#endif
-
-       memset (&card->sb_data,   0, sizeof (struct address_info));
-       memset (&card->opl3_data, 0, sizeof (struct address_info));
-       memset (&card->mpu_data,  0, sizeof (struct address_info));
-       memset (&card->ac97_dev,  0, sizeof (struct ac97_hwint));
-
-       card->card = cards;
-
-       card->sb_data.name   = YMFSB_CARD_NAME;
-       card->opl3_data.name = YMFSB_CARD_NAME;
-       card->mpu_data.name  = YMFSB_CARD_NAME;
-
-       card->sb_data.card_subtype = MDL_YMPCI;
-
-       if ( io == 0 ) io      = 0x220;
-       card->sb_data.io_base = io;
-       card->sb_data.irq     = pcidev->irq;
-       card->sb_data.dma     = dma;
-
-       if ( synth_io == 0 ) synth_io = 0x388;
-       card->opl3_data.io_base = synth_io;
-       card->opl3_data.irq     = -1;
-
-       if ( mpu_io == 0 ) mpu_io = 0x330;
-       card->mpu_data.io_base = mpu_io;
-       card->mpu_data.irq     = -1;
-
-       card->ac97_dev.reset_device   = ymfsb_resetAC97;
-       card->ac97_dev.read_reg       = ymfsb_readAC97Reg;
-       card->ac97_dev.write_reg      = ymfsb_writeAC97Reg;
-       card->ac97_dev.driver_private = (void *)card;
-
-       if ( ymf7xx_init(card, pcidev) ) {
-               printk (KERN_ERR PFX
-                       "Cannot initialize %s, aborting\n",
-                       devicename);
-               return -ENODEV;
-       }
-
-       /* regist legacy SoundBlaster Pro */
-       if (!ymf7xxsb_probe_sb(&card->sb_data)) {
-               printk (KERN_ERR PFX
-                       "SB probe at 0x%X failed, aborting\n",
-                       io);
-               return -ENODEV;
-       }
-       ymf7xxsb_attach_sb (&card->sb_data);
-
-       /* regist legacy MIDI */
-       if ( mpu_io > 0 && 0)
-       {
-               if (!ymf7xxsb_probe_midi (&card->mpu_data)) {
-                       printk (KERN_ERR PFX
-                               "MIDI probe @ 0x%X failed, aborting\n",
-                               mpu_io);
-                       ymf7xxsb_unload_sb (&card->sb_data, 0);
-                       return -ENODEV;
-               }
-               ymf7xxsb_attach_midi (&card->mpu_data);
-       }
-
-       /* regist legacy OPL3 */
-
-       cards++;        
-       return 0;
-}
-
-static int __init probe_ymf7xxsb (void)
-{
-       struct pci_dev *pcidev = NULL;
-       int i;
-
-       for (i=0 ; i<MAX_CARDS ; i++ )
-               ymf_cards[i].ymfbase = NULL;
-
-       while ( pcidev == NULL && (
-              (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-                                         PCI_DEVICE_ID_YMF724, pcidev)) ||
-              (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-                                         PCI_DEVICE_ID_YMF724F,pcidev)) ||
-              (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-                                         PCI_DEVICE_ID_YMF740, pcidev)) ||
-              (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-                                         PCI_DEVICE_ID_YMF740C,pcidev)) ||
-              (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-                                         PCI_DEVICE_ID_YMF744, pcidev)) ||
-              (pcidev = pci_find_device (PCI_VENDOR_ID_YAMAHA,
-                                         PCI_DEVICE_ID_YMF754, pcidev)))) {
-                 if (ymf7xxsb_install (pcidev)) {
-                         printk (KERN_ERR PFX "audio init failed\n");
-                         return -ENODEV;
-                 }
-
-                 if (cards == MAX_CARDS) {
-                         printk (KERN_DEBUG PFX "maximum number of cards reached\n");
-                         break;
-                 }
-       }
-
-       return 0;
-}
-
-static void free_iomaps( void )
-{
-       int i;
-
-       for ( i=0 ; i<MAX_CARDS ; i++ ) {
-               if ( ymf_cards[i].ymfbase!=NULL )
-                       iounmap(ymf_cards[i].ymfbase);
-       }
-
-       return;
-}
-
-int __init init_ymf7xxsb_module(void)
-{
-       if (!pci_present ()) {
-               printk (KERN_DEBUG PFX "PCI not present, exiting\n");
-               return -ENODEV;
-       }
-
-       if (probe_ymf7xxsb()) {
-               printk(KERN_ERR PFX "probe failed, aborting\n");
-               /* XXX unload cards registered so far, if any */
-               free_iomaps();
-               return -ENODEV;
-       }
-
-       if (cards == 0) {
-               printk(KERN_DEBUG PFX "No chips found, aborting\n");
-               free_iomaps();
-               return -ENODEV;
-       }
-
-       printk (KERN_INFO PFX YMFSB_CARD_NAME " loaded\n");
-       
-       /*
-        *      Binds us to the sound subsystem 
-        */
-       SOUND_LOCK;
-       return 0;
-}
-
-static void cleanup_ymf7xxsb_module(void)
-{
-       int i;
-       
-       for (i = 0; i < cards; i++) {
-               ymf7xxsb_unload_sb (&(ymf_cards[i].sb_data), 0);
-               ymf7xxsb_unload_midi (&(ymf_cards[i].mpu_data));
-               if ( ymf_cards[i].mixer_oss_dev >= 0 ) 
-                       sound_unload_mixerdev( ymf_cards[i].mixer_oss_dev );
-       }
-
-       free_iomaps();
-
-       /*
-        *      Final clean up with the sound layer
-        */
-       SOUND_LOCK_END;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Daisuke Nagano, breeze.nagano@nifty.ne.jp");
-MODULE_DESCRIPTION("YMF7xx Legacy Audio Driver");
-
-int init_module(void)
-{
-       return init_ymf7xxsb_module();
-}
-
-void cleanup_module(void)
-{
-       cleanup_ymf7xxsb_module();
-}
-
-#endif
index d18b96d3df1462cea497a5be2445c8612196c64b..b4a625a8c5b1435e55f7f123717b751226bc2a42 100644 (file)
@@ -34,6 +34,8 @@
  *      ? underused structure members
  */
 
+#define YMFPCI_HAVE_MIDI_SUPPORT
+
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+# include "sound_config.h"
+#endif
+
 #include "ymfpci.h"
 
 #define snd_magic_cast(t, p, err)      ((t *)(p))
@@ -1870,6 +1876,90 @@ static int ymf_ioctl(struct inode *inode, struct file *file,
        return -ENOTTY;
 }
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+/* MIDI stuff */
+
+/* */
+
+static int ymfpci_setup_legacy( ymfpci_t *codec, struct pci_dev *pcidev )
+{
+       int v;
+       int mpuio=-1, oplio=-1;
+
+       switch(codec->iomidi) {
+       case 0x330:
+               mpuio = 0;
+               break;
+       case 0x300:
+               mpuio = 1;
+               break;
+       case 0x332:
+               mpuio = 2;
+               break;
+       case 0x334:
+               mpuio = 3;
+               break;
+       default:
+               break;
+       }
+
+       switch(codec->iosynth) {
+       case 0x388:
+               oplio = 0;
+               break;
+       case 0x398:
+               oplio = 1;
+               break;
+       case 0x3a0:
+               oplio = 2;
+               break;
+       case 0x3a8:
+               oplio = 3;
+               break;
+       default:
+               break;
+       }
+
+       if ( mpuio >= 0 || oplio >= 0 ) {
+               v = 0x003e;
+               pci_write_config_word(pcidev, PCIR_LEGCTRL, v);
+       
+               switch( pcidev->device ) {
+               case PCI_DEVICE_ID_YAMAHA_724:
+               case PCI_DEVICE_ID_YAMAHA_740:
+               case PCI_DEVICE_ID_YAMAHA_724F:
+               case PCI_DEVICE_ID_YAMAHA_740C:
+                       v = 0x8800;
+                       if ( mpuio >= 0 ) { v|= (mpuio<<4)&0x03; }
+                       if ( oplio >= 0 ) { v|= (oplio&0x03); }
+                       pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
+                       break;
+
+               case PCI_DEVICE_ID_YAMAHA_744:
+               case PCI_DEVICE_ID_YAMAHA_754:
+                       v = 0x8800;
+                       pci_write_config_word(pcidev, PCIR_ELEGCTRL, v);
+                       if ( mpuio >= 0 ) {
+                               pci_write_config_word(pcidev, PCIR_OPLADR, codec->iosynth);
+                       }
+                       if ( oplio >= 0 ) {
+                               pci_write_config_word(pcidev, PCIR_MPUADR, codec->iomidi);
+                       }
+               break;
+
+               default:
+                       printk(KERN_ERR "ymfpci: Invalid device ID: %d\n",pcidev->device);
+                       return -EINVAL;
+                       break;
+               }
+       }
+
+       return 0;
+}
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+
+/* */
+
 static int ymf_open(struct inode *inode, struct file *file)
 {
        ymfpci_t *unit;
@@ -1895,7 +1985,11 @@ static int ymf_open(struct inode *inode, struct file *file)
 
        /* XXX Semaphore here! */
        for (unit = ymf_devs; unit != NULL; unit = unit->next) {
+#if 0
                if (unit->inst == instance) break;
+#else
+               if (!((unit->dev_audio ^ minor) & ~0x0f)) break;
+#endif
        }
        if (unit == NULL) return -ENODEV;
 
@@ -2234,6 +2328,20 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97)
        return 0;
 }
 
+/* */
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+# ifdef MODULE
+static int mpu_io     = 0;
+static int synth_io   = 0;
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM(synth_io, "i");
+# else
+static int mpu_io     = 0x330;
+static int synth_io   = 0x388;
+# endif
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+/* */
+
 static int /* __init */
 ymf_install(struct pci_dev *pcidev, int instance, int devx)
 {
@@ -2268,6 +2376,15 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
                return -ENODEV;
        }
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+       codec->iomidi = mpu_io;
+       codec->iosynth = synth_io;
+       if (ymfpci_setup_legacy(codec, pcidev) < 0) {
+               ymfpci_free(codec);
+               return -ENODEV;
+       }
+#endif
+
        ymfpci_download_image(codec);
 
        udelay(100); /* seems we need some delay after downloading image.. */
@@ -2304,6 +2421,28 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx)
                return err;
        }
 
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+       memset (&codec->opl3_data, 0, sizeof (struct address_info));
+       memset (&codec->mpu_data,  0, sizeof (struct address_info));
+
+       codec->opl3_data.name = "ymfpci";
+       codec->mpu_data.name  = "ymfpci";
+
+       codec->opl3_data.io_base = codec->iosynth;
+       codec->opl3_data.irq     = -1;
+
+       codec->mpu_data.io_base  = codec->iomidi;
+       codec->mpu_data.irq      = -1;
+
+       if ( mpu_io > 0 )
+       {
+               if ( probe_uart401(&codec->mpu_data) ) {
+                       attach_uart401(&codec->mpu_data);
+               }
+       }
+
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
+
        codec->next = ymf_devs;
        ymf_devs = codec;
 
@@ -2339,6 +2478,11 @@ ymfpci_free(ymfpci_t *codec)
                unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer);
                kfree(codec->ac97_codec[0]);
        }
+#ifdef YMFPCI_HAVE_MIDI_SUPPORT
+       if (codec->iomidi) {
+               unload_uart401(&(codec->mpu_data));
+       }
+#endif /* YMFPCI_HAVE_MIDI_SUPPORT */
        kfree(codec);
 }
 
index 29b611f1fc061b7db0154595e2bc20dbee37627a..0f0b674eebe85bc77cd5dce7bba08c97bb5b3fdf 100644 (file)
 #define YDSXG_AC97READCMD              0x8000
 #define YDSXG_AC97WRITECMD             0x0000
 
+#define PCIR_VENDORID                  0x00
+#define PCIR_DEVICEID                  0x02
+#define PCIR_CMD                       0x04
+#define PCIR_REVISIONID                        0x08
+#define PCIR_BASEADDR                  0x10
+#define PCIR_IRQ                       0x3c
+
+#define PCIR_LEGCTRL                   0x40
+#define PCIR_ELEGCTRL                  0x42
 #define PCIR_DSXGCTRL                  0x48
+#define PCIR_OPLADR                    0x60
+#define PCIR_SBADR                     0x62
+#define PCIR_MPUADR                    0x64
 
 #define YDSXG_DSPLENGTH                        0x0080
 #define YDSXG_CTRLLENGTH               0x3000
@@ -281,6 +293,10 @@ struct ymf_unit {
        int irq;
        int inst;               /* Unit number (instance) */
 
+        /* legacy hardware resources */
+       unsigned int iosynth, iomidi;
+       struct address_info opl3_data, mpu_data;
+
        spinlock_t reg_lock;
        spinlock_t voice_lock;
 
index 66ae3b852dd3222da165e0e2a9553cf83d1d87db..20d52b2b7a34f8f79571938895e3064b29bd899b 100644 (file)
@@ -50,6 +50,7 @@ comment 'USB Devices'
          fi
          dep_tristate '    USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL
          dep_tristate '    USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL
+         dep_tristate '    USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL
       fi
       bool '    USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL
    fi
index 65c01e9977fce18228fdc1423da540ada55c9ae4..76e6c214b9d62d047ab3c92c7864469980c52d56 100644 (file)
@@ -173,8 +173,8 @@ static void dabusb_iso_complete (purb_t purb)
 
        // process if URB was not killed
        if (purb->status != -ENOENT) {
-               unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
-               int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
+               unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
+               int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
                for (i = 0; i < purb->number_of_packets; i++)
                        if (!purb->iso_frame_desc[i].status) {
                                len = purb->iso_frame_desc[i].actual_length;
@@ -456,6 +456,8 @@ static int dabusb_startrek (pdabusb_t s)
 
                        end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
 
+                       end->purb->dev=s->usbdev;
+
                        ret = usb_submit_urb (end->purb);
                        if (ret) {
                                err("usb_submit_urb returned:%d", ret);
index c262023a7b7f6f9b2da3db9b799480d986b1f5c1..97481d2ae726457ade359eaa95eeb82489bc35b1 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN)              += keyspan.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT)       += digi_acceleport.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)                        += belkin_sa.o
+obj-$(CONFIG_USB_SERIAL_EMPEG)                 += empeg.o
  
 # Objects that export symbols.
 export-objs    := usbserial.o
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
new file mode 100644 (file)
index 0000000..cb5608b
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * USB Empeg empeg-car player driver
+ *
+ *     Copyright (C) 2000
+ *         Gary Brubaker (xavyer@ix.netcom.com)
+ *
+ *     Copyright (C) 1999, 2000
+ *         Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License, as published by
+ *     the Free Software Foundation, version 2.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (11/13/2000) gb
+ *     Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
+ *     (It only needs to be set once - Doh!)
+ * 
+ * (11/11/2000) gb
+ *     Updated to work with id_table structure.
+ * 
+ * (11/04/2000) gb
+ *     Forked this from visor.c, and hacked it up to work with an
+ *     Empeg ltd. empeg-car player.  Constructive criticism welcomed.
+ *     I would like to say, 'Thank You' to Greg Kroah-Hartman for the
+ *     use of his code, and for his guidance, advice and patience. :)
+ *     A 'Thank You' is in order for John Ripley of Empeg ltd for his
+ *     advice, and patience too.
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#ifdef CONFIG_USB_SERIAL_DEBUG
+       #define DEBUG
+#else
+       #undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include "usb-serial.h"
+
+#define EMPEG_VENDOR_ID                 0x084f
+#define EMPEG_PRODUCT_ID                0x0001
+
+#define MIN(a,b)               (((a)<(b))?(a):(b))
+
+/* function prototypes for an empeg-car player */
+static int  empeg_open         (struct usb_serial_port *port, struct file *filp);
+static void empeg_close                (struct usb_serial_port *port, struct file *filp);
+static int  empeg_write                (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static void empeg_throttle     (struct usb_serial_port *port);
+static void empeg_unthrottle   (struct usb_serial_port *port);
+static int  empeg_startup      (struct usb_serial *serial);
+static void empeg_shutdown     (struct usb_serial *serial);
+static int  empeg_ioctl                (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void empeg_set_termios  (struct usb_serial_port *port, struct termios *old_termios);
+static void empeg_write_bulk_callback  (struct urb *urb);
+static void empeg_read_bulk_callback   (struct urb *urb);
+
+static __u16   empeg_vendor_id         = EMPEG_VENDOR_ID;
+static __u16   empeg_product_id        = EMPEG_PRODUCT_ID;
+struct usb_serial_device_type empeg_device = {
+       name:                   "Empeg",
+       idVendor:               &empeg_vendor_id,
+       idProduct:              &empeg_product_id,
+       needs_interrupt_in:     MUST_HAVE_NOT,  /* must not have an interrupt in endpoint */
+       needs_bulk_in:          MUST_HAVE,      /* must have a bulk in endpoint */
+       needs_bulk_out:         MUST_HAVE,      /* must have a bulk out endpoint */
+       num_interrupt_in:       0,
+       num_bulk_in:            1,
+       num_bulk_out:           1,
+       num_ports:              1,
+       open:                   empeg_open,
+       close:                  empeg_close,
+       throttle:               empeg_throttle,
+       unthrottle:             empeg_unthrottle,
+       startup:                empeg_startup,
+       shutdown:               empeg_shutdown,
+       ioctl:                  empeg_ioctl,
+       set_termios:            empeg_set_termios,
+       write:                  empeg_write,
+       write_bulk_callback:    empeg_write_bulk_callback,
+       read_bulk_callback:     empeg_read_bulk_callback,
+};
+
+#define NUM_URBS                       16
+#define URB_TRANSFER_BUFFER_SIZE       4096
+
+static struct urb      *write_urb_pool[NUM_URBS];
+static spinlock_t      write_urb_pool_lock;
+static int             bytes_in;
+static int             bytes_out;
+
+/******************************************************************************
+ * Empeg specific driver functions
+ ******************************************************************************/
+static int empeg_open (struct usb_serial_port *port, struct file *filp)
+{
+       unsigned long flags;
+       int result;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return -ENODEV;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       spin_lock_irqsave (&port->port_lock, flags);
+
+       ++port->open_count;
+       MOD_INC_USE_COUNT;
+
+       /* gb - 2000/11/05
+        *
+        * personally, I think these termios should be set in
+        * empeg_startup(), but it appears doing so leads to one
+        * of those chicken/egg problems. :)
+        *
+        */
+       port->tty->termios->c_iflag
+               &= ~(IGNBRK
+               | BRKINT
+               | PARMRK
+               | ISTRIP
+               | INLCR
+               | IGNCR
+               | ICRNL
+               | IXON);
+
+       port->tty->termios->c_oflag
+               &= ~OPOST;
+
+       port->tty->termios->c_lflag
+               &= ~(ECHO
+               | ECHONL
+               | ICANON
+               | ISIG
+               | IEXTEN);
+
+       port->tty->termios->c_cflag
+               &= ~(CSIZE
+               | PARENB);
+
+       port->tty->termios->c_cflag
+               |= CS8;
+
+       /* gb - 2000/11/05
+        *
+        * force low_latency on
+        *
+        * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually
+        * force the data through if low_latency is set.  Otherwise the pushes are
+        * scheduled; this is bad as it opens up the possibility of dropping bytes
+        * on the floor.  We are trying to sustain high data transfer rates; and
+        * don't want to drop bytes on the floor.
+        * Moral: use low_latency - drop no bytes - life is good. :)
+        *
+        */
+       port->tty->low_latency = 1;
+
+       if (!port->active) {
+               port->active = 1;
+               bytes_in = 0;
+               bytes_out = 0;
+
+               /* Start reading from the device */
+               port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+
+               result = usb_submit_urb(port->read_urb);
+
+               if (result)
+                       err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+
+       }
+
+       spin_unlock_irqrestore (&port->port_lock, flags);
+
+       return 0;
+}
+
+
+static void empeg_close (struct usb_serial_port *port, struct file * filp)
+{
+       struct usb_serial *serial;
+       unsigned char *transfer_buffer;
+       unsigned long flags;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       serial = get_usb_serial (port, __FUNCTION__);
+       if (!serial)
+               return;
+
+       spin_lock_irqsave (&port->port_lock, flags);
+
+       --port->open_count;
+       MOD_DEC_USE_COUNT;
+
+       if (port->open_count <= 0) {
+               transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+
+               if (!transfer_buffer) {
+                       err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12);
+               } else {
+                       kfree (transfer_buffer);
+               }
+
+               /* shutdown our bulk read */
+               usb_unlink_urb (port->read_urb);
+               port->active = 0;
+               port->open_count = 0;
+       }
+
+       spin_unlock_irqrestore (&port->port_lock, flags);
+
+       /* Uncomment the following line if you want to see some statistics in your syslog */
+       /* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
+
+}
+
+
+static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
+{
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       const unsigned char *current_position = buf;
+       unsigned long flags;
+       int status;
+       int i;
+       int bytes_sent = 0;
+       int transfer_size;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf);
+
+       while (count > 0) {
+
+               /* try to find a free urb in our list of them */
+               urb = NULL;
+
+               spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+               for (i = 0; i < NUM_URBS; ++i) {
+                       if (write_urb_pool[i]->status != -EINPROGRESS) {
+                               urb = write_urb_pool[i];
+                               break;
+                       }
+               }
+
+               spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+               if (urb == NULL) {
+                       dbg (__FUNCTION__ " - no more free urbs");
+                       goto exit;
+               }
+
+               if (urb->transfer_buffer == NULL) {
+                       urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+                       if (urb->transfer_buffer == NULL) {
+                               err(__FUNCTION__" no more kernel memory...");
+                               goto exit;
+                       }
+               }
+
+               transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE);
+
+               if (from_user) {
+                       copy_from_user (urb->transfer_buffer, current_position, transfer_size);
+               } else {
+                       memcpy (urb->transfer_buffer, current_position, transfer_size);
+               }
+
+               count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+               /* build up our urb */
+               FILL_BULK_URB (
+                       urb,
+                       serial->dev,
+                       usb_sndbulkpipe(serial->dev,
+                               port->bulk_out_endpointAddress), 
+                       urb->transfer_buffer,
+                       transfer_size,
+                       empeg_write_bulk_callback,
+                       port);
+
+               urb->transfer_flags |= USB_QUEUE_BULK;
+
+               /* send it down the pipe */
+               status = usb_submit_urb(urb);
+               if (status)
+                       dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
+
+               current_position += transfer_size;
+               bytes_sent += transfer_size;
+               count -= transfer_size;
+               bytes_out += transfer_size;
+
+       }
+
+exit:
+       return bytes_sent;
+
+} 
+
+
+static void empeg_write_bulk_callback (struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       if (urb->status) {
+               dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
+               return;
+       }
+
+       queue_task(&port->tqueue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+
+       return;
+
+}
+
+
+static void empeg_read_bulk_callback (struct urb *urb)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+       struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+       struct tty_struct *tty;
+       unsigned char *data = urb->transfer_buffer;
+       int i;
+       int result;
+
+       if (port_paranoia_check (port, __FUNCTION__))
+               return;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       if (!serial) {
+               dbg(__FUNCTION__ " - bad serial pointer, exiting");
+               return;
+       }
+
+       if (urb->status) {
+               dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
+               return;
+       }
+
+       usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
+
+       tty = port->tty;
+
+       if (urb->actual_length) {
+               for (i = 0; i < urb->actual_length ; ++i) {
+                       /* gb - 2000/11/13
+                        * If we insert too many characters we'll overflow the buffer.
+                        * This means we'll lose bytes - Decidedly bad.
+                        */
+                       if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+                               tty_flip_buffer_push(tty);
+                               }
+                       /* gb - 2000/11/13
+                        * This doesn't push the data through unless tty->low_latency is set.
+                        */
+                       tty_insert_flip_char(tty, data[i], 0);
+               }
+               /* gb - 2000/11/13
+                * Goes straight through instead of scheduling - if tty->low_latency is set.
+                */
+               tty_flip_buffer_push(tty);
+               bytes_in += urb->actual_length;
+       }
+
+       /* Continue trying to always read  */
+       port->read_urb->transfer_flags |= USB_QUEUE_BULK;
+       result = usb_submit_urb(port->read_urb);
+
+       if (result)
+               err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
+
+       return;
+
+}
+
+
+static void empeg_throttle (struct usb_serial_port *port)
+{
+       unsigned long flags;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       spin_lock_irqsave (&port->port_lock, flags);
+
+       usb_unlink_urb (port->read_urb);
+
+       spin_unlock_irqrestore (&port->port_lock, flags);
+
+       return;
+
+}
+
+
+static void empeg_unthrottle (struct usb_serial_port *port)
+{
+       unsigned long flags;
+       int result;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       spin_lock_irqsave (&port->port_lock, flags);
+
+       port->read_urb->dev = port->serial->dev;
+
+       result = usb_submit_urb(port->read_urb);
+
+       if (result)
+               err(__FUNCTION__ " - failed submitting read urb, error %d", result);
+
+       spin_unlock_irqrestore (&port->port_lock, flags);
+
+       return;
+
+}
+
+
+static int  empeg_startup (struct usb_serial *serial)
+{
+
+       dbg(__FUNCTION__);
+
+       dbg(__FUNCTION__ " - Set config to 1");
+       usb_set_configuration (serial->dev, 1);
+
+       /* continue on with initialization */
+       return 0;
+
+}
+
+
+static void empeg_shutdown (struct usb_serial *serial)
+{
+       int i;
+
+       dbg (__FUNCTION__);
+
+       /* stop reads and writes on all ports */
+       for (i=0; i < serial->num_ports; ++i) {
+               while (serial->port[i].open_count > 0) {
+                       empeg_close (&serial->port[i], NULL);
+               }
+       }
+
+}
+
+
+static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+       dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
+
+       return -ENOIOCTLCMD;
+}
+
+
+/* This function is all nice and good, but we don't change anything based on it :) */
+static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{
+       unsigned int cflag = port->tty->termios->c_cflag;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+
+       /* check that they really want us to change something */
+       if (old_termios) {
+               if ((cflag == old_termios->c_cflag) &&
+                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg(__FUNCTION__ " - nothing to change...");
+                       return;
+               }
+       }
+
+       if ((!port->tty) || (!port->tty->termios)) {
+               dbg(__FUNCTION__" - no tty structures");
+               return;
+       }
+
+       /* get the byte size */
+       switch (cflag & CSIZE) {
+               case CS5:       dbg(__FUNCTION__ " - data bits = 5");   break;
+               case CS6:       dbg(__FUNCTION__ " - data bits = 6");   break;
+               case CS7:       dbg(__FUNCTION__ " - data bits = 7");   break;
+               default:
+               case CS8:       dbg(__FUNCTION__ " - data bits = 8");   break;
+       }
+
+       /* determine the parity */
+       if (cflag & PARENB)
+               if (cflag & PARODD)
+                       dbg(__FUNCTION__ " - parity = odd");
+               else
+                       dbg(__FUNCTION__ " - parity = even");
+       else
+               dbg(__FUNCTION__ " - parity = none");
+
+       /* figure out the stop bits requested */
+       if (cflag & CSTOPB)
+               dbg(__FUNCTION__ " - stop bits = 2");
+       else
+               dbg(__FUNCTION__ " - stop bits = 1");
+
+       /* figure out the flow control settings */
+       if (cflag & CRTSCTS)
+               dbg(__FUNCTION__ " - RTS/CTS is enabled");
+       else
+               dbg(__FUNCTION__ " - RTS/CTS is disabled");
+
+       /* determine software flow control */
+       if (I_IXOFF(port->tty))
+               dbg(__FUNCTION__ " - XON/XOFF is enabled, XON = %2x, XOFF = %2x", START_CHAR(port->tty), STOP_CHAR(port->tty));
+       else
+               dbg(__FUNCTION__ " - XON/XOFF is disabled");
+
+       /* get the baud rate wanted */
+       dbg(__FUNCTION__ " - baud rate = %d", tty_get_baud_rate(port->tty));
+
+       return;
+
+}
+
+
+static int __init empeg_init (void)
+{
+       struct urb *urb;
+       int i;
+
+       usb_serial_register (&empeg_device);
+
+       /* create our write urb pool and transfer buffers */ 
+       spin_lock_init (&write_urb_pool_lock);
+       for (i = 0; i < NUM_URBS; ++i) {
+               urb = usb_alloc_urb(0);
+               write_urb_pool[i] = urb;
+               if (urb == NULL) {
+                       err("No more urbs???");
+                       continue;
+               }
+
+               urb->transfer_buffer = NULL;
+               urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+               if (!urb->transfer_buffer) {
+                       err (__FUNCTION__ " - out of memory for urb buffers.");
+                       continue;
+               }
+       }
+
+       return 0;
+
+}
+
+
+static void __exit empeg_exit (void)
+{
+       int i;
+       unsigned long flags;
+
+       usb_serial_deregister (&empeg_device);
+
+       spin_lock_irqsave (&write_urb_pool_lock, flags);
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (write_urb_pool[i]) {
+                       /* FIXME - uncomment the following usb_unlink_urb call when
+                        * the host controllers get fixed to set urb->dev = NULL after
+                        * the urb is finished.  Otherwise this call oopses. */
+                       /* usb_unlink_urb(write_urb_pool[i]); */
+                       if (write_urb_pool[i]->transfer_buffer)
+                               kfree(write_urb_pool[i]->transfer_buffer);
+                       usb_free_urb (write_urb_pool[i]);
+               }
+       }
+
+       spin_unlock_irqrestore (&write_urb_pool_lock, flags);
+
+}
+
+
+module_init(empeg_init);
+module_exit(empeg_exit);
+
+MODULE_AUTHOR("Gary Brubaker <xavyer@ix.netcom.com>");
+MODULE_DESCRIPTION("USB Empeg Mark I/II Driver");
index e8ac09004f20946f857c7a4dc88836561f4e109c..51aa6a9feb5cb7cef56ccd681c313dc7b30ecad4 100644 (file)
@@ -75,14 +75,10 @@ static int  mda_last_vc  = 16;
 
 static struct vc_data  *mda_display_fg = NULL;
 
-#ifdef MODULE_PARM
 MODULE_PARM(mda_first_vc, "1-255i");
 MODULE_PARM(mda_last_vc,  "1-255i");
-#endif
-
 
-/* MDA register values
- */
+/* MDA register values */
 
 #define MDA_CURSOR_BLINKING    0x00
 #define MDA_CURSOR_OFF         0x20
@@ -200,11 +196,7 @@ __initfunc(void mdacon_setup(char *str, int *ints))
 }
 #endif
 
-#ifdef MODULE
-static int mda_detect(void)
-#else
 __initfunc(static int mda_detect(void))
-#endif
 {
        int count=0;
        u16 *p, p_save;
@@ -287,11 +279,7 @@ __initfunc(static int mda_detect(void))
        return 1;
 }
 
-#ifdef MODULE
-static void mda_initialize(void)
-#else
 __initfunc(static void mda_initialize(void))
-#endif
 {
        write_mda_b(97, 0x00);          /* horizontal total */
        write_mda_b(80, 0x01);          /* horizontal displayed */
@@ -316,11 +304,7 @@ __initfunc(static void mda_initialize(void))
        outb_p(0x00, mda_gfx_port);
 }
 
-#ifdef MODULE
-static const char *mdacon_startup(void)
-#else
 __initfunc(static const char *mdacon_startup(void))
-#endif
 {
        mda_num_columns = 80;
        mda_num_lines   = 25;
@@ -606,11 +590,7 @@ struct consw mda_con = {
        mdacon_invert_region,   /* con_invert_region */
 };
 
-#ifdef MODULE
-void mda_console_init(void)
-#else
 __initfunc(void mda_console_init(void))
-#endif
 {
        if (mda_first_vc > mda_last_vc)
                return;
index 84e9ac54c9f9a8eb7d4ac9b97860d8440b85b40c..3a25b167a1dbda0101045c7041595619ae5639d1 100644 (file)
@@ -1056,7 +1056,7 @@ static int writenote(struct memelfnote *men, struct file *file)
 #undef DUMP_SEEK
 
 #define DUMP_WRITE(addr, nr)   \
-       if (!dump_write(file, (addr), (nr))) \
+       if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
                goto close_coredump;
 #define DUMP_SEEK(off) \
        if (!dump_seek(file, (off))) \
@@ -1078,7 +1078,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
        char corefile[6+sizeof(current->comm)];
        int segs;
        int i;
-       size_t size;
+       size_t size = 0;
        struct vm_area_struct *vma;
        struct elfhdr elf;
        off_t offset = 0, dataoff;
@@ -1099,24 +1099,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
        MOD_INC_USE_COUNT;
 #endif
 
-       /* Count what's needed to dump, up to the limit of coredump size */
-       segs = 0;
-       size = 0;
-       for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
-               if (maydump(vma))
-               {
-                       unsigned long sz = vma->vm_end-vma->vm_start;
-
-                       if (size+sz >= limit)
-                               break;
-                       else
-                               size += sz;
-               }
+       segs = current->mm->map_count;
 
-               segs++;
-       }
 #ifdef DEBUG
-       printk("elf_core_dump: %d segs taking %d bytes\n", segs, size);
+       printk("elf_core_dump: %d segs %lu limit\n", segs, limit);
 #endif
 
        /* Set up header */
@@ -1294,13 +1280,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
        dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 
        /* Write program headers for segments dump */
-       for(vma = current->mm->mmap, i = 0;
-               i < segs && vma != NULL; vma = vma->vm_next) {
+       for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
                struct elf_phdr phdr;
                size_t sz;
 
-               i++;
-
                sz = vma->vm_end - vma->vm_start;
 
                phdr.p_type = PT_LOAD;
@@ -1326,19 +1309,36 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
 
        DUMP_SEEK(dataoff);
 
-       for(i = 0, vma = current->mm->mmap;
-           i < segs && vma != NULL;
-           vma = vma->vm_next) {
-               unsigned long addr = vma->vm_start;
-               unsigned long len = vma->vm_end - vma->vm_start;
+       for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
+               unsigned long addr;
 
-               i++;
                if (!maydump(vma))
                        continue;
 #ifdef DEBUG
                printk("elf_core_dump: writing %08lx %lx\n", addr, len);
 #endif
-               DUMP_WRITE((void *)addr, len);
+               for (addr = vma->vm_start;
+                    addr < vma->vm_end;
+                    addr += PAGE_SIZE) {
+                       pgd_t *pgd;
+                       pmd_t *pmd;
+                       pte_t *pte;
+
+                       pgd = pgd_offset(vma->vm_mm, addr);
+                       pmd = pmd_alloc(pgd, addr);
+       
+                       if (!pmd)
+                               goto end_coredump;
+                       pte = pte_alloc(pmd, addr);
+                       if (!pte)
+                               goto end_coredump;
+                       if (!pte_present(*pte) &&
+                           pte_none(*pte)) {
+                               DUMP_SEEK (file->f_pos + PAGE_SIZE);
+                       } else {
+                               DUMP_WRITE((void*)addr, PAGE_SIZE);
+                       }
+               }
        }
 
        if ((off_t) file->f_pos != offset) {
index a99d13577d6030c5f24054990b70c485c9e89445..a79c34cef74c2ade58cc5419020b37b4232ac622 100644 (file)
@@ -2,6 +2,8 @@
  *  linux/fs/fat/misc.c
  *
  *  Written 1992,1993 by Werner Almesberger
+ *  22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
+ *              and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
  */
 
 #include <linux/fs.h>
@@ -288,7 +290,9 @@ int date_dos2unix(unsigned short time,unsigned short date)
 {
        int month,year,secs;
 
-       month = ((date >> 5) & 15)-1;
+       /* first subtract and mask after that... Otherwise, if
+          date == 0, bad things happen */
+       month = ((date >> 5) - 1) & 15;
        year = date >> 9;
        secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
            ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
@@ -310,6 +314,10 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
        unix_date -= sys_tz.tz_minuteswest*60;
        if (sys_tz.tz_dsttime) unix_date += 3600;
 
+       /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
+       if (unix_date < 315532800)
+               unix_date = 315532800;
+
        *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
            (((unix_date/3600) % 24) << 11);
        day = unix_date/86400-3652;
index da221ab2e97787311272a7fdb7028d04ea1a5380..ae9c1c4cc2702d638dff1eba6d42b489b158e84f 100644 (file)
@@ -1,5 +1,10 @@
 ChangeLog for smbfs.
 
+2000-11-22 Igor Zhbanov <bsg@uniyar.ac.ru>
+
+       * proc.c: fixed date_unix2dos for dates earlier than 01/01/1980
+         and date_dos2unix for date==0
+
 2000-11-04 Urban Widmark <urban@svenskatest.se>
 
        * proc.c, sock.c: adjust max parameters & max data to follow max_xmit
@@ -41,7 +46,7 @@ ChangeLog for smbfs.
        * proc.c: removed support for old protocol levels. It didn't work
          anyway and was cluttering things up a lot.
 
-2000-01-?? cpg@aladdin.de
+2000-01-03 Christian Groessler <cpg@aladdin.de>
 
        * proc.c: added posix semantics for unlink
 
index 2b3afb65bfd8a54b6a0d8b9f47d4d0b5e88629ed..ba511314494a0928397fdd5e6a478d9377da9c62 100644 (file)
@@ -280,7 +280,9 @@ date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time)
        int month, year;
        time_t secs;
 
-       month = ((date >> 5) & 15) - 1;
+       /* first subtract and mask after that... Otherwise, if
+          date == 0, bad things happen */
+       month = ((date >> 5) - 1) & 15;
        year = date >> 9;
        secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
            ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
@@ -299,6 +301,11 @@ date_unix2dos(struct smb_sb_info *server,
        int day, year, nl_day, month;
 
        unix_date = utc2local(server, unix_date);
+
+       /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
+       if (unix_date < 315532800)
+               unix_date = 315532800;
+
        *time = (unix_date % 60) / 2 +
                (((unix_date / 60) % 60) << 5) +
                (((unix_date / 3600) % 24) << 11);
index 8ed3a93423c8f551940ef5c648e737eea70e2efd..14c0b22f2679305c90b47806126a5964850581b8 100644 (file)
@@ -188,6 +188,7 @@ __asm__(".align 4\nvide: ret");
 __initfunc(static void check_amd_k6(void))
 {
        if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+           boot_cpu_data.x86 == 5 &&
            boot_cpu_data.x86_model == 6 &&
            boot_cpu_data.x86_mask == 1)
        {
index 5c4bef97a3a4675b09bb2e13b5c321c0b6ed22b9..8a6adceca4f217921a043c3504550b2a62418ee5 100644 (file)
@@ -510,20 +510,20 @@ do {                                                              \
                        "       popl %0\n"                      \
                        "       shl $2,%0\n"                    \
                        "       addl $3,%0\n"                   \
-                       "       jmp 2b\n"                       \
+                       "       jmp 3b\n"                       \
                        "5:     pushl %%eax\n"                  \
                        "       xorl %%eax,%%eax\n"             \
                        "       stosw\n"                        \
                        "       stosb\n"                        \
                        "       popl %%eax\n"                   \
                        "       addl $3,%0\n"                   \
-                       "       jmp 2b\n"                       \
+                       "       jmp 3b\n"                       \
                        "6:     pushl %%eax\n"                  \
                        "       xorl %%eax,%%eax\n"             \
                        "       stosb\n"                        \
                        "       popl %%eax\n"                   \
                        "       incl %0\n"                      \
-                       "       jmp 2b\n"                       \
+                       "       jmp 3b\n"                       \
                        ".previous\n"                           \
                        ".section __ex_table,\"a\"\n"           \
                        "       .align 4\n"                     \
index 3e3edd8b13b6af74eb938cefd066be74fa9e2b00..8b0180c063fe2905aabb331b8b4967fcf1aa7aef 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <asm/bitops.h>
 #include <asm/atomic.h>
+#include <asm/ptrace.h>
 
 struct irqaction {
        void (*handler)(int, void *, struct pt_regs *);
index 79339f33b48149b6284b2427a8593db3fbbb2a7a..ff7655468b77d565fa0d70d3fa3e8577fe416f97 100644 (file)
  * (and according to card ID within vendor). Send all updates to
  * <linux-pcisupport@cck.uni-kl.de>.
  */
+#define PCI_VENDOR_ID_DYNALINK          0x0675
+#define PCI_DEVICE_ID_DYNALINK_IS64PH   0x1702
+
+#define PCI_VENDOR_ID_BERKOM                   0x0871
+#define PCI_DEVICE_ID_BERKOM_A1T               0xFFA1
+#define PCI_DEVICE_ID_BERKOM_T_CONCEPT          0xFFA2
+#define PCI_DEVICE_ID_BERKOM_A4T               0xFFA4
+#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO      0xFFA8
+
 #define PCI_VENDOR_ID_COMPAQ           0x0e11
 #define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508
 #define PCI_DEVICE_ID_COMPAQ_1280      0x3033
 #define PCI_DEVICE_ID_CT_65554         0x00e4
 #define PCI_DEVICE_ID_CT_65555         0x00e5
 
+#define PCI_DEVICE_ID_PLX_R685         0x1030
+#define PCI_DEVICE_ID_PLX_DJINN_ITOO    0x1151
+#define PCI_DEVICE_ID_PLX_R753          0x1152
+
 #define PCI_VENDOR_ID_MIRO             0x1031
 #define PCI_DEVICE_ID_MIRO_36050       0x5601
 
 #define PCI_DEVICE_ID_OPTI_82C861      0xc861
 #define PCI_DEVICE_ID_OPTI_82C825      0xd568
 
+#define PCI_VENDOR_ID_ELSA             0x1048
+#define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
+#define PCI_DEVICE_ID_ELSA_QS3000      0x3000
+
 #define PCI_VENDOR_ID_SGS              0x104a
 #define PCI_DEVICE_ID_SGS_2000         0x0008
 #define PCI_DEVICE_ID_SGS_1764         0x0009
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2         0x1050
 #define PCI_DEVICE_ID_WINBOND2_89C940  0x0940
+#define PCI_DEVICE_ID_WINBOND2_6692    0x6692
+
+#define PCI_VENDOR_ID_ANIGMA           0x1051
+#define PCI_DEVICE_ID_ANIGMA_MC145575  0x0100
 
 #define PCI_VENDOR_ID_MOTOROLA         0x1057
 #define PCI_VENDOR_ID_MOTOROLA_OOPS    0x1507
 #define PCI_DEVICE_ID_PHILIPS_SAA7145  0x7145
 #define PCI_DEVICE_ID_PHILIPS_SAA7146  0x7146
 
+#define PCI_VENDOR_ID_EICON            0x1133
+#define PCI_DEVICE_ID_EICON_DIVA20PRO  0xe001
+#define PCI_DEVICE_ID_EICON_DIVA20     0xe002
+#define PCI_DEVICE_ID_EICON_DIVA20PRO_U        0xe003
+#define PCI_DEVICE_ID_EICON_DIVA20_U   0xe004
+#define PCI_DEVICE_ID_EICON_DIVA201    0xe005
+#define PCI_DEVICE_ID_EICON_MAESTRA    0xe010
+#define PCI_DEVICE_ID_EICON_MAESTRAQ   0xe012
+#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013
+#define PCI_DEVICE_ID_EICON_MAESTRAP   0xe014
+
 #define PCI_VENDOR_ID_CYCLONE          0x113c
 #define PCI_DEVICE_ID_CYCLONE_SDK      0x0001
 
 #define PCI_DEVICE_ID_DIGI_XRJ         0x0009
 #define PCI_DEVICE_ID_DIGI_EPCJ                0x000a
 #define PCI_DEVICE_ID_DIGI_XR_920      0x0027
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
+#define PCI_DEVICE_ID_DIGI_DF_M_E      0x0071
+#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
+#define PCI_DEVICE_ID_DIGI_DF_M_A      0x0073
 
 #define PCI_VENDOR_ID_MUTECH           0x1159
 #define PCI_DEVICE_ID_MUTECH_MV1000    0x0001
 
 #define PCI_VENDOR_ID_AVM              0x1244
 #define PCI_DEVICE_ID_AVM_A1           0x0a00
+#define PCI_DEVICE_ID_AVM_B1           0x0700
+#define PCI_DEVICE_ID_AVM_C4           0x0800
+#define PCI_DEVICE_ID_AVM_T1           0x1200
 
 #define PCI_VENDOR_ID_DIPIX            0x1246
 
 #define PCI_DEVICE_ID_OPTIBASE_VQUEST  0x2130
 
 #define PCI_VENDOR_ID_SATSAGEM         0x1267
+#define PCI_DEVICE_ID_SATSAGEM_NICCY   0x1016
 #define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
 #define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
 
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_650        0x2061
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_850        0x2062
 
+#define PCI_VENDOR_ID_HYPERCOPE                0x1365
+#define PCI_DEVICE_ID_HYPERCOPE_PLX    0x9050
+#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO     0x0104
+#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO         0x0106
+#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO        0x0107
+#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2       0x0108
+#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS       0x0109
+
 #define PCI_VENDOR_ID_NETGEAR          0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620    0x620a
 
+#define PCI_VENDOR_ID_CCD              0x1397
+#define PCI_DEVICE_ID_CCD_2BD0         0x2BD0
+#define PCI_DEVICE_ID_CCD_B000         0xB000
+#define PCI_DEVICE_ID_CCD_B006         0xB006
+#define PCI_DEVICE_ID_CCD_B007         0xB007
+#define PCI_DEVICE_ID_CCD_B008         0xB008
+#define PCI_DEVICE_ID_CCD_B009         0xB009
+#define PCI_DEVICE_ID_CCD_B00A         0xB00A
+#define PCI_DEVICE_ID_CCD_B00B         0xB00B
+#define PCI_DEVICE_ID_CCD_B00C         0xB00C
+#define PCI_DEVICE_ID_CCD_B100         0xB100
+
+#define PCI_VENDOR_ID_ABOCOM           0x13D1
+#define PCI_DEVICE_ID_ABOCOM_2BD1       0x2BD1
+
 #define PCI_VENDOR_ID_LAVA             0x1407
 #define PCI_DEVICE_ID_LAVA_PARALLEL    0x8000
 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_A  0x8002 /* The Lava Dual Parallel is */
 #define PCI_VENDOR_ID_AFAVLAB          0x14db
 #define PCI_DEVICE_ID_AFAVLAB_TK9902   0x2120
 
+#define PCI_VENDOR_ID_ZOLTRIX          0x15b0
+#define PCI_DEVICE_ID_ZOLTRIX_2BD0     0x2BD0
+
 #define PCI_VENDOR_ID_SYMPHONY         0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101     0x0001
 
 
 #define PCI_VENDOR_ID_TIGERJET         0xe159
 #define PCI_DEVICE_ID_TIGERJET_300     0x0001
+#define PCI_DEVICE_ID_TIGERJET_100     0x0002
 
 #define PCI_VENDOR_ID_ARK              0xedd8
 #define PCI_DEVICE_ID_ARK_STING                0xa091
index 450341b74628f1d1210029566e1453ba7f034810..21e8a6f6473fbddb4d29ccffc742cdbe87697927 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * SyncLink Multiprotocol Serial Adapter Driver
  *
- * ==FILEDATE 19990810==
+ * $Id: synclink.h,v 2.2 2000/11/08 17:08:30 paul Exp $
  *
- * Copyright (C) 1998 by Microgate Corporation
+ * Copyright (C) 1998-2000 by Microgate Corporation
  * 
  * Redistribution of this file is permitted under 
  * the terms of the GNU Public License (GPL)
@@ -11,6 +11,7 @@
 
 #ifndef _SYNCLINK_H_
 #define _SYNCLINK_H_
+#define SYNCLINK_H_VERSION 2.2
 
 #define BOOLEAN int
 #define TRUE 1
index 868f812acbfbd49c09d9bcfcb647770869f405a6..c552ff21b124bdc33f751aede9df93954d349749 100644 (file)
@@ -63,7 +63,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT   9
+#define WIRELESS_EXT   10
 
 /*
  * Changes :
  *     - Change encoding to support larger tokens (>64 bits)
  *     - Updated iw_params (disable, flags) and use it for NWID
  *     - Extracted iw_point from iwreq for clarity
+ *
+ * V9 to V10
+ * ---------
+ *     - Add PM capability to range structure
+ *     - Add PM modifier : MAX/MIN/RELATIVE
+ *     - Add encoding option : IW_ENCODE_NOKEY
+ *     - Add TxPower ioctls (work like TxRate)
  */
 
 /* -------------------------- IOCTL LIST -------------------------- */
 
 /* Basic operations */
-#define SIOCSIWNAME    0x8B00          /* Unused ??? */
-#define SIOCGIWNAME    0x8B01          /* get name */
+#define SIOCSIWNAME    0x8B00          /* Unused */
+#define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
 #define SIOCSIWNWID    0x8B02          /* set network id (the cell) */
 #define SIOCGIWNWID    0x8B03          /* get network id */
-#define SIOCSIWFREQ    0x8B04          /* set channel/frequency */
-#define SIOCGIWFREQ    0x8B05          /* get channel/frequency */
+#define SIOCSIWFREQ    0x8B04          /* set channel/frequency (Hz) */
+#define SIOCGIWFREQ    0x8B05          /* get channel/frequency (Hz) */
 #define SIOCSIWMODE    0x8B06          /* set operation mode */
 #define SIOCGIWMODE    0x8B07          /* get operation mode */
-#define SIOCSIWSENS    0x8B08          /* set sensitivity */
-#define SIOCGIWSENS    0x8B09          /* get sensitivity */
+#define SIOCSIWSENS    0x8B08          /* set sensitivity (dBm) */
+#define SIOCGIWSENS    0x8B09          /* get sensitivity (dBm) */
 
 /* Informative stuff */
-#define SIOCSIWRANGE   0x8B0A          /* Unused ??? */
+#define SIOCSIWRANGE   0x8B0A          /* Unused */
 #define SIOCGIWRANGE   0x8B0B          /* Get range of parameters */
-#define SIOCSIWPRIV    0x8B0C          /* Unused ??? */
+#define SIOCSIWPRIV    0x8B0C          /* Unused */
 #define SIOCGIWPRIV    0x8B0D          /* get private ioctl interface info */
 
 /* Mobile IP support */
 #define SIOCGIWRTS     0x8B23          /* get RTS/CTS threshold (bytes) */
 #define SIOCSIWFRAG    0x8B24          /* set fragmentation thr (bytes) */
 #define SIOCGIWFRAG    0x8B25          /* get fragmentation thr (bytes) */
+#define SIOCSIWTXPOW   0x8B26          /* set transmit power (dBm) */
+#define SIOCGIWTXPOW   0x8B27          /* get transmit power (dBm) */
 
 /* Encoding stuff (scrambling, hardware security, WEP...) */
 #define SIOCSIWENCODE  0x8B2A          /* set encoding token & mode */
 /* Maximum bit rates in the range struct */
 #define IW_MAX_BITRATES                8
 
+/* Maximum tx powers in the range struct */
+#define IW_MAX_TXPOWER         8
+
 /* Maximum of address that you may set with SPY */
 #define IW_MAX_SPY             8
 
 
 /* Flags for encoding (along with the token) */
 #define IW_ENCODE_INDEX                0x00FF  /* Token index (if needed) */
-#define IW_ENCODE_FLAGS                0xF000  /* Flags defined below */
+#define IW_ENCODE_FLAGS                0xFF00  /* Flags defined below */
+#define IW_ENCODE_MODE         0xF000  /* Modes defined below */
 #define IW_ENCODE_DISABLED     0x8000  /* Encoding disabled */
 #define IW_ENCODE_ENABLED      0x0000  /* Encoding enabled */
 #define IW_ENCODE_RESTRICTED   0x4000  /* Refuse non-encoded packets */
 #define IW_ENCODE_OPEN         0x2000  /* Accept non-encoded packets */
+#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
 
 /* Power management flags available (along with the value, if any) */
 #define IW_POWER_ON            0x0000  /* No details... */
 #define IW_POWER_ALL_R         0x0300  /* Receive all messages though PM */
 #define IW_POWER_FORCE_S       0x0400  /* Force PM procedure for sending unicast */
 #define IW_POWER_REPEATER      0x0800  /* Repeat broadcast messages in PM period */
+#define IW_POWER_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_POWER_MIN           0x0001  /* Value is a minimum  */
+#define IW_POWER_MAX           0x0002  /* Value is a maximum */
+#define IW_POWER_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+
+/* Transmit Power flags available */
+#define IW_TXPOW_DBM           0x0000  /* Value is in dBm */
+#define IW_TXPOW_MWATT         0x0001  /* Value is in mW */
 
 /****************************** TYPES ******************************/
 
@@ -359,6 +381,7 @@ struct      iwreq
 
                struct iw_param sens;           /* signal level threshold */
                struct iw_param bitrate;        /* default bit rate */
+               struct iw_param txpower;        /* default transmit power */
                struct iw_param rts;            /* RTS threshold threshold */
                struct iw_param frag;           /* Fragmentation threshold */
                __u32           mode;           /* Operation mode */
@@ -422,15 +445,23 @@ struct    iw_range
        __s32           max_frag;       /* Maximal frag threshold */
 
        /* Power Management duration & timeout */
-       __s32           min_pmd;        /* Minimal PM duration */
-       __s32           max_pmd;        /* Maximal PM duration */
+       __s32           min_pmp;        /* Minimal PM period */
+       __s32           max_pmp;        /* Maximal PM period */
        __s32           min_pmt;        /* Minimal PM timeout */
        __s32           max_pmt;        /* Maximal PM timeout */
+       __u16           pmp_flags;      /* How to decode max/min PM period */
+       __u16           pmt_flags;      /* How to decode max/min PM timeout */
+       __u16           pm_capa;        /* What PM options are supported */
 
        /* Encoder stuff */
        __u16   encoding_size[IW_MAX_ENCODING_SIZES];   /* Different token sizes */
        __u8    num_encoding_sizes;     /* Number of entry in the list */
        __u8    max_encoding_tokens;    /* Max number of tokens */
+
+       /* Transmit power */
+       __u16           txpower_capa;   /* What options are supported */
+       __u8            num_txpower;    /* Number of entries in the list */
+       __s32           txpower[IW_MAX_TXPOWER];        /* list, in bps */
 };
 
 /*
index 4a33fa8fe85060781de7070a5f22bd75a6be7e3a..b978f2a207f13556fcde2eb4fc48948f6e20d42d 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -340,6 +340,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
                        shp->u.shm_perm.mode |= SHM_DEST;
                        if (shp->u.shm_nattch <= 0)
                                killseg (id);
+                       /* Do not find it any more */
+                       shp->u.shm_perm.key = IPC_PRIVATE;
                        break;
                }
                err = -EPERM;
index eec81bbbee05a13452f5a78134e5345040c9a9d7..1212d7526f61b5a97faa73e5fc3a0a5a60668528 100644 (file)
@@ -422,7 +422,18 @@ function define_string () {
 function string () {
        old=$(eval echo "\${$2}")
        def=${old:-$3}
-       readln "$1 ($2) [$def] " "$def" "$old"
+       while :; do
+          if [ "$old" = "?" ]; then
+             readln "$1 ($2) [$def] " "$def" ""
+          else
+            readln "$1 ($2) [$def] " "$def" "$old"
+          fi
+         if [ "$ans" = "?" ]; then
+           help "$2"
+         else
+           break
+         fi
+       done
        define_string "$2" "$ans"
 }
 #