From 47c1864c258551d6c0b2257ac277fec583b6890f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:14:35 -0500 Subject: [PATCH] Import 2.1.82 --- Documentation/Configure.help | 17 + Documentation/cdrom/ide-cd | 29 +- Documentation/paride.txt | 2 +- Makefile | 18 +- arch/alpha/config.in | 4 + arch/alpha/defconfig | 1 + arch/alpha/kernel/apecs.c | 8 +- arch/alpha/kernel/cia.c | 9 +- arch/alpha/kernel/entry.S | 2 +- arch/alpha/kernel/irq.c | 6 +- arch/alpha/kernel/osf_sys.c | 2 +- arch/alpha/kernel/pyxis.c | 9 + arch/alpha/kernel/signal.c | 2 +- arch/alpha/kernel/t2.c | 9 + arch/i386/config.in | 4 + arch/i386/defconfig | 2 + arch/i386/kernel/i386_ksyms.c | 4 +- arch/i386/kernel/irq.c | 4 + arch/i386/kernel/mca.c | 25 +- arch/i386/kernel/time.c | 2 + arch/i386/math-emu/fpu_entry.c | 6 +- arch/i386/math-emu/get_address.c | 28 +- arch/i386/math-emu/reg_ld_str.c | 6 +- drivers/block/Config.in | 6 +- drivers/block/ide-cd.c | 28 +- drivers/block/ide-proc.c | 5 +- drivers/block/paride/Config.in | 1 + drivers/block/paride/Makefile | 8 + drivers/block/paride/paride.c | 5 + drivers/block/paride/pcd.c | 44 +- drivers/block/paride/pd.c | 32 +- drivers/block/paride/pt.c | 957 +++++++++++++++++++++++ drivers/cdrom/cdrom.c | 77 +- drivers/cdrom/cdu31a.c | 33 +- drivers/cdrom/cm206.c | 24 +- drivers/cdrom/mcd.c | 4 +- drivers/cdrom/sbpcd.c | 12 +- drivers/char/Config.in | 2 +- drivers/char/ftape/lowlevel/fdc-io.c | 14 +- drivers/char/keyboard.c | 1 - drivers/char/lp.c | 429 +++++----- drivers/isdn/avmb1/b1capi.c | 6 +- drivers/isdn/hisax/config.c | 16 +- drivers/isdn/pcbit/module.c | 6 +- drivers/isdn/sc/hardware.h | 5 - drivers/isdn/sc/includes.h | 1 - drivers/isdn/sc/init.c | 8 +- drivers/misc/BUGS-parport | 4 +- drivers/misc/Makefile | 4 +- drivers/misc/TODO-parport | 8 +- drivers/misc/parport_arc.c | 54 +- drivers/misc/parport_ax.c | 274 +++---- drivers/misc/parport_init.c | 5 +- drivers/misc/parport_pc.c | 381 ++++----- drivers/misc/parport_procfs.c | 230 +++--- drivers/misc/parport_share.c | 261 +++++-- drivers/net/de4x5.c | 12 +- drivers/net/dgrs.c | 4 +- drivers/net/hamradio/soundmodem/gentbl.c | 12 + drivers/net/ne.c | 19 +- drivers/net/ppp.c | 281 ++++--- drivers/net/ppp_deflate.c | 43 +- drivers/net/slhc.c | 32 +- drivers/net/tulip.c | 2 +- drivers/pci/Makefile | 9 +- drivers/pci/oldproc.c | 871 +++++++++++++++++++++ drivers/pci/pci.c | 892 +-------------------- drivers/pci/proc.c | 292 +++++++ drivers/pnp/parport_probe.c | 36 +- drivers/scsi/NCR5380.c | 3 +- drivers/scsi/hosts.c | 39 +- drivers/sound/audio.c | 12 +- drivers/sound/sb_mixer.h | 4 +- drivers/sound/softoss.c | 2 +- fs/adfs/inode.c | 2 +- fs/bad_inode.c | 10 +- fs/filesystems.c | 4 + fs/nfs/dir.c | 11 +- fs/nfs/inode.c | 181 +++-- fs/nfs/nfs2xdr.c | 5 +- fs/nfs/write.c | 92 +-- fs/nfsd/nfsproc.c | 30 +- fs/nfsd/nfssvc.c | 4 +- fs/nfsd/vfs.c | 2 +- fs/nls/nls_cp862.c | 3 +- fs/nls/nls_cp863.c | 3 +- fs/nls/nls_cp864.c | 3 +- fs/nls/nls_cp865.c | 3 +- fs/nls/nls_cp866.c | 3 +- fs/nls/nls_cp869.c | 3 +- fs/nls/nls_cp874.c | 3 +- fs/nls/nls_iso8859-1.c | 3 +- fs/nls/nls_iso8859-2.c | 3 +- fs/nls/nls_iso8859-3.c | 3 +- fs/nls/nls_iso8859-4.c | 3 +- fs/nls/nls_iso8859-5.c | 3 +- fs/nls/nls_iso8859-6.c | 3 +- fs/nls/nls_iso8859-7.c | 3 +- fs/nls/nls_iso8859-8.c | 3 +- fs/nls/nls_iso8859-9.c | 3 +- fs/nls/nls_koi8-r.c | 3 +- fs/proc/array.c | 4 +- fs/proc/root.c | 8 +- fs/sysv/CHANGES | 9 + fs/sysv/inode.c | 5 +- fs/sysv/namei.c | 5 +- fs/ufs/ufs_swab.c | 4 +- include/asm-alpha/mman.h | 6 +- include/asm-alpha/smp.h | 2 + include/asm-alpha/softirq.h | 4 +- include/asm-alpha/types.h | 2 + include/asm-alpha/unistd.h | 4 +- include/asm-i386/softirq.h | 4 +- include/asm-i386/types.h | 2 + include/asm-m68k/types.h | 2 + include/asm-mips/types.h | 2 + include/linux/adfs_fs.h | 2 +- include/linux/adfs_fs_fs.h | 2 +- include/linux/affs_fs.h | 1 + include/linux/isdn.h | 20 +- include/linux/lp.h | 24 +- include/linux/nfs.h | 14 +- include/linux/nfs_fs.h | 8 +- include/linux/nfs_fs_i.h | 1 + include/linux/nls.h | 1 + include/linux/parport.h | 118 ++- include/linux/parport_pc.h | 117 +++ include/linux/pci.h | 123 +-- include/linux/proc_fs.h | 9 +- include/linux/sched.h | 2 +- include/linux/smb_fs.h | 1 + init/main.c | 8 +- kernel/ksyms.c | 3 - kernel/signal.c | 77 +- net/packet/af_packet.c | 8 + net/socket.c | 3 + net/wanrouter/wanmain.c | 4 + net/wanrouter/wanproc.c | 1 + 138 files changed, 4296 insertions(+), 2415 deletions(-) create mode 100644 drivers/block/paride/pt.c create mode 100644 drivers/pci/oldproc.c create mode 100644 drivers/pci/proc.c create mode 100644 fs/sysv/CHANGES create mode 100644 include/linux/parport_pc.h diff --git a/Documentation/Configure.help b/Documentation/Configure.help index bc8e754778d5..854c49b81e97 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -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 diff --git a/Documentation/cdrom/ide-cd b/Documentation/cdrom/ide-cd index 70384d975cd9..d6ceef8a5e1d 100644 --- a/Documentation/cdrom/ide-cd +++ b/Documentation/cdrom/ide-cd @@ -1,12 +1,12 @@ IDE-CD driver documentation -19 May 1996 -scott snyder +Originally by scott snyder (19 May 1996) +Carrying on the torch is: Erik Andersen 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 (?) diff --git a/Documentation/paride.txt b/Documentation/paride.txt index 1a6b46400174..923377cad69e 100644 --- a/Documentation/paride.txt +++ b/Documentation/paride.txt @@ -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.) diff --git a/Makefile b/Makefile index cbd64778738c..303abea28d1a 100644 --- 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 diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 67427be1b18a..bfad551993ba 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -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 diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 9f8cde775eea..64acd645b811 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -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 diff --git a/arch/alpha/kernel/apecs.c b/arch/alpha/kernel/apecs.c index 93c55b9262c5..d5e7fa2a71b8 100644 --- a/arch/alpha/kernel/apecs.c +++ b/arch/alpha/kernel/apecs.c @@ -18,6 +18,10 @@ #include #include +/* 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(); diff --git a/arch/alpha/kernel/cia.c b/arch/alpha/kernel/cia.c index 7ea930e5a0c0..4bebe2732288 100644 --- a/arch/alpha/kernel/cia.c +++ b/arch/alpha/kernel/cia.c @@ -17,6 +17,10 @@ #include #include +/* 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); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 222d042ed999..cd8541380a82 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -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 diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index f94915bb29a4..f1bfa1bef885 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -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. diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 9b430d148738..d1a96fc9da07 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -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])) diff --git a/arch/alpha/kernel/pyxis.c b/arch/alpha/kernel/pyxis.c index cbfd96d2a3d2..1e695dc3fdc1 100644 --- a/arch/alpha/kernel/pyxis.c +++ b/arch/alpha/kernel/pyxis.c @@ -16,6 +16,10 @@ #include #include +/* 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); diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 1d4e8931d4e4..1943b26f7179 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -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; diff --git a/arch/alpha/kernel/t2.c b/arch/alpha/kernel/t2.c index 76ed4dd14059..db3e29939c15 100644 --- a/arch/alpha/kernel/t2.c +++ b/arch/alpha/kernel/t2.c @@ -20,6 +20,10 @@ #include #include +/* 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; diff --git a/arch/i386/config.in b/arch/i386/config.in index f279cde8d82b..8f0582c93b2c 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -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 diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 11c398cba8be..2ca6da6bc4fc 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -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 diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index ab85b2df407f..4b03fc40378a 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -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); diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index ac83e4c7d6c2..16c97d946592 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -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, ®s); diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c index 1f8d0799dfca..de6de8f14518 100644 --- a/arch/i386/kernel/mca.c +++ b/arch/i386/kernel/mca.c @@ -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; diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 5d7d3a6fe62c..a05292d6d2b3 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -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; diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c index 36ca90a35107..f120bbc49739 100644 --- a/arch/i386/math-emu/fpu_entry.c +++ b/arch/i386/math-emu/fpu_entry.c @@ -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); diff --git a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c index 799bc1c416b1..a4b15ee7f50a 100644 --- a/arch/i386/math-emu/get_address.c +++ b/arch/i386/math-emu/get_address.c @@ -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); diff --git a/arch/i386/math-emu/reg_ld_str.c b/arch/i386/math-emu/reg_ld_str.c index 468e51cc8601..b3ed9acbb712 100644 --- a/arch/i386/math-emu/reg_ld_str.c +++ b/arch/i386/math-emu/reg_ld_str.c @@ -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); diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 0597ea3d677c..10e9f56d08c6 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -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 diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index caf334d27d56..d477b7eba8d5 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -3,13 +3,14 @@ * linux/drivers/block/ide-cd.c * Copyright (C) 1994, 1995, 1996 scott snyder * Copyright (C) 1996-1998 Erik Andersen + * * 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: @@ -182,10 +183,16 @@ * -- 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 #include @@ -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); diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c index 102e641ff28c..bb5432cb26b4 100644 --- a/drivers/block/ide-proc.c +++ b/drivers/block/ide-proc.c @@ -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 */ diff --git a/drivers/block/paride/Config.in b/drivers/block/paride/Config.in index 47489770619f..cc9479184516 100644 --- a/drivers/block/paride/Config.in +++ b/drivers/block/paride/Config.in @@ -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 diff --git a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile index a6fa9603aa67..61e710801716 100644 --- a/drivers/block/paride/Makefile +++ b/drivers/block/paride/Makefile @@ -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 diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c index 1d5530c7dbe3..0d7cf2f01c90 100644 --- a/drivers/block/paride/paride.c +++ b/drivers/block/paride/paride.c @@ -473,6 +473,11 @@ void paride_init( void ) pf_init(); }; #endif +#ifdef CONFIG_PARIDE_PT + { extern int pt_init(void); + pt_init(); + }; +#endif } #endif diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 177f898a497f..ca520d32b9c4 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -83,7 +83,13 @@ */ -#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 ) diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index e9efbcd54f83..aa431ae33dfa 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -96,7 +96,14 @@ */ -#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 #include #include +#include /* for the eject ioctl */ #include @@ -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 index 000000000000..b6b3d3fcb942 --- /dev/null +++ b/drivers/block/paride/pt.c @@ -0,0 +1,957 @@ +/* + pt.c (c) 1998 Grant R. Guenther + 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 ,,,,, + + Where, + + is the base of the parallel port address for + the corresponding drive. (required) + + 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) + + 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) + + this can be -1 to choose the best mode, or one + of the mode numbers supported by the adapter. + (-1 if not given) + + 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. + + 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 +#include +#include +#include +#include +#include +#include + +#include + +#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_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;ki_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 */ + diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 23ece7e7260a..48a3ae427de9 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -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 May be copied or modified under the terms of the GNU General Public License. See linux/COPYING for more information. @@ -10,46 +10,71 @@ 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 + -- 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 + -- 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 + -- 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 @@ -68,10 +93,6 @@ #include -#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 @@ -96,15 +117,17 @@ #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); diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 9a7b268716cd..7ff08bb85241 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -186,6 +186,10 @@ * Heiko Eissfeldt with additional * changes by Erik Andersen * + * 24 January 1998 -- Removed the scd_disc_status() function, which was now + * just dead code left over from the port. + * Erik Andersen + * */ #include @@ -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 diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index 65517ba5720b..e255fa54e649 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c @@ -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: diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c index 090d58498e8f..f806743e9bbc 100644 --- a/drivers/cdrom/mcd.c +++ b/drivers/cdrom/mcd.c @@ -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: diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 62396576a9ed..f3fce22d54d4 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -304,6 +304,9 @@ * Heiko Eissfeldt with additional * changes by Erik Andersen * + * 4.62 Fix a bug where playing audio left the drive in an unusable state. + * Heiko Eissfeldt + * * * 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; } diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 5139faba0853..01b90940a709 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -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 diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c index fd1ac0cd7135..6d40de3a198b 100644 --- a/drivers/char/ftape/lowlevel/fdc-io.c +++ b/drivers/char/ftape/lowlevel/fdc-io.c @@ -403,10 +403,10 @@ int fdc_interrupt_wait(unsigned int time) current->state = TASK_INTERRUPTIBLE; spin_lock_irq(¤t->sigmask_lock); - old_sigmask = current->blocked; - siginitset(¤t->blocked, _BLOCK_ALL); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); + old_sigmask = current->blocked; + sigfillset(¤t->blocked); + recalc_sigpending(current); + spin_unlock_irq(¤t->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(¤t->sigmask_lock); - current->blocked = old_sigmask; - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); + current->blocked = old_sigmask; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); remove_wait_queue(&ftape_wait_intr, &wait); /* the following IS necessary. True: as well diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 41527aa3f268..5bd5beabb0f4 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -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; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index fb30c3e0c9ba..47868a50323d 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -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 @@ -11,14 +13,58 @@ * lp_read (Status readback) support added by Carsten Gross, * carsten@sol.wohnheim.uni-ulm.de * Support for parport by Philip Blundell - * Reverted interrupt to polling at runtime if more than one device is parport - * registered and joined the interrupt and polling code. - * by Andrea Arcangeli + * parport_sharing hacking by Andrea Arcangeli */ -/* 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 +#include #include #include @@ -26,31 +72,24 @@ #include #include #include -#include #include #include +#include +#include + #include -#include #include #include -#include -#include /* 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++) { diff --git a/drivers/isdn/avmb1/b1capi.c b/drivers/isdn/avmb1/b1capi.c index a9f06c880c59..525f447f84e0 100644 --- a/drivers/isdn/avmb1/b1capi.c +++ b/drivers/isdn/avmb1/b1capi.c @@ -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 "); @@ -64,6 +65,7 @@ MODULE_PARM(irq, "2-15i"); MODULE_PARM(showcapimsgs, "0-3i"); MODULE_PARM(loaddebug, "0-1i"); #endif +#endif /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 595fb713e56a..7379c8a779e5 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -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"); diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c index 598dc8ca93cf..34f8fc1c54e6 100644 --- a/drivers/isdn/pcbit/module.c +++ b/drivers/isdn/pcbit/module.c @@ -22,10 +22,10 @@ #include #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); diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h index b0f07ac3c9cd..4a769822567b 100644 --- a/drivers/isdn/sc/hardware.h +++ b/drivers/isdn/sc/hardware.h @@ -16,11 +16,6 @@ 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 */ diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h index 6ce4fb06e5a8..951f06f258f8 100644 --- a/drivers/isdn/sc/includes.h +++ b/drivers/isdn/sc/includes.h @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index eeaecdd8ffdf..c9eb24035e65 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -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 diff --git a/drivers/misc/BUGS-parport b/drivers/misc/BUGS-parport index cecbf703be39..4fb4fd45aba0 100644 --- a/drivers/misc/BUGS-parport +++ b/drivers/misc/BUGS-parport @@ -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. + diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 1137f6e80ccc..9b4aab919405 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -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 diff --git a/drivers/misc/TODO-parport b/drivers/misc/TODO-parport index 5ffe406fa15e..08860cc27956 100644 --- a/drivers/misc/TODO-parport +++ b/drivers/misc/TODO-parport @@ -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). + + diff --git a/drivers/misc/parport_arc.c b/drivers/misc/parport_arc.c index 3a013b4cf218..f86ec75305f7 100644 --- a/drivers/misc/parport_arc.c +++ b/drivers/misc/parport_arc.c @@ -1,24 +1,32 @@ -/* Parallel-port routines for ARC onboard hardware. +/* Low-level parallel port routines for Archimedes onboard hardware * * Author: Phil Blundell */ -#include - -#include -#include -#include +/* 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 #include #include #include #include #include #include - #include -#include +#include +#include +#include +#include #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; +} diff --git a/drivers/misc/parport_ax.c b/drivers/misc/parport_ax.c index caaccd6e703a..c4f29e90334f 100644 --- a/drivers/misc/parport_ax.c +++ b/drivers/misc/parport_ax.c @@ -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 @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -36,116 +37,126 @@ #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) { diff --git a/drivers/misc/parport_init.c b/drivers/misc/parport_init.c index 1ccb67d3262c..3fc222ff9c90 100644 --- a/drivers/misc/parport_init.c +++ b/drivers/misc/parport_init.c @@ -1,6 +1,6 @@ /* Parallel-port initialisation code. * - * Authors: David Campbell + * Authors: David Campbell * Tim Waugh * Jose Renau * @@ -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); diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c index 71eb184ac004..3d9fabf1dc09 100644 --- a/drivers/misc/parport_pc.c +++ b/drivers/misc/parport_pc.c @@ -1,4 +1,4 @@ -/* Parallel-port routines for PC architecture +/* Low-level parallel-port routines for PC-style hardware. * * Authors: Phil Blundell * Tim Waugh @@ -8,6 +8,28 @@ * based on work by Grant Guenther 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 #include @@ -25,120 +47,112 @@ #include #include +#include -#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 ). */ +#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) { diff --git a/drivers/misc/parport_procfs.c b/drivers/misc/parport_procfs.c index e75fba3351f2..1817f876c5f1 100644 --- a/drivers/misc/parport_procfs.c +++ b/drivers/misc/parport_procfs.c @@ -1,10 +1,11 @@ /* Parallel port /proc interface code. * - * Authors: David Campbell - * Tim Waugh + * Authors: David Campbell + * Tim Waugh + * Philip Blundell * * based on work by Grant Guenther - * and Philip Blundell + * and Philip Blundell */ #include @@ -19,14 +20,10 @@ #include #include #include - #include - #include -#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; diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c index f12debcb8214..62af8735741c 100644 --- a/drivers/misc/parport_share.c +++ b/drivers/misc/parport_share.c @@ -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 * Tim Waugh - * Jose Renau + * Jose Renau + * Philip Blundell + * Andrea Arcangeli * * based on work by Grant Guenther - * and Philip Blundell + * and Philip Blundell */ +#undef PARPORT_DEBUG_SHARING /* undef for production */ + +#include + #include #include @@ -18,8 +24,9 @@ #include #include #include +#include -#include +#include #ifdef CONFIG_KERNELD #include @@ -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); } } diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c index d21df7bbb435..227a06976f67 100644 --- a/drivers/net/de4x5.c +++ b/drivers/net/de4x5.c @@ -369,11 +369,13 @@ Fix bug in pci_probe() for 64 bit systems reported by . 0.533 9-Jan-98 Fix more 64 bit bugs reported by . + 0.534 24-Jan-98 Fix last (?) endian bug from + ========================================================================= */ -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 @@ -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); diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c index 4e29cb6abc21..7c8c3b20fe7f 100644 --- a/drivers/net/dgrs.c +++ b/drivers/net/dgrs.c @@ -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 diff --git a/drivers/net/hamradio/soundmodem/gentbl.c b/drivers/net/hamradio/soundmodem/gentbl.c index d1dce6687792..4750c18ee91e 100644 --- a/drivers/net/hamradio/soundmodem/gentbl.c +++ b/drivers/net/hamradio/soundmodem/gentbl.c @@ -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"); } diff --git a/drivers/net/ne.c b/drivers/net/ne.c index efbfc54e4ec7..203e3fbf7a03 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -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); diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 1ebb58aea939..1fef280d25c4 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -7,7 +7,7 @@ * Dynamic PPP devices by Jim Freeman . * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid * - * ==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; } diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c index 3ec6dd4ba056..edb3d10f7690 100644 --- a/drivers/net/ppp_deflate.c +++ b/drivers/net/ppp_deflate.c @@ -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 diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index 187e51616bf3..13a020869b0e 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -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; } diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c index 5c1d0f3524af..f7f6151cba35 100644 --- a/drivers/net/tulip.c +++ b/drivers/net/tulip.c @@ -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. */ diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 2ab6b19ac98c..9c4b53d13a4a 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -12,7 +12,14 @@ 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 index 000000000000..551d2b6691e7 --- /dev/null +++ b/drivers/pci/oldproc.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7f43307ae9c4..dff9a4c6bc50 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -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 -#include #include #include #include @@ -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 index 000000000000..a28cc8aff700 --- /dev/null +++ b/drivers/pci/proc.c @@ -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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; + } + } +} diff --git a/drivers/pnp/parport_probe.c b/drivers/pnp/parport_probe.c index 836d1aa669df..8b735fb52511 100644 --- a/drivers/pnp/parport_probe.c +++ b/drivers/pnp/parport_probe.c @@ -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; } diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 6eccb24c75db..ba1753147fb6 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -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; }; diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index cf5a87814d31..243be1eca8ac 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -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); } } diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index 9b6fa5c1258e..592006f09a83 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -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: diff --git a/drivers/sound/sb_mixer.h b/drivers/sound/sb_mixer.h index 205b7ea341b1..2f68a62f3611 100644 --- a/drivers/sound/sb_mixer.h +++ b/drivers/sound/sb_mixer.h @@ -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), diff --git a/drivers/sound/softoss.c b/drivers/sound/softoss.c index ee8409f175b7..ff11018a2b19 100644 --- a/drivers/sound/softoss.c +++ b/drivers/sound/softoss.c @@ -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; diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 3e78be073fd2..37daaa3c3673 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -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; diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 47675bf29da7..71106655b7cc 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -11,12 +11,14 @@ #include /* - * 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 */ }; diff --git a/fs/filesystems.c b/fs/filesystems.c index cb7b843b0552..996b42279823 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c @@ -37,6 +37,10 @@ #include #include +#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); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 77421855f30d..8d75f3b85d44 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -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)) { diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 54e0ceabee6d..8300fee67030 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -32,9 +32,12 @@ #include #include +#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; } diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 8879e02a853c..216aafb80882 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -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) { diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8f2e40711cd5..e4bf46f41760 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -46,7 +46,6 @@ * Copyright (C) 1996, 1997, Olaf Kirch */ -#define NFS_NEED_XDR_TYPES #include #include #include @@ -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. diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index f9d7e8060e86..77a158612e42 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -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); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index cba32eea781c..0164b6a7e335 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -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 */ /* diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index e3b6b9303638..48ab4cbeba77 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -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 diff --git a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c index 1f50a26dc712..b0c7a49b49e0 100644 --- a/fs/nls/nls_cp862.c +++ b/fs/nls/nls_cp862.c @@ -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) { diff --git a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c index 6b6c7a99e8d7..cea3d163d523 100644 --- a/fs/nls/nls_cp863.c +++ b/fs/nls/nls_cp863.c @@ -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) { diff --git a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c index e425d5d48531..972c728bdfeb 100644 --- a/fs/nls/nls_cp864.c +++ b/fs/nls/nls_cp864.c @@ -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) { diff --git a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c index 7763b9ddd479..c681274504a6 100644 --- a/fs/nls/nls_cp865.c +++ b/fs/nls/nls_cp865.c @@ -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) { diff --git a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c index 985b2dfbbe77..d548247046b1 100644 --- a/fs/nls/nls_cp866.c +++ b/fs/nls/nls_cp866.c @@ -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) { diff --git a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c index 1edac6b6342d..586fb993648d 100644 --- a/fs/nls/nls_cp869.c +++ b/fs/nls/nls_cp869.c @@ -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) { diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c index 26350555ffc5..b2c35c843c16 100644 --- a/fs/nls/nls_cp874.c +++ b/fs/nls/nls_cp874.c @@ -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) { diff --git a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c index 3b32a706e62e..94ff9c39c429 100644 --- a/fs/nls/nls_iso8859-1.c +++ b/fs/nls/nls_iso8859-1.c @@ -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) { diff --git a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c index b21961b69ea8..8349b879a25c 100644 --- a/fs/nls/nls_iso8859-2.c +++ b/fs/nls/nls_iso8859-2.c @@ -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) { diff --git a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c index d5d7f7f27b04..23af5447b9a0 100644 --- a/fs/nls/nls_iso8859-3.c +++ b/fs/nls/nls_iso8859-3.c @@ -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) { diff --git a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c index f03aaaa2c71e..abbe1bd9bd53 100644 --- a/fs/nls/nls_iso8859-4.c +++ b/fs/nls/nls_iso8859-4.c @@ -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) { diff --git a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c index 94bece0bb833..1fe18003f329 100644 --- a/fs/nls/nls_iso8859-5.c +++ b/fs/nls/nls_iso8859-5.c @@ -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) { diff --git a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c index 050aee92dc49..7ed46f426ef4 100644 --- a/fs/nls/nls_iso8859-6.c +++ b/fs/nls/nls_iso8859-6.c @@ -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) { diff --git a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c index 3790378acfb2..180ac239b3ce 100644 --- a/fs/nls/nls_iso8859-7.c +++ b/fs/nls/nls_iso8859-7.c @@ -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) { diff --git a/fs/nls/nls_iso8859-8.c b/fs/nls/nls_iso8859-8.c index b639b739207a..054f5a4a8af3 100644 --- a/fs/nls/nls_iso8859-8.c +++ b/fs/nls/nls_iso8859-8.c @@ -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) { diff --git a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c index aef5b410e999..eaa8c4c68ad8 100644 --- a/fs/nls/nls_iso8859-9.c +++ b/fs/nls/nls_iso8859-9.c @@ -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) { diff --git a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c index 8d08ba3ef972..c6ee51f99151 100644 --- a/fs/nls/nls_koi8-r.c +++ b/fs/nls/nls_koi8-r.c @@ -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) { diff --git a/fs/proc/array.c b/fs/proc/array.c index e4f1003fdcf1..ae477843b80e 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -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 diff --git a/fs/proc/root.c b/fs/proc/root.c index ae9ccce2e6bd..d8c80cc9b3b6 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -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 index 000000000000..090c328fed92 --- /dev/null +++ b/fs/sysv/CHANGES @@ -0,0 +1,9 @@ +Mon Dec 15 1997 Krzysztof G. Baranowski + * namei.c: struct sysv_dir_inode_operations updated to use dentries. + +Fri Jan 23 1998 Krzysztof G. Baranowski + * 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 + for identifying the problem. diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 0201ff6458ac..457a869f9ec3 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -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) { diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index 01ab086d2e3e..f147967adcc9 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -10,11 +10,8 @@ * sysv/namei.c * Copyright (C) 1993 Bruno Haible * - * - * Revised: 15 Dec 1997 by Krzysztof G. Baranowski - * Driver updated to use dentries. */ - + #include #include diff --git a/fs/ufs/ufs_swab.c b/fs/ufs/ufs_swab.c index 2dc4061a09c1..40fa75101c8a 100644 --- a/fs/ufs/ufs_swab.c +++ b/fs/ufs/ufs_swab.c @@ -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 } diff --git a/include/asm-alpha/mman.h b/include/asm-alpha/mman.h index a08ec81df7fd..ddfe6bda47da 100644 --- a/include/asm-alpha/mman.h +++ b/include/asm-alpha/mman.h @@ -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 */ diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h index d206bcc3b630..f7596af913db 100644 --- a/include/asm-alpha/smp.h +++ b/include/asm-alpha/smp.h @@ -1,6 +1,8 @@ #ifndef __ASM_SMP_H #define __ASM_SMP_H +#define cpu_logical_map(cpu) (cpu) + /* We'll get here eventually.. */ #endif diff --git a/include/asm-alpha/softirq.h b/include/asm-alpha/softirq.h index 456103536318..3cf28cc1c1c9 100644 --- a/include/asm-alpha/softirq.h +++ b/include/asm-alpha/softirq.h @@ -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 diff --git a/include/asm-alpha/types.h b/include/asm-alpha/types.h index 28e5d487de08..381d5f0441dc 100644 --- a/include/asm-alpha/types.h +++ b/include/asm-alpha/types.h @@ -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 diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h index daf90d709694..c7c32636689a 100644 --- a/include/asm-alpha/unistd.h +++ b/include/asm-alpha/unistd.h @@ -156,7 +156,7 @@ #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 @@ -186,7 +186,7 @@ #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 diff --git a/include/asm-i386/softirq.h b/include/asm-i386/softirq.h index a28f6bae8d72..7b642d667ac4 100644 --- a/include/asm-i386/softirq.h +++ b/include/asm-i386/softirq.h @@ -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 */ diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h index 71309ac823de..d792546f9fb7 100644 --- a/include/asm-i386/types.h +++ b/include/asm-i386/types.h @@ -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 diff --git a/include/asm-m68k/types.h b/include/asm-m68k/types.h index 945edb982a1a..b0ece7bda893 100644 --- a/include/asm-m68k/types.h +++ b/include/asm-m68k/types.h @@ -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 */ diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h index 4d27f768b18a..3f8f9da78f27 100644 --- a/include/asm-mips/types.h +++ b/include/asm-mips/types.h @@ -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 diff --git a/include/linux/adfs_fs.h b/include/linux/adfs_fs.h index 15d7d7a9ce09..453bb9258cba 100644 --- a/include/linux/adfs_fs.h +++ b/include/linux/adfs_fs.h @@ -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 */ diff --git a/include/linux/adfs_fs_fs.h b/include/linux/adfs_fs_fs.h index c2b0d8d31f4d..7fff6be19fb6 100644 --- a/include/linux/adfs_fs_fs.h +++ b/include/linux/adfs_fs_fs.h @@ -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 */ diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h index 11cbc7e7268e..79e3c3639d5c 100644 --- a/include/linux/affs_fs.h +++ b/include/linux/affs_fs.h @@ -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 */ diff --git a/include/linux/isdn.h b/include/linux/isdn.h index ea45d35cb592..f7b4747d38a0 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -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 *, diff --git a/include/linux/lp.h b/include/linux/lp.h index 368cd9bef015..1566fee80d50 100644 --- a/include/linux/lp.h +++ b/include/linux/lp.h @@ -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... @@ -89,20 +94,6 @@ #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 */ diff --git a/include/linux/nfs.h b/include/linux/nfs.h index 2a6a4c080715..c4aab89e1103 100644 --- a/include/linux/nfs.h +++ b/include/linux/nfs.h @@ -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; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 666e5bde4f60..9a2d8a67f39b 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -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 *); diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h index 722a9930dce5..885f21f01de4 100644 --- a/include/linux/nfs_fs_i.h +++ b/include/linux/nfs_fs_i.h @@ -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 diff --git a/include/linux/nls.h b/include/linux/nls.h index 73f83633dc89..3321e29587fd 100644 --- a/include/linux/nls.h +++ b/include/linux/nls.h @@ -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); diff --git a/include/linux/parport.h b/include/linux/parport.h index 6a2bbd183cd0..102594683683 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -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 #include +#include #include +#include + +#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 +#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 index 000000000000..3d6e5cb27dfa --- /dev/null +++ b/include/linux/parport_pc.h @@ -0,0 +1,117 @@ +#ifndef __LINUX_PARPORT_PC_H +#define __LINUX_PARPORT_PC_H + +#include + +/* --- 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 diff --git a/include/linux/pci.h b/include/linux/pci.h index 4763d4b2168b..92730ee38ba0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -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 * - * 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 @@ -102,7 +81,7 @@ */ #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 */ @@ -118,6 +97,7 @@ #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 @@ -131,6 +111,46 @@ #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 @@ -175,7 +195,6 @@ #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 @@ -856,7 +875,6 @@ #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 @@ -869,6 +887,7 @@ #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 */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index ce31bacd13b9..c5a6054eea21 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -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); diff --git a/include/linux/sched.h b/include/linux/sched.h index ed896058edf1..bad6d16101ef 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -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, \ diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h index 96bc89fd276b..2e83cf446987 100644 --- a/include/linux/smb_fs.h +++ b/include/linux/smb_fs.h @@ -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 *); diff --git a/init/main.c b/init/main.c index f776efa02e61..d592ad3267af 100644 --- a/init/main.c +++ b/init/main.c @@ -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 } }; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 0573176510f5..96db1f7176e5 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -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 */ diff --git a/kernel/signal.c b/kernel/signal.c index 521fad227cfb..6149741a092e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -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(¤t->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(¤t->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(¤t->sigmask_lock); old_set = current->blocked; spin_unlock_irq(¤t->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(¤t->sigmask_lock); sigandsets(&pending, ¤t->blocked, ¤t->signal); spin_unlock_irq(¤t->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(¤t->sigmask_lock); old_set = current->blocked.sig[0]; + error = 0; switch (how) { default: - return -EINVAL; + error = -EINVAL; + break; case SIG_BLOCK: sigaddsetmask(¤t->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(¤t->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(¤t->sigmask_lock); pending = current->blocked.sig[0] & current->signal.sig[0]; spin_unlock_irq(¤t->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 diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index c0efdb1caa06..589c8f6bdb9b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -70,6 +70,14 @@ #include #endif +#ifdef CONFIG_BRIDGE +#include +#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. diff --git a/net/socket.c b/net/socket.c index 3be15da633bd..6670bcf904f8 100644 --- a/net/socket.c +++ b/net/socket.c @@ -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)) { diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index ccc1ce0e3a17..f214a949ed8c 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -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 diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index b95b39425352..088487077e67 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -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 */ -- 2.39.5