]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.82 2.1.82
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:14:35 +0000 (15:14 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:14:35 +0000 (15:14 -0500)
138 files changed:
Documentation/Configure.help
Documentation/cdrom/ide-cd
Documentation/paride.txt
Makefile
arch/alpha/config.in
arch/alpha/defconfig
arch/alpha/kernel/apecs.c
arch/alpha/kernel/cia.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/pyxis.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/t2.c
arch/i386/config.in
arch/i386/defconfig
arch/i386/kernel/i386_ksyms.c
arch/i386/kernel/irq.c
arch/i386/kernel/mca.c
arch/i386/kernel/time.c
arch/i386/math-emu/fpu_entry.c
arch/i386/math-emu/get_address.c
arch/i386/math-emu/reg_ld_str.c
drivers/block/Config.in
drivers/block/ide-cd.c
drivers/block/ide-proc.c
drivers/block/paride/Config.in
drivers/block/paride/Makefile
drivers/block/paride/paride.c
drivers/block/paride/pcd.c
drivers/block/paride/pd.c
drivers/block/paride/pt.c [new file with mode: 0644]
drivers/cdrom/cdrom.c
drivers/cdrom/cdu31a.c
drivers/cdrom/cm206.c
drivers/cdrom/mcd.c
drivers/cdrom/sbpcd.c
drivers/char/Config.in
drivers/char/ftape/lowlevel/fdc-io.c
drivers/char/keyboard.c
drivers/char/lp.c
drivers/isdn/avmb1/b1capi.c
drivers/isdn/hisax/config.c
drivers/isdn/pcbit/module.c
drivers/isdn/sc/hardware.h
drivers/isdn/sc/includes.h
drivers/isdn/sc/init.c
drivers/misc/BUGS-parport
drivers/misc/Makefile
drivers/misc/TODO-parport
drivers/misc/parport_arc.c
drivers/misc/parport_ax.c
drivers/misc/parport_init.c
drivers/misc/parport_pc.c
drivers/misc/parport_procfs.c
drivers/misc/parport_share.c
drivers/net/de4x5.c
drivers/net/dgrs.c
drivers/net/hamradio/soundmodem/gentbl.c
drivers/net/ne.c
drivers/net/ppp.c
drivers/net/ppp_deflate.c
drivers/net/slhc.c
drivers/net/tulip.c
drivers/pci/Makefile
drivers/pci/oldproc.c [new file with mode: 0644]
drivers/pci/pci.c
drivers/pci/proc.c [new file with mode: 0644]
drivers/pnp/parport_probe.c
drivers/scsi/NCR5380.c
drivers/scsi/hosts.c
drivers/sound/audio.c
drivers/sound/sb_mixer.h
drivers/sound/softoss.c
fs/adfs/inode.c
fs/bad_inode.c
fs/filesystems.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/nfs/nfs2xdr.c
fs/nfs/write.c
fs/nfsd/nfsproc.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
fs/nls/nls_cp862.c
fs/nls/nls_cp863.c
fs/nls/nls_cp864.c
fs/nls/nls_cp865.c
fs/nls/nls_cp866.c
fs/nls/nls_cp869.c
fs/nls/nls_cp874.c
fs/nls/nls_iso8859-1.c
fs/nls/nls_iso8859-2.c
fs/nls/nls_iso8859-3.c
fs/nls/nls_iso8859-4.c
fs/nls/nls_iso8859-5.c
fs/nls/nls_iso8859-6.c
fs/nls/nls_iso8859-7.c
fs/nls/nls_iso8859-8.c
fs/nls/nls_iso8859-9.c
fs/nls/nls_koi8-r.c
fs/proc/array.c
fs/proc/root.c
fs/sysv/CHANGES [new file with mode: 0644]
fs/sysv/inode.c
fs/sysv/namei.c
fs/ufs/ufs_swab.c
include/asm-alpha/mman.h
include/asm-alpha/smp.h
include/asm-alpha/softirq.h
include/asm-alpha/types.h
include/asm-alpha/unistd.h
include/asm-i386/softirq.h
include/asm-i386/types.h
include/asm-m68k/types.h
include/asm-mips/types.h
include/linux/adfs_fs.h
include/linux/adfs_fs_fs.h
include/linux/affs_fs.h
include/linux/isdn.h
include/linux/lp.h
include/linux/nfs.h
include/linux/nfs_fs.h
include/linux/nfs_fs_i.h
include/linux/nls.h
include/linux/parport.h
include/linux/parport_pc.h [new file with mode: 0644]
include/linux/pci.h
include/linux/proc_fs.h
include/linux/sched.h
include/linux/smb_fs.h
init/main.c
kernel/ksyms.c
kernel/signal.c
net/packet/af_packet.c
net/socket.c
net/wanrouter/wanmain.c
net/wanrouter/wanproc.c

index bc8e754778d5633862f6689f93adeb3084aef955..854c49b81e97ba74cb6803dfaf730c535450df98 100644 (file)
@@ -479,6 +479,17 @@ CONFIG_PARIDE_PF
   MicroSolutions backpack PD/CD drive and the Imation Superdisk
   LS-120 drive.
 
+Parallel port ATAPI tapes
+CONFIG_PARIDE_PT
+  This option enable the high-level driver for ATAPI tape devices
+  connected through a parallel port.  If you chose to build PARIDE
+  support into your kernel, you may answer Y here to build in the
+  parallel port ATAPI disk driver, otherwise you should answer M
+  to build it as a loadable module.  The module will be called pt.o.
+  You must also have at least one parallel port protocol driver in
+  your system.  Among the devices supported by this driver is the
+  parallel port version of the HP 5GB drive.
+
 ATEN EH-100 protocol
 CONFIG_PARIDE_ATEN 
   This option enables support for the ATEN EH-100 parallel port IDE
@@ -1182,6 +1193,12 @@ CONFIG_PARPORT_AX
   Ultra/AX machines.  This code is also available as a module (say M),
   called parport_ax.o.  If in doubt, saying N is the safe plan.
 
+Foreign parallel hardware
+CONFIG_PARPORT_OTHER
+  Say Y here if you want to be able to load driver modules to support
+  other types of parallel port.  This causes a performance loss, so most
+  people say N.
+
 Compile the kernel into the ELF object format 
 CONFIG_ELF_KERNEL
   ELF (Executable and Linkable Format) is a format for libraries and
index 70384d975cd98fa9c222a6672bfac90d5639622f..d6ceef8a5e1d340fa267eb42ab1209c00f3a41ec 100644 (file)
@@ -1,12 +1,12 @@
 IDE-CD driver documentation
-19 May 1996
-scott snyder  <snyder@fnald0.fnal.gov>
+Originally by scott snyder  <snyder@fnald0.fnal.gov> (19 May 1996)
+Carrying on the torch is: Erik Andersen <andersee@debian.org>
 
 1. Introduction
 ---------------
 
-The ide-cd driver should work with all ATAPI 1.2 compliant cdrom
-drives which attach to an IDE interface.  Note that some cdrom vendors
+The ide-cd driver should work with all ATAPI ver 1.2 to ATAPI 2.6 compliant 
+cdrom drives which attach to an IDE interface.  Note that some cdrom vendors
 (including Mitsumi, Sony, Creative, Aztech, and Goldstar) have made
 both ATAPI-compliant drives and drives which use a proprietary
 interface.  If your drive uses one of those proprietary interfaces,
@@ -28,9 +28,7 @@ This driver provides the following features:
 
  - On drives which support it, reading digital audio data directly
    from audio tracks.  The program cdda2wav can be used for this.
-   Note, however, that only a few drives actually support this
-   function; the only ones which i've heard of successes with are Sony
-   and Toshiba drives.
+   Note, however, that only some drives actually support this.
 
  - There is now support for cdrom changers which comply with the 
    ATAPI 2.6 draft standard (such as the NEC CDR-251).  This additional
@@ -50,10 +48,13 @@ This driver provides the following features:
    driver.
 
 1. Make sure that the ide and ide-cd drivers are compiled into the
-   kernel you're using.  When configuring the kernel, say `yes' to the
-   options 
+   kernel you're using.  When configuring the kernel, in the section 
+   entitled "Floppy, IDE, and other block devices", say either `Y' 
+   (which will compile the support directly into the kernel) or `M'
+   (to compile support as a module which can be loaded and unloaded)
+   to the options: 
 
-      Enhanced IDE/MFM/RLL disk/cdrom/tape support
+      Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
       Include IDE/ATAPI CDROM support
 
    and `no' to
@@ -74,8 +75,8 @@ This driver provides the following features:
    address and an IRQ number, the standard assignments being
    0x170 and 14 for the primary interface and 0x1f0 and 15 for the
    secondary interface.  Each interface can control up to two devices,
-   where each device can be either a hard drive, a cdrom drive, or a
-   tape drive.  The two devices on an interface are called `master'
+   where each device can be a hard drive, a cdrom drive, a floppy drive, 
+   or a tape drive.  The two devices on an interface are called `master'
    and `slave'; this is usually selectable via a jumper on the drive.
 
    Linux names these devices as follows.  The master and slave devices
@@ -223,7 +224,9 @@ a. Drive is not detected during booting.
    - If the autoprobing is not finding your drive, you can tell the
      driver to assume that one exists by using a lilo option of the
      form `hdX=cdrom', where X is the drive letter corresponding to
-     where your drive is installed (see section 2).  Note that if you
+     where your drive is installed (see section 2). This is required
+     for CDROM drives such as the Pioneer DR-A24X, which do not properly
+     identify themselves as ATAPI CDROM drives.  Note that if you
      do this and you see a boot message like
 
        hdX: ATAPI cdrom (?)
index 1a6b464001744aa748ac3f4d2845f3b80c83912b..923377cad69e2cdce311deed1402991b88233a48 100644 (file)
@@ -55,7 +55,7 @@ high-level drivers for each of the different type of supported device:
        pd      IDE disk
        pcd     ATAPI CD-ROM
        pf      ATAPI disk
-       pt      ATAPI tape      (not yet available)
+       pt      ATAPI tape
 
 (Support for ATAPI CD-R and CD-RW drives is not yet in development,
 but this may change.)
index cbd64778738ce9674507d69daeae49904940868c..303abea28d1ad35247ee4d844f2f0f4b6edc544d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 81
+SUBLEVEL = 82
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
@@ -211,21 +211,29 @@ symlinks:
 
 oldconfig: symlinks scripts/split-include
        $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
-       scripts/split-include include/linux/autoconf.h include/config
+       if [ -r include/linux/autoconf.h ]; then \
+           scripts/split-include include/linux/autoconf.h include/config; \
+       fi
 
 xconfig: symlinks scripts/split-include
        $(MAKE) -C scripts kconfig.tk
        wish -f scripts/kconfig.tk
-       scripts/split-include include/linux/autoconf.h include/config
+       if [ -r include/linux/autoconf.h ]; then \
+           scripts/split-include include/linux/autoconf.h include/config; \
+       fi
 
 menuconfig: include/linux/version.h symlinks scripts/split-include
        $(MAKE) -C scripts/lxdialog all
        $(CONFIG_SHELL) scripts/Menuconfig arch/$(ARCH)/config.in
-       scripts/split-include include/linux/autoconf.h include/config
+       if [ -r include/linux/autoconf.h ]; then \
+           scripts/split-include include/linux/autoconf.h include/config; \
+       fi
 
 config: symlinks scripts/split-include
        $(CONFIG_SHELL) scripts/Configure arch/$(ARCH)/config.in
-       scripts/split-include include/linux/autoconf.h include/config
+       if [ -r include/linux/autoconf.h ]; then \
+           scripts/split-include include/linux/autoconf.h include/config; \
+       fi
 
 linuxsubdirs: dummy
        set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done
index 67427be1b18a7ceb88a95a875c88a8494673b15b..bfad551993bad80780ee6a96bc4203fca3467cf6 100644 (file)
@@ -141,6 +141,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool 'PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
   fi
+  bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
 fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
@@ -155,6 +156,9 @@ tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate '  PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+  if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+    bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
+  fi
 fi
 endmenu
 
index 9f8cde775eeabe504a3226c151301e128eb1a770..64acd645b8116eac9deb407d279c9a93d02918b9 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_NATIVE=y
 CONFIG_ALPHA_ALCOR=y
 # CONFIG_ALPHA_P2K is not set
 CONFIG_PCI=y
+CONFIG_PCI_OLD_PROC=y
 CONFIG_ALPHA_EV5=y
 CONFIG_ALPHA_CIA=y
 CONFIG_ALPHA_SRM=y
index 93c55b9262c59ce5e5d39142b843d91e7ddb6911..d5e7fa2a71b89b602c428639856f3f53639f22c9 100644 (file)
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic. 
+   A plausible explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
@@ -162,6 +166,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
        /* access configuration space: */
        value = *(vuip)addr;
        mb();
+       mb();  /* magic */
        if (apecs_mcheck_taken) {
                apecs_mcheck_taken = 0;
                value = 0xffffffffU;
@@ -242,6 +247,7 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ
        /* access configuration space: */
        *(vuip)addr = value;
        mb();
+       mb();  /* magic */
        apecs_mcheck_expected = 0;
        mb();
 
@@ -539,7 +545,7 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
                apecs_mcheck_expected = 0;
                apecs_mcheck_taken = 1;
                mb();
-               mb();
+               mb(); /* magic */
                apecs_pci_clr_err();
                wrmces(0x7);
                mb();
index 7ea930e5a0c092f846e1e20e68c6ddc00abefbef..4bebe2732288a0479cc8fce7abf6af572e64ceeb 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic.
+   A plausible explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
@@ -170,6 +174,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
        /* access configuration space: */
        value = *(vuip)addr;
        mb();
+       mb();  /* magic */
        if (CIA_mcheck_taken) {
                CIA_mcheck_taken = 0;
                value = 0xffffffffU;
@@ -244,6 +249,7 @@ static void conf_write(unsigned long addr, unsigned int value,
        /* access configuration space: */
        *(vuip)addr = value;
        mb();
+       mb();  /* magic */
 
        CIA_mcheck_expected = 0;
        mb();
@@ -555,12 +561,13 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
         * ignore the machine check.
         */
        mb();
+       mb();  /* magic */
        if (CIA_mcheck_expected) {
                DBGM(("CIA machine check expected\n"));
                CIA_mcheck_expected = 0;
                CIA_mcheck_taken = 1;
                mb();
-               mb();
+               mb();  /* magic */
                draina();
                cia_pci_clr_err();
                wrmces(0x7);
index 222d042ed9992d35bf9d772afca38c3500130465..cd8541380a82cd6bc77e5a8f19e2317317cc02ca 100644 (file)
@@ -950,7 +950,7 @@ sys_call_table:
        .quad sys_semget                        /* 205 */
        .quad sys_semop
        .quad osf_utsname
-       .quad alpha_ni_syscall
+       .quad sys_lchown
        .quad osf_shmat
        .quad sys_shmctl                        /* 210 */
        .quad sys_shmdt
index f94915bb29a4b9bb9418178be751460a3d09c9ad..f1bfa1bef885f37649ab849489cbc6cf0f0ed73e 100644 (file)
@@ -373,7 +373,7 @@ int get_irq_list(char *buf)
                if (!action) 
                        continue;
                len += sprintf(buf+len, "%2d: %10u %c %s",
-                              i, kstat.interrupts[0][i],
+                              i, kstat.irqs[0][i],
                               (action->flags & SA_INTERRUPT) ? '+' : ' ',
                               action->name);
                for (action=action->next; action; action = action->next) {
@@ -567,7 +567,7 @@ static inline void handle_irq(int irq, struct pt_regs * regs)
        int cpu = smp_processor_id();
 
        irq_enter(cpu, irq);
-       kstat.interrupts[0][irq] += 1;
+       kstat.irqs[0][irq] += 1;
        if (!action) {
                unexpected_irq(irq, regs);
        } else {
@@ -590,7 +590,7 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
        }
 
        irq_enter(cpu, irq);
-       kstat.interrupts[0][irq] += 1;
+       kstat.irqs[0][irq] += 1;
        action = irq_action[irq];
        /*
         * For normal interrupts, we mask it out, and then ACK it.
index 9b430d148738a6b2db71fc743e6f84093941a1b8..d1a96fc9da077f2c91740e6cfab746bd21a6d7af 100644 (file)
@@ -246,7 +246,7 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
        unsigned long ret = -EBADF;
 
        lock_kernel();
-       if (flags & (MAP_HASSEMAPHORE | MAP_INHERIT | MAP_UNALIGNED))
+       if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
                printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
        if (!(flags & MAP_ANONYMOUS)) {
                if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
index cbfd96d2a3d208e920a648069949f6f4f0504ba4..1e695dc3fdc16c726a305f39de8085e495fb060e 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic.
+   A plausible explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern int alpha_sys_type;
@@ -153,6 +157,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
        /* access configuration space: */
        value = *(vuip)addr;
        mb();
+       mb();  /* magic */
        if (PYXIS_mcheck_taken) {
                PYXIS_mcheck_taken = 0;
                value = 0xffffffffU;
@@ -228,6 +233,7 @@ static void conf_write(unsigned long addr, unsigned int value,
        /* access configuration space: */
        *(vuip)addr = value;
        mb();
+       mb();  /* magic */
        PYXIS_mcheck_expected = 0;
        mb();
 
@@ -473,11 +479,13 @@ void pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
         * ignore the machine check.
         */
        mb();
+       mb();  /* magic */
        if (PYXIS_mcheck_expected/* && (mchk_sysdata->epic_dcsr && 0x0c00UL)*/) {
                DBG(("PYXIS machine check expected\n"));
                PYXIS_mcheck_expected = 0;
                PYXIS_mcheck_taken = 1;
                mb();
+               mb();  /* magic */
                draina();
                pyxis_pci_clr_err();
                wrmces(0x7);
@@ -494,6 +502,7 @@ void pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
                PYXIS_mcheck_expected = 0;
                PYXIS_mcheck_taken = 1;
                mb();
+               mb();  /* magic */
                draina();
                pyxis_pci_clr_err();
                wrmces(0x7);
index 1d4e8931d4e4d5f59a4b265acf6d44bb9b7bceec..1943b26f7179cd2453cb916288cf7ad02d186556 100644 (file)
@@ -116,7 +116,7 @@ osf_sigaction(int sig, const struct osf_sigaction *act,
 
 asmlinkage int 
 sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
-                void *restorer, size_t sigsetsize)
+                size_t sigsetsize, void *restorer)
 {
        struct k_sigaction new_ka, old_ka;
        int ret;
index 76ed4dd14059e3b7ba948c6bfb4ad36f79b11c36..db3e29939c1561679df642de6d131a40080579c5 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/mmu_context.h>
 
+/* NOTE: Herein are back-to-back mb insns.  They are magic.
+   A plausable explanation is that the i/o controler does not properly
+   handle the system transaction.  Another involves timing.  Ho hum.  */
+
 extern struct hwrpb_struct *hwrpb;
 extern asmlinkage void wrmces(unsigned long mces);
 extern asmlinkage unsigned long whami(void);
@@ -173,6 +177,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
        /* access configuration space: */
        value = *(vuip)addr;
        mb();
+       mb();  /* magic */
        if (T2_mcheck_taken) {
                T2_mcheck_taken = 0;
                value = 0xffffffffU;
@@ -226,6 +231,7 @@ static void conf_write(unsigned long addr, unsigned int value,
        /* access configuration space: */
        *(vuip)addr = value;
        mb();
+       mb();  /* magic */
        T2_mcheck_expected = 0;
        mb();
 
@@ -480,6 +486,7 @@ int t2_clear_errors(void)
        *(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
 
        mb();
+       mb();  /* magic */
        return 0;
 }
 
@@ -530,12 +537,14 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
         * ignore the machine check.
         */
        mb();
+       mb();  /* magic */
        if (T2_mcheck_expected/* && (mchk_sysdata->epic_dcsr && 0x0c00UL)*/) {
                DBGMC(("T2 machine check expected\n"));
                T2_mcheck_taken = 1;
                t2_clear_errors();
                T2_mcheck_expected = 0;
                mb();
+               mb();  /* magic */
                wrmces(rdmces()|1);/* ??? */
                draina();
                return;
index f279cde8d82b661914db23953b98caa52d219285..8f0582c93b2c29230c194a7a34174b93c1012e07 100644 (file)
@@ -39,6 +39,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
   fi
+  bool '   Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
 fi
 bool 'MCA support' CONFIG_MCA
 bool 'System V IPC' CONFIG_SYSVIPC
@@ -56,6 +57,9 @@ bool 'Video mode selection support' CONFIG_VIDEO_SELECT
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate '   PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+  if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+    bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
+  fi
 fi
 
 endmenu
index 11c398cba8be121289a13f0395eeb3d2905f57ed..2ca6da6bc4fc020cde6ecb725024c5a54ac7d831 100644 (file)
@@ -30,6 +30,8 @@ CONFIG_NET=y
 CONFIG_PCI=y
 CONFIG_PCI_BIOS=y
 CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_OPTIMIZE is not set
+CONFIG_PCI_OLD_PROC=y
 # CONFIG_MCA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
index ab85b2df407fcdb6ed13a5a1f8c27f5891676c46..4b03fc40378a7ddb7ab2179883846db6ab5e2b85 100644 (file)
@@ -35,11 +35,11 @@ EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
-EXPORT_SYMBOL(global_bh_lock);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 /* Delay loops */
@@ -73,6 +73,8 @@ EXPORT_SYMBOL(lk_lockmsg);
 
 /* Global SMP irq stuff */
 EXPORT_SYMBOL(synchronize_irq);
+EXPORT_SYMBOL(synchronize_bh);
+EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
index ac83e4c7d6c288a7e3d05c1f34d9e802e559a7b5..16c97d94659201c1b09facd335d984aa6bacd517 100644 (file)
@@ -639,6 +639,7 @@ static void do_8259A_IRQ(int irq, int cpu, struct pt_regs * regs)
        irq_exit(cpu, irq);
 }
 
+#ifdef __SMP__
 /*
  * FIXME! This is completely broken.
  */
@@ -679,6 +680,7 @@ again:
 
        enable_IO_APIC_irq(irq);
 }
+#endif
 
 /*
  * do_IRQ handles all normal device IRQ's (the special
@@ -714,8 +716,10 @@ asmlinkage void do_IRQ(struct pt_regs regs)
        kstat.irqs[cpu][irq]++;
 
        do_lowlevel_IRQ = do_8259A_IRQ;
+#ifdef __SMP__
        if (IO_APIC_IRQ(irq))
                do_lowlevel_IRQ = do_ioapic_IRQ;
+#endif
        
        do_lowlevel_IRQ(irq, cpu, &regs);
 
index 1f8d0799dfca5adb91dbfb896e422f9c77899f3b..de6de8f145187e1bf3dc71aab27c53195897f1d8 100644 (file)
@@ -65,7 +65,7 @@ static struct MCA_info* mca_info = 0;
 static long mca_do_proc_init( long memory_start, long memory_end );
 static int mca_default_procfn( char* buf, int slot );
 
-static long proc_mca_read( struct inode*, struct file*, char* buf, unsigned long count );
+static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *);
 static struct file_operations proc_mca_operations = {
        NULL, proc_mca_read,
        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
@@ -527,7 +527,7 @@ static int mca_not_implemented( char* buf )
 */
 
 static int mca_fill( char* page, int pid, int type, char** start,
-       off_t offset, int length)
+       loff_t *offset, int length)
 {
        int len = 0;
        int slot = 0;
@@ -571,8 +571,8 @@ static int mca_fill( char* page, int pid, int type, char** start,
 
 #define PROC_BLOCK_SIZE        (3*1024)
 
-long proc_mca_read( struct inode* inode, struct file* file,
-       char* buf, unsigned long count)
+static ssize_t proc_mca_read( struct file* file,
+       char* buf, size_t count, loff_t *ppos)
 {
        unsigned long page;
        char *start;
@@ -580,6 +580,7 @@ long proc_mca_read( struct inode* inode, struct file* file,
        int end;
        unsigned int type, pid;
        struct proc_dir_entry *dp;
+       struct inode *inode = file->f_dentry->d_inode;
 
        if (count < 0)
                return -EINVAL;
@@ -593,7 +594,7 @@ long proc_mca_read( struct inode* inode, struct file* file,
        start = 0;
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
        length = mca_fill((char *) page, pid, type,
-                           &start, file->f_pos, count);
+                           &start, ppos, count);
        if (length < 0) {
                free_page(page);
                return length;
@@ -601,19 +602,19 @@ long proc_mca_read( struct inode* inode, struct file* file,
        if (start != 0) {
                /* We have had block-adjusting processing! */
                copy_to_user(buf, start, length);
-               file->f_pos += length;
+               *ppos += length;
                count = length;
        } else {
                /* Static 4kB (or whatever) block capacity */
-               if (file->f_pos >= length) {
+               if (*ppos >= length) {
                        free_page(page);
                        return 0;
                }
-               if (count + file->f_pos > length)
-                       count = length - file->f_pos;
-               end = count + file->f_pos;
-               copy_to_user(buf, (char *) page + file->f_pos, count);
-               file->f_pos = end;
+               if (count + *ppos > length)
+                       count = length - *ppos;
+               end = count + *ppos;
+               copy_to_user(buf, (char *) page + *ppos, count);
+               *ppos = end;
        }
        free_page(page);
        return count;
index 5d7d3a6fe62cf6af8418b51fcebf7aadbe6a5a20..a05292d6d2b33739ea91576c0ae39c8298975094 100644 (file)
@@ -248,6 +248,7 @@ static unsigned long do_slow_gettimeoffset(void)
        return count;
 }
 
+#ifndef CONFIG_APM
 /*
  * this is only used if we have fast gettimeoffset:
  */
@@ -255,6 +256,7 @@ static void do_x86_get_fast_time(struct timeval * tv)
 {
        do_gettimeofday(tv);
 }
+#endif
 
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
index 36ca90a35107184e044e397f65a805484f08acec..f120bbc4973967912645aed3b2215890cb385d41 100644 (file)
@@ -728,11 +728,11 @@ struct _fpstate * save_i387_soft(void *s387, struct _fpstate * buf)
   FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
 #ifdef PECULIAR_486
   S387->cwd &= ~0xe080;
-  /* An 80486 sets all the reserved bits to 1. */
-  S387->cwd |= 0xffff0000;
+  /* An 80486 sets nearly all of the reserved bits to 1. */
+  S387->cwd |= 0xffff0040;
   S387->swd = sstatus_word() | 0xffff0000;
   S387->twd |= 0xffff0000;
-  S387->fcs |= 0xf8000000;
+  S387->fcs &= ~0xf8000000;
   S387->fos |= 0xffff0000;
 #endif PECULIAR_486
   __copy_to_user(d, &S387->cwd, 7*4);
index 799bc1c416b151d86c5f3380db7bf43ddae79380..a4b15ee7f50aff479b08e815bb16a8d9b8050477 100644 (file)
@@ -134,8 +134,8 @@ static int sib(int mod, unsigned long *fpu_eip)
 
 
 static unsigned long vm86_segment(u_char segment,
-                                 unsigned short *selector)
-{ 
+                                 struct address *addr)
+{
   segment--;
 #ifdef PARANOID
   if ( segment > PREFIX_SS_ )
@@ -144,14 +144,14 @@ static unsigned long vm86_segment(u_char segment,
       math_abort(FPU_info,SIGSEGV);
     }
 #endif PARANOID
-  *selector = VM86_REG_(segment);
+  addr->selector = VM86_REG_(segment);
   return (unsigned long)VM86_REG_(segment) << 4;
 }
 
 
 /* This should work for 16 and 32 bit protected mode. */
 static long pm_address(u_char FPU_modrm, u_char segment,
-                      unsigned short *selector, long offset)
+                      struct address *addr, long offset)
 { 
   struct desc_struct descriptor;
   unsigned long base_address, limit, address, seg_top;
@@ -172,13 +172,17 @@ static long pm_address(u_char FPU_modrm, u_char segment,
       /* fs and gs aren't used by the kernel, so they still have their
         user-space values. */
     case PREFIX_FS_-1:
-      __asm__("mov %%fs,%0":"=r" (*selector));
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+        in the assembler statement. */
+      __asm__("mov %%fs,%0":"=r" ((unsigned short)addr->selector));
       break;
     case PREFIX_GS_-1:
-      __asm__("mov %%gs,%0":"=r" (*selector));
+      /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
+        in the assembler statement. */
+      __asm__("mov %%gs,%0":"=r" ((unsigned short)addr->selector));
       break;
     default:
-      *selector = PM_REG_(segment);
+      addr->selector = PM_REG_(segment);
     }
 
   descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
@@ -312,13 +316,12 @@ void *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
     case 0:
       break;
     case VM86:
-      address += vm86_segment(addr_modes.override.segment,
-                             (unsigned short *)&(addr->selector));
+      address += vm86_segment(addr_modes.override.segment, addr);
       break;
     case PM16:
     case SEG32:
       address = pm_address(FPU_modrm, addr_modes.override.segment,
-                          (unsigned short *)&(addr->selector), address);
+                          addr, address);
       break;
     default:
       EXCEPTION(EX_INTERNAL|0x133);
@@ -427,13 +430,12 @@ void *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
     case 0:
       break;
     case VM86:
-      address += vm86_segment(addr_modes.override.segment,
-                             (unsigned short *)&(addr->selector));
+      address += vm86_segment(addr_modes.override.segment, addr);
       break;
     case PM16:
     case SEG32:
       address = pm_address(FPU_modrm, addr_modes.override.segment,
-                          (unsigned short *)&(addr->selector), address);
+                          addr, address);
       break;
     default:
       EXCEPTION(EX_INTERNAL|0x131);
index 468e51cc8601cfcd19f44dfb369e714df8f09fdd..b3ed9acbb712e2fcaaef70adc4feb92f9104c27d 100644 (file)
@@ -1329,11 +1329,11 @@ u_char *fstenv(fpu_addr_modes addr_modes, u_char *d)
       FPU_verify_area(VERIFY_WRITE, d, 7*4);
 #ifdef PECULIAR_486
       control_word &= ~0xe080;
-      /* An 80486 sets all the reserved bits to 1. */
-      control_word |= 0xffff0000;
+      /* An 80486 sets nearly all of the reserved bits to 1. */
+      control_word |= 0xffff0040;
       partial_status = status_word() | 0xffff0000;
       fpu_tag_word |= 0xffff0000;
-      I387.soft.fcs |= 0xf8000000;
+      I387.soft.fcs &= ~0xf8000000;
       I387.soft.fos |= 0xffff0000;
 #endif PECULIAR_486
       __copy_to_user(d, &control_word, 7*4);
index 0597ea3d677c8e05ac416ef5b236d4f219047da4..10e9f56d08c69eac145860959858d4bcab779bd4 100644 (file)
@@ -71,13 +71,17 @@ if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
 fi
 tristate 'XT harddisk support' CONFIG_BLK_DEV_XD
 
+# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
+# PARIDE must also be a module.  The bogus CONFIG_PARIDE_PARPORT option
+# controls the choices given to the user ...
+
 if [ "$CONFIG_PARPORT" = "y" -o "$CONFIG_PARPORT" = "n" ] ; then
    define_bool CONFIG_PARIDE_PARPORT y
 else
    define_bool CONFIG_PARIDE_PARPORT m
 fi
 dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARIDE_PARPORT
-if [ "$CONFIG_PARIDE" != "n" ]; then
+if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   source drivers/block/paride/Config.in
 fi
 
index caf334d27d56f0bcaf35e99e361c2feead829918..d477b7eba8d542dff58f35d8af141e0ff87d71f8 100644 (file)
@@ -3,13 +3,14 @@
  * linux/drivers/block/ide-cd.c
  * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
  * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
+ *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  *
  * ATAPI CD-ROM driver.  To be used with ide.c.
  * See Documentation/cdrom/ide-cd for usage information.
  *
- * Suggestions are welcome. Patches that work are more welcome though.
+ * Suggestions are welcome. Patches that work are more welcome though. ;-)
  * For those wishing to work on this driver, please be sure you download
  * and comply with the latest ATAPI standard. This document can be
  * obtained by anonymous ftp from fission.dt.wdc.com in directory:
  *                     -- fix speed display for ACER 24X, 18X
  * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
  *                         an end of file instead of an I/O error (Gadi)
+ * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
+ *                         slot when there is no disc in the current slot.
+ *                     -- Fixed a memory leak where info->changer_info was
+ *                         malloc'ed but never free'd when closing the device.
+ *                     -- Cleaned up the global namespace a bit by making more
+ *                         functions static that should already have been.
  *
  *************************************************************************/
 
-#define IDECD_VERSION "4.09"
+#define IDECD_VERSION "4.10"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -1309,7 +1316,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
 /****************************************************************************
  * cdrom driver request routine.
  */
-
+static
 void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
        if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND)
@@ -2467,10 +2474,6 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
        if (drive->usage > 1)
                return -EBUSY;
 
-       stat = cdrom_check_status (drive, &my_reqbuf);
-       if (stat && my_reqbuf.sense_key == NOT_READY)
-               return -ENOENT;
-
        if (slot == CDSL_NONE) {
                (void) cdrom_load_unload (drive, -1, NULL);
                cdrom_saw_media_change (drive);
@@ -2765,8 +2768,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
                printk (" changer w/%d slots", nslots);
         else   
                printk (" drive");
-       printk (" %s/%dkB Cache\n", 
-               (CDROM_CONFIG_FLAGS (drive)->is_changer)? "&" : "w",  
+       printk (", %dkB Cache\n", 
                ntohs(buf.cap.buffer_size) );
 
        return nslots;
@@ -2900,7 +2902,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
 }
 
 /* Forwarding functions to generic routines. */
-
+static
 int ide_cdrom_ioctl (ide_drive_t *drive,
                     struct inode *inode, struct file *file,
                     unsigned int cmd, unsigned long arg)
@@ -2908,6 +2910,7 @@ int ide_cdrom_ioctl (ide_drive_t *drive,
        return cdrom_fops.ioctl (inode, file, cmd, arg);
 }
 
+static
 int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
 {
        int rc;
@@ -2921,6 +2924,7 @@ int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
        return rc;
 }
 
+static
 void ide_cdrom_release (struct inode *inode, struct file *file,
                        ide_drive_t *drive)
 {
@@ -2928,6 +2932,7 @@ void ide_cdrom_release (struct inode *inode, struct file *file,
        MOD_DEC_USE_COUNT;
 }
 
+static
 int ide_cdrom_check_media_change (ide_drive_t *drive)
 {
        return cdrom_fops.check_media_change
@@ -2936,6 +2941,7 @@ int ide_cdrom_check_media_change (ide_drive_t *drive)
 }
 
 
+static
 int ide_cdrom_cleanup(ide_drive_t *drive)
 {
        struct cdrom_info *info = drive->driver_data;
@@ -2947,6 +2953,8 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
                kfree (info->sector_buffer);
        if (info->toc != NULL)
                kfree (info->toc);
+       if (info->changer_info != NULL)
+               kfree (info->changer_info);
        if (devinfo->handle == drive && unregister_cdrom (devinfo))
                printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
        kfree (info);
index 102e641ff28c6ef2c54621a1043b76af322c1a8e..bb5432cb26b40485f1622c312f16b9b97659dd5f 100644 (file)
@@ -274,11 +274,8 @@ static int proc_ide_read_imodel
 {
        ide_hwif_t      *hwif = (ide_hwif_t *) data;
        int             len;
-       const char      *vids, *dids;
 
-       vids = pci_strvendor(hwif->pci_devid.vid);
-       dids = pci_strdev(hwif->pci_devid.vid, hwif->pci_devid.did);
-       len = sprintf(page,"%s: %s\n", vids ? vids : "(none)", dids ? dids : "(none)");
+       len = sprintf(page,"%04x: %04x\n", hwif->pci_devid.vid, hwif->pci_devid.did);
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 #endif /* CONFIG_PCI */
index 47489770619fb475f00abf4b97e139c47463983f..cc94791845168541ceb72f47951fbbd7cdfd9b66 100644 (file)
@@ -5,6 +5,7 @@ comment 'Parallel IDE high-level drivers'
 dep_tristate '  Parallel port IDE disks' CONFIG_PARIDE_PD $CONFIG_PARIDE
 dep_tristate '  Parallel port ATAPI CD-ROMs' CONFIG_PARIDE_PCD $CONFIG_PARIDE
 dep_tristate '  Parallel port ATAPI disks' CONFIG_PARIDE_PF $CONFIG_PARIDE
+dep_tristate '  Parallel port ATAPI tapes' CONFIG_PARIDE_PT $CONFIG_PARIDE
 comment 'Parallel IDE protocol modules'
 dep_tristate '    ATEN EH-100 protocol' CONFIG_PARIDE_ATEN $CONFIG_PARIDE
 dep_tristate '    MicroSolutions backpack protocol' CONFIG_PARIDE_BPCK $CONFIG_PARIDE
index a6fa9603aa670267febadafa6d7410ea51b47225..61e710801716847b79a1751568d70a8adb59f222 100644 (file)
@@ -50,6 +50,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_PARIDE_PT),y)
+  LX_OBJS += pt.o
+else
+  ifeq ($(CONFIG_PARIDE_PT),m)
+    MX_OBJS += pt.o
+  endif
+endif
+
 ifeq ($(CONFIG_PARIDE_ATEN),y)
   LX_OBJS += aten.o
 else
index 1d5530c7dbe36e2e91da79b1f8c8940fc1baa290..0d7cf2f01c908ddb779db1c93d30689d6ecf1ce1 100644 (file)
@@ -473,6 +473,11 @@ void       paride_init( void )
           pf_init();
         };
 #endif
+#ifdef CONFIG_PARIDE_PT
+        { extern int pt_init(void);
+          pt_init();
+        };
+#endif
 }
 
 #endif
index 177f898a497f29e1fdccb8e9fb3d8277e64cdd09..ca520d32b9c4a6fd1a28fc0e522f35008fba94e0 100644 (file)
 
 */
 
-#define        PCD_VERSION     "1.0"
+/* Changes:
+
+       1.01    GRG 1997.01.24  Added test unit ready support
+
+*/
+
+#define        PCD_VERSION     "1.01"
 #define PCD_MAJOR      46
 #define PCD_NAME       "pcd"
 #define PCD_UNITS      4
@@ -173,6 +179,7 @@ MODULE_PARM(drive3,"1-6i");
 #define PCD_RETRIES         5
 #define PCD_TMO                   800          /* timeout in jiffies */
 #define PCD_DELAY           50          /* spin delay in uS */
+#define PCD_READY_TMO      20
 
 #define PCD_SPIN               (10000/PCD_DELAY)*PCD_TMO
 
@@ -207,6 +214,7 @@ struct pcd_unit {
        struct pi_adapter pia;  /* interface to paride layer */
        struct pi_adapter *pi;
        int drive;              /* master/slave */
+       int last_sense;         /* result of last request sense */
        int access;             /* count of active opens */
        int present;            /* does this unit exist ? */
        char name[PCD_NAMELEN]; /* pcd0, pcd1, etc */
@@ -264,6 +272,7 @@ static void pcd_init_units( void )
                 PCD.pi = & PCD.pia;
                 PCD.access = 0;
                 PCD.present = 0;
+               PCD.last_sense = 0;
                 j = 0;
                 while ((j < PCD_NAMELEN-2) && (PCD.name[j]=name[j])) j++;
                 PCD.name[j++] = '0' + unit;
@@ -509,9 +518,13 @@ static void pcd_req_sense( int unit, int quiet )
        udelay(1000);
        if (!r) pcd_completion(unit,buf,"Request sense");
 
-        if ((!r)&&(!quiet)) 
-               printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
-                      PCD.name,buf[2]&0xf,buf[12],buf[13]);
+       PCD.last_sense = -1;
+       if (!r) {
+            if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
+                              PCD.name,buf[2]&0xf,buf[12],buf[13]);
+           PCD.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
+                                          | ((buf[13]&0xff)<<16) ;
+        } 
 }
 
 static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
@@ -607,13 +620,30 @@ static int pcd_reset( int unit )
        return flg-1;   
 }
 
+static int pcd_ready_wait( int unit, int tmo )
+
+{       char    tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
+        int     k, p;
+
+        k = 0;
+        while (k < tmo) {
+          PCD.last_sense = 0;
+          pcd_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
+          p = PCD.last_sense;
+          if (!p) return 0;
+          if (!((p == 0x010402)||((p & 0xff) == 6))) return p;
+          k++;
+          pcd_sleep(100);
+        }
+        return 0x000020;        /* timeout */
+}
+
 static int pcd_check_media( int unit )
 
 {      char    rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
 
-       pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("cm1"));
-       pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("cm2"));
-       return (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("cm3")));
+       pcd_ready_wait(unit,PCD_READY_TMO);
+       return (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")));
 }
 
 static int pcd_identify( int unit, char * id )
index e9efbcd54f83bd027097ea8bb0b2b99c1696b516..aa431ae33dfaeefd93563036ee7cf3ff3617df36 100644 (file)
  
 */
 
-#define PD_VERSION      "1.0"
+/* Changes:
+
+       1.01    GRG 1997.01.24  Restored pd_reset()
+                               Added eject ioctl
+
+*/
+
+#define PD_VERSION      "1.01"
 #define PD_MAJOR       45
 #define PD_NAME                "pd"
 #define PD_UNITS       4
@@ -141,6 +148,7 @@ static int pd_drive_count;
 #include <linux/delay.h>
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
+#include <linux/cdrom.h>       /* for the eject ioctl */
 
 #include <asm/uaccess.h>
 
@@ -234,6 +242,7 @@ MODULE_PARM(drive3,"1-7i");
 #define IDE_DOORLOCK           0xde
 #define IDE_DOORUNLOCK         0xdf
 #define IDE_IDENTIFY           0xec
+#define IDE_EJECT              0xed
 
 int pd_init(void);
 void pd_setup(char * str, int * ints);
@@ -257,6 +266,7 @@ static int pd_identify (int unit);
 static void pd_media_check(int unit);
 static void pd_doorlock(int unit, int func);
 static int pd_check_media(kdev_t dev);
+static void pd_eject( int unit);
 
 static struct hd_struct pd_hd[PD_DEVS];
 static int pd_sizes[PD_DEVS];
@@ -435,6 +445,9 @@ static int pd_ioctl(struct inode *inode,struct file *file,
        if (!PD.present) return -ENODEV;
 
         switch (cmd) {
+           case CDROMEJECT:
+               if (PD.access == 1) pd_eject(unit);
+               return 0;
             case HDIO_GETGEO:
                 if (!geo) return -EINVAL;
                 err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
@@ -642,7 +655,6 @@ static void pd_print_error( int unit, char * msg, int status )
        printk("\n");
 }
 
-/*
 static void pd_reset( int unit )
 
 {       pi_connect(PI);
@@ -650,8 +662,8 @@ static void pd_reset( int unit )
         udelay(50);
         WR(1,6,0);
        pi_disconnect(PI);
+       udelay(250);
 }
-*/
 
 #define DBMSG(msg)     NULL
 
@@ -730,6 +742,18 @@ static void pd_doorlock( int unit, int func )
         pi_disconnect(PI);
 }
 
+static void pd_eject( int unit )
+
+{      pi_connect(PI);
+        pd_wait_for(unit,0,DBMSG("before unlock on eject"));
+        pd_send_command(unit,1,0,0,0,0,IDE_DOORUNLOCK);
+        pd_wait_for(unit,0,DBMSG("after unlock on eject"));
+        pd_wait_for(unit,0,DBMSG("before eject"));
+        pd_send_command(unit,0,0,0,0,0,IDE_EJECT);
+        pd_wait_for(unit,0,DBMSG("after eject"));
+        pi_disconnect(PI);
+}
+
 static void pd_media_check( int unit )
 
 {       int    r;
@@ -767,6 +791,8 @@ static int pd_identify( int unit )
 {       int    j;
        char id[PD_ID_LEN+1];
 
+       pd_reset(unit);
+
         pi_connect(PI);
        WR(0,6,0xa0);
         pd_wait_for(unit,0,DBMSG("before IDENT"));  
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
new file mode 100644 (file)
index 0000000..b6b3d3f
--- /dev/null
@@ -0,0 +1,957 @@
+/* 
+        pt.c    (c) 1998  Grant R. Guenther <grant@torque.net>
+                          Under the terms of the GNU public license.
+
+        This is the high-level driver for parallel port ATAPI tape
+        drives based on chips supported by the paride module.
+
+       The driver implements both rewinding and non-rewinding
+       devices, filemarks, and the rewind ioctl.  It allocates
+       a small internal "bounce buffer" for each open device, but
+        otherwise expects buffering and blocking to be done at the
+        user level.  As with most block-structured tapes, short
+       writes are padded to full tape blocks, so reading back a file
+        may return more data than was actually written.
+
+        By default, the driver will autoprobe for a single parallel
+        port ATAPI tape drive, but if their individual parameters are
+        specified, the driver can handle up to 4 drives.
+
+       The rewinding devices are named /dev/pt0, /dev/pt1, ...
+       while the non-rewinding devices are /dev/npt0, /dev/npt1, etc.
+
+        The behaviour of the pt driver can be altered by setting
+        some parameters from the insmod command line.  The following
+        parameters are adjustable:
+
+            drive0      These four arguments can be arrays of       
+            drive1      1-6 integers as follows:
+            drive2
+            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
+
+                        Where,
+
+                <prt>   is the base of the parallel port address for
+                        the corresponding drive.  (required)
+
+                <pro>   is the protocol number for the adapter that
+                        supports this drive.  These numbers are
+                        logged by 'paride' when the protocol modules
+                        are initialised.  (0 if not given)
+
+                <uni>   for those adapters that support chained
+                        devices, this is the unit selector for the
+                        chain of devices on the given port.  It should
+                        be zero for devices that don't support chaining.
+                        (0 if not given)
+
+                <mod>   this can be -1 to choose the best mode, or one
+                        of the mode numbers supported by the adapter.
+                        (-1 if not given)
+
+                <slv>   ATAPI devices can be jumpered to master or slave.
+                        Set this to 0 to choose the master drive, 1 to
+                        choose the slave, -1 (the default) to choose the
+                        first drive found.
+
+                <dly>   some parallel ports require the driver to 
+                        go more slowly.  -1 sets a default value that
+                        should work with the chosen protocol.  Otherwise,
+                        set this to a small integer, the larger it is
+                        the slower the port i/o.  In some cases, setting
+                        this to zero will speed up the device. (default -1)
+
+           major       You may use this parameter to overide the
+                       default major number (96) that this driver
+                       will use.  Be sure to change the device
+                       name as well.
+
+           name        This parameter is a character string that
+                       contains the name the kernel will use for this
+                       device (in /proc output, for instance).
+                       (default "pt").
+
+            verbose     This parameter controls the amount of logging
+                        that is done while the driver probes for
+                        devices.  Set it to 0 for a quiet load, or 1 to
+                        see all the progress messages.  (default 0)
+
+        If this driver is built into the kernel, you can use 
+        the following command line parameters, with the same values
+        as the corresponding module parameters listed above:
+
+            pt.drive0
+            pt.drive1
+            pt.drive2
+            pt.drive3
+
+        In addition, you can use the parameter pt.disable to disable
+        the driver entirely.
+
+*/
+
+#define PT_VERSION      "1.0"
+#define PT_MAJOR       96
+#define PT_NAME                "pt"
+#define PT_UNITS       4
+
+/* Here are things one can override from the insmod command.
+   Most are autoprobed by paride unless set here.  Verbose is on
+   by default.
+
+*/
+
+static int     verbose = 0;
+static int     major = PT_MAJOR;
+static char    *name = PT_NAME;
+static int      disable = 0;
+
+static int drive0[6] = {0,0,0,-1,-1,-1};
+static int drive1[6] = {0,0,0,-1,-1,-1};
+static int drive2[6] = {0,0,0,-1,-1,-1};
+static int drive3[6] = {0,0,0,-1,-1,-1};
+
+static int (*drives[4])[6] = {&drive0,&drive1,&drive2,&drive3};
+static int pt_drive_count;
+
+#define D_PRT   0
+#define D_PRO   1
+#define D_UNI   2
+#define D_MOD   3
+#define D_SLV   4
+#define D_DLY   5
+
+#define DU              (*drives[unit])
+
+/* end of parameters */
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/mtio.h>
+
+#include <asm/uaccess.h>
+
+#ifndef MODULE
+
+#include "setup.h"
+
+static STT pt_stt[5] = {{"drive0",6,drive0},
+                        {"drive1",6,drive1},
+                        {"drive2",6,drive2},
+                        {"drive3",6,drive3},
+                       {"disable",1,&disable}};
+
+void pt_setup( char *str, int *ints)
+
+{       generic_setup(pt_stt,5,str);
+}
+
+#endif
+
+MODULE_PARM(verbose,"i");
+MODULE_PARM(major,"i");
+MODULE_PARM(name,"s");
+MODULE_PARM(drive0,"1-6i");
+MODULE_PARM(drive1,"1-6i");
+MODULE_PARM(drive2,"1-6i");
+MODULE_PARM(drive3,"1-6i");
+
+#include "paride.h"
+
+#define PT_MAX_RETRIES  5
+#define PT_TMO          800             /* interrupt timeout in jiffies */
+#define PT_SPIN_DEL     50              /* spin delay in micro-seconds  */
+#define PT_RESET_TMO    30             /* 3 seconds */
+#define PT_READY_TMO   60              /* 60 seconds */
+#define PT_REWIND_TMO  1200            /* 20 minutes */
+
+#define PT_SPIN         (10000/PT_SPIN_DEL)*PT_TMO  
+
+#define STAT_ERR        0x00001
+#define STAT_INDEX      0x00002
+#define STAT_ECC        0x00004
+#define STAT_DRQ        0x00008
+#define STAT_SEEK       0x00010
+#define STAT_WRERR      0x00020
+#define STAT_READY      0x00040
+#define STAT_BUSY       0x00080
+#define STAT_SENSE     0x1f000
+
+#define ATAPI_TEST_READY       0x00
+#define ATAPI_REWIND           0x01
+#define ATAPI_REQ_SENSE                0x03
+#define ATAPI_READ_6           0x08
+#define ATAPI_WRITE_6          0x0a
+#define ATAPI_WFM              0x10
+#define ATAPI_IDENTIFY         0x12
+#define ATAPI_MODE_SENSE       0x1a
+#define ATAPI_LOG_SENSE                0x4d
+
+int pt_init(void);
+#ifdef MODULE
+void cleanup_module( void );
+#endif
+
+static int pt_open(struct inode *inode, struct file *file);
+static int pt_ioctl(struct inode *inode,struct file *file,
+                    unsigned int cmd, unsigned long arg);
+static int pt_release (struct inode *inode, struct file *file);
+static ssize_t pt_read(struct file * filp, char * buf, 
+                       size_t count, loff_t *ppos);
+static ssize_t pt_write(struct file * filp, const char * buf, 
+                        size_t count, loff_t *ppos);
+static int pt_detect(void);
+
+static int pt_identify (int unit);
+
+/* bits in PT.flags */
+
+#define PT_MEDIA       1
+#define PT_WRITE_OK    2
+#define PT_REWIND      4
+#define PT_WRITING      8
+#define PT_READING     16
+#define PT_EOF        32
+
+#define PT_NAMELEN      8
+#define PT_BUFSIZE  16384
+
+struct pt_unit {
+       struct pi_adapter pia;    /* interface to paride layer */
+       struct pi_adapter *pi;
+       int flags;                /* various state flags */
+       int last_sense;           /* result of last request sense */
+       int drive;                /* drive */
+       int access;               /* count of active opens ... */
+       int bs;                   /* block size */
+       int capacity;             /* Size of tape in KB */
+       int present;              /* device present ? */
+       char *bufptr;
+       char name[PT_NAMELEN];    /* pf0, pf1, ... */
+       };
+
+struct pt_unit pt[PT_UNITS];
+
+/*  'unit' must be defined in all functions - either as a local or a param */
+
+#define PT pt[unit]
+#define PI PT.pi
+
+static char pt_scratch[512];            /* scratch block buffer */
+
+/* kernel glue structures */
+
+static struct file_operations pt_fops = {
+        NULL,                   /* lseek - default */
+        pt_read,                /* read */
+        pt_write,               /* write */
+        NULL,                   /* readdir - bad */
+        NULL,                   /* select */
+        pt_ioctl,               /* ioctl */
+        NULL,                   /* mmap */
+        pt_open,                /* open */
+        pt_release,             /* release */
+        NULL,                   /* fsync */
+        NULL,                   /* fasync */
+        NULL,                   /* media change ? */
+        NULL                    /* revalidate new media */
+};
+
+void pt_init_units( void )
+
+{       int     unit, j;
+
+        pt_drive_count = 0;
+        for (unit=0;unit<PT_UNITS;unit++) {
+                PT.pi = & PT.pia;
+                PT.access = 0;
+                PT.flags = 0;
+               PT.last_sense = 0;
+                PT.present = 0;
+               PT.bufptr = NULL;
+               PT.drive = DU[D_SLV];
+                j = 0;
+                while ((j < PT_NAMELEN-2) && (PT.name[j]=name[j])) j++;
+                PT.name[j++] = '0' + unit;
+                PT.name[j] = 0;
+                if (DU[D_PRT]) pt_drive_count++;
+        }
+} 
+
+int pt_init (void)      /* preliminary initialisation */
+
+{       int unit;
+
+       if (disable) return -1;
+
+       pt_init_units();
+
+       if (pt_detect()) return -1;
+
+        if (register_chrdev(major,name,&pt_fops)) {
+                printk("pt_init: unable to get major number %d\n",
+                        major);
+               for (unit=0;unit<PT_UNITS;unit++)
+                 if (PT.present) pi_release(PI);
+                return -1;
+        }
+
+        return 0;
+}
+
+#ifdef MODULE
+
+/* Glue for modules ... */
+
+void    cleanup_module(void);
+
+int     init_module(void)
+
+{       int     err;
+        long    flags;
+
+        save_flags(flags);
+        cli();
+
+        err = pt_init();
+
+        restore_flags(flags);
+        return err;
+}
+
+void    cleanup_module(void)
+
+{       long flags;
+       int unit;
+
+        save_flags(flags);
+        cli();
+
+        unregister_chrdev(major,name);
+
+       for (unit=0;unit<PT_UNITS;unit++)
+         if (PT.present) pi_release(PI);
+       
+        restore_flags(flags);
+}
+
+#endif
+
+#define        WR(c,r,v)       pi_write_regr(PI,c,r,v)
+#define        RR(c,r)         (pi_read_regr(PI,c,r))
+
+#define DRIVE           (0xa0+0x10*PT.drive)
+
+static int pt_wait( int unit, int go, int stop, char * fun, char * msg )
+
+{       int j, r, e, s, p;
+
+        j = 0;
+        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(j++<PT_SPIN))
+                udelay(PT_SPIN_DEL);
+
+        if ((r&(STAT_ERR&stop))||(j>=PT_SPIN)) {
+           s = RR(0,7);
+           e = RR(0,1);
+           p = RR(0,2);
+           if (j >= PT_SPIN) e |= 0x100;
+           if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x"
+                           " loop=%d phase=%d\n",
+                            PT.name,fun,msg,r,s,e,j,p);
+           return (e<<8)+s;
+        }
+        return 0;
+}
+
+static int pt_command( int unit, char * cmd, int dlen, char * fun )
+
+{       pi_connect(PI);
+
+        WR(0,6,DRIVE);
+
+        if (pt_wait(unit,STAT_BUSY|STAT_DRQ,0,fun,"before command")) {
+                pi_disconnect(PI);
+                return -1;
+        }
+
+        WR(0,4,dlen % 256);
+        WR(0,5,dlen / 256);
+        WR(0,7,0xa0);          /* ATAPI packet command */
+
+        if (pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR,fun,"command DRQ")) {
+                pi_disconnect(PI);
+                return -1;
+        }
+
+        if (RR(0,2) != 1) {
+           printk("%s: %s: command phase error\n",PT.name,fun);
+           pi_disconnect(PI);
+           return -1;
+        }
+
+        pi_write_block(PI,cmd,12);
+
+        return 0;
+}
+
+static int pt_completion( int unit, char * buf, char * fun )
+
+{       int r, s, n, p;
+
+        r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
+                       fun,"completion");
+
+        if (RR(0,7)&STAT_DRQ) { 
+           n = (RR(0,4)+256*RR(0,5));
+          p = RR(0,2)&3;
+          if (p == 0) pi_write_block(PI,buf,n);
+          if (p == 2) pi_read_block(PI,buf,n);
+        }
+
+        s = pt_wait(unit,STAT_BUSY,STAT_READY|STAT_ERR,fun,"data done");
+
+        pi_disconnect(PI); 
+
+        return (r?r:s);
+}
+
+static void pt_req_sense( int unit, int quiet )
+
+{       char    rs_cmd[12] = { ATAPI_REQ_SENSE,0,0,0,16,0,0,0,0,0,0,0 };
+        char    buf[16];
+        int     r;
+
+        r = pt_command(unit,rs_cmd,16,"Request sense");
+        udelay(1000);
+        if (!r) pt_completion(unit,buf,"Request sense");
+
+       PT.last_sense = -1;
+        if (!r) {
+           if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
+                                    PT.name,buf[2]&0xf,buf[12],buf[13]);
+           PT.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
+                                        | ((buf[13]&0xff)<<16) ;
+       } 
+}
+
+static int pt_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
+
+{       int r;
+
+        r = pt_command(unit,cmd,dlen,fun);
+        udelay(1000);
+        if (!r) r = pt_completion(unit,buf,fun);
+        if (r) pt_req_sense(unit,!fun);
+        
+        return r;
+}
+
+static void pt_sleep( int cs )
+
+{       current->state = TASK_INTERRUPTIBLE;
+        current->timeout = jiffies + cs;
+        schedule();
+}
+
+static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
+
+{      int     k, e, s;
+
+       k = 0;
+       while (k < tmo) {
+               pt_sleep(pause);
+               k++;
+               pi_connect(PI);
+               WR(0,6,DRIVE);
+               s = RR(0,7);
+               e = RR(0,1);
+               pi_disconnect(PI);
+               if (s & (STAT_ERR|STAT_SEEK)) break;
+       }
+       if ((k >= tmo) || (s & STAT_ERR)) {
+          if (k >= tmo) printk("%s: %s DSC timeout\n",PT.name,msg);
+            else printk("%s: %s stat=0x%x err=0x%x\n",PT.name,msg,s,e);
+          pt_req_sense(unit,0);
+          return 0;
+       }
+       return 1;
+}
+
+static void pt_media_access_cmd( int unit, int tmo, char *cmd, char *fun)
+
+{      if (pt_command(unit,cmd,0,fun)) {
+               pt_req_sense(unit,0);
+               return;
+       }
+       pi_disconnect(PI);
+       pt_poll_dsc(unit,100,tmo,fun);
+}
+
+static void pt_rewind( int unit )
+
+{      char    rw_cmd[12] = {ATAPI_REWIND,0,0,0,0,0,0,0,0,0,0,0};
+
+       pt_media_access_cmd(unit,PT_REWIND_TMO,rw_cmd,"rewind");
+}
+
+static void pt_write_fm( int unit )
+
+{      char    wm_cmd[12] = {ATAPI_WFM,0,0,0,1,0,0,0,0,0,0,0};
+
+        pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
+}
+
+#define DBMSG(msg)      NULL
+
+static int pt_reset( int unit )
+
+{      int     i, k, flg;
+       int     expect[5] = {1,1,1,0x14,0xeb};
+       long    flags;
+
+       pi_connect(PI);
+       WR(0,6,DRIVE);
+       WR(0,7,8);
+
+       save_flags(flags);
+       sti();
+
+       pt_sleep(2);
+
+        k = 0;
+        while ((k++ < PT_RESET_TMO) && (RR(1,6)&STAT_BUSY))
+                pt_sleep(10);
+
+       restore_flags(flags);
+
+       flg = 1;
+       for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
+
+       if (verbose) {
+               printk("%s: Reset (%d) signature = ",PT.name,k);
+               for (i=0;i<5;i++) printk("%3x",RR(0,i+1));
+               if (!flg) printk(" (incorrect)");
+               printk("\n");
+       }
+       
+       pi_disconnect(PI);
+       return flg-1;   
+}
+
+static int pt_ready_wait( int unit, int tmo )
+
+{      char    tr_cmd[12] = {ATAPI_TEST_READY,0,0,0,0,0,0,0,0,0,0,0};
+       int     k, p;
+
+       k = 0;
+       while (k < tmo) {
+         PT.last_sense = 0;
+         pt_atapi(unit,tr_cmd,0,NULL,DBMSG("test unit ready"));
+         p = PT.last_sense;
+         if (!p) return 0;
+         if (!((p == 0x010402)||((p & 0xff) == 6))) return p;
+         k++;
+          pt_sleep(100);
+       }
+       return 0x000020;        /* timeout */
+}
+
+static void xs( char *buf, char *targ, int offs, int len )
+
+{      int     j,k,l;
+
+       j=0; l=0;
+       for (k=0;k<len;k++) 
+          if((buf[k+offs]!=0x20)||(buf[k+offs]!=l))
+               l=targ[j++]=buf[k+offs];
+       if (l==0x20) j--; targ[j]=0;
+}
+
+static int xn( char *buf, int offs, int size )
+
+{      int     v,k;
+
+       v=0; 
+       for(k=0;k<size;k++) v=v*256+(buf[k+offs]&0xff);
+       return v;
+}
+
+static int pt_identify( int unit )
+
+{      int     dt, s;
+       char    *ms[2] = {"master","slave"};
+       char    mf[10], id[18];
+       char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
+        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,128,0,0,0,0,0,0,0};
+       char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,128,0,0,0};
+       char    buf[36];
+
+        s = pt_atapi(unit,id_cmd,36,buf,"identify");
+       if (s) return -1;
+
+       dt = buf[0] & 0x1f;
+       if (dt != 1) {
+               if (verbose) 
+                  printk("%s: Drive %d, unsupported type %d\n",
+                               PT.name,PT.drive,dt);
+               return -1;
+               }
+
+       xs(buf,mf,8,8);
+       xs(buf,id,16,16);
+
+       PT.flags = 0;
+       PT.capacity = 0;
+       PT.bs = 0;
+
+       if (!pt_ready_wait(unit,PT_READY_TMO)) PT.flags |= PT_MEDIA;
+
+        if (!pt_atapi(unit,ms_cmd,36,buf,"mode sense")) {
+          if (!(buf[2] & 0x80)) PT.flags |= PT_WRITE_OK;
+         PT.bs = xn(buf,10,2);
+       }
+
+        if (!pt_atapi(unit,ls_cmd,36,buf,"log sense")) 
+               PT.capacity = xn(buf,24,4);
+
+        printk("%s: %s %s, %s",
+               PT.name,mf,id,ms[PT.drive]);
+        if (!(PT.flags & PT_MEDIA)) 
+                printk(", no media\n");
+        else {  if (!(PT.flags & PT_WRITE_OK)) printk(", RO");
+                printk(", blocksize %d, %d MB\n",
+                      PT.bs,PT.capacity/1024);
+        }
+
+       return 0;
+}
+
+static int pt_probe( int unit )
+
+/*     returns  0, with id set if drive is detected
+               -1, if drive detection failed
+*/
+
+{      if (PT.drive == -1) {
+          for (PT.drive=0;PT.drive<=1;PT.drive++)
+               if (!pt_reset(unit)) return pt_identify(unit);
+       } else {
+          if (!pt_reset(unit)) return pt_identify(unit);
+       }
+        return -1; 
+}
+
+static int pt_detect( void )
+
+{      int     k, unit;
+
+       printk("%s: %s version %s, major %d\n",
+               name,name,PT_VERSION,major);
+
+       k = 0;
+       if (pt_drive_count == 0) {
+           unit = 0;
+           if (pi_init(PI,1,-1,-1,-1,-1,-1,pt_scratch,
+                        PI_PT,verbose,PT.name)) {
+               if (!pt_probe(unit)) {
+                       PT.present = 1;
+                       k++;
+               } else pi_release(PI);
+           }
+
+       } else for (unit=0;unit<PT_UNITS;unit++) if (DU[D_PRT])
+           if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
+                       DU[D_PRO],DU[D_DLY],pt_scratch,PI_PT,verbose,
+                       PT.name)) { 
+                if (!pt_probe(unit)) {
+                        PT.present = 1;
+                        k++;
+                } else pi_release(PI);
+            }
+
+       if (k) return 0;
+
+       printk("%s: No ATAPI tape drive detected\n",name);
+       return -1;
+}
+
+#define DEVICE_NR(x)   (x % 128)
+
+static int pt_open (struct inode *inode, struct file *file)
+
+{       int    unit = DEVICE_NR(inode->i_rdev);
+
+        if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
+
+        PT.access++;
+
+       if (PT.access > 1) {
+               PT.access--;
+               return -EBUSY;
+       }
+
+        MOD_INC_USE_COUNT;
+
+       pt_identify(unit);
+
+       if (!PT.flags & PT_MEDIA) {
+               PT.access--;
+               MOD_DEC_USE_COUNT;
+               return -ENODEV;
+               }
+
+       if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
+               PT.access--;
+               MOD_DEC_USE_COUNT;
+               return -EROFS;
+               }
+
+       if (!(inode->i_rdev & 128)) PT.flags |= PT_REWIND;
+
+       PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
+       if (PT.bufptr == NULL) {
+               PT.access--;
+               MOD_DEC_USE_COUNT;
+               printk("%s: buffer allocation failed\n",PT.name);
+               return -ENOMEM;
+       }
+
+        return 0;
+}
+
+static int pt_ioctl(struct inode *inode,struct file *file,
+                    unsigned int cmd, unsigned long arg)
+
+{       int unit;
+       struct mtop mtop;
+
+
+        if ((!inode) || (!inode->i_rdev)) return -EINVAL;
+        unit = DEVICE_NR(inode->i_rdev);
+        if (unit >= PT_UNITS) return -EINVAL;
+        if (!PT.present) return -ENODEV;
+
+        switch (cmd) {
+
+           case MTIOCTOP:      
+               if (copy_from_user((char *)&mtop, (char *)arg, 
+                                  sizeof(struct mtop))) return -EFAULT;
+
+               switch (mtop.mt_op) {
+
+                   case MTREW: 
+                       pt_rewind(unit);
+                       return 0;
+
+                   default:    
+                       printk("%s: Unimplemented mt_op %d\n",PT.name,
+                                       mtop.mt_op);
+                       return -EINVAL;
+               }
+
+            default:
+               printk("%s: Unimplemented ioctl 0x%x\n",PT.name,cmd);
+                return -EINVAL;
+
+        }
+}
+
+
+static int pt_release (struct inode *inode, struct file *file)
+
+{       int    unit = DEVICE_NR(inode->i_rdev);
+
+        if ((unit >= PT_UNITS) || (PT.access <= 0)) 
+                return -EINVAL;
+
+       if (PT.flags & PT_WRITING) pt_write_fm(unit);
+
+       if (PT.flags & PT_REWIND) pt_rewind(unit);      
+
+       PT.access--;
+
+       kfree(PT.bufptr);
+       PT.bufptr = NULL;
+
+        MOD_DEC_USE_COUNT;
+
+       return 0;
+
+}
+
+static ssize_t pt_read(struct file * filp, char * buf, 
+                       size_t count, loff_t *ppos)
+
+{      struct  inode *ino = filp->f_dentry->d_inode;
+       int     unit = DEVICE_NR(ino->i_rdev);
+       char    rd_cmd[12] = {ATAPI_READ_6,1,0,0,0,0,0,0,0,0,0,0};
+       int     k, n, r, p, s, t, b;
+
+       if (!(PT.flags & (PT_READING|PT_WRITING))) {
+           PT.flags |= PT_READING;
+           if (pt_atapi(unit,rd_cmd,0,NULL,"start read-ahead"))
+                       return -EIO;
+       } else if (PT.flags & PT_WRITING) return -EIO;
+
+       if (PT.flags & PT_EOF) return 0;
+
+       t = 0;
+
+       while (count > 0) {
+
+           if (!pt_poll_dsc(unit,1,PT_TMO,"read")) return -EIO;
+
+           n = count;
+           if (n > 32768) n = 32768;   /* max per command */
+           b = (n-1+PT.bs)/PT.bs;
+           n = b*PT.bs;                /* rounded up to even block */
+
+           rd_cmd[4] = b;
+
+           r = pt_command(unit,rd_cmd,n,"read");
+
+           udelay(1000);
+
+           if (r) {
+               pt_req_sense(unit,0);
+               return -EIO;
+           }
+
+           while (1) {
+
+               r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
+                                           DBMSG("read DRQ"),"");
+
+               if (r & STAT_SENSE) {
+                   pi_disconnect(PI);
+                   pt_req_sense(unit,0);
+                   return -EIO;
+               }
+
+               if (r) PT.flags |= PT_EOF; 
+
+               s = RR(0,7);
+
+               if (!(s & STAT_DRQ)) break;
+
+               n = (RR(0,4)+256*RR(0,5));
+               p = (RR(0,2)&3);
+               if (p != 2) {
+                   pi_disconnect(PI);
+                   printk("%s: Phase error on read: %d\n",PT.name,p);
+                   return -EIO;
+               }
+
+               while (n > 0) {
+                   k = n;
+                   if (k > PT_BUFSIZE) k = PT_BUFSIZE; 
+                   pi_read_block(PI,PT.bufptr,k);
+                   n -= k;
+                   b = k;
+                   if (b > count) b = count;
+                   copy_to_user(buf+t,PT.bufptr,b);
+                   t += b;
+                   count -= b;
+               }
+
+           }
+           pi_disconnect(PI);
+           if (PT.flags & PT_EOF) break;
+       }
+
+       return t;
+
+}
+
+static ssize_t pt_write(struct file * filp, const char * buf, 
+                        size_t count, loff_t *ppos)
+
+{       struct inode *ino = filp->f_dentry->d_inode;
+        int unit = DEVICE_NR(ino->i_rdev);
+        char    wr_cmd[12] = {ATAPI_WRITE_6,1,0,0,0,0,0,0,0,0,0,0};
+        int     k, n, r, p, s, t, b;
+
+       if (!(PT.flags & PT_WRITE_OK)) return -EROFS;
+
+        if (!(PT.flags & (PT_READING|PT_WRITING))) {
+            PT.flags |= PT_WRITING;
+            if (pt_atapi(unit,wr_cmd,0,NULL,"start buffer-available mode"))
+                        return -EIO;
+        } else if (PT.flags&PT_READING) return -EIO;
+
+       if (PT.flags & PT_EOF) return -ENOSPC;
+
+       t = 0;
+
+       while (count > 0) {
+
+           if (!pt_poll_dsc(unit,1,PT_TMO,"write")) return -EIO;
+
+            n = count;
+            if (n > 32768) n = 32768;  /* max per command */
+            b = (n-1+PT.bs)/PT.bs;
+            n = b*PT.bs;                /* rounded up to even block */
+
+            wr_cmd[4] = b;
+
+            r = pt_command(unit,wr_cmd,n,"write");
+
+            udelay(1000);
+
+            if (r) {                   /* error delivering command only */
+                pt_req_sense(unit,0);
+                return -EIO;
+            }
+
+           while (1) {
+
+                r = pt_wait(unit,STAT_BUSY,STAT_DRQ|STAT_ERR|STAT_READY,
+                                               DBMSG("write DRQ"),NULL);
+
+                if (r & STAT_SENSE) {
+                    pi_disconnect(PI);
+                    pt_req_sense(unit,0);
+                    return -EIO;
+                }
+
+                if (r) PT.flags |= PT_EOF;
+
+               s = RR(0,7);
+
+               if (!(s & STAT_DRQ)) break;
+
+                n = (RR(0,4)+256*RR(0,5));
+                p = (RR(0,2)&3);
+                if (p != 0) {
+                    pi_disconnect(PI);
+                    printk("%s: Phase error on write: %d \n",PT.name,p);
+                    return -EIO;
+                }
+
+                while (n > 0) {
+                   k = n;
+                   if (k > PT_BUFSIZE) k = PT_BUFSIZE;
+                   b = k;
+                   if (b > count) b = count;
+                   copy_from_user(PT.bufptr,buf+t,b);
+                    pi_write_block(PI,PT.bufptr,k);
+                   t += b;
+                   count -= b;
+                   n -= k;
+                }
+
+           }
+           pi_disconnect(PI);
+           if (PT.flags & PT_EOF) break;
+       }
+
+       return t;
+}
+
+/* end of pt.c */
+
index 23ece7e7260ab7d1f6a54eaa90bfd7ef2be94d87..48a3ae427de99437548d1616adeeda94aa84a6fe 100644 (file)
@@ -1,6 +1,6 @@
 /* linux/drivers/cdrom/cdrom.c. 
    Copyright (c) 1996, 1997 David A. van Leeuwen.
-   Copyright (c) 1997, 1998 Erik Andersen (andersee@debian.org)
+   Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
 
    May be copied or modified under the terms of the GNU General Public
    License.  See linux/COPYING for more information.
 
    The routines in the file provide a uniform interface between the
    software that uses CD-ROMs and the various low-level drivers that
-   actually talk to actual hardware devices. Suggestions are welcome.
+   actually talk to the hardware. Suggestions are welcome.
    Patches that work are more welcome though.  ;-)
 
+ To Do List:
+ ----------------------------------
 
-  Recent Changes:
-  ----------------------------------
+ -- Modify sysctl/proc interface. I plan on having one directory per
+ drive, with entries for outputing general drive information, and sysctl
+ based tunable parameters such as whether the tray should auto-close for
+ that drive. Suggestions (or patches) for this welcome!
 
-  New maintainer! As David A. van Leeuwen has been too busy to activly
+ -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and 
+ CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
+
+
+
+
+ Revision History
+ ----------------------------------
+ 1.00  Date Unknown -- David van Leeuwen <david@tm.tno.nl>
+ -- Initial version by David A. van Leeuwen. I don't have a detailed
+  changelog for the 1.x series, David?
+
+2.00  Dec  2, 1997 -- Erik Andersen <andersee@debian.org>
+  -- New maintainer! As David A. van Leeuwen has been too busy to activly
   maintain and improve this driver, I am now carrying on the torch. If
   you have a problem with this driver, please feel free to contact me.
 
-  Added (rudimentary) sysctl interface. I realize this is really weak
-  right now, and is _very_ badly implemented. It will be improved... I
-  plan on having one directory per drive, with entries for outputing
-  general drive information, and sysctl based tunable parameters such
-  as whether the tray should auto-close for that drive. Suggestions (or
-  patches) for improvements are very welcome.
+  -- Added (rudimentary) sysctl interface. I realize this is really weak
+  right now, and is _very_ badly implemented. It will be improved...
 
-  Modified CDROM_DISC_STATUS so that it is now incorporated into
+  -- Modified CDROM_DISC_STATUS so that it is now incorporated into
   the Uniform CD-ROM driver via the cdrom_count_tracks function.
   The cdrom_count_tracks function helps resolve some of the false
   assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
   for the correct media type when mounting or playing audio from a CD.
 
-  Remove the calls to verify_area and only use the copy_from_user and
+  -- Remove the calls to verify_area and only use the copy_from_user and
   copy_to_user stuff, since these calls now provide their own memory
   checking with the 2.1.x kernels.
 
-  Major update to return codes so that errors from low-level drivers
+  -- Major update to return codes so that errors from low-level drivers
   are passed on through (thanks to Gerd Knorr for pointing out this
   problem).
 
-  Made it so if a function isn't implemented in a low-level driver,
+  -- Made it so if a function isn't implemented in a low-level driver,
   ENOSYS is now returned instead of EINVAL.
 
-  Simplified some complex logic so that the source code is easier to read.
+  -- Simplified some complex logic so that the source code is easier to read.
 
-  Other stuff I probably forgot to mention (lots of changes).
+  -- Other stuff I probably forgot to mention (lots of changes).
 
- */
+2.01 to 2.11 Dec 1997-Jan 1998
+  -- TO-DO!  Write changelogs for 2.01 to 2.12.
+
+2.12  Jan  24, 1998 -- Erik Andersen <andersee@debian.org>
+  -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros.  It turns out that
+  copy_*_user does not return EFAULT on error, but instead return the number 
+  of bytes not copied.  I was returning whatever non-zero stuff came back from 
+  the copy_*_user functions directly, which would result in strange errors.
+
+-------------------------------------------------------------------------*/
+
+#define REVISION "Revision: 2.12"
+#define VERSION "Id: cdrom.c 2.12 1998/01/24 22:15:45 erik Exp"
 
 
 #include <linux/config.h>
 #include <asm/uaccess.h>
 
 
-#define VERSION "$Id: cdrom.c,v 2.11 1998/01/04 01:11:18 erik Exp $"
-#define REVISION "Revision: 2.11"
-#define FM_WRITE       0x2                 /* file mode write bit */
-
 /* I use an error-log mask to give fine grain control over the type of
    error messages dumped to the system logs.  The available masks include: */
 #define CD_WARNING     0x1
 #define cdinfo(type, fmt, args...) 
 #endif
 
-
 /* These are used to simplify getting data in from and back to user land */
 #define IOCTL_IN(arg, type, in) { \
-            int ret=copy_from_user(&in, (type *) arg, sizeof in); \
-            if (ret) return ret; }
+            if ( copy_from_user(&in, (type *) arg, sizeof in) ) \
+               return -EFAULT; }
 
 #define IOCTL_OUT(arg, type, out) { \
-            int ret=copy_to_user((type *) arg, &out, sizeof out); \
-            if (ret) return ret; }
+            if ( copy_to_user((type *) arg, &out, sizeof out) ) \
+               return -EFAULT; }
+
+
+#define FM_WRITE       0x2                 /* file mode write bit */
 
 /* Not-exported routines. */
 static int cdrom_open(struct inode *ip, struct file *fp);
index 9a7b268716cddc0ece32748911bd339c2fd7d98d..7ff08bb852410435fcddafbc3de2bbd6b6ce9c13 100644 (file)
  *                 Heiko Eissfeldt <heiko@colossus.escape.de> with additional
  *                 changes by Erik Andersen <andersee@debian.org>
  *
+ *  24 January 1998 -- Removed the scd_disc_status() function, which was now
+ *                     just dead code left over from the port.
+ *                          Erik Andersen <andersee@debian.org>
+ *
 */
 
 #include <linux/major.h>
@@ -1242,35 +1246,6 @@ size_to_buf(unsigned int size,
    buf[2] = size % 256;
 }
 
-#if 0
-/* Uniform cdrom interface function.
-   Return the status of the current disc:
-   If it is recognized as CD-I -> return XA Mode 2 Form 2
-   If it is recognized as XA   -> return XA Mode 2 Form 1
-   If there is at least one data track return Mode 1
-   else return type AUDIO
- */
-static int scd_disc_status(struct cdrom_device_info *cdi)
-{
-  if (sony_spun_up)
-  {
-    int i;
-
-    sony_get_toc();
-    /* look into the TOC */
-    if (sony_toc.disk_type == 0x10)   /* this is a CD-I disc */
-      return CDS_XA_2_2;
-    if (sony_toc.disk_type == 0x20)   /* this is a XA disc */
-      return CDS_XA_2_1;
-    for (i = 0; i < sony_toc.track_entries; i++)
-      if (sony_toc.tracks[i].control & CDROM_DATA_TRACK)
-        return CDS_DATA_1;
-    return CDS_AUDIO;
-  } else 
-    return CDS_NO_INFO;
-}
-#endif
-
 /* Starts a read operation. Returns 0 on success and 1 on failure. 
    The read operation used here allows multiple sequential sectors 
    to be read and status returned for each sector.  The driver will
index 65517ba5720bf2ef38fba15c1c4b60f7e8af75f2..e255fa54e64998bedafad13f7f861788f5a7f1cc 100644 (file)
@@ -149,6 +149,8 @@ History:
 
 21 dec 1997   1.4 Upgrade to Linux 2.1.72.  
 
+24 jan 1998   Removed the cm206_disc_status() function, as it was now dead
+              code.  The Uniform CDROM driver now provides this functionality.
  * 
  * Parts of the code are based upon lmscd.c written by Kai Petzke,
  * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
@@ -1140,24 +1142,6 @@ int cm206_drive_status(struct cdrom_device_info * cdi, int slot_nr)
   return CDS_DISC_OK;
 }
  
-/* gives current state of disc in drive */
-int cm206_disc_status(struct cdrom_device_info * cdi)
-{
-  uch xa;
-  get_drive_status();
-  if ((cd->dsb & dsb_not_useful) | !(cd->dsb & dsb_disc_present))
-    return CDS_NO_DISC;
-  get_disc_status();
-  if (DISC_STATUS & cds_all_audio) return CDS_AUDIO;
-  xa = DISC_STATUS >> 4;
-  switch (xa) {
-  case 0: return CDS_DATA_1;   /* can we detect CDS_DATA_2? */
-  case 1: return CDS_XA_2_1;   /* untested */
-  case 2: return CDS_XA_2_2;
-  }
-  return 0;
-}
-
 /* locks or unlocks door lock==1: lock; return 0 upon success */
 int cm206_lock_door(struct cdrom_device_info * cdi, int lock)
 {
@@ -1274,9 +1258,9 @@ static struct cdrom_device_info cm206_info = {
   "cm206"                      /* name of the device type */
 };
 
-/* This routine gets called during initialization if thing go wrong,
+/* This routine gets called during initialization if things go wrong,
  * can be used in cleanup_module as well. */
-void cleanup(int level)
+static void cleanup(int level)
 {
   switch (level) {
   case 4: 
index 090d58498e8f4b9b0130371ee8215864ac99e2c4..f806743e9bbc47223f1bbc47e00e20910d043ec0 100644 (file)
@@ -1126,9 +1126,9 @@ static void mcd_release(struct cdrom_device_info * cdi)
 
 
 
-/* This routine gets called during initialization if thing go wrong,
+/* This routine gets called during initialization if things go wrong,
  * and is used in cleanup_module as well. */
-void cleanup(int level)
+static void cleanup(int level)
 {
   switch (level) {
   case 3:
index 62396576a9ed1e82233429d0fbdedd392cc9d202..f3fce22d54d490fcc81f69510c488ef26d7fbdf6 100644 (file)
  *       Heiko Eissfeldt <heiko@colossus.escape.de> with additional
  *       changes by Erik Andersen <andersee@debian.org>
  *
+ *  4.62 Fix a bug where playing audio left the drive in an unusable state.
+ *         Heiko Eissfeldt <heiko@colossus.escape.de>
+ *
  *
  *  TODO
  *     implement "read all subchannel data" (96 bytes per frame)
@@ -1046,7 +1049,7 @@ static int CDi_stat_loop(void)
                sbp_sleep(1);
                i = 1;
        }
-       msg(DBG_LCS,"CDi_stat_loop failed\n");
+       msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
        return (-1);
 }
 /*==========================================================================*/
@@ -4295,7 +4298,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
                        }
                        if (status_tries == 0)
                        {
-                               msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries.\n");
+                               msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
                                continue;
                        }
                        msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
@@ -4467,7 +4470,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
 #endif OLD_BUSY
                if (data_tries == 0)
                {
-                       msg(DBG_AUD,"read_audio: failed after 5 tries.\n");
+                       msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
                        RETURN_UP(-EIO);
                }
                msg(DBG_AUD,"read_audio: successful return.\n");
@@ -4651,6 +4654,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
 #endif SAFE_MIXED
                i=cc_Pause_Resume(1);
                D_S[d].audio_state=0;
+               cc_DriveReset();
                RETURN_UP(i);
                
        case CDROMSTART:  /* Spin up the drive */
@@ -4886,7 +4890,7 @@ static void DO_SBPCD_REQUEST(void)
                }
                if (status_tries == 0)
                {
-                       msg(DBG_INF,"sbp_status: failed after 3 tries\n");
+                       msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
                        break;
                }
                
index 5139faba085363f5ae62df918d9d10f684d72848..01b90940a709222bbd8cf8347b101b2376627b80 100644 (file)
@@ -109,7 +109,7 @@ if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then
   bool 'Tadpole ANA H8 Support'  CONFIG_H8
 fi
 tristate 'Video For Linux' CONFIG_VIDEO_DEV
-if [ "$CONFIG_VIDEO_DEV" != n ]; then
+if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
   dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
   if [ "$CONFIG_PARPORT" != "n" ]; then
     dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV
index fd1ac0cd7135e9a661a17bfaa900645d53a9e462..6d40de3a198be70c93b7ab624a8c24090c33bf69 100644 (file)
@@ -403,10 +403,10 @@ int fdc_interrupt_wait(unsigned int time)
        current->state = TASK_INTERRUPTIBLE;
 
        spin_lock_irq(&current->sigmask_lock);
-        old_sigmask = current->blocked;
-        siginitset(&current->blocked, _BLOCK_ALL);
-        recalc_sigpending(current);
-        spin_unlock_irq(&current->sigmask_lock);
+       old_sigmask = current->blocked;
+       sigfillset(&current->blocked);
+       recalc_sigpending(current);
+       spin_unlock_irq(&current->sigmask_lock);
 
        add_wait_queue(&ftape_wait_intr, &wait);
        while (!ft_interrupt_seen && current->state != TASK_RUNNING) {
@@ -414,9 +414,9 @@ int fdc_interrupt_wait(unsigned int time)
         }
 
        spin_lock_irq(&current->sigmask_lock);
-        current->blocked = old_sigmask;
-        recalc_sigpending(current);
-        spin_unlock_irq(&current->sigmask_lock);
+       current->blocked = old_sigmask;
+       recalc_sigpending(current);
+       spin_unlock_irq(&current->sigmask_lock);
        
        remove_wait_queue(&ftape_wait_intr, &wait);
        /*  the following IS necessary. True: as well
index 41527aa3f2685de9de5aeb7f5c77df77aba3212d..5bd5beabb0f4cf65d322b3434e9dac3bfdb02554 100644 (file)
@@ -80,7 +80,6 @@ int keyboard_wait_for_keypress(struct console *co)
 /* shift state counters.. */
 static unsigned char k_down[NR_SHIFT] = {0, };
 /* keyboard key bitmap */
-#define BITS_PER_LONG (8*sizeof(unsigned long))
 static unsigned long key_down[256/BITS_PER_LONG] = { 0, };
 
 static int dead_key_next = 0;
index fb30c3e0c9ba0717899af85119b6047d3366a4d0..47868a50323d0dadab43e493744dc16e2a42d7ae 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Generic parallel printer driver
+ *
  * Copyright (C) 1992 by Jim Weigand and Linus Torvalds
  * Copyright (C) 1992,1993 by Michael K. Johnson
  * - Thanks much to Gunter Windau for pointing out to me where the error
  * lp_read (Status readback) support added by Carsten Gross,
  *                                             carsten@sol.wohnheim.uni-ulm.de
  * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
- * Reverted interrupt to polling at runtime if more than one device is parport
- * registered and joined the interrupt and polling code.
- *                               by Andrea Arcangeli <arcangeli@mbox.queen.it>
+ * parport_sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
  */
 
-/* This driver is about due for a rewrite. */
+/* This driver should, in theory, work with any parallel port that has an
+ * appropriate low-level driver; all I/O is done through the parport
+ * abstraction layer.  There is a performance penalty for this, but parallel
+ * ports are comparitively low-speed devices anyway.
+ *
+ * If this driver is built into the kernel, you can configure it using the
+ * kernel command-line.  For example:
+ *
+ *      lp=parport1,none,parport2      (bind lp0 to parport1, disable lp1 and
+ *                                      bind lp2 to parport2)
+ *
+ *     lp=auto                         (assign lp devices to all ports that
+ *                                      have printers attached, as determined
+ *                                      by the IEEE-1284 autoprobe)
+ * 
+ *      lp=reset                       (reset the printer during 
+ *                                      initialisation)
+ *
+ *     lp=off                          (disable the printer driver entirely)
+ *
+ * If the driver is loaded as a module, similar functionality is available
+ * using module parameters.  The equivalent of the above commands would be:
+ *
+ *     # insmod lp.o parport=1,-1,2    (use -1 for disabled ports, since
+ *                                      module parameters do not allow you
+ *                                      to mix textual and numeric values)
+ *
+ *      # insmod lp.o autoprobe=1
+ *
+ *     # insmod lp.0 reset=1
+ */
+
+/* COMPATIBILITY WITH OLD KERNELS
+ *
+ * Under Linux 2.0 and previous versions, lp devices were bound to ports at
+ * particular I/O addresses, as follows:
+ *
+ *     lp0             0x3bc
+ *     lp1             0x378
+ *     lp2             0x278
+ *
+ * The new driver, by default, binds lp devices to parport devices as it
+ * finds them.  This means that if you only have one port, it will be bound
+ * to lp0 regardless of its I/O address.  If you need the old behaviour, you
+ * can force it using the parameters described above.
+ */
 
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/malloc.h>
-#include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 
+#include <linux/parport.h>
+#include <linux/lp.h>
+
 #include <asm/irq.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <linux/parport.h>
-#include <linux/lp.h>
 
 /* if you have more than 3 printers, remember to increase LP_NO */
-struct lp_struct lp_table[] =
-{
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
-  {0}},
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
-  {0}},
- {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, 0,
-  {0}}
-};
 #define LP_NO 3
 
-/* Device name */
-static char *dev_name = "lp";
+struct lp_struct lp_table[LP_NO] =
+{
+       [0 ... LP_NO-1] = {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT,
+                          NULL, 0, 0, 0, {0}}
+};
 
 /* Test if printer is ready (and optionally has no error conditions) */
 #define LP_READY(minor, status) \
@@ -64,61 +103,60 @@ static char *dev_name = "lp";
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
 
-/* Magic numbers */
-#define AUTO -3
-#define OFF -2
-#define UNSPEC -1
+/* --- parport support ----------------------------------------- */
 
-static inline void lp_parport_release (int minor)
+static int lp_preempt(void *handle)
 {
-       parport_release (lp_table[minor].dev);
-       lp_table[minor].should_relinquish = 0;
-}
+       struct lp_struct *lps = (struct lp_struct *)handle;
 
-static inline void lp_parport_claim (int minor)
-{
-       if (parport_claim (lp_table[minor].dev))
-               sleep_on (&lp_table[minor].lp_wait_q);
+       if (waitqueue_active (&lps->dev->wait_q))
+               wake_up_interruptible(&lps->dev->wait_q);
+
+       /* Don't actually release the port now */
+       return 1;
 }
 
-static inline void lp_schedule (int minor)
+#define lp_parport_release(x)  do { parport_release(lp_table[(x)].dev); } while (0);
+#define lp_parport_claim(x)    do { parport_claim_or_block(lp_table[(x)].dev); } while (0);
+
+/* --- low-level port access ----------------------------------- */
+
+#define r_dtr(x)       (parport_read_data(lp_table[(x)].dev->port))
+#define r_str(x)       (parport_read_status(lp_table[(x)].dev->port))
+#define w_ctr(x,y)     do { parport_write_control(lp_table[(x)].dev->port, (y)); } while (0)
+#define w_dtr(x,y)     do { parport_write_data(lp_table[(x)].dev->port, (y)); } while (0)
+
+static __inline__ void lp_yield (int minor)
 {
-       if (lp_table[minor].should_relinquish) {
-               lp_parport_release (minor);
-               schedule ();
-               lp_parport_claim (minor);
-       }
-       else
+       if (parport_yield (lp_table[minor].dev, 1) == 1 && need_resched)
                schedule ();
 }
 
-
-static int lp_preempt (void *handle)
+static __inline__ void lp_schedule(int minor)
 {
-       struct lp_struct *lps = (struct lp_struct *)handle;
-
-       /* Just remember that someone wants the port */
-       lps->should_relinquish = 1;
-
-       /* Don't actually release the port now */
-       return 1;
+       struct pardevice *dev = lp_table[minor].dev;
+       register unsigned long int timeslip = (jiffies - dev->time);
+       if ((timeslip > dev->timeslice) && (dev->port->waithead != NULL)) {
+               lp_parport_release(minor);
+               schedule ();
+               lp_parport_claim(minor);
+       } else
+               schedule();
 }
 
 static int lp_reset(int minor)
 {
+       int retval;
+       lp_parport_claim (minor);
        w_ctr(minor, LP_PSELECP);
-       udelay(LP_DELAY);
+       udelay (LP_DELAY);
        w_ctr(minor, LP_PSELECP | LP_PINITP);
-       return r_str(minor);
-}
-
-static inline int must_use_polling(int minor)
-{
-       return lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE ||
-                      lp_table[minor].dev->port->devices->next;
+       retval = r_str(minor);
+       lp_parport_release (minor);
+       return retval;
 }
 
-static inline int lp_char(char lpchar, int minor, int use_polling)
+static inline int lp_char(char lpchar, int minor)
 {
        int status;
        unsigned int wait = 0;
@@ -126,28 +164,33 @@ static inline int lp_char(char lpchar, int minor, int use_polling)
        struct lp_stats *stats;
 
        do {
-               status = r_str(minor);
+               status = r_str (minor);
                count++;
-               if (need_resched)
-                       lp_schedule (minor);
-       } while (((use_polling && !LP_READY(minor, status)) || 
-                (!use_polling && !(status & LP_PBUSY))) &&
-                (count < LP_CHAR(minor)));
-
-       if (count == LP_CHAR(minor) ||
-           (!use_polling && !LP_CAREFUL_READY(minor, status)))
+               lp_yield(minor);
+       } while (!LP_READY(minor, status) && count < LP_CHAR(minor));
+
+       if (count == LP_CHAR(minor))
                return 0;
+
        w_dtr(minor, lpchar);
        stats = &LP_STAT(minor);
        stats->chars++;
        /* must wait before taking strobe high, and after taking strobe
           low, according spec.  Some printers need it, others don't. */
+#ifndef __sparc__
        while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */
                wait++;
+#else
+       udelay(1);
+#endif
        /* control port takes strobe high */
        w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
+#ifndef __sparc__
        while (wait)                    /* FIXME: should be a udelay() */
                wait--;
+#else
+       udelay(1);
+#endif
        /* take strobe low */
        w_ctr(minor, LP_PSELECP | LP_PINITP);
        /* update waittime statistics */
@@ -170,19 +213,42 @@ static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
 
-       if (waitqueue_active (&lp_dev->lp_wait_q))
-               wake_up(&lp_dev->lp_wait_q);
+       if (waitqueue_active (&lp_dev->dev->wait_q))
+               wake_up_interruptible(&lp_dev->dev->wait_q);
 }
 
 static void lp_error(int minor)
 {
-       if (must_use_polling(minor)) {
+       if (LP_POLLING(minor) || LP_PREEMPTED(minor)) {
                current->state = TASK_INTERRUPTIBLE;
                current->timeout = jiffies + LP_TIMEOUT_POLLED;
-               lp_schedule (minor);
+               lp_parport_release(minor);
+               schedule();
+               lp_parport_claim(minor);
        }
 }
 
+static int lp_check_status(int minor) {
+       unsigned char status = r_str(minor);
+       if ((status & LP_POUTPA)) {
+               printk(KERN_INFO "lp%d out of paper\n", minor);
+               if (LP_F(minor) & LP_ABORT)
+                       return 1;
+               lp_error(minor);
+       } else if (!(status & LP_PSELECD)) {
+               printk(KERN_INFO "lp%d off-line\n", minor);
+               if (LP_F(minor) & LP_ABORT)
+                       return 1;
+               lp_error(minor);
+       } else if (!(status & LP_PERRORP)) {
+               printk(KERN_ERR "lp%d printer error\n", minor);
+               if (LP_F(minor) & LP_ABORT)
+                       return 1;
+               lp_error(minor);
+       }
+       return 0;
+}
+
 static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
 {
        unsigned long copy_size;
@@ -202,7 +268,7 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
                copy_from_user(lp->lp_buffer, buf, copy_size);
 
                while (copy_size) {
-                       if (lp_char(lp->lp_buffer[bytes_written], minor, must_use_polling(minor))) {
+                       if (lp_char(lp->lp_buffer[bytes_written], minor)) {
                                --copy_size;
                                ++bytes_written;
                                lp_table[minor].runchars++;
@@ -210,36 +276,24 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
                                int rc = total_bytes_written + bytes_written;
                                if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
                                        LP_STAT(minor).maxrun = lp_table[minor].runchars;
-                               status = r_str(minor);
-                               if ((status & LP_POUTPA)) {
-                                       printk(KERN_INFO "lp%d out of paper\n", minor);
-                                       if (LP_F(minor) & LP_ABORT)
-                                               return rc ? rc : -ENOSPC;
-                                       lp_error(minor);
-                               } else if (!(status & LP_PSELECD)) {
-                                       printk(KERN_INFO "lp%d off-line\n", minor);
-                                       if (LP_F(minor) & LP_ABORT)
-                                               return rc ? rc : -EIO;
-                                       lp_error(minor);
-                               } else if (!(status & LP_PERRORP)) {
-                                       printk(KERN_ERR "lp%d printer error\n", minor);
-                                       if (LP_F(minor) & LP_ABORT)
-                                               return rc ? rc : -EIO;
-                                       lp_error(minor);
-                               }
-
                                LP_STAT(minor).sleeps++;
 
-                               if (must_use_polling(minor)) {
+                               if (LP_POLLING(minor)) {
+                               lp_polling:
+                                       if (lp_check_status(minor))
+                                               return rc ? rc : -EIO;
 #ifdef LP_DEBUG
                                        printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp_table[minor].runchars, LP_TIME(minor));
 #endif
-                                       lp_table[minor].runchars = 0;
                                        current->state = TASK_INTERRUPTIBLE;
                                        current->timeout = jiffies + LP_TIME(minor);
                                        lp_schedule (minor);
                                } else {
                                        cli();
+                                       if (LP_PREEMPTED(minor)) {
+                                               sti();
+                                               goto lp_polling;
+                                       }
                                        enable_irq(lp->dev->port->irq);
                                        w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN);
                                        status = r_str(minor);
@@ -249,14 +303,16 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
                                                sti();
                                                continue;
                                        }
-                                       lp_table[minor].runchars = 0;
                                        current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
-                                       interruptible_sleep_on(&lp->lp_wait_q);
-
+                                       interruptible_sleep_on(&lp->dev->wait_q);
                                        w_ctr(minor, LP_PSELECP | LP_PINITP);
                                        sti();
+                                       if (lp_check_status(minor))
+                                               return rc ? rc : -EIO;
                                }
 
+                               lp_table[minor].runchars = 0;
+
                                if (signal_pending(current)) {
                                        if (total_bytes_written + bytes_written)
                                                return total_bytes_written + bytes_written;
@@ -287,12 +343,11 @@ static ssize_t lp_write(struct file * file, const char * buf,
        lp_table[minor].lastcall = jiffies;
 
        /* Claim Parport or sleep until it becomes available
-        * (see lp_wakeup() for details)
         */
        lp_parport_claim (minor);
 
        retv = lp_write_buf(minor, buf, count);
+
        lp_parport_release (minor);
        return retv;
 }
@@ -307,14 +362,15 @@ static long long lp_lseek(struct file * file, long long offset, int origin)
 static int lp_read_nibble(int minor) 
 {
        unsigned char i;
-       i=r_str(minor)>>3;
-       i&=~8;
-       if ( ( i & 0x10) == 0) i|=8;
-       return(i & 0x0f);
+       i = r_str(minor)>>3;
+       i &= ~8;
+       if ((i & 0x10) == 0) i |= 8;
+       return (i & 0x0f);
 }
 
-static void lp_select_in_high(int minor) {
-       w_ctr(minor, (r_ctr(minor) | 8));
+static inline void lp_select_in_high(int minor) 
+{
+       parport_frob_control(lp_table[minor].dev->port, 8, 8);
 }
 
 /* Status readback confirming to ieee1284 */
@@ -329,7 +385,6 @@ static ssize_t lp_read(struct file * file, char * buf,
        unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
        
        /* Claim Parport or sleep until it becomes available
-        * (see lp_wakeup() for details)
         */
        lp_parport_claim (minor);
 
@@ -351,26 +406,27 @@ static ssize_t lp_read(struct file * file, char * buf,
                return temp-buf;          /*  End of file */
        }
        for (i=0; i<=(count*2); i++) {
-               w_ctr(minor, r_ctr(minor) | 2); /* AutoFeed high */
+               parport_frob_control(lp_table[minor].dev->port, 2, 2); /* AutoFeed high */
                do {
-                       status=(r_str(minor) & 0x40);
+                       status = (r_str(minor) & 0x40);
                        udelay(50);
                        counter++;
                        if (need_resched)
                                schedule ();
-               } while ( (status == 0x40) && (counter < 20) );
-               if ( counter == 20 ) { /* Timeout */
+               } while ((status == 0x40) && (counter < 20));
+               if (counter == 20) { 
+                       /* Timeout */
 #ifdef LP_READ_DEBUG
                        printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n");
-#endif         
-                       w_ctr(minor, r_ctr(minor) & ~2);
+#endif
+                       parport_frob_control(lp_table[minor].dev->port, 2, 0);
                        lp_select_in_high(minor);
                        parport_release(lp_table[minor].dev);
                        return temp-buf; /* end the read at timeout */
                }
                counter=0;
-               z=lp_read_nibble(minor);
-               w_ctr(minor, r_ctr(minor) & ~2); /* AutoFeed low */
+               z = lp_read_nibble(minor);
+               parport_frob_control(lp_table[minor].dev->port, 2, 0); /* AutoFeed low */
                do {
                        status=(r_str(minor) & 0x40);
                        udelay(20);
@@ -427,7 +483,10 @@ static int lp_open(struct inode * inode, struct file * file)
           a non-standard manner.  This is strictly a Linux hack, and
           should most likely only ever be used by the tunelp application. */
        if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
-               int status = r_str(minor);
+               int status;
+               lp_parport_claim (minor);
+               status = r_str(minor);
+               lp_parport_release (minor);
                if (status & LP_POUTPA) {
                        printk(KERN_INFO "lp%d out of paper\n", minor);
                        MOD_DEC_USE_COUNT;
@@ -462,7 +521,6 @@ static int lp_release(struct inode * inode, struct file * file)
        return 0;
 }
 
-
 static int lp_ioctl(struct inode *inode, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
@@ -520,7 +578,10 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        if (retval)
                                return retval;
                        else {
-                               int status = r_str(minor);
+                               int status;
+                               lp_parport_claim (minor);
+                               status = r_str(minor);
+                               lp_parport_release (minor);
                                copy_to_user((int *) arg, &status, sizeof(int));
                        }
                        break;
@@ -571,19 +632,27 @@ static struct file_operations lp_fops = {
        lp_release
 };
 
-static int parport[LP_NO] = { UNSPEC, };
+/* --- initialisation code ------------------------------------- */
 
 #ifdef MODULE
-#define lp_init init_module
+
+static int parport[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int reset = 0;
+static int autoprobe = 0;
+
 MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "i");
+MODULE_PARM(reset, "i");
+MODULE_PARM(autoprobe, "i");
 
 #else
 
+static int parport[LP_NO] __initdata = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
+static int reset __initdata = 0;
+
 static int parport_ptr = 0;
 
-void lp_setup(char *str, int *ints)
+__initfunc(void lp_setup(char *str, int *ints))
 {
-       /* Ugh. */
        if (!strncmp(str, "parport", 7)) {
                int n = simple_strtoul(str+7, NULL, 10);
                if (parport_ptr < LP_NO)
@@ -592,11 +661,15 @@ void lp_setup(char *str, int *ints)
                        printk(KERN_INFO "lp: too many ports, %s ignored.\n",
                               str);
        } else if (!strcmp(str, "auto")) {
-               parport[0] = AUTO;
+               parport[0] = LP_PARPORT_AUTO;
+       } else if (!strcmp(str, "none")) {
+               parport_ptr++;
+       } else if (!strcmp(str, "reset")) {
+               reset = 1;
        } else {
                if (ints[0] == 0 || ints[1] == 0) {
                        /* disable driver on "lp=" or "lp=0" */
-                       parport[0] = OFF;
+                       parport[0] = LP_PARPORT_OFF;
                } else {
                        printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]);
                }
@@ -605,87 +678,91 @@ void lp_setup(char *str, int *ints)
 
 #endif
 
-void lp_wakeup(void *ref)
+int lp_register(int nr, struct parport *port)
 {
-       struct lp_struct *lp_dev = (struct lp_struct *) ref;
+       lp_table[nr].dev = parport_register_device(port, "lp", 
+                                                  lp_preempt, NULL,
+                                                  lp_interrupt, 
+                                                  PARPORT_DEV_TRAN,
+                                                  (void *) &lp_table[nr]);
+       if (lp_table[nr].dev == NULL)
+               return 1;
+       lp_table[nr].flags |= LP_EXIST;
 
-       if (!waitqueue_active (&lp_dev->lp_wait_q))
-               return; /* Wake up whom? */
+       if (reset)
+               lp_reset(nr);
 
-       /* Claim the Parport */
-       if (parport_claim(lp_dev->dev))
-               return; /* Shouldn't happen */
+       printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, 
+              (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
 
-       wake_up(&lp_dev->lp_wait_q);
-}
-
-static int inline lp_searchfor(int list[], int a)
-{
-       int i;
-       for (i = 0; i < LP_NO && list[i] != UNSPEC; i++) {
-               if (list[i] == a) return 1;
-       }
        return 0;
 }
 
 int lp_init(void)
 {
-       int count = 0;
-       struct parport *pb;
-  
-       if (parport[0] == OFF) return 0;
-
-       pb = parport_enumerate();
-
-       while (pb) {
-               /* We only understand PC-style ports. */
-               if (pb->modes & PARPORT_MODE_PCSPP) {
-                       if (parport[0] == UNSPEC ||
-                           lp_searchfor(parport, count) ||
-                           (parport[0] == AUTO &&
-                            pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
-                               lp_table[count].dev =
-                                 parport_register_device(pb, dev_name, 
-                                               lp_preempt, lp_wakeup,
-                                               lp_interrupt, PARPORT_DEV_TRAN,
-                                               (void *) &lp_table[count]);
-                               lp_table[count].flags |= LP_EXIST;
-                               init_waitqueue (&lp_table[count].lp_wait_q);
-                               lp_parport_claim (count);
-                               lp_reset (count);
-                               lp_parport_release (count);
-                               printk(KERN_INFO "lp%d: using %s (%s).\n", 
-                                      count, pb->name, (pb->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven");
+       unsigned int count = 0;
+       struct parport *port;
+
+       switch (parport[0])
+       {
+       case LP_PARPORT_OFF:
+               return 0;
+
+       case LP_PARPORT_UNSPEC:
+       case LP_PARPORT_AUTO:
+               for (port = parport_enumerate(); port; port = port->next) {
+
+                       if (parport[0] == LP_PARPORT_AUTO &&
+                           port->probe_info.class != PARPORT_CLASS_PRINTER)
+                               continue;
+
+                       if (!lp_register(count, port))
+                               if (++count == LP_NO)
+                                       break;
+               }
+               break;
+
+       default:
+               for (count = 0; count < LP_NO; count++) {
+                       if (parport[count] != LP_PARPORT_UNSPEC) {
+                               char buffer[16];
+                               sprintf(buffer, "parport%d", parport[count]);
+                               for (port = parport_enumerate(); port; 
+                                    port = port->next) {
+                                       if (!strcmp(port->name, buffer)) {
+                                               (void) lp_register(count, port);
+                                               break;
+                                       }
+                               }
                        }
-                       if (++count == LP_NO)
-                               break;
                }
-               pb = pb->next;
-       }
+               break;
+       }
 
-       /* Successful specified devices increase count
-        * Unsuccessful specified devices increase failed
-        */
-       if (count) {
+       if (count) {
                if (register_chrdev(LP_MAJOR, "lp", &lp_fops)) {
                        printk("lp: unable to get major %d\n", LP_MAJOR);
                        return -EIO;
                }
-               return 0;
+       } else {
+               printk(KERN_INFO "lp: driver loaded but no devices found\n");
        }
 
-       printk(KERN_INFO "lp: driver loaded but no devices found\n");
-#ifdef MODULE
        return 0;
-#else  
-       return 1;
-#endif
 }
 
 #ifdef MODULE
+int init_module(void)
+{
+       if (autoprobe)
+               parport[0] = LP_PARPORT_AUTO;
+
+       return lp_init();
+}
+
 void cleanup_module(void)
 {
-       int offset;
+       unsigned int offset;
 
        unregister_chrdev(LP_MAJOR, "lp");
        for (offset = 0; offset < LP_NO; offset++) {
index a9f06c880c59cdfbe9f542715cb080a428b76fd7..525f447f84e0d53691b439d3a92812154e938768 100644 (file)
@@ -52,10 +52,11 @@ static char *revision = "$Revision: 1.4 $";
 
 /* ------------------------------------------------------------- */
 
-int portbase = 0x150;
-int irq = 15;
 int showcapimsgs = 0;          /* used in lli.c */
 int loaddebug = 0;
+static int portbase = 0x150;
+#ifdef MODULE
+static int irq = 15;
 
 #ifdef HAS_NEW_SYMTAB
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -64,6 +65,7 @@ MODULE_PARM(irq, "2-15i");
 MODULE_PARM(showcapimsgs, "0-3i");
 MODULE_PARM(loaddebug, "0-1i");
 #endif
+#endif
 
 /* ------------------------------------------------------------- */
 
index 595fb713e56ad7662c0b4fba9ef0992c8c8aa99c..7379c8a779e5caef87f1309290312031a2058cbd 100644 (file)
@@ -179,23 +179,23 @@ static char HiSaxID[96] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
 char *HiSax_id = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
-int type[] =
+static int type[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int protocol[] =
+static int protocol[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int io[] =
+static int io[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #ifdef CONFIG_HISAX_16_3       /* For Creatix/Teles PnP */
-int io0[] =
+static int io0[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int io1[] =
+static int io1[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #endif
-int irq[] =
+static int irq[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-int mem[] =
+static int mem[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-char *id = HiSaxID;
+static char *id = HiSaxID;
 
 #if (LINUX_VERSION_CODE > 0x020111)
 MODULE_AUTHOR("Karsten Keil");
index 598dc8ca93cf67a6383f60acc166a1567a6735fb..34f8fc1c54e604bc1bfe7c65c51a8f84f0bf9360 100644 (file)
 #include <linux/isdnif.h>
 #include "pcbit.h"
 
-int mem[MAX_PCBIT_CARDS] = {0, };
-int irq[MAX_PCBIT_CARDS] = {0, };
+static int mem[MAX_PCBIT_CARDS] = {0, };
+static int irq[MAX_PCBIT_CARDS] = {0, };
 
-int num_boards;
+static int num_boards;
 struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS] = {0, 0, 0, 0};
 
 int init_module(void);
index b0f07ac3c9cda1cc8b4a7f51fe6b6fcda98d6526..4a769822567b2c5bcfccb3f83ebd26e6e3808805 100644 (file)
                                           this, you must also change the number
                                           of elements in io, irq, and ram to
                                           match. Initialized in init.c */
-/*
-extern unsigned int io[];
-extern unsigned char irq[];
-extern unsigned long ram[];
-*/
 
 #define SIGNATURE      0x87654321      /* Board reset signature */
 #define SIG_OFFSET     0x1004          /* Where to find signature in shared RAM */
index 6ce4fb06e5a8ed02c1a8193af19f9f19c8438762..951f06f258f81f1d191eeab1cb207de49917e9b0 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/module.h>
 #include <linux/version.h>
-#include <stdio.h>
 #include <linux/errno.h>
 #include <asm/segment.h>
 #include <asm/io.h>
index eeaecdd8ffdf4725653557acb99855e8de573641..c9eb24035e658aca69b2b98d3e32a5144bbe69a8 100644 (file)
@@ -11,10 +11,10 @@ const char version[] = "2.0b1";
 const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
 
 /* insmod set parameters */
-unsigned int io[] = {0,0,0,0};
-unsigned char irq[] = {0,0,0,0};
-unsigned long ram[] = {0,0,0,0};
-int do_reset = 0;
+static unsigned int io[] = {0,0,0,0};
+static unsigned char irq[] = {0,0,0,0};
+static unsigned long ram[] = {0,0,0,0};
+static int do_reset = 0;
 
 static int sup_irq[] = { 11, 10, 9, 5, 12, 14, 7, 3, 4, 6 };
 #define MAX_IRQS       10
index cecbf703be398e183e0cc682a9e268efd12ef6fe..4fb4fd45aba09f63db2442144c2f7abc0e7860fa 100644 (file)
@@ -1,6 +1,4 @@
 Currently known (or at least suspected) bugs in parport:
 
-o IEEE1284 code does not do the terminating handshake after transfers, which
-  seems to upset some devices.
-
 o lp doesn't allow you to read status while printing is in progress.
+
index 1137f6e80ccc2c2f83d35cb751565aa45d7f2632..9b4aab9194051634cba43bf70b637f936cfac77c 100644 (file)
@@ -48,10 +48,10 @@ else
     M_OBJS += parport.o
   endif
   ifeq ($(CONFIG_PARPORT_PC),m)
-    MX_OBJS += parport_pc.o
+    M_OBJS += parport_pc.o
   endif
   ifeq ($(CONFIG_PARPORT_AX),m)
-    MX_OBJS += parport_ax.o
+    M_OBJS += parport_ax.o
   endif
 endif
 
index 5ffe406fa15e27d05c105324d7c5dcbebace764b..08860cc2795670222e22b7000d226183b31e09dd 100644 (file)
@@ -4,7 +4,7 @@ Things to be done.
 
 1. Proper documentation.
 
-2. Overhaul lp.c:
+2. A better lp.c:
 
    a) It's a _mess_
 
@@ -18,4 +18,8 @@ Things to be done.
       bits when they have something to say.  We should read out and deal 
       with (maybe just log) whatever the printer wants to tell the world.
 
-3. Assimilate more drivers.
+3. Support more hardware (eg m68k, Sun bpp).
+
+4. A better PLIP (make use of bidirectional/ECP/EPP ports).
+
+
index 3a013b4cf2186b47a484d6b6eab5f349ec025eb2..f86ec75305f73087d8fdaf111ec579f43f6b98c1 100644 (file)
@@ -1,24 +1,32 @@
-/* Parallel-port routines for ARC onboard hardware.
+/* Low-level parallel port routines for Archimedes onboard hardware
  *
  * Author: Phil Blundell <Philip.Blundell@pobox.com>
  */
 
-#include <linux/tasks.h>
-
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/dma.h>
+/* This driver is for the parallel port hardware found on Acorn's old
+ * range of Archimedes machines.  The A5000 and newer systems have PC-style
+ * I/O hardware and should use the parport_pc driver instead.
+ *
+ * The Acorn printer port hardware is very simple.  There is a single 8-bit
+ * write-only latch for the data port and control/status bits are handled
+ * with various auxilliary input and output lines.  The port is not
+ * bidirectional, does not support any modes other than SPP, and has only
+ * a subset of the standard printer control lines connected.
+ */
 
+#include <linux/tasks.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
-
 #include <linux/parport.h>
 
-#include <linux/arch/oldlatches.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/arch/oldlatches.h>
+#include <asm/arch/irqs.h>
 
 #define DATA_LATCH    0x3350010
 
@@ -50,7 +58,7 @@ static void arc_dec_use_count(void)
 #endif
 }
 
-static struct parport_operations arc_ops = 
+static struct parport_operations parport_arc_ops = 
 {
        arc_write_data,
        arc_read_data,
@@ -90,3 +98,31 @@ static struct parport_operations arc_ops =
        arc_inc_use_count,
        arc_dec_use_count
 };
+
+/* --- Initialisation code -------------------------------- */
+
+int parport_arc_init(void)
+{
+       /* Archimedes hardware provides only one port, at a fixed address */
+       struct parport *p;
+
+       if (check_region(DATA_LATCH, 4))
+               return 0;
+       
+               if (!(p = parport_register_port(base, IRQ_PRINTERACK, 
+                                       PARPORT_DMA_NONE, &parport_arc_ops))) 
+               return 0;
+
+       p->modes = PARPORT_MODE_ARCSPP;
+       p->size = 4;
+
+       printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
+              p->irq);
+       parport_proc_register(p);
+       p->flags |= PARPORT_FLAG_COMA;
+
+       if (parport_probe_hook)
+               (*parport_probe_hook)(p);
+
+       return 1;
+}
index caaccd6e703ad00a4a4664eee4e963e8ba362f48..c4f29e90334f5b311268a750be35917e6d3bd389 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport_ax.c,v 1.2 1997/10/25 17:27:03 philip Exp $
+/* $Id: parport_ax.c,v 1.5 1998/01/10 18:28:39 ecd Exp $
  * Parallel-port routines for Sun Ultra/AX architecture
  * 
  * Author: Eddie C. Dost <ecd@skynet.be>
@@ -18,6 +18,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 
 #include <linux/parport.h>
 
 #undef HAVE_SLOW_DEVICES
 
 
-#define DATA     0x00
-#define STATUS   0x01
-#define CONTROL  0x02
+#define DATA           0x00
+#define STATUS         0x01
+#define CONTROL                0x02
+#define EPPREG         0x04
 
-#define CFIFO  0x400
-#define DFIFO  0x400
-#define TFIFO  0x400
-#define CNFA   0x400
-#define CNFB   0x401
-#define ECR    0x402
+#define CFIFO          0x400
+#define DFIFO          0x400
+#define TFIFO          0x400
+#define CONFIGA                0x400
+#define CONFIGB                0x401
+#define ECONTROL       0x402
 
 static void
-ax_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+parport_ax_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
        /* NULL function - Does nothing */
-       return;
 }
 
-#if 0
-static unsigned int
-ax_read_configb(struct parport *p)
+void
+parport_ax_write_epp(struct parport *p, unsigned int d)
 {
-       return (unsigned int)inb(p->base + CNFB);
+       outb(d, p->base + EPPREG);
 }
-#endif
 
-static void
-ax_write_data(struct parport *p, unsigned int d)
+unsigned int
+parport_ax_read_epp(struct parport *p)
+{
+       return (unsigned int)inb(p->base + EPPREG);
+}
+
+unsigned int
+parport_ax_read_configb(struct parport *p)
+{
+       return (unsigned int)inb(p->base + CONFIGB);
+}
+
+void
+parport_ax_write_data(struct parport *p, unsigned int d)
 {
        outb(d, p->base + DATA);
 }
 
-static unsigned int
-ax_read_data(struct parport *p)
+unsigned int
+parport_ax_read_data(struct parport *p)
 {
        return (unsigned int)inb(p->base + DATA);
 }
 
-static void
-ax_write_control(struct parport *p, unsigned int d)
+void
+parport_ax_write_control(struct parport *p, unsigned int d)
 {
        outb(d, p->base + CONTROL);
 }
 
-static unsigned int
-ax_read_control(struct parport *p)
+unsigned int
+parport_ax_read_control(struct parport *p)
 {
        return (unsigned int)inb(p->base + CONTROL);
 }
 
-static unsigned int
-ax_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int
+parport_ax_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
 {
        unsigned int old = (unsigned int)inb(p->base + CONTROL);
        outb(((old & ~mask) ^ val), p->base + CONTROL);
        return old;
 }
 
-static void
-ax_write_status(struct parport *p, unsigned int d)
+void
+parport_ax_write_status(struct parport *p, unsigned int d)
 {
        outb(d, p->base + STATUS);
 }
 
-static unsigned int
-ax_read_status(struct parport *p)
+unsigned int
+parport_ax_read_status(struct parport *p)
 {
        return (unsigned int)inb(p->base + STATUS);
 }
 
-static void
-ax_write_econtrol(struct parport *p, unsigned int d)
+void
+parport_ax_write_econtrol(struct parport *p, unsigned int d)
 {
-       outb(d, p->base + ECR);
+       outb(d, p->base + ECONTROL);
 }
 
-static unsigned int
-ax_read_econtrol(struct parport *p)
+unsigned int
+parport_ax_read_econtrol(struct parport *p)
 {
-       return (unsigned int)inb(p->base + ECR);
+       return (unsigned int)inb(p->base + ECONTROL);
 }
 
-static unsigned int
-ax_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int
+parport_ax_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val)
 {
-       unsigned int old = (unsigned int)inb(p->base + ECR);
-       outb(((old & ~mask) ^ val), p->base + ECR);
+       unsigned int old = (unsigned int)inb(p->base + ECONTROL);
+       outb(((old & ~mask) ^ val), p->base + ECONTROL);
        return old;
 }
 
-static void
-ax_change_mode(struct parport *p, int m)
+void
+parport_ax_change_mode(struct parport *p, int m)
 {
-       ax_frob_econtrol(p, 0xe0, m << 5);
+       parport_ax_frob_econtrol(p, 0xe0, m << 5);
 }
 
-static void
-ax_write_fifo(struct parport *p, unsigned int v)
+void
+parport_ax_write_fifo(struct parport *p, unsigned int v)
 {
        outb(v, p->base + DFIFO);
 }
 
-static unsigned int
-ax_read_fifo(struct parport *p)
+unsigned int
+parport_ax_read_fifo(struct parport *p)
 {
        return inb(p->base + DFIFO);
 }
 
-static void
-ax_disable_irq(struct parport *p)
+void
+parport_ax_disable_irq(struct parport *p)
 {
        struct linux_ebus_dma *dma = p->private_data;
        unsigned int dcsr;
@@ -155,8 +166,8 @@ ax_disable_irq(struct parport *p)
        writel(dcsr, (unsigned long)&dma->dcsr);
 }
 
-static void
-ax_enable_irq(struct parport *p)
+void
+parport_ax_enable_irq(struct parport *p)
 {
        struct linux_ebus_dma *dma = p->private_data;
        unsigned int dcsr;
@@ -166,11 +177,11 @@ ax_enable_irq(struct parport *p)
        writel(dcsr, (unsigned long)&dma->dcsr);
 }
 
-static void
-ax_release_resources(struct parport *p)
+void
+parport_ax_release_resources(struct parport *p)
 {
        if (p->irq != PARPORT_IRQ_NONE) {
-               ax_disable_irq(p);
+               parport_ax_disable_irq(p);
                free_irq(p->irq, NULL);
        }
        release_region(p->base, p->size);
@@ -180,13 +191,14 @@ ax_release_resources(struct parport *p)
                       sizeof(struct linux_ebus_dma));
 }
 
-static int
-ax_claim_resources(struct parport *p)
+int
+parport_ax_claim_resources(struct parport *p)
 {
        /* FIXME check that resources are free */
        if (p->irq != PARPORT_IRQ_NONE) {
-               request_irq(p->irq, ax_null_intr_func, 0, p->name, NULL);
-               ax_enable_irq(p);
+               request_irq(p->irq, parport_ax_null_intr_func,
+                           0, p->name, NULL);
+               parport_ax_enable_irq(p);
        }
        request_region(p->base, p->size, p->name);
        if (p->modes & PARPORT_MODE_PCECR)
@@ -196,109 +208,109 @@ ax_claim_resources(struct parport *p)
        return 0;
 }
 
-static void
-ax_save_state(struct parport *p, struct parport_state *s)
+void
+parport_ax_save_state(struct parport *p, struct parport_state *s)
 {
-       s->u.pc.ctr = ax_read_control(p);
-       s->u.pc.ecr = ax_read_econtrol(p);
+       s->u.pc.ctr = parport_ax_read_control(p);
+       s->u.pc.ecr = parport_ax_read_econtrol(p);
 }
 
-static void
-ax_restore_state(struct parport *p, struct parport_state *s)
+void
+parport_ax_restore_state(struct parport *p, struct parport_state *s)
 {
-       ax_write_control(p, s->u.pc.ctr);
-       ax_write_econtrol(p, s->u.pc.ecr);
+       parport_ax_write_control(p, s->u.pc.ctr);
+       parport_ax_write_econtrol(p, s->u.pc.ecr);
 }
 
-static unsigned int
-ax_epp_read_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int
+parport_ax_epp_read_block(struct parport *p, void *buf, unsigned  int length)
 {
        return 0; /* FIXME */
 }
 
-static unsigned int
-ax_epp_write_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int
+parport_ax_epp_write_block(struct parport *p, void *buf, unsigned  int length)
 {
        return 0; /* FIXME */
 }
 
-static unsigned int
-ax_ecp_read_block(struct parport *p, void *buf, unsigned  int length,
-                 void (*fn)(struct parport *, void *, unsigned int),
-                 void *handle)
+unsigned int
+parport_ax_ecp_read_block(struct parport *p, void *buf, unsigned  int length,
+                         void (*fn)(struct parport *, void *, unsigned int),
+                         void *handle)
 {
        return 0; /* FIXME */
 }
 
-static unsigned int
-ax_ecp_write_block(struct parport *p, void *buf, unsigned  int length,
-                  void (*fn)(struct parport *, void *, unsigned int),
-                  void *handle)
+unsigned int
+parport_ax_ecp_write_block(struct parport *p, void *buf, unsigned  int length,
+                          void (*fn)(struct parport *, void *, unsigned int),
+                          void *handle)
 {
        return 0; /* FIXME */
 }
 
-static int
-ax_examine_irq(struct parport *p)
+int
+parport_ax_examine_irq(struct parport *p)
 {
        return 0; /* FIXME */
 }
 
-static void
-ax_inc_use_count(void)
+void
+parport_ax_inc_use_count(void)
 {
 #ifdef MODULE
        MOD_INC_USE_COUNT;
 #endif
 }
 
-static void
-ax_dec_use_count(void)
+void
+parport_ax_dec_use_count(void)
 {
 #ifdef MODULE
        MOD_DEC_USE_COUNT;
 #endif
 }
 
-static struct parport_operations ax_ops = 
+static struct parport_operations parport_ax_ops = 
 {
-       ax_write_data,
-       ax_read_data,
+       parport_ax_write_data,
+       parport_ax_read_data,
 
-       ax_write_control,
-       ax_read_control,
-       ax_frob_control,
+       parport_ax_write_control,
+       parport_ax_read_control,
+       parport_ax_frob_control,
 
-       ax_write_econtrol,
-       ax_read_econtrol,
-       ax_frob_econtrol,
+       parport_ax_write_econtrol,
+       parport_ax_read_econtrol,
+       parport_ax_frob_econtrol,
 
-       ax_write_status,
-       ax_read_status,
+       parport_ax_write_status,
+       parport_ax_read_status,
 
-       ax_write_fifo,
-       ax_read_fifo,
+       parport_ax_write_fifo,
+       parport_ax_read_fifo,
        
-       ax_change_mode,
+       parport_ax_change_mode,
        
-       ax_release_resources,
-       ax_claim_resources,
+       parport_ax_release_resources,
+       parport_ax_claim_resources,
        
-       ax_epp_write_block,
-       ax_epp_read_block,
+       parport_ax_epp_write_block,
+       parport_ax_epp_read_block,
 
-       ax_ecp_write_block,
-       ax_ecp_read_block,
+       parport_ax_ecp_write_block,
+       parport_ax_ecp_read_block,
        
-       ax_save_state,
-       ax_restore_state,
+       parport_ax_save_state,
+       parport_ax_restore_state,
 
-       ax_enable_irq,
-       ax_disable_irq,
-       ax_examine_irq,
+       parport_ax_enable_irq,
+       parport_ax_disable_irq,
+       parport_ax_examine_irq,
 
-       ax_inc_use_count,
-       ax_dec_use_count
+       parport_ax_inc_use_count,
+       parport_ax_dec_use_count
 };
 
 
@@ -308,14 +320,14 @@ static struct parport_operations ax_ops =
 
 /* Check for ECP
  *
- * Old style XT ports alias io ports every 0x400, hence accessing ECR
+ * Old style XT ports alias io ports every 0x400, hence accessing ECONTROL
  * on these cards actually accesses the CTR.
  *
- * Modern cards don't do this but reading from ECR will return 0xff
+ * Modern cards don't do this but reading from ECONTROL will return 0xff
  * regardless of what is written here if the card does NOT support
  * ECP.
  *
- * We will write 0x2c to ECR and 0xcc to CTR since both of these
+ * We will write 0x2c to ECONTROL and 0xcc to CTR since both of these
  * values are "safe" on the CTR since bits 6-7 of CTR are unused.
  */
 static int parport_ECR_present(struct parport *pb)
@@ -330,7 +342,7 @@ static int parport_ECR_present(struct parport *pb)
                r = pb->ops->read_control(pb);  
                if ((pb->ops->read_econtrol(pb) & 0x2) == (r & 0x2)) {
                        pb->ops->write_control(pb, octr);
-                       return 0; /* Sure that no ECR register exists */
+                       return 0; /* Sure that no ECONTROL register exists */
                }
        }
        
@@ -351,12 +363,12 @@ static int parport_ECP_supported(struct parport *pb)
 {
        int i, oecr = pb->ops->read_econtrol(pb);
        
-       /* If there is no ECR, we have no hope of supporting ECP. */
+       /* If there is no ECONTROL, we have no hope of supporting ECP. */
        if (!(pb->modes & PARPORT_MODE_PCECR))
                return 0;
 
        /*
-        * Using LGS chipset it uses ECR register, but
+        * Using LGS chipset it uses ECONTROL register, but
         * it doesn't support ECP or FIFO MODE
         */
        
@@ -439,7 +451,7 @@ init_one_port(struct linux_ebus_device *dev)
 
        /* Setup temporary access to Device operations */
        tmpport.base = dev->base_address[0];
-       tmpport.ops = &ax_ops;
+       tmpport.ops = &parport_ax_ops;
 
        /* Enable ECP mode, set bit 2 of the CTR first */
        tmpport.ops->write_control(&tmpport, 0x04);
@@ -472,7 +484,7 @@ init_one_port(struct linux_ebus_device *dev)
        irq = dev->irqs[0];
        dma = PARPORT_DMA_AUTO;
 
-       if (!(p = parport_register_port(base, irq, dma, &ax_ops)))
+       if (!(p = parport_register_port(base, irq, dma, &parport_ax_ops)))
                return 0;
 
        /* Safe away pointer to our EBus DMA */
@@ -506,8 +518,8 @@ init_one_port(struct linux_ebus_device *dev)
        parport_proc_register(p);
        p->flags |= PARPORT_FLAG_COMA;
 
-       ax_write_control(p, 0x0c);
-       ax_write_data(p, 0);
+       p->ops->write_control(p, 0x0c);
+       p->ops->write_data(p, 0);
 
        if (parport_probe_hook)
                (*parport_probe_hook)(p);
@@ -515,8 +527,13 @@ init_one_port(struct linux_ebus_device *dev)
        return 1;
 }
 
-int
-parport_ax_init(void)
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int parport_ax_init(void))
+#endif
 {
        struct linux_ebus *ebus;
        struct linux_ebus_device *edev;
@@ -525,17 +542,10 @@ parport_ax_init(void)
        for_all_ebusdev(edev, ebus)
                if (!strcmp(edev->prom_name, "ecpp"))
                        count += init_one_port(edev);
-       return count;
+       return count ? 0 : -ENODEV;
 }
 
 #ifdef MODULE
-
-int
-init_module(void)
-{      
-       return (parport_ax_init() ? 0 : 1);
-}
-
 void
 cleanup_module(void)
 {
index 1ccb67d3262ce8fc21dde439c65629527bc0ebb1..3fc222ff9c90f027b0768b82eeb783cf5a6358b4 100644 (file)
@@ -1,6 +1,6 @@
 /* Parallel-port initialisation code.
  * 
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
+ * Authors: David Campbell <campbell@torque.net>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *         Jose Renau <renau@acm.org>
  *
@@ -57,7 +57,7 @@ __initfunc(void parport_setup(char *str, int *ints))
 #ifdef MODULE
 int init_module(void)
 {
-       parport_proc_init();
+       (void)parport_proc_init();      /* We can go on without it. */
        return 0;
 }
 
@@ -88,6 +88,7 @@ __initfunc(int parport_init(void))
 /* Exported symbols for modules. */
 
 EXPORT_SYMBOL(parport_claim);
+EXPORT_SYMBOL(parport_claim_or_block);
 EXPORT_SYMBOL(parport_release);
 EXPORT_SYMBOL(parport_register_port);
 EXPORT_SYMBOL(parport_unregister_port);
index 71eb184ac004c0fa864fed045a3d3d6d1164202b..3d9fabf1dc096ae92b91e50a6ed179edccbd84de 100644 (file)
@@ -1,4 +1,4 @@
-/* Parallel-port routines for PC architecture
+/* Low-level parallel-port routines for PC-style hardware.
  * 
  * Authors: Phil Blundell <Philip.Blundell@pobox.com>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
@@ -8,6 +8,28 @@
  * based on work by Grant Guenther <grant@torque.net> and Phil Blundell.
  */
 
+/* This driver should work with any hardware that is broadly compatible
+ * with that in the IBM PC.  This applies to the majority of integrated
+ * I/O chipsets that are commonly available.  The expected register
+ * layout is:
+ *
+ *     base+0          data
+ *     base+1          status
+ *     base+2          control
+ *
+ * In addition, there are some optional registers:
+ *
+ *     base+3          EPP command
+ *     base+4          EPP
+ *     base+0x400      ECP config A
+ *     base+0x401      ECP config B
+ *     base+0x402      ECP control
+ *
+ * All registers are 8 bits wide and read/write.  If your hardware differs
+ * only in register addresses (eg because your registers are on 32-bit
+ * word boundaries) then you can alter the constants below to accomodate this.
+ */
+
 #include <linux/stddef.h>
 #include <linux/tasks.h>
 
 #include <linux/malloc.h>
 
 #include <linux/parport.h>
+#include <linux/parport_pc.h>
 
-#define ECONTROL 0x402
-#define CONFIGB  0x401
-#define CONFIGA  0x400
-#define EPPREG   0x4
-#define CONTROL  0x2
-#define STATUS   0x1
-#define DATA     0
+/* Maximum number of ports to support.  It is useless to set this greater
+   than PARPORT_MAX (in <linux/parport.h>).  */
+#define PARPORT_PC_MAX_PORTS  8
 
-#define PC_MAX_PORTS  8
-
-static void pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+static void parport_pc_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
-       /* NULL function - Does nothing */
-       return;
+       /* Null function - does nothing */
 }
 
-#if 0
-static void pc_write_epp(struct parport *p, unsigned int d)
+void parport_pc_write_epp(struct parport *p, unsigned int d)
 {
        outb(d, p->base+EPPREG);
 }
-#endif
 
-static unsigned int pc_read_epp(struct parport *p)
+unsigned int parport_pc_read_epp(struct parport *p)
 {
        return (unsigned int)inb(p->base+EPPREG);
 }
 
-static unsigned int pc_read_configb(struct parport *p)
+unsigned int parport_pc_read_configb(struct parport *p)
 {
        return (unsigned int)inb(p->base+CONFIGB);
 }
 
-static void pc_write_data(struct parport *p, unsigned int d)
+void parport_pc_write_data(struct parport *p, unsigned int d)
 {
        outb(d, p->base+DATA);
 }
 
-static unsigned int pc_read_data(struct parport *p)
+unsigned int parport_pc_read_data(struct parport *p)
 {
        return (unsigned int)inb(p->base+DATA);
 }
 
-static void pc_write_control(struct parport *p, unsigned int d)
+void parport_pc_write_control(struct parport *p, unsigned int d)
 {
        outb(d, p->base+CONTROL);
 }
 
-static unsigned int pc_read_control(struct parport *p)
+unsigned int parport_pc_read_control(struct parport *p)
 {
        return (unsigned int)inb(p->base+CONTROL);
 }
 
-static unsigned int pc_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
 {
        unsigned int old = (unsigned int)inb(p->base+CONTROL);
        outb(((old & ~mask) ^ val), p->base+CONTROL);
        return old;
 }
 
-static void pc_write_status(struct parport *p, unsigned int d)
+void parport_pc_write_status(struct parport *p, unsigned int d)
 {
        outb(d, p->base+STATUS);
 }
 
-static unsigned int pc_read_status(struct parport *p)
+unsigned int parport_pc_read_status(struct parport *p)
 {
        return (unsigned int)inb(p->base+STATUS);
 }
 
-static void pc_write_econtrol(struct parport *p, unsigned int d)
+void parport_pc_write_econtrol(struct parport *p, unsigned int d)
 {
        outb(d, p->base+ECONTROL);
 }
 
-static unsigned int pc_read_econtrol(struct parport *p)
+unsigned int parport_pc_read_econtrol(struct parport *p)
 {
        return (unsigned int)inb(p->base+ECONTROL);
 }
 
-static unsigned int pc_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
+unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
 {
        unsigned int old = (unsigned int)inb(p->base+ECONTROL);
        outb(((old & ~mask) ^ val), p->base+ECONTROL);
        return old;
 }
 
-static void pc_change_mode(struct parport *p, int m)
+void parport_pc_change_mode(struct parport *p, int m)
 {
        /* FIXME */
 }
 
-static void pc_write_fifo(struct parport *p, unsigned int v)
+void parport_pc_write_fifo(struct parport *p, unsigned int v)
 {
        /* FIXME */
 }
 
-static unsigned int pc_read_fifo(struct parport *p)
+unsigned int parport_pc_read_fifo(struct parport *p)
 {
        return 0; /* FIXME */
 }
 
-static void pc_disable_irq(struct parport *p)
+void parport_pc_disable_irq(struct parport *p)
 {
-       /* FIXME */
+       parport_pc_frob_control(p, 0x10, 0);
 }
 
-static void pc_enable_irq(struct parport *p)
+void parport_pc_enable_irq(struct parport *p)
 {
-       /* FIXME */
+       parport_pc_frob_control(p, 0x10, 0x10);
 }
 
-static void pc_release_resources(struct parport *p)
+void parport_pc_release_resources(struct parport *p)
 {
        if (p->irq != PARPORT_IRQ_NONE)
                free_irq(p->irq, NULL);
@@ -147,112 +161,110 @@ static void pc_release_resources(struct parport *p)
                release_region(p->base+0x400, 3);
 }
 
-static int pc_claim_resources(struct parport *p)
+int parport_pc_claim_resources(struct parport *p)
 {
        /* FIXME check that resources are free */
        if (p->irq != PARPORT_IRQ_NONE)
-               request_irq(p->irq, pc_null_intr_func, 0, p->name, NULL);
+               request_irq(p->irq, parport_pc_null_intr_func, 0, p->name, NULL);
        request_region(p->base, p->size, p->name);
        if (p->modes & PARPORT_MODE_PCECR)
                request_region(p->base+0x400, 3, p->name);
        return 0;
 }
 
-static void pc_save_state(struct parport *p, struct parport_state *s)
+void parport_pc_save_state(struct parport *p, struct parport_state *s)
 {
-       s->u.pc.ctr = pc_read_control(p);
-       s->u.pc.ecr = pc_read_econtrol(p);
+       s->u.pc.ctr = parport_pc_read_control(p);
+       s->u.pc.ecr = parport_pc_read_econtrol(p);
 }
 
-static void pc_restore_state(struct parport *p, struct parport_state *s)
+void parport_pc_restore_state(struct parport *p, struct parport_state *s)
 {
-       pc_write_control(p, s->u.pc.ctr);
-       pc_write_econtrol(p, s->u.pc.ecr);
+       parport_pc_write_control(p, s->u.pc.ctr);
+       parport_pc_write_econtrol(p, s->u.pc.ecr);
 }
 
-static unsigned int pc_epp_read_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned  int length)
 {
        return 0; /* FIXME */
 }
 
-static unsigned int pc_epp_write_block(struct parport *p, void *buf, unsigned  int length)
+unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned  int length)
 {
        return 0; /* FIXME */
 }
 
-static unsigned int pc_ecp_read_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
+unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
 {
        return 0; /* FIXME */
 }
 
-static unsigned int pc_ecp_write_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
+unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle)
 {
        return 0; /* FIXME */
 }
 
-static int pc_examine_irq(struct parport *p)
+int parport_pc_examine_irq(struct parport *p)
 {
        return 0; /* FIXME */
 }
 
-static void pc_inc_use_count(void)
+void parport_pc_inc_use_count(void)
 {
 #ifdef MODULE
        MOD_INC_USE_COUNT;
 #endif
 }
 
-static void pc_dec_use_count(void)
+void parport_pc_dec_use_count(void)
 {
 #ifdef MODULE
        MOD_DEC_USE_COUNT;
 #endif
 }
 
-static struct parport_operations pc_ops = 
+struct parport_operations parport_pc_ops = 
 {
-       pc_write_data,
-       pc_read_data,
+       parport_pc_write_data,
+       parport_pc_read_data,
 
-       pc_write_control,
-       pc_read_control,
-       pc_frob_control,
+       parport_pc_write_control,
+       parport_pc_read_control,
+       parport_pc_frob_control,
 
-       pc_write_econtrol,
-       pc_read_econtrol,
-       pc_frob_econtrol,
+       parport_pc_write_econtrol,
+       parport_pc_read_econtrol,
+       parport_pc_frob_econtrol,
 
-       pc_write_status,
-       pc_read_status,
+       parport_pc_write_status,
+       parport_pc_read_status,
 
-       pc_write_fifo,
-       pc_read_fifo,
+       parport_pc_write_fifo,
+       parport_pc_read_fifo,
        
-       pc_change_mode,
+       parport_pc_change_mode,
        
-       pc_release_resources,
-       pc_claim_resources,
+       parport_pc_release_resources,
+       parport_pc_claim_resources,
        
-       pc_epp_write_block,
-       pc_epp_read_block,
+       parport_pc_epp_write_block,
+       parport_pc_epp_read_block,
 
-       pc_ecp_write_block,
-       pc_ecp_read_block,
+       parport_pc_ecp_write_block,
+       parport_pc_ecp_read_block,
        
-       pc_save_state,
-       pc_restore_state,
+       parport_pc_save_state,
+       parport_pc_restore_state,
 
-       pc_enable_irq,
-       pc_disable_irq,
-       pc_examine_irq,
+       parport_pc_enable_irq,
+       parport_pc_disable_irq,
+       parport_pc_examine_irq,
 
-       pc_inc_use_count,
-       pc_dec_use_count
+       parport_pc_inc_use_count,
+       parport_pc_dec_use_count
 };
 
-/******************************************************
- *  DMA detection section:
- */
+/* --- DMA detection -------------------------------------- */
 
 /*
  * Prepare DMA channels from 0-8 to transmit towards buffer
@@ -289,10 +301,10 @@ static int parport_enable_dma(int dma)
        
        for (i = 0; i < 8; i++)
                if (dma & (1 << i)) {
-               cli();
-               enable_dma(i);
-               sti();
-           }
+                       cli();
+                       enable_dma(i);
+                       sti();
+               }
 
        return dma;
 }
@@ -325,13 +337,13 @@ static int parport_detect_dma_transfer(int dma, int size)
 /* Only if supports ECP mode */
 static int programmable_dma_support(struct parport *pb)
 {
-       int dma, oldstate = pc_read_econtrol(pb);
+       int dma, oldstate = parport_pc_read_econtrol(pb);
 
-       pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
+       parport_pc_write_econtrol(pb, 0xe0); /* Configuration MODE */
        
-       dma = pc_read_configb(pb) & 0x07;
+       dma = parport_pc_read_configb(pb) & 0x07;
 
-       pc_write_econtrol(pb, oldstate);
+       parport_pc_write_econtrol(pb, oldstate);
        
        if (dma == 0 || dma == 4) /* Jumper selection */
                return PARPORT_DMA_NONE;
@@ -405,9 +417,7 @@ static int parport_dma_probe(struct parport *pb)
        return retv;
 }
 
-/******************************************************
- *  MODE detection section:
- */
+/* --- Mode detection ------------------------------------- */
 
 /*
  * Clear TIMEOUT BIT in EPP MODE
@@ -416,15 +426,15 @@ static int epp_clear_timeout(struct parport *pb)
 {
        int r;
 
-       if (!(pc_read_status(pb) & 0x01))
+       if (!(parport_pc_read_status(pb) & 0x01))
                return 1;
 
        /* To clear timeout some chips require double read */
-       pc_read_status(pb);
-       r = pc_read_status(pb);
-       pc_write_status(pb, r | 0x01); /* Some reset by writing 1 */
-       pc_write_status(pb, r & 0xfe); /* Others by writing 0 */
-       r = pc_read_status(pb);
+       parport_pc_read_status(pb);
+       r = parport_pc_read_status(pb);
+       parport_pc_write_status(pb, r | 0x01); /* Some reset by writing 1 */
+       parport_pc_write_status(pb, r & 0xfe); /* Others by writing 0 */
+       r = parport_pc_read_status(pb);
 
        return !(r & 0x01);
 }
@@ -436,12 +446,12 @@ static int epp_clear_timeout(struct parport *pb)
 static int parport_SPP_supported(struct parport *pb)
 {
        /* Do a simple read-write test to make sure the port exists. */
-       pc_write_control(pb, 0xc);
-       pc_write_data(pb, 0xaa);
-       if (pc_read_data(pb) != 0xaa) return 0;
+       parport_pc_write_control(pb, 0xc);
+       parport_pc_write_data(pb, 0xaa);
+       if (parport_pc_read_data(pb) != 0xaa) return 0;
        
-       pc_write_data(pb, 0x55);
-       if (pc_read_data(pb) != 0x55) return 0;
+       parport_pc_write_data(pb, 0x55);
+       if (parport_pc_read_data(pb) != 0x55) return 0;
 
        return PARPORT_MODE_PCSPP;
 }
@@ -460,36 +470,36 @@ static int parport_SPP_supported(struct parport *pb)
  */
 static int parport_ECR_present(struct parport *pb)
 {
-       unsigned int r, octr = pc_read_control(pb), 
-         oecr = pc_read_econtrol(pb);
+       unsigned int r, octr = parport_pc_read_control(pb), 
+         oecr = parport_pc_read_econtrol(pb);
 
-       r = pc_read_control(pb);        
-       if ((pc_read_econtrol(pb) & 0x3) == (r & 0x3)) {
-               pc_write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
+       r = parport_pc_read_control(pb);        
+       if ((parport_pc_read_econtrol(pb) & 0x3) == (r & 0x3)) {
+               parport_pc_write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
 
-               r = pc_read_control(pb);        
-               if ((pc_read_econtrol(pb) & 0x2) == (r & 0x2)) {
-                       pc_write_control(pb, octr);
+               r = parport_pc_read_control(pb);        
+               if ((parport_pc_read_econtrol(pb) & 0x2) == (r & 0x2)) {
+                       parport_pc_write_control(pb, octr);
                        return 0; /* Sure that no ECR register exists */
                }
        }
        
-       if ((pc_read_econtrol(pb) & 0x3 ) != 0x1)
+       if ((parport_pc_read_econtrol(pb) & 0x3 ) != 0x1)
                return 0;
 
-       pc_write_econtrol(pb, 0x34);
-       if (pc_read_econtrol(pb) != 0x35)
+       parport_pc_write_econtrol(pb, 0x34);
+       if (parport_pc_read_econtrol(pb) != 0x35)
                return 0;
 
-       pc_write_econtrol(pb, oecr);
-       pc_write_control(pb, octr);
+       parport_pc_write_econtrol(pb, oecr);
+       parport_pc_write_control(pb, octr);
        
        return PARPORT_MODE_PCECR;
 }
 
 static int parport_ECP_supported(struct parport *pb)
 {
-       int i, oecr = pc_read_econtrol(pb);
+       int i, oecr = parport_pc_read_econtrol(pb);
        
        /* If there is no ECR, we have no hope of supporting ECP. */
        if (!(pb->modes & PARPORT_MODE_PCECR))
@@ -500,11 +510,11 @@ static int parport_ECP_supported(struct parport *pb)
         * it doesn't support ECP or FIFO MODE
         */
        
-       pc_write_econtrol(pb, 0xc0); /* TEST FIFO */
-       for (i=0; i < 1024 && (pc_read_econtrol(pb) & 0x01); i++)
-               pc_write_fifo(pb, 0xaa);
+       parport_pc_write_econtrol(pb, 0xc0); /* TEST FIFO */
+       for (i=0; i < 1024 && (parport_pc_read_econtrol(pb) & 0x01); i++)
+               parport_pc_write_fifo(pb, 0xaa);
 
-       pc_write_econtrol(pb, oecr);
+       parport_pc_write_econtrol(pb, oecr);
        return (i==1024)?0:PARPORT_MODE_PCECP;
 }
 
@@ -526,14 +536,14 @@ static int parport_EPP_supported(struct parport *pb)
        if (!epp_clear_timeout(pb))
                return 0;  /* No way to clear timeout */
 
-       pc_write_control(pb, pc_read_control(pb) | 0x20);
-       pc_write_control(pb, pc_read_control(pb) | 0x10);
+       parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20);
+       parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10);
        epp_clear_timeout(pb);
        
-       pc_read_epp(pb);
+       parport_pc_read_epp(pb);
        udelay(30);  /* Wait for possible EPP timeout */
        
-       if (pc_read_status(pb) & 0x01) {
+       if (parport_pc_read_status(pb) & 0x01) {
                epp_clear_timeout(pb);
                return PARPORT_MODE_PCEPP;
        }
@@ -543,17 +553,17 @@ static int parport_EPP_supported(struct parport *pb)
 
 static int parport_ECPEPP_supported(struct parport *pb)
 {
-       int mode, oecr = pc_read_econtrol(pb);
+       int mode, oecr = parport_pc_read_econtrol(pb);
 
        if (!(pb->modes & PARPORT_MODE_PCECR))
                return 0;
        
        /* Search for SMC style EPP+ECP mode */
-       pc_write_econtrol(pb, 0x80);
+       parport_pc_write_econtrol(pb, 0x80);
        
        mode = parport_EPP_supported(pb);
 
-       pc_write_econtrol(pb, oecr);
+       parport_pc_write_econtrol(pb, oecr);
        
        return mode?PARPORT_MODE_PCECPEPP:0;
 }
@@ -577,42 +587,41 @@ static int parport_ECPEPP_supported(struct parport *pb)
 
 static int parport_PS2_supported(struct parport *pb)
 {
-       int ok = 0, octr = pc_read_control(pb);
+       int ok = 0, octr = parport_pc_read_control(pb);
   
        epp_clear_timeout(pb);
 
-       pc_write_control(pb, octr | 0x20);  /* try to tri-state the buffer */
+       parport_pc_write_control(pb, octr | 0x20);  /* try to tri-state the buffer */
        
-       pc_write_data(pb, 0x55);
-       if (pc_read_data(pb) != 0x55) ok++;
+       parport_pc_write_data(pb, 0x55);
+       if (parport_pc_read_data(pb) != 0x55) ok++;
 
-       pc_write_data(pb, 0xaa);
-       if (pc_read_data(pb) != 0xaa) ok++;
+       parport_pc_write_data(pb, 0xaa);
+       if (parport_pc_read_data(pb) != 0xaa) ok++;
        
-       pc_write_control(pb, octr);          /* cancel input mode */
+       parport_pc_write_control(pb, octr);          /* cancel input mode */
 
        return ok?PARPORT_MODE_PCPS2:0;
 }
 
 static int parport_ECPPS2_supported(struct parport *pb)
 {
-       int mode, oecr = pc_read_econtrol(pb);
+       int mode, oecr = parport_pc_read_econtrol(pb);
 
        if (!(pb->modes & PARPORT_MODE_PCECR))
                return 0;
        
-       pc_write_econtrol(pb, 0x20);
+       parport_pc_write_econtrol(pb, 0x20);
        
        mode = parport_PS2_supported(pb);
 
-       pc_write_econtrol(pb, oecr);
+       parport_pc_write_econtrol(pb, oecr);
        return mode?PARPORT_MODE_PCECPPS2:0;
 }
 
-/******************************************************
- *  IRQ detection section:
- *
- * This code is for detecting ECP interrupts (due to problems with the
+/* --- IRQ detection -------------------------------------- */
+
+/* This code is for detecting ECP interrupts (due to problems with the
  * monolithic interrupt probing routines).
  *
  * In short this is a voting system where the interrupt with the most
@@ -667,11 +676,11 @@ static int close_intr_election(long tmp)
 /* Only if supports ECP mode */
 static int programmable_irq_support(struct parport *pb)
 {
-       int irq, oecr = pc_read_econtrol(pb);
+       int irq, oecr = parport_pc_read_econtrol(pb);
 
-       pc_write_econtrol(pb,0xE0); /* Configuration MODE */
+       parport_pc_write_econtrol(pb,0xE0); /* Configuration MODE */
        
-       irq = (pc_read_configb(pb) >> 3) & 0x07;
+       irq = (parport_pc_read_configb(pb) >> 3) & 0x07;
 
        switch(irq){
        case 2:
@@ -687,26 +696,26 @@ static int programmable_irq_support(struct parport *pb)
                irq += 7;
        }
        
-       pc_write_econtrol(pb, oecr);
+       parport_pc_write_econtrol(pb, oecr);
        return irq;
 }
 
 static int irq_probe_ECP(struct parport *pb)
 {
-       int irqs, i, oecr = pc_read_econtrol(pb);
+       int irqs, i, oecr = parport_pc_read_econtrol(pb);
                
        probe_irq_off(probe_irq_on());  /* Clear any interrupts */
        irqs = open_intr_election();
                
-       pc_write_econtrol(pb, 0x00);        /* Reset FIFO */
-       pc_write_econtrol(pb, 0xd0);        /* TEST FIFO + nErrIntrEn */
+       parport_pc_write_econtrol(pb, 0x00);        /* Reset FIFO */
+       parport_pc_write_econtrol(pb, 0xd0);        /* TEST FIFO + nErrIntrEn */
 
        /* If Full FIFO sure that WriteIntrThresold is generated */
-       for (i=0; i < 1024 && !(pc_read_econtrol(pb) & 0x02) ; i++) 
-               pc_write_fifo(pb, 0xaa);
+       for (i=0; i < 1024 && !(parport_pc_read_econtrol(pb) & 0x02) ; i++) 
+               parport_pc_write_fifo(pb, 0xaa);
                
        pb->irq = close_intr_election(irqs);
-       pc_write_econtrol(pb, oecr);
+       parport_pc_write_econtrol(pb, oecr);
        return pb->irq;
 }
 
@@ -716,7 +725,7 @@ static int irq_probe_ECP(struct parport *pb)
  */
 static int irq_probe_EPP(struct parport *pb)
 {
-       int irqs, octr = pc_read_control(pb);
+       int irqs, octr = parport_pc_read_control(pb);
 
 #ifndef ADVANCED_DETECT
        return PARPORT_IRQ_NONE;
@@ -726,27 +735,27 @@ static int irq_probe_EPP(struct parport *pb)
        irqs = open_intr_election();
 
        if (pb->modes & PARPORT_MODE_PCECR)
-               pc_write_econtrol(pb, pc_read_econtrol(pb) | 0x10);
+               parport_pc_write_econtrol(pb, parport_pc_read_econtrol(pb) | 0x10);
        
        epp_clear_timeout(pb);
-       pc_write_control(pb, pc_read_control(pb) | 0x20);
-       pc_write_control(pb, pc_read_control(pb) | 0x10);
+       parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x20);
+       parport_pc_write_control(pb, parport_pc_read_control(pb) | 0x10);
        epp_clear_timeout(pb);
 
        /*  Device isn't expecting an EPP read
         * and generates an IRQ.
         */
-       pc_read_epp(pb);
+       parport_pc_read_epp(pb);
        udelay(20);
 
        pb->irq = close_intr_election(irqs);
-       pc_write_control(pb, octr);
+       parport_pc_write_control(pb, octr);
        return pb->irq;
 }
 
 static int irq_probe_SPP(struct parport *pb)
 {
-       int irqs, octr = pc_read_control(pb);
+       int irqs, octr = parport_pc_read_control(pb);
 
 #ifndef ADVANCED_DETECT
        return PARPORT_IRQ_NONE;
@@ -756,26 +765,26 @@ static int irq_probe_SPP(struct parport *pb)
        irqs = probe_irq_on();
 
        if (pb->modes & PARPORT_MODE_PCECR)
-               pc_write_econtrol(pb, 0x10);
+               parport_pc_write_econtrol(pb, 0x10);
 
-       pc_write_data(pb,0x00);
-       pc_write_control(pb,0x00);
-       pc_write_control(pb,0x0c);
+       parport_pc_write_data(pb,0x00);
+       parport_pc_write_control(pb,0x00);
+       parport_pc_write_control(pb,0x0c);
        udelay(5);
-       pc_write_control(pb,0x0d);
+       parport_pc_write_control(pb,0x0d);
        udelay(5);
-       pc_write_control(pb,0x0c);
+       parport_pc_write_control(pb,0x0c);
        udelay(25);
-       pc_write_control(pb,0x08);
+       parport_pc_write_control(pb,0x08);
        udelay(25);
-       pc_write_control(pb,0x0c);
+       parport_pc_write_control(pb,0x0c);
        udelay(50);
 
        pb->irq = probe_irq_off(irqs);
        if (pb->irq <= 0)
                pb->irq = PARPORT_IRQ_NONE;     /* No interrupt detected */
        
-       pc_write_control(pb, octr);
+       parport_pc_write_control(pb, octr);
        return pb->irq;
 }
 
@@ -796,10 +805,10 @@ static int parport_irq_probe(struct parport *pb)
                        
        if (pb->irq == PARPORT_IRQ_NONE && 
            (pb->modes & PARPORT_MODE_PCECPEPP)) {
-               int oecr = pc_read_econtrol(pb);
-               pc_write_econtrol(pb, 0x80);
+               int oecr = parport_pc_read_econtrol(pb);
+               parport_pc_write_econtrol(pb, 0x80);
                pb->irq = irq_probe_EPP(pb);
-               pc_write_econtrol(pb, oecr);
+               parport_pc_write_econtrol(pb, oecr);
        }
 
        epp_clear_timeout(pb);
@@ -815,14 +824,16 @@ static int parport_irq_probe(struct parport *pb)
        return pb->irq;
 }
 
+/* --- Initialisation code -------------------------------- */
+
 static int probe_one_port(unsigned long int base, int irq, int dma)
 {
        struct parport tmpport, *p;
        if (check_region(base, 3)) return 0;
        tmpport.base = base;
-       tmpport.ops = &pc_ops;
+       tmpport.ops = &parport_pc_ops;
        if (!(parport_SPP_supported(&tmpport))) return 0;
-               if (!(p = parport_register_port(base, irq, dma, &pc_ops))) return 0;
+               if (!(p = parport_register_port(base, irq, dma, &parport_pc_ops))) return 0;
        p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p);
        if (p->base != 0x3bc) {
                if (!check_region(base+0x400,3)) {
@@ -866,8 +877,8 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
        p->flags |= PARPORT_FLAG_COMA;
 
        /* Done probing.  Now put the port into a sensible start-up state. */
-       pc_write_control(p, 0xc);
-       pc_write_data(p, 0);
+       parport_pc_write_control(p, 0xc);
+       parport_pc_write_data(p, 0);
 
        if (parport_probe_hook)
                (*parport_probe_hook)(p);
@@ -882,23 +893,29 @@ int parport_pc_init(int *io, int *irq, int *dma)
                /* Only probe the ports we were given. */
                do {
                        count += probe_one_port(*(io++), *(irq++), *(dma++));
-               } while (*io && (++i < PC_MAX_PORTS));
+               } while (*io && (++i < PARPORT_PC_MAX_PORTS));
        } else {
                /* Probe all the likely ports. */
                count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
                count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
                count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
        }
+
+       /* Give any attached devices a chance to gather their thoughts */
+       current->state = TASK_INTERRUPTIBLE;
+       current->timeout = jiffies + 75;
+       schedule ();
+
        return count;
 }
 
 #ifdef MODULE
-static int io[PC_MAX_PORTS+1] = { [0 ... PC_MAX_PORTS] = 0 };
-static int dma[PC_MAX_PORTS] = { [0 ... PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
-static int irq[PC_MAX_PORTS] = { [0 ... PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
-MODULE_PARM(io, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
-MODULE_PARM(dma, "1-" __MODULE_STRING(PC_MAX_PORTS) "i");
+static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int dma[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
+static int irq[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_AUTO };
+MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
 
 int init_module(void)
 {      
index e75fba3351f2cf716a382314510a2657e270087f..1817f876c5f1ff5cc588ea78fabb4d743098b81a 100644 (file)
@@ -1,10 +1,11 @@
 /* Parallel port /proc interface code.
  * 
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
- *          Tim Waugh <tmw20@cam.ac.uk>
+ * Authors: David Campbell <campbell@torque.net>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *          Philip Blundell <philb@gnu.org>
  *
  * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell <Philip.Blundell@pobox.com>
+ *              and Philip Blundell
  */
 
 #include <linux/stddef.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
-
 #include <linux/proc_fs.h>
-
 #include <linux/parport.h>
 
-#undef PARPORT_INCLUDE_BENCH
-
-struct proc_dir_entry *base=NULL;
+struct proc_dir_entry *base = NULL;
 
 extern void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
 
@@ -36,24 +33,28 @@ static int irq_write_proc(struct file *file, const char *buffer,
        int newirq;
        struct parport *pp = (struct parport *)data;
        
-       if (count > 4 )  /* more than 4 digits for a irq 0x?? 0?? ??  */
-               return(-EOVERFLOW);
+       if (count > 5 )  /* more than 4 digits + \n for a irq 0x?? 0?? ??  */
+               return -EOVERFLOW;
 
        if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) {
                newirq = PARPORT_IRQ_NONE;
        } else {
                if (buffer[0] == '0') {
-                       if( buffer[1] == 'x' )
-                               newirq = simple_strtoul(&buffer[2],0,16);
+                       if (buffer[1] == 'x')
+                               newirq = simple_strtoul(&buffer[2], 0, 16);
                        else
-                               newirq = simple_strtoul(&buffer[1],0,8);
+                               newirq = simple_strtoul(&buffer[1], 0, 8);
                } else {
-                       newirq = simple_strtoul(buffer,0,10);
+                       newirq = simple_strtoul(buffer, 0, 10);
                }
        }
 
-       if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) 
-               free_irq(pp->irq, pp);
+       if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) {
+               if (pp->cad->irq_func)
+                       free_irq(pp->irq, pp->cad->private);
+               else
+                       free_irq(pp->irq, NULL);
+       }
 
        pp->irq = newirq;
 
@@ -66,11 +67,12 @@ static int irq_write_proc(struct file *file, const char *buffer,
                                request_irq(pp->irq, pd->irq_func ? 
                                            pd->irq_func :
                                            parport_null_intr_func,
-                                           SA_INTERRUPT, pd->name, pd->port);
+                                           SA_INTERRUPT, pd->name,
+                                           pd->private);
                } else {
                        request_irq(pp->irq, pd->irq_func ? pd->irq_func :
                                    parport_null_intr_func,
-                                   SA_INTERRUPT, pp->name, pd->port);
+                                   SA_INTERRUPT, pp->name, NULL);
                }
        }
 
@@ -102,16 +104,13 @@ static int devices_read_proc(char *page, char **start, off_t off,
 
        for (pd1 = pp->devices; pd1 ; pd1 = pd1->next) {
                if (pd1 == pp->cad)
-                       len += sprintf(page+len, "+");
+                       page[len++] = '+';
                else
-                       len += sprintf(page+len, " ");
+                       page[len++] = ' ';
 
-               len += sprintf(page+len, "%s",pd1->name);
+               len += sprintf(page+len, "%s", pd1->name);
 
-               if (pd1 == pp->lurker)
-                       len += sprintf(page+len, " LURK");
-               
-               len += sprintf(page+len,"\n");
+               page[len++] = '\n';
        }
                
        *start = 0;
@@ -120,26 +119,26 @@ static int devices_read_proc(char *page, char **start, off_t off,
 }
 
 static int hardware_read_proc(char *page, char **start, off_t off,
-                                                         int count, int *eof, void *data)
+                                 int count, int *eof, void *data)
 {
        struct parport *pp = (struct parport *)data;
        int len=0;
        
        len += sprintf(page+len, "base:\t0x%lx\n",pp->base);
+
        if (pp->irq == PARPORT_IRQ_NONE)
                len += sprintf(page+len, "irq:\tnone\n");
        else
                len += sprintf(page+len, "irq:\t%d\n",pp->irq);
+
        if (pp->dma == PARPORT_DMA_NONE)
                len += sprintf(page+len, "dma:\tnone\n");
        else
                len += sprintf(page+len, "dma:\t%d\n",pp->dma);
 
-
-#if 0
        len += sprintf(page+len, "modes:\t");
        {
-#define printmode(x) {if(pp->modes&PARPORT_MODE_##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
+#define printmode(x) {if(pp->modes&PARPORT_MODE_PC##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
                int f = 0;
                printmode(SPP);
                printmode(PS2);
@@ -149,65 +148,21 @@ static int hardware_read_proc(char *page, char **start, off_t off,
                printmode(ECPPS2);
 #undef printmode
        }
-       len += sprintf(page+len, "\n");
-
-       len += sprintf(page+len, "mode:\t");
-       if (pp->modes & PARPORT_MODE_ECR) {
-               switch (r_ecr(pp) >> 5) {
-               case 0:
-                       len += sprintf(page+len, "SPP");
-                       if( pp->modes & PARPORT_MODE_PS2 )
-                               len += sprintf(page+len, ",PS2");
-                       if( pp->modes & PARPORT_MODE_EPP )
-                               len += sprintf(page+len, ",EPP");
-                       break;
-               case 1:
-                       len += sprintf(page+len, "ECPPS2");
-                       break;
-               case 2:
-                       len += sprintf(page+len, "DATAFIFO");
-                       break;
-               case 3:
-                       len += sprintf(page+len, "ECP");
-                       break;
-               case 4:
-                       len += sprintf(page+len, "ECPEPP");
-                       break;
-               case 5:
-                       len += sprintf(page+len, "Reserved?");
-                       break;
-               case 6:
-                       len += sprintf(page+len, "TEST");
-                       break;
-               case 7:
-                       len += sprintf(page+len, "Configuration");
-                       break;
-               }
-       } else {
-               len += sprintf(page+len, "SPP");
-               if (pp->modes & PARPORT_MODE_PS2)
-                       len += sprintf(page+len, ",PS2");
-               if (pp->modes & PARPORT_MODE_EPP)
-                       len += sprintf(page+len, ",EPP");
-       }
-       len += sprintf(page+len, "\n");
-#endif 
-#if 0
-       /* Now no detection, please fix with an external function */
-       len += sprintf(page+len, "chipset:\tunknown\n");
-#endif
-#ifdef PARPORT_INCLUDE_BENCHMARK
-       if (pp->speed)
-               len += sprintf(page+len, "bench:\t%d Bytes/s\n",pp->speed);
-       else
-               len += sprintf(page+len, "bench:\tunknown\n");
-#endif 
+       page[len++] = '\n';
 
        *start = 0;
        *eof   = 1;
        return len;
 }
 
+static inline void destroy_proc_entry(struct proc_dir_entry *root, 
+                                     struct proc_dir_entry **d)
+{
+       proc_unregister(root, (*d)->low_ino);
+       kfree(*d);
+       *d = NULL;
+}
+
 static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
                                             struct proc_dir_entry *parent,
                                             unsigned short ino)
@@ -217,6 +172,7 @@ static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
        ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
        if (!ent)
                return NULL;
+
        memset(ent, 0, sizeof(struct proc_dir_entry));
        
        if (mode == S_IFDIR)
@@ -224,11 +180,11 @@ static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
        else if (mode == 0)
                mode = S_IFREG | S_IRUGO;
 
-
        ent->low_ino = ino;
        ent->name = name;
        ent->namelen = strlen(name);
        ent->mode = mode;
+
        if (S_ISDIR(mode)) 
                ent->nlink = 2;
        else
@@ -240,103 +196,95 @@ static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
 }
 
 
-int parport_proc_init()
+int parport_proc_init(void)
 {
        base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT);
 
-       if (base)
-               return 1;
-       else {
-               printk(KERN_ERR "parport: Error creating proc entry /proc/parport\n");
+       if (base == NULL) {
+               printk(KERN_ERR "Unable to initialise /proc/parport.\n");
                return 0;
        }
+
+       return 1;
 }
 
-int parport_proc_cleanup()
+void parport_proc_cleanup(void)
 {
-       if (base)
-               proc_unregister(&proc_root,base->low_ino);
-
+       if (base) proc_unregister(&proc_root,base->low_ino);
        base = NULL;
-       
-       return 0;
 }
 
 int parport_proc_register(struct parport *pp)
 {
-       struct proc_dir_entry *ent;
-       static int conta=0;
-       char *name;
+       static const char *proc_msg = KERN_ERR "%s: Trouble with /proc.\n";
 
-       memset(&pp->pdir,0,sizeof(struct parport_dir));
+       memset(&pp->pdir, 0, sizeof(struct parport_dir));
 
-       if (!base) {
-               printk(KERN_ERR "parport: Error entry /proc/parport, not generated?\n");
+       if (base == NULL) {
+               printk(KERN_ERR "parport_proc not initialised yet.\n");
                return 1;
        }
        
-       name = pp->pdir.name;
-       sprintf(name,"%d",conta++);
+       strncpy(pp->pdir.name, pp->name + strlen("parport"), 
+               sizeof(pp->pdir.name));
 
-       ent = new_proc_entry(name, S_IFDIR, base,0);
-       if (!ent) {
-               printk(KERN_ERR "parport: Error registering proc_entry /proc/%s\n",name);
+       pp->pdir.entry = new_proc_entry(pp->pdir.name, S_IFDIR, base, 0);
+       if (pp->pdir.entry == NULL) {
+               printk(proc_msg, pp->name);
                return 1;
        }
-       pp->pdir.entry = ent;
 
-       ent = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, pp->pdir.entry,0);
-       if (!ent) {
-               printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/irq\n",name);
+       pp->pdir.irq = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, 
+                                     pp->pdir.entry, 0);
+       if (pp->pdir.irq == NULL) {
+               printk(proc_msg, pp->name);
+               destroy_proc_entry(base, &pp->pdir.entry);
                return 1;
        }
-       ent->read_proc = irq_read_proc;
-       ent->write_proc= irq_write_proc;
-       ent->data      = pp;
-       pp->pdir.irq   = ent;
+       pp->pdir.irq->read_proc = irq_read_proc;
+       pp->pdir.irq->write_proc = irq_write_proc;
+       pp->pdir.irq->data = pp;
        
-       ent = new_proc_entry("devices", 0, pp->pdir.entry,0);
-       if (!ent) {
-               printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/devices\n",name);
+       pp->pdir.devices = new_proc_entry("devices", 0, pp->pdir.entry, 0);
+       if (pp->pdir.devices == NULL) {
+               printk(proc_msg, pp->name);
+               destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+               destroy_proc_entry(base, &pp->pdir.entry);
                return 1;
        }
-       ent->read_proc   = devices_read_proc;
-       ent->data        = pp;
-       pp->pdir.devices = ent;
+       pp->pdir.devices->read_proc = devices_read_proc;
+       pp->pdir.devices->data = pp;
        
-       ent = new_proc_entry("hardware", 0, pp->pdir.entry,0);
-       if (!ent) {
-               printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/hardware\n",name);
+       pp->pdir.hardware = new_proc_entry("hardware", 0, pp->pdir.entry, 0);
+       if (pp->pdir.hardware == NULL) {
+               printk(proc_msg, pp->name);
+               destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
+               destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
+               destroy_proc_entry(base, &pp->pdir.entry);
                return 1;
        }
-       ent->read_proc    = hardware_read_proc;
-       ent->data         = pp;
-       pp->pdir.hardware = ent;
+       pp->pdir.hardware->read_proc = hardware_read_proc;
+       pp->pdir.hardware->data = pp;
+
        return 0;
 }
 
 int parport_proc_unregister(struct parport *pp)
 {
        if (pp->pdir.entry) {
-               if (pp->pdir.irq) {
-                       proc_unregister(pp->pdir.entry, pp->pdir.irq->low_ino);
-                       kfree(pp->pdir.irq);
-               }
+               if (pp->pdir.irq) 
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.irq);
                
-               if (pp->pdir.devices) {
-                       proc_unregister(pp->pdir.entry,
-                                       pp->pdir.devices->low_ino);
-                       kfree(pp->pdir.devices);
-               }
+               if (pp->pdir.devices) 
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.devices);
                
-               if (pp->pdir.hardware) {
-                       proc_unregister(pp->pdir.entry,
-                                       pp->pdir.hardware->low_ino);
-                       kfree(pp->pdir.hardware);
-               }
+               if (pp->pdir.hardware)
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.hardware);
+
+               if (pp->pdir.probe)
+                       destroy_proc_entry(pp->pdir.entry, &pp->pdir.probe);
                
-               proc_unregister(base, pp->pdir.entry->low_ino);
-               kfree(pp->pdir.entry);
+               destroy_proc_entry(base, &pp->pdir.entry);
        }
        
        return 0;
index f12debcb821406f5cced39277ef625fde3178f2a..62af8735741ca0a087a4b2d06edf4fc127cb892c 100644 (file)
@@ -1,14 +1,20 @@
-/* $Id: parport_share.c,v 1.8 1997/11/08 18:55:29 philip Exp $
+/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
  * Parallel-port resource manager code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *         Jose Renau <renau@acm.org>
+ *          Jose Renau <renau@acm.org>
+ *          Philip Blundell <philb@gnu.org>
+ *         Andrea Arcangeli <arcangeli@mbox.queen.it>
  *
  * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell <Philip.Blundell@pobox.com>
+ *          and Philip Blundell
  */
 
+#undef PARPORT_DEBUG_SHARING           /* undef for production */
+
+#include <linux/config.h>
+
 #include <linux/tasks.h>
 
 #include <linux/parport.h>
@@ -18,8 +24,9 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
+#include <linux/sched.h>
 
-#include <linux/config.h>
+#include <asm/spinlock.h>
 
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
@@ -27,6 +34,8 @@
 
 #undef PARPORT_PARANOID
 
+#define PARPORT_DEFAULT_TIMESLICE      (HZ/10)
+
 static struct parport *portlist = NULL, *portlist_tail = NULL;
 static int portcount = 0;
 
@@ -48,8 +57,8 @@ struct parport *parport_enumerate(void)
 
 void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
-       /* NULL function - Does nothing */
-       return;
+       /* Null function - does nothing.  IRQs are pointed here whenever
+          there is no real handler for them.  */
 }
 
 struct parport *parport_register_port(unsigned long base, int irq, int dma,
@@ -58,9 +67,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        struct parport *tmp;
 
        /* Check for a previously registered port.
-        * NOTE: we will ignore irq and dma if we find a previously
-        * registered device.
-        */
+          NOTE: we will ignore irq and dma if we find a previously
+          registered device.  */
        for (tmp = portlist; tmp; tmp = tmp->next) {
                if (tmp->base == base)
                        return tmp;
@@ -79,9 +87,10 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        tmp->dma = dma;
        tmp->modes = 0;
        tmp->next = NULL;
-       tmp->devices = tmp->cad = tmp->lurker = NULL;
+       tmp->devices = tmp->cad = NULL;
        tmp->flags = 0;
-       tmp->ops = ops; 
+       tmp->ops = ops;
+       spin_lock_init (&tmp->lock);
 
        tmp->name = kmalloc(15, GFP_KERNEL);
        if (!tmp->name) {
@@ -91,7 +100,7 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        }
        sprintf(tmp->name, "parport%d", portcount);
 
-       /* Here we chain the entry to our list. */
+       /* Chain the entry to our list. */
        if (portlist_tail)
                portlist_tail->next = tmp;
        portlist_tail = tmp;
@@ -101,6 +110,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
        portcount++;
 
        tmp->probe_info.class = PARPORT_CLASS_LEGACY;  /* assume the worst */
+       tmp->waithead = tmp->waittail = NULL;
+
        return tmp;
 }
 
@@ -146,13 +157,7 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
 {
        struct pardevice *tmp;
 
-       /* We only allow one lurking device. */
        if (flags & PARPORT_DEV_LURK) {
-               if (port->lurker) {
-                       printk(KERN_INFO "%s: refused to register second lurker (%s)\n",
-                                  port->name, name);
-                       return NULL;
-               }
                if (!pf || !kf) {
                        printk(KERN_INFO "%s: refused to register lurking device (%s) without callbacks\n", port->name, name);
                        return NULL;
@@ -189,6 +194,7 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
        tmp->flags = flags;
        tmp->irq_func = irq_func;
        port->ops->save_state(port, tmp->state);
+       tmp->waiting = 0;
 
        /* Chain this onto the list */
        tmp->prev = NULL;
@@ -197,40 +203,44 @@ struct pardevice *parport_register_device(struct parport *port, const char *name
                port->devices->prev = tmp;
        port->devices = tmp;
 
-       if (flags & PARPORT_DEV_LURK)
-               port->lurker = tmp;
-
        inc_parport_count();
        port->ops->inc_use_count();
 
+       init_waitqueue(&tmp->wait_q);
+       tmp->timeslice = PARPORT_DEFAULT_TIMESLICE;
+       tmp->waitnext = tmp->waitprev = NULL;
+
        return tmp;
 }
 
 void parport_unregister_device(struct pardevice *dev)
 {
        struct parport *port;
+       unsigned long flags;
 
+#ifdef PARPORT_PARANOID
        if (dev == NULL) {
                printk(KERN_ERR "parport_unregister_device: passed NULL\n");
                return;
        }
+#endif
 
        port = dev->port;
 
        if (port->cad == dev) {
-               printk(KERN_WARNING "%s: refused to unregister currently active device %s.\n", port->name, dev->name);
+               printk(KERN_WARNING "%s: refused to unregister "
+                      "currently active device %s.\n", port->name, dev->name);
                return;
        }
 
-       if (port->lurker == dev)
-               port->lurker = NULL;
-
+       spin_lock_irqsave (&port->lock, flags);
        if (dev->next)
                dev->next->prev = dev->prev;
        if (dev->prev)
                dev->prev->next = dev->next;
        else
                port->devices = dev->next;
+       spin_unlock_irqrestore (&port->lock, flags);
 
        kfree(dev->state);
        kfree(dev);
@@ -247,99 +257,184 @@ void parport_unregister_device(struct pardevice *dev)
 
 int parport_claim(struct pardevice *dev)
 {
-       struct pardevice *pd1;
+       struct pardevice *oldcad;
+       struct parport *port = dev->port;
+       unsigned long flags;
 
-       if (dev->port->cad == dev) {
+       if (port->cad == dev) {
                printk(KERN_INFO "%s: %s already owner\n",
                           dev->port->name,dev->name);
                return 0;
        }
 
+try_again:
        /* Preempt any current device */
-       pd1 = dev->port->cad;
-       if (dev->port->cad) {
-               if (dev->port->cad->preempt) {
-                       if (dev->port->cad->preempt(dev->port->cad->private))
-                               return -EAGAIN;
-                       dev->port->ops->save_state(dev->port, dev->state);
+       if ((oldcad = port->cad)) {
+               if (oldcad->preempt) {
+                       if (oldcad->preempt(oldcad->private))
+                               goto blocked;
+                       port->ops->save_state(port, dev->state);
                } else
-                       return -EAGAIN;
+                       goto blocked;
+
+               if (port->cad != oldcad) {
+                       printk(KERN_WARNING 
+                              "%s: %s released port when preempted!\n",
+                              port->name, oldcad->name);
+                       if (port->cad)
+                               goto blocked;
+               }
        }
 
-       /* Watch out for bad things */
-       if (dev->port->cad != pd1) {
-               printk(KERN_WARNING "%s: death while preempting %s\n",
-                      dev->port->name, dev->name);
-               if (dev->port->cad)
-                       return -EAGAIN;
+       /* Can't fail from now on, so mark ourselves as no longer waiting.  */
+       if (dev->waiting & 1) {
+               dev->waiting = 0;
+
+               /* Take ourselves out of the wait list again.  */
+               spin_lock_irqsave (&port->lock, flags);
+               if (dev->waitprev)
+                       dev->waitprev->waitnext = dev->waitnext;
+               else
+                       port->waithead = dev->waitnext;
+               if (dev->waitnext)
+                       dev->waitnext->waitprev = dev->waitprev;
+               else
+                       port->waittail = dev->waitprev;
+               spin_unlock_irqrestore (&port->lock, flags);
+               dev->waitprev = dev->waitnext = NULL;
        }
 
        /* Now we do the change of devices */
-       dev->port->cad = dev;
+       port->cad = dev;
 
        /* Swap the IRQ handlers. */
-       if (dev->port->irq != PARPORT_IRQ_NONE) {
-               free_irq(dev->port->irq, pd1?pd1->private:NULL);
-               request_irq(dev->port->irq, dev->irq_func ? dev->irq_func :
-                           parport_null_intr_func, SA_INTERRUPT, dev->name,
-                           dev->private);
+       if (port->irq != PARPORT_IRQ_NONE) {
+               if (oldcad && oldcad->irq_func) {
+                       free_irq(port->irq, oldcad->private);
+                       request_irq(port->irq, parport_null_intr_func,
+                                   SA_INTERRUPT, port->name, NULL);
+               }
+               if (dev->irq_func) {
+                       free_irq(port->irq, NULL);
+                       request_irq(port->irq, dev->irq_func,
+                                   SA_INTERRUPT, dev->name, dev->private);
+               }
        }
 
        /* Restore control registers */
-       dev->port->ops->restore_state(dev->port, dev->state);
-
+       port->ops->restore_state(port, dev->state);
+       dev->time = jiffies;
        return 0;
+
+blocked:
+       /* If this is the first time we tried to claim the port, register an
+          interest.  This is only allowed for devices sleeping in
+          parport_claim_or_block(), or those with a wakeup function.  */
+       if (dev->waiting & 2 || dev->wakeup) {
+               spin_lock_irqsave (&port->lock, flags);
+               if (port->cad == NULL) {
+                       /* The port got released in the meantime. */
+                       spin_unlock_irqrestore (&port->lock, flags);
+                       goto try_again;
+               }
+               if (test_and_set_bit(0, &dev->waiting) == 0) {
+                       /* First add ourselves to the end of the wait list. */
+                       dev->waitnext = NULL;
+                       dev->waitprev = port->waittail;
+                       if (port->waittail)
+                               port->waittail->waitnext = dev;
+                       else {
+                               port->waithead = dev->port->waittail = dev;
+                       }
+               }
+               spin_unlock_irqrestore (&port->lock, flags);
+       }
+       return -EAGAIN;
+}
+
+int parport_claim_or_block(struct pardevice *dev)
+{
+       int r;
+
+       /* Signal to parport_claim() that we can wait even without a
+          wakeup function.  */
+       dev->waiting = 2;
+
+       /* Try to claim the port.  If this fails, we need to sleep.  */
+       r = parport_claim(dev);
+       if (r == -EAGAIN) {
+               unsigned long flags;
+#ifdef PARPORT_DEBUG_SHARING
+               printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name);
+#endif
+               save_flags (flags);
+               cli();
+               /* If dev->waiting is clear now, an interrupt
+                  gave us the port and we would deadlock if we slept.  */
+               if (dev->waiting) {
+                       sleep_on(&dev->wait_q);
+                       r = 1;
+               } else {
+                       r = 0;
+#ifdef PARPORT_DEBUG_SHARING
+                       printk(KERN_DEBUG "%s: didn't sleep in parport_claim_or_block()\n",
+                              dev->name);
+#endif
+               }
+               restore_flags(flags);
+#ifdef PARPORT_DEBUG_SHARING
+               if (dev->port->cad != dev)
+                       printk(KERN_DEBUG "%s: exiting parport_claim_or_block but %s owns port!\n", dev->name, dev->port->cad?dev->port->cad->name:"nobody");
+#endif
+       }
+       dev->waiting = 0;
+       return r;
 }
 
 void parport_release(struct pardevice *dev)
 {
-       struct pardevice *pd1;
+       struct parport *port = dev->port;
+       struct pardevice *pd;
 
        /* Make sure that dev is the current device */
-       if (dev->port->cad != dev) {
-               printk(KERN_WARNING "%s: %s tried to release parport when not owner\n", dev->port->name, dev->name);
+       if (port->cad != dev) {
+               printk(KERN_WARNING "%s: %s tried to release parport "
+                      "when not owner\n", port->name, dev->name);
                return;
        }
-       dev->port->cad = NULL;
+       port->cad = NULL;
 
        /* Save control registers */
-       dev->port->ops->save_state(dev->port, dev->state);
+       port->ops->save_state(port, dev->state);
 
        /* Point IRQs somewhere harmless. */
-       if (dev->port->irq != PARPORT_IRQ_NONE) {
-               free_irq(dev->port->irq, dev->private);
-               request_irq(dev->port->irq, parport_null_intr_func,
-                           SA_INTERRUPT, dev->port->name, NULL);
+       if (port->irq != PARPORT_IRQ_NONE && dev->irq_func) {
+               free_irq(port->irq, dev->private);
+               request_irq(port->irq, parport_null_intr_func,
+                           SA_INTERRUPT, port->name, NULL);
        }
 
-       /* Walk the list, offering a wakeup callback to everybody other
-        * than the lurker and the device that called us.
-        */
-       for (pd1 = dev->next; pd1; pd1 = pd1->next) {
-               if (!(pd1->flags & PARPORT_DEV_LURK)) {
-                       if (pd1->wakeup) {
-                               pd1->wakeup(pd1->private);
-                               if (dev->port->cad)
-                                       return;
-                       }
-               }
-       }
-
-       for (pd1 = dev->port->devices; pd1 && pd1 != dev; pd1 = pd1->next) {
-               if (!(pd1->flags & PARPORT_DEV_LURK)) {
-                       if (pd1->wakeup) {
-                               pd1->wakeup(pd1->private);
-                               if (dev->port->cad)
-                                       return;
-                       }
+       /* If anybody is waiting, find out who's been there longest and
+          then wake them up. (Note: no locking required) */
+       for (pd = port->waithead; pd; pd = pd->waitnext) {
+               if (pd->waiting & 2) {
+                       parport_claim(pd);
+                       if (waitqueue_active(&pd->wait_q))
+                               wake_up(&pd->wait_q);
+                       return;
+               } else if (pd->wakeup) {
+                       pd->wakeup(pd->private);
+                       if (dev->port->cad)
+                               return;
+               } else {
+                       printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
                }
        }
 
-       /* Now give the lurker a chance.
-        * There must be a wakeup callback because we checked for it
-        * at registration.
-        */
-       if (dev->port->lurker && (dev->port->lurker != dev)) {
-               dev->port->lurker->wakeup(dev->port->lurker->private);
+       /* Nobody was waiting, so walk the list to see if anyone is
+          interested in being woken up.  */
+       for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) {
+               if (pd->wakeup && pd != dev)
+                       pd->wakeup(pd->private);
        }
 }
index d21df7bbb435f49a953287b13b218962bc2897bd..227a06976f67d0d987dc693a10d67013133fb645 100644 (file)
                           Fix bug in pci_probe() for 64 bit systems reported
                           by <belliott@accessone.com>.
       0.533   9-Jan-98    Fix more 64 bit bugs reported by <jal@cs.brown.edu>.
+      0.534  24-Jan-98    Fix last (?) endian bug from 
+                           <Geert.Uytterhoeven@cs.kuleuven.ac.be>
 
     =========================================================================
 */
 
-static const char *version = "de4x5.c:V0.533 1998/1/9 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.534 1998/1/24 davies@maniac.ultranet.com\n";
 
 #include <linux/module.h>
 
@@ -2079,7 +2081,7 @@ eisa_probe(struct device *dev, u_long ioaddr))
 __initfunc(static void
 pci_probe(struct device *dev, u_long ioaddr))
 {
-    u_char pb, pbus, dev_num, dnum, dev_fn, timer;
+    u_char pb, pbus, dev_num, dnum, dev_fn, timer, tirq;
     u_short dev_id, vendor, index, status;
     u_int tmp, irq = 0, device, class = DE4X5_CLASS_CODE;
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
@@ -2151,8 +2153,8 @@ pci_probe(struct device *dev, u_long ioaddr))
 
            /* Fetch the IRQ to be used */
 #ifndef __sparc_v9__
-           pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, 
-                                                                (char *)&irq);
+           pcibios_read_config_byte(pb, PCI_DEVICE, PCI_INTERRUPT_LINE, &tirq);
+           irq = tirq;
 #else
            irq = pdev->irq;
 #endif
@@ -2176,7 +2178,7 @@ pci_probe(struct device *dev, u_long ioaddr))
            }
            if (!(status & PCI_COMMAND_MASTER)) continue;
 
-           /* Check the latency timer for values > 0x60 */
+           /* Check the latency timer for values >= 0x60 */
            pcibios_read_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, &timer);
            if (timer < 0x60) {
                pcibios_write_config_byte(pb, PCI_DEVICE, PCI_LATENCY_TIMER, 0x60);
index 4e29cb6abc21262e3880ae764f0d34787df04058..7c8c3b20fe7fdf77c8244d76c308477ed40896a8 100644 (file)
@@ -1358,6 +1358,8 @@ dgrs_found_device(
 /*
  *     Scan for all boards
  */
+static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
+
 __initfunc(static int
 dgrs_scan(struct device *dev))
 {
@@ -1463,8 +1465,6 @@ dgrs_scan(struct device *dev))
         */
        if (EISA_bus)
        {
-               static int      is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
-
                for (io = 0x1000; io < 0x9000; io += 0x1000)
                {
                        if (inb(io+ES4H_MANUFmsb) != 0x10
index d1dce6687792cb1bb81042896e4f38256dde2f7f..4750c18ee91e76d786c5198edb9c63bea6d11d0e 100644 (file)
@@ -200,7 +200,9 @@ static void gentbl_fsk9600(FILE *f)
                                        ? "\n\t" : "");
                }
        }
+#ifdef VERBOSE
        fprintf(stderr, "fsk9600: txfilt4: min = %f; max = %f\n", min, max);
+#endif
        fprintf(f, "\n};\n\n");
        min = max = 0;
        memset(c, 0, sizeof(c));
@@ -233,7 +235,9 @@ static void gentbl_fsk9600(FILE *f)
                                        ? "\n\t" : "");
                }
        }
+#ifdef VERBOSE
        fprintf(stderr, "fsk9600: txfilt5: min = %f; max = %f\n", min, max);
+#endif
        fprintf(f, "\n};\n\n");
 }
        
@@ -466,7 +470,9 @@ static void gentbl_hapn4800(FILE *f)
                                        ? "\n\t" : "");
                }
        }
+#ifdef VERBOSE
        fprintf(stderr, "hapn4800: txfilt8: min = %f; max = %f\n", min, max);
+#endif
        fprintf(f, "\n};\n\n");
        min = max = 0;
        memset(c, 0, sizeof(c));
@@ -493,7 +499,9 @@ static void gentbl_hapn4800(FILE *f)
                                        ? "\n\t" : "");
                }
        }
+#ifdef VERBOSE
        fprintf(stderr, "hapn4800: txfilt10: min = %f; max = %f\n", min, max);
+#endif
        fprintf(f, "\n};\n\n");
        /*
         * secondly generate tables for the PM transmitter modulator
@@ -524,7 +532,9 @@ static void gentbl_hapn4800(FILE *f)
                                        ? "\n\t" : "");
                }
        }
+#ifdef VERBOSE
        fprintf(stderr, "hapn4800: txfiltpm8: min = %f; max = %f\n", min, max);
+#endif
        fprintf(f, "\n};\n\n");
        min = max = 0;
        memset(c, 0, sizeof(c));
@@ -552,7 +562,9 @@ static void gentbl_hapn4800(FILE *f)
                                        ? "\n\t" : "");
                }
        }
+#ifdef VERBOSE
        fprintf(stderr, "hapn4800: txfiltpm10: min = %f; max = %f\n", min, max);
+#endif
        fprintf(f, "\n};\n\n");
        
 }
index efbfc54e4ec780ff3a8baaeda1fa15cfd3c72e01..203e3fbf7a03243b2c7f64e2e2d30b73874a3cd9 100644 (file)
@@ -72,14 +72,14 @@ static unsigned int netcard_portlist[] __initdata =
 
 #ifdef CONFIG_PCI
 /* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */
-static struct { unsigned short vendor, dev_id;}
+static struct { unsigned short vendor, dev_id; char *name; }
 pci_clone_list[] __initdata = {
-       {PCI_VENDOR_ID_REALTEK,         PCI_DEVICE_ID_REALTEK_8029},
-       {PCI_VENDOR_ID_WINBOND2,        PCI_DEVICE_ID_WINBOND2_89C940},
-       {PCI_VENDOR_ID_COMPEX,          PCI_DEVICE_ID_COMPEX_RL2000},
-       {PCI_VENDOR_ID_KTI,             PCI_DEVICE_ID_KTI_ET32P2},
-       {PCI_VENDOR_ID_NETVIN,          PCI_DEVICE_ID_NETVIN_NV5000SC},
-       {PCI_VENDOR_ID_VIA,             PCI_DEVICE_ID_VIA_82C926},
+       {PCI_VENDOR_ID_REALTEK,         PCI_DEVICE_ID_REALTEK_8029,             "Realtek 8029" },
+       {PCI_VENDOR_ID_WINBOND2,        PCI_DEVICE_ID_WINBOND2_89C940,          "Winbond 89C940" },
+       {PCI_VENDOR_ID_COMPEX,          PCI_DEVICE_ID_COMPEX_RL2000,            "Compex ReadyLink 2000" },
+       {PCI_VENDOR_ID_KTI,             PCI_DEVICE_ID_KTI_ET32P2,               "KTI ET32P2" },
+       {PCI_VENDOR_ID_NETVIN,          PCI_DEVICE_ID_NETVIN_NV5000SC,          "NetVin NV5000" },
+       {PCI_VENDOR_ID_VIA,             PCI_DEVICE_ID_VIA_82C926,               "VIA 82C926 Amazon" },
        {0,}
 };
 #endif
@@ -228,9 +228,8 @@ __initfunc(static int ne_probe_pci(struct device *dev))
                        break;  /* Beauty -- got a valid card. */
                }
                if (pci_irq_line == 0) continue;        /* Try next PCI ID */
-               printk("ne.c: PCI BIOS reports %s %s at i/o %#x, irq %d.\n",
-                               pci_strvendor(pci_clone_list[i].vendor),
-                               pci_strdev(pci_clone_list[i].vendor, pci_clone_list[i].dev_id),
+               printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
+                               pci_clone_list[i].name,
                                pci_ioaddr, pci_irq_line);
                if (ne_probe1(dev, pci_ioaddr) != 0) {  /* Shouldn't happen. */
                        printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr);
index 1ebb58aea9396db1ff7454ffbc1a4bcf29ec2507..1fef280d25c4c44af027f3aff7d5f579496fcca4 100644 (file)
@@ -7,7 +7,7 @@
  *  Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
  *  ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
  *
- *  ==FILEVERSION 971205==
+ *  ==FILEVERSION 980123==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the number above to the
@@ -568,9 +568,7 @@ ppp_changedmtu (struct ppp *ppp, int new_mtu, int new_mru)
  */
        if (new_wbuf == NULL || new_tbuf == NULL ||
            new_rbuf == NULL || new_cbuf == NULL) {
-               if (ppp->flags & SC_DEBUG)
-                       printk (KERN_ERR
-                               "ppp: failed to allocate new buffers\n");
+               printk (KERN_ERR "ppp: failed to allocate new buffers\n");
 
                ppp_free_buf (new_wbuf);
                ppp_free_buf (new_tbuf);
@@ -770,8 +768,7 @@ ppp_tty_open (struct tty_struct *tty)
  * There should not be an existing table for this slot.
  */
        if (ppp) {
-               if (ppp->flags & SC_DEBUG)
-                       printk (KERN_ERR
+               printk (KERN_ERR
                        "ppp_tty_open: gack! tty already associated to %s!\n",
                        ppp->magic == PPP_MAGIC ? ppp2dev(ppp)->name
                                                : "unknown");
@@ -793,8 +790,7 @@ ppp_tty_open (struct tty_struct *tty)
        } else {
                ppp = ppp_alloc();
                if (ppp == NULL) {
-                       if (ppp->flags & SC_DEBUG)
-                               printk (KERN_ERR "ppp_alloc failed\n");
+                       printk (KERN_ERR "ppp_alloc failed\n");
                        return -ENFILE;
                }
 /*
@@ -808,9 +804,8 @@ ppp_tty_open (struct tty_struct *tty)
  */
                ppp->slcomp = slhc_init (16, 16);
                if (ppp->slcomp == NULL) {
-                       if (ppp->flags & SC_DEBUG)
-                               printk (KERN_ERR "ppp_tty_open: "
-                                       "no space for compression buffers!\n");
+                       printk (KERN_ERR "ppp_tty_open: "
+                               "no space for compression buffers!\n");
                        ppp_release (ppp);
                        return -ENOMEM;
                }
@@ -826,9 +821,8 @@ ppp_tty_open (struct tty_struct *tty)
  */
                ppp->ubuf = ppp_alloc_buf (RBUFSIZE, BUFFER_TYPE_TTY_RD);
                if (ppp->ubuf == NULL) {
-                       if (ppp->flags & SC_DEBUG)
-                               printk (KERN_ERR "ppp_tty_open: "
-                                       "no space for user receive buffer\n");
+                       printk (KERN_ERR "ppp_tty_open: "
+                               "no space for user receive buffer\n");
                        ppp_release (ppp);
                        return -ENOMEM;
                }
@@ -1300,9 +1294,7 @@ ppp_doframe (struct ppp *ppp)
  */
                        new_data = kmalloc (ppp->mru + PPP_HDRLEN, GFP_ATOMIC);
                        if (new_data == NULL) {
-                               if (ppp->flags & SC_DEBUG)
-                                       printk (KERN_ERR
-                                               "ppp_doframe: no memory\n");
+                               printk (KERN_ERR "ppp_doframe: no memory\n");
                                new_count = DECOMP_ERROR;
                        } else {
                                new_count = (*ppp->sc_rcomp->decompress)
@@ -1321,8 +1313,7 @@ ppp_doframe (struct ppp *ppp)
 
                        case DECOMP_FATALERROR:
                                ppp->flags |= SC_DC_FERROR;
-                               if (ppp->flags & SC_DEBUG)
-                                       printk(KERN_ERR "ppp: fatal decomp error\n");
+                               printk(KERN_ERR "ppp: fatal decomp error\n");
                                break;
                        }
 /*
@@ -2069,15 +2060,16 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data,
        struct ppp *ppp = tty2ppp (tty);
        __u8 *new_data;
        int error;
+       struct wait_queue wait = {current, NULL};
 
 /*
  * Verify the pointers.
  */
+       error = -EIO;
        if (!ppp)
-               return -EIO;
-
+               goto out;
        if (ppp->magic != PPP_MAGIC)
-               return -EIO;
+               goto out;
 
        CHECK_PPP (-ENXIO);
 /*
@@ -2096,43 +2088,48 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data,
  */
        new_data = kmalloc (count, GFP_KERNEL);
        if (new_data == NULL) {
-               if (ppp->flags & SC_DEBUG)
-                       printk (KERN_ERR
-                               "ppp_tty_write: no memory\n");
+               printk (KERN_ERR "ppp_tty_write: no memory\n");
                return 0;
        }
 /*
  * Retrieve the user's buffer
  */
-       error = copy_from_user(new_data, data, count);
-       if (error) {
-               kfree (new_data);
-               return error;
-       }
+       error = -EFAULT;
+       if (copy_from_user(new_data, data, count))
+               goto out_free;
 /*
- * lock this PPP unit so we will be the only writer;
- * sleep if necessary
+ * Lock this PPP unit so we will be the only writer,
+ * sleeping if necessary.
+ *
+ * Note that we add our task to the wait queue before
+ * attempting to lock, as the lock flag may be cleared
+ * from an interrupt.
  */
-       while (lock_buffer (ppp->tbuf) != 0) {
+       add_wait_queue(&ppp->write_wait, &wait);
+       while (1) {
+               error = 0;
                current->timeout = 0;
-#if 0
-               if (ppp->flags & SC_DEBUG)
-                       printk (KERN_DEBUG "ppp_tty_write: sleeping\n");
-#endif
-               interruptible_sleep_on (&ppp->write_wait);
+               current->state = TASK_INTERRUPTIBLE;
+               if (lock_buffer(ppp->tbuf) == 0)
+                       break;
+               schedule();
 
+               error = -EINVAL;
                ppp = tty2ppp (tty);
-               if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse
-                   || tty != ppp->tty) {
-                       kfree (new_data);
-                       return 0;
-               }
-
-               if (signal_pending(current)) {
-                       kfree (new_data);
-                       return -EINTR;
+               if (!ppp || ppp->magic != PPP_MAGIC || 
+                   !ppp->inuse || tty != ppp->tty) {
+                       printk("ppp_tty_write: %p invalid after wait!\n", ppp);
+                       break;
                }
+               error = -EINTR;
+               if (signal_pending(current))
+                       break;
        }
+       current->state = TASK_RUNNING;
+       remove_wait_queue(&ppp->write_wait, &wait);
+       if (error)
+               goto out_free;
+
 /*
  * Change the LQR frame
  */
@@ -2152,9 +2149,12 @@ ppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data,
        } else {
                ppp_dev_xmit_frame (ppp, ppp->tbuf, new_data, count);
        }
+       error = count;
 
+out_free:
        kfree (new_data);
-       return count;
+out:
+       return error;
 }
 
 /*
@@ -2165,31 +2165,30 @@ static int
 ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp)
 {
        struct compressor *cp;
-       struct ppp_option_data data;
-       int error;
-       int nb;
+       int error, nb;
+       unsigned long flags;
        __u8 *ptr;
        __u8 ccp_option[CCP_MAX_OPTION_LENGTH];
-       unsigned long flags;
+       struct ppp_option_data data;
 
 /*
  * Fetch the compression parameters
  */
-       error = copy_from_user(&data, odp, sizeof (data));
-       if (error != 0)
-               return error;
+       error = -EFAULT;
+       if (copy_from_user(&data, odp, sizeof (data)))
+               goto out;
 
        nb  = data.length;
        ptr = data.ptr;
        if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH)
                nb = CCP_MAX_OPTION_LENGTH;
 
-       error = copy_from_user(ccp_option, ptr, nb);
-       if (error != 0)
-               return error;
+       if (copy_from_user(ccp_option, ptr, nb))
+               goto out;
 
+       error = -EINVAL;
        if (ccp_option[1] < 2)  /* preliminary check on the length byte */
-               return (-EINVAL);
+               goto out;
 
        save_flags(flags);
        cli();
@@ -2206,53 +2205,52 @@ ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp)
        }
 #endif /* CONFIG_KERNELD */
 
-       if (cp != (struct compressor *) 0) {
-               /*
-                * Found a handler for the protocol - try to allocate
-                * a compressor or decompressor.
-                */
-               error = 0;
-               if (data.transmit) {
-                       if (ppp->sc_xc_state != NULL)
-                               (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);
+       if (cp == NULL)
+               goto out_no_comp;
+       /*
+        * Found a handler for the protocol - try to allocate
+        * a compressor or decompressor.
+        */
+       error = 0;
+       if (data.transmit) {
+               if (ppp->sc_xc_state != NULL)
+                       (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);
+               ppp->sc_xc_state = NULL;
 
-                       ppp->sc_xcomp    = cp;
-                       ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb);
+               ppp->sc_xcomp    = cp;
+               ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb);
+               if (ppp->sc_xc_state == NULL) {
+                       printk(KERN_WARNING "%s: comp_alloc failed\n",
+                               ppp->name);
+                       error = -ENOBUFS;
+               } else if (ppp->flags & SC_DEBUG)
+                       printk(KERN_DEBUG "%s: comp_alloc -> %p\n",
+                              ppp->name, ppp->sc_xc_state);
+       } else {
+               if (ppp->sc_rc_state != NULL)
+                       (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);
+               ppp->sc_rc_state = NULL;
 
-                       if (ppp->sc_xc_state == NULL) {
-                               if (ppp->flags & SC_DEBUG)
-                                       printk(KERN_DEBUG "%s: comp_alloc failed\n",
-                                              ppp->name);
-                               error = -ENOBUFS;
-                       } else {
-                               if (ppp->flags & SC_DEBUG)
-                                       printk(KERN_DEBUG "%s: comp_alloc -> %p\n",
-                                              ppp->name, ppp->sc_xc_state);
-                       }
-               } else {
-                       if (ppp->sc_rc_state != NULL)
-                               (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);
-                       ppp->sc_rcomp    = cp;
-                       ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
-                       if (ppp->sc_rc_state == NULL) {
-                               if (ppp->flags & SC_DEBUG)
-                                       printk(KERN_DEBUG "%s: decomp_alloc failed\n",
-                                              ppp->name);
-                               error = -ENOBUFS;
-                       } else {
-                               if (ppp->flags & SC_DEBUG)
-                                       printk(KERN_DEBUG "%s: decomp_alloc -> %p\n",
-                                              ppp->name, ppp->sc_rc_state);
-                       }
-               }
-               return (error);
+               ppp->sc_rcomp    = cp;
+               ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
+               if (ppp->sc_rc_state == NULL) {
+                       printk(KERN_WARNING "%s: decomp_alloc failed\n",
+                               ppp->name);
+                       error = -ENOBUFS;
+               } else if (ppp->flags & SC_DEBUG)
+                       printk(KERN_DEBUG "%s: decomp_alloc -> %p\n",
+                              ppp->name, ppp->sc_rc_state);
        }
+out:
+       return error;
 
+out_no_comp:
+       error = -EINVAL;        /* no handler found */
        if (ppp->flags & SC_DEBUG)
                printk(KERN_DEBUG "%s: no compressor for [%x %x %x], %x\n",
-                      ppp->name, ccp_option[0], ccp_option[1],
-                      ccp_option[2], nb);
-       return (-EINVAL);       /* no handler found */
+                       ppp->name, ccp_option[0], ccp_option[1],
+                       ccp_option[2], nb);
+       goto out;
 }
 
 /*
@@ -2409,16 +2407,20 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
                        /* change absolute times to relative times. */
                        cur_ddinfo.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
                        cur_ddinfo.recv_idle = (jiffies - ppp->last_recv) / HZ;
-                       error = copy_to_user((void *) param3, &cur_ddinfo,
-                                            sizeof (cur_ddinfo));
+                       error = -EFAULT;
+                       if (!copy_to_user((void *) param3, &cur_ddinfo,
+                                            sizeof (cur_ddinfo)))
+                               error = 0;
                }
                break;
 /*
  * Retrieve the extended async map
  */
        case PPPIOCGXASYNCMAP:
-               error = copy_to_user((void *) param3, ppp->xmit_async_map,
-                                    sizeof (ppp->xmit_async_map));
+               error = -EFAULT;
+               if (!copy_to_user((void *) param3, ppp->xmit_async_map,
+                                    sizeof (ppp->xmit_async_map)))
+                       error = 0;
                break;
 /*
  * Set the async extended map
@@ -2427,15 +2429,16 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
                {
                        __u32 temp_tbl[8];
 
-                       error = copy_from_user(temp_tbl, (void *) param3,
-                                              sizeof (temp_tbl));
-                       if (error != 0)
+                       error = -EFAULT;
+                       if (copy_from_user(temp_tbl, (void *) param3,
+                                              sizeof (temp_tbl)))
                                break;
 
                        temp_tbl[1]  =  0x00000000;
                        temp_tbl[2] &= ~0x40000000;
                        temp_tbl[3] |=  0x60000000;
 
+                       error = 0;
                        if ((temp_tbl[2] & temp_tbl[3]) != 0 ||
                            (temp_tbl[4] & temp_tbl[5]) != 0 ||
                            (temp_tbl[6] & temp_tbl[7]) != 0)
@@ -2461,16 +2464,15 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
                temp_i = (temp_i & 255) + 1;
                if (ppp->flags & SC_DEBUG)
                        printk (KERN_INFO
-                               "ppp_tty_ioctl: set maxcid to %d\n",
-                               temp_i);
+                               "ppp_tty_ioctl: set maxcid to %d\n", temp_i);
                if (ppp->slcomp != NULL)
                        slhc_free (ppp->slcomp);
-               ppp->slcomp = slhc_init (16, temp_i);
+               ppp->slcomp = NULL;
 
+               ppp->slcomp = slhc_init (16, temp_i);
                if (ppp->slcomp == NULL) {
-                       if (ppp->flags & SC_DEBUG)
-                               printk (KERN_ERR
-                                       "ppp: no space for compression buffers!\n");
+                       printk (KERN_ERR "ppp_tty_ioctl: "
+                               "no space for compression buffers!\n");
                        ppp_release (ppp);
                        error = -ENOMEM;
                }
@@ -2486,39 +2488,35 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
                {
                        struct npioctl npi;
 
-                       error = copy_from_user(&npi, (void *) param3,
-                                       sizeof (npi));
-                       if (error != 0)
+                       error = -EFAULT;
+                       if (copy_from_user(&npi, (void *) param3, sizeof(npi)))
                                break;
 
-                       switch (npi.protocol) {
-                       case PPP_IP:
-                               npi.protocol = NP_IP;
-                               break;
-                       default:
+                       if (npi.protocol != PPP_IP) {
                                if (ppp->flags & SC_DEBUG)
                                        printk(KERN_DEBUG "pppioc[gs]npmode: "
-                                              "invalid proto %d\n", npi.protocol);
+                                              "invalid protocol %d\n",
+                                               npi.protocol);
                                error = -EINVAL;
-                       }
-
-                       if (error != 0)
                                break;
+                       }
+                       npi.protocol = NP_IP;
 
                        if (param2 == PPPIOCGNPMODE) {
                                npi.mode = ppp->sc_npmode[npi.protocol];
-
-                               error = copy_to_user((void *) param3, &npi,
-                                                    sizeof (npi));
-                               break;
+                               if (copy_to_user((void *) param3, &npi,
+                                               sizeof (npi)))
+                                       break;
                        }
 
                        ppp->sc_npmode[npi.protocol] = npi.mode;
                        if (ppp->flags & SC_DEBUG)
                                printk(KERN_DEBUG "ppp: set np %d to %d\n",
                                       npi.protocol, npi.mode);
+                       /* N.B. Why is the busy flag cleared here? */
                        ppp2dev(ppp)->tbusy = 0;
                        mark_bh(NET_BH);
+                       error = 0;
                }
                break;
 /*
@@ -2542,11 +2540,8 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
  */
        default:
                if (ppp->flags & SC_DEBUG)
-                       printk (KERN_ERR
-                               "ppp_tty_ioctl: invalid ioctl: %x, addr %lx\n",
-                               param2,
-                               param3);
-
+                       printk (KERN_WARNING "ppp_tty_ioctl: "
+                               "invalid ioctl=%x, addr=%lx\n", param2, param3);
                error = -ENOIOCTLCMD;
                break;
        }
@@ -2606,8 +2601,7 @@ ppp_dev_open (struct device *dev)
        struct ppp *ppp = dev2ppp (dev);
 
        if (ppp2tty (ppp) == NULL) {
-               if (ppp->flags & SC_DEBUG)
-                       printk (KERN_ERR
+               printk (KERN_ERR
                        "ppp: %s not connected to a TTY! can't go open!\n",
                        dev->name);
                return -ENXIO;
@@ -2659,8 +2653,9 @@ ppp_dev_ioctl_version (struct ppp *ppp, struct ifreq *ifr)
 /*
  * Move the version data
  */
-       error = copy_to_user(result, szVersion, len);
-
+       error = -EFAULT;
+       if (!copy_to_user(result, szVersion, len))
+               error = 0;
        return error;
 }
 
@@ -2695,8 +2690,9 @@ ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev)
 
        result = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
 
-       error = copy_to_user(result, &temp, sizeof (temp));
-
+       error = -EFAULT;
+       if (!copy_to_user(result, &temp, sizeof (temp)))
+               error = 0;
        return error;
 }
 
@@ -2727,8 +2723,9 @@ ppp_dev_ioctl_comp_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev
  */
        result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data;
 
-       error = copy_to_user(result, &temp, sizeof (temp));
-
+       error = -EFAULT;
+       if (!copy_to_user(result, &temp, sizeof (temp)))
+               error = 0;
        return error;
 }
 
index 3ec6dd4ba056457f5447948f8cabfc038c668f77..edb3d10f76906db950c239c24537824ebc431b31 100644 (file)
@@ -188,20 +188,20 @@ z_comp_alloc(options, opt_len)
        struct ppp_deflate_state *state;
        int w_size;
 
+       MOD_INC_USE_COUNT;
        if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
            || options[1] != CILEN_DEFLATE
            || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
            || options[3] != DEFLATE_CHK_SEQUENCE)
-               return NULL;
+               goto out_fail;
        w_size = DEFLATE_SIZE(options[2]);
        if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
-               return NULL;
+               goto out_fail;
 
        state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
        if (state == NULL)
-               return NULL;
+               goto out_fail;
 
-       MOD_INC_USE_COUNT;
        memset (state, 0, sizeof (struct ppp_deflate_state));
        state->strm.next_in = NULL;
        state->strm.zalloc  = zalloc_init;
@@ -210,13 +210,16 @@ z_comp_alloc(options, opt_len)
 
        if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
                         DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
-           != Z_OK) {
-               z_comp_free(state);
-               return NULL;
-       }
-
+           != Z_OK)
+               goto out_free;
        state->strm.zalloc = zalloc;
        return (void *) state;
+
+out_free:
+       z_comp_free(state);
+out_fail:
+       MOD_DEC_USE_COUNT;
+       return NULL;
 }
 
 static int
@@ -369,33 +372,35 @@ z_decomp_alloc(options, opt_len)
        struct ppp_deflate_state *state;
        int w_size;
 
+       MOD_INC_USE_COUNT;
        if (opt_len != CILEN_DEFLATE || options[0] != CI_DEFLATE
            || options[1] != CILEN_DEFLATE
            || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
            || options[3] != DEFLATE_CHK_SEQUENCE)
-               return NULL;
+               goto out_fail;
        w_size = DEFLATE_SIZE(options[2]);
        if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
-               return NULL;
+               goto out_fail;
 
        state = (struct ppp_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
        if (state == NULL)
-               return NULL;
-
-       MOD_INC_USE_COUNT;
+               goto out_fail;
        memset (state, 0, sizeof (struct ppp_deflate_state));
        state->w_size        = w_size;
        state->strm.next_out = NULL;
        state->strm.zalloc   = zalloc_init;
        state->strm.zfree    = zfree;
 
-       if (inflateInit2(&state->strm, -w_size) != Z_OK) {
-               z_decomp_free(state);
-               return NULL;
-       }
-
+       if (inflateInit2(&state->strm, -w_size) != Z_OK)
+               goto out_free;
        state->strm.zalloc = zalloc;
        return (void *) state;
+
+out_free:
+       z_decomp_free(state);
+out_fail:
+       MOD_DEC_USE_COUNT;
+       return NULL;
 }
 
 static int
index 187e51616bf3311e531d691490be56868cffbdf5..13a020869b0e1b4f7493a98b189d49dd6bf11269 100644 (file)
@@ -99,21 +99,18 @@ slhc_init(int rslots, int tslots)
        register struct cstate *ts;
        struct slcompress *comp;
 
+       MOD_INC_USE_COUNT;
        comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
                                            GFP_KERNEL);
        if (! comp)
-               return NULL;
-
+               goto out_fail;
        memset(comp, 0, sizeof(struct slcompress));
 
        if ( rslots > 0  &&  rslots < 256 ) {
                size_t rsize = rslots * sizeof(struct cstate);
                comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
                if (! comp->rstate)
-               {
-                       kfree((unsigned char *)comp);
-                       return NULL;
-               }
+                       goto out_free;
                memset(comp->rstate, 0, rsize);
                comp->rslot_limit = rslots - 1;
        }
@@ -122,11 +119,7 @@ slhc_init(int rslots, int tslots)
                size_t tsize = tslots * sizeof(struct cstate);
                comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
                if (! comp->tstate)
-               {
-                       kfree((unsigned char *)comp->rstate);
-                       kfree((unsigned char *)comp);
-                       return NULL;
-               }
+                       goto out_free2;
                memset(comp->tstate, 0, tsize);
                comp->tslot_limit = tslots - 1;
        }
@@ -151,8 +144,15 @@ slhc_init(int rslots, int tslots)
                ts[0].next = &(ts[comp->tslot_limit]);
                ts[0].cs_this = 0;
        }
-       MOD_INC_USE_COUNT;
        return comp;
+
+out_free2:
+       kfree((unsigned char *)comp->rstate);
+out_free:
+       kfree((unsigned char *)comp);
+out_fail:
+       MOD_DEC_USE_COUNT;
+       return NULL;
 }
 
 
@@ -163,14 +163,14 @@ slhc_free(struct slcompress *comp)
        if ( comp == NULLSLCOMPR )
                return;
 
-       if ( comp->rstate != NULLSLSTATE )
-               kfree( comp->rstate );
-
        if ( comp->tstate != NULLSLSTATE )
                kfree( comp->tstate );
 
-       MOD_DEC_USE_COUNT;
+       if ( comp->rstate != NULLSLSTATE )
+               kfree( comp->rstate );
+
        kfree( comp );
+       MOD_DEC_USE_COUNT;
 }
 
 
index 5c1d0f3524aff4be0beb9cc9bfc88fe28f2eb5ca..f7f6151cba35c803ea47ff800f6304239902fcdf 100644 (file)
@@ -1799,8 +1799,8 @@ tulip_start_xmit(struct sk_buff *skb, struct device *dev)
        if (entry == TX_RING_SIZE-1)
                flag |= 0xe2000000;
 
-       tp->tx_ring[entry].length = skb->len | flag;
        tp->stats.tx_bytes += skb->len;
+       tp->tx_ring[entry].length = skb->len | flag;
        tp->tx_ring[entry].status = 0x80000000; /* Pass ownership to the chip. */
        tp->cur_tx++;
        /* Trigger an immediate transmit demand. */
index 2ab6b19ac98ca505ecbfa3cd4ef473b99913d748..9c4b53d13a4a7d86b49118c9126e98bf06700bf6 100644 (file)
 L_OBJS   := pci.o
 L_TARGET := pci.a
 
-ifeq ($(CONFIG_PCI_OPTIMIZE),y)
+ifdef CONFIG_PROC_FS
+L_OBJS   += proc.o
+ifdef CONFIG_PCI_OLD_PROC
+L_OBJS   += oldproc.o
+endif
+endif
+
+ifdef CONFIG_PCI_OPTIMIZE
 L_OBJS   += quirks.o
 endif
 
diff --git a/drivers/pci/oldproc.c b/drivers/pci/oldproc.c
new file mode 100644 (file)
index 0000000..551d2b6
--- /dev/null
@@ -0,0 +1,871 @@
+/*
+ *     $Id: oldproc.c,v 1.4 1998/01/05 14:16:18 mj Exp $
+ *
+ *     Backward-compatible procfs interface for PCI.
+ *
+ *     Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
+ *     David Mosberger-Tang, Martin Mares
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <asm/page.h>
+
+#ifdef CONFIG_PROC_FS
+
+struct pci_dev_info {
+       unsigned short  vendor;         /* vendor id */
+       unsigned short  device;         /* device id */
+
+       const char      *name;          /* device name */
+};
+
+#define DEVICE(vid,did,name) \
+  {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name)}
+
+/*
+ * Sorted in ascending order by vendor and device.
+ * Use binary search for lookup. If you add a device make sure
+ * it is sequential by both vendor and device id.
+ */
+struct pci_dev_info dev_info[] = {
+       DEVICE( COMPAQ,         COMPAQ_1280,    "QVision 1280/p"),
+       DEVICE( COMPAQ,         COMPAQ_SMART2P, "Smart-2/P RAID Controller"),
+       DEVICE( COMPAQ,         COMPAQ_NETEL100,"Netelligent 10/100"),
+       DEVICE( COMPAQ,         COMPAQ_NETEL10, "Netelligent 10"),
+       DEVICE( COMPAQ,         COMPAQ_NETFLEX3I,"NetFlex 3"),
+       DEVICE( COMPAQ,         COMPAQ_NETEL100D,"Netelligent 10/100 Dual"),
+       DEVICE( COMPAQ,         COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant"),
+       DEVICE( COMPAQ,         COMPAQ_NETEL100I,"Netelligent 10/100 Integrated"),
+       DEVICE( COMPAQ,         COMPAQ_THUNDER, "ThunderLAN"),
+       DEVICE( COMPAQ,         COMPAQ_NETFLEX3B,"NetFlex 3 BNC"),
+       DEVICE( NCR,            NCR_53C810,     "53c810"),
+       DEVICE( NCR,            NCR_53C820,     "53c820"),
+       DEVICE( NCR,            NCR_53C825,     "53c825"),
+       DEVICE( NCR,            NCR_53C815,     "53c815"),
+       DEVICE( NCR,            NCR_53C860,     "53c860"),
+       DEVICE( NCR,            NCR_53C896,     "53c896"),
+       DEVICE( NCR,            NCR_53C895,     "53c895"),
+       DEVICE( NCR,            NCR_53C885,     "53c885"),
+       DEVICE( NCR,            NCR_53C875,     "53c875"),
+       DEVICE( NCR,            NCR_53C875J,    "53c875J"),
+       DEVICE( ATI,            ATI_68800,      "68800AX"),
+       DEVICE( ATI,            ATI_215CT222,   "215CT222"),
+       DEVICE( ATI,            ATI_210888CX,   "210888CX"),
+       DEVICE( ATI,            ATI_215GB,      "Mach64 GB"),
+       DEVICE( ATI,            ATI_215GD,      "Mach64 GD (Rage Pro)"),
+       DEVICE( ATI,            ATI_215GP,      "Mach64 GP (Rage Pro)"),
+       DEVICE( ATI,            ATI_215GT,      "Mach64 GT (Rage II)"),
+       DEVICE( ATI,            ATI_215GTB,     "Mach64 GT (Rage II)"),
+       DEVICE( ATI,            ATI_210888GX,   "210888GX"),
+       DEVICE( ATI,            ATI_264VT,      "Mach64 VT"),
+       DEVICE( VLSI,           VLSI_82C592,    "82C592-FC1"),
+       DEVICE( VLSI,           VLSI_82C593,    "82C593-FC1"),
+       DEVICE( VLSI,           VLSI_82C594,    "82C594-AFC2"),
+       DEVICE( VLSI,           VLSI_82C597,    "82C597-AFC2"),
+       DEVICE( VLSI,           VLSI_82C541,    "82C541 Lynx"),
+       DEVICE( VLSI,           VLSI_82C543,    "82C543 Lynx ISA"),
+       DEVICE( VLSI,           VLSI_VAS96011,  "VAS96011 (Golden Gate II)"),
+       DEVICE( ADL,            ADL_2301,       "2301"),
+       DEVICE( NS,             NS_87415,       "87415"),
+       DEVICE( NS,             NS_87410,       "87410"),
+       DEVICE( TSENG,          TSENG_W32P_2,   "ET4000W32P"),
+       DEVICE( TSENG,          TSENG_W32P_b,   "ET4000W32P rev B"),
+       DEVICE( TSENG,          TSENG_W32P_c,   "ET4000W32P rev C"),
+       DEVICE( TSENG,          TSENG_W32P_d,   "ET4000W32P rev D"),
+       DEVICE( TSENG,          TSENG_ET6000,   "ET6000"),
+       DEVICE( WEITEK,         WEITEK_P9000,   "P9000"),
+       DEVICE( WEITEK,         WEITEK_P9100,   "P9100"),
+       DEVICE( DEC,            DEC_BRD,        "DC21050"),
+       DEVICE( DEC,            DEC_TULIP,      "DC21040"),
+       DEVICE( DEC,            DEC_TGA,        "TGA"),
+       DEVICE( DEC,            DEC_TULIP_FAST, "DC21140"),
+       DEVICE( DEC,            DEC_TGA2,       "TGA2"),
+       DEVICE( DEC,            DEC_FDDI,       "DEFPA"),
+       DEVICE( DEC,            DEC_TULIP_PLUS, "DC21041"),
+       DEVICE( DEC,            DEC_21142,      "DC21142"),
+       DEVICE( DEC,            DEC_21052,      "DC21052"),
+       DEVICE( DEC,            DEC_21152,      "DC21152"),
+       DEVICE( CIRRUS,         CIRRUS_7548,    "GD 7548"),
+       DEVICE( CIRRUS,         CIRRUS_5430,    "GD 5430"),
+       DEVICE( CIRRUS,         CIRRUS_5434_4,  "GD 5434"),
+       DEVICE( CIRRUS,         CIRRUS_5434_8,  "GD 5434"),
+       DEVICE( CIRRUS,         CIRRUS_5436,    "GD 5436"),
+       DEVICE( CIRRUS,         CIRRUS_5446,    "GD 5446"),
+       DEVICE( CIRRUS,         CIRRUS_5480,    "GD 5480"),
+       DEVICE( CIRRUS,         CIRRUS_5464,    "GD 5464"),
+       DEVICE( CIRRUS,         CIRRUS_5465,    "GD 5465"),
+       DEVICE( CIRRUS,         CIRRUS_6729,    "CL 6729"),
+       DEVICE( CIRRUS,         CIRRUS_6832,    "PD 6832"),
+       DEVICE( CIRRUS,         CIRRUS_7542,    "CL 7542"),
+       DEVICE( CIRRUS,         CIRRUS_7543,    "CL 7543"),
+       DEVICE( CIRRUS,         CIRRUS_7541,    "CL 7541"),
+       DEVICE( IBM,            IBM_FIRE_CORAL, "Fire Coral"),
+       DEVICE( IBM,            IBM_TR,         "Token Ring"),
+       DEVICE( IBM,            IBM_82G2675,    "82G2675"),
+       DEVICE( IBM,            IBM_82351,      "82351"),
+       DEVICE( WD,             WD_7197,        "WD 7197"),
+       DEVICE( AMD,            AMD_LANCE,      "79C970"),
+       DEVICE( AMD,            AMD_SCSI,       "53C974"),
+       DEVICE( TRIDENT,        TRIDENT_9420,   "TG 9420"),
+       DEVICE( TRIDENT,        TRIDENT_9440,   "TG 9440"),
+       DEVICE( TRIDENT,        TRIDENT_9660,   "TG 9660 / Cyber9385"),
+       DEVICE( TRIDENT,        TRIDENT_9750,   "Image 975"),
+       DEVICE( AI,             AI_M1435,       "M1435"),
+       DEVICE( MATROX,         MATROX_MGA_2,   "Atlas PX2085"),
+       DEVICE( MATROX,         MATROX_MIL,     "Millennium"),
+       DEVICE( MATROX,         MATROX_MYS,     "Mystique"),
+       DEVICE( MATROX,         MATROX_MIL_2,   "Millennium II"),
+       DEVICE( MATROX,         MATROX_MGA_IMP, "MGA Impression"),
+       DEVICE( CT,             CT_65545,       "65545"),
+       DEVICE( CT,             CT_65548,       "65548"),
+       DEVICE( CT,             CT_65550,       "65550"),
+       DEVICE( CT,             CT_65554,       "65554"),
+       DEVICE( MIRO,           MIRO_36050,     "ZR36050"),
+       DEVICE( NEC,            NEC_PCX2,       "PowerVR PCX2"),
+       DEVICE( FD,             FD_36C70,       "TMC-18C30"),
+       DEVICE( SI,             SI_6201,        "6201"),
+       DEVICE( SI,             SI_6202,        "6202"),
+       DEVICE( SI,             SI_503,         "85C503"),
+       DEVICE( SI,             SI_6205,        "6205"),
+       DEVICE( SI,             SI_501,         "85C501"),
+       DEVICE( SI,             SI_496,         "85C496"),
+       DEVICE( SI,             SI_601,         "85C601"),
+       DEVICE( SI,             SI_5107,        "5107"),
+       DEVICE( SI,             SI_5511,                "85C5511"),
+       DEVICE( SI,             SI_5513,                "85C5513"),
+       DEVICE( SI,             SI_5571,        "5571"),
+       DEVICE( SI,             SI_5597,        "5597"),
+       DEVICE( SI,             SI_7001,        "7001"),
+       DEVICE( HP,             HP_J2585A,      "J2585A"),
+       DEVICE( HP,             HP_J2585B,      "J2585B (Lassen)"),
+       DEVICE( PCTECH,         PCTECH_RZ1000,  "RZ1000 (buggy)"),
+       DEVICE( PCTECH,         PCTECH_RZ1001,  "RZ1001 (buggy?)"),
+       DEVICE( DPT,            DPT,            "SmartCache/Raid"),
+       DEVICE( OPTI,           OPTI_92C178,    "92C178"),
+       DEVICE( OPTI,           OPTI_82C557,    "82C557 Viper-M"),
+       DEVICE( OPTI,           OPTI_82C558,    "82C558 Viper-M ISA+IDE"),
+       DEVICE( OPTI,           OPTI_82C621,    "82C621"),
+       DEVICE( OPTI,           OPTI_82C700,    "82C700"),
+       DEVICE( OPTI,           OPTI_82C701,    "82C701 FireStar Plus"),
+       DEVICE( OPTI,           OPTI_82C814,    "82C814 Firebridge 1"),
+       DEVICE( OPTI,           OPTI_82C822,    "82C822"),
+       DEVICE( SGS,            SGS_2000,       "STG 2000X"),
+       DEVICE( SGS,            SGS_1764,       "STG 1764X"),
+       DEVICE( BUSLOGIC,       BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC"),
+       DEVICE( BUSLOGIC,       BUSLOGIC_MULTIMASTER,    "MultiMaster"),
+       DEVICE( BUSLOGIC,       BUSLOGIC_FLASHPOINT,     "FlashPoint"),
+       DEVICE( TI,             TI_TVP4010,     "TVP4010 Permedia"),
+       DEVICE( TI,             TI_TVP4020,     "TVP4020 Permedia 2"),
+       DEVICE( TI,             TI_PCI1130,     "PCI1130"),
+       DEVICE( TI,             TI_PCI1131,     "PCI1131"),
+       DEVICE( OAK,            OAK_OTI107,     "OTI107"),
+       DEVICE( WINBOND2,       WINBOND2_89C940,"NE2000-PCI"),
+       DEVICE( MOTOROLA,       MOTOROLA_MPC105,"MPC105 Eagle"),
+       DEVICE( MOTOROLA,       MOTOROLA_MPC106,"MPC106 Grackle"),
+       DEVICE( MOTOROLA,       MOTOROLA_RAVEN, "Raven"),
+       DEVICE( PROMISE,        PROMISE_20246,  "IDE UltraDMA/33"),
+       DEVICE( PROMISE,        PROMISE_5300,   "DC5030"),
+       DEVICE( N9,             N9_I128,        "Imagine 128"),
+       DEVICE( N9,             N9_I128_2,      "Imagine 128v2"),
+       DEVICE( UMC,            UMC_UM8673F,    "UM8673F"),
+       DEVICE( UMC,            UMC_UM8891A,    "UM8891A"),
+       DEVICE( UMC,            UMC_UM8886BF,   "UM8886BF"),
+       DEVICE( UMC,            UMC_UM8886A,    "UM8886A"),
+       DEVICE( UMC,            UMC_UM8881F,    "UM8881F"),
+       DEVICE( UMC,            UMC_UM8886F,    "UM8886F"),
+       DEVICE( UMC,            UMC_UM9017F,    "UM9017F"),
+       DEVICE( UMC,            UMC_UM8886N,    "UM8886N"),
+       DEVICE( UMC,            UMC_UM8891N,    "UM8891N"),
+       DEVICE( X,              X_AGX016,       "ITT AGX016"),
+       DEVICE( PICOP,          PICOP_PT86C52X, "PT86C52x Vesuvius"),
+       DEVICE( APPLE,          APPLE_BANDIT,   "Bandit"),
+       DEVICE( APPLE,          APPLE_GC,       "Grand Central"),
+       DEVICE( APPLE,          APPLE_HYDRA,    "Hydra"),
+       DEVICE( NEXGEN,         NEXGEN_82C501,  "82C501"),
+       DEVICE( QLOGIC,         QLOGIC_ISP1020, "ISP1020"),
+       DEVICE( QLOGIC,         QLOGIC_ISP1022, "ISP1022"),
+       DEVICE( CYRIX,          CYRIX_5510,     "5510"),
+       DEVICE( CYRIX,          CYRIX_PCI_MASTER,"PCI Master"),
+       DEVICE( CYRIX,          CYRIX_5520,     "5520"),
+       DEVICE( CYRIX,          CYRIX_5530_LEGACY,"5530 Kahlua Legacy"),
+       DEVICE( CYRIX,          CYRIX_5530_SMI, "5530 Kahlua SMI"),
+       DEVICE( CYRIX,          CYRIX_5530_IDE, "5530 Kahlua IDE"),
+       DEVICE( CYRIX,          CYRIX_5530_AUDIO,"5530 Kahlua Audio"),
+       DEVICE( CYRIX,          CYRIX_5530_VIDEO,"5530 Kahlua Video"),
+       DEVICE( LEADTEK,        LEADTEK_805,    "S3 805"),
+       DEVICE( CONTAQ,         CONTAQ_82C599,  "82C599"),
+       DEVICE( OLICOM,         OLICOM_OC3136,  "OC-3136/3137"),
+       DEVICE( OLICOM,         OLICOM_OC2315,  "OC-2315"),
+       DEVICE( OLICOM,         OLICOM_OC2325,  "OC-2325"),
+       DEVICE( OLICOM,         OLICOM_OC2183,  "OC-2183/2185"),
+       DEVICE( OLICOM,         OLICOM_OC2326,  "OC-2326"),
+       DEVICE( OLICOM,         OLICOM_OC6151,  "OC-6151/6152"),
+       DEVICE( SUN,            SUN_EBUS,       "EBUS"),
+       DEVICE( SUN,            SUN_HAPPYMEAL,  "Happy Meal"),
+       DEVICE( SUN,            SUN_PBM,        "PCI Bus Module"),
+       DEVICE( CMD,            CMD_640,        "640 (buggy)"),
+       DEVICE( CMD,            CMD_643,        "643"),
+       DEVICE( CMD,            CMD_646,        "646"),
+       DEVICE( CMD,            CMD_670,        "670"),
+       DEVICE( VISION,         VISION_QD8500,  "QD-8500"),
+       DEVICE( VISION,         VISION_QD8580,  "QD-8580"),
+       DEVICE( BROOKTREE,      BROOKTREE_848,  "Bt848"),
+       DEVICE( SIERRA,         SIERRA_STB,     "STB Horizon 64"),
+       DEVICE( ACC,            ACC_2056,       "2056"),
+       DEVICE( WINBOND,        WINBOND_83769,  "W83769F"),
+       DEVICE( WINBOND,        WINBOND_82C105, "SL82C105"),
+       DEVICE( WINBOND,        WINBOND_83C553, "W83C553"),
+       DEVICE( DATABOOK,       DATABOOK_87144, "DB87144"),
+       DEVICE( 3COM,           3COM_3C590,     "3C590 10bT"),
+       DEVICE( 3COM,           3COM_3C595TX,   "3C595 100bTX"),
+       DEVICE( 3COM,           3COM_3C595T4,   "3C595 100bT4"),
+       DEVICE( 3COM,           3COM_3C595MII,  "3C595 100b-MII"),
+       DEVICE( 3COM,           3COM_3C900TPO,  "3C900 10bTPO"),
+       DEVICE( 3COM,           3COM_3C900COMBO,"3C900 10b Combo"),
+       DEVICE( 3COM,           3COM_3C905TX,   "3C905 100bTX"),
+       DEVICE( SMC,            SMC_EPIC100,    "9432 TX"),
+       DEVICE( AL,             AL_M1445,       "M1445"),
+       DEVICE( AL,             AL_M1449,       "M1449"),
+       DEVICE( AL,             AL_M1451,       "M1451"),
+       DEVICE( AL,             AL_M1461,       "M1461"),
+       DEVICE( AL,             AL_M1489,       "M1489"),
+       DEVICE( AL,             AL_M1511,       "M1511"),
+       DEVICE( AL,             AL_M1513,       "M1513"),
+       DEVICE( AL,             AL_M1521,       "M1521"),
+       DEVICE( AL,             AL_M1523,       "M1523"),
+       DEVICE( AL,             AL_M1531,       "M1531 Aladdin IV"),
+       DEVICE( AL,             AL_M1533,       "M1533 Aladdin IV"),
+       DEVICE( AL,             AL_M4803,       "M4803"),
+       DEVICE( AL,             AL_M5219,       "M5219"),
+       DEVICE( AL,             AL_M5229,       "M5229 TXpro"),
+       DEVICE( SURECOM,        SURECOM_NE34,   "NE-34PCI LAN"),
+       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
+       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
+       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"),
+       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"),
+       DEVICE( ASP,            ASP_ABP940,     "ABP940"),
+       DEVICE( ASP,            ASP_ABP940U,    "ABP940U"),
+       DEVICE( CERN,           CERN_SPSB_PMC,  "STAR/RD24 SCI-PCI (PMC)"),
+       DEVICE( CERN,           CERN_SPSB_PCI,  "STAR/RD24 SCI-PCI (PMC)"),
+       DEVICE( IMS,            IMS_8849,       "8849"),
+       DEVICE( TEKRAM2,        TEKRAM2_690c,   "DC690c"),
+       DEVICE( TUNDRA,         TUNDRA_CA91C042,"CA91C042 Universe"),
+       DEVICE( AMCC,           AMCC_MYRINET,   "Myrinet PCI (M2-PCI-32)"),
+       DEVICE( AMCC,           AMCC_S5933,     "S5933 PCI44"),
+       DEVICE( AMCC,           AMCC_S5933_HEPC3,"S5933 Traquair HEPC3"),
+       DEVICE( INTERG,         INTERG_1680,    "IGA-1680"),
+       DEVICE( INTERG,         INTERG_1682,    "IGA-1682"),
+       DEVICE( REALTEK,        REALTEK_8029,   "8029"),
+       DEVICE( REALTEK,        REALTEK_8129,   "8129"),
+       DEVICE( TRUEVISION,     TRUEVISION_T1000,"TARGA 1000"),
+       DEVICE( INIT,           INIT_320P,      "320 P"),
+       DEVICE( VIA,            VIA_82C505,     "VT 82C505"),
+       DEVICE( VIA,            VIA_82C561,     "VT 82C561"),
+       DEVICE( VIA,            VIA_82C586_1,   "VT 82C586 Apollo IDE"),
+       DEVICE( VIA,            VIA_82C576,     "VT 82C576 3V"),
+       DEVICE( VIA,            VIA_82C585,     "VT 82C585 Apollo VP1/VPX"),
+       DEVICE( VIA,            VIA_82C586_0,   "VT 82C586 Apollo ISA"),
+       DEVICE( VIA,            VIA_82C595,     "VT 82C595 Apollo VP2"),
+       DEVICE( VIA,            VIA_82C926,     "VT 82C926 Amazon"),
+       DEVICE( VIA,            VIA_82C416,     "VT 82C416MV"),
+       DEVICE( VIA,            VIA_82C595_97,  "VT 82C595 Apollo VP2/97"),
+       DEVICE( VIA,            VIA_82C586_2,   "VT 82C586 Apollo USB"),
+       DEVICE( VIA,            VIA_82C586_3,   "VT 82C586B Apollo ACPI"),
+       DEVICE( VORTEX,         VORTEX_GDT60x0, "GDT 60x0"),
+       DEVICE( VORTEX,         VORTEX_GDT6000B,"GDT 6000b"),
+       DEVICE( VORTEX,         VORTEX_GDT6x10, "GDT 6110/6510"),
+       DEVICE( VORTEX,         VORTEX_GDT6x20, "GDT 6120/6520"),
+       DEVICE( VORTEX,         VORTEX_GDT6530, "GDT 6530"),
+       DEVICE( VORTEX,         VORTEX_GDT6550, "GDT 6550"),
+       DEVICE( VORTEX,         VORTEX_GDT6x17, "GDT 6117/6517"),
+       DEVICE( VORTEX,         VORTEX_GDT6x27, "GDT 6127/6527"),
+       DEVICE( VORTEX,         VORTEX_GDT6537, "GDT 6537"),
+       DEVICE( VORTEX,         VORTEX_GDT6557, "GDT 6557"),
+       DEVICE( VORTEX,         VORTEX_GDT6x15, "GDT 6115/6515"),
+       DEVICE( VORTEX,         VORTEX_GDT6x25, "GDT 6125/6525"),
+       DEVICE( VORTEX,         VORTEX_GDT6535, "GDT 6535"),
+       DEVICE( VORTEX,         VORTEX_GDT6555, "GDT 6555"),
+       DEVICE( VORTEX,         VORTEX_GDT6x17RP,"GDT 6117RP/6517RP"),
+       DEVICE( VORTEX,         VORTEX_GDT6x27RP,"GDT 6127RP/6527RP"),
+       DEVICE( VORTEX,         VORTEX_GDT6537RP,"GDT 6537RP"),
+       DEVICE( VORTEX,         VORTEX_GDT6557RP,"GDT 6557RP"),
+       DEVICE( VORTEX,         VORTEX_GDT6x11RP,"GDT 6111RP/6511RP"),
+       DEVICE( VORTEX,         VORTEX_GDT6x21RP,"GDT 6121RP/6521RP"),
+       DEVICE( VORTEX,         VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1"),
+       DEVICE( VORTEX,         VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1"),
+       DEVICE( VORTEX,         VORTEX_GDT6537RP1,"GDT 6537RP1"),
+       DEVICE( VORTEX,         VORTEX_GDT6557RP1,"GDT 6557RP1"),
+       DEVICE( VORTEX,         VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1"),
+       DEVICE( VORTEX,         VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1"),
+       DEVICE( VORTEX,         VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2"),
+       DEVICE( VORTEX,         VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2"),
+       DEVICE( VORTEX,         VORTEX_GDT6537RP2,"GDT 6537RP2"),
+       DEVICE( VORTEX,         VORTEX_GDT6557RP2,"GDT 6557RP2"),
+       DEVICE( VORTEX,         VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"),
+       DEVICE( VORTEX,         VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"),
+       DEVICE( EF,             EF_ATM_FPGA,            "155P-MF1 (FPGA)"),
+       DEVICE( EF,             EF_ATM_ASIC,    "155P-MF1 (ASIC)"),
+       DEVICE( FORE,           FORE_PCA200PC, "PCA-200PC"),
+       DEVICE( FORE,           FORE_PCA200E,    "PCA-200E"),
+       DEVICE( IMAGINGTECH,    IMAGINGTECH_ICPCI, "MVC IC-PCI"),
+       DEVICE( PHILIPS,        PHILIPS_SAA7146,"SAA7146"),
+       DEVICE( PLX,            PLX_9060,       "PCI9060 i960 bridge"),
+       DEVICE( ALLIANCE,       ALLIANCE_PROMOTIO, "Promotion-6410"),
+       DEVICE( ALLIANCE,       ALLIANCE_PROVIDEO, "Provideo"),
+       DEVICE( ALLIANCE,       ALLIANCE_AT24,  "AT24"),
+       DEVICE( ALLIANCE,       ALLIANCE_AT3D,  "AT3D"),
+       DEVICE( VMIC,           VMIC_VME,       "VMIVME-7587"),
+       DEVICE( DIGI,           DIGI_RIGHTSWITCH, "RightSwitch SE-6"),
+       DEVICE( MUTECH,         MUTECH_MV1000,  "MV-1000"),
+       DEVICE( RENDITION,      RENDITION_VERITE,"Verite 1000"),
+       DEVICE( RENDITION,      RENDITION_VERITE2100,"Verite 2100"),
+       DEVICE( TOSHIBA,        TOSHIBA_601,    "Laptop"),
+       DEVICE( RICOH,          RICOH_RL5C466,  "RL5C466"),
+       DEVICE( ZEITNET,        ZEITNET_1221,   "1221"),
+       DEVICE( ZEITNET,        ZEITNET_1225,   "1225"),
+       DEVICE( OMEGA,          OMEGA_82C092G,  "82C092G"),
+       DEVICE( LITEON,         LITEON_LNE100TX,"LNE100TX"),
+       DEVICE( NP,             NP_PCI_FDDI,    "NP-PCI"),       
+       DEVICE( SPECIALIX,      SPECIALIX_XIO,  "XIO/SIO host"),
+       DEVICE( SPECIALIX,      SPECIALIX_RIO,  "RIO host"),
+       DEVICE( AURAVISION,     AURAVISION_VXP524,"VXP524"),
+       DEVICE( IKON,           IKON_10115,     "10115 Greensheet"),
+       DEVICE( IKON,           IKON_10117,     "10117 Greensheet"),
+       DEVICE( ZORAN,          ZORAN_36057,    "ZR36057"),
+       DEVICE( ZORAN,          ZORAN_36120,    "ZR36120"),
+       DEVICE( COMPEX,         COMPEX_ENET100VG4, "Readylink ENET100-VG4"),
+       DEVICE( COMPEX,         COMPEX_RL2000,  "ReadyLink 2000"),
+       DEVICE( RP,             RP8OCTA,        "RocketPort 8 Oct"),
+       DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf"),
+       DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf"),
+       DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf"),
+       DEVICE( CYCLADES,       CYCLOM_Y_Lo,    "Cyclom-Y below 1Mbyte"),
+       DEVICE( CYCLADES,       CYCLOM_Y_Hi,    "Cyclom-Y above 1Mbyte"),
+       DEVICE( CYCLADES,       CYCLOM_Z_Lo,    "Cyclom-Z below 1Mbyte"),
+       DEVICE( CYCLADES,       CYCLOM_Z_Hi,    "Cyclom-Z above 1Mbyte"),
+       DEVICE( 3DFX,           3DFX_VOODOO,    "Voodoo"),
+       DEVICE( STALLION,       STALLION_ECHPCI832,"EasyConnection 8/32"),
+       DEVICE( STALLION,       STALLION_ECHPCI864,"EasyConnection 8/64"),
+       DEVICE( STALLION,       STALLION_EIOPCI,"EasyIO"),
+       DEVICE( SIGMADES,       SIGMADES_6425,  "REALmagic64/GX"),
+       DEVICE( OPTIBASE,       OPTIBASE_FORGE, "MPEG Forge"),
+       DEVICE( OPTIBASE,       OPTIBASE_FUSION,"MPEG Fusion"),
+       DEVICE( OPTIBASE,       OPTIBASE_VPLEX, "VideoPlex"),
+       DEVICE( OPTIBASE,       OPTIBASE_VPLEXCC,"VideoPlex CC"),
+       DEVICE( OPTIBASE,       OPTIBASE_VQUEST,"VideoQuest"),
+       DEVICE( ENSONIQ,        ENSONIQ_AUDIOPCI,"AudioPCI"),
+       DEVICE( PICTUREL,       PICTUREL_PCIVST,"PCIVST"),
+       DEVICE( NVIDIA_SGS,     NVIDIA_SGS_RIVA128,     "Riva 128"),
+       DEVICE( SYMPHONY,       SYMPHONY_101,   "82C101"),
+       DEVICE( TEKRAM,         TEKRAM_DC290,   "DC-290"),
+       DEVICE( 3DLABS,         3DLABS_300SX,   "GLINT 300SX"),
+       DEVICE( 3DLABS,         3DLABS_500TX,   "GLINT 500TX"),
+       DEVICE( 3DLABS,         3DLABS_DELTA,   "GLINT Delta"),
+       DEVICE( 3DLABS,         3DLABS_PERMEDIA,"PERMEDIA"),
+       DEVICE( AVANCE,         AVANCE_ALG2064, "ALG2064i"),
+       DEVICE( AVANCE,         AVANCE_2302,    "ALG-2302"),
+       DEVICE( NETVIN,         NETVIN_NV5000SC,"NV5000"),
+       DEVICE( S3,             S3_PLATO_PXS,   "PLATO/PX (system)"),
+       DEVICE( S3,             S3_ViRGE,       "ViRGE"),
+       DEVICE( S3,             S3_TRIO,        "Trio32/Trio64"),
+       DEVICE( S3,             S3_AURORA64VP,  "Aurora64V+"),
+       DEVICE( S3,             S3_TRIO64UVP,   "Trio64UV+"),
+       DEVICE( S3,             S3_ViRGE_VX,    "ViRGE/VX"),
+       DEVICE( S3,             S3_868, "Vision 868"),
+       DEVICE( S3,             S3_928,         "Vision 928-P"),
+       DEVICE( S3,             S3_864_1,       "Vision 864-P"),
+       DEVICE( S3,             S3_864_2,       "Vision 864-P"),
+       DEVICE( S3,             S3_964_1,       "Vision 964-P"),
+       DEVICE( S3,             S3_964_2,       "Vision 964-P"),
+       DEVICE( S3,             S3_968,         "Vision 968"),
+       DEVICE( S3,             S3_TRIO64V2,    "Trio64V2/DX or /GX"),
+       DEVICE( S3,             S3_PLATO_PXG,   "PLATO/PX (graphics)"),
+       DEVICE( S3,             S3_ViRGE_DXGX,  "ViRGE/DX or /GX"),
+       DEVICE( S3,             S3_ViRGE_GX2,   "ViRGE/GX2"),
+       DEVICE( S3,             S3_ViRGE_MX,    "ViRGE/MX"),
+       DEVICE( S3,             S3_ViRGE_MXP,   "ViRGE/MX+"),
+       DEVICE( S3,             S3_ViRGE_MXPMV, "ViRGE/MX+MV"),
+       DEVICE( INTEL,          INTEL_82375,    "82375EB"),
+       DEVICE( INTEL,          INTEL_82424,    "82424ZX Saturn"),
+       DEVICE( INTEL,          INTEL_82378,    "82378IB"),
+       DEVICE( INTEL,          INTEL_82430,    "82430ZX Aries"),
+       DEVICE( INTEL,          INTEL_82434,    "82434LX Mercury/Neptune"),
+       DEVICE( INTEL,          INTEL_82092AA_0,"82092AA PCMCIA bridge"),
+       DEVICE( INTEL,          INTEL_82092AA_1,"82092AA EIDE"),
+       DEVICE( INTEL,          INTEL_7116,     "SAA7116"),
+       DEVICE( INTEL,          INTEL_82596,    "82596"),
+       DEVICE( INTEL,          INTEL_82865,    "82865"),
+       DEVICE( INTEL,          INTEL_82557,    "82557"),
+       DEVICE( INTEL,          INTEL_82437,    "82437"),
+       DEVICE( INTEL,          INTEL_82371FB_0,"82371FB PIIX ISA"),
+       DEVICE( INTEL,          INTEL_82371FB_1,"82371FB PIIX IDE"),
+       DEVICE( INTEL,          INTEL_82371MX,  "430MX - 82371MX MPIIX"),
+       DEVICE( INTEL,          INTEL_82437MX,  "430MX - 82437MX MTSC"),
+       DEVICE( INTEL,          INTEL_82441,    "82441FX Natoma"),
+       DEVICE( INTEL,          INTEL_82439,    "82439HX Triton II"),
+       DEVICE( INTEL,          INTEL_82371SB_0,"82371SB PIIX3 ISA"),
+       DEVICE( INTEL,          INTEL_82371SB_1,"82371SB PIIX3 IDE"),
+       DEVICE( INTEL,          INTEL_82371SB_2,"82371SB PIIX3 USB"),
+       DEVICE( INTEL,          INTEL_82437VX,  "82437VX Triton II"),
+       DEVICE( INTEL,          INTEL_82439TX,  "82439TX"),
+       DEVICE( INTEL,          INTEL_82371AB_0,"82371AB PIIX4 ISA"),
+       DEVICE( INTEL,          INTEL_82371AB,  "82371AB PIIX4 IDE"),
+       DEVICE( INTEL,          INTEL_82371AB_2,"82371AB PIIX4 USB"),
+       DEVICE( INTEL,          INTEL_82371AB_3,"82371AB PIIX4 ACPI"),
+       DEVICE( INTEL,          INTEL_82443LX_0,"440LX - 82443LX PAC Host"),
+       DEVICE( INTEL,          INTEL_82443LX_1,"440LX - 82443LX PAC AGP"),
+       DEVICE( INTEL,          INTEL_P6,       "Orion P6"),
+       DEVICE( INTEL,          INTEL_82450GX,  "82450GX Orion P6"),
+       DEVICE( KTI,            KTI_ET32P2,     "ET32P2"),
+       DEVICE( ADAPTEC,        ADAPTEC_7850,   "AIC-7850"),
+       DEVICE( ADAPTEC,        ADAPTEC_7855,   "AIC-7855"),
+       DEVICE( ADAPTEC,        ADAPTEC_5800,   "AIC-5800"),
+       DEVICE( ADAPTEC,        ADAPTEC_7860,   "AIC-7860"),
+       DEVICE( ADAPTEC,        ADAPTEC_7861,   "AIC-7861"),
+       DEVICE( ADAPTEC,        ADAPTEC_7870,   "AIC-7870"),
+       DEVICE( ADAPTEC,        ADAPTEC_7871,   "AIC-7871"),
+       DEVICE( ADAPTEC,        ADAPTEC_7872,   "AIC-7872"),
+       DEVICE( ADAPTEC,        ADAPTEC_7873,   "AIC-7873"),
+       DEVICE( ADAPTEC,        ADAPTEC_7874,   "AIC-7874"),
+       DEVICE( ADAPTEC,        ADAPTEC_7895,   "AIC-7895U"),
+       DEVICE( ADAPTEC,        ADAPTEC_7880,   "AIC-7880U"),
+       DEVICE( ADAPTEC,        ADAPTEC_7881,   "AIC-7881U"),
+       DEVICE( ADAPTEC,        ADAPTEC_7882,   "AIC-7882U"),
+       DEVICE( ADAPTEC,        ADAPTEC_7883,   "AIC-7883U"),
+       DEVICE( ADAPTEC,        ADAPTEC_7884,   "AIC-7884U"),
+       DEVICE( ATRONICS,       ATRONICS_2015,  "IDE-2015PL"),
+       DEVICE( ARK,            ARK_STING,      "Stingray"),
+       DEVICE( ARK,            ARK_STINGARK,   "Stingray ARK 2000PV"),
+       DEVICE( ARK,            ARK_2000MT,     "2000MT")
+};
+
+
+/*
+ * device_info[] is sorted so we can use binary search
+ */
+static struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev)
+{
+       int min = 0,
+           max = sizeof(dev_info)/sizeof(dev_info[0]) - 1;
+
+       for ( ; ; )
+       {
+           int i = (min + max) >> 1;
+           long order;
+
+           order = dev_info[i].vendor - (long) vendor;
+           if (!order)
+               order = dev_info[i].device - (long) dev;
+       
+           if (order < 0)
+           {
+                   min = i + 1;
+                   if ( min > max )
+                      return 0;
+                   continue;
+           }
+
+           if (order > 0)
+           {
+                   max = i - 1;
+                   if ( min > max )
+                      return 0;
+                   continue;
+           }
+
+           return & dev_info[ i ];
+       }
+}
+
+static const char *pci_strclass (unsigned int class)
+{
+       switch (class >> 8) {
+             case PCI_CLASS_NOT_DEFINED:               return "Non-VGA device";
+             case PCI_CLASS_NOT_DEFINED_VGA:           return "VGA compatible device";
+
+             case PCI_CLASS_STORAGE_SCSI:              return "SCSI storage controller";
+             case PCI_CLASS_STORAGE_IDE:               return "IDE interface";
+             case PCI_CLASS_STORAGE_FLOPPY:            return "Floppy disk controller";
+             case PCI_CLASS_STORAGE_IPI:               return "IPI bus controller";
+             case PCI_CLASS_STORAGE_RAID:              return "RAID bus controller";
+             case PCI_CLASS_STORAGE_OTHER:             return "Unknown mass storage controller";
+
+             case PCI_CLASS_NETWORK_ETHERNET:          return "Ethernet controller";
+             case PCI_CLASS_NETWORK_TOKEN_RING:        return "Token ring network controller";
+             case PCI_CLASS_NETWORK_FDDI:              return "FDDI network controller";
+             case PCI_CLASS_NETWORK_ATM:               return "ATM network controller";
+             case PCI_CLASS_NETWORK_OTHER:             return "Network controller";
+
+             case PCI_CLASS_DISPLAY_VGA:               return "VGA compatible controller";
+             case PCI_CLASS_DISPLAY_XGA:               return "XGA compatible controller";
+             case PCI_CLASS_DISPLAY_OTHER:             return "Display controller";
+
+             case PCI_CLASS_MULTIMEDIA_VIDEO:          return "Multimedia video controller";
+             case PCI_CLASS_MULTIMEDIA_AUDIO:          return "Multimedia audio controller";
+             case PCI_CLASS_MULTIMEDIA_OTHER:          return "Multimedia controller";
+
+             case PCI_CLASS_MEMORY_RAM:                return "RAM memory";
+             case PCI_CLASS_MEMORY_FLASH:              return "FLASH memory";
+             case PCI_CLASS_MEMORY_OTHER:              return "Memory";
+
+             case PCI_CLASS_BRIDGE_HOST:               return "Host bridge";
+             case PCI_CLASS_BRIDGE_ISA:                return "ISA bridge";
+             case PCI_CLASS_BRIDGE_EISA:               return "EISA bridge";
+             case PCI_CLASS_BRIDGE_MC:                 return "MicroChannel bridge";
+             case PCI_CLASS_BRIDGE_PCI:                return "PCI bridge";
+             case PCI_CLASS_BRIDGE_PCMCIA:             return "PCMCIA bridge";
+             case PCI_CLASS_BRIDGE_NUBUS:              return "NuBus bridge";
+             case PCI_CLASS_BRIDGE_CARDBUS:            return "CardBus bridge";
+             case PCI_CLASS_BRIDGE_OTHER:              return "Bridge";
+
+             case PCI_CLASS_COMMUNICATION_SERIAL:      return "Serial controller";
+             case PCI_CLASS_COMMUNICATION_PARALLEL:    return "Parallel controller";
+             case PCI_CLASS_COMMUNICATION_OTHER:       return "Communication controller";
+
+             case PCI_CLASS_SYSTEM_PIC:                return "PIC";
+             case PCI_CLASS_SYSTEM_DMA:                return "DMA controller";
+             case PCI_CLASS_SYSTEM_TIMER:              return "Timer";
+             case PCI_CLASS_SYSTEM_RTC:                return "RTC";
+             case PCI_CLASS_SYSTEM_OTHER:              return "System peripheral";
+
+             case PCI_CLASS_INPUT_KEYBOARD:            return "Keyboard controller";
+             case PCI_CLASS_INPUT_PEN:                 return "Digitizer Pen";
+             case PCI_CLASS_INPUT_MOUSE:               return "Mouse controller";
+             case PCI_CLASS_INPUT_OTHER:               return "Input device controller";
+
+             case PCI_CLASS_DOCKING_GENERIC:           return "Generic Docking Station";
+             case PCI_CLASS_DOCKING_OTHER:             return "Docking Station";
+
+             case PCI_CLASS_PROCESSOR_386:             return "386";
+             case PCI_CLASS_PROCESSOR_486:             return "486";
+             case PCI_CLASS_PROCESSOR_PENTIUM:         return "Pentium";
+             case PCI_CLASS_PROCESSOR_ALPHA:           return "Alpha";
+             case PCI_CLASS_PROCESSOR_POWERPC:         return "Power PC";
+             case PCI_CLASS_PROCESSOR_CO:              return "Co-processor";
+
+             case PCI_CLASS_SERIAL_FIREWIRE:           return "FireWire (IEEE 1394)";
+             case PCI_CLASS_SERIAL_ACCESS:             return "ACCESS Bus";
+             case PCI_CLASS_SERIAL_SSA:                return "SSA";
+             case PCI_CLASS_SERIAL_USB:                return "USB Controller";
+             case PCI_CLASS_SERIAL_FIBER:              return "Fiber Channel";
+
+             default:                                  return "Unknown class";
+       }
+}
+
+
+static const char *pci_strvendor(unsigned int vendor)
+{
+       switch (vendor) {
+             case PCI_VENDOR_ID_COMPAQ:        return "Compaq";
+             case PCI_VENDOR_ID_NCR:           return "NCR";
+             case PCI_VENDOR_ID_ATI:           return "ATI";
+             case PCI_VENDOR_ID_VLSI:          return "VLSI";
+             case PCI_VENDOR_ID_ADL:           return "Avance Logic";
+             case PCI_VENDOR_ID_NS:            return "NS";
+             case PCI_VENDOR_ID_TSENG:         return "Tseng'Lab";
+             case PCI_VENDOR_ID_WEITEK:        return "Weitek";
+             case PCI_VENDOR_ID_DEC:           return "DEC";
+             case PCI_VENDOR_ID_CIRRUS:        return "Cirrus Logic";
+             case PCI_VENDOR_ID_IBM:           return "IBM";
+             case PCI_VENDOR_ID_WD:            return "Western Digital";
+             case PCI_VENDOR_ID_AMD:           return "AMD";
+             case PCI_VENDOR_ID_TRIDENT:       return "Trident";
+             case PCI_VENDOR_ID_AI:            return "Acer Incorporated";
+             case PCI_VENDOR_ID_MATROX:        return "Matrox";
+             case PCI_VENDOR_ID_CT:            return "Chips & Technologies";
+             case PCI_VENDOR_ID_MIRO:          return "Miro";
+             case PCI_VENDOR_ID_NEC:           return "NEC";
+             case PCI_VENDOR_ID_FD:            return "Future Domain";
+             case PCI_VENDOR_ID_SI:            return "Silicon Integrated Systems";
+             case PCI_VENDOR_ID_HP:            return "Hewlett Packard";
+             case PCI_VENDOR_ID_PCTECH:        return "PCTECH";
+             case PCI_VENDOR_ID_DPT:           return "DPT";
+             case PCI_VENDOR_ID_OPTI:          return "OPTi";
+             case PCI_VENDOR_ID_SGS:           return "SGS Thomson";
+             case PCI_VENDOR_ID_BUSLOGIC:      return "BusLogic";
+             case PCI_VENDOR_ID_TI:            return "Texas Instruments";
+             case PCI_VENDOR_ID_OAK:           return "OAK";
+             case PCI_VENDOR_ID_WINBOND2:      return "Winbond";
+             case PCI_VENDOR_ID_MOTOROLA:      return "Motorola";
+             case PCI_VENDOR_ID_PROMISE:       return "Promise Technology";
+             case PCI_VENDOR_ID_N9:            return "Number Nine";
+             case PCI_VENDOR_ID_UMC:           return "UMC";
+             case PCI_VENDOR_ID_X:             return "X TECHNOLOGY";
+             case PCI_VENDOR_ID_PICOP:         return "PicoPower";
+             case PCI_VENDOR_ID_APPLE:         return "Apple";
+             case PCI_VENDOR_ID_NEXGEN:        return "Nexgen";
+             case PCI_VENDOR_ID_QLOGIC:        return "Q Logic";
+             case PCI_VENDOR_ID_CYRIX:         return "Cyrix";
+             case PCI_VENDOR_ID_LEADTEK:       return "Leadtek Research";
+             case PCI_VENDOR_ID_CONTAQ:        return "Contaq";
+             case PCI_VENDOR_ID_FOREX:         return "Forex";
+             case PCI_VENDOR_ID_OLICOM:        return "Olicom";
+             case PCI_VENDOR_ID_SUN:           return "Sun Microsystems";
+             case PCI_VENDOR_ID_CMD:           return "CMD";
+             case PCI_VENDOR_ID_VISION:        return "Vision";
+             case PCI_VENDOR_ID_BROOKTREE:     return "Brooktree";
+             case PCI_VENDOR_ID_SIERRA:        return "Sierra";
+             case PCI_VENDOR_ID_ACC:           return "ACC MICROELECTRONICS";
+             case PCI_VENDOR_ID_WINBOND:       return "Winbond";
+             case PCI_VENDOR_ID_DATABOOK:      return "Databook";
+             case PCI_VENDOR_ID_3COM:          return "3Com";
+             case PCI_VENDOR_ID_SMC:           return "SMC";
+             case PCI_VENDOR_ID_AL:            return "Acer Labs";
+             case PCI_VENDOR_ID_MITSUBISHI:    return "Mitsubishi";
+             case PCI_VENDOR_ID_SURECOM:       return "Surecom";
+             case PCI_VENDOR_ID_NEOMAGIC:      return "Neomagic";
+             case PCI_VENDOR_ID_ASP:           return "Advanced System Products";
+             case PCI_VENDOR_ID_CERN:          return "CERN";
+             case PCI_VENDOR_ID_NVIDIA:        return "NVidia";
+             case PCI_VENDOR_ID_IMS:           return "IMS";
+             case PCI_VENDOR_ID_TEKRAM2:       return "Tekram";
+             case PCI_VENDOR_ID_TUNDRA:        return "Tundra";
+             case PCI_VENDOR_ID_AMCC:          return "AMCC";
+             case PCI_VENDOR_ID_INTERG:        return "Intergraphics";
+             case PCI_VENDOR_ID_REALTEK:       return "Realtek";
+             case PCI_VENDOR_ID_TRUEVISION:    return "Truevision";
+             case PCI_VENDOR_ID_INIT:          return "Initio Corp";
+             case PCI_VENDOR_ID_VIA:           return "VIA Technologies";
+             case PCI_VENDOR_ID_VORTEX:        return "VORTEX";
+             case PCI_VENDOR_ID_EF:            return "Efficient Networks";
+             case PCI_VENDOR_ID_FORE:          return "Fore Systems";
+             case PCI_VENDOR_ID_IMAGINGTECH:   return "Imaging Technology";
+             case PCI_VENDOR_ID_PHILIPS:       return "Philips";
+             case PCI_VENDOR_ID_PLX:           return "PLX";
+             case PCI_VENDOR_ID_ALLIANCE:      return "Alliance";
+             case PCI_VENDOR_ID_VMIC:          return "VMIC";
+             case PCI_VENDOR_ID_DIGI:          return "Digi Intl.";
+             case PCI_VENDOR_ID_MUTECH:        return "Mutech";
+             case PCI_VENDOR_ID_RENDITION:     return "Rendition";
+             case PCI_VENDOR_ID_TOSHIBA:       return "Toshiba";
+             case PCI_VENDOR_ID_RICOH:         return "Ricoh";
+             case PCI_VENDOR_ID_ZEITNET:       return "ZeitNet";
+             case PCI_VENDOR_ID_OMEGA:         return "Omega Micro";
+             case PCI_VENDOR_ID_LITEON:        return "LiteOn";
+             case PCI_VENDOR_ID_NP:            return "Network Peripherals";
+             case PCI_VENDOR_ID_SPECIALIX:     return "Specialix";
+             case PCI_VENDOR_ID_AURAVISION:    return "Auravision";
+             case PCI_VENDOR_ID_IKON:          return "Ikon";
+             case PCI_VENDOR_ID_ZORAN:         return "Zoran";
+             case PCI_VENDOR_ID_COMPEX:        return "Compex";
+             case PCI_VENDOR_ID_RP:            return "Comtrol";
+             case PCI_VENDOR_ID_CYCLADES:      return "Cyclades";
+             case PCI_VENDOR_ID_3DFX:          return "3Dfx";
+             case PCI_VENDOR_ID_STALLION:      return "Stallion Technologies";
+             case PCI_VENDOR_ID_SIGMADES:      return "Sigma Designs";
+             case PCI_VENDOR_ID_OPTIBASE:      return "Optibase";
+             case PCI_VENDOR_ID_ENSONIQ:       return "Ensoniq";
+             case PCI_VENDOR_ID_PICTUREL:      return "Picture Elements";
+             case PCI_VENDOR_ID_NVIDIA_SGS:    return "NVidia/SGS Thomson";
+             case PCI_VENDOR_ID_SYMPHONY:      return "Symphony";
+             case PCI_VENDOR_ID_TEKRAM:        return "Tekram";
+             case PCI_VENDOR_ID_3DLABS:        return "3Dlabs";
+             case PCI_VENDOR_ID_AVANCE:        return "Avance";
+             case PCI_VENDOR_ID_NETVIN:        return "NetVin";
+             case PCI_VENDOR_ID_S3:            return "S3 Inc.";
+             case PCI_VENDOR_ID_INTEL:         return "Intel";
+             case PCI_VENDOR_ID_KTI:           return "KTI";
+             case PCI_VENDOR_ID_ADAPTEC:       return "Adaptec";
+             case PCI_VENDOR_ID_ATRONICS:      return "Atronics";
+             case PCI_VENDOR_ID_ARK:           return "ARK Logic";
+             default:                          return "Unknown vendor";
+       }
+}
+
+
+static const char *pci_strdev(unsigned int vendor, unsigned int device)
+{
+       struct pci_dev_info *info;
+
+       info =  pci_lookup_dev(vendor, device);
+       return info ? info->name : "Unknown device";
+}
+
+
+/*
+ * Convert some of the configuration space registers of the device at
+ * address (bus,devfn) into a string (possibly several lines each).
+ * The configuration string is stored starting at buf[len].  If the
+ * string would exceed the size of the buffer (SIZE), 0 is returned.
+ */
+static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
+{
+       unsigned long base;
+       unsigned int l, class_rev, bus, devfn;
+       unsigned short vendor, device, status;
+       unsigned char bist, latency, min_gnt, max_lat;
+       int reg, len = 0;
+       const char *str;
+
+       bus   = dev->bus->number;
+       devfn = dev->devfn;
+
+       pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev);
+       pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor);
+       pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device);
+       pcibios_read_config_word (bus, devfn, PCI_STATUS, &status);
+       pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist);
+       pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency);
+       pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt);
+       pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat);
+       if (len + 80 > size) {
+               return -1;
+       }
+       len += sprintf(buf + len, "  Bus %2d, device %3d, function %2d:\n",
+                      bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+       if (len + 80 > size) {
+               return -1;
+       }
+       len += sprintf(buf + len, "    %s: %s %s (rev %d).\n      ",
+                      pci_strclass(class_rev >> 8), pci_strvendor(vendor),
+                      pci_strdev(vendor, device), class_rev & 0xff);
+
+       if (!pci_lookup_dev(vendor, device)) {
+               len += sprintf(buf + len,
+                              "Vendor id=%x. Device id=%x.\n      ",
+                              vendor, device);
+       }
+
+       str = 0;        /* to keep gcc shut... */
+       switch (status & PCI_STATUS_DEVSEL_MASK) {
+             case PCI_STATUS_DEVSEL_FAST:   str = "Fast devsel.  "; break;
+             case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel.  "; break;
+             case PCI_STATUS_DEVSEL_SLOW:   str = "Slow devsel.  "; break;
+       }
+       if (len + strlen(str) > size) {
+               return -1;
+       }
+       len += sprintf(buf + len, str);
+
+       if (status & PCI_STATUS_FAST_BACK) {
+#              define fast_b2b_capable "Fast back-to-back capable.  "
+               if (len + strlen(fast_b2b_capable) > size) {
+                       return -1;
+               }
+               len += sprintf(buf + len, fast_b2b_capable);
+#              undef fast_b2b_capable
+       }
+
+       if (bist & PCI_BIST_CAPABLE) {
+#              define BIST_capable     "BIST capable.  "
+               if (len + strlen(BIST_capable) > size) {
+                       return -1;
+               }
+               len += sprintf(buf + len, BIST_capable);
+#              undef BIST_capable
+       }
+
+       if (dev->irq) {
+               if (len + 40 > size) {
+                       return -1;
+               }
+               len += sprintf(buf + len, "IRQ %x.  ", dev->irq);
+       }
+
+       if (dev->master) {
+               if (len + 80 > size) {
+                       return -1;
+               }
+               len += sprintf(buf + len, "Master Capable.  ");
+               if (latency)
+                 len += sprintf(buf + len, "Latency=%d.  ", latency);
+               else
+                 len += sprintf(buf + len, "No bursts.  ");
+               if (min_gnt)
+                 len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
+               if (max_lat)
+                 len += sprintf(buf + len, "Max Lat=%d.", max_lat);
+       }
+
+       for (reg = 0; reg < 6; reg++) {
+               if (len + 40 > size) {
+                       return -1;
+               }
+               pcibios_read_config_dword(bus, devfn,
+                               PCI_BASE_ADDRESS_0 + (reg << 2), &l);
+               if (l == 0xffffffff)
+                       base = 0;
+               else
+                       base = l;
+               if (!base)
+                       continue;
+
+               if (base & PCI_BASE_ADDRESS_SPACE_IO) {
+                       len += sprintf(buf + len,
+                                      "\n      I/O at 0x%lx [0x%lx].",
+                                      base & PCI_BASE_ADDRESS_IO_MASK,
+                                      dev->base_address[reg]);
+               } else {
+                       const char *pref, *type = "unknown";
+
+                       if (base & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+                               pref = "P";
+                       } else {
+                               pref = "Non-p";
+                       }
+                       switch (base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+                             case PCI_BASE_ADDRESS_MEM_TYPE_32:
+                               type = "32 bit"; break;
+                             case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+                               type = "20 bit"; break;
+                             case PCI_BASE_ADDRESS_MEM_TYPE_64:
+                               type = "64 bit";
+                               /* read top 32 bit address of base addr: */
+                               reg += 4;
+                               pcibios_read_config_dword(bus, devfn, reg, &l);
+                               base |= ((u64) l) << 32;
+                               break;
+                       }
+                       len += sprintf(buf + len,
+                                      "\n      %srefetchable %s memory at "
+                                      "0x%lx [0x%lx].", pref, type,
+                                      base & PCI_BASE_ADDRESS_MEM_MASK,
+                                      dev->base_address[reg]);
+               }
+       }
+
+       len += sprintf(buf + len, "\n");
+       return len;
+}
+
+
+/*
+ * Return list of PCI devices as a character string for /proc/pci.
+ * BUF is a buffer that is PAGE_SIZE bytes long.
+ */
+int get_pci_list(char *buf)
+{
+       int nprinted, len, size;
+       struct pci_dev *dev;
+       static int complained = 0;
+#      define MSG "\nwarning: page-size limit reached!\n"
+
+       if (!complained) {
+               complained++;
+               printk(KERN_INFO "%s uses obsolete /proc/pci interface\n",
+                       current->comm);
+       }
+
+       /* reserve same for truncation warning message: */
+       size  = PAGE_SIZE - (strlen(MSG) + 1);
+       len   = sprintf(buf, "PCI devices found:\n");
+
+       for (dev = pci_devices; dev; dev = dev->next) {
+               nprinted = sprint_dev_config(dev, buf + len, size - len);
+               if (nprinted < 0) {
+                       return len + sprintf(buf + len, MSG);
+               }
+               len += nprinted;
+       }
+       return len;
+}
+
+#endif
index 7f43307ae9c469cfd5217468d1c9f4e28350f992..dff9a4c6bc50be8da428ec5f6f22805b87c0db2c 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * $Id: pci.c,v 1.51 1997/12/03 06:18:11 davem Exp $
+ *     $Id: pci.c,v 1.55 1997/12/27 12:17:54 mj Exp $
  *
- * PCI services that are built on top of the BIOS32 service.
+ *     PCI services that are built on top of the BIOS32 service.
  *
- * Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
+ *     Copyright 1993, 1994, 1995, 1997 Drew Eckhardt, Frederic Potter,
  *     David Mosberger-Tang, Martin Mares
  */
+
 #include <linux/config.h>
-#include <linux/ptrace.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/bios32.h>
@@ -22,667 +22,18 @@ struct pci_dev *pci_devices = 0;
 
 #undef DEBUG
 
-#define DEVICE(vid,did,name) \
-  {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##did, (name)}
-
-/*
- * Sorted in ascending order by vendor and device.
- * Use binary search for lookup. If you add a device make sure
- * it is sequential by both vendor and device id.
- */
-struct pci_dev_info dev_info[] = {
-       DEVICE( COMPAQ,         COMPAQ_1280,    "QVision 1280/p"),
-       DEVICE( COMPAQ,         COMPAQ_SMART2P, "Smart-2/P RAID Controller"),
-       DEVICE( COMPAQ,         COMPAQ_NETEL100,"Netelligent 10/100"),
-       DEVICE( COMPAQ,         COMPAQ_NETEL10, "Netelligent 10"),
-       DEVICE( COMPAQ,         COMPAQ_NETFLEX3I,"NetFlex 3"),
-       DEVICE( COMPAQ,         COMPAQ_NETEL100D,"Netelligent 10/100 Dual"),
-       DEVICE( COMPAQ,         COMPAQ_NETEL100PI,"Netelligent 10/100 ProLiant"),
-       DEVICE( COMPAQ,         COMPAQ_NETEL100I,"Netelligent 10/100 Integrated"),
-       DEVICE( COMPAQ,         COMPAQ_THUNDER, "ThunderLAN"),
-       DEVICE( COMPAQ,         COMPAQ_NETFLEX3B,"NetFlex 3 BNC"),
-       DEVICE( NCR,            NCR_53C810,     "53c810"),
-       DEVICE( NCR,            NCR_53C820,     "53c820"),
-       DEVICE( NCR,            NCR_53C825,     "53c825"),
-       DEVICE( NCR,            NCR_53C815,     "53c815"),
-       DEVICE( NCR,            NCR_53C860,     "53c860"),
-       DEVICE( NCR,            NCR_53C896,     "53c896"),
-       DEVICE( NCR,            NCR_53C895,     "53c895"),
-       DEVICE( NCR,            NCR_53C885,     "53c885"),
-       DEVICE( NCR,            NCR_53C875,     "53c875"),
-       DEVICE( NCR,            NCR_53C875J,    "53c875J"),
-       DEVICE( ATI,            ATI_68800,      "68800AX"),
-       DEVICE( ATI,            ATI_215CT222,   "215CT222"),
-       DEVICE( ATI,            ATI_210888CX,   "210888CX"),
-       DEVICE( ATI,            ATI_215GB,      "Mach64 GB"),
-       DEVICE( ATI,            ATI_215GD,      "Mach64 GD (Rage Pro)"),
-       DEVICE( ATI,            ATI_215GP,      "Mach64 GP (Rage Pro)"),
-       DEVICE( ATI,            ATI_215GT,      "Mach64 GT (Rage II)"),
-       DEVICE( ATI,            ATI_215GTB,     "Mach64 GT (Rage II)"),
-       DEVICE( ATI,            ATI_210888GX,   "210888GX"),
-       DEVICE( ATI,            ATI_264VT,      "Mach64 VT"),
-       DEVICE( VLSI,           VLSI_82C592,    "82C592-FC1"),
-       DEVICE( VLSI,           VLSI_82C593,    "82C593-FC1"),
-       DEVICE( VLSI,           VLSI_82C594,    "82C594-AFC2"),
-       DEVICE( VLSI,           VLSI_82C597,    "82C597-AFC2"),
-       DEVICE( VLSI,           VLSI_82C541,    "82C541 Lynx"),
-       DEVICE( VLSI,           VLSI_82C543,    "82C543 Lynx ISA"),
-       DEVICE( VLSI,           VLSI_VAS96011,  "VAS96011 (Golden Gate II)"),
-       DEVICE( ADL,            ADL_2301,       "2301"),
-       DEVICE( NS,             NS_87415,       "87415"),
-       DEVICE( NS,             NS_87410,       "87410"),
-       DEVICE( TSENG,          TSENG_W32P_2,   "ET4000W32P"),
-       DEVICE( TSENG,          TSENG_W32P_b,   "ET4000W32P rev B"),
-       DEVICE( TSENG,          TSENG_W32P_c,   "ET4000W32P rev C"),
-       DEVICE( TSENG,          TSENG_W32P_d,   "ET4000W32P rev D"),
-       DEVICE( TSENG,          TSENG_ET6000,   "ET6000"),
-       DEVICE( WEITEK,         WEITEK_P9000,   "P9000"),
-       DEVICE( WEITEK,         WEITEK_P9100,   "P9100"),
-       DEVICE( DEC,            DEC_BRD,        "DC21050"),
-       DEVICE( DEC,            DEC_TULIP,      "DC21040"),
-       DEVICE( DEC,            DEC_TGA,        "TGA"),
-       DEVICE( DEC,            DEC_TULIP_FAST, "DC21140"),
-       DEVICE( DEC,            DEC_TGA2,       "TGA2"),
-       DEVICE( DEC,            DEC_FDDI,       "DEFPA"),
-       DEVICE( DEC,            DEC_TULIP_PLUS, "DC21041"),
-       DEVICE( DEC,            DEC_21142,      "DC21142"),
-       DEVICE( DEC,            DEC_21052,      "DC21052"),
-       DEVICE( DEC,            DEC_21152,      "DC21152"),
-       DEVICE( CIRRUS,         CIRRUS_7548,    "GD 7548"),
-       DEVICE( CIRRUS,         CIRRUS_5430,    "GD 5430"),
-       DEVICE( CIRRUS,         CIRRUS_5434_4,  "GD 5434"),
-       DEVICE( CIRRUS,         CIRRUS_5434_8,  "GD 5434"),
-       DEVICE( CIRRUS,         CIRRUS_5436,    "GD 5436"),
-       DEVICE( CIRRUS,         CIRRUS_5446,    "GD 5446"),
-       DEVICE( CIRRUS,         CIRRUS_5480,    "GD 5480"),
-       DEVICE( CIRRUS,         CIRRUS_5464,    "GD 5464"),
-       DEVICE( CIRRUS,         CIRRUS_5465,    "GD 5465"),
-       DEVICE( CIRRUS,         CIRRUS_6729,    "CL 6729"),
-       DEVICE( CIRRUS,         CIRRUS_6832,    "PD 6832"),
-       DEVICE( CIRRUS,         CIRRUS_7542,    "CL 7542"),
-       DEVICE( CIRRUS,         CIRRUS_7543,    "CL 7543"),
-       DEVICE( CIRRUS,         CIRRUS_7541,    "CL 7541"),
-       DEVICE( IBM,            IBM_FIRE_CORAL, "Fire Coral"),
-       DEVICE( IBM,            IBM_TR,         "Token Ring"),
-       DEVICE( IBM,            IBM_82G2675,    "82G2675"),
-       DEVICE( IBM,            IBM_82351,      "82351"),
-       DEVICE( WD,             WD_7197,        "WD 7197"),
-       DEVICE( AMD,            AMD_LANCE,      "79C970"),
-       DEVICE( AMD,            AMD_SCSI,       "53C974"),
-       DEVICE( TRIDENT,        TRIDENT_9420,   "TG 9420"),
-       DEVICE( TRIDENT,        TRIDENT_9440,   "TG 9440"),
-       DEVICE( TRIDENT,        TRIDENT_9660,   "TG 9660 / Cyber9385"),
-       DEVICE( TRIDENT,        TRIDENT_9750,   "Image 975"),
-       DEVICE( AI,             AI_M1435,       "M1435"),
-       DEVICE( MATROX,         MATROX_MGA_2,   "Atlas PX2085"),
-       DEVICE( MATROX,         MATROX_MIL,     "Millennium"),
-       DEVICE( MATROX,         MATROX_MYS,     "Mystique"),
-       DEVICE( MATROX,         MATROX_MIL_2,   "Millennium II"),
-       DEVICE( MATROX,         MATROX_MGA_IMP, "MGA Impression"),
-       DEVICE( CT,             CT_65545,       "65545"),
-       DEVICE( CT,             CT_65548,       "65548"),
-       DEVICE( CT,             CT_65550,       "65550"),
-       DEVICE( CT,             CT_65554,       "65554"),
-       DEVICE( MIRO,           MIRO_36050,     "ZR36050"),
-       DEVICE( NEC,            NEC_PCX2,       "PowerVR PCX2"),
-       DEVICE( FD,             FD_36C70,       "TMC-18C30"),
-       DEVICE( SI,             SI_6201,        "6201"),
-       DEVICE( SI,             SI_6202,        "6202"),
-       DEVICE( SI,             SI_503,         "85C503"),
-       DEVICE( SI,             SI_6205,        "6205"),
-       DEVICE( SI,             SI_501,         "85C501"),
-       DEVICE( SI,             SI_496,         "85C496"),
-       DEVICE( SI,             SI_601,         "85C601"),
-       DEVICE( SI,             SI_5107,        "5107"),
-       DEVICE( SI,             SI_5511,                "85C5511"),
-       DEVICE( SI,             SI_5513,                "85C5513"),
-       DEVICE( SI,             SI_5571,        "5571"),
-       DEVICE( SI,             SI_5597,        "5597"),
-       DEVICE( SI,             SI_7001,        "7001"),
-       DEVICE( HP,             HP_J2585A,      "J2585A"),
-       DEVICE( HP,             HP_J2585B,      "J2585B (Lassen)"),
-       DEVICE( PCTECH,         PCTECH_RZ1000,  "RZ1000 (buggy)"),
-       DEVICE( PCTECH,         PCTECH_RZ1001,  "RZ1001 (buggy?)"),
-       DEVICE( DPT,            DPT,            "SmartCache/Raid"),
-       DEVICE( OPTI,           OPTI_92C178,    "92C178"),
-       DEVICE( OPTI,           OPTI_82C557,    "82C557 Viper-M"),
-       DEVICE( OPTI,           OPTI_82C558,    "82C558 Viper-M ISA+IDE"),
-       DEVICE( OPTI,           OPTI_82C621,    "82C621"),
-       DEVICE( OPTI,           OPTI_82C700,    "82C700"),
-       DEVICE( OPTI,           OPTI_82C701,    "82C701 FireStar Plus"),
-       DEVICE( OPTI,           OPTI_82C814,    "82C814 Firebridge 1"),
-       DEVICE( OPTI,           OPTI_82C822,    "82C822"),
-       DEVICE( SGS,            SGS_2000,       "STG 2000X"),
-       DEVICE( SGS,            SGS_1764,       "STG 1764X"),
-       DEVICE( BUSLOGIC,       BUSLOGIC_MULTIMASTER_NC, "MultiMaster NC"),
-       DEVICE( BUSLOGIC,       BUSLOGIC_MULTIMASTER,    "MultiMaster"),
-       DEVICE( BUSLOGIC,       BUSLOGIC_FLASHPOINT,     "FlashPoint"),
-       DEVICE( TI,             TI_TVP4010,     "TVP4010 Permedia"),
-       DEVICE( TI,             TI_TVP4020,     "TVP4020 Permedia 2"),
-       DEVICE( TI,             TI_PCI1130,     "PCI1130"),
-       DEVICE( TI,             TI_PCI1131,     "PCI1131"),
-       DEVICE( OAK,            OAK_OTI107,     "OTI107"),
-       DEVICE( WINBOND2,       WINBOND2_89C940,"NE2000-PCI"),
-       DEVICE( MOTOROLA,       MOTOROLA_MPC105,"MPC105 Eagle"),
-       DEVICE( MOTOROLA,       MOTOROLA_MPC106,"MPC106 Grackle"),
-       DEVICE( MOTOROLA,       MOTOROLA_RAVEN, "Raven"),
-       DEVICE( PROMISE,        PROMISE_20246,  "IDE UltraDMA/33"),
-       DEVICE( PROMISE,        PROMISE_5300,   "DC5030"),
-       DEVICE( N9,             N9_I128,        "Imagine 128"),
-       DEVICE( N9,             N9_I128_2,      "Imagine 128v2"),
-       DEVICE( UMC,            UMC_UM8673F,    "UM8673F"),
-       DEVICE( UMC,            UMC_UM8891A,    "UM8891A"),
-       DEVICE( UMC,            UMC_UM8886BF,   "UM8886BF"),
-       DEVICE( UMC,            UMC_UM8886A,    "UM8886A"),
-       DEVICE( UMC,            UMC_UM8881F,    "UM8881F"),
-       DEVICE( UMC,            UMC_UM8886F,    "UM8886F"),
-       DEVICE( UMC,            UMC_UM9017F,    "UM9017F"),
-       DEVICE( UMC,            UMC_UM8886N,    "UM8886N"),
-       DEVICE( UMC,            UMC_UM8891N,    "UM8891N"),
-       DEVICE( X,              X_AGX016,       "ITT AGX016"),
-       DEVICE( PICOP,          PICOP_PT86C52X, "PT86C52x Vesuvius"),
-       DEVICE( APPLE,          APPLE_BANDIT,   "Bandit"),
-       DEVICE( APPLE,          APPLE_GC,       "Grand Central"),
-       DEVICE( APPLE,          APPLE_HYDRA,    "Hydra"),
-       DEVICE( NEXGEN,         NEXGEN_82C501,  "82C501"),
-       DEVICE( QLOGIC,         QLOGIC_ISP1020, "ISP1020"),
-       DEVICE( QLOGIC,         QLOGIC_ISP1022, "ISP1022"),
-       DEVICE( CYRIX,          CYRIX_5510,     "5510"),
-       DEVICE( CYRIX,          CYRIX_PCI_MASTER,"PCI Master"),
-       DEVICE( CYRIX,          CYRIX_5520,     "5520"),
-       DEVICE( CYRIX,          CYRIX_5530_LEGACY,"5530 Kahlua Legacy"),
-       DEVICE( CYRIX,          CYRIX_5530_SMI, "5530 Kahlua SMI"),
-       DEVICE( CYRIX,          CYRIX_5530_IDE, "5530 Kahlua IDE"),
-       DEVICE( CYRIX,          CYRIX_5530_AUDIO,"5530 Kahlua Audio"),
-       DEVICE( CYRIX,          CYRIX_5530_VIDEO,"5530 Kahlua Video"),
-       DEVICE( LEADTEK,        LEADTEK_805,    "S3 805"),
-       DEVICE( CONTAQ,         CONTAQ_82C599,  "82C599"),
-       DEVICE( OLICOM,         OLICOM_OC3136,  "OC-3136/3137"),
-       DEVICE( OLICOM,         OLICOM_OC2315,  "OC-2315"),
-       DEVICE( OLICOM,         OLICOM_OC2325,  "OC-2325"),
-       DEVICE( OLICOM,         OLICOM_OC2183,  "OC-2183/2185"),
-       DEVICE( OLICOM,         OLICOM_OC2326,  "OC-2326"),
-       DEVICE( OLICOM,         OLICOM_OC6151,  "OC-6151/6152"),
-       DEVICE( SUN,            SUN_EBUS,       "EBUS"),
-       DEVICE( SUN,            SUN_HAPPYMEAL,  "Happy Meal"),
-       DEVICE( SUN,            SUN_PBM,        "PCI Bus Module"),
-       DEVICE( CMD,            CMD_640,        "640 (buggy)"),
-       DEVICE( CMD,            CMD_643,        "643"),
-       DEVICE( CMD,            CMD_646,        "646"),
-       DEVICE( CMD,            CMD_670,        "670"),
-       DEVICE( VISION,         VISION_QD8500,  "QD-8500"),
-       DEVICE( VISION,         VISION_QD8580,  "QD-8580"),
-       DEVICE( BROOKTREE,      BROOKTREE_848,  "Bt848"),
-       DEVICE( SIERRA,         SIERRA_STB,     "STB Horizon 64"),
-       DEVICE( ACC,            ACC_2056,       "2056"),
-       DEVICE( WINBOND,        WINBOND_83769,  "W83769F"),
-       DEVICE( WINBOND,        WINBOND_82C105, "SL82C105"),
-       DEVICE( WINBOND,        WINBOND_83C553, "W83C553"),
-       DEVICE( DATABOOK,       DATABOOK_87144, "DB87144"),
-       DEVICE( 3COM,           3COM_3C590,     "3C590 10bT"),
-       DEVICE( 3COM,           3COM_3C595TX,   "3C595 100bTX"),
-       DEVICE( 3COM,           3COM_3C595T4,   "3C595 100bT4"),
-       DEVICE( 3COM,           3COM_3C595MII,  "3C595 100b-MII"),
-       DEVICE( 3COM,           3COM_3C900TPO,  "3C900 10bTPO"),
-       DEVICE( 3COM,           3COM_3C900COMBO,"3C900 10b Combo"),
-       DEVICE( 3COM,           3COM_3C905TX,   "3C905 100bTX"),
-       DEVICE( SMC,            SMC_EPIC100,    "9432 TX"),
-       DEVICE( AL,             AL_M1445,       "M1445"),
-       DEVICE( AL,             AL_M1449,       "M1449"),
-       DEVICE( AL,             AL_M1451,       "M1451"),
-       DEVICE( AL,             AL_M1461,       "M1461"),
-       DEVICE( AL,             AL_M1489,       "M1489"),
-       DEVICE( AL,             AL_M1511,       "M1511"),
-       DEVICE( AL,             AL_M1513,       "M1513"),
-       DEVICE( AL,             AL_M1521,       "M1521"),
-       DEVICE( AL,             AL_M1523,       "M1523"),
-       DEVICE( AL,             AL_M1531,       "M1531 Aladdin IV"),
-       DEVICE( AL,             AL_M1533,       "M1533 Aladdin IV"),
-       DEVICE( AL,             AL_M4803,       "M4803"),
-       DEVICE( AL,             AL_M5219,       "M5219"),
-       DEVICE( AL,             AL_M5229,       "M5229 TXpro"),
-       DEVICE( SURECOM,        SURECOM_NE34,   "NE-34PCI LAN"),
-       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
-       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
-       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"),
-       DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"),
-       DEVICE( ASP,            ASP_ABP940,     "ABP940"),
-       DEVICE( ASP,            ASP_ABP940U,    "ABP940U"),
-       DEVICE( CERN,           CERN_SPSB_PMC,  "STAR/RD24 SCI-PCI (PMC)"),
-       DEVICE( CERN,           CERN_SPSB_PCI,  "STAR/RD24 SCI-PCI (PMC)"),
-       DEVICE( IMS,            IMS_8849,       "8849"),
-       DEVICE( TEKRAM2,        TEKRAM2_690c,   "DC690c"),
-       DEVICE( TUNDRA,         TUNDRA_CA91C042,"CA91C042 Universe"),
-       DEVICE( AMCC,           AMCC_MYRINET,   "Myrinet PCI (M2-PCI-32)"),
-       DEVICE( AMCC,           AMCC_S5933,     "S5933 PCI44"),
-       DEVICE( AMCC,           AMCC_S5933_HEPC3,"S5933 Traquair HEPC3"),
-       DEVICE( INTERG,         INTERG_1680,    "IGA-1680"),
-       DEVICE( INTERG,         INTERG_1682,    "IGA-1682"),
-       DEVICE( REALTEK,        REALTEK_8029,   "8029"),
-       DEVICE( REALTEK,        REALTEK_8129,   "8129"),
-       DEVICE( TRUEVISION,     TRUEVISION_T1000,"TARGA 1000"),
-       DEVICE( INIT,           INIT_320P,      "320 P"),
-       DEVICE( VIA,            VIA_82C505,     "VT 82C505"),
-       DEVICE( VIA,            VIA_82C561,     "VT 82C561"),
-       DEVICE( VIA,            VIA_82C586_1,   "VT 82C586 Apollo IDE"),
-       DEVICE( VIA,            VIA_82C576,     "VT 82C576 3V"),
-       DEVICE( VIA,            VIA_82C585,     "VT 82C585 Apollo VP1/VPX"),
-       DEVICE( VIA,            VIA_82C586_0,   "VT 82C586 Apollo ISA"),
-       DEVICE( VIA,            VIA_82C595,     "VT 82C595 Apollo VP2"),
-       DEVICE( VIA,            VIA_82C926,     "VT 82C926 Amazon"),
-       DEVICE( VIA,            VIA_82C416,     "VT 82C416MV"),
-       DEVICE( VIA,            VIA_82C595_97,  "VT 82C595 Apollo VP2/97"),
-       DEVICE( VIA,            VIA_82C586_2,   "VT 82C586 Apollo USB"),
-       DEVICE( VIA,            VIA_82C586_3,   "VT 82C586B Apollo ACPI"),
-       DEVICE( VORTEX,         VORTEX_GDT60x0, "GDT 60x0"),
-       DEVICE( VORTEX,         VORTEX_GDT6000B,"GDT 6000b"),
-       DEVICE( VORTEX,         VORTEX_GDT6x10, "GDT 6110/6510"),
-       DEVICE( VORTEX,         VORTEX_GDT6x20, "GDT 6120/6520"),
-       DEVICE( VORTEX,         VORTEX_GDT6530, "GDT 6530"),
-       DEVICE( VORTEX,         VORTEX_GDT6550, "GDT 6550"),
-       DEVICE( VORTEX,         VORTEX_GDT6x17, "GDT 6117/6517"),
-       DEVICE( VORTEX,         VORTEX_GDT6x27, "GDT 6127/6527"),
-       DEVICE( VORTEX,         VORTEX_GDT6537, "GDT 6537"),
-       DEVICE( VORTEX,         VORTEX_GDT6557, "GDT 6557"),
-       DEVICE( VORTEX,         VORTEX_GDT6x15, "GDT 6115/6515"),
-       DEVICE( VORTEX,         VORTEX_GDT6x25, "GDT 6125/6525"),
-       DEVICE( VORTEX,         VORTEX_GDT6535, "GDT 6535"),
-       DEVICE( VORTEX,         VORTEX_GDT6555, "GDT 6555"),
-       DEVICE( VORTEX,         VORTEX_GDT6x17RP,"GDT 6117RP/6517RP"),
-       DEVICE( VORTEX,         VORTEX_GDT6x27RP,"GDT 6127RP/6527RP"),
-       DEVICE( VORTEX,         VORTEX_GDT6537RP,"GDT 6537RP"),
-       DEVICE( VORTEX,         VORTEX_GDT6557RP,"GDT 6557RP"),
-       DEVICE( VORTEX,         VORTEX_GDT6x11RP,"GDT 6111RP/6511RP"),
-       DEVICE( VORTEX,         VORTEX_GDT6x21RP,"GDT 6121RP/6521RP"),
-       DEVICE( VORTEX,         VORTEX_GDT6x17RP1,"GDT 6117RP1/6517RP1"),
-       DEVICE( VORTEX,         VORTEX_GDT6x27RP1,"GDT 6127RP1/6527RP1"),
-       DEVICE( VORTEX,         VORTEX_GDT6537RP1,"GDT 6537RP1"),
-       DEVICE( VORTEX,         VORTEX_GDT6557RP1,"GDT 6557RP1"),
-       DEVICE( VORTEX,         VORTEX_GDT6x11RP1,"GDT 6111RP1/6511RP1"),
-       DEVICE( VORTEX,         VORTEX_GDT6x21RP1,"GDT 6121RP1/6521RP1"),
-       DEVICE( VORTEX,         VORTEX_GDT6x17RP2,"GDT 6117RP2/6517RP2"),
-       DEVICE( VORTEX,         VORTEX_GDT6x27RP2,"GDT 6127RP2/6527RP2"),
-       DEVICE( VORTEX,         VORTEX_GDT6537RP2,"GDT 6537RP2"),
-       DEVICE( VORTEX,         VORTEX_GDT6557RP2,"GDT 6557RP2"),
-       DEVICE( VORTEX,         VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"),
-       DEVICE( VORTEX,         VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"),
-       DEVICE( EF,             EF_ATM_FPGA,            "155P-MF1 (FPGA)"),
-       DEVICE( EF,             EF_ATM_ASIC,    "155P-MF1 (ASIC)"),
-       DEVICE( FORE,           FORE_PCA200PC, "PCA-200PC"),
-       DEVICE( FORE,           FORE_PCA200E,    "PCA-200E"),
-       DEVICE( IMAGINGTECH,    IMAGINGTECH_ICPCI, "MVC IC-PCI"),
-       DEVICE( PHILIPS,        PHILIPS_SAA7146,"SAA7146"),
-       DEVICE( PLX,            PLX_9060,       "PCI9060 i960 bridge"),
-       DEVICE( ALLIANCE,       ALLIANCE_PROMOTIO, "Promotion-6410"),
-       DEVICE( ALLIANCE,       ALLIANCE_PROVIDEO, "Provideo"),
-       DEVICE( ALLIANCE,       ALLIANCE_AT24,  "AT24"),
-       DEVICE( ALLIANCE,       ALLIANCE_AT3D,  "AT3D"),
-       DEVICE( VMIC,           VMIC_VME,       "VMIVME-7587"),
-       DEVICE( DIGI,           DIGI_RIGHTSWITCH, "RightSwitch SE-6"),
-       DEVICE( MUTECH,         MUTECH_MV1000,  "MV-1000"),
-       DEVICE( RENDITION,      RENDITION_VERITE,"Verite 1000"),
-       DEVICE( RENDITION,      RENDITION_VERITE2100,"Verite 2100"),
-       DEVICE( TOSHIBA,        TOSHIBA_601,    "Laptop"),
-       DEVICE( RICOH,          RICOH_RL5C466,  "RL5C466"),
-       DEVICE( ZEITNET,        ZEITNET_1221,   "1221"),
-       DEVICE( ZEITNET,        ZEITNET_1225,   "1225"),
-       DEVICE( OMEGA,          OMEGA_82C092G,  "82C092G"),
-       DEVICE( LITEON,         LITEON_LNE100TX,"LNE100TX"),
-       DEVICE( NP,             NP_PCI_FDDI,    "NP-PCI"),       
-       DEVICE( SPECIALIX,      SPECIALIX_XIO,  "XIO/SIO host"),
-       DEVICE( SPECIALIX,      SPECIALIX_RIO,  "RIO host"),
-       DEVICE( AURAVISION,     AURAVISION_VXP524,"VXP524"),
-       DEVICE( IKON,           IKON_10115,     "10115 Greensheet"),
-       DEVICE( IKON,           IKON_10117,     "10117 Greensheet"),
-       DEVICE( ZORAN,          ZORAN_36057,    "ZR36057"),
-       DEVICE( ZORAN,          ZORAN_36120,    "ZR36120"),
-       DEVICE( COMPEX,         COMPEX_ENET100VG4, "Readylink ENET100-VG4"),
-       DEVICE( COMPEX,         COMPEX_RL2000,  "ReadyLink 2000"),
-       DEVICE( RP,             RP8OCTA,        "RocketPort 8 Oct"),
-       DEVICE( RP,             RP8INTF,        "RocketPort 8 Intf"),
-       DEVICE( RP,             RP16INTF,       "RocketPort 16 Intf"),
-       DEVICE( RP,             RP32INTF,       "RocketPort 32 Intf"),
-       DEVICE( CYCLADES,       CYCLOM_Y_Lo,    "Cyclom-Y below 1Mbyte"),
-       DEVICE( CYCLADES,       CYCLOM_Y_Hi,    "Cyclom-Y above 1Mbyte"),
-       DEVICE( CYCLADES,       CYCLOM_Z_Lo,    "Cyclom-Z below 1Mbyte"),
-       DEVICE( CYCLADES,       CYCLOM_Z_Hi,    "Cyclom-Z above 1Mbyte"),
-       DEVICE( 3DFX,           3DFX_VOODOO,    "Voodoo"),
-       DEVICE( STALLION,       STALLION_ECHPCI832,"EasyConnection 8/32"),
-       DEVICE( STALLION,       STALLION_ECHPCI864,"EasyConnection 8/64"),
-       DEVICE( STALLION,       STALLION_EIOPCI,"EasyIO"),
-       DEVICE( SIGMADES,       SIGMADES_6425,  "REALmagic64/GX"),
-       DEVICE( OPTIBASE,       OPTIBASE_FORGE, "MPEG Forge"),
-       DEVICE( OPTIBASE,       OPTIBASE_FUSION,"MPEG Fusion"),
-       DEVICE( OPTIBASE,       OPTIBASE_VPLEX, "VideoPlex"),
-       DEVICE( OPTIBASE,       OPTIBASE_VPLEXCC,"VideoPlex CC"),
-       DEVICE( OPTIBASE,       OPTIBASE_VQUEST,"VideoQuest"),
-       DEVICE( ENSONIQ,        ENSONIQ_AUDIOPCI,"AudioPCI"),
-       DEVICE( PICTUREL,       PICTUREL_PCIVST,"PCIVST"),
-       DEVICE( NVIDIA_SGS,     NVIDIA_SGS_RIVA128,     "Riva 128"),
-       DEVICE( SYMPHONY,       SYMPHONY_101,   "82C101"),
-       DEVICE( TEKRAM,         TEKRAM_DC290,   "DC-290"),
-       DEVICE( 3DLABS,         3DLABS_300SX,   "GLINT 300SX"),
-       DEVICE( 3DLABS,         3DLABS_500TX,   "GLINT 500TX"),
-       DEVICE( 3DLABS,         3DLABS_DELTA,   "GLINT Delta"),
-       DEVICE( 3DLABS,         3DLABS_PERMEDIA,"PERMEDIA"),
-       DEVICE( AVANCE,         AVANCE_ALG2064, "ALG2064i"),
-       DEVICE( AVANCE,         AVANCE_2302,    "ALG-2302"),
-       DEVICE( NETVIN,         NETVIN_NV5000SC,"NV5000"),
-       DEVICE( S3,             S3_PLATO_PXS,   "PLATO/PX (system)"),
-       DEVICE( S3,             S3_ViRGE,       "ViRGE"),
-       DEVICE( S3,             S3_TRIO,        "Trio32/Trio64"),
-       DEVICE( S3,             S3_AURORA64VP,  "Aurora64V+"),
-       DEVICE( S3,             S3_TRIO64UVP,   "Trio64UV+"),
-       DEVICE( S3,             S3_ViRGE_VX,    "ViRGE/VX"),
-       DEVICE( S3,             S3_868, "Vision 868"),
-       DEVICE( S3,             S3_928,         "Vision 928-P"),
-       DEVICE( S3,             S3_864_1,       "Vision 864-P"),
-       DEVICE( S3,             S3_864_2,       "Vision 864-P"),
-       DEVICE( S3,             S3_964_1,       "Vision 964-P"),
-       DEVICE( S3,             S3_964_2,       "Vision 964-P"),
-       DEVICE( S3,             S3_968,         "Vision 968"),
-       DEVICE( S3,             S3_TRIO64V2,    "Trio64V2/DX or /GX"),
-       DEVICE( S3,             S3_PLATO_PXG,   "PLATO/PX (graphics)"),
-       DEVICE( S3,             S3_ViRGE_DXGX,  "ViRGE/DX or /GX"),
-       DEVICE( S3,             S3_ViRGE_GX2,   "ViRGE/GX2"),
-       DEVICE( S3,             S3_ViRGE_MX,    "ViRGE/MX"),
-       DEVICE( S3,             S3_ViRGE_MXP,   "ViRGE/MX+"),
-       DEVICE( S3,             S3_ViRGE_MXPMV, "ViRGE/MX+MV"),
-       DEVICE( INTEL,          INTEL_82375,    "82375EB"),
-       DEVICE( INTEL,          INTEL_82424,    "82424ZX Saturn"),
-       DEVICE( INTEL,          INTEL_82378,    "82378IB"),
-       DEVICE( INTEL,          INTEL_82430,    "82430ZX Aries"),
-       DEVICE( INTEL,          INTEL_82434,    "82434LX Mercury/Neptune"),
-       DEVICE( INTEL,          INTEL_82092AA_0,"82092AA PCMCIA bridge"),
-       DEVICE( INTEL,          INTEL_82092AA_1,"82092AA EIDE"),
-       DEVICE( INTEL,          INTEL_7116,     "SAA7116"),
-       DEVICE( INTEL,          INTEL_82596,    "82596"),
-       DEVICE( INTEL,          INTEL_82865,    "82865"),
-       DEVICE( INTEL,          INTEL_82557,    "82557"),
-       DEVICE( INTEL,          INTEL_82437,    "82437"),
-       DEVICE( INTEL,          INTEL_82371FB_0,"82371FB PIIX ISA"),
-       DEVICE( INTEL,          INTEL_82371FB_1,"82371FB PIIX IDE"),
-       DEVICE( INTEL,          INTEL_82371MX,  "430MX - 82371MX MPIIX"),
-       DEVICE( INTEL,          INTEL_82437MX,  "430MX - 82437MX MTSC"),
-       DEVICE( INTEL,          INTEL_82441,    "82441FX Natoma"),
-       DEVICE( INTEL,          INTEL_82439,    "82439HX Triton II"),
-       DEVICE( INTEL,          INTEL_82371SB_0,"82371SB PIIX3 ISA"),
-       DEVICE( INTEL,          INTEL_82371SB_1,"82371SB PIIX3 IDE"),
-       DEVICE( INTEL,          INTEL_82371SB_2,"82371SB PIIX3 USB"),
-       DEVICE( INTEL,          INTEL_82437VX,  "82437VX Triton II"),
-       DEVICE( INTEL,          INTEL_82439TX,  "82439TX"),
-       DEVICE( INTEL,          INTEL_82371AB_0,"82371AB PIIX4 ISA"),
-       DEVICE( INTEL,          INTEL_82371AB,  "82371AB PIIX4 IDE"),
-       DEVICE( INTEL,          INTEL_82371AB_2,"82371AB PIIX4 USB"),
-       DEVICE( INTEL,          INTEL_82371AB_3,"82371AB PIIX4 ACPI"),
-       DEVICE( INTEL,          INTEL_82443LX_0,"440LX - 82443LX PAC Host"),
-       DEVICE( INTEL,          INTEL_82443LX_1,"440LX - 82443LX PAC AGP"),
-       DEVICE( INTEL,          INTEL_P6,       "Orion P6"),
-       DEVICE( INTEL,          INTEL_82450GX,  "82450GX Orion P6"),
-       DEVICE( KTI,            KTI_ET32P2,     "ET32P2"),
-       DEVICE( ADAPTEC,        ADAPTEC_7850,   "AIC-7850"),
-       DEVICE( ADAPTEC,        ADAPTEC_7855,   "AIC-7855"),
-       DEVICE( ADAPTEC,        ADAPTEC_5800,   "AIC-5800"),
-       DEVICE( ADAPTEC,        ADAPTEC_7860,   "AIC-7860"),
-       DEVICE( ADAPTEC,        ADAPTEC_7861,   "AIC-7861"),
-       DEVICE( ADAPTEC,        ADAPTEC_7870,   "AIC-7870"),
-       DEVICE( ADAPTEC,        ADAPTEC_7871,   "AIC-7871"),
-       DEVICE( ADAPTEC,        ADAPTEC_7872,   "AIC-7872"),
-       DEVICE( ADAPTEC,        ADAPTEC_7873,   "AIC-7873"),
-       DEVICE( ADAPTEC,        ADAPTEC_7874,   "AIC-7874"),
-       DEVICE( ADAPTEC,        ADAPTEC_7895,   "AIC-7895U"),
-       DEVICE( ADAPTEC,        ADAPTEC_7880,   "AIC-7880U"),
-       DEVICE( ADAPTEC,        ADAPTEC_7881,   "AIC-7881U"),
-       DEVICE( ADAPTEC,        ADAPTEC_7882,   "AIC-7882U"),
-       DEVICE( ADAPTEC,        ADAPTEC_7883,   "AIC-7883U"),
-       DEVICE( ADAPTEC,        ADAPTEC_7884,   "AIC-7884U"),
-       DEVICE( ATRONICS,       ATRONICS_2015,  "IDE-2015PL"),
-       DEVICE( ARK,            ARK_STING,      "Stingray"),
-       DEVICE( ARK,            ARK_STINGARK,   "Stingray ARK 2000PV"),
-       DEVICE( ARK,            ARK_2000MT,     "2000MT")
-};
-
-
 /*
- * device_info[] is sorted so we can use binary search
+ * pci_malloc() returns initialized memory of size SIZE.  Can be
+ * used only while pci_init() is active.
  */
-struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev)
-{
-       int min = 0,
-           max = sizeof(dev_info)/sizeof(dev_info[0]) - 1;
-
-       for ( ; ; )
-       {
-           int i = (min + max) >> 1;
-           long order;
-
-           order = dev_info[i].vendor - (long) vendor;
-           if (!order)
-               order = dev_info[i].device - (long) dev;
-       
-           if (order < 0)
-           {
-                   min = i + 1;
-                   if ( min > max )
-                      return 0;
-                   continue;
-           }
-
-           if (order > 0)
-           {
-                   max = i - 1;
-                   if ( min > max )
-                      return 0;
-                   continue;
-           }
-
-           return & dev_info[ i ];
-       }
-}
-
-const char *pci_strclass (unsigned int class)
-{
-       switch (class >> 8) {
-             case PCI_CLASS_NOT_DEFINED:               return "Non-VGA device";
-             case PCI_CLASS_NOT_DEFINED_VGA:           return "VGA compatible device";
-
-             case PCI_CLASS_STORAGE_SCSI:              return "SCSI bus controller";
-             case PCI_CLASS_STORAGE_IDE:               return "IDE controller";
-             case PCI_CLASS_STORAGE_FLOPPY:            return "Floppy disk controller";
-             case PCI_CLASS_STORAGE_IPI:               return "IPI bus controller";
-             case PCI_CLASS_STORAGE_RAID:              return "RAID controller";
-             case PCI_CLASS_STORAGE_OTHER:             return "Unknown mass storage controller";
-
-             case PCI_CLASS_NETWORK_ETHERNET:          return "Ethernet controller";
-             case PCI_CLASS_NETWORK_TOKEN_RING:        return "Token ring network controller";
-             case PCI_CLASS_NETWORK_FDDI:              return "FDDI network controller";
-             case PCI_CLASS_NETWORK_ATM:               return "ATM network controller";
-             case PCI_CLASS_NETWORK_OTHER:             return "Network controller";
-
-             case PCI_CLASS_DISPLAY_VGA:               return "VGA compatible controller";
-             case PCI_CLASS_DISPLAY_XGA:               return "XGA compatible controller";
-             case PCI_CLASS_DISPLAY_OTHER:             return "Display controller";
-
-             case PCI_CLASS_MULTIMEDIA_VIDEO:          return "Multimedia video controller";
-             case PCI_CLASS_MULTIMEDIA_AUDIO:          return "Multimedia audio controller";
-             case PCI_CLASS_MULTIMEDIA_OTHER:          return "Multimedia controller";
-
-             case PCI_CLASS_MEMORY_RAM:                return "RAM memory";
-             case PCI_CLASS_MEMORY_FLASH:              return "FLASH memory";
-             case PCI_CLASS_MEMORY_OTHER:              return "Memory";
-
-             case PCI_CLASS_BRIDGE_HOST:               return "Host bridge";
-             case PCI_CLASS_BRIDGE_ISA:                return "ISA bridge";
-             case PCI_CLASS_BRIDGE_EISA:               return "EISA bridge";
-             case PCI_CLASS_BRIDGE_MC:                 return "MicroChannel bridge";
-             case PCI_CLASS_BRIDGE_PCI:                return "PCI bridge";
-             case PCI_CLASS_BRIDGE_PCMCIA:             return "PCMCIA bridge";
-             case PCI_CLASS_BRIDGE_NUBUS:              return "NuBus bridge";
-             case PCI_CLASS_BRIDGE_CARDBUS:            return "CardBus bridge";
-             case PCI_CLASS_BRIDGE_OTHER:              return "Bridge";
-
-             case PCI_CLASS_COMMUNICATION_SERIAL:      return "Serial controller";
-             case PCI_CLASS_COMMUNICATION_PARALLEL:    return "Parallel controller";
-             case PCI_CLASS_COMMUNICATION_OTHER:       return "Communication controller";
-
-             case PCI_CLASS_SYSTEM_PIC:                return "PIC";
-             case PCI_CLASS_SYSTEM_DMA:                return "DMA controller";
-             case PCI_CLASS_SYSTEM_TIMER:              return "Timer";
-             case PCI_CLASS_SYSTEM_RTC:                return "RTC";
-             case PCI_CLASS_SYSTEM_OTHER:              return "System peripheral";
-
-             case PCI_CLASS_INPUT_KEYBOARD:            return "Keyboard controller";
-             case PCI_CLASS_INPUT_PEN:                 return "Digitizer Pen";
-             case PCI_CLASS_INPUT_MOUSE:               return "Mouse controller";
-             case PCI_CLASS_INPUT_OTHER:               return "Input device controller";
-
-             case PCI_CLASS_DOCKING_GENERIC:           return "Generic Docking Station";
-             case PCI_CLASS_DOCKING_OTHER:             return "Docking Station";
-
-             case PCI_CLASS_PROCESSOR_386:             return "386";
-             case PCI_CLASS_PROCESSOR_486:             return "486";
-             case PCI_CLASS_PROCESSOR_PENTIUM:         return "Pentium";
-             case PCI_CLASS_PROCESSOR_ALPHA:           return "Alpha";
-             case PCI_CLASS_PROCESSOR_POWERPC:         return "Power PC";
-             case PCI_CLASS_PROCESSOR_CO:              return "Co-processor";
-
-             case PCI_CLASS_SERIAL_FIREWIRE:           return "FireWire (IEEE 1394)";
-             case PCI_CLASS_SERIAL_ACCESS:             return "ACCESS Bus";
-             case PCI_CLASS_SERIAL_SSA:                return "SSA";
-             case PCI_CLASS_SERIAL_USB:                return "USB Controller";
-             case PCI_CLASS_SERIAL_FIBER:              return "Fiber Channel";
-
-             default:                                  return "Unknown class";
-       }
-}
-
-
-const char *pci_strvendor(unsigned int vendor)
-{
-       switch (vendor) {
-             case PCI_VENDOR_ID_COMPAQ:        return "Compaq";
-             case PCI_VENDOR_ID_NCR:           return "NCR";
-             case PCI_VENDOR_ID_ATI:           return "ATI";
-             case PCI_VENDOR_ID_VLSI:          return "VLSI";
-             case PCI_VENDOR_ID_ADL:           return "Avance Logic";
-             case PCI_VENDOR_ID_NS:            return "NS";
-             case PCI_VENDOR_ID_TSENG:         return "Tseng'Lab";
-             case PCI_VENDOR_ID_WEITEK:        return "Weitek";
-             case PCI_VENDOR_ID_DEC:           return "DEC";
-             case PCI_VENDOR_ID_CIRRUS:        return "Cirrus Logic";
-             case PCI_VENDOR_ID_IBM:           return "IBM";
-             case PCI_VENDOR_ID_WD:            return "Western Digital";
-             case PCI_VENDOR_ID_AMD:           return "AMD";
-             case PCI_VENDOR_ID_TRIDENT:       return "Trident";
-             case PCI_VENDOR_ID_AI:            return "Acer Incorporated";
-             case PCI_VENDOR_ID_MATROX:        return "Matrox";
-             case PCI_VENDOR_ID_CT:            return "Chips & Technologies";
-             case PCI_VENDOR_ID_MIRO:          return "Miro";
-             case PCI_VENDOR_ID_NEC:           return "NEC";
-             case PCI_VENDOR_ID_FD:            return "Future Domain";
-             case PCI_VENDOR_ID_SI:            return "Silicon Integrated Systems";
-             case PCI_VENDOR_ID_HP:            return "Hewlett Packard";
-             case PCI_VENDOR_ID_PCTECH:        return "PCTECH";
-             case PCI_VENDOR_ID_DPT:           return "DPT";
-             case PCI_VENDOR_ID_OPTI:          return "OPTi";
-             case PCI_VENDOR_ID_SGS:           return "SGS Thomson";
-             case PCI_VENDOR_ID_BUSLOGIC:      return "BusLogic";
-             case PCI_VENDOR_ID_TI:            return "Texas Instruments";
-             case PCI_VENDOR_ID_OAK:           return "OAK";
-             case PCI_VENDOR_ID_WINBOND2:      return "Winbond";
-             case PCI_VENDOR_ID_MOTOROLA:      return "Motorola";
-             case PCI_VENDOR_ID_PROMISE:       return "Promise Technology";
-             case PCI_VENDOR_ID_N9:            return "Number Nine";
-             case PCI_VENDOR_ID_UMC:           return "UMC";
-             case PCI_VENDOR_ID_X:             return "X TECHNOLOGY";
-             case PCI_VENDOR_ID_PICOP:         return "PicoPower";
-             case PCI_VENDOR_ID_APPLE:         return "Apple";
-             case PCI_VENDOR_ID_NEXGEN:        return "Nexgen";
-             case PCI_VENDOR_ID_QLOGIC:        return "Q Logic";
-             case PCI_VENDOR_ID_CYRIX:         return "Cyrix";
-             case PCI_VENDOR_ID_LEADTEK:       return "Leadtek Research";
-             case PCI_VENDOR_ID_CONTAQ:        return "Contaq";
-             case PCI_VENDOR_ID_FOREX:         return "Forex";
-             case PCI_VENDOR_ID_OLICOM:        return "Olicom";
-             case PCI_VENDOR_ID_SUN:           return "Sun Microsystems";
-             case PCI_VENDOR_ID_CMD:           return "CMD";
-             case PCI_VENDOR_ID_VISION:        return "Vision";
-             case PCI_VENDOR_ID_BROOKTREE:     return "Brooktree";
-             case PCI_VENDOR_ID_SIERRA:        return "Sierra";
-             case PCI_VENDOR_ID_ACC:           return "ACC MICROELECTRONICS";
-             case PCI_VENDOR_ID_WINBOND:       return "Winbond";
-             case PCI_VENDOR_ID_DATABOOK:      return "Databook";
-             case PCI_VENDOR_ID_3COM:          return "3Com";
-             case PCI_VENDOR_ID_SMC:           return "SMC";
-             case PCI_VENDOR_ID_AL:            return "Acer Labs";
-             case PCI_VENDOR_ID_MITSUBISHI:    return "Mitsubishi";
-             case PCI_VENDOR_ID_SURECOM:       return "Surecom";
-             case PCI_VENDOR_ID_NEOMAGIC:      return "Neomagic";
-             case PCI_VENDOR_ID_ASP:           return "Advanced System Products";
-             case PCI_VENDOR_ID_CERN:          return "CERN";
-             case PCI_VENDOR_ID_NVIDIA:        return "NVidia";
-             case PCI_VENDOR_ID_IMS:           return "IMS";
-             case PCI_VENDOR_ID_TEKRAM2:       return "Tekram";
-             case PCI_VENDOR_ID_TUNDRA:        return "Tundra";
-             case PCI_VENDOR_ID_AMCC:          return "AMCC";
-             case PCI_VENDOR_ID_INTERG:        return "Intergraphics";
-             case PCI_VENDOR_ID_REALTEK:       return "Realtek";
-             case PCI_VENDOR_ID_TRUEVISION:    return "Truevision";
-             case PCI_VENDOR_ID_INIT:          return "Initio Corp";
-             case PCI_VENDOR_ID_VIA:           return "VIA Technologies";
-             case PCI_VENDOR_ID_VORTEX:        return "VORTEX";
-             case PCI_VENDOR_ID_EF:            return "Efficient Networks";
-             case PCI_VENDOR_ID_FORE:          return "Fore Systems";
-             case PCI_VENDOR_ID_IMAGINGTECH:   return "Imaging Technology";
-             case PCI_VENDOR_ID_PHILIPS:       return "Philips";
-             case PCI_VENDOR_ID_PLX:           return "PLX";
-             case PCI_VENDOR_ID_ALLIANCE:      return "Alliance";
-             case PCI_VENDOR_ID_VMIC:          return "VMIC";
-             case PCI_VENDOR_ID_DIGI:          return "Digi Intl.";
-             case PCI_VENDOR_ID_MUTECH:        return "Mutech";
-             case PCI_VENDOR_ID_RENDITION:     return "Rendition";
-             case PCI_VENDOR_ID_TOSHIBA:       return "Toshiba";
-             case PCI_VENDOR_ID_RICOH:         return "Ricoh";
-             case PCI_VENDOR_ID_ZEITNET:       return "ZeitNet";
-             case PCI_VENDOR_ID_OMEGA:         return "Omega Micro";
-             case PCI_VENDOR_ID_LITEON:        return "LiteOn";
-             case PCI_VENDOR_ID_NP:            return "Network Peripherals";
-             case PCI_VENDOR_ID_SPECIALIX:     return "Specialix";
-             case PCI_VENDOR_ID_AURAVISION:    return "Auravision";
-             case PCI_VENDOR_ID_IKON:          return "Ikon";
-             case PCI_VENDOR_ID_ZORAN:         return "Zoran";
-             case PCI_VENDOR_ID_COMPEX:        return "Compex";
-             case PCI_VENDOR_ID_RP:            return "Comtrol";
-             case PCI_VENDOR_ID_CYCLADES:      return "Cyclades";
-             case PCI_VENDOR_ID_3DFX:          return "3Dfx";
-             case PCI_VENDOR_ID_STALLION:      return "Stallion Technologies";
-             case PCI_VENDOR_ID_SIGMADES:      return "Sigma Designs";
-             case PCI_VENDOR_ID_OPTIBASE:      return "Optibase";
-             case PCI_VENDOR_ID_ENSONIQ:       return "Ensoniq";
-             case PCI_VENDOR_ID_PICTUREL:      return "Picture Elements";
-             case PCI_VENDOR_ID_NVIDIA_SGS:    return "NVidia/SGS Thomson";
-             case PCI_VENDOR_ID_SYMPHONY:      return "Symphony";
-             case PCI_VENDOR_ID_TEKRAM:        return "Tekram";
-             case PCI_VENDOR_ID_3DLABS:        return "3Dlabs";
-             case PCI_VENDOR_ID_AVANCE:        return "Avance";
-             case PCI_VENDOR_ID_NETVIN:        return "NetVin";
-             case PCI_VENDOR_ID_S3:            return "S3 Inc.";
-             case PCI_VENDOR_ID_INTEL:         return "Intel";
-             case PCI_VENDOR_ID_KTI:           return "KTI";
-             case PCI_VENDOR_ID_ADAPTEC:       return "Adaptec";
-             case PCI_VENDOR_ID_ATRONICS:      return "Atronics";
-             case PCI_VENDOR_ID_ARK:           return "ARK Logic";
-             default:                          return "Unknown vendor";
-       }
-}
-
-
-const char *pci_strdev(unsigned int vendor, unsigned int device)
+__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
 {
-       struct pci_dev_info *info;
+       void *mem;
 
-       info =  pci_lookup_dev(vendor, device);
-       return info ? info->name : "Unknown device";
+       mem = (void*) *mem_startp;
+       *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+       memset(mem, 0, size);
+       return mem;
 }
 
 
@@ -704,10 +55,10 @@ const char *pcibios_strerror(int error)
                case PCIBIOS_BAD_REGISTER_NUMBER:
                        return "BAD_REGISTER_NUMBER";
 
-               case PCIBIOS_SET_FAILED:
+                case PCIBIOS_SET_FAILED:          
                        return "SET_FAILED";
 
-               case PCIBIOS_BUFFER_TOO_SMALL:
+                case PCIBIOS_BUFFER_TOO_SMALL:    
                        return "BUFFER_TOO_SMALL";
 
                default:
@@ -717,198 +68,10 @@ const char *pcibios_strerror(int error)
 }
 
 
-/*
- * Convert some of the configuration space registers of the device at
- * address (bus,devfn) into a string (possibly several lines each).
- * The configuration string is stored starting at buf[len].  If the
- * string would exceed the size of the buffer (SIZE), 0 is returned.
- */
-static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
-{
-       unsigned long base;
-       unsigned int l, class_rev, bus, devfn;
-       unsigned short vendor, device, status;
-       unsigned char bist, latency, min_gnt, max_lat;
-       int reg, len = 0;
-       const char *str;
-
-       bus   = dev->bus->number;
-       devfn = dev->devfn;
-
-       pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev);
-       pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor);
-       pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device);
-       pcibios_read_config_word (bus, devfn, PCI_STATUS, &status);
-       pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist);
-       pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency);
-       pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt);
-       pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat);
-       if (len + 80 > size) {
-               return -1;
-       }
-       len += sprintf(buf + len, "  Bus %2d, device %3d, function %2d:\n",
-                      bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-       if (len + 80 > size) {
-               return -1;
-       }
-       len += sprintf(buf + len, "    %s: %s %s (rev %d).\n      ",
-                      pci_strclass(class_rev >> 8), pci_strvendor(vendor),
-                      pci_strdev(vendor, device), class_rev & 0xff);
-
-       if (!pci_lookup_dev(vendor, device)) {
-               len += sprintf(buf + len,
-                              "Vendor id=%x. Device id=%x.\n      ",
-                              vendor, device);
-       }
-
-       str = 0;        /* to keep gcc shut... */
-       switch (status & PCI_STATUS_DEVSEL_MASK) {
-             case PCI_STATUS_DEVSEL_FAST:   str = "Fast devsel.  "; break;
-             case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel.  "; break;
-             case PCI_STATUS_DEVSEL_SLOW:   str = "Slow devsel.  "; break;
-       }
-       if (len + strlen(str) > size) {
-               return -1;
-       }
-       len += sprintf(buf + len, str);
-
-       if (status & PCI_STATUS_FAST_BACK) {
-#              define fast_b2b_capable "Fast back-to-back capable.  "
-               if (len + strlen(fast_b2b_capable) > size) {
-                       return -1;
-               }
-               len += sprintf(buf + len, fast_b2b_capable);
-#              undef fast_b2b_capable
-       }
-
-       if (bist & PCI_BIST_CAPABLE) {
-#              define BIST_capable     "BIST capable.  "
-               if (len + strlen(BIST_capable) > size) {
-                       return -1;
-               }
-               len += sprintf(buf + len, BIST_capable);
-#              undef BIST_capable
-       }
-
-       if (dev->irq) {
-               if (len + 40 > size) {
-                       return -1;
-               }
-               len += sprintf(buf + len, "IRQ %d.  ", dev->irq);
-       }
-
-       if (dev->master) {
-               if (len + 80 > size) {
-                       return -1;
-               }
-               len += sprintf(buf + len, "Master Capable.  ");
-               if (latency)
-                 len += sprintf(buf + len, "Latency=%d.  ", latency);
-               else
-                 len += sprintf(buf + len, "No bursts.  ");
-               if (min_gnt)
-                 len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
-               if (max_lat)
-                 len += sprintf(buf + len, "Max Lat=%d.", max_lat);
-       }
-
-       for (reg = 0; reg < 6; reg++) {
-               if (len + 40 > size) {
-                       return -1;
-               }
-               pcibios_read_config_dword(bus, devfn,
-                               PCI_BASE_ADDRESS_0 + (reg << 2), &l);
-               if (l == 0xffffffff)
-                       base = 0;
-               else
-                       base = l;
-               if (!base)
-                       continue;
-
-               if (base & PCI_BASE_ADDRESS_SPACE_IO) {
-                       len += sprintf(buf + len,
-                                      "\n      I/O at 0x%lx [0x%lx].",
-                                      base & PCI_BASE_ADDRESS_IO_MASK,
-                                      dev->base_address[reg]);
-               } else {
-                       const char *pref, *type = "unknown";
-
-                       if (base & PCI_BASE_ADDRESS_MEM_PREFETCH) {
-                               pref = "P";
-                       } else {
-                               pref = "Non-p";
-                       }
-                       switch (base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
-                             case PCI_BASE_ADDRESS_MEM_TYPE_32:
-                               type = "32 bit"; break;
-                             case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-                               type = "20 bit"; break;
-                             case PCI_BASE_ADDRESS_MEM_TYPE_64:
-                               type = "64 bit";
-                               /* read top 32 bit address of base addr: */
-                               reg += 4;
-                               pcibios_read_config_dword(bus, devfn, reg, &l);
-                               base |= ((u64) l) << 32;
-                               break;
-                       }
-                       len += sprintf(buf + len,
-                                      "\n      %srefetchable %s memory at "
-                                      "0x%lx [0x%lx].", pref, type,
-                                      base & PCI_BASE_ADDRESS_MEM_MASK,
-                                      dev->base_address[reg]);
-               }
-       }
-
-       len += sprintf(buf + len, "\n");
-       return len;
-}
-
-
-/*
- * Return list of PCI devices as a character string for /proc/pci.
- * BUF is a buffer that is PAGE_SIZE bytes long.
- */
-int get_pci_list(char *buf)
-{
-       int nprinted, len, size;
-       struct pci_dev *dev;
-#      define MSG "\nwarning: page-size limit reached!\n"
-
-       /* reserve same for truncation warning message: */
-       size  = PAGE_SIZE - (strlen(MSG) + 1);
-       len   = sprintf(buf, "PCI devices found:\n");
-
-       for (dev = pci_devices; dev; dev = dev->next) {
-               nprinted = sprint_dev_config(dev, buf + len, size - len);
-               if (nprinted < 0) {
-                       return len + sprintf(buf + len, MSG);
-               }
-               len += nprinted;
-       }
-       return len;
-}
-
-
-/*
- * pci_malloc() returns initialized memory of size SIZE.  Can be
- * used only while pci_init() is active.
- */
-__initfunc(static void *pci_malloc(long size, unsigned long *mem_startp))
-{
-       void *mem;
-
-       mem = (void*) *mem_startp;
-       *mem_startp += (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
-       memset(mem, 0, size);
-       return mem;
-}
-
 unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
 {
        unsigned int devfn, l, max, class;
        unsigned char cmd, irq, tmp, hdr_type = 0;
-       struct pci_dev_info *info;
        struct pci_dev *dev;
        struct pci_bus *child;
        int reg;
@@ -939,17 +102,6 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                dev->vendor = l & 0xffff;
                dev->device = (l >> 16) & 0xffff;
 
-               /*
-                * Check to see if we know about this device and report
-                * a message at boot time.  This is the only way to
-                * learn about new hardware...
-                */
-               info = pci_lookup_dev(dev->vendor, dev->device);
-               if (!info) {
-                       printk("PCI: Warning: Unknown PCI device (%x:%x).  Please read include/linux/pci.h\n",
-                               dev->vendor, dev->device);
-               }
-
                /* non-destructively determine if device can be a master: */
                pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd);
                pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
@@ -1047,7 +199,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                         * has already been configured by the system.  If so,
                         * do not modify the configuration, merely note it.
                         */
-                       pcibios_read_config_dword(bus->number, devfn, 0x18, &buses);
+                       pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
                        if ((buses & 0xFFFFFF) != 0)
                          {
                            child->primary = buses & 0xFF;
@@ -1066,7 +218,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                              (((unsigned int)(child->primary)     <<  0) |
                               ((unsigned int)(child->secondary)   <<  8) |
                               ((unsigned int)(child->subordinate) << 16));
-                           pcibios_write_config_dword(bus->number, devfn, 0x18, buses);
+                           pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
                            /*
                             * Now we can scan all subordinate buses:
                             */
@@ -1078,7 +230,7 @@ unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
                            child->subordinate = max;
                            buses = (buses & 0xff00ffff)
                              | ((unsigned int)(child->subordinate) << 16);
-                           pcibios_write_config_dword(bus->number, devfn, 0x18, buses);
+                           pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
                          }
                        pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
                }
@@ -1114,16 +266,6 @@ __initfunc(unsigned long pci_init (unsigned long mem_start, unsigned long mem_en
        /* give BIOS a chance to apply platform specific fixes: */
        mem_start = pcibios_fixup(mem_start, mem_end);
 
-#ifdef DEBUG
-       {
-               int len = get_pci_list((char*)mem_start);
-               if (len) {
-                       ((char *) mem_start)[len] = '\0';
-                       printk("%s\n", (char *) mem_start);
-               }
-       }
-#endif
-
 #ifdef CONFIG_PCI_OPTIMIZE
        pci_quirks_init();
 #endif
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
new file mode 100644 (file)
index 0000000..a28cc8a
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ *     $Id: proc.c,v 1.1 1997/12/22 17:22:31 mj Exp $
+ *
+ *     Procfs interface for the PCI bus.
+ *
+ *     Copyright (c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+#define PCI_CFG_SPACE_SIZE 256
+
+static loff_t
+proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
+{
+       loff_t new;
+
+       switch (whence) {
+       case 0:
+               new = off;
+               break;
+       case 1:
+               new = file->f_pos + off;
+               break;
+       case 2:
+               new = PCI_CFG_SPACE_SIZE + off;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (new < 0 || new > PCI_CFG_SPACE_SIZE)
+               return -EINVAL;
+       return (file->f_pos = new);
+}
+
+static ssize_t
+proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+       struct inode *ino = file->f_dentry->d_inode;
+       struct proc_dir_entry *dp = ino->u.generic_ip;
+       struct pci_dev *dev = dp->data;
+       int pos = *ppos;
+       unsigned char bus = dev->bus->number;
+       unsigned char dfn = dev->devfn;
+       int cnt;
+
+       if (pos >= PCI_CFG_SPACE_SIZE)
+               return 0;
+       if (nbytes >= PCI_CFG_SPACE_SIZE)
+               nbytes = PCI_CFG_SPACE_SIZE;
+       if (pos + nbytes > PCI_CFG_SPACE_SIZE)
+               nbytes = PCI_CFG_SPACE_SIZE - pos;
+       cnt = nbytes;
+
+       if (!access_ok(VERIFY_WRITE, buf, cnt))
+               return -EINVAL;
+
+       if ((pos & 1) && cnt) {
+               unsigned char val;
+               pcibios_read_config_byte(bus, dfn, pos, &val);
+               __put_user(val, buf);
+               buf++;
+               pos++;
+               cnt--;
+       }
+
+       if ((pos & 3) && cnt > 2) {
+               unsigned short val;
+               pcibios_read_config_word(bus, dfn, pos, &val);
+               __put_user(cpu_to_le16(val), (unsigned short *) buf);
+               buf += 2;
+               pos += 2;
+               cnt -= 2;
+       }
+
+       while (cnt >= 4) {
+               unsigned int val;
+               pcibios_read_config_dword(bus, dfn, pos, &val);
+               __put_user(cpu_to_le32(val), (unsigned int *) buf);
+               buf += 4;
+               pos += 4;
+               cnt -= 4;
+       }
+
+       if (cnt >= 2) {
+               unsigned short val;
+               pcibios_read_config_word(bus, dfn, pos, &val);
+               __put_user(cpu_to_le16(val), (unsigned short *) buf);
+               buf += 2;
+               pos += 2;
+               cnt -= 2;
+       }
+
+       if (cnt) {
+               unsigned char val;
+               pcibios_read_config_byte(bus, dfn, pos, &val);
+               __put_user(val, buf);
+               buf++;
+               pos++;
+               cnt--;
+       }
+
+       *ppos = pos;
+       return nbytes;
+}
+
+static ssize_t
+proc_bus_pci_write(struct file *file, const char *buf, size_t nbytes, loff_t *ppos)
+{
+       struct inode *ino = file->f_dentry->d_inode;
+       struct proc_dir_entry *dp = ino->u.generic_ip;
+       struct pci_dev *dev = dp->data;
+       int pos = *ppos;
+       unsigned char bus = dev->bus->number;
+       unsigned char dfn = dev->devfn;
+       int cnt;
+
+       if (pos >= PCI_CFG_SPACE_SIZE)
+               return 0;
+       if (nbytes >= PCI_CFG_SPACE_SIZE)
+               nbytes = PCI_CFG_SPACE_SIZE;
+       if (pos + nbytes > PCI_CFG_SPACE_SIZE)
+               nbytes = PCI_CFG_SPACE_SIZE - pos;
+       cnt = nbytes;
+
+       if (!access_ok(VERIFY_READ, buf, cnt))
+               return -EINVAL;
+
+       if ((pos & 1) && cnt) {
+               unsigned char val;
+               __get_user(val, buf);
+               pcibios_write_config_byte(bus, dfn, pos, val);
+               buf++;
+               pos++;
+               cnt--;
+       }
+
+       if ((pos & 3) && cnt > 2) {
+               unsigned short val;
+               __get_user(val, (unsigned short *) buf);
+               pcibios_write_config_word(bus, dfn, pos, le16_to_cpu(val));
+               buf += 2;
+               pos += 2;
+               cnt -= 2;
+       }
+
+       while (cnt >= 4) {
+               unsigned int val;
+               __get_user(val, (unsigned int *) buf);
+               pcibios_write_config_dword(bus, dfn, pos, le32_to_cpu(val));
+               buf += 4;
+               pos += 4;
+               cnt -= 4;
+       }
+
+       if (cnt >= 2) {
+               unsigned short val;
+               __get_user(val, (unsigned short *) buf);
+               pcibios_write_config_word(bus, dfn, pos, le16_to_cpu(val));
+               buf += 2;
+               pos += 2;
+               cnt -= 2;
+       }
+
+       if (cnt) {
+               unsigned char val;
+               __get_user(val, buf);
+               pcibios_write_config_byte(bus, dfn, pos, val);
+               buf++;
+               pos++;
+               cnt--;
+       }
+
+       *ppos = pos;
+       return nbytes;
+}
+
+static struct file_operations proc_bus_pci_operations = {
+       proc_bus_pci_lseek,
+       proc_bus_pci_read,
+       proc_bus_pci_write,
+       NULL,           /* readdir */
+       NULL,           /* poll */
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       NULL,           /* no special open code */
+       NULL,           /* no special release code */
+       NULL            /* can't fsync */
+};
+
+static struct inode_operations proc_bus_pci_inode_operations = {
+       &proc_bus_pci_operations, /* default base directory file-ops */
+       NULL,                   /* create */
+       NULL,                   /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* readpage */
+       NULL,                   /* writepage */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL                    /* permission */
+};
+
+int
+get_pci_dev_info(char *buf, char **start, off_t pos, int count, int wr)
+{
+       struct pci_dev *dev = pci_devices;
+       off_t at = 0;
+       int len, i, cnt;
+
+       cnt = 0;
+       while (dev && count > cnt) {
+               len = sprintf(buf, "%02x%02x\t%04x%04x\t%x",
+                       dev->bus->number,
+                       dev->devfn,
+                       dev->vendor,
+                       dev->device,
+                       dev->irq);
+               for(i=0; i<6; i++)
+                       len += sprintf(buf+len,
+#if BITS_PER_LONG == 32
+                                               "\t%08lx",
+#else
+                                               "\t%016lx",
+#endif
+                                       dev->base_address[i]);
+               buf[len++] = '\n';
+               at += len;
+               if (at >= pos) {
+                       if (!*start) {
+                               *start = buf + (pos - (at - len));
+                               cnt = at - pos;
+                       } else
+                               cnt += len;
+                       buf += len;
+               }
+               dev = dev->next;
+       }
+       return (count > cnt) ? cnt : count;
+}
+
+static struct proc_dir_entry proc_pci_devices = {
+       PROC_BUS_PCI_DEVICES, 7, "devices",
+       S_IFREG | S_IRUGO, 1, 0, 0,
+       0, &proc_array_inode_operations,
+       get_pci_dev_info
+};
+
+__initfunc(void proc_bus_pci_init(void))
+{
+       struct proc_dir_entry *proc_pci;
+       struct pci_bus *bus;
+
+       if (!pcibios_present())
+               return;
+       proc_pci = create_proc_entry("pci", S_IFDIR, proc_bus);
+       proc_register(proc_pci, &proc_pci_devices);
+       for(bus = &pci_root; bus; bus = bus->next) {
+               char name[16];
+               struct proc_dir_entry *de;
+               struct pci_dev *dev;
+
+               sprintf(name, "%02x", bus->number);
+               de = create_proc_entry(name, S_IFDIR, proc_pci);
+               for(dev = bus->devices; dev; dev = dev->sibling) {
+                       struct proc_dir_entry *e;
+
+                       sprintf(name, "%02x.%x",
+                               PCI_SLOT(dev->devfn),
+                               PCI_FUNC(dev->devfn));
+                       e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, de);
+                       e->ops = &proc_bus_pci_inode_operations;
+                       e->data = dev;
+                       e->size = PCI_CFG_SPACE_SIZE;
+               }
+       }
+}
index 836d1aa669df38c7093fcadbb3ebddfdc4a04f9f..8b735fb5251187981e5b5df13a0343d822deb1d1 100644 (file)
@@ -58,7 +58,11 @@ static long read_polled(struct parport *port, char *buf,
        for (i=0; ; i++) {
                parport_write_control(port, parport_read_control(port) | 2); /* AutoFeed high */
                if (parport_wait_peripheral(port, 0x40, 0)) {
+#ifdef DEBUG_PROBE
+                       /* Some peripherals just time out when they've sent
+                          all their data.  */
                        printk("%s: read1 timeout.\n", port->name);
+#endif
                        parport_write_control(port, parport_read_control(port) & ~2);
                        break;
                }
@@ -68,36 +72,26 @@ static long read_polled(struct parport *port, char *buf,
                        printk("%s: read2 timeout.\n", port->name);
                        break;
                }
-               if (( i & 1) != 0) {
-                       Byte= (Byte | z<<4);
+               if ((i & 1) != 0) {
+                       Byte |= (z<<4);
                        if (temp) 
                                *(temp++) = Byte; 
                        if (count++ == length)
                                temp = NULL;
                        /* Does the error line indicate end of data? */
-                       if ((parport_read_status(port) & LP_PERRORP) == LP_PERRORP) 
+                       if ((parport_read_status(port) & LP_PERRORP) == 
+                           LP_PERRORP) 
                                break;
-               } else Byte=z;
+               } else 
+                       Byte=z;
        }
        read_terminate(port);
        return count; 
 }
 
-static struct wait_queue *wait_q;
-
-static void wakeup(void *ref)
-{
-       struct pardevice **dev = (struct pardevice **)ref;
-       
-       if (!waitqueue_active || parport_claim(*dev))
-               return;
-
-       wake_up(&wait_q);
-}
-
 int parport_probe(struct parport *port, char *buffer, int len)
 {
-       struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, wakeup, NULL, PARPORT_DEV_TRAN, &dev);
+       struct pardevice *dev = parport_register_device(port, "IEEE 1284 probe", NULL, NULL, NULL, PARPORT_DEV_TRAN, &dev);
 
        int result = 0;
 
@@ -106,9 +100,7 @@ int parport_probe(struct parport *port, char *buffer, int len)
                return -EINVAL;
        }
 
-       init_waitqueue (&wait_q);
-       if (parport_claim(dev))
-               sleep_on(&wait_q);
+       parport_claim_or_block(dev);
 
        switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
        case 1:
@@ -233,6 +225,7 @@ void parport_probe_one(struct parport *port)
        char *buffer = kmalloc(2048, GFP_KERNEL);
        int r;
 
+       MOD_INC_USE_COUNT;
        port->probe_info.model = "Unknown device";
        port->probe_info.mfr = "Unknown vendor";
        port->probe_info.description = NULL;
@@ -261,17 +254,16 @@ void parport_probe_one(struct parport *port)
                pretty_print(port);
        }
        kfree(buffer);
+       MOD_DEC_USE_COUNT;
 }
 
 #if MODULE
 int init_module(void)
 {
        struct parport *p;
-       MOD_INC_USE_COUNT;
        for (p = parport_enumerate(); p; p = p->next) 
                parport_probe_one(p);
        parport_probe_hook = &parport_probe_one;
-       MOD_DEC_USE_COUNT;
        return 0;
 }
 
index 6eccb24c75dbc081a88f22a1d0a6cd12749f838d..ba1753147fb6010bfed446a76ffeb9250e85be77 100644 (file)
@@ -625,7 +625,8 @@ static inline void NCR5380_all_init (void) {
  */
 
 
-static int probe_irq __initdata ;
+static int probe_irq __initdata = 0;
+
 __initfunc(static void probe_intr (int irq, void *dev_id, struct pt_regs * regs)) {
     probe_irq = irq;
 };
index cf5a87814d31366d30a3cf391cb9ae6590a08260..243be1eca8ac0f3dd9286b27bd5e087e57c56382 100644 (file)
@@ -503,6 +503,32 @@ scsi_register_device(struct Scsi_Device_Template * sdpnt)
     return 0;
 }
 
+/*
+ * Why is this a seperate function?  Because the kernel_thread code
+ * effectively does a fork, and there is a builtin exit() call when
+ * the child returns.   The difficulty is that scsi_init() is
+ * marked __initfunc(), which means the memory is unmapped after bootup
+ * is complete, which means that the thread's exit() call gets wiped.
+ *
+ * The lesson is to *NEVER*, *NEVER* call kernel_thread() from an
+ * __initfunc() function, if that function could ever return.
+ */
+static void launch_error_handler_thread(struct Scsi_Host * shpnt)
+{
+            struct semaphore sem = MUTEX_LOCKED;
+            
+            shpnt->eh_notify = &sem;
+
+            kernel_thread((int (*)(void *))scsi_error_handler, 
+                          (void *) shpnt, 0);
+            /*
+             * Now wait for the kernel error thread to initialize itself
+             * as it might be needed when we scan the bus.
+             */
+            down (&sem);
+            shpnt->eh_notify = NULL;
+}
+
 __initfunc(unsigned int scsi_init(void))
 {
     static int called = 0;
@@ -559,18 +585,7 @@ __initfunc(unsigned int scsi_init(void))
          */
         if( shpnt->hostt->use_new_eh_code )
         {
-            struct semaphore sem = MUTEX_LOCKED;
-            
-            shpnt->eh_notify = &sem;
-
-            kernel_thread((int (*)(void *))scsi_error_handler, 
-                          (void *) shpnt, 0);
-            /*
-             * Now wait for the kernel error thread to initialize itself
-             * as it might be needed when we scan the bus.
-             */
-            down (&sem);
-            shpnt->eh_notify = NULL;
+            launch_error_handler_thread(shpnt);
         }
     }
     
index 9b6fa5c1258eeb89093c767f2fbb0b0196cbbad2..592006f09a83e137f08bdac5902015c691835bdd 100644 (file)
@@ -350,7 +350,7 @@ int audio_read(int dev, struct fileinfo *file, char *buf, int count)
 int audio_ioctl(int dev, struct fileinfo *file_must_not_be_used,
                unsigned int cmd, caddr_t arg)
 {
-       int val = 0, info, count;
+       int val, count;
        unsigned long flags;
        struct dma_buffparms *dmap;
 
@@ -419,16 +419,16 @@ int audio_ioctl(int dev, struct fileinfo *file_must_not_be_used,
                        return 0;
 
                case SNDCTL_DSP_GETCAPS:
-                               info = 1 | DSP_CAP_MMAP;        /* Revision level of this ioctl() */
+                               val = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */
                                if (audio_devs[dev]->flags & DMA_DUPLEX &&
                                        audio_devs[dev]->open_mode == OPEN_READWRITE)
-                                       info |= DSP_CAP_DUPLEX;
+                                       val |= DSP_CAP_DUPLEX;
                                if (audio_devs[dev]->coproc)
-                                       info |= DSP_CAP_COPROC;
+                                       val |= DSP_CAP_COPROC;
                                if (audio_devs[dev]->d->local_qlen)     /* Device has hidden buffers */
-                                       info |= DSP_CAP_BATCH;
+                                       val |= DSP_CAP_BATCH;
                                if (audio_devs[dev]->d->trigger)        /* Supports SETTRIGGER */
-                                       info |= DSP_CAP_TRIGGER;
+                                       val |= DSP_CAP_TRIGGER;
                                break;
                        
                case SOUND_PCM_WRITE_RATE:
index 205b7ea341b178c59584890e1d9da4d5490a0a6c..2f68a62f3611f70310eaefff6623438c2e3d31be 100644 (file)
@@ -136,7 +136,8 @@ MIX_ENT(SOUND_MIXER_LINE3,  0x00, 0, 0, 0x00, 0, 0)
 };
 
 #ifdef __SGNXPRO__
-static mixer_tab sgnxpro_mix = {
+#if 0
+static mixer_tab sgnxpro_mix = {       /* not used anywhere */
 MIX_ENT(SOUND_MIXER_VOLUME,    0x22, 7, 4, 0x22, 3, 4),
 MIX_ENT(SOUND_MIXER_BASS,      0x46, 2, 3, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,    0x44, 2, 3, 0x00, 0, 0),
@@ -153,6 +154,7 @@ MIX_ENT(SOUND_MIXER_IGAIN,  0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_OGAIN,     0x00, 0, 0, 0x00, 0, 0)
 };
 #endif
+#endif
 
 static mixer_tab sb16_mix = {
 MIX_ENT(SOUND_MIXER_VOLUME,    0x30, 7, 5, 0x31, 7, 5),
index ee8409f175b776bc4790e2a983904ca7c4ed9281..ff11018a2b19b1311801b93863282126607c50d3 100644 (file)
@@ -106,7 +106,7 @@ static struct synth_info softsyn_info =
 
 static struct softsyn_devc sdev_info =
 {0};
-static softsyn_devc   *devc = &sdev_info;
+softsyn_devc   *devc = &sdev_info;     /* used in softoss_rs.c */
 
 static struct voice_alloc_info *voice_alloc;
 
index 3e78be073fd2f495461d44d0d5d6d325f477bd2d..37daaa3c367336d9e730c2e8d76026e55f475596 100644 (file)
@@ -71,7 +71,7 @@ unsigned long adfs_inode_objid (struct inode *inode)
        return inode->u.adfs_i.file_id;
 }
 
-unsigned int adfs_bmap (struct inode *inode, int block)
+int adfs_bmap (struct inode *inode, int block)
 {
        struct super_block *sb = inode->i_sb;
        unsigned int blk;
index 47675bf29da79b51350a893f3d1f278cfa5b58b5..71106655b7cc560d14aebca00dbb21cc19916820 100644 (file)
 #include <linux/sched.h>
 
 /*
- * The follow_symlink operation must dput() the base.
+ * The follow_link operation is special: it must behave as a no-op
+ * so that a bad root inode can at least be unmounted. To do this
+ * we must dput() the base and return the dentry with a dget().
  */
 static struct dentry * bad_follow_link(struct dentry *dent, struct dentry *base)
 {
        dput(base);
-       return ERR_PTR(-EIO);
+       return dget(dent);
 }
 
 static int return_EIO(void)
@@ -62,7 +64,9 @@ struct inode_operations bad_inode_ops =
        EIO_ERROR,              /* bmap */
        EIO_ERROR,              /* truncate */
        EIO_ERROR,              /* permission */
-       EIO_ERROR               /* smap */
+       EIO_ERROR,              /* smap */
+       EIO_ERROR,              /* update_page */
+       EIO_ERROR               /* revalidate */
 };
 
 
index cb7b843b055203cb960febebfca3110827f1df97..996b42279823d71fca1bd3c0b6afcc2f13e04450 100644 (file)
 #include <linux/init.h>
 #include <linux/nls.h>
 
+#ifdef CONFIG_CODA_FS
+extern int init_coda_fs(void);
+#endif
+
 extern void device_setup(void);
 extern void binfmt_setup(void);
 extern void free_initmem(void);
index 77421855f30dda33c41942147222379afb8ba08e..8d75f3b85d4419e957836c8045e0c2d02b83c4d4 100644 (file)
@@ -535,11 +535,6 @@ void nfs_renew_times(struct dentry * dentry)
        }
 }
 
-static void nfs_set_fh(struct dentry *dentry, struct nfs_fh *fhandle)
-{
-       *((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
-}
-
 static int nfs_lookup(struct inode *dir, struct dentry * dentry)
 {
        struct inode *inode;
@@ -574,8 +569,7 @@ static int nfs_lookup(struct inode *dir, struct dentry * dentry)
                goto no_entry;
        if (!error) {
                error = -EACCES;
-               nfs_set_fh(dentry, &fhandle);
-               inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
+               inode = nfs_fhget(dentry, &fhandle, &fattr);
                if (inode) {
 #ifdef NFS_PARANOIA
 if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
@@ -609,8 +603,7 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
        struct inode *inode;
        int error = -EACCES;
 
-       nfs_set_fh(dentry, fhandle);
-       inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+       inode = nfs_fhget(dentry, fhandle, fattr);
        if (inode) {
 #ifdef NFS_PARANOIA
 if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
index 54e0ceabee6d8f31f786c151024eee0cf0a72c87..8300fee670301aab2ccc5f261847758fbcbab36d 100644 (file)
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#define CONFIG_NFS_SNAPSHOT 1
 #define NFSDBG_FACILITY                NFSDBG_VFS
 #define NFS_PARANOIA 1
 
+static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
+
 static void nfs_read_inode(struct inode *);
 static void nfs_put_inode(struct inode *);
 static void nfs_delete_inode(struct inode *);
@@ -190,6 +193,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
        int                     tcp;
        struct sockaddr_in      srvaddr;
        struct rpc_timeout      timeparms;
+       struct nfs_fattr        fattr;
 
        MOD_INC_USE_COUNT;
        if (!data)
@@ -274,7 +278,10 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
                goto out_no_fh;
        *root_fh = data->root;
 
-       root_inode = nfs_fhget(sb, &data->root, NULL);
+       if (nfs_proc_getattr(server, root_fh, &fattr) != 0)
+               goto out_no_fattr;
+
+       root_inode = __nfs_fhget(sb, &fattr);
        if (!root_inode)
                goto out_no_root;
        sb->s_root = d_alloc_root(root_inode, NULL);
@@ -295,6 +302,11 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
 out_no_root:
        printk("nfs_read_super: get root inode failed\n");
        iput(root_inode);
+       goto out_free_fh;
+
+out_no_fattr:
+       printk("nfs_read_super: get root fattr failed\n");
+out_free_fh:
        kfree(root_fh);
 out_no_fh:
        rpciod_down();
@@ -383,43 +395,111 @@ dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_count);
        }
 }
 
+/*
+ * Fill in inode information from the fattr.
+ */
+static void
+nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+       /*
+        * Check whether the mode has been set, as we only want to
+        * do this once. (We don't allow inodes to change types.)
+        */
+       if (inode->i_mode == 0) {
+               inode->i_mode = fattr->mode;
+               if (S_ISREG(inode->i_mode))
+                       inode->i_op = &nfs_file_inode_operations;
+               else if (S_ISDIR(inode->i_mode))
+                       inode->i_op = &nfs_dir_inode_operations;
+               else if (S_ISLNK(inode->i_mode))
+                       inode->i_op = &nfs_symlink_inode_operations;
+               else if (S_ISCHR(inode->i_mode)) {
+                       inode->i_op = &chrdev_inode_operations;
+                       inode->i_rdev = to_kdev_t(fattr->rdev);
+               } else if (S_ISBLK(inode->i_mode)) {
+                       inode->i_op = &blkdev_inode_operations;
+                       inode->i_rdev = to_kdev_t(fattr->rdev);
+               } else if (S_ISFIFO(inode->i_mode))
+                       init_fifo(inode);
+               else
+                       inode->i_op = NULL;
+               /*
+                * Preset the size and mtime, as there's no need
+                * to invalidate the caches.
+                */ 
+               inode->i_size  = fattr->size;
+               inode->i_mtime = fattr->mtime.seconds;
+               NFS_OLDMTIME(inode) = fattr->mtime.seconds;
+       }
+       nfs_refresh_inode(inode, fattr);
+}
+
 /*
  * This is our own version of iget that looks up inodes by file handle
  * instead of inode number.  We use this technique instead of using
  * the vfs read_inode function because there is no way to pass the
  * file handle or current attributes into the read_inode function.
  *
+ * We provide a special check for NetApp .snapshot directories to avoid
+ * inode aliasing problems. All snapshot inodes are anonymous (unhashed).
+ */
+struct inode *
+nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
+                                struct nfs_fattr *fattr)
+{
+       struct super_block *sb = dentry->d_sb;
+
+       dprintk("NFS: nfs_fhget(%s/%s fileid=%d)\n",
+               dentry->d_parent->d_name.name, dentry->d_name.name,
+               fattr->fileid);
+
+       /* Install the filehandle in the dentry */
+       *((struct nfs_fh *) dentry->d_fsdata) = *fhandle;
+
+#ifdef CONFIG_NFS_SNAPSHOT
+       /*
+        * Check for NetApp snapshot dentries, and get an 
+        * unhashed inode to avoid aliasing problems.
+        */
+       if ((dentry->d_parent->d_inode->u.nfs_i.flags & NFS_IS_SNAPSHOT) ||
+           (IS_ROOT(dentry->d_parent) && dentry->d_name.len == 9 &&
+            memcmp(dentry->d_name.name, ".snapshot", 9) == 0)) {
+               struct inode *inode = get_empty_inode();
+               if (!inode)
+                       goto out;       
+               inode->i_sb = sb;
+               inode->i_dev = sb->s_dev;
+               inode->i_ino = fattr->fileid;
+               nfs_read_inode(inode);
+               nfs_fill_inode(inode, fattr);
+               inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT;
+               dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino);
+       out:
+               return inode;
+       }
+#endif
+       return __nfs_fhget(sb, fattr);
+}
+
+/*
+ * Look up the inode by super block and fattr->fileid.
+ *
  * Note carefully the special handling of busy inodes (i_count > 1).
- * With the Linux 2.1.xx dcache all inodes except hard links must
+ * With the kernel 2.1.xx dcache all inodes except hard links must
  * have i_count == 1 after iget(). Otherwise, it indicates that the
  * server has reused a fileid (i_ino) and we have a stale inode.
  */
-struct inode *
-nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle,
-                                 struct nfs_fattr *fattr)
+static struct inode *
+__nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
 {
-       int error, max_count;
-       struct inode *inode = NULL;
-       struct nfs_fattr newfattr;
-
-       if (!sb)
-               goto out_bad_args;
-       if (!fattr) {
-               fattr = &newfattr;
-               error = nfs_proc_getattr(&sb->u.nfs_sb.s_server, fhandle,fattr);
-               if (error)
-                       goto out_bad_attr;
-       }
+       struct inode *inode;
+       int max_count;
 
 retry:
        inode = iget(sb, fattr->fileid);
        if (!inode)
                goto out_no_inode;
-#ifdef NFS_PARANOIA
-if (inode->i_dev != sb->s_dev)
-printk("nfs_fhget: impossible\n");
-#endif
-
+       /* N.B. This should be impossible ... */
        if (inode->i_ino != fattr->fileid)
                goto out_bad_id;
 
@@ -434,19 +514,20 @@ printk("nfs_fhget: impossible\n");
         */
        max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink;
        if (inode->i_count > max_count) {
-printk("nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
+printk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
 inode->i_ino, inode->i_count, inode->i_nlink);
                nfs_free_dentries(inode);
                if (inode->i_count > max_count) {
-printk("nfs_fhget: inode %ld still busy, i_count=%d\n",
+printk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
 inode->i_ino, inode->i_count);
                        if (!list_empty(&inode->i_dentry)) {
                                struct dentry *dentry;
                                dentry = list_entry(inode->i_dentry.next,
                                                 struct dentry, d_alias);
-printk("nfs_fhget: killing %s/%s filehandle\n",
+printk("__nfs_fhget: killing %s/%s filehandle\n",
 dentry->d_parent->d_name.name, dentry->d_name.name);
-                               memset(dentry->d_fsdata, 0, sizeof(*fhandle));
+                               memset(dentry->d_fsdata, 0, 
+                                       sizeof(struct nfs_fh));
                        } else
                                printk("NFS: inode %ld busy, no aliases?\n",
                                        inode->i_ino);
@@ -456,56 +537,18 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
                iput(inode);
                goto retry;
        }
-
-       /*
-        * Check whether the mode has been set, as we only want to
-        * do this once. (We don't allow inodes to change types.)
-        */
-       if (inode->i_mode == 0) {
-               inode->i_mode = fattr->mode;
-               if (S_ISREG(inode->i_mode))
-                       inode->i_op = &nfs_file_inode_operations;
-               else if (S_ISDIR(inode->i_mode))
-                       inode->i_op = &nfs_dir_inode_operations;
-               else if (S_ISLNK(inode->i_mode))
-                       inode->i_op = &nfs_symlink_inode_operations;
-               else if (S_ISCHR(inode->i_mode)) {
-                       inode->i_op = &chrdev_inode_operations;
-                       inode->i_rdev = to_kdev_t(fattr->rdev);
-               } else if (S_ISBLK(inode->i_mode)) {
-                       inode->i_op = &blkdev_inode_operations;
-                       inode->i_rdev = to_kdev_t(fattr->rdev);
-               } else if (S_ISFIFO(inode->i_mode))
-                       init_fifo(inode);
-               else
-                       inode->i_op = NULL;
-               /*
-                * Preset the size and mtime, as there's no need
-                * to invalidate the caches.
-                */ 
-               inode->i_size  = fattr->size;
-               inode->i_mtime = fattr->mtime.seconds;
-               NFS_OLDMTIME(inode) = fattr->mtime.seconds;
-       }
-       nfs_refresh_inode(inode, fattr);
-       dprintk("NFS: fhget(%x/%ld ct=%d)\n",
-               inode->i_dev, inode->i_ino,
-               inode->i_count);
+       nfs_fill_inode(inode, fattr);
+       dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n",
+               inode->i_dev, inode->i_ino, inode->i_count);
 
 out:
        return inode;
 
-out_bad_args:
-       printk("nfs_fhget: super block is NULL\n");
-       goto out;
-out_bad_attr:
-       printk("nfs_fhget: getattr error = %d\n", -error);
-       goto out;
 out_no_inode:
-       printk("nfs_fhget: iget failed\n");
+       printk("__nfs_fhget: iget failed\n");
        goto out;
 out_bad_id:
-       printk("nfs_fhget: unexpected inode from iget\n");
+       printk("__nfs_fhget: unexpected inode from iget\n");
        goto out;
 }
 
index 8879e02a853caa947765e7a80e7b259e0940015b..216aafb80882af1b5a6f364e1be64736bf107f0f 100644 (file)
@@ -406,8 +406,9 @@ nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res)
 
                len = ntohl(*p++);
                if ((p + QUADLEN(len) + 3) > end) {
-                       printk(KERN_NOTICE
-                               "NFS: short packet in readdir reply!\n");
+                       printk(KERN_WARNING "NFS: short readdir reply! "
+                               "nr=%d, slots=%d, len=%d\n",
+                               nr, (end - p), len);
                        break;
                }
                if (len > NFS_MAXNAMLEN) {
index 8f2e40711cd5caa6d3ba48dcb4b0b8c52e01b93e..e4bf46f41760356acbd46a6987cd46b4515d44c8 100644 (file)
@@ -46,7 +46,6 @@
  * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
  */
 
-#define NFS_NEED_XDR_TYPES
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/malloc.h>
@@ -372,8 +371,8 @@ static inline struct nfs_wreq *
 create_write_request(struct dentry *dentry, struct inode *inode,
                struct page *page, unsigned int offset, unsigned int bytes)
 {
-       struct nfs_wreq *wreq;
        struct rpc_clnt *clnt = NFS_CLIENT(inode);
+       struct nfs_wreq *wreq;
        struct rpc_task *task;
 
        dprintk("NFS:      create_write_request(%s/%s, %ld+%d)\n",
@@ -424,7 +423,7 @@ out_fail:
  * Schedule a writeback RPC call.
  * If the server is congested, don't add to our backlog of queued
  * requests but call it synchronously.
- * The function returns true if the page has been unlocked as the
+ * The function returns false if the page has been unlocked as the
  * consequence of a synchronous write call.
  *
  * FIXME: Here we could walk the inode's lock list to see whether the
@@ -642,15 +641,16 @@ nfs_flush_pages(struct inode *inode, pid_t pid, off_t offset, off_t len,
 
        req = head = NFS_WRITEBACK(inode);
        while (req != NULL) {
-               dprintk("NFS: %4d nfs_flush inspect %x/%ld @%ld fl %x\n",
-                               req->wb_task.tk_pid,
-                               req->wb_inode->i_dev, req->wb_inode->i_ino,
-                               req->wb_page->offset, req->wb_flags);
+               dprintk("NFS: %4d nfs_flush inspect %s/%s @%ld fl %x\n",
+                       req->wb_task.tk_pid,
+                       req->wb_dentry->d_parent->d_name.name,
+                       req->wb_dentry->d_name.name,
+                       req->wb_page->offset, req->wb_flags);
+
                rqoffset = req->wb_page->offset + req->wb_offset;
                rqend    = rqoffset + req->wb_bytes;
-               
-               if (rqoffset < end && offset < rqend
-                        && (pid == 0 || req->wb_pid == pid)) {
+               if (rqoffset < end && offset < rqend &&
+                   (pid == 0 || req->wb_pid == pid)) {
                        if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) {
 #ifdef NFS_DEBUG_VERBOSE
 printk("nfs_flush: flushing inode=%ld, %d @ %lu\n",
@@ -669,12 +669,24 @@ req->wb_inode->i_ino, req->wb_bytes, rqoffset);
        return last;
 }
 
+/*
+ * Cancel a write request. We always mark it cancelled,
+ * but if it's already in progress there's no point in
+ * calling rpc_exit, and we don't want to overwrite the
+ * tk_status field.
+ */ 
+static void
+nfs_cancel_request(struct nfs_wreq *req)
+{
+       req->wb_flags |= NFS_WRITE_CANCELLED;
+       if (!WB_INPROGRESS(req)) {
+               rpc_exit(&req->wb_task, 0);
+               rpc_wake_up_task(&req->wb_task);
+       }
+}
+
 /*
  * Cancel all writeback requests, both pending and in progress.
- *
- * N.B. This doesn't seem to wake up the tasks -- are we sure
- * they will eventually complete? Also, this could overwrite a
- * failed status code from an already-completed task.
  */
 static void
 nfs_cancel_dirty(struct inode *inode, pid_t pid)
@@ -683,11 +695,8 @@ nfs_cancel_dirty(struct inode *inode, pid_t pid)
 
        req = head = NFS_WRITEBACK(inode);
        while (req != NULL) {
-               /* N.B. check for task already finished? */
-               if (pid == 0 || req->wb_pid == pid) {
-                       req->wb_flags |= NFS_WRITE_CANCELLED;
-                       rpc_exit(&req->wb_task, 0);
-               }
+               if (pid == 0 || req->wb_pid == pid)
+                       nfs_cancel_request(req);
                if ((req = WB_NEXT(req)) == head)
                        break;
        }
@@ -708,8 +717,7 @@ nfs_flush_dirty_pages(struct inode *inode, pid_t pid, off_t offset, off_t len)
        int result = 0, cancel = 0;
 
        dprintk("NFS:      flush_dirty_pages(%x/%ld for pid %d %ld/%ld)\n",
-                               inode->i_dev, inode->i_ino, current->pid,
-                               offset, len);
+               inode->i_dev, inode->i_ino, current->pid, offset, len);
 
        if (IS_SOFT && signalled()) {
                nfs_cancel_dirty(inode, pid);
@@ -762,16 +770,15 @@ nfs_truncate_dirty_pages(struct inode *inode, unsigned long offset)
        struct nfs_wreq *req, *head;
        unsigned long   rqoffset;
 
-       dprintk("NFS:      truncate_dirty_pages(%x/%ld, %ld)\n",
-                               inode->i_dev, inode->i_ino, offset);
+       dprintk("NFS:      truncate_dirty_pages(%d/%ld, %ld)\n",
+               inode->i_dev, inode->i_ino, offset);
 
        req = head = NFS_WRITEBACK(inode);
        while (req != NULL) {
                rqoffset = req->wb_page->offset + req->wb_offset;
 
                if (rqoffset >= offset) {
-                       req->wb_flags |= NFS_WRITE_CANCELLED;
-                       rpc_exit(&req->wb_task, 0);
+                       nfs_cancel_request(req);
                } else if (rqoffset + req->wb_bytes >= offset) {
                        req->wb_bytes = offset - rqoffset;
                }
@@ -831,24 +838,13 @@ nfs_wback_lock(struct rpc_task *task)
        req->wb_flags |=  NFS_WRITE_LOCKED;
        task->tk_status = 0;
 
-       if (req->wb_args == 0) {
-               size_t  size = sizeof(struct nfs_writeargs)
-                            + sizeof(struct nfs_fattr);
-               void    *ptr;
-
-               if (!(ptr = kmalloc(size, GFP_KERNEL)))
-                       goto out_no_args;
-               req->wb_args = (struct nfs_writeargs *) ptr;
-               req->wb_fattr = (struct nfs_fattr *) (req->wb_args + 1);
-       }
-
        /* Setup the task struct for a writeback call */
-       req->wb_args->fh = NFS_FH(dentry);
-       req->wb_args->offset = page->offset + req->wb_offset;
-       req->wb_args->count  = req->wb_bytes;
-       req->wb_args->buffer = (void *) (page_address(page) + req->wb_offset);
+       req->wb_args.fh     = NFS_FH(dentry);
+       req->wb_args.offset = page->offset + req->wb_offset;
+       req->wb_args.count  = req->wb_bytes;
+       req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset);
 
-       rpc_call_setup(task, NFSPROC_WRITE, req->wb_args, req->wb_fattr, 0);
+       rpc_call_setup(task, NFSPROC_WRITE, &req->wb_args, &req->wb_fattr, 0);
 
        req->wb_flags |= NFS_WRITE_INPROGRESS;
        return;
@@ -858,11 +854,6 @@ out_locked:
        task->tk_timeout = 2 * HZ;
        rpc_sleep_on(&write_queue, task, NULL, NULL);
        return;
-out_no_args:
-       printk("NFS: can't alloc args, sleeping\n");
-       task->tk_timeout = HZ;
-       rpc_sleep_on(&write_queue, task, NULL, NULL);
-       return;
 }
 
 /*
@@ -880,7 +871,7 @@ nfs_wback_result(struct rpc_task *task)
                task->tk_pid, req->wb_dentry->d_parent->d_name.name,
                req->wb_dentry->d_name.name, status, req->wb_flags);
 
-       /* Set the WRITE_COMPLETE flag, but leave INPROGRESS set */
+       /* Set the WRITE_COMPLETE flag, but leave WRITE_INPROGRESS set */
        req->wb_flags |= NFS_WRITE_COMPLETE;
        if (status < 0) {
                /*
@@ -892,7 +883,7 @@ nfs_wback_result(struct rpc_task *task)
                        status = 0;
                clear_bit(PG_uptodate, &page->flags);
        } else if (!WB_CANCELLED(req)) {
-               struct nfs_fattr *fattr = req->wb_fattr;
+               struct nfs_fattr *fattr = &req->wb_fattr;
                /* Update attributes as result of writeback. 
                 * Beware: when UDP replies arrive out of order, we
                 * may end up overwriting a previous, bigger file size.
@@ -928,11 +919,6 @@ nfs_wback_result(struct rpc_task *task)
        if (WB_HAVELOCK(req))
                nfs_unlock_page(page);
 
-       if (req->wb_args) {
-               kfree(req->wb_args);
-               req->wb_args = 0;
-       }
-
        /*
         * Now it's safe to remove the request from the inode's 
         * writeback list and wake up any tasks sleeping on it.
index f9d7e8060e86ce22439aaba1bf159f21bcb704a8..77a158612e42e8fa514a95717b8c4282b6910fe1 100644 (file)
@@ -27,12 +27,6 @@ typedef struct svc_buf       svc_buf;
 
 #define NFSDDBG_FACILITY               NFSDDBG_PROC
 
-#define sleep(msec)            \
-       {       printk(KERN_NOTICE "nfsd: sleeping %d msecs\n", msec); \
-               current->state = TASK_INTERRUPTIBLE;    \
-               current->timeout = jiffies + msec / 10; \
-               schedule();     \
-       }
 #define RETURN(st)     return st
 
 static void
@@ -298,11 +292,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
                 * size, so that creat() behaves exactly like
                 * open(..., O_CREAT|O_TRUNC|O_WRONLY).
                 */
-#if 0
-               /* N.B. What is this doing? ignores size?? */
-               if ((attr->ia_valid &= ~(ATTR_SIZE)) != 0)
-                       nfserr = nfsd_setattr(rqstp, newfhp, attr);
-#endif
                attr->ia_valid &= ATTR_SIZE;
                if (attr->ia_valid)
                        nfserr = nfsd_setattr(rqstp, newfhp, attr);
@@ -435,22 +424,25 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
        u32 *   buffer;
        int     nfserr, count;
 
-       dprintk("nfsd: READDIR  %p %d bytes at %d\n",
-               SVCFH_DENTRY(&argp->fh),
+       dprintk("nfsd: READDIR  %d/%ld %d bytes at %d\n",
+               SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
                argp->count, argp->cookie);
 
        /* Reserve buffer space for status */
        svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count, 1);
 
-       /* Make sure we've room for the NULL ptr & eof flag, and shrink to
-        * client read size */
-       if ((count -= 8) > argp->count)
-               count = argp->count;
+       /* Shrink to the client read size */
+       if (count > (argp->count >> 2))
+               count = argp->count >> 2;
+
+       /* Make sure we've room for the NULL ptr & eof flag */
+       count -= 2;
+       if (count < 0)
+               count = 0;
 
        /* Read directory and encode entries on the fly */
        nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie, 
-                                       nfssvc_encode_entry,
-                                       buffer, &count);
+                               nfssvc_encode_entry, buffer, &count);
        resp->count = count;
 
        fh_put(&argp->fh);
index cba32eea781c186ef9208c5705351b4448bee5e5..0164b6a7e3357ab90d991a554a51aeebb87e7d21 100644 (file)
@@ -97,8 +97,8 @@ nfsd(struct svc_rqst *rqstp)
 
        oldumask = current->fs->umask;          /* Set umask to 0.  */
        current->fs->umask = 0;
-       nfssvc_boot = xtime;                    /* record boot time */
-       nfsd_active++;
+       if (!nfsd_active++)
+               nfssvc_boot = xtime;            /* record boot time */
        lockd_up();                             /* start lockd */
 
        /*
index e3b6b9303638f4fb0d9bbf08eb610a42d9d25a49..48ab4cbeba777a51e9016b0e3a5233af1d05cf86 100644 (file)
@@ -1041,7 +1041,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
        memset(&cd, 0, sizeof(cd));
        cd.rqstp  = rqstp;
        cd.buffer = buffer;
-       cd.buflen = *countp >> 2;
+       cd.buflen = *countp; /* count of words */
 
        /*
         * Read the directory entries. This silly loop is necessary because
index 1f50a26dc712eb9cbbd63c18ad5f0704d291768a..b0c7a49b49e0d6b399f0c6a3e0b70ae149558bfb 100644 (file)
@@ -391,6 +391,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -425,7 +426,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 6b6c7a99e8d7e28c49439db68f533486703c9d4f..cea3d163d52325a96fe6ed7ebe53583a196b5bfd 100644 (file)
@@ -355,6 +355,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -389,7 +390,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index e425d5d485318a121ec7edefe1827f7709972837..972c728bdfebc163153c982cc722290286cc296b 100644 (file)
@@ -346,6 +346,7 @@ static unsigned char *page_uni2charset[256] = {
        NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   pagefe, NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -380,7 +381,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 7763b9ddd47961edd8793a4ba7dddcb7e4c74959..c681274504a685fa9db7a3a28537d19a267023d5 100644 (file)
@@ -355,6 +355,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -389,7 +390,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 985b2dfbbe777dd49bcd457aeee69955497ca9d1..d548247046b1185303bc21d0e44c3e1de1c41918 100644 (file)
@@ -283,6 +283,7 @@ static unsigned char *page_uni2charset[256] = {
        NULL,   page21, page22, NULL,   NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -317,7 +318,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 1edac6b6342d27cc5b6d29f30b6b615f0d20752e..586fb993648de59593e47dc48bd72488f5207451 100644 (file)
@@ -247,6 +247,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   NULL,   NULL,   NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -281,7 +282,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 26350555ffc55a29f3d015c5603ecda88e3b0060..b2c35c843c168187a29fc5e58b26e522c062f396 100644 (file)
@@ -211,6 +211,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -245,7 +246,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 3b32a706e62e9860dd0a2e478eeb7c5f0aad99cc..94ff9c39c4294a66f13dd5dcf1a6e1eaa8e2a4d5 100644 (file)
@@ -135,6 +135,7 @@ static unsigned char *page_uni2charset[256] = {
        page00, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -169,7 +170,7 @@ static unsigned char charset2upper[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index b21961b69ea839013117630fb33cee39c74fbbbf..8349b879a25c5e5c3ee7c60cb1a38cfb12521410 100644 (file)
@@ -207,6 +207,7 @@ static unsigned char *page_uni2charset[256] = {
        page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -241,7 +242,7 @@ static unsigned char charset2upper[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index d5d7f7f27b042ec83601d465c6874673f849e9fb..23af5447b9a0bca2418f65b4583dfed2c0fb095a 100644 (file)
@@ -207,6 +207,7 @@ static unsigned char *page_uni2charset[256] = {
        page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -241,7 +242,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index f03aaaa2c71e069c6daf20c1e49e7979d03e5494..abbe1bd9bd53a88ed7b5397d7391375c2b6ad745 100644 (file)
@@ -207,6 +207,7 @@ static unsigned char *page_uni2charset[256] = {
        page00, page01, page02, NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -241,7 +242,7 @@ static unsigned char charset2upper[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 94bece0bb8336e842cf657f8a00ff805f5b3bfcc..1fe18003f32938a3ba21a7d5f9a055e0695c264b 100644 (file)
@@ -211,6 +211,7 @@ static unsigned char *page_uni2charset[256] = {
        NULL,   page21, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -245,7 +246,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 050aee92dc495785619117bacc54ee70bfdaf37e..7ed46f426ef40edf775e6dedc814b2f5561d4a6a 100644 (file)
@@ -171,6 +171,7 @@ static unsigned char *page_uni2charset[256] = {
        page00, NULL,   NULL,   NULL,   NULL,   NULL,   page06, NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -205,7 +206,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 3790378acfb2b31129b2d3e61bea7ff410e5bb74..180ac239b3ceba7093e0dd704c1025681791594b 100644 (file)
@@ -247,6 +247,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -281,7 +282,7 @@ static unsigned char charset2upper[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index b639b739207ac6bab212b1514bc1be1500581d96..054f5a4a8af3cc4b76d0727583859500707a1988 100644 (file)
@@ -211,6 +211,7 @@ static unsigned char *page_uni2charset[256] = {
        page20, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -245,7 +246,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index aef5b410e99950ed325ebe4907a25d221457dc9f..eaa8c4c68ad80cb66ca23b5b81cb4aff8f13fde8 100644 (file)
@@ -171,6 +171,7 @@ static unsigned char *page_uni2charset[256] = {
        page00, page01, NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -205,7 +206,7 @@ static unsigned char charset2upper[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index 8d08ba3ef9720e36683479ae3084439c27b6509f..c6ee51f991510167db9d0eec469317d841af182e 100644 (file)
@@ -283,6 +283,7 @@ static unsigned char *page_uni2charset[256] = {
        NULL,   NULL,   page22, page23, NULL,   page25, NULL,   NULL,   
 };
 
+#if 0
 static unsigned char charset2upper[256] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -317,7 +318,7 @@ static unsigned char charset2upper[256] = {
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
        0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
 };
-
+#endif
 
 static void inc_use_count(void)
 {
index e4f1003fdcf12cc7cf9960f8dbe4c1ffbd733a55..ae477843b80e11c7b4b95f0b0a1ec1f5dfdffd99 100644 (file)
@@ -1149,7 +1149,7 @@ extern int get_filesystem_info( char * );
 extern int get_irq_list(char *);
 extern int get_dma_list(char *);
 extern int get_cpuinfo(char *);
-extern int get_pci_list(char*);
+extern int get_pci_list(char *);
 extern int get_md_status (char *);
 extern int get_rtc_status (char *);
 extern int get_locks_status (char *, char **, off_t, int);
@@ -1174,7 +1174,7 @@ static long get_root_array(char * page, int type, char **start,
                case PROC_MEMINFO:
                        return get_meminfo(page);
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_PCI_OLD_PROC
                case PROC_PCI:
                        return get_pci_list(page);
 #endif
index ae9ccce2e6bd88df3a0bd1f233ae5a33eddb070c..d8c80cc9b3b6215b5a243e7052d4f444026821a1 100644 (file)
@@ -152,7 +152,7 @@ struct proc_dir_entry proc_root = {
        &proc_root, NULL
 };
 
-struct proc_dir_entry *proc_net, *proc_scsi;
+struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus;
 
 #ifdef CONFIG_MCA
 struct proc_dir_entry proc_mca = {
@@ -636,7 +636,6 @@ static struct proc_dir_entry proc_root_ppc_htab = {
        NULL, NULL,                             /* get_info, fill_inode */
        NULL,                                   /* next */
        NULL, NULL                              /* parent, subdir */
-
 };
 #endif
 
@@ -713,6 +712,11 @@ void proc_root_init(void)
 #ifdef CONFIG_PROC_DEVICETREE
        proc_device_tree_init();
 #endif
+
+       proc_bus = create_proc_entry("bus", S_IFDIR, 0);
+#ifdef CONFIG_PCI
+       proc_bus_pci_init();
+#endif
 }
 
 /*
diff --git a/fs/sysv/CHANGES b/fs/sysv/CHANGES
new file mode 100644 (file)
index 0000000..090c328
--- /dev/null
@@ -0,0 +1,9 @@
+Mon Dec 15 1997          Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
+       *    namei.c: struct sysv_dir_inode_operations updated to use dentries.
+
+Fri Jan 23 1998   Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
+       *    inode.c: corrected 1 track offset setting (in sb->sv_block_base).
+                     Originally it was overriden (by setting to zero)
+                     in detected_[xenix,sysv4,sysv2,coherent]. Thanks
+                     to Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
+                     for identifying the problem.
index 0201ff6458ace1e6b8441cf27d58e92252767cd9..457a869f9ec3001eee81c39b0798bd97f22018af 100644 (file)
@@ -168,7 +168,6 @@ static struct super_block * detected_xenix (struct super_block *sb, struct buffe
        sb->sv_sb_flc_blocks = &sbd1->s_free[0];
        sb->sv_sb_total_free_blocks = &sbd2->s_tfree;
        sb->sv_sb_time = &sbd2->s_time;
-       sb->sv_block_base = 0;
        sb->sv_firstinodezone = 2;
        sb->sv_firstdatazone = sbd1->s_isize;
        sb->sv_nzones = sbd1->s_fsize;
@@ -226,7 +225,6 @@ static struct super_block * detected_sysv4 (struct super_block *sb, struct buffe
        sb->sv_sb_total_free_blocks = &sbd->s_tfree;
        sb->sv_sb_time = &sbd->s_time;
        sb->sv_sb_state = &sbd->s_state;
-       sb->sv_block_base = 0;
        sb->sv_firstinodezone = 2;
        sb->sv_firstdatazone = sbd->s_isize;
        sb->sv_nzones = sbd->s_fsize;
@@ -284,7 +282,6 @@ static struct super_block * detected_sysv2 (struct super_block *sb, struct buffe
        sb->sv_sb_total_free_blocks = &sbd->s_tfree;
        sb->sv_sb_time = &sbd->s_time;
        sb->sv_sb_state = &sbd->s_state;
-       sb->sv_block_base = 0;
        sb->sv_firstinodezone = 2;
        sb->sv_firstdatazone = sbd->s_isize;
        sb->sv_nzones = sbd->s_fsize;
@@ -331,7 +328,6 @@ static struct super_block * detected_coherent (struct super_block *sb, struct bu
        sb->sv_sb_flc_blocks = &sbd->s_free[0];
        sb->sv_sb_total_free_blocks = &sbd->s_tfree;
        sb->sv_sb_time = &sbd->s_time;
-       sb->sv_block_base = 0;
        sb->sv_firstinodezone = 2;
        sb->sv_firstdatazone = sbd->s_isize;
        sb->sv_nzones = from_coh_ulong(sbd->s_fsize);
@@ -359,6 +355,7 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
        MOD_INC_USE_COUNT;
        lock_super(sb);
        set_blocksize(dev,BLOCK_SIZE);
+       sb->sv_block_base = 0;
 
        /* Try to read Xenix superblock */
        if ((bh = bread(dev, 1, BLOCK_SIZE)) != NULL) {
index 01ab086d2e3e84d69036774b8ef141a9a0cd819e..f147967adcc96435b6cbbe637c6516cd501bbf36 100644 (file)
  *  sysv/namei.c
  *  Copyright (C) 1993  Bruno Haible
  *
- *
- *  Revised: 15 Dec 1997 by Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
- *    Driver updated to use dentries.
  */
-        
+
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
index 2dc4061a09c10c331ddc9bcc534b06ed37c4ac84..40fa75101c8ae9c07244cf808ac2c5995c552dff 100644 (file)
@@ -117,8 +117,8 @@ extern void ufs_superblock_be_to_cpus(struct ufs_superblock * usb) {
        be32_to_cpus(&usb->fs_cpc);
         be16_to_cpus__between(*usb,fs_opostbl,fs_sparecon);
         be32_to_cpus__between(*usb,fs_sparecon,fs_qbmask);
-        be64_to_cpus(&usb->fs_qbmask);
-        be64_to_cpus(&usb->fs_qfmask);
+        be64_to_cpus((__u64 *) &usb->fs_qbmask);
+        be64_to_cpus((__u64 *) &usb->fs_qfmask);
        be32_to_cpus__between(*usb,fs_postblformat,fs_magic);
 #endif
 }
index a08ec81df7fdd12f58d8d8ed370536543ef37ca8..ddfe6bda47da91c779c2a04530e64ffd3542df45 100644 (file)
@@ -13,9 +13,9 @@
 #define MAP_ANONYMOUS  0x10            /* don't use a file */
 
 /* not used by linux, but here to make sure we don't clash with OSF/1 defines */
-#define MAP_HASSEMAPHORE 0x0200
-#define MAP_INHERIT    0x0400
-#define MAP_UNALIGNED  0x0800
+#define _MAP_HASSEMAPHORE 0x0200
+#define _MAP_INHERIT   0x0400
+#define _MAP_UNALIGNED 0x0800
 
 /* These are linux-specific */
 #define MAP_GROWSDOWN  0x1000          /* stack-like segment */
index d206bcc3b630f4d11c4f569ba4b00c0bc1065142..f7596af913dbd9d207e12a5bd6f82c67b6e85f64 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
+#define cpu_logical_map(cpu)   (cpu)
+
 /* We'll get here eventually.. */
 
 #endif
index 4561035363188dde63a53312e81ecee3ea9eca5e..3cf28cc1c1c9713691950fd57e4697aec3c14ca2 100644 (file)
@@ -80,10 +80,10 @@ extern inline void end_bh_atomic(void)
 #ifndef __SMP__
 
 /* These are for the irq's testing the lock */
-#define softirq_trylock()      (atomic_read(&__alpha_bh_counter) ? \
+#define softirq_trylock(cpu)   (atomic_read(&__alpha_bh_counter) ? \
                                0 : \
                                ((atomic_set(&__alpha_bh_counter,1)),1))
-#define softirq_endlock()      (atomic_set(&__alpha_bh_counter, 0))
+#define softirq_endlock(cpu)   (atomic_set(&__alpha_bh_counter, 0))
 
 #else
 
index 28e5d487de089a6cd180e180d08e1f7bcb31762d..381d5f0441dca5c9de0c338b0322480ad1233e19 100644 (file)
@@ -63,11 +63,13 @@ typedef unsigned int u32;
 
 typedef signed long long s64;
 typedef unsigned long long u64;
+#define BITS_PER_LONG 32
 
 #else
 
 typedef signed long s64;
 typedef unsigned long u64;
+#define BITS_PER_LONG 64
 
 #endif
 
index daf90d70969418d5052430d5c04852ccb08ed6ba..c7c32636689aa950b962f21c1c529f110bf8fb7e 100644 (file)
 #define __NR_osf_pid_block     153     /* not implemented */
 #define __NR_osf_pid_unblock   154     /* not implemented */
 
-#define __NR_osf_sigaction     156
+#define __NR_sigaction         156
 #define __NR_osf_sigwaitprim   157     /* not implemented */
 #define __NR_osf_nfssvc                158     /* not implemented */
 #define __NR_osf_getdirentries 159
 #define __NR_semget            205
 #define __NR_semop             206
 #define __NR_osf_utsname       207
-#define __NR_osf_lchown                208     /* not implemented */
+#define __NR_lchown            208
 #define __NR_osf_shmat         209
 #define __NR_shmctl            210
 #define __NR_shmdt             211
index a28f6bae8d720cca4639154fe14e98746917a173..7b642d667ac40a876163744d30b3ee79215801be 100644 (file)
@@ -91,8 +91,8 @@ extern inline void end_bh_atomic(void)
 }
 
 /* These are for the irq's testing the lock */
-#define softirq_trylock()      (in_bh ? 0 : (local_bh_count[smp_processor_id()]=1))
-#define softirq_endlock()      (local_bh_count[smp_processor_id()] = 0)
+#define softirq_trylock(cpu)   (in_bh() ? 0 : (local_bh_count[smp_processor_id()]=1))
+#define softirq_endlock(cpu)   (local_bh_count[smp_processor_id()] = 0)
 #define synchronize_bh()       do { } while (0)
 
 #endif /* SMP */
index 71309ac823de08de6027ac69faa720488f3aa7d7..d792546f9fb7b025d5e2b960debe96a5b62fba78 100644 (file)
@@ -39,6 +39,8 @@ typedef unsigned int u32;
 typedef signed long long s64;
 typedef unsigned long long u64;
 
+#define BITS_PER_LONG 32
+
 #endif /* __KERNEL__ */
 
 #endif
index 945edb982a1a582a1cac2dc7add44e9051f2cb1b..b0ece7bda893c766b5c2f159c4688a736c45127e 100644 (file)
@@ -47,6 +47,8 @@ typedef unsigned int u32;
 typedef signed long long s64;
 typedef unsigned long long u64;
 
+#define BITS_PER_LONG 32
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_TYPES_H */
index 4d27f768b18a655dd0e92db5a55f245b43aeb620..3f8f9da78f277c6597652b74150a173abc82de64 100644 (file)
@@ -60,11 +60,13 @@ typedef unsigned int u32;
 typedef __signed__ long long s64;
 typedef unsigned long long u64;
 #endif
+#define BITS_PER_LONG 32
   
 #else
   
 typedef __signed__ long s64;
 typedef unsigned long u64;
+#define BITS_PER_LONG 64
 
 #endif
 
index 15d7d7a9ce0982acf51b4c603c0f05b8c98517f5..453bb9258cbad6f5df1a1f8c2010215c2d5afee8 100644 (file)
@@ -156,7 +156,7 @@ extern int adfs_inode_validate (struct inode *inode);
 extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx);
 extern unsigned long adfs_inode_objid (struct inode *inode);
 extern unsigned int adfs_parent_bmap (struct inode *inode, int block);
-extern unsigned int adfs_bmap (struct inode *inode, int block);
+extern int adfs_bmap (struct inode *inode, int block);
 extern void adfs_read_inode (struct inode *inode);
 
 /* map.c */
index c2b0d8d31f4dc2fd28eb26ef3b8bcb45565286b2..7fff6be19fb67926f958d6598a62c06b785c2938 100644 (file)
@@ -148,7 +148,7 @@ extern int adfs_inode_validate (struct inode *inode);
 extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx);
 extern unsigned long adfs_inode_objid (struct inode *inode);
 extern unsigned int adfs_parent_bmap (struct inode *inode, int block);
-extern unsigned int adfs_bmap (struct inode *inode, int block);
+extern int adfs_bmap (struct inode *inode, int block);
 extern void adfs_read_inode (struct inode *inode);
 
 /* map.c */
index 11cbc7e7268e68fd56ec7d048cf440c28f351fca..79e3c3639d5c12690ae1e21092b00cdb9d59590c 100644 (file)
@@ -89,6 +89,7 @@ extern void                    affs_write_inode(struct inode *inode);
 /* super.c */
 
 extern int                      affs_fs(void);
+extern int                      init_affs_fs(void);
 
 /* file.c */
 
index ea45d35cb592ec7fe98d8feef62258c361d496fe..f7b4747d38a0e8307ba9f48a0fb5477af54a3aa5 100644 (file)
@@ -425,25 +425,11 @@ typedef struct isdn_net_local_s {
   struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
   struct sk_buff         *first_skb;   /* Ptr to skb that triggers dialing */
   struct sk_buff         *sav_skb;     /* Ptr to skb, rejected by LL-driver*/
-#if (LINUX_VERSION_CODE < 0x02010F)
-                                       /* Ptr to orig. header_cache_bind   */
-  void                   (*org_hcb)(struct hh_cache **,
-                                   struct device *,
-                                    unsigned short, 
-                                   __u32);
-#else
-#if (LINUX_VERSION_CODE < 0x2011E)
-                                       /* Ptr to orig. hard_header_cache   */
-  int                    (*org_hhc)(struct dst_entry *dst,
-                                   struct dst_entry *neigh,
-                                   struct hh_cache *hh);
-#else
+
                                        /* Ptr to orig. hard_header_cache   */
-  int                    (*org_hhc)(struct dst_entry *dst,
-                                   struct neighbour *neigh,
+  int                    (*org_hhc)(struct neighbour *neigh,
                                    struct hh_cache *hh);
-#endif
-#endif
+
                                        /* Ptr to orig. header_cache_update */
   void                   (*org_hcu)(struct hh_cache *,
                                    struct device *,
index 368cd9bef01517afe0b04a500db5cb9e0de29b4e..1566fee80d503d46e422b4a04a988b9a99be1a35 100644 (file)
@@ -7,6 +7,11 @@
  * Interrupt support added 1993 Nigel Gamble
  */
 
+/* Magic numbers for defining port-device mappings */
+#define LP_PARPORT_AUTO -3
+#define LP_PARPORT_OFF -2
+#define LP_PARPORT_UNSPEC -1
+
 /*
  * Per POSIX guidelines, this module reserves the LP and lp prefixes
  * These are the lp_table[minor].flags flags...
 
 #define LP_BASE(x)     lp_table[(x)].dev->port->base
 
-#define r_dtr(x)       inb(LP_BASE(x))
-#define r_str(x)       inb(LP_BASE(x)+1)
-#define r_ctr(x)       inb(LP_BASE(x)+2)
-#define r_epp(x)       inb(LP_BASE(x)+4)
-#define r_fifo(x)      inb(LP_BASE(x)+0x400)
-#define r_ecr(x)       inb(LP_BASE(x)+0x402)
-
-#define w_dtr(x,y)     outb((y), LP_BASE(x))
-#define w_str(x,y)     outb((y), LP_BASE(x)+1)
-#define w_ctr(x,y)     outb((y), LP_BASE(x)+2)
-#define w_epp(x,y)     outb((y), LP_BASE(x)+4)
-#define w_fifo(x,y)    outb((y), LP_BASE(x)+0x400)
-#define w_ecr(x,y)     outb((y), LP_BASE(x)+0x402)
-
 struct lp_stats {
        unsigned long chars;
        unsigned long sleeps;
@@ -118,12 +109,10 @@ struct lp_struct {
        unsigned int chars;
        unsigned int time;
        unsigned int wait;
-       struct wait_queue *lp_wait_q;
        char *lp_buffer;
        unsigned int lastcall;
        unsigned int runchars;
        unsigned int waittime;
-       unsigned int should_relinquish;
        struct lp_stats stats;
 };
 
@@ -170,6 +159,9 @@ struct lp_struct {
  */
 #define LP_DELAY       50
 
+#define LP_POLLING(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE)
+#define LP_PREEMPTED(minor) (lp_table[(minor)].dev->port->waithead != NULL)
+
 /*
  * function prototypes
  */
index 2a6a4c080715857c5d269a14779cf0337ffd4c28..c4aab89e1103a8a826e702a1f86267f891e8d68a 100644 (file)
@@ -138,6 +138,13 @@ struct nfs_fsinfo {
        __u32                   bavail;
 };
 
+struct nfs_writeargs {
+       struct nfs_fh *         fh;
+       __u32                   offset;
+       __u32                   count;
+       const void *            buffer;
+};
+
 #ifdef NFS_NEED_XDR_TYPES
 
 struct nfs_sattrargs {
@@ -157,13 +164,6 @@ struct nfs_readargs {
        void *                  buffer;
 };
 
-struct nfs_writeargs {
-       struct nfs_fh *         fh;
-       __u32                   offset;
-       __u32                   count;
-       const void *            buffer;
-};
-
 struct nfs_createargs {
        struct nfs_fh *         fh;
        const char *            name;
index 666e5bde4f60da63b52c13dfb7aa8e323ce83f63..9a2d8a67f39bb3e2c8682261a4629e9e7fb1baa3 100644 (file)
@@ -103,8 +103,8 @@ struct nfs_wreq {
        pid_t                   wb_pid;         /* owner process */
        unsigned short          wb_flags;       /* status flags */
 
-       struct nfs_writeargs *  wb_args;        /* NFS RPC stuff */
-       struct nfs_fattr *      wb_fattr;       /* file attributes */
+       struct nfs_writeargs    wb_args;        /* NFS RPC stuff */
+       struct nfs_fattr        wb_fattr;       /* file attributes */
 };
 #define wb_status              wb_task.tk_status
 
@@ -177,8 +177,8 @@ extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 extern struct super_block *nfs_read_super(struct super_block *, void *, int);
 extern int init_nfs_fs(void);
-extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
-                              struct nfs_fattr *);
+extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
+                               struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_revalidate(struct dentry *);
 extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
index 722a9930dce57fdab48a996264b90fa0cb0a5e7f..885f21f01de4142ff864181a7aac8f5f67431cdb 100644 (file)
@@ -53,6 +53,7 @@ struct nfs_inode_info {
  * Legal inode flag values
  */
 #define NFS_INO_REVALIDATE     0x0001          /* revalidating attrs */
+#define NFS_IS_SNAPSHOT                0x0010          /* a snapshot file */
 
 /*
  * NFS lock info
index 73f83633dc8921cd40260dcc9254f8ac834c5ad9..3321e29587fda06c7098cca2c8b1b18e7864f468 100644 (file)
@@ -52,3 +52,4 @@ extern int init_nls_cp865(void);
 extern int init_nls_cp866(void);
 extern int init_nls_cp869(void);
 extern int init_nls_cp874(void);
+extern int init_nls_koi8_r(void);
index 6a2bbd183cd0be1c09c479bb0d6b3c57448ae054..102594683683528c3061d17cc528906d243dd50e 100644 (file)
@@ -1,11 +1,15 @@
-/* $Id: parport.h,v 1.3 1997/10/19 18:02:00 phil Exp $ */
+/* $Id: parport.h,v 1.6 1997/12/29 12:31:05 phil Exp $ */
 
 #ifndef _PARPORT_H_
 #define _PARPORT_H_
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
+#include <asm/spinlock.h>
 #include <linux/proc_fs.h>
+#include <linux/config.h>
+
+#define PARPORT_NEED_GENERIC_OPS
 
 /* Maximum of 8 ports per machine */
 #define PARPORT_MAX  8 
@@ -29,27 +33,11 @@ struct parport_state {
        union {
                struct pc_parport_state pc;
                /* ARC has no state. */
+               /* AX uses same state information as PC */
                void *misc; 
        } u;
 };
 
-/* Generic operations vector through the dispatch table. */
-#define parport_write_data(p,x)            (p)->ops->write_data(p,x)
-#define parport_read_data(p)               (p)->ops->read_data(p)
-#define parport_write_control(p,x)         (p)->ops->write_control(p,x)
-#define parport_read_control(p)            (p)->ops->read_control(p)
-#define parport_frob_control(p,m,v)        (p)->ops->frob_control(p,m,v)
-#define parport_write_econtrol(p,x)        (p)->ops->write_econtrol(p,x)
-#define parport_read_econtrol(p)           (p)->ops->read_econtrol(p)
-#define parport_frob_econtrol(p,m,v)       (p)->ops->frob_econtrol(p,m,v)
-#define parport_write_status(p,v)          (p)->ops->write_status(p,v)
-#define parport_read_status(p)             (p)->ops->read_status(p)
-#define parport_write_fifo(p,v)            (p)->ops->write_fifo(p,v)
-#define parport_read_fifo(p)               (p)->ops->read_fifo(p)
-#define parport_change_mode(p,m)           (p)->ops->change_mode(p,m)
-#define parport_release_resources(p)       (p)->ops->release_resources(p)
-#define parport_claim_resources(p)         (p)->ops->claim_resources(p)
-
 struct parport_operations {
        void (*write_data)(struct parport *, unsigned int);
        unsigned int (*read_data)(struct parport *);
@@ -144,18 +132,26 @@ struct pardevice {
        void (*wakeup)(void *);
        void *private;
        void (*irq_func)(int, void *, struct pt_regs *);
-       int flags;
+       unsigned int flags;
        struct pardevice *next;
        struct pardevice *prev;
        struct parport_state *state;     /* saved status over preemption */
+       struct wait_queue *wait_q;
+       unsigned long int time;
+       unsigned long int timeslice;
+       unsigned int waiting;
+       struct pardevice *waitprev;
+       struct pardevice *waitnext;
 };
 
+/* Directory information for the /proc interface */
 struct parport_dir {
        struct proc_dir_entry *entry;    /* Directory /proc/parport/X     */
-       struct proc_dir_entry *irq;      /* IRQ entry /proc/parport/X/irq */
-       struct proc_dir_entry *devices;  /* /proc/parport/X/devices       */
-       struct proc_dir_entry *hardware; /* /proc/parport/X/hardware      */
-       char name[4];                    /* /proc/parport/"XXXX" */
+       struct proc_dir_entry *irq;     /*              .../irq           */
+       struct proc_dir_entry *devices;  /*             .../devices       */
+       struct proc_dir_entry *hardware; /*             .../hardware      */
+       struct proc_dir_entry *probe;    /*             .../autoprobe     */
+       char name[4];
 };
 
 /* A parallel port */
@@ -169,16 +165,21 @@ struct parport {
 
        struct pardevice *devices;
        struct pardevice *cad;  /* port owner */
-       struct pardevice *lurker;
+
+       struct pardevice *waithead;
+       struct pardevice *waittail;
        
        struct parport *next;
-       unsigned int flags; 
+       unsigned int flags;
 
        struct parport_dir pdir;
        struct parport_device_info probe_info; 
 
        struct parport_operations *ops;
        void *private_data;     /* for lowlevel driver */
+
+         
+       spinlock_t lock;
 };
 
 /* parport_register_port registers a new parallel port at the given address (if
@@ -190,14 +191,14 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma,
                                      struct parport_operations *ops);
 
 /* Unregister a port. */
-void parport_unregister_port(struct parport *port);
+extern void parport_unregister_port(struct parport *port);
 
 /* parport_in_use returns nonzero if there are devices attached to a port. */
 #define parport_in_use(x)  ((x)->devices != NULL)
 
 /* Put a parallel port to sleep; release its hardware resources.  Only possible
  * if no devices are registered.  */
-void parport_quiesce(struct parport *);
+extern void parport_quiesce(struct parport *);
 
 /* parport_enumerate returns a pointer to the linked list of all the ports
  * in this machine.
@@ -219,13 +220,17 @@ struct pardevice *parport_register_device(struct parport *port,
                          int flags, void *handle);
 
 /* parport_unregister unlinks a device from the chain. */
-void parport_unregister_device(struct pardevice *dev);
+extern void parport_unregister_device(struct pardevice *dev);
 
 /* parport_claim tries to gain ownership of the port for a particular driver.
  * This may fail (return non-zero) if another driver is busy.  If this
  * driver has registered an interrupt handler, it will be enabled. 
  */
-int parport_claim(struct pardevice *dev);
+extern int parport_claim(struct pardevice *dev);
+
+/* parport_claim_or_block is the same, but sleeps if the port cannot be 
+   claimed.  Return value is 1 if it slept, 0 normally and -errno on error.  */
+extern int parport_claim_or_block(struct pardevice *dev);
 
 /* parport_release reverses a previous parport_claim.  This can never fail, 
  * though the effects are undefined (except that they are bad) if you didn't
@@ -235,7 +240,18 @@ int parport_claim(struct pardevice *dev);
  * If you mess with the port state (enabling ECP for example) you should
  * clean up before releasing the port. 
  */
-void parport_release(struct pardevice *dev);
+
+extern void parport_release(struct pardevice *dev);
+
+extern __inline__ unsigned int parport_yield(struct pardevice *dev, 
+                                            unsigned int block)
+{
+       unsigned long int timeslip = (jiffies - dev->time);
+       if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
+               return 1;
+       parport_release(dev);
+       return (block)?parport_claim_or_block(dev):parport_claim(dev);
+}
 
 /* The "modes" entry in parport is a bit field representing the following
  * modes.
@@ -262,7 +278,7 @@ extern int parport_wait_peripheral(struct parport *, unsigned char, unsigned
 
 /* Prototypes from parport_procfs */
 extern int parport_proc_init(void);
-extern int parport_proc_cleanup(void);
+extern void parport_proc_cleanup(void);
 extern int parport_proc_register(struct parport *pp);
 extern int parport_proc_unregister(struct parport *pp);
 
@@ -273,4 +289,44 @@ extern int parport_probe(struct parport *port, char *buffer, int len);
 extern void parport_probe_one(struct parport *port);
 extern void (*parport_probe_hook)(struct parport *port);
 
+/* If PC hardware is the only type supported, we can optimise a bit.  */
+#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
+#undef PARPORT_NEED_GENERIC_OPS
+#include <linux/parport_pc.h>
+#define parport_write_data(p,x)            parport_pc_write_data(p,x)
+#define parport_read_data(p)               parport_pc_read_data(p)
+#define parport_write_control(p,x)         parport_pc_write_control(p,x)
+#define parport_read_control(p)            parport_pc_read_control(p)
+#define parport_frob_control(p,m,v)        parport_pc_frob_control(p,m,v)
+#define parport_write_econtrol(p,x)        parport_pc_write_econtrol(p,x)
+#define parport_read_econtrol(p)           parport_pc_read_econtrol(p)
+#define parport_frob_econtrol(p,m,v)       parport_pc_frob_econtrol(p,m,v)
+#define parport_write_status(p,v)          parport_pc_write_status(p,v)
+#define parport_read_status(p)             parport_pc_read_status(p)
+#define parport_write_fifo(p,v)            parport_pc_write_fifo(p,v)
+#define parport_read_fifo(p)               parport_pc_read_fifo(p)
+#define parport_change_mode(p,m)           parport_pc_change_mode(p,m)
+#define parport_release_resources(p)       parport_pc_release_resources(p)
+#define parport_claim_resources(p)         parport_pc_claim_resources(p)
+#endif
+
+#ifdef PARPORT_NEED_GENERIC_OPS
+/* Generic operations vector through the dispatch table. */
+#define parport_write_data(p,x)            (p)->ops->write_data(p,x)
+#define parport_read_data(p)               (p)->ops->read_data(p)
+#define parport_write_control(p,x)         (p)->ops->write_control(p,x)
+#define parport_read_control(p)            (p)->ops->read_control(p)
+#define parport_frob_control(p,m,v)        (p)->ops->frob_control(p,m,v)
+#define parport_write_econtrol(p,x)        (p)->ops->write_econtrol(p,x)
+#define parport_read_econtrol(p)           (p)->ops->read_econtrol(p)
+#define parport_frob_econtrol(p,m,v)       (p)->ops->frob_econtrol(p,m,v)
+#define parport_write_status(p,v)          (p)->ops->write_status(p,v)
+#define parport_read_status(p)             (p)->ops->read_status(p)
+#define parport_write_fifo(p,v)            (p)->ops->write_fifo(p,v)
+#define parport_read_fifo(p)               (p)->ops->read_fifo(p)
+#define parport_change_mode(p,m)           (p)->ops->change_mode(p,m)
+#define parport_release_resources(p)       (p)->ops->release_resources(p)
+#define parport_claim_resources(p)         (p)->ops->claim_resources(p)
+#endif
+
 #endif /* _PARPORT_H_ */
diff --git a/include/linux/parport_pc.h b/include/linux/parport_pc.h
new file mode 100644 (file)
index 0000000..3d6e5cb
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __LINUX_PARPORT_PC_H
+#define __LINUX_PARPORT_PC_H
+
+#include <asm/io.h>
+
+/* --- register definitions ------------------------------- */
+
+#define ECONTROL 0x402
+#define CONFIGB  0x401
+#define CONFIGA  0x400
+#define EPPREG   0x4
+#define CONTROL  0x2
+#define STATUS   0x1
+#define DATA     0
+
+extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned int d)
+{
+       outb(d, p->base+EPPREG);
+}
+
+extern __inline__ unsigned int parport_pc_read_epp(struct parport *p)
+{
+       return (unsigned int)inb(p->base+EPPREG);
+}
+
+extern __inline__ unsigned int parport_pc_read_configb(struct parport *p)
+{
+       return (unsigned int)inb(p->base+CONFIGB);
+}
+
+extern __inline__ void parport_pc_write_data(struct parport *p, unsigned int d)
+{
+       outb(d, p->base+DATA);
+}
+
+extern __inline__ unsigned int parport_pc_read_data(struct parport *p)
+{
+       return (unsigned int)inb(p->base+DATA);
+}
+
+extern __inline__ void parport_pc_write_control(struct parport *p, unsigned int d)
+{
+       outb(d, p->base+CONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_read_control(struct parport *p)
+{
+       return (unsigned int)inb(p->base+CONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask,  unsigned int val)
+{
+       unsigned int old = (unsigned int)inb(p->base+CONTROL);
+       outb(((old & ~mask) ^ val), p->base+CONTROL);
+       return old;
+}
+
+extern __inline__ void parport_pc_write_status(struct parport *p, unsigned int d)
+{
+       outb(d, p->base+STATUS);
+}
+
+extern __inline__ unsigned int parport_pc_read_status(struct parport *p)
+{
+       return (unsigned int)inb(p->base+STATUS);
+}
+
+extern __inline__ void parport_pc_write_econtrol(struct parport *p, unsigned int d)
+{
+       outb(d, p->base+ECONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_read_econtrol(struct parport *p)
+{
+       return (unsigned int)inb(p->base+ECONTROL);
+}
+
+extern __inline__ unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask,  unsigned int val)
+{
+       unsigned int old = (unsigned int)inb(p->base+ECONTROL);
+       outb(((old & ~mask) ^ val), p->base+ECONTROL);
+       return old;
+}
+
+extern void parport_pc_change_mode(struct parport *p, int m);
+
+extern void parport_pc_write_fifo(struct parport *p, unsigned int v);
+
+extern unsigned int parport_pc_read_fifo(struct parport *p);
+
+extern void parport_pc_disable_irq(struct parport *p);
+
+extern void parport_pc_enable_irq(struct parport *p);
+
+extern void parport_pc_release_resources(struct parport *p);
+
+extern int parport_pc_claim_resources(struct parport *p);
+
+extern void parport_pc_save_state(struct parport *p, struct parport_state *s);
+
+extern void parport_pc_restore_state(struct parport *p, struct parport_state *s);
+
+extern unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned  int length);
+
+extern unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned  int length);
+
+extern unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle);
+
+extern unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned  int length, void (*fn)(struct parport *, void *, unsigned int), void *handle);
+
+extern int parport_pc_examine_irq(struct parport *p);
+
+extern void parport_pc_inc_use_count(void);
+
+extern void parport_pc_dec_use_count(void);
+
+#endif
index 4763d4b2168bce1dd36e615f92c1abf983294fd3..92730ee38ba031f53c42082586406be7015c5984 100644 (file)
@@ -1,48 +1,27 @@
 /*
- * PCI defines and function prototypes
- * Copyright 1994, Drew Eckhardt
+ *     $Id: pci.h,v 1.51 1997/12/27 13:55:23 mj Exp $
  *
- * For more information, please consult 
- * 
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
+ *     PCI defines and function prototypes
+ *     Copyright 1994, Drew Eckhardt
+ *     Copyright 1997, Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000 
- * +1 (800) 433-5177
+ *     For more information, please consult 
  * 
- * Manuals are $25 each or $50 for all three, plus $7 shipping 
- * within the United States, $35 abroad.
- */
-
-
-
-/*     PROCEDURE TO REPORT NEW PCI DEVICES
- * We are trying to collect information on new PCI devices, using
- * the standard PCI identification procedure. If some warning is
- * displayed at boot time, please report 
- *     - /proc/pci
- *     - your exact hardware description. Try to find out
- *       which device is unknown. It may be you mainboard chipset.
- *       PCI-CPU bridge or PCI-ISA bridge.
- *     - If you can't find the actual information in your hardware
- *       booklet, try to read the references of the chip on the board.
- *     - Send all that to linux-pcisupport@cck.uni-kl.de
- *       and I'll add your device to the list as soon as possible
- *
- * BEFORE you send a mail, please check the latest linux releases
- * to be sure it has not been recently added.
+ *     PCI BIOS Specification Revision
+ *     PCI Local Bus Specification
+ *     PCI System Design Guide
  *
- *        Thanks
- *             Jens Maurer
+ *     PCI Special Interest Group
+ *     M/S HF3-15A
+ *     5200 N.E. Elam Young Parkway
+ *     Hillsboro, Oregon 97124-6497
+ *     +1 (503) 696-2000 
+ *     +1 (800) 433-5177
+ * 
+ *     Manuals are $25 each or $50 for all three, plus $7 shipping 
+ *     within the United States, $35 abroad.
  */
 
-
-
 #ifndef LINUX_PCI_H
 #define LINUX_PCI_H
 
  */
 #define PCI_BASE_ADDRESS_0     0x10    /* 32 bits */
 #define PCI_BASE_ADDRESS_1     0x14    /* 32 bits */
-#define PCI_BASE_ADDRESS_2     0x18    /* 32 bits */
+#define PCI_BASE_ADDRESS_2     0x18    /* 32 bits [htype 0 only] */
 #define PCI_BASE_ADDRESS_3     0x1c    /* 32 bits */
 #define PCI_BASE_ADDRESS_4     0x20    /* 32 bits */
 #define PCI_BASE_ADDRESS_5     0x24    /* 32 bits */
 #define  PCI_BASE_ADDRESS_IO_MASK      (~0x03)
 /* bit 1 is reserved if address_space = 1 */
 
+/* Header type 0 (normal devices) */
 #define PCI_CARDBUS_CIS                0x28
 #define PCI_SUBSYSTEM_ID       0x2c
 #define PCI_SUBSYSTEM_VENDOR_ID        0x2e  
 #define PCI_MIN_GNT            0x3e    /* 8 bits */
 #define PCI_MAX_LAT            0x3f    /* 8 bits */
 
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS                0x18    /* Primary bus number */
+#define PCI_SECONDARY_BUS      0x19    /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS    0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER  0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE            0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT           0x1d
+#define  PCI_IO_RANGE_TYPE_MASK        0x0f    /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16  0x00
+#define  PCI_IO_RANGE_TYPE_32  0x01
+#define  PCI_IO_RANGE_MASK     ~0x0f
+#define PCI_SEC_STATUS         0x1e    /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE                0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT       0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define  PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT  0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define  PCI_PREF_RANGE_TYPE_32        0x00
+#define  PCI_PREF_RANGE_TYPE_64        0x01
+#define  PCI_PREF_RANGE_MASK   ~0x0f
+#define PCI_PREF_BASE_UPPER32  0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16    0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16   0x32
+/* 0x34-0x3b is reserved */
+#define PCI_ROM_ADDRESS1       0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL     0x3e
+#define  PCI_BRIDGE_CTL_PARITY 0x01    /* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR   0x02    /* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_NO_ISA 0x04    /* Disable bridging of ISA ports */
+#define  PCI_BRIDGE_CTL_VGA    0x08    /* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Device classes and subclasses */
+
 #define PCI_CLASS_NOT_DEFINED          0x0000
 #define PCI_CLASS_NOT_DEFINED_VGA      0x0001
 
 #define  PCI_CLASS_BRIDGE_CARDBUS      0x0607
 #define  PCI_CLASS_BRIDGE_OTHER                0x0680
 
-
 #define PCI_BASE_CLASS_COMMUNICATION   0x07
 #define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
 #define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
 #define PCI_DEVICE_ID_ARK_STINGARK     0xa099
 #define PCI_DEVICE_ID_ARK_2000MT       0xa0a1
 
-#ifdef __KERNEL__
 /*
  * The PCI interface treats multi-function devices as independent
  * devices.  The slot/function address of each device is encoded
 #define PCI_SLOT(devfn)                (((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)                ((devfn) & 0x07)
 
+#ifdef __KERNEL__
 /*
  * There is one pci_dev structure for each slot-number/function-number
  * combination:
@@ -920,34 +939,16 @@ struct pci_bus {
        unsigned char   subordinate;    /* max number of subordinate buses */
 };
 
-/*
- * This is used to map a vendor-id/device-id pair into device-specific
- * information.
- */
-struct pci_dev_info {
-       unsigned short  vendor;         /* vendor id */
-       unsigned short  device;         /* device id */
-
-       const char      *name;          /* device name */
-       unsigned char   bridge_type;    /* bridge type or 0xff */
-};
-
 extern struct pci_bus  pci_root;       /* root bus */
 extern struct pci_dev  *pci_devices;   /* list of all devices */
 
-
 extern unsigned long pci_init (unsigned long mem_start, unsigned long mem_end);
 
-extern unsigned int pci_scan_bus(struct pci_bus *bus, unsigned long *mem_startp);
-
-extern struct pci_dev_info *pci_lookup_dev (unsigned int vendor,
-                                           unsigned int dev);
-extern const char *pci_strclass (unsigned int class);
-extern const char *pci_strvendor (unsigned int vendor);
-extern const char *pci_strdev (unsigned int vendor, unsigned int device);
+extern unsigned int pci_scan_bus (struct pci_bus *bus, unsigned long *mem_startp);
 
 extern int get_pci_list (char *buf);
 
 extern void pci_quirks_init (void);
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index ce31bacd13b9e861b67eec80c65f0f26da75b880..c5a6054eea2107322fd0fa2b38078a318b5763d7 100644 (file)
@@ -197,6 +197,12 @@ enum mca_directory_inos {
        PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
 };
 
+enum bus_directory_inos {
+       PROC_BUS_PCI = PROC_MCA_LAST,
+       PROC_BUS_PCI_DEVICES,
+       PROC_BUS_LAST
+};
+
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
@@ -263,12 +269,13 @@ extern struct proc_dir_entry proc_openprom;
 extern struct proc_dir_entry proc_pid;
 extern struct proc_dir_entry proc_pid_fd;
 extern struct proc_dir_entry proc_mca;
+extern struct proc_dir_entry *proc_bus;
 
 extern struct inode_operations proc_scsi_inode_operations;
 
 extern void proc_root_init(void);
 extern void proc_base_init(void);
-extern void proc_net_init(void);
+extern void proc_bus_pci_init(void);
 
 extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
 extern int proc_unregister(struct proc_dir_entry *, int);
index ed896058edf1a39402e4269a4164c8c65138beab..bad6d16101ef27aa64490f69bb53a965125973bb 100644 (file)
@@ -332,7 +332,7 @@ struct task_struct {
 /* timeout */  0,SCHED_OTHER,0,0,0,0,0,0,0, \
 /* timer */    { NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */    {0,0,0,0},0, \
-/* per cpu times */ {0, 0, }, {0, 0, }, \
+/* per cpu times */ {0, }, {0, }, \
 /* flt */      0,0,0,0,0,0, \
 /* swp */      0,0,0,0,0, \
 /* rlimits */   INIT_RLIMITS, \
index 96bc89fd276b10572f3352a2cf1ee72b9837e930..2e83cf446987932c4ab9dc68e4d40768a3ff8023 100644 (file)
@@ -99,6 +99,7 @@ int  smb_revalidate_inode(struct dentry *);
 int  smb_notify_change(struct dentry *, struct iattr *);
 unsigned long smb_invent_inos(unsigned long);
 struct inode *smb_iget(struct super_block *, struct smb_fattr *);
+extern int init_smb_fs(void);
 
 /* linux/fs/smbfs/proc.c */
 __u32 smb_len(unsigned char *);
index f776efa02e6148d88a504224ba31116a2fbb03c5..d592ad3267afe9de6caab2fc911a48fd64cbb165 100644 (file)
@@ -119,6 +119,9 @@ extern void pd_setup(char *str, int *ints);
 #ifdef CONFIG_PARIDE_PF
 extern void pf_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_PARIDE_PT
+extern void pt_setup(char *str, int *ints);
+#endif
 #ifdef CONFIG_PARIDE_PCD
 extern void pcd_setup(char *str, int *ints);
 #endif
@@ -701,7 +704,7 @@ static struct kernel_param cooked_params[] __initdata = {
 #ifdef CONFIG_PLIP
        { "plip=", plip_setup },
 #endif
-#ifdef CONFIG_SOUNDMODEM
+#ifdef CONFIG_HFMODEM
        { "hfmodem=", hfmodem_setup },
 #endif
 #ifdef CONFIG_PMAC_CONSOLE
@@ -731,6 +734,9 @@ static struct kernel_param raw_params[] __initdata = {
 #endif
 #ifdef CONFIG_PARIDE_PF
        { "pf.", pf_setup },
+#endif
+#ifdef CONFIG_PARIDE_PT
+        { "pt.", pt_setup },
 #endif
        { 0, 0 }
 };
index 0573176510f57daef018ff71e8bb2cbce268bc8e..96db1f7176e5ae2919e0dc45dcea32ddd61d2d9c 100644 (file)
@@ -100,7 +100,6 @@ EXPORT_SYMBOL(kerneld_send);
 EXPORT_SYMBOL(get_options);
 
 #ifdef CONFIG_PCI
-/* PCI BIOS support */
 EXPORT_SYMBOL(pcibios_present);
 EXPORT_SYMBOL(pcibios_find_class);
 EXPORT_SYMBOL(pcibios_find_device);
@@ -111,8 +110,6 @@ EXPORT_SYMBOL(pcibios_write_config_byte);
 EXPORT_SYMBOL(pcibios_write_config_word);
 EXPORT_SYMBOL(pcibios_write_config_dword);
 EXPORT_SYMBOL(pcibios_strerror);
-EXPORT_SYMBOL(pci_strvendor);
-EXPORT_SYMBOL(pci_strdev);
 #endif
 
 /* process memory management */
index 521fad227cfb6b8e7b23e7800a4daa4c185eb156..6149741a092e1f68f16da616b283da57f3a2b3aa 100644 (file)
@@ -583,23 +583,27 @@ EXPORT_SYMBOL(send_sig_info);
 asmlinkage int
 sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize)
 {
+       int error = -EINVAL;
        sigset_t old_set, new_set;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
        if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
+               goto out;
 
        if (set) {
+               error = -EFAULT;
                if (copy_from_user(&new_set, set, sizeof(*set)))
-                       return -EFAULT;
+                       goto out;
                sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
                spin_lock_irq(&current->sigmask_lock);
                old_set = current->blocked;
 
+               error = 0;
                switch (how) {
                default:
-                       return -EINVAL;
+                       error = -EINVAL;
+                       break;
                case SIG_BLOCK:
                        sigorsets(&new_set, &old_set, &new_set);
                        break;
@@ -613,47 +617,54 @@ sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize)
                current->blocked = new_set;
                recalc_sigpending(current);
                spin_unlock_irq(&current->sigmask_lock);
-
-               if (oset) {
-                       if (copy_to_user(oset, &old_set, sizeof(*oset)))
-                               return -EFAULT;
-               }
+               if (error)
+                       goto out;
+               if (oset)
+                       goto set_old;
        } else if (oset) {
                spin_lock_irq(&current->sigmask_lock);
                old_set = current->blocked;
                spin_unlock_irq(&current->sigmask_lock);
 
+       set_old:
+               error = -EFAULT;
                if (copy_to_user(oset, &old_set, sizeof(*oset)))
-                       return -EFAULT;
+                       goto out;
        }
-
-       return 0;
+       error = 0;
+out:
+       return error;
 }
 
 asmlinkage int
 sys_rt_sigpending(sigset_t *set, size_t sigsetsize)
 {
+       int error = -EINVAL;
        sigset_t pending;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
        if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
+               goto out;
 
        spin_lock_irq(&current->sigmask_lock);
        sigandsets(&pending, &current->blocked, &current->signal);
        spin_unlock_irq(&current->sigmask_lock);
 
-       return copy_to_user(set, &pending, sizeof(*set));
+       error = -EFAULT;
+       if (!copy_to_user(set, &pending, sizeof(*set)))
+               error = 0;
+out:
+       return error;
 }
 
 asmlinkage int
 sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
                    const struct timespec *uts, size_t sigsetsize)
 {
+       int ret, sig;
        sigset_t these;
        struct timespec ts;
        siginfo_t info;
-       int ret, sig;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
        if (sigsetsize != sizeof(sigset_t))
@@ -825,19 +836,23 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
 asmlinkage int
 sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset)
 {
+       int error;
        old_sigset_t old_set, new_set;
 
        if (set) {
+               error = -EFAULT;
                if (copy_from_user(&new_set, set, sizeof(*set)))
-                       return -EFAULT;
+                       goto out;
                new_set &= ~(sigmask(SIGKILL)|sigmask(SIGSTOP));
 
                spin_lock_irq(&current->sigmask_lock);
                old_set = current->blocked.sig[0];
 
+               error = 0;
                switch (how) {
                default:
-                       return -EINVAL;
+                       error = -EINVAL;
+                       break;
                case SIG_BLOCK:
                        sigaddsetmask(&current->blocked, new_set);
                        break;
@@ -851,30 +866,36 @@ sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset)
 
                recalc_sigpending(current);
                spin_unlock_irq(&current->sigmask_lock);
-
-               if (oset) {
-                       if (copy_to_user(oset, &old_set, sizeof(*oset)))
-                               return -EFAULT;
-               }
+               if (error)
+                       goto out;
+               if (oset)
+                       goto set_old;
        } else if (oset) {
                old_set = current->blocked.sig[0];
+       set_old:
+               error = -EFAULT;
                if (copy_to_user(oset, &old_set, sizeof(*oset)))
-                       return -EFAULT;
+                       goto out;
        }
-
-       return 0;
+       error = 0;
+out:
+       return error;
 }
 
 asmlinkage int
 sys_sigpending(old_sigset_t *set)
 {
+       int error;
        old_sigset_t pending;
 
        spin_lock_irq(&current->sigmask_lock);
        pending = current->blocked.sig[0] & current->signal.sig[0];
        spin_unlock_irq(&current->sigmask_lock);
 
-       return copy_to_user(set, &pending, sizeof(*set));
+       error = -EFAULT;
+       if (!copy_to_user(set, &pending, sizeof(*set)))
+               error = 0;
+       return error;
 }
 
 asmlinkage int
@@ -882,11 +903,11 @@ sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
                 size_t sigsetsize)
 {
        struct k_sigaction new_sa, old_sa;
-       int ret;
+       int ret = -EINVAL;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
        if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
+               goto out;
 
        if (act) {
                if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
@@ -899,7 +920,7 @@ sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
                if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
                        return -EFAULT;
        }
-
+out:
        return ret;
 }
 #endif
index c0efdb1caa0621a6a38d9f3c4adb425884102d60..589c8f6bdb9b2e3fd9f28ffae8c47a93848950aa 100644 (file)
 #include <linux/if_frad.h>
 #endif
 
+#ifdef CONFIG_BRIDGE
+#include <net/br.h>
+#endif
+
+#ifdef CONFIG_DLCI
+extern int dlci_ioctl(unsigned int, void*);
+#endif
+
 /*
    Old SOCK_PACKET. Do exist programs, which use it?
    (not counting tcpdump) - lots of them yes - AC. 
index 3be15da633bd0f0ab41f5949150ded21eb6df01a..6670bcf904f8b67020239e041dc0784fcd484f13 100644 (file)
@@ -1432,6 +1432,9 @@ __initfunc(void proto_init(void))
 }
 
 extern void sk_init(void);
+#ifdef CONFIG_WAN_ROUTER
+extern void wanrouter_init(void);
+#endif
 
 __initfunc(void sock_init(void))
 {
index ccc1ce0e3a17c50850b1ac7d78ab3b0da7537961..f214a949ed8c34aa005fe1e62a72bb9d66893f9b 100644 (file)
@@ -80,8 +80,10 @@ static int delete_interface (wan_device_t* wandev, char* name, int forse);
  *     Global Data
  */
 
+#ifdef MODULE
 static char fullname[]         = "WAN Router";
 static char copyright[]                = "(c) 1995-1997 Sangoma Technologies Inc.";
+#endif
 static char modname[]          = ROUTER_NAME;  /* short module name */
 wan_device_t * router_devlist  = NULL; /* list of registered devices */
 static int devcnt              = 0;
@@ -91,7 +93,9 @@ static int devcnt             = 0;
  */
  
 static unsigned char oui_ether[] = { 0x00, 0x00, 0x00 };
+#if 0
 static unsigned char oui_802_2[] = { 0x00, 0x80, 0xC2 };
+#endif
 
 #ifdef MODULE
 
index b95b39425352bab952948b150de75f9260e611e6..088487077e67a07f40c4a56eace1b7586f1b8c5d 100644 (file)
@@ -158,6 +158,7 @@ static struct inode_operations wandev_inode =
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* readlink */
+       NULL,                   /* follow_link */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */