From 0239d6ee919c07007483baad5ab73ce8199987d3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:33:41 -0500 Subject: [PATCH] Import 2.3.99pre4-3 --- CREDITS | 9 + Documentation/Configure.help | 3817 ++++++++++------- Documentation/DocBook/Makefile | 2 + Documentation/DocBook/kernel-api.tmpl | 94 +- .../{parportbook.sgml => parportbook.tmpl} | 0 Documentation/sound/PAS16 | 185 + Documentation/usb/CREDITS | 1 + Documentation/usb/ibmcam.txt | 58 +- Documentation/video4linux/bttv/CARDLIST | 2 + Makefile | 5 +- arch/alpha/kernel/osf_sys.c | 89 +- arch/i386/defconfig | 11 +- arch/ia64/ia32/sys_ia32.c | 11 +- arch/mips/kernel/sysirix.c | 2 +- arch/ppc/8xx_io/uart.c | 1 + arch/sparc/kernel/signal.c | 4 +- arch/sparc/kernel/sys_sunos.c | 93 +- arch/sparc/mm/sun4c.c | 12 +- arch/sparc64/kernel/signal.c | 4 +- arch/sparc64/kernel/signal32.c | 4 +- arch/sparc64/kernel/sys_sparc32.c | 29 +- arch/sparc64/kernel/sys_sunos32.c | 118 +- arch/sparc64/solaris/fs.c | 41 +- arch/sparc64/solaris/misc.c | 2 +- bad | 22 + drivers/acorn/scsi/acornscsi.h | 5 + drivers/acorn/scsi/arxescsi.c | 21 +- drivers/acorn/scsi/arxescsi.h | 38 +- drivers/acorn/scsi/cumana_2.c | 55 +- drivers/acorn/scsi/cumana_2.h | 45 +- drivers/acorn/scsi/eesox.c | 76 +- drivers/acorn/scsi/eesox.h | 37 +- drivers/acorn/scsi/fas216.c | 1032 +++-- drivers/acorn/scsi/fas216.h | 12 +- drivers/acorn/scsi/msgqueue.h | 2 +- drivers/acorn/scsi/powertec.c | 51 +- drivers/acorn/scsi/powertec.h | 43 +- drivers/acorn/scsi/queue.h | 2 +- drivers/block/xd.c | 43 +- drivers/char/Config.in | 1 + drivers/char/Makefile | 1 + drivers/char/bttv.c | 241 +- drivers/char/bttv.h | 5 +- drivers/char/console.c | 2 - drivers/char/joystick/joy-spaceball.c | 6 +- drivers/char/joystick/joy-spaceorb.c | 6 +- drivers/char/joystick/joy-warrior.c | 25 +- drivers/char/joystick/joystick.c | 84 +- drivers/char/n_r3964.c | 10 +- drivers/char/pty.c | 4 - drivers/char/serial.c | 4 - drivers/char/tty_io.c | 3 - drivers/char/tuner.c | 3 +- drivers/char/wd501p.h | 25 +- drivers/char/wdt_pci.c | 558 +++ drivers/net/8390.c | 19 +- drivers/net/Config.in | 6 +- drivers/net/Space.c | 8 +- drivers/net/defxx.c | 195 +- drivers/net/defxx.h | 1 + drivers/net/pcmcia/Config.in | 1 + drivers/net/pcmcia/Makefile | 9 + drivers/net/pcmcia/ibmtr_cs.c | 635 +++ drivers/net/tokenring/ibmtr.c | 50 +- drivers/net/wan/z85230.c | 2 +- drivers/parport/share.c | 30 +- drivers/scsi/ChangeLog.ncr53c8xx | 10 + drivers/scsi/ChangeLog.sym53c8xx | 8 + drivers/scsi/ncr53c8xx.c | 34 +- drivers/scsi/sym53c8xx.c | 25 +- drivers/scsi/sym53c8xx_comm.h | 10 - drivers/sound/Makefile | 4 - drivers/sound/dev_table.c | 39 +- drivers/sound/dev_table.h | 16 +- drivers/sound/sound_calls.h | 7 - drivers/sound/sound_core.c | 20 +- drivers/sound/soundcard.c | 163 +- drivers/telephony/phonedev.c | 24 +- drivers/usb/acm.c | 14 +- drivers/usb/evdev.c | 47 + drivers/usb/ibmcam.c | 39 +- drivers/usb/pegasus.c | 2 +- drivers/usb/serial/ftdi_sio.c | 665 ++- drivers/usb/serial/ftdi_sio.h | 573 +-- drivers/usb/usb-core.c | 1 + drivers/usb/usb-storage.c | 161 +- drivers/usb/usb.c | 40 +- fs/Config.in | 1 + fs/adfs/dir.c | 2 +- fs/autofs/dirhash.c | 3 +- fs/autofs/root.c | 6 +- fs/autofs/symlink.c | 4 +- fs/autofs4/root.c | 4 +- fs/autofs4/symlink.c | 3 +- fs/bad_inode.c | 22 +- fs/dcache.c | 184 +- fs/devfs/base.c | 10 +- fs/dquot.c | 14 +- fs/exec.c | 15 +- fs/ext2/symlink.c | 4 +- fs/file_table.c | 4 + fs/hfs/dir.c | 12 +- fs/hpfs/dir.c | 2 +- fs/inode.c | 123 +- fs/ioctl.c | 4 +- fs/lockd/clntlock.c | 2 +- fs/lockd/clntproc.c | 94 +- fs/lockd/host.c | 35 +- fs/lockd/mon.c | 44 +- fs/lockd/svc4proc.c | 15 +- fs/lockd/svclock.c | 43 +- fs/lockd/svcproc.c | 8 +- fs/lockd/svcsubs.c | 4 +- fs/lockd/xdr.c | 95 +- fs/lockd/xdr4.c | 66 +- fs/locks.c | 47 +- fs/namei.c | 84 +- fs/nfs/Makefile | 3 + fs/nfs/dir.c | 201 +- fs/nfs/file.c | 4 +- fs/nfs/inode.c | 215 +- fs/nfs/mount_clnt.c | 65 +- fs/nfs/nfs2xdr.c | 251 +- fs/nfs/nfs3proc.c | 477 ++ fs/nfs/nfs3xdr.c | 1147 +++-- fs/nfs/nfsroot.c | 44 +- fs/nfs/proc.c | 294 +- fs/nfs/read.c | 50 +- fs/nfs/symlink.c | 18 +- fs/nfs/write.c | 23 +- fs/nfsd/lockd.c | 3 +- fs/open.c | 85 +- fs/proc/array.c | 4 +- fs/proc/base.c | 45 +- fs/proc/generic.c | 4 +- fs/proc/root.c | 3 +- fs/read_write.c | 13 - fs/super.c | 194 +- fs/ufs/symlink.c | 4 +- fs/umsdos/dir.c | 5 +- include/asm-alpha/namei.h | 3 +- include/asm-arm/namei.h | 41 +- include/asm-i386/namei.h | 3 +- include/asm-ia64/namei.h | 3 +- include/asm-m68k/namei.h | 3 +- include/asm-mips/namei.h | 36 +- include/asm-mips64/namei.h | 3 +- include/asm-ppc/namei.h | 3 +- include/asm-sh/namei.h | 3 +- include/asm-sparc/namei.h | 43 +- include/asm-sparc64/namei.h | 43 +- include/linux/dcache.h | 49 +- include/linux/fs.h | 55 +- include/linux/ibmtr.h | 454 ++ include/linux/input.h | 28 + include/linux/lockd/lockd.h | 2 + include/linux/lockd/nlm.h | 7 +- include/linux/mount.h | 28 +- include/linux/nfs.h | 52 +- include/linux/nfs2.h | 52 +- include/linux/nfs3.h | 123 - include/linux/nfs_fs.h | 3 + include/linux/nfs_fs_i.h | 1 + include/linux/nfs_fs_sb.h | 2 + include/linux/nfs_mount.h | 5 +- include/linux/nfs_xdr.h | 283 +- include/linux/nfsd/const.h | 8 +- include/linux/proc_fs_i.h | 2 +- include/linux/sched.h | 3 +- include/linux/sunrpc/xdr.h | 4 + include/linux/swap.h | 2 +- include/linux/tty.h | 3 + include/net/sock.h | 20 +- ipc/shm.c | 140 +- kernel/acct.c | 5 +- kernel/exit.c | 4 +- kernel/fork.c | 2 + kernel/kmod.c | 22 +- kernel/ksyms.c | 5 +- kernel/panic.c | 17 + mm/page_alloc.c | 2 + mm/slab.c | 2 +- mm/swapfile.c | 2 +- net/core/filter.c | 29 +- net/khttpd/security.c | 6 +- net/khttpd/waitheaders.c | 7 - net/sunrpc/clnt.c | 1 + net/sunrpc/sunrpc_syms.c | 3 + net/sunrpc/xdr.c | 62 +- net/unix/af_unix.c | 52 +- scripts/Menuconfig | 8 +- scripts/checkincludes.pl | 24 + scripts/gen-all-syms | 2 +- 193 files changed, 10407 insertions(+), 5378 deletions(-) rename Documentation/DocBook/{parportbook.sgml => parportbook.tmpl} (100%) create mode 100644 Documentation/sound/PAS16 create mode 100644 bad create mode 100644 drivers/char/wdt_pci.c create mode 100644 drivers/net/pcmcia/ibmtr_cs.c create mode 100644 fs/nfs/nfs3proc.c create mode 100644 include/linux/ibmtr.h create mode 100644 scripts/checkincludes.pl diff --git a/CREDITS b/CREDITS index c3a9856671c6..94cc57c7fc73 100644 --- a/CREDITS +++ b/CREDITS @@ -2115,6 +2115,15 @@ S: 301/222 City Walk S: Canberra ACT 2601 S: Australia +N: Bill Ryder +E: bryder@sgi.com +D: FTDI_SIO usb/serial converter driver +W: http://reality.sgi.com/bryder_wellington/ftdi_sio +S: I/3 Walter St +S: Wellington +S: New Zealand + + N: Sampo Saaristo E: sambo@cs.tut.fi D: Co-author of Multi-Protocol Over ATM (MPOA) diff --git a/Documentation/Configure.help b/Documentation/Configure.help index b2e31fd69b6b..d62cd9533f50 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -59,7 +59,7 @@ # All this was shamelessly stolen from several different sources. Many # thanks to all the contributors. Feel free to use these help texts in # your own kernel configuration tools. The texts are copyrighted (c) -# 1995-1999 by Axel Boldt and many others and are governed by the GNU +# 1995-2000 by Axel Boldt and many others and are governed by the GNU # General Public License. Prompt for development and/or incomplete code/drivers @@ -112,18 +112,23 @@ CONFIG_SMP Y to "Enhanced Real Time Clock Support", below. The "Advanced Power Management" code will be disabled if you say Y here. - See also: Documentation/SMP.txt, Documentation/smp.tex, - Documentation/smp.txt, and Documentation/IO-APIC.txt. Also see the + See also the files Documentation/smp.tex, Documentation/smp.txt, + Documentation/IO-APIC.txt, Documentation/nmi_watchdog.txt and the SMP-FAQ on the WWW at http://www.irisa.fr/prive/mentre/smp-faq/ . If you don't know what to do here, say N. APIC and IO-APIC Support on Uniprocessors CONFIG_X86_UP_IOAPIC - This option enables uniprocessor-kernels to switch into IO-APIC mode - if there is an IO-APIC in the system. Such a kernel will still boot - on IO-APIC-less systems with no slowdown at all. SMP kernels include - IO-APIC support unconditionally. + APIC (Advanced Programmable Interrupt Controller) is a scheme for + delivering hardware interrupt requests to the CPU. It is commonly + used on systems with several CPU's. If you have a single-CPU system + which uses APIC, you can say Y here to use it. If you say Y here + even though your machine doesn't have APIC, then the kernel will + still run with now slowdown at all. + + If you have system with several CPU's, you do not need to say Y + here: APIC will be used automatically. Kernel math emulation CONFIG_MATH_EMULATION @@ -140,10 +145,8 @@ CONFIG_MATH_EMULATION command line option "no387", which comes handy if your coprocessor is broken. Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to pass options to the kernel at - boot time. The lilo procedure is also explained in the SCSI-HOWTO, - available from http://www.linuxdoc.org/docs.html#howto .) This - means that it is a good idea to say Y here if you intend to use this - kernel on different machines. + boot time.) This means that it is a good idea to say Y here if you + intend to use this kernel on different machines. More information about the internals of the Linux math coprocessor emulation can be found in arch/i386/math-emu/README. @@ -277,7 +280,10 @@ CONFIG_BLK_DEV_LOOP This is useful if you want to check an ISO 9660 file system before burning the CD, or if you want to use floppy images without first - writing them to floppy. + writing them to floppy. Furthermore, some Linux distributions avoid + the need for a dedicated Linux partition by keeping their complete + root file system inside a DOS FAT file using this loop device + driver. The loop device driver can also be used to "hide" a file system in a disk partition, floppy, or regular file, either using encryption @@ -289,13 +295,13 @@ CONFIG_BLK_DEV_LOOP ftp://verden.pvv.org/pub/linux/kerneli/v2.1/ , and then you need to say Y to this option. - Note that alternative ways to use encrypted file systems are provided - by the cfs package, which can be gotten from + Note that alternative ways to use encrypted file systems are + provided by the cfs package, which can be gotten from ftp://ftp.replay.com/pub/crypto/disk/ , and the newer tcfs package, available at http://tcfs.dia.unisa.it/ . You do not need to say Y here if you want to use one of these. However, using cfs requires - saying Y to "NFS file system support" below while using tcfs requires - applying a kernel patch. + saying Y to "NFS file system support" below while using tcfs + requires applying a kernel patch. To use the loop device, you need the losetup utility and a recent version of the mount program, both contained in the util-linux @@ -341,35 +347,39 @@ CONFIG_BLK_DEV_NBD ATA/IDE/MFM/RLL support CONFIG_IDE - If you say Y here, your kernel will be able to manage low cost mass storage - units such as ATA/(E)IDE and ATAPI units. + If you say Y here, your kernel will be able to manage low cost mass + storage units such as ATA/(E)IDE and ATAPI units. The most common + cases are IDE hard drives and ATAPI CDROM drives. - Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard for - mass storage units such as hard disks. It was designed by Western Digital - and Compaq Computer in 1984. It was then named ST506. - Quite a number of disks use IDE interface. State of the art disks use SCSI - interface. + If your system is pure SCSI and doesn't use these interfaces, you + can say N here. + + Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard + for mass storage units such as hard disks. It was designed by + Western Digital and Compaq Computer in 1984. It was then named + ST506. Quite a number of disks use the IDE interface. - AT Atachment (ATA) is a subset of the IDE specifications. + AT Attachment (ATA) is a subset of the IDE specifications. ST506 was also called ATA-1. - Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is ATA-3. It - provides support for larger disks (up to 8.4GB by means of the LBA standard), - more disks (4 instead of 2) and for other mass storage units such as tapes - and cdrom. - UDMA/33 (aka UltraDMA/33) is ATA-4 and provides faster (and more CPU friendly) - transfer modes than previous PIO (Programmed processor Input/Ouput) from - previous ATA/IDE standards by means of fast DMA controlers. + Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is + ATA-3. It provides support for larger disks (up to 8.4GB by means of + the LBA standard), more disks (4 instead of 2) and for other mass + storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is + ATA-4 and provides faster (and more CPU friendly) transfer modes + than previous PIO (Programmed processor Input/Output) from previous + ATA/IDE standards by means of fast DMA controllers. - ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and CDROM - drives, similar in many respects to the SCSI protocol. + ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and + CDROM drives, similar in many respects to the SCSI protocol. - SMART IDE (Self Monitoring, Analysis and Reporting Technology) was designed - in order to prevent data corruption and disk crash by detecting pre hardware - faillure conditions (heat, access time, and the like...). Disks builded since - june 1995 may follow this standard. The kernel itself don't manage this; - however there are quite a number of user programs such as smart that can - query the status of SMART parameters disk. + SMART IDE (Self Monitoring, Analysis and Reporting Technology) was + designed in order to prevent data corruption and disk crash by + detecting pre hardware failure conditions (heat, access time, and + the like...). Disks built since June 1995 may follow this + standard. The kernel itself don't manage this; however there are + quite a number of user programs such as smart that can query the + status of SMART parameters disk. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -385,15 +395,15 @@ CONFIG_BLK_DEV_IDE If you say Y here, you will use the full-featured IDE driver to control up to ten ATA/IDE interfaces, each being able to serve a "master" and a "slave" device, for a total of up to twenty ATA/IDE - disk/cdrom/tape/floppy drives. People with SCSI-only systems - can say N or M here. + disk/cdrom/tape/floppy drives. Useful information about large (>540 MB) IDE disks, multiple interfaces, what to do if ATA/IDE devices are not automatically - detected, sound card ATA/IDE ports, module support, and other topics, is - contained in Documentation/ide.txt. For detailed information about - hard drives, consult the Disk-HOWTO and the Multi-Disk-HOWTO, - available from http://www.linuxdoc.org/docs.html#howto . + detected, sound card ATA/IDE ports, module support, and other + topics, is contained in Documentation/ide.txt. For detailed + information about hard drives, consult the Disk-HOWTO and the + Multi-Disk-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . To fine-tune ATA/IDE drive/interface parameters for improved performance, look for the hdparm package at @@ -403,7 +413,7 @@ CONFIG_BLK_DEV_IDE inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt and Documentation/ide.txt. The module will be called ide-mod.o. Do not - compile this driver as a module if your root filesystem (the one + compile this driver as a module if your root file system (the one containing the directory /) is located on an IDE device. If you have one or more IDE drives, say Y or M here. If your system @@ -428,8 +438,6 @@ CONFIG_BLK_DEV_HD_ONLY Disk-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . - People with SCSI-only systems can say N here. - Use old disk-only driver on primary interface CONFIG_BLK_DEV_HD_IDE There are two drivers for MFM/RLL/IDE disks. Most people use just @@ -446,9 +454,6 @@ CONFIG_BLK_DEV_HD_IDE Normally, just say N here; you will then use the new driver for all 4 interfaces. - People with SCSI-only systems don't need this and can say N here as - well. - Include IDE/ATA-2 DISK support CONFIG_BLK_DEV_IDEDISK This will include enhanced support for MFM/RLL/IDE hard disks. If @@ -505,8 +510,8 @@ CONFIG_BLK_DEV_IDETAPE to the SCSI protocol. If you have an SCSI tape drive however, you can say N here. - This now includes the OnStream DI-30 tape drive support. - Will not work with SCSI protocol, until there is support for the + You should also say Y if you have an OnStream DI-30 tape drive; this + will not work with the SCSI protocol, until there is support for the SC-30 and SC-50 versions. If you say Y here, the tape drive will be identified at boot time @@ -547,14 +552,17 @@ CONFIG_BLK_DEV_IDESCSI and will allow you to use a SCSI device driver instead of a native ATAPI driver. - Must pass "hdx=scsi" per devices if you want the native EIDE sub-drivers - to skip over the native support. This is required for use of CD-RW's. - This is useful if you have an ATAPI device for which no native driver has been written (for example, an ATAPI PD-CD or CDR drive); you can then use this emulation together with an appropriate SCSI device driver. In order to do this, say Y here and to "SCSI support" - and "SCSI generic support", below. + and "SCSI generic support", below. You must then provide the kernel + command line "hdx=scsi" (try "man bootparam" or see the + documentation of your boot loader (lilo or loadlin) about how to + pass options to the kernel at boot time) for devices if you want the + native EIDE sub-drivers to skip over the native support, so that + this SCSI emulation can be used instead. This is required for use of + CD-RW's. Note that this option does NOT allow you to attach SCSI devices to a box that doesn't have a SCSI host adapter installed. @@ -562,12 +570,10 @@ CONFIG_BLK_DEV_IDESCSI If both this SCSI emulation and native ATAPI support are compiled into the kernel, the native support will be used. - People with SCSI-only systems can say N here. If unsure, say N. - ISA-PNP EIDE support CONFIG_BLK_DEV_ISAPNP - If you have an ISA EIDE card that is PnP and requires setup first - before scanning for devices, say Y here. + If you have an ISA EIDE card that is PnP (Plug and Play) and + requires setup first before scanning for devices, say Y here. If unsure, say N. @@ -587,16 +593,12 @@ CONFIG_BLK_DEV_CMD640 (VLB) instead of PCI, you must also supply a kernel boot parameter to enable the CMD640 bugfix/support: "ide0=cmd640_vlb". (Try "man bootparam" or see the documentation of your boot loader about how to - pass options to the kernel. The lilo procedure is also explained in - the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + pass options to the kernel.) The CMD640 chip is also used on add-in cards by Acculogic, and on the "CSA-6400E PCI to IDE controller" that some people have. For details, read Documentation/ide.txt. - People with SCSI-only systems should say N here. If unsure, say Y. - CMD640 enhanced support CONFIG_BLK_DEV_CMD640_ENHANCED This option includes support for setting/autotuning PIO modes and @@ -615,16 +617,12 @@ CONFIG_BLK_DEV_RZ1000 Linux. This may slow disk throughput by a few percent, but at least things will operate 100% reliably. - People with SCSI-only systems should say N here. If unsure, say Y. - Generic PCI IDE chipset support CONFIG_BLK_DEV_IDEPCI Say Y here for PCI systems which use IDE drive(s). This option helps the IDE driver to automatically detect and configure all PCI-based IDE interfaces in your system. - People with SCSI-only systems should say N here; if unsure say Y. - Support for sharing PCI IDE interrupts CONFIG_IDEPCI_SHARE_IRQ Some ATA/IDE chipsets have hardware support which allows for @@ -646,8 +644,8 @@ CONFIG_BLK_DEV_IDEDMA_PCI the latest version of the hdparm utility from ftp://metalab.unc.edu/pub/Linux/system/hardware/ . - Read the comments at the beginning of drivers/ide/ide-dma.c and the - file Documentation/ide.txt for more information. + Read the comments at the beginning of drivers/ide/ide-dma.c and + the file Documentation/ide.txt for more information. It is safe to say Y to this question. @@ -671,16 +669,14 @@ CONFIG_BLK_DEV_OFFBOARD cards (off-board controllers) are relegated to ide2 and ide3. Answering Y here will allow you to reverse the situation, with off-board controllers on ide0/1 and on-board controllers on ide2/3. - This can improve the usability of some boot managers such as LILO + This can improve the usability of some boot managers such as lilo when booting from a drive on an off-board controller. If you say Y here, and you actually want to reverse the device scan order as explained above, you also need to issue the kernel command line option "ide=reverse". (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time. The lilo procedure is also - explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + pass options to the kernel at boot time.) Note that, if you do this, the order of the hd* devices will be rearranged which may require modification of fstab and other files. @@ -693,7 +689,7 @@ CONFIG_IDEDMA_PCI_AUTO DMA for IDE drives and chipsets which support it. Due to concerns about a couple of cases where buggy hardware may have caused damage, the default is now to NOT use DMA automatically. To revert to the - previous behavior, say Y to this question. + previous behaviour, say Y to this question. If you suspect your hardware is at all flakey, say N here. Do NOT email the IDE kernel people regarding this issue! @@ -703,8 +699,9 @@ CONFIG_IDEDMA_PCI_AUTO Various ATA, Work(s) In Progress (EXPERIMENTAL) CONFIG_IDEDMA_PCI_WIP - If you enable this you will be capable of using and testing - highly developmental projects. + If you enable this you will be able to use and test highly + developmental projects. If you say N, this configure script will + simply skip those options. It is SAFEST to say N to this question. @@ -726,8 +723,9 @@ CONFIG_BLK_DEV_AEC6210 should say Y here, and preferably also to "Use DMA by default when available". - Please read the comments at the top of drivers/ide/aec6210.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + Please read the comments at the top of drivers/ide/aec6210.c If + you say Y here, then say Y to "Use DMA by default when available" as + well. AEC6210 Tuning support (WIP) CONFIG_AEC6210_TUNING @@ -736,33 +734,37 @@ CONFIG_AEC6210_TUNING ALI M15x3 chipset support CONFIG_BLK_DEV_ALI15X3 - This driver ensures (U)DMA support for ALI 1543 and 1543C, - 1535, 1535D onboard chipsets. It also tests for Simplex mode and - enables normal dual channel support. + This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C + onboard chipsets. It also tests for Simplex mode and enables + normal dual channel support. + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. Please read the comments at the top of drivers/ide/alim15x3.c - If you say Y here, then say Y to "Use DMA by default when available" as well. If unsure, say N. ALI M15x3 WDC support (DANGEROUS) CONFIG_WDC_ALI15X3 - This allows for UltraDMA support for WDC drives that ignore CRC checking. - You are a fool for enabling this option, but there have been requests. - DO NOT COMPLAIN IF YOUR DRIVE HAS FS CORUPTION, IF YOU ENABLE THIS! - No one will listen, just laugh for ignoring this SERIOUS WARNING. + This allows for UltraDMA support for WDC drives that ignore CRC + checking. You are a fool for enabling this option, but there have + been requests. DO NOT COMPLAIN IF YOUR DRIVE HAS FS CORRUPTION, IF + YOU ENABLE THIS! No one will listen, just laugh for ignoring this + SERIOUS WARNING. - Using this option can allow WDC drives to run at ATA-4/5 transfer rates with - only an ATA-2 support structure. + Using this option can allow WDC drives to run at ATA-4/5 transfer + rates with only an ATA-2 support structure. SAY NO! AMD7409 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_AMD7409 - This driver ensures (U)DMA support for AMD756 Viper chipset. + This driver ensures (U)DMA support for the AMD756 Viper chipset. + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. Please read the comments at the top of drivers/ide/amd7409.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + If unsure, say N. AMD Viper ATA-66 Override support (WIP) @@ -773,8 +775,8 @@ CONFIG_AMD7409_OVERRIDE CMD64X chipset support CONFIG_BLK_DEV_CMD64X - Say Y here if you have an IDE controller which uses any of these chipsets, - CMD643, CMD646, or CMD648. + Say Y here if you have an IDE controller which uses any of these + chipsets: CMD643, CMD646, or CMD648. CMD64X chipset RAID support (WIP) CONFIG_CMD64X_RAID @@ -786,7 +788,8 @@ CONFIG_BLK_DEV_CY82C693 This driver adds detection and support for the CY82C693 chipset used on Digital's PC-Alpha 164SX boards. - If you say Y here, then say Y to "Use DMA by default when available" as well. + If you say Y here, you need to say Y to "Use DMA by default + when available" as well. Cyrix CS5530 MediaGX chipset support CONFIG_BLK_DEV_CS5530 @@ -795,6 +798,8 @@ CONFIG_BLK_DEV_CS5530 It is safe to say Y to this question. + People with SCSI-only systems should say N here. If unsure, say Y. + HPT34X chipset support CONFIG_BLK_DEV_HPT34X This driver adds up to 4 more EIDE devices sharing a single @@ -806,38 +811,39 @@ CONFIG_BLK_DEV_HPT34X HPT34X AUTODMA support (WIP) CONFIG_HPT34X_AUTODMA - This is a dangerous thing to attempt currently! - Please read the comments at the top of drivers/ide/hpt34x.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + This is a dangerous thing to attempt currently! Please read the + comments at the top of drivers/ide/hpt34x.c If you say Y here, + then say Y to "Use DMA by default when available" as well. If unsure, say N. HPT366 chipset support CONFIG_BLK_DEV_HPT366 - This is an Ultra DMA chipset for ATA-66. + HPT366 is an Ultra DMA chipset for ATA-66. This driver adds up to 4 more EIDE devices sharing a single - interrupt. The HPT366 chipset in its current form is a non-bootable, - without special LILO commands for redirecting the reference to device 0x80. - The other solution is to include "CONFIG_BLK_DEV_OFFBOARD" unless your - mainboard has the chipset native mounted. Regardless one should use the - fore mentioned option and call at LILO or include in your append-line: - "ide=reverse". This driver requires dynamic tuning of the chipset during - the ide-probe at boot. It is reported to support DVD II drives, by the + interrupt. + + The HPT366 chipset in its current form is non-bootable. One solution + for this problem are special LILO commands for redirecting the + reference to device 0x80. The other solution is to say Y to "Boot + off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless + your mother board has the chipset natively mounted. Regardless one + should use the fore mentioned option and call at LILO or include + "ide=reverse" in LILO's append-line. + + This driver requires dynamic tuning of the chipset during the + ide-probe at boot. It is reported to support DVD II drives, by the manufacturer. - Please read the comments at the top of drivers/ide/hpt366.c - If you say Y here, then say Y to "Use DMA by default when available" as well. - HPT366 Fast Interrupts (WIP) CONFIG_HPT366_FIP - If unsure, say N. -HPT366 mode three unsupported (WIP) +HPT366 mode three unsupported (EXPERIMENTAL) (WIP) CONFIG_HPT366_MODE3 - This is an undocumented mode that the HA366 can default to in many cases. - If unsure, say N. + This is an undocumented mode that the HA366 can default to in many + cases. If unsure, say N. NS87415 support (EXPERIMENTAL) CONFIG_BLK_DEV_NS87415 @@ -858,12 +864,14 @@ CONFIG_BLK_DEV_PIIX PIO 0-4 mode settings, this allows dynamic tuning of the chipset via the standard end-user tool 'hdparm'. - Please read the comments at the top of drivers/ide/piix.c + Please read the comments at the top of drivers/ide/piix.c. - Should also include "PIIXn Tuning support" CONFIG_PIIX_TUNING - If unsure, say Y. + If you say Y here, you should also say Y to "PIIXn Tuning support", + below. -PIIXn Tuning support + If unsure, say N. + +PIIXn Tuning support (EXPERIMENTAL) CONFIG_PIIX_TUNING This driver extension adds DMA mode setting and tuning for all PIIX IDE controllers by Intel. Since the BIOS can sometimes improperly @@ -873,7 +881,7 @@ CONFIG_PIIX_TUNING Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode 2 if the BIOS can not perform this task at initialization. - If unsure, say Y. + If unsure, say N. PROMISE PDC20246/PDC20262 support CONFIG_BLK_DEV_PDC202XX @@ -883,10 +891,10 @@ CONFIG_BLK_DEV_PDC202XX interrupt. This add-on card is a bootable PCI UDMA controller. Since multiple cards can be installed and there are BIOS ROM problems that happen if the BIOS revisions of all installed cards (three-max) do - not match, the driver attempts to do dynamic tuning of the chipset at - boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required for - more than one card. This card may require that you say Y to "Special - UDMA Feature (EXPERIMENTAL)". + not match, the driver attempts to do dynamic tuning of the chipset + at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required + for more than one card. This card may require that you say Y to + "Special UDMA Feature (EXPERIMENTAL)". Promise Ultra66 or PDC20262 @@ -896,12 +904,14 @@ CONFIG_BLK_DEV_PDC202XX boot-time for max-speed. Note tested limits are UDMA-2. Ultra66 BIOS 1.11 or newer required. - If you say Y here, then say Y to "Use DMA by default when available" as well. + If you say Y here, you need to say Y to "Use DMA by default when + available" as well. + Please read the comments at the top of drivers/ide/pdc202xx.c If unsure, say N. -Special UDMA Feature +Special UDMA Feature (EXPERIMENTAL) CONFIG_PDC202XX_BURST For PDC20246 and PDC20262 Ultra DMA chipsets. Designed originally for PDC20246/Ultra33 that has BIOS setup failures when using 3 or @@ -918,6 +928,17 @@ CONFIG_PDC202XX_MASTER Say N. +SiS5513 chipset support +CONFIG_BLK_DEV_SIS5513 + This driver ensures (U)DMA support for SIS5513 chipset based + mainboards. SiS620/530 UDMA mode 4, SiS5600/5597 UDMA mode 2, all + other DMA mode 2 limited chipsets are unsupported to date. + + If you say Y here, you need to say Y to "Use DMA by default when + available" as well. + + Please read the comments at the top of drivers/ide/sis5513.c + Winbond SL82c105 support CONFIG_BLK_DEV_SL82C105 If you have a Winbond SL82c105 IDE controller, say Y here to enable @@ -933,16 +954,18 @@ CONFIG_BLK_DEV_TRM290 VIA82CXXX chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_VIA82CXXX - This allows you to to configure your chipset for a better use while - running (U)DMA: it will allow you to enable efficiently the second - channel dma usage, as it is may not be set by BIOS. It allows you to - run a kernel command line at boot time in order to set fifo config. - If no command line is provided, it will try to set fifo configuration - at its best. It will allow you to get a proc/ide/via display - (while running a "cat") provided you enabled "proc" support. + This allows you to to configure your chipset for a better use while + running (U)DMA: it will allow you to enable efficiently the second + channel dma usage, as it may not be set by BIOS. It allows you to + pass a kernel command line at boot time in order to set fifo + config. If no command line is provided, it will try to set fifo + configuration at its best. It will allow you to get information from + /proc/ide/via provided you enabled "proc" support. + Please read the comments at the top of drivers/ide/via82cxxx.c - If you say Y here, then say Y to "Use DMA by default when available" as well. + If you say Y here, then say Y to "Use DMA by default when available" + as well. If unsure, say N. @@ -1045,7 +1068,7 @@ CONFIG_BLK_DEV_BUDDHA Amiga IDE Doubler support (EXPERIMENTAL) CONFIG_BLK_DEV_IDEDOUBLER - This driver provides support for the so called `IDE doublers' (made + This driver provides support for the so-called `IDE doublers' (made by various manufacturers, e.g. Eyetech) that can be connected to the builtin IDE interface of some Amiga models. Using such an IDE doubler, you can connect up to four instead of two IDE devices on @@ -1087,11 +1110,6 @@ CONFIG_BLK_DEV_MAC_IDE devices (hard disks, CD-ROM drives, etc.) that are connected to the builtin IDE interface. -IDE card support -CONFIG_BLK_DEV_IDE_CARDS - On Acorn systems, say Y here if you wish to use an IDE interface - expansion card. If you do not or are unsure, say N to this. - ICS IDE interface support CONFIG_BLK_DEV_IDE_ICSIDE On Acorn systems, say Y here if you wish to use the ICS IDE @@ -1100,7 +1118,8 @@ CONFIG_BLK_DEV_IDE_ICSIDE ICS DMA support CONFIG_BLK_DEV_IDEDMA_ICS - No help for CONFIG_BLK_DEV_IDEDMA_ICS + Say Y here if you want to add DMA (Direct Memory Access) support to + the ICS IDE driver. Use ICS DMA by default CONFIG_IDEDMA_ICS_AUTO @@ -1113,10 +1132,6 @@ CONFIG_IDEDMA_ICS_AUTO If you suspect your hardware is at all flakey, say N here. Do NOT email the IDE kernel people regarding this issue! -RapIDE interface support -CONFIG_BLK_DEV_IDE_RAPIDE - No help for CONFIG_BLK_DEV_IDE_RAPIDE - XT hard disk support CONFIG_BLK_DEV_XD Very old 8 bit hard disk controllers used in the IBM XT computer @@ -1133,7 +1148,7 @@ PS/2 ESDI hard disk support CONFIG_BLK_DEV_PS2 Say Y here if you have a PS/2 machine with a MCA bus and an ESDI hard disk. - + If you want to compile the driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be @@ -1157,7 +1172,7 @@ CONFIG_PARIDE your computer's parallel port. Most of them are actually IDE devices using a parallel port IDE adapter. This option enables the PARIDE subsystem which contains drivers for many of these external drives. - Read linux/Documentation/paride.txt for more information. + Read Documentation/paride.txt for more information. If you have said Y to the "Parallel-port support" configuration option, you may share a single port between your printer and other @@ -1199,8 +1214,8 @@ CONFIG_PARIDE_PCD system. Among the devices supported by this driver are the MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If you have such a CD-ROM drive, you should also say Y or M to "ISO - 9660 CDROM file system support" below, because that's the file system - used on CDROMs. + 9660 CDROM file system support" below, because that's the file + system used on CDROMs. Parallel port ATAPI disks CONFIG_PARIDE_PF @@ -1241,7 +1256,7 @@ CONFIG_PARIDE_PG your system. This driver implements an API loosely related to the generic SCSI - driver. See /usr/include/linux/pg.h for details. + driver. See include/linux/pg.h for details. You can obtain the most recent version of cdrecord from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ . Versions 1.6.1a3 and @@ -1401,9 +1416,13 @@ CONFIG_BLK_DEV_LVM to new capacity needs. Logical volumes are accessed as block devices named /dev/VolumeGroupName/LogicalVolumeName. - For details see /usr/src/linux/Documentaion/LVM-HOWTO. + For details see Documentation/LVM-HOWTO. You will need supporting + user space software from http://linux.msede.com/lvm . - To get the newest software see . + If you want to compile this support as a module ( = code which can + be inserted in and removed from the running kernel whenever you + want), say M here and read Documentation/modules.txt. The module + will be called lvm-mod.o. Logical Volume Manager /proc file system information CONFIG_LVM_PROC_FS @@ -1517,37 +1536,30 @@ CONFIG_MD_BOOT answer Y here. For lilo and loadlin options see the file Documentation/md.txt. -Support for Deskstation RPC44 -CONFIG_DESKSTATION_RPC44 - This is a machine with a R4400 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux - on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://oss.sgi.com/mips. - Support for Acer PICA 1 chipset CONFIG_ACER_PICA_61 This is a machine with a R4400 133/150 MHz CPU. To compile a Linux kernel that runs on these, say Y here. For details about Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - http://oss.sgi.com/mips. + http://oss.sgi.com/mips . Support for Algorithmics P4032 (EXPERIMENTAL) CONFIG_ALGOR_P4032 This is an evaluation board of the British company Algorithmics. The board uses the R4300 and a R5230 CPUs. For more information about - this board see http://www.algor.co.uk. + this board see http://www.algor.co.uk . Support for BAGET MIPS series CONFIG_BAGET_MIPS This enables support for the Baget, a Russian embedded system. For more details about the Baget see the Linux/MIPS FAQ on - http://oss.sgi.com/mips. + http://oss.sgi.com/mips . Support for DECstations CONFIG_DECSTATION This enables support for DEC's MIPS based workstations. For details - see the Linux/MIPS FAQ on http://oss.sgi.com/mips. the - DECstation porting pages on http://decstation.unix-ag.org. + see the Linux/MIPS FAQ on http://oss.sgi.com/mips and the + DECstation porting pages on http://decstation.unix-ag.org . If you have one of the following DECstation Models you definitely want to choose R4xx0 for the CPU Type: @@ -1561,26 +1573,8 @@ CONFIG_DECSTATION Support for NEC DDB Vrc-5074 CONFIG_DDB5074 - This enables support for the VR5000-based NEC DDB Vrc-5074 evaluation - board. - -IDE card support -CONFIG_BLK_DEV_IDE_CARDS - On Acorn systems, say Y here if you wish to use an IDE interface - expansion card. If you do not or are unsure, say N to this. - -ICS IDE interface -CONFIG_BLK_DEV_IDE_ICS - On Acorn systems, say Y here if you wish to use the ICS IDE - interface card. This is not required for ICS partition support. - If you are unsure, say N to this. - -ADFS partition support -CONFIG_BLK_DEV_PART - This allows Linux on Acorn systems to determine its partitions in - the 'non-ADFS' partition area of the hard disk - usually located - after the ADFS partition. You are probably using this system, so - you should say Y it. + This enables support for the VR5000-based NEC DDB Vrc-5074 + evaluation board. Support for Mips Magnum 4000 CONFIG_MIPS_MAGNUM_4000 @@ -1598,9 +1592,9 @@ CONFIG_OLIVETTI_M700 Support for SGI IP22 CONFIG_SGI_IP22 - This are the SGI Indy, Challenge S and Indigo2, as well as certain OEM - variants like the Tandem CMN B006S. To compile a Linux kernel that - runs on these, say Y here. + This are the SGI Indy, Challenge S and Indigo2, as well as certain + OEM variants like the Tandem CMN B006S. To compile a Linux kernel + that runs on these, say Y here. Support for SGI IP27 This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics @@ -1611,7 +1605,7 @@ IP27 N-Mode CONFIG_SGI_SN0_N_MODE The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be configured in either N-Modes which allows for more nodes or M-Mode - which allows for more more memory. Your system is most probly + which allows for more more memory. Your system is most probably running in M-Mode, so you should say N here. MIPS JAZZ onboard SONIC Ethernet support @@ -1621,26 +1615,26 @@ CONFIG_MIPS_JAZZ_SONIC MIPS JAZZ FAS216 SCSI support CONFIG_JAZZ_ESP - This is the driver for the onboard SCSI hostadapter of MIPS Magnum 4000, - Acer PICA, Olivetti M700-10 and a few other identical OEM systems. + This is the driver for the onboard SCSI host adapter of MIPS Magnum + 4000, Acer PICA, Olivetti M700-10 and a few other identical OEM + systems. CPU type CONFIG_CPU_R3000 - Please make shure to pick the right CPU type. Linux/MIPS is not + Please make sure to pick the right CPU type. Linux/MIPS is not designed to be generic, i.e. Kernels compiled for R3000 CPUs will *not* work on R4000 Machines and vice versa. - However, since most the supported Machines have an R4000 (or similar) - CPU R4xx0 might be a safe bet. + However, since most the supported Machines have an R4000 (or + similar) CPU, R4xx0 might be a safe bet. If the resulting Kernel does not work try to recompile with R3000. Support for large 64-bit configurations CONFIG_MIPS_INSANE_LARGE MIPS R10000 does support a 44 bit / 16TB address space as opposed to - previous 64-bit processors which only did only support 40 bit / 1TB. If - you need processes of more than 1TB virtual address space activate this. - Activating CONFIG_MIPS_INSANE_LARGE results in additional memory usage, - so only activate this if you really need. Very few people will need - this. + previous 64-bit processors which only supported 40 bit / 1TB. If you + need processes of more than 1TB virtual address space, say Y here. + This will result in additional memory usage, so it is not + recommended for normal users. Generate little endian code CONFIG_CPU_LITTLE_ENDIAN @@ -1648,11 +1642,6 @@ CONFIG_CPU_LITTLE_ENDIAN byte order. These modes require different kernels. Say Y if your machine is little endian, N if it's a big endian machine. -Kernel support for IRIX binaries -CONFIG_BINFMT_IRIX - If you say Y here, the kernel will support running of IRIX binaries. - You will need IRIX libraries for this to work. - Networking support CONFIG_NET Unless you really know what you are doing, you should say Y here. @@ -1675,7 +1664,7 @@ CONFIG_FILTER socket and thereby tell the kernel that it should allow or disallow certain types of data to get through the socket. Linux Socket Filtering works on all socket types except TCP for now. See the text - file linux/Documentation/networking/filter.txt for more information. + file Documentation/networking/filter.txt for more information. If unsure, say N. Network packet filtering @@ -1710,7 +1699,7 @@ CONFIG_NETFILTER are completely invisible to the outside world, even though they can reach the outside and can receive replies. It is even possible to run globally visible servers from within a masqueraded local network - using a mechanism called port-forwarding. Masquerading is also often + using a mechanism called portforwarding. Masquerading is also often called NAT (Network Address Translation). Another use of Netfilter is in transparent proxying: if a machine on @@ -1720,7 +1709,7 @@ CONFIG_NETFILTER Various modules exist for netfilter which replace the previous masquerading (ipmasqadm), packet filtering (ipchains), transparent - proxying, and port-forwarding mechanisms. More information is + proxying, and portforwarding mechanisms. More information is available from http://netfilter.kernelnotes.org . Make sure to say N to "Fast switching" below if you intend to say Y @@ -1729,6 +1718,11 @@ CONFIG_NETFILTER Chances are that you should say Y here if you compile a kernel which will run as a router and N for regular hosts. If unsure, say N. +Network packet filtering debugging +CONFIG_NETFILTER_DEBUG + You can say Y here if you want to get additional messages useful in + debugging the netfilter code. + IP: connection tracking (required for masq/NAT) CONFIG_IP_NF_CONNTRACK Connection tracking keeps a record of what packets have passed @@ -1773,7 +1767,8 @@ CONFIG_IP_NF_IPTABLES limit match support CONFIG_IP_NF_MATCH_LIMIT limit matching allows you to control the rate at which a rule can be - matched: mainly useful in combination with the LOG target. + matched: mainly useful in combination with the LOG target ("LOG + target support", below). If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. @@ -1831,7 +1826,6 @@ CONFIG_IP_NF_MATCH_UNCLEAN Owner match support (EXPERIMENTAL) CONFIG_IP_NF_MATCH_OWNER - Packet owner matching allows you to match locally-generated packets based on who created them: the user, group, process or session. @@ -1889,7 +1883,7 @@ CONFIG_IP_NF_TARGET_REDIRECT REDIRECT is a special case of NAT: all incoming connections are mapped onto the incoming interface's address, causing the packets to come to the local machine instead of passing through. This is - useful for tranparent proxies. + useful for transparent proxies. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. @@ -1914,11 +1908,12 @@ CONFIG_IP_NF_TARGET_TOS MARK target support CONFIG_IP_NF_TARGET_MARK - This option adds a `MARK' target, which allows you to create rules in - the `mangle' table which alter the netfilter mark (nfmark) field - associated with the packet packet prior to routing. This can change - the routing method (see `IP: use netfilter MARK value as routing key') - and can also be used by other subsystems to change their behavior. + This option adds a `MARK' target, which allows you to create rules + in the `mangle' table which alter the netfilter mark (nfmark) field + associated with the packet packet prior to routing. This can change + the routing method (see `IP: use netfilter MARK value as routing + key') and can also be used by other subsystems to change their + behavior. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. @@ -1989,11 +1984,6 @@ CONFIG_SYN_COOKIES If unsure, say Y. -Sun floppy controller support -CONFIG_BLK_DEV_SUNFD - This is support for floppy drives on Sun SPARC workstations. Say Y - if you have a floppy drive, otherwise N. Easy. - Alpha system type CONFIG_ALPHA_GENERIC This is the system type of your hardware. A "generic" kernel will @@ -2060,12 +2050,6 @@ CONFIG_ALPHA_SRM If unsure, say N. -Use SRM PCI setup -CONFIG_ALPHA_SRM_SETUP - This option controls whether or not the PCI configuration set up by - SRM is modified. If you say Y, the existing PCI configuration will - be left intact. - Non-standard serial port support CONFIG_SERIAL_NONSTANDARD Say Y here if you have any non-standard serial boards -- boards @@ -2128,7 +2112,7 @@ CONFIG_SERIAL_MULTIPORT SGI PROM Console Support CONFIG_SGI_PROM_CONSOLE - Enable this if you want to use the PROMs for console I/O. + Say Y here if you want to use the PROMs for console I/O. SGI Zilog85C30 serial support CONFIG_SGI_SERIAL @@ -2144,7 +2128,7 @@ CONFIG_SGI_NEWPORT_GFX SGI Newport Console support CONFIG_SGI_NEWPORT_CONSOLE - Enable this if you want the console on the Newport aka XL graphics + Say Y here if you want the console on the Newport aka XL graphics card of your Indy. Most people say Y here. SGI DS1286 RTC support @@ -2152,51 +2136,131 @@ CONFIG_SGI_DS1286 If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you will get access to the real time clock built into your computer. - Every SGI has such a clock built in. It reports status information - via the file /proc/rtc and its behaviour is set by various ioctls on + Every SGI has such a clock built in. It reports status information + via the file /proc/rtc and its behaviour is set by various ioctls on /dev/rtc. -SGI Vino Video For Linux (EXPERIMENTAL) -CONFIG_SGI_VIDEO_VINO - Support for the SGI Vino Video hardware which is part of the Newport - aka XL graphics card. Most people will say N here. - Support the Bell Technologies HUB6 card CONFIG_HUB6 Say Y here to enable support in the dumb serial driver to support the HUB6 card. -Support for hot-pluggable devices -CONFIG_HOTPLUG - Say Y here to enable support for hot plugin of certain hardware such as - PCMCIA cards and the like. - - At this moment, few drivers support it, but as they get converted to use the - new ressource allocator/manager, their number will increase. - PCMCIA serial device support CONFIG_PCMCIA_SERIAL_CS Say Y here to enable support for 16-bit PCMCIA serial devices, including serial port cards, modems, and the modem functions of - multifunction ethernet/modem cards. + multi-function ethernet/modem cards. (PCMCIA- or PC-cards are + credit-card size devices often used with laptops.) This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called serial_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called serial_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. CardBus serial device support CONFIG_PCMCIA_SERIAL_CB Say Y here to enable support for CardBus serial devices, including - the modem functions of multifunction ethernet/modem devices. + serial port cards, modems, and the modem functions of multi-function + ethernet/modem devices. (CardBus cards are the newer and better + version of PCMCIA- or PC-cards: credit card size devices often + used with laptops.) This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called serial_cb.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called serial_cb.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. +/dev/agpgart (AGP Support) (EXPERIMENTAL) +CONFIG_AGP + AGP (Accelerated Graphics Port) is a bus system mainly used to + connect graphics cards to the rest of the system. + + If you have an AGP system and you say Y here, it will be possible to + use the AGP features of your 3D rendering video card. This code acts + as a sort of "AGP driver" for the motherboard's chipset. The glx + module will then be able to program the GART (graphics aperture + relocation table) registers with appropriate values to transfer + commands to the card. + + If you need more texture memory than you can get with the AGP GART + (theoretically up to 256 MB, but in practice usually 64 or 128 MB + due to kernel allocation issues), you could use PCI accesses + and have up to a couple gigs of texture space. + + Note that this is the only means to have XFree4/GLX use + write-combining with MTRR support on the AGP bus. Without it, OpenGL + direct rendering will be a lot slower but still faster than PIO. + + For the moment, you should probably say N, unless you want to test + the GLX component for XFree86 3.3.6, which can be downloaded from + http://utah-glx.sourceforge.net/ , or need to use the 810 Xserver in + XFree 3.3.6. + + This driver is available as a module. If you want to compile it as a + module, say M here and read Documentation/modules.txt. The module + will be called agpgart.o. + +Intel 440LX/BX/GX support +CONFIG_AGP_INTEL + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on Intel 440LX/BX/GX chipsets. + + For the moment, you should probably say N, unless you want to test + the GLX component for XFree86 3.3.6, which can be downloaded from + http://utah-glx.sourceforge.net/ . + +Intel I810/I810 DC100/I810e support +CONFIG_AGP_I810 + This option gives you AGP support for the Xserver for the Intel + 810 chipset boards. This is required to do any useful video + modes. + +VIA chipset support +CONFIG_AGP_VIA + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + + For the moment, you should probably say N, unless you want to test + the GLX component for XFree86 3.3.6, which can be downloaded from + http://utah-glx.sourceforge.net/ . + +AMD Irongate support +CONFIG_AGP_AMD + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on Intel AMD Irongate chipset. + + For the moment, you should probably say N, unless you want to test + the GLX component for XFree86 3.3.6, which can be downloaded from + http://utah-glx.sourceforge.net/ . + +Generic SiS support +CONFIG_AGP_SIS + This option gives you AGP support for the GLX component of the "soon + to be released" XFree86 4.x on Silicon Integrated Systems [SiS] + chipsets. + + Note that 5591/5592 AGP chipsets are NOT supported. + + For the moment, you should probably say N, unless you want to test + the GLX component for XFree86 3.3.6, which can be downloaded from + http://utah-glx.sourceforge.net/ . + +ALI M1541 support +CONFIG_AGP_ALI + This option gives you AGP support for the GLX component of the + "soon to be released" XFree86 4.x on the ALi M1541 chipset. + + This chipset can do AGP 1x and 2x, but note that there is an + acknowledged incompatibility with Matrox G200 cards. Due to + timing issues, this chipset cannot do AGP 2x with the G200. + This is a hardware limitation. AGP 1x seems to be fine, though. + + For the moment, you should probably say N, unless you want to test + the GLX component for XFree86 3.3.6, which can be downloaded from + http://utah-glx.sourceforge.net/ . + PCI support CONFIG_PCI Find out whether you have a PCI motherboard. PCI is the name of a @@ -2221,16 +2285,17 @@ CONFIG_PCI_GOBIOS devices. If you choose "BIOS", the BIOS will be used, if you choose "Direct", the BIOS won't be used, and if you choose "Any", the kernel will try the direct access method and falls back to the BIOS - if that doesn't work. If unsure, go with the default. + if that doesn't work. If unsure, go with the default, which is + "Any". PCI device name database CONFIG_PCI_NAMES By default, the kernel contains a database of all known PCI device - names to make the information in /proc/pci, /proc/ioports and similar - files comprehensible to the user. This database increases size of - the kernel image by about 80KB, but it gets freed after the system - boots up, so it doesn't take up kernel memory. Anyway, if you are - building an installation floppy or kernel for an embedded system + names to make the information in /proc/pci, /proc/ioports and + similar files comprehensible to the user. This database increases + size of the kernel image by about 80KB, but it gets freed after the + system boots up, so it doesn't take up kernel memory. Anyway, if you + are building an installation floppy or kernel for an embedded system where kernel image size really matters, you can disable this feature and you'll get device ID numbers instead of names. @@ -2343,8 +2408,9 @@ CONFIG_PNP Say Y here if you would like Linux to configure your Plug and Play devices. You should then also say Y to "ISA Plug and Play support", - below. Alternatively, you can configure your PnP devices using the - user space utilities contained in the isapnptools package. + below. Alternatively, you can say N here and configure your PnP + devices using the user space utilities contained in the isapnptools + package. This support is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -2354,7 +2420,8 @@ CONFIG_PNP ISA Plug and Play support CONFIG_ISAPNP Say Y here if you would like support for ISA Plug and Play devices. - + Some information is in Documentation/isapnp.txt. + This support is also available as a module called isapnp.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M @@ -2362,13 +2429,27 @@ CONFIG_ISAPNP If unsure, say Y. -PCMCIA/CardBus support +Support for hot-pluggable devices +CONFIG_HOTPLUG + Say Y here if you want to attach devices to your computer that can + be attached and detached while the system is running. The most + prominent example of this are PCMCIA- or PC-cards, credit-card size + devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. + +PCMCIA/Cardbus support CONFIG_PCMCIA - Include kernel support for PCMCIA and CardBus devices. Because - PCMCIA support requires additional components that are not part of - the kernel (i.e., the pcmcia-cs package), building PCMCIA into the - kernel is generally not recommended unless you have a specific - need. If unsure, say N. + Say Y here if you want to attach PCMCIA- or PC-cards to your Linux + computer. These are credit-card size devices such as network cards, + modems or hard drives often used with laptops computers. There are + actually two varieties of these cards: the older 16 bit PCMCIA cards + and the newer 32 bit CardBus cards. If you want to use CardBus + cards, you need to say Y here and also to "CardBus support" below. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). Please also read the PCMCIA-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -2376,27 +2457,32 @@ CONFIG_PCMCIA and ds.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - You will also need David Hinds' pcmcia-cs package (see the file - Documentation/Changes for location). For more information, see the - PCMCIA-HOWTO. - CardBus support CONFIG_CARDBUS - There are two types of PCMCIA devices: 16-bit PC Cards, and higher - performance 32-bit CardBus devices. Use this option to include - support for CardBus devices. If unsure, say Y. + CardBus is a bus mastering architecture for PC-cards, which allows + for 32 bit PC-cards (the original PCMCIA standard specifies only + a 16 bit wide bus). Many newer PC-cards are actually CardBus cards. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). + + If unsure, say Y. i82365/Yenta compatible bridge support CONFIG_I82365 - Include support for PCMCIA and CardBus host bridges that are - register compatible with the Intel i82365 and/or the Yenta + Say Y here to include support for PCMCIA and CardBus host bridges + that are register compatible with the Intel i82365 and/or the Yenta specification: this includes virtually all modern PCMCIA bridges. - If unsure, say Y. + "Bridge" is the name used for the hardware inside your computer that + PCMCIA cards are plugged into. If unsure, say Y. Databook TCIC host bridge support CONFIG_TCIC - Include support for the Databook TCIC family of PCMCIA host bridges. - These are only found on a handful of old systems. If unsure, say N. + Say Y here to include support for the Databook TCIC family of PCMCIA + host bridges. These are only found on a handful of old systems. + "Bridge" is the name used for the hardware inside your computer that + PCMCIA cards are plugged into. If unsure, say N. System V IPC CONFIG_SYSVIPC @@ -2414,9 +2500,9 @@ CONFIG_SYSVIPC http://www.linuxdoc.org/docs.html#guide . Shared memory is now implemented using a new (minimal) virtual file - system, which you need to mount before programs can use shared memory. - To do this automatically at system startup just add the following line - to your /etc/fstab: + system, which you need to mount before programs can use shared + memory. To do this automatically at system startup just add the + following line to your /etc/fstab: none /var/shm shm defaults 0 0 @@ -2451,21 +2537,24 @@ CONFIG_SYSCTL Kernel core (/proc/kcore) format CONFIG_KCORE_ELF - If you enabled support for /proc file system then the file /proc/kcore - will contain the kernel core image. This can be used in gdb: + If you enabled support for /proc file system then the file + /proc/kcore will contain the kernel core image. This can be used + in gdb: $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - Selecting ELF will make /proc/kcore appear in ELF core format as defined - by the Executable and Linking Format specification. Selecting A.OUT will - choose the old "a.out" format which may be necessary for some old versions + You have two choices here: ELF and A.OUT. Selecting ELF will make + /proc/kcore appear in ELF core format as defined by the Executable + and Linking Format specification. Selecting A.OUT will choose the + old "a.out" format which may be necessary for some old versions of binutils or on some architectures. - This is especially useful if you have compiled the kernel with "-g" option - to preserve debugging information. It is mainly used for examining kernel - data structures on the live kernel so if you don't understand what this - means or are not a kernel hacker, just leave it at its default value ELF. - + This is especially useful if you have compiled the kernel with the + "-g" option to preserve debugging information. It is mainly used + for examining kernel data structures on the live kernel so if you + don't understand what this means or are not a kernel hacker, just + leave it at its default value ELF. + Kernel support for ELF binaries CONFIG_BINFMT_ELF ELF (Executable and Linkable Format) is a format for libraries and @@ -2569,10 +2658,10 @@ CONFIG_M386 all x86 CPU types (albeit not optimally fast), you can specify "386" here. - If you specify one of "486" or "586" or "Pentium" or "PPro", then - the kernel will not necessarily run on earlier architectures (e.g. a - Pentium optimized kernel will run on a PPro, but not necessarily on - a i486). + If you specify one of "486" or "586" or "Pentium" or "PPro" or + "Athlon", then the kernel will not necessarily run on earlier + architectures (e.g. a Pentium optimized kernel will run on a PPro, + but not necessarily on a i486). Here are the settings recommended for greatest speed: - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI @@ -2583,11 +2672,11 @@ CONFIG_M386 UMC U5D or U5S. - "586" for generic Pentium CPUs, possibly lacking the TSC (time stamp counter) register. - - "Pentium" for the Intel Pentium/Pentium MMX, AMD K5. + - "Pentium" for the Intel Pentium/Pentium MMX, and AMD K5. - "PPro" for the Cyrix/IBM/National Semiconductor 6x86MX, MII and - Intel Pentium II/Pentium Pro. + Intel Pentium Pro/Celeron/Pentium II/Pentium III. - "K6/II/III" for the AMD K6, K6-II and K6-III (aka K6-3D). - - "Athlon" for the AMD Athlon (aka K7) + - "Athlon" for the AMD Athlon (K7). If you don't know what to do, choose "386". @@ -2612,9 +2701,7 @@ CONFIG_VIDEO_SELECT "vga=" option from your boot loader (lilo or loadlin) or set "vga=ask" which brings up a video mode menu on kernel startup. (Try "man bootparam" or see the documentation of your boot loader about - how to pass options to the kernel. The lilo procedure is also - explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + how to pass options to the kernel.) Read the file Documentation/svga.txt for more information about the Video mode selection support. If unsure, say N. @@ -2658,11 +2745,6 @@ CONFIG_FB_ACORN hardware found in Acorn RISC PCs and other ARM-based machines. If unsure, say N. -Apollo frame buffer device -CONFIG_FB_APOLLO - This is the frame buffer device driver for the monochrome graphics - hardware found in some Apollo workstations. - Amiga native chipset support CONFIG_FB_AMIGA This is the frame buffer device driver for the builtin graphics @@ -2769,8 +2851,8 @@ CONFIG_FB_S3TRIO 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL) CONFIG_FB_3DFX - This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. - Say Y if you have such a graphics board. + This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 + chips. Say Y if you have such a graphics board. The driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The @@ -2797,17 +2879,18 @@ CONFIG_FB_ATY inserted and removed from the running kernel whenever you want). The module will be called atyfb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - + ATI Rage128 display support (EXPERIMENTAL) CONFIG_FB_ATY128 This driver supports graphics boards with the ATI Rage128 chips. - Say Y if you have such a graphics board. + Say Y if you have such a graphics board and read + Documentation/fb/aty128fb.txt. The driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). The module will be called aty128fb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - + PowerMac "control" frame buffer device support CONFIG_FB_CONTROL This driver supports a frame buffer for the graphics adapter in the @@ -2828,16 +2911,6 @@ CONFIG_FB_CT65550 This is the frame buffer device driver for the Chips & Technologies 65550 graphics chip in PowerBooks. -Mac frame buffer device -CONFIG_FB_MAC - This is the frame buffer device driver for the graphics hardware in - m68k Macintoshes. - -HP300 frame buffer device -CONFIG_FB_HP300 - This is the frame buffer device driver for the Topcat graphics - hardware found in HP300 workstations. - TGA frame buffer support CONFIG_FB_TGA This is the frame buffer device driver for generic TGA graphic @@ -2853,10 +2926,11 @@ CONFIG_FB_VESA VGA 16-color planar support CONFIG_FBCON_VGA_PLANES This low level frame buffer console driver enable the kernel to use - the 16-color planar modes of the old VGA cards where the bits of each - pixel are separated into 4 plans. - Only answer Y here if you have an (very old) VGA card that isn't - VESA 2 compatible. + the 16-color planar modes of the old VGA cards where the bits of + each pixel are separated into 4 planes. + + Only answer Y here if you have a (very old) VGA card that isn't VESA + 2 compatible. VGA 16-color graphics console CONFIG_FB_VGA16 @@ -2870,12 +2944,12 @@ CONFIG_FB_VGA16 Select other compiled-in fonts CONFIG_FBCON_FONTS - Say Y here if you would like to use fonts other than the default your frame - buffer console usually use. + Say Y here if you would like to use fonts other than the default + your frame buffer console usually use. - Note that the answer to this question won't directly affect the kernel: - saying N will just cause this configure script to skip all the questions - about foreign fonts. + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about foreign fonts. If unsure, say N (the default choices are safe). @@ -2895,22 +2969,21 @@ CONFIG_FBCON_FONTWIDTH8_ONLY Sparc console 8x16 font CONFIG_FONT_SUN8x16 - This is the high resolution console font for Sun machines. - - Say Y. + This is the high resolution console font for Sun machines. Say Y. Sparc console 12x22 font (not supported by all drivers) CONFIG_FONT_SUN12x22 - This is the high resolution console font for Sun machines with very big - letters (like the letters used in the SPARC PROM). If the standard font - is unreadable for you, say Y, otherwise say N. + This is the high resolution console font for Sun machines with very + big letters (like the letters used in the SPARC PROM). If the + standard font is unreadable for you, say Y, otherwise say N. VGA 8x8 font CONFIG_FONT_8x8 This is the "high resolution" font for the VGA frame buffer (the one - provided by the text console 80x50 (and higher) modes. - Note this is a poor quality font. The VGA 8x16 font is quite a lot - more readable. + provided by the text console 80x50 (and higher) modes). + + Note that this is a poor quality font. The VGA 8x16 font is quite a + lot more readable. Given the resolution provided by the frame buffer device, answer N here is safe. @@ -2923,7 +2996,6 @@ CONFIG_FB_COMPAT_XPMAC (XF68_FBDev). HGA monochrome support (EXPERIMENTAL) -Hercules mono graphics console (EXPERIMENTAL) CONFIG_FBCON_HGA Say Y here if you have a Hercules mono graphics card. @@ -2932,11 +3004,12 @@ CONFIG_FBCON_HGA The module will be called hgafb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - As this card technology is 15 years old, most people will answer N here. + As this card technology is 15 years old, most people will answer N + here. Matrox unified accelerated driver (EXPERIMENTAL) CONFIG_FB_MATROX - Say Y here if you have Matrox Millennium, Matrox Millennium II, + Say Y here if you have a Matrox Millennium, Matrox Millennium II, Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video or Matrox G400 card in your box. At this time, support for the G100, @@ -2976,49 +3049,51 @@ CONFIG_FB_MATROX_G100 you select "Advanced lowlevel driver options", you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can also use font widths different from 8. - - If you need support for G400 secondary head, you must first enable - I2C support and I2C bit-banging support in character devices section, - and then Matrox I2C support and G400 secondary head support here - in framebuffer section. + + If you need support for G400 secondary head, you must first say Y to + "I2C support" and "I2C bit-banging support" in the character devices + section, and then to "Matrox I2C support" and "G400 second head + support" here in the framebuffer section. Matrox I2C support CONFIG_FB_MATROX_I2C - This drivers creates I2C buses which are needed for accessing - DDC (I2C) bus present on all Matroxes, I2C bus which interconnects - Matrox optional devices, like MGA-TVO on G200 and G400, and - secondary head DDC bus, present on G400 only. + This drivers creates I2C buses which are needed for accessing the + DDC (I2C) bus present on all Matroxes, an I2C bus which + interconnects Matrox optional devices, like MGA-TVO on G200 and + G400, and the secondary head DDC bus, present on G400 only. You can say Y or M here if you want to experiment with monitor detection code. You must say Y or M here if you want to use either second head of G400 or MGA-TVO on G200 or G400. - If you compile it as module, it will create module named i2c-matroxfb.o. + If you compile it as module, it will create a module named + i2c-matroxfb.o. Matrox G400 second head support CONFIG_FB_MATROX_MAVEN - Say Y or M here if you want to use secondary head on G400 or MGA-TVO - add-on on G200. Secondary head is not compatible with accelerated - XFree 3.3.x SVGA servers - secondary head output is blanked while you - are in X. With XFree 3.9.17 preview you can use both heads if you use - SVGA over fbdev or fbdev driver on first head and fbdev driver on - second head. + Say Y or M here if you want to use a secondary head (meaning two + monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary + head is not compatible with accelerated XFree 3.3.x SVGA servers - + secondary head output is blanked while you are in X. With XFree + 3.9.17 preview you can use both heads if you use SVGA over fbdev or + the fbdev driver on first head and the fbdev driver on second head. - If you compile it as module, two modules are created, matroxfb_crtc2.o - and matroxfb_maven.o. Matroxfb_maven is needed for both G200 and G400, - matroxfb_crtc2 is needed only by G400. You must also load i2c-matroxfb - to get it to run. + If you compile it as module, two modules are created, + matroxfb_crtc2.o and matroxfb_maven.o. Matroxfb_maven is needed for + both G200 and G400, matroxfb_crtc2 is needed only by G400. You must + also load i2c-matroxfb to get it to run. - Driver starts in monitor mode and you must use matroxset tool (available - at ftp://platan.vc.cvut.cz/pub/linux/matrox-latest) to switch it to PAL - or NTSC or to swap primary and secondary head outputs. Secondary head - driver also always start in 640x480 resolution, you must use fbset to - change it. + The driver starts in monitor mode and you must use the matroxset + tool (available at ftp://platan.vc.cvut.cz/pub/linux/matrox-latest) + to switch it to PAL or NTSC or to swap primary and secondary head + outputs. Secondary head driver also always start in 640x480 + resolution, you must use fbset to change it. - Also do not forget that second head supports only 16 and 32 bpp packed - pixels, so it is good idea to compile them into kernel too. You can - use only some font widths, as driver uses generic painting procedures - (secondary head does not use acceleration engine). + Also do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). There is no need for enabling 'Matrox multihead support' if you have only one Matrox card in the box. @@ -3026,16 +3101,17 @@ CONFIG_FB_MATROX_MAVEN Matrox unified driver multihead support CONFIG_FB_MATROX_MULTIHEAD Say Y here if you have more than one (supported) Matrox device in - your computer and you want to use all of them. If you have only one - device, you should say N because the driver compiled with Y is - larger and a bit slower, especially on ia32 (ix86). + your computer and you want to use all of them for different monitors + ("multihead"). If you have only one device, you should say N because + the driver compiled with Y is larger and a bit slower, especially on + ia32 (ix86). If you said M to "Matrox unified accelerated driver" and N here, you - will still be able to use several Matrox devices simultaneously. - This is slightly faster but uses 40 KB of kernel memory per Matrox - card. You do this by inserting several instances of the module - matroxfb.o into the kernel with insmod, supplying the parameter - "dev=N" where N is 0, 1, etc. for the different Matrox devices. + will still be able to use several Matrox devices simultaneously: + insert several instances of the module matroxfb.o into the kernel + with insmod, supplying the parameter "dev=N" where N is 0, 1, etc. + for the different Matrox devices. This method is slightly faster but + uses 40 KB of kernel memory per Matrox card. MDA text console (dual-headed) CONFIG_MDA_CONSOLE @@ -3188,12 +3264,6 @@ CONFIG_FBCON_MAC bits per pixel packed pixels on Mac. It supports variable font widths for low resolution screens. -#VGA 16-color planar support -#CONFIG_FBCON_VGA_PLANES -### -###What is this? -### - VGA characters/attributes support CONFIG_FBCON_VGA This is the low level frame buffer console driver for VGA text mode; @@ -3266,17 +3336,11 @@ CONFIG_PARPORT_OTHER other non-standard types of parallel ports. This causes a performance loss, so most people say N. -Sun Ultra/AX-style hardware -CONFIG_PARPORT_AX - Say Y here if you need support for the parallel port hardware on Sun - 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. - Support IEEE1284 status readback CONFIG_PRINTER_READBACK - If you have a device on your parallel port that support this protocol, - this option'll enable it to report its status. - It is safe to say Y. + If you have a device on your parallel port that support this + protocol, this option will allow the device to report its status. It + is safe to say Y. IEEE1284 transfer modes CONFIG_PARPORT_1284 @@ -3366,9 +3430,9 @@ CONFIG_INET Internet connected Unix computer; for more information, read http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). - If you say Y here and also to "/proc file system support" and "Sysctl - support" below, you can change various aspects of the behavior of - the TCP/IP code by writing to the (virtual) files in + If you say Y here and also to "/proc file system support" and + "Sysctl support" below, you can change various aspects of the + behavior of the TCP/IP code by writing to the (virtual) files in /proc/sys/net/ipv4/*; the options are explained in the file Documentation/Networking/ip-sysctl.txt. @@ -3377,7 +3441,7 @@ CONFIG_INET IP: multicasting CONFIG_IP_MULTICAST This is code for addressing several networked computers at once, - enlarging your kernel by about 2 kB. You need multicasting if you + enlarging your kernel by about 2 KB. You need multicasting if you intend to participate in the MBONE, a high bandwidth network on top of the Internet which carries audio and video broadcasts. More information about the MBONE is on the WWW at @@ -3502,8 +3566,8 @@ CONFIG_IP_ROUTER echo "1" > /proc/sys/net/ipv4/ip_forward - at boot time after the /proc file system has been mounted. You can do - that even if you say N here. + at boot time after the /proc file system has been mounted. You can + do that even if you say N here. If unsure, say N here. @@ -3511,7 +3575,7 @@ IP: kernel level autoconfiguration CONFIG_IP_PNP This enables automatic configuration of IP addresses of devices and of the routing table during kernel boot, based on either information - supplied at the kernel command line or by BOOTP or RARP protocols. + supplied on the kernel command line or by BOOTP or RARP protocols. You need to say Y only for diskless machines requiring network access to boot (in which case you want to say Y to "Root file system on NFS" as well), because all other machines configure the network @@ -3633,16 +3697,7 @@ CONFIG_INET_PCTCP saying Y here. Everyone else says N. People having problems with NCSA telnet should see the file - linux/Documentation/networking/ncsa-telnet. - -Assume subnets are local -CONFIG_INET_SNARL - Say Y if you are on a subnetted network with all machines connected - by Ethernet segments only, as this option optimizes network access - for this special case. If there are other connections, e.g. SLIP - links, between machines of your IP network, say N. If in doubt, - answer N. The PATH mtu discovery facility will cover most cases - anyway. + Documentation/networking/ncsa-telnet. Path MTU Discovery (normally enabled) CONFIG_PATH_MTU_DISCOVERY @@ -3751,6 +3806,20 @@ CONFIG_IPV6_NETLINK say Y to "Kernel/User network link driver" and to "Routing messages" instead. +Kernel httpd acceleration (EXPERIMENTAL) +CONFIG_KHTTPD + The kernel httpd acceleration daemon (kHTTPd) is a (limited) + web server built into the kernel. It is limited since it can only + serve files from the file system. Saying "M" here builds the + kHTTPd module; this is NOT enough to have a working kHTTPd. + For safety reasons, the module has to be activated by doing a + "echo 1 > /proc/sys/net/khttpd/start" after inserting the module. + + Before using this, read the README in net/khttpd ! + + The kHTTPd is experimental. Be careful when using it on a production + machine. Also note that kHTTPd doesn't support virtual servers yet. + IPX networking CONFIG_IPX This is support for the Novell networking protocol, IPX, commonly @@ -3760,7 +3829,7 @@ CONFIG_IPX ftp://metalab.unc.edu/pub/Linux/system/filesystems/ ) or from within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from http://www.linuxdoc.org/docs.html#howto ). In order to do the - former, you'll also have to say Y to "NCP file systems support", + former, you'll also have to say Y to "NCP file system support", below. IPX is similar in scope to IP, while SPX, which runs on top of IPX, @@ -3819,7 +3888,7 @@ CONFIG_SPX Note that Novell NetWare file sharing does not use SPX; it uses a protocol called NCP, for which separate Linux support is available - ("NCP file systems support" below for the client side, and the user + ("NCP file system support" below for the client side, and the user space programs lwared or mars_nwe for the server side). Say Y here if you have use for SPX; read the IPX-HOWTO at @@ -3844,7 +3913,7 @@ CONFIG_DECNET More detailed documentation is available in the Documentation/networking/decnet.txt file. - Be sure to say Y to "/proc file systems support" and "Sysctl support" + Be sure to say Y to "/proc file system support" and "Sysctl support" below when using DECnet, since you will need sysctl support to aid in configuration at run time. @@ -3865,22 +3934,28 @@ DECnet Router Support (EXPERIMENTAL) CONFIG_DECNET_ROUTER Add support for turning your DECnet Endnode into a level 1 or 2 router. This is an unfinished option for developers only. If you do - turn it on, then make sure that you also say Y to "Kernel/User - network link driver", "Routing messages" and "Network packet + say Y here, then make sure that you also say Y to "Kernel/User + network link driver", "Routing messages" and "Network packet filtering". The first two are required to allow configuration via rtnetlink (currently you need Alexey Kuznetsov's iproute2 package - from ftp.inr.ac.ru). The "Network packet filtering" option will - be required for the forthcoming routing daemon to work. + from ftp://ftp.inr.ac.ru). The "Network packet filtering" option + will be required for the forthcoming routing daemon to work. See Documentation/networking/decnet.txt for more information. +DECnet: use FWMARK value as routing key +CONFIG_DECNET_ROUTE_FWMARK + If you say Y here, you will be able to specify different routes for + packets with different FWMARK ("firewalling mark") values + (see ipchains(8), "-m" argument). + Appletalk interfaces support CONFIG_APPLETALK AppleTalk is the way Apple computers speak to each other on a network. If your Linux box is connected to such a network and you want to join the conversation, say Y. -AppleTalk DDP +AppleTalk protocol support CONFIG_ATALK AppleTalk is the way Apple computers speak to each other on a network. If your Linux box is connected to such a network and you @@ -3894,7 +3969,7 @@ CONFIG_ATALK supported by Linux. General information about how to connect Linux, Windows machines and - Macs is on the WWW at http://www.eats.com/linux_mac_win.html The + Macs is on the WWW at http://www.eats.com/linux_mac_win.html . The NET-3-HOWTO, available from http://www.linuxdoc.org/docs.html#howto , contains valuable information as well. @@ -4401,17 +4476,23 @@ CONFIG_BRIDGE Ethernet bridge, which means that the different Ethernet segments it is connected to will appear as one Ethernet to the participants. Several such bridges can work together to create even larger - networks of Ethernets using the IEEE 802.1d spanning tree protocol. - As this is a standard, Linux bridges will interwork properly with + networks of Ethernets using the IEEE 802.1 spanning tree algorithm. + As this is a standard, Linux bridges will cooperate properly with other third party bridge products. In order to use the ethernet bridge, you'll need the bridge - configuration tools available from ftp://openrock.net/bridge. Please - read the Bridge mini-HOWTO for more information. Note that if your - box acts as a bridge, it probably contains several Ethernet devices, - but the kernel is not able to recognize more than one at boot time - without help; for details read the Ethernet-HOWTO, available from in - http://www.linuxdoc.org/docs.html#howto . + configuration tools; see Documentation/networking/bridge.txt for + location. Please read the Bridge mini-HOWTO for more information. + + Note that if your box acts as a bridge, it probably contains several + Ethernet devices, but the kernel is not able to recognize more than + one at boot time without help; for details read the Ethernet-HOWTO, + available from in http://www.linuxdoc.org/docs.html#howto . + + If you want to compile this code as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called bridge.o. If unsure, say N. @@ -4491,16 +4572,17 @@ CONFIG_ATM Classical IP over ATM CONFIG_ATM_CLIP Classical IP over ATM for PVCs and SVCs, supporting InARP and - ATMARP. Typically you will either use LAN Emulation (LANE) or - Classical IP to communicate with other IP hosts on your ATM network. + ATMARP. If you want to communication with other IP hosts on your ATM + network, you will typically either say Y here or to "LAN Emulation + (LANE)" below. -Do NOT send ICMP if no neighbor +Do NOT send ICMP if no neighbour CONFIG_ATM_CLIP_NO_ICMP - Normally, an "ICMP host unreachable" message is sent if a neighbor + Normally, an "ICMP host unreachable" message is sent if a neighbour cannot be reached because there is no VC to it in the kernel's ATMARP table. This may cause problems when ATMARP table entries are briefly removed during revalidation. If you say Y here, packets to - such neighbors are silently discarded instead. + such neighbours are silently discarded instead. LAN Emulation (LANE) support CONFIG_ATM_LANE @@ -4524,12 +4606,16 @@ CONFIG_ATM_TCP Efficient Networks ENI155P CONFIG_ATM_ENI Driver for the Efficient Networks ENI155p series and SMC ATM - Power155 155 Mbps ATM adapters. Both, the versions with 512kB and + Power155 155 Mbps ATM adapters. Both, the versions with 512KB and 2MB on-board RAM (Efficient calls them "C" and "S", respectively), and the FPGA and the ASIC Tonga versions of the board are supported. The driver works with MMF (-MF or ...F) and UTP-5 (-U5 or ...D) adapters. + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called eni.o. + Enable extended debugging CONFIG_ATM_ENI_DEBUG Extended debugging records various events and displays that list @@ -4610,6 +4696,10 @@ CONFIG_ATM_ZATM Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM adapters. + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called zatm.o. + Enable extended debugging CONFIG_ATM_ZATM_DEBUG Extended debugging records various events and displays that list @@ -4632,7 +4722,11 @@ IDT 77201/11 (NICStAR) (ForeRunnerLE) CONFIG_ATM_NICSTAR The NICStAR chipset family is used in a large number of ATM NICs for 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE - series. + series. Say Y if you have one of those. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called nicstar.o. ForeRunner LE155 PHYsical layer CONFIG_ATM_NICSTAR_USE_SUNI @@ -4717,6 +4811,35 @@ CONFIG_ATM_IA_DEBUG speed of the driver, and the size of your syslog files! When inactive, they will have only a modest impact on performance. +Linux telephony support +CONFIG_PHONE + Say Y here if you have a telephony card, which for example allows + you to use a regular phone for voice-over-IP applications. + + Note: this has nothing to do with modems. You do not need to say Y + here in order to be able to use a modem under Linux. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called phonedev.o. + +QuickNet Internet LineJack/PhoneJack support +CONFIG_PHONE_IXJ + Say M if you have a telephony card manufactured by Quicknet + Technologies, Inc. These include the Internet PhoneJACK and + Internet LineJACK Telephony Cards. You will get a module called + ixj.o. + + For the ISA versions of these products, you can configure the + cards using the isapnp tools (pnpdump/isapnp) or you can use the + isapnp support. Please read Documentation/telephony/ixj.txt. + + For more information on these cards, see Quicknet's web site at: + http://www.quicknet.net/ . + + If you do not have any Quicknet telephony cards, you can safely + say N here. + FORE Systems 200E-series CONFIG_ATM_FORE200E This is a driver for the FORE Systems 200E-series ATM adapter @@ -4729,14 +4852,14 @@ CONFIG_ATM_FORE200E Enable PCA-200E card support on PCI-based hosts CONFIG_ATM_FORE200E_PCA - Enable this if you want your PCA-200E cards to be probed. + Say Y here if you want your PCA-200E cards to be probed. Use default PCA-200E firmware CONFIG_ATM_FORE200E_PCA_DEFAULT_FW Use the default PCA-200E firmware data shipped with the driver. Normal users do not have to deal with the firmware stuff, so - this feature is normally enabled. + they should say Y here. Pathname of user-supplied binary firmware CONFIG_ATM_FORE200E_PCA_FW @@ -4744,20 +4867,20 @@ CONFIG_ATM_FORE200E_PCA_FW firmware image supplied by the user. This pathname may be absolute or relative to the drivers/atm directory. - The driver comes with an adequate firmware image, so normal users - do not have to supply an alternative one. They just enable the use - of the default firmware instead. + The driver comes with an adequate firmware image, so normal users do + not have to supply an alternative one. They just say Y to "Use + default PCA-200E firmware" instead. Enable SBA-200E card support on SBUS-based hosts CONFIG_ATM_FORE200E_SBA - Enable this if you want your SBA-200E cards to be probed. + Say Y here if you want your SBA-200E cards to be probed. Use default SBA-200E firmware CONFIG_ATM_FORE200E_SBA_DEFAULT_FW Use the default SBA-200E firmware data shipped with the driver. Normal users do not have to deal with the firmware stuff, so - this feature is normally enabled. + they should say Y here. Pathname of user-supplied binary firmware CONFIG_ATM_FORE200E_SBA_FW @@ -4765,9 +4888,9 @@ CONFIG_ATM_FORE200E_SBA_FW firmware image supplied by the user. This pathname may be absolute or relative to the drivers/atm directory. - The driver comes with an adequate firmware image, so normal users - do not have to supply an alternative one. They just enable the use - of the default firmware instead. + The driver comes with an adequate firmware image, so normal users do + not have to supply an alternative one. They just say Y to "Use + default SBA-200E firmware", above. Maximum number of tx retries CONFIG_ATM_FORE200E_TX_RETRY @@ -4815,8 +4938,8 @@ CONFIG_SCSI The module will be called scsi_mod.o. If you want to compile it as a module, say M here and read Documentation/modules.txt and Documentation/scsi.txt. However, do not compile this as a module if - your root file systems (the one containing the directory /) is located - on a SCSI device. + your root file system (the one containing the directory /) is + located on a SCSI device. SCSI disk support CONFIG_BLK_DEV_SD @@ -4831,15 +4954,15 @@ CONFIG_BLK_DEV_SD The module will be called sd_mod.o. If you want to compile it as a module, say M here and read Documentation/modules.txt and Documentation/scsi.txt. Do not compile this driver as a module if - your root file systems (the one containing the directory /) is located - on a SCSI disk. In this case, do not compile the driver for your - SCSI host adapter (below) as a module either. + your root file system (the one containing the directory /) is + located on a SCSI disk. In this case, do not compile the driver for + your SCSI host adapter (below) as a module either. Extra SCSI Disks CONFIG_SD_EXTRA_DEVS This controls the amount of additional space allocated in tables for drivers that are loaded as modules after the kernel is booted. In - the event that the SCSI core itself was loaded as a module, this this + the event that the SCSI core itself was loaded as a module, this value is the number of additional disks that can be loaded after the first host driver is loaded. @@ -4847,6 +4970,8 @@ CONFIG_SD_EXTRA_DEVS involved with resizing the internal arrays on the fly. Someday this flag will go away, and everything will work automatically. + If you don't understand what's going on, go with the default. + SCSI tape support CONFIG_CHR_DEV_ST If you want to use a SCSI tape drive under Linux, say Y and read the @@ -4866,7 +4991,7 @@ CONFIG_BLK_DEV_SR If you want to use a SCSI CDROM under Linux, say Y and read the SCSI-HOWTO and the CDROM-HOWTO at http://www.linuxdoc.org/docs.html#howto . Also make sure to say Y - or M to "ISO 9660 CDROM file systems support" later. + or M to "ISO 9660 CDROM file system support" later. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -4877,15 +5002,17 @@ CONFIG_BLK_DEV_SR Extra SCSI CDROMs CONFIG_SR_EXTRA_DEVS This controls the amount of additional space allocated in tables for - drivers that are loaded as modules after the kernel is booted. In the - event that the SCSI core itself was loaded as a module, this this value - is the number of additional CDROMs that can be loaded after the first - host driver is loaded. + drivers that are loaded as modules after the kernel is booted. In + the event that the SCSI core itself was loaded as a module, this + value is the number of additional CDROMs that can be loaded after + the first host driver is loaded. Admittedly this isn't pretty, but there are tons of race conditions involved with resizing the internal arrays on the fly. Someday this flag will go away, and everything will work automatically. + If you don't understand what's going on, go with the default. + Enable vendor-specific extensions (for SCSI CDROM) CONFIG_BLK_DEV_SR_VENDOR This enables the usage of vendor specific SCSI commands. This is @@ -4917,13 +5044,14 @@ CONFIG_CHR_DEV_SG Debug new queueing code for SCSI CONFIG_SCSI_DEBUG_QUEUES - This option turns on a lot of additional consistency checking for the new - queueing code. This will adversely affect performance, but it is likely - that bugs will be caught sooner if this is turned on. This will typically - cause the kernel to panic if an error is detected, but it would have probably - crashed if the panic weren't there. Comments/questions/problems to - linux-scsi mailing list please. See http://www.andante.org/scsi_queue.html - for more uptodate information. + This option turns on a lot of additional consistency checking for + the new queueing code. This will adversely affect performance, but + it is likely that bugs will be caught sooner if this is turned on. + This will typically cause the kernel to panic if an error is + detected, but it would have probably crashed if the panic weren't + there. Comments/questions/problems to linux-scsi mailing list + please. See http://www.andante.org/scsi_queue.html for more + up-to-date information. Probe all LUNs on each SCSI device CONFIG_SCSI_MULTI_LUN @@ -4947,12 +5075,12 @@ CONFIG_SCSI_LOGGING of SCSI related problems. If you say Y here, no logging output will appear by default, but you - can enable logging by saying Y to "/proc file systems support" and + can enable logging by saying Y to "/proc file system support" and "Sysctl support" below and executing the command echo "scsi log token [level]" > /proc/scsi/scsi - at boot time after the /proc file systems has been mounted. + at boot time after the /proc file system has been mounted. There are a number of things that can be used for 'token' (you can find them in the source: drivers/scsi/scsi.c), and this allows you @@ -4983,7 +5111,7 @@ CONFIG_SCSI_AHA152X It is explained in section 3.3 of the SCSI-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . You might also want to - read the comments at the top of drivers/scsi/aha152x.c. + read the file drivers/scsi/README.aha152x. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -5130,18 +5258,22 @@ CONFIG_AIC7XXX_RESET_DELAY after a bus reset to be ready for the next command, but most hard drives and CD-ROM devices are ready in only a few seconds. This option has a maximum upper limit of 20 seconds to avoid bad - interactions between the aic7xxx driver and the rest of the linux + interactions between the aic7xxx driver and the rest of the Linux kernel. The default value has been reduced to 5 seconds. If this doesn't work with your hardware, try increasing this value. IBM ServeRAID Support CONFIG_SCSI_IPS This is support for the IBM ServeRAID hardware RAID controllers. - Consult the SCSI-HOWTO, available via anonymous FTP from - ftp://metalab.unc.edu/pub/Linux/docs/HOWTO, and the file - README.ips in drivers/scsi for more information. If this driver - does not work correctly without modification please contact the - author by email at ipslinux@us.ibm.com. + + Please consult the SCSI-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + You can build this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + but only a single instance may be loaded. If you want to compile it + as a module, say M here and read Documentation/modules.txt. The + module will be called ips.o. BusLogic SCSI support CONFIG_SCSI_BUSLOGIC @@ -5538,9 +5670,7 @@ CONFIG_SCSI_IBMMCA info like under OS/2, but more informative, by setting 'ibmmcascsi=display' as an additional kernel parameter. Try "man bootparam" or see the documentation of your boot loader about how to - pass options to the kernel. The lilo procedure is also explained in - the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + pass options to the kernel. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -5867,13 +5997,32 @@ CONFIG_SCSI_SYM53C416 read Documentation/modules.txt. The module will be called sym53c416.o. +Simple 53c710 SCSI support (Compaq, NCR machines) +CONFIG_SCSI_SIM710 + This is a simple driver for NCR53c710 based SCSI host adapters. + + More complex drivers for this chip are available ("NCR53c7,8xx SCSI + support", above), but they require that the scsi chip be able to do + DMA block moves between memory and on-chip registers, which can + cause problems under certain conditions. This driver is designed to + avoid these problems and is intended to work with any Intel machines + using 53c710 chips, including various Compaq and NCR machines. + + Please read the comments at the top of the file + drivers/scsi/sim710.c for more information. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called sim710.o. + Tekram DC390(T) and Am53/79C974 (PCscsi) SCSI support CONFIG_SCSI_DC390T This driver supports PCI SCSI host adapters based on the Am53C974A chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard PCscsi/PCnet (Am53/79C974) solutions. - Documentation can be found in linux/drivers/scsi/README.tmscsim. + Documentation can be found in drivers/scsi/README.tmscsim. Note that this driver does NOT support Tekram DC390W/U/F, which are based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. @@ -5891,7 +6040,7 @@ CONFIG_SCSI_DC390T_NOGENSUPP EEPROM to get initial values for its settings, such as speed, termination, etc. If it can't find this EEPROM, it will use defaults or the user supplied boot/module parameters. For details on driver - configuration see linux/drivers/scsi/README.tmscsim. + configuration see drivers/scsi/README.tmscsim. If you say Y here and if no EEPROM is found, the driver gives up and thus only supports Tekram DC390(T) adapters. This can be useful if @@ -6025,21 +6174,28 @@ CONFIG_SCSI_DEBUG important data. This is primarily of use to people trying to debug the middle and upper layers of the SCSI subsystem. If unsure, say N. -Fibre Channel support +Fibre Channel support and FC4 SCSI support CONFIG_FC4 - This is an experimental support for storage arrays connected to - the system using Fibre Optic and the "X3.269-199X Fibre Channel - Protocol for SCSI" specification. You'll also need the generic SCSI - support, as well as the drivers for the storage array itself and - for the interface adapter such as SOC or SOC+. This subsystem could even - serve for IP networking, with some code extensions. If unsure, say N. + Fibre Channel is a high speed serial protocol mainly used to + connect large storage devices to the computer; it is compatible with + and intended to replace SCSI. + + This is an experimental support for storage arrays connected to your + computer using optical fibre cables and the "X3.269-199X Fibre + Channel Protocol for SCSI" specification. If you want to use this, + you need to say Y here and to "SCSI support" as well as to the + drivers for the storage array itself and for the interface adapter + such as SOC or SOC+. This subsystem could even serve for IP + networking, with some code extensions. + + If unsure, say N. Sun SOC CONFIG_FC4_SOC Serial Optical Channel is an interface card with one or two Fibre - Optic ports, each of which can be connected to a disk array. Note that - if you have older firmware in the card, you'll need the microcode from - the Solaris driver to make it work. + Optic ports, each of which can be connected to a disk array. Note + that if you have older firmware in the card, you'll need the + microcode from the Solaris driver to make it work. This support is also available as a module called soc.o ( = code which can be inserted in and removed from the running kernel @@ -6048,11 +6204,11 @@ CONFIG_FC4_SOC Sun SOC+ (aka SOCAL) CONFIG_FC4_SOCAL - Serial Optical Channel Plus is an interface card with up to two Fibre - Optic ports. This card supports FC Arbitrated Loop (usually A5000 or - internal FC disks in E[3-6]000 machines through the Interface Board). - You'll probably need the microcode from the Solaris driver to make it - work. + Serial Optical Channel Plus is an interface card with up to two + Fibre Optic ports. This card supports FC Arbitrated Loop (usually + A5000 or internal FC disks in E[3-6]000 machines through the + Interface Board). You'll probably need the microcode from the + Solaris driver to make it work. This support is also available as a module called socal.o ( = code which can be inserted in and removed from the running kernel @@ -6070,9 +6226,9 @@ CONFIG_SCSI_PLUTO Sun Enterprise Network Array (A5000 and EX500) CONFIG_SCSI_FCAL - This driver drives FC-AL disks connected through a Fibre Channel card - using the drivers/fc4 layer (currently only SOCAL). - The most common is either A5000 array or internal disks in E[3-6]000 + This driver drives FC-AL disks connected through a Fibre Channel + card using the drivers/fc4 layer (currently only SOCAL). The most + common is either A5000 array or internal disks in E[3-6]000 machines. This support is also available as a module called fcal.o ( = code @@ -6133,55 +6289,125 @@ CONFIG_SCSI_POWERTECSCSI This enables support for the Powertec SCSI card on Acorn systems. If you have one of these, say Y. If unsure, say N. -Network device support? -CONFIG_NETDEVICES - You can say N here if you don't intend to connect your Linux box to - any other computer at all or if all your connections will be over a - telephone line with a modem either via UUCP (UUCP is a protocol to - forward mail and news between unix hosts over telephone lines; read - the UUCP-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto ) or dialing up a shell - account or a BBS, even using term (term is a program which gives you - almost full Internet connectivity if you have a regular dial up - shell account on some Internet connected Unix computer. Read - http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). +IEEE 1394 (aka FireWire) support +CONFIG_IEEE1394 + IEEE 1394 describes a high performance serial bus, which is also + known as FireWire(tm) or i.Link(tm) and is used for connecting all + sorts of devices (most notably digital video cameras) to your + computer. - You'll have to say Y if your computer contains a network card that - you want to use under Linux (make sure you know its name because you - will be asked for it and read the Ethernet-HOWTO (especially if you - plan to use more than one network card under Linux)) or if you want - to use SLIP (Serial Line Internet Protocol is the protocol used to - send Internet traffic over telephone lines or null modem cables) or - CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better - and newer replacement for SLIP) or PLIP (Parallel Line Internet - Protocol is mainly used to create a mini network by connecting the - parallel ports of two local machines) or AX.25/KISS (protocol for - sending Internet traffic over amateur radio links). + If you have FireWire hardware and want to use it, say Y here. This + is the core support only, you will also need to select a driver for + your IEEE 1394 adapter. - Make sure to read the NET-3-HOWTO. Eventually, you will have to read - Olaf Kirch's excellent and free book "Network Administrator's - Guide", to be found in ftp://metalab.unc.edu/pub/Linux/docs/LDP . If - unsure, say Y. + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ieee1394.o. -Bonding driver support -CONFIG_BONDING - Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet - Channels together. This is called 'Etherchannel' by Cisco, 'Trunking' - by Sun, and 'Bonding' in Linux. +TI PCILynx IEEE 1394 support +CONFIG_IEEE1394_PCILYNX + Say Y here if you have a IEEE-1394 controller with the Texas + Instruments PCILynx chip. Note: this driver is written for revision + 2 of this chip and may not work with revision 0. - If you have two ethernet connections to some other computer, you can - make them behave like one double speed connection using this driver. - Naturally, this has to be supported at the other end as well, either - with a similar Bonding Linux driver, a Cisco 5500 switch or a - SunTrunking SunSoft driver. + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called pcilynx.o. + +Use local RAM on PCILynx board +CONFIG_IEEE1394_PCILYNX_LOCALRAM + This option makes the PCILynx driver use local RAM available on some + PCILynx setups for Packet Control Lists. Local RAM is random access + memory which resides on the PCILynx board as opposed to on your + computer's motherboard. Local RAM may speed up command processing + because no PCI transfers are necessary during use of the Packet + Control Lists. + + Note that there are no known PCILynx systems providing local RAM + except for the evaluation boards by Texas Instruments and that the + PCILynx does not reliably report missing RAM. This means that it is + dangerous to say Y here if you are not absolutely sure that your + board provides 64KB of local RAM. - This is similar to the EQL driver, but it merge ethernet segments instead - of serial lines. + If unsure, say N. + +Adaptec AIC-5800 IEEE 1394 support +CONFIG_IEEE1394_AIC5800 + Say Y here if you have a IEEE 1394 controller using the Adaptec + AIC-5800 chip. All Adaptec host adapters (89xx series) use this + chip, as well as miro's DV boards. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be - called bonding.o. + called aic5800.o. + +OHCI (Open Host Controller Interface) support +CONFIG_IEEE1394_OHCI1394 + Say Y here if you have a IEEE 1394 controller based on OHCI. + The current driver was only tested with OHCI chipsets made + by Texas Instruments. However, most third-party vendors use + TI chips. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ohci1394.o. + +Raw IEEE 1394 I/O support +CONFIG_IEEE1394_RAWIO + Say Y here if you want support for the raw device. This is generally + a good idea, so you should say Y here. The raw device enables + direct communication of user programs with the IEEE 1394 bus and + thus with the attached peripherals. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called raw1394.o. + +Excessive debugging output +CONFIG_IEEE1394_VERBOSEDEBUG + If you say Y here, you will get very verbose debugging logs from the + subsystem which includes a dump of the header of every sent and + received packet. This can amount to a high amount of data collected + in a very short time which is usually also saved to disk by the + system logging daemons. + + Say Y if you really want or need the debugging output, everyone else + says N. + +Network device support? +CONFIG_NETDEVICES + You can say N here if you don't intend to connect your Linux box to + any other computer at all or if all your connections will be over a + telephone line with a modem either via UUCP (UUCP is a protocol to + forward mail and news between unix hosts over telephone lines; read + the UUCP-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto ) or dialing up a shell + account or a BBS, even using term (term is a program which gives you + almost full Internet connectivity if you have a regular dial up + shell account on some Internet connected Unix computer. Read + http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html ). + + You'll have to say Y if your computer contains a network card that + you want to use under Linux (make sure you know its name because you + will be asked for it and read the Ethernet-HOWTO (especially if you + plan to use more than one network card under Linux)) or if you want + to use SLIP (Serial Line Internet Protocol is the protocol used to + send Internet traffic over telephone lines or null modem cables) or + CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better + and newer replacement for SLIP) or PLIP (Parallel Line Internet + Protocol is mainly used to create a mini network by connecting the + parallel ports of two local machines) or AX.25/KISS (protocol for + sending Internet traffic over amateur radio links). + + Make sure to read the NET-3-HOWTO. Eventually, you will have to read + Olaf Kirch's excellent and free book "Network Administrator's + Guide", to be found in http://www.linuxdoc.org/docs.html#guide . If + unsure, say Y. Dummy net driver support CONFIG_DUMMY @@ -6193,7 +6419,7 @@ CONFIG_DUMMY thing often comes in handy, the default is Y. It won't enlarge your kernel either. What a deal. Read about it in the Network Administrator's Guide, available from - http://metalab.unc.edu/mdw/linux.html#guide . + http://www.linuxdoc.org/docs.html#guide . If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -6202,6 +6428,26 @@ CONFIG_DUMMY time, you need to compile this driver as a module. Instead of 'dummy', the devices will then be called 'dummy0', 'dummy1' etc. +Bonding driver support +CONFIG_BONDING + Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet + Channels together. This is called 'Etherchannel' by Cisco, + 'Trunking' by Sun, and 'Bonding' in Linux. + + If you have two ethernet connections to some other computer, you can + make them behave like one double speed connection using this driver. + Naturally, this has to be supported at the other end as well, either + with a similar Bonding Linux driver, a Cisco 5500 switch or a + SunTrunking SunSoft driver. + + This is similar to the EQL driver, but it merges Ethernet segments + instead of serial lines. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called bonding.o. + SLIP (serial line) support CONFIG_SLIP Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to @@ -6241,11 +6487,11 @@ CONFIG_SLIP_COMPRESSED on both ends. Ask your access provider if you are not sure and answer Y, just in case. You will still be able to use plain SLIP. If you plan to use SLiRP, the SLIP emulator (available from - ftp://metalab.unc.edu/pub/Linux/system/network/serial/ ) which allows - you to use SLIP over a regular dial up shell connection, you + ftp://metalab.unc.edu/pub/Linux/system/network/serial/ ) which + allows you to use SLIP over a regular dial up shell connection, you definitely want to say Y here. The NET-3-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto , explains how to - configure CSLIP. This won't enlarge your kernel. + http://www.linuxdoc.org/docs.html#howto , explains how to configure + CSLIP. This won't enlarge your kernel. Keepalive and linefill CONFIG_SLIP_SMART @@ -6306,6 +6552,7 @@ CONFIG_PPP_ASYNC into and removed from the running kernel). If you want to compile it as a module, say M here and read Documentation/modules.txt. +PPP support for sync tty ports CONFIG_PPP_SYNC_TTY Say Y (or M) here if you want to be able to use PPP over synchronous (HDLC) tty devices, such as the SyncLink adapter. These devices @@ -6348,10 +6595,20 @@ CONFIG_PPP_BSDCOMP Wireless LAN (non-hamradio) CONFIG_NET_RADIO Support for wireless LANs and everything having to do with radio, - but not with amateur radio. Note that the answer to this question - won't directly affect the kernel: saying N will just cause this - configure script to skip all the questions about radio - interfaces. + but not with amateur radio or FM broadcasting. + + Saying Y here also enables the Wireless Extensions (creates + /proc/net/wireless and enables ifconfig access). The Wireless + Extension is a generic API allowing a driver to expose to the user + space configuration and statistics specific to common Wireless LANs. + The beauty of it is that a single set of tool can support all the + variations of Wireless LANs, regardless of their type (as long as + the driver supports Wireless Extension). Another advantage is that + these parameters may be changed on the fly without restarting the + driver (or Linux). If you wish to use Wireless Extensions with + wireless PCMCIA (PC-) cards, you need to say Y here; you can fetch + the tools from + http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html . Some user-level drivers for scarab devices which don't require special kernel support are available from @@ -6398,8 +6655,8 @@ CONFIG_WAVELAN in the source code drivers/net/wavelan.p.h. You will also need the wireless tools package available from - ftp://hyper.stanford.edu/pub/pcmcia/contrib/ . Please read the man - pages contained therein. + http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html . + Please read the man pages contained therein. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -6412,95 +6669,109 @@ CONFIG_ARLAN Aironet makes Arlan, a class of wireless LAN adapters. These use the www.Telxon.com chip, which is also used on several similar cards. This driver is tested on the 655 and IC2200 series cards. Look at - http://www.ylenurme.ee/~elmer/655/ for latest information. + http://www.ylenurme.ee/~elmer/655/ for the latest information. The driver is built as two modules, arlan and arlan-proc. The latter is the /proc interface and is not needed most of time. - On some computers the card ends up in non-valid state after some time. - Use a ping-reset script to clear it. + On some computers the card ends up in non-valid state after some + time. Use a ping-reset script to clear it. Aironet 4500/4800 series adapters CONFIG_AIRONET4500 www.aironet.com (recently bought by Cisco) makes these 802.11 DS adapters. Driver by Elmer Joandi (elmer@ylenurme.ee). - Work sponsored by www.spectrumwireless.net and www.vendomar.ee - This configuration option enables common code for all devices (PCI, ISA, - PCMCIA) - module is aironet4500_core + + Say Y here if you have such an adapter, and then say Y below to + the option that applies to your particular type of card (PCI, ISA, + or PCMCIA). + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called aironet4500_core.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + quick config parameters: SSID=tsunami - "The Password" adhoc=1 there are no Access Points around - master=1 Adhoc master (the one who creates network sync) - slave=1 Adhoc slave(btw, it is still forming own net + master=1 Adhoc master (the one who creates network + sync) + slave=1 Adhoc slave (btw, it is still forming own net sometimes, and has problems with firmware... change IbssJoinNetTimeout from /proc...) channel=1..? meaningful in adhoc mode - all other parameters can be set via /proc interface - These parameters belong to .._card module, but alas, they are here - if you have problems with screwing up card, both_bap_lock=1 is conservative - value (performance hit 15%) - for any other configuration options look at ..._proc module + + If you have problems with screwing up card, both_bap_lock=1 is a + conservative value (performance hit 15%). + + All other parameters can be set via the proc interface. Aironet 4500/4800 ISA/PCI/PNP/365 support CONFIG_AIRONET4500_NONCS - This is module aironet4500_card, which includes _possibility_ to - support for following - PCI device - ISA device in ISA mode(does not work currently) - ISA device in PNP mode - PCMCIA device _without_ cardservices, direct 365 chip INIT, - does not work currently - PCMCIA _with_ CardServices(normal way) is at another module - radio parameters are currently configurable at ..._core module + If you have an ISA, PCI or PCMCIA Aironet 4500/4800 wireless LAN + card, say Y here, and then also to the options below that apply + to you. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called aironet4500_card.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt Aironet 4500/4800 PNP support CONFIG_AIRONET4500_PNP - This option should be enabled for ISA cards, remember to enable - PNP jumper on board. - module aironet4500_card + If you have an ISA Aironet 4500/4800 card which you want to use in + PNP (Plug and Play) mode, say Y here. This is the recommended mode + for ISA cards. Remember however to enable the PNP jumper on the + board if you say Y here. Aironet 4500/4800 PCI support CONFIG_AIRONET4500_PCI - This option should be enabled for PCI cards - module aironet4500_card + If you have an PCI Aironet 4500/4800 card, say Y here. Aironet 4500/4800 ISA broken support (EXPERIMENTAL) CONFIG_AIRONET4500_ISA - This option enables support for ISA cards in non-PNP mode. - Does not operate correctly by now. - module aironet4500_card + If you have an ISA Aironet 4500/4800 card which you want to run in + non-PNP mode, say Y here. This is not recommended and does not work + correctly at this point. Say N. Aironet 4500/4800 I365 broken support (EXPERIMENTAL) CONFIG_AIRONET4500_I365 - This option enables support for PCMCIA cards on i365 controller - _without_ cardservices. Doesn't have much sense and is not working - properly. Comes from times where there was no PCMCIA support in - kernel main source tree + If you have a PCMCIA Aironet 4500/4800 card which you want to use + without the standard PCMCIA cardservices provided by the pcmcia-cs + package, say Y here. This is not recommended, so say N. Aironet 4500/4800 PCMCIA support CONFIG_AIRONET4500_CS - This option enables support for PCMCIA cards to be used with - CardServices. - This is not for ISA and PCI adapters. - module aironet4500_cs.o - The same option is both on: - 1. PCMCIA netdevices configuring panel - 2. Wireless netdevices configuring panel - Possibility to change this option depends on options set in 2. + Say Y here if you have a PCMCIA Aironet 4500/4800 card which you + want to use with the standard PCMCIA cardservices provided by the + pcmcia-cs package. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called aironet4500_cs.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. Aironet 4500/4800 PROC interface CONFIG_AIRONET4500_PROC - This option enables /proc/sys/aironet4500 interface for - configuring the device. - NOTE: it takes lot of memory. Compile it as module and remove - after configuration - module: aironet4500_proc - additional info: look into drivers/net/aironet4500_rids.c - this is quite human-readable(no need to know C) + If you say Y here (and to the "/proc file system" below), you will + be able to configure your Aironet card via the + /proc/sys/aironet4500 interface. + Additional info: look in drivers/net/aironet4500_rids.c. - + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called aironet4500_proc.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. + + NOTE: the proc interface uses a lot of memory, so it is recommended + to compile it as a module and remove the module after + configuration. LAPB over Ethernet driver CONFIG_LAPBETHER @@ -6530,8 +6801,18 @@ CONFIG_X25_ASY PCMCIA network device support CONFIG_NET_PCMCIA - Say Y if you would like to include support for any PCMCIA network - adapters. If unsure, say N. + Say Y if you would like to include support for any PCMCIA or CardBus + network adapters, then say Y to the driver for your particular card + below. PCMCIA- or PC-cards are credit-card size devices often used + with laptops computers; CardBus is the newer and faster version of + PCMCIA. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). You also want to check out the PCMCIA-HOWTO, available + from http://www.linuxdoc.org/docs.html#howto . + + If unsure, say N. 3Com 3c589 PCMCIA support CONFIG_PCMCIA_3C589 @@ -6562,8 +6843,8 @@ CONFIG_PCMCIA_FMVJ18X This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called fmvj18x_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called fmvj18x_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. NE2000 compatible PCMCIA support @@ -6584,8 +6865,8 @@ CONFIG_PCMCIA_NMCLAN This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called nmclan_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called nmclan_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. SMC 91Cxx PCMCIA support @@ -6595,9 +6876,9 @@ CONFIG_PCMCIA_SMC91C92 This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called smc91c92_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, - say N. + The module will be called smc91c92_cs.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. If + unsure, say N. Xircom 16-bit PCMCIA support CONFIG_PCMCIA_XIRC2PS @@ -6606,10 +6887,21 @@ CONFIG_PCMCIA_XIRC2PS This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called xirc2ps_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called xirc2ps_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. +COM20020 ARCnet PCMCIA support +CONFIG_ARCNET_COM20020_CS + Say Y here if you intend to attach this type of ARCnet PCMCIA card + to your computer. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called com20020_cs.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. If + unsure, say N. + 3Com 3c575 CardBus support CONFIG_PCMCIA_3C575 This driver supports the 3Com 3c575 series of CardBus Fast Ethernet @@ -6620,20 +6912,36 @@ CONFIG_PCMCIA_3C575 The module will be called 3c575_cb.o. If you want to do that, say M here and read Documentation/modules.txt. If unsure, say N. -SMC EPIC CardBus support -CONFIG_PCMCIA_EPIC100 - This driver supports CardBus Fast Ethernet adapters based on the SMC - EPIC chipset. +Xircom Tulip-like CardBus support +CONFIG_PCMCIA_XIRTULIP + This driver is for the Digital "Tulip" Ethernet CardBus adapters. + It should work with most DEC 21*4*-based chips/ethercards, as well + as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and + ASIX. - This driver can only be compiled as a module ( = code which can be + This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called epic100_cb.o. If you want to do that, say - M here and read Documentation/modules.txt. If unsure, say N. + The module will be called xircom_tulip_cb.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. If + unsure, say N. + +Pcmcia Wireless LAN +CONFIG_NET_PCMCIA_RADIO + Say Y here if you would like to use a PCMCIA (PC-card) device to + connect to a wireless local area network. Then say Y to the driver + for your particular card below. + + To use your PC-cards, you will need supporting software from David + Hinds' pcmcia-cs package (see the file Documentation/Changes for + location). You also want to check out the PCMCIA-HOWTO, available + from http://www.linuxdoc.org/docs.html#howto . Aviator/Raytheon 2.4MHz wireless support CONFIG_PCMCIA_RAYCS Say Y here if you intend to attach an Aviator/Raytheon PCMCIA (PC-card) wireless Ethernet networking card to your computer. + Please read the file Documentation/networking/ray_cs.txt for + details. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -6643,13 +6951,13 @@ CONFIG_PCMCIA_RAYCS Xircom Netwave AirSurfer wireless support CONFIG_PCMCIA_NETWAVE - Say Y here if you intend to attach a Xircom Netwave AirSurfer PCMCIA - (PC-card) wireless Ethernet networking card to your computer. + Say Y here if you intend to attach this type of PCMCIA (PC-card) + wireless Ethernet networking card to your computer. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called netwave_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called netwave_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. AT&T/Lucent Wavelan wireless support @@ -6660,8 +6968,8 @@ CONFIG_PCMCIA_WAVELAN This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called wavelan_cs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. If unsure, + The module will be called wavelan_cs.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. If unsure, say N. PLIP (parallel port) support @@ -6824,17 +7132,6 @@ CONFIG_ECONET_NATIVE Say Y here if you have a native Econet network card installed in your computer. -Wan interfaces support -CONFIG_WAN - Wide Area Networks (WANs), such as X.25, frame relay and leased - lines, are used to interconnect Local Area Networks (LANs) over vast - distances with data transfer rates significantly higher than those - achievable with commonly used asynchronous modem connections. - - Say Y here if you want to use such interconnections. - - It is safe to say N. Most people won't need it. - WAN Router CONFIG_WAN_ROUTER Wide Area Networks (WANs), such as X.25, frame relay and leased @@ -6860,18 +7157,6 @@ CONFIG_WAN_ROUTER If unsure, say N. -WAN router drivers -CONFIG_WAN_ROUTER_DRIVERS - Wide Area Networks (WANs), such as X.25, frame relay and leased - lines, are used to interconnect Local Area Networks (LANs) over vast - distances with data transfer rates significantly higher than those - achievable with commonly used asynchronous modem connections. - Usually, a quite expensive external device called a `WAN router' is - needed to connect to a WAN. - - Say Y here will enable the kernel to a??? as a WAN router betwenn LAN by - means of WAN adapters. - Fast switching (read help!) CONFIG_NET_FASTROUTE Saying Y here enables direct NIC-to-NIC (NIC = Network Interface @@ -6927,9 +7212,15 @@ CONFIG_NET_SCHED That package also contains some documentation; for more, check out http://snafu.freedom.org/linux2.2/iproute-notes.html . - If you say Y here and to "/proc file system support" below, you will - be able to read status information about packet schedulers from the - file /proc/net/psched. + This Quality of Service (QoS) support will enable you to use + Differentiated Services (diffserv) and Resource Reservation Protocol + (RSVP) on your Linux router if you also say Y to "QoS support", + "Packet classifier API" and to some classifiers below. Documentation + and software is at http://icawwww1.ipfl.ch/linux/diffserv/ . + + If you say Y here and to "/proc file system" below, you will be able + to read status information about packet schedulers from the file + /proc/net/psched. The available schedulers are listed in the following questions; you can say Y to as many as you like. If unsure, say N now. @@ -7040,12 +7331,23 @@ CONFIG_NET_SCH_TBF whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +### Add these +#+tristate ' GRED queue' CONFIG_NET_SCH_GRED +#+tristate ' Diffserv field marker' CONFIG_NET_SCH_DSMARK +#+tristate ' Ingress Qdisc' CONFIG_NET_SCH_INGRESS + QoS support CONFIG_NET_QOS Say Y here if you want to include Quality Of Service scheduling features, which means that you will be able to request certain rate-of-flow limits for your network devices. + This Quality of Service (QoS) support will enable you to use + Differentiated Services (diffserv) and Resource Reservation Protocol + (RSVP) on your Linux router if you also say Y to "Packet classifier + API" and to some classifiers below. Documentation and software is at + http://icawwww1.ipfl.ch/linux/diffserv/ . + Note that the answer to this question won't directly affect the kernel: saying N will just cause this configure script to skip all the questions about QoS support. @@ -7064,8 +7366,16 @@ CONFIG_NET_CLS choice of several different packet classifiers with the following questions. + This will enable you to use Differentiated Services (diffserv) and + Resource Reservation Protocol (RSVP) on your Linux router. + Documentation and software is at + http://icawwww1.ipfl.ch/linux/diffserv/ . + +### Add +#tristate ' TC index classifier' CONFIG_NET_CLS_TCINDEX + Routing tables based classifier -CONFIG_NET_CLS_ROUTE +CONFIG_NET_CLS_ROUTE4 If you say Y here, you will be able to classify outgoing packets according to the route table entry they matched. If unsure, say Y. @@ -7124,7 +7434,7 @@ CONFIG_NET_CLS_RSVP6 here and read Documentation/modules.txt # -# Ingres traffic policing +# Traffic policing (needed for in/egress) # CONFIG_NET_CLS_POLICE ### ### Some expert please fill these in @@ -7137,6 +7447,22 @@ CONFIG_NET_PROFILE performance will be written to /proc/net/profile. If you don't know what it is about, you don't need it: say N. +Wan interfaces support +CONFIG_WAN + Wide Area Networks (WANs), such as X.25, frame relay and leased + lines, are used to interconnect Local Area Networks (LANs) over vast + distances with data transfer rates significantly higher than those + achievable with commonly used asynchronous modem connections. + Usually, a quite expensive external device called a `WAN router' is + needed to connect to a WAN. + + As an alternative, a relatively inexpensive WAN interface card can + allow your Linux box to directly connect to a WAN. If you have one + of those cards and wish to use it under Linux, say Y here and also + to the WAN driver for your card, below. + + If unsure, say N. + Comtrol Hostess SV-11 support CONFIG_HOSTESS_SV11 This is a network card for low speed synchronous serial links, at @@ -7168,16 +7494,24 @@ CONFIG_COSA Fibre Channel driver support CONFIG_NET_FC - Say Y here provide support for storage arrays connected to - the system using Fibre Optic and the "X3.269-199X Fibre Channel - Protocol for SCSI" specification. You'll also need the generic SCSI - support, as well as the drivers for the storage array itself and - for the interface adapter such as SOC or SOC+. This subsystem could even - serve for IP networking, with some code extensions. If unsure, say N. + Fibre Channel is a high speed serial protocol mainly used to connect + large storage devices to the computer; it is compatible with and + intended to replace SCSI. + + If you intend to use Fibre Channel, you need to have a Fibre channel + adaptor card in your computer; say Y here and to the driver for your + adaptor below. You also should have said Y to "SCSI support" and + "SCSI generic support". -# Interphase 5526 Tachyon chipset based adaptor support -# CONFIG_IPHASE5526 +Interphase 5526 Tachyon chipset based adaptor support +CONFIG_IPHASE5526 + Say Y here if you have a Fibre Channel adaptor of this kind. + The driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called iph5526.o. For general information about + modules read Documentation/modules.txt. + Red Creek Hardware VPN (EXPERIMENTAL) CONFIG_RCPCI This is a driver for hardware which provides a Virtual Private @@ -7188,43 +7522,46 @@ CONFIG_RCPCI whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. -SBNI Leased Line Adapters +SBNI12-xx support CONFIG_SBNI - This is a driver for ISA SBNI12-xx cards that is a low cost - alternative to leased line modems. Say Y if you want to insert - driver into kernel or say M to compile driver as a module. + This is a driver for ISA SBNI12-xx cards which are low cost + alternatives to leased line modems. Say Y if you want to insert + the driver into the kernel or say M to compile it as a module (the + module will be called sbni.o). You can find more information and last versions of drivers and - utilities at http://www.granch.ru. If you have any question you - can mail to sbni@granch.ru. + utilities at http://www.granch.ru . If you have any question you + can send email to sbni@granch.ru. Say N if unsure. - -WAN Drivers -CONFIG_WAN_DRIVERS - Say Y to this option if your Linux box contains a WAN card and you - are planning to use the box as a WAN ( = Wide Area Network) router - ( = device used to interconnect local area networks over wide area - communication links, such as leased lines or public data networks, - e.g. X.25 or frame relay) and you will be offered a list of drivers - for WAN cards currently available. For more information, read - Documentation/networking/wan-router.txt. + +WAN router drivers +CONFIG_WAN_ROUTER_DRIVERS + If you have a WAN interface card and you want your Linux box to act + as a WAN router, thereby connecting you Local Area Network to the + outside world over the WAN connection, say Y here and then to the + driver for your card below. In addition, you need to say Y to "Wan + Router". + + You will need the wan-tools package which is available from + ftp://ftp.sangoma.com . Read Documentation/networking/wan-router.txt + for more information. Note that the answer to this question won't directly affect the kernel: saying N will just cause this configure script to skip all - the questions about WAN card drivers. If unsure, say N. + the questions about WAN router drivers. If unsure, say N. Sangoma WANPIPE(tm) multiprotocol cards CONFIG_VENDOR_SANGOMA - WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com ) is a - family of intelligent multiprotocol WAN adapters with data transfer - rates up to T1 (1.544 Mbps). They are also known as Synchronous Data - Link Adapters (SDLA) and designated S502E(A), S503 or S508. These - cards support the X.25, Frame Relay, and PPP protocols. If you have - one or more of these cards, say Y to this option; you may then also - want to read the file Documentation/networking/wanpipe.txt. The next - questions will ask you about the protocols you want the driver to - support. + WANPIPE from Sangoma Technologies Inc. (http://www.sangoma.com ) is + a family of intelligent multiprotocol WAN adapters with data + transfer rates up to T1 (1.544 Mbps). They are also known as + Synchronous Data Link Adapters (SDLA) and designated S502E(A), S503 + or S508. These cards support the X.25, Frame Relay, and PPP + protocols. If you have one or more of these cards, say Y to this + option; you may then also want to read the file + Documentation/networking/wanpipe.txt. The next questions will ask + you about the protocols you want the driver to support. The driver will be compiled as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -7239,6 +7576,13 @@ CONFIG_WANPIPE_CARDS re-compiling the driver, but remember that in this case you'll waste some kernel memory (about 1K per card). +WANPIPE Cisco HDLC support +CONFIG_WANPIPE_CHDLC + Say Y to this option if you are planning to connect a WANPIPE card + to a connection which uses the synchronous Cisco HDLC (High-level + Data Link Control) protocol. This protocol is often used on + high-speed leased lines like T1/E1. + WANPIPE X.25 support CONFIG_WANPIPE_X25 Say Y to this option if you are planning to connect a WANPIPE card @@ -7265,13 +7609,13 @@ CONFIG_WANPIPE_PPP MultiGate/COMX support CONFIG_COMX - Say Y if you want to use any board from the MultiGate (COMX) family. - These boards are synchronous serial adapters for the PC, manufactured - by ITConsult-Pro Co, Hungary. + Say Y if you want to use any board from the MultiGate (COMX) family. + These boards are synchronous serial adapters for the PC, + manufactured by ITConsult-Pro Co, Hungary. - Read linux/Documentation/networking/comx.txt for help on configuring - and using COMX interfaces. Further info on these cards can be found at - http://www.itc.hu or . + Read linux/Documentation/networking/comx.txt for help on configuring + and using COMX interfaces. Further info on these cards can be found + at http://www.itc.hu or . If you want to compile this as a module, say M and read Documentation/modules.txt. The module will be called comx.o. @@ -7289,30 +7633,34 @@ CONFIG_COMX_HW_COMX LoCOMX board support CONFIG_COMX_HW_LOCOMX - Hardware driver for the 'LoCOMX' board from the MultiGate family. Say Y - if you have a board like this. + Hardware driver for the 'LoCOMX' board from the MultiGate family. + Say Y if you have a board like this. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-hw-locomx.o. + Documentation/modules.txt. The module will be called + comx-hw-locomx.o. MixCOM board support CONFIG_COMX_HW_MIXCOM - Hardware driver for the 'MixCOM' board from the MultiGate family. Say Y - if you have a board like this. + Hardware driver for the 'MixCOM' board from the MultiGate family. + Say Y if you have a board like this. If you want to use the watchdog device on this card, you should select it in the Watchdog Cards section of the Character Devices - configuration. The ISDN interface of this card is Teles 16.3 compatible, - you should enable it in the ISDN configuration menu. The driver for the - flash ROM of this card is available separately on ftp://ftp.itc.hu/. + configuration. The ISDN interface of this card is Teles 16.3 + compatible, you should enable it in the ISDN configuration menu. The + driver for the flash ROM of this card is available separately on + ftp://ftp.itc.hu/. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-hw-mixcom.o. + Documentation/modules.txt. The module will be called + comx-hw-mixcom.o. MultiGate Cisco-HDLC and synchronous PPP protocol support CONFIG_COMX_PROTO_PPP - Cisco-HDLC and synchronous PPP protocol driver for all MultiGate boards. - Say Y if you want to use either protocol on your MultiGate boards. + Cisco-HDLC and synchronous PPP protocol driver for all MultiGate + boards. Say Y if you want to use either protocol on your MultiGate + boards. If you want to compile this as a module, say M and read Documentation/modules.txt. The module will be called @@ -7324,7 +7672,8 @@ CONFIG_COMX_PROTO_LAPB want to use this protocol on your MultiGate boards. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-proto-lapb.o. + Documentation/modules.txt. The module will be called + comx-proto-lapb.o. MultiGate Frame Relay protocol support CONFIG_COMX_PROTO_FR @@ -7332,7 +7681,8 @@ CONFIG_COMX_PROTO_FR want to use this protocol on your MultiGate boards. If you want to compile this as a module, say M and read - Documentation/modules.txt. The module will be called comx-proto-fr.o. + Documentation/modules.txt. The module will be called + comx-proto-fr.o. Cyclom 2X(tm) multiprotocol cards (EXPERIMENTAL) CONFIG_CYCLADES_SYNC @@ -7353,7 +7703,7 @@ CONFIG_CYCLADES_SYNC Feel free to contact me or the cycsyn-devel mailing list at acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for additional details, I hope to have documentation available as soon - as possible (Cyclades Brazil is writing the Documentation). + as possible. (Cyclades Brazil is writing the Documentation). The driver will be compiled as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -7393,22 +7743,6 @@ CONFIG_NET_ETHERNET kernel: saying N will just cause this configure script to skip all the questions about Ethernet network cards. If unsure, say N. -Sun LANCE Ethernet support -CONFIG_SUN_LANCE - This is support for lance Ethernet cards on Sun workstations such as - the SPARCstation IPC (any SPARC with a network interface 'le0' under - SunOS basically). - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called lance.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - -Sun Intel Ethernet support -CONFIG_SUN_INTEL - This is support for the Intel Ethernet cards on some Sun - workstations (all those with a network interface 'ie0' under SunOS). - Western Digital/SMC cards CONFIG_NET_VENDOR_SMC If you have a network (Ethernet) card belonging to this class, say Y @@ -7504,19 +7838,6 @@ CONFIG_NE2K_PCI module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -PCI DM9102(A)/DM9132/DM9801 support -CONFIG_DM9102 - This driver is for DM9102 compatible PCI cards from Davicom - (http://www.davicom.com.tw) including models DM9132 & DM9801. - If you have a PCI DM9102, DM9132 or DM9801 network (Ethernet) - card, say Y. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called dmfe.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. - Racal-Interlan (Micom) NI cards CONFIG_NET_VENDOR_RACAL If you have a network (Ethernet) card belonging to this class, such @@ -7580,9 +7901,9 @@ CONFIG_RTL8129 RealTek RTL-8139 PCI Fast Ethernet Adapter support CONFIG_8139TOO This is a driver for the Fast Ethernet PCI network cards based on - the RTL8139 chip. If you have one of those, say Y and - read the Ethernet-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + the RTL8139 chips. If you have one of those, say Y and read + Documentation/networking/8139too.txt as well as the Ethernet-HOWTO, + available from http://www.linuxdoc.org/docs.html#howto . If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -7594,13 +7915,13 @@ CONFIG_SIS900 This is a driver for the Fast Ethernet PCI network cards based on the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in SiS 630 and SiS 540 chipsets. If you have one of those, say Y and - read the Ethernet-HOWTO, available via FTP (user: anonymous) in - ftp://metalab.unc.edu/pub/Linux/docs/HOWTO. Please read - Documentation/networking/sis900.txt and comments at the beginning - of drivers/net/sis900.c for more information. + read the Ethernet-HOWTO, available at + http://www.linuxdoc.org/docs.html#howto . Please read + Documentation/networking/sis900.txt and comments at the beginning of + drivers/net/sis900.c for more information. - This driver also supports AMD 79C901 HomePNA such that you can use - your phone line as network cable. + This driver also supports AMD 79C901 HomePNA so that you can use + your phone line as a network cable. If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -7642,6 +7963,18 @@ CONFIG_NET_SB1000 If you don't have this card, of course say N. +Adaptec Starfire support (EXPERIMENTAL) +CONFIG_ADAPTEC_STARFIRE + Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network + adapter. The DuraLAN chip is used on the 64 bit PCI boards from + Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip + driver. + + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called starfile.o. + Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support CONFIG_ACENIC Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear @@ -7692,6 +8025,11 @@ MyriCOM Gigabit Ethernet support CONFIG_MYRI_SBUS This driver supports MyriCOM Sbus gigabit ethernet cards. + If you want to compile this driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. This is recommended. + The module will be called myri_sbus.o. + AMD LANCE and PCnet (AT1500 and NE2100) support CONFIG_LANCE If you have a network (Ethernet) card of this type, say Y and read @@ -7704,6 +8042,12 @@ CONFIG_LANCE say M here and read Documentation/modules.txt. This is recommended. The module will be called lance.o. +SGI IOC3 Ethernet +CONFIG_SGI_IOC3_ETH + If you have a network (Ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + 3COM cards CONFIG_NET_VENDOR_3COM If you have a network (Ethernet) card belonging to this class, say Y @@ -7807,6 +8151,18 @@ CONFIG_EL3 Documentation/networking/net-modules.txt. The module will be called 3c509.o. +3c515 ISA Fast EtherLink +CONFIG_3C515 + If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet + network card, say Y and read the Ethernet-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. The module will be called + 3c515.o. + 3c590 series (592/595/597) "Vortex" support CONFIG_VORTEX If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) @@ -7868,7 +8224,7 @@ CONFIG_ARCNET_ETH ARCnet documentation in Documentation/networking/arcnet.txt for more information about using arc0e and arc0s. -Enable arc0s (ARCnet RFC1051 packet format) +Enable old ARCNet packet format (RFC 1051) CONFIG_ARCNET_1051 This allows you to use RFC1051 with your ARCnet card via the virtual arc0s device. You only need arc0s if you want to talk to ARCnet @@ -8188,7 +8544,7 @@ CONFIG_LNE390 module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL) +Novell/Eagle/Microdyne NE3210 EISA support CONFIG_NE3210 If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from @@ -8273,10 +8629,10 @@ CONFIG_EEPRO100 module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. -EtherExpress PRO/100 support -CONFIG_EEPRO100_PM (EXPERIMENTAL) +Enable Power Management (EXPERIMENTAL) +CONFIG_EEPRO100_PM If you want to play around with power management code - that has reported to lock up some machines, say Y here. + that has been reported to lock up some machines, say Y here. ICL EtherTeam 16i/32 support (EXPERIMENTAL) CONFIG_ETH16I @@ -8307,7 +8663,7 @@ CONFIG_TLAN module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. - Please email feedback to torben.mathiasen@compaq.com. + Please email feedback to torben.mathiasen@compaq.com. VIA Rhine support CONFIG_VIA_RHINE @@ -8320,6 +8676,19 @@ CONFIG_VIA_RHINE a module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. +PCI DM9102(A)/DM9132/DM9801 support +CONFIG_DM9102 + This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from + Davicom ( http://www.davicom.com.tw ). If you have such a network + (Ethernet) card, say Y. Some information is contained in the file + Documentation/networking/dmfe.txt. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called dmfe.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. + Racal-Interlan EISA ES3210 support (EXPERIMENTAL) CONFIG_ES3210 If you have a network (Ethernet) card of this type, say Y and read @@ -8357,18 +8726,6 @@ CONFIG_ZNET by this driver. Read the Ethernet-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . -Adaptec Starfire support -CONFIG_ADAPTEC_STARFIRE - If you have an Ethernet network card like this, say Y and read the - Ethernet-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called starfire.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. - Pocket and portable adapters CONFIG_NET_POCKET Cute little network (Ethernet) devices which attach to the parallel @@ -8396,9 +8753,14 @@ CONFIG_ATP port. Read drivers/net/atp.c as well as the Ethernet-HOWTO, available from http://www.linuxdoc.org/docs.html#howto , if you want to use this. If you intend to use this driver, you should have - said N to the Parallel Printer support, because the two drivers + said N to the "Parallel printer support", because the two drivers don't like each other. + If you want to compile this driver as a module however ( = code + which can be inserted in and removed from the running kernel + whenever you want), say M here and read Documentation/modules.txt. + The module will be called atp.o. + D-Link DE600 pocket adapter support CONFIG_DE600 This is a network (Ethernet) device which attaches to your parallel @@ -8469,22 +8831,22 @@ CONFIG_IBMOL The module will will be called olympic.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - Also read the file Documentation/networking/olympic.txt or check the + Also read the file Documentation/networking/olympic.txt or check the Linux Token Ring Project site for the latest information at - http://www.linuxtr.net + http://www.linuxtr.net . IBM Lanstreamer chipset PCI adapter support CONFIG_IBMLS This is support for IBM Lanstreamer PCI Token Ring Cards. - If you have such an adapter, say Y and read the Token-Ring mini-HOWTO - available via FTP (user:anonymous) from + If you have such an adapter, say Y and read the Token-Ring + mini-HOWTO available via FTP (user:anonymous) from ftp://metalab.unc/edu/pub/Linux/docs/HOWTO. This driver is also available as a modules ( = code which can be inserted in and removed from the running kernel whenever you want). - The modules will be called lanstreamer.o. If you want to compile it as - a module, say M here and read Documentation/modules.txt. + The modules will be called lanstreamer.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Generic TMS380 Token Ring ISA/PCI/MCA/EISA adapter support CONFIG_TMS380TR @@ -8493,16 +8855,21 @@ CONFIG_TMS380TR includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591), Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several - Madge adapters. If selected, you will be asked to select + Madge adapters. If you say Y here, you will be asked to select which cards to support below. If you're using modules, each class of card will be supported by a separate module. - If you have such an adapter and would like to use it, say Y or M and + If you have such an adapter and would like to use it, say Y and read the Token-Ring mini-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . - Also read the file linux/Documentation/networking/tms380tr.txt or check - http://www.auk.cx/tms380tr/ + Also read the file Documentation/networking/tms380tr.txt or + check http://www.auk.cx/tms380tr/ . + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called tms380tr.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Generic TMS380 PCI support CONFIG_TMSPCI @@ -8514,30 +8881,53 @@ CONFIG_TMSPCI - Thomas-Conrad TC4048 PCI 4/16 - 3Com Token Link Velocity + This driver is available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called tmspci.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + Madge Smart 16/4 PCI Mk2 support CONFIG_ABYSS - This tms380 module supports the Madge Smart 16/4 PCI Mk2 cards (51-02). + This tms380 module supports the Madge Smart 16/4 PCI Mk2 + cards (51-02). + + This driver is available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called abyss.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Madge Smart 16/4 Ringode MicroChannel CONFIG_MADGEMC This tms380 module supports the Madge Smart 16/4 MC16 and MC32 - MicroChannel adapters + MicroChannel adapters. + + This driver is available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called madgemc.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. SMC ISA TokenRing adapter support CONFIG_SMCTR - This is support for the ISA and MCA SMC Token Ring cards, specifically - SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A (8115T/A) adapters. + This is support for the ISA and MCA SMC Token Ring cards, + specifically SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A + (8115T/A) adapters. If you have such an adapter and would like to use it, say Y or M and read the Token-Ring mini-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto . + http://www.linuxdoc.org/docs.html#howto and the file + Documentation/networking/smctr.txt. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will will be called smctr.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. Sun Happy Meal 10/100baseT support CONFIG_HAPPYMEAL - This driver supports the "hme" interface present on most Ultra systems - and as an option on older Sbus systems. This driver supports both PCI - and Sbus devices. This driver also supports the "qfe" quad 100baseT - device available in both PCI and Sbus configurations. + This driver supports the "hme" interface present on most Ultra + systems and as an option on older Sbus systems. This driver supports + both PCI and Sbus devices. This driver also supports the "qfe" quad + 100baseT device available in both PCI and Sbus configurations. This support is also available as a module called sunhme.o ( = code which can be inserted in and removed from the running kernel @@ -8549,8 +8939,8 @@ CONFIG_SUNLANCE This driver supports the "le" interface present on all 32-bit Sparc systems, on some older Ultra systems and as an Sbus option. - This support is also available as a module called sunlance.o ( = code - which can be inserted in and removed from the running kernel + This support is also available as a module called sunlance.o ( = + code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -8630,8 +9020,10 @@ CONFIG_SKFP - Netelligent 100 FDDI DAS UTP - Netelligent 100 FDDI SAS UTP - Netelligent 100 FDDI SAS Fibre MIC + Read Documentation/networking/skfp.txt for information about the driver. + WARNING: this driver does currently not support 64 bit systems! Questions concerning this driver can be addressed to: linux@syskonnect.de @@ -8641,14 +9033,6 @@ CONFIG_SKFP say M here and read Documentation/modules.txt. This is recommended. The module will be called skfp.o. -Linux telephony support -CONFIG_PHONE - This option enable the kernel to manage telephony cards. - - There are very few supported cards at this moment. - - If unsure, say N. - HIgh Performance Parallel Interface support (EXPERIMENTAL) CONFIG_HIPPI HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and @@ -8722,7 +9106,7 @@ CONFIG_CD_NO_IDESCSI read Documentation/modules.txt. If you want to use any of these CDROM drivers, you also have to - answer Y or M to "ISO 9660 CDROM file systems support" below (this + answer Y or M to "ISO 9660 CDROM file system support" below (this answer will get "defaulted" for you if you enable any of the Linux CDROM drivers). @@ -8735,11 +9119,10 @@ CONFIG_CDU31A time as described in Documentation/cdrom/cdu31a or fill in your parameters into drivers/cdrom/cdu31a.c. Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel. The lilo procedure is also - explained in the SCSI-HOWTO. + how to pass options to the kernel. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8761,7 +9144,7 @@ CONFIG_MCD this. If you want that one, say N here. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8794,7 +9177,7 @@ CONFIG_MCDX Documentation/cdrom/mcdx. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8832,7 +9215,7 @@ CONFIG_SBPCD usable. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8845,7 +9228,7 @@ CONFIG_SBPCD2 Say Y here only if you have two CDROM controller cards of this type (usually only if you have more than four drives). You should enter the parameters for the second, third and fourth interface card into - linux/include/linux/sbpcd.h before compiling the new kernel. Read + include/linux/sbpcd.h before compiling the new kernel. Read the file Documentation/cdrom/sbpcd. Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support @@ -8857,7 +9240,7 @@ CONFIG_AZTCD CDA269-031SE. Please read the file Documentation/cdrom/aztcd. If you say Y here, you should also say Y or M to "ISO 9660 CDROM - file systems support" below, because that's the file systems used on + file system support" below, because that's the file system used on CDROMs. This driver is also available as a module ( = code which can be @@ -8882,8 +9265,8 @@ CONFIG_CDU535 Goldstar R420 CDROM support CONFIG_GSCD If this is your CDROM drive, say Y here. As described in the file - linux/Documentation/cdrom/gscd, you might have to change a setting - in the file linux/drivers/cdrom/gscd.h before compiling the + Documentation/cdrom/gscd, you might have to change a setting + in the file drivers/cdrom/gscd.h before compiling the kernel. Please read the file Documentation/cdrom/gscd. If you say Y here, you should also say Y or M to "ISO 9660 CDROM @@ -8939,17 +9322,6 @@ CONFIG_SJCD The module will be called sjcd.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -Soft configurable cdrom interface card support -CONFIG_CDI_INIT - If you want to include boot-time initialization of any cdrom - interface card that is software configurable, say Y here. Currently - only the ISP16/MAD16/Mozart sound cards with built-in cdrom - interfaces are supported. - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause this configure script to skip all - the questions about these CDROM drives. - ISP16/MAD16/Mozart soft configurable cdrom interface support CONFIG_ISP16_CDI These are sound cards with built-in cdrom interfaces using the OPTi @@ -8979,8 +9351,8 @@ CONFIG_USB traditional PC serial port. The bus supplies power to peripherals and allows for hot swapping. Up to 127 USB peripherals can be connected to a single USB port in a tree structure. The USB port is - the root of the tree, the peripherals are the leaves, and the inner - nodes are special USB devices called hubs. Many newer PCs have USB + the root of the tree, the peripherals are the leaves and the inner + nodes are special USB devices called hubs. Many newer PC's have USB ports and newer peripherals such as scanners, keyboards, mice, modems, and printers support the USB protocol and can be connected to the PC via those ports. @@ -9077,17 +9449,37 @@ CONFIG_USB_KBD USB keyboard and prefer to use the keyboard in its limited Boot Protocol mode. This driver is much smaller than the HID one. + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called usbkbd.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + + If unsure, say N. + USB HIDBP Mouse support CONFIG_USB_MOUSE Say Y here if you don't want to use the generic HID driver for your USB mouse and prefer to use the mouse in its limited Boot Protocol mode. This driver is much smaller than the HID one. + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called usbmouse.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + + If unsure, say N. + Wacom Intuos/Graphire tablet support CONFIG_USB_WACOM - Say Y here if you want to use the USB version of the Wacom - Intuos or Graphire tablet. Make sure you select Mouse and Event - support as well. + Say Y here if you want to use the USB version of the Wacom Intuos or + Graphire tablet. Make sure to say Y to "Mouse support" + (CONFIG_INPUT_MOUSEDEV) and "Event interface support" + (CONFIG_INPUT_EVDEV) as well. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called wacom.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Logitech WingMan Force joystick support CONFIG_USB_WMFORCE @@ -9095,42 +9487,65 @@ CONFIG_USB_WMFORCE on the USB port. No force-feedback support yet, but other than that, it should work like a normal joystick. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called wmforce.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + Keyboard support CONFIG_INPUT_KEYBDEV Say Y here if you want your USB HID keyboard to be able to serve as a system keyboard. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called keybdev.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + Mouse support CONFIG_INPUT_MOUSEDEV Say Y here if you want your USB HID mouse to be accessible as - misc devices 32+ under /dev/, as an emulated PS/2 mouse. + misc devices 32+ under /dev/, as an emulated PS/2 mouse. That way, + all user space programs will be able to use your mouse. + + If unsure, say Y. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called mousedev.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Mix all mice into one device CONFIG_INPUT_MOUSEDEV_MIX Say Y here if you want input from all your USB HID mice to be mixed into one misc device. If you say N, you'll have a separate - device for each your USB mouse. + device for each USB mouse. Support for digitizers CONFIG_INPUT_MOUSEDEV_DIGITIZER - Use this if you have a digitizer that doesn't emulate a mouse + Say Y here if you have a digitizer that doesn't emulate a mouse itself, and want to use it as a mouse. Horizontal screen resolution CONFIG_INPUT_MOUSEDEV_SCREEN_X - For the mouse emulation to be correct, the mousedev driver needs - to know the screen resolution you are using (in X). + For the mouse emulation to be correct, the mousedev driver needs to + know the screen resolution you are using (in the X window system). Vertical screen resolution CONFIG_INPUT_MOUSEDEV_SCREEN_Y - For the mouse emulation to be correct, the mousedev driver needs - to know the screen resolution you are using (in X). + For the mouse emulation to be correct, the mousedev driver needs to + know the screen resolution you are using (in the X window system). Joystick support CONFIG_INPUT_JOYDEV Say Y here if you want your USB HID joystick or gamepad to be - accessible as /dev/js device. You can't use a normal joystick - if you select this. + accessible as a /dev/js device. You can't use a normal (non-USB) + joystick if you say Y here. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joydev.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Event interface support CONFIG_INPUT_EVDEV @@ -9140,18 +9555,18 @@ CONFIG_INPUT_EVDEV USB Scanner support CONFIG_USB_SCANNER - Say Y here if you want to connect a USB scanner to your - computer's USB port. Please read Documentation/usb/scanner.txt - and Documentation/usb/scanner-hp-sane.txt for more information. + Say Y here if you want to connect a USB scanner to your computer's + USB port. Please read Documentation/usb/scanner.txt and + Documentation/usb/scanner-hp-sane.txt for more information. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called hp_scanner.o. If you want to compile it as + The module will be called scanner.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. USB Audio support CONFIG_USB_AUDIO - Say Y here if you want to connect USB audio equipment such as + Say Y here if you want to connect UAB audio equipment such as speakers to your computer's USB port. This code is also available as a module ( = code which can be @@ -9171,11 +9586,16 @@ CONFIG_USB_ACM USB Serial converter support CONFIG_USB_SERIAL - Say Y here if you want to connect a Connect Tech WhiteHEAT - multi-port USB to serial converter; a FTDI or Keyspan single port - USB to serial converter; or a Handspring Visor. Please read - Documentation/usb/usb-serial.txt for more information. - + Say Y here if you have a USB device that provides normal serial + ports, and you want to connect it to your USB bus. Supported devices + are the Tech WhiteHEAT multi-port USB to serial converter, and the + FTDI or Keyspan single port USB to serial converter Handspring + Visor. In addition to saying Y here, you need to say Y to the driver + for your specific hardware below. Some other devices may also be + used if you say Y to "USB Generic Serial Driver", below. + + Please read Documentation/usb/usb-serial.txt for more information. + This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called usb-serial.o. If you want to compile it @@ -9183,10 +9603,11 @@ CONFIG_USB_SERIAL USB Generic Serial Driver CONFIG_USB_SERIAL_GENERIC - Say Y here if you want to use the generic USB serial driver. - Please read Documentation/usb/usb-serial.txt for more information - on using this driver. It is recommended that the USB Serial - Driver be compiled as a module for this driver to be used properly. + Say Y here if you want to use the generic USB serial driver. Please + read Documentation/usb/usb-serial.txt for more information on using + this driver. It is recommended that the "USB Serial converter + support" be compiled as a module for this driver to be used + properly. USB ConnectTech WhiteHEAT Serial Driver CONFIG_USB_SERIAL_WHITEHEAT @@ -9202,7 +9623,10 @@ CONFIG_USB_SERIAL_VISOR USB FTDI Single Port Serial Driver CONFIG_USB_SERIAL_FTDI_SIO Say Y here if you want to use a FTDI SIO single port USB to serial - converter device. + converter device. The implementation I have is called the USC-1000 + + See http://reality.sgi.com/bryder_wellington/ftdi_sio for more information + on this driver and the device USB FTDI Single Port Serial Driver CONFIG_USB_SERIAL_KEYSPAN_PDA @@ -9221,8 +9645,9 @@ CONFIG_USB_PRINTER USB IBM (Xirlink) C-It Camera support CONFIG_USB_IBMCAM - Say Y here if you want to connect this type of camera to your - computer's USB port. + Say Y here if you want to connect a IBM "C-It" camera, also known as + "Xirlink PC Camera" to your computer's USB port. For more + information, read Documentation/usb/ibmcam.txt. This driver uses the Video For Linux API. You must enable (Y or M in config) Video For Linux (under Character Devices) @@ -9243,11 +9668,10 @@ CONFIG_USB_OV511 computer's USB port. See Documentation/usb/ov511.txt for more information and for a list of supported cameras. - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found on the WWW at - http://roadrunner.swansea.uk.linux.org/v4l.shtml . + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" (under Character Devices) to use this driver. + Information on this API and pointers to "v4l" programs may be found + on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml . This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9293,7 +9717,6 @@ CONFIG_USB_MDC800 The module will be called mdc800.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - USB Mass Storage support CONFIG_USB_STORAGE Say Y here if you want to connect USB mass storage devices to your @@ -9312,8 +9735,9 @@ CONFIG_USB_STORAGE_DEBUG USS720 parport driver CONFIG_USB_USS720 This driver is for USB parallel port adapters that use the Lucent - Technologies USS-720 chip. These adapters provide USB compatibility - to peripherals designed with parallel port interfaces. + Technologies USS-720 chip. These cables are plugged into your USB + port and provide USB compatibility to peripherals designed with + parallel port interfaces. The chip has two modes: automatic mode and manual mode. In automatic mode, it looks to the computer like a standard USB printer. Only @@ -9338,38 +9762,53 @@ CONFIG_USB_USS720 USB device file system CONFIG_USB_DEVICEFS - This file system implements a "devices" file, that lists - the currently connected to your USB busses, a "drivers" file - that lists the USB kernel client drivers currently loaded, - and for every connected device a file named "xxx/yyy", where - xxx is the bus number and yyy the device number, that can be used - by userspace drivers to talk to the device. + If you say Y here (and to "/proc file system support" below), you + will get a file /proc/usb/devices which lists the devices currently + connected to your USB busses, a file /proc/usb/drivers file which + lists the USB kernel client drivers currently loaded, and for every + connected device a file named "/proc/usb/xxx/yyy", where xxx is the + bus number and yyy the device number; the latter files can be used + by userspace drivers to talk to the device. These files are + "virtual", meaning they are generated on the fly and not stored on + the hard drive. + + For the format of the /proc/usb/ files, please read + Documentation/usb/proc_usb_info.txt. + + Please note that this code is completely unrelated to devfs, the + "/dev file system support". Most users want to say Y here. DABUSB driver CONFIG_USB_DABUSB - A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought - to you by the DAB-Team (http://dab.in.tum.de). - This driver can be taken as an example for URB-based bulk, control, and - isochronous transactions. + A Digital Audio Broadcasting (DAB) Receiver for USB and Linux + brought to you by the DAB-Team (http://dab.in.tum.de). This driver + can be taken as an example for URB-based bulk, control, and + isochronous transactions. URB's are explained in + Documentation/usb/URB.txt. This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called dabusb.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. - + PLUSB driver CONFIG_USB_PLUSB - A driver for the Prolific PL-2302 USB-to-USB network device. This 'USB - cable' connects two hosts via a point-to-point network with bandwidth of - 5 Mbit/s. Configure this driver after connecting the USB cable via - ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 - (and vice versa on the other host). + A driver for the Prolific PL-2302 USB-to-USB network device. This + 'USB cable' connects two hosts via a point-to-point network with + bandwidth of 5 Mbit/s. Configure this driver after connecting the + USB cable via ifconfig plusb0 10.0.0.1 pointopoint 10.0.0.2 (and + vice versa on the other host). + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called plusb.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. USB Diamond Rio500 support CONFIG_USB_RIO500 - Say Y here if you want to connect a USB rio500 to your + Say Y here if you want to connect a USB Rio500 mp3 player to your computer's USB port. Please read Documentation/usb/rio.txt for more information. @@ -9378,7 +9817,7 @@ CONFIG_USB_RIO500 The module will be called rio500.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -D-Link DSB-R100 FM radio upport +D-Link DSB-R100 FM radio support CONFIG_USB_DSBR Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and @@ -9394,13 +9833,7 @@ CONFIG_USB_DSBR This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called dsbr100.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - -ACPI support -CONFIG_ACPI - Advanced Configuration and Power Interface (ACPI) is an interface - specification to support power management of peripherals. If your - system supports it, say Y here. + module, say M here and read Documentation/modules.txt. Minix fs support CONFIG_MINIX_FS @@ -9408,16 +9841,16 @@ CONFIG_MINIX_FS The minix file system (method to organize files on a hard disk partition or a floppy disk) was the original file system for Linux, but has been superseded by the second extended file system ext2fs. - You don't want to use the minix file system on your hard disk because - of certain built-in restrictions, but it is sometimes found on older - Linux floppy disks. This option will enlarge your kernel by about - 28 kB. If unsure, say N. + You don't want to use the minix file system on your hard disk + because of certain built-in restrictions, but it is sometimes found + on older Linux floppy disks. This option will enlarge your kernel by + about 28 KB. If unsure, say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be - called minix.o. Note that the file system of your root partition (the - one containing the directory /) cannot be compiled as a module. + called minix.o. Note that the file system of your root partition + (the one containing the directory /) cannot be compiled as a module. Second extended fs support CONFIG_EXT2_FS @@ -9425,11 +9858,11 @@ CONFIG_EXT2_FS files on a storage device) for hard disks. You want to say Y here, unless you intend to use Linux exclusively - from inside a DOS partition using the umsdos file system. The + from inside a DOS partition using the UMSDOS file system. The advantage of the latter is that you can get away without repartitioning your hard drive (which often implies backing everything up and restoring afterwards); the disadvantage is that - Linux becomes susceptible to DOS viruses and that umsdos is somewhat + Linux becomes susceptible to DOS viruses and that UMSDOS is somewhat slower than ext2fs. Even if you want to run Linux in this fashion, it might be a good idea to have ext2fs around: it enables you to read more floppy disks and facilitates the transition to a *real* @@ -9437,7 +9870,7 @@ CONFIG_EXT2_FS ext2fs is a diskless Linux box which mounts all files over the network using NFS (in this case it's sufficient to say Y to "NFS file system support" below). Saying Y here will enlarge your kernel - by about 44 kB. + by about 44 KB. The Ext2fs-Undeletion mini-HOWTO, available from http://www.linuxdoc.org/docs.html#howto , gives information about @@ -9451,9 +9884,10 @@ CONFIG_EXT2_FS command line tool package (available via FTP (user: anonymous) from ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2 ) and from within Windows NT using the ext2nt command line tool package from - ftp://metalab.unc.edu/pub/Linux/utils/dos . Explore2fs is a graphical - explorer for ext2fs partitions which runs on Windows 95 and Windows - NT and includes experimental write support; it is available from + ftp://metalab.unc.edu/pub/Linux/utils/dos . Explore2fs is a + graphical explorer for ext2fs partitions which runs on Windows 95 + and Windows NT and includes experimental write support; it is + available from http://jnewbigin-pc.it.swin.edu.au/Linux/Explore2fs.htm . If you want to compile this file system as a module ( = code which @@ -9467,31 +9901,50 @@ CONFIG_EXT2_FS BFS file system support (EXPERIMENTAL) CONFIG_BFS_FS Boot File System (BFS) is a file system used under SCO UnixWare to - allow bootloader access the kernel image and other important files - during the boot process. It is usually mounted under /stand and - corresponds to the slice marked as "STAND" in the UnixWare - partition. This is useful if you want to access files on your /stand - slice from Linux. More information on this file system can be found in - Documentation/filesystems/bfs.txt file. If you do not know what it is, - say N. + allow the bootloader access to the kernel image and other important + files during the boot process. It is usually mounted under /stand + and corresponds to the slice marked as "STAND" in the UnixWare + partition. You should say Y if you want to read or write + the files on your /stand slice from within Linux. You then also + need to say Y to "UnixWare slices support", below. More information + about the BFS file system is contained in the file + Documentation/filesystems/bfs.txt. + + If you don't know what this is about, say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called bfs.o. Note that the file system of your root partition (the one containing the directory /) cannot be compiled as a module. - + +Compressed ROM file system support +CONFIG_CRAMFS + Saying Y here includes support for CramFs (Compressed ROM File + System). Cramfs is designed to be a simple, small, and compressed + file system for ROM based embedded systems. CramFs is read-only, + limited to 256MB file systems (with 16MB files), and doesn't support + 16/32 bits uid/gid, hard links and timestamps. + + See Documentation/filesystems/cramfs.txt and fs/cramfs/README + for further information. + + If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called cramfs.o. + ISO 9660 CDROM file system support CONFIG_ISO9660_FS This is the standard file system used on CDROMs. It was previously - known as "High Sierra File System" and is called "hsfs" on other Unix - systems. The so-called Rock-Ridge extensions which allow for long - Unix filenames and symbolic links are also supported by this driver. - If you have a CDROM drive and want to do more with it than just - listen to audio CDs and watch its LEDs, say Y (and read + known as "High Sierra File System" and is called "hsfs" on other + Unix systems. The so-called Rock-Ridge extensions which allow for + long Unix filenames and symbolic links are also supported by this + driver. If you have a CDROM drive and want to do more with it than + just listen to audio CDs and watch its LEDs, say Y (and read Documentation/filesystems/isofs.txt and the CDROM-HOWTO, available - from http://www.linuxdoc.org/docs.html#howto ), thereby - enlarging your kernel by about 27 KB; otherwise say N. + from http://www.linuxdoc.org/docs.html#howto ), thereby enlarging + your kernel by about 27 KB; otherwise say N. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -9507,17 +9960,21 @@ CONFIG_JOLIET http://www.unicode.org for more information). Say Y here if you want to be able to read Joliet CDROMs under Linux. -UDF file system support (read only) +UDF File System support (read only) CONFIG_UDF_FS - This is the new file system used by some CDROMS and DVD drivers. Say - Y if you intend to mount DVD discs or CDRW's written in packet mode, - or if written to by other UDF utilities, such as DirectCD. Please - read Documentation/filesystems/udf.txt. - - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called udf.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This is the new file system used on some CDROMs and DVDs. Say Y if + you intend to mount DVD discs or CDRW's written in packet mode, or + if written to by other UDF utilities, such as DirectCD. This UDF + file system support is read-only. If you want to write to UDF + file systems on some media, you need to say Y to "UDF read-write + support" below in addition. Please read + Documentation/filesystems/udf.txt. + + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called udf.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say N. @@ -9525,7 +9982,7 @@ UDF write support (DANGEROUS) CONFIG_UDF_RW Say Y if you want to test write support for UDF file systems. Due to lack of support for writing to CDR/CDRW's, this option - is only supported for Hard Discs, DVD-RAM, and loopback files. + is only supported for hard discs, DVD-RAM, and loopback files. DOS FAT fs support CONFIG_FAT_FS @@ -9537,18 +9994,24 @@ CONFIG_FAT_FS files on them, i.e. MSDOS files will look and behave just like all other Unix files. - This FAT support is not a file system in itself, it only provides the - foundation for the other file systems. You will have to say Y or M to - at least one of "msdos fs support" or "vfat fs support" in order to - make use of it. + This FAT support is not a file system in itself, it only provides + the foundation for the other file systems. You will have to say Y or + M to at least one of "MSDOS fs support" or "VFAT fs support" in + order to make use of it. Another way to read and write MSDOS floppies and hard drive partitions from within Linux (but not transparently) is with the - mtools ("man mtools") program suite. This doesn't require the FAT - file system support. + mtools ("man mtools") program suite. You don't need to say Y here in + order to do that. + If you need to move large files on floppies between a DOS and a + Linux box, say Y here, mount the floppy under Linux with an MSDOS + file system and use GNU tar's M option. GNU tar is a program + available for Unix and DOS ("man tar" or "info tar"). + It is now also becoming possible to read and write compressed FAT - file systems; read Documentation/filesystems/fat_cvf.txt for details. + file systems; read Documentation/filesystems/fat_cvf.txt for + details. The FAT support will enlarge your kernel by about 37 KB. If unsure, say Y. @@ -9557,11 +10020,11 @@ CONFIG_FAT_FS be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called fat.o. Note that if you compile the FAT support as a - module, you cannot compile any of the FAT-based file systems into the - kernel -- they will have to be modules as well. The file system of - your root partition (the one containing the directory /) cannot be a - module, so don't say M here if you intend to use UMSDOS as your root - file system. + module, you cannot compile any of the FAT-based file systems into + the kernel -- they will have to be modules as well. The file system + of your root partition (the one containing the directory /) cannot + be a module, so don't say M here if you intend to use UMSDOS as your + root file system. MSDOS fs support CONFIG_MSDOS_FS @@ -9576,36 +10039,37 @@ CONFIG_MSDOS_FS transparent, i.e. the MSDOS files look and behave just like all other Unix files. - If you want to use umsdos, the Unix-like file system on top of DOS, - which allows you to run Linux from within a DOS partition without - repartitioning, you'll have to say Y or M here. + If you want to use UMSDOS, the Unix-like file system on top of a + DOS file system, which allows you to run Linux from within a DOS + partition without repartitioning, you'll have to say Y or M here. If you have Windows 95 or Windows NT installed on your MSDOS - partitions, you should use the VFAT file system (say Y to "vfat fs + partitions, you should use the VFAT file system (say Y to "VFAT fs support" below), or you will not be able to see the long filenames generated by Windows 95 / Windows NT. This option will enlarge your kernel by about 7 KB. If unsure, - answer Y. This will only work if you said Y to "fat fs support" as - well. If you want to compile this as a module however ( = code which - can be inserted in and removed from the running kernel whenever you - want), say M here and read Documentation/modules.txt. The module - will be called msdos.o. + answer Y. This will only work if you said Y to "DOS FAT fs support" + as well. If you want to compile this as a module however ( = code + which can be inserted in and removed from the running kernel + whenever you want), say M here and read Documentation/modules.txt. + The module will be called msdos.o. VFAT (Windows-95) fs support CONFIG_VFAT_FS This option provides support for normal Windows file systems with long filenames. That includes non-compressed FAT-based file systems - used by Windows 95, Windows 98, Windows NT 4.0, and mtools. + used by Windows 95, Windows 98, Windows NT 4.0, and the Unix + programs from the mtools package. You cannot use the VFAT file system for your Linux root partition (the one containing the directory /); use UMSDOS instead if you want to run Linux from within a DOS partition (i.e. say Y to - "umsdos: Unix like fs on top of std MSDOS fs", below). + "UMSDOS: Unix like fs on top of std MSDOS fs", below). The VFAT support enlarges your kernel by about 10 KB and it only - works if you said Y to the "fat fs support" above. Please read the - file Documentation/filesystems/vfat.txt for details. If unsure, + works if you said Y to the "DOS FAT fs support" above. Please read + the file Documentation/filesystems/vfat.txt for details. If unsure, say Y. If you want to compile this as a module ( = code which can be @@ -9613,23 +10077,6 @@ CONFIG_VFAT_FS say M here and read Documentation/modules.txt. The module will be called vfat.o. -Compressed ROM file system support -CONFIG_CRAMFS - This option provides support for CramFs (Compressed ROM File System). - Cramfs is designed to be a simple, small, and compressed file system for ROM - based embedded systems. - CramFs is read-only, limited to 256MB file systems (with 16MB files), don't - support neither 16/32 bits uid/gid nor hard links. Neither are timestamps. - It isn't endian aware. - - See Documentation/filesystems/cramfs.txt and fs/cramfs/README - for further information. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called cramfs.o. - UMSDOS: Unix-like file system on top of standard MSDOS fs CONFIG_UMSDOS_FS Say Y here if you want to run Linux from within an existing DOS @@ -9642,20 +10089,20 @@ CONFIG_UMSDOS_FS is to write files with long unix filenames to MSDOS floppies; it also allows Unix-style soft-links and owner/permissions of files on MSDOS floppies. You will need a program called umssync in order to - make use of umsdos; read Documentation/filesystems/umsdos.txt. + make use of UMSDOS; read Documentation/filesystems/umsdos.txt. To get utilities for initializing/checking UMSDOS file system, or - latest patches and/or information, visit UMSDOS homepage at + latest patches and/or information, visit the UMSDOS home page at http://www.voyager.hr/~mnalis/umsdos/ . This option enlarges your kernel by about 28 KB and it only works if - you said Y to both "fat fs support" and "msdos fs support" above. If - you want to compile this as a module ( = code which can be inserted - in and removed from the running kernel whenever you want), say M - here and read Documentation/modules.txt. The module will be called - umsdos.o. Note that the file system of your root partition (the one - containing the directory /) cannot be a module, so saying M could be - dangerous. If unsure, say N. + you said Y to both "DOS FAT fs support" and "MSDOS fs support" + above. If you want to compile this as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called umsdos.o. Note that the file system of your root partition + (the one containing the directory /) cannot be a module, so saying M + could be dangerous. If unsure, say N. /proc file system support CONFIG_PROC_FS @@ -9674,30 +10121,35 @@ CONFIG_PROC_FS The /proc file system is explained in the file Documentation/filesystems/proc.txt and on the proc(5) manpage ("man - 5 proc"). + 5 proc"). You can also use the program procinfo to display some + information about your system gathered from the /proc file system. This option will enlarge your kernel by about 67 KB. Several programs depend on this, so everyone should say Y here. /dev file system support (EXPERIMENTAL) CONFIG_DEVFS_FS - This is another virtual file system (like /proc) which provides the - file system interface to device drivers, normally found in /dev. - Devfs does not depend on major and minor number allocations. Device - drivers register entries in /dev which appear automagically. Without - devfs you need to populate /dev with hundreds, even thousands of - inodes. + This is support for devfs, a virtual file system (like /proc) which + provides the file system interface to device drivers, normally found + in /dev. Devfs does not depend on major and minor number + allocations. Device drivers register entries in /dev which then + appear automatically, which means that the system administrator does + not have to create character and block special device files in the + /dev directory using the mknod command anymore. + This is work in progress. If you want to use this you *must* read - Documentation/filesystems/devfs/README - In particular, make sure you install devfsd. If you don't, expect to - spend time patching broken code and updating configuration files. + the material in Documentation/filesystems/devfs/, especially the + file README there. + + If unsure, say N. Debug devfs CONFIG_DEVFS_DEBUG - This option appears if you have CONFIG_DEVFS_FS enabled. Setting - this to 'Y' enables devfs debugging output. See the file + If you say Y here, then the /dev file system code will generate + debugging messages. See the file Documentation/filesystems/devfs/boot-options for more details. - The default is 'N'. + + If unsure, say N. NFS file system support CONFIG_NFS_FS @@ -9710,7 +10162,7 @@ CONFIG_NFS_FS programs nfsd and mountd (but does not need to have NFS file system support enabled in its kernel). NFS is explained in the Network Administrator's Guide, available from - http://metalab.unc.edu/mdw/linux.html#guide , on its man page: "man + http://www.linuxdoc.org/docs.html#guide , on its man page: "man nfs", and in the NFS-HOWTO. A superior but less widely used alternative to NFS is provided by @@ -9761,8 +10213,7 @@ CONFIG_NFSD section. Please read the NFS-HOWTO, available from - http://www.linuxdoc.org/HOWTO/NFS-HOWTO.html . - + http://www.linuxdoc.org/docs.html#howto . The NFS server is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -9771,25 +10222,26 @@ CONFIG_NFSD Provide NFSv3 server support (EXPERIMENTAL) CONFIG_NFSD_V3 - If you would like to include the NFSv3 server was well as the NFSv2 - server, say Y here. File locking, via the NLMv4 protocol, is also - supported. If unsure, say N. + If you would like to include the NFSv3 server as well as the NFSv2 + server, say Y here. File locking, via the NLMv4 protocol, is not + supported yet. If unsure, say N. OS/2 HPFS file system support CONFIG_HPFS_FS OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS is the file system used for organizing files on OS/2 hard disk - partitions. Say Y if you want to be able to read files from an OS/2 - HPFS partition of your hard drive. OS/2 floppies however are in - regular MSDOS format, so you don't need this option in order to be - able to read them. Read Documentation/filesystems/hpfs.txt. + partitions. Say Y if you want to be able to read files from and + write files to an OS/2 HPFS partition on your hard drive. OS/2 + floppies however are in regular MSDOS format, so you don't need this + option in order to be able to read them. Read + Documentation/filesystems/hpfs.txt. This file system is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module is called hpfs.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say N. -NTFS file system support (read only) +NTFS support (read only) CONFIG_NTFS_FS NTFS is the file system of Microsoft Windows NT. Say Y if you want to get read access to files on NTFS partitions of your hard drive. @@ -9816,7 +10268,8 @@ System V and Coherent file system support (read only) CONFIG_SYSV_FS SCO, Xenix and Coherent are commercial Unix systems for Intel machines. Saying Y here would allow you to read from their floppies - and hard disk partitions. + and hard disk partitions. If you also want to write to these media, + say Y to "SYSV file system write support" below. If you have floppies or hard disk partitions like that, it is likely that they contain binaries from those other Unix systems; in order @@ -9837,7 +10290,7 @@ CONFIG_SYSV_FS tar" or preferably "info tar"). Note also that this option has nothing whatsoever to do with the option "System V IPC". Read about the System V file system in Documentation/filesystems/sysv-fs.txt. - Saying Y here will enlarge your kernel by about 27 kB. + Saying Y here will enlarge your kernel by about 27 KB. If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), @@ -9848,12 +10301,12 @@ CONFIG_SYSV_FS SYSV file system write support (DANGEROUS) CONFIG_SYSV_FS_WRITE - If you say Y here, you will (hopefully) be able to write to System V - and Coherent file systems as well as read from them. The read-write - support in SYSV is not well tested yet. If you enable this, back up - your SYSV/Coherent volumes first since they may get damaged. + If you say Y here, you will be able to write to hard drive + partitions and floppy disks which carry a SYSV file system used the + commercial Unixes SCO, Xenix and Coherent. - If unsure, say N. + This support is experimental and you may destroy your data. If + unsure, say N. Amiga FFS file system support CONFIG_AFFS_FS @@ -9883,10 +10336,11 @@ CONFIG_HFS_FS Please read fs/hfs/HFS.txt to learn about the available mount options. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called hfs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called hfs.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. ROM file system support CONFIG_ROMFS_FS @@ -9895,10 +10349,11 @@ CONFIG_ROMFS_FS other read-only media as well. Read Documentation/filesystems/romfs.txt for details. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called romfs.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called romfs.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. If you don't know whether you need it, then you don't need it: answer N. @@ -9907,13 +10362,14 @@ QNX4 file system support (read only) (EXPERIMENTAL) CONFIG_QNX4FS_FS This is the file system used by the operating system QNX 4. Say Y if you intend to mount QNX hard disks or floppies. Unless you say Y to - "QNX4FS write support" below, you will only be able to read + "QNX4FS read-write support" below, you will only be able to read these file systems. - This file system support is also available as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). The module is called qnx4.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + This file system support is also available as a module ( = code + which can be inserted in and removed from the running kernel + whenever you want). The module is called qnx4.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. If you don't know whether you need it, then you don't need it: answer N. @@ -9933,6 +10389,10 @@ CONFIG_AUTOFS_FS ftp://ftp.kernel.org/pub/linux/daemons/autofs ; you also want to answer Y to "NFS file system support", below. + If you want to use the newer version of the automounter with more + features, say N here and say Y to "Kernel automounter v4 support", + below. + If you want to compile this as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be @@ -9941,10 +10401,7 @@ CONFIG_AUTOFS_FS If you are not a part of a fairly large, distributed network, you probably do not need an automounter, and can say N here. - If you want to use the newer version of autofs with more features, - say N here and select automounter v4. - -Kernel automounter version 4 support (also supports v3) +Kernel automounter v4 support CONFIG_AUTOFS4_FS The automounter is a tool to automatically mount remote file systems on demand. This implementation is partially kernel-based to reduce @@ -9961,15 +10418,16 @@ CONFIG_AUTOFS4_FS called autofs4.o. You will need to add "alias autofs autofs4" to your modules configuration file. - If you are not a part of a fairly large, distributed network or don't - have a laptop which needs to dynamically reconfigure to the local - network, you probably do not need an automounter, and can say N here. + If you are not a part of a fairly large, distributed network or + don't have a laptop which needs to dynamically reconfigure to the + local network, you probably do not need an automounter, and can say + N here. -EFS file system support (read only) (EXPERIMENTAL) +EFS file system support (read-only) (EXPERIMENTAL) CONFIG_EFS_FS - EFS is an older file system used for non-ISO9660 CDROMs and hard disk - partitions by SGI's IRIX operating system (IRIX 6.0 and newer uses - the XFS file system for hard disk partitions however). + EFS is an older file system used for non-ISO9660 CDROMs and hard + disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer + uses the XFS file system for hard disk partitions however). This implementation only offers read-only access. If you don't know what all this is about, it's safe to say N. For more information @@ -9980,12 +10438,7 @@ CONFIG_EFS_FS whenever you want), say M here and read Documentation/modules.txt. The module will be called efs.o. -SGI disklabel support -CONFIG_SGI_DISKLABEL - Say Y to this only if you plan on mounting disks with SGI - disklabels. This is not required to mount EFS-format CDROMs. - -UFS file system support (read only) +UFS file system support (read-only) CONFIG_UFS_FS BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, OpenBSD and NeXTstep) use a file system called UFS. Some System V @@ -10028,7 +10481,7 @@ CONFIG_PARTITION_ADVANCED Note that the answer to this question won't directly affect the kernel: saying N will just cause this configure script to skip all - the questions about foreign partitioning schemes. + the questions about foreign partitioning schemes. If unsure, say N. @@ -10084,13 +10537,14 @@ CONFIG_SGI_PARTITION Say Y here if you would like to be able to read the hard disk partition table format used by SGI machines. -ADFS file system support (read only) (EXPERIMENTAL) +ADFS file system support (EXPERIMENTAL) CONFIG_ADFS_FS The Acorn Disc Filing System is the standard file system of the RiscOS operating system which runs on Acorn's ARM-based Risc PC systems and the Acorn Archimedes range of machines. If you say Y here, Linux will be able to read from ADFS partitions on hard drives - and from ADFS-formatted floppy discs. + and from ADFS-formatted floppy discs. If you also want to be able to + write to those devices, say Y to "ADFS write support" below. The ADFS partition should be the first partition (i.e., /dev/[hs]d?1) on each of your drives. Please read the file @@ -10103,6 +10557,12 @@ CONFIG_ADFS_FS If unsure, say N. +ADFS write support (DANGEROUS) +CONFIG_ADFS_FS_RW + If you say Y here, you will be able to write to ADFS partitions on + hard drives and ADFS-formatted floppy disks. This is experimental + codes, so if you're unsure, say N. + /dev/pts file system for Unix98 PTYs CONFIG_DEVPTS_FS You should say Y here if you said Y to "Unix98 PTY support" above. @@ -10119,7 +10579,8 @@ CONFIG_DEVPTS_FS mode of operation; you also need client programs that use the Unix98 API. - Note that CONFIG_DEVFS_FS is a more general facility. + Note that the experimental "/dev file system support" + (CONFIG_DEVFS_FS) is a more general facility. UnixWare slices support (EXPERIMENTAL) CONFIG_UNIXWARE_DISKLABEL @@ -10127,9 +10588,8 @@ CONFIG_UNIXWARE_DISKLABEL partition (VTOC - Virtual Table of Contents). Its format is incompatible with all other OSes. Saying Y here allows you to read VTOC and further mount UnixWare partitions read-only from within - Linux if you have also said Y to "UFS file system support", "System - V and Coherent file system support" or "BFS file system support", - above. + Linux if you have also said Y to "UFS file system support" or + "System V and Coherent file system support", above. This is mainly used to carry data from a UnixWare box to your Linux box via a removable medium like magneto-optical, ZIP or @@ -10178,9 +10638,9 @@ CONFIG_CODA_FS If you say Y here, your Linux box will be able to act as a Coda *client*. You will need user level code as well, both for the client - and server. Servers are currently user level, i.e. need no kernel - support. Please read Documentation/filesystems/coda.txt and check - out the Coda home page http://www.coda.cs.cmu.edu . + and server. Servers are currently user level, i.e. they need no + kernel support. Please read Documentation/filesystems/coda.txt and + check out the Coda home page http://www.coda.cs.cmu.edu . If you want to compile the coda client support as a module ( = code which can be inserted in and removed from the running kernel @@ -10266,7 +10726,7 @@ CONFIG_NCPFS_MOUNT_SUBDIR To utilize this feature you must use ncpfs-2.0.12 or newer. -NDS interserver authentication domains +NDS authentication support CONFIG_NCPFS_NDS_DOMAINS This allows storing NDS private keys in kernel space where they can be used to authenticate another server as interserver NDS @@ -10295,7 +10755,7 @@ CONFIG_NCPFS_EXTRAS nls codepage 437 CONFIG_NLS_CODEPAGE_437 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10306,7 +10766,7 @@ CONFIG_NLS_CODEPAGE_437 nls codepage 737 CONFIG_NLS_CODEPAGE_737 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10317,7 +10777,7 @@ CONFIG_NLS_CODEPAGE_737 nls codepage 775 CONFIG_NLS_CODEPAGE_775 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10328,7 +10788,7 @@ CONFIG_NLS_CODEPAGE_775 nls codepage 850 CONFIG_NLS_CODEPAGE_850 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10343,7 +10803,7 @@ CONFIG_NLS_CODEPAGE_850 nls codepage 852 CONFIG_NLS_CODEPAGE_852 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10357,7 +10817,7 @@ CONFIG_NLS_CODEPAGE_852 nls codepage 855 CONFIG_NLS_CODEPAGE_855 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10367,7 +10827,7 @@ CONFIG_NLS_CODEPAGE_855 nls codepage 857 CONFIG_NLS_CODEPAGE_857 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10377,7 +10837,7 @@ CONFIG_NLS_CODEPAGE_857 nls codepage 860 CONFIG_NLS_CODEPAGE_860 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10387,7 +10847,7 @@ CONFIG_NLS_CODEPAGE_860 nls codepage 861 CONFIG_NLS_CODEPAGE_861 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10397,7 +10857,7 @@ CONFIG_NLS_CODEPAGE_861 nls codepage 862 CONFIG_NLS_CODEPAGE_862 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10407,7 +10867,7 @@ CONFIG_NLS_CODEPAGE_862 nls codepage 863 CONFIG_NLS_CODEPAGE_863 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10418,7 +10878,7 @@ CONFIG_NLS_CODEPAGE_863 nls codepage 864 CONFIG_NLS_CODEPAGE_864 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10428,7 +10888,7 @@ CONFIG_NLS_CODEPAGE_864 nls codepage 865 CONFIG_NLS_CODEPAGE_865 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10439,7 +10899,7 @@ CONFIG_NLS_CODEPAGE_865 nls codepage 866 CONFIG_NLS_CODEPAGE_866 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10450,20 +10910,17 @@ CONFIG_NLS_CODEPAGE_866 nls codepage 869 CONFIG_NLS_CODEPAGE_869 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on DOS/Windows partitions correctly. This does apply to the filenames only, not to the file contents. You can include several codepages; say Y here if you want to include the DOS codepage for Greek. -### -### Why do we have two codepages for Greek and Cyrillic? -### nls codepage 874 CONFIG_NLS_CODEPAGE_874 - The Microsoft fat file system family can deal with filenames in + The Microsoft FAT file system family can deal with filenames in native language character sets. These character sets are stored in so-called DOS codepages. You need to include the appropriate codepage if you want to be able to read/write these filenames on @@ -10474,7 +10931,7 @@ CONFIG_NLS_CODEPAGE_874 nls iso8859-1 CONFIG_NLS_ISO8859_1 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 1 character set, which covers most West European languages such as Albanian, @@ -10485,7 +10942,7 @@ CONFIG_NLS_ISO8859_1 nls iso8859-2 CONFIG_NLS_ISO8859_2 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 2 character set, which works for most Latin-written Slavic and Central European @@ -10495,7 +10952,7 @@ CONFIG_NLS_ISO8859_2 nls iso8859-3 CONFIG_NLS_ISO8859_3 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 3 character set, which is popular with authors of Esperanto, Galician, Maltese, @@ -10504,7 +10961,7 @@ CONFIG_NLS_ISO8859_3 nls iso8859-4 CONFIG_NLS_ISO8859_4 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 4 character set which introduces letters for Estonian, Latvian, and @@ -10513,7 +10970,7 @@ CONFIG_NLS_ISO8859_4 nls iso8859-5 CONFIG_NLS_ISO8859_5 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-5, a Cyrillic character set with which you can type Bulgarian, Byelorussian, @@ -10523,7 +10980,7 @@ CONFIG_NLS_ISO8859_5 nls iso8859-6 CONFIG_NLS_ISO8859_6 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-6, the Arabic character set. @@ -10531,7 +10988,7 @@ CONFIG_NLS_ISO8859_6 nls iso8859-7 CONFIG_NLS_ISO8859_7 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-7, the Modern Greek character set. @@ -10539,7 +10996,7 @@ CONFIG_NLS_ISO8859_7 nls iso8859-8 CONFIG_NLS_ISO8859_8 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for ISO8859-8, the Hebrew character set. @@ -10547,7 +11004,7 @@ CONFIG_NLS_ISO8859_8 nls iso8859-9 CONFIG_NLS_ISO8859_9 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 5 character set, and it replaces the rarely needed Icelandic letters in Latin 1 @@ -10556,7 +11013,7 @@ CONFIG_NLS_ISO8859_9 nls iso8859-10 CONFIG_NLS_ISO8859_10 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 6 character set, which adds the last Inuit (Greenlandic) and Sami (Lappish) @@ -10566,7 +11023,7 @@ CONFIG_NLS_ISO8859_10 NLS ISO 8859-14 (Latin 8; Celtic) CONFIG_NLS_ISO8859_14 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 8 character set, which adds the last accented vowels for Welsh (aka Cymraeg) @@ -10576,7 +11033,7 @@ CONFIG_NLS_ISO8859_14 nls iso8859-15 CONFIG_NLS_ISO8859_15 If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the Latin 9 character set, which covers most West European languages such as Albanian, @@ -10591,7 +11048,7 @@ CONFIG_NLS_ISO8859_15 nls koi8-r CONFIG_NLS_KOI8_R If you want to display filenames with native language characters - from the Microsoft fat file system family or from JOLIET CDROMs + from the Microsoft FAT file system family or from JOLIET CDROMs correctly on the screen, you need to include the appropriate input/output character sets. Say Y here for the preferred Russian character set. @@ -10608,7 +11065,12 @@ CONFIG_VT is done with certain key combinations, usually Alt-. The setterm command ("man setterm") can be used to change the - properties (such as colors) of a virtual terminal. + properties (such as colors or beeping) of a virtual terminal. The + man page console_codes(4) ("man console_codes") contains the special + character sequences that can be used to change those properties + directly. The fonts used on virtual terminals can be changed with + the setfont ("man setfont") command and the key bindings are defined + with the loadkeys ("man loadkeys") command. You need at least one virtual terminal device in order to make use of your keyboard and monitor. Therefore, only people configuring an @@ -10634,20 +11096,10 @@ CONFIG_VT_CONSOLE that with a kernel command line option such as "console=tty3" which would use the third virtual terminal as system console. (Try "man bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time. The - lilo procedure is also explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + loadlin) about how to pass options to the kernel at boot time.) If unsure, say Y. -Software generated cursor -CONFIG_SOFTCURSOR - If you say Y here, you'll be able to do lots of nice things with the - cursors of your virtual consoles -- for example turn them into - non-blinking block cursors which are more visible on laptop screens, - or change their colors depending on the virtual console they're on. - See Documentation/VGA-softcursor.txt for more information. - Support for PowerMac keyboard CONFIG_MAC_KEYBOARD This option allows you to use an ADB keyboard attached to your @@ -10698,9 +11150,7 @@ CONFIG_SERIAL_CONSOLE you can alter that using a kernel command line option such as "console=ttyS1". (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time. The lilo procedure is also explained in the - SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) + kernel at boot time.) If you don't have a VGA card installed and you say Y here, the kernel will automatically use the first serial line, /dev/ttyS0, as @@ -10766,11 +11216,11 @@ CONFIG_RISCOM8 Computone IntelliPort Plus serial support CONFIG_COMPUTONE This driver supports the entire family of Intelliport II/Plus - controllers with the exception of the MicroChannel controllers. It - does not support products previous to the Intelliport II. These are - multiport cards, which give you many serial ports. You would need - something like this to connect more than two modems to your Linux - box, for instance in order to become a dial-in server. If you have a + controllers with the exception of the MicroChannel controllers and + products previous to the Intelliport II. These are multiport cards, + which give you many serial ports. You would need something like + this to connect more than two modems to your Linux box, for + instance in order to become a dial-in server. If you have a card like that, say Y here and read Documentation/computone.txt. If you want to compile this as a module ( = code which can be @@ -10818,13 +11268,13 @@ CONFIG_CYCLADES Cyclades-Z interrupt mode operation (EXPERIMENTAL) CONFIG_CYZ_INTR - The Cyclades-Z family of multiport cards allows 2 (two) driver - op modes: polling and interrupt. In polling mode, the driver will - check the status of the Cyclades-Z ports every certain amount of - time (which is called polling cycle and is configurable). In - interrupt mode, it will use an interrupt line (IRQ) in order to check - the status of the Cyclades-Z ports. The default op mode is polling. - If unsure, say N. + The Cyclades-Z family of multiport cards allows 2 (two) driver op + modes: polling and interrupt. In polling mode, the driver will check + the status of the Cyclades-Z ports every certain amount of time + (which is called polling cycle and is configurable). In interrupt + mode, it will use an interrupt line (IRQ) in order to check the + status of the Cyclades-Z ports. The default op mode is polling. If + unsure, say N. Stallion multiport serial support CONFIG_STALDRV @@ -10899,6 +11349,24 @@ CONFIG_ESPSERIAL and read Documentation/modules.txt. The module will be called esp.o. If unsure, say N. +Moxa Intellio support +CONFIG_MOXA_INTELLIO + Say Y here if you have a Moxa Intellio multiport serial card. + + This driver can also be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called moxa.o. If you want to do that, say M + here. + +Moxa SmartIO support +CONFIG_MOXA_SMARTIO + Say Y here if you have a Moxa SmartIO multiport serial card. + + This driver can also be built as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called mxser.o. If you want to do that, say M + here. + Multi-Tech multiport card support (EXPERIMENTAL) CONFIG_ISI This is a driver for the Multi-Tech cards which provide several @@ -10964,10 +11432,8 @@ CONFIG_PRINTER If you have several parallel ports, you can specify which ports to use with the "lp" kernel command line option. (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time. The lilo procedure - is also explained in the SCSI-HOWTO, available from - http://www.linuxdoc.org/docs.html#howto .) The syntax of the "lp" - command line option can be found in drivers/char/lp.c. + how to pass options to the kernel at boot time.) The syntax of the + "lp" command line option can be found in drivers/char/lp.c. If you have more than 3 printers, you need to increase the LP_NO variable in lp.c. @@ -10980,11 +11446,118 @@ CONFIG_LP_CONSOLE option "console=lp" to the kernel at boot time. Note that kernel messages can get lost if the printer is out of - paper (or off, or unplugged, or too busy..), but this behavior + paper (or off, or unplugged, or too busy..), but this behaviour can be changed. See drivers/char/lp.c (do this at your own risk). If unsure, say N. +Support for user-space parallel port device drivers +CONFIG_PPDEV + Saying Y to this adds support for /dev/parport device nodes. This + is needed for programs that want portable access to the parallel + port, for instance deviceid (which displays Plug-and-Play device + IDs). + + This is the parallel port equivalent of SCSI generic support (sg). + It is safe to say N to this -- it is not needed for normal printing + or parallel port CD-ROM/disk support. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called ppdev.o. + + If unsure, say N. + +I2C support +CONFIG_I2C + I2C (pronounce: I-square-C) is a slow serial bus protocol used in + many micro controller applications and developed by Philips. SMBus, + or System Management Bus is a subset of the I2C protocol. More + information is contained in the directory Documentation/i2c/, + especially in the file called "summary" there. + + Both I2C and SMBus are supported here. You will need this for + hardware sensors support, and also for Video for Linux support. + Specifically, if you want to use a BT848 based frame grabber/overlay + boards under Linux, say Y here and also to "I2C bit-banging + interfaces", below. + + If you want I2C support, you should say Y here and also to the + specific driver for your bus adapter(s) below. If you say Y to + "/proc file system" below, you will then get a /proc interface which + is documented in Documentation/i2c/proc-interface. + + This I2C support is also available as a module. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. The module will be called i2c-core.o. + +I2C bit-banging interfaces +CONFIG_I2C_ALGOBIT + This allows you to use a range of I2C adapters called bit-banging + adapters. Say Y if you own an I2C adapter belonging to this class + and then say Y to the specific driver for you adapter below. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-algo-bit.o. + +Philips style parallel port adapter +CONFIG_I2C_PHILIPSPAR + This supports parallel-port I2C adapters made by Philips. Say Y if + you own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-philips-par.o. + +ELV adapter +CONFIG_I2C_ELV + This supports parallel-port I2C adapters called ELV. Say Y if you + own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-elv.o. + +Velleman K9000 adapter +CONFIG_I2C_VELLEMAN + This supports the Velleman K9000 parallel-port I2C adapter. Say Y if + you own such an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-velleman.o. + +I2C PCF 8584 interfaces +CONFIG_I2C_ALGOPCF + This allows you to use a range of I2C adapters called PCF adapters. + Say Y if you own an I2C adapter belonging to this class and then say + Y to the specific driver for you adapter below. + + This support is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-algo-pcf.o. + +Elektor ISA card +CONFIG_I2C_ELEKTOR + This supports the PCF8584 ISA bus I2C adapter. Say Y if you own such + an adapter. + + This driver is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-elektor.o. + +I2C device interface +CONFIG_I2C_CHARDEV + Say Y here to use i2c-* device files, usually found in the /dev + directory on your system. They make it possible to have user-space + programs use the I2C bus. Information on how to do this is contained + in the file Documentation/i2c/dev-interface. + + This code is also available as a module. If you want to compile + it as a module, say M here and read Documentation/modules.txt. The + module will be called i2c-dev.o. + Bus Mouse Support CONFIG_BUSMOUSE Say Y here if your machine has a bus mouse as opposed to a serial @@ -11069,7 +11642,7 @@ CONFIG_82C710_MOUSE PC110 digitizer pad support CONFIG_PC110_PAD - This drives the digitizer pad on the IBM PC110 palmtop. It can turn + This drives the digitizer pad on the IBM PC110 palmtop. It can turn the digitizer pad into a PS/2 mouse emulation with tap gestures or into an absolute pad. @@ -11258,11 +11831,10 @@ CONFIG_FT_PROC_FS kernel driver. Saying Y will enlarge the size of the ftape driver by approximately 2 KB. - WARNING: When compiling ftape as a module (i.e. saying M to - "Floppy tape drive") it is dangerous to use ftape's /proc file - system interface. Accessing `/proc/ftape' while the module is - unloaded will result in a kernel Oops. This cannot be fixed from - inside ftape. + WARNING: When compiling ftape as a module (i.e. saying M to "Floppy + tape drive") it is dangerous to use ftape's /proc file system + interface. Accessing `/proc/ftape' while the module is unloaded will + result in a kernel Oops. This cannot be fixed from inside ftape. Controlling the amount of debugging output of ftape CONFIG_FT_NORMAL_DEBUG @@ -11434,50 +12006,52 @@ CONFIG_FT_FDC_MAX_RATE Direct Rendering Manager (XFree86 DRI support) CONFIG_DRM Kernel-level support for the Direct Rendering Infrastructure (DRI) - introduced in XFree86 4.x. These modules provide support for - synchronization, security, and DMA transfers. Select the module that - provides support for your graphics card. + introduced in XFree86 4.x. If you say Y here, you need to select + the module that's right for your graphics card from the list below. + These modules provide support for synchronization, security, and + DMA transfers. Please read drivers/char/drm/README.drm for more + details. -tdfx Direct Rendering Manager (XFree86 DRI support) +3dfx Banshee/Voodoo3 CONFIG_DRM_TDFX Choose M here if you have a 3dfx Banshee/Voodoo3 graphics card. + The module will be called tdfx.o. 3dlabs GMX 2000 Direct Rendering Driver (XFree86 DRI support) CONFIG_DRM_GAMMA Choose M here if you have a 3dlabs GMX 2000 graphics card. + The module will be called gamma.o. MTRR control and configuration CONFIG_MTRR On Intel P6 family processors (Pentium Pro, Pentium II and later) the Memory Type Range Registers (MTRRs) may be used to control - processor access to memory ranges. This is most useful when you have + processor access to memory ranges. This is most useful if you have a video (VGA) card on a PCI or AGP bus. Enabling write-combining allows bus write transfers to be combined into a larger transfer before bursting over the PCI/AGP bus. This can increase performance - of image write operations 2.5 times or more. This option creates a - /proc/mtrr file which may be used to manipulate your - MTRRs. Typically the X server should use this. This should have a - reasonably generic interface so that similar control registers on - other processors can be easily supported. + of image write operations 2.5 times or more. Saying Y here creates a + /proc/mtrr file which may be used to manipulate your processor's + MTRRs. Typically the X server should use this. + + This code has a reasonably generic interface so that similar + control registers on other processors can be easily supported + as well: The Cyrix 6x86, 6x86MX and M II processors have Address Range Registers (ARRs) which provide a similar functionality to MTRRs. For - these, the ARRs are used to emulate the MTRRs, which means that it - makes sense to say Y here for these processors as well. - + these, the ARRs are used to emulate the MTRRs. The AMD K6-2 (stepping 8 and above) and K6-3 processors have two MTRRs. The Centaur C6 (WinChip) has 8 MCRs, allowing - write-combining. All of these processors are supported by this code. - - The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These - are supported. + write-combining. All of these processors are supported by this code + and it makes sense to say Y here if you have one of them. Saying Y here also fixes a problem with buggy SMP BIOSes which only - set the MTRRs for the boot CPU and not the secondary CPUs. This can - lead to all sorts of problems. + set the MTRRs for the boot CPU and not for the secondary CPUs. This + can lead to all sorts of problems, so it's good to say Y here. You can safely say Y even if your machine doesn't have MTRRs, you'll - just add about 9K to your kernel. + just add about 9 KB to your kernel. See Documentation/mtrr.txt for more information. @@ -11487,11 +12061,6 @@ CONFIG_FT_ALPHA_CLOCK determined automatically, so you need to specify it here ONLY if running a DEC Alpha, otherwise this setting has no effect. -Zilog serial support -CONFIG_SUN_ZS - This driver does not exist at this point, so you might as well - say N. - Double Talk PC internal speech card support CONFIG_DTLK This driver is for the DoubleTalk PC, a speech synthesizer @@ -11531,26 +12100,54 @@ CONFIG_APPLICOM Power Management support CONFIG_PM - This enable the kernel to lower the requested computer power by making some - devices enter in lower power levels (standy, sleep, ... modes). - Basically, this let you save power. + "Power Management" means that parts of your computer are shut + off or put into a power conserving "sleep" mode if they are not + being used. There are two competing standards for doing this: APM + and ACPI. If you want to use either one, say Y here and then also to + the requisite support below. + + Power Management is most important for battery powered laptop + computers; if you have a laptop, check out the Linux Laptop home + page on the WWW at + http://www.cs.utexas.edu/users/kharker/linux-laptop/ and the Battery + Powered Linux mini-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . + + Note that, even if you say N here, Linux on the x86 architecture + will issue the hlt instruction if nothing is to be done, thereby + sending the processor to sleep and saving power. - Two majors interfaces exist between the hardware and the OS, the older - Advanced Power Management (APM) and the newer Advanced Configuration and - Power Interface (ACPI). +ACPI support +CONFIG_ACPI + The Advanced Configuration and Power Interface is a standard + designed to allow the operating system more control over power + management issues, such as suspending a computer in a low power + consumption state after a certain time of inaction. It aims to be + an improved version of APM (see below). ACPI has to be + supported by the motherboard. You can read more about the standard + at http://www.teleport.com/~acpi/ . + + If your computer supports ACPI and you want to use it, say Y here. + You will then need supporting software; for location and more + information, please read Documentation/pm.txt and the Battery + Powered Linux mini-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . - Both are supported by the Linux Kernel. + If you say Y here and also to "Advanced Power Management" (APM) + below, then ACPI has precedence in the sense that, if your hardware + supports ACPI, it will be used and APM won't. - Note that on some architectures (such as ia32), the idle task perform hlt - instructions which makes the CPU enter a low power mode. This can be seen as - the first kernel PM level. + To compile this driver as a module ( = code which can be inserted in + and removed from the running kernel whenever you want), say M here + and read Documentation/modules.txt. The module will be called + acpi.o. Enter S1 for sleep (EXPERIMENTAL) CONFIG_ACPI_S1_SLEEP - This enable ACPI compliant devices to enter level 1 of ACPI saving - power levels. Basically, this will let them entering in sleep mode. + If you say Y here, ACPI compliant devices can enter level 1 of ACPI + saving power levels. Basically, this will let them enter sleep mode. -Advanced Power Management +Advanced Power Management BIOS support CONFIG_APM APM is a BIOS specification for saving power using several different techniques. This is mostly useful for battery powered laptops with @@ -11565,8 +12162,9 @@ CONFIG_APM Note that the APM support is almost completely disabled for machines with more than one CPU. - Supporting software is available; for more information, read the - Battery Powered Linux mini-HOWTO, available from + In order to use APM, you will need supporting software. For location + and more information, read Documentation/pm.txt and the Battery + Powered Linux mini-HOWTO, available from http://www.linuxdoc.org/docs.html#howto . This driver does not spin down disk drives (see the hdparm(8) @@ -11578,10 +12176,6 @@ CONFIG_APM desktop machines also don't have compliant BIOSes, and this driver may cause those machines to panic during the boot phase. - If you are running Linux on a laptop, you may also want to read the - Linux Laptop home page on the WWW at - http://www.cs.utexas.edu/users/kharker/linux-laptop/ . - Generally, if you don't have a battery in your machine, there isn't much point in using this driver and you should say N. If you get random kernel OOPSes or reboots that don't seem to be related to @@ -11689,7 +12283,7 @@ CONFIG_APM_ALLOW_INTS Normally we disable external interrupts while we are making calls to the APM BIOS as a measure to lessen the effects of a badly behaving BIOS implementation. The BIOS should reenable interrupts if it - needs to. Unfortunately, some BIOSes do not - especially those in + needs to. Unfortunately, some BIOSes do not -- especially those in many of the newer IBM Thinkpads. If you experience hangs when you suspend, try setting this to Y. Otherwise, say N. @@ -11724,7 +12318,7 @@ CONFIG_WATCHDOG Disable watchdog shutdown on close CONFIG_WATCHDOG_NOWAYOUT - The default watchdog behavior (which you get if you say N here) is + The default watchdog behaviour (which you get if you say N here) is to stop the timer if the process managing it closes the file /dev/watchdog. It's always remotely possible that this process might get killed. If you say Y here, the watchdog cannot be stopped once @@ -11797,34 +12391,47 @@ CONFIG_ACQUIRE_WDT module, say M here and read Documentation/modules.txt. Most people will say N. -Intel P6 CPU Microcode Update Support +Mixcom Watchdog +CONFIG_MIXCOMWD + This is a driver for the Mixcom hardware watchdog cards. This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called mixcomwd.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. Most people + will say N. + +/dev/cpu/microcode - Intel P6 CPU microcode support CONFIG_MICROCODE - If you say Y here you will be able to update microcode on - Intel processors in P6 family, e.g. Pentium Pro, Pentium II, + If you say Y here and also to "/dev file system support" in the + 'File systems' section, you will be able to update the microcode on + Intel processors in the P6 family, e.g. Pentium Pro, Pentium II, Pentium III, Xeon etc. You will obviously need the actual microcode - binary data itself which is not shipped with the Linux kernel. - You also need to say Y to "/dev file system support" in 'File systems' - section of the kernel configuration menu. + binary data itself which is not shipped with the Linux kernel. - You need to be superuser to do that. For latest news and information - on obtaining all the required ingredients for this driver, check: - - http://www.ocston.org/~tigran/patches/microcode + For latest news and information on obtaining all the required + ingredients for this driver, check: + http://www.ocston.org/~tigran/patches/microcode . This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called microcode.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. + The module will be called microcode.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. Enhanced Real Time Clock Support CONFIG_RTC If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your computer. + will get access to the real time clock (or hardware clock) built + into your computer. + Every PC has such a clock built in. It can be used to generate signals from as low as 1Hz up to 8192Hz, and can also be used as a 24 hour alarm. It reports status information via the file - /proc/driver/rtc and its behavior is set by various ioctls on + /proc/driver/rtc and its behaviour is set by various ioctls on /dev/rtc. If you run Linux on a multiprocessor machine and said Y to @@ -11835,6 +12442,15 @@ CONFIG_RTC sampling), then say Y here, and read Documentation/rtc.txt for details. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called rtc.o. If you want to compile it as a module, + say M here and read Documentation/modules.txt. + +### Add +#EFI Real Time Clock Services +#CONFIG_EFI_RTC + Tadpole ANA H8 Support CONFIG_H8 The Hitachi H8/337 is a microcontroller used to deal with the power @@ -11878,6 +12494,11 @@ CONFIG_JOYSTICK the file Documentation/joystick.txt which contains more information and the location of the joystick package that you'll need. + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joystick.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + Classic PC analog CONFIG_JOY_ANALOG Say Y here if you have a controller that connects to the PC @@ -11887,30 +12508,55 @@ CONFIG_JOY_ANALOG ThrustMaster FCS or 6 and 8 button gamepads. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-analog.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + FPGaming and MadCatz A3D CONFIG_JOY_ASSASSIN Say Y here if you have an FPGaming or MadCatz controller using the A3D protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-assasin.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Gravis GrIP CONFIG_JOY_GRAVIS Say Y here if you have a Gravis controller using the GrIP protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-gravis.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Logitech ADI CONFIG_JOY_LOGITECH Say Y here if you have a Logitech controller using the ADI protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-logitech.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Microsoft SideWinder CONFIG_JOY_SIDEWINDER Say Y here if you have a Microsoft controller using the Digital Overdrive protocol over PC gameport. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-sidewinder.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + ThrustMaster DirectConnect CONFIG_JOY_THRUSTMASTER Say Y here if you have a ThrustMaster controller using the @@ -11918,18 +12564,44 @@ CONFIG_JOY_THRUSTMASTER information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-thrustmaster.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Creative Labs Blaster CONFIG_JOY_CREATIVE Say Y here if you have a Creative Labs controller using the Blaster protocol over the PC gameport. For more information on how to use the driver please read Documentation/joystick.txt -PDPI Lightning 4 card + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-creative.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +PDPI Lightning 4 cards CONFIG_JOY_LIGHTNING Say Y here if you have a PDPI Lightning 4 gamecard and an analog joystick or gamepad connected to it. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-lightning.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + +Logitech WingMan Warrior +CONFIG_JOY_WARRIOR + Say Y here if you have a Logitech WingMan Warrior controller + connected to your computer's serial port. For more information on + how to use the driver please read Documentation/joystick.txt + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-warrior.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Trident 4DWave and Aureal Vortex gameport CONFIG_JOY_PCI Say Y here if you have a Trident 4DWave DX/NX or Aureal Vortex 1/2 @@ -11937,12 +12609,22 @@ CONFIG_JOY_PCI with and ordinary analog joystick. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-pci.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Magellan and Space Mouse CONFIG_JOY_MAGELLAN Say Y here if you have a Magellan or Space Mouse 6DOF controller connected to your computer's serial port. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-magellan.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + SpaceTec SpaceOrb 360 and SpaceBall Avenger CONFIG_JOY_SPACEORB Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF @@ -11950,6 +12632,11 @@ CONFIG_JOY_SPACEORB information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-spaceorb.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + SpaceTec SpaceBall 4000 FLX CONFIG_JOY_SPACEBALL Say Y here if you have a SpaceTec SpaceBall 4000 FLX @@ -11957,12 +12644,11 @@ CONFIG_JOY_SPACEBALL information on how to use the driver please read Documentation/joystick.txt -Logitech WingMan Warrior -CONFIG_JOY_WARRIOR - Say Y here if you have a Logitech WingMan Warrior controller - connected to your computer's serial port. For more information on - how to use the driver please read Documentation/joystick.txt - + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-spaceball.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + NES, SNES, N64, PSX, Multi CONFIG_JOY_CONSOLE Say Y here if you have a Nintendo Entertainment System gamepad, @@ -11972,15 +12658,25 @@ CONFIG_JOY_CONSOLE For more information on how to use the driver please read Documentation/joystick.txt and Documentation/joystick-parport.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-console.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Sega, Multi CONFIG_JOY_DB9 Say Y here if you have a Sega Master System gamepad, Sega Genesis gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, - Commodore, Amstrad CPC joystick connected to your parallel port. For - more information on how to use the driver please read - Documentation/joystick.txt and Documentation/joystick-parport.txt + Commodore, Amstrad CPC joystick connected to your parallel port. + For more information on how to use the driver please read + Documentation/joystick.txt and Documentation/joystick-parport.txt. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-db9.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. -TurboGraFX interface +TurboGraFX Multisystem interface CONFIG_JOY_TURBOGRAFX Say Y here if you have the TurboGraFX interface by Steffen Schwenke, and want to use it with Multiststem -- Atari, Amiga, Commodore, @@ -11988,12 +12684,22 @@ CONFIG_JOY_TURBOGRAFX please read Documentation/joystick.txt and Documentation/joystick-parport.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-turbografx.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Amiga joysticks CONFIG_JOY_AMIGA Say Y here if you have an Amiga with a digital joystick connected to it. For more information on how to use the driver please read Documentation/joystick.txt + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called joy-amiga.o. If you want to compile + it as a module, say M here and read Documentation/modules.txt. + Atomwide Serial Support CONFIG_ATOMWIDE_SERIAL If you have an Atomwide Serial card for an Acorn system, say Y to @@ -12017,7 +12723,7 @@ CONFIG_NWBUTTON row. Do not hold the button down for too long, as the driver does not - alter the behavior of the hardware reset circuitry attached to the + alter the behaviour of the hardware reset circuitry attached to the button; it will still execute a hard reset if the button is held down for longer than approximately five seconds. @@ -12066,7 +12772,7 @@ CONFIG_SOUND I'm told that even without a sound card, you can make your computer say more than an occasional beep, by programming the PC speaker. Kernel patches and supporting utilities to do that are in the pcsp - package, available at ftp://ftp.infradead.org/pub/pcsp/. + package, available at ftp://ftp.infradead.org/pub/pcsp/ . OSS sound modules CONFIG_SOUND_OSS @@ -12096,24 +12802,25 @@ CONFIG_SOUND_SGALAXY This module initializes the older non Plug and Play sound galaxy cards from Aztech. It supports the Waverider Pro 32 - 3D and the Galaxy Washington 16. + If you compile the driver into the kernel, you have to add - "sgalaxy=,,,," to the kernel command line. + "sgalaxy=,,,," to the kernel command + line. Support for AD1816(A) based cards (EXPERIMENTAL) CONFIG_SOUND_AD1816 Say M here if you have a sound card based on the Analog Devices AD1816(A) chip. + If you compile the driver into the kernel, you have to add "ad1816=,,," to the kernel command line. - NOTE: This driver is still EXPERIMENTAL. - See Documentation/sound/AD1816 for further information. - Yamaha OPL3-SA1 audio controller CONFIG_SOUND_OPL3SA1 Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is usually built into motherboards. Read Documentation/sound/OPL3-SA for details. + If you compile the driver into the kernel, you have to add "opl3sa=,,,,," to the kernel command line. @@ -12124,6 +12831,7 @@ CONFIG_SOUND_PAS 16 or Logitech SoundMan 16 sound card. Don't answer Y if you have some other card made by Media Vision or Logitech since they are not PAS16 compatible. + If you compile the driver into the kernel, you have to add "pas2=,,,,,,, to the kernel command line. @@ -12138,14 +12846,16 @@ CONFIG_SOUND_SB Please read the file Documentation/sound/Soundblaster. You should also say Y here for cards based on the Avance Logic - ALS-007 chip (read Documentation/sound/ALS007) and for cards based + ALS-007 chip (read Documentation/sound/ALS) and for cards based on ESS chips (read Documentation/sound/ESS1868 and Documentation/sound/ESS). If you have an SB AWE 32 or SB AWE 64, say Y here and also to "Additional lowlevel drivers" and to "SB32/AWE support" below and read Documentation/sound/INSTALL.awe. If you have an IBM Mwave card, say Y here and read Documentation/sound/mwave. - If you compile the driver into the kernel and don't want to use isapnp, - you have to add "sb=,,," to the kernel command line. + + If you compile the driver into the kernel and don't want to use + isapnp, you have to add "sb=,,," to the kernel + command line. You can say M here to compile this driver as a module; the module is called sb.o. @@ -12161,6 +12871,7 @@ CONFIG_SOUND_GUS Say Y here for any type of Gravis Ultrasound card, including the GUS or GUS MAX. See also Documentation/sound/ultrasound for more information on configuring this card with modules. + If you compile the driver into the kernel, you have to add "gus=,,," to the kernel command line. @@ -12174,6 +12885,7 @@ CONFIG_SOUND_MPU401 was in the list of supported cards, look at the card specific instructions in the drivers/sound/Readme.cards file. It's safe to answer Y if you have a true MPU401 MIDI interface card. + If you compile the driver into the kernel, you have to add "mpu401=," to the kernel command line. @@ -12182,14 +12894,10 @@ CONFIG_SOUND_UART6850 This option enables support for MIDI interfaces based on the 6850 UART chip. This interface is rarely found on sound cards. It's safe to answer N to this question. + If you compile the driver into the kernel, you have to add "uart6850=," to the kernel command line. -VIDC Sound -CONFIG_VIDC_SOUND - Say Y here for ARM systems with the VIDC video controller and 16-bit - Linear sound DACs. If unsure, say N. - PSS (AD1848, ADSP-2115, ESC614) support CONFIG_SOUND_PSS Answer Y or M if you have an Orchid SW32, Cardinal DSP16, Beethoven @@ -12197,6 +12905,7 @@ CONFIG_SOUND_PSS ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on how to compile it into the kernel or as a module see the file Documentation/sound/PSS. + If you compile the driver into the kernel, you have to add "pss=,,,,," to the kernel command line. @@ -12223,16 +12932,6 @@ CONFIG_PSS_BOOT_FILE Enter the full pathname of your DSPxxx.LD file or SYNTH.LD file, starting from /. -16 bit sampling option of GUS (_NOT_ GUS MAX) -CONFIG_SOUND_GUS16 - Answer Y if you have installed the 16 bit sampling daughtercard on - your GUS. Answer N if you have a GUS MAX, since saying Y here - disables GUS MAX support. - -GUS MAX support -CONFIG_SOUND_GUSMAX - Answer Y only if you have a Gravis Ultrasound MAX. - Microsoft Sound System support CONFIG_SOUND_MSS Again think carefully before answering Y to this question. It's safe @@ -12258,8 +12957,10 @@ CONFIG_SOUND_MSS specific instructions in drivers/sound/Readme.cards. Some drivers have their own MSS support and saying Y to this option will cause a conflict. + If you compile the driver into the kernel, you have to add - "ad1848=,,,[,]" to the kernel command line. + "ad1848=,,,[,]" to the kernel command + line. SGI Visual Workstation on-board audio CONFIG_SOUND_VWSND @@ -12272,16 +12973,15 @@ CONFIG_SOUND_SSCAPE Answer Y if you have a sound card based on the Ensoniq SoundScape chipset. Such cards are being manufactured at least by Ensoniq, Spea and Reveal (Reveal makes also other cards). + If you compile the driver into the kernel, you have to add - "sscape=,,,," to the kernel command line. + "sscape=,,,," to the kernel command + line. MediaTriX AudioTriX Pro support CONFIG_SOUND_TRIX Answer Y if you have the AudioTriX Pro sound card manufactured by MediaTrix. - If you compile the driver into the kernel, you have to add - "trix=,,,,,,,," - to the kernel command line. Have TRXPRO.HEX firmware file CONFIG_TRIX_HAVE_BOOT @@ -12306,6 +13006,7 @@ CONFIG_SOUND_MAD16 and Diamond (latest ones). Note however that the Tropez sound cards have their own driver; if you have one of those, say N here and Y or M to "Full support for Turtle Beach WaveFront", below. + If you compile the driver into the kernel, you have to add "mad16=,,,,," to the kernel command line. @@ -12329,6 +13030,7 @@ Support for Crystal CS4232 based (PnP) cards CONFIG_SOUND_CS4232 Say Y here if you have a card based on the Crystal CS4232 chip set, which uses its own Plug and Play protocol. + If you compile the driver into the kernel, you have to add "cs4232=,,,,," to the kernel command line. @@ -12341,6 +13043,7 @@ CONFIG_SOUND_OPL3SA2 Say Y or M if you have a card based on one of these Yamaha sound chipsets. Read Documentation/sound/OPL3-SA2 for more information on configuring these cards. + If you compile the driver into the kernel, you have to add "opl3sa2=,,,,," to the kernel command line. @@ -12349,6 +13052,7 @@ Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers CONFIG_SOUND_MAUI Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez sound card. + If you compile the driver into the kernel, you have to add "maui=," to the kernel command line. @@ -12447,15 +13151,11 @@ CONFIG_SOUND_YM3812 cards, however). Please read the file Documentation/sound/OPL3 if your card has an OPL3 chip. + If you compile the driver into the kernel, you have to add "opl3=" to the kernel command line. If unsure, say Y. - -Sun Audio support -CONFIG_SUN_AUDIO - This is support for the sound cards on Sun workstations. The code - does not exist yet, so you might as well say N here. ACI mixer (miroPCM12/PCM20) CONFIG_SOUND_ACI_MIXER @@ -12502,6 +13202,7 @@ CONFIG_AEDSP16_SBPRO You should then say Y to "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support" and N to "Audio Excel DSP 16 (MSS emulation)". + If you compile the driver into the kernel, you have to add "aedsp16=,,,,," to the kernel command line. @@ -12590,7 +13291,7 @@ CONFIG_SOUND_TRIDENT for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018. This driver differs slightly from OSS/Free, so PLEASE READ the - comments at of driver/sound/trident.c + comments at the top of driver/sound/trident.c Rockwell WaveArtist CONFIG_SOUND_WAVEARTIST @@ -12599,18 +13300,18 @@ CONFIG_SOUND_WAVEARTIST VIA 82Cxxx Audio Codec CONFIG_SOUND_VIA82CXXX - Say Y here to include support for the audio codec found on - VIA 82Cxxx-based chips. Typically these are built into a motherboard. - DO NOT select SoundBlaster or Adlib with this driver, unless you have - a SoundBlaster or Adlib card in addition to your VIA audio chip. + Say Y here to include support for the audio codec found on VIA + 82Cxxx-based chips. Typically these are built into a motherboard. DO + NOT select Sound Blaster or Adlib with this driver, unless you have + a Sound Blaster or Adlib card in addition to your VIA audio chip. NeoMagic 256AV/256ZX sound chipsets CONFIG_SOUND_NM256 Say M here to include audio support for the NeoMagic 256AV/256ZX - chipsets. These are the audio chipsets found in the Sony Z505S/SX/DX, - some Sony F-series, and the Dell Latitude CPi and CPt laptops. It includes - support for an AC97-compatible mixer and an apparently proprietary sound - engine. + chipsets. These are the audio chipsets found in the Sony + Z505S/SX/DX, some Sony F-series, and the Dell Latitude CPi and CPt + laptops. It includes support for an AC97-compatible mixer and an + apparently proprietary sound engine. See Documentation/sound/NM256 for further information. @@ -12627,9 +13328,9 @@ CONFIG_CROSSCOMPILE Kernel support for Linux/MIPS 32-bit binary compatibility CONFIG_MIPS32_COMPAT - Select this option this option if you want Linux/MIPS 32-bit binary - compatibility. Since all software available available for Linux/MIPS - is currently 32-bit you should say Y here. + Select this option if you want Linux/MIPS 32-bit binary + compatibility. Since all software available for Linux/MIPS is + currently 32-bit you should say Y here. Build fp exception handler module CONFIG_MIPS_FPE_MODULE @@ -12717,7 +13418,7 @@ CONFIG_ISDN_AUDIO X.25 PLP on top of ISDN CONFIG_ISDN_X25 - This feature provides the X.25 protocol over ISDN connections. + This feature provides the X.25 protocol over ISDN connections. See Documentation/isdn/README.x25 for more information if you are thinking about using this. @@ -12782,11 +13483,21 @@ CONFIG_ISDN_DRV_HISAX HiSax Support for EURO/DSS1 CONFIG_HISAX_EURO - Enable this if you have a EURO ISDN line. + Say Y or N according to the D-channel protocol which your local + telephone service company provides. + + NOTE: If you say Y here and you have only one ISDN card installed, + you cannot say Y to "HiSax Support for German 1TR6", below. And vice + versa. -Support for german chargeinfo +Support for german charge info CONFIG_DE_AOC - If you have german AOC, you can enable this to get the charginfo. + If you want that the HiSax hardware driver sends messages to the + upper level of the isdn code on each AOCD (Advice Of Charge, During + the call -- transmission of the fee information during a call) and + on each AOCE (Advice Of Charge, at the End of the call -- + transmission of fee information at the end of the call), say Y here. + This works only in Germany. Disable sending complete CONFIG_HISAX_NO_SENDCOMPLETE @@ -12800,12 +13511,17 @@ CONFIG_HISAX_NO_LLC Disable keypad protocol option CONFIG_HISAX_NO_KEYPAD - If you like to send special dialstrings including * or # without + If you like to send special dial strings including * or # without using the keypad protocol, select this option. -HiSax Support for german 1TR6 +HiSax Support for German 1TR6 CONFIG_HISAX_1TR6 - Enable this if you have a old german 1TR6 line. + Say Y or N according to the D-channel protocol which your local + telephone service company provides. + + NOTE: If you say Y here and you have only one ISDN card installed, + you cannot say Y to "HiSax Support for EURO/DSS1", above. And vice + versa. Teles 16.0/8.0 CONFIG_HISAX_16_0 @@ -12829,7 +13545,7 @@ Teles PCI CONFIG_HISAX_TELESPCI This enables HiSax support for the Teles PCI. See Documentation/isdn/README.HiSax on how to configure it. - + Teles S0Box CONFIG_HISAX_S0BOX This enables HiSax support for the Teles/Creatix parallel port @@ -12992,8 +13708,8 @@ CONFIG_HISAX_W6692 HFC-S+, HFC-SP, HFC-PCMCIA cards (EXPERIMENTAL) CONFIG_HISAX_HFC_SX - This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA cards. - This code is not finished yet. + This enables HiSax support for the HFC-S+, HFC-SP and HFC-PCMCIA + cards. This code is not finished yet. Am7930 (EXPERIMENTAL) CONFIG_HISAX_AMD7930 @@ -13049,10 +13765,16 @@ CONFIG_ISDN_TTY_FAX CAPI2.0 support CONFIG_ISDN_CAPI - This provides the CAPI (Common ISDN Application Programming Interface, a - standard making it easy for programs to access ISDN hardware, see - http://www.capi.org/. This is needed for AVM's set of active ISDN - controllers like B1, T1, M1. + This provides the CAPI (Common ISDN Application Programming + Interface, a standard making it easy for programs to access ISDN + hardware, see http://www.capi.org/ . This is needed for AVM's set of + active ISDN controllers like B1, T1, M1. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The modules will be called capi.o and kernelcapi.o. If you want to + compile it as a module, say M here and read + Documentation/modules.txt. AVM B1 ISA support CONFIG_ISDN_DRV_AVMB1_B1ISA @@ -13091,7 +13813,6 @@ CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON disconnecting. This will increase the size of the kernel by 7 KB. If unsure, say Y. - IBM Active 2000 support (EXPERIMENTAL) CONFIG_ISDN_DRV_ACT2000 Say Y here if you have an IBM Active 2000 ISDN card. In order to use @@ -13100,12 +13821,12 @@ CONFIG_ISDN_DRV_ACT2000 isdn4k-utils package. Please read the file Documentation/isdn/README.act2000 for more information. -Support for AP1000 multicomputer -CONFIG_AP1000 - This enables support for a SPARC based parallel multi-computer - called AP1000+. For details on our efforts to port Linux to this - machine see http://cap.anu.edu.au/cap/projects/linux or mail to - hackers@cafe.anu.edu.au +Hypercope HYSDN cards (Champ, Ergo, Metro) support (module) +CONFIG_HYSDN + Say Y here if you have one of Hypercope's active PCI ISDN cards + Champ, Ergo and Metro. You will then get a module called hysdn.o. + Please read the file Documentation/isdn/README.hysdn for more + information. Support for Sun4 architecture CONFIG_SUN4 @@ -13127,11 +13848,11 @@ PTI Qlogic, ISP Driver CONFIG_SCSI_QLOGICPTI This driver supports SBUS SCSI controllers from PTI or QLogic. These controllers are known under Solaris as qpti and in the openprom as - PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are driven - by a different driver. + PTI,ptisp or QLGC,isp. Note that PCI QLogic SCSI controllers are + driven by a different driver. - This support is also available as a module called qlogicpti.o ( = code - which can be inserted in and removed from the running kernel + This support is also available as a module called qlogicpti.o ( = + code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -13147,14 +13868,14 @@ CONFIG_SUN_OPENPROMIO Openprom tree appears in /proc/openprom CONFIG_SUN_OPENPROMFS - If you say Y, the OpenPROM device tree will be available as a virtual - file system, which you can mount to /proc/openprom by - "mount -t openpromfs none /proc/openprom". + If you say Y, the OpenPROM device tree will be available as a + virtual file system, which you can mount to /proc/openprom by "mount + -t openpromfs none /proc/openprom". - If you want to compile the /proc/openprom support as a module ( = code - which can be inserted in and removed from the running kernel whenever - you want), say M here and read Documentation/modules.txt. The module - will be called openpromfs.o. If unsure, say M. + If you want to compile the /proc/openprom support as a module ( = + code which can be inserted in and removed from the running kernel + whenever you want), say M here and read Documentation/modules.txt. + The module will be called openpromfs.o. If unsure, say M. Kernel support for Linux/Sparc 32bit binary compatibility CONFIG_SPARC32_COMPAT @@ -13195,8 +13916,8 @@ CONFIG_OBP_FLASH JavaStation OS Flash SIMM (EXPERIMENTAL) CONFIG_SUN_JSFLASH - This option enables a driver for JavaStation OS Flash driver. - Say N unless you want to boot from your Flash SIMM. + If you say Y here, you will be able to boot from your JavaStation's + Flash memory. Siemens SAB82532 serial support CONFIG_SAB82532 @@ -13212,8 +13933,9 @@ Audio support (EXPERIMENTAL) CONFIG_SPARCAUDIO This driver provides support for the build-in sound devices on most Sun machines. If you want to be able to use this, select this option - and one or more of the lowlevel drivers below. See - http://www.dementia.org/~shadow/sparcaudio.html for more information. + and one or more of the lowlevel drivers below. See + http://www.dementia.org/~shadow/sparcaudio.html for more + information. AMD7930 Lowlevel Driver CONFIG_SPARCAUDIO_AMD7930 @@ -13227,108 +13949,20 @@ CONFIG_SPARCAUDIO_CS4231 DBRI Lowlevel Driver CONFIG_SPARCAUDIO_DBRI - This driver supports the DBRI audio interface found on the SS10, SS20, - Sparcbook 3, and Voyager systems. + This driver supports the DBRI audio interface found on the SS10, + SS20, Sparcbook 3, and Voyager systems. Dummy lowlevel Driver CONFIG_SPARCAUDIO_DUMMY - This is a pseudo-driver used for debugging and testing the sparcaudio - subsystem. Say N unless you want to work on this subsystem. + This is a pseudo-driver used for debugging and testing the + sparcaudio subsystem. Say N unless you want to work on this + subsystem. Sparc hardware (EXPERIMENTAL) CONFIG_PARPORT_SUNBPP - This driver provides support for the bidirectional parallel port found - on many Sun machines. Note that many of the newer Ultras actually have - pc style hardware instead. - -IEEE 1394 (aka FireWire) support -CONFIG_IEEE1394 - IEEE 1394 describes a high performance serial bus, which is also - known as FireWire(tm) or i.Link(tm) and is used for connecting all - sorts of devices (most notably digital video cameras). - - If you have FireWire hardware and want to use it, say Y here. This - is the core support only, you will also need to select a driver for - your IEEE 1394 adapter. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called ieee1394.o. - - FireWire is a trademark by Apple Inc. and i.Link is a trademark by - Sony. - -TI PCILynx IEEE 1394 support -CONFIG_IEEE1394_PCILYNX - Say Y here if you have a IEEE-1394 controller with the Texas - Instruments PCILynx chip. Note: this driver is written for revision - 2 of this chip and may not work with revision 0. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called pcilynx.o. - -Use local RAM on PCILynx board -CONFIG_IEEE1394_PCILYNX_LOCALRAM - This option makes the PCILynx driver use local RAM available on some - PCILynx setups for Packet Control Lists. Local RAM may speed up - command processing because no PCI transfers are necessary during - use of the Packet Control Lists. - - Note that there are no known PCILynx systems providing local RAM - except for the evaluation boards by Texas Instruments and that the - PCILynx does not reliably report missing RAM. - - Unless you are absolutely sure that you have 64kB of local RAM and - that you want to use it or if you don't know what this is all about, - say N here. - -Adaptec AIC-5800 IEEE 1394 support -CONFIG_IEEE1394_AIC5800 - Say Y here if you have a IEEE 1394 controller using the Adaptec - AIC-5800 chip. All Adaptec host adapters (89xx series) use this - chip, as well as miro's DV boards. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called aic5800.o. - -OHCI (Open Host Controller Interface) support -CONFIG_IEEE1394_OHCI1394 - Say Y here if you have a IEEE 1394 controller based on OHCI. - The current driver was only tested with OHCI chipsets made - by Texas Instruments. However, most third-party vendors use - TI chips. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called ohci1394.o. - -Raw IEEE 1394 I/O support -CONFIG_IEEE1394_RAWIO - Say Y here if you want support for the raw device. This is generally - a good idea, so you should say Y here. The raw device enables - direct communication of user programs to the IEEE 1394 bus. - - If you want to compile this as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called raw1394.o. - -Excessive debugging output -CONFIG_IEEE1394_VERBOSEDEBUG - If you say Y here, you will get very verbose debugging logs from the - subsystem which includes a dump of the header of every sent and - received packet. This can amount to a high amount of data collected - in a very short time which is usually also saved to disk by the - system logging daemons. - - Say Y if you really want or need the debugging output, everyone else - says N. + This driver provides support for the bidirectional parallel port + found on many Sun machines. Note that many of the newer Ultras + actually have pc style hardware instead. # # m68k-specific kernel options @@ -13370,23 +14004,12 @@ CONFIG_HP300 Sun 3X support CONFIG_SUN3X - This option enables support for the Sun 3x series of workstations. Be - warned that this support is very experimental. You will also want to - say Y to 68020 support and N to the other processors below. + This option enables support for the Sun 3x series of workstations. + Be warned that this support is very experimental. You will also want + to say Y to 68020 support and N to the other processors below. If you don't want to compile a kernel for a Sun 3x, say N. -Sun 3 support -CONFIG_SUN3 - This option enables support for the Sun 3 series of workstations. Be - warned that this support is very experimental. You will also want to - say Y to 68020 support and N to the other processors below. - Currently, it is not possible to build a kernel with support for the - Sun 3 and something else, so make sure you have said N to all the - other machines. This option does not support the sun3x series of - machines (the Sun 3/80 and 3/460). If you don't want to compile a - kernel for a Sun 3, say N. - 68020 support CONFIG_M68020 If you anticipate running this kernel on a computer with a MC68020 @@ -13444,7 +14067,13 @@ CONFIG_ADVANCED This gives you access to some advanced options for the CPU. The defaults should be fine for most users, but these options may make it possible for you to improve performance somewhat if you know what - you are doing. Most users should say N to this question. + you are doing. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about these options. + + Most users should say N to this question. Use read-modify-write instructions CONFIG_RMW_INSNS @@ -13465,8 +14094,9 @@ CONFIG_ZORRO cards that obey the AutoConfig(tm) specification. Say Y if you want your expansion cards to be identified on bootup; it will enlarge your kernel by about 10 KB. The identification - information is also available through /proc/zorro (say Y to - "/proc file system support"!). + information is then also available through /proc/zorro (say Y to + "/proc file system support"!). Read Documentation/zorro.txt for more + information. Note that even if you say N here, you can still use your expansion cards. If in doubt, say Y. @@ -13476,23 +14106,6 @@ CONFIG_AMIGA_PCMCIA Include support in the kernel for pcmcia on Amiga 1200 and Amiga 600. If you intend to use pcmcia cards say Y; otherwise say N. -Amiga GSP (TMS340x0) support -CONFIG_AMIGA_GSP - Include support for Amiga graphics cards that use the Texas - Instruments TMS340x0 GSP (Graphics Signal Processor) chips. Say Y - if you want to use a DMI Resolver or Commodore A2410 (Lowell) - graphics card on an Amiga; otherwise, say N. - -DMI Resolver support -CONFIG_GSP_RESOLVER - Include support in the kernel for the DMI Resolver graphics card. If - you have one, say Y; otherwise, say N. - -A2410 support -CONFIG_GSP_A2410 - Include support in the kernel for the Commodore/University of Lowell - A2410 graphics card. If you have one, say Y; otherwise, say N. - Amiga Zorro II ramdisk support CONFIG_AMIGA_Z2RAM This enables support for using Chip RAM and Zorro II RAM as a @@ -13591,7 +14204,7 @@ CONFIG_CYBERSTORMII_SCSI and the optional Cyberstorm SCSI controller, say Y. Otherwise, answer N. -Blizzard 2060 SCSI support +Blizzard 2060 SCSI support (EXPERIMENTAL) CONFIG_BLZ2060_SCSI If you have an Amiga with a Phase5 Blizzard 2060 accelerator board and want to use the onboard SCSI controller, say Y. Otherwise, @@ -13603,7 +14216,7 @@ CONFIG_BLZ1230_SCSI 1260 accelerator, and the optional SCSI module, say Y. Otherwise, say N. -Blizzard PowerUP 603e+ SCSI support (EXPERIMENTAL) +Blizzard PowerUP 603e+ SCSI support CONFIG_BLZ603EPLUS_SCSI If you have an Amiga 1200 with a Phase5 Blizzard PowerUP 603e+ accelerator, say Y. Otherwise, say N. @@ -13706,16 +14319,6 @@ CONFIG_ATARI_PAMSNET ACSI port ("ACSI node"). The driver works (has to work...) with a polled I/O scheme, so it's rather slow :-( -Multiface Card III parallel support -CONFIG_MULTIFACE_III_LP - If you have a Multiface III card for your Amiga, and want to use its - parallel port in Linux, say Y. Otherwise, say N. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module is called lp_m68k.o. If you want to compile it as a - module, say M here and read Documentation/modules.txt. - Amiga mouse support CONFIG_AMIGAMOUSE If you want to be able to use an Amiga mouse in Linux, say Y. @@ -13725,13 +14328,6 @@ CONFIG_AMIGAMOUSE The module is called amigamouse.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. -Amiga Copper Console -CONFIG_COPCON - This configures the console to use the Amiga's graphics coprocessor - for scrolling, instead of using the CPU. This option markedly - improves response times in the high color modes (5 bitplanes and - up). If you would like to use this, say Y; otherwise, say N. - Atari mouse support CONFIG_ATARIMOUSE If you want to be able to use an Atari mouse in Linux, say Y. @@ -13843,11 +14439,6 @@ CONFIG_HPLANCE If you want to use the builtin "LANCE" Ethernet controller on an HP300 machine, say Y here. -Sun 3 onboard LANCE support -CONFIG_SUN3LANCE - If you want to use the onboard AMD "LANCE" (le) Ethernet hardware - on a Sun 3, you will need to say Y here. - DIO bus support CONFIG_DIO Say Y here to enable support for the "DIO" expansion bus used in @@ -13857,10 +14448,10 @@ CONFIG_DIO Processor Type CONFIG_6xx There are three types of PowerPC chips supported. The more common - types (601, 603, 604, 740, 750), the Motorola embedded versions (821, - 823, 850, 855, 860), and the IBM embedded versions (403 and 405). - Unless you are building a kernel for one of the embedded processor - systems, choose 6xx. + types (601, 603, 604, 740, 750), the Motorola embedded versions + (821, 823, 850, 855, 860), and the IBM embedded versions (403 and + 405). Unless you are building a kernel for one of the embedded + processor systems, choose 6xx. Machine Type CONFIG_PMAC @@ -13932,6 +14523,35 @@ CONFIG_BMAC whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. +GMAC (G4/iBook ethernet) support +CONFIG_GMAC + Say Y for support of GMAC Ethernet interfaces. These are used on G4 + and iBook computers. + + This driver is also available as a module called gmac.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +Symbios 53c885 (Synergy ethernet) support +CONFIG_NCR885E + This is and Ethernet driver for the dual-function NCR 53C885 + SCSI/Ethernet controller. + + This driver is also available as a module called ncr885e.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +National DP83902AV (Oak ethernet) support +CONFIG_OAKNET + Say Y if your machine has this type of Ethernet network card. + + This driver is also available as a module called oaknet.o ( = code + which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + Video For Linux CONFIG_VIDEO_DEV Support for audio/video capture and overlay devices and FM radio @@ -14037,10 +14657,6 @@ CONFIG_RADIO_CADET say M here and read Documentation/modules.txt. The module will be called radio-cadet.o. -ADS Cadet AM/FM Radio Tuner Card I/O Port -CONFIG_RADIO_CADET_PORT - Enter the I/O address of the card here (most commonly 330). - SF16FMI Radio CONFIG_RADIO_SF16FMI Choose Y here if you have one of these FM radio cards, and then fill @@ -14160,7 +14776,9 @@ CONFIG_RADIO_GEMTEK GemTek i/o port CONFIG_RADIO_GEMTEK_PORT Enter either 0x20c, 0x30c, 0x24c or 0x34c here. The card default is - 0x34c, if you haven't changed the jumper setting on the card. + 0x34c, if you haven't changed the jumper setting on the card. On + Sound Vision 16 Gold PnP with FM Radio (ESS1869+FM Gemtek), the i/o + port is 0x28c. PlanB Video-In for PowerMacs CONFIG_VIDEO_PLANB @@ -14179,34 +14797,56 @@ CONFIG_RADIO_TERRATEC Note: This driver is in its early stages. Right now volume and frequency control and muting works at least for me, but unfortunately i have not found anybody who wants to use this card - with linux. So if it is this what YOU are trying to do right now, + with Linux. So if it is this what YOU are trying to do right now, PLEASE DROP ME A NOTE!! Rolf Offermanns (rolf@offermanns.de) In order to control your radio card, you will need to use programs that are compatible with the Video for Linux API. Information on this API and pointers to "v4l" programs may be found on the WWW at - http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, - you need to have access to a machine on the Internet that has a - program like lynx or netscape. + http://roadrunner.swansea.uk.linux.org/v4l.shtml . If you want to compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called radio-terratec.o. +Terratec i/o port (normally 0x590) +CONFIG_RADIO_TERRATEC_PORT + Fill in the i/o port of your TerraTec FM radio card. If unsure, go + with the default. + +### Add these # Zoran ZR36057/36060 support # CONFIG_VIDEO_ZORAN # Include support for Iomega Buz # CONFIG_VIDEO_BUZ +Trust FM radio card +CONFIG_RADIO_TRUST + This is a driver for the Trust FM radio cards. Say Y if you have + such a card and want to use it under Linux. + + This driver is also available as a module called radio-trust.o ( = + code which can be inserted in and removed from the running kernel + whenever you want). If you want to compile it as a module, say M + here and read Documentation/modules.txt. + +Trust i/o port (usually 0x350 or 0x358) +CONFIG_RADIO_TRUST_PORT + Enter the i/o port of your Trust FM radio card. If unsure, try the + values "0x350" or "0x358". + BT848 Video For Linux CONFIG_VIDEO_BT848 Support for BT848 based frame grabber/overlay boards. This includes the Miro, Hauppauge and STB boards. Please read the material in Documentation/video4linux/bttv for more information. - This driver is also available as a module called bttv.o ( = code + If you say Y or M here, you need to say Y or M to "I2C support" and + "I2C bit-banging interfaces" in the character device section. + + This driver is available as a module called bttv.o ( = code which can be inserted in and removed from the running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt. @@ -14245,11 +14885,12 @@ CONFIG_VIDEO_BWQCAM Colour QuickCam Video For Linux CONFIG_VIDEO_CQCAM - This is the video4linux driver for the color version of the + This is the video4linux driver for the colour version of the Connectix Quickcam. If you have one of these cameras, say Y here, otherwise say N. This driver does not work with the original monochrome Quickcam, Quickcam VC or QuickClip. It is also available - as a module (c-qcam.o). + as a module (c-qcam.o). Read Documentation/video4linux/CQcam.txt for + more information. Mediavision Pro Movie Studio Video For Linux CONFIG_VIDEO_PMS @@ -14266,114 +14907,9 @@ CONFIG_BLK_CPQ_DA boards supported by this driver, and for further information on the use of this driver. -QuickNet Internet LineJack/PhoneJack support -CONFIG_PHONE_IXJ - Say M if you have a telephony card manufactured by Quicknet - Technologies, Inc. These include the Internet PhoneJACK and - Internet LineJACK Telephony Cards. - - For the ISA versions of these products, you can configure the - cards using the isapnp tools (pnpdump/isapnp) or you can use the - isapnp support. Please read: - - /usr/src/linux/Documentation/telephony/ixj.txt. - - For more information on these cards, see Quicknet's website at: - http://www.quicknet.net/ - - If you do not have any Quicknet telephony cards, you can safely - ignore this option. - -/dev/agpgart (AGP Support) (EXPERIMENTAL) -CONFIG_AGP - The agpgart kernel module is necessary to use the AGP features - of your 3D rendering video card. It acts as a sort of "AGP - driver" for the motherboard's chipset. - Loading this module into the kernel will allow the glx module to - program the GART (graphics aperture relocation table) registers - with appropriate values to transfer commands to the card. - - If you need more texture memory than you can get with the AGP GART - (theoretically up to 256 megs, but in practice usually 64 or 128 - megs due to kernel allocation issues), you could use PCI accesses - and have up to a couple gigs of texture space. - - Note that this is the only mean to have get XFree4/GLX use - write-combining with MTRR support on AGP bus. Without, OpenGL - direct rendering will be a lot slower but still faster than PIO. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - - or need to use the 810 Xserver in XFree 3.3.6 - -Intel 440LX/BX/GX support -CONFIG_AGP_INTEL - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on Intel 440LX/BX/GX chipsets. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -Intel I810/I810 DC100/I810e support -CONFIG_AGP_I810 - This option give you AGP support for the Xserver for the intel - 810 chipset boards. This is required to do any useful video - modes. - -VIA VP3/MVP3/Apollo Pro support -CONFIG_AGP_VIA - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on VIA MPV3/Apollo Pro chipsets. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -AMD Irongate support -CONFIG_AGP_AMD - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on Intel AMD Irongate chipset. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -Generic SiS support -CONFIG_AGP_SIS - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on Silicon Integrated Systems [SiS] - chipsets. - - Note than 5591/5592 AGP chipsets are NOT supported. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - -ALI M1541 support -CONFIG_AGP_ALI - This option give you AGP support for the GLX component of the - "soon to be released" XFree86-4 on ALI M1541 chipset. - - For the moment, most people should say no, unless you want to - test the GLX component which can be downloaded from - http://glx.on.openprojects.net/ - # # ARM options # -CPU Optimization -CONFIG_CPU_ARM2 - This selects the processor type of your CPU. This is only used to - determine C compiler optimization options, and can affect the - compatibility of the kernel on other processors. If you specify - ARM6, the kernel should work on all 32-bit processors. If you - specify ARM2, ARM250 or ARM3, it should work on all 26-bit - processors. If you're not sure, set it to "None". - ARM System type CONFIG_ARCH_ARC This selects what ARM system you wish to build the kernel for. It @@ -14381,14 +14917,6 @@ CONFIG_ARCH_ARC to set this option to, please consult any information supplied with your system. -Include support for Chalice CATS boards -CONFIG_CATS - Say Y here if you intend to run this kernel on a CATS system. - -Include support for Intel EBSA285 -CONFIG_ARCH_EBSA285 - board. - Include support for the NetWinder CONFIG_ARCH_NETWINDER Say Y here if you intend to run this kernel on the NetWinder. @@ -14412,7 +14940,7 @@ CONFIG_NWFPE Say Y to include the NWFPE floating point emulator in the kernel. This is necessary to run most binaries. Linux does not currently support floating point hardware so you need to say Y here even if - your machine has an FPA or floating point co-processor module. + your machine has an FPA or floating point co-processor podule. It is also possible to say M to build the emulator as a module (nwfpe.o) or indeed to leave it out altogether. However, unless you @@ -14441,12 +14969,6 @@ CONFIG_DEBUG_ERRORS you are concerned with the code size or don't want to see these messages. -Build Tools Selection -CONFIG_BINUTILS_NEW - Say Y here if and only if you're using GCC 2.8.1/EGCS with a - binutils version >= 2.8.1 to compile the kernel (check with "gcc - --version" and "ld -v"). - Compile kernel with frame pointer CONFIG_FRAME_POINTER If you say Y here, the resulting kernel will be slightly larger and @@ -14469,12 +14991,12 @@ CONFIG_DEBUG_INFO time and disk space needed for compilation of the kernel. If in doubt say N. -Split initialization functions into discardable section +Split initialisation functions into discardable section CONFIG_TEXT_SECTIONS If you say Y here, kernel code that is only used during - initialization is collected into a special area of the kernel so + initialisation is collected into a special area of the kernel so that it can be discarded and the memory reclaimed when - initialization is complete. In addition, if the kernel you wish to + initialisation is complete. In addition, if the kernel you wish to build is able to run on multiple architectures, it allows the unused code to be discarded. Some versions of binutils, however, have a bug that causes the kernel to crash during startup when this option is @@ -14535,7 +15057,7 @@ CONFIG_HOST_FOOTBRIDGE MFM hard disk support CONFIG_BLK_DEV_MFM Support the MFM hard drives on the Acorn Archimedes both - on-board the A4x0 motherboards and via the Acorn MFM modules. + on-board the A4x0 motherboards and via the Acorn MFM podules. Drives up to 64MB are supported. If you haven't got one of these machines or drives just say N. @@ -14553,7 +15075,7 @@ CONFIG_BLK_DEV_MFM_AUTODETECT sometimes doesn't work and it also does some dodgy stuff which potentially might damage your drive. -IrDA Protocols +IrDA subsystem support CONFIG_IRDA Say Y here if you want to build support for the IrDA (TM) protocols. The Infrared Data Associations (tm) specifies standards for wireless @@ -14565,8 +15087,9 @@ CONFIG_IRDA Documentation/networking/irda.txt. You also want to read the IR-HOWTO, available at http://www.linuxdoc.org/docs.html#howto . - This support is also available as a module. If you want to compile - it as a module, say M here and read Documentation/modules.txt. + This support is also available as a module called irda.o. If you + want to compile it as a module, say M here and read + Documentation/modules.txt. IrDA Cache last LSAP CONFIG_IRDA_CACHE_LAST_LSAP @@ -14623,7 +15146,7 @@ CONFIG_IRDA_DEFLATE IrLAN Protocol CONFIG_IRLAN Say Y here if you want to build support for the IrLAN protocol. If - you want to compile it as a module, say M here and read + you want to compile it as a module (irlan.o), say M here and read Documentation/modules.txt. IrLAN emulates an Ethernet and makes it possible to put up a wireless LAN using infrared beams. @@ -14635,19 +15158,20 @@ CONFIG_IRLAN IrCOMM Protocol CONFIG_IRCOMM Say Y here if you want to build support for the IrCOMM protocol. If - you want to compile it as a module, say M here and read - Documentation/modules.txt. IrCOMM implements serial port emulation, - and makes it possible to use all existing applications that - understands TTY's with an infrared link. Thus you should be able to - use application like PPP, minicom and others. Enabling this option - will create two modules called ircomm and ircomm-tty. + you want to compile it as a module (you will get ircomm.o and + ircomm-tty.o), say M here and read Documentation/modules.txt. IrCOMM + implements serial port emulation, and makes it possible to use all + existing applications that understands TTY's with an infrared link. + Thus you should be able to use application like PPP, minicom and + others. Enabling this option will create two modules called ircomm + and ircomm_tty. IrTTY IrDA Device Driver CONFIG_IRTTY_SIR Say Y here if you want to build support for the IrTTY line - discipline. If you want to compile it as a module, say M here and - read Documentation/modules.txt. IrTTY makes it possible to use - Linux's own serial driver for all IrDA ports that are 16550 + discipline. If you want to compile it as a module (irtty.o), say M + here and read Documentation/modules.txt. IrTTY makes it possible to + use Linux's own serial driver for all IrDA ports that are 16550 compatible. Most IrDA chips are 16550 compatible so you should probably say Y to this option. Using IrTTY will however limit the speed of the connection to 115200 bps (IrDA SIR mode) @@ -14657,50 +15181,62 @@ CONFIG_IRTTY_SIR IrPORT IrDA Device Driver CONFIG_IRPORT_SIR Say Y here if you want to build support for the IrPORT IrDA device - driver. If you want to compile it as a module, say M here and - read Documentation/modules.txt. IrPORT can be used instead of - IrTTY and sometimes this can be better. One example is if your - IrDA port does not have echo-canceling, which will work OK with - IrPORT since this driver is working in half-duplex mode only. You - don't need to use irattach with IrPORT, but you just insert it - the same way as FIR drivers (insmod irport io=0x3e8 irq=11). - Notice that IrPORT is a SIR device driver which means that speed - is limited to 115200 bps. + driver. If you want to compile it as a module (irport.o), say M here + and read Documentation/modules.txt. IrPORT can be used instead of + IrTTY and sometimes this can be better. One example is if your IrDA + port does not have echo-canceling, which will work OK with IrPORT + since this driver is working in half-duplex mode only. You don't + need to use irattach with IrPORT, but you just insert it the same + way as FIR drivers (insmod irport io=0x3e8 irq=11). Notice that + IrPORT is a SIR device driver which means that speed is limited to + 115200 bps. If unsure, say Y. -SiS5513 chipset support -CONFIG_BLK_DEV_SIS5513 - This driver ensures (U)DMA support for SIS5513 chipset based - mainboards. SiS620/530 UDMA mode 4, SiS5600/5597 UDMA mode 2, all - other DMA mode 2 limited chipsets are unsupported to date. - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - - Please read the comments at the top of drivers/block/sis5513.c - Winbond W83977AF IrDA Device Driver CONFIG_WINBOND_FIR Say Y here if you want to build IrDA support for the Winbond - W83977AF super-io chipset. If you want to compile it as a module, - say M here and read Documentation/modules.txt. This driver should be - used for the IrDA chipset in the Corel NetWinder. The driver - supports SIR, MIR and FIR (4Mbps) speeds. + W83977AF super-io chipset. This driver should be used for the IrDA + chipset in the Corel NetWinder. The driver supports SIR, MIR and FIR + (4Mbps) speeds. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called w83977af_ir.o. NSC PC87108 IrDA Device Driver CONFIG_NSC_FIR Say Y here if you want to build support for the NSC PC87108 and - PC87338 IrDA chipsets. If you want to compile it as a module, say M - here and read Documentation/modules.txt. This driver supports SIR, - MIR and FIR (4Mbps) speeds. + PC87338 IrDA chipsets. This driver supports SIR, + MIR and FIR (4Mbps) speeds. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. The module will be called nsc-ircc.o. Toshiba Type-O IR Port Device Driver CONFIG_TOSHIBA_FIR Say Y here if you want to build support for the Toshiba Type-O IR - chipset. If you want to compile it as a module, say M here and - read Documentation/modules.txt. This chipset is used by the Toshiba - Libretto 100CT, and many more laptops. + chipset. This chipset is used by the Toshiba Libretto 100CT, and + many more laptops. If you want to compile it as a module, say M here + and read Documentation/modules.txt. The module will be called + toshoboe.o. + +SMC IrCC (Experimental) +CONFIG_SMC_IRCC_FIR + Say Y here if you want to build support for the SMC Infrared + Communications Controller. It is used in the Fujitsu Lifebook 635t + and Sony PCG-505TX. If you want to compile it as a module, say M + here and read Documentation/modules.txt. The module will be called + smc-ircc.o. + +Serial dongle support +CONFIG_DONGLE + Say Y here if you have an infrared device that connects to your + computer's serial port. These devices are called dongles. Then say Y + or M to the driver for your particular dongle below. + + Note that the answer to this question won't directly affect the + kernel: saying N will just cause this configure script to skip all + the questions about serial dongles. ESI JetEye PC Dongle CONFIG_ESI_DONGLE @@ -14748,6 +15284,14 @@ CONFIG_LITELINK_DONGLE by IrTTY. To activate support for Parallax dongles you will have to start irattach like this "irattach -d litelink". +Old Belkin dongle +CONFIG_OLD_BELKIN_DONGLE + Say Y here if you want to build support for the Adaptec Airport 1000 + and 2000 dongles. If you want to compile it as a module, say M here + and read Documentation/modules.txt. The module will be called + old_belkin.o. Some information is contained in the comments at the + top of drivers/net/irda/old_belkin.c. + VME (Motorola and BVM) support CONFIG_VME Say Y here if you want to build a kernel for a 680x0 based VME @@ -14795,13 +15339,6 @@ CONFIG_BVME6000_SCSI SCSI controller chip. Almost everyone using one of these boards will want to say Y to this question. -Simple 53c710 SCSI support (Compaq, NCR machines) -CONFIG_SCSI_SIM710 - This is a driver for the NCR53C710 chip commonly found in Compaq and - NCR machines. If you are looking for 53C710 support for an Amiga or - some 680x0 based VME card then you probably want the other NCR53C710 - driver. - MVME16x Ethernet support CONFIG_MVME16x_NET This is the driver for the Ethernet interface on the Motorola @@ -14955,7 +15492,7 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp metalab # LocalWords: unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz # LocalWords: cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd -# LocalWords: HD CDROMs IDECD NEC MITSUMI XT XD PCI BIOS cezar ATEN +# LocalWords: HD CDROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN # LocalWords: ISA EISA Microchannel VESA BIOSes IPC SYSVIPC ipc Ctrl dmesg hlt # LocalWords: BINFMT Linkable http ac uk jo html GCC SPARC AVANTI CABRIOLET EB # LocalWords: netscape gcc LD CC toplevel MODVERSIONS insmod rmmod modprobe IP @@ -14985,11 +15522,11 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: readprofile diskdrives org com masq EtherTalk tcp netrom sunacm # LocalWords: misc AIC aic pio scc Portmaster eql GIS PhotoCDs MCDX Perell PG # LocalWords: mcdx gscd optcd sjcd ISP hdparm Workgroups Lan samba PARIDE PCD -# LocalWords: smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI +# LocalWords: filesystems smbfs ATA ppp PCTech RZ www powerquest txt CMD ESDI # LocalWords: chipset FB multicast MROUTE appletalk ifconfig IBMTR multiport # LocalWords: Multisession STALDRV EasyIO EC EasyConnection ISTALLION ONboard # LocalWords: Brumby pci TNC cis ohio faq usenet NETLINK dev hydra ca Tyne mem -# LocalWords: carleton Deskstation DECstation SUNFD JENSEN Noname XXXM SLiRP +# LocalWords: carleton DECstation SUNFD JENSEN Noname XXXM SLiRP LILO's amifb # LocalWords: pppd Zilog ZS SRM bootloader ez mainmenu rarp ipfwadm paride pcd # LocalWords: RTNETLINK mknod xos MTU lwared Macs mac netatalk macs cs Wolff # LocalWords: dartmouth flowerpt MultiMaster FlashPoint tudelft etherexpress @@ -15002,12 +15539,13 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT # LocalWords: kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden # LocalWords: wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI -# LocalWords: QD qd UMC umc ALI ali oss sgi com azstarnet cdr fb MDA ps esdi +# LocalWords: QD qd UMC umc ALI ali lena fnet fr azstarnet cdr fb MDA ps esdi # LocalWords: Avanti XL AlphaStations Jensen DECpc AXPpci UDB Cabriolet MCA RC # LocalWords: AlphaPC mca AOUT OUTput PPro sipx gwdg lo nwe FourPort Boca unm # LocalWords: Keepalive linefill RELCOM keepalive analogue CDR conf CDI INIT # LocalWords: OPTi isp irq noisp VFAT vfat NTFS losetup dmsdosfs dosfs ISDN MP -# LocalWords: NOWAYOUT behavior dialin isdn callback BTX Teles ICN EDSS Cisco +# LocalWords: NOWAYOUT behaviour dialin isdn callback BTX Teles XXXX LVM lvm +ICN EDSS Cisco # LocalWords: ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr # LocalWords: ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD # LocalWords: initrd tue util DES funet des OnNet BIOSP smc Travan Iomega CMS @@ -15077,12 +15615,12 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: caldera Preload Preloading slowdowns schoebel uni NBD nbd prog # LocalWords: stuttgart rdist TRANS hostnames mango jukeboxes ESS userland PD # LocalWords: hardlinked NAMETRANS env mtab fstab umount nologin runlevel gid -# LocalWords: transname filespace adm Nodename hostname uname Kernelname bootp +# LocalWords: filespace adm Nodename hostname uname Kernelname bootp nmi DI OV # LocalWords: KERNNAME kname ktype kernelname Kerneltype KERNTYPE Alt RX mdafb # LocalWords: dataless kerneltype SYSNAME Comtrol Rocketport palmtop fbset EGS # LocalWords: nvram SYSRQ SysRq PrintScreen sysrq NVRAMs NvRAM Shortwave RTTY -# LocalWords: Sitor Amtor Pactor GTOR hayes TX TMOUT JFdocs HIGHMEM DAC IRQ's -# LocalWords: IDEPCI IDEDMA idedma PDC pdc TRM trm raidtools luthien nuclecu +# LocalWords: Sitor Amtor Pactor GTOR hayes TX TMOUT JFdocs BIGMEM DAC IRQ's +# LocalWords: IDEPCI IDEDMA PDC pdc TRM trm raidtools luthien nuclecu BAGET VR # LocalWords: unam mx miguel koobera uic EMUL solaris pp ieee lpsg co DMAs TOS # LocalWords: BLDCONFIG preloading jumperless BOOTINIT modutils multipath GRE # LocalWords: misconfigured autoconfiguration IPGRE ICMP tracert ipautofw PIM @@ -15098,7 +15636,7 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: Braam braam Schmidt's freiburg nls codepages codepage Romanian # LocalWords: Slovak Slovenian Sorbian Nordic iso Catalan Faeroese Galician SZ # LocalWords: Valencian Slovene Esperanto Estonian Latvian Byelorussian KOI mt -# LocalWords: charset Inuit Greenlandic Sami Lappish koi SOFTCURSOR softcursor +# LocalWords: charset Inuit Greenlandic Sami Lappish koi Alexey Kuznetsov's sa # LocalWords: Specialix specialix DTR RTS RTSCTS cycladesZ Exabyte ftape's inr # LocalWords: Iomega's LBFM claus ZFTAPE VFS zftape zft William's lzrw DFLT kb # LocalWords: MTSETBLK MTIOCTOP qft setblk zftape's tar's afio's setdrvbuffer @@ -15112,7 +15650,7 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: struct APIC realtime OSs LynxOS CNC tmp cvf HFS hfs ADFS Risc os # LocalWords: adfs ncpmount namespace SUBDIR reexport NDS kcore FT SPX spx DAT # LocalWords: interserver BLKSZ NUMBUFFERS apmd Tadpole ANA roestock QuickCam -# LocalWords: isapnptools Colour CQCAM color Connectix QuickClip prive mentre +# LocalWords: isapnptools Colour CQCAM colour Connectix QuickClip prive mentre # LocalWords: KMOD kmod conformant utexas kharker UnixWare Mwave cgi cl ts ibm # LocalWords: eXchange threepio oakland simtel pre ULTRAMCA EtherLink isa luik # LocalWords: EtherLink OpenBSD pts DEVPTS devpts ptmx ttyp glibc readback SA @@ -15128,8 +15666,8 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: Yellowfin gsfc nasa gov yellowfin pcnet Mylex LNE lne EtherH hs # LocalWords: EBSA chattr RiscOS Winmodem AGP Atomwide DUALSP pcsp robinson CT # LocalWords: SGALAXY Waverider DSPxxx TRXPRO AudioTrix OSWF MOT CFB DSY kbps -# LocalWords: tuwien kkudielk LVD mega lun MAXTAGS Gbps arcnet Olicom SKTR SNA -# LocalWords: SysKonnect tms380tr sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX +# LocalWords: tuwien kkudielk LVD mega lun MAXTAGS Gbps arcnet Olicom SNA PAE +# LocalWords: SysKonnect tms sna etherboot ufs NetBEUI MultiSound MSNDCLAS GX # LocalWords: MSNDINIT MSNDPERM MSNDPIN PNDSPINI PNDSPERM Ensoniq's RetinaZ SS # LocalWords: AudioPCI lspci SonicVibes sonicvibes SPARCs roadrunner CLgen UPA # LocalWords: swansea shtml Zoltrix zoltrix BINUTILS EGCS binutils VIDC DACs @@ -15166,7 +15704,7 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: ACTiSYS Dongle dongle dongles esi actisys IrMate tekram BVM MVME # LocalWords: BVME BVME WRITETHROUGH copyback writethrough fwmark syncookie tu # LocalWords: alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid -# LocalWords: QNX4FS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia +# LocalWords: QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia # LocalWords: IrLPT UIRCC Tecra Strebel jstrebel suse Eichwalder ke INI INIA # LocalWords: FCP qlogicfc sym isapnp DTLK DoubleTalk rcsys dtlk DMAP SGIVW ar # LocalWords: dmabuf EcoRadio MUTEFREQ GIrBIL girbil tepkom vol mha diplom PQS @@ -15176,7 +15714,7 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: VROOTHUB KBD ARRs MCRs NWBUTTON nwbutton NUM WaveArtist APNE cpu # LocalWords: apne blackhawke PlanB lu mlan planb NWFPE FPA nwfpe unbootable # LocalWords: FPEmulator ds vmlinux initialisation discardable pgtable PGT mdw -# LocalWords: quicklist pagetable arthur StrongARM module modules Autodetect +# LocalWords: quicklist pagetable arthur StrongARM podule podules Autodetect # LocalWords: dodgy IrPORT irport Litelink litelink SuSE rtfm internet hda CY # LocalWords: multmode DriveReady SeekComplete DriveStatusError miscompile AEC # LocalWords: mainboard's Digital's alim FastTrak aec PIIXn piix Gayle Eyetech @@ -15198,9 +15736,56 @@ CONFIG_VIDEO_CPIA_USB # LocalWords: ServeRAID IPS ips ipslinux gzip BSDCOMP LZW RAYCS Interphase app # LocalWords: Tachyon IPHASE Surfboard NextLevel SURFboard jacksonville Tigon # LocalWords: fventuri adelphia siglercm linuxpower AceNICs Starfire starfire -# LocalWords: ISOC CPiA cpia uss ACPI UDF DirectCD udf CDRW's OSF Manx acpi +# LocalWords: ISOC CPiA cpia uss ACPI UDF DirectCD udf CDRW's OSF Manx acpi DM # LocalWords: Unixware cymru Computone IntelliPort Intelliport computone SI sx # LocalWords: adbmouse DRI DRM dlabs GMX PLCs Applicom fieldbus applicom int # LocalWords: VWSND eg ESSSOLO CFU CFNR scribed eiconctrl eicon hylafax KFPU -# LocalWords: EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator -# LocalWords: LOGIBUSMOUSE OV511 ov511 Integraphics +# LocalWords: EXTRAPREC fpu mainboards KHTTPD kHTTPd khttpd Xcelerator SBNI tw +# LocalWords: LOGIBUSMOUSE Granch granch sbni Raylink NOHIGHMEM Athlon SIM sim +# LocalWords: hpl Tourrilhes DuraLAN starfile Davicom davicom dmfe auk tms tr +# LocalWords: TokenExpress Belkin Peracom eTek DVDs infradead Cxxx Adlib AV ZX +# LocalWords: NeoMagic CPi CPt Celeron decapsulation Undeletion BFS bfs nVidia +# LocalWords: OnStream Irongate Riva phonedev QuickNet LineJack PhoneJack IXJ +# LocalWords: Quicknet PhoneJACK LineJACK ixj pnpdump Quicknet's Joandi SSID +# LocalWords: aironet quickconfig adhoc btw bap NONCS cardservices Xircom lin +# LocalWords: Netwave AirSurfer netwave HomePNA failover MVP iMacs ALi aktual +# LocalWords: Aladin HIDBP usbkbd KEYBDEV MOUSEDEV JOYDEV EVDEV UAB WhiteHEAT +# LocalWords: Handspring ov DABUSB URB URB's dabusb CRAMFS NFSv ELV IOAPIC WIP +# LocalWords: NLMv SMBus ALGOBIT algo PHILIPSPAR philips elv Velleman velleman +# LocalWords: ALGOPCF Elektor elektor CHARDEV dfx TDFX tdfx Extensa dof gravis +# LocalWords: assasin logitech Overdrive thrustmaster DWave Aureal magellan db +# LocalWords: SpaceTec SpaceOrb SpaceBall spaceorb FLX spaceball turbografx zr +# LocalWords: amiga ESS's WaveWatcher Maxi belkin RW's ata glx GART MPV Baget +# LocalWords: OpenGL Xserver agpgart HOTPLUG CyberPro Integraphics Netwinder +# LocalWords: aty FONTWIDTH eni zatm nicstar ForeRunner OC DECstations DEC's +# LocalWords: PHYsical SUNI reinsertion ChipSAR KVC PHY ClassID iphase iadbg +# LocalWords: DEVS FireWire PCILynx pcilynx LOCALRAM miro's DV RAWIO GRED Mk +# LocalWords: Diffserv DSMARK Ingress Qdisc TCINDEX TMSPCI tmspci Ringode JE +# LocalWords: MADGEMC madgemc TokenRing SMCTR TokenCard smctr Wacom Graphire +# LocalWords: WMFORCE mousedev ConnectTech HandSpring Xirlink IBMCAM ibmcam SN +# LocalWords: DEVICEFS yyy userspace Cymraeg Dwave SIMM JSFLASH JavaStation's +# LocalWords: nsc ircc DDB Vrc CMN TB PROMs Vino rivafb DDC Matroxes MGA TVO +# LocalWords: MAVEN fbdev crtc maven matroxset NTSC PCA SBA AAL SKFP DAS SAS +# LocalWords: skfp Intuos ADMtek's pegasus PLUSB plusb pointopoint mp rio Xeon +# LocalWords: DEVFS devfs dd bs EDSS german TELESPCI FRITZPCI HFC HFCS BDS HST +# LocalWords: ISURF ISAR Saphir HSTSAPHIR Telekom BKM Scitel Quadro SCT Gazel +# LocalWords: SP PRI Hypercope HYSDN Hypercope's hysdn IbssJoinNetTimeout FTDI +# LocalWords: ARCNet Keyspan PDA ADMtek sgalaxy sgbase opl mpuio mpuirq sbio +# LocalWords: sbirq sbdma gus uart mssio mssirq mssdma sscape maui mouirq iph +# LocalWords: CHDLC UPS's usbmouse wacom wmforce keybdev joydev fibre Trunking +# LocalWords: Etherchannel IOC Moxa Intellio moxa SmartIO mxser Mixcom EFI ir +# LocalWords: MIXCOMWD mixcomwd SENDCOMPLETE GMAC iBook gmac OAKNET oaknet PCG +# LocalWords: diffserv irlan irtty toshoboe IrCC Lifebook idex AUTODMA FIP Cxx +# LocalWords: Yenta Databook TCIC FMVJ fmvj NMCLAN LiveWire nmclan XIRC xirc +# LocalWords: loadkeys setfont shm SuperIO soc SOCAL socal FCAL fc fcal COMX +# LocalWords: MultiGate ITConsult comx CMX HiCOMX downloadable hw LoCOMX PROTO +# LocalWords: locomx MixCOM mixcom proto MyriCOM MYRI Sbus myri sbus IBMLS hme +# LocalWords: lanstreamer baseT HAPPYMEAL qfe sunhme SUNLANCE sunlance BigMAC +# LocalWords: SUNBMAC sunbmac QuadEthernet SUNQE qe FastEthernet sunqe DSB PTI +# LocalWords: DSBR dsbr procinfo QLOGICPTI qpti ptisp QLGC qlogicpti se LBA NF +# LocalWords: OPENPROMFS OpenPROM openpromfs OBP OpenBoot flashable Multiboard +# LocalWords: SPARCAUDIO SparcClassic Ultras DBRI Sparcbook sparcaudio SUNBPP +# LocalWords: UltraDMA WDC CRC CONNTRACK IPTABLES iptables nfmark interface's +# LocalWords: tdfxfb TNTx HGA hgafb VERBOSEDEBUG SunTrunking SunSoft XIRTULIP +# LocalWords: ethercards PNIC Macronix MXIC ASIX xircom Mustek MDC gphoto mdc +# LocalWords: CramFs Cramfs uid cramfs AVM's kernelcapi PCIV diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 9e59a8c17de6..ad4927b60755 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -43,6 +43,8 @@ kernel-api.sgml: kernel-api.tmpl $(TOPDIR)/drivers/net/wan/syncppp.c \ $(TOPDIR)/drivers/net/wan/z85230.c \ $(TOPDIR)/kernel/pm.c \ + $(TOPDIR)/kernel/ksyms.c \ + $(TOPDIR)/net/netsyms.c \ kernel-api.sgml DVI := $(patsubst %.sgml, %.dvi, $(BOOKS)) diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index f0013b0111a2..3f886e702ec3 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -34,13 +34,71 @@ - - Interrupt Handling -!Iarch/i386/kernel/irq.c + + The Linux VFS + The Directory Cache +!Efs/dcache.c +!Iinclude/linux/dcache.h + + Inode Handling +!Efs/inode.c +!Efs/bad_inode.c + + Registration and Superblocks +!Efs/super.c + + + + + Linux Networking + Socket Buffer Functions +!Iinclude/linux/skbuff.h +!Enet/core/skbuff.c + + Socket Filter +!Enet/core/filter.c + + + + + Network device support + Driver Support +!Edrivers/net/net_init.c +!Enet/core/dev.c + + 8390 Based Network Cards +!Edrivers/net/8390.c + + Synchronous PPP +!Edrivers/net/wan/syncppp.c + + + + + Module Loading +!Ekernel/kmod.c - - MTRR Handling + + + Hardware Interfaces + Interrupt Handling +!Iarch/i386/kernel/irq.c + + + MTRR Handling !Earch/i386/kernel/mtrr.c + + PCI Support Library +!Edrivers/pci/pci.c + + MCA Architecture + MCA Device Functions +!Earch/i386/kernel/mca.c + + MCA Bus DMA +!Iinclude/asm-i386/mca_dma.h + + @@ -58,34 +116,14 @@ !Edrivers/char/videodev.c - - Network devices -!Idrivers/net/net_init.c -!Edrivers/net/8390.c - - Sound Devices !Edrivers/sound/sound_core.c !Idrivers/sound/sound_firmware.c - - MCA Architecture - MCA Device Functions -!Earch/i386/kernel/mca.c - - MCA Bus DMA -!Iinclude/asm-i386/mca_dma.h - - - - - Synchronous PPP -!Edrivers/net/wan/syncppp.c - - + 16x50 UART Driver !Edrivers/char/serial.c @@ -95,9 +133,5 @@ !Edrivers/net/wan/z85230.c - - PCI Support Library -!Edrivers/pci/pci.c - diff --git a/Documentation/DocBook/parportbook.sgml b/Documentation/DocBook/parportbook.tmpl similarity index 100% rename from Documentation/DocBook/parportbook.sgml rename to Documentation/DocBook/parportbook.tmpl diff --git a/Documentation/sound/PAS16 b/Documentation/sound/PAS16 new file mode 100644 index 000000000000..5a519df67769 --- /dev/null +++ b/Documentation/sound/PAS16 @@ -0,0 +1,185 @@ +Pro Audio Spectrum 16 for 2.3.99 and later +========================================= +by Thomas Molina (tmolina@home.com) +last modified 26 Mar 2000 +Acknowledgement to Axel Boldt (boldt@math.ucsb.edu) for stuff taken +from Configure.help, Riccardo Facchetti for stuff from README.OSS, +and others whose names I could not find. + +This documentation is relevant for the PAS16 driver (pas2_card.c and +friends) under kernel version 2.3.99 and later. If you are +unfamiliar with configuring sound under Linux, please read the +Sound-HOWTO, linux/Documentation/sound/Introduction and other +relevant docs first. + +The following information is relevant information from README.OSS +and legacy docs for the Pro Audio Spectrum 16 (PAS16): +================================================================== + +The pas2_card.c driver supports the following cards -- +Pro Audio Spectrum 16 (PAS16) and compatibles: + Pro Audio Spectrum 16 + Pro Audio Studio 16 + Logitech Sound Man 16 + NOTE! The original Pro Audio Spectrum as well as the PAS+ are not + and will not be supported by the driver. + +The sound driver configuration dialog +------------------------------------- + +Sound configuration starts by making some yes/no questions. Be careful +when answering to these questions since answering y to a question may +prevent some later ones from being asked. For example don't answer y to +the question about (PAS16) if you don't really have a PAS16. Sound +configuration may also be made modular by answering m to configuration +options presented. + +Note also that all questions may not be asked. The configuration program +may disable some questions depending on the earlier choices. It may also +select some options automatically as well. + + "ProAudioSpectrum 16 support", + - Answer 'y'_ONLY_ if you have a Pro Audio Spectrum _16_, + Pro Audio Studio 16 or Logitech SoundMan 16 (be sure that + you read the above list correctly). Don't answer 'y' if you + have some other card made by Media Vision or Logitech since they + are not PAS16 compatible. + NOTE! Since 3.5-beta10 you need to enable SB support (next question) + if you want to use the SB emulation of PAS16. It's also possible to + the emulation if you want to use a true SB card together with PAS16 + (there is another question about this that is asked later). + "Sound Blaster support", + - Answer 'y' if you have an original SB card made by Creative Labs + or a full 100% hardware compatible clone (like Thunderboard or + SM Games). If your card was in the list of supported cards (above), + please look at the card specific instructions later in this file + before answering this question. For an unknown card you may answer + 'y' if the card claims to be SB compatible. + Enable this option also with PAS16. + + "Generic OPL2/OPL3 FM synthesizer support", + - Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). + The PAS16 has an OPL3-compatible FM chip. + +With PAS16 you can use two audio device files at the same time. /dev/dsp (and +/dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and +/dev/audio1) is connected to the SB emulation (8 bit mono only). + + +The new stuff for 2.3.99 and later +============================================================================ +The following configuration options from linux/Documentation/Configure.help +are relevant to configuring the PAS16: + +Sound card support +CONFIG_SOUND + If you have a sound card in your computer, i.e. if it can say more + than an occasional beep, say Y. Be sure to have all the information + about your sound card and its configuration down (I/O port, + interrupt and DMA channel), because you will be asked for it. + + You want to read the Sound-HOWTO, available from + http://www.linuxdoc.org/docs.html#howto . General information + about the modular sound system is contained in the files + Documentation/sound/Introduction. The file + Documentation/sound/README.OSS contains some slightly outdated but + still useful information as well. + +OSS sound modules +CONFIG_SOUND_OSS + OSS is the Open Sound System suite of sound card drivers. They make + sound programming easier since they provide a common API. Say Y or M + here (the module will be called sound.o) if you haven't found a + driver for your sound card above, then pick your driver from the + list below. + +Persistent DMA buffers +CONFIG_SOUND_DMAP + Linux can often have problems allocating DMA buffers for ISA sound + cards on machines with more than 16MB of RAM. This is because ISA + DMA buffers must exist below the 16MB boundary and it is quite + possible that a large enough free block in this region cannot be + found after the machine has been running for a while. If you say Y + here the DMA buffers (64Kb) will be allocated at boot time and kept + until the shutdown. This option is only useful if you said Y to + "OSS sound modules", above. If you said M to "OSS sound modules" + then you can get the persistent DMA buffer functionality by passing + the command-line argument "dmabuf=1" to the sound.o module. + + Say y here for PAS16. + +ProAudioSpectrum 16 support +CONFIG_SOUND_PAS + Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio + 16 or Logitech SoundMan 16 sound card. Don't answer Y if you have + some other card made by Media Vision or Logitech since they are not + PAS16 compatible. + If you compile the driver into the kernel, you have to add + "pas2=,,,,,,, + to the kernel command line. + +100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support +CONFIG_SOUND_SB + Answer Y if you have an original Sound Blaster card made by Creative + Labs or a 100% hardware compatible clone (like the Thunderboard or + SM Games). For an unknown card you may answer Y if the card claims + to be Sound Blaster-compatible. The PAS16 has 8-bit Soundblaster + support, so you can answer Y here for it. + + Please read the file Documentation/sound/Soundblaster. + + If you compile the driver into the kernel and don't want to use isapnp, + you have to add "sb=,,," to the kernel command line. + + You can say M here to compile this driver as a module; the module is + called sb.o. + +FM Synthesizer (YM3812/OPL-3) support +CONFIG_SOUND_YM3812 + Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4). + Answering Y is usually a safe and recommended choice, however some + cards may have software (TSR) FM emulation. Enabling FM support with + these cards may cause trouble (I don't currently know of any such + cards, however). + Please read the file Documentation/sound/OPL3 if your card has an + OPL3 chip. + If you compile the driver into the kernel, you have to add + "opl3=" to the kernel command line. + + If you compile your drivers into the kernel, you MUST configure + OPL3 support as a module for PAS16 support to work properly. + You can then get OPL3 functionality by issuing the command: + insmod opl3 + In addition, you must either add the following line to + /etc/modules.conf: + options opl3 io=0x388 + or else add the following line to /etc/lilo.conf: + opl3=0x388 + + +EXAMPLES +=================================================================== +To use the PAS16 in my computer I have enabled the following sound +configuration options: + +CONFIG_SOUND=y +CONFIG_SOUND_OSS=y +CONFIG_SOUND_TRACEINIT=y +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_PAS=y +CONFIG_SOUND_SB=y +CONFIG_SOUND_YM3812=m + +I have also included the following append line in /etc/lilo.conf: +append="pas2=0x388,10,3,-1,0x220,5,1,-1 sb=0x220,5,1,-1 opl3=0x388" + +The io address of 0x388 is default configuration on the PAS16. The +irq of 10 and dma of 3 may not match your installation. The above +configuration enables PAS16, 8-bit Soundblaster and OPL3 +functionality. If Soundblaster functionality is not desired, the +following line would be appropriate: +append="pas2=0x388,10,3,-1,0,-1,-1,-1 opl3=0x388" + +If sound is built totally modular, the above options may be +specified in /etc/modules.conf for pas2.o, sb.o and opl3.o +respectively. diff --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS index b1230f70a16a..38bdbaee0d95 100644 --- a/Documentation/usb/CREDITS +++ b/Documentation/usb/CREDITS @@ -16,6 +16,7 @@ difficult to maintain, add yourself with a patch if desired. Paul Mackerras David E. Nelson Vojtech Pavlik + Bill Ryder Thomas Sailer Gregory P. Smith Linus Torvalds diff --git a/Documentation/usb/ibmcam.txt b/Documentation/usb/ibmcam.txt index 5943227a6978..21d07c0ba7d2 100644 --- a/Documentation/usb/ibmcam.txt +++ b/Documentation/usb/ibmcam.txt @@ -7,8 +7,7 @@ the IBM camera. However most of needed features work well. This driver was developed using logs of observed USB traffic which was produced by standard Windows driver (c-it98.sys). -I did not have any input from Xirlink. Some people asked about -data sheets, but nothing came out of that. I didn't try. +I did not have data sheets from Xirlink. Video formats: 128x96 [model 1] @@ -29,14 +28,16 @@ SUPPORTED CAMERAS: IBM "C-It" camera, also known as "Xirlink PC Camera" The device uses proprietary ASIC (and compression method); it is manufactured by Xirlink. See http://www.xirlink.com/ -or http://www.c-itnow.com/ for details and pictures. +http://www.ibmpccamera.com or http://www.c-itnow.com/ for +details and pictures. The Linux driver was developed with camera with following model number (or FCC ID): KSX-XVP510. This camera has three interfaces, each with one endpoint (control, iso, iso). This -type of cameras is referred to as "model 1". +type of cameras is referred to as "model 1". These cameras are +no longer manufactured. -It appears that Xirlink made some changes in their cameras recently. +Xirlink now manufactures new cameras which are somewhat different. In particular, following models [FCC ID] belong to that category: XVP300 [KSX-X9903] @@ -46,29 +47,20 @@ XVP610 [KSX-X9902] (see http://www.xirlink.com/ibmpccamera/ for updates, they refer to these new cameras by Windows driver dated 12-27-99, v3005 BETA) These cameras have two interfaces, one endpoint in each (iso, bulk). -Such type of cameras is referred to as "model 2". They are supported. +Such type of cameras is referred to as "model 2". They are supported +(with exception of 352x288 native mode). Quirks of Model 2 cameras: ------------------------- -These cameras apparently produce only 176x144 native video stream; -the 352x288 formats are produced from 176x144 RGB stream. In fact, -Xirlink broke perfectly good Model 1 (which used I420 on all sizes) -and instead switched to color-separated RGB which is a terrible waste -of bandwidth and resolution. However it probably allowed to simplify -the camera and use less RAM. Model 2 camera works visibly worse than -model 1 even using Xirlink's own driver on Windows. The image quality -is better on Linux than on Windows, partly thanks to _absence_ of -annoying automatic color corrections which Windows driver feeds into -the camera several times per second. - Model 2 does not have hardware contrast control. Corresponding V4L control is not used at the moment. It may be possible to implement contrast control in software, at cost of extra processor cycles. -The bandwidth demand imposed by RGB quasi-352x288 mode (800 Kbits per -frame) essentially limits this mode to 10 frames per second or less, in -ideal conditions on the bus (USB is shared, after all). The frame rate +This driver provides 352x288 mode by switching the camera into +quasi-352x288 RGB mode (800 Kbits per frame) essentially limiting +this mode to 10 frames per second or less, in ideal conditions on +the bus (USB is shared, after all). The frame rate has to be programmed very conservatively. Additional concern is that frame rate depends on brightness setting; therefore the picture can be good at one brightness and broken at another! I did not want to fix @@ -81,24 +73,21 @@ try to adjust brightness - brighter image is slower, so USB will be able to send all data. However if you regularly use Model 2 cameras you may prefer videosize=1 which makes perfectly good I420, with no scaling and lesser demands on USB (300 Kbits per second, or 26 frames per second). -Remember that model 2 cameras never produce images with resolution -better than "true" 176x144 - or so it seems. The camera that I had also has a hardware quirk: if disconnected, it needs few minutes to "relax" before it can be plugged in again (poorly designed USB processor reset circuit?) -Finally, to say something good about Model 2: it is much simpler to program -than Model 1. Commands are few, and they all are straightforward. This camera -can be programmed for very high sensitivity (starlight may be enough), this -makes it convenient for tinkering with. The driver code has enough comments -to help a programmer to tweak the camera as s/he feels necessary. +Model 2 camera can be programmed for very high sensitivity (even starlight +may be enough), this makes it convenient for tinkering with. The driver +code has enough comments to help a programmer to tweak the camera +as s/he feels necessary. WHAT YOU NEED: - A supported IBM PC (C-it) camera (model 1 or 2) -- A Linux box with USB support (2.3/2.4 or 2.2 w/backport) +- A Linux box with USB support (2.3/2.4; 2.2 w/backport may work) - A Video4Linux compatible frame grabber program such as xawtv. @@ -179,6 +168,19 @@ flags This is a bit mask, and you can combine any number of FLAGS_OVERLAY_STATS 8 Shows tiny numbers on screen, useful only for debugging. FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers. + FLAGS_SEPARATE_FRAMES 32 Shows each frame separately, as + it was received from the camera. + Default (not set) is to mix the + preceding frame in to compensate + for occasional loss of Isoc data + on high frame rates. + FLAGS_CLEAN_FRAMES 64 Forces "cleanup" of each frame + prior to use; relevant only if + FLAGS_SEPARATE_FRAMES is set. + Default is not to clean frames, + this is a little faster but may + produce flicker if frame rate is + too high and Isoc data gets lost. framerate This setting controls frame rate of the camera. This is an approximate setting (in terms of "worst" ... "best") diff --git a/Documentation/video4linux/bttv/CARDLIST b/Documentation/video4linux/bttv/CARDLIST index 495eb7e3d19c..e41e60edfb7c 100644 --- a/Documentation/video4linux/bttv/CARDLIST +++ b/Documentation/video4linux/bttv/CARDLIST @@ -37,6 +37,7 @@ bttv.o card=35 - Chronos Video Shuttle II card=36 - Typhoon TView TV/FM Tuner card=37 - PixelView PlayTV pro + card=38 - TView99 CPH063 tuner.o type=0 - Temic PAL @@ -53,3 +54,4 @@ tuner.o type=11 - Alps TSBB5 type=12 - Alps TSBE5 type=13 - Alps TSBC5 + type=14 - Temic 4006FH5 diff --git a/Makefile b/Makefile index 4dedcf39a9ec..a5ecb912f159 100644 --- a/Makefile +++ b/Makefile @@ -442,7 +442,10 @@ checkconfig: find * -name '*.[hcS]' -type f -print | grep -v scripts/ | sort | xargs $(PERL) -w scripts/checkconfig.pl checkhelp: - $(PERL) -w scripts/checkhelp.pl `find * -name [cC]onfig.in -print` + find * -name [cC]onfig.in -print | sort | xargs $(PERL) -w scripts/checkhelp.pl + +checkincludes: + find * -name '*.[hcS]' -type f -print | sort | xargs $(PERL) -w scripts/checkincludes.pl ifdef CONFIGURATION ..$(CONFIGURATION): diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index a7110bf232d0..299a1b338089 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -42,7 +42,7 @@ #include #include -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); +extern long do_sys_mount(char *, char *, char *, int, void *); extern int do_pipe(int *); extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags); @@ -319,20 +319,16 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz) { struct file *file; - struct dentry *dentry; int retval; - lock_kernel(); retval = -EBADF; file = fget(fd); - if (!file) - goto out; - dentry = file->f_dentry; - if (dentry) - retval = do_osf_statfs(dentry, buffer, bufsiz); - fput(file); -out: - unlock_kernel(); + if (file) { + lock_kernel(); + retval = do_osf_statfs(file->f_dentry, buffer, bufsiz); + unlock_kernel(); + fput(file); + } return retval; } @@ -363,32 +359,6 @@ struct procfs_args { uid_t exroot; }; -static struct dentry *getdev(const char *name, int rdonly) -{ - struct dentry *dentry; - struct inode *inode; - int retval; - - dentry = namei(name); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) - return dentry; - - retval = -ENOTBLK; - inode = dentry->d_inode; - if (!S_ISBLK(inode->i_mode)) - goto out_dput; - - retval = -EACCES; - if (IS_NODEV(inode)) - goto out_dput; - return dentry; - -out_dput: - dput(dentry); - return ERR_PTR(retval); -} - /* * We can't actually handle ufs yet, so we translate UFS mounts to * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS @@ -400,20 +370,18 @@ out_dput: static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) { int retval; - struct dentry *dentry; struct cdfs_args tmp; + char *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; - - dentry = getdev(tmp.devname, 0); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) + devname = getname(tmp.devname); + retval = PTR_ERR(devname); + if (IS_ERR(devname)) goto out; - retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, - "ext2", flags, NULL); - dput(dentry); + retval = do_sys_mount(devname, dirname, "ext2", flags, NULL); + putname(devname); out: return retval; } @@ -421,20 +389,18 @@ out: static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags) { int retval; - struct dentry * dentry; struct cdfs_args tmp; + char *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; - - dentry = getdev(tmp.devname, 1); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) + devname = getname(tmp.devname); + retval = PTR_ERR(devname); + if (IS_ERR(devname)) goto out; - retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, - "iso9660", flags, NULL); - dput(dentry); + retval = do_sys_mount(devname, dirname, "iso9660", flags, NULL); + putname(devname); out: return retval; } @@ -445,27 +411,36 @@ static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags) if (copy_from_user(&tmp, args, sizeof(tmp))) return -EFAULT; - return do_mount(NULL, "", dirname, "proc", flags, NULL); + + return do_sys_mount("", dirname, "proc", flags, NULL); } asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) { int retval = -EINVAL; + char *name; lock_kernel(); + + name = getname(path); + retval = PTR_ERR(name); + if (IS_ERR(name)) + goto out; switch (typenr) { case 1: - retval = osf_ufs_mount(path, (struct ufs_args *) data, flag); + retval = osf_ufs_mount(name, (struct ufs_args *) data, flag); break; case 6: - retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag); + retval = osf_cdfs_mount(name, (struct cdfs_args *) data, flag); break; case 9: - retval = osf_procfs_mount(path, (struct procfs_args *) data, flag); + retval = osf_procfs_mount(name, (struct procfs_args *) data, flag); break; default: printk("osf_mount(%ld, %x)\n", typenr, flag); } + putname(name); +out: unlock_kernel(); return retval; } diff --git a/arch/i386/defconfig b/arch/i386/defconfig index e2330d62c900..340bbb728b13 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -475,11 +475,6 @@ CONFIG_PCMCIA_SERIAL=y # CONFIG_PCMCIA_SERIAL_CS is not set # CONFIG_PCMCIA_SERIAL_CB is not set -# -# USB support -# -# CONFIG_USB is not set - # # File systems # @@ -523,6 +518,7 @@ CONFIG_EXT2_FS=y # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set @@ -559,6 +555,11 @@ CONFIG_VGA_CONSOLE=y # # CONFIG_SOUND is not set +# +# USB support +# +# CONFIG_USB is not set + # # Kernel hacking # diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 8d4e4a8fd2a2..00eca716dd67 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -2298,7 +2298,9 @@ copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) return 0; } -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, +extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, + unsigned long new_flags, void *data); +extern long do_sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data); #define SMBFS_NAME "smbfs" @@ -2328,7 +2330,6 @@ sys32_mount(char *dev_name, char *dir_name, char *type, (void *)AA(data)); } else { unsigned long dev_page, dir_page, data_page; - mm_segment_t old_fs; err = copy_mount_stuff_to_kernel((const void *)dev_name, &dev_page); @@ -2348,13 +2349,9 @@ sys32_mount(char *dev_name, char *dir_name, char *type, do_smb_super_data_conv((void *)data_page); else panic("The problem is here..."); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_mount((char *)dev_page, (char *)dir_page, + err = do_sys_mount((char *)dev_page, (char *)dir_page, (char *)type_page, new_flags, (void *)data_page); - set_fs(old_fs); - if(data_page) free_page(data_page); dir_out: diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index bcb2592eebcb..dbf2ecc2d321 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -696,7 +696,7 @@ asmlinkage int irix_pause(void) return -EINTR; } -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, +extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void * data); /* XXX need more than this... */ diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c index 879edbae893f..575f68a289ad 100644 --- a/arch/ppc/8xx_io/uart.c +++ b/arch/ppc/8xx_io/uart.c @@ -1938,6 +1938,7 @@ static int rs_8xx_open(struct tty_struct *tty, struct file * filp) printk("rs_open returning after block_til_ready with %d\n", retval); #endif + MOD_DEC_USE_COUNT; return retval; } diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 98b54240252c..484ffac82d32 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -1096,7 +1096,9 @@ static inline void read_maps (void) if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 83cca5ca4e7f..36670ab93b58 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -91,7 +91,7 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len, * of /dev/zero, transform it into an anonymous mapping. * SunOS is so stupid some times... hmph! */ - if(file->f_dentry && file->f_dentry->d_inode) { + if (file) { if(MAJOR(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR && MINOR(file->f_dentry->d_inode->i_rdev) == 5) { flags |= MAP_ANONYMOUS; @@ -633,10 +633,9 @@ struct sunos_nfs_mount_args { }; -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); -extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *); +extern asmlinkage long do_sys_mount(char *, char *, char *, int, void *); extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); extern asmlinkage int sys_socket(int family, int type, int protocol); extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); @@ -660,8 +659,6 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) file = fget(fd); if (!file) goto out; - if (!file->f_dentry || !(inode = file->f_dentry->d_inode)) - goto out_putf; socket = &inode->u.socket_i; local.sin_family = AF_INET; @@ -707,7 +704,7 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args *sunos_mount = data; + struct sunos_nfs_mount_args sunos_mount; /* Ok, here comes the fun part: Linux's nfs mount needs a * socket connection to the server, but SunOS mount does not @@ -715,33 +712,42 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) * address to create a socket and bind it to a reserved * port on this system */ + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + return -EFAULT; + server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (server_fd < 0) return -ENXIO; - if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){ + if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, + sizeof(*sunos_mount.addr)) || + copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, + sizeof(*sunos_mount.fh))) { + sys_close (server_fd); + return -EFAULT; + } + + if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ sys_close (server_fd); return -ENXIO; } /* Now, bind it to a locally reserved port */ linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount->flags; - linux_nfs_mount.addr = *sunos_mount->addr; - linux_nfs_mount.root = *sunos_mount->fh; + linux_nfs_mount.flags = sunos_mount.flags; linux_nfs_mount.fd = server_fd; - linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10); - linux_nfs_mount.retrans = sunos_mount->retrans; + linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); + linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); + linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); + linux_nfs_mount.retrans = sunos_mount.retrans; - linux_nfs_mount.acregmin = sunos_mount->acregmin; - linux_nfs_mount.acregmax = sunos_mount->acregmax; - linux_nfs_mount.acdirmin = sunos_mount->acdirmin; - linux_nfs_mount.acdirmax = sunos_mount->acdirmax; + linux_nfs_mount.acregmin = sunos_mount.acregmin; + linux_nfs_mount.acregmax = sunos_mount.acregmax; + linux_nfs_mount.acdirmin = sunos_mount.acdirmin; + linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - the_name = getname(sunos_mount->hostname); + the_name = getname(sunos_mount.hostname); if(IS_ERR(the_name)) return PTR_ERR(the_name); @@ -749,7 +755,7 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) linux_nfs_mount.hostname [255] = 0; putname (the_name); - return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount); + return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } asmlinkage int @@ -758,6 +764,7 @@ sunos_mount(char *type, char *dir, int flags, void *data) int linux_flags = MS_MGC_MSK; /* new semantics */ int ret = -EINVAL; char *dev_fname = 0; + char *dir_page, *type_page; if (!capable (CAP_SYS_ADMIN)) return -EPERM; @@ -777,24 +784,44 @@ sunos_mount(char *type, char *dir, int flags, void *data) linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; - if(strcmp(type, "ext2") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "iso9660") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "minix") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "nfs") == 0) { - ret = sunos_nfs_mount (dir, flags, data); + + dir_page = getname(dir); + ret = PTR_ERR(dir_page); + if (IS_ERR(dir_page)) goto out; - } else if(strcmp(type, "ufs") == 0) { + + type_page = getname(type); + ret = PTR_ERR(type_page); + if (IS_ERR(type_page)) + goto out1; + + if(strcmp(type_page, "ext2") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "iso9660") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "minix") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "nfs") == 0) { + ret = sunos_nfs_mount (dir_page, flags, data); + goto out2 + } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out; - } else if(strcmp(type, "proc")) { + goto out2 + } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out; + goto out2 } - ret = sys_mount(dev_fname, dir, type, linux_flags, NULL); + ret = PTR_ERR(dev_fname); + if (IS_ERR(dev_fname)) + goto out2; + ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + if (dev_fname) + putname(dev_fname); +out2: + putname(type_page); +out1: + putname(dir_page); out: unlock_kernel(); return ret; diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 6e93111ae4ea..3c8b079c3255 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -2408,20 +2408,16 @@ static pgd_t *sun4c_pgd_alloc(void) */ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - struct dentry *dentry = NULL; - struct inode *inode = NULL; pgd_t *pgdp; pte_t *ptep; - if (vma->vm_file) - dentry = vma->vm_file->f_dentry; - if(dentry) - inode = dentry->d_inode; - if(inode) { - struct address_space *mapping = inode->i_mapping; + if (vma->vm_file) { + struct address_space *mapping; unsigned long offset = (address & PAGE_MASK) - vma->vm_start; struct vm_area_struct *vmaring; int alias_found = 0; + + mapping = vma->vm_file->f_dentry->d_inode->i_mapping; spin_lock(&mapping->i_shared_lock); vmaring = mapping->i_mmap; do { diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 79db5bc4e0d3..e7a50c150a92 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -616,7 +616,9 @@ static inline void read_maps (void) if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 8df2116e7bb1..423c5f6481ec 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1279,7 +1279,9 @@ static inline void read_maps (void) if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 7832518e3563..b1eb160ada71 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1746,8 +1746,8 @@ static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) return 0; } -extern long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, - unsigned long new_flags, unsigned long data_page); +extern long do_sys_mount(char * dev_page, char * dir_page, char * type_page, + unsigned long new_flags, char * data_page); #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" @@ -1756,6 +1756,8 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned { unsigned long type_page = 0; unsigned long data_page = 0; + unsigned long dev_page = 0; + unsigned long dir_page = 0; int err, is_smb, is_ncp; is_smb = is_ncp = 0; @@ -1777,19 +1779,32 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned if (err) goto type_out; + err = copy_mount_stuff_to_kernel(dev_name, &dev_page); + if (err) + goto data_out; + + err = copy_mount_stuff_to_kernel(dir_name, &dir_page); + if (err) + goto dev_out; + if (!is_smb && !is_ncp) { - err = do_sys_mount(dev_name, dir_name, type_page, new_flags, - data_page); + err = do_sys_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); } else { if (is_ncp) do_ncp_super_data_conv((void *)data_page); else do_smb_super_data_conv((void *)data_page); - err = do_sys_mount(dev_name, dir_name, type_page, new_flags, - data_page); + err = do_sys_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); } + free_page(dir_page); + +dev_out: + free_page(dev_page); +data_out: free_page(data_page); type_out: @@ -4065,7 +4080,7 @@ asmlinkage long sparc32_open(const char * filename, int flags, int mode) if (fd >= 0) { struct file * f; lock_kernel(); - f = filp_open(tmp, flags, mode, NULL); + f = filp_open(tmp, flags, mode); unlock_kernel(); error = PTR_ERR(f); if (IS_ERR(f)) diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 22f74dd2a559..291b174ac8db 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -79,19 +79,17 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of } retval = -EBADF; if(!(flags & MAP_ANONYMOUS)) { + struct inode * inode; if(fd >= SUNOS_NR_OPEN) goto out; file = fget(fd); if (!file) goto out; - if (file->f_dentry && file->f_dentry->d_inode) { - struct inode * inode = file->f_dentry->d_inode; - if(MAJOR(inode->i_rdev) == MEM_MAJOR && - MINOR(inode->i_rdev) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } + inode = file->f_dentry->d_inode; + if(MAJOR(inode->i_rdev)==MEM_MAJOR && MINOR(inode->i_rdev)==5) { + flags |= MAP_ANONYMOUS; + fput(file); + file = NULL; } } @@ -601,7 +599,7 @@ struct sunos_nfs_mount_args { char *netname; /* server's netname */ }; -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); +extern long do_sys_mount(const char *, const char *, char *, int, void *); extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *); @@ -627,17 +625,12 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) struct inode *inode; struct file *file; - file = fcheck(fd); + file = fget(fd); if(!file) return 0; dentry = file->f_dentry; - if(!dentry) - return 0; - inode = dentry->d_inode; - if(!inode) - return 0; socket = &inode->u.socket_i; local.sin_family = AF_INET; @@ -651,8 +644,10 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) sizeof(local)); } while (ret && try_port > (1024 / 2)); - if (ret) + if (ret) { + fput(file); return 0; + } server.sin_family = AF_INET; server.sin_addr = addr->sin_addr; @@ -661,6 +656,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) /* Call sys_connect */ ret = socket->ops->connect (socket, (struct sockaddr *) &server, sizeof (server), file->f_flags); + fput(file); if (ret < 0) return 0; return 1; @@ -681,7 +677,7 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args *sunos_mount = data; + struct sunos_nfs_mount_args sunos_mount; /* Ok, here comes the fun part: Linux's nfs mount needs a * socket connection to the server, but SunOS mount does not @@ -689,41 +685,50 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) * address to create a socket and bind it to a reserved * port on this system */ + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + return -EFAULT; + server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (server_fd < 0) return -ENXIO; - if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){ + if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, + sizeof(*sunos_mount.addr)) || + copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, + sizeof(*sunos_mount.fh))) { + sys_close (server_fd); + return -EFAULT; + } + + if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ sys_close (server_fd); return -ENXIO; } /* Now, bind it to a locally reserved port */ linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount->flags; - linux_nfs_mount.addr = *sunos_mount->addr; - linux_nfs_mount.root = *sunos_mount->fh; + linux_nfs_mount.flags = sunos_mount.flags; linux_nfs_mount.fd = server_fd; - linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10); - linux_nfs_mount.retrans = sunos_mount->retrans; + linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); + linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); + linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); + linux_nfs_mount.retrans = sunos_mount.retrans; - linux_nfs_mount.acregmin = sunos_mount->acregmin; - linux_nfs_mount.acregmax = sunos_mount->acregmax; - linux_nfs_mount.acdirmin = sunos_mount->acdirmin; - linux_nfs_mount.acdirmax = sunos_mount->acdirmax; + linux_nfs_mount.acregmin = sunos_mount.acregmin; + linux_nfs_mount.acregmax = sunos_mount.acregmax; + linux_nfs_mount.acdirmin = sunos_mount.acdirmin; + linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - the_name = getname(sunos_mount->hostname); + the_name = getname(sunos_mount.hostname); if(IS_ERR(the_name)) - return -EFAULT; + return PTR_ERR(the_name); strncpy (linux_nfs_mount.hostname, the_name, 254); linux_nfs_mount.hostname [255] = 0; putname (the_name); - - return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount); + + return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } /* XXXXXXXXXXXXXXXXXXXX */ @@ -733,6 +738,7 @@ sunos_mount(char *type, char *dir, int flags, void *data) int linux_flags = MS_MGC_MSK; /* new semantics */ int ret = -EINVAL; char *dev_fname = 0; + char *dir_page, *type_page; if (!capable (CAP_SYS_ADMIN)) return -EPERM; @@ -751,24 +757,44 @@ sunos_mount(char *type, char *dir, int flags, void *data) linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; - if(strcmp(type, "ext2") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "iso9660") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "minix") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "nfs") == 0) { - ret = sunos_nfs_mount (dir, flags, data); + + dir_page = getname(dir); + ret = PTR_ERR(dir_page); + if (IS_ERR(dir_page)) goto out; - } else if(strcmp(type, "ufs") == 0) { + + type_page = getname(type); + ret = PTR_ERR(type_page); + if (IS_ERR(type_page)) + goto out1; + + if(strcmp(type_page, "ext2") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "iso9660") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "minix") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "nfs") == 0) { + ret = sunos_nfs_mount (dir_page, flags, data); + goto out2 + } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out; - } else if(strcmp(type, "proc")) { + goto out2 + } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out; + goto out2 } - ret = sys_mount(dev_fname, dir, type, linux_flags, NULL); + ret = PTR_ERR(dev_fname); + if (IS_ERR(dev_fname)) + goto out2; + ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + if (dev_fname) + putname(dev_fname); +out2: + putname(type_page); +out1: + putname(dir_page); out: unlock_kernel(); return ret; diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 4adaf4077058..2c17d664d2ff 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -495,26 +495,18 @@ asmlinkage int solaris_statvfs(u32 path, u32 buf) asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) { - struct inode * inode; - struct dentry * dentry; struct file * file; int error; - lock_kernel(); error = -EBADF; file = fget(fd); - if (!file) - goto out; - - if (!(dentry = file->f_dentry)) - error = -ENOENT; - else if (!(inode = dentry->d_inode)) - error = -ENOENT; - else - error = report_statvfs(inode, buf); - fput(file); + if (file) { + lock_kernel(); + error = report_statvfs(file->f_dentry->d_inode, buf); + unlock_kernel(); + fput(file); + } out: - unlock_kernel(); return error; } @@ -538,26 +530,17 @@ asmlinkage int solaris_statvfs64(u32 path, u32 buf) asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf) { - struct inode * inode; - struct dentry * dentry; struct file * file; int error; - lock_kernel(); error = -EBADF; file = fget(fd); - if (!file) - goto out; - - if (!(dentry = file->f_dentry)) - error = -ENOENT; - else if (!(inode = dentry->d_inode)) - error = -ENOENT; - else - error = report_statvfs64(inode, buf); - fput(file); -out: - unlock_kernel(); + if (file) { + lock_kernel(); + error = report_statvfs64(file->f_dentry->d_inode, buf); + unlock_kernel(); + fput(file); + } return error; } diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index b77a27236dd5..c9341b0fd83d 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -72,7 +72,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o file = fget(fd); if (!file) goto out; - if (file->f_dentry && file->f_dentry->d_inode) { + else { struct inode * inode = file->f_dentry->d_inode; if(MAJOR(inode->i_rdev) == MEM_MAJOR && MINOR(inode->i_rdev) == 5) { diff --git a/bad b/bad new file mode 100644 index 000000000000..afed4be845bc --- /dev/null +++ b/bad @@ -0,0 +1,22 @@ +--- drivers/usb/usb-storage.c.orig Thu Mar 30 20:31:08 2000 ++++ drivers/usb/usb-storage.c Sun Apr 2 15:20:21 2000 +@@ -1417,6 +1418,9 @@ + /* lock the device pointers */ + spin_lock_irqsave(&(us->dev_spinlock), flags); + ++ /* lock the device pointers */ ++ spin_lock_irqsave(&(us->dev_spinlock), flags); ++ + /* our device has gone - pretend not ready */ + /* FIXME: we also need to handle INQUIRY here, + * probably */ +@@ -1862,6 +1866,9 @@ + US_DEBUGP("-- device was not in use\n"); + return; + } ++ ++ /* lock access to the device data structure */ ++ spin_lock_irqsave(&(ss->dev_spinlock), flags); + + /* lock access to the device data structure */ + spin_lock_irqsave(&(ss->dev_spinlock), flags); diff --git a/drivers/acorn/scsi/acornscsi.h b/drivers/acorn/scsi/acornscsi.h index b6a7f3148951..18cd873d54c8 100644 --- a/drivers/acorn/scsi/acornscsi.h +++ b/drivers/acorn/scsi/acornscsi.h @@ -1,3 +1,8 @@ +/* + * Acorn SCSI driver + * + * Copyright (C) 1997 Russell King + */ #ifndef ACORNSCSI_H #define ACORNSCSI_H diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c index cc1701708bb8..27e5b266aadb 100644 --- a/drivers/acorn/scsi/arxescsi.c +++ b/drivers/acorn/scsi/arxescsi.c @@ -1,7 +1,7 @@ /* - * linux/arch/arm/drivers/scsi/cumana_2.c + * linux/arch/arm/drivers/scsi/arxescsi.c * - * Copyright (C) 1997,1998 Russell King + * Copyright (C) 1997-2000 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and @@ -13,6 +13,7 @@ * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. * 11-06-1998 0.0.2 Changed to support ARXE 16-bit SCSI card, enabled writing * by Stefan Hanske + * 02-04-2000 RMK 0.0.3 Updated for new error handling code. */ #include @@ -54,7 +55,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 3 static struct expansion_card *ecs[MAX_ECARDS]; @@ -308,10 +309,9 @@ const char *arxescsi_info(struct Scsi_Host *host) static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX irq %d v%d.%d.%d scsi %s", - host->hostt->name, host->io_port, host->irq, - VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d", VER_MAJOR, VER_MINOR, VER_PATCH); return string; } @@ -354,12 +354,7 @@ int arxescsi_proc_info(char *buffer, char **start, off_t offset, pos = sprintf(buffer, "ARXE 16-bit SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d\n" - "FAS : %s\n\n" - "Statistics:\n", - host->io_port, host->irq, info->info.scsi.type); - + pos += fas216_print_host(&info->info, buffer + pos); pos += fas216_print_stats(&info->info, buffer + pos); pos += sprintf (buffer+pos, "\nAttached devices:\n"); diff --git a/drivers/acorn/scsi/arxescsi.h b/drivers/acorn/scsi/arxescsi.h index 11dc6b6e35b1..dd97233ae782 100644 --- a/drivers/acorn/scsi/arxescsi.h +++ b/drivers/acorn/scsi/arxescsi.h @@ -1,7 +1,8 @@ /* * ARXE SCSI card driver * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-2000 Russell King + * * Changes to support ARXE 16-bit SCSI card by Stefan Hanske */ #ifndef ARXE_SCSI_H @@ -44,22 +45,25 @@ extern int arxescsi_proc_info (char *buffer, char **start, off_t offset, #include "fas216.h" #endif -#define ARXEScsi { \ -proc_info: arxescsi_proc_info, \ -name: "ARXE SCSI card", \ -detect: arxescsi_detect, /* detect */ \ -release: arxescsi_release, /* release */ \ -info: arxescsi_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CMD_PER_LUN, /* cmd per lun */ \ -use_clustering: DISABLE_CLUSTERING \ +#define ARXEScsi { \ +proc_info: arxescsi_proc_info, \ +name: "ARXE SCSI card", \ +detect: arxescsi_detect, \ +release: arxescsi_release, \ +info: arxescsi_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CMD_PER_LUN, \ +use_clustering: DISABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c index 2307ae3972f7..b812ef2d0b65 100644 --- a/drivers/acorn/scsi/cumana_2.c +++ b/drivers/acorn/scsi/cumana_2.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/drivers/scsi/cumana_2.c * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King * * Changelog: * 30-08-1997 RMK 0.0.0 Created, READONLY version. @@ -10,6 +10,7 @@ * 02-05-1998 RMK 0.0.2 Updated & added DMA support. * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth. + * 02-04-2000 RMK 0.0.4 Updated for new error handling code. */ #include @@ -70,7 +71,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 3 +#define VER_PATCH 4 static struct expansion_card *ecs[MAX_ECARDS]; @@ -433,25 +434,11 @@ const char *cumanascsi_2_info(struct Scsi_Host *host) static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX ", - host->hostt->name, host->io_port); - - if (host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", host->irq); - else - p += sprintf(p, "NO IRQ "); - - if (host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", host->dma_channel); - else - p += sprintf(p, "NO DMA "); - - p += sprintf(p, "v%d.%d.%d scsi %s", + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d terminators o%s", VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); - - p += sprintf(p, " terminators %s", - info->terms ? "on" : "off"); + info->terms ? "n" : "ff"); return string; } @@ -525,26 +512,14 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, pos = sprintf(buffer, "Cumana SCSI II driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d DMA : %d\n" - "FAS : %-10s TERM: %-3s\n\n" - "Statistics:\n", - host->io_port, host->irq, host->dma_channel, - info->info.scsi.type, info->terms ? "on" : "off"); - - pos += sprintf(buffer+pos, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", - info->info.stats.queues, info->info.stats.removes, - info->info.stats.fins, info->info.stats.reads, - info->info.stats.writes, info->info.stats.miscs, - info->info.stats.disconnects, info->info.stats.aborts, - info->info.stats.resets); - - pos += sprintf(buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + + pos += fas216_print_host(&info->info, buffer + pos); + pos += sprintf(buffer + pos, "Term : o%s\n", + info->terms ? "n" : "ff"); + + pos += fas216_print_stats(&info->info, buffer + pos); + + pos += sprintf(buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { int len; diff --git a/drivers/acorn/scsi/cumana_2.h b/drivers/acorn/scsi/cumana_2.h index 66b3740192c4..48ac695b703f 100644 --- a/drivers/acorn/scsi/cumana_2.h +++ b/drivers/acorn/scsi/cumana_2.h @@ -1,7 +1,7 @@ /* * Cumana SCSI II driver * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King */ #ifndef CUMANA_2_H #define CUMANA_2_H @@ -23,6 +23,13 @@ extern int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, #define CAN_QUEUE 1 #endif +#ifndef CMD_PER_LUN +/* + * Default queue size + */ +#define CMD_PER_LUN 1 +#endif + #ifndef SCSI_ID /* * Default SCSI host ID @@ -36,23 +43,25 @@ extern int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, #include "fas216.h" #endif -#define CUMANASCSI_2 { \ -proc_info: cumanascsi_2_proc_info, \ -name: "Cumana SCSI II", \ -detect: cumanascsi_2_detect, /* detect */ \ -release: cumanascsi_2_release, /* release */ \ -info: cumanascsi_2_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CAN_QUEUE, /* cmd per lun */ \ -unchecked_isa_dma: 0, /* unchecked isa dma */ \ -use_clustering: DISABLE_CLUSTERING \ +#define CUMANASCSI_2 { \ +proc_info: cumanascsi_2_proc_info, \ +name: "Cumana SCSI II", \ +detect: cumanascsi_2_detect, \ +release: cumanascsi_2_release, \ +info: cumanascsi_2_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CMD_PER_LUN, \ +use_clustering: DISABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c index e6a6a40050c8..2ebe06f593c6 100644 --- a/drivers/acorn/scsi/eesox.c +++ b/drivers/acorn/scsi/eesox.c @@ -1,20 +1,22 @@ /* * linux/arch/arm/drivers/scsi/eesox.c * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and * may not be reliable! * * Changelog: - * 01-10-1997 RMK Created, READONLY version - * 15-02-1998 RMK READ/WRITE version - * added DMA support and hardware definitions - * 14-03-1998 RMK Updated DMA support - * Added terminator control - * 15-04-1998 RMK Only do PIO if FAS216 will allow it. - * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 01-10-1997 RMK Created, READONLY version + * 15-02-1998 RMK READ/WRITE version + * added DMA support and hardware definitions + * 14-03-1998 RMK Updated DMA support + * Added terminator control + * 15-04-1998 RMK Only do PIO if FAS216 will allow it. + * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 02-04-2000 RMK 0.0.3 Fixed NO_IRQ/NO_DMA problem, updated for new + * error handling code. */ #include @@ -67,7 +69,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 3 static struct expansion_card *ecs[MAX_ECARDS]; @@ -382,14 +384,16 @@ eesoxscsi_detect(Scsi_Host_Template *tpnt) request_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT, "eesox2-fas"); - if (request_irq(host->irq, eesoxscsi_intr, + if (host->irq != NO_IRQ && + request_irq(host->irq, eesoxscsi_intr, SA_INTERRUPT, "eesox", host)) { printk("scsi%d: IRQ%d not free, interrupts disabled\n", host->host_no, host->irq); host->irq = NO_IRQ; } - if (request_dma(host->dma_channel, "eesox")) { + if (host->dma_channel != NO_DMA && + request_dma(host->dma_channel, "eesox")) { printk("scsi%d: DMA%d not free, DMA disabled\n", host->host_no, host->dma_channel); host->dma_channel = NO_DMA; @@ -435,24 +439,11 @@ const char *eesoxscsi_info(struct Scsi_Host *host) static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX ", - host->hostt->name, host->io_port); - - if (host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", host->irq); - else - p += sprintf(p, "NO IRQ "); - - if (host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", host->dma_channel); - else - p += sprintf(p, "NO DMA "); - - p += sprintf(p, "v%d.%d.%d scsi %s", VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); - - p += sprintf(p, " terminators %s", - info->control.control & EESOX_TERM_ENABLE ? "on" : "off"); + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d terminators o%s", + VER_MAJOR, VER_MINOR, VER_PATCH, + info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); return string; } @@ -526,26 +517,13 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, pos = sprintf(buffer, "EESOX SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d DMA : %d\n" - "FAS : %-10s TERM: %-3s\n\n" - "Statistics:\n", - host->io_port, host->irq, host->dma_channel, - info->info.scsi.type, info->control.control & EESOX_TERM_ENABLE ? "on" : "off"); - - pos += sprintf(buffer+pos, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", - info->info.stats.queues, info->info.stats.removes, - info->info.stats.fins, info->info.stats.reads, - info->info.stats.writes, info->info.stats.miscs, - info->info.stats.disconnects, info->info.stats.aborts, - info->info.stats.resets); - - pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none"); + pos += fas216_print_host(&info->info, buffer + pos); + pos += sprintf(buffer + pos, "Term : o%s\n", + info->control.control & EESOX_TERM_ENABLE ? "n" : "ff"); + + pos += fas216_print_stats(&info->info, buffer + pos); + + pos += sprintf (buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { int len; diff --git a/drivers/acorn/scsi/eesox.h b/drivers/acorn/scsi/eesox.h index 31c6c883ed78..05433fd6b14f 100644 --- a/drivers/acorn/scsi/eesox.h +++ b/drivers/acorn/scsi/eesox.h @@ -1,7 +1,7 @@ /* * EESOX SCSI driver * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King */ #ifndef EESOXSCSI_H #define EESOXSCSI_H @@ -38,22 +38,25 @@ extern int eesoxscsi_proc_info (char *buffer, char **start, off_t offset, #include "fas216.h" -#define EESOXSCSI { \ -proc_info: eesoxscsi_proc_info, \ -name: "EESOX SCSI", \ -detect: eesoxscsi_detect, /* detect */ \ -release: eesoxscsi_release, /* release */ \ -info: eesoxscsi_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CAN_QUEUE, /* cmd per lun */ \ -use_clustering: DISABLE_CLUSTERING \ +#define EESOXSCSI { \ +proc_info: eesoxscsi_proc_info, \ +name: "EESOX SCSI", \ +detect: eesoxscsi_detect, \ +release: eesoxscsi_release, \ +info: eesoxscsi_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CAN_QUEUE, \ +use_clustering: DISABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff --git a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c index 744480f516c4..1a89a91eb387 100644 --- a/drivers/acorn/scsi/fas216.c +++ b/drivers/acorn/scsi/fas216.c @@ -1,11 +1,12 @@ /* * linux/arch/arm/drivers/scsi/fas216.c * - * Copyright (C) 1997 Russell King + * Copyright (C) 1997-2000 Russell King * * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and * other sources, including: * the AMD Am53CF94 data sheet + * the AMD Am53C94 data sheet * * This is a generic driver. To use it, have a look at cumana_2.c. You * should define your own structure that overlays FAS216_Info, eg: @@ -25,6 +26,9 @@ * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT + * 02-04-2000 RMK Converted to use the new error handling, and + * automatically request sense data upon check + * condition status from targets. * * Todo: * - allow individual devices to enable sync xfers. @@ -59,8 +63,6 @@ MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver"); #define VER_MINOR 0 #define VER_PATCH 5 -#define SCSI2_TAG - /* NOTE: SCSI2 Synchronous transfers *require* DMA according to * the data sheet. This restriction is crazy, especially when * you only want to send 16 bytes! What were the guys who @@ -85,8 +87,8 @@ MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver"); * I was thinking that this was a good chip until I found this restriction ;( */ #define SCSI2_SYNC - -#define SCSI2_WIDE +#undef SCSI2_WIDE +#undef SCSI2_TAG #undef DEBUG_CONNECT #undef DEBUG_BUSSERVICE @@ -143,10 +145,11 @@ static void fas216_dumpinfo(FAS216_Info *info) info->scsi.async_stp, info->scsi.disconnectable, info->scsi.aborting); printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n" - " disconnects=%X aborts=%X resets=%X }\n", + " disconnects=%X aborts=%X bus_resets=%X host_resets=%X}\n", info->stats.queues, info->stats.removes, info->stats.fins, info->stats.reads, info->stats.writes, info->stats.miscs, - info->stats.disconnects, info->stats.aborts, info->stats.resets); + info->stats.disconnects, info->stats.aborts, info->stats.bus_resets, + info->stats.host_resets); printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n", info->ifcfg.clockrate, info->ifcfg.select_timeout, info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); @@ -164,7 +167,7 @@ static void fas216_dumpinfo(FAS216_Info *info) } #ifdef CHECK_STRUCTURE -static void fas216_checkmagic(FAS216_Info *info, const char *func) +static void __fas216_checkmagic(FAS216_Info *info, const char *func) { int corruption = 0; if (info->magic_start != MAGIC) { @@ -180,8 +183,9 @@ static void fas216_checkmagic(FAS216_Info *info, const char *func) panic("scsi memory space corrupted in %s", func); } } +#define fas216_checkmagic(info) __fas216_checkmagic((info), __FUNCTION__) #else -#define fas216_checkmagic(info,func) +#define fas216_checkmagic(info) #endif static const char *fas216_bus_phase(int stat) @@ -312,7 +316,7 @@ fas216_syncperiod(FAS216_Info *info, int ns) { int value = (info->ifcfg.clockrate * ns) / 1000; - fas216_checkmagic(info, "fas216_syncperiod"); + fas216_checkmagic(info); if (value < 4) value = 4; @@ -586,7 +590,7 @@ fas216_updateptrs(FAS216_Info *info, int bytes_transferred) unsigned char *ptr; unsigned int residual; - fas216_checkmagic(info, "fas216_updateptrs"); + fas216_checkmagic(info); ptr = info->scsi.SCp.ptr; residual = info->scsi.SCp.this_residual; @@ -629,7 +633,7 @@ fas216_pio(FAS216_Info *info, fasdmadir_t direction) unsigned int residual; char *ptr; - fas216_checkmagic(info, "fas216_pio"); + fas216_checkmagic(info); residual = info->scsi.SCp.this_residual; ptr = info->scsi.SCp.ptr; @@ -668,7 +672,7 @@ fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) { fasdmatype_t dmatype; - fas216_checkmagic(info, "fas216_starttransfer"); + fas216_checkmagic(info); info->scsi.phase = (direction == DMA_OUT) ? PHASE_DATAOUT : PHASE_DATAIN; @@ -763,7 +767,7 @@ fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo) static void fas216_stoptransfer(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_stoptransfer"); + fas216_checkmagic(info); if (info->dma.transfer_type != fasdma_none && info->dma.transfer_type != fasdma_pio) { @@ -797,7 +801,7 @@ fas216_stoptransfer(FAS216_Info *info) static void fas216_disconnect_intr(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_disconnected_intr"); + fas216_checkmagic(info); #ifdef DEBUG_CONNECT printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no, @@ -849,7 +853,7 @@ fas216_reselected_intr(FAS216_Info *info) { unsigned char target, identify_msg, ok; - fas216_checkmagic(info, "fas216_reselected_intr"); + fas216_checkmagic(info); if ((info->scsi.phase == PHASE_SELECTION || info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { @@ -949,6 +953,7 @@ fas216_reselected_intr(FAS216_Info *info) msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); info->scsi.phase = PHASE_MSGOUT_EXPECT; } + outb(CMD_MSGACCEPTED, REG_CMD(info)); } @@ -959,7 +964,7 @@ fas216_reselected_intr(FAS216_Info *info) static void fas216_finish_reconnect(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_reconnect"); + fas216_checkmagic(info); #ifdef DEBUG_CONNECT printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n", @@ -1087,7 +1092,7 @@ static void fas216_message(FAS216_Info *info) unsigned int msglen = 1, i; int msgbyte = 0; - fas216_checkmagic(info, "fas216_message"); + fas216_checkmagic(info); message[0] = inb(REG_FF(info)); @@ -1270,7 +1275,7 @@ static void fas216_send_command(FAS216_Info *info) { int i; - fas216_checkmagic(info, "fas216_send_command"); + fas216_checkmagic(info); outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info)); outb(CMD_FLUSHFIFO, REG_CMD(info)); @@ -1293,7 +1298,7 @@ static void fas216_send_messageout(FAS216_Info *info, int start) { unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs); - fas216_checkmagic(info, "fas216_send_messageout"); + fas216_checkmagic(info); outb(CMD_FLUSHFIFO, REG_CMD(info)); @@ -1326,7 +1331,7 @@ static void fas216_send_messageout(FAS216_Info *info, int start) */ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) { - fas216_checkmagic(info, "fas216_busservice_intr"); + fas216_checkmagic(info); #ifdef DEBUG_BUSSERVICE printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n", @@ -1520,7 +1525,7 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned { int status, message; - fas216_checkmagic(info, "fas216_funcdone_intr"); + fas216_checkmagic(info); #ifdef DEBUG_FUNCTIONDONE printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n", @@ -1562,7 +1567,7 @@ void fas216_intr(struct Scsi_Host *instance) FAS216_Info *info = (FAS216_Info *)instance->hostdata; unsigned char isr, ssr, stat; - fas216_checkmagic(info, "fas216_intr"); + fas216_checkmagic(info); stat = inb(REG_STAT(info)); ssr = inb(REG_IS(info)); @@ -1571,9 +1576,10 @@ void fas216_intr(struct Scsi_Host *instance) add_debug_list(stat, ssr, isr, info->scsi.phase); if (stat & STAT_INT) { - if (isr & INST_BUSRESET) + if (isr & INST_BUSRESET) { printk(KERN_DEBUG "scsi%d.H: bus reset detected\n", instance->host_no); - else if (isr & INST_ILLEGALCMD) { + scsi_report_bus_reset(instance, 0); + } else if (isr & INST_ILLEGALCMD) { printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no); fas216_dumpstate(info); } else if (isr & INST_DISCONNECT) @@ -1599,22 +1605,35 @@ void fas216_intr(struct Scsi_Host *instance) */ static void fas216_kick(FAS216_Info *info) { - Scsi_Cmnd *SCpnt; - int tot_msglen, from_queue = 0; + Scsi_Cmnd *SCpnt = NULL; + int tot_msglen, from_queue = 0, disconnect_ok; - fas216_checkmagic(info, "fas216_kick"); + fas216_checkmagic(info); - if (info->origSCpnt) { - SCpnt = info->origSCpnt; - info->origSCpnt = NULL; - } else - SCpnt = NULL; + /* + * Obtain the next command to process. + */ + do { + if (info->reqSCpnt) { + SCpnt = info->reqSCpnt; + info->reqSCpnt = NULL; + break; + } - /* retrieve next command */ - if (!SCpnt) { - SCpnt = queue_remove_exclude(&info->queues.issue, info->busyluns); - from_queue = 1; - } + if (info->origSCpnt) { + SCpnt = info->origSCpnt; + info->origSCpnt = NULL; + break; + } + + /* retrieve next command */ + if (!SCpnt) { + SCpnt = queue_remove_exclude(&info->queues.issue, + info->busyluns); + from_queue = 1; + break; + } + } while (0); if (!SCpnt) /* no command pending - just exit */ return; @@ -1627,16 +1646,6 @@ static void fas216_kick(FAS216_Info *info) info->host->host_no, fas216_target(info)); } - /* - * tagged queuing - allocate a new tag to this command - */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE) { - SCpnt->device->current_tag += 1; - if (SCpnt->device->current_tag == 0) - SCpnt->device->current_tag = 1; - SCpnt->tag = SCpnt->device->current_tag; - } - /* * claim host busy */ @@ -1653,6 +1662,9 @@ static void fas216_kick(FAS216_Info *info) if (from_queue) { #ifdef SCSI2_TAG + /* + * tagged queuing - allocate a new tag to this command + */ if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && SCpnt->cmnd[0] != INQUIRY) { SCpnt->device->current_tag += 1; @@ -1681,41 +1693,48 @@ static void fas216_kick(FAS216_Info *info) } } - /* build outgoing message bytes */ - msgqueue_flush(&info->scsi.msgs); + /* + * Don't allow request sense commands to disconnect. + */ + disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE && + info->device[SCpnt->target].disconnect_ok; - if (info->device[SCpnt->target].disconnect_ok) - msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun)); - else - msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(0, SCpnt->lun)); + /* + * build outgoing message bytes + */ + msgqueue_flush(&info->scsi.msgs); + msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->lun)); - /* add tag message if required */ + /* + * add tag message if required + */ if (SCpnt->tag) msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); + do { #ifdef SCSI2_WIDE - if (info->device[SCpnt->target].wide_state == neg_wait) { - info->device[SCpnt->target].wide_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - info->ifcfg.wide_max_size); - } -#ifdef SCSI2_SYNC - else -#endif + if (info->device[SCpnt->target].wide_state == neg_wait) { + info->device[SCpnt->target].wide_state = neg_inprogress; + msgqueue_addmsg(&info->scsi.msgs, 4, + EXTENDED_MESSAGE, 2, EXTENDED_WDTR, + info->ifcfg.wide_max_size); + break; + } #endif #ifdef SCSI2_SYNC - if ((info->device[SCpnt->target].sync_state == neg_wait || - info->device[SCpnt->target].sync_state == neg_complete) && - (SCpnt->cmnd[0] == REQUEST_SENSE || - SCpnt->cmnd[0] == INQUIRY)) { - info->device[SCpnt->target].sync_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 5, - EXTENDED_MESSAGE, 3, EXTENDED_SDTR, - 1000 / info->ifcfg.clockrate, - info->ifcfg.sync_max_depth); - } + if ((info->device[SCpnt->target].sync_state == neg_wait || + info->device[SCpnt->target].sync_state == neg_complete) && + (SCpnt->cmnd[0] == REQUEST_SENSE || + SCpnt->cmnd[0] == INQUIRY)) { + info->device[SCpnt->target].sync_state = neg_inprogress; + msgqueue_addmsg(&info->scsi.msgs, 5, + EXTENDED_MESSAGE, 3, EXTENDED_SDTR, + 1000 / info->ifcfg.clockrate, + info->ifcfg.sync_max_depth); + break; + } #endif + } while (0); /* following what the ESP driver says */ outb(0, REG_STCL(info)); @@ -1780,18 +1799,156 @@ static void fas216_kick(FAS216_Info *info) /* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */ } +/* Function: void fas216_rq_sns_done(info, SCpnt, result) + * Purpose : Finish processing automatic request sense command + * Params : info - interface that completed + * SCpnt - command that completed + * result - driver byte of result + */ +static void +fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) +{ +#ifdef DEBUG_CONNECT + printk("scsi%d.%c: request sense complete, result=%04X%02X%02X\n", + info->host->host_no, '0' + SCpnt->target, result, + SCpnt->SCp.Message, SCpnt->SCp.Status); +#endif + + if (result != DID_OK || SCpnt->SCp.Status != GOOD) + /* + * Something went wrong. Make sure that we don't + * have valid data in the sense buffer that could + * confuse the higher levels. + */ + memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); + + /* + * Note that we don't set SCpnt->result, since that should + * reflect the status of the command that we were asked by + * the upper layers to process. This would have been set + * correctly by fas216_std_done. + */ + SCpnt->scsi_done(SCpnt); +} + +/* Function: void fas216_std_done(info, SCpnt, result) + * Purpose : Finish processing of standard command + * Params : info - interface that completed + * SCpnt - command that completed + * result - driver byte of result + */ +static void +fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) +{ + info->stats.fins += 1; + + SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | + info->scsi.SCp.Status; + +#ifdef DEBUG_CONNECT + printk("scsi%d.%c: command complete, result=%08X, command=", + info->host->host_no, '0' + SCpnt->target, SCpnt->result); + print_command(SCpnt->cmnd); +#endif + + /* + * If the driver detected an error, or the command + * was request sense, then we're all done. + */ + if (result != DID_OK || SCpnt->cmnd[0] == REQUEST_SENSE) + goto done; + + /* + * If the command returned CHECK_CONDITION status, + * request the sense information. + */ + if (info->scsi.SCp.Status == CHECK_CONDITION) + goto request_sense; + + /* + * If the command did not complete with GOOD status, + * we are all done here. + */ + if (info->scsi.SCp.Status != GOOD) + goto done; + + /* + * We have successfully completed a command. Make sure that + * we do not have any buffers left to transfer. The world + * is not perfect, and we seem to occasionally hit this. + * It can be indicative of a buggy driver, target or the upper + * levels of the SCSI code. + */ + if (info->scsi.SCp.ptr) { + switch (SCpnt->cmnd[0]) { + case INQUIRY: + case START_STOP: +// case READ_CAPACITY: + case MODE_SENSE: + break; + + default: + printk(KERN_ERR "scsi%d.%c: incomplete data transfer " + "detected: res=%08X ptr=%p len=%X command=", + info->host->host_no, '0' + SCpnt->target, + SCpnt->result, info->scsi.SCp.ptr, + info->scsi.SCp.this_residual); + print_command(SCpnt->cmnd); + } + } + +done: SCpnt->scsi_done(SCpnt); + return; + +request_sense: + memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd)); + SCpnt->cmnd[0] = REQUEST_SENSE; + SCpnt->cmnd[1] = SCpnt->lun << 5; + SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer); + SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); + SCpnt->SCp.buffer = NULL; + SCpnt->SCp.buffers_residual = 0; + SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer; + SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); + SCpnt->SCp.Message = 0; + SCpnt->SCp.Status = 0; + SCpnt->sc_data_direction = SCSI_DATA_READ; + SCpnt->use_sg = 0; + SCpnt->tag = 0; + SCpnt->host_scribble = (void *)fas216_rq_sns_done; + + /* + * Place this command into the high priority "request + * sense" slot. This will be the very next command + * executed, unless a target connects to us. + */ + if (info->reqSCpnt) + printk(KERN_WARNING "scsi%d.%c: loosing request command\n", + info->host->host_no, '0' + SCpnt->target); + info->reqSCpnt = SCpnt; +} + /* Function: void fas216_done(FAS216_Info *info, unsigned int result) - * Purpose : complete processing for command + * Purpose : complete processing for current command * Params : info - interface that completed * result - driver byte of result */ static void fas216_done(FAS216_Info *info, unsigned int result) { + void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int); Scsi_Cmnd *SCpnt; - fas216_checkmagic(info, "fas216_done"); + fas216_checkmagic(info); + + if (!info->SCpnt) + goto no_command; SCpnt = info->SCpnt; + info->SCpnt = NULL; + info->scsi.phase = PHASE_IDLE; + + if (!SCpnt->scsi_done) + goto no_done; if (info->scsi.aborting) { printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n", @@ -1800,66 +1957,39 @@ static void fas216_done(FAS216_Info *info, unsigned int result) info->scsi.aborting = 0; } - info->stats.fins += 1; - - if (SCpnt) { - info->scsi.phase = PHASE_IDLE; - info->SCpnt = NULL; - - SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | - info->scsi.SCp.Status; - - /* - * In theory, this should not happen, but just in case it does. - */ - if (info->scsi.SCp.ptr && - info->scsi.SCp.this_residual && - result == DID_OK) { - switch (SCpnt->cmnd[0]) { - case INQUIRY: - case START_STOP: - case READ_CAPACITY: - case TEST_UNIT_READY: - case MODE_SENSE: - case REQUEST_SENSE: - break; - - default: - switch (status_byte(SCpnt->result)) { - case CHECK_CONDITION: - case COMMAND_TERMINATED: - case BUSY: - case QUEUE_FULL: - case RESERVATION_CONFLICT: - break; - - default: - printk(KERN_ERR "scsi%d.H: incomplete data transfer " - "detected: res=%08X ptr=%p len=%X command=", - info->host->host_no, SCpnt->result, - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - print_command(SCpnt->cmnd); - } - } - } -#ifdef DEBUG_CONNECT - printk("scsi%d.%c: scsi command (%p) complete, result=%08X\n", - info->host->host_no, fas216_target(info), - SCpnt, SCpnt->result); -#endif - - if (!SCpnt->scsi_done) - panic("scsi%d.H: null scsi_done function in " - "fas216_done", info->host->host_no); + /* + * Sanity check the completion - if we have zero bytes left + * to transfer, we should not have a valid pointer. + */ + if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) { + printk("scsi%d.%c: zero bytes left to transfer, but " + "buffer pointer still valid: ptr=%p len=%08x command=", + info->host->host_no, '0' + SCpnt->target, + info->scsi.SCp.ptr, info->scsi.SCp.this_residual); + info->scsi.SCp.ptr = NULL; + print_command(SCpnt->cmnd); + } - clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); + /* + * Clear down this command as completed. If we need to request + * the sense information, fas216_kick will re-assert the busy + * status. + */ + clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns); - SCpnt->scsi_done(SCpnt); - } else - panic("scsi%d.H: null command in fas216_done", info->host->host_no); + fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble; + fn(info, SCpnt, result); if (info->scsi.irq != NO_IRQ) fas216_kick(info); + return; + +no_command: + panic("scsi%d.H: null command in fas216_done", + info->host->host_no); +no_done: + panic("scsi%d.H: null scsi_done function in fas216_done", + info->host->host_no); } /* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) @@ -1867,13 +1997,14 @@ static void fas216_done(FAS216_Info *info, unsigned int result) * Params : SCpnt - Command to queue * done - done function to call once command is complete * Returns : 0 - success, else error + * Notes : io_request_lock is held, interrupts are disabled. */ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - unsigned long flags; + int result; - fas216_checkmagic(info, "fas216_queue_command"); + fas216_checkmagic(info); #ifdef DEBUG_CONNECT printk("scsi%d.%c: received queuable command (%p) %02X\n", @@ -1882,7 +2013,7 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) #endif SCpnt->scsi_done = done; - SCpnt->host_scribble = NULL; + SCpnt->host_scribble = (void *)fas216_std_done; SCpnt->result = 0; SCpnt->SCp.Message = 0; SCpnt->SCp.Status = 0; @@ -1896,10 +2027,16 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address; SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; /* - * Calculate correct buffer length + * Calculate correct buffer length. Some commands + * come in with the wrong request_bufflen. */ for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) len += SCpnt->SCp.buffer[buf].length; + + if (SCpnt->request_bufflen != len) + printk(KERN_WARNING "scsi%d.%c: bad request buffer " + "length %d, should be %ld\n", info->host->host_no, + '0' + SCpnt->target, SCpnt->request_bufflen, len); SCpnt->request_bufflen = len; } else { SCpnt->SCp.buffer = NULL; @@ -1908,22 +2045,36 @@ int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) SCpnt->SCp.this_residual = SCpnt->request_bufflen; } + /* + * If the upper SCSI layers pass a buffer, but zero length, + * we aren't interested in the buffer pointer. + */ + if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { +#if 0 + printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " + "command ", info->host->host_no, '0' + SCpnt->target); + print_command(SCpnt->cmnd); +#endif + SCpnt->SCp.ptr = NULL; + } + info->stats.queues += 1; SCpnt->tag = 0; - /* add command into execute queue and let it complete under + /* + * Add command into execute queue and let it complete under * whatever scheme we're using. */ - if (!queue_add_cmd_ordered(&info->queues.issue, SCpnt)) { - SCpnt->result = DID_ERROR << 16; - done(SCpnt); - } - save_flags_cli(flags); - if (!info->SCpnt || info->scsi.disconnectable) + result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt); + + /* + * If we successfully added the command, + * kick the interface to get it moving. + */ + if (result == 0 && (!info->SCpnt || info->scsi.disconnectable)) fas216_kick(info); - restore_flags(flags); - return 0; + return result; } /* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt) @@ -1934,7 +2085,7 @@ static void fas216_internal_done(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - fas216_checkmagic(info, "fas216_internal_done"); + fas216_checkmagic(info); info->internal_done = 1; } @@ -1943,13 +2094,20 @@ static void fas216_internal_done(Scsi_Cmnd *SCpnt) * Purpose : queue a command for adapter to process. * Params : SCpnt - Command to queue * Returns : scsi result code + * Notes : io_request_lock is held, interrupts are disabled. */ int fas216_command(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - unsigned long flags; - fas216_checkmagic(info, "fas216_command"); + fas216_checkmagic(info); + + /* + * We should only be using this if we don't have an interrupt. + * Provide some "incentive" to use the queueing code. + */ + if (info->scsi.irq != NO_IRQ) + BUG(); info->internal_done = 0; fas216_queue_command(SCpnt, fas216_internal_done); @@ -1960,114 +2118,52 @@ int fas216_command(Scsi_Cmnd *SCpnt) * However, we must re-enable interrupts, or else we'll be * waiting forever. */ - save_flags(flags); - sti(); + spin_unlock_irq(&io_request_lock); while (!info->internal_done) { /* - * If we don't have an IRQ, then we must - * poll the card for it's interrupt, and - * use that to call this driver's interrupt - * routine. That way, we keep the command - * progressing. + * If we don't have an IRQ, then we must poll the card for + * it's interrupt, and use that to call this driver's + * interrupt routine. That way, we keep the command + * progressing. Maybe we can add some inteligence here + * and go to sleep if we know that the device is going + * to be some time (eg, disconnected). */ - if (info->scsi.irq == NO_IRQ) { - sti(); - while (!(inb(REG_STAT(info)) & STAT_INT)); - cli(); + if (inb(REG_STAT(info)) & STAT_INT) { + spin_lock_irq(&io_request_lock); fas216_intr(info->host); + spin_unlock_irq(&io_request_lock); } } - restore_flags(flags); + spin_lock_irq(&io_request_lock); return SCpnt->result; } -/* Prototype: void fas216_reportstatus(Scsi_Cmnd **SCpntp1, - * Scsi_Cmnd **SCpntp2, int result, int no_report) - * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 - * Params : SCpntp1 - pointer to command to return - * SCpntp2 - pointer to command to check - * result - result to pass back to mid-level done function - * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command - * structure as *SCpntp2. - */ -static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, - int result, int no_report) -{ - Scsi_Cmnd *SCpnt = *SCpntp1; - - if (SCpnt) { - *SCpntp1 = NULL; - - SCpnt->result = result; - if (!no_report || SCpnt != *SCpntp2) - SCpnt->scsi_done(SCpnt); - } - - if (SCpnt == *SCpntp2) - *SCpntp2 = NULL; -} - -/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort this command - * Params : SCpnt - command to abort - * Returns : FAILED if unable to abort - */ -int fas216_eh_abort(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the device associated with this command - * Params : SCpnt - command specifing device to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the complete bus associated with this command - * Params : SCpnt - command specifing bus to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the host associated with this command - * Params : SCpnt - command specifing host to reset - * Returns : FAILED if unable to reset - */ -int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) -{ - return FAILED; -} - -enum res_abort { res_not_running, res_success, res_success_clear, res_snooze }; +enum res_abort { + res_failed, /* unable to abort */ + res_success, /* command on issue queue */ + res_success_clear, /* command marked tgt/lun busy */ + res_hw_abort /* command on disconnected dev */ +}; /* * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) - * Purpose : abort a command on this host + * Purpose : decide how to abort a command * Params : SCpnt - command to abort * Returns : abort status */ static enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) { - enum res_abort res = res_not_running; + enum res_abort res = res_failed; if (queue_removecmd(&info->queues.issue, SCpnt)) { /* * The command was on the issue queue, and has not been * issued yet. We can remove the command from the queue, - * and acknowledge the abort. Neither the devices nor the + * and acknowledge the abort. Neither the device nor the * interface know about the command. */ printk("on issue queue "); @@ -2075,54 +2171,32 @@ fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) res = res_success; } else if (queue_removecmd(&info->queues.disconnected, SCpnt)) { /* - * The command was on the disconnected queue. Simply - * acknowledge the abort condition, and when the target - * reconnects, we will give it an ABORT message. The - * target should then disconnect, and we will clear - * the busylun bit. + * The command was on the disconnected queue. We must + * reconnect with the device if possible, and send it + * an abort message. */ printk("on disconnected queue "); - res = res_success; + res = res_hw_abort; } else if (info->SCpnt == SCpnt) { - unsigned long flags; - printk("executing "); - save_flags(flags); - cli(); switch (info->scsi.phase) { /* * If the interface is idle, and the command is 'disconnectable', - * then it is the same as on the disconnected queue. We simply - * remove all traces of the command. When the target reconnects, - * we will give it an ABORT message since the command could not - * be found. When the target finally disconnects, we will clear - * the busylun bit. + * then it is the same as on the disconnected queue. */ case PHASE_IDLE: if (info->scsi.disconnectable) { info->scsi.disconnectable = 0; info->SCpnt = NULL; - res = res_success; + res = res_hw_abort; } break; - /* - * If the command has connected and done nothing futher, - * simply force a disconnect. We also need to clear the - * busylun bit. - */ - case PHASE_SELECTION: -// info->SCpnt = NULL; -// res = res_success_clear; -// break; - default: - res = res_snooze; break; } - restore_flags(flags); } else if (info->origSCpnt == SCpnt) { /* * The command will be executed next, but a command @@ -2139,17 +2213,18 @@ fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) return res; } -/* Function: int fas216_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort a command if something horrible happens. - * Params : SCpnt - Command that is believed to be causing a problem. - * Returns : one of SCSI_ABORT_ macros. +/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) + * Purpose : abort this command + * Params : SCpnt - command to abort + * Returns : FAILED if unable to abort + * Notes : io_request_lock is taken, and irqs are disabled */ -int fas216_abort(Scsi_Cmnd *SCpnt) +int fas216_eh_abort(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - int result = SCSI_ABORT_SNOOZE; + int result = FAILED; - fas216_checkmagic(info, "fas216_abort"); + fas216_checkmagic(info); info->stats.aborts += 1; @@ -2176,29 +2251,23 @@ int fas216_abort(Scsi_Cmnd *SCpnt) */ case res_success: printk("success\n"); - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done(SCpnt); - result = SCSI_ABORT_SUCCESS; + result = SUCCESS; break; /* - * We did find the command, but unfortunately we couldn't - * unhook it from ourselves. Wait some more, and if it - * still doesn't complete, reset the interface. + * We need to reconnect to the target and send it an + * ABORT or ABORT_TAG message. We can only do this + * if the bus is free. */ - case res_snooze: - printk("snooze\n"); - result = SCSI_ABORT_SNOOZE; - break; + case res_hw_abort: + /* - * The command could not be found (either because it completed, - * or it got dropped. + * We are unable to abort the command for some reason. */ default: - case res_not_running: - result = SCSI_ABORT_SNOOZE; - printk("not running\n"); + case res_failed: + printk("failed\n"); break; } @@ -2214,7 +2283,7 @@ static void fas216_reset_state(FAS216_Info *info) neg_t sync_state, wide_state; int i; - fas216_checkmagic(info, "fas216_reset_state"); + fas216_checkmagic(info); /* * Clear out all stale info in our state structure @@ -2257,6 +2326,80 @@ static void fas216_reset_state(FAS216_Info *info) info->device[i].sof = 0; info->device[i].wide_xfer = 0; } + + /* + * Drain all commands on disconnected queue + */ + while (queue_remove(&info->queues.disconnected) != NULL); + + /* + * Remove executing commands. + */ + info->SCpnt = NULL; + info->reqSCpnt = NULL; + info->origSCpnt = NULL; +} + +/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the device associated with this command + * Params : SCpnt - command specifing device to reset + * Returns : FAILED if unable to reset + */ +int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) +{ + FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + + printk("scsi%d.%c: "__FUNCTION__": called\n", + info->host->host_no, '0' + SCpnt->target); + return FAILED; +} + +/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the bus associated with the command + * Params : SCpnt - command specifing bus to reset + * Returns : FAILED if unable to reset + * Notes : io_request_lock is taken, and irqs are disabled + */ +int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) +{ + FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; + int result = FAILED; + + fas216_checkmagic(info); + + info->stats.bus_resets += 1; + + printk("scsi%d.%c: "__FUNCTION__": resetting bus\n", + info->host->host_no, '0' + SCpnt->target); + + /* + * Attempt to stop all activity on this interface. + */ + outb(info->scsi.cfg[2], REG_CNTL3(info)); + fas216_stoptransfer(info); + + /* + * Clear any pending interrupts + */ + while (inb(REG_STAT(info)) & STAT_INT) + inb(REG_INST(info)); + + /* + * Reset the SCSI bus + */ + outb(CMD_RESETSCSI, REG_CMD(info)); + udelay(5); + + /* + * Clear reset interrupt + */ + if (inb(REG_STAT(info)) & STAT_INT && + inb(REG_INST(info)) & INST_BUSRESET) + result = SUCCESS; + + fas216_reset_state(info); + + return result; } /* Function: void fas216_init_chip(FAS216_Info *info) @@ -2265,8 +2408,6 @@ static void fas216_reset_state(FAS216_Info *info) */ static void fas216_init_chip(FAS216_Info *info) { - fas216_checkmagic(info, "fas216_init_chip"); - outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info)); outb(info->scsi.cfg[0], REG_CNTL1(info)); outb(info->scsi.cfg[1], REG_CNTL2(info)); @@ -2277,100 +2418,144 @@ static void fas216_init_chip(FAS216_Info *info) outb(info->scsi.cfg[0], REG_CNTL1(info)); } -/* Function: int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) - * Purpose : resets the adapter if something horrible happens. - * Params : SCpnt - Command that is believed to be causing a problem. - * reset_flags - flags indicating reset type that is believed - * to be required. - * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET - * macros. +/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) + * Purpose : Reset the host associated with this command + * Params : SCpnt - command specifing host to reset + * Returns : FAILED if unable to reset + * Notes : io_request_lock is taken, and irqs are disabled */ -int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) +int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) { FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata; - Scsi_Cmnd *SCptr; - int result = 0; - int synchronous = reset_flags & SCSI_RESET_SYNCHRONOUS; - fas216_checkmagic(info, "fas216_reset"); + fas216_checkmagic(info); + + printk("scsi%d.%c: "__FUNCTION__": resetting host\n", + info->host->host_no, '0' + SCpnt->target); /* - * Validate that command is actually on one of our queues if we're doing - * an asynchronous reset + * Reset the SCSI chip. */ - if (reset_flags & SCSI_RESET_ASYNCHRONOUS && - SCpnt && - info->SCpnt != SCpnt && - info->origSCpnt != SCpnt && - !queue_cmdonqueue(&info->queues.disconnected, SCpnt) && - !queue_cmdonqueue(&info->queues.issue, SCpnt)) { - printk("scsi%d: fas216_reset: asynchronous reset for unknown command\n", - info->host->host_no); - return SCSI_RESET_NOT_RUNNING; - } + outb(CMD_RESETCHIP, REG_CMD(info)); - info->stats.resets += 1; + /* + * Ugly ugly ugly! + * We need to release the io_request_lock and enable + * IRQs if we sleep, but we must relock and disable + * IRQs after the sleep. + */ + spin_unlock_irq(&io_request_lock); + scsi_sleep(5); + spin_lock_irq(&io_request_lock); - print_debug_list(); - printk(KERN_WARNING "scsi%d: reset ", info->host->host_no); - if (SCpnt) - printk("for target %d ", SCpnt->target); + /* + * Release the SCSI reset. + */ + outb(CMD_NOP, REG_CMD(info)); - printk("\n"); + fas216_init_chip(info); - outb(info->scsi.cfg[3], REG_CNTL3(info)); + return SUCCESS; +} - fas216_stoptransfer(info); +#define TYPE_UNKNOWN 0 +#define TYPE_NCR53C90 1 +#define TYPE_NCR53C90A 2 +#define TYPE_NCR53C9x 3 +#define TYPE_Am53CF94 4 +#define TYPE_EmFAS216 5 +#define TYPE_QLFAS216 6 + +static char *chip_types[] = { + "unknown", + "NS NCR53C90", + "NS NCR53C90A", + "NS NCR53C9x", + "AMD Am53CF94", + "Emulex FAS216", + "QLogic FAS216" +}; + +static int fas216_detect_type(FAS216_Info *info) +{ + int family, rev; - switch (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) { - case SCSI_RESET_SUGGEST_BUS_RESET: - outb(CMD_RESETSCSI, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - result |= SCSI_RESET_BUS_RESET; - break; + /* + * Reset the chip. + */ + outb(CMD_RESETCHIP, REG_CMD(info)); + udelay(50); + outb(CMD_NOP, REG_CMD(info)); - case SCSI_RESET_SUGGEST_HOST_RESET: - outb(CMD_RESETCHIP, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - result |= SCSI_RESET_HOST_RESET; - break; + /* + * Check to see if control reg 2 is present. + */ + outb(0, REG_CNTL3(info)); + outb(CNTL2_S2FE, REG_CNTL2(info)); - default: - outb(CMD_RESETCHIP, REG_CMD(info)); - outb(CMD_NOP, REG_CMD(info)); - outb(CMD_RESETSCSI, REG_CMD(info)); - result |= SCSI_RESET_HOST_RESET | SCSI_RESET_BUS_RESET; - break; - } + /* + * If we are unable to read back control reg 2 + * correctly, it is not present, and we have a + * NCR53C90. + */ + if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) + return TYPE_NCR53C90; - udelay(300); - fas216_reset_state(info); - fas216_init_chip(info); + /* + * Now, check control register 3 + */ + outb(0, REG_CNTL2(info)); + outb(0, REG_CNTL3(info)); + outb(5, REG_CNTL3(info)); /* - * Signal all commands in progress have been reset + * If we are unable to read the register back + * correctly, we have a NCR53C90A */ - fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16, synchronous); + if (inb(REG_CNTL3(info)) != 5) + return TYPE_NCR53C90A; - while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL) - fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16, synchronous); + /* + * Now read the ID from the chip. + */ + outb(0, REG_CNTL3(info)); - if (SCpnt) { - /* - * Command not found on disconnected queue, nor currently - * executing command - check pending commands - */ - if (info->origSCpnt == SCpnt) - info->origSCpnt = NULL; + outb(CNTL3_ADIDCHK, REG_CNTL3(info)); + outb(0, REG_CNTL3(info)); - queue_removecmd(&info->queues.issue, SCpnt); + outb(CMD_RESETCHIP, REG_CMD(info)); + udelay(5); + outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info)); - SCpnt->result = DID_RESET << 16; - if (!synchronous) - SCpnt->scsi_done(SCpnt); - } + outb(CNTL2_ENF, REG_CNTL2(info)); + outb(CMD_RESETCHIP, REG_CMD(info)); + udelay(5); + outb(CMD_NOP, REG_CMD(info)); + + rev = inb(REG1_ID(info)); + family = rev >> 3; + rev &= 7; + + switch (family) { + case 0x01: + if (rev == 4) + return TYPE_Am53CF94; + break; + + case 0x02: + switch (rev) { + case 2: + return TYPE_EmFAS216; + case 3: + return TYPE_QLFAS216; + } + break; - return result | SCSI_RESET_SUCCESS; + default: + break; + } + printk("family %x rev %x\n", family, rev); + return TYPE_NCR53C9x; } /* Function: int fas216_init(struct Scsi_Host *instance) @@ -2381,19 +2566,14 @@ int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) int fas216_init(struct Scsi_Host *instance) { FAS216_Info *info = (FAS216_Info *)instance->hostdata; - unsigned long flags; - int target_jiffies; + int type; info->magic_start = MAGIC; - info->magic_end = MAGIC; - - info->host = instance; + info->magic_end = MAGIC; + info->host = instance; info->scsi.cfg[0] = instance->this_id; info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB; - info->scsi.type = "unknown"; - info->SCpnt = NULL; - fas216_reset_state(info); memset(&info->stats, 0, sizeof(info->stats)); @@ -2407,64 +2587,36 @@ int fas216_init(struct Scsi_Host *instance) return 1; } - outb(CMD_RESETCHIP, REG_CMD(info)); - - outb(0, REG_CNTL3(info)); - outb(CNTL2_S2FE, REG_CNTL2(info)); - - if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) { - info->scsi.type = "NCR53C90"; - } else { - outb(0, REG_CNTL2(info)); - outb(0, REG_CNTL3(info)); - outb(5, REG_CNTL3(info)); - if (inb(REG_CNTL3(info)) != 5) { - info->scsi.type = "NCR53C90A"; - } else { - outb(0, REG_CNTL3(info)); - info->scsi.type = "NCR53C9x"; - } - } - - - outb(CNTL3_ADIDCHK, REG_CNTL3(info)); - outb(0, REG_CNTL3(info)); - - outb(CMD_RESETCHIP, REG_CMD(info)); - outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info)); - outb(CNTL2_ENF, REG_CNTL2(info)); - outb(CMD_RESETCHIP, REG_CMD(info)); - switch (inb(REG1_ID(info))) { - case 12: - info->scsi.type = "Am53CF94"; - break; - default: - break; - } + fas216_reset_state(info); + type = fas216_detect_type(info); + info->scsi.type = chip_types[type]; udelay(300); - /* now for the real initialisation */ + + /* + * Initialise the chip correctly. + */ fas216_init_chip(info); + /* + * Reset the SCSI bus. We don't want to see + * the resulting reset interrupt, so mask it + * out. + */ outb(info->scsi.cfg[0] | CNTL1_DISR, REG_CNTL1(info)); outb(CMD_RESETSCSI, REG_CMD(info)); - /* scsi standard says 250ms */ - target_jiffies = jiffies + (25 * HZ) / 100; - save_flags(flags); - sti(); - - while (time_before(jiffies, target_jiffies)) barrier(); - - restore_flags(flags); + /* + * scsi standard says wait 250ms + */ + spin_unlock_irq(&io_request_lock); + scsi_sleep(5); + spin_lock_irq(&io_request_lock); outb(info->scsi.cfg[0], REG_CNTL1(info)); inb(REG_INST(info)); - /* now for the real initialisation */ - fas216_init_chip(info); - - fas216_checkmagic(info, "fas216_init"); + fas216_checkmagic(info); return 0; } @@ -2479,7 +2631,7 @@ int fas216_release(struct Scsi_Host *instance) { FAS216_Info *info = (FAS216_Info *)instance->hostdata; - fas216_checkmagic(info, "fas216_release"); + fas216_checkmagic(info); outb(CMD_RESETCHIP, REG_CMD(info)); queue_free(&info->queues.disconnected); @@ -2488,19 +2640,67 @@ int fas216_release(struct Scsi_Host *instance) return 0; } +/* + * Function: int fas216_info(FAS216_Info *info, char *buffer) + * Purpose : generate a string containing information about this + * host. + * Params : info - FAS216 host information + * buffer - string buffer to build string + * Returns : size of built string + */ +int fas216_info(FAS216_Info *info, char *buffer) +{ + char *p = buffer; + + p += sprintf(p, "(%s) at port 0x%08lX ", + info->scsi.type, info->host->io_port); + + if (info->host->irq != NO_IRQ) + p += sprintf(p, "irq %d ", info->host->irq); + else + p += sprintf(p, "no irq "); + + if (info->host->dma_channel != NO_DMA) + p += sprintf(p, "dma %d ", info->host->dma_channel); + else + p += sprintf(p, "no dma "); + + return p - buffer; +} + +int fas216_print_host(FAS216_Info *info, char *buffer) +{ + + return sprintf(buffer, + "\n" + "Chip : %s\n" + " Address: 0x%08lX\n" + " IRQ : %d\n" + " DMA : %d\n", + info->scsi.type, info->host->io_port, + info->host->irq, info->host->dma_channel); +} + int fas216_print_stats(FAS216_Info *info, char *buffer) { return sprintf(buffer, - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n", + "\n" + "Command Statistics:\n" + " Queued : %u\n" + " Issued : %u\n" + " Completed : %u\n" + " Reads : %u\n" + " Writes : %u\n" + " Others : %u\n" + " Disconnects: %u\n" + " Aborts : %u\n" + " Bus resets : %u\n" + " Host resets: %u\n", info->stats.queues, info->stats.removes, info->stats.fins, info->stats.reads, info->stats.writes, info->stats.miscs, info->stats.disconnects, info->stats.aborts, - info->stats.resets); + info->stats.bus_resets, info->stats.host_resets); } int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) @@ -2531,9 +2731,8 @@ int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) return p - buffer; } +EXPORT_SYMBOL(fas216_info); EXPORT_SYMBOL(fas216_init); -EXPORT_SYMBOL(fas216_abort); -EXPORT_SYMBOL(fas216_reset); EXPORT_SYMBOL(fas216_queue_command); EXPORT_SYMBOL(fas216_command); EXPORT_SYMBOL(fas216_intr); @@ -2542,6 +2741,7 @@ EXPORT_SYMBOL(fas216_eh_abort); EXPORT_SYMBOL(fas216_eh_device_reset); EXPORT_SYMBOL(fas216_eh_bus_reset); EXPORT_SYMBOL(fas216_eh_host_reset); +EXPORT_SYMBOL(fas216_print_host); EXPORT_SYMBOL(fas216_print_stats); EXPORT_SYMBOL(fas216_print_device); diff --git a/drivers/acorn/scsi/fas216.h b/drivers/acorn/scsi/fas216.h index dede53ba9763..4381888fd29d 100644 --- a/drivers/acorn/scsi/fas216.h +++ b/drivers/acorn/scsi/fas216.h @@ -1,11 +1,7 @@ /* * FAS216 generic driver * - * Copyright (C) 1997-1998 Russell King - * - * NOTE! This file should be viewed using a console with - * >100 character width (since it uses 8-space tabs) - * (it used to fit in 80-columns with 4 space) + * Copyright (C) 1997-2000 Russell King */ #ifndef FAS216_H #define FAS216_H @@ -215,6 +211,7 @@ typedef struct { struct Scsi_Host *host; /* host */ Scsi_Cmnd *SCpnt; /* currently processing command */ Scsi_Cmnd *origSCpnt; /* original connecting command */ + Scsi_Cmnd *reqSCpnt; /* request sense command */ /* driver information */ struct { @@ -254,7 +251,8 @@ typedef struct { unsigned int miscs; unsigned int disconnects; unsigned int aborts; - unsigned int resets; + unsigned int bus_resets; + unsigned int host_resets; } stats; /* configuration information */ @@ -350,6 +348,8 @@ extern void fas216_intr (struct Scsi_Host *instance); */ extern int fas216_release (struct Scsi_Host *instance); +extern int fas216_info(FAS216_Info *info, char *buffer); +extern int fas216_print_host(FAS216_Info *info, char *buffer); extern int fas216_print_stats(FAS216_Info *info, char *buffer); extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer); diff --git a/drivers/acorn/scsi/msgqueue.h b/drivers/acorn/scsi/msgqueue.h index 8016dcf4e31f..25fa2796f74c 100644 --- a/drivers/acorn/scsi/msgqueue.h +++ b/drivers/acorn/scsi/msgqueue.h @@ -1,7 +1,7 @@ /* * msgqueue.h: message queue handling * - * (c) 1997 Russell King + * Copyright (C) 1997 Russell King */ #ifndef MSGQUEUE_H #define MSGQUEUE_H diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c index 59d83dc1a6a9..cd07f7da01fb 100644 --- a/drivers/acorn/scsi/powertec.c +++ b/drivers/acorn/scsi/powertec.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/drivers/scsi/powertec.c * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and @@ -13,6 +13,7 @@ * 15-04-1998 RMK Only do PIO if FAS216 will allow it. * 02-05-1998 RMK Moved DMA sg list into per-interface structure. * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h + * 02-04-2000 RMK Updated for new error handling code. */ #include @@ -67,7 +68,7 @@ */ #define VER_MAJOR 0 #define VER_MINOR 0 -#define VER_PATCH 2 +#define VER_PATCH 5 MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("Powertec SCSI driver"); @@ -345,25 +346,11 @@ const char *powertecscsi_info(struct Scsi_Host *host) static char string[100], *p; p = string; - p += sprintf(string, "%s at port %lX ", - host->hostt->name, host->io_port); - - if (host->irq != NO_IRQ) - p += sprintf(p, "irq %d ", host->irq); - else - p += sprintf(p, "NO IRQ "); - - if (host->dma_channel != NO_DMA) - p += sprintf(p, "dma %d ", host->dma_channel); - else - p += sprintf(p, "NO DMA "); - - p += sprintf(p, "v%d.%d.%d scsi %s", + p += sprintf(p, "%s ", host->hostt->name); + p += fas216_info(&info->info, p); + p += sprintf(p, "v%d.%d.%d terminators o%s", VER_MAJOR, VER_MINOR, VER_PATCH, - info->info.scsi.type); - - p += sprintf(p, " terminators %s", - info->control.terms ? "on" : "off"); + info->control.terms ? "n" : "ff"); return string; } @@ -403,13 +390,13 @@ powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) * int length, int host_no, int inout) * Purpose : Return information about the driver to a user process accessing * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer + * Params : buffer - a buffer to write information to + * start - a pointer into this buffer set by this routine to the start + * of the required information. + * offset - offset into information that we have read upto. + * length - length of buffer * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. + * inout - 0 for reading, 1 for writing. * Returns : length of data written to buffer. */ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, @@ -437,16 +424,14 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset, pos = sprintf(buffer, "PowerTec SCSI driver version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); - pos += sprintf(buffer + pos, - "Address: %08lX IRQ : %d DMA : %d\n" - "FAS : %-10s TERM: %-3s\n\n" - "Statistics:\n", - host->io_port, host->irq, host->dma_channel, - info->info.scsi.type, info->control.terms ? "on" : "off"); + + pos += fas216_print_host(&info->info, buffer + pos); + pos += sprintf(buffer + pos, "Term : o%s\n", + info->control.terms ? "n" : "ff"); pos += fas216_print_stats(&info->info, buffer + pos); - pos += sprintf (buffer+pos, "\nAttached devices:\n"); + pos += sprintf(buffer+pos, "\nAttached devices:\n"); for (scd = host->host_queue; scd; scd = scd->next) { pos += fas216_print_device(&info->info, scd, buffer + pos); diff --git a/drivers/acorn/scsi/powertec.h b/drivers/acorn/scsi/powertec.h index bf9a8afc815e..4b0387b89910 100644 --- a/drivers/acorn/scsi/powertec.h +++ b/drivers/acorn/scsi/powertec.h @@ -1,7 +1,7 @@ /* * PowerTec SCSI driver * - * Copyright (C) 1997-1998 Russell King + * Copyright (C) 1997-2000 Russell King */ #ifndef POWERTECSCSI_H #define POWERTECSCSI_H @@ -38,28 +38,25 @@ extern int powertecscsi_proc_info (char *buffer, char **start, off_t offset, #include "fas216.h" -#define POWERTECSCSI { \ -proc_info: powertecscsi_proc_info, \ -name: "PowerTec SCSI", \ -detect: powertecscsi_detect, /* detect */ \ -release: powertecscsi_release, /* release */ \ -info: powertecscsi_info, /* info */ \ -command: fas216_command, /* command */ \ -queuecommand: fas216_queue_command, /* queuecommand */ \ -abort: fas216_abort, /* abort */ \ -reset: fas216_reset, /* reset */ \ -bios_param: scsicam_bios_param, /* biosparam */ \ -can_queue: CAN_QUEUE, /* can queue */ \ -this_id: SCSI_ID, /* scsi host id */ \ -sg_tablesize: SG_ALL, /* sg_tablesize */ \ -cmd_per_lun: CMD_PER_LUN, /* cmd per lun */ \ -use_clustering: ENABLE_CLUSTERING, \ -eh_strategy_handler: NULL, \ -eh_host_reset_handler: fas216_eh_host_reset, \ -eh_bus_reset_handler: fas216_eh_bus_reset, \ -eh_device_reset_handler: fas216_eh_device_reset, \ -eh_abort_handler: fas216_eh_abort, \ -use_new_eh_code: 0 \ +#define POWERTECSCSI { \ +proc_info: powertecscsi_proc_info, \ +name: "PowerTec SCSI", \ +detect: powertecscsi_detect, \ +release: powertecscsi_release, \ +info: powertecscsi_info, \ +bios_param: scsicam_bios_param, \ +can_queue: CAN_QUEUE, \ +this_id: SCSI_ID, \ +sg_tablesize: SG_ALL, \ +cmd_per_lun: CMD_PER_LUN, \ +use_clustering: ENABLE_CLUSTERING, \ +command: fas216_command, \ +queuecommand: fas216_queue_command, \ +eh_host_reset_handler: fas216_eh_host_reset, \ +eh_bus_reset_handler: fas216_eh_bus_reset, \ +eh_device_reset_handler: fas216_eh_device_reset, \ +eh_abort_handler: fas216_eh_abort, \ +use_new_eh_code: 1 \ } #ifndef HOSTS_C diff --git a/drivers/acorn/scsi/queue.h b/drivers/acorn/scsi/queue.h index f39816ccbb61..961a3f268902 100644 --- a/drivers/acorn/scsi/queue.h +++ b/drivers/acorn/scsi/queue.h @@ -1,7 +1,7 @@ /* * queue.h: queue handling * - * (c) 1997 Russell King + * Copyright (C) 1997 Russell King */ #ifndef QUEUE_H #define QUEUE_H diff --git a/drivers/block/xd.c b/drivers/block/xd.c index fde487ecd7f2..65d87930d858 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -1059,7 +1059,7 @@ static void __init xd_override_init_drive (u_char drive) } /* xd_setup: initialise controler from command line parameters */ -void __init xd_setup (char *command,int *integers) +void __init do_xd_setup (int *integers) { switch (integers[0]) { case 4: if (integers[4] < 0) @@ -1079,21 +1079,6 @@ void __init xd_setup (char *command,int *integers) xd_maxsectors = 0x01; } -#ifndef MODULE -/* xd_manual_geo_init: initialise drive geometry from command line parameters - (used only for WD drives) */ -void __init xd_manual_geo_init (char *command,int *integers) -{ - int i; - if (integers[0]%3 != 0) { - printk("xd: incorrect number of parameters for xd_geo\n"); - return; - } - for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++) - xd_geo[i] = integers[i+1]; -} -#endif /* MODULE */ - /* xd_setparam: set the drive characteristics */ static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc) { @@ -1149,7 +1134,7 @@ int init_module(void) if(((xd[i] = xd[i-1]) >= 0) && !count) count = i; if((xd[0] = count)) - xd_setup(NULL, xd); + do_xd_setup(xd); if (error = xd_init()) return error; @@ -1191,6 +1176,30 @@ void cleanup_module(void) } #else +static int __init xd_setup (char *str) +{ + int ints[5]; + get_options (str, ARRAY_SIZE (ints), ints); + do_xd_setup (ints); + return 1; +} + +/* xd_manual_geo_init: initialise drive geometry from command line parameters + (used only for WD drives) */ +static int __init xd_manual_geo_init (char *str) +{ + int i, integers[1 + 3*XD_MAXDRIVES]; + + get_options (str, ARRAY_SIZE (ints), ints); + if (integers[0]%3 != 0) { + printk("xd: incorrect number of parameters for xd_geo\n"); + return 1; + } + for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++) + xd_geo[i] = integers[i+1]; + return 1; +} + __setup ("xd=", xd_setup); __setup ("xd_geo=", xd_manual_geo_init); diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 87658b24c824..d6e0a55bd278 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -110,6 +110,7 @@ bool 'Watchdog Timer Support' CONFIG_WATCHDOG if [ "$CONFIG_WATCHDOG" != "n" ]; then bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT tristate ' WDT Watchdog timer' CONFIG_WDT + tristate ' WDT PCI Watchdog timer' CONFIG_WDTPCI if [ "$CONFIG_WDT" != "n" ]; then bool ' WDT501 features' CONFIG_WDT_501 if [ "$CONFIG_WDT_501" = "y" ]; then diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 26fae2ed2c12..150472a2fba4 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -171,6 +171,7 @@ obj-$(CONFIG_ATARIMOUSE) += atarimouse.o obj-$(CONFIG_ADBMOUSE) += adbmouse.o busmouse.o obj-$(CONFIG_PC110_PAD) += pc110pad.o obj-$(CONFIG_WDT) += wdt.o +obj-$(CONFIG_WDTPCI) += wdt_pci.o obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o ifeq ($(CONFIG_PPC),) diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 59adf47bc88a..a3dfdfb042a6 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -490,7 +490,8 @@ static int init_bttv_i2c(struct bttv *btv) bttv_bit_setscl(btv,1); bttv_bit_setsda(btv,1); - return i2c_bit_add_bus(&btv->i2c_adap); + btv->i2c_ok = i2c_bit_add_bus(&btv->i2c_adap); + return btv->i2c_ok; } /* read I2C */ @@ -498,6 +499,8 @@ static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { unsigned char buffer = 0; + if (0 != btv->i2c_ok) + return -1; if (verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", btv->nr,probe_for,addr); @@ -523,11 +526,13 @@ static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char buffer[2]; int bytes = both ? 2 : 1; + if (0 != btv->i2c_ok) + return -1; btv->i2c_client.addr = addr >> 1; buffer[0] = b1; buffer[1] = b2; if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) - return -1; + return -1; return 0; } @@ -702,42 +707,25 @@ static void init_PXC200(struct bttv *btv) /* ----------------------------------------------------------------------- */ -/* for some vendors it is just the PCI ID */ -static struct VENDOR { - int id; - char *name; -} vendors[] = { - { 0x0001, "ATI Technologies Inc" }, - { 0x10b4, "STB Systems Inc" }, - { 0x1118, "Terratec" }, - { 0x13eb, "Hauppauge Computer Works Inc" }, - { 0x1461, "Avermedia" }, - { 0x1850, "Chronos" }, - { 0x1852, "Typhoon" }, - { 0x3000, "Askey" }, - { 0x3002, "Askey" }, - { 0x6606, "Leadtek" }, - { -1, NULL } -}; - static struct CARD { - int vid; - int id; + unsigned id; int cardnr; char *name; } cards[] = { - { 0x0001, 0x1002, BTTV_HAUPPAUGE878, "TV Wonder" }, - { 0x10b4, 0x2636, BTTV_HAUPPAUGE878, "???" }, - { 0x1118, 0x153b, BTTV_TERRATVALUE, "TV Value" }, - { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV" }, - { 0x1461, 0x0002, BTTV_AVERMEDIA98, "TVCapture 98" }, - { 0x1850, 0x1851, BTTV_CHRONOS_VS2, "Video Shuttle II" }, - { 0x1852, 0x1852, BTTV_TYPHOON_TVIEW, "TView TV/FM Tuner" }, - { 0x3000, 0x14ff, BTTV_MAGICTVIEW061, "TView 99" }, - { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" }, - { 0x3002, 0x14ff, BTTV_PHOEBE_TVMAS, "TV Master" }, - { 0x6606, 0x217d, BTTV_WINFAST2000, "WinFast TV 2000" }, - { -1, -1, -1, NULL } + { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, + { 0x00031461, BTTV_AVERMEDIA98, "AVerMedia TVPhone98" }, + { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, + { 0x1118153b, BTTV_TERRATVALUE, "Terratec TV Value" }, + { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, + { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, + { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" }, + { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, + { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, + { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, + { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" }, + { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, + { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, + { 0, -1, NULL } }; struct tvcard @@ -869,7 +857,7 @@ static struct tvcard tvcards[] = 1,1,1,1,0 }, { "FlyVideo 98", 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, - { 0, 0x8dff00, 0x800, 0x400, 0x8dff00, 0 },0, + { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0, 1,1,1,1,0 }, { "iProTV", 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0, @@ -893,9 +881,12 @@ static struct tvcard tvcards[] = { "Typhoon TView TV/FM Tuner", 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0, 1,1,1,1,0 }, - { "PixelView PlayTV pro", - 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, - { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 } + { "PixelView PlayTV pro", + 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, + { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 }, + { "TView99 CPH063", + 3, 1, 0, 2, 0x551e00, { 2, 0, 1, 1}, + { 0x551400, 0x551200, 0, 0, 0x551200 }, 0,1,1,1,1,0 }, }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) @@ -920,39 +911,35 @@ dump_eeprom(struct bttv *btv,int addr) static int idcard_eeprom(struct bttv *btv) { - int i,id1,id2,n1,n2; + unsigned id; + int i,n; - id1 = (eeprom_data[254] << 8) | (eeprom_data[255]); - id2 = (eeprom_data[252] << 8) | (eeprom_data[253]); - if (id1 == 0 || id1 == 0xffff || - id2 == 0 || id2 == 0xffff) - return -1; + id = (eeprom_data[252] << 24) | + (eeprom_data[253] << 16) | + (eeprom_data[254] << 8) | + (eeprom_data[255]); + if (id == 0 || id == 0xffffffff) + return -1; /* look for the card */ - n1 = -1; n2 = -1; - for (i = 0; vendors[i].id != -1; i++) - if (vendors[i].id == id2) - n2 = i; - for (i = 0; cards[i].id != -1; i++) - if (cards[i].id == id1 && - cards[i].vid == id2) - n1 = i; - - if (n1 != -1 && n2 != -1) { + for (n = -1, i = 0; cards[i].id != 0; i++) + if (cards[i].id == id) + n = i; + + if (n != -1) { /* found it */ - printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n", - btv->nr,cards[n1].name,id1,vendors[n2].name,id2); + printk(KERN_INFO "bttv%d: id: %s (0x%08x)\n", + btv->nr,cards[n].name,id); if (verbose) printk(KERN_INFO "bttv%d: => card=%d (%s)\n", - btv->nr,cards[n1].cardnr, - tvcards[cards[n1].cardnr].name); - return cards[n1].cardnr; + btv->nr,cards[n].cardnr, + tvcards[cards[n].cardnr].name); + return cards[n].cardnr; } else { /* 404 */ - printk(KERN_INFO "bttv%d: id: %s (0x%04x), vendor: %s (0x%04x)\n", - btv->nr, "unknown", id1, - (n2 != -1) ? vendors[n2].name : "unknown", id2); - printk(KERN_INFO "please mail id + vendor, board name and " + printk(KERN_INFO "bttv%d: id: unknown (0x%08x)\n", + btv->nr, id); + printk(KERN_INFO "please mail id, board name and " "the correct card= insmod option to " "kraxel@goldbach.in-berlin.de\n"); return -1; @@ -1670,30 +1657,48 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr) * www.brooktree.com - nicely done those folks. */ -/* set geometry for even/odd frames - just if you are wondering: - handling of even and odd frames will be separated, e.g. for grabbing - the even ones as RGB into videomem and the others as YUV in main memory for - compressing and sending to the video conferencing partner. - -*/ -static inline void bt848_set_eogeo(struct bttv *btv, int odd, u8 vtc, - u16 hscale, u16 vscale, - u16 hactive, u16 vactive, - u16 hdelay, u16 vdelay, - u8 crop) +static inline void bt848_set_eogeo(struct bttv *btv, struct tvnorm *tvn, + int odd, int width, int height) { + u16 vscale, hscale; + u32 xsf, sr; + u16 hdelay; + u8 crop, vtc; + int inter = (height>tvn->sheight/2) ? 0 : 1; int off = odd ? 0x80 : 0x00; - + + xsf = (width*tvn->scaledtwidth)/tvn->swidth; + hscale = ((tvn->totalwidth*4096UL)/xsf-4096); + hdelay = tvn->hdelayx1; + hdelay = (hdelay*width)/tvn->swidth; + hdelay &= 0x3fe; + sr=((tvn->sheight>>inter)*512)/height-512; + vscale=(0x10000UL-sr)&0x1fff; + crop=((width>>8)&0x03)|((hdelay>>6)&0x0c)| + ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); + vscale |= inter ? (BT848_VSCALE_INT<<8) : 0; + +#if 0 + /* Some people say interpolation looks bad ... */ + vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + if (width < 767) + btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); + else + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); +#else + vtc = 0; + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); +#endif + btwrite(vtc, BT848_E_VTC+off); btwrite(hscale>>8, BT848_E_HSCALE_HI+off); btwrite(hscale&0xff, BT848_E_HSCALE_LO+off); btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); btwrite(vscale&0xff, BT848_E_VSCALE_LO+off); - btwrite(hactive&0xff, BT848_E_HACTIVE_LO+off); + btwrite(width&0xff, BT848_E_HACTIVE_LO+off); btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off); - btwrite(vactive&0xff, BT848_E_VACTIVE_LO+off); - btwrite(vdelay&0xff, BT848_E_VDELAY_LO+off); + btwrite(tvn->sheight&0xff, BT848_E_VACTIVE_LO+off); + btwrite(tvn->vdelay&0xff, BT848_E_VDELAY_LO+off); btwrite(crop, BT848_E_CROP+off); } @@ -1701,14 +1706,8 @@ static inline void bt848_set_eogeo(struct bttv *btv, int odd, u8 vtc, static void bt848_set_geo(struct bttv *btv, int no_irq_context) { - u16 vscale, hscale; - u32 xsf, sr; u16 ewidth, eheight, owidth, oheight; u16 format, bswap; - u16 hdelay; - u16 hactive; - u16 inter; - u8 crop, vtc; struct tvnorm *tvn; unsigned long flags; @@ -1727,10 +1726,6 @@ static void bt848_set_geo(struct bttv *btv, if (no_irq_context) set_pll(btv); - vtc=0; - /* Some people say interpolation looks bad ... */ - /* vtc = (hactive < 193) ? 2 : ((hactive < 385) ? 1 : 0); */ - btv->win.interlace = (btv->win.height>tvn->sheight/2) ? 1 : 0; if (0 == btv->risc_cap_odd && @@ -1762,40 +1757,11 @@ static void bt848_set_geo(struct bttv *btv, eheight = btv->gbuf[btv->gq_grab].height; format = btv->gbuf[btv->gq_grab].fmt; bswap = 0; - inter = (btv->win.height>tvn->sheight/2) ? 0 : 1; } - inter = (oheight>tvn->sheight/2) ? 0 : 1; - - /* odd field */ - hactive=owidth; - xsf = (hactive*tvn->scaledtwidth)/tvn->swidth; - hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - hdelay = tvn->hdelayx1; - hdelay = (hdelay*hactive)/tvn->swidth; - hdelay &= 0x3fe; - sr=((tvn->sheight>>inter)*512)/oheight-512; - vscale=(0x10000UL-sr)&0x1fff; - crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)| - ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); - vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; - bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, tvn->sheight, - hdelay, tvn->vdelay, crop); - - /* even field */ - hactive=ewidth; - xsf = (hactive*tvn->scaledtwidth)/tvn->swidth; - hscale = ((tvn->totalwidth*4096UL)/xsf-4096); - hdelay = tvn->hdelayx1; - hdelay = (hdelay*hactive)/tvn->swidth; - hdelay &= 0x3fe; - sr=((tvn->sheight>>inter)*512)/eheight-512; - vscale=(0x10000UL-sr)&0x1fff; - crop=((hactive>>8)&0x03)|((hdelay>>6)&0x0c)| - ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); - vscale |= btv->win.interlace ? (BT848_VSCALE_INT<<8) : 0; - bt848_set_eogeo(btv, 0, vtc, hscale, vscale, hactive, tvn->sheight, - hdelay, tvn->vdelay, crop); + /* program odd + even fields */ + bt848_set_eogeo(btv, tvn, 1, owidth, oheight); + bt848_set_eogeo(btv, tvn, 0, ewidth, eheight); btwrite(format, BT848_COLOR_FMT); btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); @@ -1897,8 +1863,8 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format); if (debug) - printk("bttv%d: cap vgrab: queue %d (%dx%d)\n", - btv->nr,mp->frame,mp->width,mp->height); + printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n", + btv->nr,mp->frame,mp->format,mp->width,mp->height); cli(); btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; @@ -1914,10 +1880,6 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp) #endif if (btv->gq_in == btv->gq_out) { - if(mp->format>=VIDEO_PALETTE_COMPONENT) { - btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI); - btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI); - } btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); } btv->gqueue[btv->gq_in++] = mp->frame; @@ -2317,7 +2279,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) btv->win.height=vw.height; bt848_set_risc_jmps(btv,0); - + bt848_set_winsize(btv); up(&btv->lock); @@ -2573,10 +2535,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) if (debug) printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i); interruptible_sleep_on(&btv->capq); - if(signal_pending(current)) { - ret = -EINTR; - break; - } + if(signal_pending(current)) + return -EINTR; } /* fall throuth */ case GBUFFER_DONE: @@ -2649,9 +2609,6 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) else vu.radio=VIDEO_NO_UNIT; vu.audio=VIDEO_NO_UNIT; -#if 0 - AUDIO(AUDC_GET_UNIT, &vu.audio); -#endif vu.teletext=VIDEO_NO_UNIT; if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu))) return -EFAULT; @@ -3054,17 +3011,6 @@ static void handle_chipset(void) } } -#if 0 -#warning please use tda8425.c instead -static void init_tda8425(struct bttv *btv) -{ - I2CWrite(btv, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */ - I2CWrite(btv, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */ -} -#endif /* can tda9855.c handle this too maybe? */ static void init_tda9840(struct bttv *btv) @@ -3164,6 +3110,7 @@ static void idcard(int i) btv->type == BTTV_PIXVIEWPLAYTV || btv->type == BTTV_AVERMEDIA98 || btv->type == BTTV_MAGICTVIEW061 || + btv->type == BTTV_MAGICTVIEW063 || btv->type == BTTV_CHRONOS_VS2 || btv->type == BTTV_TYPHOON_TVIEW || btv->type == BTTV_PXELVWPLTVPRO || @@ -3600,8 +3547,6 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) btv->risc_cap_odd = 0; btv->risc_cap_even = 0; bt848_set_risc_jmps(btv,-1); - btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI); - btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI); bt848_set_geo(btv,0); btwrite(btv->fb_color_ctl | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index c1e9b3e9ab3f..7dd6f046be61 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,24) +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,25) #include #include @@ -138,7 +138,7 @@ struct bttv { struct i2c_adapter i2c_adap; struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; - int i2c_state; + int i2c_state, i2c_ok; struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; int tuner_type; @@ -270,6 +270,7 @@ extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) #define BTTV_CHRONOS_VS2 0x23 #define BTTV_TYPHOON_TVIEW 0x24 #define BTTV_PXELVWPLTVPRO 0x25 +#define BTTV_MAGICTVIEW063 0x26 #define AUDIO_TUNER 0x00 diff --git a/drivers/char/console.c b/drivers/char/console.c index 93e710188809..4e69f8f4babb 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -121,8 +121,6 @@ struct consw *conswitchp = NULL; #define DEFAULT_BELL_PITCH 750 #define DEFAULT_BELL_DURATION (HZ/8) -extern int tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned int minor); extern void vcs_make_devfs (unsigned int index, int unregister); #ifndef MIN diff --git a/drivers/char/joystick/joy-spaceball.c b/drivers/char/joystick/joy-spaceball.c index 421a3cf8f438..874eb526881d 100644 --- a/drivers/char/joystick/joy-spaceball.c +++ b/drivers/char/joystick/joy-spaceball.c @@ -207,6 +207,8 @@ static int js_sball_ldisc_open(struct tty_struct *tty) struct js_sball_info iniinfo; struct js_sball_info *info = &iniinfo; + MOD_INC_USE_COUNT; + info->tty = tty; info->idx = 0; info->used = 1; @@ -221,8 +223,6 @@ static int js_sball_ldisc_open(struct tty_struct *tty) js_sball_init_corr(js_sball_port->corr); - MOD_INC_USE_COUNT; - return 0; } @@ -312,9 +312,7 @@ static int js_sball_ldisc_room(struct tty_struct *tty) static struct tty_ldisc js_sball_ldisc = { magic: TTY_LDISC_MAGIC, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) name: "spaceball", -#endif open: js_sball_ldisc_open, close: js_sball_ldisc_close, receive_buf: js_sball_ldisc_receive, diff --git a/drivers/char/joystick/joy-spaceorb.c b/drivers/char/joystick/joy-spaceorb.c index 464e59006e7c..a154bcdd5539 100644 --- a/drivers/char/joystick/joy-spaceorb.c +++ b/drivers/char/joystick/joy-spaceorb.c @@ -199,6 +199,8 @@ static int js_orb_ldisc_open(struct tty_struct *tty) struct js_orb_info iniinfo; struct js_orb_info *info = &iniinfo; + MOD_INC_USE_COUNT; + info->tty = tty; info->idx = 0; info->used = 1; @@ -213,8 +215,6 @@ static int js_orb_ldisc_open(struct tty_struct *tty) js_orb_init_corr(js_orb_port->corr); - MOD_INC_USE_COUNT; - return 0; } @@ -270,9 +270,7 @@ static int js_orb_ldisc_room(struct tty_struct *tty) static struct tty_ldisc js_orb_ldisc = { magic: TTY_LDISC_MAGIC, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) name: "spaceorb", -#endif open: js_orb_ldisc_open, close: js_orb_ldisc_close, receive_buf: js_orb_ldisc_receive, diff --git a/drivers/char/joystick/joy-warrior.c b/drivers/char/joystick/joy-warrior.c index fd7be578791a..8737d1cc9286 100644 --- a/drivers/char/joystick/joy-warrior.c +++ b/drivers/char/joystick/joy-warrior.c @@ -90,28 +90,12 @@ static void js_war_process_packet(struct js_war_info* info) if (!info->port->devs[0]) return; buttons[0][0] = ((data[3] & 0xa) >> 1) | ((data[3] & 0x5) << 1); return; - case 2: /* Static status (Send !S to get one) */ -#if 0 - printk("joy-warrior: Static status:"); - for (i = 0; i < 12; i++) - printk(" %02x", info->data[i]); - printk("\n"); -#endif - return; case 3: /* XY-axis info->data */ if (!info->port->devs[0]) return; axes[0][0] = ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)); axes[0][1] = (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7); return; break; - case 4: /* Dynamic status */ -#if 0 - printk("joy-warrior: Dynamic status:"); - for (i = 0; i < 4; i++) - printk(" %02x", info->data[i]); - printk("\n"); -#endif - return; case 5: /* Throttle, spinner, hat info->data */ if (!info->port->devs[0]) return; axes[0][2] = (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7); @@ -119,6 +103,9 @@ static void js_war_process_packet(struct js_war_info* info) axes[0][4] = (data[3] & 8 ? 1 : 0) - (info->data[3] & 4 ? 1 : 0); axes[0][5] = (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5); return; + case 2: /* Static status (Send !S to get one) */ + case 4: /* Dynamic status */ + return; default: printk("joy-warrior: Unknown packet %d length %d:", (data[0] >> 4) & 7, info->idx); for (i = 0; i < info->idx; i++) @@ -199,6 +186,8 @@ static int js_war_ldisc_open(struct tty_struct *tty) struct js_war_info iniinfo; struct js_war_info *info = &iniinfo; + MOD_INC_USE_COUNT; + info->tty = tty; info->idx = 0; info->len = 0; @@ -216,8 +205,6 @@ static int js_war_ldisc_open(struct tty_struct *tty) js_war_init_corr(js_war_port->corr); - MOD_INC_USE_COUNT; - return 0; } @@ -283,9 +270,7 @@ static int js_war_ldisc_room(struct tty_struct *tty) static struct tty_ldisc js_war_ldisc = { magic: TTY_LDISC_MAGIC, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) name: "warrior", -#endif open: js_war_ldisc_open, close: js_war_ldisc_close, receive_buf: js_war_ldisc_receive, diff --git a/drivers/char/joystick/joystick.c b/drivers/char/joystick/joystick.c index cfd0f2e82f86..d0dc70f55e13 100644 --- a/drivers/char/joystick/joystick.c +++ b/drivers/char/joystick/joystick.c @@ -499,6 +499,7 @@ static int js_open(struct inode *inode, struct file *file) if (MAJOR(inode->i_rdev) != JOYSTICK_MAJOR) return -EINVAL; + spin_lock_irqsave(&js_lock, flags); while (i > 0 && jd) { @@ -510,32 +511,32 @@ static int js_open(struct inode *inode, struct file *file) if (!jd) return -ENODEV; - if ((result = jd->open(jd))) return result; - - if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL))) { + if ((result = jd->open(jd))) + return result; - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; - spin_lock_irqsave(&js_lock, flags); + if ((new = kmalloc(sizeof(struct js_list), GFP_KERNEL))) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } - curl = jd->list; + spin_lock_irqsave(&js_lock, flags); - jd->list = new; - jd->list->next = curl; - jd->list->dev = jd; - jd->list->startup = 0; - jd->list->tail = GOB(jd->bhead); - file->private_data = jd->list; + curl = jd->list; - spin_unlock_irqrestore(&js_lock, flags); + jd->list = new; + jd->list->next = curl; + jd->list->dev = jd; + jd->list->startup = 0; + jd->list->tail = GOB(jd->bhead); + file->private_data = jd->list; - if (!js_use_count++) js_do_timer(0); + spin_unlock_irqrestore(&js_lock, flags); - } else { - result = -ENOMEM; - } + if (!js_use_count++) js_do_timer(0); - return result; + return 0; } /* @@ -573,10 +574,11 @@ static int js_release(struct inode *inode, struct file *file) kfree(file->private_data); if (!--js_use_count) del_timer(&js_timer); - MOD_DEC_USE_COUNT; jd->close(jd); + MOD_DEC_USE_COUNT; + return 0; } @@ -585,50 +587,6 @@ static int js_release(struct inode *inode, struct file *file) * It's used for debugging only. */ -#if 0 -static void js_dump_mem(void) -{ - - struct js_port *curp = js_port; - struct js_dev *curd = js_dev; - int i; - - printk(",--- Dumping Devices:\n"); - printk("| js_dev = %x\n", (int) js_dev); - - while (curd) { - printk("| %s-device %x, next %x axes %d, buttons %d, port %x - %#x\n", - curd->next ? "|":"`", - (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port, curd->port->io); - curd = curd->next; - } - - printk(">--- Dumping ports:\n"); - printk("| js_port = %x\n", (int) js_port); - - while (curp) { - printk("| %s-port %x, next %x, io %#x, devices %d\n", - curp->next ? "|":"`", - (int) curp, (int) curp->next, curp->io, curp->ndevs); - for (i = 0; i < curp->ndevs; i++) { - curd = curp->devs[i]; - if (curd) - printk("| %s %s-device %x, next %x axes %d, buttons %d, port %x\n", - curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", - (int) curd, (int) curd->next, curd->num_axes, curd->num_buttons, (int) curd->port); - else - printk("| %s %s-device %x, not there\n", - curp->next ? "|":" ", (i < curp->ndevs-1) ? "|":"`", (int) curd); - - } - curp = curp->next; - } - - printk("`--- Done\n"); -} -#endif - - struct js_port *js_register_port(struct js_port *port, void *info, int devs, int infos, js_read_func read) { diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index a2097967e060..f155cf091f68 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -12,7 +12,10 @@ * Author: * L. Haag * - * $Log: r3964.c,v $ + * $Log: n_r3964.c,v $ + * Revision 1.8 2000/03/23 14:14:54 dwmw2 + * Fix race in sleeping in r3964_read() + * * Revision 1.7 1999/28/08 11:41:50 dwmw2 * Port to 2.3 kernel * @@ -38,7 +41,6 @@ * * */ -#define R3964_VERSION "1.7" #include #include @@ -224,7 +226,7 @@ static int __init r3964_init(void) { int status; - printk ("r3964: Philips r3964 Driver V%s\n", R3964_VERSION); + printk ("r3964: Philips r3964 Driver $Revision: 1.8 $\n"); /* * Register the tty line discipline @@ -1280,8 +1282,8 @@ static int r3964_read(struct tty_struct *tty, struct file *file, /* block until there is a message: */ add_wait_queue(&pInfo->read_wait, &wait); repeat: - pMsg = remove_msg(pInfo, pClient); current->state = TASK_INTERRUPTIBLE; + pMsg = remove_msg(pInfo, pClient); if (!pMsg && !signal_pending(current)) { schedule(); diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 9331852e15ca..4f1c9c703115 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -29,10 +29,6 @@ #define BUILDING_PTY_C 1 #include -extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned int minor); -extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); - struct pty_struct { int magic; wait_queue_head_t open_wait; diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 387f25f80f2e..a821b6dd58e2 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -220,10 +220,6 @@ static char *serial_revdate = "2000-03-20"; #define _INLINE_ #endif -extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned int minor); -extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); - static char *serial_name = "Serial driver"; static DECLARE_TASK_QUEUE(tq_serial); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index cf998564c0f1..2c4a8777d472 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -99,9 +99,6 @@ #ifdef CONFIG_VT extern void con_init_devfs (void); #endif -void tty_register_devfs (struct tty_driver *driver, unsigned int flags, - unsigned minor); -void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); #define CONSOLE_DEV MKDEV(TTY_MAJOR,0) #define TTY_DEV MKDEV(TTYAUX_MAJOR,0) diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c index dfea37d63865..0ed55b715399 100644 --- a/drivers/char/tuner.c +++ b/drivers/char/tuner.c @@ -97,7 +97,6 @@ static struct tunertype tuners[] = { { "Temic NTSC", TEMIC, NTSC, 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, { "Temic PAL_I", TEMIC, PAL_I, - // 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, { "Temic 4036 FY5 NTSC", TEMIC, NTSC, 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, @@ -111,6 +110,8 @@ static struct tunertype tuners[] = { 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, + { "Temic 4006FH5", TEMIC, PAL_I, + 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, }; #define TUNERS (sizeof(tuners)/sizeof(struct tunertype)) diff --git a/drivers/char/wd501p.h b/drivers/char/wd501p.h index 81971da6b4f2..11fc72b04fe1 100644 --- a/drivers/char/wd501p.h +++ b/drivers/char/wd501p.h @@ -25,11 +25,21 @@ #define WDT_COUNT1 (io+1) #define WDT_COUNT2 (io+2) #define WDT_CR (io+3) -#define WDT_SR (io+4) -#define WDT_RT (io+5) -#define WDT_UNUSED (io+6) +#define WDT_SR (io+4) /* Start buzzer on PCI write */ +#define WDT_RT (io+5) /* Stop buzzer on PCI write */ +#define WDT_BUZZER (io+6) /* PCI only: rd=disable, wr=enable */ #define WDT_DC (io+7) +/* The following are only on the PCI card, they're outside of I/O space on + * the ISA card: */ +#define WDT_CLOCK (io+12) /* COUNT2: rd=16.67MHz, wr=2.0833MHz */ +/* inverted opto isolated reset output: */ +#define WDT_OPTONOTRST (io+13) /* wr=enable, rd=disable */ +/* opto isolated reset output: */ +#define WDT_OPTORST (io+14) /* wr=enable, rd=disable */ +/* programmable outputs: */ +#define WDT_PROGOUT (io+15) /* wr=enable, rd=disable */ + #define WDC_SR_WCCR 1 /* Active low */ #define WDC_SR_TGOOD 2 #define WDC_SR_ISOI0 4 @@ -39,6 +49,8 @@ #define WDC_SR_PSUUNDR 64 /* Active low */ #define WDC_SR_IRQ 128 /* Active low */ +#ifndef WDT_IS_PCI + /* * Feature Map 1 is the active high inputs not supported on your card. * Feature Map 2 is the active low inputs not supported on your card. @@ -67,6 +79,13 @@ #define WDT_OPTION_MASK (WDIOF_OVERHEAT) #endif +#else + +#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD) +#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR) +#define WDT_OPTION_MASK (WDIOF_OVERHEAT) +#endif + #ifndef FEATUREMAP1 #error "Config option not set" #endif diff --git a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c new file mode 100644 index 000000000000..6e99a72ac04c --- /dev/null +++ b/drivers/char/wdt_pci.c @@ -0,0 +1,558 @@ +/* + * Industrial Computer Source WDT500/501 driver for Linux 2.1.x + * + * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 1995 Alan Cox + * + * Release 0.08. + * + * Fixes + * Dave Gregorich : Modularisation and minor bugs + * Alan Cox : Added the watchdog ioctl() stuff + * Alan Cox : Fixed the reboot problem (as noted by + * Matt Crocker). + * Alan Cox : Added wdt= boot option + * Alan Cox : Cleaned up copy/user stuff + * Tim Hockin : Added insmod parameters, comment cleanup + * Parameterized timeout + * JP Nollmann : Added support for PCI wdt501p + * Alan Cox : Split ISA and PCI cards into two drivers + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define WDT_IS_PCI +#include "wd501p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Until Access I/O gets their application for a PCI vendor ID approved, + * I don't think that it's appropriate to move these constants into the + * regular pci_ids.h file. -- JPN 2000/01/18 + */ + +#ifndef PCI_VENDOR_ID_ACCESSIO +#define PCI_VENDOR_ID_ACCESSIO 0x494f +#endif +#ifndef PCI_DEVICE_ID_WDG_CSM +#define PCI_DEVICE_ID_WDG_CSM 0x22c0 +#endif + +static int wdt_is_open=0; + +/* + * You must set these - there is no sane way to probe for this board. + * You can use wdt=x,y to set these now. + */ + +static int io=0x240; +static int irq=11; + +#define WD_TIMO (100*60) /* 1 minute */ + +#ifndef MODULE + +/** + * wdtpci_setup: + * @str: command line string + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. Sane people build it + * modular but the others come here. + */ + +static int __init wdtpci_setup(char *str) +{ + int ints[4]; + + str = get_options (str, ARRAY_SIZE(ints), ints); + + if (ints[0] > 0) + { + io = ints[1]; + if(ints[0] > 1) + irq = ints[2]; + } + + return 1; +} + +__setup("wdt=", wdtpci_setup); + +#endif /* !MODULE */ + +/* + * Programming support + */ + +static void wdtpci_ctr_mode(int ctr, int mode) +{ + ctr<<=6; + ctr|=0x30; + ctr|=(mode<<1); + outb_p(ctr, WDT_CR); +} + +static void wdtpci_ctr_load(int ctr, int val) +{ + outb_p(val&0xFF, WDT_COUNT0+ctr); + outb_p(val>>8, WDT_COUNT0+ctr); +} + +/* + * Kernel methods. + */ + + +/** + * wdtpci_status: + * + * Extract the status information from a WDT watchdog device. There are + * several board variants so we have to know which bits are valid. Some + * bits default to one and some to zero in order to be maximally painful. + * + * we then map the bits onto the status ioctl flags. + */ + +static int wdtpci_status(void) +{ + /* + * Status register to bit flags + */ + + int flag=0; + unsigned char status=inb_p(WDT_SR); + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + if(!(status&WDC_SR_TGOOD)) + flag|=WDIOF_OVERHEAT; + if(!(status&WDC_SR_PSUOVER)) + flag|=WDIOF_POWEROVER; + if(!(status&WDC_SR_PSUUNDR)) + flag|=WDIOF_POWERUNDER; + if(!(status&WDC_SR_FANGOOD)) + flag|=WDIOF_FANFAULT; + if(status&WDC_SR_ISOI0) + flag|=WDIOF_EXTERN1; + if(status&WDC_SR_ISII1) + flag|=WDIOF_EXTERN2; + return flag; +} + +/** + * wdtpci_interrupt: + * @irq: Interrupt number + * @dev_id: Unused as we don't allow multiple devices. + * @regs: Unused. + * + * Handle an interrupt from the board. These are raised when the status + * map changes in what the board considers an interesting way. That means + * a failure condition occuring. + */ + +static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* + * Read the status register see what is up and + * then printk it. + */ + + unsigned char status=inb_p(WDT_SR); + + status|=FEATUREMAP1; + status&=~FEATUREMAP2; + + printk(KERN_CRIT "WDT status %d\n", status); + + if(!(status&WDC_SR_TGOOD)) + printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); + if(!(status&WDC_SR_PSUOVER)) + printk(KERN_CRIT "PSU over voltage.\n"); + if(!(status&WDC_SR_PSUUNDR)) + printk(KERN_CRIT "PSU under voltage.\n"); + if(!(status&WDC_SR_FANGOOD)) + printk(KERN_CRIT "Possible fan fault.\n"); + if(!(status&WDC_SR_WCCR)) +#ifdef SOFTWARE_REBOOT +#ifdef ONLY_TESTING + printk(KERN_CRIT "Would Reboot.\n"); +#else + printk(KERN_CRIT "Initiating system reboot.\n"); + machine_restart(NULL); +#endif +#else + printk(KERN_CRIT "Reset in 5ms.\n"); +#endif +} + + +static long long wdtpci_llseek(struct file *file, long long offset, int origin) +{ + return -ESPIPE; +} + +/** + * wdtpci_ping: + * + * Reload counter one with the watchdog timeout. We don't bother reloading + * the cascade counter. + */ + +static void wdtpci_ping(void) +{ + /* Write a watchdog value */ + inb_p(WDT_DC); + wdtpci_ctr_mode(1,2); + wdtpci_ctr_load(1,WD_TIMO); /* Timeout */ + outb_p(0, WDT_DC); +} + +/** + * wdtpci_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if(count) + { + wdtpci_ping(); + return 1; + } + return 0; +} + +/** + * wdtpci_read: + * @file: file handle to the watchdog board + * @buf: buffer to write 1 byte into + * @count: length of buffer + * @ptr: offset (no seek allowed) + * + * Read reports the temperature in degrees Fahrenheit. The API is in + * farenheit. It was designed by an imperial measurement luddite. + */ + +static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr) +{ + unsigned short c=inb_p(WDT_RT); + unsigned char cp; + + /* Can't seek (pread) on this device */ + if (ptr != &file->f_pos) + return -ESPIPE; + + switch(MINOR(file->f_dentry->d_inode->i_rdev)) + { + case TEMP_MINOR: + c*=11; + c/=15; + cp=c+7; + if(copy_to_user(buf,&cp,1)) + return -EFAULT; + return 1; + default: + return -EINVAL; + } +} + +/** + * wdtpci_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ + +static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER + |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT, + 1, + "WDT500/501PCI" + }; + + ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ + switch(cmd) + { + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + + case WDIOC_GETSTATUS: + return put_user(wdtpci_status(),(int *)arg); + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + wdtpci_ping(); + return 0; + } +} + +/** + * wdtpci_open: + * @inode: inode of device + * @file: file handle to device + * + * One of our two misc devices has been opened. The watchdog device is + * single open and on opening we load the counters. Counter zero is a + * 100Hz cascade, into counter 1 which downcounts to reboot. When the + * counter triggers counter 2 downcounts the length of the reset pulse + * which set set to be as long as possible. + */ + +static int wdtpci_open(struct inode *inode, struct file *file) +{ + switch(MINOR(inode->i_rdev)) + { + case WATCHDOG_MINOR: + if(wdt_is_open) + return -EBUSY; + MOD_INC_USE_COUNT; + /* + * Activate + */ + + wdt_is_open=1; + + inb_p(WDT_DC); /* Disable */ + + /* + * "pet" the watchdog, as Access says. + * This resets the clock outputs. + */ + + wdtpci_ctr_mode(2,0); + outb_p(0, WDT_DC); + + inb_p(WDT_DC); + + outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ + inb_p(WDT_BUZZER); /* disable */ + inb_p(WDT_OPTONOTRST); /* disable */ + inb_p(WDT_OPTORST); /* disable */ + inb_p(WDT_PROGOUT); /* disable */ + wdtpci_ctr_mode(0,3); + wdtpci_ctr_mode(1,2); + wdtpci_ctr_mode(2,1); + wdtpci_ctr_load(0,20833); /* count at 100Hz */ + wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */ + /* DO NOT LOAD CTR2 on PCI card! -- JPN */ + outb_p(0, WDT_DC); /* Enable */ + return 0; + case TEMP_MINOR: + MOD_INC_USE_COUNT; + return 0; + default: + return -ENODEV; + } +} + +/** + * wdtpci_close: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int wdtpci_release(struct inode *inode, struct file *file) +{ + if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) + { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + inb_p(WDT_DC); /* Disable counters */ + wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ +#endif + wdt_is_open=0; + } + MOD_DEC_USE_COUNT; + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ + +static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + inb_p(WDT_DC); + wdtpci_ctr_load(2,0); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + + +static struct file_operations wdtpci_fops = { + llseek: wdtpci_llseek, + read: wdtpci_read, + write: wdtpci_write, + ioctl: wdtpci_ioctl, + open: wdtpci_open, + release: wdtpci_release, +}; + +static struct miscdevice wdtpci_miscdev= +{ + WATCHDOG_MINOR, + "watchdog", + &wdtpci_fops +}; + +#ifdef CONFIG_WDT_501 +static struct miscdevice temp_miscdev= +{ + TEMP_MINOR, + "temperature", + &wdtpci_fops +}; +#endif + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdtpci_notifier= +{ + wdtpci_notify_sys, + NULL, + 0 +}; + +#ifdef MODULE + +#define wdtpci_init init_module + +/** + * cleanup_module: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +void cleanup_module(void) +{ + misc_deregister(&wdtpci_miscdev); +#ifdef CONFIG_WDT_501_PCI + misc_deregister(&temp_miscdev); +#endif + unregister_reboot_notifier(&wdtpci_notifier); + release_region(io,16); + free_irq(irq, &wdtpci_miscdev); +} + +#endif + +/** + * wdtpci_init: + * + * Set up the WDT watchdog board. All we have to do is grab the + * resources we require and bitch if anyone beat us to them. + * The open() function will actually kick the board off. + */ + +int __init wdtpci_init(void) +{ + struct pci_dev *dev = NULL; + + if (pci_present()) + { + while ((dev = pci_find_device(PCI_VENDOR_ID_ACCESSIO, + PCI_DEVICE_ID_WDG_CSM, dev))) { + /* See if we can do this device */ + irq = dev->irq; + io = dev->resource[2].start; + printk("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " + "(Interrupt %d)\n", io, irq); + } + } + if(request_region(io, 16, "wdt-pci")==NULL) + { + printk(KERN_ERR "I/O %d is not free.\n", io); + return -EIO; + } + if(request_irq(irq, wdtpci_interrupt, SA_INTERRUPT|SA_SHIRQ, "wdt-pci", &wdtpci_miscdev)) + { + printk(KERN_ERR "IRQ %d is not free.\n", irq); + release_region(io, 16); + return -EIO; + } + misc_register(&wdtpci_miscdev); +#ifdef CONFIG_WDT_501 + misc_register(&temp_miscdev); +#endif + register_reboot_notifier(&wdtpci_notifier); + return 0; +} + diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 9ce1cf4af045..3097345c8a1d 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -114,8 +114,8 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length, static void set_multicast_list(struct net_device *dev); static void do_set_multicast_list(struct net_device *dev); -/** - * DOC: SMP and the 8390 setup. +/* + * SMP and the 8390 setup. * * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is * a page register that controls bank and packet buffer access. We guard @@ -407,13 +407,16 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) } /** - * ei_interrupt - - * @irq: - * @dev_id: - * @regs: + * ei_interrupt - handle the interrupts from an 8390 + * @irq: interrupt number + * @dev_id: a pointer to the net_device + * @regs: unused * - * The typical workload of the driver: - * Handle the ether interface interrupts. + * Handle the ether interface interrupts. We pull packets from + * the 8390 via the card specific functions and fire them at the networking + * stack. We also handle transmit completions and wake the transmit path if + * neccessary. We also update the counters and do other housekeeping as + * needed */ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs) diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 1767e8e60f31..6b72d0b0dfeb 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -108,9 +108,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then tristate ' HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS tristate ' HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN tristate ' HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100 - if [ "$CONFIG_OBSOLETE" = "y" ]; then - tristate ' ICL EtherTeam 16i/32 support' CONFIG_ETH16I - fi + tristate ' ICL EtherTeam 16i/32 support' CONFIG_ETH16I tristate ' NE2000/NE1000 support' CONFIG_NE2000 if [ "$CONFIG_OBSOLETE" = "y" ]; then tristate ' SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005 @@ -194,7 +192,7 @@ endmenu bool 'FDDI driver support' CONFIG_FDDI if [ "$CONFIG_FDDI" = "y" ]; then - bool ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX + dep_tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX $CONFIG_FDDI tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP fi diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 535f84f0a632..a78f954729c8 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -119,7 +119,7 @@ extern int de600_probe(struct net_device *); extern int de620_probe(struct net_device *); /* FDDI adapters */ -extern int dfx_probe(struct net_device *dev); +extern int dfx_probe(void); extern int apfddi_init(struct net_device *dev); extern int skfp_probe(struct net_device *dev); @@ -184,6 +184,9 @@ struct devprobe eisa_probes[] __initdata = { #endif #ifdef CONFIG_NE3210 {ne3210_probe, 0}, +#endif +#ifdef CONFIG_DEFXX + {dfx_probe, 0}. #endif {NULL, 0}, }; @@ -469,9 +472,6 @@ static int __init fddiif_probe(struct net_device *dev) return 1; /* ENXIO */ if (1 -#ifdef CONFIG_DEFXX - && dfx_probe(dev) -#endif #ifdef CONFIG_APFDDI && apfddi_init(dev) #endif diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 91aeaced9863..fe6b00603649 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -194,11 +194,12 @@ * 12-Sep-96 LVS Reset current address to factory address during * device open. Updated transmit path to post a * single fragment which includes PRH->end of data. + * Mar 2000 AC Did various cleanups for 2.3.x */ /* Version information string - should be updated prior to each new release!!! */ -static const char *version = "defxx.c:v1.04 09/16/96 Lawrence V. Stefani (stefani@lkg.dec.com)\n"; +static const char *version = "defxx.c:v1.05 2000/03/26 Lawrence V. Stefani (stefani@lkg.dec.com) and others\n"; /* Include files */ @@ -215,6 +216,7 @@ static const char *version = "defxx.c:v1.04 09/16/96 Lawrence V. Stefani (stefa #include #include #include +#include #include #include #include @@ -236,11 +238,11 @@ static const char *version = "defxx.c:v1.04 09/16/96 Lawrence V. Stefani (stefa /* Define global routines */ -int dfx_probe(struct net_device *dev); +int dfx_probe(void); /* Define module-wide (static) routines */ -static struct net_device *dfx_alloc_device(struct net_device *dev, u16 iobase); +static struct net_device *dfx_alloc_device(u16 iobase); static void dfx_bus_init(struct net_device *dev); static void dfx_bus_config_check(DFX_board_t *bp); @@ -402,29 +404,9 @@ static inline void dfx_port_read_long( * dev - pointer to device information * * Functional Description: - * This routine is called by the OS for each FDDI device name (fddi0, - * fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c. Since - * the DEFXX.C driver currently does not support being loaded as a - * module, dfx_probe() will initialize all devices the first time - * it is called. - * - * Let's say that dfx_probe() is getting called to initialize fddi0. - * Furthermore, let's say there are three supported controllers in the - * system. Before dfx_probe() leaves, devices fddi0, fddi1, and fddi2 - * will be initialized and a global flag will be set to indicate that - * dfx_probe() has already been called. - * - * However...the OS doesn't know that we've already initialized - * devices fddi1 and fddi2 so dfx_probe() gets called again and again - * until it reaches the end of the device list for FDDI (presently, - * fddi7). It's important that the driver "pretend" to probe for - * devices fddi1 and fddi2 and return success. Devices fddi3 - * through fddi7 will return failure since they weren't initialized. - * - * This algorithm seems to work for the time being. As other FDDI - * drivers are written for Linux, a more generic approach (perhaps - * similar to the Ethernet card approach) may need to be implemented. - * + * This routine is called by the OS once at startup to scan for + * DEFXX cards. + * * Return Codes: * 0 - This device (fddi0, fddi1, etc) configured successfully * -ENODEV - No devices present, or no Digital FDDI EISA or PCI device @@ -446,7 +428,9 @@ static inline void dfx_port_read_long( * the device structure. */ -int __init dfx_probe(struct net_device *dev) +static struct net_device *bp_root; + +int __init dfx_probe(void) { int i; /* used in for loops */ int version_disp; /* was version info string already displayed? */ @@ -456,44 +440,26 @@ int __init dfx_probe(struct net_device *dev) u16 command; /* PCI Configuration space Command register val */ u32 slot_id; /* EISA hardware (slot) ID read from adapter */ DFX_board_t *bp; /* board pointer */ + struct net_device *dev; DBG_printk("In dfx_probe...\n"); - /* - * Verify whether we're going through dfx_probe() again - * - * If so, see if we're going through for a subsequent fddi device that - * we've already initialized. If we are, return success (0). If not, - * return failure (-ENODEV). - */ - version_disp = 0; /* default to version string not displayed */ - if (already_probed) - { - DBG_printk("Already entered dfx_probe\n"); - if (dev != NULL) - if ((strncmp(dev->name, "fddi", 4) == 0) && (dev->base_addr != 0)) - { - DBG_printk("In dfx_probe for fddi adapter (%s) we've already initialized it, so return success\n", dev->name); - return(0); - } - return(-ENODEV); - } - already_probed = 1; /* set global flag */ + already_probed = 1; /* set global flag */ /* Scan for FDDI EISA controllers */ for (i=0; i < DFX_MAX_EISA_SLOTS; i++) /* only scan for up to 16 EISA slots */ - { + { port = (i << 12) + PI_ESIC_K_SLOT_ID; /* port = I/O address for reading slot ID */ slot_id = inl(port); /* read EISA HW (slot) ID */ if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID) - { + { if (!version_disp) /* display version info if adapter is found */ - { + { version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ - } + } port = (i << 12); /* recalc base addr */ @@ -501,46 +467,47 @@ int __init dfx_probe(struct net_device *dev) port_len = PI_ESIC_K_CSR_IO_LEN; if (check_region(port, port_len) == 0) - { + { /* Allocate a new device structure for this adapter */ - dev = dfx_alloc_device(dev, port); + dev = dfx_alloc_device(port); if (dev != NULL) - { + { /* Initialize board structure with bus-specific info */ - bp = (DFX_board_t *) dev->priv; + bp->next = bp_root; + bp_root = dev; bp->dev = dev; bp->bus_type = DFX_BUS_TYPE_EISA; if (dfx_driver_init(dev) == DFX_K_SUCCESS) num_boards++; /* only increment global board count on success */ else dev->base_addr = 0; /* clear port address field in device structure on failure */ - } } + } else printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); - } } + } /* Scan for FDDI PCI controllers */ if (pci_present()) /* is PCI even present? */ while ((pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, pdev))) - { + { if (!version_disp) /* display version info if adapter is found */ - { + { version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ - } + } /* Verify that I/O enable bit is set (PCI slot is enabled) */ pci_read_config_word(pdev, PCI_COMMAND, &command); if ((command & PCI_COMMAND_IO) == 0) - printk("I/O enable bit not set! Verify that slot is enabled\n"); + printk(KERN_ERR "defxx: I/O enable bit not set! Verify that slot is enabled\n"); else - { + { /* Turn off memory mapped space and enable mastering */ command |= PCI_COMMAND_MASTER; @@ -556,28 +523,30 @@ int __init dfx_probe(struct net_device *dev) port_len = PFI_K_CSR_IO_LEN; if (check_region(port, port_len) == 0) - { + { /* Allocate a new device structure for this adapter */ - dev = dfx_alloc_device(dev, port); + dev = dfx_alloc_device(port); if (dev != NULL) - { + { /* Initialize board structure with bus-specific info */ bp = (DFX_board_t *) dev->priv; bp->dev = dev; + bp->next = bp_root; + bp_root = dev; bp->bus_type = DFX_BUS_TYPE_PCI; bp->pci_dev = pdev; if (dfx_driver_init(dev) == DFX_K_SUCCESS) num_boards++; /* only increment global board count on success */ else dev->base_addr = 0; /* clear port address field in device structure on failure */ - } } - else - printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); } + else + printk(KERN_ERR "defxx: I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1)); } + } /* * If we're at this point we're going through dfx_probe() for the first @@ -589,7 +558,7 @@ int __init dfx_probe(struct net_device *dev) return(0); else return(-ENODEV); - } +} /* @@ -639,32 +608,32 @@ int __init dfx_probe(struct net_device *dev) * None */ -struct net_device __init *dfx_alloc_device( struct net_device *dev, u16 iobase) +struct net_device __init *dfx_alloc_device(u16 iobase) { struct net_device *tmp_dev; /* pointer to a device structure */ + int err; DBG_printk("In dfx_alloc_device...\n"); /* Find next free fddi entry */ - for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next) - if ((strncmp(tmp_dev->name, "fddi", 4) == 0) && (tmp_dev->base_addr == 0)) - break; + tmp_dev = dev_alloc("fddi%d", &err); if (tmp_dev == NULL) - { - printk("Could not find free FDDI device structure for this adapter!\n"); + { + printk(KERN_ERR "Could not find free FDDI device structure for this adapter!\n"); return(NULL); - } + } DBG_printk("Device entry free, device name = %s\n", tmp_dev->name); /* Allocate space for private board structure */ tmp_dev->priv = (void *) kmalloc(sizeof(DFX_board_t), GFP_KERNEL); if (tmp_dev->priv == NULL) - { - printk("Could not allocate memory for private board structure!\n"); + { + printk(KERN_ERR "defxx: Could not allocate memory for private board structure!\n"); + kfree(tmp_dev); return(NULL); - } + } memset(tmp_dev->priv, 0, sizeof(DFX_board_t)); /* clear structure */ /* Initialize new device structure */ @@ -696,7 +665,7 @@ struct net_device __init *dfx_alloc_device( struct net_device *dev, u16 iobase) fddi_setup(tmp_dev); return(tmp_dev); - } +} /* @@ -1370,22 +1339,22 @@ int dfx_adap_init( * if the open is successful. */ -int dfx_open( - struct net_device *dev - ) - - { +int dfx_open(struct net_device *dev) +{ DFX_board_t *bp = (DFX_board_t *)dev->priv; DBG_printk("In dfx_open...\n"); + + MOD_INC_USE_COUNT; /* Register IRQ - support shared interrupts by passing device ptr */ if (request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev)) - { - printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq); - return(-EAGAIN); - } + { + printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); + MOD_DEC_USE_COUNT; + return -EAGAIN; + } /* * Set current address to factory MAC address @@ -1416,16 +1385,17 @@ int dfx_open( bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST; /* skip self-test */ if (dfx_adap_init(bp) != DFX_K_SUCCESS) - { - printk("%s: Adapter open failed!\n", dev->name); - return(-EAGAIN); - } + { + printk(KERN_ERR "%s: Adapter open failed!\n", dev->name); + free_irq(dev->irq, dev); + MOD_DEC_USE_COUNT; + return -EAGAIN; + } /* Set device structure info */ - netif_start_queue(dev); return(0); - } +} /* @@ -1460,11 +1430,8 @@ int dfx_open( * routine. */ -int dfx_close( - struct net_device *dev - ) - - { +int dfx_close(struct net_device *dev) +{ DFX_board_t *bp = (DFX_board_t *)dev->priv; DBG_printk("In dfx_close...\n"); @@ -1514,8 +1481,10 @@ int dfx_close( /* Deregister (free) IRQ */ free_irq(dev->irq, dev); + + MOD_DEC_USE_COUNT; return(0); - } +} /* @@ -3492,6 +3461,30 @@ void dfx_xmt_flush( return; } + +#ifdef MODULE + +int init_module(void) +{ + if(dfx_probe()<0) + return -ENODEV; + return 0; +} + +void cleanup_module(void) +{ + while(bp_root!=NULL) + { + struct net_device *tmp=bp_root; + DFX_board_t *priv=tmp->priv; + bp_root=priv->next; + kfree(tmp->priv); + kfree(tmp); + } +} + +#endif + /* * Local variables: diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h index d602b2589864..223ad7d5da5f 100644 --- a/drivers/net/defxx.h +++ b/drivers/net/defxx.h @@ -1756,6 +1756,7 @@ typedef struct DFX_board_tag /* Store device, bus-specific, and parameter information for this adapter */ struct net_device *dev; /* pointer to device structure */ + struct net_device *next; u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ u16 base_addr; /* base I/O address (same as dev->base_addr) */ struct pci_dev * pci_dev; diff --git a/drivers/net/pcmcia/Config.in b/drivers/net/pcmcia/Config.in index 936abfed8c59..9530440e3ebe 100644 --- a/drivers/net/pcmcia/Config.in +++ b/drivers/net/pcmcia/Config.in @@ -15,6 +15,7 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA dep_tristate ' COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA + dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA if [ "$CONFIG_CARDBUS" = "y" ]; then dep_tristate ' 3Com 3c575 CardBus support' CONFIG_PCMCIA_3C575 m diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile index 65938d96db86..ddefee51db17 100644 --- a/drivers/net/pcmcia/Makefile +++ b/drivers/net/pcmcia/Makefile @@ -39,9 +39,18 @@ obj-$(CONFIG_AIRONET4500_CS) += aironet4500_cs.o obj-$(CONFIG_PCMCIA_3C575) += 3c575_cb.o obj-$(CONFIG_PCMCIA_XIRTULIP) += xircom_tulip_cb.o +obj-$(CONFIG_PCMCIA_IBMTR) += ibmtr_cs.o + O_OBJS := $(filter-out $(export-objs), $(obj-y)) OX_OBJS := $(filter $(export-objs), $(obj-y)) M_OBJS := $(filter-out $(export-objs), $(obj-m)) MX_OBJS := $(filter $(export-objs), $(obj-m)) include $(TOPDIR)/Rules.make + +.ibmtr.o: ../tokenring/ibmtr.c + $(CC) $(CFLAGS) -D__NO_VERSION__ -DPCMCIA -c -o $@ ../tokenring/ibmtr.c + +ibmtr_cs.o: .ibmtr.o ibmtr_cs.c + $(CC) $(CFLAGS) -DPCMCIA -c -o .$@ ibmtr_cs.c + $(LD) -r -o $@ .$@ .ibmtr.o diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c new file mode 100644 index 000000000000..74f4bb61204e --- /dev/null +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -0,0 +1,635 @@ +/*====================================================================== + + A PCMCIA token-ring driver for IBM-based cards + + This driver supports the IBM PCMCIA Token-Ring Card. + Written by Steve Kipisz, kipisz@vnet.ibm.com or + bungy@ibm.net + + Written 1995,1996. + + This code is based on pcnet_cs.c from David Hinds. + + V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com + + Linux V2.2.x presented significant changes to the underlying + ibmtr.c code. Mainly the code became a lot more organized and + modular. + + This caused the old PCMCIA Token Ring driver to give up and go + home early. Instead of just patching the old code to make it + work, the PCMCIA code has been streamlined, updated and possibly + improved. + + This code now only contains code required for the Card Services. + All we do here is set the card up enough so that the real ibmtr.c + driver can find it and work with it properly. + + i.e. We set up the io port, irq, mmio memory and shared ram memory. + This enables ibmtr_probe in ibmtr.c to find the card and configure it + as though it was a normal ISA and/or PnP card. + + There is some confusion with the difference between available shared + ram and the amount actually reserved from memory. ibmtr.c sets up + several offsets depending upon the actual on-board memory, not the + reserved memory. We need to get around this to allow the cards to + work with other cards in restricted memory space. Therefore the + pcmcia_reality_check function. + + TODO + - Write the suspend / resume functions. + - Fix Kernel Oops when removing card before ifconfig down + + CHANGES + + v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com) + Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c + + v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com) + Updated to version 2.2.7 to match the first version of the kernel + that the modification to ibmtr.c were incorporated into. + + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define PCMCIA_DEBUG 10 +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = +"ibmtr_cs.c 1.10 1996/01/06 05:19:00 (Steve Kipisz)\n" +" 2.2.7 1999/05/03 12:00:00 (Mike Phillips)\n" ; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; + +/* MMIO base address */ +static u_long mmiobase = 0; + +/* SRAM base address */ +static u_long srambase = 0; + +/* SRAM size 8,16,32,64 */ +static u_long sramsize = 16; + +/* Ringspeed 4,16 */ +static int ringspeed = 16; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(mmiobase, "i"); +MODULE_PARM(srambase, "i"); +MODULE_PARM(sramsize, "i"); +MODULE_PARM(ringspeed, "i"); + +/*====================================================================*/ + +static void ibmtr_config(dev_link_t *link); +static void ibmtr_hw_setup(struct net_device *dev); +static void ibmtr_release(u_long arg); +static int ibmtr_event(event_t event, int priority, + event_callback_args_t *args); + +static dev_info_t dev_info = "ibmtr_cs"; + +static dev_link_t *ibmtr_attach(void); +static void ibmtr_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +extern int ibmtr_probe(struct net_device *dev); +unsigned char pcmcia_reality_check(unsigned char gss); + +extern int trdev_init(struct net_device *dev); +extern void tok_interrupt(int irq, struct pt_regs *regs); +extern int tok_init_card(struct net_device *dev); +extern unsigned char get_sram_size(struct tok_info *ti); + +/*====================================================================*/ + +typedef struct ibmtr_dev_t { + dev_link_t link; + struct net_device *dev; /* Changed for 2.2.0 */ + dev_node_t node; + window_handle_t sram_win_handle; + struct tok_info ti; +} ibmtr_dev_t; + +/*====================================================================== + + This bit of code is used to avoid unregistering network devices + at inappropriate times. 2.2 and later kernels are fairly picky + about when this can happen. + +======================================================================*/ + +static void flush_stale_links(void) +{ + dev_link_t *link, *next; + for (link = dev_list; link; link = next) { + next = link->next; + if (link->state & DEV_STALE_LINK) + ibmtr_detach(link); + } +} + +/*====================================================================*/ + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +/*====================================================================== + + ibmtr_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *ibmtr_attach(void) +{ + ibmtr_dev_t *info; + dev_link_t *link; + struct net_device *dev; + client_reg_t client_reg; + int i, ret; + + DEBUG(0, "ibmtr_attach()\n"); + flush_stale_links(); + + /* Create new token-ring device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) return NULL; + memset(info, 0, sizeof(*info)); + link = &info->link; link->priv = info; + + link->release.function = &ibmtr_release; + link->release.data = (u_long)link; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 4; + link->io.IOAddrLines = 16; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = &tok_interrupt; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.Present = PRESENT_OPTION; + + dev = init_trdev(NULL,0); + dev->priv = &info->ti; + link->irq.Instance = info->dev = dev; + + if (dev == NULL) { + ibmtr_detach(link); + return NULL; + } + + dev->init = &ibmtr_probe; + +#if 0 + dev->tbusy = 1; +#endif + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &ibmtr_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != 0) { + cs_error(link->handle, RegisterClient, ret); + ibmtr_detach(link); + return NULL; + } + + return link; +} /* ibmtr_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void ibmtr_detach(dev_link_t *link) +{ + struct ibmtr_dev_t *info = link->priv; + dev_link_t **linkp; + struct net_device *dev; + long flags; + + + DEBUG(0, "ibmtr_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + dev = info->dev; + + save_flags(flags); + cli(); + { + struct tok_info *ti = (struct tok_info *)dev->priv; + if (ti->tr_timer.next) del_timer(&(ti->tr_timer)); + } + if (link->state & DEV_RELEASE_PENDING) { + del_timer(&link->release); + link->state &= ~DEV_RELEASE_PENDING; + } + restore_flags(flags); + + if (link->state & DEV_CONFIG) { + ibmtr_release((u_long)link); + if (link->state & DEV_STALE_CONFIG) { + link->state |= DEV_STALE_LINK; + return; + } + } + + if (link->handle) + CardServices(DeregisterClient, link->handle); + + /* Unlink device structure, free bits */ + *linkp = link->next; + if (link->dev) + unregister_trdev(info->dev); + kfree(info); + +} /* ibmtr_detach */ + +/*====================================================================== + + ibmtr_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + token-ring device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +static void ibmtr_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; + struct tok_info *ti = dev->priv; + tuple_t tuple; + cisparse_t parse; + win_req_t req; + memreq_t mem; + int i, last_ret, last_fn; + u_char buf[64]; + unsigned char Shared_Ram_Base; + + DEBUG(0, "ibmtr_config(0x%p)\n", link); + + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = 64; + tuple.TupleOffset = 0; + tuple.DesiredTuple = CISTPL_CONFIG; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + + /* Configure card */ + link->state |= DEV_CONFIG; + + link->conf.ConfigIndex = 0x61; + + /* Determine if this is PRIMARY or ALTERNATE. */ + + /* Try PRIMARY card at 0xA20-0xA23 */ + link->io.BasePort1 = 0xA20; + i = CardServices(RequestIO, link->handle, &link->io); + if (i == CS_SUCCESS) { + memcpy(info->node.dev_name, "tr0\0", 4); + } else { + /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ + link->io.BasePort1 = 0xA24; + CS_CHECK(RequestIO, link->handle, &link->io); + memcpy(info->node.dev_name, "tr1\0", 4); + } + dev->base_addr = link->io.BasePort1; + + CS_CHECK(RequestIRQ, link->handle, &link->irq); + dev->irq = link->irq.AssignedIRQ; + ti->irq = link->irq.AssignedIRQ; + ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); + + /* Allocate the MMIO memory window */ + req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; + req.Attributes |= WIN_USE_WAIT|WIN_STRICT_ALIGN; + req.Base = mmiobase; + req.Size = 0x2000; + req.AccessSpeed = 250; + link->win = (window_handle_t) link->handle; + CS_CHECK(RequestWindow, &link->win, &req); + mem.CardOffset = req.Base; + mem.Page = 0; + CS_CHECK(MapMemPage, link->win, &mem); + ti->mmio = (u_long)ioremap(req.Base, req.Size); + + /* Allocate the SRAM memory window */ + req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; + req.Attributes |= WIN_USE_WAIT|WIN_MAP_BELOW_1MB; + req.Base = srambase; + req.Size = sramsize * 1024; + req.AccessSpeed = 250; + info->sram_win_handle = (window_handle_t)link->handle; + CS_CHECK(RequestWindow, &info->sram_win_handle, &req); + + mem.CardOffset = req.Base; + mem.Page = 0; + CS_CHECK(MapMemPage, info->sram_win_handle, &mem); + Shared_Ram_Base = req.Base >> 12; + + ti->sram = 0; + ti->sram_base = Shared_Ram_Base; + + CS_CHECK(RequestConfiguration, link->handle, &link->conf); + + /* Set up the Token-Ring Controller Configuration Register and + turn on the card. Check the "Local Area Network Credit Card + Adapters Technical Reference" SC30-3585 for this info. */ + ibmtr_hw_setup(dev); + +#if 0 + dev->tbusy = 0; +#endif + + i = register_trdev(dev); + + if (i != 0) { + printk(KERN_NOTICE "ibmtr_cs: register_trdev() failed\n"); + goto failed; + } + + link->dev = &info->node; + link->state &= ~DEV_CONFIG_PENDING; + + printk(KERN_INFO "%s: port %#3lx, irq %d,", + dev->name, dev->base_addr, dev->irq); + printk (" mmio %#5lx,", (u_long)ti->mmio); + printk (" sram %#5lx,", (u_long)ti->sram_base << 12); + printk ("\n" KERN_INFO " hwaddr="); + for (i = 0; i < TR_ALEN; i++) + printk("%02X", dev->dev_addr[i]); + printk("\n"); + return; + +cs_failed: + cs_error(link->handle, last_fn, last_ret); +failed: + ibmtr_release((u_long)link); +} /* ibmtr_config */ + +/*====================================================================== + + After a card is removed, ibmtr_release() will unregister the net + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void ibmtr_release(u_long arg) +{ + dev_link_t *link = (dev_link_t *)arg; + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; + struct tok_info *ti=(struct tok_info *) dev->priv; + + DEBUG(0, "ibmtr_release(0x%p)\n", link); + + if (link->open) { + DEBUG(1, "ibmtr_cs: release postponed, '%s' " + "still open\n", info->node.dev_name); + link->state |= DEV_STALE_CONFIG; + return; + } + + ti->open_status=CLOSED; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + if (link->win) { + struct tok_info *ti = dev->priv; + iounmap((void *)ti->mmio); + CardServices(ReleaseWindow, link->win); + CardServices(ReleaseWindow, info->sram_win_handle); + } + + link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); + +} /* ibmtr_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the net drivers from trying + to talk to the card any more. + +======================================================================*/ + +static int ibmtr_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; + + DEBUG(1, "ibmtr_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { +#if 0 + dev->tbusy = 1; dev->start = 0; +#endif + link->release.expires = jiffies + HZ/20; + link->state |= DEV_RELEASE_PENDING; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT; + ibmtr_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) { +#if 0 + if (link->open) { + dev->tbusy = 1; dev->start = 0; + } +#endif + CardServices(ReleaseConfiguration, link->handle); + } + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) { + CardServices(RequestConfiguration, link->handle, &link->conf); + if (link->open) { + (dev->init)(dev); +#if 0 + dev->tbusy = 0; dev->start = 1; +#endif + } + } + break; + } + return 0; +} /* ibmtr_event */ + +/*====================================================================*/ + +static void ibmtr_hw_setup(struct net_device *dev) +{ + struct tok_info *ti = dev->priv; + int i; + + /* Bizarre IBM behavior, there are 16 bits of information we + need to set, but the card only allows us to send 4 bits at a + time. For each byte sent to base_addr, bits 7-4 tell the + card which part of the 16 bits we are setting, bits 3-0 contain + the actual information */ + + /* First nibble provides 4 bits of mmio */ + i = ((int)ti->mmio >> 16) & 0x0F; + outb(i, dev->base_addr); + + /* Second nibble provides 3 bits of mmio */ + i = 0x10 | (((int)ti->mmio >> 12) & 0x0E); + outb(i, dev->base_addr); + + /* Third nibble, hard-coded values */ + i = 0x26; + outb(i, dev->base_addr); + + /* Fourth nibble sets shared ram page size */ + + /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */ + + i = (sramsize >> 4) & 0x07; + i = ((i == 4) ? 3 : i) << 2; + i |= 0x30; + + if (ringspeed == 16) + i |= 2; + if (dev->base_addr == 0xA24) + i |= 1; + outb(i, dev->base_addr); + + /* X40 will release the card for use */ + + outb(0x40, dev->base_addr); + + return; +} + +/*====================================================================== + + A sweet little function that circumvents the problem with + ibmtr.c trying to use more memory than we can allocate for + the PCMCIA card. ibmtr.c just assumes that if a card has + 64K of shared ram, the entire 64K must be mapped into memory, + whereas resources are sometimes a little tight in card services + so we fool ibmtr.c into thinking the card has less memory on + it than it has. + +======================================================================*/ + +unsigned char pcmcia_reality_check(unsigned char gss) +{ + return (gss < sramsize) ? sramsize : gss; +} + +/*====================================================================*/ + +static int __init init_ibmtr_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "ibmtr_cs: Card Services release " + "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &ibmtr_attach, &ibmtr_detach); + return 0; +} + +static void __exit exit_ibmtr_cs(void) +{ + DEBUG(0, "ibmtr_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + ibmtr_detach(dev_list); +} + +module_init(init_ibmtr_cs); +module_exit(exit_ibmtr_cs); diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 0dfffbc8edec..f206a44f9c32 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -88,6 +88,9 @@ * to support windowing into on adapter shared ram. * i.e. Use LANAID to setup a PnP configuration with 16K RAM. Paging * will shift this 16K window over the entire available shared RAM. + * + * Changes by Peter De Schrijver (p2@mind.be) : + * + fixed a problem with PCMCIA card removal */ /* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value @@ -95,16 +98,8 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */ #define IBMTR_DEBUG_MESSAGES 0 -#ifdef PCMCIA -#define MODULE -#endif - #include -#ifdef PCMCIA -#undef MODULE -#endif - #define NO_AUTODETECT 1 #undef NO_AUTODETECT /* #undef ENABLE_PAGING */ @@ -161,13 +156,13 @@ static char mcchannelid[] = { #include #include #include +#include #include #include #include #include -#include "ibmtr.h" #define DPRINTK(format, args...) printk("%s: " format, dev->name , ## args) @@ -814,6 +809,9 @@ static void tok_set_multicast_list(struct net_device *dev) int i; + if(ti->open_status==CLOSED) + return; + address[0] = address[1] = address[2] = address[3] = 0; mclist = dev->mc_list; @@ -870,26 +868,28 @@ static int tok_close(struct net_device *dev) struct tok_info *ti=(struct tok_info *) dev->priv; - netif_stop_queue(dev); - SET_PAGE(ti->srb_page); - isa_writeb(DIR_CLOSE_ADAPTER, - ti->srb + offsetof(struct srb_close_adapter, command)); - isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + if(ti->open_status!=CLOSED) { + netif_stop_queue(dev); + SET_PAGE(ti->srb_page); + isa_writeb(DIR_CLOSE_ADAPTER, + ti->srb + offsetof(struct srb_close_adapter, command)); + isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - ti->open_status=CLOSED; + ti->open_status=CLOSED; - sleep_on(&ti->wait_for_tok_int); + sleep_on(&ti->wait_for_tok_int); - SET_PAGE(ti->srb_page); - if (isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) - DPRINTK("close adapter failed: %02X\n", - (int)isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); + SET_PAGE(ti->srb_page); + if (isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) + DPRINTK("close adapter failed: %02X\n", + (int)isa_readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); #ifdef PCMCIA - ti->sram = 0 ; + ti->sram = 0 ; #endif - DPRINTK("Adapter closed.\n"); - MOD_DEC_USE_COUNT; + DPRINTK("Adapter closed.\n"); + MOD_DEC_USE_COUNT; + } return 0; } @@ -937,6 +937,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) if (status == 0xFF) { DPRINTK("PCMCIA card removed.\n"); + ti->open_status=CLOSED; goto return_point ; } @@ -944,6 +945,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) if ( isa_readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) { DPRINTK("PCMCIA card removed.\n"); + ti->open_status=CLOSED; goto return_point ; } #endif @@ -1851,6 +1853,7 @@ int ibmtr_change_mtu(struct net_device *dev, int mtu) { return 0; } +#ifndef PCMCIA #ifdef MODULE /* 3COM 3C619C supports 8 interrupts, 32 I/O ports */ @@ -1908,3 +1911,4 @@ void cleanup_module(void) } } #endif /* MODULE */ +#endif diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index f1c618a90541..7b369c00439b 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -1316,7 +1316,7 @@ EXPORT_SYMBOL(z8530_shutdown); * @rtable: Table of register, value pairs * FIXME: ioctl to allow user uploaded tables * - * Load a Z8530 channel up from the system data> We use +16 to + * Load a Z8530 channel up from the system data. We use +16 to * indicate the 'prime' registers. The value 255 terminates the * table */ diff --git a/drivers/parport/share.c b/drivers/parport/share.c index fe5ea143b58c..c280e9af3a68 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -341,17 +341,25 @@ struct pardevice *parport_register_device(struct parport *port, const char *name } } + /* We up our own module reference count, and that of the port + on which a device is to be registered, to ensure that + neither of us gets unloaded while we sleep in (e.g.) + kmalloc. To be absolutely safe, we have to require that + our caller doesn't sleep in between parport_enumerate and + parport_register_device.. */ + inc_parport_count(); + port->ops->inc_use_count(); + tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); if (tmp == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); - return NULL; + goto out; } tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL); if (tmp->state == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); - kfree(tmp); - return NULL; + goto out_free_pardevice; } tmp->name = name; @@ -376,12 +384,10 @@ struct pardevice *parport_register_device(struct parport *port, const char *name if (flags & PARPORT_DEV_EXCL) { if (port->physport->devices) { spin_unlock (&port->physport->pardevice_lock); - kfree (tmp->state); - kfree (tmp); printk (KERN_DEBUG "%s: cannot grant exclusive access for " "device %s\n", port->name, name); - return NULL; + goto out_free_all; } port->flags |= PARPORT_FLAG_EXCL; } @@ -392,9 +398,6 @@ struct pardevice *parport_register_device(struct parport *port, const char *name port->physport->devices = tmp; spin_unlock(&port->physport->pardevice_lock); - inc_parport_count(); - port->ops->inc_use_count(); - init_waitqueue_head(&tmp->wait_q); tmp->timeslice = parport_default_timeslice; tmp->waitnext = tmp->waitprev = NULL; @@ -406,6 +409,15 @@ struct pardevice *parport_register_device(struct parport *port, const char *name port->ops->init_state(tmp, tmp->state); parport_device_proc_register(tmp); return tmp; + + out_free_all: + kfree (tmp->state); + out_free_pardevice: + kfree (tmp); + out: + dec_parport_count(); + port->ops->dec_use_count(); + return NULL; } void parport_unregister_device(struct pardevice *dev) diff --git a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx index 8f4d4f19cfc1..678042b166f4 100644 --- a/drivers/scsi/ChangeLog.ncr53c8xx +++ b/drivers/scsi/ChangeLog.ncr53c8xx @@ -1,3 +1,13 @@ +Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 3.2h + - Fix a compilation problem on Alpha introduced in version 3.2g. + (`port' changed to `base_io'). + - Move from `sym' to this driver a tiny change for __sparc__ that + applies to cache line size (? Probably from David S Miller). + - Make sure no data transfer will happen for Scsi_Cmnd requests + that supply SCSI_DATA_NONE direction (this avoids some BUG() + statement in the PCI code when a data buffer is also supplied). + Mon March 6 23:15 2000 Gerard Roudier (groudier@club-internet.fr) * revision 3.2g - Add the file sym53c8xx_comm.h that collects code that should diff --git a/drivers/scsi/ChangeLog.sym53c8xx b/drivers/scsi/ChangeLog.sym53c8xx index 47448ec7140e..84f7ea1c8c40 100644 --- a/drivers/scsi/ChangeLog.sym53c8xx +++ b/drivers/scsi/ChangeLog.sym53c8xx @@ -1,3 +1,11 @@ +Sat Apr 1 12:00 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 1.5l + - Tiny change for __sparc__ appeared in 2.3.99-pre4.1 that + applies to cache line size (? Probably from David S Miller). + - Make sure no data transfer will happen for Scsi_Cmnd requests + that supply SCSI_DATA_NONE direction (this avoids some BUG() + statement in the PCI code when a data buffer is also supplied). + Mon Mar 6 23:30 2000 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5k - Test against expected data transfer direction from SCRIPTS. diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 5fc1bfaabbd5..e40cdb7c2764 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -104,7 +104,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2g" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2h" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -1120,7 +1120,7 @@ struct ncb { u_char revision_id; /* PCI device revision id */ u_char bus; /* PCI BUS number */ u_char device_fn; /* PCI BUS device and function */ - u_long port; /* IO space base address */ + u_long base_io; /* IO space base address */ u_int irq; /* IRQ level */ u_int features; /* Chip features map */ u_char myaddr; /* SCSI id of the adapter */ @@ -3734,7 +3734,7 @@ ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) */ request_region(device->slot.io_port, 128, "ncr53c8xx"); - np->port = device->slot.io_port; + np->base_io = device->slot.io_port; #ifdef SCSI_NCR_NVRAM_SUPPORT if (nvram) { @@ -3951,11 +3951,11 @@ attach_error: unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128); } #endif /* !NCR_IOMAPPED */ - if (np->port) { + if (np->base_io) { #ifdef DEBUG_NCR53C8XX - printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); + printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128); #endif - release_region(np->port, 128); + release_region(np->base_io, 128); } if (np->irq) { #ifdef DEBUG_NCR53C8XX @@ -4260,11 +4260,17 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ - segments = ncr_scatter (np, cp, cp->cmd); - - if (segments < 0) { - ncr_free_ccb(np, cp); - return(DID_ERROR); + direction = scsi_data_direction(cmd); + if (direction != SCSI_DATA_NONE) { + segments = ncr_scatter (np, cp, cp->cmd); + if (segments < 0) { + ncr_free_ccb(np, cp); + return(DID_ERROR); + } + } + else { + cp->data_len = 0; + segments = 0; } /*---------------------------------------------------- @@ -4275,8 +4281,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) */ if (!cp->data_len) direction = SCSI_DATA_NONE; - else - direction = scsi_data_direction(cmd); /* ** If data direction is UNKNOWN, speculate DATA_READ @@ -4796,9 +4800,9 @@ static int ncr_detach(ncb_p np) #endif /* !NCR_IOMAPPED */ #ifdef DEBUG_NCR53C8XX - printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->port, 128); + printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128); #endif - release_region(np->port, 128); + release_region(np->base_io, 128); /* ** Free allocated ccb(s) diff --git a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c index cae4892c7ee1..5c57cb275f24 100644 --- a/drivers/scsi/sym53c8xx.c +++ b/drivers/scsi/sym53c8xx.c @@ -84,7 +84,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5k" +#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5l" /* #define DEBUG_896R1 */ #define SCSI_NCR_OPTIMIZE_896 @@ -6303,7 +6303,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) lcb_p lp = ncr_lp(np, tp, cmd->lun); ccb_p cp; - int segments; u_char idmsg, *msgptr; u_int msglen; int direction; @@ -6452,11 +6451,17 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) **---------------------------------------------------- */ - cp->segments = segments = np->scatter (np, cp, cp->cmd); - - if (segments < 0) { - ncr_free_ccb(np, cp); - return(DID_ERROR); + direction = scsi_data_direction(cmd); + if (direction != SCSI_DATA_NONE) { + cp->segments = np->scatter (np, cp, cp->cmd); + if (cp->segments < 0) { + ncr_free_ccb(np, cp); + return(DID_ERROR); + } + } + else { + cp->data_len = 0; + cp->segments = 0; } /*---------------------------------------------------- @@ -6467,8 +6472,6 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) */ if (!cp->data_len) direction = SCSI_DATA_NONE; - else - direction = scsi_data_direction(cmd); /* ** If data direction is UNKNOWN, speculate DATA_READ @@ -6480,7 +6483,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) case SCSI_DATA_UNKNOWN: case SCSI_DATA_WRITE: goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; - lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4)); + lastp = goalp - 8 - (cp->segments * (SCR_SG_SIZE*4)); if (direction != SCSI_DATA_UNKNOWN) break; cp->phys.header.wgoalp = cpu_to_scr(goalp); @@ -6489,7 +6492,7 @@ static int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd) case SCSI_DATA_READ: cp->host_flags |= HF_DATA_IN; goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; - lastp = goalp - 8 - (segments * (SCR_SG_SIZE*4)); + lastp = goalp - 8 - (cp->segments * (SCR_SG_SIZE*4)); break; default: case SCSI_DATA_NONE: diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h index fa02ff585ef4..a9cc78a54bb3 100644 --- a/drivers/scsi/sym53c8xx_comm.h +++ b/drivers/scsi/sym53c8xx_comm.h @@ -2497,16 +2497,6 @@ sym53c8xx_pci_init(Scsi_Host_Template *tpnt, pcidev_t pdev, ncr_device *device) #endif #endif /* __powerpc__ */ -#ifdef __sparc__ - /* - ** Fix-ups for sparc. - */ - if (!cache_line_size) - suggested_cache_line_size = 16; - - driver_setup.pci_fix_up |= 0x7; -#endif /* __sparc__ */ - #if defined(__i386__) && !defined(MODULE) if (!cache_line_size) { #if LINUX_VERSION_CODE < LinuxVersionCode(2,1,75) diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 046379d37d6b..4d039b21c04c 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -138,10 +138,6 @@ MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) -ifeq ($(CONFIG_LOWLEVEL_SOUND),y) - O_OBJS += lowlevel/lowlevel.o -endif - include $(TOPDIR)/Rules.make diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 0a1e2981c11f..4a1a395064c4 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -26,15 +26,13 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, struct audio_operations *op; int l, num; - if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) - { + if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) { printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); return -(EINVAL); } num = sound_alloc_audiodev(); - if (num == -1) - { + if (num == -1) { printk(KERN_ERR "sound: Too many audio drivers\n"); return -(EBUSY); } @@ -47,8 +45,7 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, if (sound_nblocks < 1024) sound_nblocks++; - if (d == NULL || op == NULL) - { + if (d == NULL || op == NULL) { printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); sound_unload_audiodev(num); return -(ENOMEM); @@ -91,14 +88,12 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, int n = sound_alloc_mixerdev(); - if (n == -1) - { + if (n == -1) { printk(KERN_ERR "Sound: Too many mixer drivers\n"); return -EBUSY; } if (vers != MIXER_DRIVER_VERSION || - driver_size > sizeof(struct mixer_operations)) - { + driver_size > sizeof(struct mixer_operations)) { printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); return -EINVAL; } @@ -110,8 +105,7 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, if (sound_nblocks < 1024) sound_nblocks++; - if (op == NULL) - { + if (op == NULL) { printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); return -ENOMEM; } @@ -131,8 +125,7 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, void sound_unload_audiodev(int dev) { - if (dev != -1) - { + if (dev != -1) { DMAbuf_deinit(dev); audio_devs[dev] = NULL; unregister_sound_dsp((dev<<4)+3); @@ -165,10 +158,8 @@ int sound_alloc_synthdev(void) { int i; - for (i = 0; i < MAX_SYNTH_DEV; i++) - { - if (synth_devs[i] == NULL) - { + for (i = 0; i < MAX_SYNTH_DEV; i++) { + if (synth_devs[i] == NULL) { if (i >= num_synths) num_synths++; return i; @@ -192,10 +183,8 @@ int sound_alloc_timerdev(void) { int i; - for (i = 0; i < MAX_TIMER_DEV; i++) - { - if (sound_timer_devs[i] == NULL) - { + for (i = 0; i < MAX_TIMER_DEV; i++) { + if (sound_timer_devs[i] == NULL) { if (i >= num_sound_timers) num_sound_timers++; return i; @@ -206,8 +195,7 @@ int sound_alloc_timerdev(void) void sound_unload_mixerdev(int dev) { - if (dev != -1) - { + if (dev != -1) { mixer_devs[dev] = NULL; unregister_sound_mixer(dev<<4); num_mixers--; @@ -216,8 +204,7 @@ void sound_unload_mixerdev(int dev) void sound_unload_mididev(int dev) { - if (dev != -1) - { + if (dev != -1) { midi_devs[dev] = NULL; unregister_sound_midi((dev<<4)+2); } diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index a5525a4bf21c..4c71c1265155 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -133,9 +133,6 @@ struct dma_buffparms char neutral_byte; int dma; /* DMA channel */ -#ifdef OS_DMA_PARMS - OS_DMA_PARMS -#endif int applic_profile; /* Application profile (APF_*) */ /* Interrupt callback stuff */ void (*audio_callback) (int dev, int parm); @@ -347,7 +344,6 @@ struct sound_timer_operations }; #ifdef _DEV_TABLE_C_ - struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0; struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; @@ -356,20 +352,12 @@ struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0; struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0; -#ifndef EXCLUDE_TIMERS + extern struct sound_timer_operations default_sound_timer; struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { &default_sound_timer, NULL }; int num_sound_timers = 1; -#else -struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { - NULL -}; -int num_sound_timers = 0; -#endif - - #else extern struct audio_operations *audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; @@ -384,8 +372,6 @@ extern int num_sound_timers; #endif /* _DEV_TABLE_C_ */ extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info); -int sndtable_probe (int unit, struct address_info *hw_config); -int sndtable_start_card (int unit, struct address_info *hw_config); void sound_timer_init (struct sound_lowlev_timer *t, char *name); void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan); diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index 8d450ca66ad4..ffa0c1caf3ce 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -89,10 +89,3 @@ void sound_timer_syncinterval(unsigned int new_usecs); /* From midi_synth.c */ void do_midi_msg (int synthno, unsigned char *msg, int mlen); - -#ifdef FIXED_LOWLEVEL_SOUND -/* From aedsp16.c */ -int InitAEDSP16_SBPRO(struct address_info *hw_config); -int InitAEDSP16_MSS(struct address_info *hw_config); -int InitAEDSP16_MPU401(struct address_info *hw_config); -#endif diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 217bdb605575..c0d6dd06a7ea 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -218,7 +218,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit) static struct sound_unit *chains[16]; /** - * register_sound_special + * register_sound_special - register a special sound node * @fops: File operations for the driver * @unit: Unit number to allocate * @@ -288,7 +288,7 @@ int register_sound_special(struct file_operations *fops, int unit) EXPORT_SYMBOL(register_sound_special); /** - * register_sound_mixer + * register_sound_mixer - register a mixer device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -306,7 +306,7 @@ int register_sound_mixer(struct file_operations *fops, int dev) EXPORT_SYMBOL(register_sound_mixer); /** - * register_sound_midi + * register_sound_midi - register a midi device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -329,7 +329,7 @@ EXPORT_SYMBOL(register_sound_midi); */ /** - * register_sound_dsp + * register_sound_dsp - register a DSP device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -350,7 +350,7 @@ int register_sound_dsp(struct file_operations *fops, int dev) EXPORT_SYMBOL(register_sound_dsp); /** - * register_sound_synth + * register_sound_synth - register a synth device * @fops: File operations for the driver * @dev: Unit number to allocate * @@ -369,7 +369,7 @@ int register_sound_synth(struct file_operations *fops, int dev) EXPORT_SYMBOL(register_sound_synth); /** - * unregister_sound_special + * unregister_sound_special - unregister a special sound device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_special. @@ -385,7 +385,7 @@ void unregister_sound_special(int unit) EXPORT_SYMBOL(unregister_sound_special); /** - * unregister_sound_mixer + * unregister_sound_mixer - unregister a mixer * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_mixer. @@ -400,7 +400,7 @@ void unregister_sound_mixer(int unit) EXPORT_SYMBOL(unregister_sound_mixer); /** - * unregister_sound_midi + * unregister_sound_midi - unregister a midi device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_midi. @@ -415,7 +415,7 @@ void unregister_sound_midi(int unit) EXPORT_SYMBOL(unregister_sound_midi); /** - * unregister_sound_dsp + * unregister_sound_dsp - unregister a DSP device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_dsp. @@ -433,7 +433,7 @@ void unregister_sound_dsp(int unit) EXPORT_SYMBOL(unregister_sound_dsp); /** - * unregister_sound_synth + * unregister_sound_synth - unregister a synth device * @unit: Unit number to allocate * * Release a sound device that was allocated with register_sound_synth. diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index f3b008f0c27f..f222592ea83a 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -46,14 +46,6 @@ #include "soundmodule.h" -#if defined(CONFIG_LOWLEVEL_SOUND) && !defined MODULE -extern void sound_preinit_lowlevel_drivers(void); -extern void sound_init_lowlevel_drivers(void); -#endif - -/* From obsolete legacy.h */ -#define SELECTED_SOUND_OPTIONS 0x0 - struct notifier_block *sound_locker=(struct notifier_block *)0; static int lock_depth = 0; @@ -65,7 +57,6 @@ static int lock_depth = 0; #endif static int chrdev_registered = 0; -static int is_unloading = 0; /* * Table for permanently allocated memory (used when unloading the module) @@ -80,7 +71,6 @@ int sound_dmap_flag = 1; int sound_dmap_flag = 0; #endif -static int soundcard_configured = 0; static char dma_alloc_map[MAX_DMA_CHANNELS] = {0}; #define DMA_MAP_UNAVAIL 0 @@ -101,17 +91,14 @@ int *load_mixer_volumes(char *name, int *levels, int present) { int i, n; - for (i = 0; i < num_mixer_volumes; i++) - { - if (strcmp(name, mixer_vols[i].name) == 0) - { + for (i = 0; i < num_mixer_volumes; i++) { + if (strcmp(name, mixer_vols[i].name) == 0) { if (present) mixer_vols[i].num = i; return mixer_vols[i].levels; } } - if (num_mixer_volumes >= MAX_MIXER_DEV) - { + if (num_mixer_volumes >= MAX_MIXER_DEV) { printk(KERN_ERR "Sound: Too many mixers (%s)\n", name); return levels; } @@ -229,26 +216,15 @@ static long long sound_lseek(struct file *file, long long offset, int orig) static int sound_open(struct inode *inode, struct file *file) { - int dev, retval; + int dev = MINOR(inode->i_rdev); + int retval; - if (is_unloading) { - /* printk(KERN_ERR "Sound: Driver partially removed. Can't open device\n");*/ - return -EBUSY; - } - dev = MINOR(inode->i_rdev); - if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS) { - /* printk("SoundCard Error: The sound system has not been configured\n");*/ - return -ENXIO; - } DEB(printk("sound_open(dev=%d)\n", dev)); if ((dev >= SND_NDEVS) || (dev < 0)) { /* printk(KERN_ERR "Invalid minor device %d\n", dev);*/ return -ENXIO; } switch (dev & 0x0f) { - case SND_DEV_STATUS: - break; - case SND_DEV_CTL: dev >>= 4; if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) { @@ -296,7 +272,6 @@ static int sound_release(struct inode *inode, struct file *file) DEB(printk("sound_release(dev=%d)\n", dev)); switch (dev & 0x0f) { - case SND_DEV_STATUS: case SND_DEV_CTL: break; @@ -470,45 +445,38 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma) dev_class = dev & 0x0f; dev >>= 4; - if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) - { -/* printk("Sound: mmap() not supported for other than audio devices\n");*/ + if (dev_class != SND_DEV_DSP && dev_class != SND_DEV_DSP16 && dev_class != SND_DEV_AUDIO) { + printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); return -EINVAL; } if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ dmap = audio_devs[dev]->dmap_out; else if (vma->vm_flags & VM_READ) dmap = audio_devs[dev]->dmap_in; - else - { -/* printk("Sound: Undefined mmap() access\n");*/ + else { + printk(KERN_ERR "Sound: Undefined mmap() access\n"); return -EINVAL; } - if (dmap == NULL) - { -/* printk("Sound: mmap() error. dmap == NULL\n");*/ + if (dmap == NULL) { + printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); return -EIO; } - if (dmap->raw_buf == NULL) - { -/* printk("Sound: mmap() called when raw_buf == NULL\n");*/ + if (dmap->raw_buf == NULL) { + printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); return -EIO; } - if (dmap->mapping_flags) - { -/* printk("Sound: mmap() called twice for the same DMA buffer\n");*/ + if (dmap->mapping_flags) { + printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); return -EIO; } - if (vma->vm_pgoff != 0) - { -/* printk("Sound: mmap() offset must be 0.\n");*/ + if (vma->vm_pgoff != 0) { + printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); return -EINVAL; } size = vma->vm_end - vma->vm_start; - if (size != dmap->bytes_in_use) - { + if (size != dmap->bytes_in_use) { printk(KERN_WARNING "Sound: mmap() size = %ld. Should be %d\n", size, dmap->bytes_in_use); } if (remap_page_range(vma->vm_start, virt_to_phys(dmap->raw_buf), @@ -546,19 +514,14 @@ struct file_operations oss_sound_fops = static int create_special_devices(void) { int seq1,seq2; - int sndstat=register_sound_special(&oss_sound_fops, 6); - if(sndstat==-1) - goto bad1; seq1=register_sound_special(&oss_sound_fops, 1); if(seq1==-1) - goto bad2; + goto bad; seq2=register_sound_special(&oss_sound_fops, 8); if(seq2!=-1) return 0; unregister_sound_special(1); -bad2: - unregister_sound_special(6); -bad1: +bad: return -1; } @@ -594,30 +557,27 @@ soundcard_make_name(char *buf, char *name, int idx) { /* Register/unregister audio entries */ static void soundcard_register_devfs (int do_register) { - char name_buf[32]; - int i, j, num; - - for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) - { - num = (dev_list[i].num == NULL) ? 0 : *dev_list[i].num; - for (j = 0; j < num || j == 0; j++) - { - soundcard_make_name (name_buf, dev_list[i].name, j); - if (do_register) - devfs_register (NULL, name_buf, 0, DEVFS_FL_NONE, - SOUND_MAJOR, dev_list[i].minor+ (j* 0x10), - S_IFCHR | dev_list[i].mode, 0, 0, - &oss_sound_fops, NULL); - else - { - devfs_handle_t de; - - de = devfs_find_handle (NULL, name_buf, 0, 0, 0, + char name_buf[32]; + int i, j, num; + + for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { + num = (dev_list[i].num == NULL) ? 0 : *dev_list[i].num; + for (j = 0; j < num || j == 0; j++) { + soundcard_make_name (name_buf, dev_list[i].name, j); + if (do_register) + devfs_register (NULL, name_buf, 0, DEVFS_FL_NONE, + SOUND_MAJOR, dev_list[i].minor+ (j* 0x10), + S_IFCHR | dev_list[i].mode, 0, 0, + &oss_sound_fops, NULL); + else { + devfs_handle_t de; + + de = devfs_find_handle (NULL, name_buf, 0, 0, 0, DEVFS_SPECIAL_CHR, 0); - devfs_unregister (de); - } + devfs_unregister (de); + } + } } - } } #ifdef MODULE @@ -638,10 +598,6 @@ soundcard_init(void) chrdev_registered = 1; #endif - soundcard_configured = 1; - - audio_init_devices(); - soundcard_register_devfs(1); /* register after we know # of devices */ } @@ -650,14 +606,9 @@ soundcard_init(void) static void destroy_special_devices(void) { unregister_sound_special(6); - unregister_sound_special(1); unregister_sound_special(8); } -static int sound[20] = { - 0 -}; - static int dmabuf = 0; static int dmabug = 0; @@ -668,12 +619,12 @@ int init_module(void) { int err; +#ifdef CONFIG_PCI if(dmabug) isa_dma_bridge_buggy = dmabug; - +#endif err = create_special_devices(); - if (err) - { + if (err) { printk(KERN_ERR "sound: driver already loaded/included in kernel\n"); return err; } @@ -695,10 +646,8 @@ void cleanup_module(void) int i; if (MOD_IN_USE) - { return; - } - remove_proc_entry("sound", NULL); + soundcard_register_devfs (0); if (chrdev_registered) destroy_special_devices(); @@ -708,17 +657,13 @@ void cleanup_module(void) sequencer_unload(); for (i = 0; i < MAX_DMA_CHANNELS; i++) - { - if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) - { + if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { printk(KERN_ERR "Sound: Hmm, DMA%d was left allocated - fixed\n", i); sound_free_dma(i); } - } + for (i = 0; i < sound_nblocks; i++) - { vfree(sound_mem_blocks[i]); - } } #endif @@ -739,16 +684,14 @@ int sound_open_dma(int chn, char *deviceID) { unsigned long flags; - if (!valid_dma(chn)) - { + if (!valid_dma(chn)) { printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn); return 1; } save_flags(flags); cli(); - if (dma_alloc_map[chn] != DMA_MAP_FREE) - { + if (dma_alloc_map[chn] != DMA_MAP_FREE) { printk("sound_open_dma: DMA channel %d busy or not allocated (%d)\n", chn, dma_alloc_map[chn]); restore_flags(flags); return 1; @@ -760,8 +703,7 @@ int sound_open_dma(int chn, char *deviceID) void sound_free_dma(int chn) { - if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) - { + if (dma_alloc_map[chn] == DMA_MAP_UNAVAIL) { /* printk( "sound_free_dma: Bad access to DMA channel %d\n", chn); */ return; } @@ -776,8 +718,7 @@ void sound_close_dma(int chn) save_flags(flags); cli(); - if (dma_alloc_map[chn] != DMA_MAP_BUSY) - { + if (dma_alloc_map[chn] != DMA_MAP_BUSY) { printk(KERN_ERR "sound_close_dma: Bad access to DMA channel %d\n", chn); restore_flags(flags); return; @@ -799,8 +740,7 @@ void request_sound_timer(int count) { extern unsigned long seq_time; - if (count < 0) - { + if (count < 0) { seq_timer.expires = (-count) + jiffies; add_timer(&seq_timer); return; @@ -879,8 +819,7 @@ void sound_notifier_chain_register(struct notifier_block *bl) * Normalise the lock count by calling the entry directly. We * have to call the module as it owns its own use counter */ - while(ctnotifier_call(bl, 1, 0); ct++; } diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 0f3195163e4e..fc4f61b34eb8 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c @@ -28,6 +28,7 @@ #include #include +#include #define PHONE_NUM_DEVICES 256 @@ -37,6 +38,7 @@ */ static struct phone_device *phone_device[PHONE_NUM_DEVICES]; +static DECLARE_MUTEX(phone_lock); /* * Open a phone device. @@ -45,29 +47,37 @@ static struct phone_device *phone_device[PHONE_NUM_DEVICES]; static int phone_open(struct inode *inode, struct file *file) { unsigned int minor = MINOR(inode->i_rdev); - int err; + int err = 0; struct phone_device *p; if (minor >= PHONE_NUM_DEVICES) return -ENODEV; + down(&phone_lock); p = phone_device[minor]; if (p == NULL) { char modname[32]; + up(&phone_lock); sprintf(modname, "char-major-%d-%d", PHONE_MAJOR, minor); request_module(modname); + down(&phone_lock); p = phone_device[minor]; if (p == NULL) - return -ENODEV; + { + err=-ENODEV; + goto end; + } } if (p->open) { err = p->open(p, file); /* Tell the device it is open */ if (err) - return err; + goto end; } file->f_op = p->f_op; - return 0; +end: + up(&phone_lock); + return err; } /* @@ -87,14 +97,18 @@ int phone_register_device(struct phone_device *p, int unit) base = unit; end = unit + 1; /* enter the loop at least one time */ } + + down(&phone_lock); for (i = base; i < end; i++) { if (phone_device[i] == NULL) { phone_device[i] = p; p->minor = i; MOD_INC_USE_COUNT; + up(&phone_lock); return 0; } } + up(&phone_lock); return -ENFILE; } @@ -104,9 +118,11 @@ int phone_register_device(struct phone_device *p, int unit) void phone_unregister_device(struct phone_device *pfd) { + down(&phone_lock); if (phone_device[pfd->minor] != pfd) panic("phone: bad unregister"); phone_device[pfd->minor] = NULL; + up(&phone_lock); MOD_DEC_USE_COUNT; } diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c index 723ceb481120..da97fd29c498 100644 --- a/drivers/usb/acm.c +++ b/drivers/usb/acm.c @@ -52,6 +52,10 @@ #define DEBUG #include +void tty_register_devfs (struct tty_driver *driver, unsigned int flags, + unsigned minor); +void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); + /* * CMSPAR, some architectures can't have space and mark parity. */ @@ -143,6 +147,7 @@ struct acm { }; static struct usb_driver acm_driver; +static struct tty_driver acm_tty_driver; static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ }; #define ACM_READY(acm) (acm && acm->dev && acm->used) @@ -318,6 +323,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) return; } + tty_unregister_devfs(&acm_tty_driver, acm->minor); acm_table[acm->minor] = NULL; kfree(acm); } @@ -572,6 +578,7 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum) usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + tty_register_devfs(&acm_tty_driver, 0, minor); return acm_table[minor] = acm; } @@ -599,6 +606,7 @@ static void acm_disconnect(struct usb_device *dev, void *ptr) usb_driver_release_interface(&acm_driver, acm->iface + 1); if (!acm->used) { + tty_unregister_devfs(&acm_tty_driver, acm->minor); acm_table[acm->minor] = NULL; kfree(acm); return; @@ -630,14 +638,14 @@ static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS]; static struct tty_driver acm_tty_driver = { magic: TTY_DRIVER_MAGIC, - driver_name: "usb", - name: "ttyACM", + driver_name: "acm", + name: "usb/acm/%d", major: ACM_TTY_MAJOR, minor_start: 0, num: ACM_TTY_MINORS, type: TTY_DRIVER_TYPE_SERIAL, subtype: SERIAL_TYPE_NORMAL, - flags: TTY_DRIVER_REAL_RAW, + flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS, refcount: &acm_tty_refcount, diff --git a/drivers/usb/evdev.c b/drivers/usb/evdev.c index ac332a053901..307544ee8ead 100644 --- a/drivers/usb/evdev.c +++ b/drivers/usb/evdev.c @@ -192,12 +192,59 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) return 0; } +static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct evdev_list *list = file->private_data; + struct evdev *evdev = list->evdev; + struct input_dev *dev = evdev->handle.dev; + + switch (cmd) { + + case EVIOCGVERSION: + return put_user(EV_VERSION, (__u32 *) arg); + case EVIOCGID: + return copy_to_user(&dev->id, (void *) arg, + sizeof(struct input_id)) ? -EFAULT : 0; + default: + + if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) + return -EINVAL; + + if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { + + long *bits = NULL; + int len = 0; + + switch (_IOC_NR(cmd) & EV_MAX) { + case 0: bits = dev->evbit; len = EV_MAX; break; + case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; + case EV_REL: bits = dev->relbit; len = REL_MAX; break; + case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; + case EV_LED: bits = dev->ledbit; len = LED_MAX; break; + case EV_SND: bits = dev->sndbit; len = SND_MAX; break; + default: return -EINVAL; + } + len = NBITS(len) * sizeof(long); + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user((void *) arg, bits, len) ? -EFAULT : len; + } + + if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { + int len = strlen(dev->name) + 1; + if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); + return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len; + } + } + return -EINVAL; +} + static struct file_operations evdev_fops = { read: evdev_read, write: evdev_write, poll: evdev_poll, open: evdev_open, release: evdev_release, + ioctl: evdev_ioctl, fasync: evdev_fasync, }; diff --git a/drivers/usb/ibmcam.c b/drivers/usb/ibmcam.c index fe93e5bcc612..2deab03fa631 100644 --- a/drivers/usb/ibmcam.c +++ b/drivers/usb/ibmcam.c @@ -58,6 +58,8 @@ typedef enum { #define FLAGS_DISPLAY_HINTS (1 << 2) #define FLAGS_OVERLAY_STATS (1 << 3) #define FLAGS_FORCE_TESTPATTERN (1 << 4) +#define FLAGS_SEPARATE_FRAMES (1 << 5) +#define FLAGS_CLEAN_FRAMES (1 << 6) static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */ @@ -2238,6 +2240,12 @@ static void ibmcam_stop_isoc(struct usb_ibmcam *ibmcam) } } +/* + * ibmcam_new_frame() + * + * History: + * 29-Mar-00 Added copying of previous frame into the current one. + */ static int ibmcam_new_frame(struct usb_ibmcam *ibmcam, int framenum) { struct ibmcam_frame *frame; @@ -2258,10 +2266,33 @@ static int ibmcam_new_frame(struct usb_ibmcam *ibmcam, int framenum) frame->scanstate = STATE_SCANNING; frame->scanlength = 0; /* Accumulated in ibmcam_parse_data() */ ibmcam->curframe = framenum; -#if 0 - /* This provides a "clean" frame but slows things down */ - memset(frame->data, 0, MAX_FRAME_SIZE); -#endif + + /* + * Normally we would want to copy previous frame into the current one + * before we even start filling it with data; this allows us to stop + * filling at any moment; top portion of the frame will be new and + * bottom portion will stay as it was in previous frame. If we don't + * do that then missing chunks of video stream will result in flickering + * portions of old data whatever it was before. + * + * If we choose not to copy previous frame (to, for example, save few + * bus cycles - the frame can be pretty large!) then we have an option + * to clear the frame before using. If we experience losses in this + * mode then missing picture will be black (no flickering). + * + * Finally, if user chooses not to clean the current frame before + * filling it with data then the old data will be visible if we fail + * to refill entire frame with new data. + */ + if (!(flags & FLAGS_SEPARATE_FRAMES)) { + /* This copies previous frame into this one to mask losses */ + memmove(frame->data, ibmcam->frame[1-framenum].data, MAX_FRAME_SIZE); + } else { + if (flags & FLAGS_CLEAN_FRAMES) { + /* This provides a "clean" frame but slows things down */ + memset(frame->data, 0, MAX_FRAME_SIZE); + } + } switch (videosize) { case VIDEOSIZE_128x96: frame->frmwidth = 128; diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c index 05af63a7b28f..22875f8e9249 100644 --- a/drivers/usb/pegasus.c +++ b/drivers/usb/pegasus.c @@ -387,7 +387,7 @@ static void pegasus_set_rx_mode(struct net_device *net) (net->flags & IFF_ALLMULTI)) { pegasus_set_register(pegasus->usb, 0, 0xfa); pegasus_set_register(pegasus->usb, 2, 0); - info("%s set allmulti"); + info("%s: set allmulti", net->name); } else { info("%s: set Rx mode", net->name); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9d27d4f7ae30..19b1e9ccd235 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1,19 +1,24 @@ /* * USB FTDI SIO driver * - * (C) Copyright (C) 1999, 2000 - * Greg Kroah-Hartman (greg@kroah.com) + * (C) Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.com) * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * See Documentation/usb/usb-serial.txt for more information on using this driver - * + * + * (03/30/2000) Bill Ryder + * Implemented lots of ioctls + * Fixed a race condition in write + * Changed some dbg's to errs + * * (03/26/2000) gkh - * Split driver up into device specific pieces. - * + * Split driver up into device specific pieces. + * */ /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ @@ -54,9 +59,11 @@ #define FTDI_SIO_SERIAL_CONVERTER_ID 0x8372 /* function prototypes for a FTDI serial converter */ +static int ftdi_sio_startup (struct usb_serial *serial); static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp); static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp); static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static void ftdi_sio_write_bulk_callback (struct urb *urb); static void ftdi_sio_read_bulk_callback (struct urb *urb); static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old); static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); @@ -78,149 +85,197 @@ struct usb_serial_device_type ftdi_sio_device = { open: ftdi_sio_open, close: ftdi_sio_close, write: ftdi_sio_write, - ioctl: ftdi_sio_ioctl, read_bulk_callback: ftdi_sio_read_bulk_callback, - set_termios: ftdi_sio_set_termios + write_bulk_callback: ftdi_sio_write_bulk_callback, + ioctl: ftdi_sio_ioctl, + set_termios: ftdi_sio_set_termios, + startup: ftdi_sio_startup, }; -/****************************************************************************** + +/* + * *************************************************************************** * FTDI SIO Serial Converter specific driver functions - ******************************************************************************/ + * *************************************************************************** + * + * Bill Ryder bryder@sgi.com of Silicon Graphics, Inc. did the FTDI_SIO code + * Thanx to FTDI for so kindly providing details of the protocol required + * to talk to the device - http://www.ftdi.co.uk + * + * Tested as at this version - other stuff might work + * 23 March 2000 + * Works: + * Baudrates - 9600, 38400,19200, 57600, 115200 + * TIOCMBIC - TIOCM_DTR / TIOCM_RTS + * TIOCMBIS - TIOCM_DTR / TIOCM_RTS + * TIOCMSET - DTR on/RTSon / DTR off, RTS off + * no parity:CS8 even parity:CS7 odd parity:CS7 + * CRTSCTS flow control + * + * Pilot-xfer zillions of times + * + * cu works with dir option + * + * Not Tested (ie might not work): + * xon/xoff flow control + * ppp (modem handling in general) + * + * KNOWN BUGS: + * Multiple Opens + * ============== + * Seems to have problem when opening an already open port, + * Get I/O error on first attempt, then it lets you in. + * Need to do proper usage counting - keep registered callbacks for first opener. + * + * Reproduce with: + * cu -l /dev/ttyUSB0 dir + * whilst cu is running do: + * stty -a < /dev/ttyUSB0 + * + * from stty get: 'bash: /dev/ttyUSB0: Invalid argument ' + * from cu get + * write: Invalid argument + * + * Initialisation Problem + * ====================== + * Pilot transfer required me to run the serial_loopback program before it would work. + * Still working on this. See the webpage http://reality.sgi.com/bryder_wellington/ftdi_sio + * + */ -static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp) +#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ + +/* do some startup allocations not currently performed by usb_serial_probe() */ +static int ftdi_sio_startup (struct usb_serial *serial) { + init_waitqueue_head(&serial->write_wait); + + return (0); +} + +static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp) +{ /* ftdi_sio_open */ + struct termios tmp_termios; struct usb_serial *serial = port->serial; char buf[1]; /* Needed for the usb_control_msg I think */ dbg("ftdi_sio_open port %d", port->number); + /* FIXME - multiple concurrent opens cause trouble */ if (port->active) { - dbg ("port already open"); + err ("port already open"); return -EINVAL; } - port->active = 1; + port->active = 1; /* FIXME - For multiple open this should increment */ + /* See ftdi_sio.h for description of what is reset */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, - 0, buf, 0, HZ * 5); - - /* FIXME - Should I really purge the buffers? */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, - FTDI_SIO_RESET_PURGE_RX, - 0, buf, 0, HZ * 5); - - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, - FTDI_SIO_RESET_PURGE_TX, - 0, buf, 0, HZ * 5); - + 0, buf, 0, WDR_TIMEOUT); - /* As per usb_serial_init s/be CS8, B9600, 1 STOP BIT */ - if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_BAUDRATE_REQUEST, - FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - ftdi_sio_b9600, 0, - buf, 0, HZ * 5) < 0){ - dbg("Error from baudrate urb"); - return(-EINVAL); - } + /* Setup termios */ + port->tty->termios->c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; - if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_DATA_REQUEST, - FTDI_SIO_SET_DATA_REQUEST_TYPE, - 8 | FTDI_SIO_SET_DATA_PARITY_NONE | - FTDI_SIO_SET_DATA_STOP_BITS_1, 0, - buf, 0, HZ * 5) < 0){ - dbg("Error from cs8/noparity/1 stopbit urb"); - return(-EINVAL); - } + + ftdi_sio_set_termios(port, &tmp_termios); /* Disable flow control */ if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, 0, - buf, 0, HZ * 5) < 0) { - dbg("error from flowcontrol urb"); + buf, 0, WDR_TIMEOUT) < 0) { + err("error from flowcontrol urb"); return(-EINVAL); } /* Turn on RTS and DTR since we are not flow controlling*/ - /* FIXME - check for correct behaviour clocal vs non clocal */ - /* FIXME - might be able to do both simultaneously */ if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, (unsigned)FTDI_SIO_SET_DTR_HIGH, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from DTR HIGH urb"); + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from DTR HIGH urb"); } if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, (unsigned)FTDI_SIO_SET_RTS_HIGH, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from RTS HIGH urb"); + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from RTS HIGH urb"); } /*Start reading from the device*/ if (usb_submit_urb(port->read_urb)) - dbg("usb_submit_urb(read bulk) failed"); + err("usb_submit_urb(read bulk) failed"); return (0); -} +} /* ftdi_sio_open */ static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp) -{ +{ /* ftdi_sio_close */ struct usb_serial *serial = port->serial; + unsigned int c_cflag = port->tty->termios->c_cflag; char buf[1]; dbg("ftdi_sio_close port %d", port->number); - /* FIXME - might be able to do both simultaneously */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_DTR_LOW, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from DTR LOW urb"); + if (c_cflag & HUPCL){ + /* Disable flow control */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("error from flowcontrol urb"); + } + + /* drop DTR */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_DTR_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from DTR LOW urb"); + } + /* drop RTS */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_RTS_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from RTS LOW urb"); + } } - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_RTS_LOW, 0, - buf, 0, HZ * 5) < 0) { - dbg("Error from RTS LOW urb"); - } - - /* FIXME Should I flush the device here? - not doing it for now */ /* shutdown our bulk reads and writes */ usb_unlink_urb (port->write_urb); usb_unlink_urb (port->read_urb); port->active = 0; -} +} /* ftdi_sio_close */ /* The ftdi_sio requires the first byte to have: - B0 1 - B1 0 - B2..7 length of message excluding byte 0 -*/ + * B0 1 + * B1 0 + * B2..7 length of message excluding byte 0 + */ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) -{ +{ /* ftdi_sio_write */ struct usb_serial *serial = port->serial; const int data_offset = 1; - + int rc; + DECLARE_WAITQUEUE(wait, current); + dbg("ftdi_sio_serial_write port %d, %d bytes", port->number, count); if (count == 0) { - dbg("write request of 0 bytes"); + err("write request of 0 bytes"); return 0; } @@ -228,10 +283,27 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, if (serial->num_bulk_out) { unsigned char *first_byte = port->write_urb->transfer_buffer; - if (port->write_urb->status == -EINPROGRESS) { - dbg ("already writing"); - return 0; - } + /* Was seeing a race here, got a read callback, then write callback before + hitting interuuptible_sleep_on - so wrapping in add_wait_queue stuff */ + + add_wait_queue(&serial->write_wait, &wait); + set_current_state (TASK_INTERRUPTIBLE); + while (port->write_urb->status == -EINPROGRESS) { + dbg("ftdi_sio - write in progress - retrying"); + if (0 /* file->f_flags & O_NONBLOCK */) { + rc = -EAGAIN; + goto err; + } + if (signal_pending(current)) { + current->state = TASK_RUNNING; + remove_wait_queue(&serial->write_wait, &wait); + rc = -ERESTARTSYS; + goto err; + } + schedule(); + } + remove_wait_queue(&serial->write_wait, &wait); + set_current_state(TASK_RUNNING); count += data_offset; count = (count > port->bulk_out_size) ? port->bulk_out_size : count; @@ -253,23 +325,23 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, first_byte = port->write_urb->transfer_buffer; *first_byte = 1 | ((count-data_offset) << 2) ; -#ifdef DEBUG +#ifdef CONFIG_USB_SERIAL_DEBUG dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]); if (count) { int i; printk (KERN_DEBUG __FILE__ ": data written - length = %d, data = ", count); for (i = 0; i < count; ++i) { - printk ("0x%02x ", first_byte[i]); + printk ( "0x%02x ", first_byte[i]); if (first_byte[i] > ' ' && first_byte[i] < '~') { - printk("%c ", first_byte[i]); + printk( "%c ", first_byte[i]); } else { - printk(" "); + printk( " "); } } - printk ("\n"); + printk ( "\n"); } #endif @@ -277,7 +349,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, port->write_urb->transfer_buffer_length = count; if (usb_submit_urb(port->write_urb)) - dbg("usb_submit_urb(write bulk) failed"); + err("usb_submit_urb(write bulk) failed"); dbg("write returning: %d", count - data_offset); return (count - data_offset); @@ -285,19 +357,52 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user, /* no bulk out, so return 0 bytes written */ return 0; -} + err: /* error exit */ + return(rc); +} /* ftdi_sio_write */ + +static void ftdi_sio_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial; + struct tty_struct *tty = port->tty; + + dbg("ftdi_sio_write_bulk_callback"); + + if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) { + return; + } + + serial = port->serial; + if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) { + return; + } + + if (urb->status) { + dbg("nonzero write bulk status received: %d", urb->status); + return; + } + + wake_up_interruptible(&serial->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + + return; +} /* ftdi_sio_write_bulk_callback */ static void ftdi_sio_read_bulk_callback (struct urb *urb) { /* ftdi_sio_serial_buld_callback */ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial; - struct tty_struct *tty; + struct tty_struct *tty = port->tty ; unsigned char *data = urb->transfer_buffer; + const int data_offset = 2; int i; - dbg("ftdi_sio_read_bulk_callback"); + dbg("ftdi_sio read callback"); if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) { return; @@ -308,29 +413,34 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb) return; } + /* TO DO -- check for hung up line and handle appropriately: */ + /* send hangup (need to find out how to do this) */ + + if (urb->status) { - dbg("nonzero read bulk status received: %d", urb->status); + err("nonzero read bulk status received: %d", urb->status); return; } -#ifdef DEBUG +#ifdef CONFIG_USB_SERIAL_DEBUG if (urb->actual_length > 2) { printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length); for (i = 0; i < urb->actual_length; ++i) { - printk ("0x%.2x ", data[i]); + printk ( "0x%.2x ", data[i]); if (data[i] > ' ' && data[i] < '~') { - printk("%c ", data[i]); + printk( "%c ", data[i]); } else { - printk(" "); + printk( " "); } } - printk ("\n"); - } + printk ( "\n"); + } else { + dbg("Just status"); + } #endif if (urb->actual_length > data_offset) { - tty = port->tty; for (i = data_offset ; i < urb->actual_length ; ++i) { tty_insert_flip_char(tty, data[i], 0); } @@ -339,14 +449,18 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb) /* Continue trying to always read */ if (usb_submit_urb(urb)) - dbg("failed resubmitting read urb"); + err("failed resubmitting read urb"); return; } /* ftdi_sio_serial_read_bulk_callback */ +/* As I understand this - old_termios contains the original termios settings */ +/* and tty->termios contains the new setting to be used */ +/* */ +/* WARNING: set_termios calls this with old_termios in kernel space */ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios) -{ +{ /* ftdi_sio_set_termios */ struct usb_serial *serial = port->serial; unsigned int cflag = port->tty->termios->c_cflag; __u16 urb_value; /* Will hold the new flags */ @@ -354,9 +468,13 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * dbg("ftdi_sio_set_termios port %d", port->number); - /* FIXME - we should keep the old termios really */ + /* FIXME -For this cut I don't care if the line is really changing or - not - so just do the change regardless */ + not - so just do the change regardless - should be able to + compare old_termios and tty->termios */ + /* NOTE These routines can get interrupted by + ftdi_sio_read_bulk_callback - need to examine what this + means - don't see any problems yet */ /* Set number of data bits, parity, stop bits */ @@ -374,7 +492,7 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * case CS7: urb_value |= 7; dbg("Setting CS7"); break; case CS8: urb_value |= 8; dbg("Setting CS8"); break; default: - dbg("CSIZE was set but not CS5-CS8"); + err("CSIZE was set but not CS5-CS8"); } } if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -382,14 +500,13 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , 0, buf, 0, 100) < 0) { - dbg("FAILED to set databits/stopbits/parity"); + err("FAILED to set databits/stopbits/parity"); } /* Now do the baudrate */ - /* FIXME - should drop lines on B0 */ - /* FIXME Should also handle CLOCAL here */ - + switch(cflag & CBAUD){ + case B0: break; /* Handled below */ case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break; case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break; case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break; @@ -403,105 +520,283 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * default: dbg("FTDI_SIO does not support the baudrate requested"); /* FIXME - how to return an error for this? */ break; } - /* Send the URB */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_BAUDRATE_REQUEST, - FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - urb_value, 0, - buf, 0, 100) < 0) { - dbg("urb failed to set baurdrate"); + if ((cflag & CBAUD) == B0 ) { + /* Disable flow control */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("error from disable flowcontrol urb"); + } + /* Drop RTS and DTR */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_DTR_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from DTR LOW urb"); + } + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + (unsigned)FTDI_SIO_SET_RTS_LOW, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("Error from RTS LOW urb"); + } + + } else { + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_BAUDRATE_REQUEST, + FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, + urb_value, 0, + buf, 0, 100) < 0) { + err("urb failed to set baurdrate"); + } + } + /* Set flow control */ + /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ + if (cflag & CRTSCTS) { + dbg("Setting to CRTSCTS flow control"); + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0 , FTDI_SIO_RTS_CTS_HS, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to set to rts/cts flow control"); + } + + } else { + /* CHECK Assuming XON/XOFF handled by stack - not by device */ + /* Disable flow control */ + dbg("Turning off hardware flow control"); + if (usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("urb failed to clear flow control"); + } + } return; -} +} /* ftdi_sio_set_termios */ + + +/* + * set_termios - Taken from tty_ioctl.c with some mods + * + * Used to correctly handle various options (ie TERMIOS_FLUSH etc) + * + */ + +/* + * Internal flag options for termios setting behavior + */ +#define TERMIOS_FLUSH 1 +#define TERMIOS_WAIT 2 +#define TERMIOS_TERMIO 4 + + +/* + * set_termios - assumes old_termios is in kernel space not user space + * sets current to port->tty->termios, might check diffs against old_termios one day + */ +static int set_termios(struct usb_serial_port *port, struct termios *old_termios, int opt) +{ /* set_termios */ + struct tty_struct *tty = port->tty; + int retval; + +#ifdef NOT_IMPLEMENTED_YET + retval = tty_check_change(tty); + if (retval) + return retval; +#endif + + + if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + if (opt & TERMIOS_WAIT) { + tty_wait_until_sent(tty, 0); + if (signal_pending(current)) + return -EINTR; + } + + /* remember port->tty->termios has the new settings */ + ftdi_sio_set_termios(port, old_termios); + return 0; +} /* set_termios */ -/*FIXME - the beginnings of this implementation - not even hooked into the driver yet */ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) { struct usb_serial *serial = port->serial; + struct tty_struct *tty = port->tty; + struct termios old_termios; + __u16 urb_value=0; /* Will hold the new flags */ char buf[1]; int ret, mask; - dbg("ftdi_sio_ioctl port %d", port->number); + dbg("ftdi_sio_ioctl - cmd 0x%04x", cmd); - /* Based on code from acm.c */ + /* Based on code from acm.c and others */ switch (cmd) { - case TIOCMGET: - /* Request the status from the device */ + case TIOCMGET: + dbg("TIOCMGET"); + /* Request the status from the device */ + if ((ret = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, 0, + buf, 1, HZ * 5)) < 0 ) { + dbg("Get not get modem status of device"); + return(ret); + } + + return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | + (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | + (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | + (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), + (unsigned long *) arg); + break; + + case TIOCMSET: /* Turns on and off the lines as specified by the mask */ + dbg("TIOCMSET"); + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + urb_value = ((mask & TIOCM_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW); + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + urb_value , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set DTR failed"); + return(ret); + } + urb_value = ((mask & TIOCM_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW); + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + urb_value , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set RTS failed"); + return(ret); + } + break; + + case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ + dbg("TIOCMBIS"); + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (mask & TIOCM_DTR){ if ((ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, - buf, 1, HZ * 5)) < 0 ) { - dbg("Get not get modem status of device"); + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_DTR_HIGH , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set DTR failed"); return(ret); - } - - return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | - (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | - (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | - (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0), - (unsigned long *) arg); - break; - - case TIOCMSET: - case TIOCMBIS: - case TIOCMBIC: - if ((ret = get_user(mask, (unsigned long *) arg))) return ret; - - /* FIXME Need to remember if we have set DTR or RTS since we - can't ask the device */ - /* FIXME - also need to find the meaning of TIOCMBIS/BIC/SET */ - if (mask & TIOCM_DTR) { - switch(cmd) { - case TIOCMSET: - urb_value = FTDI_SIO_SET_DTR_HIGH | FTDI_SIO_SET_RTS_LOW; - break; - - case TIOCMBIS: - /* Will leave RTS alone and set DTR */ - urb_value = FTDI_SIO_SET_DTR_HIGH; - break; - - case TIOCMBIC: - urb_value = FTDI_SIO_SET_DTR_LOW; - break; } } - if (mask & TIOCM_RTS) { - switch(cmd) { - case TIOCMSET: - urb_value = FTDI_SIO_SET_DTR_LOW | FTDI_SIO_SET_RTS_HIGH; - break; - - case TIOCMBIS: - /* Will leave DTR and set RTS */ - urb_value = FTDI_SIO_SET_RTS_HIGH; - break; - - case TIOCMBIC: - /* Will unset RTS */ - urb_value = FTDI_SIO_SET_RTS_LOW; + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_RTS_HIGH , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to set RTS failed"); + return(ret); + } + } break; - } - } - - return(usb_control_msg(serial->dev, + case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ + dbg("TIOCMBIC"); + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + if (mask & TIOCM_DTR){ + if ((ret = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + FTDI_SIO_SET_DTR_LOW , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to unset DTR failed"); + return(ret); + } + } + if (mask & TIOCM_RTS) { + if ((ret = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - urb_value , 0, - buf, 0, HZ * 5)); - } + FTDI_SIO_SET_RTS_LOW , 0, + buf, 0, WDR_TIMEOUT)) < 0){ + err("Urb to unset RTS failed"); + return(ret); + } + } + break; - return -ENOIOCTLCMD; -} + /* Code for the following is based on code from tty_ioctl.c */ + case TCGETS: + if (kernel_termios_to_user_termios((struct termios *)arg, tty->termios)) { + return -EFAULT; + } else { + return 0; + } + case TCSETSF: + memcpy(&old_termios, tty->termios, sizeof (struct termios)); + if ((ret = user_termios_to_kernel_termios(tty->termios, + (struct termios *)arg))) + return -EFAULT; + return set_termios(port, &old_termios, TERMIOS_FLUSH); + case TCSETSW: + memcpy(&old_termios, tty->termios, sizeof (struct termios)); + if ((ret = user_termios_to_kernel_termios(tty->termios, + (struct termios *)arg))) + return -EFAULT; + return set_termios(port, &old_termios, TERMIOS_WAIT); + case TCSETS: + memcpy(&old_termios, tty->termios, sizeof (struct termios)); + if ((ret = user_termios_to_kernel_termios(tty->termios, + (struct termios *)arg))) + return -EFAULT; + return set_termios(port, &old_termios, 0); + +#ifdef NOT_COMPLETED_YET_NEED_TO_CONVERT_TERMIO_TO_TERMIOS + /* the 'A' flavours work on termio not termios */ + case TCGETA: + if (kernel_termios_to_user_termio((struct termios *)arg, tty->termios)) { + return -EFAULT; + } else { + return 0; + } + break; + case TCSETAF: + return set_termios(port, arg, TERMIOS_FLUSH | TERMIOS_TERMIO); + case TCSETAW: + return set_termios(port, arg, TERMIOS_WAIT | TERMIOS_TERMIO); + case TCSETA: + return set_termios(port, arg, TERMIOS_TERMIO); +#endif + default: + err("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd); + return(-ENOIOCTLCMD); + break; + } + dbg("ftdi_sio_ioctl returning 0"); + return 0; +} /* ftdi_sio_ioctl */ -#endif /* CONFIG_USB_SERIAL_FTDI_SIO */ +#endif /* CONFIG_USB_SERIAL_FTDI_SIO */ diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 36fa7bb3e956..fe5f545db327 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -1,15 +1,23 @@ -/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ -/* The device is based on the FTDI FT8U100AX chip, DB25 on one side, USB on the other */ -/* Thanx to FTDI for so kindly providing details of the protocol required */ -/* http://www.ftdi.co.uk */ - -/* The implementation of the device I have is called a USC-1000 */ -/* which is available from http://www.dse.co.nz - cat no XH4214 */ -/* It looks similar to this: http://www.dansdata.com/usbser.htm but I can't be sure */ -/* There are other USC-1000s which don't look like my device though so beware */ - -/* Definitions for the FTDI USB Single Port Serial Converter */ -/* known as FTDI_SIO (Serial Input/Output application of the chipset) */ +/* + * Definitions for the FTDI USB Single Port Serial Converter - + * known as FTDI_SIO (Serial Input/Output application of the chipset) + * + * The example I have is known as the USC-1000 which is available from + * http://www.dse.co.nz - cat no XH4214 It looks similar to this: + * http://www.dansdata.com/usbser.htm but I can't be sure There are other + * USC-1000s which don't look like my device though so beware! + * + * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, + * USB on the other. + * + * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details + * of the protocol required to talk to the device and ongoing assistence + * during development. + * + * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the + * FTDI_SIO implementation. + * + */ #define FTDI_VID 0x0403 /* Vendor Id */ #define FTDI_SIO_PID 0x8372 /* Product Id */ @@ -27,7 +35,7 @@ /* Port Identifier Table */ #define PIT_DEFAULT 0 /* SIOA */ #define PIT_SIOA 1 /* SIOA */ -/* The device this is tested with one has one port */ +/* The device this driver is tested with one has only one port */ #define PIT_SIOB 2 /* SIOB */ #define PIT_PARALLEL 3 /* Parallel */ @@ -37,17 +45,31 @@ #define FTDI_SIO_RESET_SIO 0 #define FTDI_SIO_RESET_PURGE_RX 1 #define FTDI_SIO_RESET_PURGE_TX 2 -/* - BmRequestType: 0100 0000B - bRequest: FTDI_SIO_RESET - wValue: Control Value - 0 = Reset SIO - 1 = Purge RX buffer - 2 = Purge TX buffer - wIndex: Port - wLength: 0 - Data: None +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_RESET + * wValue: Control Value + * 0 = Reset SIO + * 1 = Purge RX buffer + * 2 = Purge TX buffer + * wIndex: Port + * wLength: 0 + * Data: None + * + * The Reset SIO command has this effect: + * + * Sets flow control set to 'none' + * Event char = $0D + * Event trigger = disabled + * Purge RX buffer + * Purge TX buffer + * Clear DTR + * Clear RTS + * baud and data format not reset + * + * The Purge RX and TX buffer commands affect nothing except the buffers + * */ /* FTDI_SIO_SET_BAUDRATE */ @@ -55,13 +77,13 @@ #define FTDI_SIO_SET_BAUDRATE_REQUEST 3 /* - BmRequestType: 0100 0000B - bRequest: FTDI_SIO_SET_BAUDRATE - wValue: BaudRate value - see below - wIndex: Port - wLength: 0 - Data: None -*/ + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_SET_BAUDRATE + * wValue: BaudRate value - see below + * wIndex: Port + * wLength: 0 + * Data: None + */ typedef enum { ftdi_sio_b300 = 0, @@ -89,28 +111,30 @@ typedef enum { /* FTDI_SIO_SET_DATA */ -/* BmRequestType: 0100 0000B */ -/* bRequest: FTDI_SIO_SET_DATA */ -/* wValue: Data characteristics (see below) */ -/* wIndex: Port */ -/* wLength: 0 */ -/* Data: None */ -/* - Data characteristics - -B0..7 Number of data bits -B8..10 Parity - 0 = None - 1 = Odd - 2 = Even - 3 = Mark - 4 = Space - B11..13 Stop Bits - 0 = 1 - 1 = 1.5 - 2 = 2 - B14..15 Reserved -*/ +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_SET_DATA + * wValue: Data characteristics (see below) + * wIndex: Port + * wLength: 0 + * Data: No + * + * Data characteristics + * + * B0..7 Number of data bits + * B8..10 Parity + * 0 = None + * 1 = Odd + * 2 = Even + * 3 = Mark + * 4 = Space + * B11..13 Stop Bits + * 0 = 1 + * 1 = 1.5 + * 2 = 2 + * B14..15 Reserved + * + */ @@ -119,16 +143,17 @@ B8..10 Parity #define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL /* - BmRequestType: 0100 0000B - bRequest: FTDI_SIO_MODEM_CTRL - wValue: ControlValue (see below) - wIndex: Port - wLength: 0 - Data: None - - NOTE: If the device is in RTS/CTS flow control, the RTS set by this - command will be IGNORED without an error being returned -*/ + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_MODEM_CTRL + * wValue: ControlValue (see below) + * wIndex: Port + * wLength: 0 + * Data: None + * + * NOTE: If the device is in RTS/CTS flow control, the RTS set by this + * command will be IGNORED without an error being returned + * Also - you can not set DTR and RTS with one control message + */ #define FTDI_SIO_SET_DTR_MASK 0x1 #define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8)) @@ -137,100 +162,107 @@ B8..10 Parity #define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 )) #define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 )) -/* ControlValue - B0 DTR state - 0 = reset - 1 = set - B1 RTS state - 0 = reset - 1 = set - B2..7 Reserved - B8 DTR state enable - 0 = ignore - 1 = use DTR state - B9 RTS state enable - 0 = ignore - 1 = use RTS state - B10..15 Reserved -*/ +/* + * ControlValue + * B0 DTR state + * 0 = reset + * 1 = set + * B1 RTS state + * 0 = reset + * 1 = set + * B2..7 Reserved + * B8 DTR state enable + * 0 = ignore + * 1 = use DTR state + * B9 RTS state enable + * 0 = ignore + * 1 = use RTS state + * B10..15 Reserved + */ /* FTDI_SIO_SET_FLOW_CTRL */ #define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL #define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS 0x1 -#define FTDI_SIO_DTR_DSR_HS 0x2 -#define FTDI_SIO_XON_XOFF_HS 0x4 -/* - BmRequestType: 0100 0000b - bRequest: FTDI_SIO_SET_FLOW_CTRL - wValue: Xoff/Xon - wIndex: Protocol/Port - hIndex is protocl / lIndex is port - wLength: 0 - Data: None - -hIndex - protocol has - B0 Output handshaking using RTS/CTS - 0 = disabled - 1 = enabled - B1 Output handshaking using DTR/DSR - 0 = disabled - 1 = enabled - B2 Xon/Xoff handshaking - 0 = disabled - 1 = enabled - -A value of zero in the hIndex field selects no handshaking +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) +/* + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_FLOW_CTRL + * wValue: Xoff/Xon + * wIndex: Protocol/Port - hIndex is protocl / lIndex is port + * wLength: 0 + * Data: None + * + * hIndex protocol is: + * B0 Output handshaking using RTS/CTS + * 0 = disabled + * 1 = enabled + * B1 Output handshaking using DTR/DSR + * 0 = disabled + * 1 = enabled + * B2 Xon/Xoff handshaking + * 0 = disabled + * 1 = enabled + * + * A value of zero in the hIndex field disables handshaking + * + * If Xon/Xoff handshaking is specified, the hValue field should contain the XOFF character + * and the lValue field contains the XON character. + */ + +/* + * FTDI_SIO_SET_EVENT_CHAR + * + * Set the special event character for the specified communications port. + * If the device sees this character it will immediately return the + * data read so far - rather than wait 40ms or until 62 bytes are read + * which is what normally happens. + */ -If Xon/Xoff handshaking is specified, the hValue field contains the Xoff character -and the lValue field contains the Xon character. -*/ - -/* FTDI_SIO_SET_EVENT_CHAR */ -/* Set the special event character for the specified communications port */ -/* If the device sees this character it will immediately return the */ -/* data read so far - rather than wait 40ms or until 62 bytes is read */ #define FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR #define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40 /* - BmRequestType: 0100 0000b - bRequest: FTDI_SIO_SET_EVENT_CHAR - wValue: EventChar - wIndex: Port - wLength: 0 - Data: None - -wValue: - B0..7 Event Character - B8 Event Character Processing - 0 = disabled - 1 = enabled - B9..15 Reserved - -*/ + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_EVENT_CHAR + * wValue: EventChar + * wIndex: Port + * wLength: 0 + * Data: None + * + * wValue: + * B0..7 Event Character + * B8 Event Character Processing + * 0 = disabled + * 1 = enabled + * B9..15 Reserved + * + */ /* FTDI_SIO_SET_ERROR_CHAR */ + /* Set the parity error replacement character for the specified communications port */ /* - BmRequestType: 0100 0000b - bRequest: FTDI_SIO_SET_EVENT_CHAR - wValue: Error Char - wIndex: Port - wLength: 0 - Data: None - -Error Char - B0..7 Error Character - B8 Error Character Processing - 0 = disabled - 1 = enabled - B9..15 Reserved - -*/ + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_EVENT_CHAR + * wValue: Error Char + * wIndex: Port + * wLength: 0 + * Data: None + * + *Error Char + * B0..7 Error Character + * B8 Error Character Processing + * 0 = disabled + * 1 = enabled + * B9..15 Reserved + * + */ /* FTDI_SIO_GET_MODEM_STATUS */ /* Retreive the current value of the modem status register */ @@ -242,139 +274,140 @@ Error Char #define FTDI_SIO_RI_MASK 0x40 #define FTDI_SIO_RLSD_MASK 0x80 /* - BmRequestType: 1100 0000b - bRequest: FTDI_SIO_GET_MODEM_STATUS - wValue: zero - wIndex: Port - wLength: 1 - Data: Status - -One byte of data is returned -B0..3 0 -B4 CTS - 0 = inactive - 1 = active -B5 DSR - 0 = inactive - 1 = active -B6 Ring Indicator (RI) - 0 = inactive - 1 = active -B7 Receive Line Signal Detect (RLSD) - 0 = inactive - 1 = active -*/ + * BmRequestType: 1100 0000b + * bRequest: FTDI_SIO_GET_MODEM_STATUS + * wValue: zero + * wIndex: Port + * wLength: 1 + * Data: Status + * + * One byte of data is returned + * B0..3 0 + * B4 CTS + * 0 = inactive + * 1 = active + * B5 DSR + * 0 = inactive + * 1 = active + * B6 Ring Indicator (RI) + * 0 = inactive + * 1 = active + * B7 Receive Line Signal Detect (RLSD) + * 0 = inactive + * 1 = active + */ /* Descriptors returned by the device + * + * Device Descriptor + * + * Offset Field Size Value Description + * 0 bLength 1 0x12 Size of descriptor in bytes + * 1 bDescriptorType 1 0x01 DEVICE Descriptor Type + * 2 bcdUSB 2 0x0110 USB Spec Release Number + * 4 bDeviceClass 1 0x00 Class Code + * 5 bDeviceSubClass 1 0x00 SubClass Code + * 6 bDeviceProtocol 1 0x00 Protocol Code + * 7 bMaxPacketSize0 1 0x08 Maximum packet size for endpoint 0 + * 8 idVendor 2 0x0403 Vendor ID + * 10 idProduct 2 0x8372 Product ID (FTDI_SIO_PID) + * 12 bcdDevice 2 0x0001 Device release number + * 14 iManufacturer 1 0x01 Index of man. string desc + * 15 iProduct 1 0x02 Index of prod string desc + * 16 iSerialNumber 1 0x02 Index of serial nmr string desc + * 17 bNumConfigurations 1 0x01 Number of possible configurations + * + * Configuration Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x09 Size of descriptor in bytes + * 1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type + * 2 wTotalLength 2 0x0020 Total length of data + * 4 bNumInterfaces 1 0x01 Number of interfaces supported + * 5 bConfigurationValue 1 0x01 Argument for SetCOnfiguration() req + * 6 iConfiguration 1 0x02 Index of config string descriptor + * 7 bmAttributes 1 0x20 Config characteristics Remote Wakeup + * 8 MaxPower 1 0x1E Max power consumption + * + * Interface Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x09 Size of descriptor in bytes + * 1 bDescriptorType 1 0x04 INTERFACE Descriptor Type + * 2 bInterfaceNumber 1 0x00 Number of interface + * 3 bAlternateSetting 1 0x00 Value used to select alternate + * 4 bNumEndpoints 1 0x02 Number of endpoints + * 5 bInterfaceClass 1 0xFF Class Code + * 6 bInterfaceSubClass 1 0xFF Subclass Code + * 7 bInterfaceProtocol 1 0xFF Protocol Code + * 8 iInterface 1 0x02 Index of interface string description + * + * IN Endpoint Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x07 Size of descriptor in bytes + * 1 bDescriptorType 1 0x05 ENDPOINT descriptor type + * 2 bEndpointAddress 1 0x82 Address of endpoint + * 3 bmAttributes 1 0x02 Endpoint attributes - Bulk + * 4 bNumEndpoints 2 0x0040 maximum packet size + * 5 bInterval 1 0x00 Interval for polling endpoint + * + * OUT Endpoint Descriptor + * + * Offset Field Size Value + * 0 bLength 1 0x07 Size of descriptor in bytes + * 1 bDescriptorType 1 0x05 ENDPOINT descriptor type + * 2 bEndpointAddress 1 0x02 Address of endpoint + * 3 bmAttributes 1 0x02 Endpoint attributes - Bulk + * 4 bNumEndpoints 2 0x0040 maximum packet size + * 5 bInterval 1 0x00 Interval for polling endpoint + * + * DATA FORMAT + * + * IN Endpoint + * + * The device reserves the first two bytes of data on this endpoint to contain the current + * values of the modem and line status registers. In the absence of data, the device + * generates a message consisting of these two status bytes every 40 ms + * + * Byte 0: Modem Status + * + * Offset Description + * B0 Reserved - must be 1 + * B1 Reserved - must be 0 + * B2 Reserved - must be 0 + * B3 Reserved - must be 0 + * B4 Clear to Send (CTS) + * B5 Data Set Ready (DSR) + * B6 Ring Indicator (RI) + * B7 Receive Line Signal Detect (RLSD) + * + * Byte 1: Line Status + * + * Offset Description + * B0 Data Ready (DR) + * B1 Overrun Error (OE) + * B2 Parity Error (PE) + * B3 Framing Error (FE) + * B4 Break Interrupt (BI) + * B5 Transmitter Holding Register (THRE) + * B6 Transmitter Empty (TEMT) + * B7 Error in RCVR FIFO + * + * OUT Endpoint + * + * This device reserves the first bytes of data on this endpoint contain the length + * and port identifier of the message. For the FTDI USB Serial converter the port + * identifier is always 1. + * + * Byte 0: Line Status + * + * Offset Description + * B0 Reserved - must be 1 + * B1 Reserved - must be 0 + * B2..7 Length of message - (not including Byte 0) + * + */ - Device Descriptor - -Offset Field Size Value Description -0 bLength 1 0x12 Size of descriptor in bytes -1 bDescriptorType 1 0x01 DEVICE Descriptor Type -2 bcdUSB 2 0x0110 USB Spec Release Number -4 bDeviceClass 1 0x00 Class Code -5 bDeviceSubClass 1 0x00 SubClass Code -6 bDeviceProtocol 1 0x00 Protocol Code -7 bMaxPacketSize0 1 0x08 Maximum packet size for endpoint 0 -8 idVendor 2 0x0403 Vendor ID -10 idProduct 2 0x8372 Product ID (FTDI_SIO_PID) -12 bcdDevice 2 0x0001 Device release number -14 iManufacturer 1 0x01 Index of man. string desc -15 iProduct 1 0x02 Index of prod string desc -16 iSerialNumber 1 0x02 Index of serial nmr string desc -17 bNumConfigurations 1 0x01 Number of possible configurations - -Configuration Descriptor - -Offset Field Size Value -0 bLength 1 0x09 Size of descriptor in bytes -1 bDescriptorType 1 0x02 CONFIGURATION Descriptor Type -2 wTotalLength 2 0x0020 Total length of data -4 bNumInterfaces 1 0x01 Number of interfaces supported -5 bConfigurationValue 1 0x01 Argument for SetCOnfiguration() req -6 iConfiguration 1 0x02 Index of config string descriptor -7 bmAttributes 1 0x20 Config characteristics Remote Wakeup -8 MaxPower 1 0x1E Max power consumption - -Interface Descriptor - -Offset Field Size Value -0 bLength 1 0x09 Size of descriptor in bytes -1 bDescriptorType 1 0x04 INTERFACE Descriptor Type -2 bInterfaceNumber 1 0x00 Number of interface -3 bAlternateSetting 1 0x00 Value used to select alternate -4 bNumEndpoints 1 0x02 Number of endpoints -5 bInterfaceClass 1 0xFF Class Code -6 bInterfaceSubClass 1 0xFF Subclass Code -7 bInterfaceProtocol 1 0xFF Protocol Code -8 iInterface 1 0x02 Index of interface string description - -IN Endpoint Descriptor - -Offset Field Size Value -0 bLength 1 0x07 Size of descriptor in bytes -1 bDescriptorType 1 0x05 ENDPOINT descriptor type -2 bEndpointAddress 1 0x82 Address of endpoint -3 bmAttributes 1 0x02 Endpoint attributes - Bulk -4 bNumEndpoints 2 0x0040 maximum packet size -5 bInterval 1 0x00 Interval for polling endpoint - -OUT Endpoint Descriptor - -Offset Field Size Value -0 bLength 1 0x07 Size of descriptor in bytes -1 bDescriptorType 1 0x05 ENDPOINT descriptor type -2 bEndpointAddress 1 0x02 Address of endpoint -3 bmAttributes 1 0x02 Endpoint attributes - Bulk -4 bNumEndpoints 2 0x0040 maximum packet size -5 bInterval 1 0x00 Interval for polling endpoint - -DATA FORMAT - -IN Endpoint - -The device reserves the first two bytes of data on this endpoint to contain the current -values of the modem and line status registers. In the absence of data, the device -generates a message consisting of these two status bytes every 40 ms - -Byte 0: Modem Status - -Offset Description -B0 Reserved - must be 1 -B1 Reserved - must be 0 -B2 Reserved - must be 0 -B3 Reserved - must be 0 -B4 Clear to Send (CTS) -B5 Data Set Ready (DSR) -B6 Ring Indicator (RI) -B7 Receive Line Signal Detect (RLSD) - -Byte 1: Line Status - -Offset Description -B0 Data Ready (DR) -B1 Overrun Error (OE) -B2 Parity Error (PE) -B3 Framing Error (FE) -B4 Break Interrupt (BI) -B5 Transmitter Holding Register (THRE) -B6 Transmitter Empty (TEMT) -B7 Error in RCVR FIFO - -OUT Endpoint - -This device reserves the first bytes of data on this endpoint contain the length -and port identifier of the message. For the FTDI USB Serial converter the port -identifier is always 1. - -Byte 0: Line Status - -Offset Description -B0 Reserved - must be 1 -B1 Reserved - must be 0 -B2..7 Length of message - (not including Byte 0) - -*/ diff --git a/drivers/usb/usb-core.c b/drivers/usb/usb-core.c index 686f81521ddf..f42b96f61424 100644 --- a/drivers/usb/usb-core.c +++ b/drivers/usb/usb-core.c @@ -32,6 +32,7 @@ int usb_audio_init(void); int usb_ibmcam_init(void); int dabusb_init(void); int plusb_init(void); +int dsbr100_init(void); /* * HCI drivers diff --git a/drivers/usb/usb-storage.c b/drivers/usb/usb-storage.c index e3e0ee8c0852..b03706eddeda 100644 --- a/drivers/usb/usb-storage.c +++ b/drivers/usb/usb-storage.c @@ -39,14 +39,6 @@ #include "usb-storage.h" #include "usb-storage-debug.h" -/* - * This is the size of the structure Scsi_Host_Template. We create - * an instance of this structure in this file and this is a check - * to see if this structure may have changed within the SCSI module. - * This is by no means foolproof, but it does help us some. - */ -#define SCSI_HOST_TEMPLATE_SIZE (104) - /* direction table -- this indicates the direction of the data * transfer for each command code -- a 1 indicates input */ @@ -76,7 +68,11 @@ typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*); /* we allocate one of these for every device that we remember */ struct us_data { struct us_data *next; /* next device */ + + /* the device we're working with */ + spinlock_t dev_spinlock; /* to protect the dev ptr */ struct usb_device *pusb_dev; /* this usb_device */ + unsigned int flags; /* from filter initially */ /* information about the device -- only good if device is attached */ @@ -351,6 +347,7 @@ static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) /* send the command to the transport layer */ result = us->transport(srb, us); + US_DEBUGP("return code from transport is 0x%x\n", result); /* If we got a short transfer, but it was for a command that * can have short transfers, we're actually okay @@ -512,6 +509,7 @@ static void ufi_command(Scsi_Cmnd *srb, struct us_data *us) /* send the command to the transport layer */ result = us->transport(srb, us); + US_DEBUGP("return code from transport is 0x%x\n", result); /* If we got a short transfer, but it was for a command that * can have short transfers, we're actually okay @@ -821,7 +819,7 @@ static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb)) { us_transfer(srb, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CBI data stage result is 0x%x\n", result); + US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); } /* STATUS STAGE */ @@ -840,8 +838,10 @@ static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) /* UFI gives us ASC and ASCQ, like a request sense * - * REQUEST_SENSE and INQUIRY don't affect the sense data, so we - * ignore the information for those commands + * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI + * devices, so we ignore the information for those commands. Note + * that this means we could be ignoring a real error on these + * commands, but that can't be helped. */ if (us->subclass == US_SC_UFI) { if (srb->cmnd[0] == REQUEST_SENSE || @@ -854,11 +854,14 @@ static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } - /* otherwise, we interpret the data normally */ - switch (us->ip_data) { - case 0x0001: + /* If not UFI, we interpret the data as a result code + * The first byte should always be a 0x0 + * The second byte & 0x0F should be 0x0 for good, otherwise error + */ + switch ((us->ip_data & 0xFF0F)) { + case 0x0000: return USB_STOR_TRANSPORT_GOOD; - case 0x0002: + case 0x0001: return USB_STOR_TRANSPORT_FAILED; default: return USB_STOR_TRANSPORT_ERROR; @@ -876,7 +879,7 @@ static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) int result; __u8 status[2]; - US_DEBUGP("CBC gets a command:\n"); + US_DEBUGP("CB gets a command:\n"); US_DEBUG(us_show_command(srb)); /* COMMAND STAGE */ @@ -908,7 +911,7 @@ static int CB_transport(Scsi_Cmnd *srb, struct us_data *us) /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb)) { us_transfer(srb, US_DIRECTION(srb->cmnd[0])); - US_DEBUGP("CBC data stage result is 0x%x\n", result); + US_DEBUGP("CB data stage result is 0x%x\n", srb->result); } @@ -1077,19 +1080,24 @@ static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) * Host functions ***********************************************************************/ +static const char* us_info(struct Scsi_Host *host) +{ + return "SCSI emulation for USB Mass Storage devices\n"; +} + /* detect adapter (always true ) */ static int us_detect(struct SHT *sht) { /* FIXME - not nice at all, but how else ? */ struct us_data *us = (struct us_data *)sht->proc_dir; - char name[32]; + char local_name[32]; - /* set up our name */ - sprintf(name, "usbscsi%d", us->host_number); - sht->name = sht->proc_name = kmalloc(strlen(name)+1, GFP_KERNEL); + /* set up the name of our subdirectory under /proc/scsi/ */ + sprintf(local_name, "usb-storage-%d", us->host_number); + sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); if (!sht->proc_name) return 0; - strcpy(sht->proc_name, name); + strcpy(sht->proc_name, local_name); /* we start with no /proc directory entry */ sht->proc_dir = NULL; @@ -1105,25 +1113,23 @@ static int us_detect(struct SHT *sht) /* odd... didn't register properly. Abort and free pointers */ kfree(sht->proc_name); sht->proc_name = NULL; - sht->name = NULL; return 0; } -/* release - must be here to stop scsi - * from trying to release IRQ etc. - * Kill off our data +/* Release all resources used by the virtual host + * + * NOTE: There is no contention here, because we're allready deregistered + * the driver and we're doing each virtual host in turn, not in parallel */ static int us_release(struct Scsi_Host *psh) { struct us_data *us = (struct us_data *)psh->hostdata[0]; - unsigned long flags; int result; - /* lock the data structures */ - spin_lock_irqsave(&us_list_spinlock, flags); - US_DEBUGP("us_release() called for host %s\n", us->htmplt.name); + /* FIXME: I don't think this is necessary, becuase we've allready + * deregistered, which causes us to disconnect() */ /* release the interrupt handler, if necessary */ if (us->irq_handle) { US_DEBUGP("-- releasing irq\n"); @@ -1133,9 +1139,6 @@ static int us_release(struct Scsi_Host *psh) us->irq_handle = NULL; } - /* lock the data structures */ - spin_unlock_irqrestore(&us_list_spinlock, flags); - /* we always have a successful release */ return 0; } @@ -1171,22 +1174,36 @@ static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) return 0; } -/* FIXME: This doesn't actually abort anything */ +/*********************************************************************** + * Error handling functions + ***********************************************************************/ + +/* Command abort + * Note that this is really only meaningful right now for CBI transport + * devices which have failed to give us the command completion interrupt + */ static int us_abort( Scsi_Cmnd *srb ) { - printk(KERN_CRIT "usb-storage: abort() requested but not implemented\n" ); + struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + US_DEBUGP("us_abort() called\n"); + + /* if we're stuck waiting for an IRQ, simulate it */ + if (us->ip_wanted) { + US_DEBUGP("-- simulating missing IRQ\n"); + up(&(us->ip_waitq)); + return SUCCESS; + } return 0; } /* FIXME: this doesn't do anything right now */ static int us_bus_reset( Scsi_Cmnd *srb ) { - struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + // struct us_data *us = (struct us_data *)srb->host->hostdata[0]; printk(KERN_CRIT "usb-storage: bus_reset() requested but not implemented\n" ); US_DEBUGP("Bus reset requested\n"); - if (us->ip_wanted) - up(&(us->ip_waitq)); // us->transport_reset(us); return SUCCESS; } @@ -1301,7 +1318,10 @@ int usb_stor_proc_info (char *buffer, char **start, off_t offset, */ static Scsi_Host_Template my_host_template = { + name: "usb-storage", proc_info: usb_stor_proc_info, + info: us_info, + detect: us_detect, release: us_release, command: us_command, @@ -1347,6 +1367,7 @@ static int usb_stor_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; int action; + unsigned long flags; lock_kernel(); @@ -1356,10 +1377,11 @@ static int usb_stor_control_thread(void * __us) */ daemonize(); - sprintf(current->comm, "usbscsi%d", us->host_number); + sprintf(current->comm, "usb-storage-%d", us->host_number); unlock_kernel(); + /* signal that we've started the thread */ up(&(us->notify)); for(;;) { @@ -1393,6 +1415,9 @@ static int usb_stor_control_thread(void * __us) break; } + /* lock the device pointers */ + spin_lock_irqsave(&(us->dev_spinlock), flags); + /* our device has gone - pretend not ready */ /* FIXME: we also need to handle INQUIRY here, * probably */ @@ -1408,6 +1433,11 @@ static int usb_stor_control_thread(void * __us) us->srb->result = (DID_OK << 16) | 2; } + /* unlock the device pointers */ + spin_unlock_irqrestore(&(us->dev_spinlock), + flags); + + /* indicate that the command is done */ us->srb->scsi_done(us->srb); us->srb = NULL; break; @@ -1428,6 +1458,11 @@ static int usb_stor_control_thread(void * __us) US_DEBUGP("scsi cmd done, result=0x%x\n", us->srb->result); + + /* unlock the device pointers */ + spin_unlock_irqrestore(&(us->dev_spinlock), flags); + + /* indicate that the command is done */ us->srb->scsi_done(us->srb); us->srb = NULL; break; @@ -1447,11 +1482,15 @@ static int usb_stor_control_thread(void * __us) } /* end switch on action */ /* exit if we get a signal to exit */ - if (action == US_ACT_EXIT) + if (action == US_ACT_EXIT) { + US_DEBUGP("-- US_ACT_EXIT command recieved\n"); break; + } } /* for (;;) */ - printk("usb_stor_control_thread exiting\n"); + /* notify the exit routine that we're actually exiting now */ + up(&(us->notify)); + return 0; } @@ -1658,6 +1697,7 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum) init_MUTEX_LOCKED(&(ss->sleeper)); init_MUTEX_LOCKED(&(ss->notify)); init_MUTEX(&(ss->queue_exclusion)); + ss->dev_spinlock = SPIN_LOCK_UNLOCKED; /* copy over the subclass and protocol data */ ss->subclass = subclass; @@ -1814,6 +1854,7 @@ static void storage_disconnect(struct usb_device *dev, void *ptr) { struct us_data *ss = ptr; int result; + unsigned long flags; US_DEBUGP("storage_disconnect() called\n"); @@ -1823,6 +1864,9 @@ static void storage_disconnect(struct usb_device *dev, void *ptr) return; } + /* lock access to the device data structure */ + spin_lock_irqsave(&(ss->dev_spinlock), flags); + /* release the IRQ, if we have one */ if (ss->irq_handle) { US_DEBUGP("-- releasing irq handle\n"); @@ -1834,6 +1878,9 @@ static void storage_disconnect(struct usb_device *dev, void *ptr) /* mark the device as gone */ ss->pusb_dev = NULL; + + /* lock access to the device data structure */ + spin_unlock_irqrestore(&(ss->dev_spinlock), flags); } @@ -1858,10 +1905,13 @@ void __exit usb_stor_exit(void) static struct us_data *next; unsigned long flags; + US_DEBUGP("usb_stor_exit() called\n"); + /* * deregister the driver -- this eliminates races with probes and * disconnects */ + US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&storage_driver) ; /* lock access to the data structures */ @@ -1869,14 +1919,39 @@ void __exit usb_stor_exit(void) /* unregister all the virtual hosts */ for (ptr = us_list; ptr != NULL; ptr = ptr->next) + { + US_DEBUGP("-- calling scsi_unregister_module()\n"); scsi_unregister_module(MODULE_SCSI_HA, &(ptr->htmplt)); + } + + /* Kill the control threads + * + * NOTE: there is no contention at this point, so full mutual + * exclusion is not necessary + */ + for (ptr = us_list; ptr != NULL; ptr = ptr->next) + { + US_DEBUGP("-- sending US_ACT_EXIT command to thread\n"); + + /* enqueue the command */ + ptr->action = US_ACT_EXIT; + + /* wake up the process task */ + up(&(ptr->sleeper)); + + /* wait for the task to confirm that it's exited */ + down(&(ptr->notify)); + } - /* kill the threads */ - /* FIXME: we can do this by sending them a signal to die */ /* free up the data structures */ /* FIXME: we need to eliminate the host structure also */ + US_DEBUGP("-- freeing data structures\n"); while (ptr) { + /* free the directory name */ + kfree(ptr->htmplt.proc_dir); + + /* free the us_data structure */ next = ptr->next; kfree(ptr); ptr = next; diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 161cfea5081e..4dd0663b5778 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -1423,32 +1423,28 @@ int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id) static void usb_set_maxpacket(struct usb_device *dev) { - int i, j, b; - struct usb_interface *ifp; + int i, b; for (i=0; iactconfig->bNumInterfaces; i++) { - ifp = dev->actconfig->interface + i; - - for (j = 0; j < ifp->num_altsetting; j++) { - struct usb_interface_descriptor *as = ifp->altsetting + j; - struct usb_endpoint_descriptor *ep = as->endpoint; - int e; - - for (e=0; ebNumEndpoints; e++) { - b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + struct usb_interface *ifp = dev->actconfig->interface + i; + struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting; + struct usb_endpoint_descriptor *ep = as->endpoint; + int e; + + for (e=0; ebNumEndpoints; e++) { + b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + if ((ep[e].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { /* Control => bidirectional */ + dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; + dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; + } + else if (usb_endpoint_out(ep[e].bEndpointAddress)) { + if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; + } + else { + if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; - } - else if (usb_endpoint_out(ep[e].bEndpointAddress)) { - if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b]) - dev->epmaxpacketout[b] = ep[e].wMaxPacketSize; - } - else { - if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) - dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; - } } } } diff --git a/fs/Config.in b/fs/Config.in index af12d0b137c9..1b51412b8edc 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -71,6 +71,7 @@ if [ "$CONFIG_NET" = "y" ]; then dep_tristate 'Coda file system support (advanced network fs)' CONFIG_CODA_FS $CONFIG_INET dep_tristate 'NFS file system support' CONFIG_NFS_FS $CONFIG_INET + dep_bool ' Provide NFSv3 client support (EXPERIMENTAL)' CONFIG_NFS_V3 $CONFIG_NFS_FS dep_bool ' Root file system on NFS' CONFIG_ROOT_NFS $CONFIG_NFS_FS $CONFIG_IP_PNP dep_tristate 'NFS server support' CONFIG_NFSD $CONFIG_INET diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index c9226513e0d1..a5fcc1a54183 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c @@ -30,7 +30,7 @@ static int adfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct super_block *sb = filp->f_dentry->d_sb; + struct super_block *sb = inode->i_sb; struct adfs_dir_ops *ops = sb->u.adfs_sb.s_dir; struct object_info obj; struct adfs_dir dir; diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index d861dc59d6e2..b5626e5bbdc2 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c @@ -78,8 +78,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb, /* Make sure entry is mounted and unused; note that dentry will point to the mounted-on-top root. */ - if ( !S_ISDIR(dentry->d_inode->i_mode) - || dentry->d_mounts == dentry ) { + if (!S_ISDIR(dentry->d_inode->i_mode)||!d_mountpoint(dentry)) { DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name)); continue; } diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 1540ceda844c..06e2e86ea4af 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -63,7 +63,7 @@ static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldi /* fall through */ default: while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent) ) { - if ( !ent->dentry || ent->dentry->d_mounts != ent->dentry ) { + if ( !ent->dentry || d_mountpoint(ent->dentry) ) { if (filldir(dirent,ent->name,ent->len,onr,ent->ino) < 0) return 0; filp->f_pos = nr; @@ -117,7 +117,7 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str /* If this is a directory that isn't a mount point, bitch at the daemon and fix it in user space */ - if ( S_ISDIR(dentry->d_inode->i_mode) && dentry->d_mounts == dentry ) { + if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) { return !autofs_wait(sbi, &dentry->d_name); } @@ -157,7 +157,7 @@ static int autofs_revalidate(struct dentry * dentry, int flags) return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT); /* Check for a non-mountpoint directory */ - if ( S_ISDIR(dentry->d_inode->i_mode) && dentry->d_mounts == dentry ) { + if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) { if (autofs_oz_mode(sbi)) return 1; else diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c index 129d5917f5d2..206eabd7e5fd 100644 --- a/fs/autofs/symlink.c +++ b/fs/autofs/symlink.c @@ -18,10 +18,10 @@ static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen) return vfs_readlink(dentry, buffer, buflen, s); } -static struct dentry *autofs_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags) +static struct dentry *autofs_follow_link(struct dentry *dentry, struct dentry *base, struct vfsmount **mnt, unsigned flags) { char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data; - return vfs_follow_link(dentry, base, flags, s); + return vfs_follow_link(dentry, base, mnt, flags, s); } struct inode_operations autofs_symlink_inode_operations = { diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 8ff33b34499a..41dc98984137 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -181,7 +181,7 @@ static int try_to_fill_dentry(struct dentry *dentry, /* If this is an unused directory that isn't a mount point, bitch at the daemon and fix it in user space */ if (S_ISDIR(dentry->d_inode->i_mode) && - dentry->d_mounts == dentry && + !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { DPRINTK(("try_to_fill_entry: mounting existing dir\n")); return autofs4_wait(sbi, &dentry->d_name, NFY_MOUNT) == 0; @@ -226,7 +226,7 @@ static int autofs4_root_revalidate(struct dentry * dentry, int flags) /* Check for a non-mountpoint directory with no contents */ if (S_ISDIR(dentry->d_inode->i_mode) && - dentry->d_mounts == dentry && + !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { DPRINTK(("autofs_root_revalidate: dentry=%p %.*s, emptydir\n", dentry, dentry->d_name.len, dentry->d_name.name)); diff --git a/fs/autofs4/symlink.c b/fs/autofs4/symlink.c index b86b400cf1a7..f3a9e3458ec9 100644 --- a/fs/autofs4/symlink.c +++ b/fs/autofs4/symlink.c @@ -21,11 +21,12 @@ static int autofs4_readlink(struct dentry *dentry, char *buffer, int buflen) static struct dentry * autofs4_follow_link(struct dentry *dentry, struct dentry *base, + struct vfsmount *mnt, unsigned int flags) { struct autofs_info *ino = autofs4_dentry_ino(dentry); - return vfs_follow_link(dentry, base, flags, ino->u.symlink); + return vfs_follow_link(dentry, base, mnt, flags, ino->u.symlink); } struct inode_operations autofs4_symlink_inode_operations = { diff --git a/fs/bad_inode.c b/fs/bad_inode.c index adb26f415fb9..66877e43eadb 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -15,7 +15,7 @@ * 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, unsigned int follow) +static struct dentry * bad_follow_link(struct dentry *dent, struct dentry *base, struct vfsmount **mnt, unsigned int follow) { dput(base); return dget(dent); @@ -64,7 +64,7 @@ struct inode_operations bad_inode_ops = }; -/* +/* * When a filesystem is unable to read an inode due to an I/O error in * its read_inode() function, it can call make_bad_inode() to return a * set of stubs which will return EIO errors as required. @@ -72,6 +72,16 @@ struct inode_operations bad_inode_ops = * We only need to do limited initialisation: all other fields are * preinitialised to zero automatically. */ + +/** + * make_bad_inode - mark an inode bad due to an I/O error + * @inode: Inode to mark bad + * + * When an inode cannot be read due to a media or remote network + * failure this function makes the inode 'bad' and causes I/O operations + * on it to fail from this point on + */ + void make_bad_inode(struct inode * inode) { inode->i_mode = S_IFREG; @@ -85,6 +95,14 @@ void make_bad_inode(struct inode * inode) * &bad_inode_ops to cover the case of invalidated inodes as well as * those created by make_bad_inode() above. */ + +/** + * is_bad_inode - is an inode errored + * @inode: inode to test + * + * Returns true if the inode in question has been marked as bad + */ + int is_bad_inode(struct inode * inode) { return (inode->i_op == &bad_inode_ops); diff --git a/fs/dcache.c b/fs/dcache.c index 71ed79df27aa..24e2f2568b62 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -82,8 +82,8 @@ static inline void dentry_iput(struct dentry * dentry) } } -/* - * dput() +/* + * dput * * This is complicated by the fact that we do not want to put * dentries that are no longer on any hash chain on the unused @@ -98,6 +98,17 @@ static inline void dentry_iput(struct dentry * dentry) * on the compiler to always get this right (gcc generally doesn't). * Real recursion would eat up our stack space. */ + +/* + * dput - release a dentry + * @dentry: dentry to release + * + * Release a dentry. This will drop the usage count and if appropriate + * call the dentry unlink method as well as removing it from the queues and + * releasing its resources. If the parent dentries were scheduled for release + * they too may now get deleted. + */ + void dput(struct dentry *dentry) { int count; @@ -161,11 +172,16 @@ out: BUG(); } -/* +/** + * d_invalidate - invalidate a dentry + * @dentry: dentry to invalidate + * * Try to invalidate the dentry if it turns out to be * possible. If there are other dentries that can be - * reached through this one we can't delete it. + * reached through this one we can't delete it and we + * return -EBUSY. On success we return 0. */ + int d_invalidate(struct dentry * dentry) { check_lock(); @@ -220,12 +236,19 @@ static inline void prune_one_dentry(struct dentry * dentry) dput(parent); } -/* +/** + * prune_dcache - shrink the dcache + * @count: number of entries to try and free + * * Shrink the dcache. This is done when we need * more memory, or simply when we need to unmount * something (at which point we need to unuse * all dentries). + * + * This function may fail to free any resources if + * all the dentries are in use. */ + void prune_dcache(int count) { check_lock(); @@ -259,6 +282,16 @@ void prune_dcache(int count) * each dput(), but since the target dentries are all at * the end, it's really just a single traversal. */ + +/** + * shrink_dcache_sb - shrink dcache for a superblock + * @sb: superblock + * + * Shrink the dcache for the specified super block. This + * is used to free the dcache before unmounting a file + * system + */ + void shrink_dcache_sb(struct super_block * sb) { struct list_head *tmp, *next; @@ -302,11 +335,17 @@ repeat: } } -/* +/** + * is_root_busy - check if a root dentry could be freed + * @root: Dentry to work down from + * * Check whether a root dentry would be in use if all of its * child dentries were freed. This allows a non-destructive * test for unmounting a device. + * + * Return non zero if the root is still busy. */ + int is_root_busy(struct dentry *root) { struct dentry *this_parent = root; @@ -348,12 +387,21 @@ resume: * We descend to the next level whenever the d_subdirs * list is non-empty and continue searching. */ + +/** + * have_submounts - check for mounts over a dentry + * @parent: dentry to check. + * + * Return true if the parent or its subdirectories contain + * a mount point + */ + int have_submounts(struct dentry *parent) { struct dentry *this_parent = parent; struct list_head *next; - if (parent->d_mounts != parent) + if (d_mountpoint(parent)) return 1; repeat: next = this_parent->d_subdirs.next; @@ -363,7 +411,7 @@ resume: struct dentry *dentry = list_entry(tmp, struct dentry, d_child); next = tmp->next; /* Have we found a mount point ? */ - if (dentry->d_mounts != dentry) + if (d_mountpoint(dentry)) return 1; if (!list_empty(&dentry->d_subdirs)) { this_parent = dentry; @@ -435,9 +483,13 @@ this_parent->d_parent->d_name.name, this_parent->d_name.name, found); return found; } -/* +/** + * shrink_dcache_parent - prune dcache + * @parent: parent of entries to prune + * * Prune the dcache to remove unused children of the parent dentry. */ + void shrink_dcache_parent(struct dentry * parent) { int found; @@ -477,6 +529,16 @@ int shrink_dcache_memory(int priority, unsigned int gfp_mask, zone_t * zone) #define NAME_ALLOC_LEN(len) ((len+16) & ~15) +/** + * d_alloc - allocate a dcache entry + * @parent: parent of entry to allocate + * @name: qstr of the name + * + * Allocates a dentry. It returns NULL if there is insufficient memory + * available. On a success the dentry is returned. The name passed in is + * copied and the copy passed in may be reused after this call. + */ + struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) { char * str; @@ -525,7 +587,11 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) return dentry; } -/* +/** + * d_instantiate - fill in inode information for a dentry + * @entry: dentry to complete + * @inode: inode to attacheto this dentry + * * Fill in inode information in the entry. * * This turns negative dentries into productive full members @@ -535,6 +601,7 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) * (or otherwise set) by the caller to indicate that it is now * in use by the dcache.. */ + void d_instantiate(struct dentry *entry, struct inode * inode) { if (inode) @@ -542,6 +609,15 @@ void d_instantiate(struct dentry *entry, struct inode * inode) entry->d_inode = inode; } +/** + * d_alloc_root - allocate root dentry + * @root_inode: inode to allocate the root for + * + * Allocate a root ('/') dentry for the inode given. The inode is + * instantiated and returned. NULL is returned if there is insufficient + * memory or the inode passed is NULL. + */ + struct dentry * d_alloc_root(struct inode * root_inode) { struct dentry *res = NULL; @@ -564,6 +640,17 @@ static inline struct list_head * d_hash(struct dentry * parent, unsigned long ha return dentry_hashtable + (hash & D_HASHMASK); } +/** + * d_lookup - search for a dentry + * @parent: parent dentry + * @name: qstr of name we wish to find + * + * Searches the children of the parent dentry for the name in question. If + * the dentry is found its reference count is incremented and the dentry + * is returned. The caller must use d_put to free the entry when it has + * finished using it. NULL is returned on failure. + */ + struct dentry * d_lookup(struct dentry * parent, struct qstr * name) { unsigned int len = name->len; @@ -597,16 +684,23 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name) return NULL; } -/* - * An insecure source has sent us a dentry, here we verify it. +/** + * d_validate - verify dentry provided from insecure source + * @dentry: The dentry alleged to be valid + * @dparent: The parent dentry + * @hash: Hash of the dentry + * @len: Length of the name * + * An insecure source has sent us a dentry, here we verify it. * This is used by ncpfs in its readdir implementation. + * Zero is returned in the dentry is invalid. * - * NOTE! Do _not_ dereference the pointers before we have + * NOTE: This function does _not_ dereference the pointers before we have * validated them. We can test the pointer values, but we * must not actually use them until we have found a valid * copy of the pointer in kernel space.. */ + int d_validate(struct dentry *dentry, struct dentry *dparent, unsigned int hash, unsigned int len) { @@ -654,6 +748,15 @@ out: * it from the hash queues and waiting for * it to be deleted later when it has no users */ + +/** + * d_delete - delete a dentry + * @dentry: The dentry to delete + * + * Turn the dentry into a negative dentry if possible, otherwise + * remove it from the hash queues so it can be deleted later + */ + void d_delete(struct dentry * dentry) { check_lock(); @@ -673,6 +776,13 @@ void d_delete(struct dentry * dentry) d_drop(dentry); } +/** + * d_rehash - add an entry back to the hash + * @entry: dentry to add to the hash + * + * Adds a dentry to the hash according to its name + */ + void d_rehash(struct dentry * entry) { struct dentry * parent = entry->d_parent; @@ -726,6 +836,16 @@ static inline void switch_names(struct dentry * dentry, struct dentry * target) * the fact that any list-entry can be a head of the list. * Think about it. */ + +/** + * d_move - move a dentry + * @dentry: entry to move + * @target: new dentry + * + * Update the dcache to reflect the move of a file name. Negative + * dcache entries should not be moved in this way. + */ + void d_move(struct dentry * dentry, struct dentry * target) { check_lock(); @@ -755,14 +875,24 @@ void d_move(struct dentry * dentry, struct dentry * target) list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); } -/* +/** + * d_path - return the path of a dentry + * @dentry: dentry to report + * @buffer: buffer to return value in + * @buflen: buffer length + * + * Convert a dentry into an ascii path name. If the entry has been deleted + * the string ' (deleted)' is appended. Note that this is ambiguous. Returns + * the buffer. + * * "buflen" should be PAGE_SIZE or more. */ -char * d_path(struct dentry *dentry, char *buffer, int buflen) +char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt, + struct dentry *root, struct vfsmount *rootmnt, + char *buffer, int buflen) { char * end = buffer+buflen; char * retval; - struct dentry * root = current->fs->root; *--end = '\0'; buflen--; @@ -832,7 +962,7 @@ asmlinkage long sys_getcwd(char *buf, unsigned long size) char * cwd; lock_kernel(); - cwd = d_path(pwd, page, PAGE_SIZE); + cwd = d_path(pwd, current->fs->pwdmnt, page, PAGE_SIZE); unlock_kernel(); error = -ERANGE; @@ -853,6 +983,16 @@ asmlinkage long sys_getcwd(char *buf, unsigned long size) * * Trivially implemented using the dcache structure */ + +/** + * is_subdir - is new dentry a subdirectory of old_dentry + * @new_dentry: new dentry + * @old_dentry: old dentry + * + * Returns 1 if new_dentry is a subdirectory of the parent (at any depth). + * Returns 0 otherwise. + */ + int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry) { int result; @@ -872,14 +1012,20 @@ int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry) return result; } -/* +/** + * find_inode_number - check for dentry with name + * @dir: directory to check + * @name: Name to find. + * * Check whether a dentry already exists for the given name, - * and return the inode number if it has an inode. + * and return the inode number if it has an inode. Otherwise + * 0 is returned. * * This routine is used to post-process directory listings for * filesystems using synthetic inode numbers, and is necessary * to keep getcwd() working. */ + ino_t find_inode_number(struct dentry *dir, struct qstr *name) { struct dentry * dentry; diff --git a/fs/devfs/base.c b/fs/devfs/base.c index ab1e9ee83f7d..0a7435e6996a 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -3093,6 +3093,7 @@ static int devfs_readlink (struct dentry *dentry, char *buffer, int buflen) static struct dentry *devfs_follow_link (struct dentry *dentry, struct dentry *base, + struct vfsmount **mnt, unsigned int follow) { struct devfs_inode *di=get_devfs_inode_from_vfs_inode(dentry->d_inode); @@ -3100,7 +3101,7 @@ static struct dentry *devfs_follow_link (struct dentry *dentry, if (di && di->de->registered) name = di->de->u.symlink.linkname; - return vfs_follow_link(dentry, base, follow, name); + return vfs_follow_link(dentry, base, mnt, follow, name); } /* End Function devfs_follow_link */ static struct inode_operations devfs_iops = @@ -3393,12 +3394,11 @@ int __init init_devfs_fs (void) void __init mount_devfs_fs (void) { int err; - extern int do_mount (struct block_device *bdev, const char *dev_name, - const char *dir_name, const char * type, int flags, - void * data); + extern long do_sys_mount (char *dev_name, char *dir_name, + char * type, int flags, void * data); if ( (boot_options & OPTION_NOMOUNT) ) return; - err = do_mount (NULL, "none", "/dev", "devfs", 0, ""); + err = do_sys_mount ("none", "/dev", "devfs", 0, ""); if (err == 0) printk ("Mounted devfs on /dev\n"); else printk ("Warning: unable to mount devfs, err: %d\n", err); } /* End Function mount_devfs_fs */ diff --git a/fs/dquot.c b/fs/dquot.c index c602697f5a41..09a35d0a3c5a 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -793,20 +793,12 @@ static inline int need_print_warning(struct dquot *dquot, int flag) static void print_warning(struct dquot *dquot, int flag, const char *fmtstr) { - struct dentry *root; - char *path, *buffer; - if (!need_print_warning(dquot, flag)) return; - root = dquot->dq_sb->s_root; - dget(root); - buffer = (char *) __get_free_page(GFP_KERNEL); - path = buffer ? d_path(root, buffer, PAGE_SIZE) : "?"; - sprintf(quotamessage, fmtstr, path, quotatypes[dquot->dq_type]); - free_page((unsigned long) buffer); + sprintf(quotamessage, fmtstr, + bdevname(dquot->dq_sb->s_dev), quotatypes[dquot->dq_type]); tty_write_message(current->tty, quotamessage); dquot->dq_flags |= flag; - dput(root); } static inline char ignore_hardlimit(struct dquot *dquot) @@ -1469,7 +1461,7 @@ static int quota_on(struct super_block *sb, short type, char *path) if (IS_ERR(tmp)) goto out_lock; - f = filp_open(tmp, O_RDWR, 0600, NULL); + f = filp_open(tmp, O_RDWR, 0600); putname(tmp); error = PTR_ERR(f); diff --git a/fs/exec.c b/fs/exec.c index 8a8a106313bd..850b1ace86a2 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -112,7 +112,7 @@ asmlinkage long sys_uselib(const char * library) goto out; file = fget(fd); retval = -ENOEXEC; - if (file && file->f_dentry && file->f_op && file->f_op->read) { + if (file && file->f_op && file->f_op->read) { spin_lock(&binfmt_lock); for (fmt = formats ; fmt ; fmt = fmt->next) { if (!fmt->load_shlib) @@ -315,9 +315,11 @@ int setup_arg_pages(struct linux_binprm *bprm) return 0; } +/* MOUNT_REWRITE: &mnt should be passed to lookup_dentry */ struct file *open_exec(const char *name) { struct dentry *dentry; + struct vfsmount *mnt = NULL; struct file *file; lock_kernel(); @@ -329,13 +331,14 @@ struct file *open_exec(const char *name) int err = permission(dentry->d_inode, MAY_EXEC); file = ERR_PTR(err); if (!err) { - file = dentry_open(dentry, O_RDONLY); + file = dentry_open(dentry, mnt, O_RDONLY); out: unlock_kernel(); return file; } } dput(dentry); + mntput(mnt); } goto out; } @@ -860,7 +863,6 @@ int do_coredump(long signr, struct pt_regs * regs) struct linux_binfmt * binfmt; char corename[6+sizeof(current->comm)]; struct file * file; - struct dentry * dentry; struct inode * inode; lock_kernel(); @@ -879,17 +881,16 @@ int do_coredump(long signr, struct pt_regs * regs) #else corename[4] = '\0'; #endif - file = filp_open(corename, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600, NULL); + file = filp_open(corename, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600); if (IS_ERR(file)) goto fail; - dentry = file->f_dentry; - inode = dentry->d_inode; + inode = file->f_dentry->d_inode; if (inode->i_nlink > 1) goto close_fail; /* multiple links - don't dump */ if (!S_ISREG(inode->i_mode)) goto close_fail; - if (!inode->i_fop) + if (!file->f_op) goto close_fail; if (!file->f_op->write) goto close_fail; diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c index d56ef4c6276e..30ad562e8347 100644 --- a/fs/ext2/symlink.c +++ b/fs/ext2/symlink.c @@ -25,10 +25,10 @@ static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) return vfs_readlink(dentry, buffer, buflen, s); } -static struct dentry *ext2_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags) +static struct dentry *ext2_follow_link(struct dentry *dentry, struct dentry *base, struct vfsmount **mnt, unsigned flags) { char *s = (char *)dentry->d_inode->u.ext2_i.i_data; - return vfs_follow_link(dentry, base, flags, s); + return vfs_follow_link(dentry, base, mnt, flags, s); } struct inode_operations ext2_fast_symlink_inode_operations = { diff --git a/fs/file_table.c b/fs/file_table.c index 3f795576e629..ee7be989007a 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -122,13 +122,17 @@ int init_private_file(struct file *filp, struct dentry *dentry, int mode) static void __fput(struct file *filp) { struct dentry * dentry = filp->f_dentry; + struct vfsmount * mnt = filp->f_vfsmnt; struct inode * inode = dentry->d_inode; if (filp->f_op && filp->f_op->release) filp->f_op->release(inode, filp); filp->f_dentry = NULL; + filp->f_vfsmnt = NULL; if (filp->f_mode & FMODE_WRITE) put_write_access(inode); + if (mnt) + mntput(mnt); dput(dentry); } diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index debe0a9678dd..07f4ab93df06 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c @@ -314,14 +314,10 @@ int hfs_rmdir(struct inode * parent, struct dentry *dentry) if (!d_unhashed(dentry)) goto hfs_rmdir_put; - if (/* we only have to worry about 2 and 3 for mount points */ - (victim->sys_entry[2] && - (victim->sys_entry[2]->d_mounts != - victim->sys_entry[2]->d_covers)) || - (victim->sys_entry[3] && - (victim->sys_entry[3]->d_mounts != - victim->sys_entry[3]->d_covers)) - ) + /* we only have to worry about 2 and 3 for mount points */ + if (victim->sys_entry[2] && d_mountpoint(victim->sys_entry[2])) + goto hfs_rmdir_put; + if (victim->sys_entry[3] && d_mountpoint(victim->sys_entry[3])) goto hfs_rmdir_put; diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index a2f33d56d607..51d519d7f8d3 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c @@ -23,7 +23,7 @@ loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence) loff_t pos; struct quad_buffer_head qbh; struct inode *i = filp->f_dentry->d_inode; - struct super_block *s = filp->f_dentry->d_sb; + struct super_block *s = i->i_sb; /*printk("dir lseek\n");*/ if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok; hpfs_lock_inode(i); diff --git a/fs/inode.c b/fs/inode.c index 73406ae0aa74..de7267c842ab 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -111,6 +111,14 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) * In short, make sure you hash any inodes _before_ * you start marking them dirty.. */ + +/** + * __mark_inode_dirty - internal function + * @inode: inode to mark + * + * Mark an inode as dirty. Callers should use mark_inode_dirty + */ + void __mark_inode_dirty(struct inode *inode) { struct super_block * sb = inode->i_sb; @@ -202,10 +210,14 @@ static inline void sync_list(struct list_head *head) sync_one(list_entry(tmp, struct inode, i_list)); } -/* - * "sync_inodes()" goes through the super block's dirty list, - * writes them out, and puts them back on the normal list. +/** + * sync_inodes + * @dev: device to sync the inodes from. + * + * sync_inodes goes through the super block's dirty list, + * writes them out, and puts them back on the normal list. */ + void sync_inodes(kdev_t dev) { struct super_block * sb = sb_entry(super_blocks.next); @@ -241,9 +253,14 @@ static void sync_all_inodes(void) } } -/* - * Needed by knfsd +/** + * write_inode_now - write an inode to disk + * @inode: inode to write to disk + * + * This function commits an inode to disk immediately if it is + * dirty. This is primarily needed by knfsd. */ + void write_inode_now(struct inode *inode) { struct super_block * sb = inode->i_sb; @@ -258,11 +275,15 @@ void write_inode_now(struct inode *inode) printk("write_inode_now: no super block\n"); } -/* +/** + * clear_inode - clear an inode + * @inode: inode to clear + * * This is called by the filesystem to tell us * that the inode is no longer useful. We just * terminate it with extreme prejudice. */ + void clear_inode(struct inode *inode) { if (inode->i_data.nrpages) @@ -346,6 +367,16 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru * is because we don't want to sleep while messing * with the global lists.. */ + +/** + * invalidate_inodes - discard the inodes on a device + * @sb: superblock + * + * Discard all of the inodes for a given superblock. If the discard + * fails because there are busy inodes then a non zero value is returned. + * If the discard is successful all the inodes are dicarded. + */ + int invalidate_inodes(struct super_block * sb) { int busy; @@ -490,12 +521,19 @@ static void clean_inode(struct inode *inode) inode->i_mapping = &inode->i_data; } -/* +/** + * get_empty_inode - obtain an inode + * * This is called by things like the networking layer * etc that want to get an inode without any inode * number, or filesystems that allocate new inodes with * no pre-existing information. + * + * On a successful return the inode pointer is returned. On a failure + * a NULL pointer is returned. The returned inode is not on any superblock + * lists. */ + struct inode * get_empty_inode(void) { static unsigned long last_ino = 0; @@ -585,6 +623,22 @@ static inline unsigned long hash(struct super_block *sb, unsigned long i_ino) } /* Yeah, I know about quadratic hash. Maybe, later. */ + +/** + * iunique - get a unique inode number + * @sb: superblock + * @max_reserved: highest reserved inode number + * + * Obtain an inode number that is unique on the system for a given + * superblock. This is used by file systems that have no natural + * permanent inode numbering system. An inode number is returned that + * is higher than the reserved limit but unique. + * + * BUGS: + * With a large number of inodes live on the file system this function + * currently becomes quite slow. + */ + ino_t iunique(struct super_block *sb, ino_t max_reserved) { static ino_t counter = 0; @@ -625,6 +679,7 @@ struct inode *igrab(struct inode *inode) return inode; } + struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque) { struct list_head * head = inode_hashtable + hash(sb,ino); @@ -647,6 +702,14 @@ struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find return get_new_inode(sb, ino, head, find_actor, opaque); } +/** + * insert_inode_hash - hash an inode + * @inode: unhashed inode + * + * Add an inode to the inode hash for this superblock. If the inode + * has no superblock it is added to a seperate anonymous chain + */ + void insert_inode_hash(struct inode *inode) { struct list_head *head = &anon_hash_chain; @@ -657,6 +720,13 @@ void insert_inode_hash(struct inode *inode) spin_unlock(&inode_lock); } +/** + * remove_inode_hash - remove an inode from the hash + * @inode: inode to unhash + * + * Remove an inode from the superblock or anonymous hash + */ + void remove_inode_hash(struct inode *inode) { spin_lock(&inode_lock); @@ -665,6 +735,14 @@ void remove_inode_hash(struct inode *inode) spin_unlock(&inode_lock); } +/** + * iput - put an inode + * @inode: inode to put + * + * Puts an inode, dropping its usage count. If the inode use count hits + * zero the inode is also then freed and may be destroyed. + */ + void iput(struct inode *inode) { if (inode) { @@ -744,6 +822,18 @@ kdevname(inode->i_dev), inode->i_ino, atomic_read(&inode->i_sem.count)); } } +/** + * bmap - find a block number in a file + * @inode: inode of file + * @block: block to find + * + * Returns the block number on the device holding the inode that + * is the disk block number for the block of the file requested. + * That is asked for block 4 of inode 1 the function will return the + * disk block relative to the disk start that holds that block of the + * file + */ + int bmap(struct inode * inode, int block) { int res = 0; @@ -775,13 +865,22 @@ void __init inode_init(void) panic("cannot create inode slab cache"); } +/** + * update_atime - update the access time + * @inode: inode accessed + * + * Update the accessed time on an inode and mark it for writeback. + * This function automatically handles read only file systems and media, + * as well as the noatime flag and inode specific noatime markers + */ + void update_atime (struct inode *inode) { - if ( IS_NOATIME (inode) ) return; - if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return; - if ( IS_RDONLY (inode) ) return; - inode->i_atime = CURRENT_TIME; - mark_inode_dirty (inode); + if ( IS_NOATIME (inode) ) return; + if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return; + if ( IS_RDONLY (inode) ) return; + inode->i_atime = CURRENT_TIME; + mark_inode_dirty (inode); } /* End Function update_atime */ diff --git a/fs/ioctl.c b/fs/ioctl.c index a02bbec67ab2..614cdaf67dcf 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -98,9 +98,7 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) default: error = -ENOTTY; - if (!filp->f_dentry || !filp->f_dentry->d_inode) - error = -ENOENT; - else if (S_ISREG(filp->f_dentry->d_inode->i_mode)) + if (S_ISREG(filp->f_dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else if (filp->f_op && filp->f_op->ioctl) error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 7a4674d8561f..f89188d12220 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -152,7 +152,7 @@ nlmclnt_recovery(struct nlm_host *host, u32 newstate) host->h_monitored = 0; host->h_nsmstate = newstate; host->h_state++; - host->h_count++; + nlm_get_host(host); kernel_thread(reclaimer, host, 0); } } diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 20b9bb4902cb..d559fff3b23c 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -106,10 +106,18 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) struct nlm_rqst reqst, *call = &reqst; sigset_t oldset; unsigned long flags; - int status; + int status, proto, vers; - /* Always use NLM version 1 over UDP for now... */ - if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), IPPROTO_UDP, 1))) + vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; + if (NFS_PROTO(inode)->version > 3) { + printk(KERN_NOTICE "NFSv4 file locking not implemented!\n"); + return -ENOLCK; + } + + /* Retrieve transport protocol from NFS client */ + proto = NFS_CLIENT(inode)->cl_xprt->prot; + + if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers))) return -ENOLCK; /* Create RPC client handle if not there, and copy soft @@ -142,6 +150,10 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) spin_unlock_irqrestore(¤t->sigmask_lock, flags); call = nlmclnt_alloc_call(); + if (!call) { + status = -ENOMEM; + goto out_restore; + } call->a_flags = RPC_TASK_ASYNC; } else { spin_unlock_irqrestore(¤t->sigmask_lock, flags); @@ -165,8 +177,9 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) } if (status < 0 && (call->a_flags & RPC_TASK_ASYNC)) - rpc_free(call); + kfree(call); + out_restore: spin_lock_irqsave(¤t->sigmask_lock, flags); current->blocked = oldset; recalc_sigpending(current); @@ -200,8 +213,7 @@ nlmclnt_alloc_call(void) struct nlm_rqst *call; while (!signalled()) { - call = (struct nlm_rqst *) rpc_allocate(RPC_TASK_ASYNC, - sizeof(struct nlm_rqst)); + call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL); if (call) return call; printk("nlmclnt_alloc_call: failed, waiting for memory\n"); @@ -246,6 +258,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) case -ECONNREFUSED: case -ETIMEDOUT: case -ENOTCONN: + nlm_rebind_host(host); status = -EAGAIN; break; case -ERESTARTSYS: @@ -253,10 +266,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) default: break; } - if (req->a_args.block) - nlm_rebind_host(host); - else - break; + break; } else if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) { dprintk("lockd: server in grace period\n"); @@ -290,7 +300,7 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) * Generic NLM call, async version. */ int -nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback) +nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback) { struct nlm_host *host = req->a_host; struct rpc_clnt *clnt; @@ -313,9 +323,20 @@ nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback) msg.rpc_cred = NULL; status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req); - /* If the async call is proceeding, increment host refcount */ - if (status >= 0 && (req->a_flags & RPC_TASK_ASYNC)) - host->h_count++; + return status; +} + +int +nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback) +{ + struct nlm_host *host = req->a_host; + int status; + + /* Increment host refcount */ + nlm_get_host(host); + status = nlmsvc_async_call(req, proc, callback); + if (status < 0) + nlm_release_host(host); return status; } @@ -347,6 +368,20 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) return 0; } +static +void nlmclnt_insert_lock_callback(struct file_lock *fl) +{ + nlm_get_host(fl->fl_u.nfs_fl.host); +} +static +void nlmclnt_remove_lock_callback(struct file_lock *fl) +{ + if (fl->fl_u.nfs_fl.host) { + nlm_release_host(fl->fl_u.nfs_fl.host); + fl->fl_u.nfs_fl.host = NULL; + } +} + /* * LOCK: Try to create a lock * @@ -380,7 +415,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) return -ENOLCK; } - while (1) { + do { if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) { if (resp->status != NLM_LCK_BLOCKED) break; @@ -388,11 +423,14 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) } if (status < 0) return status; - } + } while (resp->status == NLM_LCK_BLOCKED); if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED; + fl->fl_u.nfs_fl.host = host; + fl->fl_insert = nlmclnt_insert_lock_callback; + fl->fl_remove = nlmclnt_remove_lock_callback; } return nlm_stat_to_errno(resp->status); @@ -444,15 +482,9 @@ nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl) static int nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) { - struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; int status; - /* No monitor, no lock: see nlmclnt_lock(). - * Since this is an UNLOCK, don't try to setup monitoring here. */ - if (!host->h_monitored) - return -ENOLCK; - /* Clean the GRANTED flag now so the lock doesn't get * reclaimed while we're stuck in the unlock call. */ fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; @@ -485,12 +517,15 @@ nlmclnt_unlock_callback(struct rpc_task *task) if (RPC_ASSASSINATED(task)) goto die; +#if 0 + /* FIXME: rpc_restart_call() is broken! */ if (task->tk_status < 0) { dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); nlm_rebind_host(req->a_host); rpc_restart_call(task); return; } +#endif if (status != NLM_LCK_GRANTED && status != NLM_LCK_DENIED_GRACE_PERIOD) { printk("lockd: unexpected unlock status: %d\n", status); @@ -498,6 +533,8 @@ nlmclnt_unlock_callback(struct rpc_task *task) die: rpc_release_task(task); + nlm_release_host(req->a_host); + kfree(req); } /* @@ -520,10 +557,9 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) recalc_sigpending(current); spin_unlock_irqrestore(¤t->sigmask_lock, flags); - do { - req = (struct nlm_rqst *) rpc_allocate(RPC_TASK_ASYNC, - sizeof(*req)); - } while (req == NULL); + req = nlmclnt_alloc_call(); + if (!req) + return -ENOMEM; req->a_host = host; req->a_flags = RPC_TASK_ASYNC; @@ -532,7 +568,7 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) status = nlmclnt_async_call(req, NLMPROC_CANCEL, nlmclnt_cancel_callback); if (status < 0) - rpc_free(req); + kfree(req); spin_lock_irqsave(¤t->sigmask_lock, flags); current->blocked = oldset; @@ -573,16 +609,20 @@ nlmclnt_cancel_callback(struct rpc_task *task) } die: +retry_cancel: rpc_release_task(task); nlm_release_host(req->a_host); kfree(req); return; +#if 0 + /* FIXME: rpc_restart_call() is broken */ retry_cancel: nlm_rebind_host(req->a_host); rpc_restart_call(task); rpc_delay(task, 30 * HZ); return; +#endif } /* diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 02cfb07f4129..dcd33c19bf81 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -15,6 +15,7 @@ #include #include #include +#include #define NLMDBG_FACILITY NLMDBG_HOSTCACHE @@ -105,8 +106,7 @@ nlm_lookup_host(struct svc_client *clnt, struct sockaddr_in *sin, host->h_next = nlm_hosts[hash]; nlm_hosts[hash] = host; } - host->h_expires = jiffies + NLM_HOST_EXPIRE; - host->h_count++; + nlm_get_host(host); up(&nlm_host_sema); return host; } @@ -172,9 +172,12 @@ nlm_bind_host(struct nlm_host *host) down(&host->h_sema); /* If we've already created an RPC client, check whether - * RPC rebind is required */ + * RPC rebind is required + * Note: why keep rebinding if we're on a tcp connection? + */ if ((clnt = host->h_rpcclnt) != NULL) { - if (time_after_eq(jiffies, host->h_nextrebind)) { + xprt = clnt->cl_xprt; + if (!xprt->stream && time_after_eq(jiffies, host->h_nextrebind)) { clnt->cl_port = 0; host->h_nextrebind = jiffies + NLM_HOST_REBIND; dprintk("lockd: next rebind in %ld jiffies\n", @@ -229,14 +232,28 @@ nlm_rebind_host(struct nlm_host *host) } } +/* + * Increment NLM host count + */ +struct nlm_host * nlm_get_host(struct nlm_host *host) +{ + if (host) { + dprintk("lockd: get host %s\n", host->h_name); + host->h_count ++; + host->h_expires = jiffies + NLM_HOST_EXPIRE; + } + return host; +} + /* * Release NLM host after use */ -void -nlm_release_host(struct nlm_host *host) +void nlm_release_host(struct nlm_host *host) { - dprintk("lockd: release host %s\n", host->h_name); - host->h_count -= 1; + if (host && host->h_count) { + dprintk("lockd: release host %s\n", host->h_name); + host->h_count --; + } } /* @@ -308,6 +325,8 @@ nlm_gc_hosts(void) } dprintk("lockd: delete host %s\n", host->h_name); *q = host->h_next; + if (host->h_monitored) + nsm_unmonitor(host); if ((clnt = host->h_rpcclnt) != NULL) { if (clnt->cl_users) { printk(KERN_WARNING diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 55dee3886e4b..283d66e97fad 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -30,14 +30,12 @@ u32 nsm_local_state = 0; * Common procedure for SM_MON/SM_UNMON calls */ static int -nsm_mon_unmon(struct nlm_host *host, char *what, u32 proc) +nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) { struct rpc_clnt *clnt; int status; struct nsm_args args; - struct nsm_res res; - dprintk("lockd: nsm_%s(%s)\n", what, host->h_name); status = -EACCES; clnt = nsm_create(); if (!clnt) @@ -47,23 +45,15 @@ nsm_mon_unmon(struct nlm_host *host, char *what, u32 proc) args.prog = NLM_PROGRAM; args.vers = 1; args.proc = NLMPROC_NSM_NOTIFY; + memset(res, 0, sizeof(*res)); - status = rpc_call(clnt, proc, &args, &res, 0); - if (status < 0) { + status = rpc_call(clnt, proc, &args, res, 0); + if (status < 0) printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", status); - goto out; - } - - status = -EACCES; - if (res.status != 0) { - printk(KERN_NOTICE "lockd: cannot %s %s\n", what, host->h_name); - goto out; - } - - nsm_local_state = res.state; - status = 0; -out: + else + status = 0; + out: return status; } @@ -73,10 +63,16 @@ out: int nsm_monitor(struct nlm_host *host) { + struct nsm_res res; int status; - status = nsm_mon_unmon(host, "monitor", SM_MON); - if (status >= 0) + dprintk("lockd: nsm_monitor(%s)\n", host->h_name); + + status = nsm_mon_unmon(host, SM_MON, &res); + + if (status < 0 || res.status != 0) + printk(KERN_NOTICE "lockd: cannot monitor %s\n", host->h_name); + else host->h_monitored = 1; return status; } @@ -87,9 +83,15 @@ nsm_monitor(struct nlm_host *host) int nsm_unmonitor(struct nlm_host *host) { + struct nsm_res res; int status; - if ((status = nsm_mon_unmon(host, "unmonitor", SM_UNMON)) >= 0) + dprintk("lockd: nsm_unmonitor(%s)\n", host->h_name); + + status = nsm_mon_unmon(host, SM_UNMON, &res); + if (status < 0) + printk(KERN_NOTICE "lockd: cannot unmonitor %s\n", host->h_name); + else host->h_monitored = 0; return status; } @@ -187,7 +189,7 @@ xdr_decode_stat_res(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) static int xdr_decode_stat(struct rpc_rqst *rqstp, u32 *p, struct nsm_res *resp) { - resp->status = ntohl(*p++); + resp->state = ntohl(*p++); return 0; } diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index b690eb97ef41..a204e1b5d53d 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -470,7 +470,7 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) host = nlmclnt_lookup_host(&rqstp->rq_addr, rqstp->rq_prot, rqstp->rq_vers); if (!host) { - rpc_free(call); + kfree(call); return rpc_system_err; } @@ -478,12 +478,14 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) call->a_host = host; memcpy(&call->a_args, resp, sizeof(*resp)); -/* FIXME this should become nlmSVC_async_call when that code gets - merged in XXX */ - if (nlmclnt_async_call(call, proc, nlm4svc_callback_exit) < 0) - return rpc_system_err; + if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0) + goto error; return rpc_success; + error: + kfree(call); + nlm_release_host(host); + return rpc_system_err; } static void @@ -495,8 +497,9 @@ nlm4svc_callback_exit(struct rpc_task *task) dprintk("lockd: %4d callback failed (errno = %d)\n", task->tk_pid, -task->tk_status); } + rpc_release_task(task); nlm_release_host(call->a_host); - rpc_free(call); + kfree(call); } /* diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 1bed616cbd2f..30051551d979 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -94,14 +94,16 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) struct nlm_block **head, *block; struct file_lock *fl; - dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %ld-%ld ty=%d\n", - file, lock->fl.fl_pid, lock->fl.fl_start, - lock->fl.fl_end, lock->fl.fl_type); + dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", + file, lock->fl.fl_pid, + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end, lock->fl.fl_type); for (head = &nlm_blocked; (block = *head); head = &block->b_next) { fl = &block->b_call.a_args.lock.fl; - dprintk("lockd: check f=%p pd=%d %ld-%ld ty=%d cookie=%x\n", - block->b_file, fl->fl_pid, fl->fl_start, - fl->fl_end, fl->fl_type, + dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%x\n", + block->b_file, fl->fl_pid, + (long long)fl->fl_start, + (long long)fl->fl_end, fl->fl_type, *(unsigned int*)(block->b_call.a_args.cookie.data)); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { if (remove) @@ -286,12 +288,12 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_block *block; int error; - dprintk("lockd: nlmsvc_lock(%04x/%ld, ty=%d, pi=%d, %ld-%ld, bl=%d)\n", + dprintk("lockd: nlmsvc_lock(%04x/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_type, lock->fl.fl_pid, - lock->fl.fl_start, - lock->fl.fl_end, + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end, wait); /* Lock file against concurrent access */ @@ -365,16 +367,17 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, { struct file_lock *fl; - dprintk("lockd: nlmsvc_testlock(%04x/%ld, ty=%d, %ld-%ld)\n", + dprintk("lockd: nlmsvc_testlock(%04x/%ld, ty=%d, %Ld-%Ld)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_type, - lock->fl.fl_start, - lock->fl.fl_end); + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); if ((fl = posix_test_lock(&file->f_file, &lock->fl)) != NULL) { - dprintk("lockd: conflicting lock(ty=%d, %ld-%ld)\n", - fl->fl_type, fl->fl_start, fl->fl_end); + dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", + fl->fl_type, (long long)fl->fl_start, + (long long)fl->fl_end); conflock->caller = "somehost"; /* FIXME */ conflock->oh.len = 0; /* don't return OH info */ conflock->fl = *fl; @@ -396,12 +399,12 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) { int error; - dprintk("lockd: nlmsvc_unlock(%04x/%ld, pi=%d, %ld-%ld)\n", + dprintk("lockd: nlmsvc_unlock(%04x/%ld, pi=%d, %Ld-%Ld)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_pid, - lock->fl.fl_start, - lock->fl.fl_end); + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); /* First, cancel any lock that might be there */ nlmsvc_cancel_blocked(file, lock); @@ -424,12 +427,12 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) { struct nlm_block *block; - dprintk("lockd: nlmsvc_cancel(%04x/%ld, pi=%d, %ld-%ld)\n", + dprintk("lockd: nlmsvc_cancel(%04x/%ld, pi=%d, %Ld-%Ld)\n", file->f_file.f_dentry->d_inode->i_dev, file->f_file.f_dentry->d_inode->i_ino, lock->fl.fl_pid, - lock->fl.fl_start, - lock->fl.fl_end); + (long long)lock->fl.fl_start, + (long long)lock->fl.fl_end); down(&file->f_sema); if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index c92358dec3a5..c505b731d060 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -503,10 +503,14 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) call->a_host = host; memcpy(&call->a_args, resp, sizeof(*resp)); - if (nlmclnt_async_call(call, proc, nlmsvc_callback_exit) < 0) - return rpc_system_err; + if (nlmsvc_async_call(call, proc, nlmsvc_callback_exit) < 0) + goto error; return rpc_success; + error: + nlm_release_host(host); + kfree(call); + return rpc_system_err; } static void diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index c6395a54f28e..1d5b5382c47c 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -34,7 +34,7 @@ static inline unsigned int file_hash(struct nfs_fh *f) { unsigned int tmp=0; int i; - for (i=0; idata[i]; return tmp & (FILE_NRHASH - 1); } @@ -175,7 +175,7 @@ again: lock.fl_type = F_UNLCK; lock.fl_start = 0; - lock.fl_end = NLM_OFFSET_MAX; + lock.fl_end = OFFSET_MAX; if (posix_lock_file(&file->f_file, &lock, 0) < 0) { printk("lockd: unlock failure in %s:%d\n", __FILE__, __LINE__); diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index eba3aaef61ad..9a179d530db7 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -22,6 +22,25 @@ #define NLMDBG_FACILITY NLMDBG_XDR +static inline loff_t +s32_to_loff_t(__s32 offset) +{ + return (loff_t)offset; +} + +static inline __s32 +loff_t_to_s32(loff_t offset) +{ + __s32 res; + if (offset >= NLM_OFFSET_MAX) + res = NLM_OFFSET_MAX; + else if (offset <= -NLM_OFFSET_MAX) + res = -NLM_OFFSET_MAX; + else + res = offset; + return res; +} + /* * XDR functions for basic NLM types */ @@ -65,22 +84,23 @@ nlm_decode_fh(u32 *p, struct nfs_fh *f) { unsigned int len; - if ((len = ntohl(*p++)) != sizeof(*f)) { + if ((len = ntohl(*p++)) != NFS2_FHSIZE) { printk(KERN_NOTICE "lockd: bad fhandle size %x (should be %Zu)\n", - len, sizeof(*f)); + len, NFS2_FHSIZE); return NULL; } - memcpy(f, p, sizeof(*f)); - return p + XDR_QUADLEN(sizeof(*f)); + f->size = NFS2_FHSIZE; + memcpy(f->data, p, NFS2_FHSIZE); + return p + XDR_QUADLEN(NFS2_FHSIZE); } static inline u32 * nlm_encode_fh(u32 *p, struct nfs_fh *f) { - *p++ = htonl(sizeof(*f)); - memcpy(p, f, sizeof(*f)); - return p + XDR_QUADLEN(sizeof(*f)); + *p++ = htonl(NFS2_FHSIZE); + memcpy(p, f->data, NFS2_FHSIZE); + return p + XDR_QUADLEN(NFS2_FHSIZE); } /* @@ -102,7 +122,7 @@ static inline u32 * nlm_decode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; - int len; + s32 start, len, end; if (!(p = xdr_decode_string(p, &lock->caller, &len, NLM_MAXSTRLEN)) || !(p = nlm_decode_fh(p, &lock->fh)) @@ -114,10 +134,16 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock) fl->fl_pid = ntohl(*p++); fl->fl_flags = FL_POSIX; fl->fl_type = F_RDLCK; /* as good as anything else */ - fl->fl_start = ntohl(*p++); + start = ntohl(*p++); len = ntohl(*p++); - if (len == 0 || (fl->fl_end = fl->fl_start + len - 1) < 0) - fl->fl_end = NLM_OFFSET_MAX; + end = start + len - 1; + + fl->fl_start = s32_to_loff_t(start); + + if (len == 0 || end < 0) + fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s32_to_loff_t(end); return p; } @@ -128,18 +154,26 @@ static u32 * nlm_encode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; + __s32 start, len; if (!(p = xdr_encode_string(p, lock->caller)) || !(p = nlm_encode_fh(p, &lock->fh)) || !(p = nlm_encode_oh(p, &lock->oh))) return NULL; - *p++ = htonl(fl->fl_pid); - *p++ = htonl(lock->fl.fl_start); - if (lock->fl.fl_end == NLM_OFFSET_MAX) - *p++ = xdr_zero; + if (fl->fl_start > NLM_OFFSET_MAX + || (fl->fl_end > NLM_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) + return NULL; + + start = loff_t_to_s32(fl->fl_start); + if (fl->fl_end == OFFSET_MAX) + len = 0; else - *p++ = htonl(lock->fl.fl_end - lock->fl.fl_start + 1); + len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); + + *p++ = htonl(fl->fl_pid); + *p++ = htonl(start); + *p++ = htonl(len); return p; } @@ -150,6 +184,8 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock) static u32 * nlm_encode_testres(u32 *p, struct nlm_res *resp) { + s32 start, len; + if (!(p = nlm_encode_cookie(p, &resp->cookie))) return 0; *p++ = resp->status; @@ -164,11 +200,14 @@ nlm_encode_testres(u32 *p, struct nlm_res *resp) if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) return 0; - *p++ = htonl(fl->fl_start); - if (fl->fl_end == NLM_OFFSET_MAX) - *p++ = xdr_zero; + start = loff_t_to_s32(fl->fl_start); + if (fl->fl_end == OFFSET_MAX) + len = 0; else - *p++ = htonl(fl->fl_end - fl->fl_start + 1); + len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); + + *p++ = htonl(start); + *p++ = htonl(len); } return p; @@ -387,7 +426,8 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) resp->status = ntohl(*p++); if (resp->status == NLM_LCK_DENIED) { struct file_lock *fl = &resp->lock.fl; - u32 excl, len; + u32 excl; + s32 start, len, end; memset(&resp->lock, 0, sizeof(resp->lock)); excl = ntohl(*p++); @@ -397,10 +437,15 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) fl->fl_flags = FL_POSIX; fl->fl_type = excl? F_WRLCK : F_RDLCK; - fl->fl_start = ntohl(*p++); + start = ntohl(*p++); len = ntohl(*p++); - if (len == 0 || (fl->fl_end = fl->fl_start + len - 1) < 0) - fl->fl_end = NLM_OFFSET_MAX; + end = start + len - 1; + + fl->fl_start = s32_to_loff_t(start); + if (len == 0 || end < 0) + fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s32_to_loff_t(end); } return 0; } @@ -487,7 +532,7 @@ nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) #define NLM_caller_sz 1+QUADLEN(sizeof(system_utsname.nodename)) #define NLM_netobj_sz 1+QUADLEN(XDR_MAX_NETOBJ) /* #define NLM_owner_sz 1+QUADLEN(NLM_MAXOWNER) */ -#define NLM_fhandle_sz 1+QUADLEN(NFS_FHSIZE) +#define NLM_fhandle_sz 1+QUADLEN(NFS2_FHSIZE) #define NLM_lock_sz 3+NLM_caller_sz+NLM_netobj_sz+NLM_fhandle_sz #define NLM_holder_sz 4+NLM_netobj_sz diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 025e3c5b07b3..a5cb508ac94b 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -20,14 +20,25 @@ #include #define NLMDBG_FACILITY NLMDBG_XDR -#define OFFSET_MAX ((off_t)LONG_MAX) + +static inline loff_t +s64_to_loff_t(__s64 offset) +{ + return (loff_t)offset; +} -static inline off_t -size_to_off_t(__s64 size) +static inline s64 +loff_t_to_s64(loff_t offset) { - size = (size > (__s64)LONG_MAX) ? (off_t)LONG_MAX : (off_t) size; - return (size < (__s64)-LONG_MAX) ? (off_t)-LONG_MAX : (off_t) size; + s64 res; + if (offset > NLM4_OFFSET_MAX) + res = NLM4_OFFSET_MAX; + else if (offset < -NLM4_OFFSET_MAX) + res = -NLM4_OFFSET_MAX; + else + res = offset; + return res; } /* @@ -141,11 +152,12 @@ nlm4_decode_lock(u32 *p, struct nlm_lock *lock) p = xdr_decode_hyper(p, &len); end = start + len - 1; - fl->fl_start = size_to_off_t(start); - fl->fl_end = size_to_off_t(end); + fl->fl_start = s64_to_loff_t(start); - if (len == 0 || fl->fl_end < 0) + if (len == 0 || end < 0) fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s64_to_loff_t(end); return p; } @@ -156,18 +168,26 @@ static u32 * nlm4_encode_lock(u32 *p, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; + __s64 start, len; if (!(p = xdr_encode_string(p, lock->caller)) || !(p = nlm4_encode_fh(p, &lock->fh)) || !(p = nlm4_encode_oh(p, &lock->oh))) return NULL; - *p++ = htonl(fl->fl_pid); - p = xdr_encode_hyper(p, fl->fl_start); + if (fl->fl_start > NLM4_OFFSET_MAX + || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) + return NULL; + + start = loff_t_to_s64(fl->fl_start); if (fl->fl_end == OFFSET_MAX) - p = xdr_encode_hyper(p, 0); + len = 0; else - p = xdr_encode_hyper(p, fl->fl_end - fl->fl_start + 1); + len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); + + *p++ = htonl(fl->fl_pid); + p = xdr_encode_hyper(p, start); + p = xdr_encode_hyper(p, len); return p; } @@ -178,6 +198,8 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock) static u32 * nlm4_encode_testres(u32 *p, struct nlm_res *resp) { + s64 start, len; + dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); if (!(p = nlm4_encode_cookie(p, &resp->cookie))) return 0; @@ -193,12 +215,17 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp) if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) return 0; - p = xdr_encode_hyper(p, fl->fl_start); + start = loff_t_to_s64(fl->fl_start); if (fl->fl_end == OFFSET_MAX) - p = xdr_encode_hyper(p, 0); + len = 0; else - p = xdr_encode_hyper(p, fl->fl_end - fl->fl_start + 1); - dprintk("xdr: encode_testres (status %d pid %d type %d start %ld end %ld)\n", resp->status, fl->fl_pid, fl->fl_type, fl->fl_start, fl->fl_end); + len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); + + p = xdr_encode_hyper(p, start); + p = xdr_encode_hyper(p, len); + dprintk("xdr: encode_testres (status %d pid %d type %d start %Ld end %Ld)\n", + resp->status, fl->fl_pid, fl->fl_type, + (long long)fl->fl_start, (long long)fl->fl_end); } dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); @@ -434,10 +461,11 @@ nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) p = xdr_decode_hyper(p, &len); end = start + len - 1; - fl->fl_start = size_to_off_t(start); - fl->fl_end = size_to_off_t(end); - if (len == 0 || fl->fl_end < 0) + fl->fl_start = s64_to_loff_t(start); + if (len == 0 || end < 0) fl->fl_end = OFFSET_MAX; + else + fl->fl_end = s64_to_loff_t(end); } return 0; } diff --git a/fs/locks.c b/fs/locks.c index 1661a4a5c80e..18ee63e9263f 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -111,8 +111,6 @@ #include -#define OFFSET_MAX ((off_t)LONG_MAX) /* FIXME: move elsewhere? */ - static int flock_make_lock(struct file *filp, struct file_lock *fl, unsigned int cmd); static int posix_make_lock(struct file *filp, struct file_lock *fl, @@ -195,9 +193,9 @@ static void locks_insert_block(struct file_lock *blocker, if (waiter->fl_prevblock) { printk(KERN_ERR "locks_insert_block: remove duplicated lock " - "(pid=%d %ld-%ld type=%d)\n", - waiter->fl_pid, waiter->fl_start, - waiter->fl_end, waiter->fl_type); + "(pid=%d %Ld-%Ld type=%d)\n", + waiter->fl_pid, (long long)waiter->fl_start, + (long long)waiter->fl_end, waiter->fl_type); locks_delete_block(waiter->fl_prevblock, waiter); } @@ -338,10 +336,6 @@ int fcntl_getlk(unsigned int fd, struct flock *l) if (!filp) goto out; - error = -EINVAL; - if (!filp->f_dentry || !filp->f_dentry->d_inode) - goto out_putf; - if (!posix_make_lock(filp, &file_lock, &flock)) goto out_putf; @@ -385,7 +379,6 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) struct file *filp; struct file_lock file_lock; struct flock flock; - struct dentry * dentry; struct inode *inode; int error; @@ -405,10 +398,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l) goto out; error = -EINVAL; - if (!(dentry = filp->f_dentry)) - goto out_putf; - if (!(inode = dentry->d_inode)) - goto out_putf; + inode = filp->f_dentry->d_inode; /* Don't allow mandatory locks on files that may be memory mapped * and shared. @@ -616,7 +606,7 @@ repeat: /* Block for writes against a "read" lock, * and both reads and writes against a "write" lock. */ - if (posix_locks_conflict(fl, &tfl)) { + if (posix_locks_conflict(&tfl, fl)) { error = -EAGAIN; if (filp && (filp->f_flags & O_NONBLOCK)) break; @@ -650,7 +640,7 @@ repeat: static int posix_make_lock(struct file *filp, struct file_lock *fl, struct flock *l) { - off_t start; + loff_t start; memset(fl, 0, sizeof(*fl)); @@ -683,8 +673,11 @@ static int posix_make_lock(struct file *filp, struct file_lock *fl, if (((start += l->l_start) < 0) || (l->l_len < 0)) return (0); + fl->fl_end = start + l->l_len - 1; + if (l->l_len > 0 && fl->fl_end < 0) + return (0); fl->fl_start = start; /* we record the absolute position */ - if ((l->l_len == 0) || ((fl->fl_end = start + l->l_len - 1) < 0)) + if (l->l_len == 0) fl->fl_end = OFFSET_MAX; fl->fl_file = filp; @@ -703,8 +696,6 @@ static int flock_make_lock(struct file *filp, struct file_lock *fl, memset(fl, 0, sizeof(*fl)); init_waitqueue_head(&fl->fl_wait); - if (!filp->f_dentry) /* just in case */ - return (0); switch (cmd & ~LOCK_NB) { case LOCK_SH: @@ -1128,6 +1119,8 @@ static struct file_lock *locks_init_lock(struct file_lock *new, new->fl_start = fl->fl_start; new->fl_end = fl->fl_end; new->fl_notify = fl->fl_notify; + new->fl_insert = fl->fl_insert; + new->fl_remove = fl->fl_remove; new->fl_u = fl->fl_u; } return new; @@ -1146,6 +1139,9 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl) fl->fl_next = *pos; /* insert into file's list */ *pos = fl; + if (fl->fl_insert) + fl->fl_insert(fl); + return; } @@ -1173,6 +1169,9 @@ static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait) prevfl->fl_nextlink = nextfl; else file_lock_table = nextfl; + + if (thisfl->fl_remove) + thisfl->fl_remove(thisfl); locks_wake_up_blocks(thisfl, wait); locks_free_lock(thisfl); @@ -1201,10 +1200,10 @@ static char *lock_get_status(struct file_lock *fl, int id, char *pfx) p += sprintf(p, "FLOCK ADVISORY "); } p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE"); - p += sprintf(p, "%d %s:%ld %ld %ld ", + p += sprintf(p, "%d %s:%ld %Ld %Ld ", fl->fl_pid, - kdevname(inode->i_dev), inode->i_ino, fl->fl_start, - fl->fl_end); + kdevname(inode->i_dev), inode->i_ino, + (long long)fl->fl_start, (long long)fl->fl_end); sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n", (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink, (long)fl->fl_next, (long)fl->fl_nextblock); @@ -1212,7 +1211,7 @@ static char *lock_get_status(struct file_lock *fl, int id, char *pfx) } static inline int copy_lock_status(char *p, char **q, off_t pos, int len, - off_t offset, off_t length) + off_t offset, int length) { off_t i; @@ -1236,7 +1235,7 @@ static inline int copy_lock_status(char *p, char **q, off_t pos, int len, return (1); } -int get_locks_status(char *buffer, char **start, off_t offset, off_t length) +int get_locks_status(char *buffer, char **start, off_t offset, int length) { struct file_lock *fl; struct file_lock *bfl; diff --git a/fs/namei.c b/fs/namei.c index 8675e28c5bbe..84828e49a47c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -279,7 +279,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i return result; } -static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry, unsigned int follow) +static inline struct dentry * +do_follow_link(struct dentry *base, struct dentry *dentry, + struct vfsmount **vfsmnt, unsigned int follow) { struct inode * inode = dentry->d_inode; @@ -290,7 +292,8 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry current->link_count++; /* This eats the base */ - result = inode->i_op->follow_link(dentry, base, follow); + result = inode->i_op->follow_link(dentry, base, + vfsmnt, follow); current->link_count--; dput(dentry); return result; @@ -302,6 +305,52 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry return dentry; } +/* MOUNT_REWRITE: add vfmount ** when lookup_dentry will get it */ +static inline struct dentry * +__emul_lookup_dentry(const char *name, int lookup_flags) +{ + struct dentry *base; + char *emul = __emul_prefix(); + + if (!emul) + return NULL; + + if (emul[0] == '/') + BUG(); + + base = lookup_dentry (emul, + dget (current->fs->root), + (LOOKUP_FOLLOW | LOOKUP_DIRECTORY)); + + if (IS_ERR (base)) + return NULL; + if (!base->d_inode) { + dput(base); + return NULL; + } + base = lookup_dentry (name, base, lookup_flags); + + if (IS_ERR (base)) return NULL; + + if (!base->d_inode) { + struct dentry *fromroot; + + fromroot = lookup_dentry(name, dget(current->fs->root), + lookup_flags); + + if (IS_ERR (fromroot)) return base; + + if (fromroot->d_inode) { + dput(base); + return fromroot; + } + + dput(fromroot); + } + + return base; +} + static inline struct dentry * follow_mount(struct dentry * dentry) { struct dentry * mnt = dentry->d_mounts; @@ -324,6 +373,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, unsigned { struct dentry * dentry; struct inode *inode; + struct vfsmount *mnt = NULL; if (*name == '/') { if (base) @@ -331,7 +381,10 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, unsigned do { name++; } while (*name == '/'); - __prefix_lookup_dentry(name, lookup_flags); + if (current->personality) { + dentry = __emul_lookup_dentry(name,lookup_flags); + if (dentry) return dentry; + } base = dget(current->fs->root); } else if (!base) { base = dget(current->fs->pwd); @@ -408,7 +461,7 @@ struct dentry * lookup_dentry(const char * name, struct dentry * base, unsigned dentry = follow_mount(dentry); } - base = do_follow_link(base, dentry, flags); + base = do_follow_link(base, dentry, &mnt, flags); if (IS_ERR(base)) goto return_base; @@ -600,7 +653,7 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir) return -ENOTDIR; if (IS_ROOT(victim)) return -EBUSY; - if (victim->d_mounts != victim->d_covers) + if (d_mountpoint(victim)) return -EBUSY; } else if (S_ISDIR(victim->d_inode->i_mode)) return -EISDIR; @@ -679,7 +732,8 @@ exit_lock: * which is a lot more logical, and also allows the "no perm" needed * for symlinks (where the permissions are checked later). */ -struct dentry * __open_namei(const char * pathname, int flag, int mode, struct dentry * dir) +/* MOUNT_REWRITE: pass mnt to lookup_dentry */ +struct dentry * open_namei(const char * pathname, int flag, int mode, struct dentry * dir, struct vfsmount **mnt) { int acc_mode, error; struct inode *inode; @@ -1082,13 +1136,13 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) return error; } -int do_unlink(const char * name, struct dentry * base) +static int do_unlink(const char * name) { int error; struct dentry *dir; struct dentry *dentry; - dentry = lookup_dentry(name, base, 0); + dentry = lookup_dentry(name, NULL, 0); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto exit; @@ -1113,7 +1167,7 @@ asmlinkage long sys_unlink(const char * pathname) if(IS_ERR(tmp)) return PTR_ERR(tmp); lock_kernel(); - error = do_unlink(tmp, NULL); + error = do_unlink(tmp); unlock_kernel(); putname(tmp); @@ -1512,9 +1566,10 @@ out: return len; } +/* MOUNT_REWRITE: pass &mnt to lookup_dentry */ static inline struct dentry * __vfs_follow_link(struct dentry *dentry, struct dentry *base, - unsigned follow, const char *link) + struct vfsmount **mnt, unsigned int follow, const char *link) { struct dentry *result; UPDATE_ATIME(dentry->d_inode); @@ -1532,9 +1587,9 @@ fail: struct dentry * vfs_follow_link(struct dentry *dentry, struct dentry *base, -unsigned int follow, const char *link) + struct vfsmount **mnt, unsigned int follow, const char *link) { - return __vfs_follow_link(dentry,base,follow,link); + return __vfs_follow_link(dentry,base,mnt,follow,link); } /* get the link contents into pagecache */ @@ -1573,11 +1628,12 @@ int page_readlink(struct dentry *dentry, char *buffer, int buflen) } struct dentry * -page_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) +page_follow_link(struct dentry *dentry, struct dentry *base, + struct vfsmount **mnt, unsigned int follow) { struct page *page = NULL; char *s = page_getlink(dentry, &page); - struct dentry *res = __vfs_follow_link(dentry,base,follow,s); + struct dentry *res = __vfs_follow_link(dentry,base,mnt,follow,s); if (page) { kunmap(page); page_cache_release(page); diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 3c8aac510f0c..64ef9274bdfd 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -14,6 +14,9 @@ O_OBJS := inode.o file.o read.o write.o dir.o symlink.o proc.o \ ifdef CONFIG_ROOT_NFS O_OBJS += nfsroot.o mount_clnt.o endif +ifdef CONFIG_NFS_V3 + O_OBJS += nfs3proc.o nfs3xdr.o +endif M_OBJS := $(O_TARGET) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index cb84bc61200a..7d80e6468fb0 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -122,7 +122,7 @@ static inline long find_dirent_page(struct inode *inode, loff_t offset, struct nfs_entry *entry) { - decode_dirent_t decode = nfs_decode_dirent; + decode_dirent_t decode = NFS_PROTO(inode)->decode_dirent; struct page *page; unsigned long index = entry->offset >> PAGE_CACHE_SHIFT; long status = -EIO; @@ -213,7 +213,6 @@ long try_to_get_dirent_page(struct file *file, struct inode *inode, { struct dentry *dir = file->f_dentry; struct page *page; - struct nfs_fattr dir_attr; __u32 *p; unsigned long index = entry->offset >> PAGE_CACHE_SHIFT; long res = 0; @@ -238,13 +237,12 @@ long try_to_get_dirent_page(struct file *file, struct inode *inode, if (dtsize > PAGE_CACHE_SIZE) dtsize = PAGE_CACHE_SIZE; - res = nfs_proc_readdir(dir, &dir_attr, entry->cookie, p, dtsize, plus); + res = NFS_PROTO(inode)->readdir(dir, entry->cookie, p, dtsize, plus); kunmap(page); if (res < 0) goto error; - nfs_refresh_inode(inode, &dir_attr); if (PageError(page)) ClearPageError(page); SetPageUptodate(page); @@ -342,7 +340,7 @@ static int nfs_do_filldir(struct file *file, struct inode *inode, struct nfs_entry *entry, void *dirent, filldir_t filldir) { - decode_dirent_t decode = nfs_decode_dirent; + decode_dirent_t decode = NFS_PROTO(inode)->decode_dirent; struct page *page = entry->page; __u8 *p, *start; @@ -512,7 +510,8 @@ static inline int nfs_neg_need_reval(struct dentry *dentry) */ static int nfs_lookup_revalidate(struct dentry * dentry, int flags) { - struct dentry * parent = dentry->d_parent; + struct dentry *dir = dentry->d_parent; + struct inode *dir_i = dir->d_inode; struct inode * inode = dentry->d_inode; int error; struct nfs_fh fhandle; @@ -531,7 +530,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags) if (is_bad_inode(inode)) { dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n", - parent->d_name.name, dentry->d_name.name); + dir->d_name.name, dentry->d_name.name); goto out_bad; } @@ -546,8 +545,8 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags) /* * Do a new lookup and check the dentry attributes. */ - error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent), - dentry->d_name.name, &fhandle, &fattr); + error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, &fhandle, + &fattr); if (error) goto out_bad; @@ -576,8 +575,7 @@ out_bad: goto out_valid; d_drop(dentry); /* Purge readdir caches. */ - if (dentry->d_parent->d_inode) - nfs_zap_caches(dentry->d_parent->d_inode); + nfs_zap_caches(dir_i); if (inode && S_ISDIR(inode->i_mode)) nfs_zap_caches(inode); return 0; @@ -660,18 +658,19 @@ static void show_dentry(struct list_head * dlist) #endif /* NFS_PARANOIA */ #endif /* 0 */ -static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry) +static struct dentry *nfs_lookup(struct inode *dir_i, struct dentry * dentry) { + struct dentry *dir = dentry->d_parent; struct inode *inode; int error; struct nfs_fh fhandle; struct nfs_fattr fattr; dfprintk(VFS, "NFS: lookup(%s/%s)\n", - dentry->d_parent->d_name.name, dentry->d_name.name); + dir->d_name.name, dentry->d_name.name); error = -ENAMETOOLONG; - if (dentry->d_name.len > NFS_MAXNAMLEN) + if (dentry->d_name.len > NFS_SERVER(dir_i)->namelen) goto out; error = -ENOMEM; @@ -682,8 +681,8 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry) } dentry->d_op = &nfs_dentry_operations; - error = nfs_proc_lookup(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name, &fhandle, &fattr); + error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, &fhandle, + &fattr); inode = NULL; if (error == -ENOENT) goto no_entry; @@ -716,6 +715,7 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, nfs_renew_times(dentry); error = 0; } + NFS_CACHEINV(dentry->d_parent->d_inode); return error; } @@ -725,28 +725,32 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, * that the operation succeeded on the server, but an error in the * reply path made it appear to have failed. */ -static int nfs_create(struct inode *dir, struct dentry *dentry, int mode) +static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode) { - int error; + struct dentry *dir = dentry->d_parent; struct iattr attr; struct nfs_fattr fattr; struct nfs_fh fhandle; + int error; dfprintk(VFS, "NFS: create(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); + dir_i->i_dev, dir_i->i_ino, dentry->d_name.name); attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; /* - * Invalidate the dir cache before the operation to avoid a race. + * The 0 argument passed into the create function should one day + * contain the O_EXCL flag if requested. This allows NFSv3 to + * select the appropriate create strategy. Currently open_namei + * does not pass the create flags. */ - nfs_zap_caches(dir); - error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name, &attr, &fhandle, &fattr); - if (!error) + nfs_zap_caches(dir_i); + error = NFS_PROTO(dir_i)->create(dir, &dentry->d_name, + &attr, 0, &fhandle, &fattr); + if (!error && fhandle.size != 0) error = nfs_instantiate(dentry, &fhandle, &fattr); - if (error) + if (error || fhandle.size == 0) d_drop(dentry); return error; } @@ -754,30 +758,26 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode) /* * See comments for nfs_proc_create regarding failed operations. */ -static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev) +static int nfs_mknod(struct inode *dir_i, struct dentry *dentry, int mode, int rdev) { - int error; + struct dentry *dir = dentry->d_parent; struct iattr attr; struct nfs_fattr fattr; struct nfs_fh fhandle; + int error; dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); + dir_i->i_dev, dir_i->i_ino, dentry->d_name.name); attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; - /* FIXME: move this to a special nfs_proc_mknod() */ - if (S_ISCHR(mode) || S_ISBLK(mode)) { - attr.ia_size = rdev; /* get out your barf bag */ - attr.ia_valid |= ATTR_SIZE; - } - nfs_zap_caches(dir); - error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name, &attr, &fhandle, &fattr); - if (!error) + nfs_zap_caches(dir_i); + error = NFS_PROTO(dir_i)->mknod(dir, &dentry->d_name, &attr, rdev, + &fhandle, &fattr); + if (!error && fhandle.size != 0) error = nfs_instantiate(dentry, &fhandle, &fattr); - if (error) + if (error || fhandle.size == 0) d_drop(dentry); return error; } @@ -785,19 +785,21 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde /* * See comments for nfs_proc_create regarding failed operations. */ -static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode) { - int error; + struct dentry *dir = dentry->d_parent; struct iattr attr; struct nfs_fattr fattr; struct nfs_fh fhandle; + int error; dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); + dir_i->i_dev, dir_i->i_ino, dentry->d_name.name); attr.ia_valid = ATTR_MODE; attr.ia_mode = mode | S_IFDIR; +#if 0 /* * Always drop the dentry, we can't always depend on * the fattr returned by the server (AIX seems to be @@ -805,42 +807,48 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) * depending on potentially bogus information. */ d_drop(dentry); - nfs_zap_caches(dir); - error = nfs_proc_mkdir(NFS_DSERVER(dentry), NFS_FH(dentry->d_parent), - dentry->d_name.name, &attr, &fhandle, &fattr); - if (!error) - dir->i_nlink++; +#endif + nfs_zap_caches(dir_i); + dir_i->i_nlink++; + error = NFS_PROTO(dir_i)->mkdir(dir, &dentry->d_name, &attr, &fhandle, + &fattr); + if (!error && fhandle.size != 0) + error = nfs_instantiate(dentry, &fhandle, &fattr); + if (error || fhandle.size == 0) + d_drop(dentry); return error; } -static int nfs_rmdir(struct inode *dir, struct dentry *dentry) +static int nfs_rmdir(struct inode *dir_i, struct dentry *dentry) { + struct dentry *dir = dentry->d_parent; int error; dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n", - dir->i_dev, dir->i_ino, dentry->d_name.name); + dir_i->i_dev, dir_i->i_ino, dentry->d_name.name); - nfs_zap_caches(dir); - error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name); + nfs_zap_caches(dir_i); + error = NFS_PROTO(dir_i)->rmdir(dir, &dentry->d_name); /* Update i_nlink and invalidate dentry. */ if (!error) { d_drop(dentry); - if (dir->i_nlink) - dir->i_nlink--; + if (dir_i->i_nlink) + dir_i->i_nlink--; } return error; } -static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) +static int nfs_sillyrename(struct inode *dir_i, struct dentry *dentry) { + struct dentry *dir = dentry->d_parent; static unsigned int sillycounter = 0; - const int i_inosize = sizeof(dir->i_ino)*2; + const int i_inosize = sizeof(dir_i->i_ino)*2; const int countersize = sizeof(sillycounter)*2; const int slen = strlen(".nfs") + i_inosize + countersize; char silly[slen+1]; + struct qstr qsilly; struct dentry *sdentry; int error = -EIO; @@ -892,10 +900,10 @@ dentry->d_parent->d_name.name, dentry->d_name.name); goto out; } while(sdentry->d_inode != NULL); /* need negative lookup */ - nfs_zap_caches(dir); - error = nfs_proc_rename(NFS_SERVER(dir), - NFS_FH(dentry->d_parent), dentry->d_name.name, - NFS_FH(dentry->d_parent), silly); + nfs_zap_caches(dir_i); + qsilly.name = silly; + qsilly.len = strlen(silly); + error = NFS_PROTO(dir_i)->rename(dir, &dentry->d_name, dir, &qsilly); if (!error) { nfs_renew_times(dentry); d_move(dentry, sdentry); @@ -916,7 +924,8 @@ out: */ static int nfs_safe_remove(struct dentry *dentry) { - struct inode *dir = dentry->d_parent->d_inode; + struct dentry *dir = dentry->d_parent; + struct inode *dir_i = dir->d_inode; struct inode *inode = dentry->d_inode; int error, rehash = 0; @@ -947,21 +956,22 @@ dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); d_drop(dentry); rehash = 1; } + nfs_zap_caches(dir_i); + error = NFS_PROTO(dir_i)->remove(dir, &dentry->d_name); + if (error < 0) + goto out; /* - * Update i_nlink and free the inode before unlinking. + * Update i_nlink and free the inode */ if (inode) { if (inode->i_nlink) inode->i_nlink --; d_delete(dentry); } - nfs_zap_caches(dir); - error = nfs_proc_remove(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name); /* * Rehash the negative dentry if the operation succeeded. */ - if (!error && rehash) + if (rehash) d_add(dentry, NULL); out: return error; @@ -990,16 +1000,22 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) } static int -nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +nfs_symlink(struct inode *dir_i, struct dentry *dentry, const char *symname) { + struct dentry *dir = dentry->d_parent; struct iattr attr; + struct nfs_fattr sym_attr; + struct nfs_fh sym_fh; + struct qstr qsymname; + unsigned int maxlen; int error; dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n", - dir->i_dev, dir->i_ino, dentry->d_name.name, symname); + dir_i->i_dev, dir_i->i_ino, dentry->d_name.name, symname); error = -ENAMETOOLONG; - if (strlen(symname) > NFS_MAXPATHLEN) + maxlen = (NFS_PROTO(dir_i)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN; + if (strlen(symname) > maxlen) goto out; #ifdef NFS_PARANOIA @@ -1014,20 +1030,19 @@ dentry->d_parent->d_name.name, dentry->d_name.name); attr.ia_valid = ATTR_MODE; attr.ia_mode = S_IFLNK | S_IRWXUGO; - /* - * Drop the dentry in advance to force a new lookup. - * Since nfs_proc_symlink doesn't return a fattr, we - * can't instantiate the new inode. - */ - d_drop(dentry); - nfs_zap_caches(dir); - error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dentry->d_parent), - dentry->d_name.name, symname, &attr); - if (!error) { - nfs_renew_times(dentry->d_parent); - } else if (error == -EEXIST) { - printk("nfs_proc_symlink: %s/%s already exists??\n", - dentry->d_parent->d_name.name, dentry->d_name.name); + qsymname.name = symname; + qsymname.len = strlen(symname); + + nfs_zap_caches(dir_i); + error = NFS_PROTO(dir_i)->symlink(dir, &dentry->d_name, &qsymname, + &attr, &sym_fh, &sym_attr); + if (!error && sym_fh.size != 0 && (sym_attr.valid & NFS_ATTR_FATTR)) { + error = nfs_instantiate(dentry, &sym_fh, &sym_attr); + } else { + if (error == -EEXIST) + printk("nfs_proc_symlink: %s/%s already exists??\n", + dir->d_name.name, dentry->d_name.name); + d_drop(dentry); } out: @@ -1035,8 +1050,9 @@ out: } static int -nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) +nfs_link(struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry) { + struct dentry *dir = dentry->d_parent; struct inode *inode = old_dentry->d_inode; int error; @@ -1050,9 +1066,8 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) * we can't use the existing dentry. */ d_drop(dentry); - nfs_zap_caches(dir); - error = nfs_proc_link(NFS_DSERVER(old_dentry), NFS_FH(old_dentry), - NFS_FH(dentry->d_parent), dentry->d_name.name); + nfs_zap_caches(dir_i); + error = NFS_PROTO(dir_i)->link(old_dentry, dir, &dentry->d_name); if (!error) { /* * Update the link count immediately, as some apps @@ -1164,10 +1179,10 @@ go_ahead: nfs_zap_caches(new_dir); nfs_zap_caches(old_dir); - error = nfs_proc_rename(NFS_DSERVER(old_dentry), - NFS_FH(old_dentry->d_parent), old_dentry->d_name.name, - NFS_FH(new_dentry->d_parent), new_dentry->d_name.name); - + error = NFS_PROTO(old_dir)->rename(old_dentry->d_parent, + &old_dentry->d_name, + new_dentry->d_parent, + &new_dentry->d_name); NFS_CACHEINV(old_dir); NFS_CACHEINV(new_dir); /* Update the dcache if needed */ @@ -1195,6 +1210,12 @@ int nfs_init_fhcache(void) return 0; } +void nfs_destroy_fhcache(void) +{ + if (kmem_cache_destroy(nfs_fh_cachep)) + printk(KERN_INFO "nfs_fh: not all structures were freed\n"); +} + /* * Local variables: * version-control: t diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 7483f1ebe096..d5c3d094433a 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -216,10 +216,10 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl) struct inode * inode = filp->f_dentry->d_inode; int status = 0; - dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%ld:%ld)\n", + dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n", inode->i_dev, inode->i_ino, fl->fl_type, fl->fl_flags, - fl->fl_start, fl->fl_end); + (long long)fl->fl_start, (long long)fl->fl_end); if (!inode) return -EINVAL; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index a002db4bcb86..14c43cd24aa7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -59,7 +59,26 @@ static struct super_operations nfs_sops = { umount_begin: nfs_umount_begin, }; +/* + * RPC cruft for NFS + */ struct rpc_stat nfs_rpcstat = { &nfs_program }; +static struct rpc_version * nfs_version[] = { + NULL, + NULL, + &nfs_version2, +#ifdef CONFIG_NFS_V3 + &nfs_version3, +#endif +}; + +struct rpc_program nfs_program = { + "nfs", + NFS_PROGRAM, + sizeof(nfs_version) / sizeof(nfs_version[0]), + nfs_version, + &nfs_rpcstat, +}; static inline unsigned long nfs_fattr_to_ino_t(struct nfs_fattr *fattr) @@ -161,7 +180,7 @@ nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) { /* make sure blocksize is a power of two */ if ((bsize & (bsize - 1)) || nrbitsp) { - unsigned int nrbits; + unsigned char nrbits; for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) ; @@ -197,6 +216,26 @@ nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) return nfs_block_bits(bsize, nrbitsp); } +/* + * Obtain the root inode of the file system. + */ +static struct inode * +nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh) +{ + struct nfs_server *server = &sb->u.nfs_sb.s_server; + struct nfs_fattr fattr; + struct inode *inode; + int error; + + if ((error = server->rpc_ops->getroot(server, rootfh, &fattr)) < 0) { + printk(KERN_NOTICE "nfs_get_root: getattr error = %d\n", -error); + return NULL; + } + + inode = __nfs_fhget(sb, &fattr); + return inode; +} + extern struct nfs_fh *nfs_fh_alloc(void); extern void nfs_fh_free(struct nfs_fh *p); @@ -211,19 +250,20 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) { struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data; struct nfs_server *server; - struct rpc_xprt *xprt; - struct rpc_clnt *clnt; - struct nfs_fh *root_fh; - struct inode *root_inode; + struct rpc_xprt *xprt = NULL; + struct rpc_clnt *clnt = NULL; + struct nfs_fh *root = &data->root, *root_fh, fh; + struct inode *root_inode = NULL; unsigned int authflavor; - int tcp; struct sockaddr_in srvaddr; struct rpc_timeout timeparms; - struct nfs_fattr fattr; + struct nfs_fsinfo fsinfo; + int tcp, version, maxlen; if (!data) goto out_miss_args; + memset(&fh, 0, sizeof(fh)); if (data->version != NFS_MOUNT_VERSION) { printk("nfs warning: mount version %s than kernel\n", data->version < NFS_MOUNT_VERSION ? "older" : "newer"); @@ -231,6 +271,12 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) data->namlen = 0; if (data->version < 3) data->bsize = 0; + if (data->version < 4) { + data->flags &= ~NFS_MOUNT_VER3; + root = &fh; + root->size = NFS2_FHSIZE; + memcpy(root->data, data->old_root.data, NFS2_FHSIZE); + } } /* We now require that the mount process passes the remote address */ @@ -242,11 +288,12 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) sb->s_magic = NFS_SUPER_MAGIC; sb->s_op = &nfs_sops; + sb->s_blocksize_bits = 0; sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); server = &sb->u.nfs_sb.s_server; - server->dtsize = server->rsize = nfs_block_size(data->rsize, NULL); + server->rsize = nfs_block_size(data->rsize, NULL); server->wsize = nfs_block_size(data->wsize, NULL); - server->flags = data->flags; + server->flags = data->flags & NFS_MOUNT_FLAGMASK; if (data->flags & NFS_MOUNT_NOAC) { data->acregmin = data->acregmax = 0; @@ -257,11 +304,32 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) server->acdirmin = data->acdirmin*HZ; server->acdirmax = data->acdirmax*HZ; + server->namelen = data->namlen; server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); if (!server->hostname) goto out_unlock; strcpy(server->hostname, data->hostname); + nfsv3_try_again: + /* Check NFS protocol revision and initialize RPC op vector + * and file handle pool. */ + if (data->flags & NFS_MOUNT_VER3) { +#ifdef CONFIG_NFS_V3 + server->rpc_ops = &nfs_v3_clientops; + version = 3; + if (data->version < 4) { + printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n"); + goto out_unlock; + } +#else + printk(KERN_NOTICE "NFS: NFSv3 not supported.\n"); + goto out_unlock; +#endif + } else { + server->rpc_ops = &nfs_v2_clientops; + version = 2; + } + /* Which protocol do we use? */ tcp = (data->flags & NFS_MOUNT_TCP); @@ -271,6 +339,11 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) timeparms.to_maxval = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT; timeparms.to_exponential = 1; + if (!timeparms.to_initval) + timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10; + if (!timeparms.to_retries) + timeparms.to_retries = 5; + /* Now create transport and client */ xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP, &srvaddr, &timeparms); @@ -285,7 +358,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) authflavor = RPC_AUTH_KRB; clnt = rpc_create_client(xprt, server->hostname, &nfs_program, - NFS_VERSION, authflavor); + version, authflavor); if (clnt == NULL) goto out_no_client; @@ -305,20 +378,68 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) root_fh = nfs_fh_alloc(); if (!root_fh) goto out_no_fh; - *root_fh = data->root; - - if (nfs_proc_getattr(server, root_fh, &fattr) != 0) - goto out_no_fattr; + memcpy((u8*)root_fh, (u8*)root, sizeof(*root)); + + /* Did getting the root inode fail? */ + if (!(root_inode = nfs_get_root(sb, root)) + && (data->flags & NFS_MOUNT_VER3)) { + data->flags &= ~NFS_MOUNT_VER3; + nfs_fh_free(root_fh); + rpciod_down(); + rpc_shutdown_client(server->client); + goto nfsv3_try_again; + } - root_inode = __nfs_fhget(sb, &fattr); if (!root_inode) goto out_no_root; sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) goto out_no_root; + sb->s_root->d_op = &nfs_dentry_operations; sb->s_root->d_fsdata = root_fh; + /* Get some general file system info */ + if (server->rpc_ops->statfs(server, root, &fsinfo) >= 0) { + if (server->namelen == 0) + server->namelen = fsinfo.namelen; + } else { + printk(KERN_NOTICE "NFS: cannot retrieve file system info.\n"); + goto out_no_root; + } + + /* Work out a lot of parameters */ + if (data->rsize == 0) + server->rsize = nfs_block_size(fsinfo.rtpref, NULL); + if (data->wsize == 0) + server->wsize = nfs_block_size(fsinfo.wtpref, NULL); + server->dtsize = nfs_block_size(fsinfo.dtpref, NULL); + /* NFSv3: we don't have bsize, but rather rtmult and wtmult... */ + if (!fsinfo.bsize) + fsinfo.bsize = (fsinfo.rtmult>fsinfo.wtmult) ? fsinfo.rtmult : fsinfo.wtmult; + /* Also make sure we don't go below rsize/wsize since + * RPC calls are expensive */ + if (fsinfo.bsize < server->rsize) + fsinfo.bsize = server->rsize; + if (fsinfo.bsize < server->wsize) + fsinfo.bsize = server->wsize; + + if (data->bsize == 0) + sb->s_blocksize = nfs_block_bits(fsinfo.bsize, &sb->s_blocksize_bits); + if (server->rsize > fsinfo.rtmax) + server->rsize = fsinfo.rtmax; + if (server->rsize > PAGE_CACHE_SIZE) + server->rsize = PAGE_CACHE_SIZE; + if (server->wsize > fsinfo.wtmax) + server->wsize = fsinfo.wtmax; + if (server->wsize > NFS_WRITE_MAXIOV << PAGE_CACHE_SHIFT) + server->wsize = NFS_WRITE_MAXIOV << PAGE_CACHE_SHIFT; + + maxlen = (version == 2) ? NFS2_MAXNAMLEN : NFS3_MAXNAMLEN; + + if (server->namelen == 0 || server->namelen > maxlen) + server->namelen = maxlen; + /* Fire up the writeback cache */ if (nfs_reqlist_alloc(server) < 0) { printk(KERN_NOTICE "NFS: cannot initialize writeback cache.\n"); @@ -338,11 +459,6 @@ 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: nfs_fh_free(root_fh); out_no_fh: rpciod_down(); @@ -382,21 +498,33 @@ out_fail: static int nfs_statfs(struct super_block *sb, struct statfs *buf) { - int error; + struct nfs_server *server = &sb->u.nfs_sb.s_server; + unsigned char blockbits; + unsigned long blockres; struct nfs_fsinfo res; + int error; - error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, NFS_FH(sb->s_root), - &res); - if (error) { - printk("nfs_statfs: statfs error = %d\n", -error); - res.bsize = res.blocks = res.bfree = res.bavail = -1; - } + error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root), &res); buf->f_type = NFS_SUPER_MAGIC; - buf->f_bsize = res.bsize; - buf->f_blocks = res.blocks; - buf->f_bfree = res.bfree; - buf->f_bavail = res.bavail; - buf->f_namelen = NAME_MAX; + if (error < 0) + goto out_err; + + if (res.bsize == 0) + res.bsize = sb->s_blocksize; + buf->f_bsize = nfs_block_bits(res.bsize, &blockbits); + blockres = (1 << blockbits) - 1; + buf->f_blocks = (res.tbytes + blockres) >> blockbits; + buf->f_bfree = (res.fbytes + blockres) >> blockbits; + buf->f_bavail = (res.abytes + blockres) >> blockbits; + buf->f_files = res.tfiles; + buf->f_ffree = res.afiles; + if (res.namelen == 0 || res.namelen > server->namelen) + res.namelen = server->namelen; + buf->f_namelen = res.namelen; + return 0; + out_err: + printk("nfs_statfs: statfs error = %d\n", -error); + buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; return 0; } @@ -693,8 +821,7 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error); if (error) goto out; - error = nfs_proc_setattr(NFS_DSERVER(dentry), NFS_FH(dentry), - &fattr, attr); + error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); if (error) goto out; /* @@ -792,30 +919,32 @@ __nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry) } NFS_FLAGS(inode) |= NFS_INO_REVALIDATING; - status = nfs_proc_getattr(server, NFS_FH(dentry), &fattr); + status = NFS_PROTO(inode)->getattr(dentry, &fattr); if (status) { + struct dentry *dir = dentry->d_parent; + struct inode *dir_i = dir->d_inode; int error; u32 *fh; struct nfs_fh fhandle; dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n", - dentry->d_parent->d_name.name, - dentry->d_name.name, inode->i_ino, status); + dir->d_name.name, dentry->d_name.name, + inode->i_ino, status); if (status != -ESTALE) goto out; /* * A "stale filehandle" error ... show the current fh * and find out what the filehandle should be. */ - fh = (u32 *) NFS_FH(dentry); + fh = (u32 *) NFS_FH(dentry)->data; dfprintk(PAGECACHE, "NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n", fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]); - error = nfs_proc_lookup(server, NFS_FH(dentry->d_parent), - dentry->d_name.name, &fhandle, &fattr); + error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, + &fhandle, &fattr); if (error) { dfprintk(PAGECACHE, "NFS: lookup failed, error=%d\n", error); goto out; } - fh = (u32 *) &fhandle; + fh = (u32 *) fhandle.data; dfprintk(PAGECACHE, " %08x%08x%08x%08x%08x%08x%08x%08x\n", fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]); goto out; @@ -1013,7 +1142,9 @@ out_changed: static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, 0); extern int nfs_init_fhcache(void); +extern void nfs_destroy_fhcache(void); extern int nfs_init_nfspagecache(void); +extern void nfs_destroy_nfspagecache(void); /* * Initialize NFS @@ -1055,6 +1186,8 @@ init_module(void) void cleanup_module(void) { + nfs_destroy_nfspagecache(); + nfs_destroy_fhcache(); #ifdef CONFIG_PROC_FS rpc_proc_unregister("nfs"); #endif diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index f74984de2a86..0adfacd3e50b 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -30,7 +30,9 @@ #define MOUNT_UMNT 3 */ -static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *); +static int nfs_gen_mount(struct sockaddr_in *, + char *, struct nfs_fh *, int); +static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *, int); extern struct rpc_program mnt_program; struct mnt_fhstatus { @@ -43,25 +45,39 @@ struct mnt_fhstatus { */ int nfs_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh) +{ + return nfs_gen_mount(addr, path, fh, NFS_MNT_VERSION); +} + +int +nfs3_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh) +{ + return nfs_gen_mount(addr, path, fh, NFS_MNT3_VERSION); +} + +static int +nfs_gen_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh, int version) { struct rpc_clnt *mnt_clnt; struct mnt_fhstatus result = { 0, fh }; char hostname[32]; int status; + int call; dprintk("NFS: nfs_mount(%08x:%s)\n", (unsigned)ntohl(addr->sin_addr.s_addr), path); strcpy(hostname, in_ntoa(addr->sin_addr.s_addr)); - if (!(mnt_clnt = mnt_create(hostname, addr))) + if (!(mnt_clnt = mnt_create(hostname, addr, version))) return -EACCES; - status = rpc_call(mnt_clnt, NFS_MNTPROC_MNT, path, &result, 0); + call = (version == 3) ? MOUNTPROC3_MNT : MNTPROC_MNT; + status = rpc_call(mnt_clnt, call, path, &result, 0); return status < 0? status : (result.status? -EACCES : 0); } static struct rpc_clnt * -mnt_create(char *hostname, struct sockaddr_in *srvaddr) +mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version) { struct rpc_xprt *xprt; struct rpc_clnt *clnt; @@ -70,7 +86,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr) return NULL; clnt = rpc_create_client(xprt, hostname, - &mnt_program, NFS_MNT_VERSION, + &mnt_program, version, RPC_AUTH_NULL); if (!clnt) { xprt_destroy(xprt); @@ -104,8 +120,26 @@ xdr_encode_dirpath(struct rpc_rqst *req, u32 *p, const char *path) static int xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) { - if ((res->status = ntohl(*p++)) == 0) - memcpy(res->fh, p, sizeof(*res->fh)); + memset((u8 *)res, 0, sizeof(*res)); + if ((res->status = ntohl(*p++)) == 0) { + res->fh->size = NFS2_FHSIZE; + memcpy(res->fh->data, p, NFS2_FHSIZE); + } + return 0; +} + +static int +xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res) +{ + memset((u8 *)res, 0, sizeof(*res)); + if ((res->status = ntohl(*p++)) == 0) { + int size = ntohl(*p++); + if (size <= NFS3_FHSIZE) { + res->fh->size = size; + memcpy(res->fh->data, p, res->fh->size); + } else + res->status = -EBADHANDLE; + } return 0; } @@ -122,13 +156,30 @@ static struct rpc_procinfo mnt_procedures[2] = { MNT_dirpath_sz << 2, 0 }, }; +static struct rpc_procinfo mnt3_procedures[2] = { + { "mnt3_null", + (kxdrproc_t) xdr_error, + (kxdrproc_t) xdr_error, 0, 0 }, + { "mnt3_mount", + (kxdrproc_t) xdr_encode_dirpath, + (kxdrproc_t) xdr_decode_fhstatus3, + MNT_dirpath_sz << 2, 0 }, +}; + + static struct rpc_version mnt_version1 = { 1, 2, mnt_procedures }; +static struct rpc_version mnt_version3 = { + 3, 2, mnt3_procedures +}; + static struct rpc_version * mnt_version[] = { NULL, &mnt_version1, + NULL, + &mnt_version3, }; static struct rpc_stat mnt_stats; diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 477247d48980..1dd1553ba138 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -1,14 +1,14 @@ /* - * linux/fs/nfs/xdr.c + * linux/fs/nfs/nfs2xdr.c * * XDR functions to encode/decode NFS RPC arguments and results. * * Copyright (C) 1992, 1993, 1994 Rick Sladkey * Copyright (C) 1996 Olaf Kirch + * 04 Aug 1998 Ion Badulescu + * FIFO's need special handling in NFSv2 */ -#define NFS_NEED_XDR_TYPES - #include #include #include @@ -30,8 +30,7 @@ #define NFSDBG_FACILITY NFSDBG_XDR /* #define NFS_PARANOIA 1 */ -#define QUADLEN(len) (((len) + 3) >> 2) -static int nfs_stat_to_errno(int stat); +extern int nfs_stat_to_errno(int stat); /* Mapping from NFS error code to "errno" error code. */ #define errno_NFSERR_IO EIO @@ -42,8 +41,8 @@ static int nfs_stat_to_errno(int stat); */ #define NFS_fhandle_sz 8 #define NFS_sattr_sz 8 -#define NFS_filename_sz 1+(NFS_MAXNAMLEN>>2) -#define NFS_path_sz 1+(NFS_MAXPATHLEN>>2) +#define NFS_filename_sz 1+(NFS2_MAXNAMLEN>>2) +#define NFS_path_sz 1+(NFS2_MAXPATHLEN>>2) #define NFS_fattr_sz 17 #define NFS_info_sz 5 #define NFS_entry_sz NFS_filename_sz+3 @@ -51,6 +50,7 @@ static int nfs_stat_to_errno(int stat); #define NFS_enc_void_sz 0 #define NFS_diropargs_sz NFS_fhandle_sz+NFS_filename_sz #define NFS_sattrargs_sz NFS_fhandle_sz+NFS_sattr_sz +#define NFS_readlinkargs_sz NFS_fhandle_sz #define NFS_readargs_sz NFS_fhandle_sz+3 #define NFS_writeargs_sz NFS_fhandle_sz+4 #define NFS_createargs_sz NFS_diropargs_sz+NFS_sattr_sz @@ -58,14 +58,13 @@ static int nfs_stat_to_errno(int stat); #define NFS_linkargs_sz NFS_fhandle_sz+NFS_diropargs_sz #define NFS_symlinkargs_sz NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz #define NFS_readdirargs_sz NFS_fhandle_sz+2 -#define NFS_readlinkargs_sz NFS_fhandle_sz #define NFS_dec_void_sz 0 #define NFS_attrstat_sz 1+NFS_fattr_sz #define NFS_diropres_sz 1+NFS_fhandle_sz+NFS_fattr_sz #define NFS_readlinkres_sz 1 #define NFS_readres_sz 1+NFS_fattr_sz+1 -#define NFS_writeres_sz NFS_attrstat_sz +#define NFS_writeres_sz NFS_attrstat_sz #define NFS_stat_sz 1 #define NFS_readdirres_sz 1 #define NFS_statfsres_sz 1+NFS_info_sz @@ -76,15 +75,19 @@ static int nfs_stat_to_errno(int stat); static inline u32 * xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle) { - *((struct nfs_fh *) p) = *fhandle; - return p + QUADLEN(sizeof(*fhandle)); + memcpy(p, fhandle->data, NFS2_FHSIZE); + return p + XDR_QUADLEN(NFS2_FHSIZE); } static inline u32 * xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle) { - *fhandle = *((struct nfs_fh *) p); - return p + QUADLEN(sizeof(*fhandle)); + /* Zero handle first to allow comparisons */ + memset(fhandle, 0, sizeof(*fhandle)); + /* NFSv2 handles have a fixed length */ + fhandle->size = NFS2_FHSIZE; + memcpy(fhandle->data, p, NFS2_FHSIZE); + return p + XDR_QUADLEN(NFS2_FHSIZE); } static inline u32 * @@ -95,7 +98,7 @@ xdr_decode_string2(u32 *p, char **string, unsigned int *len, if (*len > maxlen) return NULL; *string = (char *) p; - return p + QUADLEN(*len); + return p + XDR_QUADLEN(*len); } static inline u32* @@ -123,7 +126,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) p = xdr_decode_time(p, &fattr->mtime); p = xdr_decode_time(p, &fattr->ctime); fattr->valid |= NFS_ATTR_FATTR; - if (fattr->type == NFCHR && fattr->rdev == NFS_FIFO_DEV) { + if (fattr->type == NFCHR && fattr->rdev == NFS2_FIFO_DEV) { fattr->type = NFFIFO; fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; fattr->rdev = 0; @@ -131,7 +134,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) return p; } - #define SATTR(p, attr, flag, field) \ *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0 static inline u32 * @@ -206,7 +208,7 @@ static int nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args) { p = xdr_encode_fhandle(p, args->fh); - p = xdr_encode_string(p, args->name); + p = xdr_encode_array(p, args->name, args->len); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } @@ -220,7 +222,8 @@ static int nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; - int replen, buflen; + int buflen, replen; + unsigned int nr; p = xdr_encode_fhandle(p, args->fh); *p++ = htonl(args->offset); @@ -228,16 +231,25 @@ nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) *p++ = htonl(args->count); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + /* Get the number of buffers in the receive iovec */ + nr = args->nriov; + + if (nr+2 > MAX_IOVEC) { + printk(KERN_ERR "NFS: Bad number of iov's in xdr_readargs\n"); + return -EINVAL; + } + /* set up reply iovec */ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; buflen = req->rq_rvec[0].iov_len; req->rq_rvec[0].iov_len = replen; - req->rq_rvec[1].iov_base = args->buffer; - req->rq_rvec[1].iov_len = args->count; - req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; - req->rq_rvec[2].iov_len = buflen - replen; + /* Copy the iovec */ + memcpy(req->rq_rvec + 1, args->iov, nr * sizeof(struct iovec)); + + req->rq_rvec[nr+1].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; + req->rq_rvec[nr+1].iov_len = buflen - replen; req->rq_rlen = args->count + buflen; - req->rq_rnr = 3; + req->rq_rnr += nr+1; return 0; } @@ -251,7 +263,6 @@ nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) struct iovec *iov = req->rq_rvec; int status, count, recvd, hdrlen; - dprintk("RPC: readres OK status %lx\n", (long)ntohl(*p)); if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); p = xdr_decode_fattr(p, res->fattr); @@ -259,22 +270,26 @@ nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) count = ntohl(*p++); hdrlen = (u8 *) p - (u8 *) iov->iov_base; recvd = req->rq_rlen - hdrlen; - if (p != iov[2].iov_base) { + if (p != iov[req->rq_rnr-1].iov_base) { /* Unexpected reply header size. Punt. * XXX: Move iovec contents to align data on page * boundary and adjust RPC header size guess */ - printk("NFS: Odd RPC header size in read reply: %d\n", hdrlen); + printk(KERN_WARNING "NFS: Odd RPC header size in read reply: %d\n", hdrlen); return -errno_NFSERR_IO; } if (count > recvd) { - printk("NFS: server cheating in read reply: " + printk(KERN_WARNING "NFS: server cheating in read reply: " "count %d > recvd %d\n", count, recvd); count = recvd; } dprintk("RPC: readres OK count %d\n", count); - if (count < res->count) - memset((u8 *)(iov[1].iov_base+count), 0, res->count-count); + if (count < res->count) { + xdr_zero_iovec(iov+1, req->rq_rnr-2, res->count - count); + res->count = count; + res->eof = 1; /* Silly NFSv3ism which can't be helped */ + } else + res->eof = 0; return count; } @@ -300,13 +315,13 @@ nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) nr = args->nriov; if (nr+2 > MAX_IOVEC) { - printk(KERN_ERR "NFS: Bad number of iov's in xdr_writeargs " - "(nr %d max %d)\n", nr, MAX_IOVEC); - return -EINVAL; - } + printk(KERN_ERR "NFS: Bad number of iov's in xdr_writeargs " + "(nr %d max %d)\n", nr, MAX_IOVEC); + return -EINVAL; + } /* Copy the iovec */ - memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec)); + memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec)); #ifdef NFS_PAD_WRITES /* @@ -337,7 +352,7 @@ static int nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args) { p = xdr_encode_fhandle(p, args->fh); - p = xdr_encode_string(p, args->name); + p = xdr_encode_array(p, args->name, args->len); p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; @@ -350,9 +365,9 @@ static int nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args) { p = xdr_encode_fhandle(p, args->fromfh); - p = xdr_encode_string(p, args->fromname); + p = xdr_encode_array(p, args->fromname, args->fromlen); p = xdr_encode_fhandle(p, args->tofh); - p = xdr_encode_string(p, args->toname); + p = xdr_encode_array(p, args->toname, args->tolen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } @@ -365,7 +380,7 @@ nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_fhandle(p, args->tofh); - p = xdr_encode_string(p, args->toname); + p = xdr_encode_array(p, args->toname, args->tolen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } @@ -377,8 +392,8 @@ static int nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); - p = xdr_encode_string(p, args->fromname); - p = xdr_encode_string(p, args->topath); + p = xdr_encode_array(p, args->fromname, args->fromlen); + p = xdr_encode_array(p, args->topath, args->tolen); p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; @@ -392,20 +407,19 @@ nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args) { struct rpc_task *task = req->rq_task; struct rpc_auth *auth = task->tk_auth; - int bufsiz = args->bufsiz; + u32 bufsiz = args->bufsiz; int buflen, replen; - p = xdr_encode_fhandle(p, args->fh); - *p++ = htonl(args->cookie); - - /* Some servers (e.g. HP OS 9.5) seem to expect the buffer size + /* + * Some servers (e.g. HP OS 9.5) seem to expect the buffer size * to be in longwords ... check whether to convert the size. */ if (task->tk_client->cl_flags & NFS_CLNTF_BUFSIZE) - *p++ = htonl(bufsiz >> 2); - else - *p++ = htonl(bufsiz); + bufsiz = bufsiz >> 2; + p = xdr_encode_fhandle(p, args->fh); + *p++ = htonl(args->cookie); + *p++ = htonl(bufsiz); /* see above */ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); /* set up reply iovec */ @@ -413,10 +427,10 @@ nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args) buflen = req->rq_rvec[0].iov_len; req->rq_rvec[0].iov_len = replen; req->rq_rvec[1].iov_base = args->buffer; - req->rq_rvec[1].iov_len = bufsiz; + req->rq_rvec[1].iov_len = args->bufsiz; req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; req->rq_rvec[2].iov_len = buflen - replen; - req->rq_rlen = buflen + bufsiz; + req->rq_rlen = buflen + args->bufsiz; req->rq_rnr += 2; return 0; @@ -536,13 +550,9 @@ nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) { int status; - dprintk("RPC: attrstat status %lx\n", (long)ntohl(*p)); if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); xdr_decode_fattr(p, fattr); - dprintk("RPC: attrstat OK type %d mode %o dev %Lx ino %Lx\n", - fattr->type, fattr->mode, - (long long)fattr->fsid, (long long)fattr->fileid); return 0; } @@ -555,36 +565,34 @@ nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res) { int status; - dprintk("RPC: diropres status %lx\n", (long)ntohl(*p)); if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); p = xdr_decode_fhandle(p, res->fh); xdr_decode_fattr(p, res->fattr); - dprintk("RPC: diropres OK type %x mode %o dev %Lx ino %Lx\n", - res->fattr->type, res->fattr->mode, - (long long)res->fattr->fsid, (long long)res->fattr->fileid); return 0; } /* - * Encode arguments to readlink call + * Encode READLINK args */ -static int nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args) +static int +nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args) { struct rpc_task *task = req->rq_task; struct rpc_auth *auth = task->tk_auth; - int bufsiz = NFS_MAXPATHLEN; - int replen; + int buflen, replen; p = xdr_encode_fhandle(p, args->fh); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2; - req->rq_rvec[0].iov_len = replen; - req->rq_rvec[1].iov_base = (void *) args->buffer; - req->rq_rvec[1].iov_len = bufsiz; - req->rq_rlen = replen + bufsiz; - req->rq_rnr = 2; - + buflen = req->rq_rvec[0].iov_len; + req->rq_rvec[0].iov_len = replen; + req->rq_rvec[1].iov_base = args->buffer; + req->rq_rvec[1].iov_len = args->bufsiz; + req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; + req->rq_rvec[2].iov_len = buflen - replen; + req->rq_rlen = buflen + args->bufsiz; + req->rq_rnr += 2; return 0; } @@ -592,31 +600,24 @@ static int nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlin * Decode READLINK reply */ static int -nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy) +nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_readlinkres *res) { - struct iovec *iov = req->rq_rvec; - int status, len; - char *name; + u32 *strlen; + char *string; + int status; + unsigned int len; - /* Verify OK status. */ - if ((status = ntohl(*p++)) != 0) + if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); - - /* Verify OK response length. */ - if ((__u8 *)p != ((u8 *) iov->iov_base + iov->iov_len)) - return -errno_NFSERR_IO; - - /* Convert and verify that string length is in range. */ - p = iov[1].iov_base; - len = *p = ntohl(*p); - p++; - if (len > iov[1].iov_len) - return -errno_NFSERR_IO; - - /* NULL terminate the string we got. */ - name = (char *) p; - name[len] = 0; - + strlen = (u32*)res->buffer; + /* Convert length of symlink */ + len = ntohl(*strlen); + if (len > res->bufsiz - 5) + len = res->bufsiz - 5; + *strlen = len; + /* NULL terminate the string we got */ + string = (char *)(strlen + 1); + string[len] = 0; return 0; } @@ -637,14 +638,34 @@ static int nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) { int status; + u32 xfer_size; if ((status = ntohl(*p++))) return -nfs_stat_to_errno(status); - res->tsize = ntohl(*p++); - res->bsize = ntohl(*p++); - res->blocks = ntohl(*p++); - res->bfree = ntohl(*p++); - res->bavail = ntohl(*p++); + + /* For NFSv2, we more or less have to guess the preferred + * read/write/readdir sizes from the single 'transfer size' + * value. + */ + xfer_size = ntohl(*p++); /* tsize */ + res->rtmax = 8 * 1024; + res->rtpref = xfer_size; + res->rtmult = xfer_size; + res->wtmax = 8 * 1024; + res->wtpref = xfer_size; + res->wtmult = xfer_size; + res->dtpref = PAGE_CACHE_SIZE; + res->maxfilesize = 0x7FFFFFFF; /* just a guess */ + res->bsize = ntohl(*p++); + + res->tbytes = ntohl(*p++) * res->bsize; + res->fbytes = ntohl(*p++) * res->bsize; + res->abytes = ntohl(*p++) * res->bsize; + res->tfiles = 0; + res->ffiles = 0; + res->afiles = 0; + res->namelen = 0; + return 0; } @@ -661,7 +682,7 @@ static struct { { NFSERR_NOENT, ENOENT }, { NFSERR_IO, errno_NFSERR_IO }, { NFSERR_NXIO, ENXIO }, - { NFSERR_EAGAIN, EAGAIN }, +/* { NFSERR_EAGAIN, EAGAIN }, */ { NFSERR_ACCES, EACCES }, { NFSERR_EXIST, EEXIST }, { NFSERR_XDEV, EXDEV }, @@ -672,18 +693,31 @@ static struct { { NFSERR_FBIG, EFBIG }, { NFSERR_NOSPC, ENOSPC }, { NFSERR_ROFS, EROFS }, - { NFSERR_OPNOTSUPP, EOPNOTSUPP }, + { NFSERR_MLINK, EMLINK }, { NFSERR_NAMETOOLONG, ENAMETOOLONG }, { NFSERR_NOTEMPTY, ENOTEMPTY }, { NFSERR_DQUOT, EDQUOT }, { NFSERR_STALE, ESTALE }, + { NFSERR_REMOTE, EREMOTE }, #ifdef EWFLUSH { NFSERR_WFLUSH, EWFLUSH }, #endif + { NFSERR_BADHANDLE, EBADHANDLE }, + { NFSERR_NOT_SYNC, ENOTSYNC }, + { NFSERR_BAD_COOKIE, EBADCOOKIE }, + { NFSERR_NOTSUPP, ENOTSUPP }, + { NFSERR_TOOSMALL, ETOOSMALL }, + { NFSERR_SERVERFAULT, ESERVERFAULT }, + { NFSERR_BADTYPE, EBADTYPE }, + { NFSERR_JUKEBOX, EJUKEBOX }, { -1, EIO } }; -static int +/* + * Convert an NFS error code to a local one. + * This one is used jointly by NFSv2 and NFSv3. + */ +int nfs_stat_to_errno(int stat) { int i; @@ -692,7 +726,7 @@ nfs_stat_to_errno(int stat) if (nfs_errtbl[i].stat == stat) return nfs_errtbl[i].errno; } - printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat); + printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat); return nfs_errtbl[i].errno; } @@ -704,7 +738,8 @@ nfs_stat_to_errno(int stat) { "nfs_" #proc, \ (kxdrproc_t) nfs_xdr_##argtype, \ (kxdrproc_t) nfs_xdr_##restype, \ - MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2 \ + MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \ + 0 \ } static struct rpc_procinfo nfs_procedures[18] = { @@ -728,22 +763,8 @@ static struct rpc_procinfo nfs_procedures[18] = { PROC(statfs, fhandle, statfsres), }; -static struct rpc_version nfs_version2 = { +struct rpc_version nfs_version2 = { 2, sizeof(nfs_procedures)/sizeof(nfs_procedures[0]), nfs_procedures }; - -static struct rpc_version * nfs_version[] = { - NULL, - NULL, - &nfs_version2 -}; - -struct rpc_program nfs_program = { - "nfs", - NFS_PROGRAM, - sizeof(nfs_version) / sizeof(nfs_version[0]), - nfs_version, - &nfs_rpcstat, -}; diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c new file mode 100644 index 000000000000..67de662a6b10 --- /dev/null +++ b/fs/nfs/nfs3proc.c @@ -0,0 +1,477 @@ +/* + * linux/fs/nfs/nfs3proc.c + * + * Client-side NFSv3 procedures stubs. + * + * Copyright (C) 1997, Olaf Kirch + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NFSDBG_FACILITY NFSDBG_PROC + +/* + * Bare-bones access to getattr: this is for nfs_read_super. + */ +static int +nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + int status; + + dprintk("NFS call getroot\n"); + fattr->valid = 0; + status = rpc_call(server->client, NFS3PROC_GETATTR, fhandle, fattr, 0); + dprintk("NFS reply getroot\n"); + return status; +} + +/* + * One function for each procedure in the NFS protocol. + */ +static int +nfs3_proc_getattr(struct dentry *dentry, struct nfs_fattr *fattr) +{ + int status; + + dprintk("NFS call getattr\n"); + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_GETATTR, + NFS_FH(dentry), fattr, 0); + dprintk("NFS reply getattr\n"); + return status; +} + +static int +nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, + struct iattr *sattr) +{ + struct nfs3_sattrargs arg = { NFS_FH(dentry), sattr, 0, 0 }; + int status; + + dprintk("NFS call setattr\n"); + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_SETATTR, &arg, fattr, 0); + dprintk("NFS reply setattr\n"); + return status; +} + +static int +nfs3_proc_lookup(struct dentry *dir, struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) +{ + struct nfs_fattr dir_attr; + struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len }; + struct nfs3_diropres res = { &dir_attr, fhandle, fattr }; + int status; + + dprintk("NFS call lookup %s\n", name->name); + dir_attr.valid = 0; + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_LOOKUP, &arg, &res, 0); + if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_GETATTR, + fhandle, fattr, 0); + dprintk("NFS reply lookup: %d\n", status); + nfs_refresh_inode(dir->d_inode, &dir_attr); + return status; +} + +static int +nfs3_proc_access(struct dentry *dentry, int mode, int ruid) +{ + struct nfs_fattr fattr; + struct nfs3_accessargs arg = { NFS_FH(dentry), 0 }; + struct nfs3_accessres res = { &fattr, 0 }; + int status, flags; + + dprintk("NFS call access\n"); + fattr.valid = 0; + + if (mode & MAY_READ) + arg.access |= NFS3_ACCESS_READ; + if (S_ISDIR(dentry->d_inode->i_mode)) { + if (mode & MAY_WRITE) + arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE; + if (mode & MAY_EXEC) + arg.access |= NFS3_ACCESS_LOOKUP; + } else { + if (mode & MAY_WRITE) + arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND; + if (mode & MAY_EXEC) + arg.access |= NFS3_ACCESS_EXECUTE; + } + flags = (ruid) ? RPC_CALL_REALUID : 0; + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_ACCESS, &arg, &res, flags); + nfs_refresh_inode(dentry->d_inode, &fattr); + dprintk("NFS reply access\n"); + + if (status == 0 && (arg.access & res.access) != arg.access) + status = -EACCES; + return status; +} + +static int +nfs3_proc_readlink(struct dentry *dentry, void *buffer, unsigned int buflen) +{ + struct nfs_fattr fattr; + struct nfs3_readlinkargs args = { NFS_FH(dentry), buffer, buflen }; + struct nfs3_readlinkres res = { &fattr, buffer, buflen }; + int status; + + dprintk("NFS call readlink\n"); + fattr.valid = 0; + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_READLINK, + &args, &res, 0); + nfs_refresh_inode(dentry->d_inode, &fattr); + dprintk("NFS reply readlink: %d\n", status); + return status; +} + +static int +nfs3_proc_read(struct dentry *dentry, struct nfs_fattr *fattr, int flags, + loff_t offset, unsigned int count, void *buffer, int *eofp) +{ + struct nfs_readargs arg = { NFS_FH(dentry), offset, count, 1, + {{buffer, count}, {0,0}, {0,0}, {0,0}, + {0,0}, {0,0}, {0,0}, {0,0}} }; + struct nfs_readres res = { fattr, count, 0 }; + struct rpc_message msg = { NFS3PROC_READ, &arg, &res, NULL }; + int status; + + dprintk("NFS call read %d @ %Ld\n", count, (long long)offset); + fattr->valid = 0; + status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags); + dprintk("NFS reply read: %d\n", status); + *eofp = res.eof; + return status; +} + +static int +nfs3_proc_write(struct dentry *dentry, struct nfs_fattr *fattr, int flags, + loff_t offset, unsigned int count, + void *buffer, struct nfs_writeverf *verf) +{ + struct nfs_writeargs arg = { NFS_FH(dentry), offset, count, + NFS_FILE_SYNC, 1, + {{buffer, count}, {0,0}, {0,0}, {0,0}, + {0,0}, {0,0}, {0,0}, {0,0}} }; + struct nfs_writeres res = { fattr, verf, 0 }; + struct rpc_message msg = { NFS3PROC_WRITE, &arg, &res, NULL }; + int status, rpcflags = 0; + + dprintk("NFS call write %d @ %Ld\n", count, (long long)offset); + fattr->valid = 0; + if (flags & NFS_RW_SWAP) + rpcflags |= NFS_RPC_SWAPFLAGS; + arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE; + + status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, rpcflags); + + dprintk("NFS reply read: %d\n", status); + return status < 0? status : res.count; +} + +/* + * Create a regular file. + * For now, we don't implement O_EXCL. + */ +static int +nfs3_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr, + int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr) +{ + struct nfs_fattr dir_attr; + struct nfs3_createargs arg = { NFS_FH(dir), name->name, name->len, + sattr, 0, { 0, 0 } }; + struct nfs3_diropres res = { &dir_attr, fhandle, fattr }; + int status; + + dprintk("NFS call create %s\n", name->name); + arg.createmode = NFS3_CREATE_UNCHECKED; + if (flags & O_EXCL) { + arg.createmode = NFS3_CREATE_EXCLUSIVE; + arg.verifier[0] = jiffies; + arg.verifier[1] = current->pid; + } + +again: + dir_attr.valid = 0; + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_CREATE, &arg, &res, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + + /* If the server doesn't support the exclusive creation semantics, + * try again with simple 'guarded' mode. */ + if (status == NFSERR_NOTSUPP) { + switch (arg.createmode) { + case NFS3_CREATE_EXCLUSIVE: + arg.createmode = NFS3_CREATE_GUARDED; + break; + + case NFS3_CREATE_GUARDED: + arg.createmode = NFS3_CREATE_UNCHECKED; + break; + + case NFS3_CREATE_UNCHECKED: + goto exit; + } + goto again; + } + +exit: + dprintk("NFS reply create: %d\n", status); + + /* When we created the file with exclusive semantics, make + * sure we set the attributes afterwards. */ + if (status == 0 && arg.createmode == NFS3_CREATE_EXCLUSIVE) { + struct nfs3_sattrargs arg = { fhandle, sattr, 0, 0 }; + dprintk("NFS call setattr (post-create)\n"); + + /* Note: we could use a guarded setattr here, but I'm + * not sure this buys us anything (and I'd have + * to revamp the NFSv3 XDR code) */ + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_SETATTR, + &arg, fattr, 0); + dprintk("NFS reply setattr (post-create): %d\n", status); + } + + return status; +} + +static int +nfs3_proc_remove(struct dentry *dir, struct qstr *name) +{ + struct nfs_fattr dir_attr; + struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len }; + struct rpc_message msg = { NFS3PROC_REMOVE, &arg, &dir_attr, NULL }; + int status; + + dprintk("NFS call remove %s\n", name->name); + dir_attr.valid = 0; + status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + dprintk("NFS reply remove: %d\n", status); + return status; +} + +static int +nfs3_proc_rename(struct dentry *old_dir, struct qstr *old_name, + struct dentry *new_dir, struct qstr *new_name) +{ + struct nfs_fattr old_dir_attr, new_dir_attr; + struct nfs3_renameargs arg = { NFS_FH(old_dir), + old_name->name, old_name->len, + NFS_FH(new_dir), + new_name->name, new_name->len }; + struct nfs3_renameres res = { &old_dir_attr, &new_dir_attr }; + int status; + + dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); + old_dir_attr.valid = 0; + new_dir_attr.valid = 0; + status = rpc_call(NFS_CLIENT(old_dir->d_inode), NFS3PROC_RENAME, &arg, &res, 0); + nfs_refresh_inode(old_dir->d_inode, &old_dir_attr); + nfs_refresh_inode(new_dir->d_inode, &new_dir_attr); + dprintk("NFS reply rename: %d\n", status); + return status; +} + +static int +nfs3_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name) +{ + struct nfs_fattr dir_attr, fattr; + struct nfs3_linkargs arg = { NFS_FH(dentry), NFS_FH(dir), + name->name, name->len }; + struct nfs3_linkres res = { &dir_attr, &fattr }; + int status; + + dprintk("NFS call link %s\n", name->name); + dir_attr.valid = 0; + fattr.valid = 0; + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_LINK, &arg, &res, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + nfs_refresh_inode(dentry->d_inode, &fattr); + dprintk("NFS reply link: %d\n", status); + return status; +} + +static int +nfs3_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path, + struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + struct nfs_fattr dir_attr; + struct nfs3_symlinkargs arg = { NFS_FH(dir), name->name, name->len, + path->name, path->len, sattr }; + struct nfs3_diropres res = { &dir_attr, fhandle, fattr }; + int status; + + dprintk("NFS call symlink %s -> %s\n", name->name, path->name); + dir_attr.valid = 0; + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_SYMLINK, &arg, &res, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + dprintk("NFS reply symlink: %d\n", status); + return status; +} + +static int +nfs3_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) +{ + struct nfs_fattr dir_attr; + struct nfs3_createargs arg = { NFS_FH(dir), name->name, name->len, + sattr, 0, { 0, 0 } }; + struct nfs3_diropres res = { &dir_attr, fhandle, fattr }; + int status; + + dprintk("NFS call mkdir %s\n", name->name); + dir_attr.valid = 0; + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_MKDIR, &arg, &res, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + dprintk("NFS reply mkdir: %d\n", status); + return status; +} + +static int +nfs3_proc_rmdir(struct dentry *dir, struct qstr *name) +{ + struct nfs_fattr dir_attr; + struct nfs3_diropargs arg = { NFS_FH(dir), name->name, name->len }; + int status; + + dprintk("NFS call rmdir %s\n", name->name); + dir_attr.valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_RMDIR, &arg, &dir_attr, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + dprintk("NFS reply rmdir: %d\n", status); + return status; +} + +/* + * The READDIR implementation is somewhat hackish - we pass the user buffer + * to the encode function, which installs it in the receive iovec. + * The decode function itself doesn't perform any decoding, it just makes + * sure the reply is syntactically correct. + * + * Also note that this implementation handles both plain readdir and + * readdirplus. + */ +static int +nfs3_proc_readdir(struct dentry *dir, u64 cookie, void *entry, + unsigned int size, int plus) +{ + struct nfs_fattr dir_attr; + struct nfs3_readdirargs arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 }; + struct nfs3_readdirres res = { &dir_attr, 0, 0, 0, 0 }; + struct rpc_message msg = { NFS3PROC_READDIR, &arg, &res, NULL }; + u32 *verf = NFS_COOKIEVERF(dir->d_inode); + int status; + + arg.buffer = entry; + arg.bufsiz = size; + arg.verf[0] = verf[0]; + arg.verf[1] = verf[1]; + arg.plus = plus; + res.buffer = entry; + res.bufsiz = size; + res.verf = verf; + res.plus = plus; + + if (plus) + msg.rpc_proc = NFS3PROC_READDIRPLUS; + + dprintk("NFS call readdir%s %d\n", + plus? "plus" : "", (unsigned int) cookie); + + dir_attr.valid = 0; + status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + dprintk("NFS reply readdir: %d\n", status); + return status; +} + +static int +nfs3_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr, + dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr) +{ + struct nfs_fattr dir_attr; + struct nfs3_mknodargs arg = { NFS_FH(dir), name->name, name->len, 0, + sattr, rdev }; + struct nfs3_diropres res = { &dir_attr, fh, fattr }; + int status; + + switch (sattr->ia_mode & S_IFMT) { + case S_IFBLK: arg.type = NF3BLK; break; + case S_IFCHR: arg.type = NF3CHR; break; + case S_IFIFO: arg.type = NF3FIFO; break; + case S_IFSOCK: arg.type = NF3SOCK; break; + default: return -EINVAL; + } + + dprintk("NFS call mknod %s %x\n", name->name, rdev); + dir_attr.valid = 0; + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_MKNOD, &arg, &res, 0); + nfs_refresh_inode(dir->d_inode, &dir_attr); + dprintk("NFS reply mknod: %d\n", status); + return status; +} + +/* + * This is a combo call of fsstat and fsinfo + */ +static int +nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fsinfo *info) +{ + int status; + + dprintk("NFS call fsstat\n"); + memset((char *)info, 0, sizeof(*info)); + status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, info, 0); + if (status < 0) + goto error; + status = rpc_call(server->client, NFS3PROC_FSINFO, fhandle, info, 0); + +error: + dprintk("NFS reply statfs: %d\n", status); + return status; +} + +extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); + +struct nfs_rpc_ops nfs_v3_clientops = { + 3, /* protocol version */ + nfs3_proc_get_root, + nfs3_proc_getattr, + nfs3_proc_setattr, + nfs3_proc_lookup, + nfs3_proc_access, + nfs3_proc_readlink, + nfs3_proc_read, + nfs3_proc_write, + NULL, /* commit */ + nfs3_proc_create, + nfs3_proc_remove, + nfs3_proc_rename, + nfs3_proc_link, + nfs3_proc_symlink, + nfs3_proc_mkdir, + nfs3_proc_rmdir, + nfs3_proc_readdir, + nfs3_proc_mknod, + nfs3_proc_statfs, + nfs3_decode_dirent, +}; diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index beed6ec1ed4a..ef8580c02b7d 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -1,94 +1,158 @@ /* - * linux/fs/nfs/nfs2xdr.c + * linux/fs/nfs/nfs3xdr.c * * XDR functions to encode/decode NFSv3 RPC arguments and results. - * Note: this is incomplete! * - * Copyright (C) 1996 Olaf Kirch + * Copyright (C) 1996, 1997 Olaf Kirch */ -#define NFS_NEED_XDR_TYPES - #include #include #include #include -#include #include #include #include #include #include #include +#include #include +#include +#include +#include -#ifdef RPC_DEBUG -# define RPC_FACILITY RPCDBG_NFS -#endif +/* Uncomment this to support servers requiring longword lengths */ +#define NFS_PAD_WRITES 1 -#define QUADLEN(len) (((len) + 3) >> 2) -static int nfs_stat_to_errno(int stat); +#define NFSDBG_FACILITY NFSDBG_XDR /* Mapping from NFS error code to "errno" error code. */ #define errno_NFSERR_IO EIO +extern int nfs_stat_to_errno(int); + /* * Declare the space requirements for NFS arguments and replies as * number of 32bit-words */ -#define NFS_fhandle_sz (1+16) -#define NFS_sattr_sz 8 -#define NFS_filename_sz 1+(NFS_MAXNAMLEN>>2) -#define NFS_path_sz 1+(NFS_MAXPATHLEN>>2) -#define NFS_fattr_sz 17 -#define NFS_info_sz 5 -#define NFS_entry_sz NFS_filename_sz+3 - -#define NFS_enc_void_sz 0 -#define NFS_diropargs_sz NFS_fhandle_sz+NFS_filename_sz -#define NFS_sattrargs_sz NFS_fhandle_sz+NFS_sattr_sz -#define NFS_readargs_sz NFS_fhandle_sz+3 -#define NFS_writeargs_sz NFS_fhandle_sz+4 -#define NFS_createargs_sz NFS_diropargs_sz+NFS_sattr_sz -#define NFS_renameargs_sz NFS_diropargs_sz+NFS_diropargs_sz -#define NFS_linkargs_sz NFS_fhandle_sz+NFS_diropargs_sz -#define NFS_symlinkargs_sz NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz -#define NFS_readdirargs_sz NFS_fhandle_sz+2 - -#define NFS_dec_void_sz 0 -#define NFS_attrstat_sz 1+NFS_fattr_sz -#define NFS_diropres_sz 1+NFS_fhandle_sz+NFS_fattr_sz -#define NFS_readlinkres_sz 1+NFS_path_sz -#define NFS_readres_sz 1+NFS_fattr_sz+1 -#define NFS_stat_sz 1 -#define NFS_readdirres_sz 1 -#define NFS_statfsres_sz 1+NFS_info_sz +#define NFS3_fhandle_sz 1+16 +#define NFS3_fh_sz NFS3_fhandle_sz /* shorthand */ +#define NFS3_sattr_sz 15 +#define NFS3_filename_sz 1+(NFS3_MAXNAMLEN>>2) +#define NFS3_path_sz 1+(NFS3_MAXPATHLEN>>2) +#define NFS3_fattr_sz 21 +#define NFS3_wcc_attr_sz 6 +#define NFS3_pre_op_attr_sz 1+NFS3_wcc_attr_sz +#define NFS3_post_op_attr_sz 1+NFS3_fattr_sz +#define NFS3_wcc_data_sz NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz +#define NFS3_fsstat_sz +#define NFS3_fsinfo_sz +#define NFS3_pathconf_sz +#define NFS3_entry_sz NFS3_filename_sz+3 + +#define NFS3_enc_void_sz 0 +#define NFS3_sattrargs_sz NFS3_fh_sz+NFS3_sattr_sz+3 +#define NFS3_diropargs_sz NFS3_fh_sz+NFS3_filename_sz +#define NFS3_accessargs_sz NFS3_fh_sz+1 +#define NFS3_readlinkargs_sz NFS3_fh_sz +#define NFS3_readargs_sz NFS3_fh_sz+3 +#define NFS3_writeargs_sz NFS3_fh_sz+5 +#define NFS3_createargs_sz NFS3_diropargs_sz+NFS3_sattr_sz +#define NFS3_mkdirargs_sz NFS3_diropargs_sz+NFS3_sattr_sz +#define NFS3_symlinkargs_sz NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz +#define NFS3_mknodargs_sz NFS3_diropargs_sz+2+NFS3_sattr_sz +#define NFS3_renameargs_sz NFS3_diropargs_sz+NFS3_diropargs_sz +#define NFS3_linkargs_sz NFS3_fh_sz+NFS3_diropargs_sz +#define NFS3_readdirargs_sz NFS3_fh_sz+2 +#define NFS3_commitargs_sz NFS3_fh_sz+3 + +#define NFS3_dec_void_sz 0 +#define NFS3_attrstat_sz 1+NFS3_fattr_sz +#define NFS3_wccstat_sz 1+NFS3_wcc_data_sz +#define NFS3_lookupres_sz 1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz) +#define NFS3_accessres_sz 1+NFS3_post_op_attr_sz+1 +#define NFS3_readlinkres_sz 1+NFS3_post_op_attr_sz +#define NFS3_readres_sz 1+NFS3_post_op_attr_sz+3 +#define NFS3_writeres_sz 1+NFS3_wcc_data_sz+4 +#define NFS3_createres_sz 1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz +#define NFS3_renameres_sz 1+(2 * NFS3_wcc_data_sz) +#define NFS3_linkres_sz 1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz +#define NFS3_readdirres_sz 1+NFS3_post_op_attr_sz+2 +#define NFS3_fsstatres_sz 1+NFS3_post_op_attr_sz+13 +#define NFS3_fsinfores_sz 1+NFS3_post_op_attr_sz+12 +#define NFS3_pathconfres_sz 1+NFS3_post_op_attr_sz+6 +#define NFS3_commitres_sz 1+NFS3_wcc_data_sz+2 + +/* + * Map file type to S_IFMT bits + */ +static struct { + unsigned int mode; + unsigned int nfs2type; +} nfs_type2fmt[] = { + { 0, NFNON }, + { S_IFREG, NFREG }, + { S_IFDIR, NFDIR }, + { S_IFBLK, NFBLK }, + { S_IFCHR, NFCHR }, + { S_IFLNK, NFLNK }, + { S_IFSOCK, NFSOCK }, + { S_IFIFO, NFFIFO }, + { 0, NFBAD } +}; /* * Common NFS XDR functions as inlines */ static inline u32 * -xdr_encode_fhandle(u32 *p, struct nfs3_fh *fh) +xdr_encode_fhandle(u32 *p, struct nfs_fh *fh) { *p++ = htonl(fh->size); memcpy(p, fh->data, fh->size); - return p + QUADLEN(fh->size); + return p + XDR_QUADLEN(fh->size); } static inline u32 * -xdr_decode_fhandle(u32 *p, struct nfs3_fh *fh) +xdr_decode_fhandle(u32 *p, struct nfs_fh *fh) { + /* + * Zero all nonused bytes + */ + memset((u8 *)fh, 0, sizeof(*fh)); if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) { memcpy(fh->data, p, fh->size); - return p + QUADLEN(fh->size); + return p + XDR_QUADLEN(fh->size); } return NULL; } -static inline enum nfs_ftype -xdr_decode_ftype(u32 type) +/* + * Encode/decode time. + * Since the VFS doesn't care for fractional times, we ignore the + * nanosecond field. + */ +static inline u32 * +xdr_encode_time(u32 *p, time_t time) +{ + *p++ = htonl(time); + *p++ = 0; + return p; +} + +static inline u32 * +xdr_decode_time3(u32 *p, u64 *timep) { - return (type == NF3FIFO)? NFFIFO : (enum nfs_ftype) type; + *timep = ((u64)ntohl(*p++) << 32) + (u64)ntohl(*p++); + return p; +} + +static inline u32 * +xdr_encode_time3(u32 *p, u64 time) +{ + *p++ = htonl(time >> 32); + *p++ = htonl(time & 0xFFFFFFFF); + return p; } static inline u32 * @@ -99,47 +163,119 @@ xdr_decode_string2(u32 *p, char **string, unsigned int *len, if (*len > maxlen) return NULL; *string = (char *) p; - return p + QUADLEN(*len); + return p + XDR_QUADLEN(*len); } static inline u32 * -xdr_decode_fattr(u32 *p, struct nfs3_fattr *fattr) +xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) { - fattr->type = xdr_decode_ftype(ntohl(*p++)); - fattr->mode = ntohl(*p++); + unsigned int type; + int fmode; + + type = ntohl(*p++); + if (type >= NF3BAD) + type = NF3BAD; + fmode = nfs_type2fmt[type].mode; + fattr->type = nfs_type2fmt[type].nfs2type; + fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode; fattr->nlink = ntohl(*p++); fattr->uid = ntohl(*p++); fattr->gid = ntohl(*p++); - fattr->size = ((u64) ntohl(*p++) << 32) | ntohl(*p++); - fattr->used = ((u64) ntohl(*p++) << 32) | ntohl(*p++); - fattr->rdev_maj = ntohl(*p++); - fattr->rdev_min = ntohl(*p++); - fattr->fsid = ntohl(*p++); - fattr->fileid = ntohl(*p++); - fattr->atime.seconds = ntohl(*p++); - fattr->atime.useconds = ntohl(*p++); - fattr->mtime.seconds = ntohl(*p++); - fattr->mtime.useconds = ntohl(*p++); - fattr->ctime.seconds = ntohl(*p++); - fattr->ctime.useconds = ntohl(*p++); + p = xdr_decode_hyper(p, &fattr->size); + p = xdr_decode_hyper(p, &fattr->du.nfs3.used); + /* Turn remote device info into Linux-specific dev_t */ + fattr->rdev = (ntohl(*p++) << MINORBITS) | (ntohl(*p++) & MINORMASK); + p = xdr_decode_hyper(p, &fattr->fsid); + p = xdr_decode_hyper(p, &fattr->fileid); + p = xdr_decode_time3(p, &fattr->atime); + p = xdr_decode_time3(p, &fattr->mtime); + p = xdr_decode_time3(p, &fattr->ctime); + + /* Update the mode bits */ + fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); + return p; +} + +static inline u32 * +xdr_encode_sattr(u32 *p, struct iattr *attr) +{ + if (attr->ia_valid & ATTR_MODE) { + *p++ = xdr_one; + *p++ = htonl(attr->ia_mode); + } else { + *p++ = xdr_zero; + } + if (attr->ia_valid & ATTR_UID) { + *p++ = xdr_one; + *p++ = htonl(attr->ia_uid); + } else { + *p++ = xdr_zero; + } + if (attr->ia_valid & ATTR_GID) { + *p++ = xdr_one; + *p++ = htonl(attr->ia_gid); + } else { + *p++ = xdr_zero; + } + if (attr->ia_valid & ATTR_SIZE) { + *p++ = xdr_one; + p = xdr_encode_hyper(p, (__u64) attr->ia_size); + } else { + *p++ = xdr_zero; + } + if (attr->ia_valid & ATTR_ATIME_SET) { + *p++ = xdr_two; + p = xdr_encode_time(p, attr->ia_atime); + } else if (attr->ia_valid & ATTR_ATIME) { + *p++ = xdr_one; + } else { + *p++ = xdr_zero; + } + if (attr->ia_valid & ATTR_MTIME_SET) { + *p++ = xdr_two; + p = xdr_encode_time(p, attr->ia_mtime); + } else if (attr->ia_valid & ATTR_MTIME) { + *p++ = xdr_one; + } else { + *p++ = xdr_zero; + } + return p; +} + +static inline u32 * +xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr) +{ + p = xdr_decode_hyper(p, &fattr->pre_size); + p = xdr_decode_time3(p, &fattr->pre_mtime); + p = xdr_decode_time3(p, &fattr->pre_ctime); + fattr->valid |= NFS_ATTR_WCC; return p; } static inline u32 * -xdr_encode_sattr(u32 *p, struct nfs_sattr *sattr) -{ - *p++ = htonl(sattr->mode); - *p++ = htonl(sattr->uid); - *p++ = htonl(sattr->gid); - *p++ = htonl(sattr->size >> 32); - *p++ = htonl(sattr->size & 0xFFFFFFFF); - *p++ = htonl(sattr->atime.seconds); - *p++ = htonl(sattr->atime.useconds); - *p++ = htonl(sattr->mtime.seconds); - *p++ = htonl(sattr->mtime.useconds); +xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr) +{ + if (*p++) + p = xdr_decode_fattr(p, fattr); return p; } +static inline u32 * +xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr) +{ + if (*p++) + return xdr_decode_wcc_attr(p, fattr); + return p; +} + + +static inline u32 * +xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr) +{ + p = xdr_decode_pre_op_attr(p, fattr); + return xdr_decode_post_op_attr(p, fattr); +} + /* * NFS encode functions */ @@ -147,7 +283,7 @@ xdr_encode_sattr(u32 *p, struct nfs_sattr *sattr) * Encode void argument */ static int -nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy) +nfs3_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy) { req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; @@ -155,10 +291,9 @@ nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy) /* * Encode file handle argument - * GETATTR, READLINK, STATFS */ static int -nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs3_fh *fh) +nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh) { p = xdr_encode_fhandle(p, fh); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); @@ -169,23 +304,37 @@ nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs3_fh *fh) * Encode SETATTR arguments */ static int -nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args) +nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args) { p = xdr_encode_fhandle(p, args->fh); p = xdr_encode_sattr(p, args->sattr); + *p++ = htonl(args->guard); + if (args->guard) + p = xdr_encode_time3(p, args->guardtime); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } /* * Encode directory ops argument - * LOOKUP, REMOVE, RMDIR */ static int -nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args) +nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args) +{ + p = xdr_encode_fhandle(p, args->fh); + p = xdr_encode_array(p, args->name, args->len); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +/* + * Encode access() argument + */ +static int +nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args) { p = xdr_encode_fhandle(p, args->fh); - p = xdr_encode_string(p, args->name); + *p++ = htonl(args->access); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } @@ -193,149 +342,181 @@ nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args) /* * Arguments to a READ call. Since we read data directly into the page * cache, we also set up the reply iovec here so that iov[1] points - * exactly to the page wewant to fetch. + * exactly to the page we want to fetch. */ static int -nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) +nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; - int replen, buflen; + int buflen, replen; + unsigned int nr; p = xdr_encode_fhandle(p, args->fh); - *p++ = htonl(args->offset); - *p++ = htonl(args->count); + p = xdr_encode_hyper(p, args->offset); *p++ = htonl(args->count); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); -#if 1 + /* Get the number of buffers in the receive iovec */ + nr = args->nriov; + + if (nr+2 > MAX_IOVEC) { + printk(KERN_ERR "NFS: Bad number of iov's in xdr_readargs\n"); + return -EINVAL; + } + /* set up reply iovec */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; + replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; buflen = req->rq_rvec[0].iov_len; req->rq_rvec[0].iov_len = replen; - req->rq_rvec[1].iov_base = args->buffer; - req->rq_rvec[1].iov_len = args->count; - req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; - req->rq_rvec[2].iov_len = buflen - replen; + + /* Copy the iovec */ + memcpy(req->rq_rvec + 1, args->iov, nr * sizeof(struct iovec)); + + req->rq_rvec[nr+1].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; + req->rq_rvec[nr+1].iov_len = buflen - replen; req->rq_rlen = args->count + buflen; - req->rq_rnr = 3; -#else - replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2; - req->rq_rvec[0].iov_len = replen; -#endif + req->rq_rnr += nr+1; return 0; } /* - * Decode READ reply + * Write arguments. Splice the buffer to be written into the iovec. */ static int -nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) +nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) { - struct iovec *iov = req->rq_rvec; - int status, count, recvd, hdrlen; + unsigned int nr; + u32 count = args->count; - dprintk("RPC: readres OK status %lx\n", ntohl(*p)); - if ((status = ntohl(*p++))) - return -nfs_stat_to_errno(status); - p = xdr_decode_fattr(p, res->fattr); + p = xdr_encode_fhandle(p, args->fh); + p = xdr_encode_hyper(p, args->offset); + *p++ = htonl(count); + *p++ = htonl(args->stable); + *p++ = htonl(count); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - count = ntohl(*p++); - hdrlen = (u8 *) p - (u8 *) iov->iov_base; - recvd = req->rq_rlen - hdrlen; - if (p != iov[2].iov_base) { - /* Unexpected reply header size. Punt. - * XXX: Move iovec contents to align data on page - * boundary and adjust RPC header size guess */ - printk("NFS: Odd RPC header size in read reply: %d\n", hdrlen); - return -errno_NFSERR_IO; - } - if (count > recvd) { - printk("NFS: server cheating in read reply: " - "count %d > recvd %d\n", count, recvd); - count = recvd; + /* Get the number of buffers in the send iovec */ + nr = args->nriov; + + if (nr+2 > MAX_IOVEC) { + printk(KERN_ERR "NFS: Bad number of iov's in xdr_writeargs\n"); + return -EINVAL; } - dprintk("RPC: readres OK count %d\n", count); - if (count < res->count) - memset((u8 *)(iov[1].iov_base+count), 0, res->count-count); + /* Copy the iovec */ + memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec)); - return count; -} +#ifdef NFS_PAD_WRITES + /* + * Some old servers require that the message length + * be a multiple of 4, so we pad it here if needed. + */ + if (count & 3) { + struct iovec *iov = req->rq_svec + nr + 1; + int pad = 4 - (count & 3); + + iov->iov_base = (void *) "\0\0\0"; + iov->iov_len = pad; + count += pad; + nr++; + } +#endif + req->rq_slen += count; + req->rq_snr += nr; + return 0; +} /* - * Write arguments. Splice the buffer to be written into the iovec. + * Encode CREATE arguments */ static int -nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) +nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args) { p = xdr_encode_fhandle(p, args->fh); - *p++ = htonl(args->offset); - *p++ = htonl(args->offset); - *p++ = htonl(args->count); - *p++ = htonl(args->count); - req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + p = xdr_encode_array(p, args->name, args->len); - req->rq_svec[1].iov_base = (void *) args->buffer; - req->rq_svec[1].iov_len = args->count; - req->rq_slen += args->count; - req->rq_snr = 2; + *p++ = htonl(args->createmode); + if (args->createmode == NFS3_CREATE_EXCLUSIVE) { + *p++ = args->verifier[0]; + *p++ = args->verifier[1]; + } else + p = xdr_encode_sattr(p, args->sattr); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } /* - * Encode create arguments - * CREATE, MKDIR + * Encode MKDIR arguments */ static int -nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args) +nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args) { p = xdr_encode_fhandle(p, args->fh); - p = xdr_encode_string(p, args->name); + p = xdr_encode_array(p, args->name, args->len); p = xdr_encode_sattr(p, args->sattr); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } /* - * Encode RENAME arguments + * Encode SYMLINK arguments */ static int -nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args) +nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); - p = xdr_encode_string(p, args->fromname); - p = xdr_encode_fhandle(p, args->tofh); - p = xdr_encode_string(p, args->toname); + p = xdr_encode_array(p, args->fromname, args->fromlen); + p = xdr_encode_sattr(p, args->sattr); + p = xdr_encode_array(p, args->topath, args->tolen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } /* - * Encode LINK arguments + * Encode MKNOD arguments + */ +static int +nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args) +{ + p = xdr_encode_fhandle(p, args->fh); + p = xdr_encode_array(p, args->name, args->len); + *p++ = htonl(args->type); + p = xdr_encode_sattr(p, args->sattr); + if (args->type == NF3CHR || args->type == NF3BLK) { + *p++ = htonl(args->rdev >> MINORBITS); + *p++ = htonl(args->rdev & MINORMASK); + } + + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + +/* + * Encode RENAME arguments */ static int -nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args) +nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args) { p = xdr_encode_fhandle(p, args->fromfh); + p = xdr_encode_array(p, args->fromname, args->fromlen); p = xdr_encode_fhandle(p, args->tofh); - p = xdr_encode_string(p, args->toname); + p = xdr_encode_array(p, args->toname, args->tolen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } /* - * Encode SYMLINK arguments + * Encode LINK arguments */ static int -nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) +nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args) { p = xdr_encode_fhandle(p, args->fromfh); - p = xdr_encode_string(p, args->fromname); - p = xdr_encode_string(p, args->topath); - p = xdr_encode_sattr(p, args->sattr); + p = xdr_encode_fhandle(p, args->tofh); + p = xdr_encode_array(p, args->toname, args->tolen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } @@ -344,131 +525,164 @@ nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) * Encode arguments to readdir call */ static int -nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args) +nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args) { struct rpc_auth *auth = req->rq_task->tk_auth; - int replen; + int buflen, replen; p = xdr_encode_fhandle(p, args->fh); - *p++ = htonl(args->cookie); + p = xdr_encode_hyper(p, args->cookie); + *p++ = args->verf[0]; + *p++ = args->verf[1]; + if (args->plus) { + /* readdirplus: need dircount + buffer size. + * We just make sure we make dircount big enough */ + *p++ = htonl(args->bufsiz >> 3); + } *p++ = htonl(args->bufsiz); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); /* set up reply iovec */ - replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2; - /* - dprintk("RPC: readdirargs: slack is 4 * (%d + %d + %d) = %d\n", - RPC_REPHDRSIZE, auth->au_rslack, NFS_readdirres_sz, replen); - */ + replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2; + buflen = req->rq_rvec[0].iov_len; req->rq_rvec[0].iov_len = replen; req->rq_rvec[1].iov_base = args->buffer; req->rq_rvec[1].iov_len = args->bufsiz; - req->rq_rlen = replen + args->bufsiz; - req->rq_rnr = 2; - - /* - dprintk("RPC: readdirargs set up reply vec:\n"); - dprintk(" rvec[0] = %p/%d\n", - req->rq_rvec[0].iov_base, - req->rq_rvec[0].iov_len); - dprintk(" rvec[1] = %p/%d\n", - req->rq_rvec[1].iov_base, - req->rq_rvec[1].iov_len); - */ + req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; + req->rq_rvec[2].iov_len = buflen - replen; + req->rq_rlen = buflen + args->bufsiz; + req->rq_rnr += 2; return 0; } /* - * Decode the result of a readdir call. We decode the result in place - * to avoid a malloc of NFS_MAXNAMLEN+1 for each file name. - * After decoding, the layout in memory looks like this: - * entry1 entry2 ... entryN stringN ... string2 string1 - * Each entry consists of three __u32 values, the same space as NFS uses. - * Note that the strings are not null-terminated so that the entire number - * of entries returned by the server should fit into the buffer. + * Decode the result of a readdir call. + * We just check for syntactical correctness. */ static int -nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res) +nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res) { - struct iovec *iov = req->rq_rvec; - int status, nr, len; - char *string, *start; - u32 *end; - __u32 fileid, cookie, *entry; - - if ((status = ntohl(*p++))) + struct iovec *iov = req->rq_rvec; + int hdrlen; + int status, nr; + unsigned int len; + u32 *entry, *end; + + status = ntohl(*p++); + /* Decode post_op_attrs */ + p = xdr_decode_post_op_attr(p, res->dir_attr); + if (status) return -nfs_stat_to_errno(status); - if ((void *) p != ((u8 *) iov->iov_base+iov->iov_len)) { - /* Unexpected reply header size. Punt. */ - printk("NFS: Odd RPC header size in readdirres reply\n"); - return -errno_NFSERR_IO; + /* Decode verifier cookie */ + if (res->verf) { + res->verf[0] = *p++; + res->verf[1] = *p++; + } else { + p += 2; } - p = (u32 *) iov[1].iov_base; - end = (u32 *) ((u8 *) p + iov[1].iov_len); - - if (p != res->buffer) { - printk("NFS: p != res->buffer in %s:%d!!!\n", - __FILE__, __LINE__); - return -errno_NFSERR_IO; + hdrlen = (u8 *) p - (u8 *) iov->iov_base; + if (iov->iov_len > hdrlen) { + dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); + xdr_shift_iovec(iov, req->rq_rnr, iov->iov_len - hdrlen); } - entry = (__u32 *) res->buffer; - start = (char *) res->buffer; - string = start + res->bufsiz; + p = (u32 *) iov[1].iov_base; + end = (u32 *) ((u8 *) p + iov[1].iov_len); for (nr = 0; *p++; nr++) { - fileid = ntohl(*p++); - - len = ntohl(*p++); - if ((p + QUADLEN(len) + 3) > end) { - printk(KERN_NOTICE - "NFS: short packet in readdir reply!\n"); - break; - } - if (len > NFS_MAXNAMLEN) { - printk("NFS: giant filename in readdir (len %x)!\n", + entry = p - 1; + p += 2; /* inode # */ + len = ntohl(*p++); /* string length */ + p += XDR_QUADLEN(len) + 2; /* name + cookie */ + if (len > NFS3_MAXNAMLEN) { + printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n", len); return -errno_NFSERR_IO; } - string -= len; - if ((void *) (entry+3) > (void *) string) { - /* - * This error is impossible as long as the temp - * buffer is no larger than the user buffer. The - * current packing algorithm uses the same amount - * of space in the user buffer as in the XDR data, - * so it's guaranteed to fit. - */ - printk("NFS: incorrect buffer size in %s!\n", - __FUNCTION__); - break; + + if (res->plus) { + /* post_op_attr */ + if (*p++) + p += 21; + /* post_op_fh3 */ + if (*p++) { + len = ntohl(*p++); + if (len > NFS3_FHSIZE) { + printk(KERN_WARNING "NFS: giant filehandle in " + "readdir (len %x)!\n", len); + return -errno_NFSERR_IO; + } + p += XDR_QUADLEN(len); + } } - memmove(string, p, len); - p += QUADLEN(len); - cookie = ntohl(*p++); - /* - * To make everything fit, we encode the length, offset, - * and eof flag into 32 bits. This works for filenames - * up to 32K and PAGE_SIZE up to 64K. - */ - status = !p[0] && p[1] ? (1 << 15) : 0; /* eof flag */ - *entry++ = fileid; - *entry++ = cookie; - *entry++ = ((string - start) << 16) | status | (len & 0x7FFF); - /* - dprintk("NFS: decoded dirent %.*s cookie %d eof %d\n", - len, string, cookie, status); - */ + if (p + 2 > end) { + printk(KERN_NOTICE + "NFS: short packet in readdir reply!\n"); + /* truncate listing */ + entry[0] = entry[1] = 0; + break; + } } -#ifdef NFS_PARANOIA -printk("nfs_xdr_readdirres: %d entries, ent sp=%d, str sp=%d\n", -nr, ((char *) entry - start), (start + res->bufsiz - string)); -#endif + return nr; } +u32 * +nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) +{ + struct nfs_entry old = *entry; + + if (!*p++) { + if (!*p) + return ERR_PTR(-EAGAIN); + entry->eof = 1; + return ERR_PTR(-EBADCOOKIE); + } + + p = xdr_decode_hyper(p, &entry->ino); + entry->len = ntohl(*p++); + entry->name = (const char *) p; + p += XDR_QUADLEN(entry->len); + entry->prev_cookie = entry->cookie; + p = xdr_decode_hyper(p, &entry->cookie); + + if (plus) { + p = xdr_decode_post_op_attr(p, &entry->fattr); + /* In fact, a post_op_fh3: */ + if (*p++) { + p = xdr_decode_fhandle(p, &entry->fh); + /* Ugh -- server reply was truncated */ + if (p == NULL) { + dprintk("NFS: FH truncated\n"); + *entry = old; + return ERR_PTR(-EAGAIN); + } + } else { + /* If we don't get a file handle, the attrs + * aren't worth a lot. */ + entry->fattr.valid = 0; + } + } + + entry->eof = !p[0] && p[1]; + return p; +} + +/* + * Encode COMMIT arguments + */ +static int +nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args) +{ + p = xdr_encode_fhandle(p, args->fh); + p = xdr_encode_hyper(p, args->offset); + *p++ = htonl(args->count); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + return 0; +} + /* * NFS XDR decode functions */ @@ -476,59 +690,92 @@ nr, ((char *) entry - start), (start + res->bufsiz - string)); * Decode void reply */ static int -nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy) +nfs3_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy) { return 0; } /* - * Decode simple status reply + * Decode attrstat reply. */ static int -nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy) +nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) { int status; - if ((status = ntohl(*p++)) != 0) - status = -nfs_stat_to_errno(status); - return status; + if ((status = ntohl(*p++))) + return -nfs_stat_to_errno(status); + xdr_decode_fattr(p, fattr); + return 0; } /* - * Decode attrstat reply - * GETATTR, SETATTR, WRITE + * Decode status+wcc_data reply + * SATTR, REMOVE, RMDIR */ static int -nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) +nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr) { int status; - dprintk("RPC: attrstat status %lx\n", ntohl(*p)); if ((status = ntohl(*p++))) - return -nfs_stat_to_errno(status); - xdr_decode_fattr(p, fattr); - dprintk("RPC: attrstat OK type %d mode %o dev %x ino %x\n", - fattr->type, fattr->mode, fattr->fsid, fattr->fileid); - return 0; + status = -nfs_stat_to_errno(status); + xdr_decode_wcc_data(p, fattr); + return status; } /* - * Decode diropres reply - * LOOKUP, CREATE, MKDIR + * Decode LOOKUP reply */ static int -nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res) +nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res) { int status; - dprintk("RPC: diropres status %lx\n", ntohl(*p)); - if ((status = ntohl(*p++))) + if ((status = ntohl(*p++))) { + status = -nfs_stat_to_errno(status); + } else { + if (!(p = xdr_decode_fhandle(p, res->fh))) + return -errno_NFSERR_IO; + p = xdr_decode_post_op_attr(p, res->fattr); + } + xdr_decode_post_op_attr(p, res->dir_attr); + return status; +} + +/* + * Decode ACCESS reply + */ +static int +nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res) +{ + int status = ntohl(*p++); + + p = xdr_decode_post_op_attr(p, res->fattr); + if (status) return -nfs_stat_to_errno(status); - p = xdr_decode_fhandle(p, res->fh); - xdr_decode_fattr(p, res->fattr); - dprintk("RPC: diropres OK type %x mode %o dev %x ino %x\n", - res->fattr->type, res->fattr->mode, - res->fattr->fsid, res->fattr->fileid); + res->access = ntohl(*p++); + return 0; +} + +static int +nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args) +{ + struct rpc_task *task = req->rq_task; + struct rpc_auth *auth = task->tk_auth; + int buflen, replen; + + p = xdr_encode_fhandle(p, args->fh); + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); + replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2; + buflen = req->rq_rvec[0].iov_len; + req->rq_rvec[0].iov_len = replen; + req->rq_rvec[1].iov_base = args->buffer; + req->rq_rvec[1].iov_len = args->bufsiz; + req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen; + req->rq_rvec[2].iov_len = buflen - replen; + req->rq_rlen = buflen + args->bufsiz; + req->rq_rnr += 2; return 0; } @@ -536,155 +783,299 @@ nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res) * Decode READLINK reply */ static int -nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_readlinkres *res) +nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkres *res) { + struct iovec *iov = req->rq_rvec; + int hdrlen; + u32 *strlen; + char *string; int status; + unsigned int len; - if ((status = ntohl(*p++))) + status = ntohl(*p++); + p = xdr_decode_post_op_attr(p, res->fattr); + + if (status != 0) return -nfs_stat_to_errno(status); - xdr_decode_string2(p, res->string, res->lenp, res->maxlen); - /* Caller takes over the buffer here to avoid extra copy */ - res->buffer = req->rq_task->tk_buffer; - req->rq_task->tk_buffer = NULL; + hdrlen = (u8 *) p - (u8 *) iov->iov_base; + if (iov->iov_len > hdrlen) { + dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); + xdr_shift_iovec(iov, req->rq_rnr, iov->iov_len - hdrlen); + } + + strlen = (u32*)res->buffer; + /* Convert length of symlink */ + len = ntohl(*strlen); + if (len > res->bufsiz - 5) + len = res->bufsiz - 5; + *strlen = len; + /* NULL terminate the string we got */ + string = (char *)(strlen + 1); + string[len] = 0; return 0; } /* - * Decode STATFS reply + * Decode READ reply */ static int -nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) +nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res) { - int status; + struct iovec *iov = req->rq_rvec; + int status, count, ocount, recvd, hdrlen; - if ((status = ntohl(*p++))) + status = ntohl(*p++); + p = xdr_decode_post_op_attr(p, res->fattr); + + if (status != 0) return -nfs_stat_to_errno(status); - res->tsize = ntohl(*p++); - res->bsize = ntohl(*p++); - res->blocks = ntohl(*p++); - res->bfree = ntohl(*p++); - res->bavail = ntohl(*p++); - return 0; + + /* Decode reply could and EOF flag. NFSv3 is somewhat redundant + * in that it puts the count both in the res struct and in the + * opaque data count. */ + count = ntohl(*p++); + res->eof = ntohl(*p++); + ocount = ntohl(*p++); + + if (ocount != count) { + printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n"); + return -errno_NFSERR_IO; + } + + hdrlen = (u8 *) p - (u8 *) iov->iov_base; + if (iov->iov_len > hdrlen) { + dprintk("NFS: READ header is short. iovec will be shifted.\n"); + xdr_shift_iovec(iov, req->rq_rnr, iov->iov_len - hdrlen); + } + + recvd = req->rq_rlen - hdrlen; + if (count > recvd) { + printk(KERN_WARNING "NFS: server cheating in read reply: " + "count %d > recvd %d\n", count, recvd); + count = recvd; + } + + if (count < res->count) { + xdr_zero_iovec(iov+1, req->rq_rnr-2, res->count - count); + res->count = count; + } + + return count; } /* - * We need to translate between nfs status return values and - * the local errno values which may not be the same. + * Decode WRITE response */ -static struct { - int stat; - int errno; -} nfs_errtbl[] = { - { NFS_OK, 0 }, - { NFSERR_PERM, EPERM }, - { NFSERR_NOENT, ENOENT }, - { NFSERR_IO, errno_NFSERR_IO }, - { NFSERR_NXIO, ENXIO }, - { NFSERR_EAGAIN, EAGAIN }, - { NFSERR_ACCES, EACCES }, - { NFSERR_EXIST, EEXIST }, - { NFSERR_XDEV, EXDEV }, - { NFSERR_NODEV, ENODEV }, - { NFSERR_NOTDIR, ENOTDIR }, - { NFSERR_ISDIR, EISDIR }, - { NFSERR_INVAL, EINVAL }, - { NFSERR_FBIG, EFBIG }, - { NFSERR_NOSPC, ENOSPC }, - { NFSERR_ROFS, EROFS }, - { NFSERR_NAMETOOLONG, ENAMETOOLONG }, - { NFSERR_NOTEMPTY, ENOTEMPTY }, - { NFSERR_DQUOT, EDQUOT }, - { NFSERR_STALE, ESTALE }, -#ifdef EWFLUSH - { NFSERR_WFLUSH, EWFLUSH }, -#endif - { -1, EIO } -}; +static int +nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) +{ + int status; + + status = ntohl(*p++); + p = xdr_decode_wcc_data(p, res->fattr); + if (status != 0) + return -nfs_stat_to_errno(status); + + res->count = ntohl(*p++); + res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); + res->verf->verifier[0] = *p++; + res->verf->verifier[1] = *p++; + + return res->count; +} + +/* + * Decode a CREATE response + */ static int -nfs_stat_to_errno(int stat) +nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res) { - int i; + int status; - for (i = 0; nfs_errtbl[i].stat != -1; i++) { - if (nfs_errtbl[i].stat == stat) - return nfs_errtbl[i].errno; + status = ntohl(*p++); + if (status == 0) { + if (*p++) { + if (!(p = xdr_decode_fhandle(p, res->fh))) + return -errno_NFSERR_IO; + p = xdr_decode_post_op_attr(p, res->fattr); + } else { + memset(res->fh, 0, sizeof(*res->fh)); + /* Do decode post_op_attr but set it to NULL */ + p = xdr_decode_post_op_attr(p, res->fattr); + res->fattr->valid = 0; + } + } else { + status = -nfs_stat_to_errno(status); } - printk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat); - return nfs_errtbl[i].errno; + p = xdr_decode_wcc_data(p, res->dir_attr); + return status; } -#ifndef MAX -# define MAX(a, b) (((a) > (b))? (a) : (b)) -#endif +/* + * Decode RENAME reply + */ +static int +nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res) +{ + int status; -#define PROC(proc, argtype, restype) \ - { "nfs_" #proc, \ - (kxdrproc_t) nfs_xdr_##argtype, \ - (kxdrproc_t) nfs_xdr_##restype, \ - MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2 \ - } + if ((status = ntohl(*p++)) != 0) + status = -nfs_stat_to_errno(status); + p = xdr_decode_wcc_data(p, res->fromattr); + p = xdr_decode_wcc_data(p, res->toattr); + return status; +} -static struct rpc_procinfo nfs_procedures[18] = { - PROC(null, enc_void, dec_void), - PROC(getattr, fhandle, attrstat), - PROC(setattr, sattrargs, attrstat), - PROC(root, enc_void, dec_void), - PROC(lookup, diropargs, diropres), - PROC(readlink, fhandle, readlinkres), - PROC(read, readargs, readres), - PROC(writecache, enc_void, dec_void), - PROC(write, writeargs, attrstat), - PROC(create, createargs, diropres), - PROC(remove, diropargs, stat), - PROC(rename, renameargs, stat), - PROC(link, linkargs, stat), - PROC(symlink, symlinkargs, stat), - PROC(mkdir, createargs, diropres), - PROC(rmdir, diropargs, stat), - PROC(readdir, readdirargs, readdirres), - PROC(statfs, fhandle, statfsres), -}; +/* + * Decode LINK reply + */ +static int +nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res) +{ + int status; -static struct rpc_version nfs_version2 = { - 2, - sizeof(nfs_procedures)/sizeof(nfs_procedures[0]), - nfs_procedures -}; + if ((status = ntohl(*p++)) != 0) + status = -nfs_stat_to_errno(status); + p = xdr_decode_post_op_attr(p, res->fattr); + p = xdr_decode_wcc_data(p, res->dir_attr); + return status; +} -static struct rpc_version * nfs_version[] = { - NULL, - NULL, - &nfs_version2 -}; +/* + * Decode FSSTAT reply + */ +static int +nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) +{ + struct nfs_fattr dummy; + int status; -struct rpc_program nfs_program = { - "nfs", - NFS_PROGRAM, - sizeof(nfs_version) / sizeof(nfs_version[0]), - nfs_version, - &nfs_rpcstat, -}; + status = ntohl(*p++); + + p = xdr_decode_post_op_attr(p, &dummy); + if (status != 0) + return -nfs_stat_to_errno(status); + + p = xdr_decode_hyper(p, &res->tbytes); + p = xdr_decode_hyper(p, &res->fbytes); + p = xdr_decode_hyper(p, &res->abytes); + p = xdr_decode_hyper(p, &res->tfiles); + p = xdr_decode_hyper(p, &res->ffiles); + p = xdr_decode_hyper(p, &res->afiles); + + /* ignore invarsec */ + return 0; +} + +/* + * Decode FSINFO reply + */ +static int +nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) +{ + struct nfs_fattr dummy; + int status; + + status = ntohl(*p++); + + p = xdr_decode_post_op_attr(p, &dummy); + if (status != 0) + return -nfs_stat_to_errno(status); + + res->rtmax = ntohl(*p++); + res->rtpref = ntohl(*p++); + res->rtmult = ntohl(*p++); + res->wtmax = ntohl(*p++); + res->wtpref = ntohl(*p++); + res->wtmult = ntohl(*p++); + res->dtpref = ntohl(*p++); + p = xdr_decode_hyper(p, &res->maxfilesize); + + /* ignore time_delta and properties */ + return 0; +} + +/* + * Decode PATHCONF reply + */ +static int +nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res) +{ + struct nfs_fattr dummy; + int status; + + status = ntohl(*p++); + + p = xdr_decode_post_op_attr(p, &dummy); + if (status != 0) + return -nfs_stat_to_errno(status); + res->linkmax = ntohl(*p++); + res->namelen = ntohl(*p++); + + /* ignore remaining fields */ + return 0; +} /* - * RPC stats support + * Decode COMMIT reply */ static int -nfs_get_info(char *buffer, char **start, off_t offset, int length, int dummy) +nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res) { - return rpcstat_get_info(&nfs_rpcstat, buffer, start, offset, length); + int status; + + status = ntohl(*p++); + p = xdr_decode_wcc_data(p, res->fattr); + if (status != 0) + return -nfs_stat_to_errno(status); + + res->verf->verifier[0] = *p++; + res->verf->verifier[1] = *p++; + return 0; } -static struct proc_dir_entry proc_nfsclnt = { - 0, 3, "nfs", - S_IFREG | S_IRUGO, 1, 0, 0, - 6, NULL, - nfs_get_info +#ifndef MAX +# define MAX(a, b) (((a) > (b))? (a) : (b)) +#endif + +#define PROC(proc, argtype, restype) \ + { "nfs3_" #proc, \ + (kxdrproc_t) nfs3_xdr_##argtype, \ + (kxdrproc_t) nfs3_xdr_##restype, \ + MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \ + 0 \ + } + +static struct rpc_procinfo nfs3_procedures[22] = { + PROC(null, enc_void, dec_void), + PROC(getattr, fhandle, attrstat), + PROC(setattr, sattrargs, wccstat), + PROC(lookup, diropargs, lookupres), + PROC(access, accessargs, accessres), + PROC(readlink, readlinkargs, readlinkres), + PROC(read, readargs, readres), + PROC(write, writeargs, writeres), + PROC(create, createargs, createres), + PROC(mkdir, mkdirargs, createres), + PROC(symlink, symlinkargs, createres), + PROC(mknod, mknodargs, createres), + PROC(remove, diropargs, wccstat), + PROC(rmdir, diropargs, wccstat), + PROC(rename, renameargs, renameres), + PROC(link, linkargs, linkres), + PROC(readdir, readdirargs, readdirres), + PROC(readdirplus, readdirargs, readdirres), + PROC(fsstat, fhandle, fsstatres), + PROC(fsinfo, fhandle, fsinfores), + PROC(pathconf, fhandle, pathconfres), + PROC(commit, commitargs, commitres), }; -struct rpc_stat nfs_rpcstat = { - NULL, /* next */ - &proc_nfsclnt, /* /proc/net directory entry */ - &nfs_program, /* RPC program */ +struct rpc_version nfs_version3 = { + 3, + sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]), + nfs3_procedures }; + diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index a592608be023..6e1c8e7b22ff 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c @@ -61,6 +61,9 @@ * Martin Mares : Use root_server_addr appropriately during setup. * Martin Mares : Rewrote parameter parsing, now hopefully giving * correct overriding. + * Trond Myklebust : Add in preliminary support for NFSv3 and TCP. + * Fix bug in root_nfs_addr(). nfs_data.namlen + * is NOT for the length of the hostname. */ #include @@ -147,6 +150,12 @@ static struct nfs_bool_opts { { "noac", ~NFS_MOUNT_NOAC, NFS_MOUNT_NOAC }, { "lock", ~NFS_MOUNT_NONLM, 0 }, { "nolock", ~NFS_MOUNT_NONLM, NFS_MOUNT_NONLM }, +#ifdef CONFIG_NFS_V3 + { "v2", ~NFS_MOUNT_VER3, 0 }, + { "v3", ~NFS_MOUNT_VER3, NFS_MOUNT_VER3 }, +#endif + { "udp", ~NFS_MOUNT_TCP, 0 }, + { "tcp", ~NFS_MOUNT_TCP, NFS_MOUNT_TCP }, { NULL, 0, 0 } }; @@ -271,7 +280,6 @@ static int __init root_nfs_addr(void) } strncpy(nfs_data.hostname, in_ntoa(servaddr), sizeof(nfs_data.hostname)-1); - nfs_data.namlen = strlen(nfs_data.hostname); return 0; } @@ -360,14 +368,14 @@ set_sockaddr(struct sockaddr_in *sin, __u32 addr, __u16 port) /* * Query server portmapper for the port of a daemon program. */ -static int __init root_nfs_getport(int program, int version) +static int __init root_nfs_getport(int program, int version, int proto) { struct sockaddr_in sin; printk(KERN_NOTICE "Looking up port of RPC %d/%d on %s\n", program, version, in_ntoa(servaddr)); set_sockaddr(&sin, servaddr, 0); - return rpc_getport_external(&sin, program, version, IPPROTO_UDP); + return rpc_getport_external(&sin, program, version, proto); } @@ -379,22 +387,39 @@ static int __init root_nfs_getport(int program, int version) static int __init root_nfs_ports(void) { int port; + int nfsd_ver, mountd_ver; + int nfsd_port, mountd_port; + int proto; + + if (nfs_data.flags & NFS_MOUNT_VER3) { + nfsd_ver = NFS3_VERSION; + mountd_ver = NFS_MNT3_VERSION; + nfsd_port = NFS_PORT; + mountd_port = NFS_MNT_PORT; + } else { + nfsd_ver = NFS2_VERSION; + mountd_ver = NFS_MNT_VERSION; + nfsd_port = NFS_PORT; + mountd_port = NFS_MNT_PORT; + } + + proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; if (nfs_port < 0) { - if ((port = root_nfs_getport(NFS_PROGRAM, NFS_VERSION)) < 0) { + if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) { printk(KERN_ERR "Root-NFS: Unable to get nfsd port " "number from server, using default\n"); - port = NFS_PORT; + port = nfsd_port; } nfs_port = htons(port); dprintk("Root-NFS: Portmapper on server returned %d " "as nfsd port\n", port); } - if ((port = root_nfs_getport(NFS_MNT_PROGRAM, NFS_MNT_VERSION)) < 0) { + if ((port = root_nfs_getport(NFS_MNT_PROGRAM, nfsd_ver, proto)) < 0) { printk(KERN_ERR "Root-NFS: Unable to get mountd port " "number from server, using default\n"); - port = NFS_MNT_PORT; + port = mountd_port; } mount_port = htons(port); dprintk("Root-NFS: mountd port is %d\n", port); @@ -413,7 +438,10 @@ static int __init root_nfs_get_handle(void) int status; set_sockaddr(&sin, servaddr, mount_port); - status = nfs_mount(&sin, nfs_path, &nfs_data.root); + if (nfs_data.flags & NFS_MOUNT_VER3) + status = nfs3_mount(&sin, nfs_path, &nfs_data.root); + else + status = nfs_mount(&sin, nfs_path, &nfs_data.root); if (status < 0) printk(KERN_ERR "Root-NFS: Server returned error %d " "while mounting %s\n", status, nfs_path); diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 252ce6a91514..d6d5322174f6 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -13,10 +13,6 @@ * Note: Error returns are optimized for NFS_OK, which isn't translated via * nfs_stat_to_errno(), but happens to be already the right return code. * - * FixMe: We ought to define a sensible small max size for - * things like getattr that are tiny packets and use the - * old get_free_page stuff with it. - * * Also, the code currently doesn't check the size of the packet, when * it decodes the packet. * @@ -25,14 +21,17 @@ * Completely rewritten to support the new RPC call interface; * rewrote and moved the entire XDR stuff to xdr.c * --Olaf Kirch June 1996 + * + * The code below initializes all auto variables explicitly, otherwise + * it will fail to work as a module (gcc generates a memset call for an + * incomplete struct). */ -#define NFS_NEED_XDR_TYPES - +#include #include +#include #include #include -#include #include #include #include @@ -45,187 +44,261 @@ #include -#ifdef NFS_DEBUG -# define NFSDBG_FACILITY NFSDBG_PROC -#endif +#define NFSDBG_FACILITY NFSDBG_PROC +/* + * Bare-bones access to getattr: this is for nfs_read_super. + */ +static int +nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) +{ + int status; + + dprintk("NFS call getroot\n"); + fattr->valid = 0; + status = rpc_call(server->client, NFSPROC_GETATTR, fhandle, fattr, 0); + dprintk("NFS reply getroot\n"); + return status; +} /* * One function for each procedure in the NFS protocol. */ -int -nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) +static int +nfs_proc_getattr(struct dentry *dentry, struct nfs_fattr *fattr) { int status; dprintk("NFS call getattr\n"); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_GETATTR, fhandle, fattr, 0); + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_GETATTR, + NFS_FH(dentry), fattr, 0); dprintk("NFS reply getattr\n"); return status; } -int -nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fattr *fattr, struct iattr *sattr) +static int +nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, + struct iattr *sattr) { - struct nfs_sattrargs arg = { fhandle, sattr }; + struct nfs_sattrargs arg = { NFS_FH(dentry), sattr }; int status; dprintk("NFS call setattr\n"); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_SETATTR, &arg, fattr, 0); + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_SETATTR, &arg, fattr, 0); dprintk("NFS reply setattr\n"); return status; } -int -nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int +nfs_proc_lookup(struct dentry *dir, struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { - struct nfs_diropargs arg = { dir, name }; + struct nfs_diropargs arg = { NFS_FH(dir), name->name, name->len }; struct nfs_diropok res = { fhandle, fattr }; int status; - dprintk("NFS call lookup %s\n", name); + dprintk("NFS call lookup %s\n", name->name); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_LOOKUP, &arg, &res, 0); + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_LOOKUP, &arg, &res, 0); dprintk("NFS reply lookup: %d\n", status); return status; } -int -nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, int swap, - unsigned long offset, unsigned int count, - void *buffer, struct nfs_fattr *fattr) +static int +nfs_proc_readlink(struct dentry *dentry, void *buffer, unsigned int bufsiz) +{ + struct nfs_readlinkargs args = { NFS_FH(dentry), buffer, bufsiz }; + struct nfs_readlinkres res = { buffer, bufsiz }; + int status; + + dprintk("NFS call readlink\n"); + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_READLINK, + &args, &res, 0); + dprintk("NFS reply readlink: %d\n", status); + return status; +} + +static int +nfs_proc_read(struct dentry *dentry, struct nfs_fattr *fattr, int flags, + loff_t offset, unsigned int count, void *buffer, int *eofp) { - struct nfs_readargs arg = { fhandle, offset, count, buffer }; - struct nfs_readres res = { fattr, count }; + struct nfs_readargs arg = { NFS_FH(dentry), offset, count, 1, + {{ buffer, count }, {0,0}, {0,0}, {0,0}, + {0,0}, {0,0}, {0,0}, {0,0}} }; + struct nfs_readres res = { fattr, count, 0}; + struct rpc_message msg = { NFSPROC_READ, &arg, &res, NULL }; int status; - dprintk("NFS call read %d @ %ld\n", count, offset); + dprintk("NFS call read %d @ %Ld\n", count, (long long)offset); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_READ, &arg, &res, - swap? NFS_RPC_SWAPFLAGS : 0); + status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags); + dprintk("NFS reply read: %d\n", status); + *eofp = res.eof; return status; } -int -nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, int swap, - unsigned long offset, unsigned int count, - const void *buffer, struct nfs_fattr *fattr) +static int +nfs_proc_write(struct dentry *dentry, struct nfs_fattr *fattr, int how, + loff_t offset, unsigned int count, + void *buffer, struct nfs_writeverf *verf) { - struct nfs_writeargs arg = { fhandle, offset, count, + struct nfs_writeargs arg = {NFS_FH(dentry), offset, count, NFS_FILE_SYNC, 1, - {{(void *) buffer, count}, {0,0}, {0,0}, {0,0}, - {0,0}, {0,0}, {0,0}, {0,0}}}; - struct nfs_writeverf verf; - struct nfs_writeres res = {fattr, &verf, count}; - int status; + {{buffer, count}, {0,0}, {0,0}, {0,0}, + {0,0}, {0,0}, {0,0}, {0,0}}}; + struct nfs_writeres res = {fattr, verf, count}; + struct rpc_message msg = { NFSPROC_WRITE, &arg, &res, NULL }; + int status, flags = 0; - dprintk("NFS call write %d @ %ld\n", count, offset); + dprintk("NFS call write %d @ %Ld\n", count, (long long)offset); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_WRITE, &arg, &res, - swap? (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS) : 0); - dprintk("NFS reply read: %d\n", status); + if (how & NFS_RW_SWAP) + flags |= NFS_RPC_SWAPFLAGS; + status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags); + + dprintk("NFS reply write: %d\n", status); + verf->committed = NFS_FILE_SYNC; /* NFSv2 always syncs data */ return status < 0? status : count; } -int -nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir, - const char *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int +nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr, + int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { - struct nfs_createargs arg = { dir, name, sattr }; + struct nfs_createargs arg = { NFS_FH(dir), name->name, + name->len, sattr }; struct nfs_diropok res = { fhandle, fattr }; int status; - dprintk("NFS call create %s\n", name); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_CREATE, &arg, &res, 0); + dprintk("NFS call create %s\n", name->name); + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0); dprintk("NFS reply create: %d\n", status); return status; } -int -nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name) +/* + * In NFSv2, mknod is grafted onto the create call. + */ +static int +nfs_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr, + dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { - struct nfs_diropargs arg = { dir, name }; + struct nfs_createargs arg = { NFS_FH(dir), name->name, + name->len, sattr }; + struct nfs_diropok res = { fhandle, fattr }; + int status, mode; + + dprintk("NFS call mknod %s\n", name->name); + + mode = sattr->ia_mode; + if (S_ISFIFO(mode)) { + sattr->ia_mode = (mode & ~S_IFMT) | S_IFCHR; + sattr->ia_valid &= ~ATTR_SIZE; + } else if (S_ISCHR(rdev) || S_ISBLK(rdev)) { + sattr->ia_valid |= ATTR_SIZE; + sattr->ia_size = rdev; /* get out your barf bag */ + } + + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0); + + if (status == -EINVAL && S_ISFIFO(mode)) { + sattr->ia_mode = mode; + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0); + } + dprintk("NFS reply mknod: %d\n", status); + return status; +} + +static int +nfs_proc_remove(struct dentry *dir, struct qstr *name) +{ + struct nfs_diropargs arg = { NFS_FH(dir), name->name, name->len }; + struct rpc_message msg = { NFSPROC_REMOVE, &arg, NULL, NULL }; int status; - dprintk("NFS call remove %s\n", name); - status = rpc_call(server->client, NFSPROC_REMOVE, &arg, NULL, 0); + dprintk("NFS call remove %s\n", name->name); + status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0); + dprintk("NFS reply remove: %d\n", status); return status; } -int -nfs_proc_rename(struct nfs_server *server, - struct nfs_fh *old_dir, const char *old_name, - struct nfs_fh *new_dir, const char *new_name) +static int +nfs_proc_rename(struct dentry *old_dir, struct qstr *old_name, + struct dentry *new_dir, struct qstr *new_name) { - struct nfs_renameargs arg = { old_dir, old_name, new_dir, new_name }; + struct nfs_renameargs arg = { NFS_FH(old_dir), old_name->name, + old_name->len, + NFS_FH(new_dir), new_name->name, + new_name->len}; int status; - dprintk("NFS call rename %s -> %s\n", old_name, new_name); - status = rpc_call(server->client, NFSPROC_RENAME, &arg, NULL, 0); + dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); + status = rpc_call(NFS_CLIENT(old_dir->d_inode), NFSPROC_RENAME, &arg, NULL, 0); dprintk("NFS reply rename: %d\n", status); return status; } -int -nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fh *dir, const char *name) +static int +nfs_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name) { - struct nfs_linkargs arg = { fhandle, dir, name }; + struct nfs_linkargs arg = { NFS_FH(dentry), NFS_FH(dir), + name->name, name->len }; int status; - dprintk("NFS call link %s\n", name); - status = rpc_call(server->client, NFSPROC_LINK, &arg, NULL, 0); + dprintk("NFS call link %s\n", name->name); + status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_LINK, &arg, NULL, 0); dprintk("NFS reply link: %d\n", status); return status; } -int -nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir, - const char *name, const char *path, - struct iattr *sattr) +static int +nfs_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path, + struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { - struct nfs_symlinkargs arg = { dir, name, path, sattr }; + struct nfs_symlinkargs arg = { NFS_FH(dir), name->name, name->len, + path->name, path->len, sattr }; int status; - dprintk("NFS call symlink %s -> %s\n", name, path); - status = rpc_call(server->client, NFSPROC_SYMLINK, &arg, NULL, 0); + dprintk("NFS call symlink %s -> %s\n", name->name, path->name); + fattr->valid = 0; + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_SYMLINK, &arg, NULL, 0); dprintk("NFS reply symlink: %d\n", status); return status; } -int -nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir, - const char *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int +nfs_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { - struct nfs_createargs arg = { dir, name, sattr }; + struct nfs_createargs arg = { NFS_FH(dir), name->name, name->len, + sattr }; struct nfs_diropok res = { fhandle, fattr }; int status; - dprintk("NFS call mkdir %s\n", name); + dprintk("NFS call mkdir %s\n", name->name); fattr->valid = 0; - status = rpc_call(server->client, NFSPROC_MKDIR, &arg, &res, 0); + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_MKDIR, &arg, &res, 0); dprintk("NFS reply mkdir: %d\n", status); return status; } -int -nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name) +static int +nfs_proc_rmdir(struct dentry *dir, struct qstr *name) { - struct nfs_diropargs arg = { dir, name }; + struct nfs_diropargs arg = { NFS_FH(dir), name->name, name->len }; int status; - dprintk("NFS call rmdir %s\n", name); - status = rpc_call(server->client, NFSPROC_RMDIR, &arg, NULL, 0); + dprintk("NFS call rmdir %s\n", name->name); + status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_RMDIR, &arg, NULL, 0); dprintk("NFS reply rmdir: %d\n", status); return status; } @@ -237,9 +310,9 @@ nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name) * sure it is syntactically correct; the entries itself are decoded * from nfs_readdir by calling the decode_entry function directly. */ -int -nfs_proc_readdir(struct dentry *dir, struct nfs_fattr *dir_attr, - __u64 cookie, void *entry, unsigned int size, int plus) +static int +nfs_proc_readdir(struct dentry *dir, __u64 cookie, void *entry, + unsigned int size, int plus) { struct nfs_readdirargs arg; struct nfs_readdirres res; @@ -250,7 +323,6 @@ nfs_proc_readdir(struct dentry *dir, struct nfs_fattr *dir_attr, if (server->rsize < size) size = server->rsize; - dir_attr->valid = 0; arg.fh = NFS_FH(dir); arg.cookie = cookie; arg.buffer = entry; @@ -258,7 +330,6 @@ nfs_proc_readdir(struct dentry *dir, struct nfs_fattr *dir_attr, res.buffer = entry; res.bufsiz = size; - dir_attr->valid = 0; dprintk("NFS call readdir %d\n", (unsigned int)cookie); status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0); @@ -266,14 +337,41 @@ nfs_proc_readdir(struct dentry *dir, struct nfs_fattr *dir_attr, return status; } -int +static int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { int status; dprintk("NFS call statfs\n"); + memset((char *)info, 0, sizeof(*info)); status = rpc_call(server->client, NFSPROC_STATFS, fhandle, info, 0); dprintk("NFS reply statfs: %d\n", status); return status; } + +extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); + +struct nfs_rpc_ops nfs_v2_clientops = { + 2, /* protocol version */ + nfs_proc_get_root, + nfs_proc_getattr, + nfs_proc_setattr, + nfs_proc_lookup, + NULL, /* access */ + nfs_proc_readlink, + nfs_proc_read, + nfs_proc_write, + NULL, /* commit */ + nfs_proc_create, + nfs_proc_remove, + nfs_proc_rename, + nfs_proc_link, + nfs_proc_symlink, + nfs_proc_mkdir, + nfs_proc_rmdir, + nfs_proc_readdir, + nfs_proc_mknod, + nfs_proc_statfs, + nfs_decode_dirent, +}; diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 813e0aff0969..0f455cfb5eaf 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -15,7 +15,6 @@ * within the RPC code when root squashing is suspected. */ -#define NFS_NEED_XDR_TYPES #include #include #include @@ -52,15 +51,18 @@ struct nfs_rreq { */ static inline void nfs_readreq_setup(struct nfs_rreq *req, struct nfs_fh *fh, - unsigned long offset, void *buffer, unsigned int rsize) + loff_t offset, void *buffer, unsigned int rsize) { req->ra_args.fh = fh; req->ra_args.offset = offset; req->ra_args.count = rsize; - req->ra_args.buffer = buffer; + req->ra_args.iov[0].iov_base = (void *)buffer; + req->ra_args.iov[0].iov_len = rsize; + req->ra_args.nriov = 1; + req->ra_fattr.valid = 0; req->ra_res.fattr = &req->ra_fattr; req->ra_res.count = rsize; - req->ra_fattr.valid = 0; + req->ra_res.eof = 0; } @@ -71,11 +73,12 @@ static int nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) { struct nfs_rreq rqst; - unsigned long offset = page->index << PAGE_CACHE_SHIFT; + struct rpc_message msg; + loff_t offset = page_offset(page); char *buffer; int rsize = NFS_SERVER(inode)->rsize; int result, refresh = 0; - int count = PAGE_SIZE; + int count = PAGE_CACHE_SIZE; int flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0; dprintk("NFS: nfs_readpage_sync(%p)\n", page); @@ -90,15 +93,19 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page) if (count < rsize) rsize = count; - dprintk("NFS: nfs_proc_read(%s, (%s/%s), %ld, %d, %p)\n", + dprintk("NFS: nfs_proc_read(%s, (%s/%s), %Ld, %d, %p)\n", NFS_SERVER(inode)->hostname, dentry->d_parent->d_name.name, dentry->d_name.name, - offset, rsize, buffer); + (long long)offset, rsize, buffer); /* Set up arguments and perform rpc call */ nfs_readreq_setup(&rqst, NFS_FH(dentry), offset, buffer, rsize); lock_kernel(); - result = rpc_call(NFS_CLIENT(inode), NFSPROC_READ, &rqst.ra_args, &rqst.ra_res, flags); + msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ? NFS3PROC_READ : NFSPROC_READ; + msg.rpc_argp = &rqst.ra_args; + msg.rpc_resp = &rqst.ra_res; + msg.rpc_cred = NULL; + result = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); unlock_kernel(); nfs_refresh_inode(inode, &rqst.ra_fattr); @@ -138,19 +145,18 @@ nfs_readpage_result(struct rpc_task *task) { struct nfs_rreq *req = (struct nfs_rreq *) task->tk_calldata; struct page *page = req->ra_page; - unsigned long address = page_address(page); + char *address = req->ra_args.iov[0].iov_base; int result = task->tk_status; static int succ = 0, fail = 0; - dprintk("NFS: %4d received callback for page %lx, result %d\n", + dprintk("NFS: %4d received callback for page %p, result %d\n", task->tk_pid, address, result); nfs_refresh_inode(req->ra_inode, &req->ra_fattr); if (result >= 0) { result = req->ra_res.count; - if (result < PAGE_SIZE) { - memset((char *) address + result, 0, PAGE_SIZE - result); - } + if (result < PAGE_CACHE_SIZE) + memset(address + result, 0, PAGE_CACHE_SIZE - result); SetPageUptodate(page); succ++; } else { @@ -160,7 +166,7 @@ nfs_readpage_result(struct rpc_task *task) } kunmap(page); UnlockPage(page); - __free_page(page); + page_cache_release(page); rpc_release_task(task); kfree(req); @@ -188,15 +194,15 @@ nfs_readpage_async(struct dentry *dentry, struct inode *inode, address = kmap(page); /* Initialize request */ /* N.B. Will the dentry remain valid for life of request? */ - nfs_readreq_setup(req, NFS_FH(dentry), page->index << PAGE_CACHE_SHIFT, - (void *) address, PAGE_SIZE); + nfs_readreq_setup(req, NFS_FH(dentry), page_offset(page), + (void *) address, PAGE_CACHE_SIZE); req->ra_inode = inode; req->ra_page = page; /* count has been incremented by caller */ /* Start the async call */ dprintk("NFS: executing async READ request.\n"); - msg.rpc_proc = NFSPROC_READ; + msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ? NFS3PROC_READ : NFSPROC_READ; msg.rpc_argp = &req->ra_args; msg.rpc_resp = &req->ra_res; msg.rpc_cred = NULL; @@ -224,7 +230,7 @@ out_free: * We read the page synchronously in the following cases: * - The file is a swap file. Swap-ins are always sync operations, * so there's no need bothering to make async reads 100% fail-safe. - * - The NFS rsize is smaller than PAGE_SIZE. We could kludge our way + * - The NFS rsize is smaller than PAGE_CACHE_SIZE. We could kludge our way * around this by creating several consecutive read requests, but * that's hardly worth it. * - The error flag is set for this page. This happens only when a @@ -239,7 +245,7 @@ nfs_readpage(struct dentry *dentry, struct page *page) lock_kernel(); dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", - page, PAGE_SIZE, page->index); + page, PAGE_CACHE_SIZE, page->index); get_page(page); /* @@ -255,7 +261,7 @@ nfs_readpage(struct dentry *dentry, struct page *page) error = -1; if (!IS_SWAPFILE(inode) && !PageError(page) && - NFS_SERVER(inode)->rsize >= PAGE_SIZE) + NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) error = nfs_readpage_async(dentry, inode, page); if (error >= 0) goto out; @@ -268,7 +274,7 @@ nfs_readpage(struct dentry *dentry, struct page *page) out_error: UnlockPage(page); out_free: - __free_page(page); + page_cache_release(page); out: unlock_kernel(); return error; diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index ba2a87b1feb3..da3a425bedf8 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c @@ -28,16 +28,17 @@ */ static int nfs_symlink_filler(struct dentry *dentry, struct page *page) { - struct nfs_readlinkargs rl_args; - kmap(page); + struct inode *inode = dentry->d_inode; + void *buffer = (void *)kmap(page); + int error; + /* We place the length at the beginning of the page, * in host byte order, followed by the string. The * XDR response verification will NULL terminate it. */ - rl_args.fh = NFS_FH(dentry); - rl_args.buffer = (const void *)page_address(page); - if (rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_READLINK, - &rl_args, NULL, 0) < 0) + error = NFS_PROTO(inode)->readlink(dentry, buffer, + PAGE_CACHE_SIZE - sizeof(u32)-4); + if (error < 0) goto error; SetPageUptodate(page); kunmap(page); @@ -87,10 +88,11 @@ static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen) } static struct dentry * -nfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) +nfs_follow_link(struct dentry *dentry, struct dentry *base, + struct vfsmount **mnt, unsigned int follow) { struct page *page = NULL; - struct dentry *res = vfs_follow_link(dentry, base, follow, + struct dentry *res = vfs_follow_link(dentry, base, mnt, follow, nfs_getlink(dentry, &page)); if (page) { kunmap(page); diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 62f5563e8696..5c37543363d3 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -190,10 +190,12 @@ static int nfs_writepage_sync(struct dentry *dentry, struct inode *inode, struct page *page, unsigned long offset, unsigned int count) { + loff_t base; unsigned int wsize = NFS_SERVER(inode)->wsize; - int result, refresh = 0, written = 0; + int result, refresh = 0, written = 0, flags; u8 *buffer; struct nfs_fattr fattr; + struct nfs_writeverf verf; lock_kernel(); dprintk("NFS: nfs_writepage_sync(%s/%s %d@%lu/%ld)\n", @@ -201,15 +203,16 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode, count, page->index, offset); buffer = (u8 *) kmap(page) + offset; - offset += page->index << PAGE_CACHE_SHIFT; + base = page_offset(page) + offset; + + flags = ((IS_SWAPFILE(inode)) ? NFS_RW_SWAP : 0) | NFS_RW_SYNC; do { if (count < wsize && !IS_SWAPFILE(inode)) wsize = count; - result = nfs_proc_write(NFS_DSERVER(dentry), NFS_FH(dentry), - IS_SWAPFILE(inode), offset, wsize, - buffer, &fattr); + result = NFS_PROTO(inode)->write(dentry, &fattr, flags, + base, wsize, buffer, &verf); nfs_write_attributes(inode, &fattr); if (result < 0) { @@ -222,15 +225,15 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode, wsize, result); refresh = 1; buffer += wsize; - offset += wsize; + base += wsize; written += wsize; count -= wsize; /* * If we've extended the file, update the inode * now so we don't invalidate the cache. */ - if (offset > inode->i_size) - inode->i_size = offset; + if (base > inode->i_size) + inode->i_size = base; } while (count); io_error: @@ -1427,11 +1430,11 @@ nfs_commit_done(struct rpc_task *task) req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); - dprintk("NFS: commit (%s/%s %d@%ld)", + dprintk("NFS: commit (%s/%s %d@%Ld)", req->wb_file->f_dentry->d_parent->d_name.name, req->wb_file->f_dentry->d_name.name, req->wb_bytes, - page_offset(req->wb_page) + req->wb_offset); + (long long)(page_offset(req->wb_page) + req->wb_offset)); if (task->tk_status < 0) { req->wb_file->f_error = task->tk_status; nfs_inode_remove_request(req); diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index c45d494ba4d7..f38e2552b818 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -27,7 +27,8 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp) /* must initialize before using! but maxsize doesn't matter */ fh_init(&fh,0); - memcpy((char*)&fh.fh_handle.fh_base, (char*)f, NFS_FHSIZE); + fh.fh_handle.fh_size = f->size; + memcpy((char*)&fh.fh_handle.fh_base, f->data, NFS_FHSIZE); fh.fh_export = NULL; nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp); diff --git a/fs/open.c b/fs/open.c index 8de3c310a631..45de02b68ba2 100644 --- a/fs/open.c +++ b/fs/open.c @@ -141,11 +141,8 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length) file = fget(fd); if (!file) goto out; - error = -ENOENT; - if (!(dentry = file->f_dentry)) - goto out_putf; - if (!(inode = dentry->d_inode)) - goto out_putf; + dentry = file->f_dentry; + inode = dentry->d_inode; error = -EACCES; if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) goto out_putf; @@ -330,20 +327,32 @@ asmlinkage long sys_access(const char * filename, int mode) return res; } +/* MOUNT_REWRITE: pass &mnt to lookup_dentry */ asmlinkage long sys_chdir(const char * filename) { int error; struct inode *inode; struct dentry *dentry, *tmp; + struct vfsmount *mnt = NULL, *tmp_mnt; + char *name; lock_kernel(); - dentry = namei(filename); + name = getname(filename); + error = PTR_ERR(name); + if (IS_ERR(name)) + goto out; + + dentry = lookup_dentry(name, NULL, 0); + putname(name); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out; + error = -ENOENT; inode = dentry->d_inode; + if (!inode) + goto dput_and_out; error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) @@ -355,10 +364,14 @@ asmlinkage long sys_chdir(const char * filename) /* exchange dentries */ tmp = current->fs->pwd; + tmp_mnt = current->fs->pwdmnt; current->fs->pwd = dentry; + current->fs->pwdmnt = mnt; dentry = tmp; + mnt = tmp_mnt; dput_and_out: + mntput(mnt); dput(dentry); out: unlock_kernel(); @@ -370,6 +383,7 @@ asmlinkage long sys_fchdir(unsigned int fd) struct file *file; struct dentry *dentry; struct inode *inode; + struct vfsmount *mnt; int error; error = -EBADF; @@ -377,11 +391,9 @@ asmlinkage long sys_fchdir(unsigned int fd) if (!file) goto out; - error = -ENOENT; - if (!(dentry = file->f_dentry)) - goto out_putf; - if (!(inode = dentry->d_inode)) - goto out_putf; + dentry = file->f_dentry; + mnt = file->f_vfsmnt; + inode = dentry->d_inode; error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) @@ -391,7 +403,10 @@ asmlinkage long sys_fchdir(unsigned int fd) error = permission(inode, MAY_EXEC); if (!error) { struct dentry *tmp = current->fs->pwd; + struct vfsmount *tmp_mnt = current->fs->pwdmnt; current->fs->pwd = dget(dentry); + current->fs->pwdmnt = mntget(mnt); + mntput(tmp_mnt); dput(tmp); } unlock_kernel(); @@ -401,20 +416,32 @@ out: return error; } +/* MOUNT_REWRITE: pass &mnt to lookup_dentry */ asmlinkage long sys_chroot(const char * filename) { int error; struct inode *inode; struct dentry *dentry, *tmp; + struct vfsmount *mnt = NULL, *tmp_mnt; + char *name; lock_kernel(); - dentry = namei(filename); + name = getname(filename); + error = PTR_ERR(name); + if (IS_ERR(name)) + goto out; + + dentry = lookup_dentry(name, NULL, 0); + putname(name); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out; + error = -ENOENT; inode = dentry->d_inode; + if (!inode) + goto dput_and_out; error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) @@ -430,11 +457,15 @@ asmlinkage long sys_chroot(const char * filename) /* exchange dentries */ tmp = current->fs->root; + tmp_mnt = current->fs->rootmnt; current->fs->root = dentry; + current->fs->rootmnt = mnt; dentry = tmp; + mnt = tmp_mnt; error = 0; dput_and_out: + mntput(mnt); dput(dentry); out: unlock_kernel(); @@ -453,11 +484,8 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) if (!file) goto out; - err = -ENOENT; - if (!(dentry = file->f_dentry)) - goto out_putf; - if (!(inode = dentry->d_inode)) - goto out_putf; + dentry = file->f_dentry; + inode = dentry->d_inode; err = -EROFS; if (IS_RDONLY(inode)) @@ -612,20 +640,16 @@ asmlinkage long sys_lchown(const char * filename, uid_t user, gid_t group) asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) { - struct dentry * dentry; struct file * file; int error = -EBADF; file = fget(fd); if (!file) goto out; - error = -ENOENT; lock_kernel(); - if ((dentry = file->f_dentry) != NULL) - error = chown_common(dentry, user, group); + error = chown_common(file->f_dentry, user, group); unlock_kernel(); fput(file); - out: return error; } @@ -644,7 +668,7 @@ out: * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ -struct file *filp_open(const char * filename, int flags, int mode, struct dentry * base) +struct file *__filp_open(const char * filename, int flags, int mode, struct dentry * base, struct vfsmount *mnt) { struct dentry * dentry; int flag,error; @@ -655,15 +679,15 @@ struct file *filp_open(const char * filename, int flags, int mode, struct dentry if (flag & O_TRUNC) flag |= 2; - dentry = __open_namei(filename, flag, mode, base); + dentry = open_namei(filename, flag, mode, base, &mnt); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) - return dentry_open(dentry, flags); + return dentry_open(dentry, mnt, flags); return ERR_PTR(error); } -struct file *dentry_open(struct dentry *dentry, int flags) +struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) { struct file * f; struct inode *inode; @@ -683,6 +707,7 @@ struct file *dentry_open(struct dentry *dentry, int flags) } f->f_dentry = dentry; + f->f_vfsmnt = mnt; f->f_pos = 0; f->f_reada = 0; f->f_op = inode->i_fop; @@ -701,8 +726,10 @@ cleanup_all: if (f->f_mode & FMODE_WRITE) put_write_access(inode); f->f_dentry = NULL; + f->f_vfsmnt = NULL; cleanup_dentry: dput(dentry); + mntput(mnt); put_filp(f); return ERR_PTR(error); } @@ -793,7 +820,7 @@ asmlinkage long sys_open(const char * filename, int flags, int mode) if (fd >= 0) { struct file * f; lock_kernel(); - f = filp_open(tmp, flags, mode, NULL); + f = filp_open(tmp, flags, mode); unlock_kernel(); error = PTR_ERR(f); if (IS_ERR(f)) @@ -831,7 +858,6 @@ asmlinkage long sys_creat(const char * pathname, int mode) int filp_close(struct file *filp, fl_owner_t id) { int retval; - struct dentry *dentry = filp->f_dentry; if (!file_count(filp)) { printk("VFS: Close: file count is 0\n"); @@ -840,8 +866,7 @@ int filp_close(struct file *filp, fl_owner_t id) retval = 0; if (filp->f_op && filp->f_op->flush) retval = filp->f_op->flush(filp); - if (dentry->d_inode) - locks_remove_posix(filp, id); + locks_remove_posix(filp, id); fput(filp); return retval; } diff --git a/fs/proc/array.c b/fs/proc/array.c index 414434245483..476f05f8cd92 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -574,7 +574,9 @@ ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); buffer[PAGE_SIZE-1] = '\n'; line -= maxlen; if(line < buffer) diff --git a/fs/proc/base.c b/fs/proc/base.c index 4a191bfef5b3..37ac246bf48f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -38,14 +38,18 @@ int proc_pid_status(struct task_struct*,char*); int proc_pid_statm(struct task_struct*,char*); int proc_pid_cpu(struct task_struct*,char*); -static struct dentry *proc_fd_link(struct inode *inode) +static struct dentry *proc_fd_link(struct inode *inode, struct vfsmount **mnt) { - if (inode->u.proc_i.file) + if (inode->u.proc_i.file) { + if (inode->u.proc_i.file->f_vfsmnt) { + *mnt = mntget(inode->u.proc_i.file->f_vfsmnt); + } return dget(inode->u.proc_i.file->f_dentry); + } return NULL; } -static struct dentry *proc_exe_link(struct inode *inode) +static struct dentry *proc_exe_link(struct inode *inode, struct vfsmount **mnt) { struct mm_struct * mm; struct vm_area_struct * vma; @@ -62,6 +66,7 @@ static struct dentry *proc_exe_link(struct inode *inode) while (vma) { if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { + *mnt = mntget(vma->vm_file->f_vfsmnt); result = dget(vma->vm_file->f_dentry); break; } @@ -73,25 +78,29 @@ out: return result; } -static struct dentry *proc_cwd_link(struct inode *inode) +static struct dentry *proc_cwd_link(struct inode *inode, struct vfsmount **mnt) { struct dentry *result = NULL; if (task_lock(inode->u.proc_i.task)) { struct fs_struct *fs = inode->u.proc_i.task->fs; - if (fs) + if (fs) { + *mnt = mntget(fs->pwdmnt); result = dget(fs->pwd); + } task_unlock(inode->u.proc_i.task); } return result; } -static struct dentry *proc_root_link(struct inode *inode) +static struct dentry *proc_root_link(struct inode *inode, struct vfsmount **mnt) { struct dentry *result = NULL; if (task_lock(inode->u.proc_i.task)) { struct fs_struct *fs = inode->u.proc_i.task->fs; - if (fs) + if (fs) { + *mnt = mntget(fs->rootmnt); result = dget(fs->root); + } task_unlock(inode->u.proc_i.task); } return result; @@ -160,16 +169,19 @@ static int proc_permission(struct inode *inode, int mask) { struct dentry *de, *base, *root; struct super_block *our_sb, *sb, *below; + struct vfsmount *our_vfsmnt, *vfsmnt, *mnt; if (standard_permission(inode, mask) != 0) return -EACCES; base = current->fs->root; - de = root = proc_root_link(inode); /* Ewww... */ + our_vfsmnt = current->fs->rootmnt; + de = root = proc_root_link(inode, &vfsmnt); /* Ewww... */ if (!de) return -ENOENT; + mnt = vfsmnt; our_sb = base->d_inode->i_sb; sb = de->d_inode->i_sb; while (sb != our_sb) { @@ -184,9 +196,11 @@ static int proc_permission(struct inode *inode, int mask) goto out; dput(root); + mntput(mnt); return 0; out: dput(root); + mntput(mnt); return -EACCES; } @@ -347,6 +361,7 @@ static struct inode_operations proc_mem_inode_operations = { static struct dentry * proc_pid_follow_link(struct dentry *dentry, struct dentry *base, + struct vfsmount **vfsmnt, unsigned int follow) { struct inode *inode = dentry->d_inode; @@ -355,20 +370,22 @@ static struct dentry * proc_pid_follow_link(struct dentry *dentry, /* We don't need a base pointer in the /proc filesystem */ dput(base); + mntput(*vfsmnt); error = proc_permission(inode, MAY_EXEC); result = ERR_PTR(error); if (error) goto out; - result = inode->u.proc_i.op.proc_get_link(inode); + result = inode->u.proc_i.op.proc_get_link(inode, vfsmnt); out: if (!result) result = ERR_PTR(-ENOENT); return result; } -static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen) +static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, + char * buffer, int buflen) { struct inode * inode; char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern; @@ -391,7 +408,7 @@ static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen) len = sprintf(tmp, pattern, inode->i_ino); path = tmp; } else { - path = d_path(dentry, tmp, PAGE_SIZE); + path = d_path(dentry, mnt, tmp, PAGE_SIZE); len = tmp + PAGE_SIZE - 1 - path; } @@ -406,12 +423,13 @@ static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) { int error; struct inode *inode = dentry->d_inode; + struct vfsmount *mnt; error = proc_permission(inode, MAY_EXEC); if (error) goto out; - dentry = inode->u.proc_i.op.proc_get_link(inode); + dentry = inode->u.proc_i.op.proc_get_link(inode, &mnt); error = -ENOENT; if (!dentry) goto out; @@ -420,8 +438,9 @@ static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) if (IS_ERR(dentry)) goto out; - error = do_proc_readlink(dentry, buffer, buflen); + error = do_proc_readlink(dentry, mnt, buffer, buflen); dput(dentry); + mntput(mnt); out: return error; } diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 28e0c08e5dc4..3f30f6a3d32a 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -201,10 +201,10 @@ static int proc_readlink(struct dentry *dentry, char *buffer, int buflen) return vfs_readlink(dentry, buffer, buflen, s); } -static struct dentry *proc_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags) +static struct dentry *proc_follow_link(struct dentry *dentry, struct dentry *base, struct vfsmount **mnt, unsigned flags) { char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; - return vfs_follow_link(dentry, base, flags, s); + return vfs_follow_link(dentry, base, mnt, flags, s); } static struct inode_operations proc_link_inode_operations = { diff --git a/fs/proc/root.c b/fs/proc/root.c index cce48d845b07..0aa585a45a7f 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -34,11 +34,12 @@ static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen) static struct dentry * proc_self_follow_link(struct dentry *dentry, struct dentry *base, + struct vfsmount **mnt, unsigned int follow) { char tmp[30]; sprintf(tmp, "%d", current->pid); - return vfs_follow_link(dentry,base,follow,tmp); + return vfs_follow_link(dentry,base,mnt,follow,tmp); } static struct inode_operations proc_self_inode_operations = { diff --git a/fs/read_write.c b/fs/read_write.c index e82aaea968d3..4569ee18aca6 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -64,17 +64,11 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) { off_t retval; struct file * file; - struct dentry * dentry; - struct inode * inode; retval = -EBADF; file = fget(fd); if (!file) goto bad; - /* N.B. Shouldn't this be ENOENT?? */ - if (!(dentry = file->f_dentry) || - !(inode = dentry->d_inode)) - goto out_putf; retval = -EINVAL; if (origin <= 2) { loff_t res = llseek(file, offset, origin); @@ -82,7 +76,6 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ } -out_putf: fput(file); bad: return retval; @@ -95,18 +88,12 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, { int retval; struct file * file; - struct dentry * dentry; - struct inode * inode; loff_t offset; retval = -EBADF; file = fget(fd); if (!file) goto bad; - /* N.B. Shouldn't this be ENOENT?? */ - if (!(dentry = file->f_dentry) || - !(inode = dentry->d_inode)) - goto out_putf; retval = -EINVAL; if (origin > 2) goto out_putf; diff --git a/fs/super.c b/fs/super.c index 967cd1317eb8..05a4773c9120 100644 --- a/fs/super.c +++ b/fs/super.c @@ -91,6 +91,19 @@ static struct file_system_type **find_filesystem(const char *name) return p; } +/** + * register_filesystem - register a new filesystem + * @fs: the file system structure + * + * Adds the file system passed to the list of file systems the kernel + * is aware of for by mount and other syscalls. Returns 0 on success, + * or a negative errno code on an error. + * + * The file_system_type that is passed is linked into the kernel + * structures and must not be freed until the file system has been + * unregistered. + */ + int register_filesystem(struct file_system_type * fs) { int res = 0; @@ -110,6 +123,18 @@ int register_filesystem(struct file_system_type * fs) return res; } +/** + * unregister_filesystem - unregister a file system + * @fs: filesystem to unregister + * + * Remove a file system that was previously successfully registered + * with the kernel. An error is returned if the file system is not found. + * Zero is returned on a success. + * + * Once this function has returned the file_system_type structure may be + * freed or reused. + */ + int unregister_filesystem(struct file_system_type * fs) { struct file_system_type ** tmp; @@ -251,7 +276,7 @@ static struct vfsmount *add_vfsmnt(struct super_block *sb, const char *dev_name, const char *dir_name) { struct vfsmount *lptr; - char *tmp, *name; + char *name; lptr = (struct vfsmount *)kmalloc(sizeof(struct vfsmount), GFP_KERNEL); if (!lptr) @@ -262,21 +287,19 @@ static struct vfsmount *add_vfsmnt(struct super_block *sb, lptr->mnt_dev = sb->s_dev; /* N.B. Is it really OK to have a vfsmount without names? */ - if (dev_name && !IS_ERR(tmp = getname(dev_name))) { - name = (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL); + if (dev_name) { + name = (char *) kmalloc(strlen(dev_name)+1, GFP_KERNEL); if (name) { - strcpy(name, tmp); + strcpy(name, dev_name); lptr->mnt_devname = name; } - putname(tmp); } - if (dir_name && !IS_ERR(tmp = getname(dir_name))) { - name = (char *) kmalloc(strlen(tmp)+1, GFP_KERNEL); + if (dir_name) { + name = (char *) kmalloc(strlen(dir_name)+1, GFP_KERNEL); if (name) { - strcpy(name, tmp); + strcpy(name, dir_name); lptr->mnt_dirname = name; } - putname(tmp); } if (vfsmntlist == (struct vfsmount *)NULL) { @@ -360,9 +383,10 @@ int get_filesystem_info( char *buf ) char *path,*buffer = (char *) __get_free_page(GFP_KERNEL); if (!buffer) return 0; - for (tmp = vfsmntlist; tmp && len < PAGE_SIZE - 160; - tmp = tmp->mnt_next) { - path = d_path(tmp->mnt_sb->s_root, buffer, PAGE_SIZE); + for (tmp = vfsmntlist; tmp && len < PAGE_SIZE - 160; tmp = tmp->mnt_next) { + if (!tmp->mnt_sb || !tmp->mnt_sb->s_root) + continue; + path = d_path(tmp->mnt_sb->s_root, tmp, buffer, PAGE_SIZE); if (!path) continue; len += sprintf( buf + len, "%s %s %s %s", @@ -427,6 +451,14 @@ int get_filesystem_info( char *buf ) return len; } +/** + * __wait_on_super - wait on a superblock + * @sb: superblock to wait on + * + * Waits for a superblock to become unlocked and then returns. It does + * not take the lock. This is an internal function. See wait_on_super. + */ + void __wait_on_super(struct super_block * sb) { DECLARE_WAITQUEUE(wait, current); @@ -471,6 +503,14 @@ void sync_supers(kdev_t dev) } } +/** + * get_super - get the superblock of a device + * @dev: device to get the super block for + * + * Scans the superblock list and finds the superblock of the file system + * mounted on the device given. NULL is returned if no match is found. + */ + struct super_block * get_super(kdev_t dev) { struct super_block * s; @@ -515,9 +555,15 @@ out: return err; } -/* - * Find a super_block with no device assigned. +/** + * get_empty_super - find empty superblocks + * + * Find a super_block with no device assigned. A free superblock is + * found and returned. If neccessary new superblocks are allocated. + * NULL is returned if there are insufficient resources to complete + * the request */ + struct super_block *get_empty_super(void) { struct super_block *s; @@ -848,7 +894,7 @@ int fs_may_mount(kdev_t dev) * Anyone using this new feature must know what he/she is doing. */ -int do_mount(struct block_device *bdev, const char *dev_name, +static int do_mount(struct block_device *bdev, const char *dev_name, const char *dir_name, const char * type, int flags, void * data) { kdev_t dev; @@ -879,12 +925,15 @@ int do_mount(struct block_device *bdev, const char *dev_name, /* * Do the lookup first to force automounting. */ - dir_d = namei(dir_name); + dir_d = lookup_dentry(dir_name, NULL, LOOKUP_FOLLOW); error = PTR_ERR(dir_d); if (IS_ERR(dir_d)) goto out; down(&mount_sem); + error = -ENOENT; + if (!dir_d->d_inode) + goto dput_and_out; error = -ENOTDIR; if (!S_ISDIR(dir_d->d_inode->i_mode)) goto dput_and_out; @@ -979,11 +1028,10 @@ static int do_remount_sb(struct super_block *sb, int flags, char *data) sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); /* - * Invalidate the inodes, as some mount options may be changed. - * N.B. If we are changing media, we should check the return - * from invalidate_inodes ... can't allow _any_ open files. + * We can't invalidate inodes as we can loose data when remounting + * (someone might manage to alter data while we are waiting in lock_super() + * or in foo_remount_fs())) */ - invalidate_inodes(sb); return 0; } @@ -993,23 +1041,25 @@ static int do_remount(const char *dir,int flags,char *data) struct dentry *dentry; int retval; - dentry = namei(dir); + dentry = lookup_dentry(dir, NULL, LOOKUP_FOLLOW); retval = PTR_ERR(dentry); if (!IS_ERR(dentry)) { - struct super_block * sb = dentry->d_inode->i_sb; - - retval = -ENODEV; - if (sb) { - retval = -EINVAL; - if (dentry == sb->s_root) { - /* - * Shrink the dcache and sync the device. - */ - shrink_dcache_sb(sb); - fsync_dev(sb->s_dev); - if (flags & MS_RDONLY) - acct_auto_close(sb->s_dev); - retval = do_remount_sb(sb, flags, data); + retval = -ENOENT; + if (dentry->d_inode) { + struct super_block * sb = dentry->d_inode->i_sb; + retval = -ENODEV; + if (sb) { + retval = -EINVAL; + if (dentry == sb->s_root) { + /* + * Shrink the dcache and sync the device. + */ + shrink_dcache_sb(sb); + fsync_dev(sb->s_dev); + if (flags & MS_RDONLY) + acct_auto_close(sb->s_dev); + retval = do_remount_sb(sb, flags, data); + } } } dput(dentry); @@ -1060,8 +1110,8 @@ static int copy_mount_options (const void * data, unsigned long *where) * aren't used, as the syscall assumes we are talking to an older * version that didn't understand them. */ -long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, - unsigned long new_flags, unsigned long data_page) +long do_sys_mount(char * dev_name, char * dir_name, char *type_page, + unsigned long new_flags, void *data_page) { struct file_system_type * fstype; struct dentry * dentry = NULL; @@ -1069,6 +1119,15 @@ long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, struct block_device *bdev = NULL; int retval; unsigned long flags = 0; + + /* Basic sanity checks */ + + if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) + return -EINVAL; + if (!type_page || !memchr(type_page, 0, PAGE_SIZE)) + return -EINVAL; + if (dev_name && !memchr(dev_name, 0, PAGE_SIZE)) + return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1081,7 +1140,7 @@ long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, goto out; } - fstype = get_fs_type((char *) type_page); + fstype = get_fs_type(type_page); retval = -ENODEV; if (!fstype) goto out; @@ -1089,12 +1148,18 @@ long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, if (fstype->fs_flags & FS_REQUIRES_DEV) { struct block_device_operations *bdops; - dentry = namei(dev_name); + retval = -EINVAL; + if (!dev_name || !*dev_name) + goto fs_out; + dentry = lookup_dentry(dev_name, NULL, LOOKUP_FOLLOW); retval = PTR_ERR(dentry); if (IS_ERR(dentry)) goto fs_out; + retval = -ENOENT; inode = dentry->d_inode; + if (!inode) + goto dput_and_out; retval = -ENOTBLK; if (!S_ISBLK(inode->i_mode)) goto dput_and_out; @@ -1112,7 +1177,7 @@ long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, flags = new_flags & ~MS_MGC_MSK; retval = do_mount(bdev, dev_name, dir_name, fstype->name, flags, - (void *) data_page); + data_page); dput_and_out: dput(dentry); @@ -1128,6 +1193,8 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, int retval; unsigned long data_page = 0; unsigned long type_page = 0; + unsigned long dev_page = 0; + char *dir_page; lock_kernel(); retval = copy_mount_options (type, &type_page); @@ -1144,12 +1211,24 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, goto out; } + dir_page = getname(dir_name); + retval = PTR_ERR(dir_page); + if (IS_ERR(dir_page)) + goto out1; + + retval = copy_mount_options (dev_name, &dev_page); + if (retval < 0) + goto out2; retval = copy_mount_options (data, &data_page); if (retval >= 0) { - retval = do_sys_mount(dev_name, dir_name, type_page, - new_flags, data_page); + retval = do_sys_mount((char*)dev_page,dir_page,(char*)type_page, + new_flags, (void*)data_page); free_page(data_page); } + free_page(dev_page); +out2: + putname(dir_page); +out1: free_page(type_page); out: unlock_kernel(); @@ -1160,7 +1239,7 @@ void __init mount_root(void) { struct file_system_type * fs_type; struct super_block * sb; - struct vfsmount *vfsmnt; + struct vfsmount *vfsmnt = NULL; struct block_device *bdev = NULL; mode_t mode; int retval; @@ -1184,7 +1263,9 @@ void __init mount_root(void) sb->s_dirt = 0; sb->s_type = fs_type; current->fs->root = dget(sb->s_root); + current->fs->rootmnt = mntget(vfsmnt); current->fs->pwd = dget(sb->s_root); + current->fs->pwdmnt = mntget(vfsmnt); ROOT_DEV = sb->s_dev; printk (KERN_NOTICE "VFS: Mounted root (NFS filesystem)%s.\n", (sb->s_flags & MS_RDONLY) ? " readonly" : ""); return; @@ -1296,7 +1377,9 @@ void __init mount_root(void) mount_it: sb->s_flags = root_mountflags; current->fs->root = dget(sb->s_root); + current->fs->rootmnt = mntget(vfsmnt); current->fs->pwd = dget(sb->s_root); + current->fs->pwdmnt = mntget(vfsmnt); printk ("VFS: Mounted root (%s filesystem)%s.\n", fs_type->name, (sb->s_flags & MS_RDONLY) ? " readonly" : ""); @@ -1319,22 +1402,28 @@ mount_it: static void chroot_fs_refs(struct dentry *old_root, - struct dentry *new_root) + struct vfsmount *old_rootmnt, + struct dentry *new_root, + struct vfsmount *new_rootmnt) { struct task_struct *p; read_lock(&tasklist_lock); for_each_task(p) { if (!p->fs) continue; - if (p->fs->root == old_root) { - dput(old_root); + if (p->fs->root == old_root && p->fs->rootmnt == old_rootmnt) { p->fs->root = dget(new_root); + p->fs->rootmnt = mntget(new_rootmnt); + mntput(old_rootmnt); + dput(old_root); printk(KERN_DEBUG "chroot_fs_refs: changed root of " "process %d\n",p->pid); } - if (p->fs->pwd == old_root) { - dput(old_root); + if (p->fs->pwd == old_root && p->fs->pwdmnt == old_rootmnt) { p->fs->pwd = dget(new_root); + p->fs->pwdmnt = mntget(new_rootmnt); + mntput(old_rootmnt); + dput(old_root); printk(KERN_DEBUG "chroot_fs_refs: changed cwd of " "process %d\n",p->pid); } @@ -1342,7 +1431,6 @@ static void chroot_fs_refs(struct dentry *old_root, read_unlock(&tasklist_lock); } - /* * Moves the current root to put_root, and sets root/cwd of all processes * which had them on the old root to new_root. @@ -1358,9 +1446,11 @@ static void chroot_fs_refs(struct dentry *old_root, asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) { struct dentry *root = current->fs->root; + struct vfsmount *root_mnt = current->fs->rootmnt; struct dentry *d_new_root, *d_put_old, *covered; struct dentry *root_dev_root, *new_root_dev_root; struct dentry *walk, *next; + struct vfsmount *new_root_mnt = NULL; int error; if (!capable(CAP_SYS_ADMIN)) @@ -1412,7 +1502,7 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old) root_dev_root = root->d_sb->s_root; root_dev_root->d_covers = dget(d_put_old); d_put_old->d_mounts = root_dev_root; - chroot_fs_refs(root,d_new_root); + chroot_fs_refs(root,root_mnt,d_new_root,new_root_mnt); error = 0; out2: up(&mount_sem); @@ -1442,7 +1532,7 @@ int __init change_root(kdev_t new_root_dev,const char *put_old) return -EBUSY; } /* First unmount devfs if mounted */ - dir_d = lookup_dentry ("/dev", NULL, 1); + dir_d = lookup_dentry ("/dev", NULL, LOOKUP_FOLLOW); if (!IS_ERR(dir_d)) { struct super_block *sb = dir_d->d_inode->i_sb; @@ -1465,7 +1555,7 @@ int __init change_root(kdev_t new_root_dev,const char *put_old) /* * Get the new mount directory */ - dir_d = lookup_dentry(put_old, NULL, 1); + dir_d = lookup_dentry(put_old, NULL, LOOKUP_FOLLOW); if (IS_ERR(dir_d)) { error = PTR_ERR(dir_d); } else if (!dir_d->d_inode) { diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c index 4550f44cfd6a..a65bfa150e6a 100644 --- a/fs/ufs/symlink.c +++ b/fs/ufs/symlink.c @@ -33,10 +33,10 @@ static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen) return vfs_readlink(dentry, buffer, buflen, s); } -static struct dentry *ufs_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags) +static struct dentry *ufs_follow_link(struct dentry *dentry, struct dentry *base, struct vfsmount **mnt, unsigned flags) { char *s = (char *)dentry->d_inode->u.ufs_i.i_u1.i_symlink; - return vfs_follow_link(dentry, base, flags, s); + return vfs_follow_link(dentry, base, mnt, flags, s); } struct inode_operations ufs_fast_symlink_inode_operations = { diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c index 18dd76572564..29eebb3f2d86 100644 --- a/fs/umsdos/dir.c +++ b/fs/umsdos/dir.c @@ -651,9 +651,7 @@ char * umsdos_d_path(struct dentry *dentry, char * buffer, int len) struct dentry * old_root = current->fs->root; char * path; - /* N.B. not safe -- fix this soon! */ - current->fs->root = dentry->d_sb->s_root; - path = d_path(dentry, buffer, len); + path = __d_path(dentry, NULL, dentry->d_sb->s_root, NULL, buffer, len); if (*path == '/') path++; /* skip leading '/' */ @@ -665,7 +663,6 @@ char * umsdos_d_path(struct dentry *dentry, char * buffer, int len) memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN); } - current->fs->root = old_root; return path; } diff --git a/include/asm-alpha/namei.h b/include/asm-alpha/namei.h index 644ec09902ca..5cc9bb39499d 100644 --- a/include/asm-alpha/namei.h +++ b/include/asm-alpha/namei.h @@ -12,7 +12,6 @@ * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* __ALPHA_NAMEI_H */ diff --git a/include/asm-arm/namei.h b/include/asm-arm/namei.h index 082f2c910e83..a402d3b9d0f7 100644 --- a/include/asm-arm/namei.h +++ b/include/asm-arm/namei.h @@ -12,51 +12,14 @@ #define ARM_BSD_EMUL "usr/gnemul/bsd/" -static inline struct dentry * -__arm_lookup_dentry(const char *name, int lookup_flags) +static inline char *__emul_prefix(void) { - struct dentry *base; - char *emul; - switch (current->personality) { case PER_BSD: - emul = ARM_BSD_EMUL; break; + return ARM_BSD_EMUL; default: return NULL; } - - base = lookup_dentry (emul, dget (current->fs->root), - (LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_SLASHOK)); - - if (IS_ERR (base)) return NULL; - - base = lookup_dentry (name, base, lookup_flags); - - if (IS_ERR (base)) return NULL; - - if (!base->d_inode) { - struct dentry *fromroot; - - fromroot = lookup_dentry (name, dget (current->fs->root), - lookup_flags); - - if (IS_ERR (fromroot)) return base; - - if (fromroot->d_inode) { - dput(base); - return fromroot; - } - - dput(fromroot); - } - - return base; } -#define __prefix_lookup_dentry(name, lookup_flags) \ - if (current->personality) { \ - dentry = __arm_lookup_dentry (name, lookup_flags); \ - if (dentry) return dentry; \ - } - #endif /* __ASMARM_NAMEI_H */ diff --git a/include/asm-i386/namei.h b/include/asm-i386/namei.h index 5708ffd8dd17..814865088617 100644 --- a/include/asm-i386/namei.h +++ b/include/asm-i386/namei.h @@ -12,7 +12,6 @@ * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* __I386_NAMEI_H */ diff --git a/include/asm-ia64/namei.h b/include/asm-ia64/namei.h index 74e195253d7e..0507e03dcfc9 100644 --- a/include/asm-ia64/namei.h +++ b/include/asm-ia64/namei.h @@ -11,7 +11,6 @@ * for /usr/gnemul/ emulation stuff. * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* _ASM_IA64_NAMEI_H */ diff --git a/include/asm-m68k/namei.h b/include/asm-m68k/namei.h index 7b4f02680998..f33f243b644a 100644 --- a/include/asm-m68k/namei.h +++ b/include/asm-m68k/namei.h @@ -12,7 +12,6 @@ * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif diff --git a/include/asm-mips/namei.h b/include/asm-mips/namei.h index 58ed80b0b946..eadf748e2982 100644 --- a/include/asm-mips/namei.h +++ b/include/asm-mips/namei.h @@ -13,42 +13,18 @@ /* Only one at this time. */ #define IRIX32_EMUL "usr/gnemul/irix/" -static inline struct dentry * -__mips_lookup_dentry(const char *name, int lookup_flags) -{ - struct dentry *base; +#ifdef CONFIG_BINFMT_IRIX +static inline char *__emul_prefix(void) +{ if (current->personality != PER_IRIX32) - return ERR_PTR(-ENOENT); - - base = lookup_dentry (IRIX32_EMUL, - dget (current->fs->root), - (LOOKUP_FOLLOW | LOOKUP_DIRECTORY)); - - if (IS_ERR (base)) return base; - - base = lookup_dentry (name, base, lookup_flags); - - if (IS_ERR (base)) return base; - - if (!base->d_inode) { - dput(base); - return ERR_PTR(-ENOENT); - } - - return base; + return NULL; + return IRIX32_EMUL; } -#ifdef CONFIG_BINFMT_IRIX - -#define __prefix_lookup_dentry(name, lookup_flags) \ - dentry = __mips_lookup_dentry (name, lookup_flags); \ - if (!IS_ERR (dentry)) return dentry; - #else /* !defined(CONFIG_BINFMT_IRIX) */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* !defined(CONFIG_BINFMT_IRIX) */ diff --git a/include/asm-mips64/namei.h b/include/asm-mips64/namei.h index 14a7043838ac..ac36b113cba2 100644 --- a/include/asm-mips64/namei.h +++ b/include/asm-mips64/namei.h @@ -13,7 +13,6 @@ * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* _ASM_NAMEI_H */ diff --git a/include/asm-ppc/namei.h b/include/asm-ppc/namei.h index 9e0268b03b97..cd871903de76 100644 --- a/include/asm-ppc/namei.h +++ b/include/asm-ppc/namei.h @@ -13,7 +13,6 @@ * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* __PPC_NAMEI_H */ diff --git a/include/asm-sh/namei.h b/include/asm-sh/namei.h index 582fc77e3671..a51522ac1f8b 100644 --- a/include/asm-sh/namei.h +++ b/include/asm-sh/namei.h @@ -12,7 +12,6 @@ * Look at asm-sparc/namei.h for details. */ -#define __prefix_lookup_dentry(name, lookup_flags) \ - do {} while (0) +#define __emul_prefix() NULL #endif /* __ASM_SH_NAMEI_H */ diff --git a/include/asm-sparc/namei.h b/include/asm-sparc/namei.h index 89cd1c3a968e..18430c8d1f65 100644 --- a/include/asm-sparc/namei.h +++ b/include/asm-sparc/namei.h @@ -11,53 +11,16 @@ #define SPARC_BSD_EMUL "usr/gnemul/sunos/" #define SPARC_SOL_EMUL "usr/gnemul/solaris/" -static inline struct dentry * -__sparc_lookup_dentry(const char *name, int lookup_flags) +static inline char * __emul_prefix(void) { - struct dentry *base; - char *emul; - switch (current->personality) { case PER_BSD: - emul = SPARC_BSD_EMUL; break; + return SPARC_BSD_EMUL; case PER_SVR4: - emul = SPARC_SOL_EMUL; break; + return SPARC_SOL_EMUL; default: return NULL; } - - base = lookup_dentry (emul, - dget (current->fs->root), - (LOOKUP_FOLLOW | LOOKUP_DIRECTORY)); - - if (IS_ERR (base)) return NULL; - - base = lookup_dentry (name, base, lookup_flags); - - if (IS_ERR (base)) return NULL; - - if (!base->d_inode) { - struct dentry *fromroot; - - fromroot = lookup_dentry (name, dget (current->fs->root), lookup_flags); - - if (IS_ERR (fromroot)) return base; - - if (fromroot->d_inode) { - dput(base); - return fromroot; - } - - dput(fromroot); - } - - return base; } -#define __prefix_lookup_dentry(name, lookup_flags) \ - if (current->personality) { \ - dentry = __sparc_lookup_dentry (name, lookup_flags); \ - if (dentry) return dentry; \ - } - #endif /* __SPARC_NAMEI_H */ diff --git a/include/asm-sparc64/namei.h b/include/asm-sparc64/namei.h index d3d57545c186..7f6dd9495f03 100644 --- a/include/asm-sparc64/namei.h +++ b/include/asm-sparc64/namei.h @@ -11,53 +11,16 @@ #define SPARC_BSD_EMUL "usr/gnemul/sunos/" #define SPARC_SOL_EMUL "usr/gnemul/solaris/" -static inline struct dentry * -__sparc64_lookup_dentry(const char *name, int lookup_flags) +static inline char * __emul_prefix(void) { - struct dentry *base; - char *emul; - switch (current->personality) { case PER_BSD: - emul = SPARC_BSD_EMUL; break; + return SPARC_BSD_EMUL; case PER_SVR4: - emul = SPARC_SOL_EMUL; break; + return SPARC_SOL_EMUL; default: return NULL; } - - base = lookup_dentry (emul, - dget (current->fs->root), - (LOOKUP_FOLLOW | LOOKUP_DIRECTORY)); - - if (IS_ERR (base)) return NULL; - - base = lookup_dentry (name, base, lookup_flags); - - if (IS_ERR (base)) return NULL; - - if (!base->d_inode) { - struct dentry *fromroot; - - fromroot = lookup_dentry (name, dget (current->fs->root), lookup_flags); - - if (IS_ERR (fromroot)) return base; - - if (fromroot->d_inode) { - dput(base); - return fromroot; - } - - dput(fromroot); - } - - return base; } -#define __prefix_lookup_dentry(name, lookup_flags) \ - if (current->personality) { \ - dentry = __sparc64_lookup_dentry (name, lookup_flags); \ - if (dentry) return dentry; \ - } - #endif /* __SPARC64_NAMEI_H */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 4cc4c56ced46..f28b3bd9ec3e 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -1,6 +1,9 @@ #ifndef __LINUX_DCACHE_H #define __LINUX_DCACHE_H +#include +#include + #ifdef __KERNEL__ /* @@ -105,7 +108,10 @@ struct dentry_operations { * s_nfsd_free_path semaphore will be down */ -/* +/** + * d_drop - drop a dentry + * @dentry: dentry to drop + * * d_drop() unhashes the entry from the parent * dentry hashes, so that it won't be found through * a VFS lookup any more. Note that this is different @@ -118,6 +124,7 @@ struct dentry_operations { * to invalidate a dentry for some reason (NFS * timeouts or autofs deletes). */ + static __inline__ void d_drop(struct dentry * dentry) { list_del(&dentry->d_hash); @@ -164,10 +171,16 @@ extern int have_submounts(struct dentry *); * This adds the entry to the hash queues. */ extern void d_rehash(struct dentry *); -/* + +/** + * d_add - add dentry to hash queues + * @entry: dentry to add + * @inode: The inode to attach to this dentry + * * This adds the entry to the hash queues and initializes "d_inode". * The entry was actually filled in earlier during "d_alloc()" */ + static __inline__ void d_add(struct dentry * entry, struct inode * inode) { d_rehash(entry); @@ -183,10 +196,24 @@ extern struct dentry * d_lookup(struct dentry *, struct qstr *); /* validate "insecure" dentry pointer */ extern int d_validate(struct dentry *, struct dentry *, unsigned int, unsigned int); +extern char * __d_path(struct dentry *, struct vfsmount *, struct dentry *, + struct vfsmount *, char *, int); /* write full pathname into buffer and return start of pathname */ -extern char * d_path(struct dentry *, char *, int); - +#define d_path(dentry, vfsmnt, buffer, buflen) \ + __d_path(dentry, vfsmnt, current->fs->root, current->fs->rootmnt, \ + buffer, buflen) + /* Allocation counts.. */ + +/** + * dget - get a reference to a dentry + * @dentry: dentry to get a reference too + * + * Given a dentry or NULL pointer increment the reference count + * if appropriate and return the dentry. A dentry will not be + * destroyed when it has references. + */ + static __inline__ struct dentry * dget(struct dentry *dentry) { if (dentry) @@ -194,6 +221,13 @@ static __inline__ struct dentry * dget(struct dentry *dentry) return dentry; } +/** + * d_unhashed - is dentry hashed + * @dentry: entry to check + * + * Returns true if the dentry passed is not currently hashed + */ + static __inline__ int d_unhashed(struct dentry *dentry) { return list_empty(&dentry->d_hash); @@ -201,6 +235,13 @@ static __inline__ int d_unhashed(struct dentry *dentry) extern void dput(struct dentry *); +/* MOUNT_REWRITE: replace with the check for d_vfsmnt */ +static __inline__ int d_mountpoint(struct dentry *dentry) +{ + return dentry != dentry->d_mounts; +} + + #endif /* __KERNEL__ */ #endif /* __LINUX_DCACHE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index d9ed0a1ab2ac..63fde2f0ca5f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -455,6 +455,7 @@ struct fown_struct { struct file { struct list_head f_list; struct dentry *f_dentry; + struct vfsmount *f_vfsmnt; struct file_operations *f_op; atomic_t f_count; unsigned int f_flags; @@ -506,16 +507,24 @@ struct file_lock { struct file *fl_file; unsigned char fl_flags; unsigned char fl_type; - off_t fl_start; - off_t fl_end; + loff_t fl_start; + loff_t fl_end; void (*fl_notify)(struct file_lock *); /* unblock callback */ + void (*fl_insert)(struct file_lock *); /* lock insertion callback */ + void (*fl_remove)(struct file_lock *); /* lock removal callback */ union { struct nfs_lock_info nfs_fl; } fl_u; }; +/* The following constant reflects the upper bound of the file/locking space */ +#ifndef OFFSET_MAX +#define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1))) +#define OFFSET_MAX INT_LIMIT(loff_t) +#endif + extern struct file_lock *file_lock_table; #include @@ -542,6 +551,26 @@ struct fasync_struct { extern int fasync_helper(int, struct file *, int, struct fasync_struct **); +#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ +#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ + +struct quota_mount_options +{ + unsigned int flags; /* Flags for diskquotas on this device */ + struct semaphore dqio_sem; /* lock device while I/O in progress */ + struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */ + struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ + time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */ + time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */ + char rsquash[MAXQUOTAS]; /* for quotas threat root as any other user */ +}; + +/* + * Umount options + */ + +#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ + #include #include #include @@ -684,7 +713,7 @@ struct inode_operations { int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *); int (*readlink) (struct dentry *, char *,int); - struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int); + struct dentry * (*follow_link) (struct dentry *, struct dentry *, struct vfsmount **, unsigned int); void (*truncate) (struct inode *); int (*permission) (struct inode *, int); int (*revalidate) (struct dentry *); @@ -808,10 +837,13 @@ extern int do_truncate(struct dentry *, loff_t start); extern int get_unused_fd(void); extern void put_unused_fd(unsigned int); -extern struct file *filp_open(const char *, int, int, struct dentry *); -extern struct file *dentry_open(struct dentry *, int); +extern struct file *__filp_open(const char *, int, int, struct dentry *, struct vfsmount *); +extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); +static inline struct file *filp_open(const char *name, int flags, int mode) +{ + return __filp_open(name, flags, mode, NULL, NULL); +} extern int filp_close(struct file *, fl_owner_t id); - extern char * getname(const char *); #define __getname() ((char *) __get_free_page(GFP_KERNEL)) #define putname(name) free_page((unsigned long)(name)) @@ -926,13 +958,8 @@ extern int get_write_access(struct inode *); extern void put_write_access(struct inode *); extern struct dentry * do_mknod(const char *, int, dev_t); extern int do_pipe(int *); -extern int do_unlink(const char * name, struct dentry *); -extern struct dentry * __open_namei(const char *, int, int, struct dentry *); -static inline struct dentry * open_namei(const char *pathname) -{ - return __open_namei(pathname, 0, 0, NULL); -} +extern struct dentry * open_namei(const char *, int, int, struct dentry *, struct vfsmount **); extern int kernel_read(struct file *, unsigned long, char *, unsigned long); extern struct file * open_exec(const char *); @@ -1058,9 +1085,9 @@ extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *); extern struct file_operations generic_ro_fops; extern int vfs_readlink(struct dentry *, char *, int, const char *); -extern struct dentry *vfs_follow_link(struct dentry *, struct dentry *, unsigned, const char *); +extern struct dentry *vfs_follow_link(struct dentry *, struct dentry *, struct vfsmount **, unsigned, const char *); extern int page_readlink(struct dentry *, char *, int); -extern struct dentry *page_follow_link(struct dentry *, struct dentry *, unsigned); +extern struct dentry *page_follow_link(struct dentry *, struct dentry *, struct vfsmount **, unsigned); extern struct inode_operations page_symlink_inode_operations; extern int vfs_readdir(struct file *, filldir_t, void *); diff --git a/include/linux/ibmtr.h b/include/linux/ibmtr.h new file mode 100644 index 000000000000..3e341078b0eb --- /dev/null +++ b/include/linux/ibmtr.h @@ -0,0 +1,454 @@ +/* Definitions for an IBM Token Ring card. */ +/* This file is distributed under the GNU GPL */ + +/* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */ + +#define TR_RETRY_INTERVAL (5*HZ) /* 500 on PC = 5 s */ +#define TR_RESET_INTERVAL (HZ/20) /* 5 on PC = 50 ms */ +#define TR_BUSY_INTERVAL (HZ/5) /* 5 on PC = 200 ms */ +#define TR_SPIN_INTERVAL (3*HZ) /* 3 seconds before init timeout */ +#define TR_RETRIES 6 /* number of open retries */ + +#define TR_ISA 1 +#define TR_MCA 2 +#define TR_ISAPNP 3 +#define NOTOK 0 +#define TOKDEBUG 1 + +#define IBMTR_SHARED_RAM_SIZE 0x10000 +#define IBMTR_IO_EXTENT 4 +#define IBMTR_MAX_ADAPTERS 2 + +#define CHANNEL_ID 0X1F30 +#define AIP 0X1F00 +#define AIPCHKSUM1 0X1F60 +#define AIPCHKSUM2 0X1FF0 +#define AIPADAPTYPE 0X1FA0 +#define AIPDATARATE 0X1FA2 +#define AIPEARLYTOKEN 0X1FA4 +#define AIPAVAILSHRAM 0X1FA6 +#define AIPSHRAMPAGE 0X1FA8 +#define AIP4MBDHB 0X1FAA +#define AIP16MBDHB 0X1FAC +#define AIPFID 0X1FBA + +/* Note, 0xA20 == 0x220 since motherboard decodes 10 bits. I left everything + the way my documentation had it, ie: 0x0A20. */ +#define ADAPTINTCNTRL 0x02f0 /* Adapter interrupt control */ +#define ADAPTRESET 0x1 /* Control Adapter reset (add to base) */ +#define ADAPTRESETREL 0x2 /* Release Adapter from reset ( """) */ +#define ADAPTINTREL 0x3 /* Adapter interrupt release */ + +#define MMIOStartLocP 0x0a20 /* Primary adapter's starting MMIO area */ +#define MMIOStartLocA 0x0a24 /* Alternate adapter's starting MMIO area */ + +#define GLOBAL_INT_ENABLE 0x02f0 + +/* MMIO bits 0-4 select register */ +#define RRR_EVEN 0x00 /* Shared RAM relocation registers - even and odd */ +/* Used to set the starting address of shared RAM */ +/* Bits 1 through 7 of this register map to bits 13 through 19 of the shared RAM address.*/ +/* ie: 0x02 sets RAM address to ...ato! issy su wazzoo !! GODZILLA!!! */ +#define RRR_ODD 0x01 +/* Bits 2 and 3 of this register can be read to determine shared RAM size */ +/* 00 for 8k, 01 for 16k, 10 for 32k, 11 for 64k */ +#define WRBR_EVEN 0x02 /* Write region base registers - even and odd */ +#define WRBR_ODD 0x03 +#define WWOR_EVEN 0x04 /* Write window open registers - even and odd */ +#define WWOR_ODD 0x05 +#define WWCR_EVEN 0x06 /* Write window close registers - even and odd */ +#define WWCR_ODD 0x07 + +/* Interrupt status registers - PC system - even and odd */ +#define ISRP_EVEN 0x08 + +#define TCR_INT 0x10 /* Bit 4 - Timer interrupt. The TVR_EVEN timer has + expired. */ +#define ERR_INT 0x08 /* Bit 3 - Error interrupt. The adapter has had an + internal error. */ +#define ACCESS_INT 0x04 /* Bit 2 - Access interrupt. You have attempted to + write to an invalid area of shared RAM or an invalid + register within the MMIO. */ +/* In addition, the following bits within ISRP_EVEN can be turned on or off by you */ +/* to control the interrupt processing: */ +#define INT_IRQ 0x80 /* Bit 7 - If 0 the adapter will issue a CHCK, if 1 and + IRQ. This should normally be set (by you) to 1. */ +#define INT_ENABLE 0x40 /* Bit 6 - Interrupt enable. If 0, no interrupts will + occur. If 1, interrupts will occur normally. + Normally set to 1. */ +/* Bit 0 - Primary or alternate adapter. Set to zero if this adapter is the primary adapter,*/ +/* 1 if this adapter is the alternate adapter. */ + + +#define ISRP_ODD 0x09 + +#define ADAP_CHK_INT 0x40 /* Bit 6 - Adapter check. the adapter has + encountered a serious problem and has closed + itself. Whoa. */ +#define SRB_RESP_INT 0x20 /* Bit 5 - SRB response. The adapter has accepted + an SRB request and set the return code within + the SRB. */ +#define ASB_FREE_INT 0x10 /* Bit 4 - ASB free. The adapter has read the ASB + and this area can be safely reused. This interrupt + is only used if your application has set the ASB + free request bit in ISRA_ODD or if an error was + detected in your response. */ +#define ARB_CMD_INT 0x08 /* Bit 3 - ARB command. The adapter has given you a + command for action. The command is located in the + ARB area of shared memory. */ +#define SSB_RESP_INT 0x04 /* Bit 2 - SSB response. The adapter has posted a + response to your SRB (the response is located in + the SSB area of shared memory). */ +/* Bit 1 - Bridge frame forward complete. */ + + + +#define ISRA_EVEN 0x0A /* Interrupt status registers - adapter - even and odd */ +/* Bit 7 - Internal parity error (on adapter's internal bus) */ +/* Bit 6 - Timer interrupt pending */ +/* Bit 5 - Access interrupt (attempt by adapter to access illegal address) */ +/* Bit 4 - Adapter microcode problem (microcode dead-man timer expired) */ +/* Bit 3 - Adapter processor check status */ +/* Bit 2 - Reserved */ +/* Bit 1 - Adapter hardware interrupt mask (prevents internal interrupts) */ +/* Bit 0 - Adapter software interrupt mask (prevents internal software interrupts) */ + +#define ISRA_ODD 0x0B +#define CMD_IN_SRB 0x20 /* Bit 5 - Indicates that you have placed a new + command in the SRB and are ready for the adapter to + process the command. */ +#define RESP_IN_ASB 0x10 /* Bit 4 - Indicates that you have placed a response + (an ASB) in the shared RAM which is available for + the adapter's use. */ +/* Bit 3 - Indicates that you are ready to put an SRB in the shared RAM, but that a previous */ +/* command is still pending. The adapter will then interrupt you when the previous */ +/* command is completed */ +/* Bit 2 - Indicates that you are ready to put an ASB in the shared RAM, but that a previous */ +/* ASB is still pending. The adapter will then interrupt you when the previous ASB */ +/* is copied. */ +#define ARB_FREE 0x2 +#define SSB_FREE 0x1 + +#define TCR_EVEN 0x0C /* Timer control registers - even and odd */ +#define TCR_ODD 0x0D +#define TVR_EVEN 0x0E /* Timer value registers - even and odd */ +#define TVR_ODD 0x0F +#define SRPR_EVEN 0x18 /* Shared RAM paging registers - even and odd */ +#define SRPR_ENABLE_PAGING 0xc0 +#define SRPR_ODD 0x19 /* Not used. */ +#define TOKREAD 0x60 +#define TOKOR 0x40 +#define TOKAND 0x20 +#define TOKWRITE 0x00 + +/* MMIO bits 5-6 select operation */ +/* 00 is used to write to a register */ +/* 01 is used to bitwise AND a byte with a register */ +/* 10 is used to bitwise OR a byte with a register */ +/* 11 is used to read from a register */ + +/* MMIO bits 7-8 select area of interest.. see below */ +/* 00 selects attachment control area. */ +/* 01 is reserved. */ +/* 10 selects adapter identification area A containing the adapter encoded address. */ +/* 11 selects the adapter identification area B containing test patterns. */ + +#define PCCHANNELID 5049434F3631313039393020 +#define MCCHANNELID 4D4152533633583435313820 + +#define ACA_OFFSET 0x1e00 +#define ACA_SET 0x40 +#define ACA_RESET 0x20 +#define ACA_RW 0x00 + +#ifdef ENABLE_PAGING +#define SET_PAGE(x) (isa_writeb((x), \ + ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN)) +#else +#define SET_PAGE(x) +#endif + +typedef enum { IN_PROGRESS, SUCCESS, FAILURE, CLOSED } open_state; + +/* do_tok_int possible values */ +#define FIRST_INT 1 +#define NOT_FIRST 2 + +struct tok_info { + unsigned char irq; + __u32 mmio; + unsigned char hw_address[32]; + unsigned char adapter_type; + unsigned char data_rate; + unsigned char token_release; + unsigned char avail_shared_ram; + unsigned char shared_ram_paging; + unsigned short dhb_size4mb; + unsigned short rbuf_len4; + unsigned short rbuf_cnt4; + unsigned short maxmtu4; + unsigned short dhb_size16mb; + unsigned short rbuf_len16; + unsigned short rbuf_cnt16; + unsigned short maxmtu16; + /* Additions by David Morris */ + unsigned char do_tok_int; + wait_queue_head_t wait_for_tok_int; + wait_queue_head_t wait_for_reset; + unsigned char sram_base; + /* Additions by Peter De Schrijver */ + unsigned char page_mask; /* mask to select RAM page to Map*/ + unsigned char mapped_ram_size; /* size of RAM page */ + __u32 sram; /* Shared memory base address */ + __u32 init_srb; /* Initial System Request Block address */ + __u32 srb; /* System Request Block address */ + __u32 ssb; /* System Status Block address */ + __u32 arb; /* Adapter Request Block address */ + __u32 asb; /* Adapter Status Block address */ + __u8 init_srb_page; + __u8 srb_page; + __u8 ssb_page; + __u8 arb_page; + __u8 asb_page; + unsigned short exsap_station_id; + unsigned short global_int_enable; + struct sk_buff *current_skb; + struct net_device_stats tr_stats; + unsigned char auto_ringspeedsave; + open_state open_status; + unsigned char readlog_pending; + unsigned short adapter_int_enable; /* Adapter-specific int enable */ + struct timer_list tr_timer; + unsigned char ring_speed; + __u32 func_addr; + unsigned int retry_count; + spinlock_t lock; /* SMP protection */ +}; + +/* token ring adapter commands */ +#define DIR_INTERRUPT 0x00 /* struct srb_interrupt */ +#define DIR_MOD_OPEN_PARAMS 0x01 +#define DIR_OPEN_ADAPTER 0x03 /* struct dir_open_adapter */ +#define DIR_CLOSE_ADAPTER 0x04 +#define DIR_SET_GRP_ADDR 0x06 +#define DIR_SET_FUNC_ADDR 0x07 /* struct srb_set_funct_addr */ +#define DIR_READ_LOG 0x08 /* struct srb_read_log */ +#define DLC_OPEN_SAP 0x15 /* struct dlc_open_sap */ +#define DLC_CLOSE_SAP 0x16 +#define DATA_LOST 0x20 /* struct asb_rec */ +#define REC_DATA 0x81 /* struct arb_rec_req */ +#define XMIT_DATA_REQ 0x82 /* struct arb_xmit_req */ +#define DLC_STATUS 0x83 /* struct arb_dlc_status */ +#define RING_STAT_CHANGE 0x84 /* struct dlc_open_sap ??? */ + +/* DIR_OPEN_ADAPTER options */ +#define OPEN_PASS_BCON_MAC 0x0100 +#define NUM_RCV_BUF 2 +#define RCV_BUF_LEN 1024 +#define DHB_LENGTH 2048 +#define NUM_DHB 2 +#define DLC_MAX_SAP 2 +#define DLC_MAX_STA 1 + +/* DLC_OPEN_SAP options */ +#define MAX_I_FIELD 0x0088 +#define SAP_OPEN_IND_SAP 0x04 +#define SAP_OPEN_PRIORITY 0x20 +#define SAP_OPEN_STATION_CNT 0x1 +#define XMIT_DIR_FRAME 0x0A +#define XMIT_UI_FRAME 0x0d +#define XMIT_XID_CMD 0x0e +#define XMIT_TEST_CMD 0x11 + +/* srb close return code */ +#define SIGNAL_LOSS 0x8000 +#define HARD_ERROR 0x4000 +#define XMIT_BEACON 0x1000 +#define LOBE_FAULT 0x0800 +#define AUTO_REMOVAL 0x0400 +#define REMOVE_RECV 0x0100 +#define LOG_OVERFLOW 0x0080 +#define RING_RECOVER 0x0020 + +struct srb_init_response { + unsigned char command; + unsigned char init_status; + unsigned char init_status_2; + unsigned char reserved[3]; + __u16 bring_up_code; + __u16 encoded_address; + __u16 level_address; + __u16 adapter_address; + __u16 parms_address; + __u16 mac_address; +}; + +struct dir_open_adapter { + unsigned char command; + char reserved[7]; + __u16 open_options; + unsigned char node_address[6]; + unsigned char group_address[4]; + unsigned char funct_address[4]; + __u16 num_rcv_buf; + __u16 rcv_buf_len; + __u16 dhb_length; + unsigned char num_dhb; + char reserved2; + unsigned char dlc_max_sap; + unsigned char dlc_max_sta; + unsigned char dlc_max_gsap; + unsigned char dlc_max_gmem; + unsigned char dlc_t1_tick_1; + unsigned char dlc_t2_tick_1; + unsigned char dlc_ti_tick_1; + unsigned char dlc_t1_tick_2; + unsigned char dlc_t2_tick_2; + unsigned char dlc_ti_tick_2; + unsigned char product_id[18]; +}; + +struct srb_open_response { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2[3]; + __u16 error_code; + __u16 asb_addr; + __u16 srb_addr; + __u16 arb_addr; + __u16 ssb_addr; +}; + +struct dlc_open_sap { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2; + __u16 station_id; + unsigned char timer_t1; + unsigned char timer_t2; + unsigned char timer_ti; + unsigned char maxout; + unsigned char maxin; + unsigned char maxout_incr; + unsigned char max_retry_count; + unsigned char gsap_max_mem; + __u16 max_i_field; + unsigned char sap_value; + unsigned char sap_options; + unsigned char station_count; + unsigned char sap_gsap_mem; + unsigned char gsap[0]; +}; + +struct srb_xmit { + unsigned char command; + unsigned char cmd_corr; + unsigned char ret_code; + unsigned char reserved1; + __u16 station_id; +}; + +struct srb_interrupt { + unsigned char command; + unsigned char cmd_corr; + unsigned char ret_code; +}; + +struct srb_read_log { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2; + unsigned char line_errors; + unsigned char internal_errors; + unsigned char burst_errors; + unsigned char A_C_errors; + unsigned char abort_delimiters; + unsigned char reserved3; + unsigned char lost_frames; + unsigned char recv_congest_count; + unsigned char frame_copied_errors; + unsigned char frequency_errors; + unsigned char token_errors; +}; + +struct asb_xmit_resp { + unsigned char command; + unsigned char cmd_corr; + unsigned char ret_code; + unsigned char reserved; + __u16 station_id; + __u16 frame_length; + unsigned char hdr_length; + unsigned char rsap_value; +}; + +struct arb_xmit_req { + unsigned char command; + unsigned char cmd_corr; + unsigned char reserved1[2]; + __u16 station_id; + __u16 dhb_address; +}; + +struct arb_rec_req { + unsigned char command; + unsigned char reserved1[3]; + __u16 station_id; + __u16 rec_buf_addr; + unsigned char lan_hdr_len; + unsigned char dlc_hdr_len; + __u16 frame_len; + unsigned char msg_type; +}; + +struct asb_rec { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2; + __u16 station_id; + __u16 rec_buf_addr; +}; + +struct rec_buf { + /* unsigned char reserved1[2]; */ + __u16 buf_ptr; + unsigned char reserved2; + __u16 buf_len; + unsigned char data[0]; +}; + +struct arb_dlc_status { + unsigned char command; + unsigned char reserved1[3]; + __u16 station_id; + __u16 status; + unsigned char frmr_data[5]; + unsigned char access_prio; + unsigned char rem_addr[TR_ALEN]; + unsigned char rsap_value; +}; + +struct arb_ring_stat_change { + unsigned char command; + unsigned char reserved1[5]; + __u16 ring_status; +}; + +struct srb_close_adapter { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; +}; + +struct srb_set_funct_addr { + unsigned char command; + unsigned char reserved1; + unsigned char ret_code; + unsigned char reserved2[3]; + unsigned char funct_address[4]; +}; + diff --git a/include/linux/input.h b/include/linux/input.h index 07d16988bd49..25c0c3f9cce3 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -46,6 +46,32 @@ struct input_event { unsigned int value; }; +/* + * The device ID structure; + */ + +struct input_id { + __u16 bus; + __u16 vendor; + __u16 product; +}; + +/* + * Protocol version. + */ + +#define EV_VERSION 0x010000 + +/* + * IOCTLs (0x00 - 0x7f) + */ + +#define EVIOCGVERSION _IOR('E', 0x01, __u32) /* get driver version */ +#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ +#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x03, len) /* get device name */ +#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + ev, len) /* get event bits */ +#define EVIOCGABSLIM(num) _IOR('E', 0x40 + num, 4 * sizeof(int)) /* get abs event limits */ + /* * Event types */ @@ -394,6 +420,8 @@ struct input_dev { void *private; int number; + char *name; + struct input_id id; unsigned long evbit[NBITS(EV_MAX)]; unsigned long keybit[NBITS(KEY_MAX)]; diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index d949bd649334..694046eaa215 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -146,12 +146,14 @@ struct nlm_host * nlm_lookup_host(struct svc_client *, struct sockaddr_in *, int, int); struct rpc_clnt * nlm_bind_host(struct nlm_host *); void nlm_rebind_host(struct nlm_host *); +struct nlm_host * nlm_get_host(struct nlm_host *); void nlm_release_host(struct nlm_host *); void nlm_shutdown_hosts(void); /* * Server-side lock handling */ +int nlmsvc_async_call(struct nlm_rqst *, u32, rpc_action); u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, struct nlm_lock *, int, struct nlm_cookie *); u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); diff --git a/include/linux/lockd/nlm.h b/include/linux/lockd/nlm.h index 4bc44e7d9aba..e22388d5097b 100644 --- a/include/linux/lockd/nlm.h +++ b/include/linux/lockd/nlm.h @@ -12,11 +12,8 @@ #include /* Maximum file offset in file_lock.fl_end */ -#ifdef OFFSET_MAX -# define NLM_OFFSET_MAX OFFSET_MAX -#else -# define NLM_OFFSET_MAX ((off_t) 0x7fffffff) -#endif +# define NLM_OFFSET_MAX ((s32) 0x7fffffff) +# define NLM4_OFFSET_MAX ((s64) ((~(u64)0) >> 1)) /* Return states for NLM */ enum { diff --git a/include/linux/mount.h b/include/linux/mount.h index c2dcfe93fb5f..547163d2e97f 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -11,20 +11,6 @@ #ifndef _LINUX_MOUNT_H #define _LINUX_MOUNT_H -#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ -#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ - -struct quota_mount_options -{ - unsigned int flags; /* Flags for diskquotas on this device */ - struct semaphore dqio_sem; /* lock device while I/O in progress */ - struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */ - struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ - time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */ - time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */ - char rsquash[MAXQUOTAS]; /* for quotas threat root as any other user */ -}; - struct vfsmount { kdev_t mnt_dev; /* Device this applies to */ @@ -34,10 +20,14 @@ struct vfsmount struct vfsmount *mnt_next; /* pointer to next in linkedlist */ }; -/* - * Umount options - */ - -#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ +/* MOUNT_REWRITE: fill these */ +static inline struct vfsmount *mntget(struct vfsmount *mnt) +{ + return mnt; +} + +static inline void mntput(struct vfsmount *mnt) +{ +} #endif /* _LINUX_MOUNT_H */ diff --git a/include/linux/nfs.h b/include/linux/nfs.h index 0046415a172d..aa36f7bd3927 100644 --- a/include/linux/nfs.h +++ b/include/linux/nfs.h @@ -9,6 +9,7 @@ #include +#define NFS_PROGRAM 100003 #define NFS_PORT 2049 #define NFS_MAXDATA 8192 #define NFS_MAXPATHLEN 1024 @@ -26,7 +27,9 @@ #define NFSMODE_SOCK 0140000 #define NFSMODE_FIFO 0010000 - +#define NFS_MNT_PROGRAM 100005 +#define NFS_MNT_PORT 627 + /* * NFS stats. The good thing with these values is that NFSv3 errors are * a superset of NFSv2 errors (with the exception of NFSERR_WFLUSH which @@ -84,51 +87,22 @@ enum nfs_ftype { NFFIFO = 8 }; +#if defined(__KERNEL__) +/* + * This is the kernel NFS client file handle representation + */ +#define NFS_MAXFHSIZE 64 struct nfs_fh { - char data[NFS_FHSIZE]; + unsigned short size; + unsigned char data[NFS_MAXFHSIZE]; }; -#define NFS_PROGRAM 100003 -#define NFS_VERSION 2 -#define NFSPROC_NULL 0 -#define NFSPROC_GETATTR 1 -#define NFSPROC_SETATTR 2 -#define NFSPROC_ROOT 3 -#define NFSPROC_LOOKUP 4 -#define NFSPROC_READLINK 5 -#define NFSPROC_READ 6 -#define NFSPROC_WRITECACHE 7 -#define NFSPROC_WRITE 8 -#define NFSPROC_CREATE 9 -#define NFSPROC_REMOVE 10 -#define NFSPROC_RENAME 11 -#define NFSPROC_LINK 12 -#define NFSPROC_SYMLINK 13 -#define NFSPROC_MKDIR 14 -#define NFSPROC_RMDIR 15 -#define NFSPROC_READDIR 16 -#define NFSPROC_STATFS 17 - -/* Mount support for NFSroot */ -#ifdef __KERNEL__ -#define NFS_MNT_PROGRAM 100005 -#define NFS_MNT_VERSION 1 -#define NFS_MNT_PORT 627 -#define NFS_MNTPROC_MNT 1 -#define NFS_MNTPROC_UMNT 3 - /* * This is really a general kernel constant, but since nothing like * this is defined in the kernel headers, I have to do it here. */ #define NFS_OFFSET_MAX ((__s64)((~(__u64)0) >> 1)) -#endif /* __KERNEL__ */ - -#if defined(__KERNEL__) - -extern struct rpc_program nfs_program; -extern struct rpc_stat nfs_rpcstat; enum nfs3_stable_how { NFS_UNSTABLE = 0, @@ -136,6 +110,4 @@ enum nfs3_stable_how { NFS_FILE_SYNC = 2 }; #endif /* __KERNEL__ */ - - -#endif +#endif /* _LINUX_NFS_H */ diff --git a/include/linux/nfs2.h b/include/linux/nfs2.h index f4cb41c4cb32..0ed9517138fc 100644 --- a/include/linux/nfs2.h +++ b/include/linux/nfs2.h @@ -22,5 +22,53 @@ #define NFS2MODE_LNK 0120000 #define NFS2MODE_SOCK 0140000 #define NFS2MODE_FIFO 0010000 - -#endif + + +/* NFSv2 file types - beware, these are not the same in NFSv3 */ +enum nfs2_ftype { + NF2NON = 0, + NF2REG = 1, + NF2DIR = 2, + NF2BLK = 3, + NF2CHR = 4, + NF2LNK = 5, + NF2SOCK = 6, + NF2BAD = 7, + NF2FIFO = 8 +}; + +struct nfs2_fh { + char data[NFS2_FHSIZE]; +}; + +/* + * Procedure numbers for NFSv2 + */ +#define NFS2_VERSION 2 +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_ROOT 3 +#define NFSPROC_LOOKUP 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITECACHE 7 +#define NFSPROC_WRITE 8 +#define NFSPROC_CREATE 9 +#define NFSPROC_REMOVE 10 +#define NFSPROC_RENAME 11 +#define NFSPROC_LINK 12 +#define NFSPROC_SYMLINK 13 +#define NFSPROC_MKDIR 14 +#define NFSPROC_RMDIR 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_STATFS 17 + +#define NFS_MNT_PROGRAM 100005 +#define NFS_MNT_VERSION 1 +#define MNTPROC_NULL 0 +#define MNTPROC_MNT 1 +#define MNTPROC_UMNT 3 +#define MNTPROC_UMNTALL 4 + +#endif /* _LINUX_NFS2_H */ diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h index 9df817e30586..1f45a9296488 100644 --- a/include/linux/nfs3.h +++ b/include/linux/nfs3.h @@ -95,128 +95,5 @@ enum nfs3_ftype { /* Number of 32bit words in post_op_attr */ #define NFS3_POST_OP_ATTR_WORDS 22 -#ifdef NFS_NEED_NFS3_XDR_TYPES - -struct nfs3_sattrargs { - struct nfs_fh * fh; - struct iattr * sattr; - unsigned int guard; - __u64 guardtime; -}; - -struct nfs3_diropargs { - struct nfs_fh * fh; - const char * name; - int len; -}; - -struct nfs3_accessargs { - struct nfs_fh * fh; - __u32 access; -}; - -struct nfs3_createargs { - struct nfs_fh * fh; - const char * name; - int len; - struct iattr * sattr; - enum nfs3_createmode createmode; - __u32 verifier[2]; -}; - -struct nfs3_mkdirargs { - struct nfs_fh * fh; - const char * name; - int len; - struct iattr * sattr; -}; - -struct nfs3_symlinkargs { - struct nfs_fh * fromfh; - const char * fromname; - int fromlen; - const char * topath; - int tolen; - struct iattr * sattr; -}; - -struct nfs3_mknodargs { - struct nfs_fh * fh; - const char * name; - int len; - enum nfs3_ftype type; - struct iattr * sattr; - dev_t rdev; -}; - -struct nfs3_renameargs { - struct nfs_fh * fromfh; - const char * fromname; - int fromlen; - struct nfs_fh * tofh; - const char * toname; - int tolen; -}; - -struct nfs3_linkargs { - struct nfs_fh * fromfh; - struct nfs_fh * tofh; - const char * toname; - int tolen; -}; - -struct nfs3_readdirargs { - struct nfs_fh * fh; - __u64 cookie; - __u32 verf[2]; - void * buffer; - unsigned int bufsiz; - int plus; -}; - -struct nfs3_diropres { - struct nfs_fattr * dir_attr; - struct nfs_fh * fh; - struct nfs_fattr * fattr; -}; - -struct nfs3_accessres { - struct nfs_fattr * fattr; - __u32 access; -}; - -struct nfs3_readlinkargs { - struct nfs_fh * fh; - void * buffer; - unsigned int bufsiz; -}; - -struct nfs3_readlinkres { - struct nfs_fattr * fattr; - void * buffer; - unsigned int bufsiz; -}; - -struct nfs3_renameres { - struct nfs_fattr * fromattr; - struct nfs_fattr * toattr; -}; - -struct nfs3_linkres { - struct nfs_fattr * dir_attr; - struct nfs_fattr * fattr; -}; - -struct nfs3_readdirres { - struct nfs_fattr * dir_attr; - __u32 * verf; - void * buffer; - unsigned int bufsiz; - int plus; -}; - -#endif /* NFS_NEED_XDR_TYPES */ - - #endif /* __KERNEL__ */ #endif /* _LINUX_NFS3_H */ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index f5a807c438e4..5f9a5dded7a2 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -18,6 +18,7 @@ #include #include +#include #include /* @@ -64,6 +65,7 @@ #define NFS_DSERVER(dentry) (&(dentry)->d_sb->u.nfs_sb.s_server) #define NFS_SERVER(inode) (&(inode)->i_sb->u.nfs_sb.s_server) #define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) +#define NFS_PROTO(inode) (NFS_SERVER(inode)->rpc_ops) #define NFS_REQUESTLIST(inode) (NFS_SERVER(inode)->rw_requests) #define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode))) #define NFS_CONGESTED(inode) (RPC_CONGESTED(NFS_CLIENT(inode))) @@ -233,6 +235,7 @@ extern int nfs_readpage(struct dentry *, struct page *); * (Used only by nfsroot module) */ extern int nfs_mount(struct sockaddr_in *, char *, struct nfs_fh *); +extern int nfs3_mount(struct sockaddr_in *, char *, struct nfs_fh *); /* * inline functions diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h index a1088db0a226..05e25990055b 100644 --- a/include/linux/nfs_fs_i.h +++ b/include/linux/nfs_fs_i.h @@ -81,6 +81,7 @@ struct nfs_inode_info { struct nfs_lock_info { u32 state; u32 flags; + struct nlm_host *host; }; /* diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index a6231d761862..da76c1d62a61 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -6,6 +6,7 @@ */ struct nfs_server { struct rpc_clnt * client; /* RPC client handle */ + struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ int flags; /* various flags */ unsigned int rsize; /* read size */ unsigned int wsize; /* write size */ @@ -15,6 +16,7 @@ struct nfs_server { unsigned int acregmax; unsigned int acdirmin; unsigned int acdirmax; + unsigned int namelen; char * hostname; /* remote hostname */ struct nfs_reqlist * rw_requests; /* async read/write requests */ }; diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h index d5150c1f2790..8e11ef368f69 100644 --- a/include/linux/nfs_mount.h +++ b/include/linux/nfs_mount.h @@ -18,12 +18,12 @@ * mount-to-kernel version compatibility. Some of these aren't used yet * but here they are anyway. */ -#define NFS_MOUNT_VERSION 3 +#define NFS_MOUNT_VERSION 4 struct nfs_mount_data { int version; /* 1 */ int fd; /* 1 */ - struct nfs_fh root; /* 1 */ + struct nfs2_fh old_root; /* 1 */ int flags; /* 1 */ int rsize; /* 1 */ int wsize; /* 1 */ @@ -37,6 +37,7 @@ struct nfs_mount_data { char hostname[256]; /* 1 */ int namlen; /* 2 */ unsigned int bsize; /* 3 */ + struct nfs_fh root; /* 4 */ }; /* bits in the flags field */ diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index ba2ff7c49a08..eca3e1b2d570 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -36,12 +36,46 @@ struct nfs_fattr { #define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ #define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ +/* + * Info on the file system + */ struct nfs_fsinfo { - __u32 tsize; - __u32 bsize; - __u32 blocks; - __u32 bfree; - __u32 bavail; + __u32 rtmax; /* max. read transfer size */ + __u32 rtpref; /* pref. read transfer size */ + __u32 rtmult; /* reads should be multiple of this */ + __u32 wtmax; /* max. write transfer size */ + __u32 wtpref; /* pref. write transfer size */ + __u32 wtmult; /* writes should be multiple of this */ + __u32 dtpref; /* pref. readdir transfer size */ + __u64 maxfilesize; + __u64 bsize; /* block size */ + __u64 tbytes; /* total size in bytes */ + __u64 fbytes; /* # of free bytes */ + __u64 abytes; /* # of bytes available to user */ + __u64 tfiles; /* # of files */ + __u64 ffiles; /* # of free files */ + __u64 afiles; /* # of files available to user */ + __u32 linkmax;/* max # of hard links */ + __u32 namelen;/* max name length */ +}; + +/* Arguments to the read call. + * Note that NFS_READ_MAXIOV must be <= (MAX_IOVEC-2) from sunrpc/xprt.h + */ +#define NFS_READ_MAXIOV 8 + +struct nfs_readargs { + struct nfs_fh * fh; + __u64 offset; + __u32 count; + unsigned int nriov; + struct iovec iov[NFS_READ_MAXIOV]; +}; + +struct nfs_readres { + struct nfs_fattr * fattr; + unsigned int count; + int eof; }; /* Arguments to the write call. @@ -68,18 +102,6 @@ struct nfs_writeres { __u32 count; }; -struct nfs_readargs { - struct nfs_fh * fh; - __u32 offset; - __u32 count; - void * buffer; -}; - -struct nfs_readres { - struct nfs_fattr * fattr; - unsigned int count; -}; - /* * Argument struct for decode_entry function */ @@ -108,31 +130,38 @@ struct nfs_sattrargs { struct nfs_diropargs { struct nfs_fh * fh; const char * name; + unsigned int len; }; struct nfs_createargs { struct nfs_fh * fh; const char * name; + unsigned int len; struct iattr * sattr; }; struct nfs_renameargs { struct nfs_fh * fromfh; const char * fromname; + unsigned int fromlen; struct nfs_fh * tofh; const char * toname; + unsigned int tolen; }; struct nfs_linkargs { struct nfs_fh * fromfh; struct nfs_fh * tofh; const char * toname; + unsigned int tolen; }; struct nfs_symlinkargs { struct nfs_fh * fromfh; const char * fromname; + unsigned int fromlen; const char * topath; + unsigned int tolen; struct iattr * sattr; }; @@ -150,7 +179,13 @@ struct nfs_diropok { struct nfs_readlinkargs { struct nfs_fh * fh; - const void * buffer; + void * buffer; + unsigned int bufsiz; +}; + +struct nfs_readlinkres { + void * buffer; + unsigned int bufsiz; }; struct nfs_readdirres { @@ -158,44 +193,182 @@ struct nfs_readdirres { unsigned int bufsiz; }; +struct nfs3_sattrargs { + struct nfs_fh * fh; + struct iattr * sattr; + unsigned int guard; + __u64 guardtime; +}; + +struct nfs3_diropargs { + struct nfs_fh * fh; + const char * name; + unsigned int len; +}; + +struct nfs3_accessargs { + struct nfs_fh * fh; + __u32 access; +}; + +struct nfs3_createargs { + struct nfs_fh * fh; + const char * name; + unsigned int len; + struct iattr * sattr; + enum nfs3_createmode createmode; + __u32 verifier[2]; +}; + +struct nfs3_mkdirargs { + struct nfs_fh * fh; + const char * name; + unsigned int len; + struct iattr * sattr; +}; + +struct nfs3_symlinkargs { + struct nfs_fh * fromfh; + const char * fromname; + unsigned int fromlen; + const char * topath; + unsigned int tolen; + struct iattr * sattr; +}; + +struct nfs3_mknodargs { + struct nfs_fh * fh; + const char * name; + unsigned int len; + enum nfs3_ftype type; + struct iattr * sattr; + dev_t rdev; +}; + +struct nfs3_renameargs { + struct nfs_fh * fromfh; + const char * fromname; + unsigned int fromlen; + struct nfs_fh * tofh; + const char * toname; + unsigned int tolen; +}; + +struct nfs3_linkargs { + struct nfs_fh * fromfh; + struct nfs_fh * tofh; + const char * toname; + unsigned int tolen; +}; + +struct nfs3_readdirargs { + struct nfs_fh * fh; + __u64 cookie; + __u32 verf[2]; + void * buffer; + unsigned int bufsiz; + int plus; +}; + +struct nfs3_diropres { + struct nfs_fattr * dir_attr; + struct nfs_fh * fh; + struct nfs_fattr * fattr; +}; + +struct nfs3_accessres { + struct nfs_fattr * fattr; + __u32 access; +}; + +struct nfs3_readlinkargs { + struct nfs_fh * fh; + void * buffer; + unsigned int bufsiz; +}; + +struct nfs3_readlinkres { + struct nfs_fattr * fattr; + void * buffer; + unsigned int bufsiz; +}; + +struct nfs3_renameres { + struct nfs_fattr * fromattr; + struct nfs_fattr * toattr; +}; + +struct nfs3_linkres { + struct nfs_fattr * dir_attr; + struct nfs_fattr * fattr; +}; + +struct nfs3_readdirres { + struct nfs_fattr * dir_attr; + __u32 * verf; + void * buffer; + unsigned int bufsiz; + int plus; +}; + /* - * linux/fs/nfs/proc.c + * RPC procedure vector for NFSv2/NFSv3 demuxing */ -extern int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fattr *fattr); -extern int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fattr *fattr, struct iattr *sattr); -extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, - const char *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr); -extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle, - int swap, unsigned long offset, unsigned int count, - void *buffer, struct nfs_fattr *fattr); -extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, - int swap, unsigned long offset, unsigned int count, - const void *buffer, struct nfs_fattr *fattr); -extern int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir, - const char *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr); -extern int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, - const char *name); -extern int nfs_proc_rename(struct nfs_server *server, - struct nfs_fh *old_dir, const char *old_name, - struct nfs_fh *new_dir, const char *new_name); -extern int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fh *dir, const char *name); -extern int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir, - const char *name, const char *path, - struct iattr *sattr); -extern int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir, - const char *name, struct iattr *sattr, - struct nfs_fh *fhandle, struct nfs_fattr *fattr); -extern int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, - const char *name); -extern int nfs_proc_readdir(struct dentry *, struct nfs_fattr *, - u64 cookie, void *, unsigned int size, int plus); -extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *res); -extern u32 * nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); +struct nfs_rpc_ops { + int version; /* Protocol version */ + + int (*getroot) (struct nfs_server *, struct nfs_fh *, + struct nfs_fattr *); + int (*getattr) (struct dentry *, struct nfs_fattr *); + int (*setattr) (struct dentry *, struct nfs_fattr *, + struct iattr *); + int (*lookup) (struct dentry *, struct qstr *, + struct nfs_fh *, struct nfs_fattr *); + int (*access) (struct dentry *, int , int); + int (*readlink)(struct dentry *, void *, unsigned int); + int (*read) (struct dentry *, struct nfs_fattr *, + int, loff_t, unsigned int, + void *buffer, int *eofp); + int (*write) (struct dentry *, struct nfs_fattr *, + int, loff_t, unsigned int, + void *buffer, struct nfs_writeverf *verfp); + int (*commit) (struct dentry *, struct nfs_fattr *, + unsigned long, unsigned int); + int (*create) (struct dentry *, struct qstr *, struct iattr *, + int, struct nfs_fh *, struct nfs_fattr *); + int (*remove) (struct dentry *, struct qstr *); + int (*rename) (struct dentry *, struct qstr *, + struct dentry *, struct qstr *); + int (*link) (struct dentry *, struct dentry *, struct qstr *); + int (*symlink) (struct dentry *, struct qstr *, struct qstr *, + struct iattr *, struct nfs_fh *, + struct nfs_fattr *); + int (*mkdir) (struct dentry *, struct qstr *, struct iattr *, + struct nfs_fh *, struct nfs_fattr *); + int (*rmdir) (struct dentry *, struct qstr *); + int (*readdir) (struct dentry *, u64 cookie, void *, unsigned int, + int); + int (*mknod) (struct dentry *, struct qstr *, struct iattr *, + dev_t, struct nfs_fh *, struct nfs_fattr *); + int (*statfs) (struct nfs_server *, struct nfs_fh *, + struct nfs_fsinfo *); + u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); +}; + +/* + * NFS_CALL(getattr, inode, (fattr)); + * into + * NFS_PROTO(inode)->getattr(fattr); + */ +#define NFS_CALL(op, inode, args) NFS_PROTO(inode)->op args + +/* + * Function vectors etc. for the NFS client + */ +extern struct nfs_rpc_ops nfs_v2_clientops; +extern struct nfs_rpc_ops nfs_v3_clientops; +extern struct rpc_version nfs_version2; +extern struct rpc_version nfs_version3; +extern struct rpc_program nfs_program; #endif diff --git a/include/linux/nfsd/const.h b/include/linux/nfsd/const.h index ebb8a3b4bc93..f59c6a6ef8c4 100644 --- a/include/linux/nfsd/const.h +++ b/include/linux/nfsd/const.h @@ -11,6 +11,7 @@ #include #include +#include /* * Maximum protocol version supported by knfsd @@ -22,13 +23,6 @@ */ #define NFSSVC_MAXBLKSIZE 8192 -#define NFS3_MAXPATHLEN PATH_MAX -#define NFS3_MAXNAMLEN NAME_MAX -#define NFS3_FHSIZE 64 -#define NFS3_COOKIEVERFSIZE 8 -#define NFS3_CREATEVERFSIZE 8 -#define NFS3_WRITEVERFSIZE 8 - #ifdef __KERNEL__ #ifndef NFS_SUPER_MAGIC diff --git a/include/linux/proc_fs_i.h b/include/linux/proc_fs_i.h index 5060d08fc4c9..43cf4dfeff93 100644 --- a/include/linux/proc_fs_i.h +++ b/include/linux/proc_fs_i.h @@ -2,7 +2,7 @@ struct proc_inode_info { struct task_struct *task; int type; union { - struct dentry *(*proc_get_link)(struct inode *); + struct dentry *(*proc_get_link)(struct inode *, struct vfsmount **); int (*proc_read)(struct task_struct *task, char *page); } op; struct file *file; diff --git a/include/linux/sched.h b/include/linux/sched.h index a0b80f69005f..010a8ac9c385 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -185,12 +185,13 @@ struct fs_struct { atomic_t count; int umask; struct dentry * root, * pwd; + struct vfsmount * rootmnt, * pwdmnt; }; #define INIT_FS { \ ATOMIC_INIT(1), \ 0022, \ - NULL, NULL \ + NULL, NULL, NULL, NULL \ } /* Maximum number of active map areas.. This is a random (large) number */ diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 5a29918e6f13..98bf0ec20499 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -59,6 +59,7 @@ void xdr_init(void); /* * Miscellaneous XDR helper functions */ +u32 * xdr_encode_array(u32 *p, const char *s, unsigned int len); u32 * xdr_encode_string(u32 *p, const char *s); u32 * xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen); u32 * xdr_encode_netobj(u32 *p, const struct xdr_netobj *); @@ -93,6 +94,9 @@ xdr_adjust_iovec(struct iovec *iov, u32 *p) return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base); } +void xdr_shift_iovec(struct iovec *, int, size_t); +void xdr_zero_iovec(struct iovec *, int, size_t); + #endif /* __KERNEL__ */ #endif /* _SUNRPC_XDR_H_ */ diff --git a/include/linux/swap.h b/include/linux/swap.h index e4e035db7e33..d24ff0e0a880 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -154,7 +154,7 @@ static inline int is_page_shared(struct page *page) return 1; count = page_count(page); if (PageSwapCache(page)) - count += swap_count(page) - 2; + count += swap_count(page) - 2 - !!page->buffers; return count > 1; } diff --git a/include/linux/tty.h b/include/linux/tty.h index b49745fbee9b..f8914df6bd3c 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -374,6 +374,9 @@ extern void start_tty(struct tty_struct * tty); extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); extern int tty_register_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver); +extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags, + unsigned minor); +extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); extern void tty_write_message(struct tty_struct *tty, char *msg); diff --git a/include/net/sock.h b/include/net/sock.h index f9d986b81705..9b7720969cc2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -838,11 +838,19 @@ extern void sklist_insert_socket(struct sock **list, struct sock *sk); extern void sklist_destroy_socket(struct sock **list, struct sock *sk); #ifdef CONFIG_FILTER -/* + +/** + * sk_filter - run a packet through a socket filter + * @skb: buffer to filter + * @filter: filter to apply + * * Run the filter code and then cut skb->data to correct size returned by * sk_run_filter. If pkt_len is 0 we toss packet. If skb->len is smaller - * than pkt_len we keep whole skb->data. + * than pkt_len we keep whole skb->data. This is the socket level + * wrapper to sk_run_filter. It returns 0 if the packet should + * be accepted or 1 if the packet should be tossed. */ + extern __inline__ int sk_filter(struct sk_buff *skb, struct sk_filter *filter) { int pkt_len; @@ -856,6 +864,14 @@ extern __inline__ int sk_filter(struct sk_buff *skb, struct sk_filter *filter) return 0; } +/** + * sk_filter_release: Release a socket filter + * @sk: socket + * @fp: filter to remove + * + * Remove a filter from a socket and release its resources. + */ + extern __inline__ void sk_filter_release(struct sock *sk, struct sk_filter *fp) { unsigned int size = sk_filter_len(fp); diff --git a/ipc/shm.c b/ipc/shm.c index 232feedad9b6..fcf07f3d562c 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -18,8 +18,9 @@ * 1) It only can handle one directory. * 2) Because the directory is represented by the SYSV shm array it * can only be mounted one time. - * 3) Read and write are not implemented (should they?) - * 4) No special nodes are supported + * 3) Private writeable mappings are not supported + * 4) Read and write are not implemented (should they?) + * 5) No special nodes are supported * * There are the following mount options: * - nr_blocks (^= shmall) is the number of blocks of size PAGE_SIZE @@ -117,7 +118,7 @@ static struct ipc_ids shm_ids; ipc_buildid(&shm_ids, id, seq) static int newseg (key_t key, const char *name, int namelen, int shmflg, size_t size); -static void killseg_core(struct shmid_kernel *shp, int doacc); +static void seg_free(struct shmid_kernel *shp, int doacc); static void shm_open (struct vm_area_struct *shmd); static void shm_close (struct vm_area_struct *shmd); static int shm_remove_name(int id); @@ -348,7 +349,7 @@ static void shm_put_super(struct super_block *sb) printk(KERN_DEBUG "shm_nattch = %ld\n", shp->shm_nattch); shp = shm_rmid(i); shm_unlock(i); - killseg_core(shp, 1); + seg_free(shp, 1); } dput (sb->s_root); up(&shm_ids.sem); @@ -542,7 +543,7 @@ static int shm_unlink (struct inode *dir, struct dentry *dent) #define SHM_ENTRY(shp, index) (shp)->shm_dir[(index)/PTRS_PER_PTE][(index)%PTRS_PER_PTE] -static pte_t **shm_alloc(unsigned long pages) +static pte_t **shm_alloc(unsigned long pages, int doacc) { unsigned short dir = pages / PTRS_PER_PTE; unsigned short last = pages % PTRS_PER_PTE; @@ -572,6 +573,12 @@ static pte_t **shm_alloc(unsigned long pages) for (pte = *ptr; pte < *ptr + last; pte++) pte_clear (pte); } + if (doacc) { + shm_lockall(); + shm_tot += pages; + used_segs++; + shm_unlockall(); + } return ret; free: @@ -584,13 +591,28 @@ nomem: return ERR_PTR(-ENOMEM); } -static void shm_free(pte_t** dir, unsigned long pages) +static void shm_free(pte_t** dir, unsigned long pages, int doacc) { + int i, rss, swp; pte_t **ptr = dir+pages/PTRS_PER_PTE; if (!dir) return; + for (i = 0, rss = 0, swp = 0; i < pages ; i++) { + pte_t pte; + pte = dir[i/PTRS_PER_PTE][i%PTRS_PER_PTE]; + if (pte_none(pte)) + continue; + if (pte_present(pte)) { + __free_page (pte_page(pte)); + rss++; + } else { + swap_free(pte_to_swp_entry(pte)); + swp++; + } + } + /* first the last page */ if (pages%PTRS_PER_PTE) kfree (*ptr); @@ -601,6 +623,15 @@ static void shm_free(pte_t** dir, unsigned long pages) /* Now the indirect block */ kfree (dir); + + if (doacc) { + shm_lockall(); + shm_rss -= rss; + shm_swp -= swp; + shm_tot -= pages; + used_segs--; + shm_unlockall(); + } } static int shm_setattr (struct dentry *dentry, struct iattr *attr) @@ -611,7 +642,8 @@ static int shm_setattr (struct dentry *dentry, struct iattr *attr) unsigned long new_pages, old_pages; pte_t **new_dir, **old_dir; - if ((error = inode_change_ok(inode, attr))) + error = inode_change_ok(inode, attr); + if (error) return error; if (!(attr->ia_valid & ATTR_SIZE)) goto set_attr; @@ -620,15 +652,19 @@ static int shm_setattr (struct dentry *dentry, struct iattr *attr) /* We set old_pages and old_dir for easier cleanup */ old_pages = new_pages = (attr->ia_size + PAGE_SIZE - 1) >> PAGE_SHIFT; - if (shm_tot + new_pages >= shm_ctlall) - return -ENOSPC; - if (IS_ERR(old_dir = new_dir = shm_alloc(new_pages))) + old_dir = new_dir = shm_alloc(new_pages, 1); + if (IS_ERR(new_dir)) return PTR_ERR(new_dir); if (!(shp = shm_lock(inode->i_ino))) BUG(); + error = -ENOSPC; + if (shm_tot - shp->shm_npages >= shm_ctlall) + goto out; + error = 0; if (shp->shm_segsz == attr->ia_size) goto out; + /* Now we set them to the real values */ old_dir = shp->shm_dir; old_pages = shp->shm_npages; if (old_dir){ @@ -650,16 +686,13 @@ static int shm_setattr (struct dentry *dentry, struct iattr *attr) shp->shm_segsz = attr->ia_size; out: shm_unlock(inode->i_ino); - shm_lockall(); - shm_tot += new_pages - old_pages; - shm_unlockall(); - shm_free (old_dir, old_pages); + shm_free (old_dir, old_pages, 1); set_attr: inode_setattr(inode, attr); - return 0; + return error; } -static inline struct shmid_kernel *newseg_alloc(int numpages, size_t namelen) +static struct shmid_kernel *seg_alloc(int numpages, size_t namelen) { struct shmid_kernel *shp; pte_t **dir; @@ -668,7 +701,7 @@ static inline struct shmid_kernel *newseg_alloc(int numpages, size_t namelen) if (!shp) return ERR_PTR(-ENOMEM); - dir = shm_alloc (numpages); + dir = shm_alloc (numpages, namelen); if (IS_ERR(dir)) { kfree(shp); return ERR_PTR(PTR_ERR(dir)); @@ -680,6 +713,12 @@ static inline struct shmid_kernel *newseg_alloc(int numpages, size_t namelen) return(shp); } +static void seg_free(struct shmid_kernel *shp, int doacc) +{ + shm_free (shp->shm_dir, shp->shm_npages, doacc); + kfree(shp); +} + static int newseg (key_t key, const char *name, int namelen, int shmflg, size_t size) { @@ -696,12 +735,11 @@ static int newseg (key_t key, const char *name, int namelen, if (shm_tot + numpages >= shm_ctlall) return -ENOSPC; - if (!(shp = newseg_alloc(numpages, namelen ? namelen : SHM_FMT_LEN + 1))) + if (!(shp = seg_alloc(numpages, namelen ? namelen : SHM_FMT_LEN + 1))) return -ENOMEM; id = shm_addid(shp); if(id == -1) { - shm_free(shp->shm_dir,numpages); - kfree(shp); + seg_free(shp, 1); return -ENOSPC; } shp->shm_perm.key = key; @@ -719,9 +757,6 @@ static int newseg (key_t key, const char *name, int namelen, } else { shp->shm_namelen = sprintf (shp->shm_name, SHM_FMT, shp->id); } - - shm_tot += numpages; - used_segs++; shm_unlock(id); return shp->id; @@ -768,36 +803,6 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) return err; } -static void killseg_core(struct shmid_kernel *shp, int doacc) -{ - int i, numpages, rss, swp; - - numpages = shp->shm_npages; - for (i = 0, rss = 0, swp = 0; i < numpages ; i++) { - pte_t pte; - pte = SHM_ENTRY (shp,i); - if (pte_none(pte)) - continue; - if (pte_present(pte)) { - __free_page (pte_page(pte)); - rss++; - } else { - swap_free(pte_to_swp_entry(pte)); - swp++; - } - } - shm_free (shp->shm_dir, numpages); - kfree(shp); - if (doacc) { - shm_lockall(); - shm_rss -= rss; - shm_swp -= swp; - shm_tot -= numpages; - used_segs--; - shm_unlockall(); - } -} - static void shm_delete (struct inode *ino) { int shmid = ino->i_ino; @@ -811,7 +816,7 @@ static void shm_delete (struct inode *ino) shp = shm_rmid(shmid); shm_unlock(shmid); up(&shm_ids.sem); - killseg_core(shp, 1); + seg_free(shp, 1); clear_inode(ino); } @@ -1146,6 +1151,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma) /* * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. */ +/* MOUNT_REWRITE: kernel vfsmnt of shmfs should be passed to __filp_open() */ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) { unsigned long addr; @@ -1181,7 +1187,7 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) sprintf (name, SHM_FMT, shmid); lock_kernel(); - file = filp_open(name, o_flags, 0, dget(shm_sb->s_root)); + file = __filp_open(name, o_flags, 0, dget(shm_sb->s_root), NULL); if (IS_ERR (file)) goto bad_file; *raddr = do_mmap (file, addr, file->f_dentry->d_inode->i_size, @@ -1213,13 +1219,23 @@ static void shm_open (struct vm_area_struct *shmd) static int shm_remove_name(int id) { - int err; + struct dentry *dir; + struct dentry *dentry; + int error; char name[SHM_FMT_LEN+1]; + sprintf (name, SHM_FMT, id); lock_kernel(); - err = do_unlink (name, dget(shm_sb->s_root)); + dir = lock_parent(shm_sb->s_root); + dentry = lookup_one(name, dir); + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = vfs_unlink(dir->d_inode, dentry); + dput(dentry); + } + unlock_dir(dir); unlock_kernel(); - return err; + return error; } /* @@ -1637,6 +1653,7 @@ static struct vm_operations_struct shmzero_vm_ops = { * on the pseudo-file. This is possible because the open/close calls * are bracketed by the file count update calls. */ +/* MOUNT_REWRITE: set ->f_vfsmnt to shmfs one */ static struct file *file_setup(struct file *fzero, struct shmid_kernel *shp) { struct file *filp; @@ -1654,6 +1671,7 @@ static struct file *file_setup(struct file *fzero, struct shmid_kernel *shp) put_filp(filp); return(0); } + filp->f_vfsmnt = NULL; d_instantiate(filp->f_dentry, inp); /* @@ -1674,10 +1692,10 @@ int map_zero_setup(struct vm_area_struct *vma) if (!vm_enough_memory((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)) return -ENOMEM; - if (IS_ERR(shp = newseg_alloc((vma->vm_end - vma->vm_start) / PAGE_SIZE, 0))) + if (IS_ERR(shp = seg_alloc((vma->vm_end - vma->vm_start) / PAGE_SIZE, 0))) return PTR_ERR(shp); if ((filp = file_setup(vma->vm_file, shp)) == 0) { - killseg_core(shp, 0); + seg_free(shp, 0); return -ENOMEM; } vma->vm_file = filp; @@ -1719,7 +1737,7 @@ static void shmzero_close(struct vm_area_struct *shmd) struct shmid_kernel, zero_list); list_del(&shp->zero_list); spin_unlock(&zmap_list_lock); - killseg_core(shp, 0); + seg_free(shp, 0); } } diff --git a/kernel/acct.c b/kernel/acct.c index f15b6971f281..2bd7d121d416 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -36,8 +36,7 @@ * but this one obviously doesn't introduce deadlocks. Later. BTW, found * one race (and leak) in BSD implementation. * OK, that's better. ANOTHER race and leak in BSD variant. There always - * is one more bug... TODO: move filp_open into open.c and make - * parameters sysctl-controllable. 10/11/98, AV. + * is one more bug... 10/11/98, AV. */ #include @@ -154,7 +153,7 @@ asmlinkage long sys_acct(const char *name) if (IS_ERR(tmp)) goto out; /* Difference from BSD - they don't do O_APPEND */ - file = filp_open(tmp, O_WRONLY|O_APPEND, 0, NULL); + file = filp_open(tmp, O_WRONLY|O_APPEND, 0); putname(tmp); if (IS_ERR(file)) { error = PTR_ERR(file); diff --git a/kernel/exit.c b/kernel/exit.c index c6f22872de4e..e4938f17b93f 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -216,7 +216,9 @@ static inline void __exit_fs(struct task_struct *tsk) tsk->fs = NULL; if (atomic_dec_and_test(&fs->count)) { dput(fs->root); + mntput(fs->rootmnt); dput(fs->pwd); + mntput(fs->pwdmnt); kfree(fs); } } @@ -414,12 +416,12 @@ fake_volatile: #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif - task_lock(tsk); sem_exit(); __exit_mm(tsk); __exit_files(tsk); __exit_fs(tsk); __exit_sighand(tsk); + task_lock(tsk); exit_thread(); tsk->state = TASK_ZOMBIE; tsk->exit_code = code; diff --git a/kernel/fork.c b/kernel/fork.c index 2fbb08e32fc6..6eca792d96e9 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -432,6 +432,8 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk) tsk->fs->umask = current->fs->umask; tsk->fs->root = dget(current->fs->root); tsk->fs->pwd = dget(current->fs->pwd); + tsk->fs->rootmnt = mntget(current->fs->rootmnt); + tsk->fs->pwdmnt = mntget(current->fs->pwdmnt); return 0; } diff --git a/kernel/kmod.c b/kernel/kmod.c index dca806e9434d..75d31eadf5fd 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -54,11 +54,15 @@ use_init_fs_context(void) our_fs = current->fs; dput(our_fs->root); dput(our_fs->pwd); + mntput(our_fs->rootmnt); + mntput(our_fs->pwdmnt); init_fs = init_task.fs; our_fs->umask = init_fs->umask; our_fs->root = dget(init_fs->root); our_fs->pwd = dget(init_fs->pwd); + our_fs->rootmnt = mntget(init_fs->rootmnt); + our_fs->pwdmnt = mntget(init_fs->pwdmnt); unlock_kernel(); } @@ -119,10 +123,20 @@ static int exec_modprobe(void * module_name) return ret; } -/* - request_module: the function that everyone calls when they need - a module. -*/ +/** + * request_module - try to load a kernel module + * @module_name: Name of module + * + * Load a module using the user mode module loader. The function returns + * zero on success or a negative errno code on failure. Note that a + * successful module load does not mean the module did not then unload + * and exit on an error of its own. Callers must check that the service + * they requested is now available not blindly invoke it. + * + * If module auto-loading support is disabled then this function + * becomes a no-operation. + */ + int request_module(const char * module_name) { int pid; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 2cd4525a96e6..873b038ae282 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -142,7 +142,6 @@ EXPORT_SYMBOL(iput); EXPORT_SYMBOL(__namei); EXPORT_SYMBOL(lookup_dentry); EXPORT_SYMBOL(lookup_one); -EXPORT_SYMBOL(__open_namei); EXPORT_SYMBOL(sys_close); EXPORT_SYMBOL(d_alloc_root); EXPORT_SYMBOL(d_delete); @@ -153,13 +152,13 @@ EXPORT_SYMBOL(d_move); EXPORT_SYMBOL(d_instantiate); EXPORT_SYMBOL(d_alloc); EXPORT_SYMBOL(d_lookup); -EXPORT_SYMBOL(d_path); +EXPORT_SYMBOL(__d_path); EXPORT_SYMBOL(mark_buffer_dirty); EXPORT_SYMBOL(__mark_buffer_dirty); EXPORT_SYMBOL(__mark_inode_dirty); EXPORT_SYMBOL(get_empty_filp); EXPORT_SYMBOL(init_private_file); -EXPORT_SYMBOL(filp_open); +EXPORT_SYMBOL(__filp_open); EXPORT_SYMBOL(filp_close); EXPORT_SYMBOL(put_filp); EXPORT_SYMBOL(files_lock); diff --git a/kernel/panic.c b/kernel/panic.c index e040ee454d72..491eae26f357 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -32,10 +32,24 @@ static int __init panic_setup(char *str) __setup("panic=", panic_setup); +/** + * panic - halt the system + * @fmt: The text string to print + * + * Display a message, then unblank the console and perform + * cleanups. Functions in the panic notifier list are called + * after the filesystem cache is flushed (when possible). + * + * This function never returns. + */ + NORET_TYPE void panic(const char * fmt, ...) { static char buf[1024]; va_list args; +#if defined(CONFIG_ARCH_S390) + unsigned long caller = (unsigned long) __builtin_return_address(0); +#endif va_start(args, fmt); vsprintf(buf, fmt, args); @@ -78,6 +92,9 @@ NORET_TYPE void panic(const char * fmt, ...) stop_a_enabled = 1; printk("Press L1-A to return to the boot prom\n"); } +#endif +#if defined(CONFIG_ARCH_S390) + disabled_wait(caller); #endif sti(); for(;;) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b715f5d5b888..20663e5e84ed 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -100,6 +100,8 @@ void __free_pages_ok (struct page *page, unsigned long order) if (page->buffers) BUG(); + if (page->mapping) + BUG(); if (page-mem_map >= max_mapnr) BUG(); if (PageSwapCache(page)) diff --git a/mm/slab.c b/mm/slab.c index dc8294f2d705..6dcc67815a00 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -127,7 +127,7 @@ * SLAB_SELFTEST - 1 to perform a few tests, mainly for development. */ #define SLAB_MGMT_CHECKS 1 -#define SLAB_DEBUG_SUPPORT 0 +#define SLAB_DEBUG_SUPPORT 1 #define SLAB_STATS 0 #define SLAB_SELFTEST 0 diff --git a/mm/swapfile.c b/mm/swapfile.c index e8a2a0b2fc72..679a42484ebc 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -538,7 +538,7 @@ int get_swaparea_info(char *buf) len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed\tPriority\n"); for (i = 0 ; i < nr_swapfiles ; i++, ptr++) { if (ptr->flags & SWP_USED) { - char * path = d_path(ptr->swap_file, page, PAGE_SIZE); + char * path = d_path(ptr->swap_file, NULL, page, PAGE_SIZE); len += sprintf(buf + len, "%-31s ", path); diff --git a/net/core/filter.c b/net/core/filter.c index 8749e8c7b511..9d16a69fea63 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -54,7 +54,12 @@ static u8 *load_pointer(struct sk_buff *skb, int k) return NULL; } -/* +/** + * sk_run_filter - run a filter on a socket + * @skb: buffer to run the filter on + * @filter: filter to apply + * @flen: length of filter + * * Decode and apply filter instructions to the skb->data. * Return length to keep, 0 for none. skb is the data we are * filtering, filter is the array of filter instructions, and @@ -341,9 +346,17 @@ load_b: return (0); } -/* +/** + * sk_chk_filter - verify socket filter code + * @filter: filter to verify + * @flen: length of filter + * * Check the user's filter code. If we let some ugly - * filter code slip through kaboom! + * filter code slip through kaboom! The filter must contain + * no references or jumps that are out of range, no illegal instructions + * and no backward jumps. It must end with a RET instruction + * + * Returns 0 if the rule set is legal or a negative errno code if not. */ int sk_chk_filter(struct sock_filter *filter, int flen) @@ -413,9 +426,15 @@ int sk_chk_filter(struct sock_filter *filter, int flen) return (BPF_CLASS(filter[flen - 1].code) == BPF_RET)?0:-EINVAL; } -/* +/** + * sk_attach_filter - attach a socket filter + * @fprog: the filter program + * @sk: the socket to use + * * Attach the user's filter code. We first run some sanity checks on - * it to make sure it does not explode on us later. + * it to make sure it does not explode on us later. If an error + * occurs or there is insufficient memory for the filter a negative + * errno code is returned. On success the return is zero. */ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) diff --git a/net/khttpd/security.c b/net/khttpd/security.c index 7e0780a26a77..16503ceb5af8 100644 --- a/net/khttpd/security.c +++ b/net/khttpd/security.c @@ -115,14 +115,12 @@ struct file *OpenFileForSecurity(char *Filename) lock_kernel(); - filp = filp_open(Filename, 0, O_RDONLY, NULL); + filp = filp_open(Filename, O_RDONLY, 0); unlock_kernel(); - if ((IS_ERR(filp))||(filp==NULL)||(filp->f_dentry==NULL)) - { + if (IS_ERR(filp)) return NULL; - } #ifndef BENCHMARK permission = filp->f_dentry->d_inode->i_mode; diff --git a/net/khttpd/waitheaders.c b/net/khttpd/waitheaders.c index 47fa1581d557..2c24f3744c83 100644 --- a/net/khttpd/waitheaders.c +++ b/net/khttpd/waitheaders.c @@ -239,7 +239,6 @@ static int DecodeHeader(const int CPUNR, struct http_request *Request) return 0; } else - if ((Request->filp->f_dentry!=NULL)&&(Request->filp->f_dentry->d_inode!=NULL)) { Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size; Request->Time = Request->filp->f_dentry->d_inode->i_mtime; @@ -262,12 +261,6 @@ static int DecodeHeader(const int CPUNR, struct http_request *Request) } - } else - { - /* Ehhh... */ - - printk(KERN_CRIT "kHTTPd: Unexpected filesystem response\n"); - return -1; } LeaveFunction("DecodeHeader"); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 3d693673182f..09a231305d8f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -80,6 +80,7 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, #ifdef RPC_DEBUG rpc_register_sysctl(); #endif + xdr_init(); if (!xprt) goto out; diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 92559fa65c7a..0455e14519e8 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -89,12 +89,15 @@ EXPORT_SYMBOL(svc_proc_read); #endif /* Generic XDR */ +EXPORT_SYMBOL(xdr_encode_array); EXPORT_SYMBOL(xdr_encode_string); EXPORT_SYMBOL(xdr_decode_string); EXPORT_SYMBOL(xdr_decode_netobj); EXPORT_SYMBOL(xdr_encode_netobj); EXPORT_SYMBOL(xdr_zero); EXPORT_SYMBOL(xdr_one); +EXPORT_SYMBOL(xdr_shift_iovec); +EXPORT_SYMBOL(xdr_zero_iovec); /* RPC errors */ EXPORT_SYMBOL(rpc_success); diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 6ebd9407912d..99b286af9d6a 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -56,8 +57,8 @@ xdr_encode_netobj(u32 *p, const struct xdr_netobj *obj) { unsigned int quadlen = XDR_QUADLEN(obj->len); + p[quadlen] = 0; /* zero trailing bytes */ *p++ = htonl(obj->len); - p[quadlen-1] = 0; /* zero trailing bytes */ memcpy(p, obj->data, obj->len); return p + XDR_QUADLEN(obj->len); } @@ -84,17 +85,22 @@ xdr_decode_netobj(u32 *p, struct xdr_netobj *obj) } u32 * -xdr_encode_string(u32 *p, const char *string) +xdr_encode_array(u32 *p, const char *array, unsigned int len) { - int len = strlen(string); int quadlen = XDR_QUADLEN(len); p[quadlen] = 0; *p++ = htonl(len); - memcpy(p, string, len); + memcpy(p, array, len); return p + quadlen; } +u32 * +xdr_encode_string(u32 *p, const char *string) +{ + return xdr_encode_array(p, string, strlen(string)); +} + u32 * xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen) { @@ -116,3 +122,51 @@ xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen) return p + XDR_QUADLEN(len); } +/* + * Realign the iovec if the server missed out some reply elements + * (such as post-op attributes,...) + * Note: This is a simple implementation that assumes that + * len <= iov->iov_len !!! + * The RPC header (assumed to be the 1st element in the iov array) + * is not shifted. + */ +void xdr_shift_iovec(struct iovec *iov, int nr, size_t len) +{ + struct iovec *pvec; + + for (pvec = iov + nr - 1; nr > 1; nr--, pvec--) { + struct iovec *svec = pvec - 1; + + if (len > pvec->iov_len) { + printk(KERN_DEBUG "RPC: Urk! Large shift of short iovec.\n"); + return; + } + memmove((char *)pvec->iov_base + len, pvec->iov_base, + pvec->iov_len - len); + + if (len > svec->iov_len) { + printk(KERN_DEBUG "RPC: Urk! Large shift of short iovec.\n"); + return; + } + memcpy(pvec->iov_base, + (char *)svec->iov_base + svec->iov_len - len, len); + } +} + +/* + * Zero the last n bytes in an iovec array of 'nr' elements + */ +void xdr_zero_iovec(struct iovec *iov, int nr, size_t n) +{ + struct iovec *pvec; + + for (pvec = iov + nr - 1; n && nr > 0; nr--, pvec--) { + if (n < pvec->iov_len) { + memset((char *)pvec->iov_base + pvec->iov_len - n, 0, n); + n = 0; + } else { + memset(pvec->iov_base, 0, pvec->iov_len); + n -= pvec->iov_len; + } + } +} diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 0eab57fac0fe..f71b38dfa7b0 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -564,39 +564,55 @@ static unix_socket *unix_find_other(struct sockaddr_un *sunname, int len, int type, unsigned hash, int *error) { unix_socket *u; + struct dentry *dentry; + int err; - if (sunname->sun_path[0]) - { - struct dentry *dentry; - + if (sunname->sun_path[0]) { /* Do not believe to VFS, grab kernel lock */ lock_kernel(); - dentry = __open_namei(sunname->sun_path, 2|O_NOFOLLOW, S_IFSOCK, NULL); + dentry = lookup_dentry(sunname->sun_path, NULL, 0); + err = PTR_ERR(dentry); if (IS_ERR(dentry)) { - *error = PTR_ERR(dentry); unlock_kernel(); - return NULL; + goto fail; } + err = -ENOENT; + if (!dentry->d_inode) + goto put_fail; + + err = permission(dentry->d_inode,MAY_WRITE); + if (err) + goto put_fail; + + err = -ECONNREFUSED; + if (!S_ISSOCK(dentry->d_inode->i_mode)) + goto put_fail; u=unix_find_socket_byinode(dentry->d_inode); + if (!u) + goto put_fail; + dput(dentry); unlock_kernel(); - if (u && u->type != type) - { - *error=-EPROTOTYPE; + err=-EPROTOTYPE; + if (u->type != type) { sock_put(u); - return NULL; + goto fail; } - } - else + } else { + err = -ECONNREFUSED; u=unix_find_socket_byname(sunname, len, type, hash); - - if (u==NULL) - { - *error=-ECONNREFUSED; - return NULL; + if (!u) + goto fail; } return u; + +put_fail: + dput(dentry); + unlock_kernel(); +fail: + *error=err; + return NULL; } diff --git a/scripts/Menuconfig b/scripts/Menuconfig index 3d724bf63576..3e0da2a9f1b5 100644 --- a/scripts/Menuconfig +++ b/scripts/Menuconfig @@ -404,7 +404,7 @@ function help () { $DIALOG --backtitle "$backtitle" \ --textbox help.out $ROWS $COLS fi - rm help.out + rm -f help.out } # @@ -1450,4 +1450,10 @@ else echo Your kernel configuration changes were NOT saved. echo fi + +# Remove log if empty. +if [ ! -s .menuconfig.log ] ; then + rm -f .menuconfig.log +fi + exit 0 diff --git a/scripts/checkincludes.pl b/scripts/checkincludes.pl new file mode 100644 index 000000000000..8e6b716c191c --- /dev/null +++ b/scripts/checkincludes.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl +# +# checkincludes: Find files included more than once in (other) files. +# Copyright abandoned, 2000, Niels Kristian Bech Jensen . + +foreach $file (@ARGV) { + open(FILE, $file) or die "Cannot open $file: $!.\n"; + + my %includedfiles = (); + + while () { + if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) { + ++$includedfiles{$1}; + } + } + + foreach $filename (keys %includedfiles) { + if ($includedfiles{$filename} > 1) { + print "$file: $filename is included more than once.\n"; + } + } + + close(FILE); +} diff --git a/scripts/gen-all-syms b/scripts/gen-all-syms index d65e196ca2c3..b15b160040e8 100644 --- a/scripts/gen-all-syms +++ b/scripts/gen-all-syms @@ -3,5 +3,5 @@ for i in $* do grep "EXPORT_SYMBOL.*(.*)" "$i" \ | sed -e "s/EXPORT_SYMBOL.*(/ /" \ - | sed -e "s/).*$//" + | sed -e "s/).*$//" | sed -e "s/^ //" done -- 2.39.5