From 62e3b9df0357af8d3a4e49a0a0a167480235f996 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:14:13 -0500 Subject: [PATCH] Import 2.1.72 --- CREDITS | 8 + Documentation/Configure.help | 56 +- Documentation/devices.tex | 77 +- Documentation/devices.txt | 50 +- Documentation/filesystems/coda.txt | 1427 +++++++++++++++++ MAINTAINERS | 6 + Makefile | 10 +- arch/alpha/kernel/entry.S | 16 +- arch/alpha/kernel/osf_sys.c | 412 ++++- arch/alpha/kernel/signal.c | 81 +- arch/i386/kernel/process.c | 11 +- arch/i386/kernel/sys_i386.c | 19 +- arch/sparc64/kernel/sys_sparc32.c | 199 ++- drivers/char/acquirewdt.c | 4 + drivers/char/n_tty.c | 150 +- drivers/char/rtc.c | 2 +- drivers/char/serial.c | 9 +- drivers/char/softdog.c | 4 + drivers/char/stallion.c | 62 + drivers/char/vga.c | 3 +- drivers/char/wdt.c | 10 +- drivers/isdn/avmb1/capi.c | 3 +- drivers/isdn/isdn_common.c | 2 +- drivers/isdn/isdn_ppp.c | 2 +- drivers/misc/parport_ax.c | 4 +- drivers/misc/parport_pc.c | 4 +- drivers/net/Config.in | 1 + drivers/net/Space.c | 1 + drivers/net/dmascc.c | 1260 +++++++++++++++ drivers/net/e2100.c | 1 + drivers/net/eql.c | 2 +- drivers/net/hamradio/Config.in | 2 - drivers/net/hamradio/soundmodem/sm_sbc.c | 4 +- drivers/net/ne.c | 4 +- drivers/sound/Config.in | 354 ++-- drivers/sound/Makefile | 45 +- drivers/sound/Readme | 16 +- drivers/sound/Readme.cards | 20 +- drivers/sound/Readme.linux | 4 +- drivers/sound/audio.c | 31 + drivers/sound/configure.c | 4 +- drivers/sound/dmabuf.c | 7 +- drivers/sound/lowlevel/awe_wave.c | 2 +- drivers/sound/mad16.c | 12 + drivers/sound/midi_synth.c | 127 +- drivers/sound/mpu401.c | 9 - drivers/sound/soundvers.h | 2 +- drivers/sound/uart401.c | 3 +- fs/Config.in | 2 +- fs/buffer.c | 16 +- fs/coda/file.c | 13 +- fs/coda/namecache.c | 18 +- fs/coda/psdev.c | 2 +- fs/coda/sysctl.c | 9 + fs/lockd/svcsubs.c | 64 +- fs/namei.c | 20 +- fs/nfs/dir.c | 130 +- fs/nfsd/lockd.c | 6 + fs/nfsd/vfs.c | 94 +- fs/pipe.c | 2 +- fs/proc/array.c | 2 + fs/select.c | 268 ++-- fs/sysv/namei.c | 188 +-- fs/ufs/ufs_namei.c | 2 +- fs/ufs/ufs_super.c | 5 +- fs/ufs/ufs_symlink.c | 2 +- include/asm-alpha/byteorder.h | 2 +- include/asm-alpha/posix_types.h | 1 + include/asm-alpha/signal.h | 20 + include/asm-alpha/socket.h | 5 + include/asm-i386/byteorder.h | 2 +- include/asm-i386/posix_types.h | 1 + include/asm-i386/signal.h | 22 +- include/asm-i386/system.h | 10 +- include/asm-m68k/byteorder.h | 2 +- include/asm-m68k/posix_types.h | 1 + include/asm-mips/byteorder.h | 4 +- include/asm-mips/posix_types.h | 1 + include/asm-ppc/byteorder.h | 10 +- include/asm-ppc/posix_types.h | 1 + include/asm-sparc/byteorder.h | 2 +- include/asm-sparc/posix_types.h | 1 + include/asm-sparc64/byteorder.h | 2 +- include/asm-sparc64/posix_types.h | 3 + .../big_endian.h} | 4 +- .../generic.h} | 167 +- .../little_endian.h} | 4 +- include/linux/byteorder/swab.h | 155 ++ include/linux/byteorder/swabb.h | 122 ++ .../vax_endian.h} | 39 +- include/linux/coda.h | 8 + include/linux/coda_cnode.h | 8 + include/linux/coda_opstats.h | 39 +- include/linux/coda_sysctl.h | 8 + include/linux/console.h | 4 +- include/linux/fs.h | 2 +- include/linux/pi2.h | 130 -- include/linux/poll.h | 105 ++ include/linux/pt.h | 174 -- include/linux/sched.h | 16 - include/linux/soundcard.h | 1 + include/linux/sysv_fs.h | 19 +- include/linux/time.h | 7 +- include/linux/tty_ldisc.h | 3 +- include/linux/types.h | 1 + include/linux/wait.h | 12 - init/main.c | 6 + ipc/msg.c | 8 +- ipc/sem.c | 4 +- ipc/shm.c | 8 +- ipc/util.c | 9 +- kernel/itimer.c | 19 +- kernel/printk.c | 23 +- kernel/sched.c | 14 +- kernel/time.c | 35 +- linux/include/linux/dmascc.h | 43 + net/Config.in | 2 + net/core/dev.c | 12 +- net/core/sock.c | 6 +- net/ipv4/tcp_ipv4.c | 23 +- scripts/Menuconfig | 127 +- 121 files changed, 4978 insertions(+), 1864 deletions(-) create mode 100644 Documentation/filesystems/coda.txt create mode 100644 drivers/net/dmascc.c rename include/linux/{byteorder_big_endian.h => byteorder/big_endian.h} (96%) rename include/linux/{byteorder_generic.h => byteorder/generic.h} (54%) rename include/linux/{byteorder_little_endian.h => byteorder/little_endian.h} (96%) create mode 100644 include/linux/byteorder/swab.h create mode 100644 include/linux/byteorder/swabb.h rename include/linux/{byteorder_vaxendian.h => byteorder/vax_endian.h} (72%) delete mode 100644 include/linux/pi2.h delete mode 100644 include/linux/pt.h create mode 100644 linux/include/linux/dmascc.h diff --git a/CREDITS b/CREDITS index 7a6aa067f06b..c6ffedf911ee 100644 --- a/CREDITS +++ b/CREDITS @@ -1342,6 +1342,14 @@ E: dl1bke@db0pra.ampr.org D: Generic Z8530 driver, AX.25 DAMA slave implementation D: Several AX.25 hacks +N: Francois-Rene Rideau +E: rideau@ens.fr +W: http://www.eleves.ens.fr:8080/home/rideau/ +D: petty kernel janitor (byteorder, ufs) +S: 6, rue Augustin Thierry +S: 75019 Paris +S: France + N: William E. Roadcap E: roadcapw@cfw.com W: http://www.cfw.com/~roadcapw diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 8e22e578e93a..d0b46f4e3d1f 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -1494,9 +1494,9 @@ CONFIG_SKB_LARGE a second or satellite links this option will make no difference to performance. -BSD Unix domain sockets +Unix domain sockets CONFIG_UNIX - Y if you want BSD Unix domain sockets. Unless you are working on an + Y if you want Unix domain sockets. Unless you are working on an embedded system or somthing, you probably want to say Y. If you try building this as a module and you are running kerneld, you need to make sure and add 'alias net-pf-1 unix' to your /etc/conf.module file. @@ -2795,6 +2795,28 @@ CONFIG_SCC running kernel whenever you want), say M here and read Documentation/modules.txt. The module will be called scc.o. +High-speed (DMA) SCC driver for AX.25 +CONFIG_DMASCC + This is a driver for high-speed SCC boards, i.e. those supporting + DMA on one port. Currently, only Ottawa PI/PI2 boards (see + http://hydra.carleton.ca/info/pi2.html) and Gracilis PackeTwin + boards (see http://www.paccomm.com/) are supported and detected + automatically. Multiple boards are operated simultaneously. If + you compile this driver as a module, it will be called dmascc.o. + If you don't give any parameter to the driver, all possible I/O + addresses are probed. This could irritate other devices that are + currently not in use. You may specify the list of addresses to be + probed by "dmascc=addr1,addr2,..." (when compiled into the kernel + image) or "io=addr1,addr2,..." (when loaded as a module). + The network interfaces will be called dmascc0 and dmascc1 for the + board detected first, dmascc2 and dmascc3 for the second one, and + so on. Before you configure each interface with ifconfig, you MUST + set certain parameters, such as channel access timing, clock mode, + and DMA channel. This is accomplished with a small utility program + called dmascc_cfg, which is part of the ax25-utils package. + Alternatively, you may download the utility from + http://www.oevsv.at/~oe1kib/Linux.html. + BAYCOM picpar and par96 driver for AX.25 CONFIG_BAYCOM_PAR This is a driver for Baycom style simple amateur radio @@ -3583,36 +3605,6 @@ CONFIG_NI65 read the Multiple-Ethernet-mini-HOWTO, available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. -Ottawa PI and PI/2 support -CONFIG_PI - This is a driver for the Ottawa Amateur Radio Club PI and PI2 cards, - which are commonly used to send internet traffic over amateur radio. - More information about these cards is on the WWW at - http://hydra.carleton.ca/info/pi2.html (To browse the WWW, you need - to have access to a machine on the Internet that has a program like - lynx or netscape). If you have one of these cards, you can say Y - here and should read the HAM-HOWTO, available via ftp (user: - anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Also, you - should have said Y to "AX.25 support" above, because AX.25 is the - protocol used for digital traffic over radio links. 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 pi2.o. - -Gracilis PackeTwin support -CONFIG_PT - This is a card used mainly by amateur radio operators for packet - radio. You should have already said Y to "AX.25 support" as this - card uses that protocol. More information about this driver can be - found in the file drivers/net/README.pt. NOTE: The card is capable - of DMA and full duplex but neither of these have been coded in the - driver as yet. This driver is also available as a module ( = 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 as well as - Documentation/networking/net-modules.txt. The module will be called - pt.o. - AT&T WaveLAN & DEC RoamAbout DS support CONFIG_WAVELAN The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS) is diff --git a/Documentation/devices.tex b/Documentation/devices.tex index 4604ce744dad..cbca534338bc 100644 --- a/Documentation/devices.tex +++ b/Documentation/devices.tex @@ -4,7 +4,7 @@ % pages to print... :-) If you're actually putting this in print, you % may wish to change these. % -% $Id: devices.tex,v 1.28 1997/11/12 23:59:41 davem Exp $ +% $Id: devices.tex,v 1.4 1997/12/05 01:34:21 hpa Exp $ % \oddsidemargin=0in \textwidth=6.5in @@ -50,7 +50,7 @@ foo \kill}% % \title{{\bf Linux Allocated Devices}} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} -\date{Last revised: November 9, 1997} +\date{Last revised: December 4, 1997} \maketitle % \noindent @@ -193,8 +193,11 @@ Your cooperation is appreciated. \major{44}{}{char }{isdn4linux virtual modem -- alternate devices} \major{ }{}{block}{Flash Translation Layer (FTL) filesystems} \major{45}{}{char }{isdn4linux ISDN BRI driver} +\major{ }{}{block}{Reserved for parallel port IDE disk} \major{46}{}{char }{Comtrol Rocketport serial card} +\major{ }{}{block}{Reserved for parallel port ATAPI CD-ROM} \major{47}{}{char }{Comtrol Rocketport serial card -- alternate devices} +\major{ }{}{block}{Reserved for parallel port ATAPI disk} \major{48}{}{char }{SDL RISCom serial card} \major{49}{}{char }{SDL RISCom serial card -- alternate devices} \major{50}{}{char }{Reserved for GLINT} @@ -240,7 +243,8 @@ Your cooperation is appreciated. \major{93}{}{char }{IBM Smart Capture Card frame grabber} \major{94}{}{char }{miroVIDEO DC10/30 capture/playback device} \major{95}{}{char }{IP Filter} -\major{96}{--119}{}{Unallocated} +\major{96}{}{char }{Reserved for parallel port ATAPI tape} +\major{97}{--119}{}{Unallocated} \major{120}{--127}{}{Local/experimental use} \major{128}{--239}{}{Unallocated} \major{240}{--254}{}{Local/experimental use} @@ -407,15 +411,15 @@ Linux. To ensure proper operation, do not mix old and new PTY devices. \begin{devicelist} \major{ 5}{}{char }{Alternate TTY devices} \minor{0}{/dev/tty}{Current TTY device} - \minor{1}{}{Reserved for console device} + \minor{1}{/dev/console}{System console} \minor{64}{/dev/cua0}{Callout device corresponding to {\file ttyS0}} \minordots \minor{127}{/dev/cua63}{Callout device corresponding to {\file ttyS63}} \end{devicelist} \noindent -Minor number 1 is reserved for a kernel-managed -{\file /dev/console} in a future version of Linux. +(5,1) is {\file /dev/console} starting with Linux 2.1.71. See the +section on terminal devices for more information on {\file /dev/console}. \begin{devicelist} \major{ 6}{}{char }{Parallel printer devices} @@ -550,6 +554,7 @@ physical disks. \minor{149}{/dev/input/mouse}{Linux/SGI Irix emulation mouse} \minor{150}{/dev/input/keyboard}{Linux/SGI Irix emulation keyboard} \minor{151}{/dev/led}{Front panel LEDs} + \minor{152}{/dev/radio}{Radio card (type?)} \end{devicelist} \begin{devicelist} @@ -797,30 +802,30 @@ major number 3). \begin{devicelist} \major{27}{}{char }{QIC-117 tape} - \minor{0}{/dev/qft0}{Unit 0, rewind-on-close} - \minor{1}{/dev/qft1}{Unit 1, rewind-on-close} - \minor{2}{/dev/qft2}{Unit 2, rewind-on-close} - \minor{3}{/dev/qft3}{Unit 3, rewind-on-close} - \minor{4}{/dev/nqft0}{Unit 0, no rewind-on-close} - \minor{5}{/dev/nqft1}{Unit 1, no rewind-on-close} - \minor{6}{/dev/nqft2}{Unit 2, no rewind-on-close} - \minor{7}{/dev/nqft3}{Unit 3, no rewind-on-close} - \minor{16}{/dev/zqft0}{Unit 0, rewind-on-close, compression} - \minor{17}{/dev/zqft1}{Unit 1, rewind-on-close, compression} - \minor{18}{/dev/zqft2}{Unit 2, rewind-on-close, compression} - \minor{19}{/dev/zqft3}{Unit 3, rewind-on-close, compression} - \minor{20}{/dev/nzqft0}{Unit 0, no-rewind-on-close, compression} - \minor{21}{/dev/nzqft1}{Unit 1, no-rewind-on-close, compression} - \minor{22}{/dev/nzqft2}{Unit 2, no-rewind-on-close, compression} - \minor{23}{/dev/nzqft3}{Unit 3, no-rewind-on-close, compression} - \minor{32}{/dev/rawft0}{Unit 0, rewind-on-close, no file marks} - \minor{33}{/dev/rawft1}{Unit 1, rewind-on-close, no file marks} - \minor{34}{/dev/rawft2}{Unit 2, rewind-on-close, no file marks} - \minor{35}{/dev/rawft3}{Unit 3, rewind-on-close, no file marks} - \minor{36}{/dev/zqft0}{Unit 0, no-rewind-on-close, no file marks} - \minor{37}{/dev/zqft1}{Unit 1, no-rewind-on-close, no file marks} - \minor{38}{/dev/zqft2}{Unit 2, no-rewind-on-close, no file marks} - \minor{39}{/dev/zqft3}{Unit 3, no-rewind-on-close, no file marks} + \minor{0}{/dev/qft0}{Unit 0, rewind-on-close} + \minor{1}{/dev/qft1}{Unit 1, rewind-on-close} + \minor{2}{/dev/qft2}{Unit 2, rewind-on-close} + \minor{3}{/dev/qft3}{Unit 3, rewind-on-close} + \minor{4}{/dev/nqft0}{Unit 0, no rewind-on-close} + \minor{5}{/dev/nqft1}{Unit 1, no rewind-on-close} + \minor{6}{/dev/nqft2}{Unit 2, no rewind-on-close} + \minor{7}{/dev/nqft3}{Unit 3, no rewind-on-close} + \minor{16}{/dev/zqft0}{Unit 0, rewind-on-close, compression} + \minor{17}{/dev/zqft1}{Unit 1, rewind-on-close, compression} + \minor{18}{/dev/zqft2}{Unit 2, rewind-on-close, compression} + \minor{19}{/dev/zqft3}{Unit 3, rewind-on-close, compression} + \minor{20}{/dev/nzqft0}{Unit 0, no rewind-on-close, compression} + \minor{21}{/dev/nzqft1}{Unit 1, no rewind-on-close, compression} + \minor{22}{/dev/nzqft2}{Unit 2, no rewind-on-close, compression} + \minor{23}{/dev/nzqft3}{Unit 3, no rewind-on-close, compression} + \minor{32}{/dev/rawqft0}{Unit 0, rewind-on-close, no file marks} + \minor{33}{/dev/rawqft1}{Unit 1, rewind-on-close, no file marks} + \minor{34}{/dev/rawqft2}{Unit 2, rewind-on-close, no file marks} + \minor{35}{/dev/rawqft3}{Unit 3, rewind-on-close, no file marks} + \minor{36}{/dev/nrawqft0}{Unit 0, no rewind-on-close, no file marks} + \minor{37}{/dev/nrawqft1}{Unit 1, no rewind-on-close, no file marks} + \minor{38}{/dev/nrawqft2}{Unit 2, no rewind-on-close, no file marks} + \minor{39}{/dev/nrawqft3}{Unit 3, no rewind-on-close, no file marks} \\ \major{ }{}{block}{Third Matsushita (Panasonic/SoundBlaster) CD-ROM} \minor{0}{/dev/sbpcd8}{Panasonic CD-ROM controller 2 unit 0} @@ -1629,8 +1634,7 @@ It is recommended that these links exist on all systems: \begin{nodelist} \link{/dev/core}{/proc/kcore}{symbolic}{Backward compatibility} \link{/dev/ramdisk}{ram0}{symbolic}{Backward compatibility} -\link{/dev/rft0}{qft0}{symbolic}{Backward compatibility} -\link{/dev/ftape}{rft0}{symbolic}{Backward compatibility} +\link{/dev/ftape}{qft0}{symbolic}{Backward compatibility} \link{/dev/scd?}{sr?}{hard}{Alternate name for CD-ROMs} \link{/dev/fd?D*}{fd?u*}{hard}{Backward compatibility} \link{/dev/fd?H*}{fd?u*}{hard}{Backward compatibility} @@ -1715,10 +1719,11 @@ purpose. The {\em console device\/}, {\file /dev/console}, is the device to which system messages should be sent, and on which logins should be -permitted in single-user mode. {\file /dev/console} should be a -symbolic link to either {\file /dev/tty0}, a specific virtual console -such as {\file /dev/tty1}, or to a serial port primary ({\file tty}) -device, depending on the configuration of the system. +permitted in single-user mode. Starting with Linux 2.1.71, {\file +/dev/console} is managed by the kernel; for previous versions it +should be a symbolic link to either {\file /dev/tty0}, a specific +virtual console such as {\file /dev/tty1}, or to a serial port primary +({\file tty}) device, depending on the configuration of the system. \subsection{Serial ports} diff --git a/Documentation/devices.txt b/Documentation/devices.txt index 86799025bf1d..3f229ff41ed1 100644 --- a/Documentation/devices.txt +++ b/Documentation/devices.txt @@ -1,7 +1,7 @@ LINUX ALLOCATED DEVICES Maintained by H. Peter Anvin - Last revised: November 9, 1997 + Last revised: December 4, 1997 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -191,13 +191,14 @@ Your cooperation is appreciated. 5 char Alternate TTY devices 0 = /dev/tty Current TTY device - 1 Reserved for console device + 1 = /dev/console System console 64 = /dev/cua0 Callout device corresponding to ttyS0 ... 127 = /dev/cua63 Callout device corresponding to ttyS63 - Minor number 1 is reserved for a kernel-managed - /dev/console in a future version of Linux. + (5,1) is /dev/console starting with Linux 2.1.71. See + the section on terminal devices for more information + on /dev/console. 6 char Parallel printer devices 0 = /dev/lp0 First parallel printer (0x3bc) @@ -315,6 +316,7 @@ Your cooperation is appreciated. 149 = /dev/input/mouse Linux/SGI Irix emulation mouse 150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard 151 = /dev/led Front panel LEDs + 152 = /dev/radio Radio card (type?) 11 char Raw keyboard device 0 = /dev/kbd Raw keyboard device @@ -515,22 +517,22 @@ Your cooperation is appreciated. 5 = /dev/nqft1 Unit 1, no rewind-on-close 6 = /dev/nqft2 Unit 2, no rewind-on-close 7 = /dev/nqft3 Unit 3, no rewind-on-close - 16 = /dev/zqft0 Unit 0, rewind-on-close, compression - 17 = /dev/zqft1 Unit 1, rewind-on-close, compression - 18 = /dev/zqft2 Unit 2, rewind-on-close, compression - 19 = /dev/zqft3 Unit 3, rewind-on-close, compression - 20 = /dev/nzqft0 Unit 0, no-rewind, compression - 21 = /dev/nzqft1 Unit 1, no-rewind, compression - 22 = /dev/nzqft2 Unit 2, no-rewind, compression - 23 = /dev/nzqft3 Unit 3, no-rewind, compression - 32 = /dev/rawft0 Unit 0, rewind-on-close, no file marks - 33 = /dev/rawft1 Unit 1, rewind-on-close, no file marks - 34 = /dev/rawft2 Unit 2, rewind-on-close, no file marks - 35 = /dev/rawft3 Unit 3, rewind-on-close, no file marks - 36 = /dev/zqft0 Unit 0, no-rewind, no file marks - 37 = /dev/zqft1 Unit 1, no-rewind, no file marks - 38 = /dev/zqft2 Unit 2, no-rewind, no file marks - 39 = /dev/zqft3 Unit 3, no-rewind, no file marks + 16 = /dev/zqft0 Unit 0, rewind-on-close, compression + 17 = /dev/zqft1 Unit 1, rewind-on-close, compression + 18 = /dev/zqft2 Unit 2, rewind-on-close, compression + 19 = /dev/zqt3 Unit 3, rewind-on-close, compression + 20 = /dev/nzqft0 Unit 0, no rewind-on-close, compression + 21 = /dev/nzqft1 Unit 1, no rewind-on-close, compression + 22 = /dev/nzqft2 Unit 2, no rewind-on-close, compression + 23 = /dev/nzqft3 Unit 3, no rewind-on-close, compression + 32 = /dev/rawqft0 Unit 0, rewind-on-close, no file marks + 33 = /dev/rawqft1 Unit 1, rewind-on-close, no file marks + 34 = /dev/rawqft2 Unit 2, rewind-on-close, no file marks + 35 = /dev/rawqft3 Unit 3, rewind-on-close, no file marks + 32 = /dev/nrawqft0 Unit 0, no rewind-on-close, no file marks + 33 = /dev/nrawqft1 Unit 1, no rewind-on-close, no file marks + 34 = /dev/nrawqft2 Unit 2, no rewind-on-close, no file marks + 35 = /dev/nrawqft3 Unit 3, no rewind-on-close, no file marks block Third Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd8 Panasonic CD-ROM controller 2 unit 0 1 = /dev/sbpcd9 Panasonic CD-ROM controller 2 unit 1 @@ -1153,7 +1155,6 @@ It is recommended that these links exist on all systems: /dev/core /proc/kcore symbolic Backward compatibility /dev/ramdisk ram0 symbolic Backward compatibility -/dev/rft0 qft0 symbolic Backward compatibility /dev/ftape qft0 symbolic Backward compatibility /dev/scd? sr? hard Alternate SCSI CD-ROM name @@ -1228,9 +1229,10 @@ for this purpose. The console device, /dev/console, is the device to which system messages should be sent, and on which logins should be permitted in -single-user mode. /dev/console should be a symbolic link to either -/dev/tty0, a specific virtual console such as /dev/tty1, or to a -serial port primary (tty*, not cu*) device, depending on the +single-user mode. Starting with Linux 2.1.71, /dev/console is managed +by the kernel; for previous versions it should be a symbolic link to +either /dev/tty0, a specific virtual console such as /dev/tty1, or to +a serial port primary (tty*, not cu*) device, depending on the configuration of the system. Serial ports diff --git a/Documentation/filesystems/coda.txt b/Documentation/filesystems/coda.txt new file mode 100644 index 000000000000..829fd2d206c4 --- /dev/null +++ b/Documentation/filesystems/coda.txt @@ -0,0 +1,1427 @@ + The Venus kernel interface + Peter J. Braam + v1.0, Nov 9, 1997 + + This document describes the communication between Venus and kernel + level file system code needed for the operation of the Coda filesys- + tem. This version document is meant to describe the current interface + (version 1.0) as well as improvements we envisage. + ______________________________________________________________________ + + Table of Contents: + + 1. Introduction + + 2. Servicing Coda filesystem calls + + 3. The message layer + + 3.1. Implementation details + + 4. The interface at the call level + + 4.1. Data structures shared by the kernel and Venus + + 4.2. The pioctl interface + + 4.3. root + + 4.4. lookup + + 4.5. getattr + + 4.6. setattr + + 4.7. access + + 4.8. create + + 4.9. mkdir + + 4.10. link + + 4.11. synlink + + 4.12. remove + + 4.13. rmdir + + 4.14. readlink + + 4.15. open + + 4.16. close + + 4.17. ioctl + + 4.18. rename + + 4.19. readdir + + 4.20. vget + + 4.21. fsync + + 4.22. inactive + + 4.23. rdwr + + 4.24. odymount + + 4.25. ody_lookup + + 4.26. ody_expand + + 4.27. prefetch + + 4.28. signal + + 5. The minicache and downcalls + + 5.1. INVALIDATE + + 5.2. FLUSH + + 5.3. PURGEUSER + + 5.4. ZAPFILE + + 5.5. ZAPDIR + + 5.6. ZAPVNODE + + 5.7. PURGEFID + + 5.8. REPLACE + + 6. Initialization and cleanup + + 6.1. Requirements + ______________________________________________________________________ + 0wpage + + 11.. IInnttrroodduuccttiioonn + + A key component in the Coda Distributed File System is the cache + manager, _V_e_n_u_s. + + When processes on a Coda enabled system access files in the Coda + filesystem, requests are directed at the filesystem layer in the + operating system. The operating system will communicate with Venus to + service the request for the process. Venus manages a persistent + client cache and makes remote procedure calls to Coda file servers and + related servers (such as authentication servers) to service these + requests it receives from the operating system. When Venus has + serviced a request it replies to the operating system with appropiate + return codes, and other data related to the request. Optionally the + kernel support for Coda may maintain a minicache of recently processed + requests to limit the number of interactions with Venus. Venus + possesses the facility to inform the kernel when elements from its + minicache are no longer valid. + + This document describes precisely this communication between the + kernel and Venus. The definitions of so called upcalls and downcalls + will be given with the format of the data they handle. We shall also + describe the semantic invariants resulting from the calls. + + Historically Coda was implemented in a BSD file system in Mach 2.6. + The interface between the kernel and Venus is very similar to the BSD + VFS interface. Similar functionality is provided, and the format of + the parameters and returned data is very similar to the BSD VFS. This + leads to an almost natural environment for implementing a kernel level + filesystem driver for Coda in a BSD system. However, other operating + systems such as Linux and Windows 95 and NT have virtual filesystem + with different interfaces. + + To implement Coda on these systems some reverse engineering of the + Venus/Kernel protocol is necessary. Also it came to light that other + systems could profit significantly from certain small optimizations + and modifications to the protocol. To facilitate this work as well as + to make future ports easier, communication between Venus and the + kernel should be documented in great detail. This is the aim of this + document. + + 0wpage + + 22.. SSeerrvviicciinngg CCooddaa ffiilleessyysstteemm ccaallllss + + The service of a request for a Coda file system service originates in + a process PP which accessing a Coda file. It makes a system call which + traps to the OS kernel. Examples of such calls trapping to the kernel + are _r_e_a_d_, _w_r_i_t_e_, _o_p_e_n_, _c_l_o_s_e_, _c_r_e_a_t_e_, _m_k_d_i_r_, _r_m_d_i_r_, _c_h_m_o_d in a Unix + context. Similar calls exist in the Win32 environment, and are named + _C_r_e_a_t_e_F_i_l_e_, . + + Generally the operating system handles the request in a virtual + filesystem (VFS) layer, which is named I/O Manager in NT and IFS + manager in Windows 95. The VFS is responsible for partial processing + of the request and for locating the specific filesystem(s) which will + service parts of the request. Usually the information in the path + assists in locating the correct FS drivers. Sometimes after extensive + pre-processing, the VFS starts invoking exported routines in the FS + driver. This is the point where the FS specific processing of the + request starts, and here the Coda specific kernel code comes into + play. + + The FS layer for Coda must expose and implement several interfaces. + First and foremost the VFS must be able to make all necessary calls to + the Coda FS layer, so the Coda FS driver must expose the VFS interface + as applicable in the operating system. These differ very significantly + among operating systems, but share features such as facilities to + read/write and create and remove object. The Coda FS layer services + such VFS requests in by invoking on or more well defined services + offered by the cache manager Venus. When the replies from Venus have + come back to the FS driver, servicing of the VFS call continues and + finishes with a reply to the kernels VFS. Finally the VFS layer + returns to the process. + + As a result of this design a basic interface exposed by the FS driver + must allow Venus to handle manage message traffic. In particular + Venus must be able to retrieve and place messages and to be notified + of the arrival of a new message. The notification must be through a + mechanism which does not block Venus since Venus must attend to other + tasks even when no messages are waiting or being processed. + + Interfaces of Coda FS Driver + + Furthermore the FS layer provides for a special path of communication + between a user process and Venus, called the pioctl interface. The + pioctl interface is used for Coda specific services, such as + requesting detailed information about the persistent cache managed by + Venus. Here the involvement of the kernel is minimal. It identifies + the calling process and passes the information on to Venus. When + Venus replies the response is passed back to the caller in unmodified + form. + + Finally Venus allows the kernel FS driver to cache the results from + certain services. This is done to avoid excessive context switches + and results in an efficient system. However, Venus may acquire + information, for example from the network which implies that cached + information must be flushed or replaced. Venus then makes a downcall + to the Coda FS layer to request flushes or updates in the cache. The + kernel FS driver handles such requests synchronously. + + Among these interfaces the VFS interface and the facility to place, + receive and be notified of messages are platform specific. We will + not go into the calls exported to the VFS layer but we will state the + requirements of the message exchange mechanism. + + 0wpage + + 33.. TThhee mmeessssaaggee llaayyeerr + + At the lowest level the communication between Venus and the FS driver + proceeds through messages. The synchronization of between processes + requesting Coda file service and Venus relies on blocking and waking + up processes. The Coda FS driver processes VFS- and pioctl-requests + on behalf of a process P, creates messages for Venus, awaits replies + and finally returns to the caller. The implementation of the exchange + of messages is platform specific, but the semantics have (so far) + appeared to be generally applicable. Data buffers are created by the + FS Driver in kernel memory on behalf of P and copied to user memory in + Venus. + + The FS Driver while servicing P makes upcall's to Venus. Such an + upcall is dispatched to Venus by creating a message structure. The + structure contains the identification of P, the message sequence + number, the size of the request and a pointer to the data in kernel + memory for the request. Since the data buffer is re-used to hold the + reply from Venus, there is a field for the size of the reply. A flags + field is used in the message to precisely record the status of the + message. Additional platform dependent structures involve pointers to + determine the position of the message on queues and pointers to + synchronization objects. In the upcall routine the message structure + is filled in, flags are set to 0, and it is placed on the _p_e_n_d_i_n_g + queue. The routine calling upcall is responsible for allocating the + data buffer; it's structure will be described in the next section. + + A facility must exist to notify Venus that the message has been + created, and implemented using available synchronization objects in + the OS. This notification is done in the upcall context of the process + P. When the message is on the pending queue, process P cannot proceed + in upcall. The (kernel mode) processing of P in the filesystem + request routine must be suspended until Venus has replied. Therefore + the calling thread in P is blocked in upcall. A pointer in the + message structure will locate the synchronization object on which P is + sleeping. + + Venus detects the notification that a message has arrived, and the FS + driver allow Venus to retrieve the message with a getmsg_from_kernel + call. This action finishes in the kernel by putting the message on the + queue of processing messages and setting flags to READ. Venus is + passed the contents of the data buffer. The getmsg_from_kernel call + now returns and Venus processes the request. + + At some later point the FS driver receives a message from Venus, + namely when Venus calls sendmsg_to_kernel. At this moment the Coda FS + driver looks at the contents of the message and decides if: + + +o the message is a reply for a suspended thread P. If so it removes + the message from the processing queue and marks the message as + WRITTEN. Finally, the FS driver unblocks P (still in the kernel + mode context of Venus) and the sendmsg_to_kernel call returns to + Venus. The process P will be scheduled at some point and continues + processing its upcall with the data buffer replaced with the reply + from Venus. + + +o The message is a _d_o_w_n_c_a_l_l. A downcall is a request from Venus to + the FS Driver. The FS driver processes the request immediately + (usually a cach eviction or replacement) and when finishes + sendmsg_to_kernel returns. + + Now P awakes and continues processing upcall. There are some + subtleties to take account off. First P will determine if it was woken + up in upcall by a signal from some other source (for example an + attempt to terminate P) or as is normally the case by Venus in its + sendmsg_to_kernel call. In the normal case, the upcall routine will + deallocate message structure and return. The FS routine can proceed + with its processing. + + Sleeping and IPC arrangements + + In case P is woken up by a signal and not by Venus, it will first look + at the flags field. If the message is not yet READ, the process P can + handle it's signal without notifying Venus. If Venus has READ, and + the request should not be processed, P can send Venus a signal message + to indicate that it should disregard the previous message. Such + signals are put in the queue at the head, and read first by Venus. If + the message is already marked as WRITTEN it is too late to stop the + processing. The VFS routine will now continue. (-- If a VFS request + involves more than one upcall, this can lead to complicated state, an + extra field "handle_signals" could be added in the message structure + to indicate points of no return have been passed.--) + + 33..11.. IImmpplleemmeennttaattiioonn ddeettaaiillss + + The Unix implementation of this mechanism has been through the + implemenation of a character device associated with Coda. Venus + retrieves messages by doing a read on the device, replies are sent + with a write and notification is through the select system call on the + file descriptor for the device. The process P is kept waiting on an + interruptible wait queue object. + + In Windows NT and the DPMI Windows 95 implementation a DeviceIoControl + call is used. The DeviceIoControl call is designed to copy buffers + from user memory to kernel memory with OPCODES. The sendmsg_to_kernel + is issued as a synchronous call, while the getmsg_from_kernel call is + asynchrounous. Windows EventObjects are used for notification of + message arrival. The process P is kept waiting on a KernelEvent + object in NT and a semaphore in Windows 95. + + 0wpage + + 44.. TThhee iinntteerrffaaccee aatt tthhee ccaallll lleevveell + + This section describes the upcalls a Coda FS driver can make to Venus. + Each of these upcalls make use of two structures: inputArgs and + outputArgs. In pseudo BNF form the structures take the following + form: + + struct inputArgs { + u_long opcode; + u_long unique; /* Keep multiple outstanding msgs distinct */ + u_short pid; /* Common to all */ + u_short pgid; /* Common to all */ + struct CodaCred cred; /* Common to all */ + + + }; + + struct outputArgs { + u_long opcode; + u_long unique; /* Keep multiple outstanding msgs distinct */ + u_long result; + + + }; + + Before going on let us elucidate the role of the various fields. The + inputArgs start with the opcode which defines the type of service + requested from Venus. There are approximately 30 upcalls at present + which we will discuss. The unique field labels the inputArg with + unique number which will identify the message uniquely. A process and + process group id are passed. Finally the credentials of the caller + are included. + + Before delving into the specific calls we need to discuss a variety of + data structures shared by the kernel and Venus. + + 44..11.. DDaattaa ssttrruuccttuurreess sshhaarreedd bbyy tthhee kkeerrnneell aanndd VVeennuuss + + The CodaCred structure defines a variety of user and group id's as + they are set for the calling process. The vuid_t and guid_t are 32 bit + unsigned integers. It also defines group member ship in an array. On + Unix the CodaCred has proven sufficient to implement good security + semantics for Coda but the structure may have to undergo modification + for the Windows environment when these mature. + + struct CodaCred { + vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/ + vgid_t cr_gid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */ + vgid_t cr_groups[NGROUPS]; /* Group membership for caller */ + }; + + NNOOTTEE It is questionable if we need CodaCreds in Venus. Finally Venus + doesn't know about groups, although it does create files with the + default uid/gid. Perhaps the list of group membership is superfluous. + + The next item is the fundamental identifier used to identify Coda + files, the ViceFid. A fid of a file uniquely defines a file or + directory in the Coda filesystem within a _c_e_l_l. (-- A _c_e_l_l is a + group of Coda servers acting under the aegis of a single system + control machine or SCM. See the Coda Administration manual for a + detailed description of the role of the SCM.--) + + typedef struct ViceFid { + VolumeId Volume; + VnodeId Vnode; + Unique_t Unique; + } ViceFid; + + Each of the constituent fields: VolumeId, VnodeId and Unique_t are + unsigned 32 bit integers. We envisage that a further field will need + to be prefixed to identify the Coda cell; this will probably take the + form of a Ipv6 size IP address naming the Coda cell through DNS. + + The next important structure shared between Venus and the kernel are + the attributes of the file. The following structure is used to + exchange information. It has room for future extensions such as + support for device files (currently not present in Coda). + + struct coda_vattr { + enum coda_vtype va_type; /* vnode type (for create) */ + u_short va_mode; /* files access mode and type */ + short va_nlink; /* number of references to file */ + vuid_t va_uid; /* owner user id */ + vgid_t va_gid; /* owner group id */ + long va_fsid; /* file system id (dev for now) */ + long va_fileid; /* file id */ + u_quad_t va_size; /* file size in bytes */ + long va_blocksize; /* blocksize preferred for i/o */ + struct timespec va_atime; /* time of last access */ + struct timespec va_mtime; /* time of last modification */ + struct timespec va_ctime; /* time file changed */ + u_long va_gen; /* generation number of file */ + u_long va_flags; /* flags defined for file */ + dev_t va_rdev; /* device special file represents */ + u_quad_t va_bytes; /* bytes of disk space held by file */ + u_quad_t va_filerev; /* file modification number */ + u_int va_vaflags; /* operations flags, see below */ + long va_spare; /* remain quad aligned */ + }; + + 44..22.. TThhee ppiiooccttll iinntteerrffaaccee + + Coda specific requests can be made by application through a pioctl + interface. The pioctl is implemented as an ordinary ioctl on a + ficticious file /coda/.CONTROL. The piocl call opens this file, gets + a file handle and makes the ioctl call. Finally it closes the file. + + The kernel involvement in this is limited to providing the facility to + open and close and pass the ioctl message _a_n_d to verify that a path in + the pioctl data buffers is a file in a Coda filesystem. + + The kernel is handed a data packet of the form: + + struct { + const char *path; + struct ViceIoctl vidata; + int follow; + } data; + + where + + struct ViceIoctl { + caddr_t in, out; /* Data to be transferred in, or out */ + short in_size; /* Size of input buffer <= 2K */ + short out_size; /* Maximum size of output buffer, <= 2K */ + }; + + The path must be a Coda file, otherwise the ioctl upcall will not be + made. + + NNOOTTEE The data structures and code are a mess. We need to clean this + up. + + We now proceed to document the individual calls: + + 0wpage + + 44..33.. rroooott + + AArrgguummeennttss + + iinn empty + + oouutt + + struct cfs_root_out { + ViceFid VFid; + } cfs_root; + + DDeessccrriippttiioonn This call is made to Venus during the initialization of + the Coda filesystem. If the result is zero, the cfs_root structure + contains the ViceFid of the root of the Coda filesystem. If a non-zero + result is generated, its value is a platform dependent error code + indicating the difficulty Venus encountered in locating the root of + the Coda filesystem. + + 0wpage + + 44..44.. llooookkuupp + + SSuummmmaarryy Find the ViceFid and type of an object in a directory if it + exists. + + AArrgguummeennttss + + iinn + + struct cfs_lookup_in { + ViceFid VFid; + char *name; /* Place holder for data. */ + } cfs_lookup; + + oouutt + + struct cfs_lookup_out { + ViceFid VFid; + int vtype; + } cfs_lookup; + + DDeessccrriippttiioonn This call is made to determine the ViceFid and filetype of + a directory entry. The directory entry requested carries name name + and Venus will search the directory identified by cfs_lookup_in.VFid. + The result may indicate that the name does not exist, or that + difficulty was encountered in finding it (e.g. due to disconnection). + If the result is zero, the field cfs_lookup_out.VFid contains the + targets ViceFid and cfs_lookup_out.vtype the coda_vtype giving the + type of object the name designates. + + The name of the object is an 8 bit character string of maximum length + CFS_MAXNAMLEN, currently set to 256 (including a 0 terminator.) + + It is extremely important to realize that Venus bitwise or's the field + cfs_lookup.vtype with CFS_NOCACHE to indicate that the object should + not be put in the kernel name cache. + + NNOOTTEE The type of the vtype is currently wrong. It should be + coda_vtype. Linux does not take note of CFS_NOCACHE. It should. + + 0wpage + + 44..55.. ggeettaattttrr + + SSuummmmaarryy Get the attributes of a file. + + AArrgguummeennttss + + iinn + + struct cfs_getattr_in { + ViceFid VFid; + struct coda_vattr attr; /* XXXXX */ + } cfs_getattr; + + oouutt + + struct cfs_getattr_out { + struct coda_vattr attr; + } cfs_getattr; + + DDeessccrriippttiioonn This call returns the attributes of the file identified by + fid. + + EErrrroorrss Errors can occur if the object with fid does not exist, are + unaccessible or if the caller does not have permission to fetch + attributes. + + NNoottee Many kernel FS drivers (Linux, NT and Windows 95 need to acquire + the attributes as well as the Fid for the instantiation of an internal + "inode" or "FileHandle". A significant improvement in performance on + such systems could be made by combining the _l_o_o_k_u_p and _g_e_t_a_t_t_r calls + both at the Venus/kernel interaction level and at the RPC level. + + The vattr structure included in the input arguments is superfluous and + should be removed. + + 0wpage + + 44..66.. sseettaattttrr + + SSuummmmaarryy Set the attributes of a file. + + AArrgguummeennttss + + iinn + + struct cfs_setattr_in { + ViceFid VFid; + struct coda_vattr attr; + } cfs_setattr; + + oouutt + empty + + DDeessccrriippttiioonn The structure attr is filled with attributes to be changed + in BSD style. Attributes not to be changed are set to -1, apart from + vtype which is set to VNON. Other are set to the value to be assigned. + The only attributes which the FS driver may request to change are the + mode, ownner, groupid, atime, mtime and ctime. The return value + indicates success or failure. + + EErrrroorrss A variety of errors can occur. The object may not exist, may + be inaccessible, or permission may not be granted by Venus. + + 0wpage + + 44..77.. aacccceessss + + SSuummmmaarryy + + AArrgguummeennttss + + iinn + + struct cfs_access_in { + ViceFid VFid; + int flags; + } cfs_access; + + oouutt + empty + + DDeessccrriippttiioonn Verify if access to the object identified by VFid for + operetions described by flags is permitted. The result indicates if + access will be granted. It is important to remember that Coda uses + ACL's to enforce protection and that ultimately the servers, not the + clients enforce the security of the system. The result of this call + will depend on wether a _t_o_k_e_n is held by the user. + + EErrrroorrss The object may not exist, or the ACL describing the protection + may not be accessible. + + 0wpage + + 44..88.. ccrreeaattee + + SSuummmmaarryy Invoked to create a file + + AArrgguummeennttss + + iinn + + struct cfs_create_in { + ViceFid VFid; + struct coda_vattr attr; + int excl; + int mode; + char *name; /* Place holder for data. */ + } cfs_create; + + oouutt + + struct cfs_create_out { + ViceFid VFid; + struct coda_vattr attr; + } cfs_create; + + DDeessccrriippttiioonn This upcall is invoked to request creation of a file. + The file will be created in the directory identified by VFid, its name + will be name, and the mode will be mode. If excl is set an error will + be returned if the file already exists. If the size field in attr is + set to zero the file will be truncated. The uid and gid of the file + are set by converting the CodaCred to a uid using a macro CRTOUID + (this macro is platform dependent). Upon success the VFid and + attributes of the file are returned. The Coda FS Driver will normally + instantiate a vnode, inode or filehandle at kernel level for the new + object. + + EErrrroorrss A variety of errors can occur. Permissions may be insufficient. + If the object exists and is not a file the error EISDIR is returned + under Unix. + + NNOOTTEE The packing of parameters is very inefficient and appears to + indicate confusion between the system call creat and the VFS operation + create. The VFS operation create is only called to create new objects. + This create call differs from the Unix one in that it is not invoked + to return a file descriptor. The trunctate and exclusive options, + together with the mode, could simply be part of the mode as it is + under Unix. There should be no flags argument; this is used in open + (2) to return a filedescriptor for READ or WRITE mode. + + The attributes of the directory should be returned too, since the size + and mtime changed. + + 0wpage + + 44..99.. mmkkddiirr + + SSuummmmaarryy Create a new directory. + + AArrgguummeennttss + + iinn + + struct cfs_mkdir_in { + ViceFid VFid; + struct coda_vattr attr; + char *name; /* Place holder for data. */ + } cfs_mkdir; + + oouutt + + struct cfs_mkdir_out { + ViceFid VFid; + struct coda_vattr attr; + } cfs_mkdir; + + DDeessccrriippttiioonn This call is similar to create but creates a directory. + Only the mode field in the input parameters is used for creation. + Upon successful creation, the attr returned contains the attributes of + the new directory. + + EErrrroorrss As for create. + + NNOOTTEE The input parameter should be changed to mode instead of + attributes. + + The attributes of the parent should be returned since the size and + mtime changes. + + 0wpage + + 44..1100.. lliinnkk + + SSuummmmaarryy Create a link to an existing file. + + AArrgguummeennttss + + iinn + + struct cfs_link_in { + ViceFid sourceFid; /* cnode to link *to* */ + ViceFid destFid; /* Directory in which to place link */ + char *tname; /* Place holder for data. */ + } cfs_link; + + oouutt + empty + + DDeessccrriippttiioonn This call creates a link to the sourceFid in the directory + identified by destFid with name tname. The source must reside in the + targets parent, i.e. the source must be have parent destFid, i.e. Coda + does not support cross directory hard links. Only the return value is + relevant. It indicates success or the type of failure. + + EErrrroorrss The usual errors can occur.0wpage + + 44..1111.. ssyynnlliinnkk + + SSuummmmaarryy create a symbolic link + + AArrgguummeennttss + + iinn + + struct cfs_symlink_in { + ViceFid VFid; /* Directory to put symlink in */ + char *srcname; + struct coda_vattr attr; + char *tname; + } cfs_symlink; + + oouutt + none + + DDeessccrriippttiioonn Create a symbolic link. The link is to be placed in the + directory identified by VFid and named tname. It should point to the + pathname srcname. The attributes of the newly creaeted object are to + be set to attr. + + EErrrroorrss + + NNOOTTEE The attributes of the target directory should be returned since + its size changed. + + 0wpage + + 44..1122.. rreemmoovvee + + SSuummmmaarryy Remove a file + + AArrgguummeennttss + + iinn + + struct cfs_remove_in { + ViceFid VFid; + char *name; /* Place holder for data. */ + } cfs_remove; + + oouutt + none + + DDeessccrriippttiioonn Remove file named cfs_remove_in.name in directory + identified by VFid. + + EErrrroorrss + + NNOOTTEE The attributes of the directory should be returned since its + mtime and size may change. + + 0wpage + + 44..1133.. rrmmddiirr + + SSuummmmaarryy Remove a directory + + AArrgguummeennttss + + iinn + + struct cfs_rmdir_in { + ViceFid VFid; + char *name; /* Place holder for data. */ + } cfs_rmdir; + + oouutt + none + + DDeessccrriippttiioonn Remove the directory with name name from the directory + identified by VFid. + + EErrrroorrss + + NNOOTTEE The attributes of the parent directory should be returned since + its mtime and size may change. + + 0wpage + + 44..1144.. rreeaaddlliinnkk + + SSuummmmaarryy Read the value of a symbolic link. + + AArrgguummeennttss + + iinn + + struct cfs_readlink_in { + ViceFid VFid; + } cfs_readlink; + + oouutt + + struct cfs_readlink_out { + int count; + caddr_t data; /* Place holder for data. */ + } cfs_readlink; + + DDeessccrriippttiioonn This routine reads the contents of symbolic link + identified by VFid into the buffer data. The buffer data must be able + to hold any name up to CFS_MAXNAMLEN (PATH or NAM??). + + EErrrroorrss No unusual errors. + + 0wpage + + 44..1155.. ooppeenn + + SSuummmmaarryy Open a file. + + AArrgguummeennttss + + iinn + + struct cfs_open_in { + ViceFid VFid; + int flags; + } cfs_open; + + oouutt + + struct cfs_open_out { + dev_t dev; + ino_t inode; + } cfs_open; + + DDeessccrriippttiioonn This request asks Venus to place the file identified by + VFid in its cache and to note that the calling process wishes to open + it with flags as in open(2). The return value to the kernel differs + for Unix and Windows systems. For Unix systems the Coda FS Driver is + informed of the device and inode number of the container file in the + fields dev and inode. For Windows the path of the container file is + returned to the kernel. + + EErrrroorrss + + NNOOTTEE Currently the cfs_open_out structure is not properly adapted to + deal with the windows case. It might be best to implement two + upcalls, one to open aiming at a container file name, the other at a + container file inode. + + 0wpage + + 44..1166.. cclloossee + + SSuummmmaarryy Close a file, update it on the servers. + + AArrgguummeennttss + + iinn + + struct cfs_close_in { + ViceFid VFid; + int flags; + } cfs_close; + + oouutt + none + + DDeessccrriippttiioonn Close the file identified by VFid. + + EErrrroorrss + + NNOOTTEE The flags argument is bogus and not used. However, Venus' code + has room to deal with an execp input field, probably this field should + be used to inform Venus that the file was closed but is still memory + mapped for execution. There are comments about fetching versus not + fetching the data in Venus vproc_vfscalls. This seems silly. If a + file is being closed, the data in the container file is to be the new + data. Here again the execp flag might be in play to create confusion: + presently Venus might think a file can be flushed from the cache when + it is still memory mapped. This needs to be understood. + + 0wpage + + 44..1177.. iiooccttll + + SSuummmmaarryy Do an ioctl on a file. This includes the piocl interface. + + AArrgguummeennttss + + iinn + + struct cfs_ioctl_in { + ViceFid VFid; + int cmd; + int len; + int rwflag; + char *data; /* Place holder for data. */ + } cfs_ioctl; + + oouutt + + struct cfs_ioctl_out { + int len; + caddr_t data; /* Place holder for data. */ + } cfs_ioctl; + + DDeessccrriippttiioonn Do an ioctl operation on a file. The command, len and + data arguments are filled as usual. flags is not used by Venus. + + EErrrroorrss + + NNOOTTEE Another bogus parameter. flags is not used. What is the + business about PREFETCHING in the Venus' code? + + 0wpage + + 44..1188.. rreennaammee + + SSuummmmaarryy Rename a fid. + + AArrgguummeennttss + + iinn + + struct cfs_rename_in { + ViceFid sourceFid; + char *srcname; + ViceFid destFid; + char *destname; + } cfs_rename; + + oouutt + none + + DDeessccrriippttiioonn Rename the object with name srcname in directory + sourceFid to destname in destFid. It is important that the names + srcname and destname are 0 terminated strings. Strings in Unix + kernels are not always null terminated. + + EErrrroorrss + + 0wpage + + 44..1199.. rreeaaddddiirr + + SSuummmmaarryy Read directory entries. + + AArrgguummeennttss + + iinn + + struct cfs_readdir_in { + ViceFid VFid; + int count; + int offset; + } cfs_readdir; + + oouutt + + struct cfs_readdir_out { + int size; + caddr_t data; /* Place holder for data. */ + } cfs_readdir; + + DDeessccrriippttiioonn Read directory entries from VFid starting at offset and + read at most count bytes. Returns the data into data and indicates + the size returned size. + + EErrrroorrss + + NNOOTTEE This call is not used. Readdir operations exploit container + files. We will re-evaluate this during the directory revamp which is + about to take place. + + 0wpage + + 44..2200.. vvggeett + + SSuummmmaarryy instructs Venus to do an FSDB->Get. + + AArrgguummeennttss + + iinn + + struct cfs_fsync_in { + ViceFid VFid; + } cfs_fsync; + + oouutt + + struct cfs_vget_out { + ViceFid VFid; + int vtype; + } cfs_vget; + + DDeessccrriippttiioonn This upcall asks Venus to do a get operation on an fsobj + labelled by VFid. + + EErrrroorrss + + NNOOTTEE This operation is not used. However, it is extremely useful + since it can be used to deal with read/write memory mapped files. + These can be "pinned" in the Venus cache using vget and release with + inactive. + + 0wpage + + 44..2211.. ffssyynncc + + SSuummmmaarryy Tell Venus to update the RVM attributes of a file. + + AArrgguummeennttss + + iinn + + struct cfs_fsync_in { + ViceFid VFid; + } cfs_fsync; + + oouutt + none + + DDeessccrriippttiioonn Ask Venus to update RVM attributes of object VFid. This + should be called as part of kernel level fsync type calls. The + result indicates if the synching was successful. + + EErrrroorrss + + NNOOTTEE Linux does not implement this call. It should. + + 0wpage + + 44..2222.. iinnaaccttiivvee + + SSuummmmaarryy Tell Venus a vnode is no longer in use. + + AArrgguummeennttss + + iinn + + struct cfs_inactive_in { + ViceFid VFid; + } cfs_inactive; + + oouutt + none + + DDeessccrriippttiioonn This operation returns EOPNOTSUPP. + + EErrrroorrss + + NNOOTTEE This should perhaps be removed. + + 0wpage + + 44..2233.. rrddwwrr + + SSuummmmaarryy Read or write from a file + + AArrgguummeennttss + + iinn + + struct cfs_rdwr_in { + ViceFid VFid; + int rwflag; + int count; + int offset; + int ioflag; + caddr_t data; /* Place holder for data. */ + } cfs_rdwr; + + oouutt + + struct cfs_rdwr_out { + int rwflag; + int count; + caddr_t data; /* Place holder for data. */ + } cfs_rdwr; + + DDeessccrriippttiioonn This upcall asks Venus to read or write from a file. + + EErrrroorrss + + NNOOTTEE It should be removed since it is against the Coda philosophy that + read/write operations never reach Venus. I have been told the + operation does not work. It is not currently used. + + 0wpage + + 44..2244.. ooddyymmoouunntt + + SSuummmmaarryy Allows mounting multiple Coda "filesystems" on one Unix mount + point. + + AArrgguummeennttss + + iinn + + struct ody_mount_in { + char *name; /* Place holder for data. */ + } ody_mount; + + oouutt + + struct ody_mount_out { + ViceFid VFid; + } ody_mount; + + DDeessccrriippttiioonn Asks Venus to return the rootfid of a Coda system named + name. The fid is returned in VFid. + + EErrrroorrss + + NNOOTTEE This call was used by David for dynamic sets. It should be + removed since it causes a jungle of pointers in the VFS mounting area. + It is not used by Coda proper. Call is not implemented by Venus. + + 0wpage + + 44..2255.. ooddyy__llooookkuupp + + SSuummmmaarryy Looks up something. + + AArrgguummeennttss + + iinn irrelevant + + oouutt + irrelevant + + DDeessccrriippttiioonn + + EErrrroorrss + + NNOOTTEE Gut it. Call is not implemented by Venus. + + 0wpage + + 44..2266.. ooddyy__eexxppaanndd + + SSuummmmaarryy expands something in a dynamic set. + + AArrgguummeennttss + + iinn irrelevant + + oouutt + irrelevant + + DDeessccrriippttiioonn + + EErrrroorrss + + NNOOTTEE Gut it. Call is not implemented by Venus. + + 0wpage + + 44..2277.. pprreeffeettcchh + + SSuummmmaarryy Prefetch a dynamic set. + + AArrgguummeennttss + + iinn Not documented. + + oouutt + Not documented. + + DDeessccrriippttiioonn Venus worker.cc has support for this call, although it is + noted that it doesn't work. Not surprising, since the kernel does not + have support for it. (ODY_PREFETCH is not a defined operation). + + EErrrroorrss + + NNOOTTEE Gut it. It isn't working and isn't used by Coda. + + 0wpage + + 44..2288.. ssiiggnnaall + + SSuummmmaarryy Send Venus a signal about an upcall. + + AArrgguummeennttss + + iinn none + + oouutt + not applicable. + + DDeessccrriippttiioonn This is an out-of-band upcall to Venus to inform Venus + that the calling process received a signal after Venus read the + message from the input queue. Venus is supposed to clean up the + operation. + + EErrrroorrss No reply is given. + + NNOOTTEE We need to better understand what Venus needs to clean up and if + it is doing this correctly. Also we need to handle multiple upcall + per system call situations correctly. It would be important to know + what state changes in Venus take place after an upcall for which the + kernel is responsible for notifying Venus to clean up (e.g. open + definitely is such a state change, but many others are maybe not). + + 0wpage + + 55.. TThhee mmiinniiccaacchhee aanndd ddoowwnnccaallllss + + The Coda FS Driver can cache results of lookup and access upcalls, to + limit the frequency of upcalls. Upcalls carry a price since a process + context switch needs to take place. The counterpart of caching the + information is that Venus will notify the FS Driver that cached + entries must be flushed or renamed. + + The kernel code generally has to maintain a structure which links the + internal file handles (called vnodes in BSD, inodes in Linux and + FileHandles in Windows) with the ViceFid's which Venus maintains. + Ther reason is that frequent translations back and forth are needed in + order to make upcalls and use the results of upcalls. Such linking + objects are called ccnnooddeess. + + The current minicache implementations have cache entries which record + the following: + + 1. the name of the file + + 2. the cnode of the directory containing the object + + 3. a list of CodaCred's for which the lookup is permitted. + + 4. the cnode of the object + + The lookup call in the Coda FS Driver may request the cnode of the + desired object from the cache, by passing it's name, directory and the + CodaCred's of the caller. The cache will return the cnode or indicate + and it cannot be found. The Coda FS Driver must be careful to + invalidate cache entries when it modifies or removes objects. + + When Venus obtains information that indicates that cache entries are + no longer valid, it will make a downcall to the kernel. Downcalls are + intercepted by the Coda FS Driver and lead to cache invalidations of + the kind described below. The Coda FS Driver does not return an error + unless the downcall data could not be read into kernel memory. + + 55..11.. IINNVVAALLIIDDAATTEE + + No information is available on this call. + + 55..22.. FFLLUUSSHH + + AArrgguummeennttss None + + SSuummmmaarryy Flush the name cache entirely. + + DDeessccrriippttiioonn Venus issues this call upon startup and when it dies. This + is to prevent stale cache information being held. Some operating + systems allow the kernel name cache to be switched off dynamically. + When this is done, this downcall is made. + + 55..33.. PPUURRGGEEUUSSEERR + + AArrgguummeennttss + + struct cfs_purgeuser_out {/* CFS_PURGEUSER is a venus->kernel call */ + struct CodaCred cred; + } cfs_purgeuser; + + DDeessccrriippttiioonn Remove all entries in the cache carrying the Cred. This + call is issued when tokes for a user expire or are flushed. + + 55..44.. ZZAAPPFFIILLEE + + AArrgguummeennttss + + struct cfs_zapfile_out { /* CFS_ZAPFILE is a venus->kernel call */ + ViceFid CodaFid; + } cfs_zapfile; + + DDeessccrriippttiioonn Remove all entries which have the (dir vnode, name) pair. + This is issued as a result of an invalidation of cached attributes of + a vnode. + + NNOOTTEE Call is not named correctly in NetBSD and Mach. The minicache + zapfile routine takes different arguments. Linux does not implement + the invalidation of attributes correctly. + + 55..55.. ZZAAPPDDIIRR + + AArrgguummeennttss + + struct cfs_zapdir_out { /* CFS_ZAPDIR is a venus->kernel call */ + ViceFid CodaFid; + } cfs_zapdir; + + DDeessccrriippttiioonn Remove all entries in the cache lying in a directory + CodaFid, and all children of this directory. This call is issed when + Venus receives a callback on the this directory. + + 55..66.. ZZAAPPVVNNOODDEE + + AArrgguummeennttss + + struct cfs_zapvnode_out { /* CFS_ZAPVNODE is a venus->kernel call */ + struct CodaCred cred; + ViceFid VFid; + } cfs_zapvnode; + + DDeessccrriippttiioonn Remove all entries in the cache carrying the cred and VFid + as in the arguments. This downcall is probably never issued. + + 55..77.. PPUURRGGEEFFIIDD + + SSuummmmaarryy + + AArrgguummeennttss + + struct cfs_purgefid_out { /* CFS_PURGEFID is a venus->kernel call */ + ViceFid CodaFid; + } cfs_purgefid; + + DDeessccrriippttiioonn Flush the attribute for the file. If it is a dir (odd + vnode), purge its children from the namecache remove the file from the + namecache. + + 55..88.. RREEPPLLAACCEE + + SSuummmmaarryy Replace the Fid's for a collection of names. + + AArrgguummeennttss + + struct cfs_replace_out { /* cfs_replace is a venus->kernel call */ + ViceFid NewFid; + ViceFid OldFid; + } cfs_replace; + + DDeessccrriippttiioonn This routine replaces a ViceFid in the name cache with + another. It is added to allow Venus during reintegration to replace + locally allocated temp fids while disconnected with global fids even + when the reference count on those fids are not zero. + + 0wpage + + 66.. IInniittiiaalliizzaattiioonn aanndd cclleeaannuupp + + This section gives brief hints as to desirable features for the Coda + FS Driver at startup and upon shutdown or Venus failures. Before + entering the discussion it is useful to repeat that the Coda FS Driver + maintains the following data: + + 1. message queues + + 2. cnodes + + 3. name cache entries + + The name cache entries are entirely private to the driver, so they + can easily be manipulated. The message queues will generally have + clear points of initialization and destruction. The cnodes are + much more delicate. User processes hold reference counts in Coda + filesystems and it can be difficult to clean up the cnodes. + + It can expect requests through: + + 1. the message subsystem + + 2. the VFS layer + + 3. pioctl interface + + Currently the _p_i_o_c_t_l passes through the VFS for Coda so we can + treat these similarly. + + 66..11.. RReeqquuiirreemmeennttss + + The following requirements should be accomodated: + + 1. The message queueus should have open and close routines. On Unix + the opening of the character devices are such routines. + + +o Before opening, no messages can be placed. + + +o Opening will remove any old messages still pending. + + +o Close will notify any sleeping processes that their upcall cannot + be completed. + + +o Close will free all memory allocated by the message queues. + + 2. At open the namecache shall be initialized to empty state. + + 3. Before the message queues are open, all VFS operations will fail. + Fortunately this can be achieved by making sure than mounting the + Coda filesystem cannot succeed before opening. + + 4. After closing of the queues, no VFS operations can succeed. Here + one needs to be careful, since a few operations (lookup, + read/write, readdir) can proceed without upcalls. These must be + explicitly blocked. + + 5. Upon closing the namecache shall be flushed and disabled. + + 6. All memory held by cnodes can be freed without relying on upcalls. + + 7. Unmounting the file system can be done without relying on upcalss. + + 8. Mounting the Coda filesystem should fail gracefully if Venus cannot + get the rootfid or the attributes of the rootfid. The latter is + best implemented by Venus fetching these objects before attempting + to mount. + + NNOOTTEE NetBSD in particular but also Linux have not implemented the + above requirements fully. For smooth operation this needs to be + corrected. + diff --git a/MAINTAINERS b/MAINTAINERS index a850f03db4c6..cca41d95e1e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -173,6 +173,12 @@ M: jreuter@lykos.oche.de L: linux-hams@vger.rutgers.edu S: Maintained +HIGH-SPEED SCC DRIVER FOR AX.25 +P: Klaus Kudielka +M: oe1kib@oe1xtu.ampr.org +L: linux-hams@vger.rutgers.edu +S: Maintained + BAYCOM/HDLCDRV/SOUNDMODEM DRIVERS FOR AX.25 P: Thomas Sailer M: sailer@ife.ee.ethz.ch diff --git a/Makefile b/Makefile index 8e84584380e5..f4fc443f031c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 71 +SUBLEVEL = 72 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) @@ -157,6 +157,10 @@ ifdef CONFIG_PNP DRIVERS := $(DRIVERS) drivers/pnp/pnp.a endif +ifdef CONFIG_HAMRADIO +DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a +endif + include arch/$(ARCH)/Makefile ifdef SMP @@ -363,8 +367,8 @@ distclean: mrproper rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ -o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS - rm -f drivers/sound/Config.in - cp drivers/sound/Config.std drivers/sound/Config.in +# rm -f drivers/sound/Config.in +# cp drivers/sound/Config.std drivers/sound/Config.in backup: mrproper cd .. && tar cf - linux/ | gzip -9 > backup.gz diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 19b4f173560b..0eef8b539d8f 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -727,7 +727,7 @@ sys_call_table: .quad sys_write .quad alpha_ni_syscall /* 5 */ .quad sys_close - .quad sys_wait4 + .quad osf_wait4 .quad alpha_ni_syscall .quad sys_link .quad sys_unlink /* 10 */ @@ -804,17 +804,17 @@ sys_call_table: .quad sys_setgroups /* 80 */ .quad alpha_ni_syscall .quad sys_setpgid - .quad sys_setitimer + .quad osf_setitimer .quad alpha_ni_syscall .quad alpha_ni_syscall /* 85 */ - .quad sys_getitimer + .quad osf_getitimer .quad sys_gethostname .quad sys_sethostname .quad sys_getdtablesize .quad sys_dup2 /* 90 */ .quad sys_newfstat .quad sys_fcntl - .quad sys_select + .quad osf_select .quad sys_poll .quad sys_fsync /* 95 */ .quad sys_setpriority @@ -837,13 +837,13 @@ sys_call_table: .quad sys_recvmsg .quad sys_sendmsg .quad alpha_ni_syscall /* 115 */ - .quad sys_gettimeofday - .quad sys_getrusage + .quad osf_gettimeofday + .quad osf_getrusage .quad sys_getsockopt .quad alpha_ni_syscall .quad sys_readv /* 120 */ .quad sys_writev - .quad sys_settimeofday + .quad osf_settimeofday .quad sys_fchown .quad sys_fchmod .quad sys_recvfrom /* 125 */ @@ -859,7 +859,7 @@ sys_call_table: .quad sys_socketpair /* 135 */ .quad sys_mkdir .quad sys_rmdir - .quad sys_utimes + .quad osf_utimes .quad alpha_ni_syscall .quad alpha_ni_syscall /* 140 */ .quad sys_getpeername diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index a736704a0a89..e64b6d5e1ead 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -167,6 +168,9 @@ out: return error; } +#undef ROUND_UP +#undef NAME_OFFSET + /* * Alpha syscall convention has no problem returning negative * values: @@ -202,24 +206,24 @@ asmlinkage unsigned long sys_madvise(void) /* * No need to acquire the kernel lock, we're local.. */ -asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5, - struct pt_regs regs) +asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, + int a5, struct pt_regs regs) { struct task_struct * tsk = current; (®s)->r20 = tsk->euid; return tsk->uid; } -asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5, - struct pt_regs regs) +asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, + int a5, struct pt_regs regs) { struct task_struct * tsk = current; (®s)->r20 = tsk->egid; return tsk->gid; } -asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5, - struct pt_regs regs) +asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, + int a5, struct pt_regs regs) { struct task_struct *tsk = current; @@ -524,47 +528,6 @@ asmlinkage int osf_umount(char *path, int flag) return ret; } -/* - * I don't know what the parameters are: the first one - * seems to be a timeval pointer, and I suspect the second - * one is the time remaining.. Ho humm.. No documentation. - */ -asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain) -{ - struct timeval tmp; - unsigned long ticks; - int retval; - - lock_kernel(); - retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep)); - if (retval) - goto out; - if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain)))) - goto out; - copy_from_user(&tmp, sleep, sizeof(*sleep)); - ticks = tmp.tv_usec; - ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ); - ticks += tmp.tv_sec * HZ; - current->timeout = ticks + jiffies; - current->state = TASK_INTERRUPTIBLE; - schedule(); - retval = 0; - if (!remain) - goto out; - ticks = jiffies; - if (ticks < current->timeout) - ticks = current->timeout - ticks; - else - ticks = 0; - current->timeout = 0; - tmp.tv_sec = ticks / HZ; - tmp.tv_usec = ticks % HZ; - copy_to_user(remain, &tmp, sizeof(*remain)); -out: - unlock_kernel(); - return retval; -} - asmlinkage int osf_utsname(char *name) { int error; @@ -956,3 +919,358 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, return -EOPNOTSUPP; } + +/* Translations due to the fact that OSF's time_t is an int. Which + affects all sorts of things, like timeval and itimerval. */ + +extern struct timezone sys_tz; +extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); +extern int do_getitimer(int which, struct itimerval *value); +extern int do_setitimer(int which, struct itimerval *, struct itimerval *); +asmlinkage int sys_utimes(char *, struct timeval *); +extern int sys_wait4(pid_t, int *, int, struct rusage *); + +struct timeval32 +{ + int tv_sec, tv_usec; +}; + +struct itimerval32 +{ + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +static inline long get_tv32(struct timeval *o, struct timeval32 *i) +{ + return (!access_ok(VERIFY_READ, i, sizeof(*i)) || + (__get_user(o->tv_sec, &i->tv_sec) | + __get_user(o->tv_usec, &i->tv_usec))); +} + +static inline long put_tv32(struct timeval32 *o, struct timeval *i) +{ + return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || + (__put_user(i->tv_sec, &o->tv_sec) | + __put_user(i->tv_usec, &o->tv_usec))); +} + +static inline long get_it32(struct itimerval *o, struct itimerval32 *i) +{ + return (!access_ok(VERIFY_READ, i, sizeof(*i)) || + (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | + __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) | + __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) | + __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); +} + +static inline long put_it32(struct itimerval32 *o, struct itimerval *i) +{ + return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) || + (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | + __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) | + __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) | + __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); +} + +asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) +{ + if (tv) { + struct timeval ktv; + do_gettimeofday(&ktv); + if (put_tv32(tv, &ktv)) + return -EFAULT; + } + if (tz) { + if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) + return -EFAULT; + } + return 0; +} + +asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz) +{ + struct timeval ktv; + struct timezone ktz; + + if (tv) { + if (get_tv32(&ktv, tv)) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&ktz, tz, sizeof(*tz))) + return -EFAULT; + } + + return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); +} + +asmlinkage int osf_getitimer(int which, struct itimerval32 *it) +{ + struct itimerval kit; + int error; + + error = do_getitimer(which, &kit); + if (!error && put_it32(it, &kit)) + error = -EFAULT; + + return error; +} + +asmlinkage int osf_setitimer(int which, struct itimerval32 *in, + struct itimerval32 *out) +{ + struct itimerval kin, kout; + int error; + + if (in) { + if (get_it32(&kin, in)) + return -EFAULT; + } else + memset(&kin, 0, sizeof(kin)); + + error = do_setitimer(which, &kin, out ? &kout : NULL); + if (error || !out) + return error; + + if (put_it32(out, &kout)) + return -EFAULT; + + return 0; + +} + +asmlinkage int osf_utimes(const char *filename, struct timeval32 *tvs) +{ + char *kfilename; + struct timeval ktvs[2]; + mm_segment_t old_fs; + int ret; + + kfilename = getname(filename); + if (IS_ERR(kfilename)) + return PTR_ERR(kfilename); + + if (tvs) { + if (get_tv32(&ktvs[0], &tvs[0]) || + get_tv32(&ktvs[1], &tvs[1])) + return -EFAULT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_utimes(kfilename, tvs ? ktvs : 0); + set_fs(old_fs); + + putname(kfilename); + + return ret; +} + +asmlinkage int +osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, + struct timeval32 *tvp) +{ + fd_set_buffer *fds; + unsigned long timeout; + int ret; + + timeout = ~0UL; + if (tvp) { + time_t sec, usec; + + if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) + || (ret = __get_user(sec, &tvp->tv_sec)) + || (ret = __get_user(usec, &tvp->tv_usec))) + goto out_nofds; + + timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); + timeout += sec * HZ; + if (timeout) + timeout += jiffies + 1; + } + + ret = -ENOMEM; + fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL); + if (!fds) + goto out_nofds; + ret = -EINVAL; + if (n < 0) + goto out; + if (n > KFDS_NR) + n = KFDS_NR; + if ((ret = get_fd_set(n, inp->fds_bits, fds->in)) || + (ret = get_fd_set(n, outp->fds_bits, fds->out)) || + (ret = get_fd_set(n, exp->fds_bits, fds->ex))) + goto out; + zero_fd_set(n, fds->res_in); + zero_fd_set(n, fds->res_out); + zero_fd_set(n, fds->res_ex); + + ret = do_select(n, fds, timeout); + + /* OSF does not copy back the remaining time. */ + + if (ret < 0) + goto out; + if (!ret) { + ret = -ERESTARTNOHAND; + if (signal_pending(current)) + goto out; + ret = 0; + } + + set_fd_set(n, inp->fds_bits, fds->res_in); + set_fd_set(n, outp->fds_bits, fds->res_out); + set_fd_set(n, exp->fds_bits, fds->res_ex); + +out: + free_page((unsigned long) fds); +out_nofds: + return ret; +} + +struct rusage32 { + struct timeval32 ru_utime; /* user time used */ + struct timeval32 ru_stime; /* system time used */ + long ru_maxrss; /* maximum resident set size */ + long ru_ixrss; /* integral shared memory size */ + long ru_idrss; /* integral unshared data size */ + long ru_isrss; /* integral unshared stack size */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary " */ +}; + +asmlinkage int osf_getrusage(int who, struct rusage32 *ru) +{ + struct rusage32 r; + + if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) + return -EINVAL; + + memset(&r, 0, sizeof(r)); + switch (who) { + case RUSAGE_SELF: + r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime); + r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime); + r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime); + r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime); + r.ru_minflt = current->min_flt; + r.ru_majflt = current->maj_flt; + r.ru_nswap = current->nswap; + break; + case RUSAGE_CHILDREN: + r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_cutime); + r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_cutime); + r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_cstime); + r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_cstime); + r.ru_minflt = current->cmin_flt; + r.ru_majflt = current->cmaj_flt; + r.ru_nswap = current->cnswap; + break; + default: + r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime + + current->times.tms_cutime); + r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime + + current->times.tms_cutime); + r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime + + current->times.tms_cstime); + r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime + + current->times.tms_cstime); + r.ru_minflt = current->min_flt + current->cmin_flt; + r.ru_majflt = current->maj_flt + current->cmaj_flt; + r.ru_nswap = current->nswap + current->cnswap; + break; + } + + return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; +} + +asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options, + struct rusage32 *ur) +{ + if (!ur) { + return sys_wait4(pid, ustatus, options, NULL); + } else { + struct rusage r; + int ret, status; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_wait4(pid, &status, options, &r); + set_fs (old_fs); + + if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) + return -EFAULT; + __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); + __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); + __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); + __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec); + __put_user(r.ru_maxrss, &ur->ru_maxrss); + __put_user(r.ru_ixrss, &ur->ru_ixrss); + __put_user(r.ru_idrss, &ur->ru_idrss); + __put_user(r.ru_isrss, &ur->ru_isrss); + __put_user(r.ru_minflt, &ur->ru_minflt); + __put_user(r.ru_majflt, &ur->ru_majflt); + __put_user(r.ru_nswap, &ur->ru_nswap); + __put_user(r.ru_inblock, &ur->ru_inblock); + __put_user(r.ru_oublock, &ur->ru_oublock); + __put_user(r.ru_msgsnd, &ur->ru_msgsnd); + __put_user(r.ru_msgrcv, &ur->ru_msgrcv); + __put_user(r.ru_nsignals, &ur->ru_nsignals); + __put_user(r.ru_nvcsw, &ur->ru_nvcsw); + if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw)) + return -EFAULT; + + if (ustatus && put_user(status, ustatus)) + return -EFAULT; + return ret; + } +} + +/* + * I don't know what the parameters are: the first one + * seems to be a timeval pointer, and I suspect the second + * one is the time remaining.. Ho humm.. No documentation. + */ +asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain) +{ + struct timeval tmp; + unsigned long ticks; + + if (get_tv32(&tmp, sleep)) + goto fault; + + ticks = tmp.tv_usec; + ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ); + ticks += tmp.tv_sec * HZ; + current->timeout = ticks + jiffies; + current->state = TASK_INTERRUPTIBLE; + + schedule(); + + if (remain) { + ticks = jiffies; + if (ticks < current->timeout) + ticks = current->timeout - ticks; + else + ticks = 0; + current->timeout = 0; + tmp.tv_sec = ticks / HZ; + tmp.tv_usec = ticks % HZ; + if (put_tv32(remain, &tmp)) + goto fault; + } + + return 0; +fault: + return -EFAULT; +} diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 7884e1239a70..1d4e8931d4e4 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -75,6 +75,7 @@ osf_sigprocmask(int how, unsigned long newmask, long a2, long a3, if (_NSIG_WORDS > 1 && sign > 0) sigemptyset(¤t->blocked); current->blocked.sig[0] = newmask; + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); (®s)->r0 = 0; /* special no error return */ @@ -570,21 +571,23 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, unsigned long r0, unsigned long r19) { - sigset_t _oldset; - siginfo_t info; - unsigned long signr, single_stepping, core = 0; - struct k_sigaction *ka; + unsigned long single_stepping = ptrace_cancel_bpt(current); - single_stepping = ptrace_cancel_bpt(current); + if (!oldset) + oldset = ¤t->blocked; - spin_lock_irq(¤t->sigmask_lock); - if (!oldset) { - _oldset = current->blocked; - oldset = &_oldset; - } - while ((signr = dequeue_signal(¤t->blocked, &info)) != 0) { + while (1) { + unsigned long signr; + struct k_sigaction *ka; + siginfo_t info; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); + if (!signr) + break; + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; @@ -595,12 +598,12 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) - goto skip_signal; + continue; current->exit_code = 0; /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) - goto skip_signal; + continue; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { @@ -614,23 +617,34 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); - goto skip_signal; + continue; } } ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { + if (signr != SIGCHLD) + continue; + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + /* nothing */; + continue; + } + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr & 0x7f; + /* Init gets no signals it doesn't want. */ if (current->pid == 1) - goto skip_signal; + continue; switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: - goto skip_signal; + continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) - goto skip_signal; + continue; /* FALLTHRU */ case SIGSTOP: @@ -641,15 +655,15 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); - break; + continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: lock_kernel(); if (current->binfmt && current->binfmt->core_dump - &¤t->binfmt->core_dump(signr, regs)) - core = 0x80; + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); /* FALLTHRU */ @@ -657,26 +671,19 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, lock_kernel(); sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - do_exit((signr & 0x7f) | core); - } - } else if (ka->sa.sa_handler == SIG_IGN) { - if (signr == SIGCHLD) { - /* Check for SIGCHLD: it's special. */ - while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - /* nothing */; + do_exit(exit_code); + /* NOTREACHED */ } - } else { - /* Whee! Actually deliver the signal. */ - if (r0) syscall_restart(r0, r19, regs, ka); - handle_signal(signr, ka, &info, oldset, regs, sw); - if (single_stepping) - ptrace_set_bpt(current); /* re-set bpt */ - return 1; + continue; } - skip_signal: - spin_lock_irq(¤t->sigmask_lock); + + /* Whee! Actually deliver the signal. */ + if (r0) syscall_restart(r0, r19, regs, ka); + handle_signal(signr, ka, &info, oldset, regs, sw); + if (single_stepping) + ptrace_set_bpt(current); /* re-set bpt */ + return 1; } - spin_unlock_irq(¤t->sigmask_lock); if (r0 && (regs->r0 == ERESTARTNOHAND || diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 3506ff1f75cc..5a13e0179440 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -281,22 +281,19 @@ void machine_restart(char * __unused) { if(!reboot_thru_bios) { -#if 0 - sti(); -#endif /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { int i; for (i=0; i<100; i++) { - int j; kb_wait(); - for(j = 0; j < 100000 ; j++) - /* nothing */; + udelay(10); outb(0xfe,0x64); /* pulse reset low */ udelay(10); } - __asm__ __volatile__("\tlidt %0": "=m" (no_idt)); + /* That didn't work - force a triple fault.. */ + __asm__ __volatile__("lidt %0": :"m" (no_idt)); + __asm__ __volatile__("int3"); } } diff --git a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c index 9c77993021ba..80ef4be47866 100644 --- a/arch/i386/kernel/sys_i386.c +++ b/arch/i386/kernel/sys_i386.c @@ -225,15 +225,16 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) return -EFAULT; error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error -= __put_user(0,name->sysname+__OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error -= __put_user(0,name->nodename+__OLD_UTS_LEN); - error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error -= __put_user(0,name->release+__OLD_UTS_LEN); - error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error -= __put_user(0,name->version+__OLD_UTS_LEN); - error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error = __put_user(0,name->machine+__OLD_UTS_LEN); + error |= __put_user(0,name->sysname+__OLD_UTS_LEN); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); + error |= __put_user(0,name->nodename+__OLD_UTS_LEN); + error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); + error |= __put_user(0,name->release+__OLD_UTS_LEN); + error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); + error |= __put_user(0,name->version+__OLD_UTS_LEN); + error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); + error |= __put_user(0,name->machine+__OLD_UTS_LEN); + error = error ? -EFAULT : 0; return error; diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index e2c199f606ef..81640c8e647b 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -38,9 +38,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -1075,104 +1075,139 @@ out: /* end of readdir & getdents */ -extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, - fd_set *exp, struct timeval *tvp); +/* + * Ooo, nasty. We need here to frob 32-bit unsigned longs to + * 64-bit unsigned longs. + */ -asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp) +static inline int +get_fd_set32(unsigned long n, unsigned long *fdset, u32 ufdset_x) { - struct timeval kern_tv, *ktvp; - unsigned long old_fs; - char *p; - u32 *q, *Inp, *Outp, *Exp; - int i, ret = -EINVAL, nn; - - if (n < 0 || n > PAGE_SIZE*2) - return -EINVAL; - - lock_kernel (); - p = (char *)__get_free_page (GFP_KERNEL); - if (!p) - goto out_nofree; + u32 *ufdset = (u32 *)A(ufdset_x); - q = (u32 *)p; - Inp = (u32 *)A(inp); - Outp = (u32 *)A(outp); - Exp = (u32 *)A(exp); + if (ufdset) { + unsigned long odd; - ret = -EFAULT; + if (verify_area(VERIFY_WRITE, ufdset, nn*sizeof(u32))) + return -EFAULT; - nn = (n + (8 * sizeof(long)) - 1) / (8 * sizeof(long)); - if (inp && verify_area(VERIFY_WRITE, Inp, nn*sizeof(long))) - goto out; - if (outp && verify_area(VERIFY_WRITE, Outp, nn*sizeof(long))) - goto out; - if (exp && verify_area(VERIFY_WRITE, Exp, nn*sizeof(long))) - goto out; - for (i = 0; i < nn; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { - if(inp && (__get_user (q[1], Inp) || __get_user (q[0], Inp+1))) - goto out; - if(outp && (__get_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) || - __get_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) - goto out; - if(exp && (__get_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) || - __get_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) - goto out; + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + __get_user(l, ufdset); + __get_user(h, ufdset+1); + ufdset += 2; + *fdset++ = h << 32 | l; + n -= 2; + } + if (odd) + __get_user(*fdset, ufdset); + } else { + /* Tricky, must clear full unsigned long in the kernel + fdset at the end, this makes sure that actually + happens. */ + memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); } - ktvp = NULL; - if(tvp) { - if (get_tv32(&kern_tv, (struct timeval32 *)A(tvp))) - goto out; - ktvp = &kern_tv; - } + return 0; +} - old_fs = get_fs (); - set_fs (KERNEL_DS); - q = (u32 *) p; - ret = sys_select(n, - inp ? (fd_set *)&q[0] : (fd_set *)0, - outp ? (fd_set *)&q[PAGE_SIZE/4/sizeof(u32)] : (fd_set *)0, - exp ? (fd_set *)&q[PAGE_SIZE/2/sizeof(u32)] : (fd_set *)0, - ktvp); - set_fs (old_fs); +static inline void +set_fd_set32(unsigned long n, u32 ufdset_x, unsigned long *fdset) +{ + unsigned long odd; + u32 *ufdset = (u32 *)A(ufdset_x); - if(tvp && !(current->personality & STICKY_TIMEOUTS)) { - if (put_tv32((struct timeval32 *)A(tvp), &kern_tv)) { - ret = -EFAULT; - goto out; - } + if (!ufdset) + return; + + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + l = *fdset++; + h = l >> 32; + __put_user(l, ufdset); + __put_user(h, ufdset+1); + ufdset += 2; + n -= 2; } + if (odd) + __put_user(*fdset, ufdset); +} + +asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp_x) +{ + fd_set_buffer *fds; + struct timeval32 *tvp = (struct timeval32 *)A(tvp_x); + unsigned long timeout, nn; + int ret; - q = (u32 *)p; - Inp = (u32 *)A(inp); - Outp = (u32 *)A(outp); - Exp = (u32 *)A(exp); + timeout = ~0UL; + if (tvp) { + time_t sec, usec; - if(ret < 0) - goto out; + if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) + || (ret = __get_user(sec, &tvp->tv_sec)) + || (ret = __get_user(usec, &tvp->tv_usec))) + goto out_nofds; - for (i = 0; - i < nn; - i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { - if(inp && (__put_user (q[1], Inp) || __put_user (q[0], Inp+1))) { - ret = -EFAULT; - goto out; - } - if(outp && (__put_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) || - __put_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) { - ret = -EFAULT; - goto out; + timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); + timeout += sec * HZ; + if (timeout) + timeout += jiffies + 1; + } + + ret = -ENOMEM; + fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL); + if (!fds) + goto out_nofds; + ret = -EINVAL; + if (n < 0) + goto out; + if (n > KFDS_NR) + n = KFDS_NR; + + nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); + if ((ret = get_fd_set32(nn, fds->in, inp)) || + (ret = get_fd_set32(nn, fds->out, outp)) || + (ret = get_fd_set32(nn, fds->ex, exp))) + goto out; + zero_fd_set(n, fds->res_in); + zero_fd_set(n, fds->res_out); + zero_fd_set(n, fds->res_ex); + + ret = do_select(n, fds, timeout); + + if (tvp && !(current->personality & STICKY_TIMEOUTS)) { + unsigned long timeout = current->timeout - jiffies - 1; + time_t sec = 0, usec = 0; + if ((long) timeout > 0) { + sec = timeout / HZ; + usec = timeout % HZ; + usec *= (1000000/HZ); } - if(exp && (__put_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) || - __put_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) { - ret = -EFAULT; + put_user(sec, &tvp->tv_sec); + put_user(usec, &tvp->tv_usec); + } + + if (ret < 0) + goto out; + if (!ret) { + ret = -ERESTARTNOHAND; + if (current->signal & ~current->blocked) goto out; - } + ret = 0; } + + set_fd_set32(nn, inp, fds->res_in); + set_fd_set32(nn, outp, fds->res_out); + set_fd_set32(nn, exp, fds->res_ex); + out: - free_page ((unsigned long)p); -out_nofree: - unlock_kernel(); + free_page ((unsigned long)fds); +out_nofds: return ret; } diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c index 8d2600f41172..be1c28456787 100644 --- a/drivers/char/acquirewdt.c +++ b/drivers/char/acquirewdt.c @@ -64,6 +64,10 @@ static void acq_ping(void) static ssize_t acq_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) { acq_ping(); diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 758633a1a626..251f73f9660c 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -54,7 +54,7 @@ * unthrottling the TTY driver. These watermarks are used for * controlling the space in the read buffer. */ -#define TTY_THRESHOLD_THROTTLE (N_TTY_BUF_SIZE - 128) +#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ #define TTY_THRESHOLD_UNTHROTTLE 128 static inline void put_tty_queue(unsigned char c, struct tty_struct *tty) @@ -66,21 +66,42 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty) } } +/* + * Check whether to call the driver.unthrottle function. + * We test the TTY_THROTTLED bit first so that it always + * indicates the current state. + */ +static void check_unthrottle(struct tty_struct * tty) +{ + if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && + tty->driver.unthrottle) + tty->driver.unthrottle(tty); +} + /* - * Flush the input buffer + * Reset the read buffer counters, clear the flags, + * and make sure the driver is unthrottled. Called + * from n_tty_open() and n_tty_flush_buffer(). */ -void n_tty_flush_buffer(struct tty_struct * tty) +static void reset_buffer_flags(struct tty_struct *tty) { tty->read_head = tty->read_tail = tty->read_cnt = 0; tty->canon_head = tty->canon_data = tty->erasing = 0; memset(&tty->read_flags, 0, sizeof tty->read_flags); + check_unthrottle(tty); +} + +/* + * Flush the input buffer + */ +void n_tty_flush_buffer(struct tty_struct * tty) +{ + /* clear everything and unthrottle the driver */ + reset_buffer_flags(tty); if (!tty->link) return; - if (tty->driver.unthrottle && - test_and_clear_bit(TTY_THROTTLED, &tty->flags)) - tty->driver.unthrottle(tty); if (tty->link->packet) { tty->ctrl_status |= TIOCPKT_FLUSHREAD; wake_up_interruptible(&tty->link->read_wait); @@ -508,7 +529,7 @@ send_signal: return; } } - if (L_ICANON(tty)) { + if (tty->icanon) { if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); @@ -611,11 +632,29 @@ send_signal: put_tty_queue(c, tty); } +static int n_tty_receive_room(struct tty_struct *tty) +{ + int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; + + /* + * If we are doing input canonicalization, and there are no + * pending newlines, let characters through without limit, so + * that erase characters will be handled. Other excess + * characters will be beeped. + */ + if (tty->icanon && !tty->canon_data) + return N_TTY_BUF_SIZE; + + if (left > 0) + return left; + return 0; +} + static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { const unsigned char *p; - char *f, flags = 0; + char *f, flags = TTY_NORMAL; int i; if (!tty->read_buf) @@ -670,28 +709,17 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, wake_up_interruptible(&tty->read_wait); } - if ((tty->read_cnt >= TTY_THRESHOLD_THROTTLE) && - tty->driver.throttle && - !test_and_set_bit(TTY_THROTTLED, &tty->flags)) - tty->driver.throttle(tty); -} - -static int n_tty_receive_room(struct tty_struct *tty) -{ - int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; - /* - * If we are doing input canonicalization, and there are no - * pending newlines, let characters through without limit, so - * that erase characters will be handled. Other excess - * characters will be beeped. + * Check the remaining room for the input canonicalization + * mode. We don't want to throttle the driver if we're in + * canonical mode and don't have a newline yet! */ - if (tty->icanon && !tty->canon_data) - return N_TTY_BUF_SIZE; - - if (left > 0) - return left; - return 0; + if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) { + /* check TTY_THROTTLED first so it indicates our state */ + if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && + tty->driver.throttle) + tty->driver.throttle(tty); + } } int is_ignored(int sig) @@ -786,10 +814,8 @@ static int n_tty_open(struct tty_struct *tty) return -ENOMEM; } memset(tty->read_buf, 0, N_TTY_BUF_SIZE); - tty->read_head = tty->read_tail = tty->read_cnt = 0; - tty->canon_head = tty->canon_data = tty->erasing = 0; + reset_buffer_flags(tty); tty->column = 0; - memset(tty->read_flags, 0, sizeof(tty->read_flags)); n_tty_set_termios(tty, 0); tty->minimum_to_wake = 1; tty->closing = 0; @@ -798,7 +824,7 @@ static int n_tty_open(struct tty_struct *tty) static inline int input_available_p(struct tty_struct *tty, int amt) { - if (L_ICANON(tty)) { + if (tty->icanon) { if (tty->canon_data) return 1; } else if (tty->read_cnt >= (amt ? amt : 1)) @@ -825,7 +851,8 @@ static inline void copy_from_read_buf(struct tty_struct *tty, n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail)); if (!n) return; - copy_to_user(*b, &tty->read_buf[tty->read_tail], n); + /* N.B. copy_to_user may work only partially */ + n -= copy_to_user(*b, &tty->read_buf[tty->read_tail], n); tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); tty->read_cnt -= n; *b += n; @@ -868,7 +895,7 @@ do_it_again: } } - if (L_ICANON(tty)) { + if (tty->icanon) { minimum = time = 0; current->timeout = (unsigned long) -1; } else { @@ -897,9 +924,10 @@ do_it_again: while (1) { /* First test for status change. */ if (tty->packet && tty->link->ctrl_status) { - if (b != buf) + if (b != buf || !nr) break; put_user(tty->link->ctrl_status, b++); + nr--; tty->link->ctrl_status = 0; break; } @@ -937,50 +965,52 @@ do_it_again: current->state = TASK_RUNNING; /* Deal with packet mode. */ - if (tty->packet && b == buf) { + if (tty->packet && b == buf && nr) { put_user(TIOCPKT_DATA, b++); nr--; } - if (L_ICANON(tty)) { - while (1) { - int eol; + if (tty->icanon) { + /* N.B. avoid overrun if nr == 0 */ + while (nr && tty->read_cnt) { + int eol; - if (!tty->read_cnt) { - break; - } eol = test_and_clear_bit(tty->read_tail, &tty->read_flags); c = tty->read_buf[tty->read_tail]; tty->read_tail = ((tty->read_tail+1) & (N_TTY_BUF_SIZE-1)); tty->read_cnt--; - if (!eol) { - put_user(c, b++); - if (--nr) - continue; - break; - } - if (--tty->canon_data < 0) { - tty->canon_data = 0; - } - if (c != __DISABLED_CHAR) { + + if (!eol || (c != __DISABLED_CHAR)) { put_user(c, b++); nr--; } - break; + if (eol) { + /* this test should be redundant: + * we shouldn't be reading data if + * canon_data is 0 + */ + if (--tty->canon_data < 0) + tty->canon_data = 0; + break; + } } } else { + /* N.B. check for errors writing to user space? */ copy_from_read_buf(tty, &b, &nr); copy_from_read_buf(tty, &b, &nr); } /* If there is enough space in the read buffer now, let the - low-level driver know. */ - if (tty->driver.unthrottle && - (tty->read_cnt <= TTY_THRESHOLD_UNTHROTTLE) - && test_and_clear_bit(TTY_THROTTLED, &tty->flags)) - tty->driver.unthrottle(tty); + * low-level driver know. We use n_tty_chars_in_buffer() to + * check the buffer, as it now knows about canonical mode. + * Otherwise, if the driver is throttled and the line is + * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, + * we won't get any more characters. + */ + if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) + check_unthrottle(tty); if (b - buf >= minimum || !nr) break; @@ -1048,6 +1078,10 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, tty->driver.flush_chars(tty); } else { c = tty->driver.write(tty, 1, b, nr); + if (c < 0) { + retval = c; + break; + } b += c; nr -= c; } diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 26cfa4768d23..1b1990480e39 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -52,11 +52,11 @@ #include #include #include +#include #include #include #include -#include /* Adjust starting epoch if ARC console time is being used */ #ifdef CONFIG_RTC_ARC diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 7f21fae15eab..26f06b3e1508 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -3522,8 +3522,9 @@ static kdev_t serial_console_device(struct console *c) * Setup initial baud/bits/parity. We do two things here: * - construct a cflag setting for the first rs_open() * - initialize the serial port + * Return non-zero if we didn't find a serial port. */ -__initfunc(static void serial_console_setup(struct console *co, char *options)) +__initfunc(static int serial_console_setup(struct console *co, char *options)) { struct serial_state *ser; unsigned cval; @@ -3619,6 +3620,12 @@ __initfunc(static void serial_console_setup(struct console *co, char *options)) outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */ outb(cval, ser->port + UART_LCR); /* reset DLAB */ + /* + * If we read 0xff from the LSR, there is no UART here. + */ + if (inb(ser->port + UART_LSR) == 0xff) + return -1; + return 0; } static struct console sercons = { diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c index be63f08b468d..c0ecaccf4208 100644 --- a/drivers/char/softdog.c +++ b/drivers/char/softdog.c @@ -115,6 +115,10 @@ static void softdog_ping(void) static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) { + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + /* * Refresh the timer. */ diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 8e378215f901..9fadb9e4e034 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -101,11 +101,34 @@ typedef struct { int irqtype; } stlconf_t; +/*static stlconf_t stl_brdconf[] = { + { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, +};*/ + +#ifdef MODULE +static char *brdtype[STL_MAXBRDS] = {"\0", }; +static int io[STL_MAXBRDS] = { 0, }; +static int secio[STL_MAXBRDS] = { 0, }; +static int irq[STL_MAXBRDS] = { 0, }; + +MODULE_PARM(brdtype, "1-" __MODULE_STRING(STL_MAXBRDS) "s"); +MODULE_PARM(io, "1-" __MODULE_STRING(STL_MAXBRDS) "i"); +MODULE_PARM(secio, "1-" __MODULE_STRING(STL_MAXBRDS) "i"); +MODULE_PARM(irq, "1-" __MODULE_STRING(STL_MAXBRDS) "i"); + +static stlconf_t stl_brdconf[STL_MAXBRDS]; +static int stl_nrbrds = 0; + +#else static stlconf_t stl_brdconf[] = { { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, + { BRD_EASYIO, 0x2a8, 0, 0, 10, 0 }, + { BRD_EASYIO, 0x2b0, 0, 0, 10, 0 }, + { BRD_ECH, 0x2a0, 0x240, 0, 10, 0 }, }; static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); +#endif /*****************************************************************************/ @@ -616,9 +639,22 @@ static struct file_operations stl_fsiomem = { * Loadable module initialization stuff. */ +struct board_type_elem +{ + int type_id; + char *name; +}; + +struct board_type_elem board_types[] = { + { BRD_EASYIO, "easyio" }, + { BRD_ECH, "ech" }, + { BRD_ECHMC, "echmc" }, + { BRD_ECHPCI, "echpci" } }; + int init_module() { unsigned long flags; + int i, j, num_board_types; #if DEBUG printk("init_module()\n"); @@ -626,6 +662,25 @@ int init_module() save_flags(flags); cli(); + + num_board_types = sizeof(board_types) / sizeof(struct board_type_elem); + for (i = 0; (i < STL_MAXBRDS && io[i]); i++) + { + stl_brdconf[stl_nrbrds].brdtype = 0; + for (j = 0; j < num_board_types; j++) + if(strcmp(board_types[j].name, brdtype[i]) == 0) + stl_brdconf[stl_nrbrds].brdtype = board_types[j].type_id; + if(stl_brdconf[stl_nrbrds].brdtype != 0) + { + stl_brdconf[stl_nrbrds].ioaddr1 = io[i]; + stl_brdconf[stl_nrbrds].ioaddr2 = secio[i]; + stl_brdconf[stl_nrbrds].memaddr = 0; + stl_brdconf[stl_nrbrds].irq = irq[i]; + stl_brdconf[stl_nrbrds].irqtype = 0; + stl_nrbrds++; + } + } + stl_init(); restore_flags(flags); @@ -823,7 +878,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp) return(-EBUSY); } else { if ((rc = stl_waitcarrier(portp, filp)) != 0) + { + MOD_INC_USE_COUNT; return(rc); + } } portp->flags |= ASYNC_NORMAL_ACTIVE; } @@ -838,6 +896,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) portp->session = current->session; portp->pgrp = current->pgrp; + MOD_INC_USE_COUNT; return(0); } @@ -925,6 +984,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp) restore_flags(flags); return; } + MOD_DEC_USE_COUNT; if (portp->refcount-- > 1) { restore_flags(flags); return; @@ -2237,10 +2297,12 @@ static inline int stl_initbrds() printk("stl_initbrds()\n"); #endif +#ifndef MODULE if (stl_nrbrds > STL_MAXBRDS) { printk("STALLION: too many boards in configuration table, truncating to %d\n", STL_MAXBRDS); stl_nrbrds = STL_MAXBRDS; } +#endif /* * Firstly scan the list of static boards configured. Allocate diff --git a/drivers/char/vga.c b/drivers/char/vga.c index df92ec64da37..8efc04f11a99 100644 --- a/drivers/char/vga.c +++ b/drivers/char/vga.c @@ -162,8 +162,7 @@ __initfunc(int con_is_present(void)) * Find out if there is a graphics card present. * Are there smarter methods around? */ - p = (unsigned short *)(((ORIG_VIDEO_MODE == 7) ? 0xb0000 : 0xb8000) + - + VGA_OFFSET); + p = (unsigned short *) video_mem_base; saved = scr_readw(p); scr_writew(0xAA55, p); if (scr_readw(p) != 0xAA55) { diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c index 37f444e29e7d..36af5fdcc2da 100644 --- a/drivers/char/wdt.c +++ b/drivers/char/wdt.c @@ -53,7 +53,7 @@ static int wdt_is_open=0; */ static int io=0x240; -static int irq=14; +static int irq=11; #define WD_TIMO (100*60) /* 1 minute */ @@ -171,6 +171,10 @@ static void wdt_ping(void) static ssize_t wdt_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) { wdt_ping(); @@ -189,6 +193,10 @@ static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr) unsigned char cp; int err; + /* 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: diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c index aed5ca0f5029..e02de0bddddb 100644 --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -47,8 +47,7 @@ #include #include #include - -#include +#include #include "compat.h" #include "capiutil.h" diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index 5402c5b8d1d6..1b23464964bf 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -201,7 +201,7 @@ #include #include #if (LINUX_VERSION_CODE >= 0x020117) -#include +#include #endif #include #include "isdn_common.h" diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c index f9eadc034846..1cfcd07abfbc 100644 --- a/drivers/isdn/isdn_ppp.c +++ b/drivers/isdn/isdn_ppp.c @@ -129,7 +129,7 @@ #include #include #if (LINUX_VERSION_CODE >= 0x020117) -#include +#include #endif #include "isdn_common.h" #include "isdn_ppp.h" diff --git a/drivers/misc/parport_ax.c b/drivers/misc/parport_ax.c index 25f9e5defcef..caaccd6e703a 100644 --- a/drivers/misc/parport_ax.c +++ b/drivers/misc/parport_ax.c @@ -171,7 +171,7 @@ ax_release_resources(struct parport *p) { if (p->irq != PARPORT_IRQ_NONE) { ax_disable_irq(p); - free_irq(p->irq, p); + free_irq(p->irq, NULL); } release_region(p->base, p->size); if (p->modes & PARPORT_MODE_PCECR) @@ -185,7 +185,7 @@ ax_claim_resources(struct parport *p) { /* FIXME check that resources are free */ if (p->irq != PARPORT_IRQ_NONE) { - request_irq(p->irq, ax_null_intr_func, 0, p->name, p); + request_irq(p->irq, ax_null_intr_func, 0, p->name, NULL); ax_enable_irq(p); } request_region(p->base, p->size, p->name); diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c index d34dad17d1e3..71eb184ac004 100644 --- a/drivers/misc/parport_pc.c +++ b/drivers/misc/parport_pc.c @@ -141,7 +141,7 @@ static void pc_enable_irq(struct parport *p) static void pc_release_resources(struct parport *p) { if (p->irq != PARPORT_IRQ_NONE) - free_irq(p->irq, p); + free_irq(p->irq, NULL); release_region(p->base, p->size); if (p->modes & PARPORT_MODE_PCECR) release_region(p->base+0x400, 3); @@ -151,7 +151,7 @@ static int pc_claim_resources(struct parport *p) { /* FIXME check that resources are free */ if (p->irq != PARPORT_IRQ_NONE) - request_irq(p->irq, pc_null_intr_func, 0, p->name, p); + request_irq(p->irq, pc_null_intr_func, 0, p->name, NULL); request_region(p->base, p->size, p->name); if (p->modes & PARPORT_MODE_PCECR) request_region(p->base+0x400, 3, p->name); diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 9fe98ee2db28..99c2845d448f 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -180,6 +180,7 @@ if [ "$CONFIG_WAN_ROUTER" != "n" ]; then bool ' WANPIPE Frame Relay support' CONFIG_WANPIPE_FR bool ' WANPIPE PPP support' CONFIG_WANPIPE_PPP fi + dep_tristate 'High-speed (DMA) SCC driver for AX.25' CONFIG_DMASCC $CONFIG_AX25 fi fi # diff --git a/drivers/net/Space.c b/drivers/net/Space.c index eedc48f98a42..81fbe3e46d09 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -31,6 +31,7 @@ #include #include #include +#include #define NEXT_DEV NULL diff --git a/drivers/net/dmascc.c b/drivers/net/dmascc.c new file mode 100644 index 000000000000..33b473d328b5 --- /dev/null +++ b/drivers/net/dmascc.c @@ -0,0 +1,1260 @@ +/* + * $Id: dmascc.c,v 1.2 1997/12/02 16:49:49 oe1kib Exp $ + * + * Driver for high-speed SCC boards (those with DMA support) + * Copyright (C) 1997 Klaus Kudielka + * + * 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 distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "z8530.h" + + +/* Number of buffers per channel */ + +#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (2 recommended) */ +#define NUM_RX_BUF 2 /* NUM_RX_BUF >= 1 (2 recommended) */ +#define BUF_SIZE 2016 + + +/* Cards supported */ + +#define HW_PI { "Ottawa PI", 0x300, 0x20, 0x10, 8, \ + 0, 8, 1843200, 3686400 } +#define HW_PI2 { "Ottawa PI2", 0x300, 0x20, 0x10, 8, \ + 0, 8, 3686400, 7372800 } +#define HW_TWIN { "Gracilis PackeTwin", 0x200, 0x10, 0x10, 32, \ + 0, 4, 6144000, 6144000 } + +#define HARDWARE { HW_PI, HW_PI2, HW_TWIN } + +#define TYPE_PI 0 +#define TYPE_PI2 1 +#define TYPE_TWIN 2 +#define NUM_TYPES 3 + +#define MAX_NUM_DEVS 32 + + +/* SCC chips supported */ + +#define Z8530 0 +#define Z85C30 1 +#define Z85230 2 + +#define CHIPNAMES { "Z8530", "Z85C30", "Z85230" } + + +/* I/O registers */ + +/* 8530 registers relative to card base */ +#define SCCB_CMD 0x00 +#define SCCB_DATA 0x01 +#define SCCA_CMD 0x02 +#define SCCA_DATA 0x03 + +/* 8254 registers relative to card base */ +#define TMR_CNT0 0x00 +#define TMR_CNT1 0x01 +#define TMR_CNT2 0x02 +#define TMR_CTRL 0x03 + +/* Additional PI/PI2 registers relative to card base */ +#define PI_DREQ_MASK 0x04 + +/* Additional PackeTwin registers relative to card base */ +#define TWIN_INT_REG 0x08 +#define TWIN_CLR_TMR1 0x09 +#define TWIN_CLR_TMR2 0x0a +#define TWIN_SPARE_1 0x0b +#define TWIN_DMA_CFG 0x08 +#define TWIN_SERIAL_CFG 0x09 +#define TWIN_DMA_CLR_FF 0x0a +#define TWIN_SPARE_2 0x0b + + +/* PackeTwin I/O register values */ + +/* INT_REG */ +#define TWIN_SCC_MSK 0x01 +#define TWIN_TMR1_MSK 0x02 +#define TWIN_TMR2_MSK 0x04 +#define TWIN_INT_MSK 0x07 + +/* SERIAL_CFG */ +#define TWIN_DTRA_ON 0x01 +#define TWIN_DTRB_ON 0x02 +#define TWIN_EXTCLKA 0x04 +#define TWIN_EXTCLKB 0x08 +#define TWIN_LOOPA_ON 0x10 +#define TWIN_LOOPB_ON 0x20 +#define TWIN_EI 0x80 + +/* DMA_CFG */ +#define TWIN_DMA_HDX_T1 0x08 +#define TWIN_DMA_HDX_R1 0x0a +#define TWIN_DMA_HDX_T3 0x14 +#define TWIN_DMA_HDX_R3 0x16 +#define TWIN_DMA_FDX_T3R1 0x1b +#define TWIN_DMA_FDX_T1R3 0x1d + + +/* Status values */ + +/* tx_state */ +#define TX_IDLE 0 +#define TX_OFF 1 +#define TX_TXDELAY 2 +#define TX_ACTIVE 3 +#define TX_SQDELAY 4 + + +/* Data types */ + +struct scc_hardware { + char *name; + int io_region; + int io_delta; + int io_size; + int num_devs; + int scc_offset; + int tmr_offset; + int tmr_hz; + int pclk_hz; +}; + +struct scc_priv { + char name[10]; + struct enet_statistics stats; + struct scc_info *info; + int channel; + int cmd, data, tmr; + struct scc_param param; + char rx_buf[NUM_RX_BUF][BUF_SIZE]; + int rx_len[NUM_RX_BUF]; + int rx_ptr; + struct tq_struct rx_task; + int rx_head, rx_tail, rx_count; + int rx_over; + char tx_buf[NUM_TX_BUF][BUF_SIZE]; + int tx_len[NUM_TX_BUF]; + int tx_ptr; + int tx_head, tx_tail, tx_count; + int tx_sem, tx_state; + unsigned long tx_start; + int status; +}; + +struct scc_info { + int type; + int chip; + int open; + int scc_base; + int tmr_base; + int twin_serial_cfg; + struct device dev[2]; + struct scc_priv priv[2]; + struct scc_info *next; +}; + + +/* Function declarations */ + +int dmascc_init(void) __init; +static int setup_adapter(int io, int h, int n) __init; + +static inline void write_scc(int ctl, int reg, int val); +static inline int read_scc(int ctl, int reg); +static int scc_open(struct device *dev); +static int scc_close(struct device *dev); +static int scc_ioctl(struct device *dev, struct ifreq *ifr, int cmd); +static int scc_send_packet(struct sk_buff *skb, struct device *dev); +static struct enet_statistics *scc_get_stats(struct device *dev); +static int scc_set_mac_address(struct device *dev, void *sa); +static void scc_isr(int irq, void *dev_id, struct pt_regs * regs); +static inline void z8530_isr(struct scc_info *info); +static void rx_isr(struct device *dev); +static void special_condition(struct device *dev, int rc); +static void rx_bh(void *arg); +static void tx_isr(struct device *dev); +static void es_isr(struct device *dev); +static void tm_isr(struct device *dev); +static inline void delay(struct device *dev, int t); +static inline unsigned char random(void); + + +/* Initialization variables */ + +static int io[MAX_NUM_DEVS] __initdata = { 0, }; +/* Beware! hw[] is also used in cleanup_module(). If __initdata also applies + to modules, we may not declare hw[] as __initdata */ +static struct scc_hardware hw[NUM_TYPES] __initdata = HARDWARE; +static char ax25_broadcast[7] __initdata = + { 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 }; +static char ax25_test[7] __initdata = + { 'L'<<1, 'I'<<1, 'N'<<1, 'U'<<1, 'X'<<1, ' '<<1, '1'<<1 }; + + +/* Global variables */ + +static struct scc_info *first = NULL; +static unsigned long rand; + + + +/* Module functions */ + +#ifdef MODULE + + +MODULE_AUTHOR("Klaus Kudielka "); +MODULE_DESCRIPTION("Driver for high-speed SCC boards"); +MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i"); + + +int init_module(void) +{ + return dmascc_init(); +} + + +void cleanup_module(void) +{ + int i; + struct scc_info *info; + + while (first) { + info = first; + + /* Unregister devices */ + for (i = 0; i < 2; i++) { + if (info->dev[i].name) + unregister_netdev(&info->dev[i]); + } + + /* Reset board */ + if (info->type == TYPE_TWIN) + outb_p(0, info->dev[0].base_addr + TWIN_SERIAL_CFG); + write_scc(info->priv[0].cmd, R9, FHWRES); + release_region(info->dev[0].base_addr, + hw[info->type].io_size); + + /* Free memory */ + first = info->next; + kfree_s(info, sizeof(struct scc_info)); + } +} + + +#else + + +__initfunc(void dmascc_setup(char *str, int *ints)) +{ + int i; + + for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++) + io[i] = ints[i+1]; +} + + +#endif + + +/* Initialization functions */ + +__initfunc(int dmascc_init(void)) +{ + int h, i, j, n, base[MAX_NUM_DEVS], tcmd, t0, t1, status; + unsigned long time, start[MAX_NUM_DEVS], stop[MAX_NUM_DEVS]; + + /* Initialize random number generator */ + rand = jiffies; + + /* Cards found = 0 */ + n = 0; + + /* Run autodetection for each card type */ + for (h = 0; h < NUM_TYPES; h++) { + + if (io[0]) { + /* User-specified I/O address regions */ + for (i = 0; i < hw[h].num_devs; i++) base[i] = 0; + for (i = 0; i < MAX_NUM_DEVS && io[i]; i++) { + j = (io[i] - hw[h].io_region) / hw[h].io_delta; + if (j >= 0 && + j < hw[h].num_devs && + hw[h].io_region + j * hw[h].io_delta == io[i]) + base[j] = io[i]; + } + } else { + /* Default I/O address regions */ + for (i = 0; i < hw[h].num_devs; i++) + base[i] = hw[h].io_region + i * hw[h].io_delta; + } + + /* Check valid I/O address regions */ + for (i = 0; i < hw[h].num_devs; i++) + if (base[i] && check_region(base[i], hw[h].io_size)) + base[i] = 0; + + /* Start timers */ + for (i = 0; i < hw[h].num_devs; i++) + if (base[i]) { + tcmd = base[i] + hw[h].tmr_offset + TMR_CTRL; + t0 = base[i] + hw[h].tmr_offset + TMR_CNT0; + t1 = base[i] + hw[h].tmr_offset + TMR_CNT1; + /* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */ + outb_p(0x36, tcmd); + outb_p((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0); + outb_p((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0); + /* Timer 1: LSB+MSB, Mode 0, HZ/10 */ + outb_p(0x70, tcmd); + outb_p((TMR_0_HZ/HZ*10) & 0xFF, t1); + outb_p((TMR_0_HZ/HZ*10) >> 8, t1); + /* Timer 2: LSB+MSB, Mode 0 */ + outb_p(0xb0, tcmd); + } + + /* Initialize start values in case we miss the null count bit */ + time = jiffies; + for (i = 0; i < hw[h].num_devs; i++) start[i] = time; + + /* Timing loop */ + while (jiffies - time < 12) { + for (i = 0; i < hw[h].num_devs; i++) + if (base[i]) { + /* Read back Timer 1: Status */ + outb_p(0xE4, base[i] + hw[h].tmr_offset + TMR_CTRL); + status = inb_p(base[i] + hw[h].tmr_offset + TMR_CNT1); + if ((status & 0x3F) != 0x30) base[i] = 0; + if (status & 0x40) start[i] = jiffies; + if (~status & 0x80) stop[i] = jiffies; + } + } + + /* Evaluate measurements */ + for (i = 0; i < hw[h].num_devs; i++) + if (base[i]) { + time = stop[i] - start[i]; + if (time < 9 || time > 11) + /* The time expired doesn't match */ + base[i] = 0; + else { + /* Ok, we have found an adapter */ + if (setup_adapter(base[i], h, n) == 0) + n++; + } + } + + } /* NUM_TYPES */ + + /* If any adapter was successfully initialized, return ok */ + if (n) return 0; + + /* If no adapter found, return error */ + printk("dmascc: no adapters found\n"); + return -EIO; +} + + +__initfunc(int setup_adapter(int io, int h, int n)) +{ + int i, irq, chip; + struct scc_info *info; + struct device *dev; + struct scc_priv *priv; + unsigned long time; + unsigned int irqs; + int tmr = io + hw[h].tmr_offset; + int scc = io + hw[h].scc_offset; + int cmd = scc + SCCA_CMD; + char *chipnames[] = CHIPNAMES; + + /* Reset 8530 */ + write_scc(cmd, R9, FHWRES | MIE | NV); + + /* Determine type of chip */ + write_scc(cmd, R15, 1); + if (!read_scc(cmd, R15)) { + /* WR7' not present. This is an ordinary Z8530 SCC. */ + chip = Z8530; + } else { + /* Put one character in TX FIFO */ + write_scc(cmd, R8, 0); + if (read_scc(cmd, R0) & Tx_BUF_EMP) { + /* TX FIFO not full. This is a Z85230 ESCC with a 4-byte FIFO. */ + chip = Z85230; + } else { + /* TX FIFO full. This is a Z85C30 SCC with a 1-byte FIFO. */ + chip = Z85C30; + } + } + write_scc(cmd, R15, 0); + + /* Start IRQ auto-detection */ + sti(); + irqs = probe_irq_on(); + + /* Enable interrupts */ + switch (h) { + case TYPE_PI: + case TYPE_PI2: + outb_p(0, io + PI_DREQ_MASK); + write_scc(cmd, R15, CTSIE); + write_scc(cmd, R0, RES_EXT_INT); + write_scc(cmd, R1, EXT_INT_ENAB); + break; + case TYPE_TWIN: + outb_p(0, io + TWIN_DMA_CFG); + inb_p(io + TWIN_CLR_TMR1); + inb_p(io + TWIN_CLR_TMR2); + outb_p(TWIN_EI, io + TWIN_SERIAL_CFG); + break; + } + + /* Start timer */ + outb_p(1, tmr + TMR_CNT1); + outb_p(0, tmr + TMR_CNT1); + /* Wait and detect IRQ */ + time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ); + irq = probe_irq_off(irqs); + + /* Clear pending interrupt, disable interrupts */ + switch (h) { + case TYPE_PI: + case TYPE_PI2: + write_scc(cmd, R1, 0); + write_scc(cmd, R15, 0); + write_scc(cmd, R0, RES_EXT_INT); + break; + case TYPE_TWIN: + inb_p(io + TWIN_CLR_TMR1); + outb_p(0, io + TWIN_SERIAL_CFG); + break; + } + + if (irq <= 0) { + printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n", + hw[h].name, io, irq); + return -1; + } + + /* Allocate memory */ + info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA); + if (!info) { + printk("dmascc: could not allocate memory for %s at %#3x\n", + hw[h].name, io); + return -1; + } + + /* Set up data structures */ + memset(info, 0, sizeof(struct scc_info)); + info->type = h; + info->chip = chip; + info->scc_base = io + hw[h].scc_offset; + info->tmr_base = io + hw[h].tmr_offset; + info->twin_serial_cfg = 0; + for (i = 0; i < 2; i++) { + dev = &info->dev[i]; + priv = &info->priv[i]; + sprintf(priv->name, "dmascc%i", 2*n+i); + priv->info = info; + priv->channel = i; + priv->cmd = info->scc_base + (i ? SCCB_CMD : SCCA_CMD); + priv->data = info->scc_base + (i ? SCCB_DATA : SCCA_DATA); + priv->tmr = info->tmr_base + (i ? TMR_CNT2 : TMR_CNT1); + priv->param.pclk_hz = hw[h].pclk_hz; + priv->param.brg_tc = -1; + priv->param.clocks = TCTRxCP | RCRTxCP; + priv->param.txdelay = TMR_0_HZ * 10 / 1000; + priv->param.txtime = HZ * 3; + priv->param.sqdelay = TMR_0_HZ * 1 / 1000; + priv->param.slottime = TMR_0_HZ * 10 / 1000; + priv->param.waittime = TMR_0_HZ * 100 / 1000; + priv->param.persist = 32; + priv->rx_task.routine = rx_bh; + priv->rx_task.data = dev; + dev->priv = priv; + dev->name = priv->name; + dev->base_addr = io; + dev->irq = irq; + dev->open = scc_open; + dev->stop = scc_close; + dev->do_ioctl = scc_ioctl; + dev->hard_start_xmit = scc_send_packet; + dev->get_stats = scc_get_stats; + dev->hard_header = ax25_encapsulate; + dev->rebuild_header = ax25_rebuild_header; + dev->set_mac_address = scc_set_mac_address; + dev->type = ARPHRD_AX25; + dev->hard_header_len = 73; + dev->mtu = 1500; + dev->addr_len = 7; + dev->tx_queue_len = 64; + memcpy(dev->broadcast, ax25_broadcast, 7); + memcpy(dev->dev_addr, ax25_test, 7); + dev->flags = 0; + dev_init_buffers(dev); + if (register_netdev(dev)) { + printk("dmascc: could not register %s\n", dev->name); + dev->name = NULL; + } + } + + request_region(io, hw[h].io_size, "dmascc"); + + info->next = first; + first = info; + printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[h].name, + chipnames[chip], io, irq); + return 0; +} + + +/* Driver functions */ + +static inline void write_scc(int ctl, int reg, int val) +{ + outb_p(reg, ctl); + outb_p(val, ctl); +} + + +static inline int read_scc(int ctl, int reg) +{ + outb_p(reg, ctl); + return inb_p(ctl); +} + + +static int scc_open(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + struct scc_info *info = priv->info; + int io = dev->base_addr; + int cmd = priv->cmd; + + /* Request IRQ if not already used by other channel */ + if (!info->open) { + if (request_irq(dev->irq, scc_isr, SA_INTERRUPT, "dmascc", info)) + return -EAGAIN; + } + + /* Request DMA if required */ + if (dev->dma && request_dma(dev->dma, "dmascc")) { + if (!info->open) free_irq(dev->irq, info); + return -EAGAIN; + } + + /* Initialize local variables */ + dev->tbusy = 0; + priv->rx_ptr = 0; + priv->rx_over = 0; + priv->rx_head = priv->rx_tail = priv->rx_count = 0; + priv->tx_state = TX_IDLE; + priv->tx_head = priv->tx_tail = priv->tx_count = 0; + priv->tx_ptr = 0; + priv->tx_sem = 0; + + /* Reset channel */ + write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV); + /* X1 clock, SDLC mode */ + write_scc(cmd, R4, SDLC | X1CLK); + /* DMA */ + write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN); + /* 8 bit RX char, RX disable */ + write_scc(cmd, R3, Rx8); + /* 8 bit TX char, TX disable */ + write_scc(cmd, R5, Tx8); + /* SDLC address field */ + write_scc(cmd, R6, 0); + /* SDLC flag */ + write_scc(cmd, R7, FLAG); + switch (info->chip) { + case Z85C30: + /* Select WR7' */ + write_scc(cmd, R15, 1); + /* Auto EOM reset */ + write_scc(cmd, R7, 0x02); + write_scc(cmd, R15, 0); + break; + case Z85230: + /* Select WR7' */ + write_scc(cmd, R15, 1); + /* RX FIFO half full (interrupt only), Auto EOM reset, + TX FIFO empty (DMA only) */ + write_scc(cmd, R7, dev->dma ? 0x22 : 0x0a); + write_scc(cmd, R15, 0); + break; + } + /* Preset CRC, NRZ(I) encoding */ + write_scc(cmd, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ)); + + /* Configure baud rate generator */ + if (priv->param.brg_tc >= 0) { + /* Program BR generator */ + write_scc(cmd, R12, priv->param.brg_tc & 0xFF); + write_scc(cmd, R13, (priv->param.brg_tc>>8) & 0xFF); + /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by + PackeTwin, not connected on the PI2); set DPLL source to BRG */ + write_scc(cmd, R14, SSBR | DTRREQ | BRSRC | BRENABL); + /* Enable DPLL */ + write_scc(cmd, R14, SEARCH | DTRREQ | BRSRC | BRENABL); + } else { + /* Disable BR generator */ + write_scc(cmd, R14, DTRREQ | BRSRC); + } + + /* Configure clocks */ + if (info->type == TYPE_TWIN) { + /* Disable external TX clock receiver */ + outb_p((info->twin_serial_cfg &= + ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), + io + TWIN_SERIAL_CFG); + } + write_scc(cmd, R11, priv->param.clocks); + if ((info->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) { + /* Enable external TX clock receiver */ + outb_p((info->twin_serial_cfg |= + (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), + io + TWIN_SERIAL_CFG); + } + + /* Configure PackeTwin */ + if (info->type == TYPE_TWIN) { + /* Assert DTR, enable interrupts */ + outb_p((info->twin_serial_cfg |= TWIN_EI | + (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)), + io + TWIN_SERIAL_CFG); + } + + /* Read current status */ + priv->status = read_scc(cmd, R0); + /* Enable SYNC, DCD, and CTS interrupts */ + write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE); + + /* Configure PI2 DMA */ + if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK); + + dev->start = 1; + info->open++; + MOD_INC_USE_COUNT; + + return 0; +} + + +static int scc_close(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + struct scc_info *info = priv->info; + int io = dev->base_addr; + int cmd = priv->cmd; + + dev->start = 0; + info->open--; + MOD_DEC_USE_COUNT; + + if (info->type == TYPE_TWIN) + /* Drop DTR */ + outb_p((info->twin_serial_cfg &= + (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)), + io + TWIN_SERIAL_CFG); + + /* Reset channel, free DMA */ + write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV); + if (dev->dma) { + if (info->type == TYPE_TWIN) outb_p(0, io + TWIN_DMA_CFG); + free_dma(dev->dma); + } + + if (!info->open) { + if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK); + free_irq(dev->irq, info); + } + return 0; +} + + +static int scc_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +{ + int rc; + struct scc_priv *priv = dev->priv; + + switch (cmd) { + case SIOCGSCCPARAM: + rc = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct scc_param)); + if (rc) return rc; + copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)); + return 0; + case SIOCSSCCPARAM: + if (!suser()) return -EPERM; + rc = verify_area(VERIFY_READ, ifr->ifr_data, sizeof(struct scc_param)); + if (rc) return rc; + if (dev->start) return -EAGAIN; + copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)); + dev->dma = priv->param.dma; + return 0; + default: + return -EINVAL; + } +} + + +static int scc_send_packet(struct sk_buff *skb, struct device *dev) +{ + struct scc_priv *priv = dev->priv; + struct scc_info *info = priv->info; + int cmd = priv->cmd; + unsigned long flags; + int i; + + /* Block a timer-based transmit from overlapping */ + if (test_and_set_bit(0, (void *) &priv->tx_sem) != 0) { + atomic_inc((void *) &priv->stats.tx_dropped); + dev_kfree_skb(skb, FREE_WRITE); + return 0; + } + + /* Return with an error if we cannot accept more data */ + if (dev->tbusy) { + priv->tx_sem = 0; + return -1; + } + + /* Transfer data to DMA buffer */ + i = priv->tx_head; + memcpy(priv->tx_buf[i], skb->data+1, skb->len-1); + priv->tx_len[i] = skb->len-1; + + save_flags(flags); + cli(); + + /* Set the busy flag if we just filled up the last buffer */ + priv->tx_head = (i + 1) % NUM_TX_BUF; + priv->tx_count++; + if (priv->tx_count == NUM_TX_BUF) dev->tbusy = 1; + + /* Set new TX state */ + if (priv->tx_state == TX_IDLE) { + /* Assert RTS, start timer */ + priv->tx_state = TX_TXDELAY; + if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK); + write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); + if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK); + priv->tx_start = jiffies; + delay(dev, priv->param.txdelay); + } + + restore_flags(flags); + + dev_kfree_skb(skb, FREE_WRITE); + + priv->tx_sem = 0; + return 0; +} + + +static struct enet_statistics *scc_get_stats(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + + return &priv->stats; +} + + +static int scc_set_mac_address(struct device *dev, void *sa) +{ + memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len); + return 0; +} + + +static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) +{ + struct scc_info *info = dev_id; + int is, io = info->dev[0].base_addr; + + /* We're a fast IRQ handler and are called with interrupts disabled */ + + /* IRQ sharing doesn't make sense due to ISA's edge-triggered + interrupts, hence it is safe to return if we have found and + processed a single device. */ + + /* Interrupt processing: We loop until we know that the IRQ line is + low. If another positive edge occurs afterwards during the ISR, + another interrupt will be triggered by the interrupt controller + as soon as the IRQ level is enabled again (see asm/irq.h). */ + + switch (info->type) { + case TYPE_PI: + case TYPE_PI2: + outb_p(0, io + PI_DREQ_MASK); + z8530_isr(info); + outb_p(1, io + PI_DREQ_MASK); + return; + case TYPE_TWIN: + while ((is = ~inb_p(io + TWIN_INT_REG)) & + TWIN_INT_MSK) { + if (is & TWIN_SCC_MSK) { + z8530_isr(info); + } else if (is & TWIN_TMR1_MSK) { + inb_p(io + TWIN_CLR_TMR1); + tm_isr(&info->dev[0]); + } else { + inb_p(io + TWIN_CLR_TMR2); + tm_isr(&info->dev[1]); + } + } + /* No interrupts pending from the PackeTwin */ + return; + } +} + + +static inline void z8530_isr(struct scc_info *info) +{ + int is, a_cmd; + + a_cmd = info->scc_base + SCCA_CMD; + + while ((is = read_scc(a_cmd, R3))) { + if (is & CHARxIP) { + rx_isr(&info->dev[0]); + } else if (is & CHATxIP) { + tx_isr(&info->dev[0]); + } else if (is & CHAEXT) { + es_isr(&info->dev[0]); + } else if (is & CHBRxIP) { + rx_isr(&info->dev[1]); + } else if (is & CHBTxIP) { + tx_isr(&info->dev[1]); + } else { + es_isr(&info->dev[1]); + } + } + /* Ok, no interrupts pending from this 8530. The INT line should + be inactive now. */ +} + + +static void rx_isr(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + int cmd = priv->cmd; + + if (dev->dma) { + /* Check special condition and perform error reset. See 2.4.7.5. */ + special_condition(dev, read_scc(cmd, R1)); + write_scc(cmd, R0, ERR_RES); + } else { + /* Check special condition for each character. Error reset not necessary. + Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */ + int rc; + while (read_scc(cmd, R0) & Rx_CH_AV) { + rc = read_scc(cmd, R1); + if (priv->rx_ptr < BUF_SIZE) + priv->rx_buf[priv->rx_head][priv->rx_ptr++] = read_scc(cmd, R8); + else { + priv->rx_over = 2; + read_scc(cmd, R8); + } + special_condition(dev, rc); + } + } +} + + +static void special_condition(struct device *dev, int rc) +{ + struct scc_priv *priv = dev->priv; + int cb, cmd = priv->cmd; + + /* See Figure 2-15. Only overrun and EOF need to be checked. */ + + if (rc & Rx_OVR) { + /* Receiver overrun */ + priv->rx_over = 1; + if (!dev->dma) write_scc(cmd, R0, ERR_RES); + } else if (rc & END_FR) { + /* End of frame. Get byte count */ + if (dev->dma) { + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + cb = BUF_SIZE - get_dma_residue(dev->dma) - 2; + } else { + cb = priv->rx_ptr - 2; + } + if (priv->rx_over) { + /* We had an overrun */ + priv->stats.rx_errors++; + if (priv->rx_over == 2) priv->stats.rx_length_errors++; + else priv->stats.rx_fifo_errors++; + priv->rx_over = 0; + } else if (rc & CRC_ERR) { + /* Count invalid CRC only if packet length >= minimum */ + if (cb >= 8) { + priv->stats.rx_errors++; + priv->stats.rx_crc_errors++; + } + } else { + if (cb >= 8) { + /* Put good frame in FIFO */ + priv->rx_len[priv->rx_head] = cb; + priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF; + priv->rx_count++; + if (priv->rx_count == NUM_RX_BUF) { + /* Disable receiver if FIFO full */ + write_scc(cmd, R3, Rx8); + priv->stats.rx_errors++; + priv->stats.rx_over_errors++; + } + /* Mark bottom half handler */ + queue_task(&priv->rx_task, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + } + /* Get ready for new frame */ + if (dev->dma) { + set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(dev->dma, BUF_SIZE); + enable_dma(dev->dma); + } else { + priv->rx_ptr = 0; + } + } +} + + +static void rx_bh(void *arg) +{ + struct device *dev = arg; + struct scc_priv *priv = dev->priv; + struct scc_info *info = priv->info; + int cmd = priv->cmd; + int i = priv->rx_tail; + int cb; + unsigned long flags; + struct sk_buff *skb; + unsigned char *data; + + save_flags(flags); + cli(); + + while (priv->rx_count) { + restore_flags(flags); + cb = priv->rx_len[i]; + /* Allocate buffer */ + skb = dev_alloc_skb(cb+1); + if (skb == NULL) { + /* Drop packet */ + priv->stats.rx_dropped++; + } else { + /* Fill buffer */ + data = skb_put(skb, cb+1); + data[0] = 0; + memcpy(&data[1], priv->rx_buf[i], cb); + skb->dev = dev; + skb->protocol = ntohs(ETH_P_AX25); + skb->mac.raw = skb->data; + netif_rx(skb); + priv->stats.rx_packets++; + } + save_flags(flags); + cli(); + /* Enable receiver if RX buffers have been unavailable */ + if ((priv->rx_count == NUM_RX_BUF) && (priv->status & DCD)) { + if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK); + write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB); + if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK); + } + /* Move tail */ + priv->rx_tail = i = (i + 1) % NUM_RX_BUF; + priv->rx_count--; + } + + restore_flags(flags); +} + + +static void tx_isr(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + int cmd = priv->cmd; + int i = priv->tx_tail, p = priv->tx_ptr; + + /* Suspend TX interrupts if we don't want to send anything. + See Figure 2-22. */ + if (p == priv->tx_len[i]) { + write_scc(cmd, R0, RES_Tx_P); + return; + } + + /* Write characters */ + while ((read_scc(cmd, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) { + write_scc(cmd, R8, priv->tx_buf[i][p++]); + } + priv->tx_ptr = p; + +} + + +static void es_isr(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + struct scc_info *info = priv->info; + int i, cmd = priv->cmd; + int st, dst, res; + + /* Read status and reset interrupt bit */ + st = read_scc(cmd, R0); + write_scc(cmd, R0, RES_EXT_INT); + dst = priv->status ^ st; + priv->status = st; + + /* Since the EOM latch is reset automatically, we assume that + it has been zero if and only if we are in the TX_ACTIVE state. + Otherwise we follow 2.4.9.6. */ + + /* Transmit underrun */ + if ((priv->tx_state == TX_ACTIVE) && (st & TxEOM)) { + /* Get remaining bytes */ + i = priv->tx_tail; + if (dev->dma) { + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + res = get_dma_residue(dev->dma); + } else { + res = priv->tx_len[i] - priv->tx_ptr; + if (res) write_scc(cmd, R0, RES_Tx_P); + priv->tx_ptr = 0; + } + /* Remove frame from FIFO */ + priv->tx_tail = (i + 1) % NUM_TX_BUF; + priv->tx_count--; + dev->tbusy = 0; + /* Check if another frame is available and we are allowed to transmit */ + if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) { + if (dev->dma) { + set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]); + set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]); + enable_dma(dev->dma); + } else { + /* If we have an ESCC, we are allowed to write data bytes + immediately. Otherwise we have to wait for the next + TX interrupt. See Figure 2-22. */ + if (info->chip == Z85230) { + tx_isr(dev); + } + } + } else { + /* No frame available. Disable interrupts. */ + priv->tx_state = TX_SQDELAY; + delay(dev, priv->param.sqdelay); + write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE); + write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN); + } + /* Update packet statistics */ + if (res) { + priv->stats.tx_errors++; + priv->stats.tx_fifo_errors++; + } else { + priv->stats.tx_packets++; + } + /* Inform upper layers */ + mark_bh(NET_BH); + } + + /* DCD transition */ + if ((priv->tx_state < TX_TXDELAY) && (dst & DCD)) { + /* Transmitter state change */ + priv->tx_state = TX_OFF; + /* Enable or disable receiver */ + if (st & DCD) { + if (dev->dma) { + /* Program DMA controller */ + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + set_dma_mode(dev->dma, DMA_MODE_READ); + set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(dev->dma, BUF_SIZE); + enable_dma(dev->dma); + /* Configure PackeTwin DMA */ + if (info->type == TYPE_TWIN) { + outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, + dev->base_addr + TWIN_DMA_CFG); + } + /* Sp. cond. intr. only, ext int enable */ + write_scc(cmd, R1, EXT_INT_ENAB | INT_ERR_Rx | + WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); + } else { + /* Intr. on all Rx characters and Sp. cond., ext int enable */ + write_scc(cmd, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | + WT_FN_RDYFN); + } + if (priv->rx_count < NUM_RX_BUF) { + /* Enable receiver */ + write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB); + } + } else { + /* Disable DMA */ + if (dev->dma) disable_dma(dev->dma); + /* Disable receiver */ + write_scc(cmd, R3, Rx8); + /* DMA disable, RX int disable, Ext int enable */ + write_scc(cmd, R1, EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN); + /* Transmitter state change */ + if (random() > priv->param.persist) + delay(dev, priv->param.slottime); + else { + if (priv->tx_count) { + priv->tx_state = TX_TXDELAY; + write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); + priv->tx_start = jiffies; + delay(dev, priv->param.txdelay); + } else { + priv->tx_state = TX_IDLE; + } + } + } + } + + /* CTS transition */ + if ((info->type <= TYPE_PI2) && (dst & CTS) && (~st & CTS)) { + /* Timer has expired */ + tm_isr(dev); + } + + /* /SYNC/HUNT transition */ + if ((dst & SYNC_HUNT) && (~st & SYNC_HUNT)) { + /* Reset current frame and clear RX FIFO */ + while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8); + priv->rx_over = 0; + if (dev->dma) { + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(dev->dma, BUF_SIZE); + enable_dma(dev->dma); + } else { + priv->rx_ptr = 0; + } + } +} + + +static void tm_isr(struct device *dev) +{ + struct scc_priv *priv = dev->priv; + struct scc_info *info = priv->info; + int cmd = priv->cmd; + + switch (priv->tx_state) { + case TX_OFF: + if (~priv->status & DCD) { + if (random() > priv->param.persist) delay(dev, priv->param.slottime); + else { + if (priv->tx_count) { + priv->tx_state = TX_TXDELAY; + write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8); + priv->tx_start = jiffies; + delay(dev, priv->param.txdelay); + } else { + priv->tx_state = TX_IDLE; + } + } + } + break; + case TX_TXDELAY: + priv->tx_state = TX_ACTIVE; + if (dev->dma) { + /* Program DMA controller */ + disable_dma(dev->dma); + clear_dma_ff(dev->dma); + set_dma_mode(dev->dma, DMA_MODE_WRITE); + set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]); + set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]); + enable_dma(dev->dma); + /* Configure PackeTwin DMA */ + if (info->type == TYPE_TWIN) { + outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, + dev->base_addr + TWIN_DMA_CFG); + } + /* Enable interrupts and DMA. On the PackeTwin, the DTR//REQ pin + is used for TX DMA requests, but we enable the WAIT/DMA request + pin, anyway */ + write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE); + write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); + } else { + write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE); + write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); + tx_isr(dev); + } + if (info->chip == Z8530) write_scc(cmd, R0, RES_EOM_L); + break; + case TX_SQDELAY: + /* Disable transmitter */ + write_scc(cmd, R5, TxCRC_ENAB | Tx8); + /* Transmitter state change: Switch to TX_OFF and wait at least + 1 slottime. */ + priv->tx_state = TX_OFF; + if (~priv->status & DCD) delay(dev, priv->param.waittime); + } +} + + +static inline void delay(struct device *dev, int t) +{ + struct scc_priv *priv = dev->priv; + int tmr = priv->tmr; + + outb_p(t & 0xFF, tmr); + outb_p((t >> 8) & 0xFF, tmr); +} + + +static inline unsigned char random(void) +{ + /* See "Numerical Recipes in C", second edition, p. 284 */ + rand = rand * 1664525L + 1013904223L; + return (unsigned char) (rand >> 24); +} + + diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c index b8446f05f206..62558807a28e 100644 --- a/drivers/net/e2100.c +++ b/drivers/net/e2100.c @@ -44,6 +44,7 @@ static const char *version = #include #include #include +#include #include #include diff --git a/drivers/net/eql.c b/drivers/net/eql.c index 386708670092..685b1f850d16 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -329,7 +329,7 @@ static int eql_close(struct device *dev) static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd) { - if(!suser() && cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG) + if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && !suser()) return -EPERM; switch (cmd) { diff --git a/drivers/net/hamradio/Config.in b/drivers/net/hamradio/Config.in index 4c4ba23530f6..94a86238fa14 100644 --- a/drivers/net/hamradio/Config.in +++ b/drivers/net/hamradio/Config.in @@ -25,8 +25,6 @@ if [ "$CONFIG_HAMRADIO" != "n" ] ; then tristate 'Serial port KISS driver' CONFIG_MKISS # tristate 'Serial port 6PACK driver' CONFIG_6PACK tristate 'BPQ Ethernet driver' CONFIG_BPQETHER - tristate 'Gracilis PackeTwin driver' CONFIG_PT - tristate 'Ottawa PI and PI2 driver' CONFIG_PI tristate 'Z8530 SCC driver' CONFIG_SCC if [ "$CONFIG_SCC" != "n" ]; then diff --git a/drivers/net/hamradio/soundmodem/sm_sbc.c b/drivers/net/hamradio/soundmodem/sm_sbc.c index bbef05a5d4f9..e66a2e5cb2b3 100644 --- a/drivers/net/hamradio/soundmodem/sm_sbc.c +++ b/drivers/net/hamradio/soundmodem/sm_sbc.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "sm.h" #include "smdma.h" @@ -144,8 +145,7 @@ static int inline reset_dsp(struct device *dev) int i; outb(1, DSP_RESET(dev->base_addr)); - for (i = 0; i < 0x100; i++) - SLOW_DOWN_IO; + udelay(300); outb(0, DSP_RESET(dev->base_addr)); for (i = 0; i < 0xffff; i++) if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 04cc029615ed..efbfc54e4ec7 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -665,9 +665,7 @@ ne_block_output(struct device *dev, int count, outb_p(0x00, nic_base + EN0_RSARHI); outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); /* Make certain that the dummy read has occurred. */ - SLOW_DOWN_IO; - SLOW_DOWN_IO; - SLOW_DOWN_IO; + udelay(6); #endif outb_p(ENISR_RDC, nic_base + EN0_ISR); diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index d3d6dc3a69f5..80b8bd37ed93 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -1,13 +1,13 @@ dep_tristate 'ProAudioSpectrum 16 support' CONFIG_PAS $CONFIG_SOUND -dep_tristate '100%% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND +dep_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND dep_tristate 'Generic OPL2/OPL3 FM synthesizer support' CONFIG_ADLIB $CONFIG_SOUND dep_tristate 'Gravis Ultrasound support' CONFIG_GUS $CONFIG_SOUND -dep_tristate 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 $CONFIG_SOUND -dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND if [ "$CONFIG_GUS" != "n" ]; then bool '16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16 bool 'GUS MAX support' CONFIG_GUSMAX fi +dep_tristate 'MPU-401 support (NOT for SB16)' CONFIG_MPU401 $CONFIG_SOUND +dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND dep_tristate 'Microsoft Sound System support' CONFIG_MSS $CONFIG_SOUND dep_tristate 'Ensoniq SoundScape support' CONFIG_SSCAPE $CONFIG_SOUND dep_tristate 'MediaTrix AudioTrix Pro support' CONFIG_TRIX $CONFIG_SOUND @@ -18,294 +18,125 @@ dep_tristate 'Yamaha OPL3-SA1 audio controller' CONFIG_OPL3SA1 $CONFIG_SOUND dep_tristate 'SoftOSS software wave table engine' CONFIG_SOFTOSS $CONFIG_SOUND dep_tristate 'FM synthesizer (YM3812/OPL-3) support' CONFIG_YM3812 $CONFIG_SOUND -if [ "$CONFIG_AEDSP16" = "y" ]; then -hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220 -fi - -if [ "$CONFIG_SB" = "y" ]; then -hex 'I/O base for SB Check from manual of the card' SBC_BASE 220 -fi - -if [ "$CONFIG_SB" = "y" ]; then -int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7 +if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then + hex 'I/O base for Audio Excel DSP 16 220 or 240' AEDSP16_BASE 220 fi -if [ "$CONFIG_SB" = "y" ]; then -int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1 +if [ "$CONFIG_SB" = "y" -o "$CONFIG_SB" = "m" ]; then + hex 'I/O base for SB Check from manual of the card' SBC_BASE 220 + int 'Sound Blaster IRQ Check from manual of the card' SBC_IRQ 7 + int 'Sound Blaster DMA 0, 1 or 3' SBC_DMA 1 + int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5 + hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330 + comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.' + comment 'Enter -1 to the following question if you have something else such as SB16/32.' + int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1 fi -if [ "$CONFIG_SB" = "y" ]; then -int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' SB_DMA2 5 -fi - -if [ "$CONFIG_SB" = "y" ]; then -hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' SB_MPU_BASE 330 -fi - - -if [ "$CONFIG_SB" = "y" ]; then -comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.' -fi - - -if [ "$CONFIG_SB" = "y" ]; then -comment 'Enter -1 to the following question if you have something else such as SB16/32.' +if [ "$CONFIG_PAS" = "y" -o "$CONFIG_PAS" = "m" ]; then + int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10 + int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3 fi -if [ "$CONFIG_SB" = "y" ]; then -int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' SB_MPU_IRQ -1 -fi - -if [ "$CONFIG_PAS" = "y" ]; then -int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' PAS_IRQ 10 -fi - -if [ "$CONFIG_PAS" = "y" ]; then -int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' PAS_DMA 3 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6 -fi - -if [ "$CONFIG_GUS" = "y" ]; then -int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1 +if [ "$CONFIG_GUS" = "y" -o "$CONFIG_GUS" = "m" ]; then + hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' GUS_BASE 220 + int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' GUS_IRQ 15 + int 'GUS DMA 1, 3, 5, 6 or 7' GUS_DMA 6 + int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' GUS_DMA2 -1 fi if [ "$CONFIG_GUS16" = "y" ]; then -hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530 + hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' GUS16_BASE 530 + int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7 + int 'GUS DMA 0, 1 or 3' GUS16_DMA 3 fi -if [ "$CONFIG_GUS16" = "y" ]; then -int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' GUS16_IRQ 7 +if [ "$CONFIG_MPU401" = "y" -o "$CONFIG_MPU401" = "m" ]; then + hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330 + int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9 fi -if [ "$CONFIG_GUS16" = "y" ]; then -int 'GUS DMA 0, 1 or 3' GUS16_DMA 3 +if [ "$CONFIG_MAUI" = "y" -o "$CONFIG_MAUI" = "M" ]; then + comment 'ERROR! You have to use old sound configuration method with Maui.' + hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330 + int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9 fi -if [ "$CONFIG_MPU401" = "y" ]; then -hex 'I/O base for MPU401 Check from manual of the card' MPU_BASE 330 +if [ "$CONFIG_UART6850" = "y" -o "$CONFIG_UART6850" = "m" ]; then + hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0 + int 'UART6850 IRQ (Unknown)' U6850_IRQ -1 fi -if [ "$CONFIG_MPU401" = "y" ]; then -int 'MPU401 IRQ Check from manual of the card' MPU_IRQ 9 +if [ "$CONFIG_PSS" = "y" -o "$CONFIG_PSS" = "y" ]; then + comment 'ERROR! You have to use old sound configuration method with PSS cards.' + hex 'PSS I/O base 220 or 240' PSS_BASE 220 + hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530 + int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11 + int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3 + hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330 + int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9 fi - -if [ "$CONFIG_MAUI" = "y" ]; then -comment 'ERROR! You have to use old sound configuration method with Maui.' +if [ "$CONFIG_MSS" = "y" -o "$CONFIG_MSS" = "m" ]; then + hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530 + int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11 + int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3 + int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1 fi -if [ "$CONFIG_MAUI" = "y" ]; then -hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' MAUI_BASE 330 +if [ "$CONFIG_SSCAPE" = "y" -o "$CONFIG_SSCAPE" = "m" ]; then + hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330 + int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9 + int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3 + hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534 + int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11 fi -if [ "$CONFIG_MAUI" = "y" ]; then -int 'Maui IRQ 5, 9, 12 or 15' MAUI_IRQ 9 +if [ "$CONFIG_TRIX" = "y" -o "$CONFIG_TRIX" = "m" ]; then + comment 'ERROR! You have to use old sound configuration method with OPL3-SA1.' + hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' TRIX_BASE 530 + int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11 + int 'OPL3-SA1 audio DMA 0, 1 or 3' TRIX_DMA 0 + int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3 + hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330 + int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9 + hex 'OPL3-SA1 SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220 + int 'OPL3-SA1 SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7 + int 'OPL3-SA1 SB DMA 1 or 3' TRIX_SB_DMA 1 fi -if [ "$CONFIG_UART6850" = "y" ]; then -hex 'I/O base for UART 6850 MIDI port (Unknown)' U6850_BASE 0 +if [ "$CONFIG_OPL3SA1" = "y" -o "$CONFIG_OPL3SA1" = "m" ]; then + hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' OPL3SA1_BASE 530 + int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' OPL3SA1_IRQ 11 + int 'OPL3-SA1 audio DMA 0, 1 or 3' OPL3SA1_DMA 0 + int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' OPL3SA1_DMA2 3 + hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' OPL3SA1_MPU_BASE 330 + int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' OPL3SA1_MPU_IRQ 9 fi -if [ "$CONFIG_UART6850" = "y" ]; then -int 'UART6850 IRQ (Unknown)' U6850_IRQ -1 +if [ "$CONFIG_CS4232" = "y" -o "$CONFIG_CS4232" = "m" ]; then + hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530 + int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11 + int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0 + int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3 + hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330 + int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9 fi - -if [ "$CONFIG_PSS" = "y" ]; then -comment 'ERROR! You have to use old sound configuration method with PSS cards.' -fi - -if [ "$CONFIG_PSS" = "y" ]; then -hex 'PSS I/O base 220 or 240' PSS_BASE 220 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -hex 'PSS audio I/O base 530, 604, E80 or F40' PSS_MSS_BASE 530 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -int 'PSS audio IRQ 7, 9, 10 or 11' PSS_MSS_IRQ 11 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -int 'PSS audio DMA 0, 1 or 3' PSS_MSS_DMA 3 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -hex 'PSS MIDI I/O base ' PSS_MPU_BASE 330 -fi - -if [ "$CONFIG_PSS" = "y" ]; then -int 'PSS MIDI IRQ 3, 4, 5, 7 or 9' PSS_MPU_IRQ 9 -fi - -if [ "$CONFIG_MSS" = "y" ]; then -hex 'MSS/WSS I/O base 530, 604, E80 or F40' MSS_BASE 530 +if [ "$CONFIG_MAD16" = "y" -o "$CONFIG_MAD16" = "m" ]; then + hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530 + int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11 + int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3 + int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0 + hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330 + int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9 fi -if [ "$CONFIG_MSS" = "y" ]; then -int 'MSS/WSS IRQ 7, 9, 10 or 11' MSS_IRQ 11 +if [ "$CONFIG_SOFTOSS" = "y" -o "$CONFIG_SOFTOSS" = "m" ]; then + int 'Sampling rate for SoftOSS 8000 to 48000' SOFTOSS_RATE 22050 + int 'Max # of concurrent voices for SoftOSS 4 to 32' SOFTOSS_VOICES 32 fi -if [ "$CONFIG_MSS" = "y" ]; then -int 'MSS/WSS DMA 0, 1 or 3' MSS_DMA 3 -fi - -if [ "$CONFIG_MSS" = "y" ]; then -int 'MSS/WSS second DMA (if possible) 0, 1 or 3' MSS_DMA2 -1 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' SSCAPE_BASE 330 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -int 'SoundScape MIDI IRQ ' SSCAPE_IRQ 9 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -int 'SoundScape initialization DMA 0, 1 or 3' SSCAPE_DMA 3 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -hex 'SoundScape audio I/O base 534, 608, E84 or F44' SSCAPE_MSS_BASE 534 -fi - -if [ "$CONFIG_SSCAPE" = "y" ]; then -int 'SoundScape audio IRQ 7, 9, 10 or 11' SSCAPE_MSS_IRQ 11 -fi - - -if [ "$CONFIG_TRIX" = "y" ]; then -comment 'ERROR! You have to use old sound configuration method with OPL3-SA1.' -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' TRIX_BASE 530 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' TRIX_IRQ 11 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'OPL3-SA1 audio DMA 0, 1 or 3' TRIX_DMA 0 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' TRIX_DMA2 3 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' TRIX_MPU_BASE 330 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' TRIX_MPU_IRQ 9 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -hex 'OPL3-SA1 SB I/O base 220, 210, 230, 240, 250, 260 or 270' TRIX_SB_BASE 220 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'OPL3-SA1 SB IRQ 3, 4, 5 or 7' TRIX_SB_IRQ 7 -fi - -if [ "$CONFIG_TRIX" = "y" ]; then -int 'OPL3-SA1 SB DMA 1 or 3' TRIX_SB_DMA 1 -fi - -if [ "$CONFIG_OPL3SA1" = "y" ]; then -hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' OPL3SA1_BASE 530 -fi - -if [ "$CONFIG_OPL3SA1" = "y" ]; then -int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' OPL3SA1_IRQ 11 -fi - -if [ "$CONFIG_OPL3SA1" = "y" ]; then -int 'OPL3-SA1 audio DMA 0, 1 or 3' OPL3SA1_DMA 0 -fi - -if [ "$CONFIG_OPL3SA1" = "y" ]; then -int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' OPL3SA1_DMA2 3 -fi - -if [ "$CONFIG_OPL3SA1" = "y" ]; then -hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' OPL3SA1_MPU_BASE 330 -fi - -if [ "$CONFIG_OPL3SA1" = "y" ]; then -int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' OPL3SA1_MPU_IRQ 9 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -hex 'CS4232 audio I/O base 530, 604, E80 or F40' CS4232_BASE 530 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CS4232_IRQ 11 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 audio DMA 0, 1 or 3' CS4232_DMA 0 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 second (duplex) DMA 0, 1 or 3' CS4232_DMA2 3 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CS4232_MPU_BASE 330 -fi - -if [ "$CONFIG_CS4232" = "y" ]; then -int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CS4232_MPU_IRQ 9 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -hex 'MAD16 audio I/O base 530, 604, E80 or F40' MAD16_BASE 530 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 audio IRQ 7, 9, 10 or 11' MAD16_IRQ 11 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 audio DMA 0, 1 or 3' MAD16_DMA 3 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 second (duplex) DMA 0, 1 or 3' MAD16_DMA2 0 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' MAD16_MPU_BASE 330 -fi - -if [ "$CONFIG_MAD16" = "y" ]; then -int 'MAD16 MIDI IRQ 5, 7, 9 or 10' MAD16_MPU_IRQ 9 -fi - -if [ "$CONFIG_SOFTOSS" = "y" ]; then -int 'Sampling rate for SoftOSS 8000 to 48000' SOFTOSS_RATE 22050 -fi - -if [ "$CONFIG_SOFTOSS" = "y" ]; then -int 'Max # of concurrent voices for SoftOSS 4 to 32' SOFTOSS_VOICES 32 -fi # $MAKE -C drivers/sound kernelconfig || exit 1 bool 'Additional low level drivers' CONFIG_LOWLEVEL_SOUND @@ -319,7 +150,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then comment 'SC-6600 Audio Cards have no jumper switches at all' bool 'SC-6600 based audio cards (new Audio Excel DSP 16)' CONFIG_SC6600 - if [ "$CONFIG_SB" = "y" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then + if [ "$CONFIG_SB" = "y" -o "$CONFIG_SB" = "m" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then bool 'Audio Excel DSP 16 (SBPro emulation)' CONFIG_AEDSP16_SBPRO if [ "$CONFIG_AEDSP16_SBPRO" = "y" ]; then comment 'Audio Excel DSP 16 [Sound Blaster Pro]' @@ -331,7 +162,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then fi fi - if [ "$CONFIG_MSS" = "y" -a "$CONFIG_AEDSP16_SBPRO" != "y" ]; then + if [ "$CONFIG_MSS" = "y" -o "$CONFIG_MSS" = "m" -a "$CONFIG_AEDSP16_SBPRO" != "y" ]; then bool 'Audio Excel DSP 16 (MSS emulation)' CONFIG_AEDSP16_MSS if [ "$CONFIG_AEDSP16_MSS" = "y" ]; then comment 'Audio Excel DSP 16 [Microsoft Sound System]' @@ -342,7 +173,7 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then fi fi - if [ "$CONFIG_MPU401" = "y" ]; then + if [ "$CONFIG_MPU401" = "y" -o "$CONFIG_MPU401" = "m" ]; then bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401 if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then comment 'Audio Excel DSP 16 [MPU-401]' @@ -365,3 +196,4 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then fi fi + diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index edd69e438c4c..fb81925b245f 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -35,7 +35,7 @@ else ifeq (.defines,$(wildcard .defines)) include .defines -include .objects +#include .objects endif TARGET_OS=linux @@ -66,25 +66,20 @@ ifeq ($(CONFIG_MIDI),y) LX_OBJS += midi_synth.o endif -ifeq ($(CONFIG_MIDI),y) - L_OBJS += midibuf.o - LX_OBJS += midi_synth.o -endif - #ifeq ($(CONFIG_AUDIO),y) #L_OBJS += dmabuf.o #endif ifeq ($(CONFIG_YM3812),y) -LX_OBJS += opl3.o +LX_OBJS += adlib_card.o opl3.o else ifeq ($(CONFIG_YM3812),m) - MX_OBJS += opl3.o + MX_OBJS += adlib_card.o opl3.o endif endif ifeq ($(CONFIG_PAS),y) -L_OBJS += pas2_card.c pas2_midi.c pas2_mixer.c pas2_pcm.c +L_OBJS += pas2.o else ifeq ($(CONFIG_PAS),m) M_OBJS += pas2.o @@ -92,7 +87,7 @@ else endif ifeq ($(CONFIG_GUS),y) -L_OBJS += gus_card.c gus_midi.c gus_vol.c gus_wave.c ics2101.c +L_OBJS += gus.o else ifeq ($(CONFIG_GUS),m) M_OBJS += gus.o @@ -105,7 +100,8 @@ LX_OBJS += sb_card.o uart401.o else ifeq ($(CONFIG_SB),m) M_OBJS += sb.o - MX_OBJS += sb_card.o uart401.o + MX_OBJS += uart401.o + MIX_OBJS += sb_card.o endif endif @@ -130,6 +126,14 @@ LX_OBJS += mpu401.o else ifeq ($(CONFIG_MPU401),m) MX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),y) + LX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),m) + MX_OBJS += mpu401.o + endif + endif endif endif @@ -205,6 +209,16 @@ else endif endif +ifeq ($(CONFIG_OPL3SA1),y) +L_OBJS += opl3sa.o +LX_OBJS += ad1848.o +else + ifeq ($(CONFIG_OPL3SA1),m) + M_OBJS += opl3sa.o + MX_OBJS += ad1848.o + endif +endif + include $(TOPDIR)/Rules.make softoss2.o: softoss.o softoss_rs.o @@ -248,4 +262,13 @@ setup: mkscript: +config: configure + @$(MAKE) setup + @./configure > local.h + @echo \#define SOUND_CONFIG_DATE \"`date`\" >> local.h + @echo \#define SOUND_CONFIG_BY \"`whoami`\" >> local.h +# @echo \#define SOUND_CONFIG_HOST \"`hostname`\" >> local.h 2>/dev/null +# @echo \#define SOUND_CONFIG_DOMAIN \"`hostname -d`\" >> local.h 2>/dev/null + @echo \#define SOUND_UNAME_A \"`uname -a`\" >> local.h + endif diff --git a/drivers/sound/Readme b/drivers/sound/Readme index 113ad9130798..9fb851c5ff80 100644 --- a/drivers/sound/Readme +++ b/drivers/sound/Readme @@ -2,7 +2,7 @@ OSS/Free version 3.8 release notes ---------------------------------- Most up to date information about this driver is available from -http://www.4front-tech.com/ossfree. +http://www.opensound.com/ossfree. @@ -11,7 +11,7 @@ sites). It gives instructions about using sound with Linux. It's bit out of date but still very useful. Information about bug fixes and such things is available from the web page (see above). -Please check http://www.4front-tech.com/pguide for more info about programming +Please check http://www.opensound.com/pguide for more info about programming with OSS API. ==================================================== @@ -20,7 +20,7 @@ with OSS API. Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z" contain useful utilities to be used with this driver. -See http://www.4front-tech.com/ossfree/getting.html for +See http://www.opensound.com/ossfree/getting.html for download instructions. If you are looking for the installation instructions, please @@ -31,7 +31,7 @@ Supported soundcards See Readme.cards. -Please check http://www.4front-tech.com/ossfree if you don't find +Please check http://www.opensound.com/ossfree if you don't find your soundcard there. Contributors @@ -86,7 +86,7 @@ changed or what you have planned to do. Also ensure you are using the very latest (development) version of OSS/Free since the change may already be implemented there. In general it's major waste of time to try to improve several months old version. Information about the latest version can be found -from http://www.4front-tech.com/ossfree. In general there is no point in +from http://www.opensound.com/ossfree. In general there is no point in sending me patches relative to production kernels. Sponsors etc. @@ -123,7 +123,7 @@ If you have some problems ========================= Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?). -Also look at the home page (http://www.4front-tech.com/ossfree). It may +Also look at the home page (http://www.opensound.com/ossfree). It may contain info about some recent bug fixes. It's likely that you have some problems when trying to use the sound driver @@ -177,8 +177,8 @@ Best regards, Hannu Hannu Savolainen -hannu@4front-tech.com -(Please check http://www.4front-tech.com/ossfree before mailing me). +hannu@opensound.com +(Please check http://www.opensound.com/ossfree before mailing me). Snail mail: Hannu Savolainen Hiekkalaiturintie 3 A 8 diff --git a/drivers/sound/Readme.cards b/drivers/sound/Readme.cards index 79bbe464bfb7..dff774546ab5 100644 --- a/drivers/sound/Readme.cards +++ b/drivers/sound/Readme.cards @@ -4,7 +4,7 @@ Configuring version 3.8 (for Linux) with some most common soundcards This document describes configuring soundcards with freeware version of Open Sound Systems (OSS/Free). Information about the commercial version (OSS/Linux) and it's configuration is available from -http://www.4front-tech.com/linux.html. Information presented here is +http://www.opensound.com/linux.html. Information presented here is not valid for OSS/Linux. If you are unsure about how to configure OSS/Free @@ -15,7 +15,7 @@ you can use the information included in soundon.log when configuring OSS/Free. IMPORTANT! This document covers only cards that were "known" when this driver version was released. Please look at - http://www.4front-tech.com/ossfree for info about + http://www.opensound.com/ossfree for info about cards introduced recently. The following covers mainly the "old" configuration @@ -115,7 +115,7 @@ ancestors which are covered by this document. Cards that are not (fully) supported by this driver =================================================== -See http://www.4front-tech.com/ossfree for information about soundcards +See http://www.opensound.com/ossfree for information about soundcards to be supported in future. @@ -174,7 +174,7 @@ support for PnP cards. There are bugs in setting DMA channels in earlier versions of isapnptools so at least version 1.6 is required with soundcards. Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers. -See http://www.4front-tech.com/linux.html for more info. This is the way +See http://www.opensound.com/linux.html for more info. This is the way you probably like to do it if you don't waste hours of time in recompiling kernel and the required tools. @@ -1231,7 +1231,7 @@ distributed driver (diffs) for the card. Writing a driver for a new card is not possible if there are no programming information available about the card. If you don't find your new card from this file, look from the home page -(http://www.4front-tech.com/ossfree). Then please contact +(http://www.opensound.com/ossfree). Then please contact manufacturer of the card and ask if they have (or are willing to) released technical details of the card. Do this before contacting me. I can only answer 'no' if there are no programming information available. @@ -1252,7 +1252,7 @@ of this driver (see http://www.4Front-tech.com/oss.html for more info). There are some common audio chipsets that are not supported yet. For example Sierra Aria and IBM Mwave. It's possible that these architectures get some support in future but I can't make any promises. Just look -at the home page (http://www.4front-tech.com/ossfree/new_cards.html) +at the home page (http://www.opensound.com/ossfree/new_cards.html) for latest info. Information about unsupported soundcards and chipsets is welcome as well @@ -1261,10 +1261,10 @@ as free copies of soundcards, SDKs and operating systems. If you have any corrections and/or comments, please contact me. Hannu Savolainen -hannu@4front-tech.com +hannu@opensound.com -Personal home page: http://personal.eunet.fi/pp/voxware/hannu.html -www home page of OSS/Free: http://www.4front-tech.com/ossfree +Personal home page: http://www.compusonic.fi/~hannu +www home page of OSS/Free: http://www.opensound.com/ossfree www home page of commercial OSS -(Open Sound System) drivers: http://www.4front-tech.com/oss.html +(Open Sound System) drivers: http://www.opensound.com/oss.html diff --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux index 103470869a4a..b3fa3a833099 100644 --- a/drivers/sound/Readme.linux +++ b/drivers/sound/Readme.linux @@ -67,10 +67,10 @@ Readme.cards for info about configuring the driver with your card. Also check for possible boot (insmod) time error messages in /var/adm/messages. - Other messages or problems -Please check http://www.4front-tech.com/ossfree for more info. +Please check http://www.opensound.com/ossfree for more info. Hannu Savolainen -hannu@4front-tech.com +hannu@opensound.com ----------------- cut here ------------------------------ SURPRISE SURPRISE!!! diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index 24bbaa0e0b97..3ccdc589296e 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -304,6 +304,9 @@ audio_read(int dev, struct fileinfo *file, char *buf, int count) if (dev_nblock[dev] && buf_no == -EAGAIN) return p; + if (p > 0) /* Avoid throwing away data */ + return p; /* Return it instead */ + return buf_no; } if (l > c) @@ -958,6 +961,34 @@ dma_ioctl(int dev, unsigned int cmd, caddr_t arg) } break; + case SNDCTL_DSP_GETODELAY: + { + int count; + unsigned long flags; + struct dma_buffparms *dmap = dmap_out; + + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return -EINVAL; + if (!(dmap->flags & DMA_ALLOC_DONE)) + return (*(int *) arg = 0); + + save_flags (flags); + cli (); + /* Compute number of bytes that have been played */ + count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT); + if (count < dmap->fragment_size && dmap->qhead != 0) + count += dmap->bytes_in_use; /* Pointer wrap not handled yet */ + count += dmap->byte_counter; + + /* Substract current count from the number of bytes written by app */ + count = dmap->user_counter - count; + if (count < 0) + count = 0; + restore_flags (flags); + + return (*(int *) arg = count); + } + break; case SNDCTL_DSP_POST: ; diff --git a/drivers/sound/configure.c b/drivers/sound/configure.c index aea32b388a28..e00ca26f5bb4 100644 --- a/drivers/sound/configure.c +++ b/drivers/sound/configure.c @@ -1132,8 +1132,8 @@ ask_parameters(void) ask_int_choice(B(OPT_CS4232), "CS4232_BASE", "CS4232 audio I/O base", FMT_HEX, - 0x530, - "530, 604, E80 or F40"); + 0x534, + "534, 608, E84 or F44"); ask_int_choice(B(OPT_CS4232), "CS4232_IRQ", "CS4232 audio IRQ", diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index 4e41468f0b39..ab5164ee4d2a 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -13,6 +13,7 @@ #include #define BE_CONSERVATIVE +#define SAMPLE_ROUNDUP 0 #include "sound_config.h" @@ -896,7 +897,7 @@ find_output_space(int dev, char **buf, int *size) active_offs += dmap->byte_counter; #endif - offs = (dmap->user_counter % dmap->bytes_in_use) & ~3; + offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP; if (offs < 0 || offs >= dmap->bytes_in_use) { printk("OSS: Got unexpected offs %ld. Giving up.\n", offs); @@ -920,10 +921,10 @@ find_output_space(int dev, char **buf, int *size) { len = (maxfrags * dmap->fragment_size) - occupied_bytes; } - *size = len & ~3; + *size = len & ~SAMPLE_ROUNDUP; restore_flags(flags); - return (len > 0); + return (*size > 0); } int diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c index a9ac8850e709..8ac02d49000d 100644 --- a/drivers/sound/lowlevel/awe_wave.c +++ b/drivers/sound/lowlevel/awe_wave.c @@ -564,7 +564,7 @@ int attach_awe(void) synth_devs[my_dev] = &awe_operations; #ifdef CONFIG_AWE32_MIXER - if ((my_mixerdev=sound_alloc_mixerdev())!=-1) { + if ((my_mixerdev=sound_alloc_mixerdev())==-1) { mixer_devs[my_mixerdev] = &awe_mixer_operations; } #endif diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c index f1f6559c42ec..bffc6ef17647 100644 --- a/drivers/sound/mad16.c +++ b/drivers/sound/mad16.c @@ -795,6 +795,18 @@ int cddma = 3; int opl4 = 0; int joystick = 0; +MODULE_PARM(io,"i"); +MODULE_PARM(dma,"i"); +MODULE_PARM(dma16,"i"); +MODULE_PARM(irq,"i"); +MODULE_PARM(cdtype,"i"); +MODULE_PARM(cdirq,"i"); +MODULE_PARM(cdport,"i"); +MODULE_PARM(cddma,"i"); +MODULE_PARM(opl4,"i"); +MODULE_PARM(joystick,"i"); + + static int found_mpu; diff --git a/drivers/sound/midi_synth.c b/drivers/sound/midi_synth.c index f0f774e3e490..b123473cc59f 100644 --- a/drivers/sound/midi_synth.c +++ b/drivers/sound/midi_synth.c @@ -498,15 +498,15 @@ midi_synth_load_patch(int dev, int format, const char *addr, return 0; if (format != SYSEX_PATCH) - { - printk("MIDI Error: Invalid patch format (key) 0x%x\n", format); + { +/* printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/ return -EINVAL; - } + } if (count < hdr_size) - { - printk("MIDI Error: Patch header too short\n"); - return -EINVAL; - } + { +/* printk("MIDI Error: Patch header too short\n");*/ + return -EINVAL; + } count -= hdr_size; /* @@ -514,74 +514,73 @@ midi_synth_load_patch(int dev, int format, const char *addr, * been transferred already. */ - copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs); - - if (count < sysex.len) - { - printk("MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len); - sysex.len = count; - } - left = sysex.len; - src_offs = 0; + if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs)) + return -EFAULT; + + if (count < sysex.len) + { +/* printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/ + sysex.len = count; + } + left = sysex.len; + src_offs = 0; sysex_sleep_flag.opts = WK_NONE; for (i = 0; i < left && !signal_pending(current); i++) - { - unsigned char data; - - get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i])); - - eox_seen = (i > 0 && data & 0x80); /* End of sysex */ - - if (eox_seen && data != 0xf7) - data = 0xf7; - - if (i == 0) - { - if (data != 0xf0) - { - printk("Error: Sysex start missing\n"); - return -EINVAL; - } - } - while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) && - !signal_pending(current)) - - { - unsigned long tlimit; - - if (1) - current->timeout = tlimit = jiffies + (1); - else - tlimit = (unsigned long) -1; - sysex_sleep_flag.opts = WK_SLEEP; - interruptible_sleep_on(&sysex_sleeper); - if (!(sysex_sleep_flag.opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - sysex_sleep_flag.opts |= WK_TIMEOUT; - } - sysex_sleep_flag.opts &= ~WK_SLEEP; - }; /* Wait for timeout */ - - if (!first_byte && data & 0x80) - return 0; - first_byte = 0; - } + { + unsigned char data; + + get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i])); + + eox_seen = (i > 0 && data & 0x80); /* End of sysex */ + + if (eox_seen && data != 0xf7) + data = 0xf7; + + if (i == 0) + { + if (data != 0xf0) + { + printk(KERN_WARNING "midi_synth: Sysex start missing\n"); + return -EINVAL; + } + } + while (!midi_devs[orig_dev]->outputc(orig_dev, (unsigned char) (data & 0xff)) && + !signal_pending(current)) + + { + unsigned long tlimit; + + if (1) + current->timeout = tlimit = jiffies + (1); + else + tlimit = (unsigned long) -1; + sysex_sleep_flag.opts = WK_SLEEP; + interruptible_sleep_on(&sysex_sleeper); + if (!(sysex_sleep_flag.opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + sysex_sleep_flag.opts |= WK_TIMEOUT; + } + sysex_sleep_flag.opts &= ~WK_SLEEP; + }; /* Wait for timeout */ + + if (!first_byte && data & 0x80) + return 0; + first_byte = 0; + } if (!eox_seen) midi_outc(orig_dev, 0xf7); return 0; } - -void -midi_synth_panning(int dev, int channel, int pressure) + +void midi_synth_panning(int dev, int channel, int pressure) { } - -void -midi_synth_aftertouch(int dev, int channel, int pressure) + +void midi_synth_aftertouch(int dev, int channel, int pressure) { int orig_dev = synth_devs[dev]->midi_dev; int msg, chn; diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index f504a5d9dd81..cf00dc9e46f0 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -1844,14 +1844,5 @@ void cleanup_module(void) SOUND_LOCK_END; } -#else - -void -export_mpu401_syms(void) -{ - register_symtab(&mpu401_syms); -} - - #endif #endif diff --git a/drivers/sound/soundvers.h b/drivers/sound/soundvers.h index b3a8356c2167..e9084d2f46a9 100644 --- a/drivers/sound/soundvers.h +++ b/drivers/sound/soundvers.h @@ -1,2 +1,2 @@ -#define SOUND_VERSION_STRING "3.8s-971110" +#define SOUND_VERSION_STRING "3.8s2++-971130" #define SOUND_INTERNAL_VERSION 0x030804 diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c index 22e4fe8f998a..63bfd9211cc4 100644 --- a/drivers/sound/uart401.c +++ b/drivers/sound/uart401.c @@ -452,8 +452,7 @@ unload_uart401(struct address_info *hw_config) if (!devc->share_irq) snd_release_irq(devc->irq); - /* Free device too !! - AC FIXME: CHECK THIS IS RIGHT */ - if (devc) + if (!devc) vfree(devc); sound_unload_mididev(hw_config->slots[4]); } diff --git a/fs/Config.in b/fs/Config.in index 2ab01ba3da4f..f9670ee5607a 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -23,7 +23,7 @@ dep_tristate 'VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS bool '/proc filesystem support' CONFIG_PROC_FS if [ "$CONFIG_INET" = "y" ]; then tristate 'NFS filesystem support' CONFIG_NFS_FS - if [ "$CONFIG_NFS_FS" = "y" ]; then + if [ "$CONFIG_NFS_FS" = "y" -a "$CONFIG_IP_PNP" = "y" ]; then bool ' Root file system on NFS' CONFIG_ROOT_NFS if [ "$CONFIG_ROOT_NFS" = "y" ]; then bool ' BOOTP support' CONFIG_RNFS_BOOTP diff --git a/fs/buffer.c b/fs/buffer.c index 86e22482b02b..941580f3ecbb 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -582,21 +582,23 @@ struct buffer_head *efind_buffer(kdev_t dev, int block, int size) */ struct buffer_head * get_hash_table(kdev_t dev, int block, int size) { + struct buffer_head * bh; for (;;) { - struct buffer_head * bh; - - bh=find_buffer(dev,block,size); + bh = find_buffer(dev,block,size); if (!bh) - return bh; + break; bh->b_count++; bh->b_lru_time = jiffies; - wait_on_buffer(bh); + if (!test_bit(BH_Lock, &bh->b_state)) + break; + __wait_on_buffer(bh); if (bh->b_dev == dev && bh->b_blocknr == block && bh->b_size == size) - return bh; + break; bh->b_count--; } + return bh; } unsigned int get_hardblocksize(kdev_t dev) @@ -836,6 +838,8 @@ repeat: continue; if (buffer_dirty(bh) || buffer_protected(bh)) continue; + if (MAJOR(bh->b_dev) == LOOP_MAJOR) + continue; /* * We've found an unused, locked, non-dirty buffer of * the correct size. Claim it so no one else can, diff --git a/fs/coda/file.c b/fs/coda/file.c index e97c854161c8..225ca881a923 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c @@ -219,7 +219,7 @@ int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind) { struct super_block *sbptr; - sbptr = coda_find_super(dev); + sbptr = get_super(dev); if ( !sbptr ) { printk("coda_inode_grab: coda_find_super returns NULL.\n"); @@ -238,14 +238,3 @@ int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind) return 0; } -struct super_block *coda_find_super(kdev_t device) -{ - struct super_block *super; - - for (super = super_blocks + 0; super < super_blocks + NR_SUPER ; - super++) { - if (super->s_dev == device) - return super; - } - return NULL; -} diff --git a/fs/coda/namecache.c b/fs/coda/namecache.c index 9584e91a898b..08f1ee9e7e8e 100644 --- a/fs/coda/namecache.c +++ b/fs/coda/namecache.c @@ -1,17 +1,12 @@ -/* - * Mach Operating System - * Copyright (c) 1990 Carnegie-Mellon University - * Copyright (c) 1989 Carnegie-Mellon University - * All rights reserved. The CMU software License Agreement specifies - * the terms and conditions for use and redistribution. - */ - /* - * This code was written for the Coda file system at Carnegie Mellon University. - * Contributers include David Steere, James Kistler, and M. Satyanarayanan. + * Cache operations for Coda. + * Original version: (C) 1996 Peter Braam + * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon encourages users of this code to contribute improvements + * to the Coda project. Contact Peter Braam . */ - /* * This module contains the routines to implement the CFS name cache. The * purpose of this cache is to reduce the cost of translating pathnames @@ -47,7 +42,6 @@ #include #include - int cfsnc_use; static struct cfscache * cfsnc_find(struct cnode *dcp, const char * name, int namelen, int hash); diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index d75dd057bf1a..cd591d3e9b62 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -31,10 +31,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index a3b4cccfd988..04523a38346f 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -1,4 +1,13 @@ +/* + * Sysctl operations for Coda filesystem + * Original version: (C) 1996 P. Braam and M. Callahan + * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon encourages users to contribute improvements to + * the Coda project. Contact Peter Braam (coda@cs.cmu.edu). + */ /* sysctl entries for Coda! */ + #include #include #include diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 0c2380de3618..ce405d8d5c13 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -24,24 +24,25 @@ * Global file hash table */ #define FILE_NRHASH 32 -#define FILE_HASH(dhash) ((dhash) & FILE_NRHASH) +#define FILE_HASH_BITS 5 static struct nlm_file * nlm_files[FILE_NRHASH]; static struct semaphore nlm_file_sema = MUTEX; +static unsigned int file_hash(dev_t dev, ino_t ino) +{ + unsigned long tmp = (unsigned long) ino | (unsigned long) dev; + tmp = tmp + (tmp >> FILE_HASH_BITS) + (tmp >> FILE_HASH_BITS*2); + return tmp & (FILE_NRHASH - 1); +} + /* * Lookup file info. If it doesn't exist, create a file info struct * and open a (VFS) file for the given inode. * - * The NFS filehandle must have been validated prior to this call, - * as we assume that the dentry pointer is valid. - * * FIXME: * Note that we open the file O_RDONLY even when creating write locks. * This is not quite right, but for now, we assume the client performs * the proper R/W checking. - * - * The dentry in the FH may not be validated .. can we call this with - * the full svc_fh? */ u32 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, @@ -49,40 +50,38 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, { struct nlm_file *file; struct knfs_fh *fh = (struct knfs_fh *) f; - struct dentry *dentry = fh->fh_dcookie; - unsigned int hash = FILE_HASH(dentry->d_name.hash); + unsigned int hash = file_hash(fh->fh_dev, fh->fh_ino); u32 nfserr; - dprintk("lockd: nlm_file_lookup(%s/%s)\n", - dentry->d_parent->d_name.name, dentry->d_name.name); + dprintk("lockd: nlm_file_lookup(%s/%ld)\n", + kdevname(fh->fh_dev), fh->fh_ino); /* Lock file table */ down(&nlm_file_sema); for (file = nlm_files[hash]; file; file = file->f_next) { - if (file->f_handle.fh_dcookie == dentry - && !memcmp(&file->f_handle, fh, sizeof(*fh))) + if (file->f_handle.fh_dcookie == fh->fh_dcookie && + !memcmp(&file->f_handle, fh, sizeof(*fh))) goto found; } - dprintk("lockd: creating file for %s/%s\n", - dentry->d_parent->d_name.name, dentry->d_name.name); - if (!(file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL))) { - up(&nlm_file_sema); - return nlm_lck_denied_nolocks; - } + dprintk("lockd: creating file for %s/%ld\n", + kdevname(fh->fh_dev), fh->fh_ino); + nfserr = nlm_lck_denied_nolocks; + file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL); + if (!file) + goto out_unlock; memset(file, 0, sizeof(*file)); file->f_handle = *fh; file->f_sema = MUTEX; /* Open the file. Note that this must not sleep for too long, else - * we would lock up lockd:-) So no NFS re-exports, folks. */ + * we would lock up lockd:-) So no NFS re-exports, folks. + */ if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) { dprintk("lockd: open failed (nfserr %ld)\n", ntohl(nfserr)); - kfree(file); - up(&nlm_file_sema); - return nlm_lck_denied; + goto out_free; } file->f_next = nlm_files[hash]; @@ -91,9 +90,17 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, found: dprintk("lockd: found file %p (count %d)\n", file, file->f_count); *result = file; - up(&nlm_file_sema); file->f_count++; - return 0; + nfserr = 0; + +out_unlock: + up(&nlm_file_sema); + return nfserr; + +out_free: + kfree(file); + nfserr = nlm_lck_denied; + goto out_unlock; } /* @@ -102,11 +109,12 @@ found: static inline void nlm_delete_file(struct nlm_file *file) { - struct dentry *dentry = file->f_file.f_dentry; + struct inode *inode = file->f_file.f_dentry->d_inode; struct nlm_file **fp, *f; - dprintk("lockd: closing file %p\n", dentry); - fp = nlm_files + FILE_HASH(dentry->d_name.hash); + dprintk("lockd: closing file %s/%ld\n", + kdevname(inode->i_dev), inode->i_ino); + fp = nlm_files + file_hash(inode->i_dev, inode->i_ino); while ((f = *fp) != NULL) { if (f == file) { *fp = file->f_next; diff --git a/fs/namei.c b/fs/namei.c index 5dbb6e074f74..2e7c4bff6835 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -737,10 +737,9 @@ static inline int do_mkdir(const char * pathname, int mode) goto exit; dir = lock_parent(dentry); - error = PTR_ERR(dir); if (IS_ERR(dir)) - goto exit; + goto exit_dput; error = -EEXIST; if (dentry->d_inode) @@ -765,6 +764,7 @@ static inline int do_mkdir(const char * pathname, int mode) exit_lock: unlock_dir(dir); +exit_dput: dput(dentry); exit: return error; @@ -798,10 +798,9 @@ static inline int do_rmdir(const char * name) goto exit; dir = lock_parent(dentry); - error = PTR_ERR(dir); if (IS_ERR(dir)) - goto exit; + goto exit_dput; error = -ENOENT; if (!dentry->d_inode) @@ -838,6 +837,7 @@ static inline int do_rmdir(const char * name) exit_lock: unlock_dir(dir); +exit_dput: dput(dentry); exit: return error; @@ -871,10 +871,9 @@ static inline int do_unlink(const char * name) goto exit; dir = lock_parent(dentry); - error = PTR_ERR(dir); if (IS_ERR(dir)) - goto exit; + goto exit_dput; error = -ENOENT; if (!dentry->d_inode) @@ -911,6 +910,7 @@ static inline int do_unlink(const char * name) exit_lock: unlock_dir(dir); +exit_dput: dput(dentry); exit: return error; @@ -945,10 +945,9 @@ static inline int do_symlink(const char * oldname, const char * newname) goto exit; dir = lock_parent(dentry); - error = PTR_ERR(dir); if (IS_ERR(dir)) - goto exit; + goto exit_dput; error = -EEXIST; if (dentry->d_inode) @@ -972,6 +971,7 @@ static inline int do_symlink(const char * oldname, const char * newname) exit_lock: unlock_dir(dir); +exit_dput: dput(dentry); exit: return error; @@ -1016,10 +1016,9 @@ static inline int do_link(const char * oldname, const char * newname) goto exit_old; dir = lock_parent(new_dentry); - error = PTR_ERR(dir); if (IS_ERR(dir)) - goto exit; + goto exit_new; error = -ENOENT; inode = old_dentry->d_inode; @@ -1059,6 +1058,7 @@ static inline int do_link(const char * oldname, const char * newname) exit_lock: unlock_dir(dir); +exit_new: dput(new_dentry); exit_old: dput(old_dentry); diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 48b92f58b554..c74c73243c83 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -498,6 +498,12 @@ static int nfs_lookup(struct inode *dir, struct dentry * dentry) error = -EACCES; inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); if (inode) { +#ifdef NFS_PARANOIA +if (inode->i_count > 1) +printk("nfs_lookup: %s/%s ino=%ld in use, count=%d, nlink=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, +inode->i_ino, inode->i_count, inode->i_nlink); +#endif no_entry: dentry->d_op = &nfs_dentry_operations; d_add(dentry, inode); @@ -512,14 +518,20 @@ out: /* * Code common to create, mkdir, and mknod. */ -static int nfs_instantiate(struct inode *dir, struct dentry *dentry, - struct nfs_fattr *fattr, struct nfs_fh *fhandle) +static int nfs_instantiate(struct dentry *dentry, struct nfs_fattr *fattr, + struct nfs_fh *fhandle) { struct inode *inode; int error = -EACCES; - inode = nfs_fhget(dir->i_sb, fhandle, fattr); + inode = nfs_fhget(dentry->d_sb, fhandle, fattr); if (inode) { +#ifdef NFS_PARANOIA +if (inode->i_count > 1) +printk("nfs_instantiate: %s/%s ino=%ld in use, count=%d, nlink=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, +inode->i_ino, inode->i_count, inode->i_nlink); +#endif d_instantiate(dentry, inode); nfs_renew_times(dentry); error = 0; @@ -563,14 +575,9 @@ static int nfs_create(struct inode *dir, struct dentry * dentry, int mode) error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name, &sattr, &fhandle, &fattr); if (!error) - error = nfs_instantiate(dir, dentry, &fattr, &fhandle); - else { -#ifdef NFS_PARANOIA -printk("nfs_create: %s/%s failed, error=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, error); -#endif + error = nfs_instantiate(dentry, &fattr, &fhandle); + else d_drop(dentry); - } out: return error; } @@ -606,14 +613,9 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name, &sattr, &fhandle, &fattr); if (!error) - error = nfs_instantiate(dir, dentry, &fattr, &fhandle); - else { -#ifdef NFS_PARANOIA -printk("nfs_mknod: %s/%s failed, error=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, error); -#endif + error = nfs_instantiate(dentry, &fattr, &fhandle); + else d_drop(dentry); - } return error; } @@ -645,13 +647,22 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) nfs_invalidate_dircache(dir); error = nfs_proc_mkdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name, &sattr, &fhandle, &fattr); - if (!error) - error = nfs_instantiate(dir, dentry, &fattr, &fhandle); - else { -#ifdef NFS_PARANOIA -printk("nfs_mkdir: %s/%s failed, error=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, error); -#endif + if (!error) { + /* + * Some AIX servers reportedly fail to fill out the fattr. + * Check for a bad mode value and complain, then drop the + * dentry to force a new lookup. + */ + if (!S_ISDIR(fattr.mode)) { + static int complain = 0; + if (!complain++) + printk("NFS: buggy server! fattr mode=%x\n", + fattr.mode); + goto drop; + } + error = nfs_instantiate(dentry, &fattr, &fhandle); + } else { + drop: d_drop(dentry); } return error; @@ -662,12 +673,12 @@ dentry->d_parent->d_name.name, dentry->d_name.name, error); * use count prior to the operation, and return EBUSY if it has * multiple users. * - * Update inode->i_nlink immediately after a successful operation. - * (See comments for nfs_unlink.) + * We update inode->i_nlink and free the inode prior to the operation + * to avoid possible races if the server reuses the inode. */ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) { - int error; + int error, rehash = 0; dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n", dir->i_dev, dir->i_ino, dentry->d_name.name); @@ -688,13 +699,31 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) if (dentry->d_count > 1) goto out; } - /* Drop the dentry to force a new lookup */ - d_drop(dentry); - error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dir), dentry->d_name.name); +#ifdef NFS_PARANOIA +if (dentry->d_inode->i_count > 1) +printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, +dentry->d_inode->i_count, dentry->d_inode->i_nlink); +#endif + /* + * Unhash the dentry while we remove the directory. + */ + if (!list_empty(&dentry->d_hash)) { + d_drop(dentry); + rehash = 1; + } + /* + * Update i_nlink and free the inode before unlinking. + */ + if (dentry->d_inode->i_nlink) + dentry->d_inode->i_nlink --; + d_delete(dentry); + nfs_invalidate_dircache(dir); + error = nfs_proc_rmdir(NFS_SERVER(dir), + NFS_FH(dir), dentry->d_name.name); if (!error) { - if (dentry->d_inode->i_nlink) - dentry->d_inode->i_nlink --; - nfs_invalidate_dircache(dir); + if (rehash) + d_add(dentry, NULL); nfs_renew_times(dentry); } out: @@ -867,6 +896,12 @@ dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); #endif goto out; } +#ifdef NFS_PARANOIA +if (inode && inode->i_count > 1) +printk("nfs_safe_remove: %s/%s inode busy?? i_count=%d, i_nlink=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, +inode->i_count, inode->i_nlink); +#endif /* * Unhash the dentry while we remove the file ... */ @@ -874,29 +909,22 @@ dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); d_drop(dentry); rehash = 1; } - error = nfs_proc_remove(NFS_SERVER(dir), - NFS_FH(dir), dentry->d_name.name); /* - * ... then restore the hashed state. This ensures that the - * dentry can't become busy after having its file deleted. + * Update i_nlink and free the inode before unlinking. */ - if (rehash) { - d_add(dentry, inode); - } -#ifdef NFS_PARANOIA -if (dentry->d_count > 1) -printk("nfs_safe_remove: %s/%s busy after delete?? d_count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count); -if (inode && inode->i_count > 1) -printk("nfs_safe_remove: %s/%s inode busy?? i_count=%d\n", -dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_count); -#endif - if (!error) { - nfs_invalidate_dircache(dir); - if (inode && inode->i_nlink) + if (inode) { + if (inode->i_nlink) inode->i_nlink --; d_delete(dentry); } + nfs_invalidate_dircache(dir); + error = nfs_proc_remove(NFS_SERVER(dir), + NFS_FH(dir), dentry->d_name.name); + /* + * Rehash the negative dentry if the operation succeeded. + */ + if (!error && rehash) + d_add(dentry, NULL); out: return error; } diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 6e161d62b4f1..ccca2cc7c2a7 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -16,6 +16,9 @@ #define NFSDDBG_FACILITY NFSDDBG_LOCKD +/* + * Note: we hold the dentry use count while the file is open. + */ static u32 nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp) { @@ -27,6 +30,8 @@ nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp) fh.fh_dverified = 0; nfserr = nfsd_open(rqstp, &fh, S_IFREG, 0, filp); + if (!nfserr) + dget(filp->f_dentry); fh_put(&fh); return nfserr; } @@ -35,6 +40,7 @@ static void nlm_fclose(struct file *filp) { nfsd_close(filp); + dput(filp->f_dentry); } struct nlmsvc_binding nfsd_nlm_ops = { diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 0bfa50827380..81b9a3f790fd 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -240,24 +240,24 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access, err; access = wflag? MAY_WRITE : MAY_READ; - if ((err = fh_verify(rqstp, fhp, type, access)) != 0) + err = fh_verify(rqstp, fhp, type, access); + if (err) goto out; dentry = fhp->fh_dentry; inode = dentry->d_inode; /* Disallow access to files with the append-only bit set or - * with mandatory locking enabled */ + * with mandatory locking enabled + */ err = nfserr_perm; if (IS_APPEND(inode) || IS_ISMNDLK(inode)) goto out; if (!inode->i_op || !inode->i_op->default_file_ops) goto out; - if (wflag && (err = get_write_access(inode)) != 0) { - err = nfserrno(-err); - goto out; - } + if (wflag && (err = get_write_access(inode)) != 0) + goto out_nfserr; memset(filp, 0, sizeof(*filp)); filp->f_op = inode->i_op->default_file_ops; @@ -267,7 +267,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, filp->f_dentry = dentry; err = 0; - if (filp->f_op->open) { + if (filp->f_op && filp->f_op->open) { err = filp->f_op->open(inode, filp); if (err) { if (wflag) @@ -277,9 +277,11 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, * is really on callers stack frame. -DaveM */ filp->f_count--; - err = nfserrno(-err); } } +out_nfserr: + if (err) + err = nfserrno(-err); out: return err; } @@ -633,14 +635,16 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size) struct iattr newattrs; int err; - if ((err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE|MAY_TRUNC)) != 0) - return err; + err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC); + if (err) + goto out; dentry = fhp->fh_dentry; inode = dentry->d_inode; - if ((err = get_write_access(inode)) != 0) - goto out; + err = get_write_access(inode); + if (err) + goto out_nfserr; /* Things look sane, lock and do it. */ fh_lock(fhp); @@ -654,8 +658,11 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size) } put_write_access(inode); fh_unlock(fhp); +out_nfserr: + if (err) + err = nfserrno(-err); out: - return (err ? nfserrno(-err) : 0); + return err; } /* @@ -671,7 +678,8 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) mm_segment_t oldfs; int err; - if ((err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ)) != 0) + err = fh_verify(rqstp, fhp, S_IFLNK, MAY_READ); + if (err) goto out; dentry = fhp->fh_dentry; @@ -715,7 +723,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, if (!flen || !plen) goto out; - if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE)) != 0) + err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE); + if (err) goto out; dentry = fhp->fh_dentry; @@ -762,17 +771,20 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, struct inode *dirp, *dest; int err; - if ((err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE) != 0) || - (err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP)) != 0) - return err; + err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE); + if (err) + goto out; + err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP); + if (err) + goto out; ddir = ffhp->fh_dentry; dirp = ddir->d_inode; - dnew = lookup_dentry(fname, dget(ddir), 1); + dnew = lookup_dentry(fname, dget(ddir), 0); err = PTR_ERR(dnew); if (IS_ERR(dnew)) - return nfserrno(-err); + goto out_nfserr; err = -EEXIST; if (dnew->d_inode) @@ -805,7 +817,11 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, } dput_and_out: dput(dnew); - return (err ? nfserrno(-err) : 0); +out_nfserr: + if (err) + err = nfserrno(-err); +out: + return err; } /* More "hidden treasure" from the generic VFS. -DaveM */ @@ -836,9 +852,12 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, struct inode *fdir, *tdir; int err; - if ((err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE) != 0) - || (err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE)) != 0) - return err; + err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE); + if (err) + goto out; + err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE); + if (err) + goto out; fdentry = ffhp->fh_dentry; fdir = fdentry->d_inode; @@ -846,18 +865,19 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, tdentry = tfhp->fh_dentry; tdir = tdentry->d_inode; + /* N.B. We shouldn't need this ... dentry layer handles it */ if (!flen || (fname[0] == '.' && (flen == 1 || (flen == 2 && fname[1] == '.'))) || !tlen || (tname[0] == '.' && (tlen == 1 || (tlen == 2 && tname[1] == '.')))) return nfserr_perm; - odentry = lookup_dentry(fname, dget(fdentry), 1); + odentry = lookup_dentry(fname, dget(fdentry), 0); err = PTR_ERR(odentry); if (IS_ERR(odentry)) goto out_no_unlock; - ndentry = lookup_dentry(tname, dget(tdentry), 1); + ndentry = lookup_dentry(tname, dget(tdentry), 0); err = PTR_ERR(ndentry); if (IS_ERR(ndentry)) goto out_dput_old; @@ -883,7 +903,10 @@ out_unlock: out_dput_old: dput(odentry); out_no_unlock: - return (err ? nfserrno(-err) : 0); + if (err) + err = nfserrno(-err); +out: + return err; } /* @@ -898,10 +921,13 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, struct inode *dirp; int err; + /* N.B. We shouldn't need this test ... handled by dentry layer */ + err = nfserr_acces; if (!flen || isdotent(fname, flen)) - return nfserr_acces; - if ((err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE)) != 0) - return err; + goto out; + err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE); + if (err) + goto out; dentry = fhp->fh_dentry; dirp = dentry->d_inode; @@ -909,7 +935,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, rdentry = lookup_dentry(fname, dget(dentry), 0); err = PTR_ERR(rdentry); if (IS_ERR(rdentry)) - goto out; + goto out_nfserr; fh_lock(fhp); if (type == S_IFDIR) { @@ -926,8 +952,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, dput(rdentry); if (!err && EX_ISSYNC(fhp->fh_export)) write_inode_now(dirp); + +out_nfserr: + if (err) + err = nfserrno(-err); out: - return (err ? nfserrno(-err) : 0); + return err; } /* diff --git a/fs/pipe.c b/fs/pipe.c index 8c476c34a9a8..078d6be3b3e8 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -12,8 +12,8 @@ #include #include #include +#include -#include #include /* diff --git a/fs/proc/array.c b/fs/proc/array.c index 4e97724c2485..f6f73ad1c06e 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -685,6 +685,7 @@ static inline char * task_sig(struct task_struct *p, char *buffer) buffer += sprintf(buffer, "SigPnd:\t"); buffer = render_sigset_t(&p->signal, buffer); + *buffer++ = '\n'; buffer += sprintf(buffer, "SigBlk:\t"); buffer = render_sigset_t(&p->blocked, buffer); *buffer++ = '\n'; @@ -692,6 +693,7 @@ static inline char * task_sig(struct task_struct *p, char *buffer) collect_sigign_sigcatch(p, &ign, &catch); buffer += sprintf(buffer, "SigIgn:\t"); buffer = render_sigset_t(&ign, buffer); + *buffer++ = '\n'; buffer += sprintf(buffer, "SigCat:\t"); buffer = render_sigset_t(&catch, buffer); *buffer++ = '\n'; diff --git a/fs/select.c b/fs/select.c index d804d58b3105..4c88f0437842 100644 --- a/fs/select.c +++ b/fs/select.c @@ -24,10 +24,10 @@ #include #include #include +#include #include #include -#include #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) @@ -39,9 +39,10 @@ * understand what I'm doing here, then you understand how the linux * sleep/wakeup mechanism works. * - * Two very simple procedures, poll_wait() and free_wait() make all the work. - * poll_wait() is an inline-function defined in , as all select/poll - * functions have to call it to add an entry to the poll table. + * Two very simple procedures, poll_wait() and free_wait() make all the + * work. poll_wait() is an inline-function defined in , + * as all select/poll functions have to call it to add an entry to the + * poll table. */ /* @@ -61,26 +62,6 @@ static void free_wait(poll_table * p) } } -/* - * For the kernel fd_set we use a fixed set-size for allocation purposes. - * This set-size doesn't necessarily bear any relation to the size the user - * uses, but should preferably obviously be larger than any possible user - * size (NR_OPEN bits). - * - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we - * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits, - * to be divided by 6. And we'd better make sure we round to a full - * long-word (in fact, we'll round to 64 bytes). - */ -#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64) -#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8) -typedef unsigned long kernel_fd_set[KFDS_NR/(8*sizeof(unsigned long))]; - -typedef struct { - kernel_fd_set in, out, ex; - kernel_fd_set res_in, res_out, res_ex; -} fd_set_buffer; - #define __IN(in) (in) #define __OUT(in) (in + sizeof(kernel_fd_set)/sizeof(unsigned long)) #define __EX(in) (in + 2*sizeof(kernel_fd_set)/sizeof(unsigned long)) @@ -141,11 +122,28 @@ get_max: #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR) #define POLLEX_SET (POLLPRI) -static int do_select(int n, fd_set_buffer *fds, poll_table *wait) +int do_select(int n, fd_set_buffer *fds, unsigned long timeout) { + poll_table wait_table, *wait; int retval; int i; + lock_kernel(); + + wait = NULL; + current->timeout = timeout; + if (timeout) { + struct poll_table_entry *entry = (struct poll_table_entry *) + __get_free_page(GFP_KERNEL); + if (!entry) { + retval = -ENOMEM; + goto out_nowait; + } + wait_table.nr = 0; + wait_table.entry = entry; + wait = &wait_table; + } + retval = max_select_fd(n, fds); if (retval < 0) goto out; @@ -154,33 +152,36 @@ static int do_select(int n, fd_set_buffer *fds, poll_table *wait) for (;;) { struct file ** fd = current->files->fd; current->state = TASK_INTERRUPTIBLE; - for (i = 0 ; i < n ; i++,fd++) { + for (i = 0 ; i < n ; i++, fd++) { unsigned long bit = BIT(i); unsigned long *in = MEM(i,fds->in); + unsigned long mask; + struct file *file; - if (bit & BITS(in)) { - struct file * file = *fd; - unsigned int mask = POLLNVAL; - if (file) { - mask = DEFAULT_POLLMASK; - if (file->f_op && file->f_op->poll) - mask = file->f_op->poll(file, wait); - } - if ((mask & POLLIN_SET) && ISSET(bit, __IN(in))) { - SET(bit, __RES_IN(in)); - retval++; - wait = NULL; - } - if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(in))) { - SET(bit, __RES_OUT(in)); - retval++; - wait = NULL; - } - if ((mask & POLLEX_SET) && ISSET(bit, __EX(in))) { - SET(bit, __RES_EX(in)); - retval++; - wait = NULL; - } + if (!(bit & BITS(in))) + continue; + + file = *fd; + mask = POLLNVAL; + if (file) { + mask = DEFAULT_POLLMASK; + if (file->f_op && file->f_op->poll) + mask = file->f_op->poll(file, wait); + } + if ((mask & POLLIN_SET) && ISSET(bit, __IN(in))) { + SET(bit, __RES_IN(in)); + retval++; + wait = NULL; + } + if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(in))) { + SET(bit, __RES_OUT(in)); + retval++; + wait = NULL; + } + if ((mask & POLLEX_SET) && ISSET(bit, __EX(in))) { + SET(bit, __RES_EX(in)); + retval++; + wait = NULL; } } wait = NULL; @@ -189,82 +190,18 @@ static int do_select(int n, fd_set_buffer *fds, poll_table *wait) schedule(); } current->state = TASK_RUNNING; -out: - return retval; -} - -/* - * We do a VERIFY_WRITE here even though we are only reading this time: - * we'll write to it eventually.. - * - * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned. - */ -static int __get_fd_set(unsigned long nr, unsigned long * fs_pointer, unsigned long * fdset) -{ - /* round up nr to nearest "unsigned long" */ - nr = (nr + 8*sizeof(unsigned long)-1) / (8*sizeof(unsigned long)); - if (fs_pointer) { - int error = verify_area(VERIFY_WRITE,fs_pointer, - nr*sizeof(unsigned long)); - if (!error) { - while (nr) { - __get_user(*fdset, fs_pointer); - nr--; - fs_pointer++; - fdset++; - } - } - return error; - } - while (nr) { - *fdset = 0; - nr--; - fdset++; - } - return 0; -} -static void __set_fd_set(long nr, unsigned long * fs_pointer, unsigned long * fdset) -{ - if (!fs_pointer) - return; - while (nr >= 0) { - __put_user(*fdset, fs_pointer); - nr -= 8 * sizeof(unsigned long); - fdset++; - fs_pointer++; +out: + if (timeout) { + free_wait(&wait_table); + free_page((unsigned long) wait_table.entry); } +out_nowait: + current->timeout = 0; + unlock_kernel(); + return retval; } -/* We can do long accesses here, kernel fdsets are always long-aligned */ -static inline void __zero_fd_set(long nr, unsigned long * fdset) -{ - while (nr >= 0) { - *fdset = 0; - nr -= 8 * sizeof(unsigned long); - fdset++; - } -} - -/* - * Note a few subtleties: we use "long" for the dummy, not int, and we do a - * subtract by 1 on the nr of file descriptors. The former is better for - * machines with long > int, and the latter allows us to test the bit count - * against "zero or positive", which can mostly be just a sign bit test.. - * - * Unfortunately this scheme falls apart on big endian machines where - * sizeof(long) > sizeof(int) (ie. V9 Sparc). -DaveM - */ - -#define get_fd_set(nr,fsp,fdp) \ -__get_fd_set(nr, (unsigned long *) (fsp), (unsigned long *) (fdp)) - -#define set_fd_set(nr,fsp,fdp) \ -__set_fd_set((nr)-1, (unsigned long *) (fsp), (unsigned long *) (fdp)) - -#define zero_fd_set(nr,fdp) \ -__zero_fd_set((nr)-1, (unsigned long *) (fdp)) - /* * We can actually return ERESTARTSYS instead of EINTR, but I'd * like to be certain this leads to no problems. So I return @@ -273,64 +210,50 @@ __zero_fd_set((nr)-1, (unsigned long *) (fdp)) * Update: ERESTARTSYS breaks at least the xview clock binary, so * I'm trying ERESTARTNOHAND which restart only when you want to. */ -asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) +asmlinkage int +sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { - int error; fd_set_buffer *fds; unsigned long timeout; - poll_table wait_table, *wait; + int ret; - lock_kernel(); timeout = ~0UL; if (tvp) { - error = -EFAULT; - if (!access_ok(VERIFY_WRITE, tvp, sizeof(*tvp))) - goto out_nowait; - error = __get_user(timeout, &tvp->tv_usec); - if (error) - goto out_nowait; - timeout = ROUND_UP(timeout,(1000000/HZ)); - { - unsigned long tmp; - error = __get_user(tmp, &tvp->tv_sec); - if (error) - goto out_nowait; - timeout += tmp * (unsigned long) HZ; - } + time_t sec, usec; + + if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) + || (ret = __get_user(sec, &tvp->tv_sec)) + || (ret = __get_user(usec, &tvp->tv_usec))) + goto out_nofds; + + timeout = ROUND_UP(usec, 1000000/HZ); + timeout += sec * (unsigned long) HZ; if (timeout) timeout += jiffies + 1; } - error = -ENOMEM; - wait = NULL; - current->timeout = timeout; - if (timeout) { - struct poll_table_entry *entry; - entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL); - if (!entry) - goto out_nowait; - wait_table.nr = 0; - wait_table.entry = entry; - wait = &wait_table; - } + ret = -ENOMEM; fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL); if (!fds) goto out_nofds; - error = -EINVAL; + ret = -EINVAL; if (n < 0) goto out; if (n > KFDS_NR) n = KFDS_NR; - if ((error = get_fd_set(n, inp, &fds->in)) || - (error = get_fd_set(n, outp, &fds->out)) || - (error = get_fd_set(n, exp, &fds->ex))) goto out; - zero_fd_set(n, &fds->res_in); - zero_fd_set(n, &fds->res_out); - zero_fd_set(n, &fds->res_ex); - error = do_select(n, fds, wait); + if ((ret = get_fd_set(n, inp, fds->in)) || + (ret = get_fd_set(n, outp, fds->out)) || + (ret = get_fd_set(n, exp, fds->ex))) + goto out; + zero_fd_set(n, fds->res_in); + zero_fd_set(n, fds->res_out); + zero_fd_set(n, fds->res_ex); + + ret = do_select(n, fds, timeout); + if (tvp && !(current->personality & STICKY_TIMEOUTS)) { unsigned long timeout = current->timeout - jiffies - 1; - unsigned long sec = 0, usec = 0; + time_t sec = 0, usec = 0; if ((long) timeout > 0) { sec = timeout / HZ; usec = timeout % HZ; @@ -340,27 +263,24 @@ asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct put_user(usec, &tvp->tv_usec); } current->timeout = 0; - if (error < 0) + + if (ret < 0) goto out; - if (!error) { - error = -ERESTARTNOHAND; + if (!ret) { + ret = -ERESTARTNOHAND; if (signal_pending(current)) goto out; - error = 0; + ret = 0; } - set_fd_set(n, inp, &fds->res_in); - set_fd_set(n, outp, &fds->res_out); - set_fd_set(n, exp, &fds->res_ex); + + set_fd_set(n, inp, fds->res_in); + set_fd_set(n, outp, fds->res_out); + set_fd_set(n, exp, fds->res_ex); + out: free_page((unsigned long) fds); out_nofds: - if (wait) { - free_wait(&wait_table); - free_page((unsigned long) wait->entry); - } -out_nowait: - unlock_kernel(); - return error; + return ret; } static int do_poll(unsigned int nfds, struct pollfd *fds, poll_table *wait) diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index b3586b58fd4b..bb8828efacb1 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -10,6 +10,11 @@ * sysv/namei.c * Copyright (C) 1993 Bruno Haible */ +/* + 7 Dec 1997 - updated to use dentries by Krzysztof G. Baranowski + + */ + #include #include @@ -100,31 +105,29 @@ static struct buffer_head * sysv_find_entry(struct inode * dir, return NULL; } -int sysv_lookup(struct inode * dir,const char * name, int len, - struct inode ** result) +int sysv_lookup(struct inode * dir, struct dentry * dentry) { int ino; + struct inode * inode = NULL; struct sysv_dir_entry * de; struct buffer_head * bh; - *result = NULL; if (!dir) return -ENOENT; if (!S_ISDIR(dir->i_mode)) { - iput(dir); return -ENOENT; } - if (!(bh = sysv_find_entry(dir,name,len,&de))) { - iput(dir); + if (!(bh = sysv_find_entry(dir, dentry->d_name.name, + dentry->d_name.len, &de))) { return -ENOENT; } ino = de->inode; brelse(bh); - if (!(*result = iget(dir->i_sb,ino))) { - iput(dir); + inode = iget(dir->i_sb,ino); + + if (!inode) return -EACCES; - } - iput(dir); + d_add(dentry, inode); return 0; } @@ -201,42 +204,37 @@ static int sysv_add_entry(struct inode * dir, return 0; } -int sysv_create(struct inode * dir,const char * name, int len, int mode, - struct inode ** result) +int sysv_create(struct inode * dir, struct dentry * dentry, int mode) { int error; struct inode * inode; struct buffer_head * bh; struct sysv_dir_entry * de; - *result = NULL; if (!dir) return -ENOENT; inode = sysv_new_inode(dir); - if (!inode) { - iput(dir); + if (!inode) return -ENOSPC; - } inode->i_op = &sysv_file_inode_operations; inode->i_mode = mode; mark_inode_dirty(inode); - error = sysv_add_entry(dir,name,len, &bh ,&de); + error = sysv_add_entry(dir,dentry->d_name.name, + dentry->d_name.len, &bh, &de); if (error) { inode->i_nlink--; mark_inode_dirty(inode); iput(inode); - iput(dir); return error; } de->inode = inode->i_ino; mark_buffer_dirty(bh, 1); brelse(bh); - iput(dir); - *result = inode; + d_instantiate(dentry, inode); return 0; } -int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rdev) +int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev) { int error; struct inode * inode; @@ -245,17 +243,15 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde if (!dir) return -ENOENT; - bh = sysv_find_entry(dir,name,len,&de); + bh = sysv_find_entry(dir,dentry->d_name.name, + dentry->d_name.len,&de); if (bh) { brelse(bh); - iput(dir); return -EEXIST; } inode = sysv_new_inode(dir); - if (!inode) { - iput(dir); + if (!inode) return -ENOSPC; - } inode->i_uid = current->fsuid; inode->i_mode = mode; inode->i_op = NULL; @@ -277,53 +273,45 @@ int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rde if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); mark_inode_dirty(inode); - error = sysv_add_entry(dir, name, len, &bh, &de); + error = sysv_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de); if (error) { inode->i_nlink--; mark_inode_dirty(inode); iput(inode); - iput(dir); return error; } de->inode = inode->i_ino; mark_buffer_dirty(bh, 1); brelse(bh); - iput(dir); - iput(inode); + d_instantiate(dentry, inode); return 0; } -int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) +int sysv_mkdir(struct inode * dir, struct dentry *dentry, int mode) { int error; struct inode * inode; struct buffer_head * bh, *dir_block; struct sysv_dir_entry * de; - if (!dir) { - iput(dir); + if (!dir) return -EINVAL; - } - bh = sysv_find_entry(dir,name,len,&de); + bh = sysv_find_entry(dir, dentry->d_name.name, + dentry->d_name.len, &de); if (bh) { brelse(bh); - iput(dir); return -EEXIST; } if (dir->i_nlink >= dir->i_sb->sv_link_max) { - iput(dir); return -EMLINK; } inode = sysv_new_inode(dir); - if (!inode) { - iput(dir); + if (!inode) return -ENOSPC; - } inode->i_op = &sysv_dir_inode_operations; inode->i_size = 2 * SYSV_DIRSIZE; dir_block = sysv_file_bread(inode,0,1); if (!dir_block) { - iput(dir); inode->i_nlink--; mark_inode_dirty(inode); iput(inode); @@ -342,9 +330,9 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) if (dir->i_mode & S_ISGID) inode->i_mode |= S_ISGID; mark_inode_dirty(inode); - error = sysv_add_entry(dir, name, len, &bh, &de); - if (error) { - iput(dir); + error = sysv_add_entry(dir, dentry->d_name.name, + dentry->d_name.len, &bh, &de); + if (error) { inode->i_nlink=0; iput(inode); return error; @@ -353,10 +341,9 @@ int sysv_mkdir(struct inode * dir, const char * name, int len, int mode) mark_buffer_dirty(bh, 1); dir->i_nlink++; mark_inode_dirty(dir); - iput(dir); - iput(inode); brelse(bh); - return 0; + d_instantiate(dentry, inode); + return 0; } /* @@ -419,7 +406,7 @@ bad_dir: return 1; } -int sysv_rmdir(struct inode * dir, const char * name, int len) +int sysv_rmdir(struct inode * dir, struct dentry * dentry) { int retval; struct inode * inode; @@ -427,13 +414,14 @@ int sysv_rmdir(struct inode * dir, const char * name, int len) struct sysv_dir_entry * de; inode = NULL; - bh = sysv_find_entry(dir,name,len,&de); + bh = sysv_find_entry(dir, dentry->d_name.name, + dentry->d_name.len, &de); retval = -ENOENT; if (!bh) goto end_rmdir; retval = -EPERM; - if (!(inode = iget(dir->i_sb, de->inode))) - goto end_rmdir; + inode = dentry->d_inode; + if ((dir->i_mode & S_ISVTX) && !fsuser() && current->fsuid != inode->i_uid && current->fsuid != dir->i_uid) @@ -467,15 +455,14 @@ int sysv_rmdir(struct inode * dir, const char * name, int len) dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(dir); + d_delete(dentry); retval = 0; end_rmdir: - iput(dir); - iput(inode); brelse(bh); return retval; } -int sysv_unlink(struct inode * dir, const char * name, int len) +int sysv_unlink(struct inode * dir, struct dentry * dentry) { int retval; struct inode * inode; @@ -485,16 +472,16 @@ int sysv_unlink(struct inode * dir, const char * name, int len) repeat: retval = -ENOENT; inode = NULL; - bh = sysv_find_entry(dir,name,len,&de); + bh = sysv_find_entry(dir, dentry->d_name.name, + dentry->d_name.len, &de); if (!bh) goto end_unlink; - if (!(inode = iget(dir->i_sb, de->inode))) - goto end_unlink; + inode = dentry->d_inode; + retval = -EPERM; if (S_ISDIR(inode->i_mode)) goto end_unlink; if (de->inode != inode->i_ino) { - iput(inode); brelse(bh); current->counter = 0; schedule(); @@ -510,7 +497,7 @@ repeat: } if (!inode->i_nlink) { printk("Deleting nonexistent file (%s:%lu), %d\n", - kdevname(inode->i_dev), + kdevname(inode->i_dev), inode->i_ino, inode->i_nlink); inode->i_nlink=1; } @@ -521,15 +508,15 @@ repeat: inode->i_nlink--; inode->i_ctime = dir->i_ctime; mark_inode_dirty(inode); + d_delete(dentry); retval = 0; end_unlink: brelse(bh); - iput(inode); - iput(dir); return retval; } -int sysv_symlink(struct inode * dir, const char * name, int len, const char * symname) +int sysv_symlink(struct inode * dir, struct dentry * dentry, + const char * symname) { struct sysv_dir_entry * de; struct inode * inode; @@ -540,15 +527,13 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy char c; struct buffer_head * bh; - if (!(inode = sysv_new_inode(dir))) { - iput(dir); + if (!(inode = sysv_new_inode(dir))) return -ENOSPC; - } + inode->i_mode = S_IFLNK | 0777; inode->i_op = &sysv_symlink_inode_operations; name_block = sysv_file_bread(inode,0,1); if (!name_block) { - iput(dir); inode->i_nlink--; mark_inode_dirty(inode); iput(inode); @@ -564,94 +549,81 @@ int sysv_symlink(struct inode * dir, const char * name, int len, const char * sy brelse(name_block); inode->i_size = i; mark_inode_dirty(inode); - bh = sysv_find_entry(dir,name,len,&de); + bh = sysv_find_entry(dir, dentry->d_name.name, + dentry->d_name.len, &de); if (bh) { inode->i_nlink--; mark_inode_dirty(inode); iput(inode); brelse(bh); - iput(dir); return -EEXIST; } - i = sysv_add_entry(dir, name, len, &bh, &de); + i = sysv_add_entry(dir, dentry->d_name.name, + dentry->d_name.len, &bh, &de); if (i) { inode->i_nlink--; mark_inode_dirty(inode); iput(inode); - iput(dir); return i; } de->inode = inode->i_ino; mark_buffer_dirty(bh, 1); brelse(bh); - iput(dir); - iput(inode); + d_instantiate(dentry, inode); return 0; } -int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len) +int sysv_link(struct inode * oldinode, struct inode * dir, + struct dentry * dentry) { int error; struct sysv_dir_entry * de; struct buffer_head * bh; if (S_ISDIR(oldinode->i_mode)) { - iput(oldinode); - iput(dir); return -EPERM; } if (oldinode->i_nlink >= oldinode->i_sb->sv_link_max) { - iput(oldinode); - iput(dir); return -EMLINK; } - bh = sysv_find_entry(dir,name,len,&de); + bh = sysv_find_entry(dir, dentry->d_name.name, + dentry->d_name.len, &de); if (bh) { brelse(bh); - iput(dir); - iput(oldinode); return -EEXIST; } - error = sysv_add_entry(dir, name, len, &bh, &de); + error = sysv_add_entry(dir, dentry->d_name.name, + dentry->d_name.len, &bh, &de); if (error) { - iput(dir); - iput(oldinode); return error; } de->inode = oldinode->i_ino; mark_buffer_dirty(bh, 1); brelse(bh); - iput(dir); oldinode->i_nlink++; oldinode->i_ctime = CURRENT_TIME; mark_inode_dirty(oldinode); - iput(oldinode); + d_instantiate(dentry, oldinode); return 0; } /* return 1 if `new' is a subdir of `old' on the same device */ -static int subdir(struct inode * new_inode, struct inode * old_inode) +static int subdir(struct dentry * new_dentry, struct dentry * old_dentry) { - int ino; - int result; - - new_inode->i_count++; - result = 0; - for (;;) { - if (new_inode == old_inode) { - result = 1; - break; - } - if (new_inode->i_dev != old_inode->i_dev) - break; - ino = new_inode->i_ino; - if (sysv_lookup(new_inode,"..",2,&new_inode)) - break; - if (new_inode->i_ino == ino) /* root dir reached ? */ - break; - } - iput(new_inode); - return result; + int result = 0; + + for (;;) { + if (new_dentry != old_dentry) { + struct dentry * parent = new_dentry->d_parent; + if (parent == new_dentry) + break; + new_dentry = parent; + continue; + } + result = 1; + break; + } + return result; } #define PARENT_INO(buffer) \ @@ -716,7 +688,7 @@ start_up: if (!S_ISDIR(old_inode->i_mode)) goto end_rename; retval = -EINVAL; - if (subdir(new_dir, old_inode)) + if (subdir(new_dentry, old_dentry)) goto end_rename; retval = -ENOTEMPTY; if (!empty_dir(new_inode)) @@ -735,7 +707,7 @@ start_up: if (new_inode && !S_ISDIR(new_inode->i_mode)) goto end_rename; retval = -EINVAL; - if (subdir(new_dir, old_inode)) + if (subdir(new_dentry, old_dentry)) goto end_rename; retval = -EIO; dir_bh = sysv_file_bread(old_inode,0,0); diff --git a/fs/ufs/ufs_namei.c b/fs/ufs/ufs_namei.c index 0c48b5cfc94e..6cf8c6c39e84 100644 --- a/fs/ufs/ufs_namei.c +++ b/fs/ufs/ufs_namei.c @@ -7,7 +7,7 @@ * Rutgers, The State University of New Jersey * * Clean swab support by Francois-Rene Rideau 19970406 - * Ported to 2.1.62 by Francois-Rene Rideau 19971109 + * Ported to 2.1.62 by Francois-Rene Rideau 19971109 * */ diff --git a/fs/ufs/ufs_super.c b/fs/ufs/ufs_super.c index 0d02f96f3484..a3c32cccecb0 100644 --- a/fs/ufs/ufs_super.c +++ b/fs/ufs/ufs_super.c @@ -21,12 +21,14 @@ * Francois-Rene Rideau */ +#include #include #include #include #include #include +#include #include #include "ufs_swab.h" @@ -54,8 +56,7 @@ static struct file_system_type ufs_fs_type = { NULL }; -int -init_ufs_fs(void) +__initfunc(int init_ufs_fs(void)) { return(register_filesystem(&ufs_fs_type)); } diff --git a/fs/ufs/ufs_symlink.c b/fs/ufs/ufs_symlink.c index f53bcf298bd4..76d5fbf113c1 100644 --- a/fs/ufs/ufs_symlink.c +++ b/fs/ufs/ufs_symlink.c @@ -6,7 +6,7 @@ * Laboratory for Computer Science Research Computing Facility * Rutgers, The State University of New Jersey * - * Ported to 2.1.62 by Francois-Rene Rideau 19971109 + * Ported to 2.1.62 by Francois-Rene Rideau 19971109 * */ diff --git a/include/asm-alpha/byteorder.h b/include/asm-alpha/byteorder.h index b48a144c5dd3..b8afddcd5add 100644 --- a/include/asm-alpha/byteorder.h +++ b/include/asm-alpha/byteorder.h @@ -47,6 +47,6 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 x) #define __BYTEORDER_HAS_U64__ -#include +#include #endif /* _ALPHA_BYTEORDER_H */ diff --git a/include/asm-alpha/posix_types.h b/include/asm-alpha/posix_types.h index 92855e8bc661..b98290660f32 100644 --- a/include/asm-alpha/posix_types.h +++ b/include/asm-alpha/posix_types.h @@ -20,6 +20,7 @@ typedef unsigned long __kernel_size_t; typedef long __kernel_ssize_t; typedef long __kernel_ptrdiff_t; typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; diff --git a/include/asm-alpha/signal.h b/include/asm-alpha/signal.h index 6c5a821bac7f..06c3bb7e36ca 100644 --- a/include/asm-alpha/signal.h +++ b/include/asm-alpha/signal.h @@ -6,6 +6,7 @@ /* Avoid too many header ordering problems. */ struct siginfo; +#ifdef __KERNEL__ /* Digital Unix defines 64 signals. Most things should be clean enough to redefine this at will, if care is taken to make libc match. */ @@ -19,6 +20,15 @@ typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; +#else +/* Here we must cater to libcs that poke about in kernel headers. */ + +#define NSIG 32 +typedef unsigned long sigset_t; + +#endif /* __KERNEL__ */ + + /* * Linux/AXP has different signal numbers that Linux/i386: I'm trying * to make it OSF/1 binary compatible, at least for normal binaries. @@ -114,6 +124,7 @@ typedef void (*__sighandler_t)(int); #define SIG_IGN ((__sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ +#ifdef __KERNEL__ struct osf_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; @@ -130,6 +141,15 @@ struct k_sigaction { struct sigaction sa; void (*ka_restorer)(void); }; +#else +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + __sighandler_t sa_handler; + sigset_t sa_mask; + int sa_flags; +}; +#endif /* __KERNEL__ */ typedef struct sigaltstack { void *ss_sp; diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h index ff34ee0f23bd..dbfcb66cdea0 100644 --- a/include/asm-alpha/socket.h +++ b/include/asm-alpha/socket.h @@ -37,10 +37,15 @@ #define SO_PASSCRED 17 #define SO_PEERCRED 18 +#define SO_BINDTODEVICE 25 + +#define SO_BINDTODEVICE 25 /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 19 #define SO_SECURITY_ENCRYPTION_TRANSPORT 20 #define SO_SECURITY_ENCRYPTION_NETWORK 21 +#define SO_BINDTODEVICE 22 + #endif /* _ASM_SOCKET_H */ diff --git a/include/asm-i386/byteorder.h b/include/asm-i386/byteorder.h index c41f1a14fc1c..51d66f8fc233 100644 --- a/include/asm-i386/byteorder.h +++ b/include/asm-i386/byteorder.h @@ -42,6 +42,6 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 x) #endif /* __GNUC__ */ -#include +#include #endif /* _I386_BYTEORDER_H */ diff --git a/include/asm-i386/posix_types.h b/include/asm-i386/posix_types.h index 4da54d2becc0..aed0fd6fde30 100644 --- a/include/asm-i386/posix_types.h +++ b/include/asm-i386/posix_types.h @@ -20,6 +20,7 @@ typedef unsigned int __kernel_size_t; typedef int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h index 6550c41c75f1..5da9ff0ed200 100644 --- a/include/asm-i386/signal.h +++ b/include/asm-i386/signal.h @@ -6,6 +6,7 @@ /* Avoid too many header ordering problems. */ struct siginfo; +#ifdef __KERNEL__ /* Most things should be clean enough to redefine this at will, if care is taken to make libc match. */ @@ -19,6 +20,14 @@ typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; +#else +/* Here we must cater to libcs that poke about in kernel headers. */ + +#define NSIG 32 +typedef unsigned long sigset_t; + +#endif /* __KERNEL__ */ + #define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 @@ -113,6 +122,7 @@ typedef void (*__sighandler_t)(int); #define SIG_IGN ((__sighandler_t)1) /* ignore signal */ #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ +#ifdef __KERNEL__ struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; @@ -130,6 +140,16 @@ struct sigaction { struct k_sigaction { struct sigaction sa; }; +#else +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + __sighandler_t sa_handler; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; +#endif /* __KERNEL__ */ typedef struct sigaltstack { void *ss_sp; @@ -179,6 +199,6 @@ extern __inline__ int sigfindinword(unsigned long word) return word; } -#endif +#endif /* __KERNEL__ */ #endif diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index 479c6c522df5..145118a71614 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h @@ -21,8 +21,8 @@ #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1) #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3)) #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3)) -#define load_TR(n) __asm__("ltr %%ax": /* no output */ :"a" (_TSS(n))) -#define load_ldt(n) __asm__("lldt %%ax": /* no output */ :"a" (_LDT(n))) +#define load_TR(n) __asm__ __volatile__("ltr %%ax": /* no output */ :"a" (_TSS(n))) +#define load_ldt(n) __asm__ __volatile__("lldt %%ax": /* no output */ :"a" (_LDT(n))) #define store_TR(n) \ __asm__("str %%ax\n\t" \ "subl %2,%%eax\n\t" \ @@ -33,11 +33,9 @@ __asm__("str %%ax\n\t" \ /* This special macro can be used to load a debugging register */ #define loaddebug(tsk,register) \ - __asm__("movl %0,%%edx\n\t" \ - "movl %%edx,%%db" #register "\n\t" \ + __asm__("movl %0,%%db" #register \ : /* no output */ \ - :"m" (tsk->debugreg[register]) \ - :"dx"); + :"r" (tsk->debugreg[register])) /* diff --git a/include/asm-m68k/byteorder.h b/include/asm-m68k/byteorder.h index d7475a376b00..31271886b12f 100644 --- a/include/asm-m68k/byteorder.h +++ b/include/asm-m68k/byteorder.h @@ -19,6 +19,6 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 val) # define __SWAB_64_THRU_32__ #endif -#include +#include #endif /* _M68K_BYTEORDER_H */ diff --git a/include/asm-m68k/posix_types.h b/include/asm-m68k/posix_types.h index 5350959715f2..33c423980303 100644 --- a/include/asm-m68k/posix_types.h +++ b/include/asm-m68k/posix_types.h @@ -20,6 +20,7 @@ typedef unsigned int __kernel_size_t; typedef int __kernel_ssize_t; typedef int __kernel_ptrdiff_t; typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h index 30d465e7fdc8..c3a3fd7dc510 100644 --- a/include/asm-mips/byteorder.h +++ b/include/asm-mips/byteorder.h @@ -4,9 +4,9 @@ #include #if defined (__MIPSEB__) -# include +# include #elif defined (__MIPSEL__) -# include +# include #else # error What's that? MIPS, but neither MIPSEB, nor MIPSEL??? #endif diff --git a/include/asm-mips/posix_types.h b/include/asm-mips/posix_types.h index deffcf2000bd..64256a0b2639 100644 --- a/include/asm-mips/posix_types.h +++ b/include/asm-mips/posix_types.h @@ -33,6 +33,7 @@ typedef __SIZE_TYPE__ __kernel_size_t; typedef __SSIZE_TYPE__ __kernel_ssize_t; typedef int __kernel_ptrdiff_t; typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; typedef long __kernel_daddr_t; typedef char * __kernel_caddr_t; diff --git a/include/asm-ppc/byteorder.h b/include/asm-ppc/byteorder.h index 7c4e86f27dbc..a16503851714 100644 --- a/include/asm-ppc/byteorder.h +++ b/include/asm-ppc/byteorder.h @@ -61,15 +61,15 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 value) #endif /* 0 */ /* The same, but returns converted value from the location pointer by addr. */ -#define __arch_swab16p(addr) ld_le16(addr) -#define __arch_swab32p(addr) ld_le32(addr) +#define __arch__swab16p(addr) ld_le16(addr) +#define __arch__swab32p(addr) ld_le32(addr) /* The same, but do the conversion in situ, ie. put the value back to addr. */ -#define __arch_swab16s(addr) st_le16(addr,*addr) -#define __arch_swab32s(addr) st_le32(addr,*addr) +#define __arch__swab16s(addr) st_le16(addr,*addr) +#define __arch__swab32s(addr) st_le32(addr,*addr) #endif /* __GNUC__ */ -#include +#include #endif /* _PPC_BYTEORDER_H */ diff --git a/include/asm-ppc/posix_types.h b/include/asm-ppc/posix_types.h index 72b24318ebe2..e659279ff8fb 100644 --- a/include/asm-ppc/posix_types.h +++ b/include/asm-ppc/posix_types.h @@ -19,6 +19,7 @@ typedef unsigned long __kernel_size_t; typedef long __kernel_ssize_t; typedef long __kernel_ptrdiff_t; typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; diff --git a/include/asm-sparc/byteorder.h b/include/asm-sparc/byteorder.h index 72c01480c2e4..7cbbfd26d292 100644 --- a/include/asm-sparc/byteorder.h +++ b/include/asm-sparc/byteorder.h @@ -8,6 +8,6 @@ # define __SWAB_64_THRU_32__ #endif -#include +#include #endif /* _SPARC_BYTEORDER_H */ diff --git a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h index 1df2f62d2308..a3fb5bb586bc 100644 --- a/include/asm-sparc/posix_types.h +++ b/include/asm-sparc/posix_types.h @@ -17,6 +17,7 @@ typedef long unsigned int __kernel_size_t; typedef int __kernel_ssize_t; typedef long int __kernel_ptrdiff_t; typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; typedef int __kernel_pid_t; typedef unsigned short __kernel_ipc_pid_t; diff --git a/include/asm-sparc64/byteorder.h b/include/asm-sparc64/byteorder.h index f663e3e8de7d..43964767b5fe 100644 --- a/include/asm-sparc64/byteorder.h +++ b/include/asm-sparc64/byteorder.h @@ -41,6 +41,6 @@ static __inline__ __u64 ___arch__swab64p(__u64 *addr) { #define __BYTEORDER_HAS_U64__ -#include +#include #endif /* _SPARC64_BYTEORDER_H */ diff --git a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h index 6bf51c96aa26..0c0e25a77d3e 100644 --- a/include/asm-sparc64/posix_types.h +++ b/include/asm-sparc64/posix_types.h @@ -26,6 +26,9 @@ typedef int __kernel_daddr_t; typedef long __kernel_off_t; typedef char * __kernel_caddr_t; +/* Note this piece of asymmetry from the v9 ABI. */ +typedef int __kernel_suseconds_t; + #ifdef __GNUC__ typedef long long __kernel_loff_t; #endif diff --git a/include/linux/byteorder_big_endian.h b/include/linux/byteorder/big_endian.h similarity index 96% rename from include/linux/byteorder_big_endian.h rename to include/linux/byteorder/big_endian.h index db014c1b9336..da6c40e1c151 100644 --- a/include/linux/byteorder_big_endian.h +++ b/include/linux/byteorder/big_endian.h @@ -8,6 +8,8 @@ #define __BIG_ENDIAN_BITFIELD #endif +#include + #define __constant_htonl(x) ((__u32)(x)) #define __constant_ntohl(x) ((__u32)(x)) #define __constant_htons(x) ((__u16)(x)) @@ -49,6 +51,6 @@ #define __cpu_to_be16s(x) do {} while (0) #define __be16_to_cpus(x) do {} while (0) -#include +#include #endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */ diff --git a/include/linux/byteorder_generic.h b/include/linux/byteorder/generic.h similarity index 54% rename from include/linux/byteorder_generic.h rename to include/linux/byteorder/generic.h index 716560df78b9..633f7b90ae61 100644 --- a/include/linux/byteorder_generic.h +++ b/include/linux/byteorder/generic.h @@ -3,7 +3,7 @@ /* * linux/byteorder_generic.h - * Generic Byteswap support + * Generic Byte-reordering support * * Francois-Rene Rideau 19970707 * gathered all the good ideas from all asm-foo/byteorder.h into one file, @@ -16,6 +16,10 @@ * Upgraded it to 2.1.57 * to please Linus T., replaced huge #ifdef's between little/big endian * by nestedly #include'd files. + * Francois-Rene Rideau 19971205 + * Made it to 2.1.71; now a facelift: + * Put files under include/linux/byteorder/ + * Split swab from generic support. * * TODO: * = Regular kernel maintainers could also replace all these manual @@ -23,21 +27,12 @@ * after some grep or the sources... * = Linus might want to rename all these macros and files to fit his taste, * to fit his personal naming scheme. - * = it seems that many drivers would also appreciate + * = it seems that a few drivers would also appreciate * nybble swapping support... * = every architecture could add their byteswap macro in asm/byteorder.h * see how some architectures already do (i386, alpha, ppc, etc) */ -/* - * This file is included by both and - * . People porting from machines with - * bizarre bytedisorder (like the VAX?) will have to write a different one. - * Actually, this file mostly does byteswapping, and could be named - * or rather than - * - */ - /* * The following macros are to be defined by : * @@ -73,152 +68,17 @@ * cpu_to_[bl]eXXs(__uXX x) * [bl]eXX_to_cpus(__uXX x) * - * Byteswapping, independently from cpu endianness - * swabXX[ps]?(foo) - * - * * See asm-foo/byteorder.h for examples of how to provide * architecture-optimized versions * */ -#include - -/* - * Generic byte swapping routines. We fall back on - * these if we don't have any optimized code, and - * when we have constants that we want the compiler - * to byte swap for us.. - */ -#define ___swab16(x) \ - ((__u16)( \ - (((__u16)(x) & 0x00ffU) << 8) | \ - (((__u16)(x) & 0xff00U) >> 8) )) -#define ___swab32(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ - (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ - (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ - (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) -#define ___swab64(x) \ - ((__u64)( \ - (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ - (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ - (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ - (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ - (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ - (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ - (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ - (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) +#if defined(__KERNEL__) /* - * These do constant folding - this allows the - * compiler to do any constants at compile - * time. Any architecture inline asm optimizations - * would be pessimizations. + * inside the kernel, we can use nicknames; + * outside of it, we must avoid POSIX namespace pollution... */ -#define __swab16(x) \ - (__builtin_constant_p((__u16)(x)) ? \ - ___swab16((x)) : __fswab16((x))) -#define __swab32(x) \ - (__builtin_constant_p((__u32)(x)) ? \ - ___swab32((x)) : __fswab32((x))) -#define __swab64(x) \ - (__builtin_constant_p((__u64)(x)) ? \ - ___swab64((x)) : __fswab64((x))) - - -/* - * provide defaults when no architecture-specific optimization is detected - */ -#ifndef __arch__swab16 -# define __arch__swab16(x) ___swab16(x) -#endif -#ifndef __arch__swab32 -# define __arch__swab32(x) ___swab32(x) -#endif -#ifndef __arch__swab64 -# define __arch__swab64(x) ___swab64(x) -#endif - -#ifndef __arch__swab16p -# define __arch__swab16p(x) __swab16(*(x)) -#endif -#ifndef __arch__swab32p -# define __arch__swab32p(x) __swab32(*(x)) -#endif -#ifndef __arch__swab64p -# define __arch__swab64p(x) __swab64(*(x)) -#endif - -#ifndef __arch__swab16s -# define __arch__swab16s(x) *(x) = __swab16p((x)) -#endif -#ifndef __arch__swab32s -# define __arch__swab32s(x) *(x) = __swab32p((x)) -#endif -#ifndef __arch__swab64s -# define __arch__swab64s(x) *(x) = __swab64p((x)) -#endif - - -extern __inline__ __const__ __u16 __fswab16(__u16 x) -{ - return __arch__swab16(x); -} -extern __inline__ __u16 __swab16p(__u16 *x) -{ - return __arch__swab16p(x); -} -extern __inline__ void __swab16s(__u16 *addr) -{ - __arch__swab16s(addr); -} - -extern __inline__ __const__ __u32 __fswab32(__u32 x) -{ - return __arch__swab32(x); -} -extern __inline__ __u32 __swab32p(__u32 *x) -{ - return __arch__swab32p(x); -} -extern __inline__ void __swab32s(__u32 *addr) -{ - __arch__swab32s(addr); -} - -#ifdef __BYTEORDER_HAS_U64__ -extern __inline__ __const__ __u64 __fswab64(__u64 x) -{ -# ifdef __SWAB_64_THRU_32__ - __u32 h = x >> 32; - __u32 l = x & ((1ULL<<32)-1); - return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); -# else - return __arch__swab64(x); -# endif -} -extern __inline__ __u64 __swab64p(__u64 *x) -{ - return __arch__swab64p(x); -} -extern __inline__ void __swab64s(__u64 *addr) -{ - __arch__swab64s(addr); -} -#endif /* __BYTEORDER_HAS_U64__ */ - -#if defined(__KERNEL__) || defined(__REQUIRE_CPU_TO_XX) -#define swab16 __swab16 -#define swab32 __swab32 -#define swab64 __swab64 -#define swab16p __swab16p -#define swab32p __swab32p -#define swab64p __swab64p -#define swab16s __swab16s -#define swab32s __swab32s -#define swab64s __swab64s #define cpu_to_le64 __cpu_to_le64 #define le64_to_cpu __le64_to_cpu #define cpu_to_le32 __cpu_to_le32 @@ -257,6 +117,7 @@ extern __inline__ void __swab64s(__u64 *addr) #define be16_to_cpus __be16_to_cpus #endif + /* * Handle ntohl and suches. These have various compatibility * issues - like we want to give the prototype even though we @@ -285,6 +146,9 @@ extern unsigned short int ntohs(unsigned short int); extern unsigned long int htonl(unsigned long int); extern unsigned short int htons(unsigned short int); + +#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) + #define ___htonl(x) __cpu_to_be32(x) #define ___htons(x) __cpu_to_be16(x) #define ___ntohl(x) __be32_to_cpu(x) @@ -295,4 +159,7 @@ extern unsigned short int htons(unsigned short int); #define ntohl(x) ((unsigned long)___ntohl(x)) #define ntohs(x) ___ntohs(x) -#endif /* _LINUX_BYTEORDER_H */ +#endif /* OPTIMIZE */ + + +#endif /* _LINUX_BYTEORDER_GENERIC_H */ diff --git a/include/linux/byteorder_little_endian.h b/include/linux/byteorder/little_endian.h similarity index 96% rename from include/linux/byteorder_little_endian.h rename to include/linux/byteorder/little_endian.h index 4482138b9800..ede7054c1571 100644 --- a/include/linux/byteorder_little_endian.h +++ b/include/linux/byteorder/little_endian.h @@ -8,6 +8,8 @@ #define __LITTLE_ENDIAN_BITFIELD #endif +#include + #define __constant_htonl(x) ___swab32((x)) #define __constant_ntohl(x) ___swab32((x)) #define __constant_htons(x) ___swab16((x)) @@ -49,6 +51,6 @@ #define __cpu_to_be16s(x) __swab16s((x)) #define __be16_to_cpus(x) __swab16s((x)) -#include +#include #endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */ diff --git a/include/linux/byteorder/swab.h b/include/linux/byteorder/swab.h new file mode 100644 index 000000000000..8110bfb85bee --- /dev/null +++ b/include/linux/byteorder/swab.h @@ -0,0 +1,155 @@ +#ifndef _LINUX_BYTEORDER_SWAB_H +#define _LINUX_BYTEORDER_SWAB_H + +/* + * linux/byteorder/swab.h + * Byteswapping, independently from cpu endianness + * swabXX[ps]?(foo) + * + * Francois-Rene Rideau 19971205 + * separated swab functions from cpu_to_XX, + * to clean up support for bizarre-endian architectures. + * + * See asm-i386/byteorder.h and suches for examples of how to provide + * architecture-dependent optimized versions + * + */ + +#define ___swab16(x) \ + ((__u16)( \ + (((__u16)(x) & 0x00ffU) << 8) | \ + (((__u16)(x) & 0xff00U) >> 8) )) +#define ___swab32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) +#define ___swab64(x) \ + ((__u64)( \ + (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) + +/* + * provide defaults when no architecture-specific optimization is detected + */ +#ifndef __arch__swab16 +# define __arch__swab16(x) ___swab16(x) +#endif +#ifndef __arch__swab32 +# define __arch__swab32(x) ___swab32(x) +#endif +#ifndef __arch__swab64 +# define __arch__swab64(x) ___swab64(x) +#endif + +#ifndef __arch__swab16p +# define __arch__swab16p(x) __swab16(*(x)) +#endif +#ifndef __arch__swab32p +# define __arch__swab32p(x) __swab32(*(x)) +#endif +#ifndef __arch__swab64p +# define __arch__swab64p(x) __swab64(*(x)) +#endif + +#ifndef __arch__swab16s +# define __arch__swab16s(x) do { *(x) = __swab16p((x)); } while (0) +#endif +#ifndef __arch__swab32s +# define __arch__swab32s(x) do { *(x) = __swab32p((x)); } while (0) +#endif +#ifndef __arch__swab64s +# define __arch__swab64s(x) do { *(x) = __swab64p((x)); } while (0) +#endif + + +/* + * Allow constant folding + */ +#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) +# define __swab16(x) \ +(__builtin_constant_p((__u16)(x)) ? \ + ___swab16((x)) : \ + __fswab16((x))) +# define __swab32(x) \ +(__builtin_constant_p((__u32)(x)) ? \ + ___swab32((x)) : \ + __fswab32((x))) +# define __swab64(x) \ +(__builtin_constant_p((__u64)(x)) ? \ + ___swab64((x)) : \ + __fswab64((x))) +#else +# define __swab16(x) __fswab16(x) +# define __swab32(x) __fswab32(x) +# define __swab64(x) __fswab64(x) +#endif /* OPTIMIZE */ + + +extern __inline__ __const__ __u16 __fswab16(__u16 x) +{ + return __arch__swab16(x); +} +extern __inline__ __u16 __swab16p(__u16 *x) +{ + return __arch__swab16p(x); +} +extern __inline__ void __swab16s(__u16 *addr) +{ + __arch__swab16s(addr); +} + +extern __inline__ __const__ __u32 __fswab32(__u32 x) +{ + return __arch__swab32(x); +} +extern __inline__ __u32 __swab32p(__u32 *x) +{ + return __arch__swab32p(x); +} +extern __inline__ void __swab32s(__u32 *addr) +{ + __arch__swab32s(addr); +} + +#ifdef __BYTEORDER_HAS_U64__ +extern __inline__ __const__ __u64 __fswab64(__u64 x) +{ +# ifdef __SWAB_64_THRU_32__ + __u32 h = x >> 32; + __u32 l = x & ((1ULL<<32)-1); + return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); +# else + return __arch__swab64(x); +# endif +} +extern __inline__ __u64 __swab64p(__u64 *x) +{ + return __arch__swab64p(x); +} +extern __inline__ void __swab64s(__u64 *addr) +{ + __arch__swab64s(addr); +} +#endif /* __BYTEORDER_HAS_U64__ */ + +#if defined(__KERNEL__) +#define swab16 __swab16 +#define swab32 __swab32 +#define swab64 __swab64 +#define swab16p __swab16p +#define swab32p __swab32p +#define swab64p __swab64p +#define swab16s __swab16s +#define swab32s __swab32s +#define swab64s __swab64s +#endif + +#endif /* _LINUX_BYTEORDER_SWAB_H */ diff --git a/include/linux/byteorder/swabb.h b/include/linux/byteorder/swabb.h new file mode 100644 index 000000000000..1f34bc13d8b3 --- /dev/null +++ b/include/linux/byteorder/swabb.h @@ -0,0 +1,122 @@ +#ifndef _LINUX_BYTEORDER_SWABB_H +#define _LINUX_BYTEORDER_SWABB_H + +/* + * linux/byteorder/swabb.h + * SWAp Bytes Bizarrely + * swaHHXX[ps]?(foo) + * + * Support for obNUXIous vax-endian and other bizarre architectures... + * + */ + +/* + * Meaning of the names I chose (vaxlinux people feel free to correct them): + * swahw32 swap 16-bit half-words in a 32-bit word + * swahb32 swap 8-bit halves of each 16-bit half-word in a 32-bit word + * + * No 64-bit support yet. I don't know VAX conventions for long longs. + * I guarantee it will be a mess when it's there, though :-> + * It will be even worse if there are conflicting 64-bit conventions for vaxen + * + * Note that if communicating with vax machines becomes useful in some kernel + * FS driver, we'd have to move that mess into byteorder/swab.h, and + * create cpu_to_ve32 and suches. Ouch. + */ + + +#define ___swahw32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x0000ffffUL) << 16) | \ + (((__u32)(x) & (__u32)0xffff0000UL) >> 16) )) +#define ___swahb32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x00ff00ffUL) << 16) | \ + (((__u32)(x) & (__u32)0xff00ff00UL) >> 16) )) + +/* + * provide defaults when no architecture-specific optimization is detected + */ +#ifndef __arch__swahw32 +# define __arch__swahw32(x) ___swahw32(x) +#endif +#ifndef __arch__swahb32 +# define __arch__swahb32(x) ___swahb32(x) +#endif + +#ifndef __arch__swahw32p +# define __arch__swahw32p(x) __swahw32(*(x)) +#endif +#ifndef __arch__swahb32p +# define __arch__swahb32p(x) __swahb32(*(x)) +#endif + +#ifndef __arch__swahw32s +# define __arch__swahw32s(x) do { *(x) = __swahw32p((x)); } while (0) +#endif +#ifndef __arch__swahb32s +# define __arch__swahb32s(x) do { *(x) = __swahb32p((x)); } while (0) +#endif + + +/* + * Allow constant folding + */ +#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) +# define __swahw32(x) \ +(__builtin_constant_p((__u32)(x)) ? \ + ___swahw32((x)) : \ + __fswahw32((x))) +# define __swahb32(x) \ +(__builtin_constant_p((__u32)(x)) ? \ + ___swahb32((x)) : \ + __fswahb32((x))) +#else +# define __swahw32(x) __fswahw32(x) +# define __swahb32(x) __fswahb32(x) +#endif /* OPTIMIZE */ + + +extern __inline__ __const__ __u32 __fswahw32(__u32 x) +{ + return __arch__swahw32(x); +} +extern __inline__ __u32 __swahw32p(__u32 *x) +{ + return __arch__swahw32p(x); +} +extern __inline__ void __swahw32s(__u32 *addr) +{ + __arch__swahw32s(addr); +} + + +extern __inline__ __const__ __u32 __fswahb32(__u32 x) +{ + return __arch__swahb32(x); +} +extern __inline__ __u32 __swahb32p(__u32 *x) +{ + return __arch__swahb32p(x); +} +extern __inline__ void __swahb32s(__u32 *addr) +{ + __arch__swahb32s(addr); +} + +#ifdef __BYTEORDER_HAS_U64__ +/* + * Not supported yet + */ +#endif /* __BYTEORDER_HAS_U64__ */ + +#if defined(__KERNEL__) +#define swahw32 __swahw32 +#define swahb32 __swahb32 +#define swahw32p __swahw32p +#define swahb32p __swahb32p +#define swahw32s __swahw32s +#define swahb32s __swahb32s +#endif + +#endif /* _LINUX_BYTEORDER_SWABB_H */ diff --git a/include/linux/byteorder_vaxendian.h b/include/linux/byteorder/vax_endian.h similarity index 72% rename from include/linux/byteorder_vaxendian.h rename to include/linux/byteorder/vax_endian.h index 966f26473d3b..1c420fa69896 100644 --- a/include/linux/byteorder_vaxendian.h +++ b/include/linux/byteorder/vax_endian.h @@ -3,12 +3,14 @@ /* * Could have been named NUXI-endian - * This file isn't operational. + * This file *should* work, but has not been tested. * It's the beginning of what vaxlinux implementers will have to do. * I just hope we won't have to write standardized cpu_to_ve32() and suches! * little endian is 1234; bigendian is 4321; vaxendian is 3412 + * * But what does a __u64 look like: is it 34127856 or 78563412 ??? - * I don't dare imagine! + * I don't dare imagine! Hence, no 64-bit byteorder support yet. + * */ #ifndef __VAX_ENDIAN @@ -18,35 +20,8 @@ #define __VAX_ENDIAN_BITFIELD #endif -#define ___swahw32(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x0000ffffUL) << 16) | \ - (((__u32)(x) & (__u32)0xffff0000UL) >> 16) )) -#define ___swahb32(x) \ - ((__u32)( \ - (((__u32)(x) & (__u32)0x00ff00ffUL) << 16) | \ - (((__u32)(x) & (__u32)0xff00ff00UL) >> 16) )) - - -#ifndef __arch__swahw32 -# define __arch__swahw32(x) ___swahw32(x) -#endif -#ifndef __arch__swahb32 -# define __arch__swahb32(x) ___swahb32(x) -#endif -#ifndef __arch__swahw32p -# define __arch__swahw32p(x) __swahw32(*(x)) -#endif -#ifndef __arch__swahb32p -# define __arch__swahb32p(x) __swahb32(*(x)) -#endif -#ifndef __arch__swahw32s -# define __arch__swahw32s(x) *(x) = __swahw32p((x)) -#endif -#ifndef __arch__swahb32s -# define __arch__swahb32s(x) *(x) = __swahb32p((x)) -#endif - +#include +#include #define __constant_htonl(x) ___swahb32((x)) #define __constant_ntohl(x) ___swahb32((x)) @@ -89,6 +64,6 @@ #define __cpu_to_be16s(x) __swab16s((x)) #define __be16_to_cpus(x) __swab16s((x)) -#include +#include #endif /* _LINUX_BYTEORDER_VAX_ENDIAN_H */ diff --git a/include/linux/coda.h b/include/linux/coda.h index 557dc733efa6..08e263925a69 100644 --- a/include/linux/coda.h +++ b/include/linux/coda.h @@ -1,3 +1,11 @@ +/* + * Venus interface for Coda. + * Original version: (C) 1996 Peter Braam + * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon encourages users of this code to contribute improvements + * to the Coda project. Contact Peter Braam . + */ /* * diff --git a/include/linux/coda_cnode.h b/include/linux/coda_cnode.h index 49613c4519ba..43bf1b2cc960 100644 --- a/include/linux/coda_cnode.h +++ b/include/linux/coda_cnode.h @@ -1,3 +1,11 @@ +/* + * Cnode definitions for Coda. + * Original version: (C) 1996 Peter Braam + * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon encourages users of this code to contribute improvements + * to the Coda project. Contact Peter Braam . + */ /* revamped cnode.h file: platform dependent, kernel only! */ diff --git a/include/linux/coda_opstats.h b/include/linux/coda_opstats.h index 209675ff71fd..2c127e6e5927 100644 --- a/include/linux/coda_opstats.h +++ b/include/linux/coda_opstats.h @@ -1,36 +1,11 @@ -#ifndef _BLURB_ -#define _BLURB_ /* - - Coda: an Experimental Distributed File System - Release 3.1 - - Copyright (c) 1987-1996 Carnegie Mellon University - All Rights Reserved - -Permission to use, copy, modify and distribute this software and its -documentation is hereby granted, provided that both the copyright -notice and this permission notice appear in all copies of the -software, derivative works or modified versions, and any portions -thereof, and that both notices appear in supporting documentation, and -that credit is given to Carnegie Mellon University in all documents -and publicity pertaining to direct or indirect use of this code or its -derivatives. - -CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS, -SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS -FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON -DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER -RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF -ANY DERIVATIVE WORK. - -Carnegie Mellon encourages users of this software to return any -improvements or extensions that they make, and to grant Carnegie -Mellon the rights to redistribute these changes without encumbrance. -*/ - -static char *rcsid = "$Header: /afs/cs/project/coda-src/cvs/coda/kernel-src/vfs/linux/cfs_opstats.h,v 4.1 1997/01/08 21:53:19 rvb Exp $"; -#endif /*_BLURB_*/ + * Operations statistics for Coda. + * Original version: (C) 1996 Peter Braam + * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon encourages users of this code to contribute improvements + * to the Coda project. Contact Peter Braam . + */ /* diff --git a/include/linux/coda_sysctl.h b/include/linux/coda_sysctl.h index 1971098d6859..add670b3575f 100644 --- a/include/linux/coda_sysctl.h +++ b/include/linux/coda_sysctl.h @@ -1,2 +1,10 @@ +/* + * Sysctl operations for Coda. + * Original version: (C) 1996 Peter Braam + * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University + * + * Carnegie Mellon encourages users of this code to contribute improvements + * to the Coda project. Contact Peter Braam . + */ void coda_sysctl_init(void); void coda_sysctl_clean(void); diff --git a/include/linux/console.h b/include/linux/console.h index 7561de989281..fc5cd4b2d987 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -90,8 +90,8 @@ struct console int (*read)(struct console *, const char *, unsigned); kdev_t (*device)(struct console *); int (*wait_key)(struct console *); - void (*unblank)(void); - void (*setup)(struct console *, char *); + void (*unblank)(void); + int (*setup)(struct console *, char *); short flags; short index; int cflag; diff --git a/include/linux/fs.h b/include/linux/fs.h index 8da1df471d7b..2fa4cde01e25 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -547,7 +547,7 @@ struct file_operations { ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); - unsigned int (*poll) (struct file *, poll_table *); + unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); diff --git a/include/linux/pi2.h b/include/linux/pi2.h deleted file mode 100644 index 1740cc0b2ebd..000000000000 --- a/include/linux/pi2.h +++ /dev/null @@ -1,130 +0,0 @@ - -#define DMA_BUFF_SIZE 2200 - -#define ON 1 -#define OFF 0 - - -/* Register offset info, specific to the PI - * E.g., to read the data port on channel A, use - * inportb(pichan[dev].base + CHANA + DATA) - */ -#define CHANB 0 /* Base of channel B regs */ -#define CHANA 2 /* Base of channel A regs */ - -/* 8530 ports on each channel */ -#define CTL 0 -#define DATA 1 - -#define DMAEN 0x4 /* Offset off DMA Enable register */ - -/* Timer chip offsets */ -#define TMR0 0x8 /* Offset of timer 0 register */ -#define TMR1 0x9 /* Offset of timer 1 register */ -#define TMR2 0xA /* Offset of timer 2 register */ -#define TMRCMD 0xB /* Offset of timer command register */ - -/* Timer chip equates */ -#define SC0 0x00 /* Select counter 0 */ -#define SC1 0x40 /* Select counter 1 */ -#define SC2 0x80 /* Select counter 2 */ -#define CLATCH 0x00 /* Counter latching operation */ -#define MSB 0x20 /* Read/load MSB only */ -#define LSB 0x10 /* Read/load LSB only */ -#define LSB_MSB 0x30 /* Read/load LSB, then MSB */ -#define MODE0 0x00 /* Interrupt on terminal count */ -#define MODE1 0x02 /* Programmable one shot */ -#define MODE2 0x04 /* Rate generator */ -#define MODE3 0x06 /* Square wave rate generator */ -#define MODE4 0x08 /* Software triggered strobe */ -#define MODE5 0x0a /* Hardware triggered strobe */ -#define BCD 0x01 /* BCD counter */ - -/* DMA controller registers */ -#define DMA_STAT 8 /* DMA controller status register */ -#define DMA_CMD 8 /* DMA controller command register */ -#define DMA_MASK 10 /* DMA controller mask register */ -#define DMA_MODE 11 /* DMA controller mode register */ -#define DMA_RESETFF 12 /* DMA controller first/last flip flop */ -/* DMA data */ -#define DMA_DISABLE (0x04) /* Disable channel n */ -#define DMA_ENABLE (0x00) /* Enable channel n */ -/* Single transfers, incr. address, auto init, writes, ch. n */ -#define DMA_RX_MODE (0x54) -/* Single transfers, incr. address, no auto init, reads, ch. n */ -#define DMA_TX_MODE (0x48) - -#define SINGLE 3686400 -#define DOUBLE 7372800 - -#define SIOCGPIPARAM 0x5000 /* get PI parameters */ -#define SIOCSPIPARAM 0x5001 /* set */ -#define SIOCGPIBAUD 0x5002 /* get only baud rate */ -#define SIOCSPIBAUD 0x5003 -#define SIOCGPIDMA 0x5004 /* get only DMA */ -#define SIOCSPIDMA 0x5005 -#define SIOCGPIIRQ 0x5006 /* get only IRQ */ -#define SIOCSPIIRQ 0x5007 - -struct pi_req { - int cmd; - int speed; - int clockmode; - int txdelay; - unsigned char persist; - int slotime; - int squeldelay; - int dmachan; - int irq; -}; - -#ifdef __KERNEL__ - -/* Information that needs to be kept for each channel. */ -struct pi_local { - struct net_device_stats stats; - long open_time; /* Useless example local info. */ - unsigned long xtal; - - struct mbuf *rcvbuf;/* Buffer for current rx packet */ - struct mbuf *rxdmabuf1; /* DMA rx buffer */ - struct mbuf *rxdmabuf2; /* DMA rx buffer */ - - int bufsiz; /* Size of rcvbuf */ - char *rcp; /* Pointer into rcvbuf */ - - struct sk_buff_head sndq; /* Packets awaiting transmission */ - int sndcnt; /* Number of packets on sndq */ - struct sk_buff *sndbuf; /* Current buffer being transmitted */ - char *txdmabuf; /* Transmit DMA buffer */ - char *txptr; /* Used by B port tx */ - int txcnt; - char tstate; /* Transmitter state */ -#define IDLE 0 /* Transmitter off, no data pending */ -#define ACTIVE 1 /* Transmitter on, sending data */ -#define UNDERRUN 2 /* Transmitter on, flushing CRC */ -#define FLAGOUT 3 /* CRC sent - attempt to start next frame */ -#define DEFER 4 /* Receive Active - DEFER Transmit */ -#define ST_TXDELAY 5 /* Sending leading flags */ -#define CRCOUT 6 - char rstate; /* Set when !DCD goes to 0 (TRUE) */ -/* Normal state is ACTIVE if Receive enabled */ -#define RXERROR 2 /* Error -- Aborting current Frame */ -#define RXABORT 3 /* ABORT sequence detected */ -#define TOOBIG 4 /* too large a frame to store */ - int dev; /* Device number */ - int base; /* Base of I/O registers */ - int cardbase; /* Base address of card */ - int stata; /* address of Channel A status regs */ - int statb; /* address of Channel B status regs */ - int speed; /* Line speed, bps */ - int clockmode; /* tapr 9600 modem clocking option */ - int txdelay; /* Transmit Delay 10 ms/cnt */ - unsigned char persist; /* Persistence (0-255) as a % */ - int slotime; /* Delay to wait on persistence hit */ - int squeldelay; /* Delay after XMTR OFF for squelch tail */ - struct iface *iface; /* Associated interface */ - int dmachan; /* DMA channel for this port */ -}; - -#endif diff --git a/include/linux/poll.h b/include/linux/poll.h index 2001fedfb223..01c4d15196e4 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -1 +1,106 @@ +#ifndef _LINUX_POLL_H + #include + +#ifdef __KERNEL__ + +#include +#include +#include + + +struct poll_table_entry { + struct wait_queue wait; + struct wait_queue ** wait_address; +}; + +typedef struct poll_table_struct { + unsigned int nr; + struct poll_table_entry * entry; +} poll_table; + +#define __MAX_POLL_TABLE_ENTRIES (PAGE_SIZE / sizeof (struct poll_table_entry)) + +extern inline void poll_wait(struct wait_queue ** wait_address, poll_table *p) +{ + struct poll_table_entry * entry; + + if (!p || !wait_address) + return; + if (p->nr >= __MAX_POLL_TABLE_ENTRIES) + return; + entry = p->entry + p->nr; + entry->wait_address = wait_address; + entry->wait.task = current; + entry->wait.next = NULL; + add_wait_queue(wait_address,&entry->wait); + p->nr++; +} + + +/* + * For the kernel fd_set we use a fixed set-size for allocation purposes. + * This set-size doesn't necessarily bear any relation to the size the user + * uses, but should preferably obviously be larger than any possible user + * size (NR_OPEN bits). + * + * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we + * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits, + * to be divided by 6. And we'd better make sure we round to a full + * long-word (in fact, we'll round to 64 bytes). + */ + + +#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64) +#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8) +typedef unsigned long kernel_fd_set[KFDS_NR/__NFDBITS]; + +typedef struct { + kernel_fd_set in, out, ex; + kernel_fd_set res_in, res_out, res_ex; +} fd_set_buffer; + + +/* + * We do a VERIFY_WRITE here even though we are only reading this time: + * we'll write to it eventually.. + * + * Use "unsigned long" accesses to let user-mode fd_set's be long-aligned. + */ +static inline +int get_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset) +{ + /* round up nr to nearest "unsigned long" */ + nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long); + if (ufdset) { + int error; + error = verify_area(VERIFY_WRITE, ufdset, nr); + if (!error) + error = __copy_from_user(fdset, ufdset, nr); + return error; + } + memset(fdset, 0, nr); + return 0; +} + +static inline +void set_fd_set(unsigned long nr, void *ufdset, unsigned long *fdset) +{ + if (ufdset) { + nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long))*sizeof(long); + __copy_to_user(ufdset, fdset, nr); + } +} + +static inline +void zero_fd_set(unsigned long nr, unsigned long *fdset) +{ + nr = (nr + 8*sizeof(long) - 1) / (8*sizeof(long)) * sizeof(long); + memset(fdset, 0, nr); +} + +extern int do_select(int n, fd_set_buffer *fds, unsigned long timeout); + +#endif /* KERNEL */ + +#endif /* _LINUX_POLL_H */ diff --git a/include/linux/pt.h b/include/linux/pt.h deleted file mode 100644 index 9ab17f501577..000000000000 --- a/include/linux/pt.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * pt.h: Linux device driver for the Gracilis PackeTwin - * Copyright (C) 1995 Craig Small VK2XLZ (vk2xlz@vk2xlz.ampr.org.) - * - * Please read the notice appearing at the top of the file pt.c - */ -#define DMA_BUFF_SIZE 2200 - -#define ON 1 -#define OFF 0 - - -/* Register offset info, specific to the PT - * E.g., to read the data port on channel A, use - * inportb(pichan[dev].base + CHANA + DATA) - */ -#define CHANB 0 /* Base of channel B regs */ -#define CHANA 2 /* Base of channel A regs */ - -/* 8530 ports on each channel */ -#define CTL 0 -#define DATA 1 - -#define DMAEN 0x8 /* Offset off DMA Enable register */ - -/* Timer chip offsets */ -#define TMR0 0x4 /* Offset of timer 0 register */ -#define TMR1 0x5 /* Offset of timer 1 register */ -#define TMR2 0x6 /* Offset of timer 2 register */ -#define TMRCMD 0x7 /* Offset of timer command register */ -#define INT_REG 0x8 -#define TMR1CLR 0x9 -#define TMR2CLR 0xa - -/* Interrupt register equates */ -#define PT_SCC_MSK 0x1 -#define PT_TMR1_MSK 0x2 -#define PT_TMR2_MSK 0x4 - -/* Serial/interrupt register equates */ -#define PT_DTRA_ON 0x1 -#define PT_DTRB_ON 0x2 -#define PT_EXTCLKA 0x4 -#define PT_EXTCLKB 0x8 -#define PT_LOOPA_ON 0x10 -#define PT_LOOPB_ON 0x20 -#define PT_EI 0x80 - -/* Timer chip equates */ -#define SC0 0x00 /* Select counter 0 */ -#define SC1 0x40 /* Select counter 1 */ -#define SC2 0x80 /* Select counter 2 */ -#define CLATCH 0x00 /* Counter latching operation */ -#define MSB 0x20 /* Read/load MSB only */ -#define LSB 0x10 /* Read/load LSB only */ -#define LSB_MSB 0x30 /* Read/load LSB, then MSB */ -#define MODE0 0x00 /* Interrupt on terminal count */ -#define MODE1 0x02 /* Programmable one shot */ -#define MODE2 0x04 /* Rate generator */ -#define MODE3 0x06 /* Square wave rate generator */ -#define MODE4 0x08 /* Software triggered strobe */ -#define MODE5 0x0a /* Hardware triggered strobe */ -#define BCD 0x01 /* BCD counter */ - -/* DMA controller registers */ -#define DMA_STAT 8 /* DMA controller status register */ -#define DMA_CMD 8 /* DMA controller command register */ -#define DMA_MASK 10 /* DMA controller mask register */ -#define DMA_MODE 11 /* DMA controller mode register */ -#define DMA_RESETFF 12 /* DMA controller first/last flip flop */ -/* DMA data */ -#define DMA_DISABLE (0x04) /* Disable channel n */ -#define DMA_ENABLE (0x00) /* Enable channel n */ -/* Single transfers, incr. address, auto init, writes, ch. n */ -#define DMA_RX_MODE (0x54) -/* Single transfers, incr. address, no auto init, reads, ch. n */ -#define DMA_TX_MODE (0x48) - -/* Write registers */ -#define DMA_CFG 0x08 -#define SERIAL_CFG 0x09 -#define INT_CFG 0x09 /* shares with serial config */ -#define DMA_CLR_FF 0x0a - -#define SINGLE 3686400 -#define DOUBLE 7372800 -#define XTAL ((long) 6144000L) - -#define SIOCGPIPARAM 0x5000 /* get PI parameters */ -#define SIOCSPIPARAM 0x5001 /* set */ -#define SIOCGPIBAUD 0x5002 /* get only baud rate */ -#define SIOCSPIBAUD 0x5003 -#define SIOCGPIDMA 0x5004 /* get only DMA */ -#define SIOCSPIDMA 0x5005 -#define SIOCGPIIRQ 0x5006 /* get only IRQ */ -#define SIOCSPIIRQ 0x5007 - -struct pt_req -{ - int cmd; - int speed; - int clockmode; - int txdelay; - unsigned char persist; - int slotime; - int squeldelay; - int dmachan; - int irq; -}; - -/* SCC Interrupt vectors, if we have set 'status low' */ -#define CHBTxIV 0x00 -#define CHBEXTIV 0x02 -#define CHBRxIV 0x04 -#define CHBSRCIV 0x06 -#define CHATxIV 0x08 -#define CHAEXTIV 0x0a -#define CHARxIV 0x0c -#define CHASRCIV 0x0e - - -#ifdef __KERNEL__ - -/* Information that needs to be kept for each channel. */ -struct pt_local -{ - struct net_device_stats stats; /* %%%dp*/ - long open_time; /* Useless example local info. */ - unsigned long xtal; - - struct mbuf *rcvbuf;/* Buffer for current rx packet */ - struct mbuf *rxdmabuf1; /* DMA rx buffer */ - struct mbuf *rxdmabuf2; /* DMA rx buffer */ - - int bufsiz; /* Size of rcvbuf */ - char *rcp; /* Pointer into rcvbuf */ - struct sk_buff_head sndq; /* Packets awaiting transmission */ - int sndcnt; /* Number of packets on sndq */ - struct sk_buff *sndbuf; /* Current buffer being transmitted */ - char *txdmabuf; /* Transmit DMA buffer */ - char *txptr; /* Used by B port tx */ - int txcnt; - char tstate; /* Transmitter state */ -#define IDLE 0 /* Transmitter off, no data pending */ -#define ACTIVE 1 /* Transmitter on, sending data */ -#define UNDERRUN 2 /* Transmitter on, flushing CRC */ -#define FLAGOUT 3 /* CRC sent - attempt to start next frame */ -#define DEFER 4 /* Receive Active - DEFER Transmit */ -#define ST_TXDELAY 5 /* Sending leading flags */ -#define CRCOUT 6 - char rstate; /* Set when !DCD goes to 0 (TRUE) */ -/* Normal state is ACTIVE if Receive enabled */ -#define RXERROR 2 /* Error -- Aborting current Frame */ -#define RXABORT 3 /* ABORT sequence detected */ -#define TOOBIG 4 /* too large a frame to store */ - - int dev; /* Device number */ - int base; /* Base of I/O registers */ - int cardbase; /* Base address of card */ - int stata; /* address of Channel A status regs */ - int statb; /* address of Channel B status regs */ - int speed; /* Line speed, bps */ - int clockmode; /* tapr 9600 modem clocking option */ - int txdelay; /* Transmit Delay 10 ms/cnt */ - unsigned char persist; /* Persistence (0-255) as a % */ - int slotime; /* Delay to wait on persistence hit */ - int squeldelay; /* Delay after XMTR OFF for squelch tail */ - struct iface *iface; /* Associated interface */ - int dmachan; /* DMA channel for this port */ - char saved_RR0; /* The saved version of RR) that we compare with */ - int nrzi; /* Do we use NRZI (or NRZ) */ -}; - -#endif diff --git a/include/linux/sched.h b/include/linux/sched.h index 257b2329ff1d..f2b34cb3161e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -601,22 +601,6 @@ extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * write_unlock_irqrestore(&waitqueue_lock, flags); } -extern inline void poll_wait(struct wait_queue ** wait_address, poll_table * p) -{ - struct poll_table_entry * entry; - - if (!p || !wait_address) - return; - if (p->nr >= __MAX_POLL_TABLE_ENTRIES) - return; - entry = p->entry + p->nr; - entry->wait_address = wait_address; - entry->wait.task = current; - entry->wait.next = NULL; - add_wait_queue(wait_address,&entry->wait); - p->nr++; -} - #define REMOVE_LINKS(p) do { unsigned long flags; \ write_lock_irqsave(&tasklist_lock, flags); \ (p)->next_task->prev_task = (p)->prev_task; \ diff --git a/include/linux/soundcard.h b/include/linux/soundcard.h index bfd28359e53d..e48c0b079eed 100644 --- a/include/linux/soundcard.h +++ b/include/linux/soundcard.h @@ -599,6 +599,7 @@ typedef struct buffmem_desc { #define SNDCTL_DSP_MAPOUTBUF _SIOR ('P', 20, buffmem_desc) #define SNDCTL_DSP_SETSYNCRO _SIO ('P', 21) #define SNDCTL_DSP_SETDUPLEX _SIO ('P', 22) +#define SNDCTL_DSP_GETODELAY _SIOR ('P', 23, int) /* * Application's profile defines the way how playback underrun situations should be handled. diff --git a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h index eb443b26986a..7c5167fa815d 100644 --- a/include/linux/sysv_fs.h +++ b/include/linux/sysv_fs.h @@ -361,17 +361,14 @@ sv_bread (struct super_block *sb, kdev_t dev, unsigned int block) * Function prototypes */ -extern int sysv_lookup(struct inode * dir,const char * name, int len, - struct inode ** result); -extern int sysv_create(struct inode * dir,const char * name, int len, int mode, - struct inode ** result); -extern int sysv_mkdir(struct inode * dir, const char * name, int len, int mode); -extern int sysv_rmdir(struct inode * dir, const char * name, int len); -extern int sysv_unlink(struct inode * dir, const char * name, int len); -extern int sysv_symlink(struct inode * inode, const char * name, int len, - const char * symname); -extern int sysv_link(struct inode * oldinode, struct inode * dir, const char * name, int len); -extern int sysv_mknod(struct inode * dir, const char * name, int len, int mode, int rdev); +extern int sysv_lookup(struct inode * dir, struct dentry * dentry); +extern int sysv_create(struct inode * dir, struct dentry * dentry, int mode); +extern int sysv_mkdir(struct inode * dir, struct dentry * dentry, int mode); +extern int sysv_rmdir(struct inode * dir, struct dentry * dentry); +extern int sysv_unlink(struct inode * dir, struct dentry * dentry); +extern int sysv_symlink(struct inode * inode, struct dentry * dentry, const char * symname); +extern int sysv_link(struct inode * oldinode, struct inode * dir, struct dentry * dentry); +extern int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev); extern int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, struct inode * new_dir, struct dentry * new_dentry); extern struct inode * sysv_new_inode(const struct inode * dir); diff --git a/include/linux/time.h b/include/linux/time.h index 62417ebb5255..8bc6592d87dc 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -2,11 +2,12 @@ #define _LINUX_TIME_H #include +#include #ifndef _STRUCT_TIMESPEC #define _STRUCT_TIMESPEC struct timespec { - long tv_sec; /* seconds */ + time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #endif /* _STRUCT_TIMESPEC */ @@ -36,8 +37,8 @@ jiffies_to_timespec(unsigned long jiffies, struct timespec *value) } struct timeval { - int tv_sec; /* seconds */ - int tv_usec; /* microseconds */ + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* microseconds */ }; struct timezone { diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index f5f3296071a0..501ea07651da 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -119,7 +119,8 @@ struct tty_ldisc { int (*ioctl)(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); void (*set_termios)(struct tty_struct *tty, struct termios * old); - unsigned int (*poll)(struct tty_struct *, struct file *, poll_table *); + unsigned int (*poll)(struct tty_struct *, struct file *, + struct poll_table_struct *); /* * The following routines are called from below. diff --git a/include/linux/types.h b/include/linux/types.h index 7f98711a41a2..a990773af62f 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -17,6 +17,7 @@ typedef __kernel_uid_t uid_t; typedef __kernel_gid_t gid_t; typedef __kernel_daddr_t daddr_t; typedef __kernel_key_t key_t; +typedef __kernel_suseconds_t suseconds_t; #if defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef __kernel_loff_t loff_t; diff --git a/include/linux/wait.h b/include/linux/wait.h index 0a0d11fc9b69..6514693c26e5 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -28,18 +28,6 @@ static inline int waitqueue_active(struct wait_queue **q) return head && head != WAIT_QUEUE_HEAD(q); } -struct poll_table_entry { - struct wait_queue wait; - struct wait_queue ** wait_address; -}; - -typedef struct poll_table_struct { - unsigned int nr; - struct poll_table_entry * entry; -} poll_table; - -#define __MAX_POLL_TABLE_ENTRIES (PAGE_SIZE / sizeof (struct poll_table_entry)) - #endif /* __KERNEL__ */ #endif diff --git a/init/main.c b/init/main.c index 0f58909d1ad9..43e592d561d0 100644 --- a/init/main.c +++ b/init/main.c @@ -225,6 +225,9 @@ extern void riscom8_setup(char *str, int *ints); #ifdef CONFIG_SPECIALIX extern void specialix_setup(char *str, int *ints); #endif +#ifdef CONFIG_DMASCC +extern void dmascc_setup(char *str, int *ints); +#endif #ifdef CONFIG_BAYCOM_PAR extern void baycom_par_setup(char *str, int *ints); #endif @@ -553,6 +556,9 @@ struct { #ifdef CONFIG_RISCOM8 { "riscom8=", riscom8_setup }, #endif +#ifdef CONFIG_DMASCC + { "dmascc=", dmascc_setup }, +#endif #ifdef CONFIG_SPECIALIX { "specialix=", specialix_setup }, #endif diff --git a/ipc/msg.c b/ipc/msg.c index 0bf4a695ee77..6ff658b02386 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -669,8 +669,8 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) goto out; case IPC_SET: err = -EPERM; - if (!suser() && current->euid != ipcp->cuid && - current->euid != ipcp->uid) + if (current->euid != ipcp->cuid && + current->euid != ipcp->uid && !suser()) goto out; if (tbuf.msg_qbytes > MSGMNB && !suser()) goto out; @@ -684,8 +684,8 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) goto out; case IPC_RMID: err = -EPERM; - if (!suser() && current->euid != ipcp->cuid && - current->euid != ipcp->uid) + if (current->euid != ipcp->cuid && + current->euid != ipcp->uid && !suser()) goto out; /* * There is only one kerneld message queue, diff --git a/ipc/sem.c b/ipc/sem.c index f63f2a7a9104..de7b2a2624bd 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -487,7 +487,7 @@ asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg) goto out; break; case IPC_RMID: - if (suser() || current->euid == ipcp->cuid || current->euid == ipcp->uid) { + if (current->euid == ipcp->cuid || current->euid == ipcp->uid || suser()) { freeary (id); err = 0; goto out; @@ -545,7 +545,7 @@ asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg) update_queue(sma); break; case IPC_SET: - if (suser() || current->euid == ipcp->cuid || current->euid == ipcp->uid) { + if (current->euid == ipcp->cuid || current->euid == ipcp->uid || suser()) { ipcp->uid = tbuf.sem_perm.uid; ipcp->gid = tbuf.sem_perm.gid; ipcp->mode = (ipcp->mode & ~S_IRWXUGO) diff --git a/ipc/shm.c b/ipc/shm.c index 9a3949cc6413..896ee132500a 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -346,8 +346,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) copy_to_user (buf, &tbuf, sizeof(*buf)); break; case IPC_SET: - if (suser() || current->euid == shp->shm_perm.uid || - current->euid == shp->shm_perm.cuid) { + if (current->euid == shp->shm_perm.uid || + current->euid == shp->shm_perm.cuid || suser()) { ipcp->uid = tbuf.shm_perm.uid; ipcp->gid = tbuf.shm_perm.gid; ipcp->mode = (ipcp->mode & ~S_IRWXUGO) @@ -358,8 +358,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) err = -EPERM; goto out; case IPC_RMID: - if (suser() || current->euid == shp->shm_perm.uid || - current->euid == shp->shm_perm.cuid) { + if (current->euid == shp->shm_perm.uid || + current->euid == shp->shm_perm.cuid || suser()) { shp->shm_perm.mode |= SHM_DEST; if (shp->shm_nattch <= 0) killseg (id); diff --git a/ipc/util.c b/ipc/util.c index 88e63c6fc407..f0ba7feddc69 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -1,6 +1,11 @@ /* * linux/ipc/util.c * Copyright (C) 1992 Krishna Balasubramanian + * + * Sep 1997 - Call suser() last after "normal" permission checks so we + * get BSD style process accounting right. + * Occurs in several places in the IPC code. + * Chris Evans, */ #include @@ -35,8 +40,6 @@ int ipcperms (struct ipc_perm *ipcp, short flag) { /* flag will most probably be 0 or S_...UGO from */ int requested_mode, granted_mode; - if (suser()) - return 0; requested_mode = (flag >> 6) | (flag >> 3) | flag; granted_mode = ipcp->mode; if (current->euid == ipcp->cuid || current->euid == ipcp->uid) @@ -44,7 +47,7 @@ int ipcperms (struct ipc_perm *ipcp, short flag) else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) granted_mode >>= 3; /* is there some bit set in requested_mode but not in granted_mode? */ - if (requested_mode & ~granted_mode & 0007) + if ((requested_mode & ~granted_mode & 0007) && !suser()) return -1; return 0; } diff --git a/kernel/itimer.c b/kernel/itimer.c index 479f660a0dde..d4bbf7851ca8 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -45,7 +45,7 @@ static void jiffiestotv(unsigned long jiffies, struct timeval *value) value->tv_sec = jiffies / HZ; } -static int _getitimer(int which, struct itimerval *value) +int do_getitimer(int which, struct itimerval *value) { register unsigned long val, interval; @@ -86,10 +86,10 @@ asmlinkage int sys_getitimer(int which, struct itimerval *value) struct itimerval get_buffer; if (value) { - error = _getitimer(which, &get_buffer); - if (!error) - error = copy_to_user(value, &get_buffer, sizeof(get_buffer)) - ? -EFAULT : 0; + error = do_getitimer(which, &get_buffer); + if (!error && + copy_to_user(value, &get_buffer, sizeof(get_buffer))) + error = -EFAULT; } return error; } @@ -111,14 +111,14 @@ void it_real_fn(unsigned long __data) } } -int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue) +int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) { register unsigned long i, j; int k; i = tvtojiffies(&value->it_interval); j = tvtojiffies(&value->it_value); - if (ovalue && (k = _getitimer(which, ovalue)) < 0) + if (ovalue && (k = do_getitimer(which, ovalue)) < 0) return k; switch (which) { case ITIMER_REAL: @@ -155,7 +155,8 @@ int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue) /* SMP: Again, only we play with our itimers, and signals are SMP safe * now so that is not an issue at all anymore. */ -asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue) +asmlinkage int sys_setitimer(int which, struct itimerval *value, + struct itimerval *ovalue) { struct itimerval set_buffer, get_buffer; int error; @@ -168,7 +169,7 @@ asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerva } else memset((char *) &set_buffer, 0, sizeof(set_buffer)); - error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0); + error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : 0); if (error || !ovalue) return error; diff --git a/kernel/printk.c b/kernel/printk.c index d56937a602a0..c67c4d7480e9 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -80,9 +80,9 @@ __initfunc(void console_setup(char *str, int *ints)) if ((c->options = strchr(str, ',')) != NULL) *(c->options++) = 0; #ifdef __sparc__ - if (strcmp(str, "ttya")) + if (!strcmp(str, "ttya")) strcpy(c->name, "ttyS0"); - if (strcmp(str, "ttyb")) + if (!strcmp(str, "ttyb")) strcpy(c->name, "ttyS1"); #endif @@ -317,11 +317,13 @@ void register_console(struct console * console) * that registers here. */ if (selected_console == 0) { - console->flags |= CON_ENABLED | CON_FIRST; - selected_console = 1; - if (console->setup) - console->setup(console, NULL); + if (console->setup == NULL || + console->setup(console, NULL) == 0) { + console->flags |= CON_ENABLED | CON_FIRST; + selected_console = 1; + } } + /* * See if this console matches one we selected on * the command line. @@ -332,15 +334,20 @@ void register_console(struct console * console) if (console->index >= 0 && console->index != console_cmdline[i].index) continue; + if (console->index < 0) console->index = 0; + if (console->setup && + console->setup(console, console_cmdline[i].options) != 0) + break; console->flags |= CON_ENABLED; console->index = console_cmdline[i].index; if (i == 0) console->flags |= CON_FIRST; - if (console->setup) - console->setup(console, console_cmdline[i].options); break; } + if (!(console->flags & CON_ENABLED)) + return; + /* * Put this console in the list - keep the * preferred driver at the head of the list. diff --git a/kernel/sched.c b/kernel/sched.c index 41cd39c3f718..cfaea21165cb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -50,8 +50,12 @@ int securelevel = 0; /* system security level */ long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */ -volatile struct timeval xtime __attribute__ ((aligned (8))); /* The current time */ -int tickadj = 500/HZ; /* microsecs */ + +/* The current time */ +volatile struct timeval xtime __attribute__ ((aligned (16))); + +/* Don't completely fail for HZ > 500. */ +int tickadj = 500/HZ ? : 1; /* microsecs */ DECLARE_TASK_QUEUE(tq_timer); DECLARE_TASK_QUEUE(tq_immediate); @@ -80,7 +84,7 @@ long time_adjust_step = 0; int need_resched = 0; unsigned long event = 0; -extern int _setitimer(int, struct itimerval *, struct itimerval *); +extern int do_setitimer(int, struct itimerval *, struct itimerval *); unsigned int * prof_buffer = NULL; unsigned long prof_len = 0; unsigned long prof_shift = 0; @@ -1114,7 +1118,7 @@ asmlinkage unsigned int sys_alarm(unsigned int seconds) it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; it_new.it_value.tv_sec = seconds; it_new.it_value.tv_usec = 0; - _setitimer(ITIMER_REAL, &it_new, &it_old); + do_setitimer(ITIMER_REAL, &it_new, &it_old); oldalarm = it_old.it_value.tv_sec; /* ehhh.. We can't return 0 if we have an alarm pending.. */ /* And we'd better return too much than too little anyway */ @@ -1508,7 +1512,7 @@ static void show_task(int nr,struct task_struct * p) render_sigset_t(&p->signal, s); render_sigset_t(&p->blocked, b); - printk("\tsig: %d %s %s :", signal_pending(p), s, b); + printk(" sig: %d %s %s :", signal_pending(p), s, b); for (q = p->sigqueue; q ; q = q->next) printk(" %d", q->info.si_signo); printk(" X\n"); diff --git a/kernel/time.c b/kernel/time.c index 7ba688b60af4..7927c2aa1eae 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -151,25 +151,17 @@ inline static void warp_clock(void) * as soon as possible, so that the clock can be set right. Otherwise, * various programs will get confused when the clock gets warped. */ -asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz) + +int do_sys_settimeofday(struct timeval *tv, struct timezone *tz) { - static int firsttime = 1; - struct timeval new_tv; - struct timezone new_tz; + static int firsttime = 1; if (!suser()) return -EPERM; - if (tv) { - if (copy_from_user(&new_tv, tv, sizeof(*tv))) - return -EFAULT; - } if (tz) { - if (copy_from_user(&new_tz, tz, sizeof(*tz))) - return -EFAULT; - /* SMP safe, global irq locking makes it work. */ - sys_tz = new_tz; + sys_tz = *tz; if (firsttime) { firsttime = 0; if (!tv) @@ -181,11 +173,28 @@ asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz) /* SMP safe, again the code in arch/foo/time.c should * globally block out interrupts when it runs. */ - do_settimeofday(&new_tv); + do_settimeofday(tv); } return 0; } +asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz) +{ + struct timeval new_tv; + struct timezone new_tz; + + if (tv) { + if (copy_from_user(&new_tv, tv, sizeof(*tv))) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&new_tz, tz, sizeof(*tz))) + return -EFAULT; + } + + return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL); +} + long pps_offset = 0; /* pps time offset (us) */ long pps_jitter = MAXTIME; /* time dispersion (jitter) (us) */ diff --git a/linux/include/linux/dmascc.h b/linux/include/linux/dmascc.h new file mode 100644 index 000000000000..01b46df731ce --- /dev/null +++ b/linux/include/linux/dmascc.h @@ -0,0 +1,43 @@ +/* + * $Id: dmascc.h,v 1.1 1997/12/01 10:44:55 oe1kib Exp $ + * + * Driver for high-speed SCC boards (those with DMA support) + * Copyright (C) 1997 Klaus Kudielka + * + * 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 distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Ioctls */ +#define SIOCGSCCPARAM SIOCDEVPRIVATE +#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1) + +/* Frequency of timer 0 */ +#define TMR_0_HZ 25600 + +/* Configurable parameters */ +struct scc_param { + int pclk_hz; /* frequency of BRG input (read-only - don't change) */ + int brg_tc; /* baud rate generator terminal count - BRG disabled if < 0 */ + int nrzi; /* 0 (nrz), 1 (nrzi) */ + int clocks; /* see documentation */ + int txdelay; /* [1/TMR_0_HZ] */ + int txtime; /* [1/HZ] */ + int sqdelay; /* [1/TMR_0_HZ] */ + int waittime; /* [1/TMR_0_HZ] */ + int slottime; /* [1/TMR_0_HZ] */ + int persist; /* 0 ... 255 */ + int dma; /* 1, 3 */ +}; + diff --git a/net/Config.in b/net/Config.in index f67bbd8cc154..e1c9487bf855 100644 --- a/net/Config.in +++ b/net/Config.in @@ -48,6 +48,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then # fi tristate 'WAN router' CONFIG_WAN_ROUTER bool 'CPU is too slow to handle full bandwidth' CONFIG_CPU_IS_SLOW + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'QoS and/or fair queueing' CONFIG_NET_SCHED if [ "$CONFIG_NET_SCHED" = "y" ]; then tristate 'CBQ packet scheduler' CONFIG_NET_SCH_CBQ @@ -59,5 +60,6 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'auxiliary FIFO queue' CONFIG_NET_SCH_PFIFO tristate 'auxiliary PRIO queue' CONFIG_NET_SCH_PRIO fi + fi fi endmenu diff --git a/net/core/dev.c b/net/core/dev.c index 6c295b72bd52..8d94f6817e95 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1573,12 +1573,11 @@ int unregister_netdevice(struct device *dev) * */ extern int lance_init(void); -extern int pi_init(void); extern int bpq_init(void); extern int scc_init(void); extern void sdla_setup(void); extern void dlci_setup(void); -extern int pt_init(void); +extern int dmascc_init(void); extern int sm_init(void); extern int baycom_ser_fdx_init(void); extern int baycom_ser_hdx_init(void); @@ -1635,15 +1634,12 @@ __initfunc(int net_dev_init(void)) #if defined(CONFIG_LANCE) lance_init(); #endif -#if defined(CONFIG_PI) - pi_init(); -#endif #if defined(CONFIG_SCC) scc_init(); #endif -#if defined(CONFIG_PT) - pt_init(); -#endif +#if defined(CONFIG_DMASCC) + dmascc_init(); +#endif #if defined(CONFIG_BPQETHER) bpq_init(); #endif diff --git a/net/core/sock.c b/net/core/sock.c index 16d5435ed89c..7254748875ab 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -75,6 +75,7 @@ * protocol private data. * Steve Whitehouse: Added various other default routines * common to several socket families. + * Chris Evans : Call suser() check last on F_SETOWN * * To Fix: * @@ -938,8 +939,9 @@ int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) * way to make sure that you can't send a sigurg to * another process. */ - if (!suser() && current->pgrp != -arg && - current->pid != arg) return(-EPERM); + if (current->pgrp != -arg && + current->pid != arg && + !suser()) return(-EPERM); sk->proc = arg; return(0); case F_GETOWN: diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6f62306ffc1c..10c7cd4f4e4b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -60,8 +60,13 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_syncookies; -/* Define this to check TCP sequence numbers in ICMP packets. */ -#define ICMP_PARANOIA 1 +/* Check TCP sequence numbers in ICMP packets. */ +#define ICMP_PARANOIA 1 +#ifndef ICMP_PARANOIA +#define ICMP_MIN_LENGTH 4 +#else +#define ICMP_MIN_LENGTH 8 +#endif static void tcp_v4_send_reset(struct sk_buff *skb); @@ -772,9 +777,7 @@ static struct open_request *tcp_v4_search_req(struct tcp_opt *tp, /* * This routine does path mtu discovery as defined in RFC1197. */ -static inline void do_pmtu_discovery(struct sock *sk, - struct iphdr *ip, - struct tcphdr *th) +static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *ip) { int new_mtu; struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; @@ -825,11 +828,13 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len) int type = skb->h.icmph->type; int code = skb->h.icmph->code; struct sock *sk; - __u32 seq; int opening; +#ifdef ICMP_PARANOIA + __u32 seq; +#endif - if (len < (iph->ihl << 2)+sizeof(struct tcphdr)) { - icmp_statistics.IcmpInErrors++; + if (len < (iph->ihl << 2) + ICMP_MIN_LENGTH) { + icmp_statistics.IcmpInErrors++; return; } @@ -891,7 +896,7 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len) break; case ICMP_DEST_UNREACH: if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ - do_pmtu_discovery(sk, iph, th); + do_pmtu_discovery(sk, iph); return; } break; diff --git a/scripts/Menuconfig b/scripts/Menuconfig index c452e1921577..2897643ce939 100644 --- a/scripts/Menuconfig +++ b/scripts/Menuconfig @@ -24,6 +24,10 @@ # 070497 Bernhard Kaindl (bkaindl@netway.at) - get default values for # new bool, tristate and dep_tristate parameters from the defconfig file. # new configuration parameters are marked with '(NEW)' as in make config. +# 180697 Bernhard Kaindl (bkaindl@netway.at) - added the needed support +# for string options. They are handled like the int and hex options. +# 081297 Pavel Machek (pavel@atrey.karlin.mff.cuni.cz) - better error +# handling #---------------------------------------------------------------------------- @@ -179,7 +183,7 @@ function int () { } # -# Add a menu item which will call our local int function. +# Add a menu item which will call our local hex function. # function hex () { eval $2=\${$2:-"$3"} x=\${$2##*[x,X]} @@ -189,6 +193,17 @@ function hex () { echo -e "function $2 () { l_hex '$1' '$2' '$3' '$x' ;}" >>MCradiolists } +# +# Add a menu item which will call our local string function. +# +function string () { + eval $2=\${$2:-"$3"} x=\$$2 + + echo -ne "'$2' ' $1: \"$x\"' " >>MCmenu + + echo -e "function $2 () { l_string '$1' '$2' '$3' '$x' ;}" >>MCradiolists +} + # # Add a menu item which will call our local One-of-Many choice list. # @@ -481,6 +496,34 @@ function l_hex () { done } +# +# Create a dialog for entering a string into a kernel option. +# +function l_string () { + while true + do + if $DIALOG --title "$1" \ + --backtitle "$backtitle" \ + --inputbox "$inputbox_instructions_string" \ + 10 75 "$4" 2>MCdialog.out + then + answer="`cat MCdialog.out`" + answer="${answer:-$3}" + + # + # Someone may add a nice check for the entered + # string here... + # + eval $2=\"$answer\" + + break + fi + + help "$2" "$1" + done +} + + # # Handle a one-of-many choice list. # @@ -540,12 +583,18 @@ function l_choice () { done } +# +# Call awk, and watch for error codes, etc. +# +function callawk () { +awk "$1" || echo "Awk died with error code $?. Giving up." || exit 1 +} # # A faster awk based recursive parser. (I hope) # function parser1 () { -awk ' +callawk ' BEGIN { menu_no = 0 comment_is_option = 0 @@ -598,7 +647,7 @@ function parser(ifile,menu) { # Secondary parser for single menu mode. # function parser2 () { -awk ' +callawk ' BEGIN { parser("'$CONFIG_IN'","MCmenu0") } @@ -657,9 +706,9 @@ function parse_config_files () { # for i in MCmenu* do + echo -n "." source ./$i done - rm -f MCmenu* } @@ -681,7 +730,6 @@ function activate_menu () { then clear cat <>$CONFIG_H } + function string () { + eval x=\${$2:-"$3"} + echo "$2=\"$x\"" >>$CONFIG + echo "#define $2 \"$x\"" >>$CONFIG_H + } + function define_bool () { eval $1="$2" @@ -1051,6 +1104,8 @@ save_configuration () { fi } + echo -n "." + DEF_CONFIG="${1:-.config}" DEF_CONFIG_H="include/linux/autoconf.h" @@ -1067,7 +1122,8 @@ save_configuration () { echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H MAKE=: #To prevent sound Makefile from running. - + + echo -n "." if . $CONFIG_IN >>.menuconfig.log 2>&1 then if [ "$DEF_CONFIG" = ".config" ] @@ -1080,6 +1136,7 @@ save_configuration () { "_$CONFIG_PSS" != "_y" -a\ "_$CONFIG_SMWAVE" != "_y" ] then + echo -n ", sound..." make -C drivers/sound kernelconfig >>.menuconfig.log 2>&1 fi @@ -1164,6 +1221,10 @@ inputbox_instructions_hex="\ Please enter a hexadecimal value. \ Use the key to move from the input field to the buttons below it." +inputbox_instructions_string="\ +Please enter a string value. \ +Use the key to move from the input field to the buttons below it." + DIALOG="./scripts/lxdialog/lxdialog" kernel_version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}" @@ -1188,22 +1249,17 @@ fi if [ -f $DEFAULTS ] then - echo "#" - echo "# Using defaults found in" $DEFAULTS - echo "#" + echo "Using defaults found in" $DEFAULTS load_config_file $DEFAULTS else - echo "#" - echo "# No defaults found" - echo "#" + echo "No defaults found" fi # Fresh new log. >.menuconfig.log -$DIALOG --backtitle "$backtitle" \ - --infobox "Preparing configuration scripts..." 3 40 +echo -n "Preparing configuration scripts: version" # # Check kernel version of previous menuconfig build. @@ -1222,6 +1278,7 @@ fi if [ "$rebuildsound" ] then + echo -n ", sound" # Activate the Linux compatible sound configuration. # This may not work for all sound cards. (See sound docs) # @@ -1231,13 +1288,28 @@ then fi # Load the functions used by the config.in files. +echo -n ", functions" load_functions +if [ ! -e $CONFIG_IN ] +then + echo "Your main config.in file ($CONFIG_IN) does not exist" + exit 1 +fi + +if [ ! -x $DIALOG ] +then + echo "Your lxdialog utility does not exist" + exit 1 +fi + # # Read config.in files and parse them into one shell function per menu. # +echo -n ", parsing" parse_config_files $CONFIG_IN +echo "done." # # Start the ball rolling from the top. # @@ -1253,25 +1325,12 @@ cleanup1 # if $DIALOG --backtitle "$backtitle" \ --yesno "Do you wish to save your new kernel configuration?" 5 60 - then save_configuration - - clear - cat <